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

Last change on this file since 10644 was 10633, checked in by tbretz, 14 years ago
Fixed case of sclaing in Rates plot == 0
File size: 53.4 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 // ===================== Services and Commands ==========================
345
346 QStandardItem *AddServiceItem(const std::string &server, const std::string &service, bool iscmd)
347 {
348 QListView *servers = iscmd ? fDimCmdServers : fDimSvcServers;
349 QListView *services = iscmd ? fDimCmdCommands : fDimSvcServices;
350 QListView *description = iscmd ? fDimCmdDescription : fDimSvcDescription;
351
352 QStandardItemModel *m = dynamic_cast<QStandardItemModel*>(servers->model());
353 if (!m)
354 {
355 m = new QStandardItemModel(this);
356 servers->setModel(m);
357 services->setModel(m);
358 description->setModel(m);
359 }
360
361 QList<QStandardItem*> l = m->findItems(server.c_str());
362
363 if (l.size()>1)
364 {
365 cout << "hae" << endl;
366 return 0;
367 }
368
369 QStandardItem *col = l.size()==0 ? NULL : l[0];
370
371 if (!col)
372 {
373 col = new QStandardItem(server.c_str());
374 m->appendRow(col);
375
376 if (!services->rootIndex().isValid())
377 {
378 services->setRootIndex(col->index());
379 servers->setCurrentIndex(col->index());
380 }
381 }
382
383 QStandardItem *item = 0;
384 for (int i=0; i<col->rowCount(); i++)
385 {
386 QStandardItem *coli = col->child(i);
387 if (coli->text().toStdString()==service)
388 return coli;
389 }
390
391 item = new QStandardItem(service.c_str());
392 col->appendRow(item);
393 col->sortChildren(0);
394
395 if (!description->rootIndex().isValid())
396 {
397 description->setRootIndex(item->index());
398 services->setCurrentIndex(item->index());
399 }
400
401 if (!iscmd)
402 item->setCheckable(true);
403
404 return item;
405 }
406
407 void AddDescription(QStandardItem *item, const vector<Description> &vec)
408 {
409 if (!item)
410 return;
411 if (vec.size()==0)
412 return;
413
414 item->setToolTip(vec[0].comment.c_str());
415
416 const string str = Description::GetHtmlDescription(vec);
417
418 QStandardItem *desc = new QStandardItem(str.c_str());
419 desc->setSelectable(false);
420 item->setChild(0, 0, desc);
421 }
422
423 void AddServer(const std::string &s)
424 {
425 DimNetwork::AddServer(s);
426
427 QApplication::postEvent(this,
428 new FunctionEvent(boost::bind(&FactGui::handleAddServer, this, s)));
429 }
430
431 void RemoveServer(const std::string &s)
432 {
433 UnsubscribeServer(s);
434
435 DimNetwork::RemoveServer(s);
436
437 QApplication::postEvent(this,
438 new FunctionEvent(boost::bind(&FactGui::handleRemoveServer, this, s)));
439 }
440
441 void RemoveAllServers()
442 {
443 UnsubscribeAllServers();
444
445 vector<string> v = GetServerList();
446 for (vector<string>::iterator i=v.begin(); i<v.end(); i++)
447 QApplication::postEvent(this,
448 new FunctionEvent(boost::bind(&FactGui::handleStateOffline, this, *i)));
449
450 DimNetwork::RemoveAllServers();
451
452 QApplication::postEvent(this,
453 new FunctionEvent(boost::bind(&FactGui::handleRemoveAllServers, this)));
454 }
455
456 void AddService(const std::string &server, const std::string &service, const std::string &fmt, bool iscmd)
457 {
458 QApplication::postEvent(this,
459 new FunctionEvent(boost::bind(&FactGui::handleAddService, this, server, service, fmt, iscmd)));
460 }
461
462 void RemoveService(const std::string &server, const std::string &service, bool iscmd)
463 {
464 if (fServices.find(server+'/'+service)!=fServices.end())
465 UnsubscribeService(server+'/'+service);
466
467 QApplication::postEvent(this,
468 new FunctionEvent(boost::bind(&FactGui::handleRemoveService, this, server, service, iscmd)));
469 }
470
471 void RemoveAllServices(const std::string &server)
472 {
473 UnsubscribeServer(server);
474
475 QApplication::postEvent(this,
476 new FunctionEvent(boost::bind(&FactGui::handleRemoveAllServices, this, server)));
477 }
478
479 void AddDescription(const std::string &server, const std::string &service, const vector<Description> &vec)
480 {
481 QApplication::postEvent(this,
482 new FunctionEvent(boost::bind(&FactGui::handleAddDescription, this, server, service, vec)));
483 }
484
485 // ======================================================================
486
487 void handleAddServer(const std::string &server)
488 {
489 const State s = GetState(server, GetCurrentState(server));
490 handleStateChanged(Time(), server, s);
491 }
492
493 void handleRemoveServer(const string &server)
494 {
495 handleStateOffline(server);
496 handleRemoveAllServices(server);
497 }
498
499 void handleRemoveAllServers()
500 {
501 QStandardItemModel *m = 0;
502 if ((m=dynamic_cast<QStandardItemModel*>(fDimCmdServers->model())))
503 m->removeRows(0, m->rowCount());
504
505 if ((m = dynamic_cast<QStandardItemModel*>(fDimSvcServers->model())))
506 m->removeRows(0, m->rowCount());
507 }
508
509 void handleAddService(const std::string &server, const std::string &service, const std::string &/*fmt*/, bool iscmd)
510 {
511 QStandardItem *item = AddServiceItem(server, service, iscmd);
512 const vector<Description> v = GetDescription(server, service);
513 AddDescription(item, v);
514 }
515
516 void handleRemoveService(const std::string &server, const std::string &service, bool iscmd)
517 {
518 QListView *servers = iscmd ? fDimCmdServers : fDimSvcServers;
519
520 QStandardItemModel *m = dynamic_cast<QStandardItemModel*>(servers->model());
521 if (!m)
522 return;
523
524 QList<QStandardItem*> l = m->findItems(server.c_str());
525 if (l.size()!=1)
526 return;
527
528 for (int i=0; i<l[0]->rowCount(); i++)
529 {
530 QStandardItem *row = l[0]->child(i);
531 if (row->text().toStdString()==service)
532 {
533 l[0]->removeRow(row->index().row());
534 return;
535 }
536 }
537 }
538
539 void handleRemoveAllServices(const std::string &server)
540 {
541 QStandardItemModel *m = 0;
542 if ((m=dynamic_cast<QStandardItemModel*>(fDimCmdServers->model())))
543 {
544 QList<QStandardItem*> l = m->findItems(server.c_str());
545 if (l.size()==1)
546 m->removeRow(l[0]->index().row());
547 }
548
549 if ((m = dynamic_cast<QStandardItemModel*>(fDimSvcServers->model())))
550 {
551 QList<QStandardItem*> l = m->findItems(server.c_str());
552 if (l.size()==1)
553 m->removeRow(l[0]->index().row());
554 }
555 }
556
557 void handleAddDescription(const std::string &server, const std::string &service, const vector<Description> &vec)
558 {
559 const bool iscmd = IsCommand(server, service)==true;
560
561 QStandardItem *item = AddServiceItem(server, service, iscmd);
562 AddDescription(item, vec);
563 }
564
565 // ======================================================================
566
567 void SubscribeService(const string &service)
568 {
569 if (fServices.find(service)!=fServices.end())
570 {
571 cout << "ERROR - We are already subscribed to " << service << endl;
572 return;
573 }
574
575 fServices[service] = new DimStampedInfo(service.c_str(), (void*)NULL, 0, this);
576 }
577
578 void UnsubscribeService(const string &service)
579 {
580 const map<string,DimInfo*>::iterator i=fServices.find(service);
581
582 if (i==fServices.end())
583 {
584 cout << "ERROR - We are not subscribed to " << service << endl;
585 return;
586 }
587
588 delete i->second;
589
590 fServices.erase(i);
591 }
592
593 void UnsubscribeServer(const string &server)
594 {
595 for (map<string,DimInfo*>::iterator i=fServices.begin();
596 i!=fServices.end(); i++)
597 if (i->first.substr(0, server.length()+1)==server+'/')
598 {
599 delete i->second;
600 fServices.erase(i);
601 }
602 }
603
604 void UnsubscribeAllServers()
605 {
606 for (map<string,DimInfo*>::iterator i=fServices.begin();
607 i!=fServices.end(); i++)
608 delete i->second;
609
610 fServices.clear();
611 }
612
613 // ======================================================================
614
615 struct DimData
616 {
617 Time time;
618 int qos;
619 string name;
620 string format;
621 vector<char> data;
622
623 DimInfo *info; // this is ONLY for a fast check of the type of the DimData!!
624
625 DimData(DimInfo *inf) :
626 qos(inf->getQuality()),
627 name(inf->getName()),
628 format(inf->getFormat()),
629 data(inf->getString(), inf->getString()+inf->getSize()),
630 info(inf)
631 {
632 // Must be called in exactly this order!
633 const int tsec = inf->getTimestamp();
634 const int tms = inf->getTimestampMillisecs();
635
636 time = Time(tsec, tms*1000);
637 }
638
639 template<typename T>
640 T get() const { return *reinterpret_cast<const T*>(data.data()); }
641
642 vector<char> vec(int b) const { return vector<char>(data.begin()+b, data.end()); }
643 string str(unsigned int b) const { return b>=data.size()?string():string(data.data()+b, data.size()-b); }
644 const char *c_str() const { return (char*)data.data(); }
645
646 vector<boost::any> any() const
647 {
648 const Converter conv(format);
649 conv.Print();
650 return conv.GetAny(data.data(), data.size());
651 }
652 int size() const { return data.size(); }
653 const void *ptr() const { return data.data(); }
654 };
655
656 // ======================= DNS ==========================================
657
658 void handleDimDNS(const DimData &d)
659 {
660 const int version = d.get<unsigned int>();
661
662 ostringstream str;
663 str << "V" << version/100 << 'r' << version%100;
664
665 if (version==0)
666 fStatusDNSLed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
667 else
668 fStatusDNSLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
669
670 fStatusDNSLabel->setText(version==0?"Offline":str.str().c_str());
671 fStatusDNSLabel->setToolTip(version==0?"No connection to DIM DNS.":"Connection to DIM DNS established.");
672 }
673
674
675 // ======================= Logger =======================================
676
677 void handleLoggerStats(const DimData &d)
678 {
679 const bool connected = d.size()!=0;
680
681 fLoggerET->setEnabled(connected);
682 fLoggerRate->setEnabled(connected);
683 fLoggerWritten->setEnabled(connected);
684 fLoggerFreeSpace->setEnabled(connected);
685 fLoggerSpaceLeft->setEnabled(connected);
686
687 if (!connected)
688 return;
689
690 const uint64_t *vals = reinterpret_cast<const uint64_t*>(d.ptr());
691
692 const size_t written = vals[0];
693 const size_t space = vals[1];
694 const size_t rate = vals[2];
695
696 fLoggerFreeSpace->setSuffix(" MB");
697 fLoggerFreeSpace->setDecimals(0);
698 fLoggerFreeSpace->setValue(space*1e-6);
699
700 if (space> 1000000) // > 1GB
701 {
702 fLoggerFreeSpace->setSuffix(" GB");
703 fLoggerFreeSpace->setDecimals(2);
704 fLoggerFreeSpace->setValue(space*1e-9);
705 }
706 if (space>= 3000000) // >= 3GB
707 {
708 fLoggerFreeSpace->setSuffix(" GB");
709 fLoggerFreeSpace->setDecimals(1);
710 fLoggerFreeSpace->setValue(space*1e-9);
711 }
712 if (space>=100000000) // >= 100GB
713 {
714 fLoggerFreeSpace->setSuffix(" GB");
715 fLoggerFreeSpace->setDecimals(0);
716 fLoggerFreeSpace->setValue(space*1e-9);
717 }
718
719 fLoggerET->setTime(QTime().addSecs(rate>0?space/rate:0));
720 fLoggerRate->setValue(rate*1e-3); // kB/s
721 fLoggerWritten->setValue(written*1e-6);
722
723 fLoggerRate->setSuffix(" kB/s");
724 fLoggerRate->setDecimals(2);
725 fLoggerRate->setValue(rate*1e-3);
726 if (rate> 2000) // > 2kB/s
727 {
728 fLoggerRate->setSuffix(" kB/s");
729 fLoggerRate->setDecimals(1);
730 fLoggerRate->setValue(rate*1e-3);
731 }
732 if (rate>=100000) // >100kB/s
733 {
734 fLoggerRate->setSuffix(" kB/s");
735 fLoggerRate->setDecimals(0);
736 fLoggerRate->setValue(rate*1e-3);
737 }
738 if (rate>=1000000) // >100kB/s
739 {
740 fLoggerRate->setSuffix(" MB/s");
741 fLoggerRate->setDecimals(2);
742 fLoggerRate->setValue(rate*1e-6);
743 }
744 if (rate>=10000000) // >1MB/s
745 {
746 fLoggerRate->setSuffix(" MB/s");
747 fLoggerRate->setDecimals(1);
748 fLoggerRate->setValue(rate*1e-6);
749 }
750 if (rate>=100000000) // >10MB/s
751 {
752 fLoggerRate->setSuffix(" MB/s");
753 fLoggerRate->setDecimals(0);
754 fLoggerRate->setValue(rate*1e-6);
755 }
756
757 if (space/1000000>static_cast<size_t>(fLoggerSpaceLeft->maximum()))
758 fLoggerSpaceLeft->setValue(fLoggerSpaceLeft->maximum()); // GB
759 else
760 fLoggerSpaceLeft->setValue(space/1000000); // MB
761 }
762
763 void handleLoggerFilenameNight(const DimData &d)
764 {
765 const bool connected = d.size()!=0;
766
767 fLoggerFilenameNight->setEnabled(connected);
768 if (!connected)
769 return;
770
771 fLoggerFilenameNight->setText(d.c_str()+4);
772
773 const uint32_t files = d.get<uint32_t>();
774
775 if (files&1)
776 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
777 else
778 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
779
780 if (files&2)
781 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
782 else
783 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
784
785 if (files&4)
786 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
787 else
788 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
789 }
790
791 void handleLoggerFilenameRun(const DimData &d)
792 {
793 const bool connected = d.size()!=0;
794
795 fLoggerFilenameRun->setEnabled(connected);
796 if (!connected)
797 return;
798
799 fLoggerFilenameRun->setText(d.c_str()+4);
800
801 const uint32_t files = d.get<uint32_t>();
802
803 if (files&1)
804 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
805 else
806 fLoggerLedLog->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
807
808 if (files&2)
809 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
810 else
811 fLoggerLedRep->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
812
813 if (files&4)
814 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
815 else
816 fLoggerLedFits->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
817 }
818
819 void handleLoggerNumSubs(const DimData &d)
820 {
821 const bool connected = d.size()!=0;
822
823 fLoggerSubscriptions->setEnabled(connected);
824 fLoggerOpenFiles->setEnabled(connected);
825 if (!connected)
826 return;
827
828 const uint32_t *vals = reinterpret_cast<const uint32_t*>(d.ptr());
829
830 fLoggerSubscriptions->setValue(vals[0]);
831 fLoggerOpenFiles->setValue(vals[1]);
832 }
833
834 // ===================== FTM ============================================
835
836 void handleFtmTriggerCounter(const DimData &d)
837 {
838 if (d.size()==0)
839 return;
840
841 if (d.size()!=sizeof(FTM::DimTriggerCounter))
842 {
843 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimTriggerCounter) << endl;
844 return;
845 }
846
847 const FTM::DimTriggerCounter &sdata = *reinterpret_cast<const FTM::DimTriggerCounter*>(d.ptr());
848
849 fFtmTime->setText(QString::number(sdata.fTimeStamp));
850 fTriggerCounter->setText(QString::number(sdata.fTriggerCounter));
851 }
852
853 void handleFtmCounter(const DimData &d)
854 {
855 if (d.size()==0)
856 return;
857
858 if (d.size()!=sizeof(uint32_t)*6)
859 {
860 cout << "Size mismatch: " << d.size() << " " << sizeof(uint32_t)*6 << endl;
861 return;
862 }
863
864 const uint32_t *sdata = reinterpret_cast<const uint32_t*>(d.ptr());
865
866 fFtmCounterH->setValue(sdata[0]);
867 fFtmCounterS->setValue(sdata[1]);
868 fFtmCounterD->setValue(sdata[2]);
869 fFtmCounterF->setValue(sdata[3]);
870 fFtmCounterE->setValue(sdata[4]);
871 fFtmCounterR->setValue(sdata[5]);
872 }
873
874 void handleFtmDynamicData(const DimData &d)
875 {
876 if (d.size()==0)
877 return;
878
879 if (d.size()!=sizeof(FTM::DimDynamicData))
880 {
881 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimDynamicData) << endl;
882 return;
883 }
884
885 const FTM::DimDynamicData &sdata = *reinterpret_cast<const FTM::DimDynamicData*>(d.ptr());
886
887 fFtmTime->setText(QString::number(sdata.fTimeStamp));
888 fOnTime->setText(QString::number(sdata.fOnTimeCounter));
889
890 fFtmTemp0->setValue(sdata.fTempSensor[0]*0.1);
891 fFtmTemp1->setValue(sdata.fTempSensor[1]*0.1);
892 fFtmTemp2->setValue(sdata.fTempSensor[2]*0.1);
893 fFtmTemp3->setValue(sdata.fTempSensor[3]*0.1);
894
895
896 // ----------------------------------------------
897#ifdef HAS_ROOT
898 TCanvas *c = fFtmTempCanv->GetCanvas();
899
900 static int cntr = 0;
901 double_t tm = cntr++;//Time().RootTime();
902
903 TH1 *h = (TH1*)c->FindObject("MyFrame");
904 h->FindBin(tm);
905
906 fGraphFtmTemp[0].SetPoint(fGraphFtmTemp[0].GetN(), tm, sdata.fTempSensor[0]*0.1);
907 fGraphFtmTemp[1].SetPoint(fGraphFtmTemp[1].GetN(), tm, sdata.fTempSensor[1]*0.1);
908 fGraphFtmTemp[2].SetPoint(fGraphFtmTemp[2].GetN(), tm, sdata.fTempSensor[2]*0.1);
909 fGraphFtmTemp[3].SetPoint(fGraphFtmTemp[3].GetN(), tm, sdata.fTempSensor[3]*0.1);
910
911 c->Modified();
912 c->Update();
913
914 // ----------------------------------------------
915
916 valarray<double> dat(0., 1438);
917
918 for (int i=0; i<1438; i++)
919 dat[i] = sdata.fRatePatch[fPatch[i]];
920
921 c = fRatesCanv->GetCanvas();
922 Camera *cam = (Camera*)c->FindObject("Camera");
923
924 cam->SetData(dat);
925
926 c->Modified();
927 c->Update();
928#endif
929 }
930
931 FTM::DimStaticData fFtmStaticData;
932
933 void SetFtuLed(int idx, int counter)
934 {
935 if (counter==0)
936 counter = 3;
937
938 if (counter==-1)
939 counter = 0;
940
941 switch (counter)
942 {
943 case 0:
944 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
945 break;
946
947 case 1:
948 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
949 break;
950
951 case 2:
952 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/orange circle 1.png"));
953 break;
954
955 case 3:
956 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
957 break;
958 }
959
960 fFtuStatus[idx] = counter;
961 }
962
963 void SetFtuStatusLed()
964 {
965 const int max = fFtuStatus.max();
966
967 switch (max)
968 {
969 case 0:
970 fStatusFTULed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
971 fStatusFTULabel->setText("All disabled");
972 fStatusFTULabel->setToolTip("All FTUs are disabled");
973 break;
974
975 case 1:
976 fStatusFTULed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
977 fStatusFTULabel->setToolTip("Communication with FTU is smooth.");
978 fStatusFTULabel->setText("Ok");
979 break;
980
981 case 2:
982 fStatusFTULed->setIcon(QIcon(":/Resources/icons/orange circle 1.png"));
983 fStatusFTULabel->setText("Warning");
984 fStatusFTULabel->setToolTip("At least one FTU didn't answer immediately");
985 break;
986
987 case 3:
988 fStatusFTULed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
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);
1041 else
1042 {
1043 if (fFtuStatus[i]==0)
1044 SetFtuLed(i, 1);
1045 }
1046 fFtuLED[i]->setChecked(false);
1047 }
1048 SetFtuStatusLed();
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);
1125
1126 SetFtuStatusLed();
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);
1137 SetFtuStatusLed();
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 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1161 if (s.index==FTM::kDisconnected) // Dim connection / FTM disconnected
1162 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1163 if (s.index==FTM::kConnected || s.index==FTM::kIdle) // Dim connection / FTM connected
1164 {
1165 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1166 enable = true;
1167 }
1168
1169 fTriggerWidget->setEnabled(enable);
1170 fFtuWidget->setEnabled(enable);
1171 fRatesWidget->setEnabled(enable);
1172
1173 if (!enable)
1174 {
1175 fStatusFTULed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
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 fStatusFADLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1188 if (s.index==FTM::kDisconnected) // Dim connection / FTM disconnected
1189 fStatusFADLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1190 if (s.index==FTM::kConnected) // Dim connection / FTM connected
1191 fStatusFADLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
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 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1203 if (s.index<-1) // Offline
1204 {
1205 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1206 enable = false;
1207 }
1208 if (s.index>=0x100) // Error
1209 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
1210 if (s.index==40) // Logging
1211 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
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 if (fChatOnline) // Dim connection / FTM connected
1223 fStatusChatLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1224 else
1225 fStatusChatLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1226
1227 fChatSend->setEnabled(fChatOnline);
1228 fChatMessage->setEnabled(fChatOnline);
1229 }
1230
1231 if (server=="SCHEDULER")
1232 {
1233 fStatusSchedulerLabel->setText(s.name.c_str());
1234
1235 if (s.index>=0) // Dim connection / FTM connected
1236 fStatusSchedulerLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1237 else
1238 fStatusSchedulerLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1239 }
1240 }
1241
1242 void handleStateOffline(const string &server)
1243 {
1244 handleStateChanged(Time(), server, State(-2, "Offline", "No connection via DIM."));
1245 }
1246
1247 void on_fTabWidget_currentChanged(int which)
1248 {
1249 if (fTabWidget->tabText(which)=="Chat")
1250 fTabWidget->setTabIcon(which, QIcon());
1251 }
1252
1253 void handleWrite(const Time &time, const string &text, int qos)
1254 {
1255 stringstream out;
1256
1257 if (text.substr(0, 6)=="CHAT: ")
1258 {
1259 out << "<font size='-1' color='navy'>[<B>";
1260 out << Time::fmt("%H:%M:%S") << time << "</B>]</FONT> ";
1261 out << text.substr(6);
1262 fChatText->append(out.str().c_str());
1263
1264 if (fTabWidget->tabText(fTabWidget->currentIndex())=="Chat")
1265 return;
1266
1267 static int num = 0;
1268 if (num++<2)
1269 return;
1270
1271 for (int i=0; i<fTabWidget->count(); i++)
1272 if (fTabWidget->tabText(i)=="Chat")
1273 {
1274 fTabWidget->setTabIcon(i, QIcon(":/Resources/icons/warning 3.png"));
1275 break;
1276 }
1277
1278 return;
1279 }
1280
1281
1282 out << "<font style='font-family:monospace' color='";
1283
1284 switch (qos)
1285 {
1286 case kMessage: out << "black"; break;
1287 case kInfo: out << "green"; break;
1288 case kWarn: out << "#FF6600"; break;
1289 case kError: out << "maroon"; break;
1290 case kFatal: out << "maroon"; break;
1291 case kDebug: out << "navy"; break;
1292 default: out << "navy"; break;
1293 }
1294 out << "'>" << time.GetAsStr() << " - " << text << "</font>";
1295
1296 fLogText->append(out.str().c_str());
1297
1298 if (qos>=kWarn)
1299 fTextEdit->append(out.str().c_str());
1300 }
1301
1302 void IndicateStateChange(const Time &time, const std::string &server)
1303 {
1304 const State s = GetState(server, GetCurrentState(server));
1305
1306 QApplication::postEvent(this,
1307 new FunctionEvent(boost::bind(&FactGui::handleStateChanged, this, time, server, s)));
1308 }
1309
1310 int Write(const Time &time, const string &txt, int qos)
1311 {
1312 QApplication::postEvent(this,
1313 new FunctionEvent(boost::bind(&FactGui::handleWrite, this, time, txt, qos)));
1314
1315 return 0;
1316 }
1317
1318 // ====================== Dim infoHandler================================
1319
1320 void handleDimService(const string &txt)
1321 {
1322 fDimSvcText->append(txt.c_str());
1323 }
1324
1325 void infoHandlerService(DimInfo &info)
1326 {
1327 const string fmt = string(info.getFormat()).empty() ? "C" : info.getFormat();
1328
1329 stringstream dummy;
1330 const Converter conv(dummy, fmt, false);
1331
1332 const Time tm(info.getTimestamp(), info.getTimestampMillisecs()*1000);
1333
1334 stringstream out;
1335 out << "<font size'-1' color='navy'>[" << Time::fmt("%H:%M:%S.%f") << tm << "]</font> <B>" << info.getName() << "</B> - ";
1336
1337 bool iserr = true;
1338 if (!conv)
1339 {
1340 out << "Compilation of format string '" << fmt << "' failed!";
1341 }
1342 else
1343 {
1344 try
1345 {
1346 const string dat = conv.GetString(info.getData(), info.getSize());
1347 out << dat;
1348 iserr = false;
1349 }
1350 catch (const runtime_error &e)
1351 {
1352 out << "Conversion to string failed!<pre>" << e.what() << "</pre>";
1353 }
1354 }
1355
1356 // srand(hash<string>()(string(info.getName())));
1357 // int bg = rand()&0xffffff;
1358
1359 int bg = hash<string>()(string(info.getName()));
1360
1361 // allow only light colors
1362 bg = ~(bg&0x1f1f1f)&0xffffff;
1363
1364 if (iserr)
1365 bg = 0xffffff;
1366
1367 stringstream bgcol;
1368 bgcol << hex << setfill('0') << setw(6) << bg;
1369
1370 const string col = iserr ? "red" : "black";
1371 const string str = "<table width='100%' bgcolor=#"+bgcol.str()+"><tr><td><font color='"+col+"'>"+out.str()+"</font></td></tr></table>";
1372
1373 QApplication::postEvent(this,
1374 new FunctionEvent(boost::bind(&FactGui::handleDimService, this, str)));
1375 }
1376
1377 void PostInfoHandler(void (FactGui::*handler)(const DimData&))
1378 {
1379 QApplication::postEvent(this,
1380 new FunctionEvent(boost::bind(handler, this, DimData(getInfo()))));
1381 }
1382
1383 void infoHandler()
1384 {
1385 // Initialize the time-stamp (what a weird workaround...)
1386 if (getInfo())
1387 getInfo()->getTimestamp();
1388
1389 if (getInfo()==&fDimDNS)
1390 return PostInfoHandler(&FactGui::handleDimDNS);
1391
1392 cout << "HandleDimInfo " << getInfo()->getName() << endl;
1393
1394 if (getInfo()==&fDimLoggerStats)
1395 return PostInfoHandler(&FactGui::handleLoggerStats);
1396
1397 if (getInfo()==&fDimLoggerFilenameNight)
1398 return PostInfoHandler(&FactGui::handleLoggerFilenameNight);
1399
1400 if (getInfo()==&fDimLoggerNumSubs)
1401 return PostInfoHandler(&FactGui::handleLoggerNumSubs);
1402
1403 if (getInfo()==&fDimLoggerFilenameRun)
1404 return PostInfoHandler(&FactGui::handleLoggerFilenameRun);
1405
1406 if (getInfo()==&fDimFtmTriggerCounter)
1407 return PostInfoHandler(&FactGui::handleFtmTriggerCounter);
1408
1409 if (getInfo()==&fDimFtmCounter)
1410 return PostInfoHandler(&FactGui::handleFtmCounter);
1411
1412 if (getInfo()==&fDimFtmDynamicData)
1413 return PostInfoHandler(&FactGui::handleFtmDynamicData);
1414
1415 if (getInfo()==&fDimFtmPassport)
1416 return PostInfoHandler(&FactGui::handleFtmPassport);
1417
1418 if (getInfo()==&fDimFtmFtuList)
1419 return PostInfoHandler(&FactGui::handleFtmFtuList);
1420
1421 if (getInfo()==&fDimFtmStaticData)
1422 return PostInfoHandler(&FactGui::handleFtmStaticData);
1423
1424 if (getInfo()==&fDimFtmError)
1425 return PostInfoHandler(&FactGui::handleFtmError);
1426
1427 for (map<string,DimInfo*>::iterator i=fServices.begin(); i!=fServices.end(); i++)
1428 if (i->second==getInfo())
1429 {
1430 infoHandlerService(*i->second);
1431 return;
1432 }
1433
1434 DimNetwork::infoHandler();
1435 }
1436
1437
1438 // ======================================================================
1439
1440 bool event(QEvent *evt)
1441 {
1442 if (dynamic_cast<FunctionEvent*>(evt))
1443 return static_cast<FunctionEvent*>(evt)->Exec();
1444
1445 if (dynamic_cast<CheckBoxEvent*>(evt))
1446 {
1447 const QStandardItem &item = static_cast<CheckBoxEvent*>(evt)->item;
1448 const QStandardItem *par = item.parent();
1449 if (par)
1450 {
1451 const QString server = par->text();
1452 const QString service = item.text();
1453
1454 const string s = (server+'/'+service).toStdString();
1455
1456 if (item.checkState()==Qt::Checked)
1457 SubscribeService(s);
1458 else
1459 UnsubscribeService(s);
1460 }
1461 }
1462
1463 return MainWindow::event(evt); // unrecognized
1464 }
1465
1466 void on_fDimCmdSend_clicked()
1467 {
1468 const QString server = fDimCmdServers->currentIndex().data().toString();
1469 const QString command = fDimCmdCommands->currentIndex().data().toString();
1470 const QString arguments = fDimCmdLineEdit->displayText();
1471
1472 // FIXME: Sending a command exactly when the info Handler changes
1473 // the list it might lead to confusion.
1474 try
1475 {
1476 SendDimCommand(server.toStdString(), command.toStdString()+" "+arguments.toStdString());
1477 fTextEdit->append("<font color='green'>Command '"+server+'/'+command+"' successfully emitted.</font>");
1478 fDimCmdLineEdit->clear();
1479 }
1480 catch (const runtime_error &e)
1481 {
1482 stringstream txt;
1483 txt << e.what();
1484
1485 string buffer;
1486 while (getline(txt, buffer, '\n'))
1487 fTextEdit->append(("<font color='red'><pre>"+buffer+"</pre></font>").c_str());
1488 }
1489 }
1490 void ChoosePatch(Camera &cam, int idx)
1491 {
1492 cam.Reset();
1493
1494 fThresholdIdx->setValue(idx);
1495 fThresholdVal->setValue(fFtmStaticData.fThreshold[idx<0?0:idx]);
1496
1497 if (idx<0)
1498 return;
1499
1500 for (unsigned int i=0; i<fPatch.size(); i++)
1501 if (fPatch[i]==idx)
1502 cam.SetBold(i);
1503 }
1504
1505 void ChoosePixel(Camera &cam, int idx)
1506 {
1507 cam.SetWhite(idx);
1508 ChoosePatch(cam, fPatch[idx]);
1509 }
1510
1511#ifdef HAS_ROOT
1512 void slot_RootEventProcessed(TObject *obj, unsigned int evt, TCanvas *)
1513 {
1514 // kMousePressEvent // TCanvas processed QEvent mousePressEvent
1515 // kMouseMoveEvent // TCanvas processed QEvent mouseMoveEvent
1516 // kMouseReleaseEvent // TCanvas processed QEvent mouseReleaseEvent
1517 // kMouseDoubleClickEvent // TCanvas processed QEvent mouseDoubleClickEvent
1518 // kKeyPressEvent // TCanvas processed QEvent keyPressEvent
1519 // kEnterEvent // TCanvas processed QEvent enterEvent
1520 // kLeaveEvent // TCanvas processed QEvent leaveEvent
1521 if (dynamic_cast<TCanvas*>(obj))
1522 return;
1523
1524 TQtWidget *tipped = static_cast<TQtWidget*>(sender());
1525
1526 if (evt==11/*kMouseReleaseEvent*/)
1527 {
1528 if (dynamic_cast<Camera*>(obj))
1529 {
1530 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1531 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1532
1533 Camera *cam = static_cast<Camera*>(obj);
1534 const int idx = cam->GetIdx(xx, yy);
1535
1536 ChoosePixel(*cam, idx);
1537 }
1538 return;
1539 }
1540
1541 if (evt==61/*kMouseDoubleClickEvent*/)
1542 {
1543 if (dynamic_cast<Camera*>(obj))
1544 {
1545 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1546 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1547
1548 Camera *cam = static_cast<Camera*>(obj);
1549 const int idx = cam->GetIdx(xx, yy);
1550
1551 cam->Toggle(idx);
1552 }
1553 return;
1554 }
1555
1556 // Find the object which will get picked by the GetObjectInfo
1557 // due to buffer overflows in many root-versions
1558 // in TH1 and TProfile we have to work around and implement
1559 // our own GetObjectInfo which make everything a bit more
1560 // complicated.
1561#if ROOT_VERSION_CODE > ROOT_VERSION(5,22,00)
1562 const char *objectInfo =
1563 obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1564#else
1565 const char *objectInfo = dynamic_cast<TH1*>(obj) ?
1566 "" : obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1567#endif
1568
1569 QString tipText;
1570 tipText += obj->GetName();
1571 tipText += " [";
1572 tipText += obj->ClassName();
1573 tipText += "]: ";
1574 tipText += objectInfo;
1575
1576 if (dynamic_cast<Camera*>(obj))
1577 {
1578 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1579 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1580
1581 Camera *cam = static_cast<Camera*>(obj);
1582 int idx = fPatch[cam->GetIdx(xx, yy)];
1583
1584 tipText+=" Patch=";
1585 tipText+=QString::number(idx);
1586 }
1587
1588
1589 fStatusBar->showMessage(tipText, 3000);
1590
1591 gSystem->ProcessEvents();
1592 //QWhatsThis::display(tipText)
1593 }
1594
1595 void slot_RootUpdate()
1596 {
1597 gSystem->ProcessEvents();
1598 QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1599 }
1600
1601 void on_fThresholdIdx_valueChanged(int idx)
1602 {
1603 Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera");
1604 ChoosePatch(*cam, idx);
1605 }
1606#endif
1607
1608 TGraph fGraphFtmTemp[4];
1609
1610 map<int, int> fPatch;
1611
1612public:
1613 FactGui() :
1614 fFtuStatus(40),
1615 fDimDNS("DIS_DNS/VERSION_NUMBER", 1, int(0), this),
1616
1617 fDimLoggerStats ("DATA_LOGGER/STATS", (void*)NULL, 0, this),
1618 fDimLoggerFilenameNight("DATA_LOGGER/FILENAME_NIGHTLY", const_cast<char*>(""), 0, this),
1619 fDimLoggerFilenameRun ("DATA_LOGGER/FILENAME_RUN", const_cast<char*>(""), 0, this),
1620 fDimLoggerNumSubs ("DATA_LOGGER/NUM_SUBS", const_cast<char*>(""), 0, this),
1621
1622 fDimFtmPassport ("FTM_CONTROL/PASSPORT", (void*)NULL, 0, this),
1623 fDimFtmTriggerCounter("FTM_CONTROL/TRIGGER_COUNTER", (void*)NULL, 0, this),
1624 fDimFtmError ("FTM_CONTROL/ERROR", (void*)NULL, 0, this),
1625 fDimFtmFtuList ("FTM_CONTROL/FTU_LIST", (void*)NULL, 0, this),
1626 fDimFtmStaticData ("FTM_CONTROL/STATIC_DATA", (void*)NULL, 0, this),
1627 fDimFtmDynamicData ("FTM_CONTROL/DYNAMIC_DATA", (void*)NULL, 0, this),
1628 fDimFtmCounter ("FTM_CONTROL/COUNTER", (void*)NULL, 0, this)
1629 {
1630 fTriggerWidget->setEnabled(false);
1631 fFtuWidget->setEnabled(false);
1632 fRatesWidget->setEnabled(false);
1633 fLoggerWidget->setEnabled(false);
1634
1635 fChatSend->setEnabled(false);
1636 fChatMessage->setEnabled(false);
1637
1638 DimClient::sendCommand("CHAT/MSG", "GUI online.");
1639 // + MessageDimRX
1640
1641 // --------------------------------------------------------------------------
1642
1643 ifstream fin("fact-trigger-all.txt");
1644
1645 int l = 0;
1646
1647 string buf;
1648 while (getline(fin, buf, '\n'))
1649 {
1650 buf = Tools::Trim(buf);
1651 if (buf[0]=='#')
1652 continue;
1653
1654 stringstream str(buf);
1655 for (int i=0; i<9; i++)
1656 {
1657 int n;
1658 str >> n;
1659
1660 fPatch[n] = l;
1661 }
1662 l++;
1663 }
1664
1665 // --------------------------------------------------------------------------
1666#ifdef HAS_ROOT
1667 TCanvas *c = fFtmTempCanv->GetCanvas();
1668 c->SetBit(TCanvas::kNoContextMenu);
1669 c->SetBorderMode(0);
1670 c->SetFrameBorderMode(0);
1671 c->SetFillColor(kWhite);
1672 c->SetRightMargin(0.03);
1673 c->SetTopMargin(0.03);
1674 c->cd();
1675
1676 TH1F h("MyFrame", "", 1000, 0, 1);//Time().RootTime()-1./24/60/60, Time().RootTime());
1677 h.SetDirectory(0);
1678 h.SetBit(TH1::kCanRebin);
1679 h.SetStats(kFALSE);
1680 h.SetMinimum(-20);
1681 h.SetMaximum(100);
1682 h.SetXTitle("Time");
1683 h.SetYTitle("Temperature / °C");
1684 h.GetXaxis()->CenterTitle();
1685 h.GetYaxis()->CenterTitle();
1686// h.GetXaxis()->SetTitleSize(1.2);
1687// h.GetYaxis()->SetTitleSize(1.2);
1688 h.DrawCopy();
1689
1690 fGraphFtmTemp[0].SetMarkerStyle(kFullDotSmall);
1691 fGraphFtmTemp[1].SetMarkerStyle(kFullDotSmall);
1692 fGraphFtmTemp[2].SetMarkerStyle(kFullDotSmall);
1693 fGraphFtmTemp[3].SetMarkerStyle(kFullDotSmall);
1694
1695 fGraphFtmTemp[1].SetLineColor(kBlue);
1696 fGraphFtmTemp[2].SetLineColor(kRed);
1697 fGraphFtmTemp[3].SetLineColor(kGreen);
1698
1699 fGraphFtmTemp[1].SetMarkerColor(kBlue);
1700 fGraphFtmTemp[2].SetMarkerColor(kRed);
1701 fGraphFtmTemp[3].SetMarkerColor(kGreen);
1702
1703 fGraphFtmTemp[0].Draw("LP");
1704 fGraphFtmTemp[1].Draw("LP");
1705 fGraphFtmTemp[2].Draw("LP");
1706 fGraphFtmTemp[3].Draw("LP");
1707
1708 // --------------------------------------------------------------------------
1709
1710 c = fRatesCanv->GetCanvas();
1711 c->SetBit(TCanvas::kNoContextMenu);
1712 c->SetBorderMode(0);
1713 c->SetFrameBorderMode(0);
1714 c->SetFillColor(kWhite);
1715 c->cd();
1716
1717 Camera *cam = new Camera;
1718 cam->SetBit(kCanDelete);
1719 cam->Draw();
1720
1721 ChoosePixel(*cam, 1);
1722
1723// QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1724
1725 //widget->setMouseTracking(true);
1726 //widget->EnableSignalEvents(kMouseMoveEvent);
1727
1728 fFtmTempCanv->setMouseTracking(true);
1729 fFtmTempCanv->EnableSignalEvents(kMouseMoveEvent);
1730
1731 fRatesCanv->setMouseTracking(true);
1732 fRatesCanv->EnableSignalEvents(kMouseMoveEvent|kMouseReleaseEvent|kMouseDoubleClickEvent);
1733
1734 connect(fRatesCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1735 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1736 connect(fFtmTempCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1737 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1738#endif
1739 }
1740
1741 ~FactGui()
1742 {
1743 UnsubscribeAllServers();
1744 }
1745};
1746
1747#endif
Note: See TracBrowser for help on using the repository browser.