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