source: Evidence/Edd/Edd.cc @ 142

Last change on this file since 142 was 142, checked in by ogrimm, 11 years ago
Various updates
File size: 21.9 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() + 2]) {
72        case 0:  Pal.setColor(QPalette::Base, Qt::white); break;
73        case 1:  Pal.setColor(QPalette::Base, Qt::cyan); 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  insertLegend(Legend, QwtPlot::TopLegend);
177
178  // Connect to DIM handler
179  if (connect(Handler, SIGNAL(YEP(DimInfo *, int, QString, QByteArray, QString)), SLOT(Update(DimInfo *, int, QString, QByteArray, QString))) == false) {
180    printf("Failed connection for %s\n", DIMService.toAscii().data());
181  }
182
183  // Context menu
184  Menu = new QMenu(this);
185  YLogAction = Menu->addAction("y scale log", this, SLOT(UpdatePlot()));
186  YLogAction->setCheckable(true);
187  NormAction = Menu->addAction("Normalize", this, SLOT(UpdatePlot()));
188  NormAction->setCheckable(true);
189  StyleAction = Menu->addAction("Draw dots", this, SLOT(UpdatePlot()));
190  StyleAction->setCheckable(true);
191  Menu->addAction("Zoom out", this, SLOT(MenuZoomOut()));
192  Menu->addAction("Single trace", this, SLOT(MenuSingleTrace()));
193  Menu->addSeparator();
194  Menu->addAction("Save as ASCII", this, SLOT(MenuSaveASCII()));
195  Menu->addAction("Save plot", this, SLOT(MenuSave()));
196  Menu->addAction("Print plot", this, SLOT(MenuPrint()));
197  Menu->addSeparator();
198  Menu->addAction("Paste service", this, SLOT(MenuPasteService()));
199
200  // DIM client
201  if (!DIMService.isEmpty()) AddService(DIMService);
202}
203
204//
205// Destructor (items with parent widget are automatically deleted)
206//
207Edd_Plot::~Edd_Plot() {
208
209  for (int i=0; i<Items.size(); i++) {
210    delete Items[i].Data;
211    delete Items[i].LiveData;
212    delete Items[i].Signal;
213    delete[] Items[i].x;
214    delete[] Items[i].y;
215  } 
216  delete Grid;
217}
218
219//
220// Add history service to plot
221//
222void Edd_Plot::AddService(QString Name) {
223
224  QString HistName = Name+".hist";
225
226  // Lock before accessing Items list
227  QMutexLocker Locker(&Mutex);
228
229  // Check if already subsribed to service
230  for (int i=0; i<Items.size(); i++) {
231    if (HistName == Items[i].Data->getName()) {
232      QMessageBox::warning(this, "Edd Message",HistName+" already present",QMessageBox::Ok);
233      return;
234    }
235  } 
236 
237  // Generate new curve and subscribe to service
238  struct PlotItem New;
239  New.Signal = new QwtPlotCurve;
240  New.Signal->attach(this);
241  New.Signal->setTitle(HistName);
242  New.Signal->setPen(QColor(LineColors[Items.size() % (sizeof(LineColors)/sizeof(Qt::GlobalColor))]));
243  New.x = NULL;
244  New.y = NULL;
245  New.Count = 0;
246  New.Data = new DimStampedInfo(HistName.toAscii().data(), (char *) NO_LINK, Handler);
247  New.LiveData = new DimStampedInfo(Name.toAscii().data(), (char *) NO_LINK, Handler); 
248
249  Items.append(New);
250}
251
252// Update widget (must happen in GUI thread)
253void Edd_Plot::Update(DimInfo *Info, int Time, QString Format, QByteArray Data, QString Text) {
254
255  // Check if service available
256  if (Time == -1) {
257        setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
258  }
259
260  // Lock before accessing Items list
261  QMutexLocker Locker(&Mutex);
262
263  // Determine which plot item this call belongs to
264  int ItemNo;
265  for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Info == Items[ItemNo].Data) {
266    // This is a history service 
267    EvidenceHistoryItem *Curr = (EvidenceHistoryItem *) Data.data();
268    int Count=0, DataPoints = Data.size()/sizeof(struct EvidenceHistoryItem);
269
270    delete[] Items[ItemNo].x;
271    delete[] Items[ItemNo].y;
272    Items[ItemNo].x = new int [DataPoints];
273    Items[ItemNo].y = new double [DataPoints];
274
275    // Find oldest item
276    int Oldest;
277    for (Oldest=1; Oldest<DataPoints; Oldest++) {
278      if (Curr[Oldest].Seconds < Curr[Oldest-1].Seconds) break;
279    }
280
281    // Plot data starting with oldest value
282    for (int i=0; i<DataPoints; i++) {
283      Items[ItemNo].x[Count] = Curr[(i+Oldest)%DataPoints].Seconds;
284      Items[ItemNo].y[Count] = Curr[(i+Oldest)%DataPoints].Value;
285      if (Items[ItemNo].x[Count] != 0) Count++;
286    }
287
288    // Find smallest and largest item
289    double Smallest = DBL_MAX, Largest = DBL_MIN;
290    for (int i=0; i<Count; i++) {
291      if (Largest < Items[ItemNo].y[i]) Largest = Items[ItemNo].y[i];
292      if (Smallest > Items[ItemNo].y[i]) Smallest = Items[ItemNo].y[i];
293    }
294    Items[ItemNo].Smallest = Smallest;
295    Items[ItemNo].Largest = Largest;
296    Items[ItemNo].Count = Count;
297
298    // Clear local history
299    Items[ItemNo].Live.clear();
300
301    // Update status tip
302    QDateTime Timex = QDateTime::fromTime_t(Time); 
303    StatusTip = QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), Timex.toString()).arg(Format);
304
305  } else if (Info == Items[ItemNo].LiveData) {
306    // This is a live service
307
308    // Limit size of list
309    if (Items[ItemNo].Live.size() > 1000) Items[ItemNo].Live.removeFirst();
310
311    // Append data
312    struct EvidenceHistoryItem Data;
313    Data.Seconds = Time;
314    Data.Value = atof(Text.toAscii().data());           
315    Items[ItemNo].Live.append(Data);
316
317    // Update largest and smallest value   
318    if (Data.Value > Items[ItemNo].Largest) Items[ItemNo].Largest = Data.Value;
319    if (Data.Value < Items[ItemNo].Smallest) Items[ItemNo].Smallest = Data.Value;   
320  }
321
322  Locker.unlock();
323
324  UpdatePlot();
325}
326
327//
328// Update all curves in plot
329//
330void Edd_Plot::UpdatePlot() {
331
332  static QwtSymbol Symbol, Sym1;
333  Symbol.setStyle(QwtSymbol::Ellipse);
334  Symbol.setSize(4);
335
336  if (!YLogAction->isChecked()) {
337    setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
338  }
339  else setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10ScaleEngine);
340
341  // Lock before accessing Items list
342  QMutexLocker Locker(&Mutex);
343
344  setStatusTip(StatusTip);
345 
346  for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
347
348    if (StyleAction->isChecked()) Items[ItemNo].Signal->setSymbol(Symbol);
349    else Items[ItemNo].Signal->setSymbol(Sym1);
350
351    int DataPoints = Items[ItemNo].Count + Items[ItemNo].Live.size();
352       
353        if (DataPoints == 0) continue;
354   
355    double *x = new double [DataPoints];
356    double *y = new double [DataPoints];
357 
358    // Adapt time scale and normalize y scale if requested
359    for (int i=0; i<DataPoints; i++) {
360      if (i < Items[ItemNo].Count) {
361        x[i] = Items[ItemNo].x[i] / 86400.0 + 40587.5 - 55200;
362        y[i] = Items[ItemNo].y[i];
363      }
364      else {
365        x[i]= Items[ItemNo].Live[i-Items[ItemNo].Count].Seconds / 86400.0 + 40587.5 - 55200;
366        y[i] = Items[ItemNo].Live[i-Items[ItemNo].Count].Value;
367      }
368
369      if (NormAction->isChecked()) {
370        if (Items[ItemNo].Smallest != Items[ItemNo].Largest) y[i] = (y[i] - Items[ItemNo].Smallest)/(Items[ItemNo].Largest-Items[ItemNo].Smallest);
371        else y[i] = 1;
372      } 
373    }
374
375    // Plot datas
376    Items[ItemNo].Signal->setData(x, y, DataPoints);
377    Items[ItemNo].Signal->show();
378    Zoomer->setZoomBase(Items[ItemNo].Signal->boundingRect());
379
380    delete[] x;
381    delete[] y;
382  }
383  replot();
384}
385
386//
387// Reset graph axes to autoscale when fully unzoomed
388//
389void Edd_Plot::HandleZoom(const QwtDoubleRect &) {
390
391  if(Zoomer->zoomRectIndex() == 0) {
392    setAxisAutoScale(QwtPlot::xBottom);
393    setAxisAutoScale(QwtPlot::yLeft);
394  }
395}
396
397//
398// Drag and drop methods
399//
400
401void Edd_Plot::dragEnterEvent(QDragEnterEvent *Event) {
402   
403  if (Event->mimeData()->hasFormat("text/plain")) Event->acceptProposedAction();
404}
405
406void Edd_Plot::dropEvent(QDropEvent *Event) {
407
408  AddService(Event->mimeData()->text().toAscii().data());
409}
410   
411//
412// Opening context menu
413//
414void Edd_Plot::contextMenuEvent(QContextMenuEvent *Event) {
415
416  Menu->exec(Event->globalPos());
417}
418
419void Edd_Plot::MenuZoomOut() {
420
421  Zoomer->zoom(0);
422  UpdatePlot();
423}
424
425// Remove all items except last
426void Edd_Plot::MenuSingleTrace() {
427
428  // Lock before accessing Items list
429  QMutexLocker Locker(&Mutex);
430
431  while (Items.size() > 1) { 
432    delete Items.last().Data;
433    delete Items.last().LiveData;
434    delete Items.last().Signal;
435    delete[] Items.last().x;
436    delete[] Items.last().y;
437    Items.takeLast();
438  }
439 
440  Locker.unlock();
441  UpdatePlot();
442}
443
444// Save data of plot as test
445void Edd_Plot::MenuSaveASCII() {
446  QString Filename = QFileDialog::getSaveFileName(this,
447     "Filename", ".", "Text files (*.txt *.ascii *.asc);;All files (*)");
448  if (Filename.length() <= 0) return;
449 
450  QFile File(Filename);
451  if (!File.open(QFile::WriteOnly | QIODevice::Text | QFile::Truncate)) {
452    QMessageBox::warning(this, "Edd Message","Could not open file for writing.",QMessageBox::Ok);
453    return;
454  }
455 
456  // Lock before accessing Items list
457  QMutexLocker Locker(&Mutex);
458  QTextStream Stream(&File);
459
460   // Write x and y data for all signals to file
461  for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
462    Stream << QString("# ")+Items[ItemNo].Data->getName() << endl;
463    for (int i=0; i<Items[ItemNo].Signal->dataSize(); i++) {
464      Stream << (int) Items[ItemNo].x[i] << " " << Items[ItemNo].Signal->y(i) << endl;
465    }
466  }
467}
468
469// Print plot
470void Edd_Plot::MenuPrint() {
471
472  QPrinter *Printer = new QPrinter;
473  QPrintDialog *PrintDialog = new QPrintDialog(Printer, this);
474  if (PrintDialog->exec() == QDialog::Accepted) {
475    QPainter Painter(Printer);
476    QPixmap Pixmap = QPixmap::grabWidget(this);
477    Painter.drawPixmap(0, 0, Pixmap);
478  }
479  delete Printer;       delete PrintDialog;
480}
481
482// Save plot as image
483void Edd_Plot::MenuSave() {
484
485  QString Filename = QFileDialog::getSaveFileName(this,
486     "Filename of image", "/home/ogrimm/ddd", "Image files (*.bmp *.jpg *.png *.ppm *.tiff *.xbm *.xpm);;All files (*)");
487  if (Filename.length()>0) {
488    QPixmap Pixmap = QPixmap::grabWidget(this);
489    if(!Pixmap.save(Filename)) {
490      QMessageBox::warning(this, "Edd Message","Could not write image file.",QMessageBox::Ok);
491      remove(Filename.toAscii().data());
492    }
493  }
494}
495
496// Add new service by pasting name
497void Edd_Plot::MenuPasteService() {
498
499  AddService(QApplication::clipboard()->text().toAscii().data());
500}
501
502
503//////////////////
504// Text display //
505//////////////////
506
507// Constructor
508Edd_Textout::Edd_Textout(QString DIMService, QWidget *P): QTextEdit(P) {
509
510  // Widget properties
511  setReadOnly(true);
512  setAutoFillBackground(true);
513  document()->setMaximumBlockCount(1000);
514  Accumulate = true;
515 
516  // Connect to DIM handler
517  if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QString, QByteArray, QString)), SLOT(Update(DimInfo*, int, QString, QByteArray, QString))) == false) {
518    printf("Failed connection for %s\n", DIMService.toAscii().data());
519  }
520
521  // DIM client
522  Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, (char *) NO_LINK, Handler);
523}
524
525// Destructor
526Edd_Textout::~Edd_Textout() {
527
528  delete Data;
529}
530
531// Handling of DIM service update
532void Edd_Textout::Update(DimInfo *Info, int Time, QString Format, QByteArray, QString Text) {
533
534  if (Info != this->Data) return;
535 
536  QPalette Pal = palette(); 
537
538  // Check if service available
539  if (Time == -1) {
540        setStatusTip(QString("%1:  unavailable").arg(Info->getName()));
541    Pal.setColor(QPalette::Base, Qt::lightGray);
542  }
543  else {
544    Pal.setColor(QPalette::Base, Qt::white);
545
546        // Clear display in case text should not accumulate
547        if (Accumulate == false) clear();
548       
549    // Add if service contains only a string
550    if (Format == "C") insertPlainText(Text);
551
552    // Update status tip
553    setStatusTip(QString("%1:  Last update %2  Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Format));
554  }
555  setPalette(Pal);
556}
557
558
559//
560// Main GUI (all widgets have ultimately Central as parent)
561//
562GUI::GUI() {
563 
564  Handler = this;
565 
566  // Set features of main window
567  Central = new QWidget(this);
568  setCentralWidget(Central);
569  setStatusBar(new QStatusBar(this));
570  setGeometry(100, 100, 800, 650);
571  setWindowTitle("Edd - Evidence Data Display");
572
573  Edd_Indicator *Value;
574  Edd_Plot *Graph;
575  Edd_Textout *Textout; 
576  QString Text;
577
578   // TextBox for value
579  //Value = new Edd_Indicator((char *) "SQM/NSB", Central);
580  //Graph = new Edd_Plot((char *) "SQM/NSB", Central);
581  //Graph->AddService("BIAS/VOLT/ID00/00-000");
582 
583
584  // Clock (updated every second)
585  //Clock = new QwtAnalogClock(Central);
586  //Clock->scaleDraw()->setPenWidth(3);
587  //Clock->setLineWidth(6);
588  //Clock->setFrameShadow(QwtDial::Sunken);
589  //Clock->setGeometry(0,0,10,10);
590  //Clock->setTime();
591 
592  //QTimer *Timer = new QTimer(Clock);
593  //Timer->connect(Timer, SIGNAL(timeout()), Clock, SLOT(setCurrentTime()));
594  //Timer->start(1000);
595
596  MainWidget = new QWidget();
597  MainLayout = new QGridLayout(MainWidget);
598
599  Value = new Edd_Indicator("DColl/DataSizekB");
600  MainLayout->addWidget(Value, 3, 5, 1, 1);
601
602  Value = new Edd_Indicator("DColl/LogSizekB");
603  MainLayout->addWidget(Value, 4, 5, 1, 1);
604
605  Value = new Edd_Indicator("Config/ModifyTime");
606  Value->setMaximumWidth(200);
607  Value->ShowAsTime = true;
608  MainLayout->addWidget(Value, 5, 5, 1, 1);
609
610  Value = new Edd_Indicator("Alarm/MasterAlarm");
611  MainLayout->addWidget(Value, 2, 0, 1, 1);
612
613  Textout = new Edd_Textout("Alarm/Summary");
614  Textout->Accumulate = false;
615  MainLayout->addWidget(Textout, 3, 0, 2, 1);
616
617  // Layout of all widgets
618  //MainLayout->addWidget(Value, 0, 0, 1, 1);
619  //MainLayout->addWidget(Clock, 0, 1, 1, 1);
620  //MainLayout->addWidget(Graph, 1, 0, 1, 2);
621  //MainLayout->setColumnStretch(1, 10);
622 
623  //MainLayout->addWidget(Clock, 0, 1, 1, 1);
624  //MainLayout->addWidget(Graph1, 2, 0, 1, 2);
625
626  // Bias voltage page
627  BiasWidget = new QWidget();
628  BiasLayout = new QGridLayout(BiasWidget);
629  Graph = new Edd_Plot();
630  for (int i=0; i<18; i++) {
631    Text = Text.sprintf("BIAS/VOLT/ID00/00-%.3d",i);
632    Value = new Edd_Indicator(Text);
633    BiasLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1);
634    Graph->AddService(Text);
635
636    Text = Text.sprintf("BIAS/VOLT/ID00/01-%.3d",i);
637    Value = new Edd_Indicator(Text);
638    BiasLayout->addWidget(Value, i%9+1, 2+i/9, 1, 1);
639    Graph->AddService(Text);
640  }
641
642  BiasLayout->addWidget(Graph, 0, 4, 12, 3);
643  Value = new Edd_Indicator("BIAS/Status");
644  Value->setMaximumWidth(200);
645  BiasLayout->addWidget(Value, 0, 0, 1, 3);     
646
647  Textout = new Edd_Textout("BIAS/Textout");
648  Textout->setFixedWidth(400);
649  BiasLayout->addWidget(Textout, 10, 0, 4, 4);     
650 
651  // Environment page
652  EnvironmentWidget = new QWidget();
653  EnvironmentLayout = new QGridLayout(EnvironmentWidget);
654  Value = new Edd_Indicator("ARDUINO/Status");
655  Value->setMaximumWidth(200);
656  EnvironmentLayout->addWidget(Value, 0, 0, 1, 3);     
657
658  Graph = new Edd_Plot();
659  for (int i=0; i<10; i++) {
660    Text = Text.sprintf("ARDUINO/VAL%.2d", i);
661    Value = new Edd_Indicator(Text);
662    EnvironmentLayout->addWidget(Value, i%5+1, i/5, 1, 1);
663    Graph->AddService(Text);
664  }
665  EnvironmentLayout->addWidget(Graph, 0, 3, 7, 4);     
666
667  Value = new Edd_Indicator("SQM/NSB");
668  EnvironmentLayout->addWidget(Value, 6, 0, 1, 1);     
669
670  // Tab widget
671  TabWidget = new QTabWidget(Central);
672  TabWidget->addTab(MainWidget, "&Main");
673  TabWidget->addTab(BiasWidget, "&Bias");
674  TabWidget->addTab(EnvironmentWidget, "&Environment");
675
676  // Menu bar
677  QMenu* Menu = menuBar()->addMenu("&Menu");
678  Menu->addAction("New history plot", this, SLOT(MenuNewHistory()));
679  Menu->addSeparator();
680  Menu->addAction("About", this, SLOT(MenuAbout()));
681  Menu->addSeparator();
682  QAction* QuitAction = Menu->addAction("Quit", qApp, SLOT(quit()));
683  QuitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
684
685  // Show main window
686  show();
687} 
688   
689GUI::~GUI() {
690  delete Central;
691}
692
693
694void GUI::MenuAbout() {
695  QString Rev(SVN_REVISION);
696  Rev.remove(0,1).chop(2);
697 
698  QMessageBox::about(this, "About Edd","Evidence Data Display\n\n"
699    "Written by Oliver Grimm, IPP, ETH Zurich\n"
700    "This version compiled "__DATE__" ("+Rev+")\n\n"
701    "Graphical user interface implemented with Qt and Qwt.\n"
702    "Evidence control system based on DIM (http://dim.web.cern.ch).\n\n"
703    "Comments to oliver.grimm@phys.ethz.ch.");
704}
705
706// Open request for new history plot
707void GUI::MenuNewHistory() {
708
709  QStringList List;
710  char *Name, *Format;
711  int Type;
712  bool OK;
713
714  // Find all services that are not history services and sort
715  getServices("*");
716  while ((Type = getNextService(Name, Format)) != 0) {
717    if (Type==DimSERVICE && strstr(Name, ".hist")==NULL) List.append(Name);
718  }
719  List.sort();
720
721  // Open dialog and open history window
722  QString Result = QInputDialog::getItem(this, "Edd Request",
723    "Enter DIM service name", List, 0, true, &OK);
724  if (OK && !Result.isEmpty()) {
725    Result = Result.trimmed();
726    if (Result.endsWith(".hist")) Result.chop(5);
727    Edd_Plot *Plot = new Edd_Plot(Result);
728    Plot->show();
729  }
730}
731
732// Handling of DIM service update
733void GUI::infoHandler() {
734
735  // Check if service available
736  if (getInfo()->getSize() == strlen(NO_LINK)+1 && strcmp(getInfo()->getString(), NO_LINK) == 0) {
737    YEP(getInfo(), -1);
738  }
739  else {
740    char *Txt = EvidenceServer::ToString(getInfo());
741
742    YEP(getInfo(), getInfo()->getTimestamp(), getInfo()->getFormat(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), QString(Txt));
743                free(Txt);
744  }
745}
746
747//---------------------------------------------------------------------
748//************************ All functions ****************************
749//-------------------------------------------------------------------
750
751// Quit application when clicking close button on window
752void GUI::closeEvent(QCloseEvent *) {
753  qApp->quit();
754}
755
756
757//---------------------------------------------------------------------
758//**************************** Main program ***************************
759//---------------------------------------------------------------------
760
761int main(int argc, char *argv[]) {
762
763  QApplication app(argc, argv); 
764  GUI MainWindow;
765
766  return app.exec();
767}
Note: See TracBrowser for help on using the repository browser.