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

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