source: Evidence/Edd/Edd.cc@ 163

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