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

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