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

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