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

Last change on this file since 10666 was 10665, checked in by tbretz, 14 years ago
Changed 'last changed' time for LEDs from local time to time of received service.
File size: 52.7 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 PostInfoHandler(void (FactGui::*handler)(const DimData&))
1372 {
1373 QApplication::postEvent(this,
1374 new FunctionEvent(boost::bind(handler, this, DimData(getInfo()))));
1375 }
1376
1377 void infoHandler()
1378 {
1379 // Initialize the time-stamp (what a weird workaround...)
1380 if (getInfo())
1381 getInfo()->getTimestamp();
1382
1383 if (getInfo()==&fDimDNS)
1384 return PostInfoHandler(&FactGui::handleDimDNS);
1385
1386 cout << "HandleDimInfo " << getInfo()->getName() << endl;
1387
1388 if (getInfo()==&fDimLoggerStats)
1389 return PostInfoHandler(&FactGui::handleLoggerStats);
1390
1391 if (getInfo()==&fDimLoggerFilenameNight)
1392 return PostInfoHandler(&FactGui::handleLoggerFilenameNight);
1393
1394 if (getInfo()==&fDimLoggerNumSubs)
1395 return PostInfoHandler(&FactGui::handleLoggerNumSubs);
1396
1397 if (getInfo()==&fDimLoggerFilenameRun)
1398 return PostInfoHandler(&FactGui::handleLoggerFilenameRun);
1399
1400 if (getInfo()==&fDimFtmTriggerCounter)
1401 return PostInfoHandler(&FactGui::handleFtmTriggerCounter);
1402
1403 if (getInfo()==&fDimFtmCounter)
1404 return PostInfoHandler(&FactGui::handleFtmCounter);
1405
1406 if (getInfo()==&fDimFtmDynamicData)
1407 return PostInfoHandler(&FactGui::handleFtmDynamicData);
1408
1409 if (getInfo()==&fDimFtmPassport)
1410 return PostInfoHandler(&FactGui::handleFtmPassport);
1411
1412 if (getInfo()==&fDimFtmFtuList)
1413 return PostInfoHandler(&FactGui::handleFtmFtuList);
1414
1415 if (getInfo()==&fDimFtmStaticData)
1416 return PostInfoHandler(&FactGui::handleFtmStaticData);
1417
1418 if (getInfo()==&fDimFtmError)
1419 return PostInfoHandler(&FactGui::handleFtmError);
1420
1421 for (map<string,DimInfo*>::iterator i=fServices.begin(); i!=fServices.end(); i++)
1422 if (i->second==getInfo())
1423 {
1424 infoHandlerService(*i->second);
1425 return;
1426 }
1427
1428 DimNetwork::infoHandler();
1429 }
1430
1431
1432 // ======================================================================
1433
1434 bool event(QEvent *evt)
1435 {
1436 if (dynamic_cast<FunctionEvent*>(evt))
1437 return static_cast<FunctionEvent*>(evt)->Exec();
1438
1439 if (dynamic_cast<CheckBoxEvent*>(evt))
1440 {
1441 const QStandardItem &item = static_cast<CheckBoxEvent*>(evt)->item;
1442 const QStandardItem *par = item.parent();
1443 if (par)
1444 {
1445 const QString server = par->text();
1446 const QString service = item.text();
1447
1448 const string s = (server+'/'+service).toStdString();
1449
1450 if (item.checkState()==Qt::Checked)
1451 SubscribeService(s);
1452 else
1453 UnsubscribeService(s);
1454 }
1455 }
1456
1457 return MainWindow::event(evt); // unrecognized
1458 }
1459
1460 void on_fDimCmdSend_clicked()
1461 {
1462 const QString server = fDimCmdServers->currentIndex().data().toString();
1463 const QString command = fDimCmdCommands->currentIndex().data().toString();
1464 const QString arguments = fDimCmdLineEdit->displayText();
1465
1466 // FIXME: Sending a command exactly when the info Handler changes
1467 // the list it might lead to confusion.
1468 try
1469 {
1470 SendDimCommand(server.toStdString(), command.toStdString()+" "+arguments.toStdString());
1471 fTextEdit->append("<font color='green'>Command '"+server+'/'+command+"' successfully emitted.</font>");
1472 fDimCmdLineEdit->clear();
1473 }
1474 catch (const runtime_error &e)
1475 {
1476 stringstream txt;
1477 txt << e.what();
1478
1479 string buffer;
1480 while (getline(txt, buffer, '\n'))
1481 fTextEdit->append(("<font color='red'><pre>"+buffer+"</pre></font>").c_str());
1482 }
1483 }
1484 void ChoosePatch(Camera &cam, int idx)
1485 {
1486 cam.Reset();
1487
1488 fThresholdIdx->setValue(idx);
1489 fThresholdVal->setValue(fFtmStaticData.fThreshold[idx<0?0:idx]);
1490
1491 if (idx<0)
1492 return;
1493
1494 for (unsigned int i=0; i<fPatch.size(); i++)
1495 if (fPatch[i]==idx)
1496 cam.SetBold(i);
1497 }
1498
1499 void ChoosePixel(Camera &cam, int idx)
1500 {
1501 cam.SetWhite(idx);
1502 ChoosePatch(cam, fPatch[idx]);
1503 }
1504
1505#ifdef HAS_ROOT
1506 void slot_RootEventProcessed(TObject *obj, unsigned int evt, TCanvas *)
1507 {
1508 // kMousePressEvent // TCanvas processed QEvent mousePressEvent
1509 // kMouseMoveEvent // TCanvas processed QEvent mouseMoveEvent
1510 // kMouseReleaseEvent // TCanvas processed QEvent mouseReleaseEvent
1511 // kMouseDoubleClickEvent // TCanvas processed QEvent mouseDoubleClickEvent
1512 // kKeyPressEvent // TCanvas processed QEvent keyPressEvent
1513 // kEnterEvent // TCanvas processed QEvent enterEvent
1514 // kLeaveEvent // TCanvas processed QEvent leaveEvent
1515 if (dynamic_cast<TCanvas*>(obj))
1516 return;
1517
1518 TQtWidget *tipped = static_cast<TQtWidget*>(sender());
1519
1520 if (evt==11/*kMouseReleaseEvent*/)
1521 {
1522 if (dynamic_cast<Camera*>(obj))
1523 {
1524 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1525 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1526
1527 Camera *cam = static_cast<Camera*>(obj);
1528 const int idx = cam->GetIdx(xx, yy);
1529
1530 ChoosePixel(*cam, idx);
1531 }
1532 return;
1533 }
1534
1535 if (evt==61/*kMouseDoubleClickEvent*/)
1536 {
1537 if (dynamic_cast<Camera*>(obj))
1538 {
1539 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1540 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1541
1542 Camera *cam = static_cast<Camera*>(obj);
1543 const int idx = cam->GetIdx(xx, yy);
1544
1545 cam->Toggle(idx);
1546 }
1547 return;
1548 }
1549
1550 // Find the object which will get picked by the GetObjectInfo
1551 // due to buffer overflows in many root-versions
1552 // in TH1 and TProfile we have to work around and implement
1553 // our own GetObjectInfo which make everything a bit more
1554 // complicated.
1555#if ROOT_VERSION_CODE > ROOT_VERSION(5,22,00)
1556 const char *objectInfo =
1557 obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1558#else
1559 const char *objectInfo = dynamic_cast<TH1*>(obj) ?
1560 "" : obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1561#endif
1562
1563 QString tipText;
1564 tipText += obj->GetName();
1565 tipText += " [";
1566 tipText += obj->ClassName();
1567 tipText += "]: ";
1568 tipText += objectInfo;
1569
1570 if (dynamic_cast<Camera*>(obj))
1571 {
1572 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1573 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1574
1575 Camera *cam = static_cast<Camera*>(obj);
1576 int idx = fPatch[cam->GetIdx(xx, yy)];
1577
1578 tipText+=" Patch=";
1579 tipText+=QString::number(idx);
1580 }
1581
1582
1583 fStatusBar->showMessage(tipText, 3000);
1584
1585 gSystem->ProcessEvents();
1586 //QWhatsThis::display(tipText)
1587 }
1588
1589 void slot_RootUpdate()
1590 {
1591 gSystem->ProcessEvents();
1592 QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1593 }
1594
1595 void on_fThresholdIdx_valueChanged(int idx)
1596 {
1597 Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera");
1598 ChoosePatch(*cam, idx);
1599 }
1600#endif
1601
1602 TGraph fGraphFtmTemp[4];
1603
1604 map<int, int> fPatch;
1605
1606public:
1607 FactGui() :
1608 fFtuStatus(40),
1609 fDimDNS("DIS_DNS/VERSION_NUMBER", 1, int(0), this),
1610
1611 fDimLoggerStats ("DATA_LOGGER/STATS", (void*)NULL, 0, this),
1612 fDimLoggerFilenameNight("DATA_LOGGER/FILENAME_NIGHTLY", const_cast<char*>(""), 0, this),
1613 fDimLoggerFilenameRun ("DATA_LOGGER/FILENAME_RUN", const_cast<char*>(""), 0, this),
1614 fDimLoggerNumSubs ("DATA_LOGGER/NUM_SUBS", const_cast<char*>(""), 0, this),
1615
1616 fDimFtmPassport ("FTM_CONTROL/PASSPORT", (void*)NULL, 0, this),
1617 fDimFtmTriggerCounter("FTM_CONTROL/TRIGGER_COUNTER", (void*)NULL, 0, this),
1618 fDimFtmError ("FTM_CONTROL/ERROR", (void*)NULL, 0, this),
1619 fDimFtmFtuList ("FTM_CONTROL/FTU_LIST", (void*)NULL, 0, this),
1620 fDimFtmStaticData ("FTM_CONTROL/STATIC_DATA", (void*)NULL, 0, this),
1621 fDimFtmDynamicData ("FTM_CONTROL/DYNAMIC_DATA", (void*)NULL, 0, this),
1622 fDimFtmCounter ("FTM_CONTROL/COUNTER", (void*)NULL, 0, this)
1623 {
1624 fTriggerWidget->setEnabled(false);
1625 fFtuWidget->setEnabled(false);
1626 fRatesWidget->setEnabled(false);
1627 fLoggerWidget->setEnabled(false);
1628
1629 fChatSend->setEnabled(false);
1630 fChatMessage->setEnabled(false);
1631
1632 DimClient::sendCommand("CHAT/MSG", "GUI online.");
1633 // + MessageDimRX
1634
1635 // --------------------------------------------------------------------------
1636
1637 ifstream fin("fact-trigger-all.txt");
1638
1639 int l = 0;
1640
1641 string buf;
1642 while (getline(fin, buf, '\n'))
1643 {
1644 buf = Tools::Trim(buf);
1645 if (buf[0]=='#')
1646 continue;
1647
1648 stringstream str(buf);
1649 for (int i=0; i<9; i++)
1650 {
1651 int n;
1652 str >> n;
1653
1654 fPatch[n] = l;
1655 }
1656 l++;
1657 }
1658
1659 // --------------------------------------------------------------------------
1660#ifdef HAS_ROOT
1661 TCanvas *c = fFtmTempCanv->GetCanvas();
1662 c->SetBit(TCanvas::kNoContextMenu);
1663 c->SetBorderMode(0);
1664 c->SetFrameBorderMode(0);
1665 c->SetFillColor(kWhite);
1666 c->SetRightMargin(0.03);
1667 c->SetTopMargin(0.03);
1668 c->cd();
1669
1670 TH1F h("MyFrame", "", 1000, 0, 1);//Time().RootTime()-1./24/60/60, Time().RootTime());
1671 h.SetDirectory(0);
1672 h.SetBit(TH1::kCanRebin);
1673 h.SetStats(kFALSE);
1674 h.SetMinimum(-20);
1675 h.SetMaximum(100);
1676 h.SetXTitle("Time");
1677 h.SetYTitle("Temperature / °C");
1678 h.GetXaxis()->CenterTitle();
1679 h.GetYaxis()->CenterTitle();
1680// h.GetXaxis()->SetTitleSize(1.2);
1681// h.GetYaxis()->SetTitleSize(1.2);
1682 h.DrawCopy();
1683
1684 fGraphFtmTemp[0].SetMarkerStyle(kFullDotSmall);
1685 fGraphFtmTemp[1].SetMarkerStyle(kFullDotSmall);
1686 fGraphFtmTemp[2].SetMarkerStyle(kFullDotSmall);
1687 fGraphFtmTemp[3].SetMarkerStyle(kFullDotSmall);
1688
1689 fGraphFtmTemp[1].SetLineColor(kBlue);
1690 fGraphFtmTemp[2].SetLineColor(kRed);
1691 fGraphFtmTemp[3].SetLineColor(kGreen);
1692
1693 fGraphFtmTemp[1].SetMarkerColor(kBlue);
1694 fGraphFtmTemp[2].SetMarkerColor(kRed);
1695 fGraphFtmTemp[3].SetMarkerColor(kGreen);
1696
1697 fGraphFtmTemp[0].Draw("LP");
1698 fGraphFtmTemp[1].Draw("LP");
1699 fGraphFtmTemp[2].Draw("LP");
1700 fGraphFtmTemp[3].Draw("LP");
1701
1702 // --------------------------------------------------------------------------
1703
1704 c = fRatesCanv->GetCanvas();
1705 c->SetBit(TCanvas::kNoContextMenu);
1706 c->SetBorderMode(0);
1707 c->SetFrameBorderMode(0);
1708 c->SetFillColor(kWhite);
1709 c->cd();
1710
1711 Camera *cam = new Camera;
1712 cam->SetBit(kCanDelete);
1713 cam->Draw();
1714
1715 ChoosePixel(*cam, 1);
1716
1717// QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1718
1719 //widget->setMouseTracking(true);
1720 //widget->EnableSignalEvents(kMouseMoveEvent);
1721
1722 fFtmTempCanv->setMouseTracking(true);
1723 fFtmTempCanv->EnableSignalEvents(kMouseMoveEvent);
1724
1725 fRatesCanv->setMouseTracking(true);
1726 fRatesCanv->EnableSignalEvents(kMouseMoveEvent|kMouseReleaseEvent|kMouseDoubleClickEvent);
1727
1728 connect(fRatesCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1729 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1730 connect(fFtmTempCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1731 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1732#endif
1733 }
1734
1735 ~FactGui()
1736 {
1737 UnsubscribeAllServers();
1738 }
1739};
1740
1741#endif
Note: See TracBrowser for help on using the repository browser.