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

Last change on this file since 10580 was 10580, checked in by tbretz, 10 years ago
Added scheduler LED.
File size: 52.8 KB
Line 
1#ifndef FACT_FactGui
2#define FACT_FactGui
3
4#include "MainWindow.h"
5
6#include <iomanip>
7#include <valarray>
8
9#include <boost/bind.hpp>
10
11#include <QTimer>
12#include <QStandardItemModel>
13
14#include "CheckBoxDelegate.h"
15
16#include "src/Converter.h"
17#include "src/HeadersFTM.h"
18#include "src/DimNetwork.h"
19#include "src/tools.h"
20
21#include "TROOT.h"
22#include "TSystem.h"
23#include "TGraph.h"
24#include "TH1.h"
25#include "TStyle.h"
26#include "TMarker.h"
27#include "TColor.h"
28
29#define HAS_ROOT
30
31using namespace std;
32
33// #########################################################################
34
35class Camera : public TObject
36{
37 typedef pair<double,double> Position;
38 typedef vector<Position> Positions;
39
40 Positions fGeom;
41
42 void CreatePalette()
43 {
44 /*
45 double ss[5] = {0., 0.10, 0.45, 0.75, 1.00};
46 double rr[5] = {0., 0.35, 0.85, 1.00, 1.00};
47 double gg[5] = {0., 0.10, 0.20, 0.73, 1.00};
48 double bb[5] = {0., 0.03, 0.06, 0.00, 1.00};
49 */
50 double ss[5] = {0., 0.25, 0.50, 0.75, 1.00};
51 double rr[5] = {0., 0.00, 0.00, 1.00, 1.00};
52 double gg[5] = {0., 0.00, 1.00, 0.00, 1.00};
53 double bb[5] = {0., 1.00, 0.00, 0.00, 1.00};
54
55 const Int_t nn = 1438;
56
57 Int_t idx = TColor::CreateGradientColorTable(5, ss, rr, gg, bb, nn);
58 for (int i=0; i<nn; i++)
59 fPalette.push_back(idx++);
60 }
61
62 void CreateGeometry()
63 {
64 const double gsSin60 = sqrt(3.)/2;
65
66 const int rings = 23;
67
68 // add the first pixel to the list
69
70 fGeom.push_back(make_pair(0, -0.5));
71
72 for (int ring=1; ring<=rings; ring++)
73 {
74 for (int s=0; s<6; s++)
75 {
76 for (int i=1; i<=ring; i++)
77 {
78 double xx, yy;
79 switch (s)
80 {
81 case 0: // Direction South East
82 xx = (ring+i)*0.5;
83 yy = (-ring+i)*gsSin60;
84 break;
85
86 case 1: // Direction North East
87 xx = ring-i*0.5;
88 yy = i*gsSin60;
89 break;
90
91 case 2: // Direction North
92 xx = ring*0.5-i;
93 yy = ring*gsSin60;
94 break;
95
96 case 3: // Direction North West
97 xx = -(ring+i)*0.5;
98 yy = (ring-i)*gsSin60;
99 break;
100
101 case 4: // Direction South West
102 xx = 0.5*i-ring;
103 yy = -i*gsSin60;
104 break;
105
106 case 5: // Direction South
107 xx = i-ring*0.5;
108 yy = -ring*gsSin60;
109 break;
110 }
111
112 if (xx*xx + yy*yy - xx > 395.75)
113 continue;
114
115 fGeom.push_back(make_pair(yy, xx-0.5));
116 }
117 }
118 }
119 }
120
121 valarray<double> fData;
122 map<int, bool> fBold;
123 map<int, bool> fEnable;
124
125 int fWhite;
126
127public:
128 Camera() : fData(0., 1438), fWhite(-1)
129 {
130 CreatePalette();
131 CreateGeometry();
132
133 for (int i=0; i<1438; i++)
134 fData[i] = i;
135 }
136
137 void Reset() { fBold.clear(); }
138
139 void SetBold(int idx) { fBold[idx]=true; }
140 void SetWhite(int idx) { fWhite=idx; }
141 void SetEnable(int idx, bool b) { fEnable[idx]=b; }
142 void Toggle(int idx) { fEnable[idx]=!fEnable[idx]; }
143
144 const char *GetName() const { return "Camera"; }
145
146 vector<Int_t> fPalette;
147
148 void Paint(const Position &p)
149 {
150 static const Double_t fgCos60 = 0.5; // TMath::Cos(60/TMath::RadToDeg());
151 static const Double_t fgSin60 = sqrt(3.)/2; // TMath::Sin(60/TMath::RadToDeg());
152
153 static const Double_t fgDy[6] = { fgCos60, 0., -fgCos60, -fgCos60, 0., fgCos60 };
154 static const Double_t fgDx[6] = { fgSin60/3, fgSin60*2/3, fgSin60/3, -fgSin60/3, -fgSin60*2/3, -fgSin60/3 };
155
156 //
157 // calculate the positions of the pixel corners
158 //
159 Double_t x[7], y[7];
160 for (Int_t i=0; i<7; i++)
161 {
162 x[i] = p.first + fgDx[i%6];
163 y[i] = p.second + fgDy[i%6];
164 }
165
166 gPad->PaintFillArea(6, x, y);
167 gPad->PaintPolyLine(7, x, y);
168
169 }
170
171 void Paint(Option_t *)
172 {
173 gStyle->SetPalette(fPalette.size(), fPalette.data());
174
175
176 const double r = double(gPad->GetWw())/gPad->GetWh();
177 const double max = 20.5; // 20.5 rings in x and y
178
179 if (r>1)
180 gPad->Range(-r*max, -max, r*max, max);
181 else
182 gPad->Range(-max, -max/r, max, max/r);
183
184
185 const double min = fData.min();
186 const double scale = fData.max()-fData.min();
187
188 TAttFill fill(0, 1001);
189 TAttLine line;
190
191 int cnt=0;
192 for (Positions::iterator p=fGeom.begin(); p!=fGeom.end(); p++, cnt++)
193 {
194 if (fBold[cnt])
195 continue;
196
197
198 const int col = (fData[cnt]-min)/scale*(fPalette.size()-1);
199
200 if (fEnable[cnt])
201 fill.SetFillColor(gStyle->GetColorPalette(col));
202 else
203 fill.SetFillColor(kWhite);
204
205 fill.Modify();
206
207 Paint(*p);
208 }
209
210 line.SetLineWidth(2);
211 line.Modify();
212
213 cnt = 0;
214 for (Positions::iterator p=fGeom.begin(); p!=fGeom.end(); p++, cnt++)
215 {
216 if (!fBold[cnt])
217 continue;
218
219 const int col = (fData[cnt]-min)/scale*(fPalette.size()-1);
220
221 if (fEnable[cnt])
222 fill.SetFillColor(gStyle->GetColorPalette(col));
223 else
224 fill.SetFillColor(kWhite);
225 fill.Modify();
226
227 Paint(*p);
228 }
229
230 TMarker m(0,0,kStar);
231 m.DrawMarker(0, 0);
232
233 if (fWhite<0)
234 return;
235
236 const Position &p = fGeom[fWhite];
237
238 line.SetLineColor(kWhite);
239 line.Modify();
240
241 const int col = (fData[fWhite]-min)/scale*(fPalette.size()-1);
242
243 if (fEnable[fWhite])
244 fill.SetFillColor(gStyle->GetColorPalette(col));
245 else
246 fill.SetFillColor(kWhite);
247 fill.Modify();
248
249 Paint(p);
250 }
251
252 int GetIdx(float px, float py) const
253 {
254 static const double sqrt3 = sqrt(3);
255
256 int idx = 0;
257 for (Positions::const_iterator p=fGeom.begin(); p!=fGeom.end(); p++, idx++)
258 {
259 const Double_t dy = py - p->second;
260 if (fabs(dy)>0.5)
261 continue;
262
263 const Double_t dx = px - p->first;
264
265 if (TMath::Abs(dy + dx*sqrt3) > 1)
266 continue;
267
268 if (TMath::Abs(dy - dx*sqrt3) > 1)
269 continue;
270
271 return idx;
272 }
273 return -1;
274 }
275
276 char* GetObjectInfo(Int_t px, Int_t py) const
277 {
278 static stringstream stream;
279 static string str;
280
281 const float x = gPad->PadtoX(gPad->AbsPixeltoX(px));
282 const float y = gPad->PadtoY(gPad->AbsPixeltoY(py));
283
284 const int idx = GetIdx(x, y);
285
286 stream.seekp(0);
287 if (idx>=0)
288 stream << "Pixel=" << idx << " Data=" << fData[idx] << '\0';
289
290 str = stream.str();
291 return const_cast<char*>(str.c_str());
292 }
293
294 Int_t DistancetoPrimitive(Int_t px, Int_t py)
295 {
296 const float x = gPad->PadtoX(gPad->AbsPixeltoX(px));
297 const float y = gPad->PadtoY(gPad->AbsPixeltoY(py));
298
299 return GetIdx(x, y)>=0 ? 0 : 99999;
300 }
301
302 void SetData(const valarray<double> &data)
303 {
304 fData = data;
305 }
306};
307
308// #########################################################################
309
310
311class FactGui : public MainWindow, public DimNetwork
312{
313private:
314 class FunctionEvent : public QEvent
315 {
316 public:
317 boost::function<void(const QEvent &)> fFunction;
318
319 FunctionEvent(const boost::function<void(const QEvent &)> &f)
320 : QEvent((QEvent::Type)QEvent::registerEventType()),
321 fFunction(f) { }
322
323 bool Exec() { fFunction(*this); return true; }
324 };
325
326 valarray<int8_t> fFtuStatus;
327
328 DimStampedInfo fDimDNS;
329
330 DimStampedInfo fDimLoggerStats;
331 DimStampedInfo fDimLoggerFilenameNight;
332 DimStampedInfo fDimLoggerFilenameRun;
333 DimStampedInfo fDimLoggerNumSubs;
334
335 DimStampedInfo fDimFtmPassport;
336 DimStampedInfo fDimFtmTriggerCounter;
337 DimStampedInfo fDimFtmError;
338 DimStampedInfo fDimFtmFtuList;
339 DimStampedInfo fDimFtmStaticData;
340 DimStampedInfo fDimFtmDynamicData;
341
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 handleFtmDynamicData(const DimData &d)
854 {
855 if (d.size()==0)
856 return;
857
858 if (d.size()!=sizeof(FTM::DimDynamicData))
859 {
860 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimDynamicData) << endl;
861 return;
862 }
863
864 const FTM::DimDynamicData &sdata = *reinterpret_cast<const FTM::DimDynamicData*>(d.ptr());
865
866 fFtmTime->setText(QString::number(sdata.fTimeStamp));
867 fOnTime->setText(QString::number(sdata.fOnTimeCounter));
868
869 fFtmTemp0->setValue(sdata.fTempSensor[0]*0.1);
870 fFtmTemp1->setValue(sdata.fTempSensor[1]*0.1);
871 fFtmTemp2->setValue(sdata.fTempSensor[2]*0.1);
872 fFtmTemp3->setValue(sdata.fTempSensor[3]*0.1);
873
874
875 // ----------------------------------------------
876#ifdef HAS_ROOT
877 TCanvas *c = fFtmTempCanv->GetCanvas();
878
879 static int cntr = 0;
880 double_t tm = cntr++;//Time().RootTime();
881
882 TH1 *h = (TH1*)c->FindObject("MyFrame");
883 h->FindBin(tm);
884
885 fGraphFtmTemp[0].SetPoint(fGraphFtmTemp[0].GetN(), tm, sdata.fTempSensor[0]*0.1);
886 fGraphFtmTemp[1].SetPoint(fGraphFtmTemp[1].GetN(), tm, sdata.fTempSensor[1]*0.1);
887 fGraphFtmTemp[2].SetPoint(fGraphFtmTemp[2].GetN(), tm, sdata.fTempSensor[2]*0.1);
888 fGraphFtmTemp[3].SetPoint(fGraphFtmTemp[3].GetN(), tm, sdata.fTempSensor[3]*0.1);
889
890 c->Modified();
891 c->Update();
892
893 // ----------------------------------------------
894
895 valarray<double> dat(0., 1438);
896
897 for (int i=0; i<1438; i++)
898 dat[i] = sdata.fRatePatch[fPatch[i]];
899
900 c = fRatesCanv->GetCanvas();
901 Camera *cam = (Camera*)c->FindObject("Camera");
902
903 cam->SetData(dat);
904
905 c->Modified();
906 c->Update();
907#endif
908 }
909
910 FTM::DimStaticData fFtmStaticData;
911
912 void SetFtuLed(int idx, int counter)
913 {
914 if (counter==0)
915 counter = 3;
916
917 if (counter==-1)
918 counter = 0;
919
920 switch (counter)
921 {
922 case 0:
923 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
924 break;
925
926 case 1:
927 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
928 break;
929
930 case 2:
931 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/orange circle 1.png"));
932 break;
933
934 case 3:
935 fFtuLED[idx]->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
936 break;
937 }
938
939 fFtuStatus[idx] = counter;
940 }
941
942 void SetFtuStatusLed()
943 {
944 const int max = fFtuStatus.max();
945
946 switch (max)
947 {
948 case 0:
949 fStatusFTULed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
950 fStatusFTULabel->setText("All disabled");
951 fStatusFTULabel->setToolTip("All FTUs are disabled");
952 break;
953
954 case 1:
955 fStatusFTULed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
956 fStatusFTULabel->setToolTip("Communication with FTU is smooth.");
957 fStatusFTULabel->setText("Ok");
958 break;
959
960 case 2:
961 fStatusFTULed->setIcon(QIcon(":/Resources/icons/orange circle 1.png"));
962 fStatusFTULabel->setText("Warning");
963 fStatusFTULabel->setToolTip("At least one FTU didn't answer immediately");
964 break;
965
966 case 3:
967 fStatusFTULed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
968 fStatusFTULabel->setToolTip("At least one FTU didn't answer!");
969 fStatusFTULabel->setText("ERROR");
970 break;
971 }
972 }
973
974 void handleFtmStaticData(const DimData &d)
975 {
976 if (d.size()==0)
977 return;
978
979 if (d.size()!=sizeof(FTM::DimStaticData))
980 {
981 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimStaticData) << endl;
982 return;
983 }
984
985 const FTM::DimStaticData &sdata = *reinterpret_cast<const FTM::DimStaticData*>(d.ptr());
986
987 fTriggerInterval->setValue(sdata.fTriggerInterval);
988 fPhysicsCoincidence->setValue(sdata.fCoincidencePhysics);
989 fCalibCoincidence->setValue(sdata.fCoincidenceCalib);
990 fPhysicsWindow->setValue(sdata.fWindowPhysics);
991 fCalibWindow->setValue(sdata.fWindowCalib);
992
993 fTriggerDelay->setValue(sdata.fDelayTrigger);
994 fTimeMarkerDelay->setValue(sdata.fDelayTimeMarker);
995 fDeadTime->setValue(sdata.fDeadTime);
996
997 fClockCondR0->setValue(sdata.fClockConditioner[0]);
998 fClockCondR1->setValue(sdata.fClockConditioner[1]);
999 fClockCondR8->setValue(sdata.fClockConditioner[2]);
1000 fClockCondR9->setValue(sdata.fClockConditioner[3]);
1001 fClockCondR11->setValue(sdata.fClockConditioner[4]);
1002 fClockCondR13->setValue(sdata.fClockConditioner[5]);
1003 fClockCondR14->setValue(sdata.fClockConditioner[6]);
1004 fClockCondR15->setValue(sdata.fClockConditioner[7]);
1005
1006 fTriggerSeqPed->setValue(sdata.fTriggerSeqPed);
1007 fTriggerSeqLPint->setValue(sdata.fTriggerSeqLPint);
1008 fTriggerSeqLPext->setValue(sdata.fTriggerSeqLPext);
1009
1010 fEnableTrigger->setChecked(sdata.HasTrigger());
1011 fEnableLPint->setChecked(sdata.HasLPint());
1012 fEnableLPext->setChecked(sdata.HasLPext());
1013 fEnableVeto->setChecked(sdata.HasVeto());
1014 fEnablePedestal->setChecked(sdata.HasPedestal());
1015 fEnableExt1->setChecked(sdata.HasExt1());
1016 fEnableExt2->setChecked(sdata.HasExt2());
1017 fEnableTimeMarker->setChecked(sdata.HasTimeMarker());
1018
1019 for (int i=0; i<40; i++)
1020 {
1021 if (!sdata.IsActive(i))
1022 SetFtuLed(i, -1);
1023 else
1024 {
1025 if (fFtuStatus[i]==0)
1026 SetFtuLed(i, 1);
1027 }
1028 fFtuLED[i]->setChecked(false);
1029 }
1030 SetFtuStatusLed();
1031
1032#ifdef HAS_ROOT
1033 Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera");
1034 for (int i=0; i<1438; i++)
1035 cam->SetEnable(i, sdata.IsEnabled(i));
1036#endif
1037
1038 const int patch1 = fThresholdIdx->value();
1039 fThresholdVal->setValue(sdata.fThreshold[patch1<0?0:patch1]);
1040
1041 fPrescalingVal->setValue(sdata.fPrescaling[0]);
1042
1043 fFtmStaticData = sdata;
1044 }
1045
1046 void handleFtmPassport(const DimData &d)
1047 {
1048 if (d.size()==0)
1049 return;
1050
1051 if (d.size()!=sizeof(FTM::DimPassport))
1052 {
1053 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimPassport) << endl;
1054 return;
1055 }
1056
1057 const FTM::DimPassport &sdata = *reinterpret_cast<const FTM::DimPassport*>(d.ptr());
1058
1059 stringstream str1, str2;
1060 str1 << hex << "0x" << setfill('0') << setw(16) << sdata.fBoardId;
1061 str2 << sdata.fFirmwareId;
1062
1063 fFtmBoardId->setText(str1.str().c_str());
1064 fFtmFirmwareId->setText(str2.str().c_str());
1065 }
1066
1067 void handleFtmFtuList(const DimData &d)
1068 {
1069 if (d.size()==0)
1070 return;
1071
1072 if (d.size()!=sizeof(FTM::DimFtuList))
1073 {
1074 cout << "Size mismatch: " << d.size() << " " << sizeof(FTM::DimFtuList) << endl;
1075 return;
1076 }
1077
1078 fPing->setChecked(false);
1079
1080 const FTM::DimFtuList &sdata = *reinterpret_cast<const FTM::DimFtuList*>(d.ptr());
1081
1082 stringstream str;
1083 str << "<table width='100%'>" << setfill('0');
1084 str << "<tr><th>Num</th><th></th><th>Addr</th><th></th><th>DNA</th></tr>";
1085 for (int i=0; i<40; i++)
1086 {
1087 str << "<tr>";
1088 str << "<td align='center'>" << dec << i << hex << "</td>";
1089 str << "<td align='center'>:</td>";
1090 str << "<td align='center'>0x" << setw(2) << (int)sdata.fAddr[i] << "</td>";
1091 str << "<td align='center'>:</td>";
1092 str << "<td align='center'>0x" << setw(16) << sdata.fDNA[i] << "</td>";
1093 str << "</tr>";
1094 }
1095 str << "</table>";
1096
1097 fFtuDNA->setText(str.str().c_str());
1098
1099 fFtuAnswersTotal->setValue(sdata.fNumBoards);
1100 fFtuAnswersCrate0->setValue(sdata.fNumBoardsCrate[0]);
1101 fFtuAnswersCrate1->setValue(sdata.fNumBoardsCrate[1]);
1102 fFtuAnswersCrate2->setValue(sdata.fNumBoardsCrate[2]);
1103 fFtuAnswersCrate3->setValue(sdata.fNumBoardsCrate[3]);
1104
1105 for (int i=0; i<40; i++)
1106 SetFtuLed(i, sdata.IsActive(i) ? sdata.fPing[i] : -1);
1107
1108 SetFtuStatusLed();
1109 }
1110
1111 void handleFtmError(const DimData &d)
1112 {
1113 if (d.size()==0)
1114 return;
1115
1116 const FTM::DimError &sdata = *reinterpret_cast<const FTM::DimError*>(d.ptr());
1117
1118 SetFtuLed(sdata.fError.fDestAddress , sdata.fError.fNumCalls);
1119 SetFtuStatusLed();
1120
1121 // Write to special window!
1122 Out() << "Error:" << endl;
1123 Out() << sdata.fError << endl;
1124 }
1125
1126 // ====================== MessageImp ====================================
1127
1128 bool fChatOnline;
1129
1130 void handleStateChanged(const Time &/*time*/, const std::string &server,
1131 const State &s)
1132 {
1133 // FIXME: Prefix tooltip with time
1134 if (server=="FTM_CONTROL")
1135 {
1136 fStatusFTMLabel->setText(s.name.c_str());
1137 fStatusFTMLabel->setToolTip(s.comment.c_str());
1138
1139 bool enable = false;
1140
1141 if (s.index<FTM::kDisconnected) // No Dim connection
1142 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1143 if (s.index==FTM::kDisconnected) // Dim connection / FTM disconnected
1144 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1145 if (s.index==FTM::kConnected || s.index==FTM::kIdle) // Dim connection / FTM connected
1146 {
1147 fStatusFTMLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1148 enable = true;
1149 }
1150
1151 fTriggerWidget->setEnabled(enable);
1152 fFtuWidget->setEnabled(enable);
1153 fRatesWidget->setEnabled(enable);
1154
1155 if (!enable)
1156 {
1157 fStatusFTULed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1158 fStatusFTULabel->setText("Offline");
1159 fStatusFTULabel->setToolTip("FTM is not online.");
1160 }
1161 }
1162
1163 if (server=="FAD_CONTROL")
1164 {
1165 fStatusFADLabel->setText(s.name.c_str());
1166 fStatusFADLabel->setToolTip(s.comment.c_str());
1167
1168 if (s.index<FTM::kDisconnected) // No Dim connection
1169 fStatusFADLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1170 if (s.index==FTM::kDisconnected) // Dim connection / FTM disconnected
1171 fStatusFADLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1172 if (s.index==FTM::kConnected) // Dim connection / FTM connected
1173 fStatusFADLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1174 }
1175
1176 if (server=="DATA_LOGGER")
1177 {
1178 fStatusLoggerLabel->setText(s.name.c_str());
1179 fStatusLoggerLabel->setToolTip(s.comment.c_str());
1180
1181 bool enable = true;
1182
1183 if (s.index<=30) // Ready/Waiting
1184 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/yellow circle 1.png"));
1185 if (s.index<-1) // Offline
1186 {
1187 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1188 enable = false;
1189 }
1190 if (s.index>=0x100) // Error
1191 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/red circle 1.png"));
1192 if (s.index==40) // Logging
1193 fStatusLoggerLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1194
1195 fLoggerWidget->setEnabled(enable);
1196 }
1197
1198 if (server=="CHAT")
1199 {
1200 fStatusChatLabel->setText(s.name.c_str());
1201
1202 fChatOnline = s.index==0;
1203
1204 if (fChatOnline) // Dim connection / FTM connected
1205 fStatusChatLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1206 else
1207 fStatusChatLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1208
1209 fChatSend->setEnabled(fChatOnline);
1210 fChatMessage->setEnabled(fChatOnline);
1211 }
1212
1213 if (server=="SCHEDULER")
1214 {
1215 fStatusSchedulerLabel->setText(s.name.c_str());
1216
1217 if (s.index>=0) // Dim connection / FTM connected
1218 fStatusSchedulerLed->setIcon(QIcon(":/Resources/icons/green circle 1.png"));
1219 else
1220 fStatusSchedulerLed->setIcon(QIcon(":/Resources/icons/gray circle 1.png"));
1221 }
1222 }
1223
1224 void handleStateOffline(const string &server)
1225 {
1226 handleStateChanged(Time(), server, State(-2, "Offline", "No connection via DIM."));
1227 }
1228
1229 void on_fTabWidget_currentChanged(int which)
1230 {
1231 if (fTabWidget->tabText(which)=="Chat")
1232 fTabWidget->setTabIcon(which, QIcon());
1233 }
1234
1235 void handleWrite(const Time &time, const string &text, int qos)
1236 {
1237 stringstream out;
1238
1239 if (text.substr(0, 6)=="CHAT: ")
1240 {
1241 out << "<font size='-1' color='navy'>[<B>";
1242 out << Time::fmt("%H:%M:%S") << time << "</B>]</FONT> ";
1243 out << text.substr(6);
1244 fChatText->append(out.str().c_str());
1245
1246 if (fTabWidget->tabText(fTabWidget->currentIndex())=="Chat")
1247 return;
1248
1249 static int num = 0;
1250 if (num++<2)
1251 return;
1252
1253 for (int i=0; i<fTabWidget->count(); i++)
1254 if (fTabWidget->tabText(i)=="Chat")
1255 {
1256 fTabWidget->setTabIcon(i, QIcon(":/Resources/icons/warning 3.png"));
1257 break;
1258 }
1259
1260 return;
1261 }
1262
1263
1264 out << "<font style='font-family:monospace' color='";
1265
1266 switch (qos)
1267 {
1268 case kMessage: out << "black"; break;
1269 case kInfo: out << "green"; break;
1270 case kWarn: out << "#FF6600"; break;
1271 case kError: out << "maroon"; break;
1272 case kFatal: out << "maroon"; break;
1273 case kDebug: out << "navy"; break;
1274 default: out << "navy"; break;
1275 }
1276 out << "'>" << time.GetAsStr() << " - " << text << "</font>";
1277
1278 fLogText->append(out.str().c_str());
1279
1280 if (qos>=kWarn)
1281 fTextEdit->append(out.str().c_str());
1282 }
1283
1284 void IndicateStateChange(const Time &time, const std::string &server)
1285 {
1286 const State s = GetState(server, GetCurrentState(server));
1287
1288 QApplication::postEvent(this,
1289 new FunctionEvent(boost::bind(&FactGui::handleStateChanged, this, time, server, s)));
1290 }
1291
1292 int Write(const Time &time, const string &txt, int qos)
1293 {
1294 QApplication::postEvent(this,
1295 new FunctionEvent(boost::bind(&FactGui::handleWrite, this, time, txt, qos)));
1296
1297 return 0;
1298 }
1299
1300 // ====================== Dim infoHandler================================
1301
1302 void handleDimService(const string &txt)
1303 {
1304 fDimSvcText->append(txt.c_str());
1305 }
1306
1307 void infoHandlerService(DimInfo &info)
1308 {
1309 const string fmt = string(info.getFormat()).empty() ? "C" : info.getFormat();
1310
1311 stringstream dummy;
1312 const Converter conv(dummy, fmt, false);
1313
1314 const Time tm(info.getTimestamp(), info.getTimestampMillisecs()*1000);
1315
1316 stringstream out;
1317 out << "<font size'-1' color='navy'>[" << Time::fmt("%H:%M:%S.%f") << tm << "]</font> <B>" << info.getName() << "</B> - ";
1318
1319 bool iserr = true;
1320 if (!conv)
1321 {
1322 out << "Compilation of format string '" << fmt << "' failed!";
1323 }
1324 else
1325 {
1326 try
1327 {
1328 const string dat = conv.GetString(info.getData(), info.getSize());
1329 out << dat;
1330 iserr = false;
1331 }
1332 catch (const runtime_error &e)
1333 {
1334 out << "Conversion to string failed!<pre>" << e.what() << "</pre>";
1335 }
1336 }
1337
1338 // srand(hash<string>()(string(info.getName())));
1339 // int bg = rand()&0xffffff;
1340
1341 int bg = hash<string>()(string(info.getName()));
1342
1343 // allow only light colors
1344 bg = ~(bg&0x1f1f1f)&0xffffff;
1345
1346 if (iserr)
1347 bg = 0xffffff;
1348
1349 stringstream bgcol;
1350 bgcol << hex << setfill('0') << setw(6) << bg;
1351
1352 const string col = iserr ? "red" : "black";
1353 const string str = "<table width='100%' bgcolor=#"+bgcol.str()+"><tr><td><font color='"+col+"'>"+out.str()+"</font></td></tr></table>";
1354
1355 QApplication::postEvent(this,
1356 new FunctionEvent(boost::bind(&FactGui::handleDimService, this, str)));
1357 }
1358
1359 void PostInfoHandler(void (FactGui::*handler)(const DimData&))
1360 {
1361 QApplication::postEvent(this,
1362 new FunctionEvent(boost::bind(handler, this, DimData(getInfo()))));
1363 }
1364
1365 void infoHandler()
1366 {
1367 // Initialize the time-stamp (what a weird workaround...)
1368 if (getInfo())
1369 getInfo()->getTimestamp();
1370
1371 if (getInfo()==&fDimDNS)
1372 return PostInfoHandler(&FactGui::handleDimDNS);
1373
1374 cout << "HandleDimInfo " << getInfo()->getName() << endl;
1375
1376 if (getInfo()==&fDimLoggerStats)
1377 return PostInfoHandler(&FactGui::handleLoggerStats);
1378
1379 if (getInfo()==&fDimLoggerFilenameNight)
1380 return PostInfoHandler(&FactGui::handleLoggerFilenameNight);
1381
1382 if (getInfo()==&fDimLoggerNumSubs)
1383 return PostInfoHandler(&FactGui::handleLoggerNumSubs);
1384
1385 if (getInfo()==&fDimLoggerFilenameRun)
1386 return PostInfoHandler(&FactGui::handleLoggerFilenameRun);
1387
1388 if (getInfo()==&fDimFtmTriggerCounter)
1389 return PostInfoHandler(&FactGui::handleFtmTriggerCounter);
1390
1391 if (getInfo()==&fDimFtmDynamicData)
1392 return PostInfoHandler(&FactGui::handleFtmDynamicData);
1393
1394 if (getInfo()==&fDimFtmPassport)
1395 return PostInfoHandler(&FactGui::handleFtmPassport);
1396
1397 if (getInfo()==&fDimFtmFtuList)
1398 return PostInfoHandler(&FactGui::handleFtmFtuList);
1399
1400 if (getInfo()==&fDimFtmStaticData)
1401 return PostInfoHandler(&FactGui::handleFtmStaticData);
1402
1403 if (getInfo()==&fDimFtmError)
1404 return PostInfoHandler(&FactGui::handleFtmError);
1405
1406 for (map<string,DimInfo*>::iterator i=fServices.begin(); i!=fServices.end(); i++)
1407 if (i->second==getInfo())
1408 {
1409 infoHandlerService(*i->second);
1410 return;
1411 }
1412
1413 DimNetwork::infoHandler();
1414 }
1415
1416
1417 // ======================================================================
1418
1419 bool event(QEvent *evt)
1420 {
1421 if (dynamic_cast<FunctionEvent*>(evt))
1422 return static_cast<FunctionEvent*>(evt)->Exec();
1423
1424 if (dynamic_cast<CheckBoxEvent*>(evt))
1425 {
1426 const QStandardItem &item = static_cast<CheckBoxEvent*>(evt)->item;
1427 const QStandardItem *par = item.parent();
1428 if (par)
1429 {
1430 const QString server = par->text();
1431 const QString service = item.text();
1432
1433 const string s = (server+'/'+service).toStdString();
1434
1435 if (item.checkState()==Qt::Checked)
1436 SubscribeService(s);
1437 else
1438 UnsubscribeService(s);
1439 }
1440 }
1441
1442 return MainWindow::event(evt); // unrecognized
1443 }
1444
1445 void on_fDimCmdSend_clicked()
1446 {
1447 const QString server = fDimCmdServers->currentIndex().data().toString();
1448 const QString command = fDimCmdCommands->currentIndex().data().toString();
1449 const QString arguments = fDimCmdLineEdit->displayText();
1450
1451 // FIXME: Sending a command exactly when the info Handler changes
1452 // the list it might lead to confusion.
1453 try
1454 {
1455 SendDimCommand(server.toStdString(), command.toStdString()+" "+arguments.toStdString());
1456 fTextEdit->append("<font color='green'>Command '"+server+'/'+command+"' successfully emitted.</font>");
1457 fDimCmdLineEdit->clear();
1458 }
1459 catch (const runtime_error &e)
1460 {
1461 stringstream txt;
1462 txt << e.what();
1463
1464 string buffer;
1465 while (getline(txt, buffer, '\n'))
1466 fTextEdit->append(("<font color='red'><pre>"+buffer+"</pre></font>").c_str());
1467 }
1468 }
1469 void ChoosePatch(Camera &cam, int idx)
1470 {
1471 cam.Reset();
1472
1473 fThresholdIdx->setValue(idx);
1474 fThresholdVal->setValue(fFtmStaticData.fThreshold[idx<0?0:idx]);
1475
1476 if (idx<0)
1477 return;
1478
1479 for (unsigned int i=0; i<fPatch.size(); i++)
1480 if (fPatch[i]==idx)
1481 cam.SetBold(i);
1482 }
1483
1484 void ChoosePixel(Camera &cam, int idx)
1485 {
1486 cam.SetWhite(idx);
1487 ChoosePatch(cam, fPatch[idx]);
1488 }
1489
1490#ifdef HAS_ROOT
1491 void slot_RootEventProcessed(TObject *obj, unsigned int evt, TCanvas *)
1492 {
1493 // kMousePressEvent // TCanvas processed QEvent mousePressEvent
1494 // kMouseMoveEvent // TCanvas processed QEvent mouseMoveEvent
1495 // kMouseReleaseEvent // TCanvas processed QEvent mouseReleaseEvent
1496 // kMouseDoubleClickEvent // TCanvas processed QEvent mouseDoubleClickEvent
1497 // kKeyPressEvent // TCanvas processed QEvent keyPressEvent
1498 // kEnterEvent // TCanvas processed QEvent enterEvent
1499 // kLeaveEvent // TCanvas processed QEvent leaveEvent
1500 if (dynamic_cast<TCanvas*>(obj))
1501 return;
1502
1503 TQtWidget *tipped = static_cast<TQtWidget*>(sender());
1504
1505 if (evt==11/*kMouseReleaseEvent*/)
1506 {
1507 if (dynamic_cast<Camera*>(obj))
1508 {
1509 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1510 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1511
1512 Camera *cam = static_cast<Camera*>(obj);
1513 const int idx = cam->GetIdx(xx, yy);
1514
1515 ChoosePixel(*cam, idx);
1516 }
1517 return;
1518 }
1519
1520 if (evt==61/*kMouseDoubleClickEvent*/)
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 cam->Toggle(idx);
1531 }
1532 return;
1533 }
1534
1535 // Find the object which will get picked by the GetObjectInfo
1536 // due to buffer overflows in many root-versions
1537 // in TH1 and TProfile we have to work around and implement
1538 // our own GetObjectInfo which make everything a bit more
1539 // complicated.
1540#if ROOT_VERSION_CODE > ROOT_VERSION(5,22,00)
1541 const char *objectInfo =
1542 obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1543#else
1544 const char *objectInfo = dynamic_cast<TH1*>(obj) ?
1545 "" : obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
1546#endif
1547
1548 QString tipText;
1549 tipText += obj->GetName();
1550 tipText += " [";
1551 tipText += obj->ClassName();
1552 tipText += "]: ";
1553 tipText += objectInfo;
1554
1555 if (dynamic_cast<Camera*>(obj))
1556 {
1557 const float xx = gPad->PadtoX(gPad->AbsPixeltoX(tipped->GetEventX()));
1558 const float yy = gPad->PadtoY(gPad->AbsPixeltoY(tipped->GetEventY()));
1559
1560 Camera *cam = static_cast<Camera*>(obj);
1561 int idx = fPatch[cam->GetIdx(xx, yy)];
1562
1563 tipText+=" Patch=";
1564 tipText+=QString::number(idx);
1565 }
1566
1567
1568 fStatusBar->showMessage(tipText, 3000);
1569
1570 gSystem->ProcessEvents();
1571 //QWhatsThis::display(tipText)
1572 }
1573
1574 void slot_RootUpdate()
1575 {
1576 gSystem->ProcessEvents();
1577 QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1578 }
1579
1580 void on_fThresholdIdx_valueChanged(int idx)
1581 {
1582 Camera *cam = (Camera*)fRatesCanv->GetCanvas()->FindObject("Camera");
1583 ChoosePatch(*cam, idx);
1584 }
1585#endif
1586
1587 TGraph fGraphFtmTemp[4];
1588
1589 map<int, int> fPatch;
1590
1591public:
1592 FactGui() :
1593 fFtuStatus(40),
1594 fDimDNS("DIS_DNS/VERSION_NUMBER", 1, int(0), this),
1595
1596 fDimLoggerStats ("DATA_LOGGER/STATS", (void*)NULL, 0, this),
1597 fDimLoggerFilenameNight("DATA_LOGGER/FILENAME_NIGHTLY", const_cast<char*>(""), 0, this),
1598 fDimLoggerFilenameRun ("DATA_LOGGER/FILENAME_RUN", const_cast<char*>(""), 0, this),
1599 fDimLoggerNumSubs ("DATA_LOGGER/NUM_SUBS", const_cast<char*>(""), 0, this),
1600
1601 fDimFtmPassport ("FTM_CONTROL/PASSPORT", (void*)NULL, 0, this),
1602 fDimFtmTriggerCounter("FTM_CONTROL/TRIGGER_COUNTER", (void*)NULL, 0, this),
1603 fDimFtmError ("FTM_CONTROL/ERROR", (void*)NULL, 0, this),
1604 fDimFtmFtuList ("FTM_CONTROL/FTU_LIST", (void*)NULL, 0, this),
1605 fDimFtmStaticData ("FTM_CONTROL/STATIC_DATA", (void*)NULL, 0, this),
1606 fDimFtmDynamicData ("FTM_CONTROL/DYNAMIC_DATA", (void*)NULL, 0, this)
1607 {
1608 fTriggerWidget->setEnabled(false);
1609 fFtuWidget->setEnabled(false);
1610 fRatesWidget->setEnabled(false);
1611 fLoggerWidget->setEnabled(false);
1612
1613 fChatSend->setEnabled(false);
1614 fChatMessage->setEnabled(false);
1615
1616 DimClient::sendCommand("CHAT/MSG", "GUI online.");
1617 // + MessageDimRX
1618
1619 // --------------------------------------------------------------------------
1620
1621 ifstream fin("fact-trigger-all.txt");
1622
1623 int l = 0;
1624
1625 string buf;
1626 while (getline(fin, buf, '\n'))
1627 {
1628 buf = Tools::Trim(buf);
1629 if (buf[0]=='#')
1630 continue;
1631
1632 stringstream str(buf);
1633 for (int i=0; i<9; i++)
1634 {
1635 int n;
1636 str >> n;
1637
1638 fPatch[n] = l;
1639 }
1640 l++;
1641 }
1642
1643 // --------------------------------------------------------------------------
1644#ifdef HAS_ROOT
1645 TCanvas *c = fFtmTempCanv->GetCanvas();
1646 c->SetBit(TCanvas::kNoContextMenu);
1647 c->SetBorderMode(0);
1648 c->SetFrameBorderMode(0);
1649 c->SetFillColor(kWhite);
1650 c->SetRightMargin(0.03);
1651 c->SetTopMargin(0.03);
1652 c->cd();
1653
1654 TH1F h("MyFrame", "", 1000, 0, 1);//Time().RootTime()-1./24/60/60, Time().RootTime());
1655 h.SetDirectory(0);
1656 h.SetBit(TH1::kCanRebin);
1657 h.SetStats(kFALSE);
1658 h.SetMinimum(-20);
1659 h.SetMaximum(100);
1660 h.SetXTitle("Time");
1661 h.SetYTitle("Temperature / °C");
1662 h.GetXaxis()->CenterTitle();
1663 h.GetYaxis()->CenterTitle();
1664// h.GetXaxis()->SetTitleSize(1.2);
1665// h.GetYaxis()->SetTitleSize(1.2);
1666 h.DrawCopy();
1667
1668 fGraphFtmTemp[0].SetMarkerStyle(kFullDotSmall);
1669 fGraphFtmTemp[1].SetMarkerStyle(kFullDotSmall);
1670 fGraphFtmTemp[2].SetMarkerStyle(kFullDotSmall);
1671 fGraphFtmTemp[3].SetMarkerStyle(kFullDotSmall);
1672
1673 fGraphFtmTemp[1].SetLineColor(kBlue);
1674 fGraphFtmTemp[2].SetLineColor(kRed);
1675 fGraphFtmTemp[3].SetLineColor(kGreen);
1676
1677 fGraphFtmTemp[1].SetMarkerColor(kBlue);
1678 fGraphFtmTemp[2].SetMarkerColor(kRed);
1679 fGraphFtmTemp[3].SetMarkerColor(kGreen);
1680
1681 fGraphFtmTemp[0].Draw("LP");
1682 fGraphFtmTemp[1].Draw("LP");
1683 fGraphFtmTemp[2].Draw("LP");
1684 fGraphFtmTemp[3].Draw("LP");
1685
1686 // --------------------------------------------------------------------------
1687
1688 c = fRatesCanv->GetCanvas();
1689 c->SetBit(TCanvas::kNoContextMenu);
1690 c->SetBorderMode(0);
1691 c->SetFrameBorderMode(0);
1692 c->SetFillColor(kWhite);
1693 c->cd();
1694
1695 Camera *cam = new Camera;
1696 cam->SetBit(kCanDelete);
1697 cam->Draw();
1698
1699 ChoosePixel(*cam, 1);
1700
1701// QTimer::singleShot(0, this, SLOT(slot_RootUpdate()));
1702
1703 //widget->setMouseTracking(true);
1704 //widget->EnableSignalEvents(kMouseMoveEvent);
1705
1706 fFtmTempCanv->setMouseTracking(true);
1707 fFtmTempCanv->EnableSignalEvents(kMouseMoveEvent);
1708
1709 fRatesCanv->setMouseTracking(true);
1710 fRatesCanv->EnableSignalEvents(kMouseMoveEvent|kMouseReleaseEvent|kMouseDoubleClickEvent);
1711
1712 connect(fRatesCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1713 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1714 connect(fFtmTempCanv, SIGNAL( RootEventProcessed(TObject*, unsigned int, TCanvas*)),
1715 this, SLOT (slot_RootEventProcessed(TObject*, unsigned int, TCanvas*)));
1716#endif
1717 }
1718
1719 ~FactGui()
1720 {
1721 UnsubscribeAllServers();
1722 }
1723};
1724
1725#endif
Note: See TracBrowser for help on using the repository browser.