source: trunk/FACT++/gui/FactGui.h@ 10601

Last change on this file since 10601 was 10601, checked in by tbretz, 10 years ago
Added FTM_CONTROL/COUNTER
File size: 53.6 KB
Line 
1#ifndef FACT_FactGui
2#define FACT_FactGui
3
4#include "MainWindow.h"
5
6#include <iomanip>
7#include <valarray>
8
9#include <boost/bind.hpp>
10
11#include <QTimer>
12#include <QStandardItemModel>
13
14#include "CheckBoxDelegate.h"
15
16#include "src/Converter.h"
17#include "src/HeadersFTM.h"
18#include "src/DimNetwork.h"
19#include "src/tools.h"
20
21#include "TROOT.h"
22#include "TSystem.h"
23#include "TGraph.h"
24#include "TH1.h"
25#include "TStyle.h"
26#include "TMarker.h"
27#include "TColor.h"
28
29#define HAS_ROOT
30
31using namespace std;
32
33// #########################################################################
34
35class Camera : public TObject
36{
37 typedef pair<double,double> Position;
38 typedef vector<Position> Positions;
39
40 Positions fGeom;
41
42 void CreatePalette()
43 {
44 /*
45 double ss[5] = {0., 0.10, 0.45, 0.75, 1.00};
46 double rr[5] = {0., 0.35, 0.85, 1.00, 1.00};
47 double gg[5] = {0., 0.10, 0.20, 0.73, 1.00};
48 double bb[5] = {0., 0.03, 0.06, 0.00, 1.00};
49 */
50 double ss[5] = {0., 0.25, 0.50, 0.75, 1.00};
51 double rr[5] = {0., 0.00, 0.00, 1.00, 1.00};
52 double gg[5] = {0., 0.00, 1.00, 0.00, 1.00};
53 double bb[5] = {0., 1.00, 0.00, 0.00, 1.00};
54
55 const Int_t nn = 1438;
56
57 Int_t idx = TColor::CreateGradientColorTable(5, ss, rr, gg, bb, nn);
58 for (int i=0; i<nn; i++)
59 fPalette.push_back(idx++);
60 }
61
62 void CreateGeometry()
63 {
64 const double gsSin60 = sqrt(3.)/2;
65
66 const int rings = 23;
67
68 // add the first pixel to the list
69
70 fGeom.push_back(make_pair(0, -0.5));
71
72 for (int ring=1; ring<=rings; ring++)
73 {
74 for (int s=0; s<6; s++)
75 {
76 for (int i=1; i<=ring; i++)
77 {
78 double xx, yy;
79 switch (s)
80 {
81 case 0: // Direction South East
82 xx = (ring+i)*0.5;
83 yy = (-ring+i)*gsSin60;
84 break;
85
86 case 1: // Direction North East
87 xx = ring-i*0.5;
88 yy = i*gsSin60;
89 break;
90
91 case 2: // Direction North
92 xx = ring*0.5-i;
93 yy = ring*gsSin60;
94 break;
95
96 case 3: // Direction North West
97 xx = -(ring+i)*0.5;
98 yy = (ring-i)*gsSin60;
99 break;
100
101 case 4: // Direction South West
102 xx = 0.5*i-ring;
103 yy = -i*gsSin60;
104 break;
105
106 case 5: // Direction South
107 xx = i-ring*0.5;
108 yy = -ring*gsSin60;
109 break;
110 }
111
112 if (xx*xx + yy*yy - xx > 395.75)
113 continue;
114
115 fGeom.push_back(make_pair(yy, xx-0.5));
116 }
117 }
118 }
119 }
120
121 valarray<double> fData;
122 map<int, bool> fBold;
123 map<int, bool> fEnable;
124
125 int fWhite;
126
127public:
128 Camera() : fData(0., 1438), fWhite(-1)
129 {
130 CreatePalette();
131 CreateGeometry();
132
133 for (int i=0; i<1438; i++)
134 fData[i] = i;
135 }
136
137 void Reset() { fBold.clear(); }
138
139 void SetBold(int idx) { fBold[idx]=true; }
140 void SetWhite(int idx) { fWhite=idx; }
141 void SetEnable(int idx, bool b) { fEnable[idx]=b; }
142 void Toggle(int idx) { fEnable[idx]=!fEnable[idx]; }
143
144 const char *GetName() const { return "Camera"; }
145
146 vector<Int_t> fPalette;
147
148 void Paint(const Position &p)
149 {
150 static const Double_t fgCos60 = 0.5; // TMath::Cos(60/TMath::RadToDeg());
151 static const Double_t fgSin60 = sqrt(3.)/2; // TMath::Sin(60/TMath::RadToDeg());
152
153 static const Double_t fgDy[6] = { fgCos60, 0., -fgCos60, -fgCos60, 0., fgCos60 };
154 static const Double_t fgDx[6] = { fgSin60/3, fgSin60*2/3, fgSin60/3, -fgSin60/3, -fgSin60*2/3, -fgSin60/3 };
155
156 //
157 // calculate the positions of the pixel corners
158 //
159 Double_t x[7], y[7];
160 for (Int_t i=0; i<7; i++)
161 {
162 x[i] = p.first + fgDx[i%6];
163 y[i] = p.second + fgDy[i%6];
164 }
165
166 gPad->PaintFillArea(6, x, y);
167 gPad->PaintPolyLine(7, x, y);
168
169 }
170
171 void Paint(Option_t *)
172 {
173 gStyle->SetPalette(fPalette.size(), fPalette.data());
174
175
176 const double r = double(gPad->GetWw())/gPad->GetWh();
177 const double max = 20.5; // 20.5 rings in x and y
178
179 if (r>1)
180 gPad->Range(-r*max, -max, r*max, max);
181 else
182 gPad->Range(-max, -max/r, max, max/r);
183
184
185 const double min = fData.min();
186 const double scale = fData.max()-fData.min();
187
188 TAttFill fill(0, 1001);
189 TAttLine line;
190
191 int cnt=0;
192 for (Positions::iterator p=fGeom.begin(); p!=fGeom.end(); p++, cnt++)
193 {
194 if (fBold[cnt])
195 continue;
196
197
198 const int col = (fData[cnt]-min)/scale*(fPalette.size()-1);
199
200 if (fEnable[cnt])
201 fill.SetFillColor(gStyle->GetColorPalette(col));
202 else
203 fill.SetFillColor(kWhite);
204
205 fill.Modify();
206
207 Paint(*p);
208 }
209
210 line.SetLineWidth(2);
211 line.Modify();
212
213 cnt = 0;
214 for (Positions::iterator p=fGeom.begin(); p!=fGeom.end(); p++, cnt++)
215 {
216 if (!fBold[cnt])
217 continue;
218
219 const int col = (fData[cnt]-min)/scale*(fPalette.size()-1);
220
221 if (fEnable[cnt])
222 fill.SetFillColor(gStyle->GetColorPalette(col));
223 else
224 fill.SetFillColor(kWhite);
225 fill.Modify();
226
227 Paint(*p);
228 }
229
230 TMarker m(0,0,kStar);
231 m.DrawMarker(0, 0);
232
233 if (fWhite<0)
234 return;
235
236 const Position &p = fGeom[fWhite];
237
238 line.SetLineColor(kWhite);
239 line.Modify();
240
241 const int col = (fData[fWhite]-min)/scale*(fPalette.size()-1);
242
243 if (fEnable[fWhite])
244 fill.SetFillColor(gStyle->GetColorPalette(col));
245 else
246 fill.SetFillColor(kWhite);
247 fill.Modify();
248
249 Paint(p);
250 }
251
252 int GetIdx(float px, float py) const
253 {
254 static const double sqrt3 = sqrt(3);
255
256 int idx = 0;
257 for (Positions::const_iterator p=fGeom.begin(); p!=fGeom.end(); p++, idx++)
258 {
259 const Double_t dy = py - p->second;
260 if (fabs(dy)>0.5)
261 continue;
262
263 const Double_t dx = px - p->first;
264
265 if (TMath::Abs(dy + dx*sqrt3) > 1)
266 continue;
267
268 if (TMath::Abs(dy - dx*sqrt3) > 1)
269 continue;
270
271 return idx;
272 }
273 return -1;
274 }
275
276 char* GetObjectInfo(Int_t px, Int_t py) const
277 {
278 static stringstream stream;
279 static string str;
280
281 const float x = gPad->PadtoX(gPad->AbsPixeltoX(px));
282 const float y = gPad->PadtoY(gPad->AbsPixeltoY(py));
283
284 const int idx = GetIdx(x, y);
285
286 stream.seekp(0);
287 if (idx>=0)
288 stream << "Pixel=" << idx << " Data=" << fData[idx] << '\0';
289
290 str = stream.str();
291 return const_cast<char*>(str.c_str());
292 }
293
294 Int_t DistancetoPrimitive(Int_t px, Int_t py)
295 {
296 const float x = gPad->PadtoX(gPad->AbsPixeltoX(px));
297 const float y = gPad->PadtoY(gPad->AbsPixeltoY(py));
298
299 return GetIdx(x, y)>=0 ? 0 : 99999;
300 }
301
302 void SetData(const valarray<double> &data)
303 {
304 fData = data;
305 }
306};
307
308// #########################################################################
309
310
311class FactGui : public MainWindow, public DimNetwork
312{
313private:
314 class FunctionEvent : public QEvent
315 {
316 public:
317 boost::function<void(const QEvent &)> fFunction;
318
319 FunctionEvent(const boost::function<void(const QEvent &)> &f)
320 : QEvent((QEvent::Type)QEvent::registerEventType()),
321 fFunction(f) { }
322
323 bool Exec() { fFunction(*this); return true; }
324 };
325
326 valarray<int8_t> fFtuStatus;
327
328 DimStampedInfo fDimDNS;
329
330 DimStampedInfo fDimLoggerStats;
331 DimStampedInfo fDimLoggerFilenameNight;
332 DimStampedInfo fDimLoggerFilenameRun;
333 DimStampedInfo fDimLoggerNumSubs;
334
335 DimStampedInfo fDimFtmPassport;
336 DimStampedInfo fDimFtmTriggerCounter;
337 DimStampedInfo fDimFtmError;
338 DimStampedInfo fDimFtmFtuList;
339 DimStampedInfo fDimFtmStaticData;
340 DimStampedInfo fDimFtmDynamicData;
341 DimStampedInfo fDimFtmCounter;
342
343 map<string, DimInfo*> fServices;
344
345 // ===================== Services and Commands ==========================
346
347 QStandardItem *AddServiceItem(const std::string &server, const std::string &service, bool iscmd)
348 {
349 QListView *servers = iscmd ? fDimCmdServers : fDimSvcServers;
350 QListView *services = iscmd ? fDimCmdCommands : fDimSvcServices;
351 QListView *description = iscmd ? fDimCmdDescription : fDimSvcDescription;
352
353 QStandardItemModel *m = dynamic_cast<QStandardItemModel*>(servers->model());
354 if (!m)
355 {
356 m = new QStandardItemModel(this);
357 servers->setModel(m);
358 services->setModel(m);
359 description->setModel(m);
360 }
361
362 QList<QStandardItem*> l = m->findItems(server.c_str());
363
364 if (l.size()>1)
365 {
366 cout << "hae" << endl;
367 return 0;
368 }
369
370 QStandardItem *col = l.size()==0 ? NULL : l[0];
371
372 if (!col)
373 {
374 col = new QStandardItem(server.c_str());
375 m->appendRow(col);
376
377 if (!services->rootIndex().isValid())
378 {
379 services->setRootIndex(col->index());
380 servers->setCurrentIndex(col->index());
381 }
382 }
383
384 QStandardItem *item = 0;
385 for (int i=0; i<col->rowCount(); i++)
386 {
387 QStandardItem *coli = col->child(i);
388 if (coli->text().toStdString()==service)
389 return coli;
390 }
391
392 item = new QStandardItem(service.c_str());
393 col->appendRow(item);
394 col->sortChildren(0);
395
396 if (!description->rootIndex().isValid())
397 {
398 description->setRootIndex(item->index());
399 services->setCurrentIndex(item->index());
400 }
401
402 if (!iscmd)
403 item->setCheckable(true);
404
405 return item;
406 }
407
408 void AddDescription(QStandardItem *item, const vector<Description> &vec)
409 {
410 if (!item)
411 return;
412 if (vec.size()==0)
413 return;
414
415 item->setToolTip(vec[0].comment.c_str());
416
417 const string str = Description::GetHtmlDescription(vec);
418
419 QStandardItem *desc = new QStandardItem(str.c_str());
420 desc->setSelectable(false);
421 item->setChild(0, 0, desc);
422 }
423
424 void AddServer(const std::string &s)
425 {
426 DimNetwork::AddServer(s);
427
428 QApplication::postEvent(this,
429 new FunctionEvent(boost::bind(&FactGui::handleAddServer, this, s)));
430 }
431
432 void RemoveServer(const std::string &s)
433 {
434 UnsubscribeServer(s);
435
436 DimNetwork::RemoveServer(s);
437
438 QApplication::postEvent(this,
439 new FunctionEvent(boost::bind(&FactGui::handleRemoveServer, this, s)));
440 }
441
442 void RemoveAllServers()
443 {
444 UnsubscribeAllServers();
445
446 vector<string> v = GetServerList();
447 for (vector<string>::iterator i=v.begin(); i<v.end(); i++)
448 QApplication::postEvent(this,
449 new FunctionEvent(boost::bind(&FactGui::handleStateOffline, this, *i)));
450
451 DimNetwork::RemoveAllServers();
452
453 QApplication::postEvent(this,
454 new FunctionEvent(boost::bind(&FactGui::handleRemoveAllServers, this)));
455 }
456
457 void AddService(const std::string &server, const std::string &service, const std::string &fmt, bool iscmd)
458 {
459 QApplication::postEvent(this,
460 new FunctionEvent(boost::bind(&FactGui::handleAddService, this, server, service, fmt, iscmd)));
461 }
462
463 void RemoveService(const std::string &server, const std::string &service, bool iscmd)
464 {
465 if (fServices.find(server+'/'+service)!=fServices.end())
466 UnsubscribeService(server+'/'+service);
467
468 QApplication::postEvent(this,
469 new FunctionEvent(boost::bind(&FactGui::handleRemoveService, this, server, service, iscmd)));
470 }
471
472 void RemoveAllServices(const std::string &server)
473 {
474 UnsubscribeServer(server);
475
476 QApplication::postEvent(this,
477 new FunctionEvent(boost::bind(&FactGui::handleRemoveAllServices, this, server)));
478 }
479
480 void AddDescription(const std::string &server, const std::string &service, const vector<Description> &vec)
481 {
482 QApplication::postEvent(this,
483 new FunctionEvent(boost::bind(&FactGui::handleAddDescription, this, server, service, vec)));
484 }
485
486 // ======================================================================
487
488 void handleAddServer(const std::string &server)
489 {
490 const State s = GetState(server, GetCurrentState(server));
491 handleStateChanged(Time(), server, s);
492 }
493
494 void handleRemoveServer(const string &server)
495 {
496 handleStateOffline(server);
497 handleRemoveAllServices(server);
498 }
499
500 void handleRemoveAllServers()
501 {
502 QStandardItemModel *m = 0;
503 if ((m=dynamic_cast<QStandardItemModel*>(fDimCmdServers->model())))
504 m->removeRows(0, m->rowCount());
505
506 if ((m = dynamic_cast<QStandardItemModel*>(fDimSvcServers->model())))
507 m->removeRows(0, m->rowCount());
508 }
509
510 void handleAddService(const std::string &server, const std::string &service, const std::string &/*fmt*/, bool iscmd)
511 {
512 QStandardItem *item = AddServiceItem(server, service, iscmd);
513 const vector<Description> v = GetDescription(server, service);
514 AddDescription(item, v);
515 }
516
517 void handleRemoveService(const std::string &server, const std::string &service, bool iscmd)
518 {
519 QListView *servers = iscmd ? fDimCmdServers : fDimSvcServers;
520
521 QStandardItemModel *m = dynamic_cast<QStandardItemModel*>(servers->model());
522 if (!m)
523 return;
524
525 QList<QStandardItem*> l = m->findItems(server.c_str());
526 if (l.size()!=1)
527 return;
528
529 for (int i=0; i<l[0]->rowCount(); i++)
530 {
531 QStandardItem *row = l[0]->child(i);
532 if (row->text().toStdString()==service)
533 {
534 l[0]->removeRow(row->index().row());
535 return;
536 }
537 }
538 }
539
540 void handleRemoveAllServices(const std::string &server)
541 {
542 QStandardItemModel *m = 0;
543 if ((m=dynamic_cast<QStandardItemModel*>(fDimCmdServers->model())))
544 {
545 QList<QStandardItem*> l = m->findItems(server.c_str());
546 if (l.size()==1)
547 m->removeRow(l[0]->index().row());
548 }
549
550 if ((m = dynamic_cast<QStandardItemModel*>(fDimSvcServers->model())))
551 {
552 QList<QStandardItem*> l = m->findItems(server.c_str());
553 if (l.size()==1)
554 m->removeRow(l[0]->index().row());
555 }
556 }
557
558 void handleAddDescription(const std::string &server, const std::string &service, const vector<Description> &vec)
559 {
560 const bool iscmd = IsCommand(server, service)==true;
561
562 QStandardItem *item = AddServiceItem(server, service, iscmd);
563 AddDescription(item, vec);
564 }
565
566 // ======================================================================
567
568 void SubscribeService(const string &service)
569 {
570 if (fServices.find(service)!=fServices.end())
571 {
572 cout << "ERROR - We are already subscribed to " << service << endl;
573 return;
574 }
575
576 fServices[service] = new DimStampedInfo(service.c_str(), (void*)NULL, 0, this);
577 }
578
579 void UnsubscribeService(const string &service)
580 {
581 const map<string,DimInfo*>::iterator i=fServices.find(service);
582
583 if (i==fServices.end())
584 {
585 cout << "ERROR - We are not subscribed to " << service << endl;
586 return;
587 }
588
589 delete i->second;
590
591 fServices.erase(i);
592 }
593
594 void UnsubscribeServer(const string &server)
595 {
596 for (map<string,DimInfo*>::iterator i=fServices.begin();
597 i!=fServices.end(); i++)
598 if (i->first.substr(0, server.length()+1)==server+'/')
599 {
600 delete i->second;
601 fServices.erase(i);
602 }
603 }
604
605 void UnsubscribeAllServers()
606 {
607 for (map<string,DimInfo*>::iterator i=fServices.begin();
608 i!=fServices.end(); i++)
609 delete i->second;
610
611 fServices.clear();
612 }
613
614 // ======================================================================
615
616 struct DimData
617 {
618 Time time;
619 int qos;
620 string name;
621 string format;
622 vector<char> data;
623
624 DimInfo *info; // this is ONLY for a fast check of the type of the DimData!!
625
626 DimData(DimInfo *inf) :
627 qos(inf->getQuality()),
628 name(inf->getName()),
629 format(inf->getFormat()),
630 data(inf->getString(), inf->getString()+inf->getSize()),
631 info(inf)
632 {
633 // Must be called in exactly this order!
634 const int tsec = inf->getTimestamp();
635 const int tms = inf->getTimestampMillisecs();
636
637 time = Time(tsec, tms*1000);
638 }
639
640 template<typename T>
641 T get() const { return *reinterpret_cast<const T*>(data.data()); }
642
643 vector<char> vec(int b) const { return vector<char>(data.begin()+b, data.end()); }
644 string str(unsigned int b) const { return b>=data.size()?string():string(data.data()+b, data.size()-b); }
645 const char *c_str() const { return (char*)data.data(); }
646
647 vector<boost::any> any() const
648 {
649 const Converter conv(format);
650 conv.Print();
651 return conv.GetAny(data.data(), data.size());
652 }
653 int size() const { return data.size(); }
654 const void *ptr() const { return data.data(); }
655 };
656
657 // ======================= DNS ==========================================
658
659 void handleDimDNS(const DimData &d)
660 {
661 const int version = d.get<unsigned int>();
662
663 ostringstream str;
664 str << "V" << version/100 << 'r' << version%100;
665
666 if (version==0)
667 fStatusDNSLed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
668 else
669 fStatusDNSLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
670
671 fStatusDNSLabel->setText(version==0?"Offline":str.str().c_str());
672 fStatusDNSLabel->setToolTip(version==0?"No connection to DIM DNS.":"Connection to DIM DNS established.");
673 }
674
675
676 // ======================= Logger =======================================
677
678 void handleLoggerStats(const DimData &d)
679 {
680 const bool connected = d.size()!=0;
681
682 fLoggerET->setEnabled(connected);
683 fLoggerRate->setEnabled(connected);
684 fLoggerWritten->setEnabled(connected);
685 fLoggerFreeSpace->setEnabled(connected);
686 fLoggerSpaceLeft->setEnabled(connected);
687
688 if (!connected)
689 return;
690
691 const uint64_t *vals = reinterpret_cast<const uint64_t*>(d.ptr());
692
693 const size_t written = vals[0];
694 const size_t space = vals[1];
695 const size_t rate = vals[2];
696
697 fLoggerFreeSpace->setSuffix(" MB");
698 fLoggerFreeSpace->setDecimals(0);
699 fLoggerFreeSpace->setValue(space*1e-6);
700
701 if (space> 1000000) // > 1GB
702 {
703 fLoggerFreeSpace->setSuffix(" GB");
704 fLoggerFreeSpace->setDecimals(2);
705 fLoggerFreeSpace->setValue(space*1e-9);
706 }
707 if (space>= 3000000) // >= 3GB
708 {
709 fLoggerFreeSpace->setSuffix(" GB");
710 fLoggerFreeSpace->setDecimals(1);
711 fLoggerFreeSpace->setValue(space*1e-9);
712 }
713 if (space>=100000000) // >= 100GB
714 {
715 fLoggerFreeSpace->setSuffix(" GB");
716 fLoggerFreeSpace->setDecimals(0);
717 fLoggerFreeSpace->setValue(space*1e-9);
718 }
719
720 fLoggerET->setTime(QTime().addSecs(rate>0?space/rate:0));
721 fLoggerRate->setValue(rate*1e-3); // kB/s
722 fLoggerWritten->setValue(written*1e-6);
723
724 fLoggerRate->setSuffix(" kB/s");
725 fLoggerRate->setDecimals(2);
726 fLoggerRate->setValue(rate*1e-3);
727 if (rate> 2000) // > 2kB/s
728 {
729 fLoggerRate->setSuffix(" kB/s");
730 fLoggerRate->setDecimals(1);
731 fLoggerRate->setValue(rate*1e-3);
732 }
733 if (rate>=100000) // >100kB/s
734 {
735 fLoggerRate->setSuffix(" kB/s");
736 fLoggerRate->setDecimals(0);
737 fLoggerRate->setValue(rate*1e-3);
738 }
739 if (rate>=1000000) // >100kB/s
740 {
741 fLoggerRate->setSuffix(" MB/s");
742 fLoggerRate->setDecimals(2);
743 fLoggerRate->setValue(rate*1e-6);
744 }
745 if (rate>=10000000) // >1MB/s
746 {
747 fLoggerRate->setSuffix(" MB/s");
748 fLoggerRate->setDecimals(1);
749 fLoggerRate->setValue(rate*1e-6);
750 }
751 if (rate>=100000000) // >10MB/s
752 {
753 fLoggerRate->setSuffix(" MB/s");
754 fLoggerRate->setDecimals(0);
755 fLoggerRate->setValue(rate*1e-6);
756 }
757
758 if (space/1000000>static_cast<size_t>(fLoggerSpaceLeft->maximum()))
759 fLoggerSpaceLeft->setValue(fLoggerSpaceLeft->maximum()); // GB
760 else
761 fLoggerSpaceLeft->setValue(space/1000000); // MB
762 }
763
764 void handleLoggerFilenameNight(const DimData &d)
765 {
766 const bool connected = d.size()!=0;
767
768 fLoggerFilenameNight->setEnabled(connected);
769 if (!connected)
770 return;
771
772 fLoggerFilenameNight->setText(d.c_str()+4);
773
774 const uint32_t files = d.get<uint32_t>();
775
776 if (files&1)
777 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
778 else
779 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
780
781 if (files&2)
782 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
783 else
784 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
785
786 if (files&4)
787 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
788 else
789 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
790 }
791
792 void handleLoggerFilenameRun(const DimData &d)
793 {
794 const bool connected = d.size()!=0;
795
796 fLoggerFilenameRun->setEnabled(connected);
797 if (!connected)
798 return;
799
800 fLoggerFilenameRun->setText(d.c_str()+4);
801
802 const uint32_t files = d.get<uint32_t>();
803
804 if (files&1)
805 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
806 else
807 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
808
809 if (files&2)
810 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
811 else
812 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
813
814 if (files&4)
815 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
816 else
817 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
818 }
819
820 void handleLoggerNumSubs(const DimData &d)
821 {
822 const bool connected = d.size()!=0;
823
824 fLoggerSubscriptions->setEnabled(connected);
825 fLoggerOpenFiles->setEnabled(connected);
826 if (!connected)
827 return;
828
829 const uint32_t *vals = reinterpret_cast<const uint32_t*>(d.ptr());
830
831 fLoggerSubscriptions->setValue(vals[0]);
832 fLoggerOpenFiles->setValue(vals[1]);
833 }
834
835 // ===================== FTM ============================================
836
837 void handleFtmTriggerCounter(const DimData &d)
838 {
839 if (d.size()==0)
840 return;
841
842 if (d.size()!=sizeof(FTM::DimTriggerCounter))
843 {
844 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimTriggerCounter) << endl;
845 return;
846 }
847
848 const FTM::DimTriggerCounter &sdata = *reinterpret_cast<const FTM::DimTriggerCounter*>(d.ptr());
849
850 fFtmTime->setText(QString::number(sdata.fTimeStamp));
851 fTriggerCounter->setText(QString::number(sdata.fTriggerCounter));
852 }
853
854 void handleFtmCounter(const DimData &d)
855 {
856 if (d.size()==0)
857 return;
858
859 if (d.size()!=sizeof(uint32_t)*6)
860 {
861 cout << "Size mismatch: " << d.size() << " " << sizeof(uint32_t)*6 << endl;
862 return;
863 }
864
865 const uint32_t *sdata = reinterpret_cast<const uint32_t*>(d.ptr());
866
867 fFtmCounterH->setValue(sdata[0]);
868 fFtmCounterS->setValue(sdata[1]);
869 fFtmCounterD->setValue(sdata[2]);
870 fFtmCounterF->setValue(sdata[3]);
871 fFtmCounterE->setValue(sdata[4]);
872 fFtmCounterR->setValue(sdata[5]);
873 }
874
875 void handleFtmDynamicData(const DimData &d)
876 {
877 if (d.size()==0)
878 return;
879
880 if (d.size()!=sizeof(FTM::DimDynamicData))
881 {
882 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimDynamicData) << endl;
883 return;
884 }
885
886 const FTM::DimDynamicData &sdata = *reinterpret_cast<const FTM::DimDynamicData*>(d.ptr());
887
888 fFtmTime->setText(QString::number(sdata.fTimeStamp));
889 fOnTime->setText(QString::number(sdata.fOnTimeCounter));
890
891 fFtmTemp0->setValue(sdata.fTempSensor[0]*0.1);
892 fFtmTemp1->setValue(sdata.fTempSensor[1]*0.1);
893 fFtmTemp2->setValue(sdata.fTempSensor[2]*0.1);
894 fFtmTemp3->setValue(sdata.fTempSensor[3]*0.1);
895
896
897 // ----------------------------------------------
898#ifdef HAS_ROOT
899 TCanvas *c = fFtmTempCanv->GetCanvas();
900
901 static int cntr = 0;
902 double_t tm = cntr++;//Time().RootTime();
903
904 TH1 *h = (TH1*)c->FindObject("MyFrame");
905 h->FindBin(tm);
906
907 fGraphFtmTemp[0].SetPoint(fGraphFtmTemp[0].GetN(), tm, sdata.fTempSensor[0]*0.1);
908 fGraphFtmTemp[1].SetPoint(fGraphFtmTemp[1].GetN(), tm, sdata.fTempSensor[1]*0.1);
909 fGraphFtmTemp[2].SetPoint(fGraphFtmTemp[2].GetN(), tm, sdata.fTempSensor[2]*0.1);
910 fGraphFtmTemp[3].SetPoint(fGraphFtmTemp[3].GetN(), tm, sdata.fTempSensor[3]*0.1);
911
912 c->Modified();
913 c->Update();
914
915 // ----------------------------------------------
916
917 valarray<double> dat(0., 1438);
918
919 for (int i=0; i<1438; i++)
920 dat[i] = sdata.fRatePatch[fPatch[i]];
921
922 c = fRatesCanv->GetCanvas();
923 Camera *cam = (Camera*)c->FindObject("Camera");
924
925 cam->SetData(dat);
926
927 c->Modified();
928 c->Update();
929#endif
930 }
931
932 FTM::DimStaticData fFtmStaticData;
933
934 void SetFtuLed(int idx, int counter)
935 {
936 if (counter==0)
937 counter = 3;
938
939 if (counter==-1)
940 counter = 0;
941
942 switch (counter)
943 {
944 case 0:
945 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
946 break;
947
948 case 1:
949 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
950 break;
951
952 case 2:
953 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/orange circle 1.png"));
954 break;
955
956 case 3:
957 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
958 break;
959 }
960
961 fFtuStatus[idx] = counter;
962 }
963
964 void SetFtuStatusLed()
965 {
966 const int max = fFtuStatus.max();
967
968 switch (max)
969 {
970 case 0:
971 fStatusFTULed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
972 fStatusFTULabel->setText("All disabled");
973 fStatusFTULabel->setToolTip("All FTUs are disabled");
974 break;
975
976 case 1:
977 fStatusFTULed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
978 fStatusFTULabel->setToolTip("Communication with FTU is smooth.");
979 fStatusFTULabel->setText("Ok");
980 break;
981
982 case 2:
983 fStatusFTULed->setIcon(QIcon(":/Resources/icons/orange circle 1.png"));
984 fStatusFTULabel->setText("Warning");
985 fStatusFTULabel->setToolTip("At least one FTU didn't answer immediately");
986 break;
987
988 case 3:
989 fStatusFTULed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
990 fStatusFTULabel->setToolTip("At least one FTU didn't answer!");
991 fStatusFTULabel->setText("ERROR");
992 break;
993 }
994 }
995
996 void handleFtmStaticData(const DimData &d)
997 {
998 if (d.size()==0)
999 return;
1000
1001 if (d.size()!=sizeof(FTM::DimStaticData))
1002 {
1003 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimStaticData) << endl;
1004 return;
1005 }
1006
1007 const FTM::DimStaticData &sdata = *reinterpret_cast<const FTM::DimStaticData*>(d.ptr());
1008
1009 fTriggerInterval->setValue(sdata.fTriggerInterval);
1010 fPhysicsCoincidence->setValue(sdata.fCoincidencePhysics);
1011 fCalibCoincidence->setValue(sdata.fCoincidenceCalib);
1012 fPhysicsWindow->setValue(sdata.fWindowPhysics);
1013 fCalibWindow->setValue(sdata.fWindowCalib);
1014
1015 fTriggerDelay->setValue(sdata.fDelayTrigger);
1016 fTimeMarkerDelay->setValue(sdata.fDelayTimeMarker);
1017 fDeadTime->setValue(sdata.fDeadTime);
1018
1019 fClockCondR0->setValue(sdata.fClockConditioner[0]);
1020 fClockCondR1->setValue(sdata.fClockConditioner[1]);
1021 fClockCondR8->setValue(sdata.fClockConditioner[2]);
1022 fClockCondR9->setValue(sdata.fClockConditioner[3]);
1023 fClockCondR11->setValue(sdata.fClockConditioner[4]);
1024 fClockCondR13->setValue(sdata.fClockConditioner[5]);
1025 fClockCondR14->setValue(sdata.fClockConditioner[6]);
1026 fClockCondR15->setValue(sdata.fClockConditioner[7]);
1027
1028 fTriggerSeqPed->setValue(sdata.fTriggerSeqPed);
1029 fTriggerSeqLPint->setValue(sdata.fTriggerSeqLPint);
1030 fTriggerSeqLPext->setValue(sdata.fTriggerSeqLPext);
1031
1032 fEnableTrigger->setChecked(sdata.HasTrigger());
1033 fEnableLPint->setChecked(sdata.HasLPint());
1034 fEnableLPext->setChecked(sdata.HasLPext());
1035 fEnableVeto->setChecked(sdata.HasVeto());
1036 fEnablePedestal->setChecked(sdata.HasPedestal());
1037 fEnableExt1->setChecked(sdata.HasExt1());
1038 fEnableExt2->setChecked(sdata.HasExt2());
1039 fEnableTimeMarker->setChecked(sdata.HasTimeMarker());
1040
1041 for (int i=0; i<40; i++)
1042 {
1043 if (!sdata.IsActive(i))
1044 SetFtuLed(i, -1);
1045 else
1046 {
1047 if (fFtuStatus[i]==0)
1048 SetFtuLed(i, 1);
1049 }
1050 fFtuLED[i]->setChecked(false);
1051 }
1052 SetFtuStatusLed();
1053
1054#ifdef HAS_ROOT
1055 Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera");
1056 for (int i=0; i<1438; i++)
1057 cam->SetEnable(i, sdata.IsEnabled(i));
1058#endif
1059
1060 const int patch1 = fThresholdIdx->value();
1061 fThresholdVal->setValue(sdata.fThreshold[patch1<0?0:patch1]);
1062
1063 fPrescalingVal->setValue(sdata.fPrescaling[0]);
1064
1065 fFtmStaticData = sdata;
1066 }
1067
1068 void handleFtmPassport(const DimData &d)
1069 {
1070 if (d.size()==0)
1071 return;
1072
1073 if (d.size()!=sizeof(FTM::DimPassport))
1074 {
1075 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimPassport) << endl;
1076 return;
1077 }
1078
1079 const FTM::DimPassport &sdata = *reinterpret_cast<const FTM::DimPassport*>(d.ptr());
1080
1081 stringstream str1, str2;
1082 str1 << hex << "0x" << setfill('0') << setw(16) << sdata.fBoardId;
1083 str2 << sdata.fFirmwareId;
1084
1085 fFtmBoardId->setText(str1.str().c_str());
1086 fFtmFirmwareId->setText(str2.str().c_str());
1087 }
1088
1089 void handleFtmFtuList(const DimData &d)
1090 {
1091 if (d.size()==0)
1092 return;
1093
1094 if (d.size()!=sizeof(FTM::DimFtuList))
1095 {
1096 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimFtuList) << endl;
1097 return;
1098 }
1099
1100 fPing->setChecked(false);
1101
1102 const FTM::DimFtuList &sdata = *reinterpret_cast<const FTM::DimFtuList*>(d.ptr());
1103
1104 stringstream str;
1105 str << "<table width='100%'>" << setfill('0');
1106 str << "<tr><th>Num</th><th></th><th>Addr</th><th></th><th>DNA</th></tr>";
1107 for (int i=0; i<40; i++)
1108 {
1109 str << "<tr>";
1110 str << "<td align='center'>" << dec << i << hex << "</td>";
1111 str << "<td align='center'>:</td>";
1112 str << "<td align='center'>0x" << setw(2) << (int)sdata.fAddr[i] << "</td>";
1113 str << "<td align='center'>:</td>";
1114 str << "<td align='center'>0x" << setw(16) << sdata.fDNA[i] << "</td>";
1115 str << "</tr>";
1116 }
1117 str << "</table>";
1118
1119 fFtuDNA->setText(str.str().c_str());
1120
1121 fFtuAnswersTotal->setValue(sdata.fNumBoards);
1122 fFtuAnswersCrate0->setValue(sdata.fNumBoardsCrate[0]);
1123 fFtuAnswersCrate1->setValue(sdata.fNumBoardsCrate[1]);
1124 fFtuAnswersCrate2->setValue(sdata.fNumBoardsCrate[2]);
1125 fFtuAnswersCrate3->setValue(sdata.fNumBoardsCrate[3]);
1126
1127 for (int i=0; i<40; i++)
1128 SetFtuLed(i, sdata.IsActive(i) ? sdata.fPing[i] : -1);
1129
1130 SetFtuStatusLed();
1131 }
1132
1133 void handleFtmError(const DimData &d)
1134 {
1135 if (d.size()==0)
1136 return;
1137
1138 const FTM::DimError &sdata = *reinterpret_cast<const FTM::DimError*>(d.ptr());
1139
1140 SetFtuLed(sdata.fError.fDestAddress , sdata.fError.fNumCalls);
1141 SetFtuStatusLed();
1142
1143 // Write to special window!
1144 Out() << "Error:" << endl;
1145 Out() << sdata.fError << endl;
1146 }
1147
1148 // ====================== MessageImp ====================================
1149
1150 bool fChatOnline;
1151
1152 void handleStateChanged(const Time &/*time*/, const std::string &server,
1153 const State &s)
1154 {
1155 // FIXME: Prefix tooltip with time
1156 if (server=="FTM_CONTROL")
1157 {
1158 fStatusFTMLabel->setText(s.name.c_str());
1159 fStatusFTMLabel->setToolTip(s.comment.c_str());
1160
1161 bool enable = false;
1162
1163 if (s.index<FTM::kDisconnected) // No Dim connection
1164 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1165 if (s.index==FTM::kDisconnected) // Dim connection / FTM disconnected
1166 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1167 if (s.index==FTM::kConnected || s.index==FTM::kIdle) // Dim connection / FTM connected
1168 {
1169 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1170 enable = true;
1171 }
1172
1173 fTriggerWidget->setEnabled(enable);
1174 fFtuWidget->setEnabled(enable);
1175 fRatesWidget->setEnabled(enable);
1176
1177 if (!enable)
1178 {
1179 fStatusFTULed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1180 fStatusFTULabel->setText("Offline");
1181 fStatusFTULabel->setToolTip("FTM is not online.");
1182 }
1183 }
1184
1185 if (server=="FAD_CONTROL")
1186 {
1187 fStatusFADLabel->setText(s.name.c_str());
1188 fStatusFADLabel->setToolTip(s.comment.c_str());
1189
1190 if (s.index<FTM::kDisconnected) // No Dim connection
1191 fStatusFADLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1192 if (s.index==FTM::kDisconnected) // Dim connection / FTM disconnected
1193 fStatusFADLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1194 if (s.index==FTM::kConnected) // Dim connection / FTM connected
1195 fStatusFADLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1196 }
1197
1198 if (server=="DATA_LOGGER")
1199 {
1200 fStatusLoggerLabel->setText(s.name.c_str());
1201 fStatusLoggerLabel->setToolTip(s.comment.c_str());
1202
1203 bool enable = true;
1204
1205 if (s.index<=30) // Ready/Waiting
1206 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1207 if (s.index<-1) // Offline
1208 {
1209 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1210 enable = false;
1211 }
1212 if (s.index>=0x100) // Error
1213 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
1214 if (s.index==40) // Logging
1215 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1216
1217 fLoggerWidget->setEnabled(enable);
1218 }
1219
1220 if (server=="CHAT")
1221 {
1222 fStatusChatLabel->setText(s.name.c_str());
1223
1224 fChatOnline = s.index==0;
1225
1226 if (fChatOnline) // Dim connection / FTM connected
1227 fStatusChatLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1228 else
1229 fStatusChatLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1230
1231 fChatSend->setEnabled(fChatOnline);
1232 fChatMessage->setEnabled(fChatOnline);
1233 }
1234
1235 if (server=="SCHEDULER")
1236 {
1237 fStatusSchedulerLabel->setText(s.name.c_str());
1238
1239 if (s.index>=0) // Dim connection / FTM connected
1240 fStatusSchedulerLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1241 else
1242 fStatusSchedulerLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1243 }
1244 }
1245
1246 void handleStateOffline(const string &server)
1247 {
1248 handleStateChanged(Time(), server, State(-2, "Offline", "No connection via DIM."));
1249 }
1250
1251 void on_fTabWidget_currentChanged(int which)
1252 {
1253 if (fTabWidget->tabText(which)=="Chat")
1254 fTabWidget->setTabIcon(which, QIcon());
1255 }
1256
1257 void handleWrite(const Time &time, const string &text, int qos)
1258 {
1259 stringstream out;
1260
1261 if (text.substr(0, 6)=="CHAT: ")
1262 {
1263 out << "<font size='-1' color='navy'>[<B>";
1264 out << Time::fmt("%H:%M:%S") << time << "</B>]</FONT> ";
1265 out << text.substr(6);
1266 fChatText->append(out.str().c_str());
1267
1268 if (fTabWidget->tabText(fTabWidget->currentIndex())=="Chat")
1269 return;
1270
1271 static int num = 0;
1272 if (num++<2)
1273 return;
1274
1275 for (int i=0; i<fTabWidget->count(); i++)
1276 if (fTabWidget->tabText(i)=="Chat")
1277 {
1278 fTabWidget->setTabIcon(i, QIcon(":/Resources/icons/warning 3.png"));
1279 break;
1280 }
1281
1282 return;
1283 }
1284
1285
1286 out << "<font style='font-family:monospace' color='";
1287
1288 switch (qos)
1289 {
1290 case kMessage: out << "black"; break;
1291 case kInfo: out << "green"; break;
1292 case kWarn: out << "#FF6600"; break;
1293 case kError: out << "maroon"; break;
1294 case kFatal: out << "maroon"; break;
1295 case kDebug: out << "navy"; break;
1296 default: out << "navy"; break;
1297 }
1298 out << "'>" << time.GetAsStr() << " - " << text << "</font>";
1299
1300 fLogText->append(out.str().c_str());
1301
1302 if (qos>=kWarn)
1303 fTextEdit->append(out.str().c_str());
1304 }
1305
1306 void IndicateStateChange(const Time &time, const std::string &server)
1307 {
1308 const State s = GetState(server, GetCurrentState(server));
1309
1310 QApplication::postEvent(this,
1311 new FunctionEvent(boost::bind(&FactGui::handleStateChanged, this, time, server, s)));
1312 }
1313
1314 int Write(const Time &time, const string &txt, int qos)
1315 {
1316 QApplication::postEvent(this,
1317 new FunctionEvent(boost::bind(&FactGui::handleWrite, this, time, txt, qos)));
1318
1319 return 0;
1320 }
1321
1322 // ====================== Dim infoHandler================================
1323
1324 void handleDimService(const string &txt)
1325 {
1326 fDimSvcText->append(txt.c_str());
1327 }
1328
1329 void infoHandlerService(DimInfo &info)
1330 {
1331 const string fmt = string(info.getFormat()).empty() ? "C" : info.getFormat();
1332
1333 stringstream dummy;
1334 const Converter conv(dummy, fmt, false);
1335
1336 const Time tm(info.getTimestamp(), info.getTimestampMillisecs()*1000);
1337
1338 stringstream out;
1339 out << "<font size'-1' color='navy'>[" << Time::fmt("%H:%M:%S.%f") << tm << "]</font> <B>" << info.getName() << "</B> - ";
1340
1341 bool iserr = true;
1342 if (!conv)
1343 {
1344 out << "Compilation of format string '" << fmt << "' failed!";
1345 }
1346 else
1347 {
1348 try
1349 {
1350 const string dat = conv.GetString(info.getData(), info.getSize());
1351 out << dat;
1352 iserr = false;
1353 }
1354 catch (const runtime_error &e)
1355 {
1356 out << "Conversion to string failed!<pre>" << e.what() << "</pre>";
1357 }
1358 }
1359
1360 // srand(hash<string>()(string(info.getName())));
1361 // int bg = rand()&0xffffff;
1362
1363 int bg = hash<string>()(string(info.getName()));
1364
1365 // allow only light colors
1366 bg = ~(bg&0x1f1f1f)&0xffffff;
1367
1368 if (iserr)
1369 bg = 0xffffff;
1370
1371 stringstream bgcol;
1372 bgcol << hex << setfill('0') << setw(6) << bg;
1373
1374 const string col = iserr ? "red" : "black";
1375 const string str = "<table width='100%' bgcolor=#"+bgcol.str()+"><tr><td><font color='"+col+"'>"+out.str()+"</font></td></tr></table>";
1376
1377 QApplication::postEvent(this,
1378 new FunctionEvent(boost::bind(&FactGui::handleDimService, this, str)));
1379 }
1380
1381 void PostInfoHandler(void (FactGui::*handler)(const DimData&))
1382 {
1383 QApplication::postEvent(this,
1384 new FunctionEvent(boost::bind(handler, this, DimData(getInfo()))));
1385 }
1386
1387 void infoHandler()
1388 {
1389 // Initialize the time-stamp (what a weird workaround...)
1390 if (getInfo())
1391 getInfo()->getTimestamp();
1392
1393 if (getInfo()==&fDimDNS)
1394 return PostInfoHandler(&FactGui::handleDimDNS);
1395
1396 cout << "HandleDimInfo " << getInfo()->getName() << endl;
1397
1398 if (getInfo()==&fDimLoggerStats)
1399 return PostInfoHandler(&FactGui::handleLoggerStats);
1400
1401 if (getInfo()==&fDimLoggerFilenameNight)
1402 return PostInfoHandler(&FactGui::handleLoggerFilenameNight);
1403
1404 if (getInfo()==&fDimLoggerNumSubs)
1405 return PostInfoHandler(&FactGui::handleLoggerNumSubs);
1406
1407 if (getInfo()==&fDimLoggerFilenameRun)
1408 return PostInfoHandler(&FactGui::handleLoggerFilenameRun);
1409
1410 if (getInfo()==&fDimFtmTriggerCounter)
1411 return PostInfoHandler(&FactGui::handleFtmTriggerCounter);
1412
1413 if (getInfo()==&fDimFtmCounter)
1414 return PostInfoHandler(&FactGui::handleFtmCounter);
1415
1416 if (getInfo()==&fDimFtmDynamicData)
1417 return PostInfoHandler(&FactGui::handleFtmDynamicData);
1418
1419 if (getInfo()==&fDimFtmPassport)
1420 return PostInfoHandler(&FactGui::handleFtmPassport);
1421
1422 if (getInfo()==&fDimFtmFtuList)
1423 return PostInfoHandler(&FactGui::handleFtmFtuList);
1424
1425 if (getInfo()==&fDimFtmStaticData)
1426 return PostInfoHandler(&FactGui::handleFtmStaticData);
1427
1428 if (getInfo()==&fDimFtmError)
1429 return PostInfoHandler(&FactGui::handleFtmError);
1430
1431 for (map<string,DimInfo*>::iterator i=fServices.begin(); i!=fServices.end(); i++)
1432 if (i->second==getInfo())
1433 {
1434 infoHandlerService(*i->second);
1435 return;
1436 }
1437
1438 DimNetwork::infoHandler();
1439 }
1440
1441
1442 // ======================================================================
1443
1444 bool event(QEvent *evt)
1445 {
1446 if (dynamic_cast<FunctionEvent*>(evt))
1447 return static_cast<FunctionEvent*>(evt)->Exec();
1448
1449 if (dynamic_cast<CheckBoxEvent*>(evt))
1450 {
1451 const QStandardItem &item = static_cast<CheckBoxEvent*>(evt)->item;
1452 const QStandardItem *par = item.parent();
1453 if (par)
1454 {
1455 const QString server = par->text();
1456 const QString service = item.text();
1457
1458 const string s = (server+'/'+service).toStdString();
1459
1460 if (item.checkState()==Qt::Checked)
1461 SubscribeService(s);
1462 else
1463 UnsubscribeService(s);
1464 }
1465 }
1466
1467 return MainWindow::event(evt); // unrecognized
1468 }
1469
1470 void on_fDimCmdSend_clicked()
1471 {
1472 const QString server = fDimCmdServers->currentIndex().data().toString();
1473 const QString command = fDimCmdCommands->currentIndex().data().toString();
1474 const QString arguments = fDimCmdLineEdit->displayText();
1475
1476 // FIXME: Sending a command exactly when the info Handler changes
1477 // the list it might lead to confusion.
1478 try
1479 {
1480 SendDimCommand(server.toStdString(), command.toStdString()+" "+arguments.toStdString());
1481 fTextEdit->append("<font color='green'>Command '"+server+'/'+command+"' successfully emitted.</font>");
1482 fDimCmdLineEdit->clear();
1483 }
1484 catch (const runtime_error &e)
1485 {
1486 stringstream txt;
1487 txt << e.what();
1488
1489 string buffer;
1490 while (getline(txt, buffer, '\n'))
1491 fTextEdit->append(("<font color='red'><pre>"+buffer+"</pre></font>").c_str());
1492 }
1493 }
1494 void ChoosePatch(Camera &cam, int idx)
1495 {
1496 cam.Reset();
1497
1498 fThresholdIdx->setValue(idx);
1499 fThresholdVal->setValue(fFtmStaticData.fThreshold[idx<0?0:idx]);
1500
1501 if (idx<0)
1502 return;
1503
1504 for (unsigned int i=0; i<fPatch.size(); i++)
1505 if (fPatch[i]==idx)
1506 cam.SetBold(i);
1507 }
1508
1509 void ChoosePixel(Camera &cam, int idx)
1510 {
1511 cam.SetWhite(idx);
1512 ChoosePatch(cam, fPatch[idx]);
1513 }
1514
1515#ifdef HAS_ROOT
1516 void slot_RootEventProcessed(TObject *obj, unsigned int evt, TCanvas *)
1517 {
1518 // kMousePressEvent // TCanvas processed QEvent mousePressEvent
1519 // kMouseMoveEvent // TCanvas processed QEvent mouseMoveEvent
1520 // kMouseReleaseEvent // TCanvas processed QEvent mouseReleaseEvent
1521 // kMouseDoubleClickEvent // TCanvas processed QEvent mouseDoubleClickEvent
1522 // kKeyPressEvent // TCanvas processed QEvent keyPressEvent
1523 // kEnterEvent // TCanvas processed QEvent enterEvent
1524 // kLeaveEvent // TCanvas processed QEvent leaveEvent
1525 if (dynamic_cast<TCanvas*>(obj))
1526 return;
1527
1528 TQtWidget *tipped = static_cast<TQtWidget*>(sender());
1529
1530 if (evt==11/*kMouseReleaseEvent*/)
1531 {
1532 if (dynamic_cast<Camera*>(obj))
1533 {
1534 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1535 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1536
1537 Camera *cam = static_cast<Camera*>(obj);
1538 const int idx = cam->GetIdx(xx, yy);
1539
1540 ChoosePixel(*cam, idx);
1541 }
1542 return;
1543 }
1544
1545 if (evt==61/*kMouseDoubleClickEvent*/)
1546 {
1547 if (dynamic_cast<Camera*>(obj))
1548 {
1549 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1550 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1551
1552 Camera *cam = static_cast<Camera*>(obj);
1553 const int idx = cam->GetIdx(xx, yy);
1554
1555 cam->Toggle(idx);
1556 }
1557 return;
1558 }
1559
1560 // Find the object which will get picked by the GetObjectInfo
1561 // due to buffer overflows in many root-versions
1562 // in TH1 and TProfile we have to work around and implement
1563 // our own GetObjectInfo which make everything a bit more
1564 // complicated.
1565#if ROOT_VERSION_CODE > ROOT_VERSION(5,22,00)
1566 const char *objectInfo =
1567 obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1568#else
1569 const char *objectInfo = dynamic_cast<TH1*>(obj) ?
1570 "" : obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1571#endif
1572
1573 QString tipText;
1574 tipText += obj->GetName();
1575 tipText += " [";
1576 tipText += obj->ClassName();
1577 tipText += "]: ";
1578 tipText += objectInfo;
1579
1580 if (dynamic_cast<Camera*>(obj))
1581 {
1582 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1583 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1584
1585 Camera *cam = static_cast<Camera*>(obj);
1586 int idx = fPatch[cam->GetIdx(xx, yy)];
1587
1588 tipText+=" Patch=";
1589 tipText+=QString::number(idx);
1590 }
1591
1592
1593 fStatusBar->showMessage(tipText, 3000);
1594
1595 gSystem->ProcessEvents();
1596 //QWhatsThis::display(tipText)
1597 }
1598
1599 void slot_RootUpdate()
1600 {
1601 gSystem->ProcessEvents();
1602 QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1603 }
1604
1605 void on_fThresholdIdx_valueChanged(int idx)
1606 {
1607 Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera");
1608 ChoosePatch(*cam, idx);
1609 }
1610#endif
1611
1612 TGraph fGraphFtmTemp[4];
1613
1614 map<int, int> fPatch;
1615
1616public:
1617 FactGui() :
1618 fFtuStatus(40),
1619 fDimDNS("DIS_DNS/VERSION_NUMBER", 1, int(0), this),
1620
1621 fDimLoggerStats ("DATA_LOGGER/STATS", (void*)NULL, 0, this),
1622 fDimLoggerFilenameNight("DATA_LOGGER/FILENAME_NIGHTLY", const_cast<char*>(""), 0, this),
1623 fDimLoggerFilenameRun ("DATA_LOGGER/FILENAME_RUN", const_cast<char*>(""), 0, this),
1624 fDimLoggerNumSubs ("DATA_LOGGER/NUM_SUBS", const_cast<char*>(""), 0, this),
1625
1626 fDimFtmPassport ("FTM_CONTROL/PASSPORT", (void*)NULL, 0, this),
1627 fDimFtmTriggerCounter("FTM_CONTROL/TRIGGER_COUNTER", (void*)NULL, 0, this),
1628 fDimFtmError ("FTM_CONTROL/ERROR", (void*)NULL, 0, this),
1629 fDimFtmFtuList ("FTM_CONTROL/FTU_LIST", (void*)NULL, 0, this),
1630 fDimFtmStaticData ("FTM_CONTROL/STATIC_DATA", (void*)NULL, 0, this),
1631 fDimFtmDynamicData ("FTM_CONTROL/DYNAMIC_DATA", (void*)NULL, 0, this),
1632 fDimFtmCounter ("FTM_CONTROL/COUNTER", (void*)NULL, 0, this)
1633 {
1634 fTriggerWidget->setEnabled(false);
1635 fFtuWidget->setEnabled(false);
1636 fRatesWidget->setEnabled(false);
1637 fLoggerWidget->setEnabled(false);
1638
1639 fChatSend->setEnabled(false);
1640 fChatMessage->setEnabled(false);
1641
1642 DimClient::sendCommand("CHAT/MSG", "GUI online.");
1643 // + MessageDimRX
1644
1645 // --------------------------------------------------------------------------
1646
1647 ifstream fin("fact-trigger-all.txt");
1648
1649 int l = 0;
1650
1651 string buf;
1652 while (getline(fin, buf, '\n'))
1653 {
1654 buf = Tools::Trim(buf);
1655 if (buf[0]=='#')
1656 continue;
1657
1658 stringstream str(buf);
1659 for (int i=0; i<9; i++)
1660 {
1661 int n;
1662 str >> n;
1663
1664 fPatch[n] = l;
1665 }
1666 l++;
1667 }
1668
1669 // --------------------------------------------------------------------------
1670#ifdef HAS_ROOT
1671 TCanvas *c = fFtmTempCanv->GetCanvas();
1672 c->SetBit(TCanvas::kNoContextMenu);
1673 c->SetBorderMode(0);
1674 c->SetFrameBorderMode(0);
1675 c->SetFillColor(kWhite);
1676 c->SetRightMargin(0.03);
1677 c->SetTopMargin(0.03);
1678 c->cd();
1679
1680 TH1F h("MyFrame", "", 1000, 0, 1);//Time().RootTime()-1./24/60/60, Time().RootTime());
1681 h.SetDirectory(0);
1682 h.SetBit(TH1::kCanRebin);
1683 h.SetStats(kFALSE);
1684 h.SetMinimum(-20);
1685 h.SetMaximum(100);
1686 h.SetXTitle("Time");
1687 h.SetYTitle("Temperature / °C");
1688 h.GetXaxis()->CenterTitle();
1689 h.GetYaxis()->CenterTitle();
1690// h.GetXaxis()->SetTitleSize(1.2);
1691// h.GetYaxis()->SetTitleSize(1.2);
1692 h.DrawCopy();
1693
1694 fGraphFtmTemp[0].SetMarkerStyle(kFullDotSmall);
1695 fGraphFtmTemp[1].SetMarkerStyle(kFullDotSmall);
1696 fGraphFtmTemp[2].SetMarkerStyle(kFullDotSmall);
1697 fGraphFtmTemp[3].SetMarkerStyle(kFullDotSmall);
1698
1699 fGraphFtmTemp[1].SetLineColor(kBlue);
1700 fGraphFtmTemp[2].SetLineColor(kRed);
1701 fGraphFtmTemp[3].SetLineColor(kGreen);
1702
1703 fGraphFtmTemp[1].SetMarkerColor(kBlue);
1704 fGraphFtmTemp[2].SetMarkerColor(kRed);
1705 fGraphFtmTemp[3].SetMarkerColor(kGreen);
1706
1707 fGraphFtmTemp[0].Draw("LP");
1708 fGraphFtmTemp[1].Draw("LP");
1709 fGraphFtmTemp[2].Draw("LP");
1710 fGraphFtmTemp[3].Draw("LP");
1711
1712 // --------------------------------------------------------------------------
1713
1714 c = fRatesCanv->GetCanvas();
1715 c->SetBit(TCanvas::kNoContextMenu);
1716 c->SetBorderMode(0);
1717 c->SetFrameBorderMode(0);
1718 c->SetFillColor(kWhite);
1719 c->cd();
1720
1721 Camera *cam = new Camera;
1722 cam->SetBit(kCanDelete);
1723 cam->Draw();
1724
1725 ChoosePixel(*cam, 1);
1726
1727// QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1728
1729 //widget->setMouseTracking(true);
1730 //widget->EnableSignalEvents(kMouseMoveEvent);
1731
1732 fFtmTempCanv->setMouseTracking(true);
1733 fFtmTempCanv->EnableSignalEvents(kMouseMoveEvent);
1734
1735 fRatesCanv->setMouseTracking(true);
1736 fRatesCanv->EnableSignalEvents(kMouseMoveEvent|kMouseReleaseEvent|kMouseDoubleClickEvent);
1737
1738 connect(fRatesCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1739 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1740 connect(fFtmTempCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1741 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1742#endif
1743 }
1744
1745 ~FactGui()
1746 {
1747 UnsubscribeAllServers();
1748 }
1749};
1750
1751#endif
Note: See TracBrowser for help on using the repository browser.