source: Evidence/Edd/Edd.cc@ 154

Last change on this file since 154 was 154, checked in by ogrimm, 15 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.