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#include <QPageSize>
32
33#include "Cube.h"
34#include "CubePlotCurve.h"
35#include "CubePlotCurveConfigureDialog.h" //
36#include "CubeViewport.h"
37#include "FileName.h"
38#include "Interpolator.h"
39#include "MainWindow.h"
40#include "MdiCubeViewport.h"
41#include "PlotWindowBestFitDialog.h"
42#include "Pvl.h"
43#include "PvlGroup.h"
44#include "PvlKeyword.h"
45#include "QHistogram.h"
46#include "Stretch.h"
47#include "TableMainWindow.h"
48
49
50using namespace std;
51
52namespace Isis {
66 PlotWindow::PlotWindow(QString title, PlotCurve::Units xAxisUnits,
67 PlotCurve::Units yAxisUnits, QWidget *parent,
68 MenuOptions optionsToProvide) :
69 MainWindow(title, parent) {
70
71 m_toolBar = NULL;
72 m_menubar = NULL;
73 m_tableWindow = NULL;
74 m_pasteAct = NULL;
76 m_autoscaleAxes = true;
77
78 setObjectName("Plot Window: " + title);
79
80 m_parent = parent;
83
84 if (!m_parent) {
85 IString msg = "PlotWindow cannot be instantiated with a NULL parent";
86 throw IException(IException::Programmer, msg, _FILEINFO_);
87 }
88
89 installEventFilter(this);
90 setAcceptDrops(true);
91
92 createWidgets(optionsToProvide);
93 setWindowTitle(title);
94
95 setPlotBackground(Qt::black);
96
97 connect(QGuiApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)),
98 this, SLOT(onClipboardChanged()));
99 connect(this, SIGNAL(plotChanged()),
100 this, SLOT(scheduleFillTable()));
101 connect(this, SIGNAL(requestFillTable()),
102 this, SLOT(fillTable()), Qt::QueuedConnection);
103
104 QMap<PlotCurve::Units, QString> unitLabels;
105 unitLabels.insert(PlotCurve::Band, "Band");
106 unitLabels.insert(PlotCurve::Percentage, "Percentage");
107 unitLabels.insert(PlotCurve::PixelNumber, "Pixel Number");
108 unitLabels.insert(PlotCurve::CubeDN, "Pixel Value");
109 unitLabels.insert(PlotCurve::Elevation, "Elevation");
110 unitLabels.insert(PlotCurve::Meters, "Meters");
111 unitLabels.insert(PlotCurve::Kilometers, "Kilometers");
112 unitLabels.insert(PlotCurve::Wavelength, "Wavelength");
113
114 plot()->setAxisTitle(QwtPlot::xBottom, unitLabels[xAxisUnits]);
115 plot()->setAxisTitle(QwtPlot::yLeft, unitLabels[yAxisUnits]);
116 setPlotTitle(title);
117
119
120 readSettings();
121
122#ifdef __APPLE__
123 setWindowFlags(Qt::Tool);
124#else
125 setWindowFlags(Qt::Dialog);
126#endif
127 }
128
129
130
131 PlotWindow::~PlotWindow() {
132 foreach (QwtPlotCurve *curve, plotCurves()) {
133 delete curve;
134 }
135 }
136
137
145 void PlotWindow::createWidgets(MenuOptions optionsToProvide) {
146 /*Create plot*/
147 m_plot = new QwtPlot();
148 m_plot->installEventFilter(this);
149 m_plot->setAxisMaxMinor(QwtPlot::yLeft, 5);
150 m_plot->setAxisMaxMajor(QwtPlot::xBottom, 30);
151 m_plot->setAxisMaxMinor(QwtPlot::xBottom, 5);
152 m_plot->setAxisLabelRotation(QwtPlot::xBottom, 45);
153 m_plot->setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignRight);
154
155 /*Plot Legend*/
156 m_legend = new QwtLegend();
157 m_legend->setDefaultItemMode(QwtLegendData::Clickable);
158 m_legend->setWhatsThis("Right Click on a legend item to display the context "
159 "menu.");
160 m_plot->insertLegend(m_legend, QwtPlot::RightLegend, 1.0);
161 m_legend->installEventFilter(this);
162
163 /*Plot Grid*/
164 m_grid = new QwtPlotGrid;
165 m_grid->enableXMin(true);
166 m_grid->setMajorPen(QPen(Qt::white, 1, Qt::DotLine));
167 m_grid->setMinorPen(QPen(Qt::gray, 1, Qt::DotLine));
168 m_grid->attach(m_plot);
169 m_grid->setVisible(false);
170
171 /*Plot Zoomer*/
172 m_zoomer = new QwtPlotZoomer(m_plot->canvas());
173 m_zoomer->setRubberBandPen(QPen(Qt::lightGray));
174 m_zoomer->setTrackerPen(QPen(Qt::lightGray));
175
176 setCentralWidget(m_plot);
177 setupDefaultMenu(optionsToProvide);
178 }
179
180
186 raise();
187 show();
188 }
190
197 void PlotWindow::update(MdiCubeViewport *activeViewport) {
198 }
199
200
208 void PlotWindow::setAxisLabel(int axisId, QString title) {
209 m_plot->setAxisTitle(axisId, title);
210 }
211
212
219 void PlotWindow::setPlotTitle(QString pt) {
220 m_plot->setTitle(pt);
221 }
222
223
231 void PlotWindow::setUserCanAddCurves(bool userHasControl) {
232 m_allowUserToAddCurves = userHasControl;
233 }
234
241 QString PlotWindow::plotTitle() const {
242 return m_plot->title().text();
243 }
244
245
256 }
257
258
269
270
281
282
290 m_plot->setCanvasBackground(c);
291 }
292
293
305 bool PlotWindow::canAdd(CubePlotCurve *curveToTest) const {
306 return (curveToTest->xUnits() == m_xAxisUnits &&
307 curveToTest->yUnits() == m_yAxisUnits);
308 }
309
310
318 return m_plot->canvasBackground().color();
319 }
320
321
328 QList<CubePlotCurve *> PlotWindow::plotCurves() {
329 QList<CubePlotCurve *> foundCurves;
330
331 const QwtPlotItemList &plotItems = m_plot->itemList();
332
333 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
334 QwtPlotItem *item = plotItems[itemIndex];
335
336 if (item->rtti() == QwtPlotItem::Rtti_PlotCurve) {
337 CubePlotCurve *curve = dynamic_cast<CubePlotCurve *>(item);
338
339 if (curve && curve->color().alpha() != 0)
340 foundCurves.append(curve);
341 }
342 }
343
344 return foundCurves;
345 }
346
347
354 QList<const CubePlotCurve *> PlotWindow::plotCurves() const {
355 QList<const CubePlotCurve *> foundCurves;
356
357 const QwtPlotItemList &plotItems = m_plot->itemList();
358
359 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
360 const QwtPlotItem *item = plotItems[itemIndex];
361
362 if (item->rtti() == QwtPlotItem::Rtti_PlotCurve) {
363 const CubePlotCurve *curve = dynamic_cast<const CubePlotCurve *>(item);
364
365 if (curve)
366 foundCurves.append(curve);
367 }
368 }
369
370 return foundCurves;
371 }
372
373
381 QList<QwtPlotSpectrogram *> PlotWindow::plotSpectrograms() {
382 QList<QwtPlotSpectrogram *> foundSpectrograms;
383
384 const QwtPlotItemList &plotItems = m_plot->itemList();
385
386 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
387 QwtPlotItem *item = plotItems[itemIndex];
388
389 if (item->rtti() == QwtPlotItem::Rtti_PlotSpectrogram) {
390 QwtPlotSpectrogram *spectrogram =
391 dynamic_cast<QwtPlotSpectrogram *>(item);
392
393 if (spectrogram)
394 foundSpectrograms.append(spectrogram);
395 }
396 }
397
398 return foundSpectrograms;
399 }
400
401
409 QList<const QwtPlotSpectrogram *> PlotWindow::plotSpectrograms() const {
410 QList<const QwtPlotSpectrogram *> foundSpectrograms;
411
412 const QwtPlotItemList &plotItems = m_plot->itemList();
413
414 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
415 const QwtPlotItem *item = plotItems[itemIndex];
416
417 if (item->rtti() == QwtPlotItem::Rtti_PlotSpectrogram) {
418 const QwtPlotSpectrogram *spectrogram =
419 dynamic_cast<const QwtPlotSpectrogram *>(item);
420
421 if (spectrogram)
422 foundSpectrograms.append(spectrogram);
423 }
424 }
425
426 return foundSpectrograms;
427 }
428
429
437 if (!canAdd(pc)) {
438 QMessageBox::warning(NULL, "Failed to add plot curve",
439 "Can not add plot curves with x/y units that do not match the plot's "
440 "x/y units");
441 }
442 else {
443 QString curveTitle = pc->title().text();
444
445 bool titleAccepted = false;
446 int titleTryCount = 0;
447 while (!titleAccepted) {
448 if (titleTryCount > 0) {
449 curveTitle = pc->title().text() + " (" +
450 QString::number(titleTryCount + 1) + ")";
451 }
452
453 titleTryCount++;
454 titleAccepted = true;
455
456 const QwtPlotItemList &plotItems = m_plot->itemList();
457
458 for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex ++) {
459 QwtPlotItem *item = plotItems[itemIndex];
460
461 if (item->title().text() == curveTitle)
462 titleAccepted = false;
463 }
464 }
465
466 pc->setTitle(curveTitle);
467 pc->attach(m_plot);
468 pc->attachMarkers();
469 fillTable();
470
472
473 connect(pc, SIGNAL(needsRepaint()),
474 this, SIGNAL(plotChanged()));
475 connect(pc, SIGNAL(destroyed(QObject *)),
476 this, SLOT(resetScale()));
477
478 // Get the legend widget for the recently attached plotcurve and give to the plotcurve
479 QWidget *legendWidget = m_legend->legendWidget( plot()->itemToInfo(pc) );
480 pc->updateLegendItemWidget(legendWidget);
481
482 replot();
483 }
484 }
485
486
494
495 /*Table Stuff if table is open*/
496 if (m_tableWindow != NULL && m_tableWindow->isVisible()) {
497 m_tableWindow->table()->setColumnCount(1);
498 m_tableWindow->table()->setRowCount(0);
499// deleteFromTable();
500 }
501 }
502
503
509 // make sure that there are CubePlotCurves to configure
510 QList<CubePlotCurve *> curves = plotCurves();
511 // can't configure 0 curves - menu item is deactivated
512 if (curves.size() < 1) {
513 return;
514 }
515 CubePlotCurve *curve = curves.first();
516 CubePlotCurveConfigureDialog *configDialog = new CubePlotCurveConfigureDialog(curve, this);
517 configDialog->exec();
518
519 emit plotChanged();
520 }
521
522
531 dialog->show();
532 }
533
534
541 const QwtPlotItemList &plotItems = m_plot->itemList();
542
543 for (int itemIndex = plotItems.size()- 1; itemIndex >= 0; itemIndex --) {
544 QwtPlotItem *item = plotItems[itemIndex];
545
546 if (item->rtti() == QwtPlotItem::Rtti_PlotCurve ||
547 item->rtti() == QwtPlotItem::Rtti_PlotHistogram) {
548 delete item;
549 }
550 }
551
552 replot();
553 }
554
555
561 if (m_zoomer->trackerMode() == QwtPicker::ActiveOnly) {
562 m_zoomer->setTrackerMode(QwtPicker::AlwaysOn);
563 }
564 else {
565 m_zoomer->setTrackerMode(QwtPicker::ActiveOnly);
566 }
567 }
568
569
574 QPixmap pixmap;
575 /* Initialize a printer*/
576 static QPrinter *printer = NULL;
577 if (printer == NULL) printer = new QPrinter;
578 QPageSize pageSize(QPageSize::Letter);
579 printer->setPageSize(pageSize);
580 printer->setColorMode(QPrinter::Color);
581
582 QPrintDialog printDialog(printer, (QWidget *)parent());
583
584 if (printDialog.exec() == QDialog::Accepted) {
585 /* Get display widget as a pixmap and convert to an image*/
586 pixmap = m_plot->grab();
587 QImage img = pixmap.toImage();
588 /* C++ Gui Programming with Qt, page 201*/
589 QPainter painter(printer);
590 QRect rect = painter.viewport();
591 QSize size = img.size();
592 size.scale(rect.size(), Qt::KeepAspectRatio);
593 painter.setViewport(rect.x(), rect.y(),
594 size.width(), size.height());
595 painter.setWindow(img.rect());
596 painter.drawImage(0, 0, img);
597 }
598
599 }
600
601
607 QPixmap pixmap;
608 QString output =
609 QFileDialog::getSaveFileName((QWidget *)parent(),
610 "Choose output file",
611 "./",
612 QString("Images (*.png *.jpg *.tif)"));
613 if (output.isEmpty()) return;
614 //Make sure the filename is valid
615 if (!output.isEmpty()) {
616 if (!output.endsWith(".png") && !output.endsWith(".jpg") && !output.endsWith(".tif")) {
617 output = output + ".png";
618 }
619 }
620
621 QString format = QFileInfo(output).suffix();
622 pixmap = m_plot->grab();
623
624 std::string formatString = format.toStdString();
625 if (!pixmap.save(output, formatString.c_str())) {
626 QMessageBox::information((QWidget *)parent(), "Error", "Unable to save " + output);
627 return;
628 }
629 }
630
631
637 QPen *pen = new QPen(Qt::white);
638
639 if (m_plot->canvasBackground() == Qt::white) {
640 m_plot->setCanvasBackground(Qt::black);
641 m_grid->setMajorPen(QPen(Qt::white, 1, Qt::DotLine));
642 }
643 else {
644 m_plot->setCanvasBackground(Qt::white);
645 pen->setColor(Qt::black);
646 m_grid->setMajorPen(QPen(Qt::black, 1, Qt::DotLine));
647 }
648
649 m_zoomer->setRubberBandPen(*pen);
650 m_zoomer->setTrackerPen(*pen);
651 pen->setWidth(2);
652 /*Replot with the new background and pen colors*/
653 m_plot->replot();
654 }
655
656
662 m_zoomer->zoom(0);
663
664 if (m_autoscaleAxes) {
666 m_plot->setAxisAutoScale(QwtPlot::xBottom);
667 }
668 else {
669 QPair<double, double> calculatedXRange = findDataRange(
670 QwtPlot::xBottom);
671 m_plot->setAxisScale(QwtPlot::xBottom, calculatedXRange.first,
672 calculatedXRange.second);
673 }
674
676 m_plot->setAxisAutoScale(QwtPlot::yLeft);
677 }
678 else {
679 QPair<double, double> calculatedYRange = findDataRange(
680 QwtPlot::yLeft);
681 m_plot->setAxisScale(QwtPlot::yLeft, calculatedYRange.first,
682 calculatedYRange.second);
683 }
684 }
685
686 m_zoomer->setZoomBase();
687 m_plot->replot();
688 }
689
690
696 if (m_xLogCheckBox->isChecked()) {
697 m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine);
698 m_plotXLogScale = true;
699 }
700 else {
701 m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
702 m_plotXLogScale = false;
703 }
704
705 if (m_yLogCheckBox->isChecked()) {
706 m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine);
707 m_plotYLogScale = true;
708 }
709 else {
710 m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
711 m_plotYLogScale = false;
712 }
713
715
716 if (!m_autoscaleAxes) {
717 double xMin = m_xMinEdit->text().toDouble();
718 double xMax = m_xMaxEdit->text().toDouble();
719 // QwtScaleDiv xAxisScale =
720 // m_plot->axisScaleEngine(QwtPlot::xBottom)->divideScale(xMin, xMax,
721 // 25, 100);
722 // m_plot->setAxisScaleDiv(QwtPlot::xBottom, xAxisScale);
723 m_plot->setAxisScale(QwtPlot::xBottom, xMin, xMax);
724
725 double yMin = m_yMinEdit->text().toDouble();
726 double yMax = m_yMaxEdit->text().toDouble();
727 // QwtScaleDiv yAxisScale =
728 // m_plot->axisScaleEngine(QwtPlot::yLeft)->divideScale(yMin, yMax,
729 // 25, 100);
730 // m_plot->setAxisScaleDiv(QwtPlot::yLeft, yAxisScale);
731 m_plot->setAxisScale(QwtPlot::yLeft, yMin, yMax);
732
733 m_zoomer->setZoomBase();
734 }
735
736 replot();
737 }
738
739
745 QDialog *dialog = new QDialog(this);
746 dialog->setWindowTitle("Set Display Range");
747
748 QGridLayout *dialogLayout = new QGridLayout;
749
750 int row = 0;
751
752 QLabel *autoLabel = new QLabel("Auto-Scale: ");
753 dialogLayout->addWidget(autoLabel, row, 0);
754
755 m_autoScaleCheckBox = new QCheckBox("Scale X/Y Axes Automatically");
757 connect(m_autoScaleCheckBox, SIGNAL(stateChanged(int)),
758 this, SLOT(autoScaleCheckboxToggled()));
759 dialogLayout->addWidget(m_autoScaleCheckBox, row, 1);
760 row++;
761
762 QLabel *xLabel = new QLabel("<h3>X-Axis</h3>");
763 dialogLayout->addWidget(xLabel, row, 0, 1, 2);
764 row++;
765
766 QLabel *xMinLabel = new QLabel("Minimum: ");
767 dialogLayout->addWidget(xMinLabel, row, 0);
768
769 double xMin = plot()->axisScaleDiv(QwtPlot::xBottom).lowerBound();
770 m_xMinEdit = new QLineEdit(QString::number(xMin));
771 dialogLayout->addWidget(m_xMinEdit, row, 1);
772 row++;
773
774 QLabel *xMaxLabel = new QLabel("Maximum: ");
775 dialogLayout->addWidget(xMaxLabel, row, 0);
776
777 double xMax = plot()->axisScaleDiv(QwtPlot::xBottom).upperBound();
778 m_xMaxEdit = new QLineEdit(QString::number(xMax));
779 dialogLayout->addWidget(m_xMaxEdit, row, 1);
780 row++;
781
782 QLabel *xLogLabel = new QLabel("Logarithmic Scale");
783 dialogLayout->addWidget(xLogLabel, row, 0);
784
785 m_xLogCheckBox = new QCheckBox;
786 m_xLogCheckBox->setChecked(m_plotXLogScale);
787// m_xLogCheckBox->setChecked(
788// m_plot->axisScaleEngine(QwtPlot::xBottom)->transformation()->type() ==
789// QwtScaleTransformation::Log10);
790 dialogLayout->addWidget(m_xLogCheckBox, row, 1);
791 row++;
792
793 QLabel *yLabel = new QLabel("<h3>Y-Axis</h3>");
794 dialogLayout->addWidget(yLabel, row, 0, 1, 2);
795 row++;
796
797 QLabel *yMinLabel = new QLabel("Minimum: ");
798 dialogLayout->addWidget(yMinLabel, row, 0);
799
800 double yMin = plot()->axisScaleDiv(QwtPlot::yLeft).lowerBound();
801 m_yMinEdit = new QLineEdit(QString::number(yMin));
802 dialogLayout->addWidget(m_yMinEdit, row, 1);
803 row++;
804
805 QLabel *yMaxLabel = new QLabel("Maximum: ");
806 dialogLayout->addWidget(yMaxLabel, row, 0);
807
808 double yMax = plot()->axisScaleDiv(QwtPlot::yLeft).upperBound();
809 m_yMaxEdit = new QLineEdit(QString::number(yMax));
810 dialogLayout->addWidget(m_yMaxEdit, row, 1);
811 row++;
812
813 QLabel *yLogLabel = new QLabel("Logarithmic Scale");
814 dialogLayout->addWidget(yLogLabel, row, 0);
815
816 m_yLogCheckBox = new QCheckBox;
817 m_yLogCheckBox->setChecked(m_plotYLogScale);
818// m_yLogCheckBox->setChecked(
819// m_plot->axisScaleEngine(QwtPlot::yLeft)->transformation()->type() ==
820// QwtScaleTransformation::Log10);
821 dialogLayout->addWidget(m_yLogCheckBox, row, 1);
822 row++;
823
824 QHBoxLayout *buttonsLayout = new QHBoxLayout;
825 buttonsLayout->addStretch();
826
827 QPushButton *okButton = new QPushButton("&Ok");
828 okButton->setIcon(QIcon::fromTheme("dialog-ok"));
829 connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept()));
830 connect(dialog, SIGNAL(accepted()), this, SLOT(setUserValues()));
831 okButton->setShortcut(Qt::Key_Enter);
832 buttonsLayout->addWidget(okButton);
833
834 QPushButton *cancelButton = new QPushButton("&Cancel");
835 cancelButton->setIcon(QIcon::fromTheme("dialog-cancel"));
836 connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
837 buttonsLayout->addWidget(cancelButton);
838
839 QWidget *buttonsWrapper = new QWidget;
840 buttonsWrapper->setLayout(buttonsLayout);
841 dialogLayout->addWidget(buttonsWrapper, row, 0, 1, 2);
842 row++;
843
845
846 dialog->setLayout(dialogLayout);
847 dialog->show();
848 }
849
850
856 QDialog *dialog = new QDialog(this);
857 dialog->setWindowTitle("Name Plot Labels");
858
859 QGridLayout *dialogLayout = new QGridLayout;
860
861 int row = 0;
862 QLabel *plotLabel = new QLabel("Plot Title: ");
863 dialogLayout->addWidget(plotLabel, row, 0);
864
865 m_plotTitleText = new QLineEdit(plot()->title().text());
866 dialogLayout->addWidget(m_plotTitleText, row, 1);
867 row++;
868
869 QLabel *xAxisLabel = new QLabel("X-Axis Label: ");
870 dialogLayout->addWidget(xAxisLabel, row, 0);
871
872 m_xAxisText = new QLineEdit(m_plot->axisTitle(QwtPlot::xBottom).text());
873 dialogLayout->addWidget(m_xAxisText, row, 1);
874 row++;
875
876 QLabel *yAxisLabel = new QLabel("Y-Axis Label: ");
877 dialogLayout->addWidget(yAxisLabel, row, 0);
878
879 m_yAxisText = new QLineEdit(m_plot->axisTitle(QwtPlot::yLeft).text());
880 dialogLayout->addWidget(m_yAxisText, row, 1);
881 row++;
882
883 QHBoxLayout *buttonsLayout = new QHBoxLayout;
884 buttonsLayout->addStretch();
885
886 QPushButton *okButton = new QPushButton("&Ok");
887 okButton->setIcon(QIcon::fromTheme("dialog-ok"));
888 connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept()));
889 connect(dialog, SIGNAL(accepted()), this, SLOT(setLabels()));
890 okButton->setShortcut(Qt::Key_Enter);
891 buttonsLayout->addWidget(okButton);
892
893 QPushButton *cancelButton = new QPushButton("&Cancel");
894 cancelButton->setIcon(QIcon::fromTheme("dialog-cancel"));
895 connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
896 buttonsLayout->addWidget(cancelButton);
897
898 QWidget *buttonsWrapper = new QWidget;
899 buttonsWrapper->setLayout(buttonsLayout);
900 dialogLayout->addWidget(buttonsWrapper, row, 0, 1, 2);
901 row++;
902
903 dialog->setLayout(dialogLayout);
904 dialog->show();
905 }
906
907
912 m_plot->setTitle(m_plotTitleText->text());
913 m_plot->setAxisTitle(QwtPlot::xBottom, m_xAxisText->text());
914 m_plot->setAxisTitle(QwtPlot::yLeft, m_yAxisText->text());
915 /*Replot with new labels.*/
916 m_plot->replot();
917 }
918
919
925 m_grid->setVisible(!m_grid->isVisible());
926
927 if (m_grid->isVisible()) {
928 m_showHideGrid->setText("Hide Grid");
929 }
930 else {
931 m_showHideGrid->setText("Show Grid");
932 }
933 m_plot->replot();
934 }
935
936
941 void (QwtPlotItem::*method)();
942 if (m_showHideAllMarkers->text() == "Hide All Symbols") {
943 method = &QwtPlotItem::hide;
944
945 m_showHideAllMarkers->setText("Show All Symbols");
946
947 }
948 else {
949 method = &QwtPlotItem::show;
950
951 m_showHideAllMarkers->setText("Hide All Symbols");
952 }
953
954 for (int i = 0; i < m_plot->itemList().size(); i ++) {
955 QwtPlotItem *plotItem = m_plot->itemList()[i];
956 if (plotItem->rtti() == QwtPlotItem::Rtti_PlotMarker)
957 (plotItem->*method)();
958 }
959 /*Replot with all symbols hidden*/
960 m_plot->replot();
961 }
962
963
969 void (QwtPlotItem::*method)();
970 if (m_showHideAllCurves->text() == "Hide All Curves") {
971 method = &QwtPlotItem::hide;
972
973 m_showHideAllCurves->setText("Show All Curves");
974 m_showHideAllCurves->setIcon(
975 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_showCurves.png").expanded()));
976
977 }
978 else {
979 method = &QwtPlotItem::show;
980
981 m_showHideAllCurves->setText("Hide All Curves");
982 m_showHideAllCurves->setIcon(
983 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_hideCurves.png").expanded()));
984 }
985
986 for (int i = 0; i < m_plot->itemList().size(); i ++) {
987 QwtPlotItem *plotItem = m_plot->itemList()[i];
988 if (plotItem->rtti() == QwtPlotItem::Rtti_PlotCurve)
989 (plotItem->*method)();
990 }
991 /*Replot with all curves hidden*/
992 m_plot->replot();
993 }
994
995
1001 QDialog *d = new QDialog(m_plot);
1002 d->setWindowTitle("Basic Help");
1003
1004 QLabel *zoomLabel = new QLabel("<U>Zoom Options:</U>");
1005 QLabel *zoomIn = new
1006 QLabel(" <b>Left click</b> on the mouse, drag, and release to select an area to zoom in on");
1007 QLabel *zoomOut = new
1008 QLabel(" <b>Middle click</b> on the mouse to zoom out one level");
1009 QLabel *zoomReset = new
1010 QLabel(" <b>Right click</b> on the mouse and select <I>Reset Scale</I> to clear the zoom and return to the original plot");
1011
1012 QLabel *curveConfigLabel = new QLabel("<br><U>Curve Configuration:</U>");
1013 QLabel *configDirections = new
1014 QLabel(" <b>To configure the curve properties</b> Right click on the legend and select <I>Configure</I> from <br> the menu"
1015 " or click on the configure icon in the tool bar.");
1016 QLabel *config = new QLabel();
1017 config->setPixmap(QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_configure.png").expanded()));
1018
1019 QLabel *tableLabel = new QLabel("<br><U>Table Options:</U>");
1020 QLabel *tableDirections = new
1021 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.");
1022 QLabel *table = new QLabel();
1023 table->setPixmap(QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_table.png").expanded()));
1024
1025 QVBoxLayout *layout = new QVBoxLayout();
1026 layout->addWidget(zoomLabel);
1027 layout->addWidget(zoomIn);
1028 layout->addWidget(zoomOut);
1029 layout->addWidget(zoomReset);
1030 layout->addWidget(curveConfigLabel);
1031 layout->addWidget(config);
1032 layout->addWidget(configDirections);
1033 layout->addWidget(tableLabel);
1034 layout->addWidget(table);
1035 layout->addWidget(tableDirections);
1036
1037 d->setLayout(layout);
1038 d->show();
1039 }
1040
1041
1050 QList<QMenu *> menu;
1051 QList<QAction *> actions;
1052
1053 QMenu *fileMenu = new QMenu("&File");
1054 QMenu *editMenu = new QMenu("&Edit");
1055 QMenu *optionsMenu = new QMenu("&Options");
1056 QMenu *helpMenu = new QMenu("&Help");
1057
1058 if ((optionsToProvide & SaveMenuOption) == SaveMenuOption) {
1059 QAction *save = new QAction(m_plot);
1060 save->setText("&Save Plot As");
1061 save->setIcon(QIcon::fromTheme("document-save-as"));
1062 QString text =
1063 "<b>Function:</b> Save the plot as a png, jpg, or tif file.";
1064 save->setWhatsThis(text);
1065 connect(save, SIGNAL(triggered()), this, SLOT(savePlot()));
1066 fileMenu->addAction(save);
1067 actions.push_back(save);
1068 }
1069
1070 if ((optionsToProvide & PrintMenuOption) == PrintMenuOption) {
1071 QAction *prt = new QAction(m_plot);
1072 prt->setText("&Print Plot");
1073 prt->setIcon(QIcon::fromTheme("document-print"));
1074 QString text =
1075 "<b>Function:</b> Sends the plot image to the printer";
1076 prt->setWhatsThis(text);
1077 connect(prt, SIGNAL(triggered()), this, SLOT(printPlot()));
1078 fileMenu->addAction(prt);
1079 actions.push_back(prt);
1080 }
1081
1082 if ((optionsToProvide & ShowTableMenuOption) == ShowTableMenuOption) {
1083 QAction *table = new QAction(m_plot);
1084 table->setText("Show Table");
1085 table->setIcon(
1086 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_table.png").expanded()));
1087 QString text =
1088 "<b>Function:</b> Activates the table which displays the data of the "
1089 "current plot";
1090 table->setWhatsThis(text);
1091 connect(table, SIGNAL(triggered()), this, SLOT(showTable()));
1092 fileMenu->addAction(table);
1093 actions.push_back(table);
1094 }
1095
1096 QAction *close = new QAction(QIcon::fromTheme("document-close"), "&Close",
1097 m_plot);
1098 connect(close, SIGNAL(triggered()), this, SLOT(close()));
1099 fileMenu->addAction(close);
1100
1101 if ((optionsToProvide & TrackMenuOption) == TrackMenuOption) {
1102 QAction *track = new QAction(m_plot);
1103 track->setText("Show Mouse &Tracking");
1104 track->setIcon(
1105 QPixmap(FileName("$ISISROOT/appdata/images/icons/goto.png").expanded()));
1106 track->setCheckable(true);
1107 QString text =
1108 "<b>Function:</b> Displays the x,y coordinates as the cursor moves "
1109 "around on the plot.";
1110 track->setWhatsThis(text);
1111 connect(track, SIGNAL(triggered()), this, SLOT(trackerEnabled()));
1112 optionsMenu->addAction(track);
1113 }
1114
1115 if ((optionsToProvide & BackgroundSwitchMenuOption) ==
1117 QAction *backgrdSwitch = new QAction(m_plot);
1118 backgrdSwitch->setText("White/Black &Background");
1119 backgrdSwitch->setIcon(
1120 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_switchBackgrd.png").expanded()));
1121 QString text =
1122 "<b>Function:</b> Switch the background color between black and "
1123 "white.";
1124 backgrdSwitch->setWhatsThis(text);
1125 connect(backgrdSwitch, SIGNAL(triggered()),
1126 this, SLOT(switchBackground()));
1127 optionsMenu->addAction(backgrdSwitch);
1128 actions.push_back(backgrdSwitch);
1129 }
1130
1131 if ((optionsToProvide & ShowHideGridMenuOption) == ShowHideGridMenuOption) {
1133 m_showHideGrid->setText("Show Grid");
1134 m_showHideGrid->setIcon(
1135 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_grid.png").expanded()));
1136 QString text =
1137 "<b>Function:</b> Display grid lines on the plot.";
1138 m_showHideGrid->setWhatsThis(text);
1139 connect(m_showHideGrid, SIGNAL(triggered()), this, SLOT(showHideGrid()));
1140 optionsMenu->addAction(m_showHideGrid);
1141 actions.push_back(m_showHideGrid);
1142 }
1143
1144 if ((optionsToProvide & RenameLabelsMenuOption) == RenameLabelsMenuOption) {
1145 QAction *changeLabels = new QAction(m_plot);
1146 changeLabels->setText("Rename Plot &Labels");
1147 changeLabels->setIcon(
1148 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_renameLabels.png").expanded()));
1149 QString text =
1150 "<b>Function:</b> Edit the plot title, x and y axis labels.";
1151 changeLabels->setWhatsThis(text);
1152 connect(changeLabels, SIGNAL(triggered()),
1153 this, SLOT(changePlotLabels()));
1154 optionsMenu->addAction(changeLabels);
1155 actions.push_back(changeLabels);
1156 }
1157
1158 if ((optionsToProvide & SetDisplayRangeMenuOption) ==
1160 QAction *changeScale = new QAction(m_plot);
1161 changeScale->setText("Set &Display Range");
1162 changeScale->setIcon(
1163 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_setScale.png").expanded()));
1164 QString text =
1165 "<b>Function:</b> Adjust the scale for the x and y axis on the "
1166 "plot.";
1167 changeScale->setWhatsThis(text);
1168 connect(changeScale, SIGNAL(triggered()), this, SLOT(setDefaultRange()));
1169 optionsMenu->addAction(changeScale);
1170 actions.push_back(changeScale);
1171 }
1172
1173 if ((optionsToProvide & ShowHideCurvesMenuOption) ==
1176 m_showHideAllCurves->setText("Hide All Curves");
1177 m_showHideAllCurves->setIcon(
1178 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_showCurves.png").expanded()));
1179 QString text =
1180 "<b>Function:</b> Displays or hides all the curves currently "
1181 "displayed on the plot.";
1182 m_showHideAllCurves->setWhatsThis(text);
1183 connect(m_showHideAllCurves, SIGNAL(triggered()),
1184 this, SLOT(showHideAllCurves()));
1185 optionsMenu->addAction(m_showHideAllCurves);
1186 actions.push_back(m_showHideAllCurves);
1187 }
1188
1189 if ((optionsToProvide & ShowHideMarkersMenuOption) ==
1192 m_showHideAllMarkers->setText("Hide All Symbols");
1193 m_showHideAllMarkers->setIcon(
1194 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_markers.png").expanded()));
1195 QString text = "<b>Function:</b> Displays or hides a symbol for each "
1196 "data point plotted on a plot.";
1197 m_showHideAllMarkers->setWhatsThis(text);
1198 connect(m_showHideAllMarkers, SIGNAL(triggered()),
1199 this, SLOT(showHideAllMarkers()));
1200 optionsMenu->addAction(m_showHideAllMarkers);
1201 actions.push_back(m_showHideAllMarkers);
1202 }
1203
1204 if ((optionsToProvide & ResetScaleMenuOption) == ResetScaleMenuOption) {
1205 QAction *resetScaleButton = new QAction(m_plot);
1206 resetScaleButton->setText("Reset Scale");
1207 resetScaleButton->setIcon(
1208 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_resetscale.png").expanded()));
1209 QString text =
1210 "<b>Function:</b> Reset the plot's scale.";
1211 resetScaleButton->setWhatsThis(text);
1212 connect(resetScaleButton, SIGNAL(triggered()), this, SLOT(resetScale()));
1213 actions.push_back(resetScaleButton);
1214 }
1215
1216 if ((optionsToProvide & ClearPlotMenuOption) == ClearPlotMenuOption) {
1217 QAction *clear = new QAction(m_plot);
1218 clear->setText("Clear Plot");
1219 clear->setIcon(
1220 QPixmap(FileName("$ISISROOT/appdata/images/icons/plot_clear.png").expanded()));
1221 QString text =
1222 "<b>Function:</b> Removes all the curves from the plot.";
1223 clear->setWhatsThis(text);
1224 connect(clear, SIGNAL(triggered()), this, SLOT(clearPlot()));
1225 actions.push_back(clear);
1226 }
1227
1228 if ((optionsToProvide & LineFitMenuOption) == LineFitMenuOption) {
1229 QAction *lineFit = new QAction(m_plot);
1230 lineFit->setText("Create Best Fit Line");
1231 lineFit->setIcon(
1232 QPixmap(FileName("$ISISROOT/appdata/images/icons/linefit.png").expanded()));
1233 QString text = "<b>Function:</b> Calculates a best fit line from an "
1234 "existing curve.";
1235 lineFit->setWhatsThis(text);
1236 connect(lineFit, SIGNAL(triggered()), this, SLOT( createBestFitLine() ) );
1237 optionsMenu->addAction(lineFit);
1238 actions.push_back(lineFit);
1239 }
1240
1241 if ((optionsToProvide & ConfigurePlotMenuOption) == ConfigurePlotMenuOption) {
1242 QAction *configurePlot = new QAction(m_plot);
1243 configurePlot->setText("Configure Plot");
1244 configurePlot->setIcon(
1245 QPixmap( FileName("$ISISROOT/appdata/images/icons/plot_configure.png").expanded() ) );
1246 QString text = "<b>Function:</b> Change the name, color, style, and vertex symbol of the "
1247 "curves.";
1248 configurePlot->setWhatsThis(text);
1249 connect( configurePlot, SIGNAL( triggered() ),
1250 this, SLOT( configurePlotCurves() ) );
1251 optionsMenu->addAction(configurePlot);
1252 actions.push_back(configurePlot);
1253 }
1254
1255 QAction *basicHelp = new QAction(m_plot);
1256 basicHelp->setText("Basic Help");
1257 QString text = "<b>Function:</b> Provides a basic overview on using components "
1258 "of the qview plot window";
1259 basicHelp->setWhatsThis(text);
1260 connect( basicHelp, SIGNAL( triggered() ),
1261 this, SLOT( showHelp() ) );
1262 helpMenu->addAction(basicHelp);
1263
1264 /*setup menus*/
1265 m_pasteAct = new QAction(QIcon::fromTheme("edit-paste"),
1266 "&Paste Curve", m_plot);
1267 m_pasteAct->setEnabled(false);
1268 m_pasteAct->setShortcut(Qt::CTRL | Qt::Key_V);
1269 connect(m_pasteAct, SIGNAL(triggered()),
1270 this, SLOT(pasteCurve()));
1271 editMenu->addAction(m_pasteAct);
1272
1273 menu.push_back(fileMenu);
1274 menu.push_back(editMenu);
1275
1276 if (optionsMenu->actions().size()) {
1277 menu.push_back(optionsMenu);
1278 }
1279 else {
1280 delete optionsMenu;
1281 optionsMenu = NULL;
1282 }
1283
1284 if (helpMenu->actions().size()) {
1285 menu.push_back(helpMenu);
1286 }
1287 else {
1288 delete helpMenu;
1289 helpMenu = NULL;
1290 }
1291
1292 setMenus(menu, actions);
1293 }
1294
1295
1307 bool PlotWindow::userCanAddCurve(const QMimeData *curve) {
1308 bool userCanAdd = false;
1309
1311 curve->hasFormat("application/isis3-plot-curve")) {
1312
1313 CubePlotCurve * testCurve = new CubePlotCurve(
1314 curve->data("application/isis3-plot-curve"));
1315
1316 userCanAdd = canAdd(testCurve);
1317 }
1318
1319 return userCanAdd;
1320 }
1321
1322
1332 if (m_showHideAllCurves) {
1333 if (m_showHideAllCurves->text() == "Hide All Curves") {
1334 curve->show();
1335 }
1336 else {
1337 curve->hide();
1338 }
1339
1340 if (m_showHideAllMarkers->text() == "Hide All Symbols") {
1341 curve->setMarkerVisible(true);
1342 }
1343 else {
1344 curve->setMarkerVisible(false);
1345 }
1346 }
1347
1348 emit plotChanged();
1349 }
1350
1351
1359 void PlotWindow::setMenus(QList<QMenu *> menu, QList<QAction *> actions) {
1360 if (m_toolBar == NULL) {
1361 m_toolBar = new QToolBar(this);
1362 m_toolBar->setObjectName("PlotWindow");
1363 m_toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea | Qt::TopToolBarArea);
1364 addToolBar(Qt::TopToolBarArea, m_toolBar);
1365 }
1366 else {
1367 m_toolBar->clear();
1368 }
1369
1370 m_menubar = menuBar();
1371 m_menubar->clear();
1372
1373 for (int i = 0; i < menu.size(); i++) {
1374 m_menubar->addMenu(menu[i]);
1375 }
1376
1377 for (int i = 0; i < actions.size(); i++) {
1378 m_toolBar->addAction(actions[i]);
1379 }
1380
1381 }
1382
1383
1389 QwtPlotZoomer *PlotWindow::zoomer() {
1390 return m_zoomer;
1391 }
1392
1393
1401 if (!m_scheduledFillTable) {
1402 m_scheduledFillTable = true;
1403 emit requestFillTable();
1404 }
1405 }
1406
1407
1413 m_scheduledFillTable = false;
1414
1415 if (m_tableWindow == NULL) return;
1416 m_tableWindow->listWidget()->clear();
1417 m_tableWindow->table()->clear();
1418 m_tableWindow->table()->setRowCount(0);
1419 m_tableWindow->table()->setColumnCount(0);
1420
1422 m_plot->axisTitle(QwtPlot::xBottom).text(),
1423 m_plot->axisTitle(QwtPlot::xBottom).text());
1424
1425 QList<CubePlotCurve *> curves = plotCurves();
1426 foreach (CubePlotCurve *curve, curves) {
1428 curve->title().text(),
1429 curve->title().text());
1430 }
1431
1432 // We really need all of the x-values associated with the curves,
1433 // but qwt doesn't seem to want to give this to us. It'll give us the
1434 // axis scale, but that isn't quite what we want (especially when zooming)
1435 // So let's find the list of x-points ourselves.
1436 //
1437 // This is what I tried and it did NOT work:
1438 // QwtScaleDiv *xAxisScaleDiv = m_plot->axisScaleDiv(QwtPlot::xBottom);
1439 // QList<double> xAxisPoints = xAxisScaleDiv->ticks(QwtScaleDiv::MajorTick);
1440 //
1441 // We're going to keep xAxisPoints in standard text sort order until we're done populating it,
1442 // then we'll re-sort numerically. That enables us to effectively use binary searches and
1443 // insertion sort-like capabilities for speed.
1444 QList<QString> xAxisPoints;
1445
1446 QProgressDialog progress(tr("Re-calculating Table"), tr(""), 0, 1000, this);
1447 double percentPerCurve = 0.5 * 1.0 / curves.count();
1448
1449 for (int curveIndex = 0; curveIndex < curves.count(); curveIndex++) {
1450 progress.setValue(qRound(curveIndex * percentPerCurve * 1000.0));
1451
1452 CubePlotCurve *curve = curves[curveIndex];
1453
1454 double percentPerDataIndex = (1.0 / curve->data()->size()) * percentPerCurve;
1455
1456 // Loop backwards because our insertion sort will have a much better
1457 // chance of success on it's first try this way.
1458 for (int dataIndex = (int)curve->data()->size() - 1;
1459 dataIndex >= 0;
1460 dataIndex--) {
1461 double xValue = curve->data()->sample(dataIndex).x();
1462 QString xValueString = toString(xValue);
1463
1464 int inverseDataIndex = (curve->data()->size() - 1) - dataIndex;
1465 progress.setValue(
1466 qRound( ((curveIndex * percentPerCurve) +
1467 (inverseDataIndex * percentPerDataIndex)) * 1000.0));
1468
1469
1471 std::lower_bound(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 sort(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.