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

Last change on this file since 10564 was 10564, checked in by tbretz, 9 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.