- Timestamp:
- 05/18/10 15:39:48 (15 years ago)
- Location:
- Evidence/Edd
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
Evidence/Edd/Edd.cc
r204 r208 37 37 } 38 38 39 // Set status tip (returns true if service was available) 40 bool SetStatus(QWidget *W, QString Name, int Time, QString Format, int Index) { 41 42 QString Status; 43 44 if (Index != -1) Name = Name + "(" + QString::number(Index) + ")"; 45 46 if (Time == -1) Status = QString("%1: unavailable").arg(Name); 47 else Status = QString("%1: Last update %2 Format '%3'").arg(Name).arg(QDateTime::fromTime_t(Time).toString()).arg(Format); 48 49 W->setStatusTip(Status); 50 if (W->parent() == NULL) W->setToolTip(Status); 51 52 return(Time != -1); 53 } 54 39 55 40 56 ////////////////////////////////////////// … … 45 61 EddLineDisplay::EddLineDisplay(QString Name, int Index, QWidget *P): 46 62 QLineEdit(P), ServiceName(Name), Index(Index) { 47 63 48 64 LastPlot = NULL; 49 65 … … 52 68 setMaximumWidth(100); 53 69 ShowAsTime = false; 70 setFrame(false); 54 71 55 72 // Connect to DIM handler … … 82 99 83 100 // Check if service available 84 if ( Time == -1) {101 if (!SetStatus(this, Name, Time, Format, Index)) { 85 102 setText("n/a"); 86 setStatusTip(QString("%1: unavailable").arg(ServiceName));87 103 Pal.setColor(QPalette::Base, Qt::lightGray); 88 104 } … … 102 118 else setText(QDateTime::fromTime_t(Text.toInt()).toString()); 103 119 setCursorPosition(0); 104 105 // Update status tip106 setStatusTip(QString("%1 (%4): Last update %2 Format '%3'").arg(ServiceName).arg( QDateTime::fromTime_t(Time).toString()).arg(Format).arg(Index));107 120 } 108 121 … … 183 196 ////////////////////////////////// 184 197 185 //186 198 // Constructor 187 // 188 EddPlot::EddPlot(QString DIMService, int Index, QWidget *P): 189 QwtPlot(P) { 190 191 Mutex = new QMutex(QMutex::Recursive); 192 199 EddPlot::EddPlot(QString DIMService, int Index, QWidget *P): EddBasePlot(P) { 200 193 201 // Widget properties 194 202 setAcceptDrops(true); 203 setAxisScaleDraw(QwtPlot::xBottom, new EddTimeScale); 204 205 // Update time range on plot when axis change (update() results in paintEvent()) 206 connect(axisWidget(QwtPlot::xBottom), SIGNAL(scaleDivChanged()), SLOT(update())); 207 208 legend()->setItemMode(QwtLegend::ClickableItem); 209 connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *))); 210 211 // Connect to DIM handler 212 if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString))) == false) { 213 printf("Failed connection for %s\n", DIMService.toAscii().data()); 214 } 215 216 // Additonal context menu items 217 QAction* Action = Menu->addAction("Paste service", this, SLOT(MenuPasteService())); 218 Menu->removeAction(Action); 219 Menu->insertAction(Menu->actions().value(1), Action); 220 221 // Maximum number if points in curve (will be increased in Update()) 222 SizeLimit = 0; 223 224 // DIM client 225 if (!DIMService.isEmpty()) AddService(DIMService, Index); 226 } 227 228 // Destructor (items with parent widget are automatically deleted) 229 EddPlot::~EddPlot() { 230 231 while (!List.isEmpty()) DeleteCurve(List.last().Signal); 232 } 233 234 // Add history service to plot 235 void EddPlot::AddService(QString Name, int Index) { 236 237 // Check if curve already present on plot 238 for (int i=0; i<List.size(); i++) { 239 if (Name == List[i].Name && Index == List[i].Index) { 240 QMessageBox::warning(this, "Edd Message",Name+" ("+QString::number(Index)+") already present",QMessageBox::Ok); 241 return; 242 } 243 } 244 245 // Generate new curve and subscribe to service 246 struct ItemDetails N; 247 248 N.Name = Name; 249 N.Signal = NewCurve(Name+"("+QString::number(Index)+")"); 250 N.Index = Index; 251 List.append(N); 252 253 Handler->Subscribe(Name); 254 } 255 256 // Update widget (must happen in GUI thread) 257 void EddPlot::Update(QString Name, int Time, QByteArray, QString Format, QString Text) { 258 259 // Determine which plot item this call belongs to 260 int ItemNo; 261 for (ItemNo=0; ItemNo<List.size(); ItemNo++) if (List[ItemNo].Name == Name) { 262 263 // Service available? 264 if (!SetStatus(this, Name, Time, Format)) return; 265 266 // If size limit reached, clear buffer 267 if (List[ItemNo].Signal->dataSize() > SizeLimit) List[ItemNo].Signal->setData(QPolygonF()); 268 269 // If buffer empty, request new history buffer 270 if (List[ItemNo].Signal->dataSize() == 0) { 271 int Time, Size; 272 void *Data; 273 274 class EvidenceHistory *HistClass = Handler->GetHistory(List[ItemNo].Name); 275 276 if (HistClass->GetHistory()) { 277 double Number=0; 278 while (HistClass->Next(Time, Size, Data)) { 279 switch (Format[0].toUpper().toAscii()) { 280 case 'I': 281 case 'L': Number = *((int *) Data + List[ItemNo].Index); break; 282 case 'S': Number = *((short *) Data + List[ItemNo].Index); break; 283 case 'F': Number = *((float *) Data + List[ItemNo].Index); break; 284 case 'D': Number = *((double *) Data + List[ItemNo].Index); break; 285 case 'X': Number = *((long long *) Data + List[ItemNo].Index); break; 286 default: break; 287 } 288 AddPoint(ItemNo, Time, Number); 289 } 290 291 // Local buffer at least twice as large as longest history 292 if (SizeLimit < 2*List[ItemNo].Signal->dataSize()) SizeLimit = 2*List[ItemNo].Signal->dataSize(); 293 } 294 } 295 296 // Append data 297 QString Txt = Text; 298 Txt = Txt.section(' ', List[ItemNo].Index, List[ItemNo].Index); 299 AddPoint(ItemNo, Time, atof(Txt.toAscii().data())); 300 } 301 302 UpdatePlot(); 303 } 304 305 306 // Add text indicating time range to plot 307 void EddPlot::paintEvent(QPaintEvent *) { 308 309 QString Text; 310 QFont Font; 311 QPainter Painter(this); 312 313 Text = QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->lowerBound()).toString("d-MMM-yyyy hh:mm:ss") + " to " + QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->upperBound()).toString("d-MMM-yyyy hh:mm:ss"); 314 315 Font.setPointSize(6); 316 Painter.setFont(Font); 317 Painter.drawText(0, height(), Text); 318 } 319 320 // Drag and drop methods 321 void EddPlot::dragEnterEvent(QDragEnterEvent *Event) { 322 323 if (Event->mimeData()->hasFormat("Edd/Service")) Event->acceptProposedAction(); 324 } 325 326 void EddPlot::dropEvent(QDropEvent *Event) { 327 328 QByteArray D(Event->mimeData()->data("Edd/Service")); 329 AddService(D.left(D.lastIndexOf(' ')), D.right(D.size()-D.lastIndexOf(' ')).toInt()); 330 } 331 332 void EddPlot::LegendClicked(QwtPlotItem *Item) { 333 334 QString D(Item->title().text()); 335 D.replace('(',' ').chop(1); 336 337 QDrag *Drag = new QDrag(this); 338 QMimeData *MimeData = new QMimeData; 339 QByteArray Data; 340 MimeData->setData("Edd/Service", Data.append(D)); 341 Drag->setMimeData(MimeData); 342 Drag->exec(); 343 } 344 345 // Add new service by pasting name 346 void EddPlot::MenuPasteService() { 347 348 const QMimeData *D = QApplication::clipboard()->mimeData(); 349 if (!D->hasFormat("Edd/Service")) return; 350 351 QByteArray E(D->data("Edd/Service")); 352 AddService(E.left(E.lastIndexOf(' ')), E.right(E.size()-E.lastIndexOf(' ')).toInt()); 353 } 354 355 // Remove list entry 356 void EddPlot::DeleteCurve(QwtPlotCurve *Curve) { 357 358 for (int i=0; i<List.size(); i++) if (List[i].Signal == Curve) { 359 Handler->Unsubscribe(List[i].Name); 360 List.removeAt(i); 361 } 362 } 363 364 365 ////////////////// 366 // General plot // 367 ////////////////// 368 369 // Constructor (all slots called in GUI thread, therefore no mutex necessary) 370 EddBasePlot::EddBasePlot(QWidget *P): QwtPlot(P) { 371 372 // Widget properties 195 373 setAttribute(Qt::WA_DeleteOnClose); 196 374 setAutoReplot(false); 197 375 setCanvasBackground(EddPlotBackgroundColor); 198 setAxisScaleDraw(QwtPlot::xBottom, new EddTimeScale);199 376 setMargin(15); 200 377 201 // Update additional information (e.g. time range) on widget when axis change 202 connect(axisWidget(QwtPlot::xBottom), SIGNAL(scaleDivChanged()), SLOT(update())); 203 204 Picker = new QwtPicker(QwtPicker::CornerToCorner|QwtPicker::RectSelection, QwtPicker::RectRubberBand, QwtPicker::AlwaysOff, this); 205 connect(Picker, SIGNAL(selected(const QwtPolygon &)), SLOT(MouseSelection(const QwtPolygon &))); 206 378 // Plot navigation 207 379 Zoomer = new QwtPlotZoomer(QwtPlot::xBottom,QwtPlot::yLeft,canvas()); 208 380 connect(Zoomer, SIGNAL(zoomed(const QwtDoubleRect &)), this, SLOT(HandleZoom(const QwtDoubleRect &))); … … 216 388 Panner->setMouseButton(Qt::LeftButton, Qt::ShiftModifier); 217 389 390 Picker = new QwtPicker(QwtPicker::CornerToCorner|QwtPicker::RectSelection, QwtPicker::RectRubberBand, QwtPicker::AlwaysOff, this); 391 connect(Picker, SIGNAL(selected(const QwtPolygon &)), SLOT(MouseSelection(const QwtPolygon &))); 392 393 // Grid and legend 218 394 Grid = new QwtPlotGrid; 219 395 Grid->setMajPen(QPen(Qt::gray, 0, Qt::DotLine)); 220 396 Grid->attach(this); 221 222 Legend = new QwtLegend(); 223 Legend->setItemMode(QwtLegend::ClickableItem); 224 insertLegend(Legend, QwtPlot::TopLegend, 0.3); 225 connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *))); 226 227 // Connect to DIM handler 228 if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString))) == false) { 229 printf("Failed connection for %s\n", DIMService.toAscii().data()); 230 } 397 398 insertLegend(new QwtLegend(), QwtPlot::TopLegend, 0.3); 231 399 232 400 // Context menu … … 247 415 Menu->addAction("Save plot", this, SLOT(MenuSave())); 248 416 Menu->addAction("Print plot", this, SLOT(MenuPrint())); 249 Menu->addSeparator();250 Menu->addAction("Paste service", this, SLOT(MenuPasteService()));251 417 Menu->addAction("Plot help", this, SLOT(MenuPlotHelp())); 252 253 // DIM client 254 if (!DIMService.isEmpty()) AddService(DIMService, Index); 255 } 256 257 // 418 } 419 258 420 // Destructor (items with parent widget are automatically deleted) 259 // 260 EddPlot::~EddPlot() { 261 262 for (int i=0; i<Items.size(); i++) { 263 Handler->Unsubscribe(Items[i].Name); 264 delete Items[i].Signal; 265 } 266 421 EddBasePlot::~EddBasePlot() { 422 423 for (int i=0; i<Items.size(); i++) delete Items[i].Signal; 267 424 delete Grid; 268 delete Mutex; 269 } 270 271 // 272 // Add history service to plot 273 // 274 void EddPlot::AddService(QString Name, int Index) { 275 276 // Lock before accessing Items list 277 QMutexLocker Locker(Mutex); 278 279 // Check if already subscribed to service 280 for (int i=0; i<Items.size(); i++) { 281 if (Name == Items[i].Name && Index == Items[i].Index) { 282 QMessageBox::warning(this, "Edd Message",Name+" ("+QString::number(Index)+") already present",QMessageBox::Ok); 283 return; 284 } 285 } 286 287 // Generate new curve and subscribe to service 288 struct PlotItem New; 289 290 New.Name = Name; 291 New.Signal = new QwtPlotCurve; 292 New.Signal->attach(this); 293 New.Signal->setTitle(Name+"("+QString::number(Index)+")"); 294 New.Signal->setPen(QColor(LineColors[Items.size() % (sizeof(LineColors)/sizeof(Qt::GlobalColor))])); 295 New.SizeLimit = 5000; 296 New.Index = Index; 297 298 Items.append(New); 299 Handler->Subscribe(Name); 300 } 301 302 // Update widget (must happen in GUI thread) 303 void EddPlot::Update(QString Name, int Time, QByteArray, QString Format, QString Text) { 304 305 // Lock before accessing Items list 306 QMutexLocker Locker(Mutex); 307 308 // Determine which plot item this call belongs to 309 int ItemNo; 310 for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Items[ItemNo].Name == Name) { 311 312 // Check if service available 313 if (Time == -1) { 314 setStatusTip(QString("%1: unavailable").arg(Name)); 315 return; 316 } 317 318 // If size limit reached, clear buffer 319 if (Items[ItemNo].x.size() > Items[ItemNo].SizeLimit) { 320 Items[ItemNo].x.clear(); 321 Items[ItemNo].y.clear(); 322 } 323 324 // If buffer empty, request new history buffer 325 if (Items[ItemNo].x.isEmpty()) { 326 int Time, Size; 327 void *Data; 328 329 class EvidenceHistory *HistClass = Handler->GetHistory(Items[ItemNo].Name); 330 331 if (HistClass->GetHistory()) { 332 double Smallest = DBL_MAX, Largest = DBL_MIN; 333 double Number=0; 334 while (HistClass->Next(Time, Size, Data)) { 335 switch (Format[0].toUpper().toAscii()) { 336 case 'I': 337 case 'L': Number = *((int *) Data + Items[ItemNo].Index); break; 338 case 'S': Number = *((short *) Data + Items[ItemNo].Index); break; 339 case 'F': Number = *((float *) Data + Items[ItemNo].Index); break; 340 case 'D': Number = *((double *) Data + Items[ItemNo].Index); break; 341 case 'X': Number = *((long long *) Data + Items[ItemNo].Index); break; 342 default: break; 343 } 344 Items[ItemNo].x.append(Time); 345 Items[ItemNo].y.append(Number); 346 347 if (Largest < Items[ItemNo].y.last()) Largest = Items[ItemNo].y.last(); 348 if (Smallest > Items[ItemNo].y.last()) Smallest = Items[ItemNo].y.last(); 349 } 350 351 Items[ItemNo].Smallest = Smallest; 352 Items[ItemNo].Largest = Largest; 353 354 // Local buffer always at least twice as large as history 355 if (Items[ItemNo].SizeLimit < 2*Items[ItemNo].x.size()) { 356 Items[ItemNo].SizeLimit = 2*Items[ItemNo].x.size(); 357 } 358 } 359 } 360 361 // Append data 362 QString Txt = Text; 363 Txt = Txt.section(' ', Items[ItemNo].Index, Items[ItemNo].Index); 364 Items[ItemNo].x.append(Time); 365 Items[ItemNo].y.append(atof(Txt.toAscii().data())); 366 367 // Update largest and smallest value 368 if (Items[ItemNo].y.last() > Items[ItemNo].Largest) Items[ItemNo].Largest = Items[ItemNo].y.last(); 369 if (Items[ItemNo].y.last() < Items[ItemNo].Smallest) Items[ItemNo].Smallest = Items[ItemNo].y.last(); 370 371 // Update status tip 372 QDateTime Timex = QDateTime::fromTime_t(Time); 373 setStatusTip(QString("%1: Last update %2 Format '%3'").arg(Name).arg(Timex.toString()).arg(Format)); 374 } 375 376 UpdatePlot(); 377 } 378 379 // 425 } 426 380 427 // Update all curves in plot 381 // 382 void EddPlot::UpdatePlot() { 428 void EddBasePlot::UpdatePlot() { 383 429 384 430 double Lower = axisScaleDiv(QwtPlot::xBottom)->lowerBound(); … … 394 440 } 395 441 else setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10ScaleEngine); 396 397 // Lock before accessing Items list398 QMutexLocker Locker(Mutex);399 442 400 443 for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) { … … 447 490 } 448 491 449 // Add text indicating time range to plot 450 void EddPlot::paintEvent(QPaintEvent *) { 451 452 QString Text; 453 QFont Font; 454 QPainter Painter(this); 455 456 Text = QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->lowerBound()).toString("d-MMM-yyyy hh:mm:ss") + " to " + QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->upperBound()).toString("d-MMM-yyyy hh:mm:ss"); 457 458 Font.setPointSize(6); 459 Painter.setFont(Font); 460 Painter.drawText(0, height(),Text); 492 // Append curve to plot 493 QwtPlotCurve *EddBasePlot::NewCurve(QwtText Title) { 494 495 struct PlotItem N; 496 497 N.Signal = new QwtPlotCurve; 498 N.Signal->attach(this); 499 N.Signal->setTitle(Title); 500 N.Signal->setPen(QColor(LineColors[Items.size() % (sizeof(LineColors)/sizeof(Qt::GlobalColor))])); 501 N.Largest = DBL_MIN; 502 N.Smallest = DBL_MAX; 503 Items.append(N); 504 505 return N.Signal; 506 } 507 508 // Clear curve data 509 void EddBasePlot::ClearCurve(unsigned int Item) { 510 511 if (Item >= (unsigned int) Items.size()) return; 512 513 Items[Item].x.clear(); 514 Items[Item].y.clear(); 515 } 516 517 // Append data point 518 void EddBasePlot::AddPoint(unsigned int Item, double x, double y) { 519 520 if (Item >= (unsigned int) Items.size()) return; 521 522 Items[Item].x.append(x); 523 Items[Item].y.append(y); 524 525 if (y > Items[Item].Largest) Items[Item].Largest = y; 526 if (y < Items[Item].Smallest) Items[Item].Smallest = y; 461 527 } 462 528 463 529 // Rescale plot in case selection has been made outside the canvas 464 void Edd Plot::MouseSelection(const QPolygon &P) {530 void EddBasePlot::MouseSelection(const QPolygon &P) { 465 531 466 532 QwtDoubleInterval xPlot, xMouse, yPlot, yMouse; … … 520 586 } 521 587 522 523 //524 588 // Reset graph axes to autoscale when fully unzoomed 525 // 526 void EddPlot::HandleZoom(const QwtDoubleRect &) { 589 void EddBasePlot::HandleZoom(const QwtDoubleRect &) { 527 590 528 591 if(Zoomer->zoomRectIndex() == 0) { … … 531 594 } 532 595 } 533 534 //535 // Drag and drop methods536 //537 538 void EddPlot::dragEnterEvent(QDragEnterEvent *Event) {539 540 if (Event->mimeData()->hasFormat("Edd/Service")) Event->acceptProposedAction();541 }542 543 void EddPlot::dropEvent(QDropEvent *Event) {544 545 QByteArray D(Event->mimeData()->data("Edd/Service"));546 AddService(D.left(D.lastIndexOf(' ')), D.right(D.size()-D.lastIndexOf(' ')).toInt());547 }548 596 549 597 // Opening context menu 550 void Edd Plot::contextMenuEvent(QContextMenuEvent *Event) {598 void EddBasePlot::contextMenuEvent(QContextMenuEvent *Event) { 551 599 552 600 Menu->exec(Event->globalPos()); 553 601 } 554 602 555 // Drag&Drop method556 void EddPlot::LegendClicked(QwtPlotItem *Item) {557 558 559 QString D(Item->title().text());560 D.replace('(',' ').chop(1);561 562 QDrag *Drag = new QDrag(this);563 QMimeData *MimeData = new QMimeData;564 QByteArray Data;565 MimeData->setData("Edd/Service", Data.append(D));566 Drag->setMimeData(MimeData);567 Drag->exec();568 }569 570 571 603 // Zoom completely out 572 void Edd Plot::MenuZoomOut() {604 void EddBasePlot::MenuZoomOut() { 573 605 574 606 Zoomer->zoom(0); … … 576 608 } 577 609 578 // Remove all items except last 579 void EddPlot::MenuSingleTrace() { 580 581 // Lock before accessing Items list 582 QMutexLocker Locker(Mutex); 610 // Remove all items except one 611 void EddBasePlot::MenuSingleTrace() { 583 612 584 613 while (Items.size() > 1) { 585 Handler->Unsubscribe(Items.last().Name);614 DeleteCurve(Items.last().Signal); 586 615 delete Items.last().Signal; 587 616 Items.takeLast(); … … 591 620 592 621 // Save data of plot as test 593 void Edd Plot::MenuSaveASCII() {622 void EddBasePlot::MenuSaveASCII() { 594 623 QString Filename = QFileDialog::getSaveFileName(this, 595 624 "Filename", ".", "Text files (*.txt *.ascii *.asc);;All files (*)"); … … 601 630 return; 602 631 } 603 604 // Lock before accessing Items list 605 QMutexLocker Locker(Mutex); 632 633 // Write x and y data for all signals to file 606 634 QTextStream Stream(&File); 607 635 608 // Write x and y data for all signals to file609 636 for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) { 610 Stream << QString("# ") + Items[ItemNo]. Name+ ".hist" << endl;637 Stream << QString("# ") + Items[ItemNo].Signal->title().text() + ".hist" << endl; 611 638 for (int i=0; i<Items[ItemNo].Signal->dataSize(); i++) { 612 639 Stream << (int) Items[ItemNo].x.at(i) << " " << Items[ItemNo].Signal->y(i) << endl; … … 616 643 617 644 // Print plot 618 void Edd Plot::MenuPrint() {645 void EddBasePlot::MenuPrint() { 619 646 620 647 QPrinter *Printer = new QPrinter; … … 629 656 630 657 // Save plot as image 631 void Edd Plot::MenuSave() {658 void EddBasePlot::MenuSave() { 632 659 633 660 QString Filename = QFileDialog::getSaveFileName(this, … … 642 669 } 643 670 644 // Add new service by pasting name645 void EddPlot::MenuPasteService() {646 647 const QMimeData *D = QApplication::clipboard()->mimeData();648 if (!D->hasFormat("Edd/Service")) return;649 650 QByteArray E(D->data("Edd/Service"));651 AddService(E.left(E.lastIndexOf(' ')), E.right(E.size()-E.lastIndexOf(' ')).toInt());652 }653 654 671 // Help text 655 void Edd Plot::MenuPlotHelp() {672 void EddBasePlot::MenuPlotHelp() { 656 673 657 674 QMessageBox::about(this, "Edd - Plot navigation", … … 667 684 } 668 685 669 670 686 ////////////////////////////////////// 671 687 // History text box for DIM service // 672 688 ////////////////////////////////////// 673 689 674 //675 690 // Constructor 676 //677 691 EddText::EddText(QString Name, bool Pure, QWidget *P): 678 692 QTextEdit(P), Name(Name), Pure(Pure) { … … 724 738 725 739 // Check if service available 726 if (Time == -1) { 727 setStatusTip(QString("%1: unavailable").arg(Name)); 740 if (!SetStatus(this, Name, Time, Format)) { 728 741 Pal.setColor(QPalette::Base, Qt::lightGray); 729 742 setPalette(Pal); … … 744 757 } 745 758 else if (Format == "C") insertPlainText(Text); 746 747 // Update status tip748 setStatusTip(QString("%1: Last update %2 Format '%3'").arg(Name).arg(Timex.toString()).arg(Format));749 759 } 750 760 … … 883 893 } 884 894 885 895 // 896 // 897 // ====== FACT specific part ====== 898 // 899 // 900 901 //////////////////////// 902 // Event oscilloscope // 903 //////////////////////// 904 905 // Constructor 906 EventScope::EventScope(QWidget *P): EddBasePlot(P), PixelMap("../../config/PixelMap.txt", false) { 907 908 Name = "Feedback/EventData"; 909 910 Tmpfile = tmpfile(); 911 if(Tmpfile == NULL) { 912 QMessageBox::warning(this, "Edd Message", "Could not open temporary file.", QMessageBox::Ok); 913 } 914 915 // Open file with RawDataCTX 916 RD = new RawDataCTX(true); 917 ErrCode = CTX_NOTOPEN; 918 919 // Context menu 920 PhysPipeAction = new QAction("Plot physical pipeline", this); 921 PhysPipeAction->setCheckable(true); 922 connect(PhysPipeAction, SIGNAL(triggered()), SLOT(PlotTraces())); 923 Menu->insertAction(StripAction, PhysPipeAction); 924 Menu->removeAction(StripAction); 925 926 // Initial trace 927 AddTrace(0,0,0); 928 929 // Connect to DIM handler 930 if (connect(Handler, SIGNAL(YEP(QString, int, QByteArray, QString, QString)), SLOT(Update(QString, int, QByteArray, QString, QString))) == false) { 931 printf("Failed connection for %s\n", Name.toAscii().data()); 932 } 933 Handler->Subscribe(Name); 934 } 935 936 // Destructor (items with parent widget are automatically deleted) 937 EventScope::~EventScope() { 938 939 Handler->Unsubscribe(Name); 940 while (!List.isEmpty()) DeleteCurve(List.last().Signal); 941 delete RD; 942 if (Tmpfile != NULL) fclose(Tmpfile); 943 } 944 945 // Add trace 946 void EventScope::AddTrace(int Board, int Chip, int Channel) { 947 948 struct ItemDetails N; 949 950 N.Signal = NewCurve(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel)+ " (" + DRS_to_Pixel(Board, Chip, Channel).c_str() + ")"); 951 N.Board = Board; 952 N.Chip = Chip; 953 N.Channel = Channel; 954 N.Trigger = new QwtPlotMarker(); 955 N.Trigger->setSymbol(QwtSymbol(QwtSymbol::Diamond, QBrush(N.Signal->pen().color()), N.Signal->pen(), QSize(10,10))); 956 N.Trigger->attach(this); 957 958 if (List.isEmpty()) { 959 QPen Pen = N.Signal->pen(); 960 Pen.setWidth(2); 961 N.Signal->setPen(Pen); 962 } 963 List.append(N); 964 965 PlotTraces(); 966 } 967 968 // Update last trace (to reflect current setting of spin boxes in DAQ page) 969 void EventScope::UpdateFirst(int Board, int Chip, int Channel) { 970 971 if (List.isEmpty()) return; 972 973 List.first().Signal->setTitle(QString::number(Board)+","+QString::number(Chip)+","+ QString::number(Channel) + " (" + DRS_to_Pixel(Board, Chip, Channel).c_str() + ")"); 974 List.first().Board = Board; 975 List.first().Chip = Chip; 976 List.first().Channel = Channel; 977 978 PlotTraces(); 979 } 980 981 // Update event buffer 982 void EventScope::Update(QString Name, int Time, QByteArray Data, QString Format, QString) { 983 984 if (Name != this->Name) return; 985 986 // Check if service available 987 if (!SetStatus(this, Name, Time, Format)) return; 988 if (Data.size() < (int) sizeof(RunHeader)) return; 989 990 // Open tempory file and write event data to this file 991 QTemporaryFile File; 992 if (!File.open()) { 993 QMessageBox::warning(this, "Edd Message","Could not open temporary file.",QMessageBox::Ok); 994 return; 995 } 996 if (File.write(Data) == -1) { 997 QMessageBox::warning(this, "Edd Message","Could not write data to temporary file.",QMessageBox::Ok); 998 return; 999 } 1000 1001 // Prepare temporary file for run header 1002 ftruncate(fileno(Tmpfile), 0); 1003 rewind(Tmpfile); 1004 1005 // Open file with RawDataCTX 1006 switch (ErrCode = RD->OpenDataFile(File.fileName().toAscii().data(), Tmpfile)) { 1007 case CTX_FOPEN: QMessageBox::warning(this, "Edd Message","Could not open file.",QMessageBox::Ok); 1008 return; 1009 case CTX_RHEADER: QMessageBox::warning(this, "Edd Message","Could not read run header.",QMessageBox::Ok); 1010 return; 1011 case CTX_BSTRUCT: QMessageBox::warning(this, "Edd Message","Could not read board structures.",QMessageBox::Ok); 1012 return; 1013 default: break; 1014 } 1015 1016 // Emit signal containing run header 1017 rewind(Tmpfile); 1018 QTextStream Stream(Tmpfile); 1019 emit(RunHeaderChanged(Stream.readAll())); 1020 1021 // Prepare temporary file for event header 1022 ftruncate(fileno(Tmpfile), 0); 1023 rewind(Tmpfile); 1024 1025 if (RD->ReadEvent(0, Tmpfile) != CTX_OK) { 1026 QMessageBox::warning(this, "Edd Warning","Could not read event.",QMessageBox::Ok); 1027 return; 1028 } 1029 1030 // Emit signal containing run header 1031 rewind(Tmpfile); 1032 emit(EventHeaderChanged(Stream.readAll())); 1033 1034 PlotTraces(); 1035 } 1036 1037 // Update curves 1038 void EventScope::PlotTraces() { 1039 1040 double x,y; 1041 unsigned int Cell, Trig; 1042 1043 // Only process if valid data in RawDataCTX class 1044 if (ErrCode != CTX_OK) return; 1045 1046 // Set x axis title 1047 if (PhysPipeAction->isChecked()) setAxisTitle(QwtPlot::xBottom, "Time from start of pipeline (ns)"); 1048 else setAxisTitle(QwtPlot::xBottom, "Time from trigger minus one revolution (ns)"); 1049 1050 // Loop through event data 1051 RunHeader *R = RD->RHeader; 1052 for (int i=0; i<List.size(); i++) { 1053 1054 ClearCurve(i); 1055 1056 // Check if current event contains requested trace 1057 if (List[i].Board>=R->NBoards || List[i].Chip>=R->NChips || List[i].Channel>=R->NChannels) continue; 1058 1059 // Set trigger marker visibility 1060 List[i].Trigger->setVisible(PhysPipeAction->isChecked()); 1061 1062 // Determine trigger cell 1063 Trig = *((int *) RD->Data + List[i].Board*R->NChips + List[i].Chip); 1064 1065 for (unsigned int j=0; j<R->Samples; j++) { 1066 1067 if (PhysPipeAction->isChecked()) Cell = (j + Trig) % 1024; 1068 else Cell = j; 1069 1070 x = j / RD->BStruct[List[i].Board].NomFreq; 1071 y = *((short *) (RD->Data + R->NBoards*R->NChips*sizeof(int)) + 1072 List[i].Board*R->NChips*R->NChannels*R->Samples + List[i].Chip*R->NChannels*R->Samples + 1073 List[i].Channel*R->Samples + Cell) * RD->BStruct[List[i].Board].ScaleFactor; 1074 1075 AddPoint(i, x, y); 1076 1077 // Set trigger point indicator 1078 if (Trig == j/*+R->Offset*/) List[i].Trigger->setValue(x, y); 1079 } 1080 } 1081 1082 UpdatePlot(); 1083 } 1084 1085 // Remove list entry 1086 void EventScope::DeleteCurve(QwtPlotCurve *Curve) { 1087 1088 for (int i=0; i<List.size(); i++) if (List[i].Signal == Curve) { 1089 delete List[i].Trigger; 1090 List.removeAt(i); 1091 } 1092 } 1093 1094 // 1095 // Tab page classes 1096 // 1097 1098 // Environment page 1099 TP_Environment::TP_Environment() { 1100 1101 QGridLayout *Layout = new QGridLayout(this); 1102 1103 // Status display 1104 EddLineDisplay *Line = new EddLineDisplay("ARDUINO/Status"); 1105 Line->setMaximumWidth(200); 1106 Layout->addWidget(Line, 0, 0, 1, 3); 1107 1108 // Generate plot and data displays 1109 EddPlot *Plot = new EddPlot(); 1110 for (int i=0; i<10; i++) { 1111 Line = new EddLineDisplay("ARDUINO/Data", i); 1112 Layout->addWidget(Line, i%5+1, i/5, 1, 1); 1113 Plot->AddService("ARDUINO/Data", i); 1114 } 1115 Layout->addWidget(Plot, 0, 3, 6, 4); 1116 1117 // Night sky monitor 1118 Line = new EddLineDisplay("SQM/NSB"); 1119 Layout->addWidget(Line, 6, 0, 1, 1); 1120 } 1121 1122 // Bias page 1123 TP_Bias::TP_Bias() { 1124 1125 QGridLayout *Layout = new QGridLayout(this); 1126 EddLineDisplay *Line; 1127 1128 EddPlot *Plot = new EddPlot(); 1129 Plot->setMinimumWidth(400); 1130 for (int i=0; i<18; i++) { 1131 Line = new EddLineDisplay("Bias/VOLT/ID00", i); 1132 Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1); 1133 Plot->AddService("Bias/VOLT/ID00", i); 1134 1135 Line = new EddLineDisplay("Bias/VOLT/ID00", i+32); 1136 Layout->addWidget(Line, i%9+1, 2+i/9, 1, 1); 1137 Plot->AddService("Bias/VOLT/ID00",i+32); 1138 } 1139 1140 Layout->addWidget(Plot, 0, 4, 12, 3); 1141 Line = new EddLineDisplay("Bias/Status"); 1142 Line->setMaximumWidth(200); 1143 Layout->addWidget(Line, 0, 0, 1, 3); 1144 1145 EddText *Text = new EddText("Bias/Textout", true); 1146 Text->setFixedWidth(400); 1147 Layout->addWidget(Text, 10, 0, 4, 4); 1148 } 1149 1150 // Feedback page 1151 TP_Feedback::TP_Feedback() { 1152 1153 QGridLayout *Layout = new QGridLayout(this); 1154 EddLineDisplay *Line; 1155 1156 EddPlot *Plot = new EddPlot(); 1157 for (int i=0; i<36; i++) { 1158 Line = new EddLineDisplay("Feedback/Average", i); 1159 Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1); 1160 Plot->AddService("Feedback/Average", i); 1161 } 1162 Layout->addWidget(Plot, 0, 4, 11, 3); 1163 1164 //Graph = new EddPlot(); 1165 //for (int i=0; i<36; i++) { 1166 //Text = Text.sprintf("Feedback/Sigma/ID%.2d/%.2d-%.3d",i/16, (i%16)/8, i%8); 1167 //Graph->AddService(Text); 1168 //} 1169 //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3); 1170 1171 Line = new EddLineDisplay("Feedback/Status"); 1172 Line->setMaximumWidth(200); 1173 Layout->addWidget(Line, 0, 0, 1, 3); 1174 Line = new EddLineDisplay("Feedback/Count"); 1175 Layout->addWidget(Line, 0, 3, 1, 1); 1176 1177 QWidget *Button = new QPushButton("Details"); 1178 Layout->addWidget(Button, 10, 0, 1, 1); 1179 connect(Button, SIGNAL(pressed()), SLOT(FeedbackDetails())); 1180 1181 } 1182 1183 void TP_Feedback::FeedbackDetails() { 1184 1185 EddLineDisplay *Line; 1186 QWidget *Widget = new QWidget(); 1187 QGridLayout *Layout = new QGridLayout(Widget); 1188 EddPlot *Plot = new EddPlot(); 1189 for (int i=0; i<36; i++) { 1190 Line = new EddLineDisplay("Feedback/Sigma", i); 1191 Layout->addWidget(Line, i%9+1, 0+i/9, 1, 1); 1192 Plot->AddService("Feedback/Sigma", i); 1193 } 1194 Layout->addWidget(Plot, 0, 4, 11, 3); 1195 1196 Widget->show(); 1197 } 1198 1199 // DAQ page 1200 TP_DAQ::TP_DAQ() { 1201 1202 QGridLayout *Layout = new QGridLayout(this); 1203 1204 // Event scope 1205 Scope = new EventScope; 1206 Scope->setMinimumWidth(700); 1207 1208 // Text boxes for run and event header 1209 RunHeaderDisplay = new QPlainTextEdit(); 1210 EventHeaderDisplay = new QPlainTextEdit(); 1211 RunHeaderDisplay->setReadOnly(true); 1212 EventHeaderDisplay->setReadOnly(true); 1213 1214 // Tab widget 1215 QTabWidget *TabWidget = new QTabWidget(); 1216 TabWidget->addTab(Scope, "&Signals"); 1217 TabWidget->addTab(RunHeaderDisplay, "&Run Header"); 1218 TabWidget->addTab(EventHeaderDisplay, "&Event Header"); 1219 Layout->addWidget(TabWidget, 0, 1, 3, 3); 1220 1221 connect(Scope, SIGNAL(RunHeaderChanged(QString)), RunHeaderDisplay, SLOT(setPlainText(QString))); 1222 connect(Scope, SIGNAL(EventHeaderChanged(QString)), EventHeaderDisplay, SLOT(setPlainText(QString))); 1223 1224 // Channel number 1225 Channel = new QSpinBox; 1226 connect(Channel, SIGNAL(valueChanged(int)), SLOT(UpdateScope(int))); 1227 Channel->setToolTip("DRS channel number"); 1228 1229 // Chip number 1230 Chip = new QSpinBox; 1231 connect(Chip, SIGNAL(valueChanged(int)), SLOT(UpdateScope(int))); 1232 Chip->setToolTip("DRS chip number"); 1233 1234 // Board number 1235 Board = new QSpinBox; 1236 connect(Board, SIGNAL(valueChanged(int)), SLOT(UpdateScope(int))); 1237 Board->setToolTip("DRS board number"); 1238 1239 // Pixel ID 1240 PixelID = new QLineEdit; 1241 PixelID->setMaximumWidth(60); 1242 connect(PixelID, SIGNAL(returnPressed()), SLOT(TranslatePixelID())); 1243 PixelID->setToolTip("Pixel identification"); 1244 1245 // Layout of pixel addressing widgets 1246 QFormLayout *FormLayout = new QFormLayout(); 1247 FormLayout->setRowWrapPolicy(QFormLayout::WrapAllRows); 1248 FormLayout->addRow("Channel", Channel); 1249 FormLayout->addRow("Chip", Chip); 1250 FormLayout->addRow("Board", Board); 1251 FormLayout->addRow("Pixel ID", PixelID); 1252 Layout->addLayout(FormLayout, 0, 0); 1253 1254 // Add trace permanently 1255 QPushButton *Button = new QPushButton("Keep trace"); 1256 Button->setToolTip("Keep trace in display"); 1257 Button->setMaximumWidth(80); 1258 Layout->addWidget(Button, 2, 0); 1259 connect(Button, SIGNAL(clicked()), SLOT(KeepCurrent())); 1260 } 1261 1262 void TP_DAQ::TranslatePixelID() { 1263 1264 if (Scope->Pixel_to_DRSboard(PixelID->text().toStdString()) == 999999999) { 1265 QMessageBox::warning(this, "Edd Message","Pixel ID unknown.",QMessageBox::Ok); 1266 } 1267 else { 1268 Board->setValue(Scope->Pixel_to_DRSboard(PixelID->text().toStdString())); 1269 Chip->setValue(Scope->Pixel_to_DRSchip(PixelID->text().toStdString())); 1270 Channel->setValue(Scope->Pixel_to_DRSchannel(PixelID->text().toStdString())); 1271 } 1272 } 1273 1274 // Update event scope 1275 void TP_DAQ::KeepCurrent() { 1276 1277 Scope->AddTrace(Board->value(), Chip->value(), Channel->value()); 1278 } 1279 1280 // Update event scope 1281 void TP_DAQ::UpdateScope(int) { 1282 1283 // Update pixel ID 1284 PixelID->setText(Scope->DRS_to_Pixel(Board->value(), Chip->value(), Channel->value()).c_str()); 1285 // Update first trace 1286 Scope->UpdateFirst(Board->value(), Chip->value(), Channel->value()); 1287 } 1288 1289 // DAQ page 1290 TP_Evidence::TP_Evidence() { 1291 1292 QGridLayout *Layout = new QGridLayout(this); 1293 EddLineDisplay *Line; 1294 EddText *Text; 1295 1296 Line = new EddLineDisplay("Alarm/Status"); 1297 Line->setMaximumWidth(200); 1298 Layout->addWidget(Line, 0, 0, 1, 2); 1299 1300 Line = new EddLineDisplay("Alarm/MasterAlarm"); 1301 Layout->addWidget(Line, 0, 1, 1, 1); 1302 1303 Text = new EddText("Alarm/Summary", true); 1304 Text->Accumulate = false; 1305 Text->setMaximumWidth(200); 1306 Text->setMaximumHeight(150); 1307 Layout->addWidget(Text, 1, 0, 1, 2); 1308 1309 Line = new EddLineDisplay("DColl/Status"); 1310 Line->setMaximumWidth(200); 1311 Layout->addWidget(Line, 3, 0, 1, 2); 1312 1313 Line = new EddLineDisplay("DColl/DataSizekB"); 1314 Layout->addWidget(Line, 4, 0, 1, 1); 1315 1316 Line = new EddLineDisplay("DColl/LogSizekB"); 1317 Layout->addWidget(Line, 4, 1, 1, 1); 1318 1319 Line = new EddLineDisplay("DColl/CurrentFile"); 1320 Line->setMaximumWidth(400); 1321 Layout->addWidget(Line, 5, 0, 1, 3); 1322 1323 Line = new EddLineDisplay("Config/Status"); 1324 Line->setMaximumWidth(200); 1325 Layout->addWidget(Line, 6, 0, 1, 2); 1326 1327 Line = new EddLineDisplay("Config/ModifyTime"); 1328 Line->setMaximumWidth(200); 1329 Line->ShowAsTime = true; 1330 Layout->addWidget(Line, 7, 0, 1, 1); 1331 1332 QPushButton *Button = new QPushButton(); 1333 Button->setText("Start DIM browser"); 1334 connect(Button, SIGNAL(released()), SLOT(StartDIMBrowser())); 1335 Layout->addWidget(Button, 7, 1, 1, 1); 1336 1337 Line = new EddLineDisplay("Edd/Rate_kBMin"); 1338 Layout->addWidget(Line, 8, 0, 1, 1); 1339 Line = new EddLineDisplay("Edd/Total_MB"); 1340 Layout->addWidget(Line, 8, 1, 1, 1); 1341 } 1342 1343 // Start DIM Browser 1344 void TP_Evidence::StartDIMBrowser() { 1345 1346 QProcess::startDetached("did", QStringList(), QString(getenv("DIMDIR"))+"/linux/"); 1347 } 1348 1349 886 1350 //-------------------------------------------------------------------- 887 1351 //*************************** Main GUI ******************************* … … 891 1355 // 892 1356 GUI::GUI() { 893 1357 894 1358 Handler = new EddDim(); 895 1359 … … 901 1365 setWindowTitle("Edd - Evidence Data Display"); 902 1366 903 EddLineDisplay *Value; 904 EddPlot *Graph; 905 EddText *Textout; 906 QString Text; 907 908 // TextBox for value 909 910 911 // Clock (updated every second) 912 //Clock = new QwtAnalogClock(Central); 913 //Clock->scaleDraw()->setPenWidth(3); 914 //Clock->setLineWidth(6); 915 //Clock->setFrameShadow(QwtDial::Sunken); 916 //Clock->setGeometry(0,0,10,10); 917 //Clock->setTime(); 918 919 //QTimer *Timer = new QTimer(Clock); 920 //Timer->connect(Timer, SIGNAL(timeout()), Clock, SLOT(setCurrentTime())); 921 //Timer->start(1000); 922 923 MainWidget = new QWidget(); 924 MainLayout = new QGridLayout(MainWidget); 925 926 Value = new EddLineDisplay("Alarm/Status"); 927 Value->setMaximumWidth(200); 928 MainLayout->addWidget(Value, 0, 0, 1, 2); 929 930 Value = new EddLineDisplay("Alarm/MasterAlarm"); 931 MainLayout->addWidget(Value, 0, 1, 1, 1); 932 933 Textout = new EddText("Alarm/Summary", true); 934 Textout->Accumulate = false; 935 Textout->setMaximumWidth(200); 936 Textout->setMaximumHeight(150); 937 MainLayout->addWidget(Textout, 1, 0, 1, 2); 938 939 Value = new EddLineDisplay("DColl/Status"); 940 Value->setMaximumWidth(200); 941 MainLayout->addWidget(Value, 3, 0, 1, 2); 942 943 Value = new EddLineDisplay("DColl/DataSizekB"); 944 MainLayout->addWidget(Value, 4, 0, 1, 1); 945 946 Value = new EddLineDisplay("DColl/LogSizekB"); 947 MainLayout->addWidget(Value, 4, 1, 1, 1); 948 949 Value = new EddLineDisplay("DColl/CurrentFile"); 950 Value->setMaximumWidth(400); 951 MainLayout->addWidget(Value, 5, 0, 1, 3); 952 953 Value = new EddLineDisplay("Config/Status"); 954 Value->setMaximumWidth(200); 955 MainLayout->addWidget(Value, 6, 0, 1, 2); 956 957 Value = new EddLineDisplay("Config/ModifyTime"); 958 Value->setMaximumWidth(200); 959 Value->ShowAsTime = true; 960 MainLayout->addWidget(Value, 7, 0, 1, 1); 961 962 QPushButton *Button = new QPushButton(); 963 Button->setText("Start DIM browser"); 964 connect(Button, SIGNAL(released()), SLOT(StartDIMBrowser())); 965 MainLayout->addWidget(Button, 7, 1, 1, 1); 966 967 Value = new EddLineDisplay("Edd/Rate_kBMin"); 968 MainLayout->addWidget(Value, 8, 0, 1, 1); 969 Value = new EddLineDisplay("Edd/Total_MB"); 970 MainLayout->addWidget(Value, 8, 1, 1, 1); 971 972 // Layout of all widgets 973 //MainLayout->addWidget(Value, 0, 0, 1, 1); 974 //MainLayout->addWidget(Clock, 0, 1, 1, 1); 975 //MainLayout->addWidget(Graph, 1, 0, 1, 2); 976 //MainLayout->setColumnStretch(1, 10); 977 978 //MainLayout->addWidget(Clock, 0, 1, 1, 1); 979 //MainLayout->addWidget(Graph1, 2, 0, 1, 2); 980 981 // Feedback page 982 FeedbackWidget = new QWidget(); 983 FeedbackLayout = new QGridLayout(FeedbackWidget); 984 Graph = new EddPlot(); 985 for (int i=0; i<36; i++) { 986 Value = new EddLineDisplay("Feedback/Average", i); 987 FeedbackLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1); 988 Graph->AddService("Feedback/Average", i); 989 } 990 FeedbackLayout->addWidget(Graph, 0, 4, 11, 3); 991 992 //Graph = new EddPlot(); 993 //for (int i=0; i<36; i++) { 994 //Text = Text.sprintf("Feedback/Sigma/ID%.2d/%.2d-%.3d",i/16, (i%16)/8, i%8); 995 //Graph->AddService(Text); 996 //} 997 //FeedbackLayout->addWidget(Graph, 10, 0, 10, 3); 998 999 Value = new EddLineDisplay("Feedback/Status"); 1000 Value->setMaximumWidth(200); 1001 FeedbackLayout->addWidget(Value, 0, 0, 1, 3); 1002 Value = new EddLineDisplay("Feedback/Count"); 1003 FeedbackLayout->addWidget(Value, 0, 3, 1, 1); 1004 1005 QWidget *Value1 = new QPushButton("Details"); 1006 FeedbackLayout->addWidget(Value1, 10, 0, 1, 1); 1007 connect(Value1, SIGNAL(pressed()), this, SLOT(FeedbackDetails())); 1008 1009 1010 // Bias voltage page 1011 BiasWidget = new QWidget(); 1012 BiasLayout = new QGridLayout(BiasWidget); 1013 Graph = new EddPlot(); 1014 for (int i=0; i<18; i++) { 1015 Value = new EddLineDisplay("Bias/VOLT/ID00", i); 1016 BiasLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1); 1017 Graph->AddService("Bias/VOLT/ID00", i); 1018 1019 Value = new EddLineDisplay("Bias/VOLT/ID00", i+32); 1020 BiasLayout->addWidget(Value, i%9+1, 2+i/9, 1, 1); 1021 Graph->AddService("Bias/VOLT/ID00",i+32); 1022 } 1023 1024 BiasLayout->addWidget(Graph, 0, 4, 12, 3); 1025 Value = new EddLineDisplay("Bias/Status"); 1026 Value->setMaximumWidth(200); 1027 BiasLayout->addWidget(Value, 0, 0, 1, 3); 1028 1029 Textout = new EddText("Bias/Textout", true); 1030 Textout->setFixedWidth(400); 1031 BiasLayout->addWidget(Textout, 10, 0, 4, 4); 1032 1033 // Environment page 1034 EnvironmentWidget = new QWidget(); 1035 EnvironmentLayout = new QGridLayout(EnvironmentWidget); 1036 Value = new EddLineDisplay("ARDUINO/Status"); 1037 Value->setMaximumWidth(200); 1038 EnvironmentLayout->addWidget(Value, 0, 0, 1, 3); 1039 1040 Graph = new EddPlot(); 1041 for (int i=0; i<10; i++) { 1042 Value = new EddLineDisplay("ARDUINO/Data", i); 1043 EnvironmentLayout->addWidget(Value, i%5+1, i/5, 1, 1); 1044 Graph->AddService("ARDUINO/Data", i); 1045 } 1046 EnvironmentLayout->addWidget(Graph, 0, 3, 6, 4); 1047 1048 Value = new EddLineDisplay("SQM/NSB"); 1049 EnvironmentLayout->addWidget(Value, 6, 0, 1, 1); 1050 1051 // Tab widget 1367 // Arrangement in tabs 1052 1368 TabWidget = new QTabWidget(Central); 1053 TabWidget->addTab(BiasWidget, "&Bias"); 1054 TabWidget->addTab(FeedbackWidget, "&Feedback"); 1055 TabWidget->addTab(EnvironmentWidget, "&Environment"); 1056 TabWidget->addTab(MainWidget, "Evidence"); 1369 TabWidget->addTab(new TP_DAQ, "&drsdaq"); 1370 TabWidget->addTab(new TP_Bias, "&Bias"); 1371 TabWidget->addTab(new TP_Feedback, "&Feedback"); 1372 TabWidget->addTab(new TP_Environment, "&Environment"); 1373 TabWidget->addTab(new TP_Evidence, "Evidence"); 1057 1374 1058 1375 // Menu bar … … 1112 1429 } 1113 1430 1114 // Feedback details page1115 void GUI::FeedbackDetails() {1116 1117 QWidget *Value;1118 QWidget *Widget = new QWidget();1119 QGridLayout *Layout = new QGridLayout(Widget);1120 EddPlot *Graph = new EddPlot();1121 for (int i=0; i<36; i++) {1122 Value = new EddLineDisplay("Feedback/Sigma", i);1123 Layout->addWidget(Value, i%9+1, 0+i/9, 1, 1);1124 Graph->AddService("Feedback/Sigma", i);1125 }1126 Layout->addWidget(Graph, 0, 4, 11, 3);1127 1128 Widget->show();1129 }1130 1131 // Start DIM Browser1132 void GUI::StartDIMBrowser() {1133 1134 QProcess::startDetached("did", QStringList(), QString(getenv("DIMDIR"))+"/linux/");1135 }1136 1137 1431 // Quit application when clicking close button on window 1138 1432 void GUI::closeEvent(QCloseEvent *) { -
Evidence/Edd/Edd.h
r204 r208 18 18 #include <qwt_symbol.h> 19 19 #include <qwt_plot_marker.h> 20 #include <qwt_data.h> 20 21 21 22 #include <limits.h> … … 24 25 #include "dic.hxx" 25 26 #include "Evidence.h" 27 #include "RawDataCTX.h" 28 #include "PixelMap.h" 26 29 27 30 #define SVN_REVISION "$Revision$" … … 30 33 31 34 QWidget *OpenHistory(char *, int); 32 33 // Time scale for axis 34 class EddTimeScale: public QwtScaleDraw { 35 36 public: 37 EddTimeScale() {} 38 39 virtual QwtText label(double v) const { 40 41 // Adapt text format to time span 42 QString Format; 43 if (scaleDiv().range() < 60*60) Format = "hh' h\n'mm:ss"; 44 else if (scaleDiv().range() < 24*60*60) Format = "hh:mm"; 45 else if (scaleDiv().range() < 30*24*60*60) Format = "h' h\n'd-MMM"; 46 else Format = "d-MMM'\n'yyyy"; 47 48 // Generate text 49 QwtText Text = QDateTime::fromTime_t((int) v).toString(Format); 50 QFont Font = Text.font(); 51 Font.setPointSize(7); 52 Text.setFont(Font); 53 54 return Text; 55 } 56 }; 57 58 59 // General indicator for DIM service 60 class EddLineDisplay: public QLineEdit { 61 Q_OBJECT 62 35 bool SetStatus(QWidget *, QString, int, QString, int = -1); 36 37 // Base class for Edd plot 38 // DeleteCurve() is pure virtual and needs to be implemented iin the application class 39 class EddBasePlot: public QwtPlot { 40 Q_OBJECT 41 42 protected: 63 43 QMenu *Menu; 64 QPoint dragStart; 65 QWidget *LastPlot; 66 67 QString ServiceName; 68 int Index; 69 70 void mousePressEvent(QMouseEvent *); 71 void mouseReleaseEvent(QMouseEvent *); 72 void mouseMoveEvent(QMouseEvent *); 73 74 public: 75 EddLineDisplay(QString, int=0, QWidget * = NULL); 76 ~EddLineDisplay(); 77 78 bool ShowAsTime; 79 80 private slots: 81 void Update(QString, int, QByteArray, QString, QString); 82 void contextMenuEvent(QContextMenuEvent *); 83 void MenuOpenHistory(); 84 void MenuCopyService(); 85 void MenuCopyData(); 86 }; 87 88 // Graph class for history display 89 class EddPlot: public QwtPlot { 90 Q_OBJECT 91 44 QAction *StripAction; 45 46 private: 92 47 struct PlotItem { 93 QString Name;94 48 QwtPlotCurve *Signal; 95 double Smallest;96 double Largest;97 int SizeLimit;98 49 QVector<double> x; 99 50 QVector<double> y; 100 int Index; 51 double Smallest; 52 double Largest; 101 53 }; 102 103 54 QList<struct PlotItem> Items; 104 QMutex *Mutex; 105 106 QMenu *Menu; 55 107 56 QAction *YLogAction; 108 57 QAction *NormAction; 109 58 QAction *StyleAction; 110 QAction *StripAction;111 59 112 60 QwtPlotPanner *Panner; … … 115 63 QwtPlotMagnifier *Magnifier; 116 64 QwtPicker *Picker; 65 QwtDoubleRect BBox; 66 67 public: 68 EddBasePlot(QWidget * = NULL); 69 ~EddBasePlot(); 70 71 QwtPlotCurve *NewCurve(QwtText); 72 void ClearCurve(unsigned int); 73 void AddPoint(unsigned int, double, double); 74 virtual void DeleteCurve(QwtPlotCurve *) = 0; 75 76 protected slots: 77 void UpdatePlot(); 78 79 private slots: 80 void HandleZoom(const QwtDoubleRect &); 81 void MouseSelection(const QwtPolygon &); 82 void contextMenuEvent(QContextMenuEvent *); 83 void MenuSingleTrace(); 84 void MenuZoomOut(); 85 void MenuSaveASCII(); 86 void MenuSave(); 87 void MenuPrint(); 88 void MenuPlotHelp(); 89 }; 90 91 // General indicator for DIM service 92 class EddLineDisplay: public QLineEdit { 93 Q_OBJECT 94 95 QMenu *Menu; 96 QPoint dragStart; 97 QWidget *LastPlot; 98 99 QString ServiceName; 100 int Index; 101 102 void mousePressEvent(QMouseEvent *); 103 void mouseReleaseEvent(QMouseEvent *); 104 void mouseMoveEvent(QMouseEvent *); 105 106 public: 107 EddLineDisplay(QString, int=0, QWidget * = NULL); 108 ~EddLineDisplay(); 109 110 bool ShowAsTime; 111 112 private slots: 113 void Update(QString, int, QByteArray, QString, QString); 114 void contextMenuEvent(QContextMenuEvent *); 115 void MenuOpenHistory(); 116 void MenuCopyService(); 117 void MenuCopyData(); 118 }; 119 120 // Graph class for history display 121 class EddPlot: public EddBasePlot { 122 Q_OBJECT 123 124 // Time scale for axis 125 class EddTimeScale: public QwtScaleDraw { 126 127 public: 128 EddTimeScale() {} 129 130 virtual QwtText label(double v) const { 131 // Adapt text format to time span 132 QString Format; 133 if (scaleDiv().range() < 60*60) Format = "hh' h\n'mm:ss"; 134 else if (scaleDiv().range() < 24*60*60) Format = "hh:mm"; 135 else if (scaleDiv().range() < 30*24*60*60) Format = "h' h\n'd-MMM"; 136 else Format = "d-MMM'\n'yyyy"; 137 138 // Generate text 139 QwtText Text = QDateTime::fromTime_t((int) v).toString(Format); 140 QFont Font = Text.font(); 141 Font.setPointSize(7); 142 Text.setFont(Font); 143 144 return Text; 145 } 146 }; 147 148 struct ItemDetails { 149 QString Name; 150 int Index; 151 QwtPlotCurve *Signal; 152 }; 153 QList<struct ItemDetails> List; 154 155 private: 117 156 QwtLegend *Legend; 118 QwtDoubleRect BBox;157 int SizeLimit; 119 158 120 159 void dragEnterEvent(QDragEnterEvent *); … … 126 165 ~EddPlot(); 127 166 void AddService(QString, int = 0); 128 129 private slots: 130 void Update(QString, int, QByteArray, QString, QString); 131 void UpdatePlot(); 132 133 void HandleZoom(const QwtDoubleRect &); 134 void MouseSelection(const QwtPolygon &); 135 void contextMenuEvent(QContextMenuEvent *); 167 void DeleteCurve(QwtPlotCurve *); 168 169 private slots: 170 void Update(QString, int, QByteArray, QString, QString); 136 171 void LegendClicked(QwtPlotItem *); 137 void MenuZoomOut();138 void MenuSingleTrace();139 void MenuSaveASCII();140 void MenuSave();141 void MenuPrint();142 172 void MenuPasteService(); 143 void MenuPlotHelp();144 }; 173 }; 174 145 175 146 176 // Text history and output class 147 177 class EddText: public QTextEdit { 148 Q_OBJECT 149 178 Q_OBJECT 179 180 private: 150 181 QString Name; 151 182 bool Pure; … … 161 192 }; 162 193 194 163 195 // Interface to DIM system 164 196 class EddDim: public QObject, public DimInfo { 165 Q_OBJECT 166 197 Q_OBJECT 198 199 private: 167 200 struct Item { 168 201 QString Name; … … 205 238 }; 206 239 240 // 241 // 242 // ====== FACT specific part ====== 243 // 244 // 245 246 // Event oscilloscope 247 class EventScope: public EddBasePlot, public PixelMap { 248 Q_OBJECT 249 250 private: 251 struct ItemDetails { 252 unsigned int Board, Chip, Channel; 253 QwtPlotCurve *Signal; 254 QwtPlotMarker *Trigger; 255 }; 256 QList<struct ItemDetails> List; 257 258 QString Name; 259 RawDataCTX *RD; 260 CTX_ErrCode ErrCode; 261 QAction *PhysPipeAction; 262 FILE *Tmpfile; 263 264 public: 265 EventScope(QWidget * = NULL); 266 ~EventScope(); 267 268 void UpdateFirst(int, int, int); 269 void AddTrace(int, int, int); 270 271 private slots: 272 void Update(QString, int, QByteArray, QString, QString); 273 void PlotTraces(); 274 void DeleteCurve(QwtPlotCurve *); 275 276 signals: 277 void RunHeaderChanged(QString); 278 void EventHeaderChanged(QString); 279 }; 280 281 282 // Tab page classes 283 class TP_Environment: public QWidget { 284 Q_OBJECT 285 286 public: 287 TP_Environment(); 288 }; 289 290 class TP_Bias: public QWidget { 291 Q_OBJECT 292 293 public: 294 TP_Bias(); 295 }; 296 297 class TP_Feedback: public QWidget { 298 Q_OBJECT 299 300 private slots: 301 void FeedbackDetails(); 302 303 public: 304 TP_Feedback(); 305 }; 306 307 class TP_DAQ: public QWidget { 308 Q_OBJECT 309 310 private: 311 EventScope *Scope; 312 QPlainTextEdit *RunHeaderDisplay, *EventHeaderDisplay; 313 314 QSpinBox *Channel, *Chip, *Board; 315 QLineEdit *PixelID; 316 QFormLayout *FormLayout; 317 318 private slots: 319 void TranslatePixelID(); 320 void UpdateScope(int); 321 void KeepCurrent(); 322 323 public: 324 TP_DAQ(); 325 }; 326 327 class TP_Evidence: public QWidget { 328 Q_OBJECT 329 330 private slots: 331 void StartDIMBrowser(); 332 333 public: 334 TP_Evidence(); 335 }; 336 207 337 208 338 // Main window class 209 339 class GUI: public QMainWindow, public DimBrowser { 210 Q_OBJECT 211 212 QwtAnalogClock *Clock; 213 214 QWidget *Central, *MainWidget, *BiasWidget, *FeedbackWidget, *FeedbackDetailsWidget, *EnvironmentWidget; 215 QGridLayout *MainLayout, *BiasLayout, *FeedbackLayout, *FeedbackDetailsLayout, *EnvironmentLayout; 216 340 Q_OBJECT 341 342 private: 343 QWidget *Central; 217 344 QTabWidget *TabWidget; 218 345 … … 226 353 void MenuAbout(); 227 354 void MenuNewHistory(); 228 void StartDIMBrowser();229 void FeedbackDetails();230 355 }; 231 356 -
Evidence/Edd/Edd.pro
r144 r208 6 6 TARGET = 7 7 DEPENDPATH += . 8 INCLUDEPATH += . .. / usr/local/qwt-5.2.0/include $(DIMDIR)/dim8 INCLUDEPATH += . .. /ihp/local/qwt-5.2.1/include $(DIMDIR)/dim ../../drsdaq ../../pixelmap 9 9 10 10 # Input 11 11 HEADERS += Edd.h 12 SOURCES += Edd.cc ../Evidence.cc 13 LIBS += -L/ usr/local/qwt-5.2.0/lib -lqwt $(DIMDIR)/linux/libdim.a12 SOURCES += Edd.cc ../Evidence.cc ../../drsdaq/RawDataCTX.cc ../../pixelmap/Pixel.cc ../../pixelmap/PixelMap.cc 13 LIBS += -L/ihp/local/qwt-5.2.1/lib -lqwt $(DIMDIR)/linux/libdim.a
Note:
See TracChangeset
for help on using the changeset viewer.