source: Evidence/Edd/Edd.cc @ 154

Last change on this file since 154 was 154, checked in by ogrimm, 11 years ago
Updates to status service
File size: 23.0 KB
Line 
1
2/* ============================================================
3
4Edd - Evidence Data Display
5
6Qt-based graphical user interface for the Evidence contron system
7
8Edd_Indicator changes its background colour in case it display
9a DIM status service
10
11December 2009, Oliver Grimm
12
13============================================================ */
14
15#include "Edd.h"
16
17Qt::GlobalColor LineColors[] = {Qt::black, Qt::blue, Qt::red, Qt::green, Qt::white,
18        Qt::darkRed, Qt::darkGreen, Qt::darkBlue, Qt::cyan,
19        Qt::darkCyan, Qt::magenta, Qt::darkMagenta,
20        Qt::gray, Qt::darkGray, Qt::lightGray};
21
22class GUI *Handler;
23
24//////////////////////////////////////////
25// Text display for arbitary DIM service//
26//////////////////////////////////////////
27
28// Constructor
29Edd_Indicator::Edd_Indicator(QString DIMService, QWidget *P): QLineEdit(P) {
30
31  // Widget properties
32  setReadOnly(true);
33  setMaximumWidth(100);
34  ShowAsTime = false;
35 
36  // Connect to DIM handler
37  if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QString, QByteArray, QString)), SLOT(Update(DimInfo*, int, QString, QByteArray, QString))) == false) {
38    printf("Failed connection for %s\n", DIMService.toAscii().data());
39  }
40
41  // Context menu
42  Menu = new QMenu(this);
43  Menu->addAction("Open history", this, SLOT(MenuOpenHistory()));
44  Menu->addAction("Copy service", this, SLOT(MenuCopyService()));
45
46  // DIM client
47  Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, (char *) NO_LINK, Handler);
48}
49
50// Destructor
51Edd_Indicator::~Edd_Indicator() {
52  delete Data;
53}
54
55// Update widget
56void Edd_Indicator::Update(DimInfo *Info, int Time, QString Format, QByteArray Data, QString Text) {
57
58  if (Info != this->Data) return;
59   
60  QPalette Pal = palette(); 
61
62  // Check if service available
63  if (Time == -1) {
64    setText("n/a");
65        setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
66    Pal.setColor(QPalette::Base, Qt::lightGray);
67  }
68  else {
69    // If this is a status indicator, adapt background colour
70    if (Data.size() == Text.size()+2) {
71      switch (Data[Text.size() + 1]) {
72        case 0:  Pal.setColor(QPalette::Base, Qt::white); break;
73        case 1:  Pal.setColor(QPalette::Base, Qt::yellow); break;
74        case 2:  Pal.setColor(QPalette::Base, Qt::red); break;
75        case 3:  Pal.setColor(QPalette::Base, Qt::red); break;
76        default: break;
77      }
78    }
79    else Pal.setColor(QPalette::Base, Qt::white);
80       
81        if (!ShowAsTime) setText(Text);
82        else setText(QDateTime::fromTime_t(Text.toInt()).toString());
83       
84    // Update status tip
85    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Format));
86  }
87 
88  setPalette(Pal);
89}
90
91// Open plot if mouse release within widget
92void Edd_Indicator::mouseReleaseEvent(QMouseEvent *Event) {
93
94  if (Event->button()!=Qt::LeftButton || !contentsRect().contains(Event->pos())) return;
95
96  // Check if last history plot still open, then raise
97  foreach (QWidget *Widget, QApplication::allWidgets()) {
98    if (Widget == LastPlot) {
99      Widget->activateWindow();
100      Widget->raise();
101      return;
102    }
103  }
104
105  // If not, open new plot
106  Edd_Indicator::MenuOpenHistory();
107}
108
109// Handling of mouse press event: Register start position for drag
110void Edd_Indicator::mousePressEvent(QMouseEvent *Event) {
111
112  if (Event->button() == Qt::LeftButton) dragStart = Event->pos();
113}
114
115// Handling of dragging (Drag and MimeData will be deleted by Qt)
116void Edd_Indicator::mouseMoveEvent(QMouseEvent *Event) {
117
118  if ((Event->buttons() & Qt::LeftButton) == 0) return;
119  if ((Event->pos()-dragStart).manhattanLength() < QApplication::startDragDistance()) return;
120
121  QDrag *Drag = new QDrag(this);
122  QMimeData *MimeData = new QMimeData;
123  MimeData->setText(QString(Data->getName()));
124  Drag->setMimeData(MimeData);
125  Drag->exec();
126}
127
128//
129// Opening context menu
130//
131void Edd_Indicator::contextMenuEvent(QContextMenuEvent *Event) {
132
133  Menu->exec(Event->globalPos());
134}
135
136// Open history plot
137void Edd_Indicator::MenuOpenHistory() {
138 
139  LastPlot = new Edd_Plot(Data->getName());
140  LastPlot->show();
141}
142
143// Copy service name
144void Edd_Indicator::MenuCopyService() {
145 
146  QApplication::clipboard()->setText(QString(Data->getName()));
147}
148
149//////////////////////////////////
150// History plot for DIM service //
151//////////////////////////////////
152
153//
154// Constructor
155//
156Edd_Plot::Edd_Plot(QString DIMService, QWidget *P): QwtPlot(P) {
157
158  setAcceptDrops(true);
159  setAttribute(Qt::WA_DeleteOnClose);
160 
161  // Graph properties
162  setAutoReplot(false);
163  QwtText XAxisTitle("Time (RJD-55200)");
164  XAxisTitle.setFont(QFont("Helvetica", 10));
165  setAxisTitle(QwtPlot::xBottom, XAxisTitle);
166  setCanvasBackground(QColor(Qt::yellow));
167
168  Zoomer = new QwtPlotZoomer(QwtPlot::xBottom,QwtPlot::yLeft,canvas());
169  connect(Zoomer, SIGNAL(zoomed(const QwtDoubleRect &)), this, SLOT(HandleZoom(const QwtDoubleRect &)));
170  Panner = new QwtPlotPanner(canvas());
171  Panner->setMouseButton(Qt::LeftButton, Qt::ShiftModifier);
172  Grid = new QwtPlotGrid;
173  Grid->setMajPen(QPen(Qt::gray, 0, Qt::DotLine));
174  Grid->attach(this);
175  Legend = new QwtLegend();
176  Legend->setItemMode(QwtLegend::ClickableItem);
177  insertLegend(Legend, QwtPlot::TopLegend);
178
179  connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *)));
180 
181  // Connect to DIM handler
182  if (connect(Handler, SIGNAL(YEP(DimInfo *, int, QString, QByteArray, QString)), SLOT(Update(DimInfo *, int, QString, QByteArray, QString))) == false) {
183    printf("Failed connection for %s\n", DIMService.toAscii().data());
184  }
185
186  // Context menu
187  Menu = new QMenu(this);
188  YLogAction = Menu->addAction("y scale log", this, SLOT(UpdatePlot()));
189  YLogAction->setCheckable(true);
190  NormAction = Menu->addAction("Normalize", this, SLOT(UpdatePlot()));
191  NormAction->setCheckable(true);
192  StyleAction = Menu->addAction("Draw dots", this, SLOT(UpdatePlot()));
193  StyleAction->setCheckable(true);
194  Menu->addAction("Zoom out", this, SLOT(MenuZoomOut()));
195  Menu->addAction("Single trace", this, SLOT(MenuSingleTrace()));
196  Menu->addSeparator();
197  Menu->addAction("Save as ASCII", this, SLOT(MenuSaveASCII()));
198  Menu->addAction("Save plot", this, SLOT(MenuSave()));
199  Menu->addAction("Print plot", this, SLOT(MenuPrint()));
200  Menu->addSeparator();
201  Menu->addAction("Paste service", this, SLOT(MenuPasteService()));
202
203  // DIM client
204  if (!DIMService.isEmpty()) AddService(DIMService);
205}
206
207//
208// Destructor (items with parent widget are automatically deleted)
209//
210Edd_Plot::~Edd_Plot() {
211
212  for (int i=0; i<Items.size(); i++) {
213    delete Items[i].Data;
214    delete Items[i].LiveData;
215    delete Items[i].Signal;
216    delete[] Items[i].x;
217    delete[] Items[i].y;
218  } 
219  delete Grid;
220}
221
222//
223// Add history service to plot
224//
225void Edd_Plot::AddService(QString Name) {
226
227  QString HistName = Name+".hist";
228
229  // Lock before accessing Items list
230  QMutexLocker Locker(&Mutex);
231
232  // Check if already subsribed to service
233  for (int i=0; i<Items.size(); i++) {
234    if (HistName == Items[i].Data->getName()) {
235      QMessageBox::warning(this, "Edd Message",HistName+" already present",QMessageBox::Ok);
236      return;
237    }
238  } 
239 
240  // Generate new curve and subscribe to service
241  struct PlotItem New;
242  New.Signal = new QwtPlotCurve;
243  New.Signal->attach(this);
244  New.Signal->setTitle(HistName);
245  New.Signal->setPen(QColor(LineColors[Items.size() % (sizeof(LineColors)/sizeof(Qt::GlobalColor))]));
246  New.x = NULL;
247  New.y = NULL;
248  New.Count = 0;
249  New.Data = new DimStampedInfo(HistName.toAscii().data(), (char *) NO_LINK, Handler);
250  New.LiveData = new DimStampedInfo(Name.toAscii().data(), (char *) NO_LINK, Handler); 
251
252  Items.append(New);
253}
254
255// Update widget (must happen in GUI thread)
256void Edd_Plot::Update(DimInfo *Info, int Time, QString Format, QByteArray Data, QString Text) {
257
258  // Check if service available
259  if (Time == -1) {
260        setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
261  }
262
263  // Lock before accessing Items list
264  QMutexLocker Locker(&Mutex);
265
266  // Determine which plot item this call belongs to
267  int ItemNo;
268  for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Info == Items[ItemNo].Data) {
269    // This is a history service 
270    EvidenceHistoryItem *Curr = (EvidenceHistoryItem *) Data.data();
271    int Count=0, DataPoints = Data.size()/sizeof(struct EvidenceHistoryItem);
272
273    delete[] Items[ItemNo].x;
274    delete[] Items[ItemNo].y;
275    Items[ItemNo].x = new int [DataPoints];
276    Items[ItemNo].y = new double [DataPoints];
277
278    // Find oldest item
279    int Oldest;
280    for (Oldest=1; Oldest<DataPoints; Oldest++) {
281      if (Curr[Oldest].Seconds < Curr[Oldest-1].Seconds) break;
282    }
283
284    // Plot data starting with oldest value
285    for (int i=0; i<DataPoints; i++) {
286      Items[ItemNo].x[Count] = Curr[(i+Oldest)%DataPoints].Seconds;
287      Items[ItemNo].y[Count] = Curr[(i+Oldest)%DataPoints].Value;
288      if (Items[ItemNo].x[Count] != 0) Count++;
289    }
290
291    // Find smallest and largest item
292    double Smallest = DBL_MAX, Largest = DBL_MIN;
293    for (int i=0; i<Count; i++) {
294      if (Largest < Items[ItemNo].y[i]) Largest = Items[ItemNo].y[i];
295      if (Smallest > Items[ItemNo].y[i]) Smallest = Items[ItemNo].y[i];
296    }
297    Items[ItemNo].Smallest = Smallest;
298    Items[ItemNo].Largest = Largest;
299    Items[ItemNo].Count = Count;
300
301    // Clear local history
302    Items[ItemNo].Live.clear();
303
304    // Update status tip
305    QDateTime Timex = QDateTime::fromTime_t(Time); 
306    StatusTip = QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), Timex.toString()).arg(Format);
307
308  } else if (Info == Items[ItemNo].LiveData) {
309    // This is a live service
310
311    // Limit size of list
312    if (Items[ItemNo].Live.size() > 1000) Items[ItemNo].Live.removeFirst();
313
314    // Append data
315    struct EvidenceHistoryItem Data;
316    Data.Seconds = Time;
317    Data.Value = atof(Text.toAscii().data());           
318    Items[ItemNo].Live.append(Data);
319
320    // Update largest and smallest value   
321    if (Data.Value > Items[ItemNo].Largest) Items[ItemNo].Largest = Data.Value;
322    if (Data.Value < Items[ItemNo].Smallest) Items[ItemNo].Smallest = Data.Value;   
323  }
324
325  Locker.unlock();
326
327  UpdatePlot();
328}
329
330//
331// Update all curves in plot
332//
333void Edd_Plot::UpdatePlot() {
334
335  static QwtSymbol Symbol, Sym1;
336  Symbol.setStyle(QwtSymbol::Ellipse);
337  Symbol.setSize(4);
338
339  if (!YLogAction->isChecked()) {
340    setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
341  }
342  else setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10ScaleEngine);
343
344  // Lock before accessing Items list
345  QMutexLocker Locker(&Mutex);
346
347  setStatusTip(StatusTip);
348 
349  for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
350
351    if (StyleAction->isChecked()) Items[ItemNo].Signal->setSymbol(Symbol);
352    else Items[ItemNo].Signal->setSymbol(Sym1);
353
354    int DataPoints = Items[ItemNo].Count + Items[ItemNo].Live.size();
355       
356        if (DataPoints == 0) continue;
357   
358    double *x = new double [DataPoints];
359    double *y = new double [DataPoints];
360 
361    // Adapt time scale and normalize y scale if requested
362    for (int i=0; i<DataPoints; i++) {
363      if (i < Items[ItemNo].Count) {
364        x[i] = Items[ItemNo].x[i] / 86400.0 + 40587.5 - 55200;
365        y[i] = Items[ItemNo].y[i];
366      }
367      else {
368        x[i]= Items[ItemNo].Live[i-Items[ItemNo].Count].Seconds / 86400.0 + 40587.5 - 55200;
369        y[i] = Items[ItemNo].Live[i-Items[ItemNo].Count].Value;
370      }
371
372      if (NormAction->isChecked()) {
373        if (Items[ItemNo].Smallest != Items[ItemNo].Largest) y[i] = (y[i] - Items[ItemNo].Smallest)/(Items[ItemNo].Largest-Items[ItemNo].Smallest);
374        else y[i] = 1;
375      } 
376    }
377
378    // Plot datas
379    Items[ItemNo].Signal->setData(x, y, DataPoints);
380    Items[ItemNo].Signal->show();
381    Zoomer->setZoomBase(Items[ItemNo].Signal->boundingRect());
382
383    delete[] x;
384    delete[] y;
385  }
386  replot();
387}
388
389//
390// Reset graph axes to autoscale when fully unzoomed
391//
392void Edd_Plot::HandleZoom(const QwtDoubleRect &) {
393
394  if(Zoomer->zoomRectIndex() == 0) {
395    setAxisAutoScale(QwtPlot::xBottom);
396    setAxisAutoScale(QwtPlot::yLeft);
397  }
398}
399
400//
401// Drag and drop methods
402//
403
404void Edd_Plot::dragEnterEvent(QDragEnterEvent *Event) {
405   
406  if (Event->mimeData()->hasFormat("text/plain")) Event->acceptProposedAction();
407}
408
409void Edd_Plot::dropEvent(QDropEvent *Event) {
410
411  AddService(Event->mimeData()->text().toAscii().data());
412}
413   
414// Opening context menu
415void Edd_Plot::contextMenuEvent(QContextMenuEvent *Event) {
416
417  Menu->exec(Event->globalPos());
418}
419
420// Drag&Drop method
421void Edd_Plot::LegendClicked(QwtPlotItem *Item) {
422
423  QDrag *Drag = new QDrag(this);
424  QMimeData *MimeData = new QMimeData;
425  MimeData->setText(Item->title().text().remove(".hist"));
426  Drag->setMimeData(MimeData);
427  Drag->exec();
428}
429
430
431// Zoom completely out
432void Edd_Plot::MenuZoomOut() {
433
434  Zoomer->zoom(0);
435  UpdatePlot();
436}
437
438// Remove all items except last
439void Edd_Plot::MenuSingleTrace() {
440
441  // Lock before accessing Items list
442  QMutexLocker Locker(&Mutex);
443
444  while (Items.size() > 1) { 
445    delete Items.last().Data;
446    delete Items.last().LiveData;
447    delete Items.last().Signal;
448    delete[] Items.last().x;
449    delete[] Items.last().y;
450    Items.takeLast();
451  }
452 
453  Locker.unlock();
454  UpdatePlot();
455}
456
457// Save data of plot as test
458void Edd_Plot::MenuSaveASCII() {
459  QString Filename = QFileDialog::getSaveFileName(this,
460     "Filename", ".", "Text files (*.txt *.ascii *.asc);;All files (*)");
461  if (Filename.length() <= 0) return;
462 
463  QFile File(Filename);
464  if (!File.open(QFile::WriteOnly | QIODevice::Text | QFile::Truncate)) {
465    QMessageBox::warning(this, "Edd Message","Could not open file for writing.",QMessageBox::Ok);
466    return;
467  }
468 
469  // Lock before accessing Items list
470  QMutexLocker Locker(&Mutex);
471  QTextStream Stream(&File);
472
473   // Write x and y data for all signals to file
474  for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
475    Stream << QString("# ")+Items[ItemNo].Data->getName() << endl;
476    for (int i=0; i<Items[ItemNo].Signal->dataSize(); i++) {
477      Stream << (int) Items[ItemNo].x[i] << " " << Items[ItemNo].Signal->y(i) << endl;
478    }
479  }
480}
481
482// Print plot
483void Edd_Plot::MenuPrint() {
484
485  QPrinter *Printer = new QPrinter;
486  QPrintDialog *PrintDialog = new QPrintDialog(Printer, this);
487  if (PrintDialog->exec() == QDialog::Accepted) {
488    QPainter Painter(Printer);
489    QPixmap Pixmap = QPixmap::grabWidget(this);
490    Painter.drawPixmap(0, 0, Pixmap);
491  }
492  delete Printer;       delete PrintDialog;
493}
494
495// Save plot as image
496void Edd_Plot::MenuSave() {
497
498  QString Filename = QFileDialog::getSaveFileName(this,
499     "Filename of image", "/home/ogrimm/ddd", "Image files (*.bmp *.jpg *.png *.ppm *.tiff *.xbm *.xpm);;All files (*)");
500  if (Filename.length()>0) {
501    QPixmap Pixmap = QPixmap::grabWidget(this);
502    if(!Pixmap.save(Filename)) {
503      QMessageBox::warning(this, "Edd Message","Could not write image file.",QMessageBox::Ok);
504      remove(Filename.toAscii().data());
505    }
506  }
507}
508
509// Add new service by pasting name
510void Edd_Plot::MenuPasteService() {
511
512  AddService(QApplication::clipboard()->text().toAscii().data());
513}
514
515
516//////////////////
517// Text display //
518//////////////////
519
520// Constructor
521Edd_Textout::Edd_Textout(QString DIMService, QWidget *P): QTextEdit(P) {
522
523  // Widget properties
524  setReadOnly(true);
525  setAutoFillBackground(true);
526  document()->setMaximumBlockCount(1000);
527  Accumulate = true;
528 
529  // Connect to DIM handler
530  if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QString, QByteArray, QString)), SLOT(Update(DimInfo*, int, QString, QByteArray, QString))) == false) {
531    printf("Failed connection for %s\n", DIMService.toAscii().data());
532  }
533
534  // DIM client
535  Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, (char *) NO_LINK, Handler);
536}
537
538// Destructor
539Edd_Textout::~Edd_Textout() {
540
541  delete Data;
542}
543
544// Handling of DIM service update
545void Edd_Textout::Update(DimInfo *Info, int Time, QString Format, QByteArray, QString Text) {
546
547  if (Info != this->Data) return;
548 
549  QPalette Pal = palette(); 
550
551  // Check if service available
552  if (Time == -1) {
553        setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
554    Pal.setColor(QPalette::Base, Qt::lightGray);
555  }
556  else {
557    Pal.setColor(QPalette::Base, Qt::white);
558
559        // Clear display in case text should not accumulate
560        if (Accumulate == false) clear();
561       
562    // Add if service contains only a string
563    if (Format == "C") insertPlainText(Text);
564
565    // Update status tip
566    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Format));
567  }
568  setPalette(Pal);
569}
570
571
572//
573// Main GUI (all widgets have ultimately Central as parent)
574//
575GUI::GUI() {
576 
577  Handler = this;
578 
579  // Set features of main window
580  Central = new QWidget(this);
581  setCentralWidget(Central);
582  setStatusBar(new QStatusBar(this));
583  setGeometry(100, 100, 800, 650);
584  setWindowTitle("Edd - Evidence Data Display");
585
586  Edd_Indicator *Value;
587  Edd_Plot *Graph;
588  Edd_Textout *Textout; 
589  QString Text;
590
591   // TextBox for value
592  //Value = new Edd_Indicator((char *) "SQM/NSB", Central);
593  //Graph = new Edd_Plot((char *) "SQM/NSB", Central);
594  //Graph->AddService("BIAS/VOLT/ID00/00-000");
595 
596
597  // Clock (updated every second)
598  //Clock = new QwtAnalogClock(Central);
599  //Clock->scaleDraw()->setPenWidth(3);
600  //Clock->setLineWidth(6);
601  //Clock->setFrameShadow(QwtDial::Sunken);
602  //Clock->setGeometry(0,0,10,10);
603  //Clock->setTime();
604 
605  //QTimer *Timer = new QTimer(Clock);
606  //Timer->connect(Timer, SIGNAL(timeout()), Clock, SLOT(setCurrentTime()));
607  //Timer->start(1000);
608
609  MainWidget = new QWidget();
610  MainLayout = new QGridLayout(MainWidget);
611
612  Value = new Edd_Indicator("Alarm/Status");
613  Value->setMaximumWidth(200);
614  MainLayout->addWidget(Value, 0, 0, 1, 2);     
615
616  Value = new Edd_Indicator("Alarm/MasterAlarm");
617  MainLayout->addWidget(Value, 0, 1, 1, 1);
618
619  Textout = new Edd_Textout("Alarm/Summary");
620  Textout->Accumulate = false;
621  Textout->setMaximumWidth(200);
622  Textout->setMaximumHeight(150);
623  MainLayout->addWidget(Textout, 1, 0, 1, 2);
624
625  QFrame *Val = new QFrame();
626  Val->setFrameStyle(QFrame::HLine);
627  Val->setLineWidth(10);
628  //Value->setMaximumWidth(200);
629  MainLayout->addWidget(Val, 2, 0, 2, 1);     
630
631  Value = new Edd_Indicator("DColl/Status");
632  Value->setMaximumWidth(200);
633  MainLayout->addWidget(Value, 3, 0, 1, 2);     
634
635  Value = new Edd_Indicator("DColl/DataSizekB");
636  MainLayout->addWidget(Value, 4, 0, 1, 1);
637
638  Value = new Edd_Indicator("DColl/LogSizekB");
639  MainLayout->addWidget(Value, 4, 1, 1, 1);
640
641  Value = new Edd_Indicator("DColl/CurrentFile");
642  Value->setMaximumWidth(400);
643  MainLayout->addWidget(Value, 5, 0, 1, 3);
644
645  Value = new Edd_Indicator("Config/Status");
646  Value->setMaximumWidth(200);
647  MainLayout->addWidget(Value, 6, 0, 1, 2);     
648
649  Value = new Edd_Indicator("Config/ModifyTime");
650  Value->setMaximumWidth(200);
651  Value->ShowAsTime = true;
652  MainLayout->addWidget(Value, 7, 0, 1, 1);
653
654
655  // Layout of all widgets
656  //MainLayout->addWidget(Value, 0, 0, 1, 1);
657  //MainLayout->addWidget(Clock, 0, 1, 1, 1);
658  //MainLayout->addWidget(Graph, 1, 0, 1, 2);
659  //MainLayout->setColumnStretch(1, 10);
660 
661  //MainLayout->addWidget(Clock, 0, 1, 1, 1);
662  //MainLayout->addWidget(Graph1, 2, 0, 1, 2);
663
664  // Bias voltage page
665  BiasWidget = new QWidget();
666  BiasLayout = new QGridLayout(BiasWidget);
667  Graph = new Edd_Plot();
668  for (int i=0; i<18; i++) {
669    Text = Text.sprintf("Bias/VOLT/ID00/00-%.3d",i);
670    Value = new Edd_Indicator(Text);
671    BiasLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1);
672    Graph->AddService(Text);
673
674    Text = Text.sprintf("Bias/VOLT/ID00/01-%.3d",i);
675    Value = new Edd_Indicator(Text);
676    BiasLayout->addWidget(Value, i%9+1, 2+i/9, 1, 1);
677    Graph->AddService(Text);
678  }
679
680  BiasLayout->addWidget(Graph, 0, 4, 12, 3);
681  Value = new Edd_Indicator("Bias/Status");
682  Value->setMaximumWidth(200);
683  BiasLayout->addWidget(Value, 0, 0, 1, 3);     
684
685  Textout = new Edd_Textout("Bias/Textout");
686  Textout->setFixedWidth(400);
687  BiasLayout->addWidget(Textout, 10, 0, 4, 4);     
688 
689  // Environment page
690  EnvironmentWidget = new QWidget();
691  EnvironmentLayout = new QGridLayout(EnvironmentWidget);
692  Value = new Edd_Indicator("ARDUINO/Status");
693  Value->setMaximumWidth(200);
694  EnvironmentLayout->addWidget(Value, 0, 0, 1, 3);     
695
696  Graph = new Edd_Plot();
697  for (int i=0; i<10; i++) {
698    Text = Text.sprintf("ARDUINO/VAL%.2d", i);
699    Value = new Edd_Indicator(Text);
700    EnvironmentLayout->addWidget(Value, i%5+1, i/5, 1, 1);
701    Graph->AddService(Text);
702  }
703  EnvironmentLayout->addWidget(Graph, 0, 3, 7, 4);     
704
705  Value = new Edd_Indicator("SQM/NSB");
706  EnvironmentLayout->addWidget(Value, 6, 0, 1, 1);     
707
708  // Tab widget
709  TabWidget = new QTabWidget(Central);
710  TabWidget->addTab(BiasWidget, "&Bias");
711  TabWidget->addTab(EnvironmentWidget, "&Environment");
712  TabWidget->addTab(MainWidget, "Evidence");
713
714  // Menu bar
715  QMenu* Menu = menuBar()->addMenu("&Menu");
716  Menu->addAction("New history plot", this, SLOT(MenuNewHistory()));
717  Menu->addSeparator();
718  Menu->addAction("About", this, SLOT(MenuAbout()));
719  Menu->addSeparator();
720  QAction* QuitAction = Menu->addAction("Quit", qApp, SLOT(quit()));
721  QuitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
722
723  // Show main window
724  show();
725} 
726   
727GUI::~GUI() {
728  delete Central;
729}
730
731
732void GUI::MenuAbout() {
733  QString Rev(SVN_REVISION);
734  Rev.remove(0,1).chop(2);
735 
736  QMessageBox::about(this, "About Edd","Evidence Data Display\n\n"
737    "Written by Oliver Grimm, IPP, ETH Zurich\n"
738    "This version compiled "__DATE__" ("+Rev+")\n\n"
739    "Graphical user interface implemented with Qt and Qwt.\n"
740    "Evidence control system based on DIM (http://dim.web.cern.ch).\n\n"
741    "Comments to oliver.grimm@phys.ethz.ch.");
742}
743
744// Open request for new history plot
745void GUI::MenuNewHistory() {
746
747  QStringList List;
748  char *Name, *Format;
749  int Type;
750  bool OK;
751
752  // Find all services that are not history services and sort
753  getServices("*");
754  while ((Type = getNextService(Name, Format)) != 0) {
755    if (Type==DimSERVICE && strstr(Name, ".hist")==NULL) List.append(Name);
756  }
757  List.sort();
758
759  // Open dialog and open history window
760  QString Result = QInputDialog::getItem(this, "Edd Request",
761    "Enter DIM service name", List, 0, true, &OK);
762  if (OK && !Result.isEmpty()) {
763    Result = Result.trimmed();
764    if (Result.endsWith(".hist")) Result.chop(5);
765    Edd_Plot *Plot = new Edd_Plot(Result);
766    Plot->show();
767  }
768}
769
770// Handling of DIM service update
771void GUI::infoHandler() {
772
773  // Check if service available
774  if (getInfo()->getSize() == strlen(NO_LINK)+1 && strcmp(getInfo()->getString(), NO_LINK) == 0) {
775    YEP(getInfo(), -1);
776  }
777  else {
778    char *Txt = EvidenceServer::ToString(getInfo());
779
780    YEP(getInfo(), getInfo()->getTimestamp(), getInfo()->getFormat(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), QString(Txt));
781                free(Txt);
782  }
783}
784
785//---------------------------------------------------------------------
786//************************ All functions ****************************
787//-------------------------------------------------------------------
788
789// Quit application when clicking close button on window
790void GUI::closeEvent(QCloseEvent *) {
791  qApp->quit();
792}
793
794
795//---------------------------------------------------------------------
796//**************************** Main program ***************************
797//---------------------------------------------------------------------
798
799int main(int argc, char *argv[]) {
800
801  QApplication app(argc, argv); 
802  GUI MainWindow;
803
804  return app.exec();
805}
Note: See TracBrowser for help on using the repository browser.