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

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