USGS

Isis 3.0 Object Programmers' Reference

Home

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 <QIcon>
16 #include <QMap>
17 #include <QSet>
18 
19 #include "Cube.h"
20 #include "CubePlotCurve.h"
21 #include "CubePlotCurveConfigureDialog.h" //
22 #include "CubeViewport.h"
23 #include "FileName.h"
24 #include "Interpolator.h"
25 #include "MainWindow.h"
26 #include "MdiCubeViewport.h"
27 #include "PlotWindowBestFitDialog.h"
28 #include "Pvl.h"
29 #include "PvlGroup.h"
30 #include "PvlKeyword.h"
31 #include "QHistogram.h"
32 #include "Stretch.h"
33 #include "TableMainWindow.h"
34 
35 
36 using namespace std;
37 
38 namespace Isis {
52  PlotWindow::PlotWindow(QString title, PlotCurve::Units xAxisUnits,
53  PlotCurve::Units yAxisUnits, QWidget *parent,
54  MenuOptions optionsToProvide) :
55  MainWindow(title, parent) {
56 
57  m_toolBar = NULL;
58  m_menubar = NULL;
59  m_tableWindow = NULL;
60  m_pasteAct = NULL;
62  m_autoscaleAxes = true;
63 
64  setObjectName("Plot Window: " + title);
65 
66  m_parent = parent;
69 
70  if (!m_parent) {
71  IString msg = "PlotWindow cannot be instantiated with a NULL parent";
73  }
74 
75  installEventFilter(this);
76  setAcceptDrops(true);
77 
78  createWidgets(optionsToProvide);
79  setWindowTitle(title);
80 
81  setPlotBackground(Qt::black);
82 
83  connect(QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)),
84  this, SLOT(onClipboardChanged()));
85  connect(this, SIGNAL(plotChanged()),
86  this, SLOT(scheduleFillTable()));
87  connect(this, SIGNAL(requestFillTable()),
88  this, SLOT(fillTable()), Qt::QueuedConnection);
89 
91  unitLabels.insert(PlotCurve::Band, "Band");
92  unitLabels.insert(PlotCurve::Percentage, "Percentage");
93  unitLabels.insert(PlotCurve::PixelNumber, "Pixel Number");
94  unitLabels.insert(PlotCurve::CubeDN, "Pixel Value");
95  unitLabels.insert(PlotCurve::Elevation, "Elevation");
96  unitLabels.insert(PlotCurve::Meters, "Meters");
97  unitLabels.insert(PlotCurve::Kilometers, "Kilometers");
98  unitLabels.insert(PlotCurve::Wavelength, "Wavelength");
99 
100  plot()->setAxisTitle(QwtPlot::xBottom, unitLabels[xAxisUnits]);
101  plot()->setAxisTitle(QwtPlot::yLeft, unitLabels[yAxisUnits]);
102  setPlotTitle(title);
103 
105 
106  readSettings();
107 
108 #ifdef __APPLE__
109  setWindowFlags(Qt::Tool);
110 #else
111  setWindowFlags(Qt::Dialog);
112 #endif
113  }
114 
115 
116 
117  PlotWindow::~PlotWindow() {
118  foreach (QwtPlotCurve *curve, plotCurves()) {
119  delete curve;
120  }
121  }
122 
123 
131  void PlotWindow::createWidgets(MenuOptions optionsToProvide) {
132  /*Create plot*/
133  m_plot = new QwtPlot();
134  m_plot->installEventFilter(this);
135  m_plot->setAxisMaxMinor(QwtPlot::yLeft, 5);
136  m_plot->setAxisMaxMajor(QwtPlot::xBottom, 30);
137  m_plot->setAxisMaxMinor(QwtPlot::xBottom, 5);
138  m_plot->setAxisLabelRotation(QwtPlot::xBottom, 45);
139  m_plot->setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignRight);
140 
141  /*Plot Legend*/
142  QwtLegend *legend = new QwtLegend();
143  legend->setItemMode(QwtLegend::ClickableItem);
144  legend->setWhatsThis("Right Click on a legend item to display the context "
145  "menu.");
146  m_plot->insertLegend(legend, QwtPlot::RightLegend, 1.0);
147  legend->installEventFilter(this);
148 
149  /*Plot Grid*/
150  m_grid = new QwtPlotGrid;
151  m_grid->enableXMin(true);
152  m_grid->setMajPen(QPen(Qt::white, 1, Qt::DotLine));
153  m_grid->setMinPen(QPen(Qt::gray, 1, Qt::DotLine));
154  m_grid->attach(m_plot);
155  m_grid->setVisible(false);
156 
157  /*Plot Zoomer*/
158  m_zoomer = new QwtPlotZoomer(m_plot->canvas());
159  m_zoomer->setRubberBandPen(QPen(Qt::lightGray));
160  m_zoomer->setTrackerPen(QPen(Qt::lightGray));
161 
162  setCentralWidget(m_plot);
163  setupDefaultMenu(optionsToProvide);
164  }
165 
166 
172  raise();
173  show();
174  }
175 
176 
183  void PlotWindow::update(MdiCubeViewport *activeViewport) {
184  }
185 
186 
194  void PlotWindow::setAxisLabel(int axisId, QString title) {
195  m_plot->setAxisTitle(axisId, title);
196  }
197 
198 
205  void PlotWindow::setPlotTitle(QString pt) {
206  m_plot->setTitle(pt);
207  }
208 
209 
217  void PlotWindow::setUserCanAddCurves(bool userHasControl) {
218  m_allowUserToAddCurves = userHasControl;
219  }
220 
227  QString PlotWindow::plotTitle() const {
228  return m_plot->title().text();
229  }
230 
231 
241  return m_allowUserToAddCurves;
242  }
243 
244 
253  return m_xAxisUnits;
254  }
255 
256 
265  return m_yAxisUnits;
266  }
267 
268 
276  m_plot->setCanvasBackground(c);
277  }
278 
279 
291  bool PlotWindow::canAdd(CubePlotCurve *curveToTest) const {
292  return (curveToTest->xUnits() == m_xAxisUnits &&
293  curveToTest->yUnits() == m_yAxisUnits);
294  }
295 
296 
304  return m_plot->canvasBackground().color();
305  }
306 
307 
315  QList<CubePlotCurve *> foundCurves;
316 
317  const QwtPlotItemList &plotItems = m_plot->itemList();
318 
319  for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
320  QwtPlotItem *item = plotItems[itemIndex];
321 
322  if (item->rtti() == QwtPlotItem::Rtti_PlotCurve) {
323  CubePlotCurve *curve = dynamic_cast<CubePlotCurve *>(item);
324 
325  if (curve && curve->color().alpha() != 0)
326  foundCurves.append(curve);
327  }
328  }
329 
330  return foundCurves;
331  }
332 
333 
341  QList<const CubePlotCurve *> foundCurves;
342 
343  const QwtPlotItemList &plotItems = m_plot->itemList();
344 
345  for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
346  const QwtPlotItem *item = plotItems[itemIndex];
347 
348  if (item->rtti() == QwtPlotItem::Rtti_PlotCurve) {
349  const CubePlotCurve *curve = dynamic_cast<const CubePlotCurve *>(item);
350 
351  if (curve)
352  foundCurves.append(curve);
353  }
354  }
355 
356  return foundCurves;
357  }
358 
359 
368  QList<QwtPlotSpectrogram *> foundSpectrograms;
369 
370  const QwtPlotItemList &plotItems = m_plot->itemList();
371 
372  for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
373  QwtPlotItem *item = plotItems[itemIndex];
374 
375  if (item->rtti() == QwtPlotItem::Rtti_PlotSpectrogram) {
376  QwtPlotSpectrogram *spectrogram =
377  dynamic_cast<QwtPlotSpectrogram *>(item);
378 
379  if (spectrogram)
380  foundSpectrograms.append(spectrogram);
381  }
382  }
383 
384  return foundSpectrograms;
385  }
386 
387 
396  QList<const QwtPlotSpectrogram *> foundSpectrograms;
397 
398  const QwtPlotItemList &plotItems = m_plot->itemList();
399 
400  for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex++) {
401  const QwtPlotItem *item = plotItems[itemIndex];
402 
403  if (item->rtti() == QwtPlotItem::Rtti_PlotSpectrogram) {
404  const QwtPlotSpectrogram *spectrogram =
405  dynamic_cast<const QwtPlotSpectrogram *>(item);
406 
407  if (spectrogram)
408  foundSpectrograms.append(spectrogram);
409  }
410  }
411 
412  return foundSpectrograms;
413  }
414 
415 
423  if (!canAdd(pc)) {
424  QMessageBox::warning(NULL, "Failed to add plot curve",
425  "Can not add plot curves with x/y units that do not match the plot's "
426  "x/y units");
427  }
428  else {
429  QString curveTitle = pc->title().text();
430 
431  bool titleAccepted = false;
432  int titleTryCount = 0;
433  while (!titleAccepted) {
434  if (titleTryCount > 0) {
435  curveTitle = pc->title().text() + " (" +
436  QString::number(titleTryCount + 1) + ")";
437  }
438 
439  titleTryCount++;
440  titleAccepted = true;
441 
442  const QwtPlotItemList &plotItems = m_plot->itemList();
443 
444  for (int itemIndex = 0; itemIndex < plotItems.size(); itemIndex ++) {
445  QwtPlotItem *item = plotItems[itemIndex];
446 
447  if (item->title().text() == curveTitle)
448  titleAccepted = false;
449  }
450  }
451 
452  pc->setTitle(curveTitle);
453  pc->attach(m_plot);
454  pc->attachMarkers();
455  fillTable();
456 
457  updateVisibility(pc);
458 
459  connect(pc, SIGNAL(needsRepaint()),
460  this, SIGNAL(plotChanged()));
461  connect(pc, SIGNAL(destroyed(QObject *)),
462  this, SLOT(resetScale()));
463 
464  replot();
465  }
466  }
467 
468 
475  clearPlotCurves();
476 
477  /*Table Stuff if table is open*/
478  if (m_tableWindow != NULL && m_tableWindow->isVisible()) {
479  m_tableWindow->table()->setColumnCount(1);
480  m_tableWindow->table()->setRowCount(0);
481 // deleteFromTable();
482  }
483  }
484 
485 
491  // make sure that there are CubePlotCurves to configure
493  // can't configure 0 curves - menu item is deactivated
494  if (curves.size() < 1) {
495  return;
496  }
497  CubePlotCurve *curve = curves.first();
498  CubePlotCurveConfigureDialog *configDialog = new CubePlotCurveConfigureDialog(curve, this);
499  configDialog->exec();
500 
501  emit plotChanged();
502  }
503 
504 
513  dialog->show();
514  }
515 
516 
523  const QwtPlotItemList &plotItems = m_plot->itemList();
524 
525  for (int itemIndex = plotItems.size()- 1; itemIndex >= 0; itemIndex --) {
526  QwtPlotItem *item = plotItems[itemIndex];
527 
528  if (item->rtti() == QwtPlotItem::Rtti_PlotCurve ||
529  item->rtti() == QwtPlotItem::Rtti_PlotHistogram) {
530  delete item;
531  }
532  }
533 
534  replot();
535  }
536 
537 
543  if (m_zoomer->trackerMode() == QwtPicker::ActiveOnly) {
544  m_zoomer->setTrackerMode(QwtPicker::AlwaysOn);
545  }
546  else {
547  m_zoomer->setTrackerMode(QwtPicker::ActiveOnly);
548  }
549  }
550 
551 
556  QPixmap pixmap;
557  /* Initialize a printer*/
558  static QPrinter *printer = NULL;
559  if (printer == NULL) printer = new QPrinter;
560  printer->setPageSize(QPrinter::Letter);
561  printer->setColorMode(QPrinter::Color);
562 
563  QPrintDialog printDialog(printer, (QWidget *)parent());
564 
565  if (printDialog.exec() == QDialog::Accepted) {
566  /* Get display widget as a pixmap and convert to an image*/
567  pixmap = QPixmap::grabWidget(m_plot);
568  QImage img = pixmap.toImage();
569  /* C++ Gui Programming with Qt, page 201*/
570  QPainter painter(printer);
571  QRect rect = painter.viewport();
572  QSize size = img.size();
573  size.scale(rect.size(), Qt::KeepAspectRatio);
574  painter.setViewport(rect.x(), rect.y(),
575  size.width(), size.height());
576  painter.setWindow(img.rect());
577  painter.drawImage(0, 0, img);
578  }
579 
580  }
581 
582 
588  QPixmap pixmap;
589  QString output =
590  QFileDialog::getSaveFileName((QWidget *)parent(),
591  "Choose output file",
592  "./",
593  QString("Images (*.png *.jpg *.tif)"));
594  if (output.isEmpty()) return;
595  //Make sure the filename is valid
596  if (!output.isEmpty()) {
597  if (!output.endsWith(".png") && !output.endsWith(".jpg") && !output.endsWith(".tif")) {
598  output = output + ".png";
599  }
600  }
601 
602  QString format = QFileInfo(output).suffix();
603  pixmap = QPixmap::grabWidget(m_plot);
604 
605  std::string formatString = format.toStdString();
606  if (!pixmap.save(output, formatString.c_str())) {
607  QMessageBox::information((QWidget *)parent(), "Error", "Unable to save " + output);
608  return;
609  }
610  }
611 
612 
618  QPen *pen = new QPen(Qt::white);
619 
620  if (m_plot->canvasBackground() == Qt::white) {
621  m_plot->setCanvasBackground(Qt::black);
622  m_grid->setMajPen(QPen(Qt::white, 1, Qt::DotLine));
623  }
624  else {
625  m_plot->setCanvasBackground(Qt::white);
626  pen->setColor(Qt::black);
627  m_grid->setMajPen(QPen(Qt::black, 1, Qt::DotLine));
628  }
629 
630  m_zoomer->setRubberBandPen(*pen);
631  m_zoomer->setTrackerPen(*pen);
632  pen->setWidth(2);
633  /*Replot with the new background and pen colors*/
634  m_plot->replot();
635  }
636 
637 
643  m_zoomer->zoom(0);
644 
645  if (m_autoscaleAxes) {
646  if (m_xAxisUnits != PlotCurve::Band) {
647  m_plot->setAxisAutoScale(QwtPlot::xBottom);
648  }
649  else {
650  QPair<double, double> calculatedXRange = findDataRange(
651  QwtPlot::xBottom);
652  m_plot->setAxisScale(QwtPlot::xBottom, calculatedXRange.first,
653  calculatedXRange.second);
654  }
655 
656  if (m_yAxisUnits != PlotCurve::Band) {
657  m_plot->setAxisAutoScale(QwtPlot::yLeft);
658  }
659  else {
660  QPair<double, double> calculatedYRange = findDataRange(
661  QwtPlot::yLeft);
662  m_plot->setAxisScale(QwtPlot::yLeft, calculatedYRange.first,
663  calculatedYRange.second);
664  }
665  }
666 
667  m_zoomer->setZoomBase();
668  m_plot->replot();
669  }
670 
671 
677  if (m_xLogCheckBox->isChecked()) {
678  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLog10ScaleEngine);
679  }
680  else {
681  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
682  }
683 
684  if (m_yLogCheckBox->isChecked()) {
685  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10ScaleEngine);
686  }
687  else {
688  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
689  }
690 
691  m_autoscaleAxes = m_autoScaleCheckBox->isChecked();
692 
693  if (!m_autoscaleAxes) {
694  double xMin = m_xMinEdit->text().toDouble();
695  double xMax = m_xMaxEdit->text().toDouble();
696  // QwtScaleDiv xAxisScale =
697  // m_plot->axisScaleEngine(QwtPlot::xBottom)->divideScale(xMin, xMax,
698  // 25, 100);
699  // m_plot->setAxisScaleDiv(QwtPlot::xBottom, xAxisScale);
700  m_plot->setAxisScale(QwtPlot::xBottom, xMin, xMax);
701 
702  double yMin = m_yMinEdit->text().toDouble();
703  double yMax = m_yMaxEdit->text().toDouble();
704  // QwtScaleDiv yAxisScale =
705  // m_plot->axisScaleEngine(QwtPlot::yLeft)->divideScale(yMin, yMax,
706  // 25, 100);
707  // m_plot->setAxisScaleDiv(QwtPlot::yLeft, yAxisScale);
708  m_plot->setAxisScale(QwtPlot::yLeft, yMin, yMax);
709 
710  m_zoomer->setZoomBase();
711  }
712 
713  replot();
714  }
715 
716 
722  QDialog *dialog = new QDialog(this);
723  dialog->setWindowTitle("Set Display Range");
724 
725  QGridLayout *dialogLayout = new QGridLayout;
726 
727  int row = 0;
728 
729  QLabel *autoLabel = new QLabel("Auto-Scale: ");
730  dialogLayout->addWidget(autoLabel, row, 0);
731 
732  m_autoScaleCheckBox = new QCheckBox("Scale X/Y Axes Automatically");
734  connect(m_autoScaleCheckBox, SIGNAL(stateChanged(int)),
735  this, SLOT(autoScaleCheckboxToggled()));
736  dialogLayout->addWidget(m_autoScaleCheckBox, row, 1);
737  row++;
738 
739  QLabel *xLabel = new QLabel("<h3>X-Axis</h3>");
740  dialogLayout->addWidget(xLabel, row, 0, 1, 2);
741  row++;
742 
743  QLabel *xMinLabel = new QLabel("Minimum: ");
744  dialogLayout->addWidget(xMinLabel, row, 0);
745 
746  double xMin = plot()->axisScaleDiv(QwtPlot::xBottom)->lowerBound();
747  m_xMinEdit = new QLineEdit(QString::number(xMin));
748  dialogLayout->addWidget(m_xMinEdit, row, 1);
749  row++;
750 
751  QLabel *xMaxLabel = new QLabel("Maximum: ");
752  dialogLayout->addWidget(xMaxLabel, row, 0);
753 
754  double xMax = plot()->axisScaleDiv(QwtPlot::xBottom)->upperBound();
755  m_xMaxEdit = new QLineEdit(QString::number(xMax));
756  dialogLayout->addWidget(m_xMaxEdit, row, 1);
757  row++;
758 
759  QLabel *xLogLabel = new QLabel("Logarithmic Scale");
760  dialogLayout->addWidget(xLogLabel, row, 0);
761 
762  m_xLogCheckBox = new QCheckBox;
763  m_xLogCheckBox->setChecked(
764  m_plot->axisScaleEngine(QwtPlot::xBottom)->transformation()->type() ==
765  QwtScaleTransformation::Log10);
766  dialogLayout->addWidget(m_xLogCheckBox, row, 1);
767  row++;
768 
769  QLabel *yLabel = new QLabel("<h3>Y-Axis</h3>");
770  dialogLayout->addWidget(yLabel, row, 0, 1, 2);
771  row++;
772 
773  QLabel *yMinLabel = new QLabel("Minimum: ");
774  dialogLayout->addWidget(yMinLabel, row, 0);
775 
776  double yMin = plot()->axisScaleDiv(QwtPlot::yLeft)->lowerBound();
777  m_yMinEdit = new QLineEdit(QString::number(yMin));
778  dialogLayout->addWidget(m_yMinEdit, row, 1);
779  row++;
780 
781  QLabel *yMaxLabel = new QLabel("Maximum: ");
782  dialogLayout->addWidget(yMaxLabel, row, 0);
783 
784  double yMax = plot()->axisScaleDiv(QwtPlot::yLeft)->upperBound();
785  m_yMaxEdit = new QLineEdit(QString::number(yMax));
786  dialogLayout->addWidget(m_yMaxEdit, row, 1);
787  row++;
788 
789  QLabel *yLogLabel = new QLabel("Logarithmic Scale");
790  dialogLayout->addWidget(yLogLabel, row, 0);
791 
792  m_yLogCheckBox = new QCheckBox;
793  m_yLogCheckBox->setChecked(
794  m_plot->axisScaleEngine(QwtPlot::yLeft)->transformation()->type() ==
795  QwtScaleTransformation::Log10);
796  dialogLayout->addWidget(m_yLogCheckBox, row, 1);
797  row++;
798 
799  QHBoxLayout *buttonsLayout = new QHBoxLayout;
800  buttonsLayout->addStretch();
801 
802  QPushButton *okButton = new QPushButton("&Ok");
803  okButton->setIcon(QIcon::fromTheme("dialog-ok"));
804  connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept()));
805  connect(dialog, SIGNAL(accepted()), this, SLOT(setUserValues()));
806  okButton->setShortcut(Qt::Key_Enter);
807  buttonsLayout->addWidget(okButton);
808 
809  QPushButton *cancelButton = new QPushButton("&Cancel");
810  cancelButton->setIcon(QIcon::fromTheme("dialog-cancel"));
811  connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
812  buttonsLayout->addWidget(cancelButton);
813 
814  QWidget *buttonsWrapper = new QWidget;
815  buttonsWrapper->setLayout(buttonsLayout);
816  dialogLayout->addWidget(buttonsWrapper, row, 0, 1, 2);
817  row++;
818 
820 
821  dialog->setLayout(dialogLayout);
822  dialog->show();
823  }
824 
825 
831  QDialog *dialog = new QDialog(this);
832  dialog->setWindowTitle("Name Plot Labels");
833 
834  QGridLayout *dialogLayout = new QGridLayout;
835 
836  int row = 0;
837  QLabel *plotLabel = new QLabel("Plot Title: ");
838  dialogLayout->addWidget(plotLabel, row, 0);
839 
840  m_plotTitleText = new QLineEdit(plot()->title().text());
841  dialogLayout->addWidget(m_plotTitleText, row, 1);
842  row++;
843 
844  QLabel *xAxisLabel = new QLabel("X-Axis Label: ");
845  dialogLayout->addWidget(xAxisLabel, row, 0);
846 
847  m_xAxisText = new QLineEdit(m_plot->axisTitle(QwtPlot::xBottom).text());
848  dialogLayout->addWidget(m_xAxisText, row, 1);
849  row++;
850 
851  QLabel *yAxisLabel = new QLabel("Y-Axis Label: ");
852  dialogLayout->addWidget(yAxisLabel, row, 0);
853 
854  m_yAxisText = new QLineEdit(m_plot->axisTitle(QwtPlot::yLeft).text());
855  dialogLayout->addWidget(m_yAxisText, row, 1);
856  row++;
857 
858  QHBoxLayout *buttonsLayout = new QHBoxLayout;
859  buttonsLayout->addStretch();
860 
861  QPushButton *okButton = new QPushButton("&Ok");
862  okButton->setIcon(QIcon::fromTheme("dialog-ok"));
863  connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept()));
864  connect(dialog, SIGNAL(accepted()), this, SLOT(setLabels()));
865  okButton->setShortcut(Qt::Key_Enter);
866  buttonsLayout->addWidget(okButton);
867 
868  QPushButton *cancelButton = new QPushButton("&Cancel");
869  cancelButton->setIcon(QIcon::fromTheme("dialog-cancel"));
870  connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
871  buttonsLayout->addWidget(cancelButton);
872 
873  QWidget *buttonsWrapper = new QWidget;
874  buttonsWrapper->setLayout(buttonsLayout);
875  dialogLayout->addWidget(buttonsWrapper, row, 0, 1, 2);
876  row++;
877 
878  dialog->setLayout(dialogLayout);
879  dialog->show();
880  }
881 
882 
887  m_plot->setTitle(m_plotTitleText->text());
888  m_plot->setAxisTitle(QwtPlot::xBottom, m_xAxisText->text());
889  m_plot->setAxisTitle(QwtPlot::yLeft, m_yAxisText->text());
890  /*Replot with new labels.*/
891  m_plot->replot();
892  }
893 
894 
900  m_grid->setVisible(!m_grid->isVisible());
901 
902  if (m_grid->isVisible()) {
903  m_showHideGrid->setText("Hide Grid");
904  }
905  else {
906  m_showHideGrid->setText("Show Grid");
907  }
908  m_plot->replot();
909  }
910 
911 
916  void (QwtPlotItem::*method)();
917  if (m_showHideAllMarkers->text() == "Hide All Symbols") {
918  method = &QwtPlotItem::hide;
919 
920  m_showHideAllMarkers->setText("Show All Symbols");
921 
922  }
923  else {
924  method = &QwtPlotItem::show;
925 
926  m_showHideAllMarkers->setText("Hide All Symbols");
927  }
928 
929  for (int i = 0; i < m_plot->itemList().size(); i ++) {
930  QwtPlotItem *plotItem = m_plot->itemList()[i];
931  if (plotItem->rtti() == QwtPlotItem::Rtti_PlotMarker)
932  (plotItem->*method)();
933  }
934  /*Replot with all symbols hidden*/
935  m_plot->replot();
936  }
937 
938 
944  void (QwtPlotItem::*method)();
945  if (m_showHideAllCurves->text() == "Hide All Curves") {
946  method = &QwtPlotItem::hide;
947 
948  m_showHideAllCurves->setText("Show All Curves");
949  m_showHideAllCurves->setIcon(
950  QPixmap(FileName("$base/icons/plot_showCurves.png").expanded()));
951 
952  }
953  else {
954  method = &QwtPlotItem::show;
955 
956  m_showHideAllCurves->setText("Hide All Curves");
957  m_showHideAllCurves->setIcon(
958  QPixmap(FileName("$base/icons/plot_hideCurves.png").expanded()));
959  }
960 
961  for (int i = 0; i < m_plot->itemList().size(); i ++) {
962  QwtPlotItem *plotItem = m_plot->itemList()[i];
963  if (plotItem->rtti() == QwtPlotItem::Rtti_PlotCurve)
964  (plotItem->*method)();
965  }
966  /*Replot with all curves hidden*/
967  m_plot->replot();
968  }
969 
970 
976  QDialog *d = new QDialog(m_plot);
977  d->setWindowTitle("Basic Help");
978 
979  QLabel *zoomLabel = new QLabel("<U>Zoom Options:</U>");
980  QLabel *zoomIn = new
981  QLabel(" <b>Left click</b> on the mouse, drag, and release to select an area to zoom in on");
982  QLabel *zoomOut = new
983  QLabel(" <b>Middle click</b> on the mouse to zoom out one level");
984  QLabel *zoomReset = new
985  QLabel(" <b>Right click</b> on the mouse and select <I>Reset Scale</I> to clear the zoom and return to the original plot");
986 
987  QLabel *curveConfigLabel = new QLabel("<br><U>Curve Configuration:</U>");
988  QLabel *configDirections = new
989  QLabel(" <b>To configure the curve properties</b> Right click on the legend and select <I>Configure</I> from <br> the menu"
990  " or click on the configure icon in the tool bar.");
991  QLabel *config = new QLabel();
992  config->setPixmap(QPixmap(FileName("$base/icons/plot_configure.png").expanded()));
993 
994  QLabel *tableLabel = new QLabel("<br><U>Table Options:</U>");
995  QLabel *tableDirections = new
996  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.");
997  QLabel *table = new QLabel();
998  table->setPixmap(QPixmap(FileName("$base/icons/plot_table.png").expanded()));
999 
1000  QVBoxLayout *layout = new QVBoxLayout();
1001  layout->addWidget(zoomLabel);
1002  layout->addWidget(zoomIn);
1003  layout->addWidget(zoomOut);
1004  layout->addWidget(zoomReset);
1005  layout->addWidget(curveConfigLabel);
1006  layout->addWidget(config);
1007  layout->addWidget(configDirections);
1008  layout->addWidget(tableLabel);
1009  layout->addWidget(table);
1010  layout->addWidget(tableDirections);
1011 
1012  d->setLayout(layout);
1013  d->show();
1014  }
1015 
1016 
1025  QList<QMenu *> menu;
1026  QList<QAction *> actions;
1027 
1028  QMenu *fileMenu = new QMenu("&File");
1029  QMenu *editMenu = new QMenu("&Edit");
1030  QMenu *optionsMenu = new QMenu("&Options");
1031 // QMenu *helpMenu = new QMenu("&Help");
1032 
1033  if ((optionsToProvide & SaveMenuOption) == SaveMenuOption) {
1034  QAction *save = new QAction(m_plot);
1035  save->setText("&Save Plot As");
1036  save->setIcon(QIcon::fromTheme("document-save-as"));
1037  QString text =
1038  "<b>Function:</b> Save the plot as a png, jpg, or tif file.";
1039  save->setWhatsThis(text);
1040  connect(save, SIGNAL(activated()), this, SLOT(savePlot()));
1041  fileMenu->addAction(save);
1042  actions.push_back(save);
1043  }
1044 
1045  if ((optionsToProvide & PrintMenuOption) == PrintMenuOption) {
1046  QAction *prt = new QAction(m_plot);
1047  prt->setText("&Print Plot");
1048  prt->setIcon(QIcon::fromTheme("document-print"));
1049  QString text =
1050  "<b>Function:</b> Sends the plot image to the printer";
1051  prt->setWhatsThis(text);
1052  connect(prt, SIGNAL(activated()), this, SLOT(printPlot()));
1053  fileMenu->addAction(prt);
1054  actions.push_back(prt);
1055  }
1056 
1057  if ((optionsToProvide & ShowTableMenuOption) == ShowTableMenuOption) {
1058  QAction *table = new QAction(m_plot);
1059  table->setText("Show Table");
1060  table->setIcon(
1061  QPixmap(FileName("$base/icons/plot_table.png").expanded()));
1062  QString text =
1063  "<b>Function:</b> Activates the table which displays the data of the "
1064  "current plot";
1065  table->setWhatsThis(text);
1066  connect(table, SIGNAL(activated()), this, SLOT(showTable()));
1067  fileMenu->addAction(table);
1068  actions.push_back(table);
1069  }
1070 
1071  QAction *close = new QAction(QIcon::fromTheme("document-close"), "&Close",
1072  m_plot);
1073  connect(close, SIGNAL(activated()), this, SLOT(close()));
1074  fileMenu->addAction(close);
1075 
1076  if ((optionsToProvide & TrackMenuOption) == TrackMenuOption) {
1077  QAction *track = new QAction(m_plot);
1078  track->setText("Show Mouse &Tracking");
1079  track->setIcon(
1080  QPixmap(FileName("$base/icons/goto.png").expanded()));
1081  track->setCheckable(true);
1082  QString text =
1083  "<b>Function:</b> Displays the x,y coordinates as the cursor moves "
1084  "around on the plot.";
1085  track->setWhatsThis(text);
1086  connect(track, SIGNAL(activated()), this, SLOT(trackerEnabled()));
1087  optionsMenu->addAction(track);
1088  }
1089 
1090  if ((optionsToProvide & BackgroundSwitchMenuOption) ==
1091  BackgroundSwitchMenuOption) {
1092  QAction *backgrdSwitch = new QAction(m_plot);
1093  backgrdSwitch->setText("White/Black &Background");
1094  backgrdSwitch->setIcon(
1095  QPixmap(FileName("$base/icons/plot_switchBackgrd.png").expanded()));
1096  QString text =
1097  "<b>Function:</b> Switch the background color between black and "
1098  "white.";
1099  backgrdSwitch->setWhatsThis(text);
1100  connect(backgrdSwitch, SIGNAL(activated()),
1101  this, SLOT(switchBackground()));
1102  optionsMenu->addAction(backgrdSwitch);
1103  actions.push_back(backgrdSwitch);
1104  }
1105 
1106  if ((optionsToProvide & ShowHideGridMenuOption) == ShowHideGridMenuOption) {
1107  m_showHideGrid = new QAction(m_plot);
1108  m_showHideGrid->setText("Show Grid");
1109  m_showHideGrid->setIcon(
1110  QPixmap(FileName("$base/icons/plot_grid.png").expanded()));
1111  QString text =
1112  "<b>Function:</b> Display grid lines on the plot.";
1113  m_showHideGrid->setWhatsThis(text);
1114  connect(m_showHideGrid, SIGNAL(activated()), this, SLOT(showHideGrid()));
1115  optionsMenu->addAction(m_showHideGrid);
1116  actions.push_back(m_showHideGrid);
1117  }
1118 
1119  if ((optionsToProvide & RenameLabelsMenuOption) == RenameLabelsMenuOption) {
1120  QAction *changeLabels = new QAction(m_plot);
1121  changeLabels->setText("Rename Plot &Labels");
1122  changeLabels->setIcon(
1123  QPixmap(FileName("$base/icons/plot_renameLabels.png").expanded()));
1124  QString text =
1125  "<b>Function:</b> Edit the plot title, x and y axis labels.";
1126  changeLabels->setWhatsThis(text);
1127  connect(changeLabels, SIGNAL(activated()),
1128  this, SLOT(changePlotLabels()));
1129  optionsMenu->addAction(changeLabels);
1130  actions.push_back(changeLabels);
1131  }
1132 
1133  if ((optionsToProvide & SetDisplayRangeMenuOption) ==
1134  SetDisplayRangeMenuOption) {
1135  QAction *changeScale = new QAction(m_plot);
1136  changeScale->setText("Set &Display Range");
1137  changeScale->setIcon(
1138  QPixmap(FileName("$base/icons/plot_setScale.png").expanded()));
1139  QString text =
1140  "<b>Function:</b> Adjust the scale for the x and y axis on the "
1141  "plot.";
1142  changeScale->setWhatsThis(text);
1143  connect(changeScale, SIGNAL(activated()), this, SLOT(setDefaultRange()));
1144  optionsMenu->addAction(changeScale);
1145  actions.push_back(changeScale);
1146  }
1147 
1148  if ((optionsToProvide & ShowHideCurvesMenuOption) ==
1149  ShowHideCurvesMenuOption) {
1151  m_showHideAllCurves->setText("Hide All Curves");
1152  m_showHideAllCurves->setIcon(
1153  QPixmap(FileName("$base/icons/plot_showCurves.png").expanded()));
1154  QString text =
1155  "<b>Function:</b> Displays or hides all the curves currently "
1156  "displayed on the plot.";
1157  m_showHideAllCurves->setWhatsThis(text);
1158  connect(m_showHideAllCurves, SIGNAL(activated()),
1159  this, SLOT(showHideAllCurves()));
1160  optionsMenu->addAction(m_showHideAllCurves);
1161  actions.push_back(m_showHideAllCurves);
1162  }
1163 
1164  if ((optionsToProvide & ShowHideMarkersMenuOption) ==
1165  ShowHideMarkersMenuOption) {
1167  m_showHideAllMarkers->setText("Hide All Symbols");
1168  m_showHideAllMarkers->setIcon(
1169  QPixmap(FileName("$base/icons/plot_markers.png").expanded()));
1170  QString text = "<b>Function:</b> Displays or hides a symbol for each "
1171  "data point plotted on a plot.";
1172  m_showHideAllMarkers->setWhatsThis(text);
1173  connect(m_showHideAllMarkers, SIGNAL(activated()),
1174  this, SLOT(showHideAllMarkers()));
1175  optionsMenu->addAction(m_showHideAllMarkers);
1176  actions.push_back(m_showHideAllMarkers);
1177  }
1178 
1179  if ((optionsToProvide & ResetScaleMenuOption) == ResetScaleMenuOption) {
1180  QAction *resetScaleButton = new QAction(m_plot);
1181  resetScaleButton->setText("Reset Scale");
1182  resetScaleButton->setIcon(
1183  QPixmap(FileName("$base/icons/plot_resetscale.png").expanded()));
1184  QString text =
1185  "<b>Function:</b> Reset the plot's scale.";
1186  resetScaleButton->setWhatsThis(text);
1187  connect(resetScaleButton, SIGNAL(activated()), this, SLOT(resetScale()));
1188  actions.push_back(resetScaleButton);
1189  }
1190 
1191  if ((optionsToProvide & ClearPlotMenuOption) == ClearPlotMenuOption) {
1192  QAction *clear = new QAction(m_plot);
1193  clear->setText("Clear Plot");
1194  clear->setIcon(
1195  QPixmap(FileName("$base/icons/plot_clear.png").expanded()));
1196  QString text =
1197  "<b>Function:</b> Removes all the curves from the plot.";
1198  clear->setWhatsThis(text);
1199  connect(clear, SIGNAL(activated()), this, SLOT(clearPlot()));
1200  actions.push_back(clear);
1201  }
1202 
1203  if ((optionsToProvide & LineFitMenuOption) == LineFitMenuOption) {
1204  QAction *lineFit = new QAction(m_plot);
1205  lineFit->setText("Create Best Fit Line");
1206  lineFit->setIcon(
1207  QPixmap(FileName("$base/icons/linefit.png").expanded()));
1208  QString text = "<b>Function:</b> Calculates a best fit line from an "
1209  "existing curve.";
1210  lineFit->setWhatsThis(text);
1211  connect(lineFit, SIGNAL(activated()), this, SLOT( createBestFitLine() ) );
1212  optionsMenu->addAction(lineFit);
1213  actions.push_back(lineFit);
1214  }
1215 
1216  if ((optionsToProvide & ConfigurePlotMenuOption) == ConfigurePlotMenuOption) {
1217  QAction *configurePlot = new QAction(m_plot);
1218  configurePlot->setText("Configure Plot");
1219  configurePlot->setIcon(
1220  QPixmap( FileName("$base/icons/plot_configure.png").expanded() ) );
1221  QString text = "<b>Function:</b> Change the name, color, style, and vertex symbol of the "
1222  "curves.";
1223  configurePlot->setWhatsThis(text);
1224  connect( configurePlot, SIGNAL( activated() ),
1225  this, SLOT( configurePlotCurves() ) );
1226  optionsMenu->addAction(configurePlot);
1227  actions.push_back(configurePlot);
1228  }
1229 
1230  /*setup menus*/
1231  m_pasteAct = new QAction(QIcon::fromTheme("edit-paste"),
1232  "&Paste Curve", m_plot);
1233  m_pasteAct->setEnabled(false);
1234  m_pasteAct->setShortcut(Qt::CTRL | Qt::Key_V);
1235  connect(m_pasteAct, SIGNAL(triggered()),
1236  this, SLOT(pasteCurve()));
1237  editMenu->addAction(m_pasteAct);
1238 
1239 // QAction *basicHelp = new QAction(m_plot);
1240 // basicHelp->setText("Basic Help");
1241 // connect( basicHelp, SIGNAL( activated() ),
1242 // this, SLOT( showHelp() ) );
1243 // helpMenu->addAction(basicHelp);
1244 
1245  menu.push_back(fileMenu);
1246  menu.push_back(editMenu);
1247 
1248  if (optionsMenu->actions().size()) {
1249  menu.push_back(optionsMenu);
1250  }
1251  else {
1252  delete optionsMenu;
1253  optionsMenu = NULL;
1254  }
1255 
1256 // if (helpMenu->actions().size()) {
1257 // menu.push_back(helpMenu);
1258 // }
1259 // else {
1260 // delete helpMenu;
1261 // helpMenu = NULL;
1262 // }
1263 
1264  setMenus(menu, actions);
1265  }
1266 
1267 
1279  bool PlotWindow::userCanAddCurve(const QMimeData *curve) {
1280  bool userCanAdd = false;
1281 
1282  if (m_allowUserToAddCurves &&
1283  curve->hasFormat("application/isis3-plot-curve")) {
1284 
1285  CubePlotCurve * testCurve = new CubePlotCurve(
1286  curve->data("application/isis3-plot-curve"));
1287 
1288  userCanAdd = canAdd(testCurve);
1289  }
1290 
1291  return userCanAdd;
1292  }
1293 
1294 
1304  if (m_showHideAllCurves) {
1305  if (m_showHideAllCurves->text() == "Hide All Curves") {
1306  curve->show();
1307  }
1308  else {
1309  curve->hide();
1310  }
1311 
1312  if (m_showHideAllMarkers->text() == "Hide All Symbols") {
1313  curve->setMarkerVisible(true);
1314  }
1315  else {
1316  curve->setMarkerVisible(false);
1317  }
1318  }
1319 
1320  emit plotChanged();
1321  }
1322 
1323 
1332  if (m_toolBar == NULL) {
1333  m_toolBar = new QToolBar(this);
1334  m_toolBar->setObjectName("PlotWindow");
1335  m_toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea | Qt::TopToolBarArea);
1336  addToolBar(Qt::TopToolBarArea, m_toolBar);
1337  }
1338  else {
1339  m_toolBar->clear();
1340  }
1341 
1342  m_menubar = menuBar();
1343  m_menubar->clear();
1344 
1345  for (int i = 0; i < menu.size(); i++) {
1346  m_menubar->addMenu(menu[i]);
1347  }
1348 
1349  for (int i = 0; i < actions.size(); i++) {
1350  m_toolBar->addAction(actions[i]);
1351  }
1352 
1353  }
1354 
1355 
1361  QwtPlotZoomer *PlotWindow::zoomer() {
1362  return m_zoomer;
1363  }
1364 
1365 
1373  if (!m_scheduledFillTable) {
1374  m_scheduledFillTable = true;
1375  emit requestFillTable();
1376  }
1377  }
1378 
1379 
1385  m_scheduledFillTable = false;
1386 
1387  if (m_tableWindow == NULL) return;
1388  m_tableWindow->listWidget()->clear();
1389  m_tableWindow->table()->clear();
1390  m_tableWindow->table()->setRowCount(0);
1391  m_tableWindow->table()->setColumnCount(0);
1392 
1393  m_tableWindow->addToTable(true,
1394  m_plot->axisTitle(QwtPlot::xBottom).text(),
1395  m_plot->axisTitle(QwtPlot::xBottom).text());
1396 
1398  foreach (CubePlotCurve *curve, curves) {
1399  m_tableWindow->addToTable(true,
1400  curve->title().text(),
1401  curve->title().text());
1402  }
1403 
1404  // We really need all of the x-values associated with the curves,
1405  // but qwt doesn't seem to want to give this to us. It'll give us the
1406  // axis scale, but that isn't quite what we want (especially when zooming)
1407  // So let's find the list of x-points ourselves.
1408  //
1409  // This is what I tried and it did NOT work:
1410  // QwtScaleDiv *xAxisScaleDiv = m_plot->axisScaleDiv(QwtPlot::xBottom);
1411  // QList<double> xAxisPoints = xAxisScaleDiv->ticks(QwtScaleDiv::MajorTick);
1412  //
1413  // We're going to keep xAxisPoints in standard text sort order until we're done populating it,
1414  // then we'll re-sort numerically. That enables us to effectively use binary searches and
1415  // insertion sort-like capabilities for speed.
1416  QList<QString> xAxisPoints;
1417 
1418  QProgressDialog progress(tr("Re-calculating Table"), tr(""), 0, 1000, this);
1419  double percentPerCurve = 0.5 * 1.0 / curves.count();
1420 
1421  for (int curveIndex = 0; curveIndex < curves.count(); curveIndex++) {
1422  progress.setValue(qRound(curveIndex * percentPerCurve * 1000.0));
1423 
1424  CubePlotCurve *curve = curves[curveIndex];
1425 
1426  double percentPerDataIndex = (1.0 / curve->data()->size()) * percentPerCurve;
1427 
1428  // Loop backwards because our insertion sort will have a much better
1429  // chance of success on it's first try this way.
1430  for (int dataIndex = (int)curve->data()->size() - 1;
1431  dataIndex >= 0;
1432  dataIndex--) {
1433  double xValue = curve->data()->sample(dataIndex).x();
1434  QString xValueString = toString(xValue);
1435 
1436  int inverseDataIndex = (curve->data()->size() - 1) - dataIndex;
1437  progress.setValue(
1438  qRound( ((curveIndex * percentPerCurve) +
1439  (inverseDataIndex * percentPerDataIndex)) * 1000.0));
1440 
1441  // It turns out that qBinaryFind(container, value) is NOT the same as
1442  // qBinaryFind(container.begin(), container.end(), value). Use the one
1443  // that works right.
1445  qBinaryFind(xAxisPoints.begin(), xAxisPoints.end(), xValueString);
1446 
1447  if (foundPos == xAxisPoints.end()) {
1448  bool inserted = false;
1449 
1450  for (int searchIndex = 0;
1451  searchIndex < xAxisPoints.size() && !inserted;
1452  searchIndex++) {
1453  if (xAxisPoints[searchIndex] > xValueString) {
1454  inserted = true;
1455  xAxisPoints.insert(searchIndex, xValueString);
1456  }
1457  }
1458 
1459  if (!inserted)
1460  xAxisPoints.append(xValueString);
1461  }
1462  }
1463  }
1464 
1465  qSort(xAxisPoints.begin(), xAxisPoints.end(), &numericStringLessThan);
1466 
1467  m_tableWindow->table()->setRowCount(xAxisPoints.size());
1468 
1469  QList<int> lastSuccessfulSamples;
1470 
1471  for (int i = 0; i < curves.count(); i++) {
1472  lastSuccessfulSamples.append(-1);
1473  }
1474 
1475  double progressPerRow = 0.5 * 1.0 / m_tableWindow->table()->rowCount();
1476 
1477  for (int row = 0; row < m_tableWindow->table()->rowCount(); row++) {
1478  progress.setValue(500 + qRound(row * progressPerRow * 1000.0));
1479 
1480  QString xValueString = xAxisPoints[row];
1481  double xValue = toDouble(xValueString);
1482 
1483  QTableWidgetItem *xAxisItem = new QTableWidgetItem(xValueString);
1484  m_tableWindow->table()->setItem(row, 0, xAxisItem);
1485 
1486  if (row == m_tableWindow->table()->rowCount() - 1) {
1487  m_tableWindow->table()->resizeColumnToContents(0);
1488  }
1489 
1490  // Now search for the x-axis points in the curves to fill in data
1491  for (int col = 1; col < m_tableWindow->table()->columnCount(); col++) {
1492  CubePlotCurve *curve = curves[col - 1];
1493 
1494  double y = Null;
1495  bool tooFar = false;
1496 
1497  for (int dataIndex = lastSuccessfulSamples[col - 1] + 1;
1498  dataIndex < (int)curve->data()->size() && y == Null && !tooFar;
1499  dataIndex++) {
1500 
1501  if (toString(curve->data()->sample(dataIndex).x()) == xValueString) {
1502  // Try to compensate for decreasing x values by not performing this optimization
1503  if (dataIndex > 0 &&
1504  curve->data()->sample(dataIndex - 1).x() < curve->data()->sample(dataIndex).x()) {
1505  lastSuccessfulSamples[col - 1] = dataIndex;
1506  }
1507  y = curve->data()->sample(dataIndex).y();
1508  }
1509  // Try to compensate for decreasing X values in the too far computation
1510  else if (dataIndex > 0 &&
1511  curve->data()->sample(dataIndex - 1).x() < curve->data()->sample(dataIndex).x() &&
1512  curve->data()->sample(dataIndex).x() > xValue) {
1513  tooFar = true;
1514  }
1515  }
1516 
1517  QTableWidgetItem *item = NULL;
1518 
1519  if (IsSpecial(y))
1520  item = new QTableWidgetItem(QString("N/A"));
1521  else
1522  item = new QTableWidgetItem(toString(y));
1523 
1524  m_tableWindow->table()->setItem(row, col, item);
1525 
1526  if (row == m_tableWindow->table()->rowCount() - 1) {
1527  m_tableWindow->table()->resizeColumnToContents(col);
1528  }
1529  }
1530  }
1531  }
1532 
1533 
1540  if (plotCurves().size()) {
1541  if (m_tableWindow == NULL) {
1542  //m_tableWindow = new TableMainWindow("Plot Table", this);
1543  m_tableWindow = new TableMainWindow("Plot Table", m_parent);
1545  }
1546 
1547  fillTable();
1548  m_tableWindow->show();
1550  }
1551  }
1552 
1553 
1563  bool PlotWindow::eventFilter(QObject *o, QEvent *e) {
1564  bool blockWidgetFromEvent = false;
1565 
1566  switch (e->type()) {
1567  case QEvent::MouseButtonPress:
1568  if (o == this &&
1569  childAt(((QMouseEvent *)e)->pos()) != plot()->canvas()) {
1570  mousePressEvent(o, (QMouseEvent *)e);
1571  blockWidgetFromEvent = true;
1572  }
1573  break;
1574 
1575  default:
1576  break;
1577  }
1578 
1579  bool stopHandlingEvent = false;
1580  if (!blockWidgetFromEvent && o == this) {
1581  stopHandlingEvent = MainWindow::eventFilter(o, e);
1582 
1583  if (e->type() == QEvent::Close && !stopHandlingEvent) {
1584  emit closed();
1585  }
1586  }
1587 
1588  return stopHandlingEvent || blockWidgetFromEvent;
1589  }
1590 
1591 
1601  void PlotWindow::mousePressEvent(QObject *object, QMouseEvent *event) {
1602  if (qobject_cast<QWidget *>(object) &&
1603  event->button() == Qt::RightButton &&
1604  userCanAddCurve(QApplication::clipboard()->mimeData())) {
1605  QMenu contextMenu;
1606 
1607  QAction *pasteAct = new QAction(QIcon::fromTheme("edit-paste"), "Paste",
1608  this);
1609  contextMenu.addAction(pasteAct);
1610 
1611  QAction *chosenAct = contextMenu.exec(
1612  qobject_cast<QWidget *>(object)->mapToGlobal(event->pos()));
1613 
1614  if (chosenAct == pasteAct) {
1615  pasteCurve();
1616  }
1617  }
1618  }
1619 
1620 
1627  return m_plot;
1628  }
1629 
1630 
1638  m_autoscaleAxes = false;
1639  }
1640 
1641 
1649  m_xMinEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1650  m_xMaxEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1651  m_yMinEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1652  m_yMaxEdit->setEnabled(!m_autoScaleCheckBox->isChecked());
1653  }
1654 
1655 
1660  m_pasteAct->setEnabled(
1661  userCanAddCurve(QApplication::clipboard()->mimeData()));
1662  }
1663 
1664 
1671  if (m_allowUserToAddCurves) {
1672  QClipboard *globalClipboard = QApplication::clipboard();
1673  const QMimeData *globalData = globalClipboard->mimeData();
1674 
1675  if (globalData->hasFormat("application/isis3-plot-curve")) {
1676  CubePlotCurve * newCurve = new CubePlotCurve(
1677  globalData->data("application/isis3-plot-curve"));
1678  // add curve to plot
1679  add(newCurve);
1680  emit plotChanged();
1681  }
1682  }
1683  }
1684 
1685 
1695  QPair<double, double> PlotWindow::findDataRange(int axisId) const {
1697 
1698  bool foundDataValue = false;
1699  QPair<double, double> rangeMinMax;
1700 
1701  foreach(const CubePlotCurve *curve, curves) {
1702  for (int dataIndex = 0; dataIndex < (int)curve->dataSize(); dataIndex++) {
1703  if (axisId == QwtPlot::xBottom) {
1704  if (!foundDataValue) {
1705  rangeMinMax.first = curve->sample(dataIndex).x();
1706  rangeMinMax.second = curve->sample(dataIndex).x();
1707  foundDataValue = true;
1708  }
1709  else {
1710  rangeMinMax.first = qMin(rangeMinMax.first, curve->sample(dataIndex).x());
1711  rangeMinMax.second = qMax(rangeMinMax.second, curve->sample(dataIndex).x());
1712  }
1713  }
1714  else if (axisId == QwtPlot::yLeft) {
1715  if (!foundDataValue) {
1716  rangeMinMax.first = curve->sample(dataIndex).y();
1717  rangeMinMax.second = curve->sample(dataIndex).y();
1718  foundDataValue = true;
1719  }
1720  else {
1721  rangeMinMax.first = qMin(rangeMinMax.first, curve->sample(dataIndex).y());
1722  rangeMinMax.second = qMax(rangeMinMax.second, curve->sample(dataIndex).y());
1723  }
1724  }
1725  }
1726  }
1727 
1728  if (!foundDataValue) {
1729  rangeMinMax.first = 1;
1730  rangeMinMax.second = 10;
1731  }
1732  else if(rangeMinMax.first == rangeMinMax.second) {
1733  rangeMinMax.first -= 0.5;
1734  rangeMinMax.second += 0.5;
1735  }
1736 
1737  return rangeMinMax;
1738  }
1739 
1740 
1741  bool PlotWindow::numericStringLessThan(QString left, QString right) {
1742  bool result = false;
1743 
1744  try {
1745  result = toDouble(left) < toDouble(right);
1746  }
1747  catch (IException &) {
1748  }
1749 
1750  return result;
1751  }
1752 
1753 
1760  void PlotWindow::paint(MdiCubeViewport *vp, QPainter *painter) {
1761  foreach (CubePlotCurve *curve, plotCurves()) {
1762  curve->paint(vp, painter);
1763  }
1764  }
1765 
1766 
1771  resetScale();
1772  emit plotChanged();
1773  }
1774 
1775 
1784  return "Plot";
1785  }
1786 
1787 
1796  void PlotWindow::dragEnterEvent(QDragEnterEvent *event) {
1797  QWidget *source = event->source();
1798 
1799  if (source != m_plot->legend()->contentsWidget() &&
1800  userCanAddCurve(event->mimeData())) {
1801  event->acceptProposedAction();
1802  }
1803  }
1804 
1805 
1817  void PlotWindow::dropEvent(QDropEvent *event) {
1818  if (m_allowUserToAddCurves &&
1819  event->mimeData()->hasFormat("application/isis3-plot-curve")) {
1820  Qt::DropActions possibleActions = event->possibleActions();
1821  Qt::DropAction actionToTake = event->proposedAction();
1822 
1823  QFont boldFont;
1824  boldFont.setBold(true);
1825  QMenu dropActionsMenu;
1826 
1827  QAction *copyAct = new QAction("&Copy Here", this);
1828  if (possibleActions.testFlag(Qt::CopyAction)) {
1829  dropActionsMenu.addAction(copyAct);
1830 
1831  if (actionToTake == Qt::CopyAction)
1832  copyAct->setFont(boldFont);
1833  }
1834 
1835  QAction *moveAct = new QAction("&Move Here", this);
1836  if (possibleActions.testFlag(Qt::MoveAction)) {
1837  dropActionsMenu.addAction(moveAct);
1838 
1839  if (actionToTake == Qt::MoveAction)
1840  moveAct->setFont(boldFont);
1841  }
1842 
1843  if (dropActionsMenu.actions().size() > 1) {
1844  dropActionsMenu.addSeparator();
1845 
1846  QAction *cancelAct = new QAction("&Cancel", this);
1847  dropActionsMenu.addAction(cancelAct);
1848 
1849  QAction *chosenAct = dropActionsMenu.exec(mapToGlobal(event->pos()));
1850 
1851  if (chosenAct == copyAct) {
1852  actionToTake = Qt::CopyAction;
1853  }
1854  else if (chosenAct == moveAct) {
1855  actionToTake = Qt::MoveAction;
1856  }
1857  else {
1858  actionToTake = Qt::IgnoreAction;
1859  }
1860  }
1861 
1862  if (actionToTake != Qt::IgnoreAction) {
1863  CubePlotCurve * newCurve = new CubePlotCurve(
1864  event->mimeData()->data("application/isis3-plot-curve"));
1865  // add curve to plot
1866  add(newCurve);
1867  emit plotChanged();
1868 
1869  event->setDropAction(actionToTake);
1870  event->accept();
1871  }
1872  }
1873  }
1874 
1875 }
1876