Isis 3 Programmer Reference
PlotWindow.cpp
1#include "PlotWindow.h"
2
3#include <algorithm>
4#include <iostream>
5
6#include <qwt_legend.h>
7#include <qwt_plot_grid.h>
8#include <qwt_plot_spectrogram.h>
9#include <qwt_symbol.h>
10#include <qwt_scale_engine.h>
11#include <qwt_text.h>
12
13#include <QAction>
14#include <QApplication>
15#include <QCheckBox>
16#include <QFileDialog>
17#include <QGridLayout>
18#include <QIcon>
19#include <QLabel>
20#include <QLineEdit>
21#include <QMap>
22#include <QMenuBar>
23#include <QMessageBox>
24#include <QPrinter>
25#include <QPrintDialog>
26#include <QProgressDialog>
27#include <QPushButton>
28#include <QSet>
29#include <QTableWidget>
30#include <QToolBar>
31
32#include "Cube.h"
33#include "CubePlotCurve.h"
34#include "CubePlotCurveConfigureDialog.h" //
35#include "CubeViewport.h"
36#include "FileName.h"
37#include "Interpolator.h"
38#include "MainWindow.h"
39#include "MdiCubeViewport.h"
40#include "PlotWindowBestFitDialog.h"
41#include "Pvl.h"
42#include "PvlGroup.h"
43#include "PvlKeyword.h"
44#include "QHistogram.h"
45#include "Stretch.h"
46#include "TableMainWindow.h"
47
48
49using namespace std;
50
51namespace Isis {
65 PlotWindow::PlotWindow(QString title, PlotCurve::Units xAxisUnits,
66 PlotCurve::Units yAxisUnits, QWidget *parent,
67 MenuOptions optionsToProvide) :
68 MainWindow(title, parent) {
69
70 m_toolBar = NULL;
71 m_menubar = NULL;
72 m_tableWindow = NULL;
73 m_pasteAct = NULL;
75 m_autoscaleAxes = true;
76
77 setObjectName("Plot Window: " + title);
78
79 m_parent = parent;
82
83 if (!m_parent) {
84 IString msg = "PlotWindow cannot be instantiated with a NULL parent";
85 throw IException(IException::Programmer, msg, _FILEINFO_);
86 }
87
88 installEventFilter(this);
89 setAcceptDrops(true);
90
91 createWidgets(optionsToProvide);
92 setWindowTitle(title);
93
94 setPlotBackground(Qt::black);
95
96 connect(QGuiApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)),
97 this, SLOT(onClipboardChanged()));
98 connect(this, SIGNAL(plotChanged()),
99 this, SLOT(scheduleFillTable()));
100 connect(this, SIGNAL(requestFillTable()),
101 this, SLOT(fillTable()), Qt::QueuedConnection);
102
103 QMap<PlotCurve::Units, QString> unitLabels;
104 unitLabels.insert(PlotCurve::Band, "Band");
105 unitLabels.insert(PlotCurve::Percentage, "Percentage");
106 unitLabels.insert(PlotCurve::PixelNumber, "Pixel Number");
107 unitLabels.insert(PlotCurve::CubeDN, "Pixel Value");
108 unitLabels.insert(PlotCurve::Elevation, "Elevation");
109 unitLabels.insert(PlotCurve::Meters, "Meters");
110 unitLabels.insert(PlotCurve::Kilometers, "Kilometers");
111 unitLabels.insert(PlotCurve::Wavelength, "Wavelength");
112
113 plot()->setAxisTitle(QwtPlot::xBottom, unitLabels[xAxisUnits]);
114 plot()->setAxisTitle(QwtPlot::yLeft, unitLabels[yAxisUnits]);
115 setPlotTitle(title);
116
118
119 readSettings();
120
121#ifdef __APPLE__
122 setWindowFlags(Qt::Tool);
123#else
124 setWindowFlags(Qt::Dialog);
125#endif
126 }
127
128
129
130 PlotWindow::~PlotWindow() {
131 foreach (QwtPlotCurve *curve, plotCurves()) {
132 delete curve;
133 }
134 }
135
136
144 void PlotWindow::createWidgets(MenuOptions optionsToProvide) {
145 /*Create plot*/
146 m_plot = new QwtPlot();
147 m_plot->installEventFilter(this);
148 m_plot->setAxisMaxMinor(QwtPlot::yLeft, 5);
149 m_plot->setAxisMaxMajor(QwtPlot::xBottom, 30);
150 m_plot->setAxisMaxMinor(QwtPlot::xBottom, 5);
151 m_plot->setAxisLabelRotation(QwtPlot::xBottom, 45);
152 m_plot->setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignRight);
153
154 /*Plot Legend*/
155 m_legend = new QwtLegend();
156 m_legend->setDefaultItemMode(QwtLegendData::Clickable);
157 m_legend->setWhatsThis("Right Click on a legend item to display the context "
158 "menu.");
159 m_plot->insertLegend(m_legend, QwtPlot::RightLegend, 1.0);
160 m_legend->installEventFilter(this);
161
162 /*Plot Grid*/
163 m_grid = new QwtPlotGrid;
164 m_grid->enableXMin(true);
165 m_grid->setMajorPen(QPen(Qt::white, 1, Qt::DotLine));
166 m_grid->setMinorPen(QPen(Qt::gray, 1, Qt::DotLine));
167 m_grid->attach(m_plot);
168 m_grid->setVisible(false);
169
170 /*Plot Zoomer*/
171 m_zoomer = new QwtPlotZoomer(m_plot->canvas());
172 m_zoomer->setRubberBandPen(QPen(Qt::lightGray));
173 m_zoomer->setTrackerPen(QPen(Qt::lightGray));
174
175 setCentralWidget(m_plot);
176 setupDefaultMenu(optionsToProvide);
177 }
178
179
185 raise();
186 show();
187 }
188
196 void PlotWindow::update(MdiCubeViewport *activeViewport) {
197 }
198
199
207 void PlotWindow::setAxisLabel(int axisId, QString title) {
208 m_plot->setAxisTitle(axisId, title);
209 }
210
211
218 void PlotWindow::setPlotTitle(QString pt) {
219 m_plot->setTitle(pt);
220 }
221
222
230 void PlotWindow::setUserCanAddCurves(bool userHasControl) {
231 m_allowUserToAddCurves = userHasControl;
232 }
233
240 QString PlotWindow::plotTitle() const {
241 return m_plot->title().text();
242 }
243
244
255 }
256
257
268
269
280
281
289 m_plot->setCanvasBackground(c);
290 }
291
292
304 bool PlotWindow::canAdd(CubePlotCurve *curveToTest) const {
305 return (curveToTest->xUnits() == m_xAxisUnits &&
306 curveToTest->yUnits() == m_yAxisUnits);
307 }
308
309
317 return m_plot->canvasBackground().color();
318 }
319
320
327 QList<CubePlotCurve *> PlotWindow::plotCurves() {
328 QList<CubePlotCurve *> foundCurves;
329
330 const QwtPlotItemList &plotItems = m_plot->itemList();
331
332 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
333 QwtPlotItem *item = plotItems[itemIndex];
334
335 if (item->rtti() == QwtPlotItem::Rtti_PlotCurve) {
336 CubePlotCurve *curve = dynamic_cast<CubePlotCurve *>(item);
337
338 if (curve && curve->color().alpha() != 0)
339 foundCurves.append(curve);
340 }
341 }
342
343 return foundCurves;
344 }
345
346
353 QList<const CubePlotCurve *> PlotWindow::plotCurves() const {
354 QList<const CubePlotCurve *> foundCurves;
355
356 const QwtPlotItemList &plotItems = m_plot->itemList();
357
358 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
359 const QwtPlotItem *item = plotItems[itemIndex];
360
361 if (item->rtti() == QwtPlotItem::Rtti_PlotCurve) {
362 const CubePlotCurve *curve = dynamic_cast<const CubePlotCurve *>(item);
363
364 if (curve)
365 foundCurves.append(curve);
366 }
367 }
368
369 return foundCurves;
370 }
371
372
380 QList<QwtPlotSpectrogram *> PlotWindow::plotSpectrograms() {
381 QList<QwtPlotSpectrogram *> foundSpectrograms;
382
383 const QwtPlotItemList &plotItems = m_plot->itemList();
384
385 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
386 QwtPlotItem *item = plotItems[itemIndex];
387
388 if (item->rtti() == QwtPlotItem::Rtti_PlotSpectrogram) {
389 QwtPlotSpectrogram *spectrogram =
390 dynamic_cast<QwtPlotSpectrogram *>(item);
391
392 if (spectrogram)
393 foundSpectrograms.append(spectrogram);
394 }
395 }
396
397 return foundSpectrograms;
398 }
399
400
408 QList<const QwtPlotSpectrogram *> PlotWindow::plotSpectrograms() const {
409 QList<const QwtPlotSpectrogram *> foundSpectrograms;
410
411 const QwtPlotItemList &plotItems = m_plot->itemList();
412
413 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
414 const QwtPlotItem *item = plotItems[itemIndex];
415
416 if (item->rtti() == QwtPlotItem::Rtti_PlotSpectrogram) {
417 const QwtPlotSpectrogram *spectrogram =
418 dynamic_cast<const QwtPlotSpectrogram *>(item);
419
420 if (spectrogram)
421 foundSpectrograms.append(spectrogram);
422 }
423 }
424
425 return foundSpectrograms;
426 }
427
428
436 if (!canAdd(pc)) {
437 QMessageBox::warning(NULL, "Failed to add plot curve",
438 "Can not add plot curves with x/y units that do not match the plot's "
439 "x/y units");
440 }
441 else {
442 QString curveTitle = pc->title().text();
443
444 bool titleAccepted = false;
445 int titleTryCount = 0;
446 while (!titleAccepted) {
447 if (titleTryCount > 0) {
448 curveTitle = pc->title().text() + " (" +
449 QString::number(titleTryCount + 1) + ")";
450 }
451
452 titleTryCount++;
453 titleAccepted = true;
454
455 const QwtPlotItemList &plotItems = m_plot->itemList();
456
457 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex ++) {
458 QwtPlotItem *item = plotItems[itemIndex];
459
460 if (item->title().text() == curveTitle)
461 titleAccepted = false;
462 }
463 }
464
465 pc->setTitle(curveTitle);
466 pc->attach(m_plot);
467 pc->attachMarkers();
468 fillTable();
469
471
472 connect(pc, SIGNAL(needsRepaint()),
473 this, SIGNAL(plotChanged()));
474 connect(pc, SIGNAL(destroyed(QObject *)),
475 this, SLOT(resetScale()));
476
477 // Get the legend widget for the recently attached plotcurve and give to the plotcurve
478 QWidget *legendWidget = m_legend->legendWidget( plot()->itemToInfo(pc) );
479 pc->updateLegendItemWidget(legendWidget);
480
481 replot();
482 }
483 }
484
485
493
494 /*Table Stuff if table is open*/
495 if (m_tableWindow != NULL && m_tableWindow->isVisible()) {
496 m_tableWindow->table()->setColumnCount(1);
497 m_tableWindow->table()->setRowCount(0);
498// deleteFromTable();
499 }
500 }
501
502
508 // make sure that there are CubePlotCurves to configure
509 QList<CubePlotCurve *> curves = plotCurves();
510 // can't configure 0 curves - menu item is deactivated
511 if (curves.size() < 1) {
512 return;
513 }
514 CubePlotCurve *curve = curves.first();
515 CubePlotCurveConfigureDialog *configDialog = new CubePlotCurveConfigureDialog(curve, this);
516 configDialog->exec();
517
518 emit plotChanged();
519 }
520
521
530 dialog->show();
531 }
532
533
540 const QwtPlotItemList &plotItems = m_plot->itemList();
541
542 for (int itemIndex = plotItems.size()- 1; itemIndex >= 0; itemIndex --) {
543 QwtPlotItem *item = plotItems[itemIndex];
544
545 if (item->rtti() == QwtPlotItem::Rtti_PlotCurve ||
546 item->rtti() == QwtPlotItem::Rtti_PlotHistogram) {
547 delete item;
548 }
549 }
550
551 replot();
552 }
553
554
560 if (m_zoomer->trackerMode() == QwtPicker::ActiveOnly) {
561 m_zoomer->setTrackerMode(QwtPicker::AlwaysOn);
562 }
563 else {
564 m_zoomer->setTrackerMode(QwtPicker::ActiveOnly);
565 }
566 }
567
568
573 QPixmap pixmap;
574 /* Initialize a printer*/
575 static QPrinter *printer = NULL;
576 if (printer == NULL) printer = new QPrinter;
577 printer->setPageSize(QPrinter::Letter);
578 printer->setColorMode(QPrinter::Color);
579
580 QPrintDialog printDialog(printer, (QWidget *)parent());
581
582 if (printDialog.exec() == QDialog::Accepted) {
583 /* Get display widget as a pixmap and convert to an image*/
584 pixmap = m_plot->grab();
585 QImage img = pixmap.toImage();
586 /* C++ Gui Programming with Qt, page 201*/
587 QPainter painter(printer);
588 QRect rect = painter.viewport();
589 QSize size = img.size();
590 size.scale(rect.size(), Qt::KeepAspectRatio);
591 painter.setViewport(rect.x(), rect.y(),
592 size.width(), size.height());
593 painter.setWindow(img.rect());
594 painter.drawImage(0, 0, img);
595 }
596
597 }
598
599
605 QPixmap pixmap;
606 QString output =
607 QFileDialog::getSaveFileName((QWidget *)parent(),
608 "Choose output file",
609 "./",
610 QString("Images (*.png *.jpg *.tif)"));
611 if (output.isEmpty()) return;
612 //Make sure the filename is valid
613 if (!output.isEmpty()) {
614 if (!output.endsWith(".png") && !output.endsWith(".jpg") && !output.endsWith(".tif")) {
615 output = output + ".png";
616 }
617 }
618
619 QString format = QFileInfo(output).suffix();
620 pixmap = m_plot->grab();
621
622 std::string formatString = format.toStdString();
623 if (!pixmap.save(output, formatString.c_str())) {
624 QMessageBox::information((QWidget *)parent(), "Error", "Unable to save " + output);
625 return;
626 }
627 }
628
629
635 QPen *pen = new QPen(Qt::white);
636
637 if (m_plot->canvasBackground() == Qt::white) {
638 m_plot->setCanvasBackground(Qt::black);
639 m_grid->setMajorPen(QPen(Qt::white, 1, Qt::DotLine));
640 }
641 else {
642 m_plot->setCanvasBackground(Qt::white);
643 pen->setColor(Qt::black);
644 m_grid->setMajorPen(QPen(Qt::black, 1, Qt::DotLine));
645 }
646
647 m_zoomer->setRubberBandPen(*pen);
648 m_zoomer->setTrackerPen(*pen);
649 pen->setWidth(2);
650 /*Replot with the new background and pen colors*/
651 m_plot->replot();
652 }
653
654
660 m_zoomer->zoom(0);
661
662 if (m_autoscaleAxes) {
664 m_plot->setAxisAutoScale(QwtPlot::xBottom);
665 }
666 else {
667 QPair<double, double> calculatedXRange = findDataRange(
668 QwtPlot::xBottom);
669 m_plot->setAxisScale(QwtPlot::xBottom, calculatedXRange.first,
670 calculatedXRange.second);
671 }
672
674 m_plot->setAxisAutoScale(QwtPlot::yLeft);
675 }
676 else {
677 QPair<double, double> calculatedYRange = findDataRange(
678 QwtPlot::yLeft);
679 m_plot->setAxisScale(QwtPlot::yLeft, calculatedYRange.first,
680 calculatedYRange.second);
681 }
682 }
683
684 m_zoomer->setZoomBase();
685 m_plot->replot();
686 }
687
688
694 if (m_xLogCheckBox->isChecked()) {
695 m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine);
696 m_plotXLogScale = true;
697 }
698 else {
699 m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
700 m_plotXLogScale = false;
701 }
702
703 if (m_yLogCheckBox->isChecked()) {
704 m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine);
705 m_plotYLogScale = true;
706 }
707 else {
708 m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
709 m_plotYLogScale = false;
710 }
711
713
714 if (!m_autoscaleAxes) {
715 double xMin = m_xMinEdit->text().toDouble();
716 double xMax = m_xMaxEdit->text().toDouble();
717 // QwtScaleDiv xAxisScale =
718 // m_plot->axisScaleEngine(QwtPlot::xBottom)->divideScale(xMin, xMax,
719 // 25, 100);
720 // m_plot->setAxisScaleDiv(QwtPlot::xBottom, xAxisScale);
721 m_plot->setAxisScale(QwtPlot::xBottom, xMin, xMax);
722
723 double yMin = m_yMinEdit->text().toDouble();
724 double yMax = m_yMaxEdit->text().toDouble();
725 // QwtScaleDiv yAxisScale =
726 // m_plot->axisScaleEngine(QwtPlot::yLeft)->divideScale(yMin, yMax,
727 // 25, 100);
728 // m_plot->setAxisScaleDiv(QwtPlot::yLeft, yAxisScale);
729 m_plot->setAxisScale(QwtPlot::yLeft, yMin, yMax);
730
731 m_zoomer->setZoomBase();
732 }
733
734 replot();
735 }
736
737
743 QDialog *dialog = new QDialog(this);
744 dialog->setWindowTitle("Set Display Range");
745
746 QGridLayout *dialogLayout = new QGridLayout;
747
748 int row = 0;
749
750 QLabel *autoLabel = new QLabel("Auto-Scale: ");
751 dialogLayout->addWidget(autoLabel, row, 0);
752
753 m_autoScaleCheckBox = new QCheckBox("Scale X/Y Axes Automatically");
755 connect(m_autoScaleCheckBox, SIGNAL(stateChanged(int)),
756 this, SLOT(autoScaleCheckboxToggled()));
757 dialogLayout->addWidget(m_autoScaleCheckBox, row, 1);
758 row++;
759
760 QLabel *xLabel = new QLabel("<h3>X-Axis</h3>");
761 dialogLayout->addWidget(xLabel, row, 0, 1, 2);
762 row++;
763
764 QLabel *xMinLabel = new QLabel("Minimum: ");
765 dialogLayout->addWidget(xMinLabel, row, 0);
766
767 double xMin = plot()->axisScaleDiv(QwtPlot::xBottom).lowerBound();
768 m_xMinEdit = new QLineEdit(QString::number(xMin));
769 dialogLayout->addWidget(m_xMinEdit, row, 1);
770 row++;
771
772 QLabel *xMaxLabel = new QLabel("Maximum: ");
773 dialogLayout->addWidget(xMaxLabel, row, 0);
774
775 double xMax = plot()->axisScaleDiv(QwtPlot::xBottom).upperBound();
776 m_xMaxEdit = new QLineEdit(QString::number(xMax));
777 dialogLayout->addWidget(m_xMaxEdit, row, 1);
778 row++;
779
780 QLabel *xLogLabel = new QLabel("Logarithmic Scale");
781 dialogLayout->addWidget(xLogLabel, row, 0);
782
783 m_xLogCheckBox = new QCheckBox;
784 m_xLogCheckBox->setChecked(m_plotXLogScale);
785// m_xLogCheckBox->setChecked(
786// m_plot->axisScaleEngine(QwtPlot::xBottom)->transformation()->type() ==
787// QwtScaleTransformation::Log10);
788 dialogLayout->addWidget(m_xLogCheckBox, row, 1);
789 row++;
790
791 QLabel *yLabel = new QLabel("<h3>Y-Axis</h3>");
792 dialogLayout->addWidget(yLabel, row, 0, 1, 2);
793 row++;
794
795 QLabel *yMinLabel = new QLabel("Minimum: ");
796 dialogLayout->addWidget(yMinLabel, row, 0);
797
798 double yMin = plot()->axisScaleDiv(QwtPlot::yLeft).lowerBound();
799 m_yMinEdit = new QLineEdit(QString::number(yMin));
800 dialogLayout->addWidget(m_yMinEdit, row, 1);
801 row++;
802
803 QLabel *yMaxLabel = new QLabel("Maximum: ");
804 dialogLayout->addWidget(yMaxLabel, row, 0);
805
806 double yMax = plot()->axisScaleDiv(QwtPlot::yLeft).upperBound();
807 m_yMaxEdit = new QLineEdit(QString::number(yMax));
808 dialogLayout->addWidget(m_yMaxEdit, row, 1);
809 row++;
810
811 QLabel *yLogLabel = new QLabel("Logarithmic Scale");
812 dialogLayout->addWidget(yLogLabel, row, 0);
813
814 m_yLogCheckBox = new QCheckBox;
815 m_yLogCheckBox->setChecked(m_plotYLogScale);
816// m_yLogCheckBox->setChecked(
817// m_plot->axisScaleEngine(QwtPlot::yLeft)->transformation()->type() ==
818// QwtScaleTransformation::Log10);
819 dialogLayout->addWidget(m_yLogCheckBox, row, 1);
820 row++;
821
822 QHBoxLayout *buttonsLayout = new QHBoxLayout;
823 buttonsLayout->addStretch();
824
825 QPushButton *okButton = new QPushButton("&Ok");
826 okButton->setIcon(QIcon::fromTheme("dialog-ok"));
827 connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept()));
828 connect(dialog, SIGNAL(accepted()), this, SLOT(setUserValues()));
829 okButton->setShortcut(Qt::Key_Enter);
830 buttonsLayout->addWidget(okButton);
831
832 QPushButton *cancelButton = new QPushButton("&Cancel");
833 cancelButton->setIcon(QIcon::fromTheme("dialog-cancel"));
834 connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
835 buttonsLayout->addWidget(cancelButton);
836
837 QWidget *buttonsWrapper = new QWidget;
838 buttonsWrapper->setLayout(buttonsLayout);
839 dialogLayout->addWidget(buttonsWrapper, row, 0, 1, 2);
840 row++;
841
843
844 dialog->setLayout(dialogLayout);
845 dialog->show();
846 }
847
848
854 QDialog *dialog = new QDialog(this);
855 dialog->setWindowTitle("Name Plot Labels");
856
857 QGridLayout *dialogLayout = new QGridLayout;
858
859 int row = 0;
860 QLabel *plotLabel = new QLabel("Plot Title: ");
861 dialogLayout->addWidget(plotLabel, row, 0);
862
863 m_plotTitleText = new QLineEdit(plot()->title().text());
864 dialogLayout->addWidget(m_plotTitleText, row, 1);
865 row++;
866
867 QLabel *xAxisLabel = new QLabel("X-Axis Label: ");
868 dialogLayout->addWidget(xAxisLabel, row, 0);
869
870 m_xAxisText = new QLineEdit(m_plot->axisTitle(QwtPlot::xBottom).text());
871 dialogLayout->addWidget(m_xAxisText, row, 1);
872 row++;
873
874 QLabel *yAxisLabel = new QLabel("Y-Axis Label: ");
875 dialogLayout->addWidget(yAxisLabel, row, 0);
876
877 m_yAxisText = new QLineEdit(m_plot->axisTitle(QwtPlot::yLeft).text());
878 dialogLayout->addWidget(m_yAxisText, row, 1);
879 row++;
880
881 QHBoxLayout *buttonsLayout = new QHBoxLayout;
882 buttonsLayout->addStretch();
883
884 QPushButton *okButton = new QPushButton("&Ok");
885 okButton->setIcon(QIcon::fromTheme("dialog-ok"));
886 connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept()));
887 connect(dialog, SIGNAL(accepted()), this, SLOT(setLabels()));
888 okButton->setShortcut(Qt::Key_Enter);
889 buttonsLayout->addWidget(okButton);
890
891 QPushButton *cancelButton = new QPushButton("&Cancel");
892 cancelButton->setIcon(QIcon::fromTheme("dialog-cancel"));
893 connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
894 buttonsLayout->addWidget(cancelButton);
895
896 QWidget *buttonsWrapper = new QWidget;
897 buttonsWrapper->setLayout(buttonsLayout);
898 dialogLayout->addWidget(buttonsWrapper, row, 0, 1, 2);
899 row++;
900
901 dialog->setLayout(dialogLayout);
902 dialog->show();
903 }
904
905
910 m_plot->setTitle(m_plotTitleText->text());
911 m_plot->setAxisTitle(QwtPlot::xBottom, m_xAxisText->text());
912 m_plot->setAxisTitle(QwtPlot::yLeft, m_yAxisText->text());
913 /*Replot with new labels.*/
914 m_plot->replot();
915 }
916
917
923 m_grid->setVisible(!m_grid->isVisible());
924
925 if (m_grid->isVisible()) {
926 m_showHideGrid->setText("Hide Grid");
927 }
928 else {
929 m_showHideGrid->setText("Show Grid");
930 }
931 m_plot->replot();
932 }
933
934
939 void (QwtPlotItem::*method)();
940 if (m_showHideAllMarkers->text() == "Hide All Symbols") {
941 method = &QwtPlotItem::hide;
942
943 m_showHideAllMarkers->setText("Show All Symbols");
944
945 }
946 else {
947 method = &QwtPlotItem::show;
948
949 m_showHideAllMarkers->setText("Hide All Symbols");
950 }
951
952 for (int i = 0; i < m_plot->itemList().size(); i ++) {
953 QwtPlotItem *plotItem = m_plot->itemList()[i];
954 if (plotItem->rtti() == QwtPlotItem::Rtti_PlotMarker)
955 (plotItem->*method)();
956 }
957 /*Replot with all symbols hidden*/
958 m_plot->replot();
959 }
960
961
967 void (QwtPlotItem::*method)();
968 if (m_showHideAllCurves->text() == "Hide All Curves") {
969 method = &QwtPlotItem::hide;
970
971 m_showHideAllCurves->setText("Show All Curves");
972 m_showHideAllCurves->setIcon(
973 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_showCurves.png").expanded()));
974
975 }
976 else {
977 method = &QwtPlotItem::show;
978
979 m_showHideAllCurves->setText("Hide All Curves");
980 m_showHideAllCurves->setIcon(
981 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_hideCurves.png").expanded()));
982 }
983
984 for (int i = 0; i < m_plot->itemList().size(); i ++) {
985 QwtPlotItem *plotItem = m_plot->itemList()[i];
986 if (plotItem->rtti() == QwtPlotItem::Rtti_PlotCurve)
987 (plotItem->*method)();
988 }
989 /*Replot with all curves hidden*/
990 m_plot->replot();
991 }
992
993
999 QDialog *d = new QDialog(m_plot);
1000 d->setWindowTitle("Basic Help");
1001
1002 QLabel *zoomLabel = new QLabel("<U>Zoom Options:</U>");
1003 QLabel *zoomIn = new
1004 QLabel(" <b>Left click</b> on the mouse, drag, and release to select an area to zoom in on");
1005 QLabel *zoomOut = new
1006 QLabel(" <b>Middle click</b> on the mouse to zoom out one level");
1007 QLabel *zoomReset = new
1008 QLabel(" <b>Right click</b> on the mouse and select <I>Reset Scale</I> to clear the zoom and return to the original plot");
1009
1010 QLabel *curveConfigLabel = new QLabel("<br><U>Curve Configuration:</U>");
1011 QLabel *configDirections = new
1012 QLabel(" <b>To configure the curve properties</b> Right click on the legend and select <I>Configure</I> from <br> the menu"
1013 " or click on the configure icon in the tool bar.");
1014 QLabel *config = new QLabel();
1015 config->setPixmap(QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_configure.png").expanded()));
1016
1017 QLabel *tableLabel = new QLabel("<br><U>Table Options:</U>");
1018 QLabel *tableDirections = new
1019 QLabel(" <b>To view the table</b> Click on the File menu and select <I>Show Table</I> or click on the table icon in the <br> tool bar.");
1020 QLabel *table = new QLabel();
1021 table->setPixmap(QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_table.png").expanded()));
1022
1023 QVBoxLayout *layout = new QVBoxLayout();
1024 layout->addWidget(zoomLabel);
1025 layout->addWidget(zoomIn);
1026 layout->addWidget(zoomOut);
1027 layout->addWidget(zoomReset);
1028 layout->addWidget(curveConfigLabel);
1029 layout->addWidget(config);
1030 layout->addWidget(configDirections);
1031 layout->addWidget(tableLabel);
1032 layout->addWidget(table);
1033 layout->addWidget(tableDirections);
1034
1035 d->setLayout(layout);
1036 d->show();
1037 }
1038
1039
1048 QList<QMenu *> menu;
1049 QList<QAction *> actions;
1050
1051 QMenu *fileMenu = new QMenu("&File");
1052 QMenu *editMenu = new QMenu("&Edit");
1053 QMenu *optionsMenu = new QMenu("&Options");
1054 QMenu *helpMenu = new QMenu("&Help");
1055
1056 if ((optionsToProvide & SaveMenuOption) == SaveMenuOption) {
1057 QAction *save = new QAction(m_plot);
1058 save->setText("&Save Plot As");
1059 save->setIcon(QIcon::fromTheme("document-save-as"));
1060 QString text =
1061 "<b>Function:</b> Save the plot as a png, jpg, or tif file.";
1062 save->setWhatsThis(text);
1063 connect(save, SIGNAL(triggered()), this, SLOT(savePlot()));
1064 fileMenu->addAction(save);
1065 actions.push_back(save);
1066 }
1067
1068 if ((optionsToProvide & PrintMenuOption) == PrintMenuOption) {
1069 QAction *prt = new QAction(m_plot);
1070 prt->setText("&Print Plot");
1071 prt->setIcon(QIcon::fromTheme("document-print"));
1072 QString text =
1073 "<b>Function:</b> Sends the plot image to the printer";
1074 prt->setWhatsThis(text);
1075 connect(prt, SIGNAL(triggered()), this, SLOT(printPlot()));
1076 fileMenu->addAction(prt);
1077 actions.push_back(prt);
1078 }
1079
1080 if ((optionsToProvide & ShowTableMenuOption) == ShowTableMenuOption) {
1081 QAction *table = new QAction(m_plot);
1082 table->setText("Show Table");
1083 table->setIcon(
1084 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_table.png").expanded()));
1085 QString text =
1086 "<b>Function:</b> Activates the table which displays the data of the "
1087 "current plot";
1088 table->setWhatsThis(text);
1089 connect(table, SIGNAL(triggered()), this, SLOT(showTable()));
1090 fileMenu->addAction(table);
1091 actions.push_back(table);
1092 }
1093
1094 QAction *close = new QAction(QIcon::fromTheme("document-close"), "&Close",
1095 m_plot);
1096 connect(close, SIGNAL(triggered()), this, SLOT(close()));
1097 fileMenu->addAction(close);
1098
1099 if ((optionsToProvide & TrackMenuOption) == TrackMenuOption) {
1100 QAction *track = new QAction(m_plot);
1101 track->setText("Show Mouse &Tracking");
1102 track->setIcon(
1103 QPixmap(FileName("$ISISROOT/appdata/images/icons/goto.png").expanded()));
1104 track->setCheckable(true);
1105 QString text =
1106 "<b>Function:</b> Displays the x,y coordinates as the cursor moves "
1107 "around on the plot.";
1108 track->setWhatsThis(text);
1109 connect(track, SIGNAL(triggered()), this, SLOT(trackerEnabled()));
1110 optionsMenu->addAction(track);
1111 }
1112
1113 if ((optionsToProvide & BackgroundSwitchMenuOption) ==
1115 QAction *backgrdSwitch = new QAction(m_plot);
1116 backgrdSwitch->setText("White/Black &Background");
1117 backgrdSwitch->setIcon(
1118 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_switchBackgrd.png").expanded()));
1119 QString text =
1120 "<b>Function:</b> Switch the background color between black and "
1121 "white.";
1122 backgrdSwitch->setWhatsThis(text);
1123 connect(backgrdSwitch, SIGNAL(triggered()),
1124 this, SLOT(switchBackground()));
1125 optionsMenu->addAction(backgrdSwitch);
1126 actions.push_back(backgrdSwitch);
1127 }
1128
1129 if ((optionsToProvide & ShowHideGridMenuOption) == ShowHideGridMenuOption) {
1131 m_showHideGrid->setText("Show Grid");
1132 m_showHideGrid->setIcon(
1133 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_grid.png").expanded()));
1134 QString text =
1135 "<b>Function:</b> Display grid lines on the plot.";
1136 m_showHideGrid->setWhatsThis(text);
1137 connect(m_showHideGrid, SIGNAL(triggered()), this, SLOT(showHideGrid()));
1138 optionsMenu->addAction(m_showHideGrid);
1139 actions.push_back(m_showHideGrid);
1140 }
1141
1142 if ((optionsToProvide & RenameLabelsMenuOption) == RenameLabelsMenuOption) {
1143 QAction *changeLabels = new QAction(m_plot);
1144 changeLabels->setText("Rename Plot &Labels");
1145 changeLabels->setIcon(
1146 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_renameLabels.png").expanded()));
1147 QString text =
1148 "<b>Function:</b> Edit the plot title, x and y axis labels.";
1149 changeLabels->setWhatsThis(text);
1150 connect(changeLabels, SIGNAL(triggered()),
1151 this, SLOT(changePlotLabels()));
1152 optionsMenu->addAction(changeLabels);
1153 actions.push_back(changeLabels);
1154 }
1155
1156 if ((optionsToProvide & SetDisplayRangeMenuOption) ==
1158 QAction *changeScale = new QAction(m_plot);
1159 changeScale->setText("Set &Display Range");
1160 changeScale->setIcon(
1161 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_setScale.png").expanded()));
1162 QString text =
1163 "<b>Function:</b> Adjust the scale for the x and y axis on the "
1164 "plot.";
1165 changeScale->setWhatsThis(text);
1166 connect(changeScale, SIGNAL(triggered()), this, SLOT(setDefaultRange()));
1167 optionsMenu->addAction(changeScale);
1168 actions.push_back(changeScale);
1169 }
1170
1171 if ((optionsToProvide & ShowHideCurvesMenuOption) ==
1174 m_showHideAllCurves->setText("Hide All Curves");
1175 m_showHideAllCurves->setIcon(
1176 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_showCurves.png").expanded()));
1177 QString text =
1178 "<b>Function:</b> Displays or hides all the curves currently "
1179 "displayed on the plot.";
1180 m_showHideAllCurves->setWhatsThis(text);
1181 connect(m_showHideAllCurves, SIGNAL(triggered()),
1182 this, SLOT(showHideAllCurves()));
1183 optionsMenu->addAction(m_showHideAllCurves);
1184 actions.push_back(m_showHideAllCurves);
1185 }
1186
1187 if ((optionsToProvide & ShowHideMarkersMenuOption) ==
1190 m_showHideAllMarkers->setText("Hide All Symbols");
1191 m_showHideAllMarkers->setIcon(
1192 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_markers.png").expanded()));
1193 QString text = "<b>Function:</b> Displays or hides a symbol for each "
1194 "data point plotted on a plot.";
1195 m_showHideAllMarkers->setWhatsThis(text);
1196 connect(m_showHideAllMarkers, SIGNAL(triggered()),
1197 this, SLOT(showHideAllMarkers()));
1198 optionsMenu->addAction(m_showHideAllMarkers);
1199 actions.push_back(m_showHideAllMarkers);
1200 }
1201
1202 if ((optionsToProvide & ResetScaleMenuOption) == ResetScaleMenuOption) {
1203 QAction *resetScaleButton = new QAction(m_plot);
1204 resetScaleButton->setText("Reset Scale");
1205 resetScaleButton->setIcon(
1206 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_resetscale.png").expanded()));
1207 QString text =
1208 "<b>Function:</b> Reset the plot's scale.";
1209 resetScaleButton->setWhatsThis(text);
1210 connect(resetScaleButton, SIGNAL(triggered()), this, SLOT(resetScale()));
1211 actions.push_back(resetScaleButton);
1212 }
1213
1214 if ((optionsToProvide & ClearPlotMenuOption) == ClearPlotMenuOption) {
1215 QAction *clear = new QAction(m_plot);
1216 clear->setText("Clear Plot");
1217 clear->setIcon(
1218 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_clear.png").expanded()));
1219 QString text =
1220 "<b>Function:</b> Removes all the curves from the plot.";
1221 clear->setWhatsThis(text);
1222 connect(clear, SIGNAL(triggered()), this, SLOT(clearPlot()));
1223 actions.push_back(clear);
1224 }
1225
1226 if ((optionsToProvide & LineFitMenuOption) == LineFitMenuOption) {
1227 QAction *lineFit = new QAction(m_plot);
1228 lineFit->setText("Create Best Fit Line");
1229 lineFit->setIcon(
1230 QPixmap(FileName("$ISISROOT/appdata/images/icons/linefit.png").expanded()));
1231 QString text = "<b>Function:</b> Calculates a best fit line from an "
1232 "existing curve.";
1233 lineFit->setWhatsThis(text);
1234 connect(lineFit, SIGNAL(triggered()), this, SLOT( createBestFitLine() ) );
1235 optionsMenu->addAction(lineFit);
1236 actions.push_back(lineFit);
1237 }
1238
1239 if ((optionsToProvide & ConfigurePlotMenuOption) == ConfigurePlotMenuOption) {
1240 QAction *configurePlot = new QAction(m_plot);
1241 configurePlot->setText("Configure Plot");
1242 configurePlot->setIcon(
1243 QPixmap( FileName("$ISISROOT/appdata/images/icons/plot_configure.png").expanded() ) );
1244 QString text = "<b>Function:</b> Change the name, color, style, and vertex symbol of the "
1245 "curves.";
1246 configurePlot->setWhatsThis(text);
1247 connect( configurePlot, SIGNAL( triggered() ),
1248 this, SLOT( configurePlotCurves() ) );
1249 optionsMenu->addAction(configurePlot);
1250 actions.push_back(configurePlot);
1251 }
1252
1253 QAction *basicHelp = new QAction(m_plot);
1254 basicHelp->setText("Basic Help");
1255 QString text = "<b>Function:</b> Provides a basic overview on using components "
1256 "of the qview plot window";
1257 basicHelp->setWhatsThis(text);
1258 connect( basicHelp, SIGNAL( triggered() ),
1259 this, SLOT( showHelp() ) );
1260 helpMenu->addAction(basicHelp);
1261
1262 /*setup menus*/
1263 m_pasteAct = new QAction(QIcon::fromTheme("edit-paste"),
1264 "&Paste Curve", m_plot);
1265 m_pasteAct->setEnabled(false);
1266 m_pasteAct->setShortcut(Qt::CTRL | Qt::Key_V);
1267 connect(m_pasteAct, SIGNAL(triggered()),
1268 this, SLOT(pasteCurve()));
1269 editMenu->addAction(m_pasteAct);
1270
1271 menu.push_back(fileMenu);
1272 menu.push_back(editMenu);
1273
1274 if (optionsMenu->actions().size()) {
1275 menu.push_back(optionsMenu);
1276 }
1277 else {
1278 delete optionsMenu;
1279 optionsMenu = NULL;
1280 }
1281
1282 if (helpMenu->actions().size()) {
1283 menu.push_back(helpMenu);
1284 }
1285 else {
1286 delete helpMenu;
1287 helpMenu = NULL;
1288 }
1289
1290 setMenus(menu, actions);
1291 }
1292
1293
1305 bool PlotWindow::userCanAddCurve(const QMimeData *curve) {
1306 bool userCanAdd = false;
1307
1309 curve->hasFormat("application/isis3-plot-curve")) {
1310
1311 CubePlotCurve * testCurve = new CubePlotCurve(
1312 curve->data("application/isis3-plot-curve"));
1313
1314 userCanAdd = canAdd(testCurve);
1315 }
1316
1317 return userCanAdd;
1318 }
1319
1320
1330 if (m_showHideAllCurves) {
1331 if (m_showHideAllCurves->text() == "Hide All Curves") {
1332 curve->show();
1333 }
1334 else {
1335 curve->hide();
1336 }
1337
1338 if (m_showHideAllMarkers->text() == "Hide All Symbols") {
1339 curve->setMarkerVisible(true);
1340 }
1341 else {
1342 curve->setMarkerVisible(false);
1343 }
1344 }
1345
1346 emit plotChanged();
1347 }
1348
1349
1357 void PlotWindow::setMenus(QList<QMenu *> menu, QList<QAction *> actions) {
1358 if (m_toolBar == NULL) {
1359 m_toolBar = new QToolBar(this);
1360 m_toolBar->setObjectName("PlotWindow");
1361 m_toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea | Qt::TopToolBarArea);
1362 addToolBar(Qt::TopToolBarArea, m_toolBar);
1363 }
1364 else {
1365 m_toolBar->clear();
1366 }
1367
1368 m_menubar = menuBar();
1369 m_menubar->clear();
1370
1371 for (int i = 0; i < menu.size(); i++) {
1372 m_menubar->addMenu(menu[i]);
1373 }
1374
1375 for (int i = 0; i < actions.size(); i++) {
1376 m_toolBar->addAction(actions[i]);
1377 }
1378
1379 }
1380
1381
1387 QwtPlotZoomer *PlotWindow::zoomer() {
1388 return m_zoomer;
1389 }
1390
1391
1399 if (!m_scheduledFillTable) {
1400 m_scheduledFillTable = true;
1401 emit requestFillTable();
1402 }
1403 }
1404
1405
1411 m_scheduledFillTable = false;
1412
1413 if (m_tableWindow == NULL) return;
1414 m_tableWindow->listWidget()->clear();
1415 m_tableWindow->table()->clear();
1416 m_tableWindow->table()->setRowCount(0);
1417 m_tableWindow->table()->setColumnCount(0);
1418
1420 m_plot->axisTitle(QwtPlot::xBottom).text(),
1421 m_plot->axisTitle(QwtPlot::xBottom).text());
1422
1423 QList<CubePlotCurve *> curves = plotCurves();
1424 foreach (CubePlotCurve *curve, curves) {
1426 curve->title().text(),
1427 curve->title().text());
1428 }
1429
1430 // We really need all of the x-values associated with the curves,
1431 // but qwt doesn't seem to want to give this to us. It'll give us the
1432 // axis scale, but that isn't quite what we want (especially when zooming)
1433 // So let's find the list of x-points ourselves.
1434 //
1435 // This is what I tried and it did NOT work:
1436 // QwtScaleDiv *xAxisScaleDiv = m_plot->axisScaleDiv(QwtPlot::xBottom);
1437 // QList<double> xAxisPoints = xAxisScaleDiv->ticks(QwtScaleDiv::MajorTick);
1438 //
1439 // We're going to keep xAxisPoints in standard text sort order until we're done populating it,
1440 // then we'll re-sort numerically. That enables us to effectively use binary searches and
1441 // insertion sort-like capabilities for speed.
1442 QList<QString> xAxisPoints;
1443
1444 QProgressDialog progress(tr("Re-calculating Table"), tr(""), 0, 1000, this);
1445 double percentPerCurve = 0.5 * 1.0 / curves.count();
1446
1447 for (int curveIndex = 0; curveIndex < curves.count(); curveIndex++) {
1448 progress.setValue(qRound(curveIndex * percentPerCurve * 1000.0));
1449
1450 CubePlotCurve *curve = curves[curveIndex];
1451
1452 double percentPerDataIndex = (1.0 / curve->data()->size()) * percentPerCurve;
1453
1454 // Loop backwards because our insertion sort will have a much better
1455 // chance of success on it's first try this way.
1456 for (int dataIndex = (int)curve->data()->size() - 1;
1457 dataIndex >= 0;
1458 dataIndex--) {
1459 double xValue = curve->data()->sample(dataIndex).x();
1460 QString xValueString = toString(xValue);
1461
1462 int inverseDataIndex = (curve->data()->size() - 1) - dataIndex;
1463 progress.setValue(
1464 qRound( ((curveIndex * percentPerCurve) +
1465 (inverseDataIndex * percentPerDataIndex)) * 1000.0));
1466
1467 // It turns out that qBinaryFind(container, value) is NOT the same as
1468 // qBinaryFind(container.begin(), container.end(), value). Use the one
1469 // that works right.
1471 qBinaryFind(xAxisPoints.begin(), xAxisPoints.end(), xValueString);
1472
1473 if (foundPos == xAxisPoints.end()) {
1474 bool inserted = false;
1475
1476 for (int searchIndex = 0;
1477 searchIndex < xAxisPoints.size() && !inserted;
1478 searchIndex++) {
1479 if (xAxisPoints[searchIndex] > xValueString) {
1480 inserted = true;
1481 xAxisPoints.insert(searchIndex, xValueString);
1482 }
1483 }
1484
1485 if (!inserted)
1486 xAxisPoints.append(xValueString);
1487 }
1488 }
1489 }
1490
1491 qSort(xAxisPoints.begin(), xAxisPoints.end(), &numericStringLessThan);
1492
1493 m_tableWindow->table()->setRowCount(xAxisPoints.size());
1494
1495 QList<int> lastSuccessfulSamples;
1496
1497 for (int i = 0; i < curves.count(); i++) {
1498 lastSuccessfulSamples.append(-1);
1499 }
1500
1501 double progressPerRow = 0.5 * 1.0 / m_tableWindow->table()->rowCount();
1502
1503 for (int row = 0; row < m_tableWindow->table()->rowCount(); row++) {
1504 progress.setValue(500 + qRound(row * progressPerRow * 1000.0));
1505
1506 QString xValueString = xAxisPoints[row];
1507 double xValue = toDouble(xValueString);
1508
1509 QTableWidgetItem *xAxisItem = new QTableWidgetItem(xValueString);
1510 m_tableWindow->table()->setItem(row, 0, xAxisItem);
1511
1512 if (row == m_tableWindow->table()->rowCount() - 1) {
1513 m_tableWindow->table()->resizeColumnToContents(0);
1514 }
1515
1516 // Now search for the x-axis points in the curves to fill in data
1517 for (int col = 1; col < m_tableWindow->table()->columnCount(); col++) {
1518 CubePlotCurve *curve = curves[col - 1];
1519
1520 double y = Null;
1521 bool tooFar = false;
1522
1523 for (int dataIndex = lastSuccessfulSamples[col - 1] + 1;
1524 dataIndex < (int)curve->data()->size() && y == Null && !tooFar;
1525 dataIndex++) {
1526
1527 if (toString(curve->data()->sample(dataIndex).x()) == xValueString) {
1528 // Try to compensate for decreasing x values by not performing this optimization
1529 if (dataIndex > 0 &&
1530 curve->data()->sample(dataIndex - 1).x() < curve->data()->sample(dataIndex).x()) {
1531 lastSuccessfulSamples[col - 1] = dataIndex;
1532 }
1533 y = curve->data()->sample(dataIndex).y();
1534 }
1535 // Try to compensate for decreasing X values in the too far computation
1536 else if (dataIndex > 0 &&
1537 curve->data()->sample(dataIndex - 1).x() < curve->data()->sample(dataIndex).x() &&
1538 curve->data()->sample(dataIndex).x() > xValue) {
1539 tooFar = true;
1540 }
1541 }
1542
1543 QTableWidgetItem *item = NULL;
1544
1545 if (IsSpecial(y))
1546 item = new QTableWidgetItem(QString("N/A"));
1547 else
1548 item = new QTableWidgetItem(toString(y));
1549
1550 m_tableWindow->table()->setItem(row, col, item);
1551
1552 if (row == m_tableWindow->table()->rowCount() - 1) {
1553 m_tableWindow->table()->resizeColumnToContents(col);
1554 }
1555 }
1556 }
1557 }
1558
1559
1566 if (plotCurves().size()) {
1567 if (m_tableWindow == NULL) {
1568 //m_tableWindow = new TableMainWindow("Plot Table", this);
1569 m_tableWindow = new TableMainWindow("Plot Table", m_parent);
1571 }
1572
1573 fillTable();
1574 m_tableWindow->show();
1576 }
1577 }
1578
1579
1589 bool PlotWindow::eventFilter(QObject *o, QEvent *e) {
1590 bool blockWidgetFromEvent = false;
1591
1592 switch (e->type()) {
1593 case QEvent::MouseButtonPress:
1594 if (o == this &&
1595 childAt(((QMouseEvent *)e)->pos()) != plot()->canvas()) {
1596 mousePressEvent(o, (QMouseEvent *)e);
1597 blockWidgetFromEvent = true;
1598 }
1599 break;
1600
1601 default:
1602 break;
1603 }
1604
1605 bool stopHandlingEvent = false;
1606 if (!blockWidgetFromEvent && o == this) {
1607 stopHandlingEvent = MainWindow::eventFilter(o, e);
1608
1609 if (e->type() == QEvent::Close && !stopHandlingEvent) {
1610 emit closed();
1611 }
1612 }
1613
1614 return stopHandlingEvent || blockWidgetFromEvent;
1615 }
1616
1617
1627 void PlotWindow::mousePressEvent(QObject *object, QMouseEvent *event) {
1628 if (qobject_cast<QWidget *>(object) &&
1629 event->button() == Qt::RightButton &&
1630 userCanAddCurve(QApplication::clipboard()->mimeData())) {
1631 QMenu contextMenu;
1632
1633 QAction *pasteAct = new QAction(QIcon::fromTheme("edit-paste"), "Paste",
1634 this);
1635 contextMenu.addAction(pasteAct);
1636
1637 QAction *chosenAct = contextMenu.exec(
1638 qobject_cast<QWidget *>(object)->mapToGlobal(event->pos()));
1639
1640 if (chosenAct == pasteAct) {
1641 pasteCurve();
1642 }
1643 }
1644 }
1645
1646
1653 return m_plot;
1654 }
1655
1656
1666
1667
1675 m_xMinEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1676 m_xMaxEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1677 m_yMinEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1678 m_yMaxEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1679 }
1680
1681
1686 m_pasteAct->setEnabled(
1687 userCanAddCurve(QApplication::clipboard()->mimeData()));
1688 }
1689
1690
1698 QClipboard *globalClipboard = QApplication::clipboard();
1699 const QMimeData *globalData = globalClipboard->mimeData();
1700
1701 if (globalData->hasFormat("application/isis3-plot-curve")) {
1702 CubePlotCurve * newCurve = new CubePlotCurve(
1703 globalData->data("application/isis3-plot-curve"));
1704 // add curve to plot
1705 add(newCurve);
1706 emit plotChanged();
1707 }
1708 }
1709 }
1710
1711
1721 QPair<double, double> PlotWindow::findDataRange(int axisId) const {
1722 QList<const CubePlotCurve *> curves = plotCurves();
1723
1724 bool foundDataValue = false;
1725 QPair<double, double> rangeMinMax;
1726
1727 foreach(const CubePlotCurve *curve, curves) {
1728 for (int dataIndex = 0; dataIndex < (int)curve->dataSize(); dataIndex++) {
1729 if (axisId == QwtPlot::xBottom) {
1730 if (!foundDataValue) {
1731 rangeMinMax.first = curve->sample(dataIndex).x();
1732 rangeMinMax.second = curve->sample(dataIndex).x();
1733 foundDataValue = true;
1734 }
1735 else {
1736 rangeMinMax.first = qMin(rangeMinMax.first, curve->sample(dataIndex).x());
1737 rangeMinMax.second = qMax(rangeMinMax.second, curve->sample(dataIndex).x());
1738 }
1739 }
1740 else if (axisId == QwtPlot::yLeft) {
1741 if (!foundDataValue) {
1742 rangeMinMax.first = curve->sample(dataIndex).y();
1743 rangeMinMax.second = curve->sample(dataIndex).y();
1744 foundDataValue = true;
1745 }
1746 else {
1747 rangeMinMax.first = qMin(rangeMinMax.first, curve->sample(dataIndex).y());
1748 rangeMinMax.second = qMax(rangeMinMax.second, curve->sample(dataIndex).y());
1749 }
1750 }
1751 }
1752 }
1753
1754 if (!foundDataValue) {
1755 rangeMinMax.first = 1;
1756 rangeMinMax.second = 10;
1757 }
1758 else if(rangeMinMax.first == rangeMinMax.second) {
1759 rangeMinMax.first -= 0.5;
1760 rangeMinMax.second += 0.5;
1761 }
1762
1763 return rangeMinMax;
1764 }
1765
1766
1767 bool PlotWindow::numericStringLessThan(QString left, QString right) {
1768 bool result = false;
1769
1770 try {
1771 result = toDouble(left) < toDouble(right);
1772 }
1773 catch (IException &) {
1774 }
1775
1776 return result;
1777 }
1778
1779
1786 void PlotWindow::paint(MdiCubeViewport *vp, QPainter *painter) {
1787 foreach (CubePlotCurve *curve, plotCurves()) {
1788 curve->paint(vp, painter);
1789 }
1790 }
1791
1792
1797 resetScale();
1798 emit plotChanged();
1799 }
1800
1801
1810 return "Plot";
1811 }
1812
1813
1822 void PlotWindow::dragEnterEvent(QDragEnterEvent *event) {
1823 QObject *source = event->source();
1824
1825 if (source != m_legend->contentsWidget() &&
1826 userCanAddCurve(event->mimeData())) {
1827 event->acceptProposedAction();
1828 }
1829 }
1830
1831
1843 void PlotWindow::dropEvent(QDropEvent *event) {
1845 event->mimeData()->hasFormat("application/isis3-plot-curve")) {
1846 Qt::DropActions possibleActions = event->possibleActions();
1847 Qt::DropAction actionToTake = event->proposedAction();
1848
1849 QFont boldFont;
1850 boldFont.setBold(true);
1851 QMenu dropActionsMenu;
1852
1853 QAction *copyAct = new QAction("&Copy Here", this);
1854 if (possibleActions.testFlag(Qt::CopyAction)) {
1855 dropActionsMenu.addAction(copyAct);
1856
1857 if (actionToTake == Qt::CopyAction)
1858 copyAct->setFont(boldFont);
1859 }
1860
1861 QAction *moveAct = new QAction("&Move Here", this);
1862 if (possibleActions.testFlag(Qt::MoveAction)) {
1863 dropActionsMenu.addAction(moveAct);
1864
1865 if (actionToTake == Qt::MoveAction)
1866 moveAct->setFont(boldFont);
1867 }
1868
1869 if (dropActionsMenu.actions().size() > 1) {
1870 dropActionsMenu.addSeparator();
1871
1872 QAction *cancelAct = new QAction("&Cancel", this);
1873 dropActionsMenu.addAction(cancelAct);
1874
1875 QAction *chosenAct = dropActionsMenu.exec(mapToGlobal(event->pos()));
1876
1877 if (chosenAct == copyAct) {
1878 actionToTake = Qt::CopyAction;
1879 }
1880 else if (chosenAct == moveAct) {
1881 actionToTake = Qt::MoveAction;
1882 }
1883 else {
1884 actionToTake = Qt::IgnoreAction;
1885 }
1886 }
1887
1888 if (actionToTake != Qt::IgnoreAction) {
1889 CubePlotCurve * newCurve = new CubePlotCurve(
1890 event->mimeData()->data("application/isis3-plot-curve"));
1891 // add curve to plot
1892 add(newCurve);
1893 emit plotChanged();
1894
1895 event->setDropAction(actionToTake);
1896 event->accept();
1897 }
1898 }
1899 }
1900
1901}
This should be an inner class for CubePlotCurve, but Qt doesn't support having a QObject as an inner ...
This is a plot curve with information relating it to a particular cube or region of a cube.
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
Base class for the Qisis main windows.
Definition MainWindow.h:24
virtual void readSettings(QSize defaultSize=QSize())
This method ensure that the settings get written even if the Main window was only hidden,...
Cube display widget for certain Isis MDI applications.
Units
These are all the possible units for the x or y data in a plot curve.
Definition PlotCurve.h:54
@ Elevation
The data is an elevation (in meters).
Definition PlotCurve.h:71
@ Band
The data is a band number.
Definition PlotCurve.h:63
@ CubeDN
The data is a Cube DN value.
Definition PlotCurve.h:67
@ Wavelength
The data is a wavelength.
Definition PlotCurve.h:92
@ Kilometers
The data is in kilometers.
Definition PlotCurve.h:87
@ PixelNumber
The data is a pixel #.
Definition PlotCurve.h:79
@ Meters
The data is in meters.
Definition PlotCurve.h:83
@ Percentage
The data is a percentage (0-100).
Definition PlotCurve.h:75
QLineEdit * m_plotTitleText
Set Labels Dialog's edit for the plot title.
Definition PlotWindow.h:299
QList< CubePlotCurve * > plotCurves()
Get a comprehensive list of the plot curves inside of this plot window, excluding plot curves that ar...
QPointer< QAction > m_showHideAllCurves
Hide all curves action.
Definition PlotWindow.h:314
QwtPlot * m_plot
The plot in this window.
Definition PlotWindow.h:330
void createWidgets(MenuOptions optionsToProvide)
This method is called by the constructor to create the plot, legend.
void closed()
Emitted when there is a close event on this window that will be accepted.
void setAxisLabel(int axisId, QString title)
Sets the plots given axis title to the given string.
virtual void add(CubePlotCurve *pc)
This method adds the curves to the plot.
virtual void dragEnterEvent(QDragEnterEvent *event)
When a user drags data into our plot window, we need to indicate whether or not this data is compatib...
QLineEdit * m_xMinEdit
Set Scale Dialog's edit for the min X-axis value.
Definition PlotWindow.h:287
void autoScaleCheckboxToggled()
This is a helper method for the set scale configuration dialog.
void showHideAllMarkers()
Shows/Hides all the markers(symbols)
bool m_plotXLogScale
Tracks if the plot X axis is using a log (true) or linear (false) scale.
Definition PlotWindow.h:332
void plotChanged()
Emitted every time there is a change to the plot window.
QMenuBar * m_menubar
Plot window's menu bar.
Definition PlotWindow.h:302
QLineEdit * m_xMaxEdit
Set Scale Dialog's edit for the max X-axis value.
Definition PlotWindow.h:289
QLineEdit * m_yMinEdit
Set Scale Dialog's edit for the min Y-axis value.
Definition PlotWindow.h:291
bool m_allowUserToAddCurves
Is the window showing the curve markers?
Definition PlotWindow.h:326
QString plotTitle() const
Returns the plot title.
QLineEdit * m_xAxisText
Set Labels Dialog's edit for the x-axis label.
Definition PlotWindow.h:295
void showHideAllCurves()
This method shows or hides all of the curves in the plotWindow.
QPointer< QAction > m_showHideGrid
Show plot grid lines action.
Definition PlotWindow.h:318
void printPlot()
Provides printing support of the plot image.
QwtPlotZoomer * m_zoomer
Plot Zoomer.
Definition PlotWindow.h:277
void setPlotBackground(QColor c)
Sets the plot background color to the given color.
MenuOptions
There is a menu option for everything in the plot window's menu.
Definition PlotWindow.h:96
@ LineFitMenuOption
This option allows the user to create a best fit line for any of the scatter plot data or cube plot c...
Definition PlotWindow.h:163
@ PrintMenuOption
This option sends the plot to a printer.
Definition PlotWindow.h:118
@ ResetScaleMenuOption
This option provides the user with an alternative zoom out button.
Definition PlotWindow.h:147
@ ShowHideMarkersMenuOption
This option is titled 'Hide All Symbols' which hides all markers.
Definition PlotWindow.h:98
@ ConfigurePlotMenuOption
This option allows the user to change the curve name, color, style size, and symbol of the curve.
Definition PlotWindow.h:169
@ SaveMenuOption
This option exports the plot into a standard image format.
Definition PlotWindow.h:114
@ ShowHideGridMenuOption
This option enables the ability for a user to enable a grid over the plot area.
Definition PlotWindow.h:134
@ ShowTableMenuOption
This option brings up the table.
Definition PlotWindow.h:108
@ ClearPlotMenuOption
This option allows the user to delete all of the data inside the plot.
Definition PlotWindow.h:153
@ RenameLabelsMenuOption
This option enables the ability for a user to change the x/y axis labels and plot title.
Definition PlotWindow.h:139
@ TrackMenuOption
This option enables mouse tracking on the plot area (displays next to the mouse which x/y point you a...
Definition PlotWindow.h:124
@ ShowHideCurvesMenuOption
This option is titled 'Hide All Curves' which makes all curves invisible.
Definition PlotWindow.h:103
@ BackgroundSwitchMenuOption
This option enables the ability for a user to change the background color of the plot from black to w...
Definition PlotWindow.h:129
@ SetDisplayRangeMenuOption
This option allows the user to set the x/y axis display value ranges.
Definition PlotWindow.h:143
QLineEdit * m_yMaxEdit
Set Scale Dialog's edit for the max Y-axis value.
Definition PlotWindow.h:293
void pasteCurve()
When the user pastes a curve try to put it into this plot window.
static QString defaultWindowTitle()
This is the typical suffix for plot windows, it's here in case we want to update all plot windows to ...
void showWindow()
Shows the plot window, and raises it to the front of any overlapping sibling widgets.
QCheckBox * m_yLogCheckBox
Set Scale Dialog's checkbox for using logarithmic scale for the y axis.
Definition PlotWindow.h:285
void resetScale()
Sets plot scale back to the defaults.
QPointer< QAction > m_showHideAllMarkers
Hide all markers action.
Definition PlotWindow.h:316
void createBestFitLine()
This method prompts the user to select the best fit line criterea.
QAction * m_pasteAct
This is the paste action in the edit menu to paste a curve into the plot window.
Definition PlotWindow.h:309
bool userCanAddCurve(const QMimeData *curve)
Ask if a user action can add this curve to this window.
void setupDefaultMenu(MenuOptions optionsToProvide)
The user can add menu items from parent classes, but there are some menu items that are common betwee...
QColor plotBackgroundColor() const
Returns the plot's background color.
QLineEdit * m_yAxisText
Set Labels Dialog's edit for the y-axis label.
Definition PlotWindow.h:297
TableMainWindow * m_tableWindow
Table window.
Definition PlotWindow.h:334
virtual void dropEvent(QDropEvent *event)
This is called when a user drops data into our window.
void onClipboardChanged()
This slot will be called when the system clipboard is changed.
void replot()
Reset the scale of the plot, replot it and emit plot changed.
QPair< double, double > findDataRange(int axisId) const
This calculates the data range of the specified axis (works with xBottom and yLeft only).
void trackerEnabled()
Enables the plot mouse tracker.
void updateVisibility(PlotCurve *curve)
This method sets the visibility states in the curve (and it's symbols) to match with this window's cu...
PlotCurve::Units xAxisUnits() const
This is the data-type of the curves' x data in this plot window.
void setPlotTitle(QString pt)
Sets the plot title to the given string.
QwtLegend * m_legend
The legend inserted in this plot.
Definition PlotWindow.h:331
void setUserCanAddCurves(bool)
Allow or disallow users from manually putting curves into this plot window through either copy-and-pa...
virtual bool eventFilter(QObject *o, QEvent *e)
This method filters the events of the objects it is connected to.
bool m_autoscaleAxes
True if we are autoscaling the x-bottom and y-left axes.
Definition PlotWindow.h:328
void changePlotLabels()
This method creates the dialog box which allows the user to relabel the plot window.
QWidget * m_parent
Parent widget.
Definition PlotWindow.h:275
void setUserValues()
This method sets the scale for the axis according to the user specified numbers.
virtual void update(MdiCubeViewport *activeViewport)
This is provided to allow children to react to tool updates.
void showHideGrid()
This method hides/shows the grid on the plotWindow and changes the text for the action.
void configurePlotCurves()
This method creates a CubePlotCurveConfigureDialog object.
PlotCurve::Units m_xAxisUnits
The units of the data on the x-bottom axis.
Definition PlotWindow.h:321
QCheckBox * m_autoScaleCheckBox
Set Scale Dialog's checkbox for enabling automatic scaling on x & y.
Definition PlotWindow.h:281
bool canAdd(CubePlotCurve *curveToTest) const
This method tests whethere or not a CubePlotCurve can be successfully added to this window.
void fillTable()
Fills in the table with the data from the current curves in the plotWindow immediately.
QToolBar * m_toolBar
Tool bar on the plot window.
Definition PlotWindow.h:335
QwtPlotGrid * m_grid
Plot grid lines.
Definition PlotWindow.h:279
void savePlot()
This method allows the user to save the plot as a png, jpg, or tif image file.
PlotCurve::Units m_yAxisUnits
The units of the data on the y-left axis.
Definition PlotWindow.h:323
void showHelp()
This method creates and shows the help dialog box for the plot window.
void showTable()
This method is called from the showTable action on the tool bar There are some checks done to make su...
void setDefaultRange()
Resets the x/y min/max to the defaults.
virtual void paint(MdiCubeViewport *vp, QPainter *painter)
Paint plot curve information onto the viewport.
PlotCurve::Units yAxisUnits() const
This is the data-type of the curves' y data in this plot window.
void clearPlot()
This method completely clears the plot of all plot items.
bool userCanAddCurves() const
Ask if a user action can add this curve to this window in general.
virtual void clearPlotCurves()
This method also clears the plot of all plot items, but does not call the table delete stuff This met...
void setLabels()
Makes the user specified changes to the plot labels.
QCheckBox * m_xLogCheckBox
Set Scale Dialog's checkbox for using logarithmic scale for the x axis.
Definition PlotWindow.h:283
void switchBackground()
This method toggles the plot background color between black and white.
void mousePressEvent(QObject *object, QMouseEvent *e)
This is a helper method for the eventFilter() method.
void scheduleFillTable()
Fills in the table with the data from the current curves in the plotWindow once all current actions/a...
void disableAxisAutoScale()
This turns off scaling the x/y axes automatically.
PlotWindow(QString title, PlotCurve::Units xAxisUnits, PlotCurve::Units yAxisUnits, QWidget *parent, MenuOptions optionsToProvide=AllMenuOptions)
This constructs a plot window.
QwtPlot * plot()
Get the plot encapsulated by this PlotWindow.
QList< QwtPlotSpectrogram * > plotSpectrograms()
Get a comprehensive list of the scatter plots (spectrograms) inside of this plot window.
QwtPlotZoomer * zoomer()
Get this window's plot's zoomer.
void setMenus(QList< QMenu * > menus, QList< QAction * > actions)
Sets up the menus added from a parent object.
bool m_plotYLogScale
Tracks if the plot Y axis is using a log (true) or linear (false) scale.
Definition PlotWindow.h:333
a subclass of the qisis mainwindow, tablemainwindow handles all of the table tasks.
QTableWidget * table() const
Returns the table.
void addToTable(bool setOn, const QString &heading, const QString &menuText="", int insertAt=-1, Qt::Orientation o=Qt::Horizontal, QString toolTip="")
Adds a new column to the table when a new curve is added to the plot.
void syncColumns()
This method hides and shows the columns according to which items the user has selected to be view-abl...
void setTrackListItems(bool track=false)
If this property is true, the class will keep track of the checked/unchecked items in the dock area w...
QListWidget * listWidget() const
Returns the list widget.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
const double Null
Value for an Isis Null pixel.
bool IsSpecial(const double d)
Returns if the input pixel is special.
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149
Namespace for the standard library.