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

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