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

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