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

Last change on this file since 10682 was 10678, checked in by tbretz, 14 years ago
Implemented a fix which should avoid that the GUI is playing ping-pong with e.g. the ftmctrl. This is done through a wrapper around all infoHandlers. In ceratin circumstances (mainly when signals of the kind valueChanged are emitted) it is advicable to not send the values back to the emitter if their origin is the handler.
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.fCoincidencePhysics);
1010 fCalibCoincidence->setValue(sdata.fCoincidenceCalib);
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.