Isis 3 Programmer Reference
MatchTool.cpp
1 #include "MatchTool.h"
2 
3 #include <sstream>
4 #include <vector>
5 #include <iomanip>
6 
7 #include <QAction>
8 #include <QComboBox>
9 #include <QFileDialog>
10 #include <QLabel>
11 #include <QLineEdit>
12 #include <QMenuBar>
13 #include <QMessageBox>
14 #include <QScrollBar>
15 #include <QShortcut>
16 #include <QSplitter>
17 #include <QTableWidget>
18 #include <QTableWidgetItem>
19 #include <QtWidgets>
20 #include <QWhatsThis>
21 
22 #include "Application.h"
23 #include "ControlMeasure.h"
24 #include "ControlMeasureLogData.h"
25 #include "ControlNet.h"
26 #include "ControlPoint.h"
27 #include "ControlPointEdit.h"
28 #include "FileName.h"
29 #include "IException.h"
30 #include "MainWindow.h"
31 #include "MatchToolDeletePointDialog.h"
32 #include "MatchToolNewPointDialog.h"
33 #include "MdiCubeViewport.h"
34 #include "Progress.h"
35 #include "Pvl.h"
36 #include "PvlEditDialog.h"
37 #include "SerialNumber.h"
38 #include "SerialNumberList.h"
39 #include "SpecialPixel.h"
40 #include "ToolPad.h"
41 #include "ViewportMainWindow.h"
42 #include "Workspace.h"
43 
44 using namespace std;
45 
46 namespace Isis {
47 
57  MatchTool::MatchTool (QWidget *parent) : Tool(parent) {
58  m_controlNet = NULL;
59  m_coregNet = false;
60  m_netChanged = false;
61  m_pointEditor = NULL;
62  m_newPointDialog = NULL;
63  m_newPoint = NULL;
64  m_leftCube = NULL;
65  m_rightCube = NULL;
66  m_editPoint = NULL;
67  m_createPoint = NULL;
68  m_modifyPoint = NULL;
69  m_deletePoint = NULL;
70  m_whatsThis = NULL;
71  m_showHelp = NULL;
72  m_ptIdValue = NULL;
73  m_numMeasures = NULL;
74  m_lockPoint = NULL;
75  m_ignorePoint = NULL;
76  m_leftReference = NULL;
77  m_leftMeasureType = NULL;
78  m_leftGoodness = NULL;
79  m_rightReference = NULL;
80  m_rightMeasureType = NULL;
81  m_rightGoodness = NULL;
82  m_lockLeftMeasure = NULL;
83  m_ignoreLeftMeasure = NULL;
84  m_lockRightMeasure = NULL;
85  m_ignoreRightMeasure = NULL;
86  m_leftCombo = NULL;
87  m_rightCombo = NULL;
88  m_leftMeasure = NULL;
89  m_rightMeasure = NULL;
90  m_templateModified = false;
91  m_measureWindow = NULL;
92  m_measureTable = NULL;
93 
94  // try to get status bar from viewportmain window which is parent
95 // QStatusBar *m_statusBar = qobject_cast<QMainWindow *>(parent)->statusBar();
96 // m_statusBar->showMessage("STATUS BAR TEST");
97 
98 // QString warn = "TEST TEST TEST";
99 // QString warn2 = "JUNK";
100 // qobject_cast<ViewportMainWindow *>(parent)->displayWarning(warn,warn2);
101  m_parent = parent;
102  connect(this, SIGNAL(toolActivated()), this, SLOT(activateTool()));
103 
104  // Connect the ViewportMainWindow's (parent) closeWindow signal to a exit slot for
105  // prompting user to save net
106  ViewportMainWindow *parentMainWindow = qobject_cast<ViewportMainWindow *>(parent);
107 
108  if (parentMainWindow) {
109  connect(parent, SIGNAL(closeWindow()), this, SLOT(exiting()));
110  }
111 
112  createMatchTool(parent);
113 
114  }
115 
116 
117  MatchTool::~MatchTool () {
118  // FIXME: Don't write settings in destructor, must do this earlier in close event
119  writeSettings();
120 
121  delete m_controlNet;
122  m_controlNet = NULL;
123  delete m_pointEditor;
124  m_pointEditor = NULL;
125  delete m_newPointDialog;
126  m_newPointDialog = NULL;
127  delete m_newPoint;
128  m_newPoint = NULL;
129  delete m_leftMeasure;
130  m_leftMeasure = NULL;
131  delete m_rightMeasure;
132  m_rightMeasure = NULL;
133  delete m_leftCube;
134  m_leftCube = NULL;
135  delete m_rightCube;
136  m_rightCube = NULL;
137  }
138 
139 
140 
166 
167  m_matchTool = new QMainWindow(parent);
168  m_matchTool->setWindowTitle("Match Tool");
169  m_matchTool->setObjectName("MatchTool");
170  connect(m_matchTool, SIGNAL(destroyed(QObject *)), this, SLOT(clearEditPoint()));
171 
172  createActions();
173  createMenus();
174  createToolBars();
175 
176  // create m_pointEditor first since we need to get its templateFileName
177  // later
178  m_pointEditor = new ControlPointEdit(m_controlNet, parent, true, false);
179  connect(this, SIGNAL(newControlNetwork(ControlNet *)),
180  m_pointEditor, SIGNAL(newControlNetwork(ControlNet *)));
181  connect(this, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)),
182  m_pointEditor, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)));
183  connect(m_pointEditor, SIGNAL(measureSaved()), this, SLOT(measureSaved()));
184  connect(this, SIGNAL(measureChanged()),
185  m_pointEditor, SLOT(colorizeSaveButton()));
186 
187  m_savePoint = new QPushButton ("Save Point");
188  m_savePoint->setShortcut(Qt::Key_P);
189  m_savePoint->setToolTip("Save the edit control point to the control network. "
190  "<strong>Shortcut: P</strong>");
191  m_savePoint->setWhatsThis("Save the edit control point to the control "
192  "network which is loaded into memory in its entirety. "
193  "When a control point is selected for editing, "
194  "a copy of the point is made so that the original control "
195  "point remains in the network.");
196  m_saveDefaultPalette = m_savePoint->palette();
197  connect (m_savePoint,SIGNAL(clicked()),this,SLOT(savePoint()));
198 
199  QHBoxLayout * addMeasureLayout = new QHBoxLayout;
200  addMeasureLayout->addStretch();
201  addMeasureLayout->addWidget(m_savePoint);
202 // addMeasureLayout->addStretch();
203 
204  m_cnetFileNameLabel = new QLabel("Control Network: " + m_cnetFileName);
205  m_cnetFileNameLabel->setToolTip("Name of opened control network file.");
206  m_cnetFileNameLabel->setWhatsThis("Name of opened control network file.");
207 
208  m_templateFileNameLabel = new QLabel("Template File: " +
209  m_pointEditor->templateFileName());
210  m_templateFileNameLabel->setToolTip("Sub-pixel registration template File.");
211 // QString patternMatchDoc =
212 // FileName("$ISISROOT/doc/documents/PatternMatch/PatternMatch.html").fileName();
213 // m_templateFileNameLabel->setOpenExternalLinks(true);
214  m_templateFileNameLabel->setWhatsThis("FileName of the sub-pixel "
215  "registration template. Refer to $ISISROOT/doc/documents/"
216  "PatternMatch/PatternMatch.html for a description of the "
217  "contents of this file.");
218 
219  QVBoxLayout * centralLayout = new QVBoxLayout;
220 
221  centralLayout->addWidget(m_cnetFileNameLabel);
222  centralLayout->addWidget(m_templateFileNameLabel);
223  centralLayout->addWidget(createTopSplitter());
224  centralLayout->addStretch();
225  centralLayout->addWidget(m_pointEditor);
226  centralLayout->addLayout(addMeasureLayout);
227  QWidget * centralWidget = new QWidget;
228  centralWidget->setLayout(centralLayout);
229 
230  QScrollArea *scrollArea = new QScrollArea();
231  scrollArea->setObjectName("MatchToolScroll");
232  scrollArea->setWidget(centralWidget);
233  scrollArea->setWidgetResizable(true);
234  centralWidget->adjustSize();
235  m_matchTool->setCentralWidget(scrollArea);
236 // m_matchTool->setCentralWidget(centralWidget);
237 
238 
239  connect(this, SIGNAL(editPointChanged()),
240  this, SLOT(paintAllViewports()));
241 
242  readSettings();
243  }
244 
245 
248 
249  QHBoxLayout * measureLayout = new QHBoxLayout;
250  measureLayout->addWidget(createLeftMeasureGroupBox());
251  measureLayout->addWidget(createRightMeasureGroupBox());
252 
253  QVBoxLayout * groupBoxesLayout = new QVBoxLayout;
254  groupBoxesLayout->addWidget(createControlPointGroupBox());
255  groupBoxesLayout->addStretch();
256  groupBoxesLayout->addLayout(measureLayout);
257 
258  QWidget * groupBoxesWidget = new QWidget;
259  groupBoxesWidget->setLayout(groupBoxesLayout);
260 
262 
263  QSplitter * topSplitter = new QSplitter;
264  topSplitter->addWidget(groupBoxesWidget);
265  topSplitter->addWidget(m_templateEditorWidget);
266  topSplitter->setStretchFactor(0, 4);
267  topSplitter->setStretchFactor(1, 3);
268 
269  m_templateEditorWidget->hide();
270 
271  return topSplitter;
272  }
273 
274 
277 
278  // create left vertical layout
279  m_ptIdValue = new QLabel;
280  m_numMeasures = new QLabel;
281  QVBoxLayout * leftLayout = new QVBoxLayout;
282  leftLayout->addWidget(m_ptIdValue);
283  leftLayout->addWidget(m_numMeasures);
284 
285  // create right vertical layout's top layout
286  m_lockPoint = new QCheckBox("Edit Lock Point");
287  connect(m_lockPoint, SIGNAL(clicked(bool)), this, SLOT(setLockPoint(bool)));
288  m_ignorePoint = new QCheckBox("Ignore Point");
289  connect(m_ignorePoint, SIGNAL(clicked(bool)),
290  this, SLOT(setIgnorePoint(bool)));
291  connect(this, SIGNAL(ignorePointChanged()), m_ignorePoint, SLOT(toggle()));
292 
293  QVBoxLayout * rightLayout = new QVBoxLayout;
294  rightLayout->addWidget(m_lockPoint);
295  rightLayout->addWidget(m_ignorePoint);
296 
297  QHBoxLayout * mainLayout = new QHBoxLayout;
298  mainLayout->addLayout(leftLayout);
299  mainLayout->addStretch();
300  mainLayout->addLayout(rightLayout);
301 
302  // create the groupbox
303  QGroupBox * groupBox = new QGroupBox("Control Point");
304  groupBox->setLayout(mainLayout);
305 
306  return groupBox;
307  }
308 
309 
312 
313  m_leftCombo = new QComboBox;
314  m_leftCombo->view()->installEventFilter(this);
315  m_leftCombo->setToolTip("Choose left control measure");
316  m_leftCombo->setWhatsThis("Choose left control measure identified by "
317  "cube filename.");
318  connect(m_leftCombo, SIGNAL(activated(int)),
319  this, SLOT(selectLeftMeasure(int)));
320  m_lockLeftMeasure = new QCheckBox("Edit Lock Measure");
321  connect(m_lockLeftMeasure, SIGNAL(clicked(bool)),
322  this, SLOT(setLockLeftMeasure(bool)));
323  m_ignoreLeftMeasure = new QCheckBox("Ignore Measure");
324  connect(m_ignoreLeftMeasure, SIGNAL(clicked(bool)),
325  this, SLOT(setIgnoreLeftMeasure(bool)));
326  connect(this, SIGNAL(ignoreLeftChanged()),
327  m_ignoreLeftMeasure, SLOT(toggle()));
328  m_leftReference = new QLabel();
329  m_leftMeasureType = new QLabel();
330  m_leftSampShift = new QLabel();
331  m_leftSampShift->setToolTip("Sample shift between apriori and current");
332  m_leftSampShift->setWhatsThis("The shift between the apriori sample and "
333  "the current sample. The apriori sample is set "
334  "when creating a new measure.");
335  m_leftLineShift = new QLabel();
336  m_leftLineShift->setToolTip("Line shift between apriori and current");
337  m_leftLineShift->setWhatsThis("The shift between the apriori line and "
338  "the current line. The apriori line is set "
339  "when creating a new measure.");
340  m_leftGoodness = new QLabel();
341  m_leftGoodness->setToolTip("Goodness of Fit result from sub-pixel "
342  "registration.");
343  m_leftGoodness->setWhatsThis("Resulting Goodness of Fit from sub-pixel "
344  "registration.");
345  QVBoxLayout * leftLayout = new QVBoxLayout;
346  leftLayout->addWidget(m_leftCombo);
347  leftLayout->addWidget(m_lockLeftMeasure);
348  leftLayout->addWidget(m_ignoreLeftMeasure);
349  leftLayout->addWidget(m_leftReference);
350  leftLayout->addWidget(m_leftMeasureType);
351  leftLayout->addWidget(m_leftSampShift);
352  leftLayout->addWidget(m_leftLineShift);
353  leftLayout->addWidget(m_leftGoodness);
354 
355  QGroupBox * leftGroupBox = new QGroupBox("Left Measure");
356  leftGroupBox->setLayout(leftLayout);
357 
358  return leftGroupBox;
359  }
360 
361 
372 
373  // create widgets for the right groupbox
374  m_rightCombo = new QComboBox;
375  m_rightCombo->view()->installEventFilter(this);
376 
377  // Attach shortcuts to Match TOol's window for selecting right measures
378  // Note: Qt handles this memory for us since m_matchTool is the parent of these shortcuts
379  QShortcut *nextMeasure = new QShortcut(Qt::Key_PageDown, m_matchTool);
380  connect(nextMeasure, SIGNAL(activated()), this, SLOT(nextRightMeasure()));
381  QShortcut *prevMeasure = new QShortcut(Qt::Key_PageUp, m_matchTool);
382  connect(prevMeasure, SIGNAL(activated()), this, SLOT(previousRightMeasure()));
383 
384  m_rightCombo->setToolTip("Choose right control measure. "
385  "<strong>Shorcuts: PageUp/PageDown</strong>");
386  m_rightCombo->setWhatsThis("Choose right control measure identified by "
387  "cube filename. "
388  "Note: PageUp selects previous measure; "
389  "PageDown selects next measure.");
390  connect(m_rightCombo, SIGNAL(activated(int)),
391  this, SLOT(selectRightMeasure(int)));
392  m_lockRightMeasure = new QCheckBox("Edit Lock Measure");
393  connect(m_lockRightMeasure, SIGNAL(clicked(bool)),
394  this, SLOT(setLockRightMeasure(bool)));
395  m_ignoreRightMeasure = new QCheckBox("Ignore Measure");
396  connect(m_ignoreRightMeasure, SIGNAL(clicked(bool)),
397  this, SLOT(setIgnoreRightMeasure(bool)));
398  connect(this, SIGNAL(ignoreRightChanged()),
399  m_ignoreRightMeasure, SLOT(toggle()));
400  m_rightReference = new QLabel();
401  m_rightMeasureType = new QLabel();
402  m_rightSampShift = new QLabel();
403  m_rightSampShift->setToolTip(m_leftSampShift->toolTip());
404  m_rightSampShift->setWhatsThis(m_leftSampShift->whatsThis());
405  m_rightLineShift = new QLabel();
406  m_rightLineShift->setToolTip(m_leftLineShift->toolTip());
407  m_rightLineShift->setWhatsThis(m_leftLineShift->whatsThis());
408  m_rightGoodness = new QLabel();
409  m_rightGoodness->setToolTip(m_leftGoodness->toolTip());
410  m_rightGoodness->setWhatsThis(m_leftGoodness->whatsThis());
411 
412  // create right groupbox
413  QVBoxLayout * rightLayout = new QVBoxLayout;
414  rightLayout->addWidget(m_rightCombo);
415  rightLayout->addWidget(m_lockRightMeasure);
416  rightLayout->addWidget(m_ignoreRightMeasure);
417  rightLayout->addWidget(m_rightReference);
418  rightLayout->addWidget(m_rightMeasureType);
419  rightLayout->addWidget(m_rightSampShift);
420  rightLayout->addWidget(m_rightLineShift);
421  rightLayout->addWidget(m_rightGoodness);
422 
423  QGroupBox * rightGroupBox = new QGroupBox("Right Measure");
424  rightGroupBox->setLayout(rightLayout);
425 
426  return rightGroupBox;
427  }
428 
429 
432 
433  QToolBar *toolBar = new QToolBar("Template Editor ToolBar");
434 
435  toolBar->addAction(m_openTemplateFile);
436  toolBar->addSeparator();
437  toolBar->addAction(m_saveTemplateFile);
438  toolBar->addAction(m_saveTemplateFileAs);
439 
440  m_templateEditor = new QTextEdit;
441  connect(m_templateEditor, SIGNAL(textChanged()), this,
442  SLOT(setTemplateModified()));
443 
444  QVBoxLayout *mainLayout = new QVBoxLayout;
445  mainLayout->addWidget(toolBar);
446  mainLayout->addWidget(m_templateEditor);
447 
448  m_templateEditorWidget = new QWidget;
449  m_templateEditorWidget->setLayout(mainLayout);
450  }
451 
452 
461 
462  m_saveNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSave.png"),
463  "Save Control Network ...",
464  m_matchTool);
465  m_saveNet->setShortcut(Qt::CTRL + Qt::Key_S);
466  m_saveNet->setToolTip("Save current control network");
467  m_saveNet->setStatusTip("Save current control network");
468  QString whatsThis = "<b>Function:</b> Saves the current <i>"
469  "control network</i>";
470  m_saveNet->setWhatsThis(whatsThis);
471  connect(m_saveNet, SIGNAL(triggered()), this, SLOT(saveNet()));
472 
473  m_saveAsNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"),
474  "Save Control Network &As...",
475  m_matchTool);
476  m_saveAsNet->setToolTip("Save current control network to chosen file");
477  m_saveAsNet->setStatusTip("Save current control network to chosen file");
478  whatsThis = "<b>Function:</b> Saves the current <i>"
479  "control network</i> under chosen filename";
480  m_saveAsNet->setWhatsThis(whatsThis);
481  connect(m_saveAsNet, SIGNAL(triggered()), this, SLOT(saveAsNet()));
482 
483  m_closeMatchTool = new QAction(QPixmap(toolIconDir() + "/fileclose.png"),
484  "&Close",
485  m_matchTool);
486  m_closeMatchTool->setToolTip("Close this window");
487  m_closeMatchTool->setStatusTip("Close this window");
488  m_closeMatchTool->setShortcut(Qt::ALT + Qt::Key_F4);
489  whatsThis = "<b>Function:</b> Closes the Match Tool window for this point "
490  "<p><b>Shortcut:</b> Alt+F4 </p>";
491  m_closeMatchTool->setWhatsThis(whatsThis);
492  connect(m_closeMatchTool, SIGNAL(triggered()), m_matchTool, SLOT(close()));
493 
494  m_showHideTemplateEditor = new QAction(QPixmap(toolIconDir() + "/view_text.png"),
495  "&View/edit registration template",
496  m_matchTool);
497  m_showHideTemplateEditor->setCheckable(true);
498  m_showHideTemplateEditor->setToolTip("View and/or edit the registration template");
499  m_showHideTemplateEditor->setStatusTip("View and/or edit the registration template");
500  whatsThis = "<b>Function:</b> Displays the curent registration template. "
501  "The user may edit and save changes under a chosen filename.";
502  m_showHideTemplateEditor->setWhatsThis(whatsThis);
503  connect(m_showHideTemplateEditor, SIGNAL(triggered()), this,
504  SLOT(showHideTemplateEditor()));
505 
506  m_saveChips = new QAction(QPixmap(toolIconDir() + "/window_new.png"),
507  "Save registration chips",
508  m_matchTool);
509  m_saveChips->setToolTip("Save registration chips");
510  m_saveChips->setStatusTip("Save registration chips");
511  whatsThis = "<b>Function:</b> Save registration chips to file. "
512  "Each chip: pattern, search, fit will be saved to a separate file.";
513  m_saveChips->setWhatsThis(whatsThis);
514  connect(m_saveChips, SIGNAL(triggered()), this, SLOT(saveChips()));
515 
516  m_openTemplateFile = new QAction(QPixmap(toolIconDir() + "/fileopen.png"),
517  "&Open registration template",
518  m_matchTool);
519  m_openTemplateFile->setToolTip("Set registration template");
520  m_openTemplateFile->setStatusTip("Set registration template");
521  whatsThis = "<b>Function:</b> Allows user to select a new file to set as "
522  "the registration template";
523  m_openTemplateFile->setWhatsThis(whatsThis);
524  connect(m_openTemplateFile, SIGNAL(triggered()), this, SLOT(openTemplateFile()));
525 
526  m_saveTemplateFile = new QAction(QPixmap(toolIconDir() + "/mActionFileSave.png"),
527  "&Save template file",
528  m_matchTool);
529  m_saveTemplateFile->setToolTip("Save the template file");
530  m_saveTemplateFile->setStatusTip("Save the template file");
531  m_saveTemplateFile->setWhatsThis("Save the registration template file");
532  connect(m_saveTemplateFile, SIGNAL(triggered()), this,
533  SLOT(saveTemplateFile()));
534 
535  m_saveTemplateFileAs = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"),
536  "&Save template as...",
537  m_matchTool);
538  m_saveTemplateFileAs->setToolTip("Save the template file as");
539  m_saveTemplateFileAs->setStatusTip("Save the template file as");
540  m_saveTemplateFileAs->setWhatsThis("Save the registration template file as");
541  connect(m_saveTemplateFileAs, SIGNAL(triggered()), this,
542  SLOT(saveTemplateFileAs()));
543 
544  m_whatsThis = new QAction(QPixmap(toolIconDir() + "/contexthelp.png"),
545  "&Whats's This",
546  m_matchTool);
547  m_whatsThis->setShortcut(Qt::SHIFT | Qt::Key_F1);
548  m_whatsThis->setToolTip("Activate What's This and click on items on "
549  "user interface to see more information.");
550  connect(m_whatsThis, SIGNAL(triggered()), this, SLOT(enterWhatsThisMode()));
551 
552  m_showHelp = new QAction(QPixmap(toolIconDir() + "/help-contents.png"), "Help", m_matchTool);
553  m_showHelp->setToolTip("Help");
554  connect(m_showHelp, SIGNAL(triggered()), this, SLOT(showHelp()));
555 
556  }
557 
558 
559 
570 
571  QMenu *fileMenu = m_matchTool->menuBar()->addMenu("&File");
572  fileMenu->addAction(m_saveNet);
573  fileMenu->addAction(m_saveAsNet);
574  fileMenu->addAction(m_closeMatchTool);
575 
576  QMenu * regMenu = m_matchTool->menuBar()->addMenu("&Registration");
577  regMenu->addAction(m_openTemplateFile);
578  regMenu->addAction(m_showHideTemplateEditor);
579  regMenu->addAction(m_saveChips);
580 
581  QMenu *helpMenu = m_matchTool->menuBar()->addMenu("&Help");
582  helpMenu->addAction(m_whatsThis);
583  }
584 
585 
586  void MatchTool::createToolBars() {
587 
588  QToolBar * toolBar = new QToolBar;
589  toolBar->setObjectName("TemplateEditorToolBar");
590  toolBar->setFloatable(false);
591  toolBar->addAction(m_saveNet);
592  toolBar->addSeparator();
593  toolBar->addAction(m_showHideTemplateEditor);
594  toolBar->addAction(m_saveChips);
595  toolBar->addAction(m_showHelp);
596  toolBar->addAction(m_whatsThis);
597 
598  m_matchTool->addToolBar(Qt::TopToolBarArea, toolBar);
599  }
600 
601 
602 
615  QAction *action = new QAction(pad);
616  action->setIcon(QPixmap(toolIconDir()+"/stock_draw-connector-with-arrows.png"));
617  action->setToolTip("Match Tool - Control Point Editor (T)");
618  action->setShortcut(Qt::Key_T);
619  return action;
620  }
621 
622 
623 
624  QWidget *MatchTool::createToolBarWidget(QStackedWidget *parent) {
625 
626  QWidget *hbox = new QWidget;
627 
628  QToolButton *openNetButton = new QToolButton(hbox);
629  openNetButton->setIcon(QPixmap(toolIconDir() + "/fileopen.png"));
630  openNetButton->setIconSize(QSize(22,22));
631  openNetButton->setToolTip("Open control network");
632  openNetButton->setEnabled(true);
633  connect(openNetButton, SIGNAL(clicked()), this, SLOT(openNet()));
634 
635  QToolButton *saveAsNetButton = new QToolButton(hbox);
636  saveAsNetButton->setDefaultAction(m_saveAsNet);
637  saveAsNetButton->setIconSize(QSize(22,22));
638 
639  QToolButton *saveNetButton = new QToolButton(hbox);
640  saveNetButton->setDefaultAction(m_saveNet);
641  saveNetButton->setIconSize(QSize(22,22));
642 
643  QToolButton *helpButton = new QToolButton(hbox);
644  helpButton->setDefaultAction(m_showHelp);
645  helpButton->setIconSize(QSize(22, 22));
646 
647  QHBoxLayout *layout = new QHBoxLayout;
648  layout->setMargin(0);
649  layout->addWidget(openNetButton);
650  layout->addWidget(saveAsNetButton);
651  layout->addWidget(saveNetButton);
652  layout->addStretch();
653  layout->addWidget(helpButton);
654  hbox->setLayout(layout);
655 
656  return hbox;
657  }
658 
659 
660 
661  void MatchTool::activateTool() {
662 
663  if (!m_controlNet) {
664  m_controlNet = new ControlNet();
665  }
666  }
667 
668 
669 
680 
681  SerialNumberList list(false);
682  foreach (MdiCubeViewport *mvp, *cubeViewportList()) {
683  try {
684  // Attempt to Compose Serial number and see if list already has duplicate. If so,
685  // use filenames as serial numbers for both cubes. This needs to be checked because
686  // coreg networks will often have 2 cubes with the same serial number.make cl
687  QString sn = SerialNumber::Compose(mvp->cube()->fileName(), true);
688  if (list.hasSerialNumber(sn)) {
689  // TODO Before removing serial number, make sure current network does not have
690  // measures with old serial number. If it does, now what? Print error?
691  //
692  // Remove old serial number & change to filename
693  FileName fileName = Isis::FileName(list.fileName(sn));
694  list.remove(sn);
695  list.add(fileName.name(),fileName.expanded());
696  // Add new serial number as filename
697  list.add(Isis::FileName(mvp->cube()->fileName()).name(),
698  mvp->cube()->fileName());
699  }
700  else {
701  list.add(mvp->cube()->fileName(), true);
702  }
703  }
704  catch (...) {
705  }
706  }
707  return list;
708  }
709 
710 
711 
712  QString MatchTool::serialNumber(MdiCubeViewport *mvp) {
713 
714  QString serialNumber;
715  try {
717  serialNumber = list.serialNumber(mvp->cube()->fileName());
718 // serialNumber = serialNumberList().SerialNumber(mvp->cube()->fileName());
719  }
720  catch (IException &e) {
721  serialNumber = "Unknown";
722  }
723  return serialNumber;
724 
725  }
726 
727 
728 
789 
790  // Read original measures from the network for comparison with measures
791  // that have been edited
792  ControlMeasure *origLeftMeasure =
793  m_editPoint->GetMeasure(m_leftMeasure->GetCubeSerialNumber());
794  ControlMeasure *origRightMeasure =
795  m_editPoint->GetMeasure(m_rightMeasure->GetCubeSerialNumber());
796  // Neither measure has changed, return
797  if (*origLeftMeasure == *m_leftMeasure && *origRightMeasure == *m_rightMeasure) {
798  return;
799  }
800 
801  if (m_editPoint->IsIgnored()) {
802  QString message = "You are saving changes to a measure on an ignored ";
803  message += "point. Do you want to set Ignore = False on the point and ";
804  message += "both measures?";
805  switch (QMessageBox::question(m_matchTool, "Match Tool Save Measure",
806  message, "&Yes", "&No", 0, 0)) {
807  // Yes: set Ignore=false for the point and measures and save point
808  case 0:
809  m_editPoint->SetIgnored(false);
810  emit ignorePointChanged();
811  if (m_leftMeasure->IsIgnored()) {
812  m_leftMeasure->SetIgnored(false);
813  emit ignoreLeftChanged();
814  }
815  if (m_rightMeasure->IsIgnored()) {
816  m_rightMeasure->SetIgnored(false);
817  emit ignoreRightChanged();
818  }
819  // No: keep Ignore=true and save measure
820  case 1:
821  break;
822  }
823  }
824 
825  bool savedAMeasure = false;
826  // Error check both measures for edit lock, ignore status and reference
827  bool leftChangeOk = validateMeasureChange(m_leftMeasure);
828  if (leftChangeOk) {
829  m_leftMeasure->SetChooserName(Application::UserName());
830  *origLeftMeasure = *m_leftMeasure;
831  savedAMeasure = true;
832  }
833  bool rightChangeOk = validateMeasureChange(m_rightMeasure);
834  if (rightChangeOk) {
835  m_rightMeasure->SetChooserName(Application::UserName());
836  *origRightMeasure = *m_rightMeasure;
837  savedAMeasure = true;
838  }
839 
840  // If left measure == right measure, update left
841  if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
842  *m_leftMeasure = *m_rightMeasure;
843  // Update left measure of pointEditor
844  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube,
845  m_editPoint->GetId());
846  }
847 
848  // Change Save Point button text to red
849  if (savedAMeasure) {
851  }
852 
853  emit editPointChanged();
854 
855  // Update measure info
859 
860  }
861 
862 
863 
864  bool MatchTool::validateMeasureChange(ControlMeasure *m) {
865 
866 
867  // Read original measures from the network for comparison with measures
868  // that have been edited
869  ControlMeasure *origMeasure =
870  m_editPoint->GetMeasure(m->GetCubeSerialNumber());
871 
872  // If measure hasn't changed, return false, to keep original
873 
874  if (*m == *origMeasure) return false;
875 
876  // Is measure on Left or Right? This is needed to print correct information
877  // to users in identifying the measure and for updating information widgets.
878  QString side = "right";
879  if (m->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
880  side = "left";
881  }
882 
883  // Only print error if both original measure in network and the current
884  // edit measure are both editLocked and measure has changed. If only the edit measure is
885  // locked, then user just locked and it needs to be saved.
886  // Do not use this classes IsMeasureLocked since we actually want to
887  // check the original againsted the edit measure and we don't care
888  // if this is a reference measure. The check for moving a reference is
889  // done below.
890  if (origMeasure->IsEditLocked() && m->IsEditLocked()) {
891  QString message = "The " + side + " measure is editLocked ";
892  message += "for editing. Do you want to set EditLock = False for this ";
893  message += "measure?";
894  int response = QMessageBox::question(m_matchTool, "Match Tool Save Measure",
895  message, QMessageBox::Yes | QMessageBox::No);
896  // Yes: set EditLock=false for the right measure
897  if (response == QMessageBox::Yes) {
898  m->SetEditLock(false);
899  if (side == "left") {
900  m_lockLeftMeasure->setChecked(false);
901  }
902  else {
903  m_lockRightMeasure->setChecked(false);
904  }
905  }
906  // No: keep EditLock=true and do NOT save measure
907  else {
908  return false;
909  }
910  }
911 
912  if (origMeasure->IsIgnored() && m->IsIgnored()) {
913  QString message = "The " + side + "measure is ignored. ";
914  message += "Do you want to set Ignore = False on the measure?";
915  switch(QMessageBox::question(m_matchTool, "Match Tool Save Measure",
916  message, "&Yes", "&No", 0, 0)){
917  // Yes: set Ignore=false for the right measure and save point
918  case 0:
919  m->SetIgnored(false);
920  if (side == "left") {
921  emit ignoreLeftChanged();
922  }
923  else {
924  emit ignoreRightChanged();
925  }
926  // No: keep Ignore=true and save point
927  case 1:
928  break;;
929  }
930  }
931 
932  // If measure is explicit reference and it has moved,warn user
933  ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
934  if (m_editPoint->IsReferenceExplicit()) {
935  if (refMeasure->GetCubeSerialNumber() == m->GetCubeSerialNumber()) {
936  if (m->GetSample() != origMeasure->GetSample() || m->GetLine() != origMeasure->GetLine()) {
937  QString message = "You are making a change to the reference measure. You ";
938  message += "may need to move all of the other measures to match the new ";
939  message += " coordinate of the reference measure. Do you really want to ";
940  message += " change the reference measure's location? ";
941  switch(QMessageBox::question(m_matchTool, "Match Tool Save Measure",
942  message, "&Yes", "&No", 0, 0)){
943  // Yes: Save measure
944  case 0:
945  break;
946  // No: keep original reference, return without saving
947  case 1:
948  loadPoint();
949  return false;
950  }
951  }
952  }
953  // New reference measure
954  else if (side == "left" && (refMeasure->GetCubeSerialNumber() != m->GetCubeSerialNumber())) {
955  if (m_coregNet) {
956  QString message = "This control network was created by the <i>coreg</i> program, and the "
957  "reference measure needs to remain the same as what <i>coreg</i> set. "
958  "Therefore, you cannot change which measure is the reference. To "
959  "save this point, move the reference measure (measure in BOLD) back "
960  "to the left side.";
961  QMessageBox::information(m_matchTool, "Cannot change reference", message);
962  }
963  else {
964  QString message = "This point already contains a reference measure. ";
965  message += "Would you like to replace it with the measure on the left?";
966  int response = QMessageBox::question(m_matchTool,
967  "Match Tool Save Measure", message,
968  QMessageBox::Yes | QMessageBox::No,
969  QMessageBox::Yes);
970  // Replace reference measure
971  if (response == QMessageBox::Yes) {
972  // Update measure file combo boxes: old reference normal font,
973  // new reference bold font
974  QString file = serialNumberList().fileName(m_leftMeasure->GetCubeSerialNumber());
975  QString fname = FileName(file).name();
976  int iref = m_leftCombo->findText(fname);
977 
978  // Save normal font from new reference measure
979  QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
980  m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
981  iref = m_rightCombo->findText(fname);
982  m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
983 
984  file = serialNumberList().fileName(refMeasure->GetCubeSerialNumber());
985  fname = FileName(file).name();
986  iref = m_leftCombo->findText(fname);
987  m_leftCombo->setItemData(iref,font,Qt::FontRole);
988  iref = m_rightCombo->findText(fname);
989  m_rightCombo->setItemData(iref,font,Qt::FontRole);
990 
991  m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
992  }
993  }
994  }
995  }
996  else {
997  // No explicit reference, If left, set explicit reference
998  if (side == "left") {
999  m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
1000  }
1001  }
1002 
1003  // All test pass, return true (ok to change measure)
1004  return true;
1005 
1006 
1007  }
1008 
1009 
1010 
1011  /*
1012  * Change which measure is the reference.
1013  *
1014  * @author 2012-04-26 Tracie Sucharski - moved funcitonality from measureSaved
1015  *
1016  * @internal
1017  * @history 2012-06-12 Tracie Sucharski - Moved check for ground loaded on left from the
1018  * measureSaved method.
1019  */
1020  void MatchTool::checkReference() {
1021 
1022  // Check if ControlPoint has reference measure, if reference Measure is
1023  // not the same measure that is on the left chip viewport, set left
1024  // measure as reference.
1025  ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
1026  if (refMeasure->GetCubeSerialNumber() != m_leftMeasure->GetCubeSerialNumber()) {
1027  QString message = "This point already contains a reference measure. ";
1028  message += "Would you like to replace it with the measure on the left?";
1029  int response = QMessageBox::question(m_matchTool,
1030  "Match Tool Save Measure", message,
1031  QMessageBox::Yes | QMessageBox::No,
1032  QMessageBox::Yes);
1033  // Replace reference measure
1034  if (response == QMessageBox::Yes) {
1035  // Update measure file combo boxes: old reference normal font,
1036  // new reference bold font
1037  QString file = serialNumberList().fileName(m_leftMeasure->GetCubeSerialNumber());
1038  QString fname = FileName(file).name();
1039  int iref = m_leftCombo->findText(fname);
1040 
1041  // Save normal font from new reference measure
1042  QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
1043  m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1044  iref = m_rightCombo->findText(fname);
1045  m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1046 
1047  file = serialNumberList().fileName(refMeasure->GetCubeSerialNumber());
1048  fname = FileName(file).name();
1049  iref = m_leftCombo->findText(fname);
1050  m_leftCombo->setItemData(iref,font,Qt::FontRole);
1051  iref = m_rightCombo->findText(fname);
1052  m_rightCombo->setItemData(iref,font,Qt::FontRole);
1053 
1054  m_editPoint->SetRefMeasure(m_leftMeasure->GetCubeSerialNumber());
1055  }
1056 
1057  // ??? Need to set rest of measures to Candiate and add more warning. ???//
1058  }
1059 
1060 
1061  }
1062 
1063 
1064 
1080 
1081  // Make a copy of edit point for updating the control net since the edit
1082  // point is still loaded in the point editor.
1083  ControlPoint *updatePoint = new ControlPoint;
1084  *updatePoint = *m_editPoint;
1085 
1086  // If edit point exists in the network, save the updated point. If it
1087  // does not exist, add it.
1088  if (m_controlNet->ContainsPoint(updatePoint->GetId())) {
1089  ControlPoint *p;
1090  p = m_controlNet->GetPoint(QString(updatePoint->GetId()));
1091  *p = *updatePoint;
1092  delete updatePoint;
1093  updatePoint = NULL;
1094  }
1095  else {
1096  m_controlNet->AddPoint(updatePoint);
1097  }
1098 
1099  // Change Save Measure button text back to default
1100  m_savePoint->setPalette(m_saveDefaultPalette);
1101 
1102  // emit signal so the nav tool can update edit point
1103  emit editPointChanged();
1104  // At exit, or when opening new net, use for prompting user for a save
1105  m_netChanged = true;
1106  // Refresh chipViewports to show new positions of controlPoints
1107  m_pointEditor->refreshChips();
1108  }
1109 
1110 
1111 
1121  void MatchTool::setLockPoint (bool lock) {
1122  if (m_editPoint == NULL) return;
1123 
1124  m_editPoint->SetEditLock(lock);
1126  }
1127 
1128 
1129 
1140  void MatchTool::setIgnorePoint (bool ignore) {
1141  if (m_editPoint == NULL) return;
1142 
1143  ControlPoint::Status status = m_editPoint->SetIgnored(ignore);
1144  if (status == ControlPoint::PointLocked) {
1145  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1146  QString message = "Unable to change Ignored on point. Set EditLock ";
1147  message += " to False.";
1148  QMessageBox::critical(m_matchTool, "Error", message);
1149  return;
1150  }
1152  }
1153 
1154 
1155 
1156 
1173 
1174  if (m_editPoint->IsEditLocked()) {
1175  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1176  QMessageBox::warning(m_matchTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1177  " before changing a measure.");
1178  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1179  return;
1180  }
1181 
1182  if (m_leftMeasure != NULL) m_leftMeasure->SetEditLock(lock);
1183 
1184  // If the right chip is the same as the left chip , update the right editLock
1185  // box.
1186  if (m_rightMeasure != NULL) {
1187  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1188  m_rightMeasure->SetEditLock(lock);
1189  m_lockRightMeasure->setChecked(lock);
1190  }
1191  }
1192  emit measureChanged();
1193  }
1194 
1195 
1213  void MatchTool::setIgnoreLeftMeasure (bool ignore) {
1214  if (m_leftMeasure != NULL) m_leftMeasure->SetIgnored(ignore);
1215 
1216  // If the right chip is the same as the left chip , update the right
1217  // ignore box.
1218  if (m_rightMeasure != NULL) {
1219  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1220  m_rightMeasure->SetIgnored(ignore);
1221  m_ignoreRightMeasure->setChecked(ignore);
1222  }
1223  }
1224  emit measureChanged();
1225  }
1226 
1227 
1244 
1245  if (m_editPoint->IsEditLocked()) {
1246  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1247  QMessageBox::warning(m_matchTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1248  " before changing a measure.");
1249  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1250  return;
1251  }
1252 
1253  if (m_rightMeasure != NULL) m_rightMeasure->SetEditLock(lock);
1254 
1255  // If the left chip is the same as the right chip , update the left editLock box.
1256  if (m_leftMeasure != NULL) {
1257  if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
1258  m_leftMeasure->SetEditLock(lock);
1259  m_lockLeftMeasure->setChecked(lock);
1260  }
1261  }
1262  emit measureChanged();
1263  }
1264 
1265 
1284  if (m_rightMeasure != NULL) m_rightMeasure->SetIgnored(ignore);
1285 
1286  // If the right chip is the same as the left chip , update the right
1287  // ignore blox.
1288  if (m_leftMeasure != NULL) {
1289  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1290  m_leftMeasure->SetIgnored(ignore);
1291  m_ignoreLeftMeasure->setChecked(ignore);
1292  }
1293  }
1294  emit measureChanged();
1295  }
1296 
1297 
1298 
1299  void MatchTool::openNet() {
1300 
1301  if (m_controlNet) {
1302  if (m_controlNet->GetNumPoints() != 0 && m_netChanged) {
1303  QString message = "A control net has already been created. Do you want to save before "
1304  "opening a new control net?";
1305  int response = QMessageBox::question(m_matchTool, "Save current control net?",
1306  message,
1307  QMessageBox::Yes | QMessageBox::No,
1308  QMessageBox::Yes);
1309  // Yes: Save old net, so return without opening network.
1310  if (response == QMessageBox::Yes) {
1311  saveAsNet();
1312  }
1313  m_matchTool->setVisible(false);
1314  }
1315  delete m_controlNet;
1316  m_controlNet = NULL;
1317  m_editPoint = NULL;
1318  m_newPoint = NULL;
1319  m_newPointDialog = NULL;
1320  }
1321 
1322  // At exit, or when opening new net, use for prompting user for a save
1323  m_netChanged = false;
1324 
1325  QApplication::restoreOverrideCursor();
1326  QString filter = "Control net (*.net *.cnet *.ctl);;";
1327  filter += "Pvl file (*.pvl);;";
1328  filter += "Text file (*.txt);;";
1329  filter += "All (*)";
1330  m_cnetFileName = QFileDialog::getOpenFileName((QWidget *)parent(),
1331  "Select a control network",
1332  ".",
1333  filter);
1334  QApplication::setOverrideCursor(Qt::WaitCursor);
1335  if (!m_cnetFileName.isEmpty()) {
1336  try {
1337  Progress progress;
1338  m_controlNet = new ControlNet(m_cnetFileName, &progress);
1339  m_coregNet = false;
1340  m_coregReferenceSN = "";
1341  if (m_controlNet->GetNetworkId() == "Coreg") {
1342  m_coregNet = true;
1343  // Find reference image of first point, the rest of the points will have the same
1344  // reference. When creating new point, use the same reference.
1345  m_coregReferenceSN = m_controlNet->GetPoint(0)->GetReferenceSN();
1346  }
1347  }
1348  catch (IException &e) {
1349  QApplication::restoreOverrideCursor();
1350  QString message = "Invalid control network. \n";
1351  message += e.toString();
1352  QMessageBox::critical(m_matchTool, "Error", message);
1353  m_cnetFileName.clear();
1354  delete m_controlNet;
1355  m_controlNet = NULL;
1356  return;
1357  }
1358  }
1359  QApplication::restoreOverrideCursor();
1360  m_matchTool->setWindowTitle("Match Tool - Control Network File: " + m_cnetFileName);
1361  m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName);
1362 
1364  }
1365 
1366 
1367 
1374  if (m_cnetFileName.isEmpty()) {
1375  QString message = "This is a new network, you must select "
1376  "\"Save As\" under the File Menu or on the toolbar.";
1377  QMessageBox::critical(m_matchTool, "Error", message);
1378  return;
1379  }
1380  try {
1381  m_controlNet->Write(m_cnetFileName);
1382  m_netChanged = false;
1383  }
1384  catch (IException &e) {
1385  QMessageBox::critical(m_matchTool, tr("Error Writing Control Net"), e.what());
1386  return;
1387  }
1388  }
1389 
1390 
1391 
1401 
1402  QString fn = QFileDialog::getSaveFileName(m_matchTool,
1403  "Choose filename to save under",
1404  ".",
1405  "Control Files (*.net)");
1406 
1407  //Make sure the filename is valid
1408  if(!fn.isEmpty()) {
1409  try {
1410  m_controlNet->Write(fn);
1411  m_netChanged = false;
1412  }
1413  catch (IException &e) {
1414  QMessageBox::critical(m_matchTool, tr("Error Writing Control Net"), e.what());
1415  return;
1416  }
1417  m_cnetFileName = fn;
1418  m_matchTool->setWindowTitle("Match Tool - Control Network File: " + m_cnetFileName);
1419  m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName);
1420  }
1421  //The user cancelled, or the filename is empty
1422  else {
1423  return;
1424  }
1425 
1426  }
1427 
1428 
1429 
1457  void MatchTool::mouseButtonRelease(QPoint p, Qt::MouseButton s) {
1458  MdiCubeViewport *mvp = cubeViewport();
1459  if (mvp == NULL) return;
1460 
1461  QString file = mvp->cube()->fileName();
1462  QString sn = serialNumberList().serialNumber(file);
1463 
1464  double samp,line;
1465  mvp->viewportToCube(p.x(),p.y(),samp,line);
1466 
1467  if (s == Qt::LeftButton) {
1468 
1469  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1470  QString message = "No points exist for editing. Create points ";
1471  message += "using the right mouse button.";
1472  QMessageBox::warning(m_matchTool, "Warning", message);
1473  return;
1474  }
1475 
1476  // Find closest control point in network
1477  QString sn = serialNumberList().serialNumber(file);
1478  ControlPoint *point = NULL;
1479  try {
1480  point = m_controlNet->FindClosest(sn, samp, line);
1481  }
1482  catch (IException &e) {
1483  QString message = "Cannot find point for editing.";
1484  message += e.toString();
1485  QMessageBox::warning(m_matchTool, "Warning", message);
1486  return;
1487  }
1488 
1489  modifyPoint(point);
1490  }
1491  else if (s == Qt::MidButton) {
1492  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1493  QString message = "No points exist for deleting. Create points ";
1494  message += "using the right mouse button.";
1495  QMessageBox::warning(m_matchTool, "Warning", message);
1496  return;
1497  }
1498 
1499  // Find closest control point in network
1500  ControlPoint *point = m_controlNet->FindClosest(sn, samp, line);
1501 
1502  if (point == NULL) {
1503  QString message = "No points exist for deleting. Create points ";
1504  message += "using the right mouse button.";
1505  QMessageBox::warning(m_matchTool, "Warning", message);
1506  return;
1507  }
1508 
1509  deletePoint(point);
1510  }
1511  else if (s == Qt::RightButton) {
1512  if (m_newPointDialog) {
1513  addMeasure(mvp, samp, line);
1514  }
1515  else {
1516  try {
1517  createPoint(mvp, samp, line);
1518  m_leftFile = mvp->cube()->fileName();
1519  }
1520  catch (IException &e) {
1521  QString message = "Cannot create control point.\n\n";
1522  message += e.toString();
1523  QMessageBox::critical(m_matchTool, "Error", message);
1524  return;
1525  }
1526  }
1527  }
1528  }
1529 
1530 
1531 
1532  QStringList MatchTool::missingCubes(ControlPoint *point) {
1533 
1534  // Make sure all measures are loaded into viewports, otherwise we cannot edit this point
1535  QStringList missingCubes;
1536  for (int i=0; i<point->GetNumMeasures(); i++) {
1537  ControlMeasure &m = *(*point)[i];
1539  missingCubes << m.GetCubeSerialNumber();
1540  }
1541  }
1542  return missingCubes;
1543  }
1544 
1545 
1546 
1553  void MatchTool::createPoint(MdiCubeViewport *cvp, double sample, double line) {
1554 
1555  m_newPointDialog = new MatchToolNewPointDialog(*m_controlNet, m_lastUsedPointId, m_matchTool);
1556  connect(m_newPointDialog, SIGNAL(measuresFinished()), this, SLOT(doneWithMeasures()));
1557  connect(m_newPointDialog, SIGNAL(newPointCanceled()), this, SLOT(cancelNewPoint()));
1558 
1559  QStringList images;
1560  for (int i = 0; i < (int)cubeViewportList()->size(); i++) {
1561  FileName cubeFile = (*(cubeViewportList()))[i]->cube()->fileName();
1562  images<<cubeFile.name();
1563  }
1564  m_newPointDialog->setFiles(images);
1565  m_newPointDialog->show();
1566 
1567  // Highlight the current cubeViewport
1568  QString current = FileName(cvp->cube()->fileName()).name();
1569  m_newPointDialog->highlightFile(current);
1570 
1571  m_newPoint = new ControlPoint();
1572  m_newPoint->SetType(ControlPoint::Free);
1573  m_newPoint->SetChooserName(Application::UserName());
1574 
1575  ControlMeasure *m = new ControlMeasure;
1576  m->SetCubeSerialNumber(serialNumber(cvp));
1577  m->SetCoordinate(sample, line);
1579  m->SetDateTime();
1581  m_newPoint->Add(m);
1582 
1584  }
1585 
1586 
1587 
1588  void MatchTool::addMeasure(MdiCubeViewport *cvp, double sample, double line) {
1589 
1590  // Highlight the current cubeViewport
1591  QString current = FileName(cvp->cube()->fileName()).name();
1592  m_newPointDialog->highlightFile(current);
1593  m_newPointDialog->raise();
1594 
1595  ControlMeasure *m = new ControlMeasure;
1596  m->SetCubeSerialNumber(serialNumber(cvp));
1597 
1598  // If serial number already exists, delete old measure before creating new
1599  if (m_newPoint->HasSerialNumber(serialNumber(cvp))) {
1600  m_newPoint->Delete(m_newPoint->GetMeasure(serialNumber(cvp)));
1601  }
1602  m->SetCoordinate(sample, line);
1604  m->SetDateTime();
1606  m_newPoint->Add(m);
1607 
1609  }
1610 
1611 
1612 
1613  void MatchTool::doneWithMeasures() {
1614 
1615  m_lastUsedPointId = m_newPointDialog->pointId();
1616  m_newPoint->SetId(m_lastUsedPointId);
1617 // // Add new control point to control network
1618 // m_controlNet->AddPoint(m_newPoint);
1619 // // Read newly added point
1620 // // TODO Make sure pt exists
1621 // m_editPoint = m_controlNet->GetPoint((QString) m_newPoint->GetId());
1622 
1623  // If this is a coreg network, make sure the reference SN exists in the new point
1624  // and set it to the reference measure.
1625  if (m_coregNet) {
1626  if (!m_newPoint->HasSerialNumber(m_coregReferenceSN)) {
1627  QString message = "This is a coreg network which needs the cube with serial number " +
1628  m_coregReferenceSN + " as the reference measure. This new control point does "
1629  "not have a measure for that serial number, so this point cannot be created until "
1630  "the cube listed above is added (Right-click on cube).";
1631  QMessageBox::critical(m_matchTool, "Error", message);
1632  m_newPointDialog->show();
1633  return;
1634  }
1635  // Set the reference measure to match the rest of the points
1636  m_newPoint->SetRefMeasure(m_newPoint->GetMeasure(m_coregReferenceSN));
1637  }
1638 
1639  // If the editPoint has been used, but there is not currently a network, delete the editPoint
1640  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1641  delete m_editPoint;
1642  m_editPoint = NULL;
1643  }
1644  m_editPoint = m_newPoint;
1645 
1646  m_newPoint = NULL;
1647  delete m_newPointDialog;
1648  m_newPointDialog = NULL;
1649 
1650  // Load new point in MatchTool
1651  loadPoint();
1652  m_matchTool->setVisible(true);
1653  m_matchTool->raise();
1654 
1655  emit editPointChanged();
1657  }
1658 
1659 
1660 
1661  void MatchTool::cancelNewPoint() {
1662 
1663  delete m_newPointDialog;
1664  m_newPointDialog = NULL;
1665  delete m_newPoint;
1666  m_newPoint = NULL;
1667  m_leftFile.clear();
1668 
1670 
1671  }
1672 
1673 
1674 
1694 
1695  QStringList mCubes = missingCubes(point);
1696  if (mCubes.size() > 0) {
1697  QString msgTitle = "Missing Cubes";
1698  QString message = "This point is missing cubes for the following measures and cannot be ";
1699  message += "loaded into the editor. Do you still want to delete this point?\n\n";
1700  for (int i=0; i<mCubes.size(); i++) {
1701  message += mCubes.at(i) + "\n";
1702  }
1703  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1704  Qt::Dialog);
1705  QPushButton *yesButton = msgBox.addButton("Yes", QMessageBox::AcceptRole);
1706  QPushButton *noButton = msgBox.addButton("No", QMessageBox::RejectRole);
1707  msgBox.setDefaultButton(yesButton);
1708  msgBox.exec();
1709  if (msgBox.clickedButton() == noButton) {
1710  return;
1711  }
1712  else {
1713  m_matchTool->setVisible(false);
1714  }
1715 
1716  }
1717 
1718  // Make a copy and make sure editPoint is a copy (which means it does not
1719  // have a parent network.
1720  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1721  delete m_editPoint;
1722  m_editPoint = NULL;
1723  }
1724  m_editPoint = new ControlPoint;
1725  *m_editPoint = *point;
1726 
1727  // No missing cubes, load edit point as usual
1728  if (mCubes.size() == 0) {
1729  loadPoint();
1730 
1731  // Change point in viewport to red so user can see what point they are
1732  // about to delete.
1733  // the nav tool will update edit point
1734  emit editPointChanged();
1735  }
1736 
1737  MatchToolDeletePointDialog *deletePointDialog = new MatchToolDeletePointDialog;
1738  QString CPId = m_editPoint->GetId();
1739  deletePointDialog->pointIdValue->setText(CPId);
1740  // Need all files for this point
1741  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1742  ControlMeasure &m = *(*m_editPoint)[i];
1743  QString file;
1746  }
1747  else {
1748  file = m.GetCubeSerialNumber();
1749  }
1750  deletePointDialog->fileList->addItem(file);
1751  }
1752 
1753  if (deletePointDialog->exec()) {
1754 
1755  int numDeleted = deletePointDialog->fileList->selectedItems().count();
1756 
1757  // Delete entire control point, either through deleteAllCheckBox or all measures selected
1758  if (deletePointDialog->deleteAllCheckBox->isChecked() ||
1759  numDeleted == m_editPoint->GetNumMeasures()) {
1760 
1761  // If all measures being deleted, let user know and give them the option to quit operation
1762  if (!deletePointDialog->deleteAllCheckBox->isChecked()) {
1763  QString message = "You have selected all measures in this point to be deleted. This "
1764  "control point will be deleted. Do you want to delete this control point?";
1765  int response = QMessageBox::question(m_matchTool,
1766  "Delete control point", message,
1767  QMessageBox::Yes | QMessageBox::No,
1768  QMessageBox::Yes);
1769  // If No, do nothing
1770  if (response == QMessageBox::No) {
1771  return;
1772  }
1773  }
1774 
1775  m_matchTool->setVisible(false);
1776  // remove this point from the control network
1777  if (m_controlNet->DeletePoint(m_editPoint->GetId()) == ControlPoint::PointLocked) {
1778  QMessageBox::information(m_matchTool, "EditLocked Point",
1779  "This point is EditLocked and cannot be deleted.");
1780  return;
1781  }
1782  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1783  delete m_editPoint;
1784  m_editPoint = NULL;
1785  }
1786  }
1787 
1788  // Delete specific measures from control point
1789  else {
1790  // Keep track of editLocked measures for reporting
1791  int lockedMeasures = 0;
1792  for (int i=0; i<deletePointDialog->fileList->count(); i++) {
1793  QListWidgetItem *item = deletePointDialog->fileList->item(i);
1794  if (!deletePointDialog->fileList->isItemSelected(item)) continue;
1795 
1796  // Do not delete reference without asking user
1797  if (m_editPoint->IsReferenceExplicit() &&
1798  (m_editPoint->GetRefMeasure()->GetCubeSerialNumber() ==
1799  (*m_editPoint)[i]->GetCubeSerialNumber())) {
1800  QString message = "You are trying to delete the Reference measure."
1801  " Do you really want to delete the Reference measure?";
1802  switch (QMessageBox::question(m_matchTool,
1803  "Delete Reference measure?", message,
1804  "&Yes", "&No", 0, 0)) {
1805  // Yes: skip to end of switch to delete the measure
1806  case 0:
1807  break;
1808  // No: continue to next measure in the loop
1809  case 1:
1810  // if only a single measure and it's reference and user chooses not to delete,
1811  // simply return. The point has not changed.
1812  if (numDeleted == 1) {
1813  return;
1814  }
1815  continue;
1816  }
1817  }
1818 
1819  if (m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
1820  lockedMeasures++;
1821  }
1822  }
1823 
1824  if (lockedMeasures > 0) {
1825  QMessageBox::information(m_matchTool,"EditLocked Measures",
1826  QString::number(lockedMeasures) + " / "
1827  + QString::number(
1828  deletePointDialog->fileList->selectedItems().size()) +
1829  " measures are EditLocked and were not deleted.");
1830  }
1831 
1832  if (mCubes.size() == 0) {
1833  loadPoint();
1834  m_matchTool->setVisible(true);
1835  m_matchTool->raise();
1836 
1838  m_pointEditor->templateFileName());
1839  }
1840  // Since the delete point is not loaded into the editor for saving by the user, we need
1841  // to save the point.
1842  else {
1843  ControlPoint *p = m_controlNet->GetPoint(QString(m_editPoint->GetId()));
1844  *p = *m_editPoint;
1845 
1846  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1847  delete m_editPoint;
1848  m_editPoint = NULL;
1849  }
1850  }
1851  }
1852 
1853  // emit a signal to alert user to save when exiting
1854  // At exit, or when opening new net, use for prompting user for a save
1855  m_netChanged = true;
1856 
1857  if (m_editPoint) {
1859  }
1860  emit editPointChanged();
1861  }
1862  }
1863 
1864 
1865 
1875 
1876  // If no measures, print info and return
1877  if (point->GetNumMeasures() == 0) {
1878  QString message = "This point has no measures.";
1879  QMessageBox::warning(m_matchTool, "Warning", message);
1880  emit editPointChanged();
1881  return;
1882  }
1883 
1884  // Make sure all measures have a cube loaded
1885  QStringList mCubes = missingCubes(point);
1886  if (mCubes.size() > 0) {
1887  QString msgTitle = "Missing Cubes";
1888  QString message = "This point is missing cubes and cannot be loaded into the editor. Open ";
1889  message += "the cubes for the following measures before selecting this point.\n\n";
1890  for (int i=0; i<mCubes.size(); i++) {
1891  message += mCubes.at(i) + "\n";
1892  }
1893  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1894  Qt::Dialog);
1895  msgBox.exec();
1896  return;
1897  }
1898 
1899  // Make a copy of point for editing, first make sure memory not already
1900  // allocated
1901  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1902  delete m_editPoint;
1903  m_editPoint = NULL;
1904  }
1905  m_editPoint = new ControlPoint;
1906  *m_editPoint = *point;
1907 
1908  loadPoint();
1909  m_matchTool->setVisible(true);
1910  m_matchTool->raise();
1912  m_pointEditor->templateFileName());
1913 
1914  // emit signal so the nav tool can update edit point
1915  emit editPointChanged();
1916 
1917  // New point loaded, make sure Save Measure Button text is default
1918  m_savePoint->setPalette(m_saveDefaultPalette);
1919  }
1920 
1921 
1922 
1941 
1942  // Write pointId
1943  QString CPId = m_editPoint->GetId();
1944  QString ptId("Point ID: ");
1945  ptId += (QString) CPId;
1946  m_ptIdValue->setText(ptId);
1947 
1948  // Write number of measures
1949  QString ptsize = "Number of Measures: " +
1950  QString::number(m_editPoint->GetNumMeasures());
1951  m_numMeasures->setText(ptsize);
1952 
1953  // Set EditLock box correctly
1954  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
1955 
1956  // Set ignore box correctly
1957  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1958 
1959  // Clear combo boxes
1960  m_leftCombo->clear();
1961  m_rightCombo->clear();
1962  m_pointFiles.clear();
1963 
1964  // Need all files for this point
1965  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1966  ControlMeasure &m = *(*m_editPoint)[i];
1967  QString file = serialNumberList().fileName(m.GetCubeSerialNumber());
1968  m_pointFiles<<file;
1969  QString tempFileName = FileName(file).name();
1970  m_leftCombo->addItem(tempFileName);
1971  m_rightCombo->addItem(tempFileName);
1972  if (m_editPoint->IsReferenceExplicit() &&
1973  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
1974  m_leftCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1975  m_rightCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1976  }
1977  }
1978 
1979  // TODO: WHAT HAPPENS IF THERE IS ONLY ONE MEASURE IN THIS CONTROLPOINT??
1980  // Assuming combo loaded in same order as measures in the control point-is
1981  // this a safe assumption???
1982  //
1983  // Find the file from the cubeViewport that was originally used to select
1984  // the point, this will be displayed on the left ChipViewport, unless the
1985  // point was selected on the ground source image. In this case, simply
1986  // load the first measure on the left.
1987  int leftIndex = 0;
1988  int rightIndex = 0;
1989  // Check for reference
1990  if (m_editPoint->IsReferenceExplicit()) {
1991  leftIndex = m_editPoint->IndexOfRefMeasure();
1992  }
1993  else {
1994  if (!m_leftFile.isEmpty()) {
1995  leftIndex = m_leftCombo->findText(FileName(m_leftFile).name());
1996  // Sanity check
1997  if (leftIndex < 0 ) leftIndex = 0;
1998  m_leftFile.clear();
1999  }
2000  }
2001 
2002  if (leftIndex == 0) {
2003  rightIndex = 1;
2004  }
2005  else {
2006  rightIndex = 0;
2007  }
2008 
2009  // Handle pts with a single measure, for now simply put measure on left/right
2010  // Evenutally put on left with black on right??
2011  if (rightIndex > m_editPoint->GetNumMeasures()-1) rightIndex = 0;
2012  m_rightCombo->setCurrentIndex(rightIndex);
2013  m_leftCombo->setCurrentIndex(leftIndex);
2014  // Initialize pointEditor with measures
2015  selectLeftMeasure(leftIndex);
2016  selectRightMeasure(rightIndex);
2017 
2018  loadMeasureTable();
2019  }
2020 
2021 
2022 
2031  if (m_measureWindow == NULL) {
2032  m_measureWindow = new QMainWindow(m_parent);
2033  m_measureTable = new QTableWidget();
2034  m_measureTable->setMinimumWidth(1600);
2035  m_measureTable->setAlternatingRowColors(true);
2036  m_measureWindow->setCentralWidget(m_measureTable);
2037  }
2038  else {
2039  m_measureTable->clear();
2040  m_measureTable->setSortingEnabled(false);
2041  }
2042  m_measureTable->setRowCount(m_editPoint->GetNumMeasures());
2043  m_measureTable->setColumnCount(NUMCOLUMNS);
2044 
2045  QStringList labels;
2046  for (int i=0; i<NUMCOLUMNS; i++) {
2047  labels<<measureColumnToString((MeasureColumns)i);
2048  }
2049  m_measureTable->setHorizontalHeaderLabels(labels);
2050 
2051  // Fill in values
2052  for (int row=0; row<m_editPoint->GetNumMeasures(); row++) {
2053  int column = 0;
2054  ControlMeasure &m = *(*m_editPoint)[row];
2055 
2056  QString file = serialNumberList().fileName(m.GetCubeSerialNumber());
2057  QTableWidgetItem *tableItem = new QTableWidgetItem(QString(file));
2058  m_measureTable->setItem(row,column++,tableItem);
2059 
2060  tableItem = new QTableWidgetItem(QString(m.GetCubeSerialNumber()));
2061  m_measureTable->setItem(row,column++,tableItem);
2062 
2063  tableItem = new QTableWidgetItem();
2064  tableItem->setData(0,m.GetSample());
2065  m_measureTable->setItem(row,column++,tableItem);
2066 
2067  tableItem = new QTableWidgetItem();
2068  tableItem->setData(0,m.GetLine());
2069  m_measureTable->setItem(row,column++,tableItem);
2070 
2071  if (m.GetAprioriSample() == Null) {
2072  tableItem = new QTableWidgetItem("Null");
2073  }
2074  else {
2075  tableItem = new QTableWidgetItem();
2076  tableItem->setData(0,m.GetAprioriSample());
2077  }
2078  m_measureTable->setItem(row,column++,tableItem);
2079 
2080  if (m.GetAprioriLine() == Null) {
2081  tableItem = new QTableWidgetItem("Null");
2082  }
2083  else {
2084  tableItem = new QTableWidgetItem();
2085  tableItem->setData(0,m.GetAprioriLine());
2086  }
2087  m_measureTable->setItem(row,column++,tableItem);
2088 
2089  if (m.GetSampleResidual() == Null) {
2090  tableItem = new QTableWidgetItem(QString("Null"));
2091  }
2092  else {
2093  tableItem = new QTableWidgetItem();
2094  tableItem->setData(0,m.GetSampleResidual());
2095  }
2096  m_measureTable->setItem(row,column++,tableItem);
2097 
2098  if (m.GetLineResidual() == Null) {
2099  tableItem = new QTableWidgetItem(QString("Null"));
2100  }
2101  else {
2102  tableItem = new QTableWidgetItem();
2103  tableItem->setData(0,m.GetLineResidual());
2104  }
2105  m_measureTable->setItem(row,column++,tableItem);
2106 
2107  if (m.GetResidualMagnitude() == Null) {
2108  tableItem = new QTableWidgetItem(QString("Null"));
2109  }
2110  else {
2111  tableItem = new QTableWidgetItem();
2112  tableItem->setData(0,m.GetResidualMagnitude());
2113  }
2114  m_measureTable->setItem(row,column++,tableItem);
2115 
2116  double sampleShift = m.GetSampleShift();
2117  if (sampleShift == Null) {
2118  tableItem = new QTableWidgetItem(QString("Null"));
2119  }
2120  else {
2121  tableItem = new QTableWidgetItem();
2122  tableItem->setData(0,sampleShift);
2123  }
2124  m_measureTable->setItem(row,column++,tableItem);
2125 
2126  double lineShift = m.GetLineShift();
2127  if (lineShift == Null) {
2128  tableItem = new QTableWidgetItem(QString("Null"));
2129  }
2130  else {
2131  tableItem = new QTableWidgetItem();
2132  tableItem->setData(0,lineShift);
2133  }
2134  m_measureTable->setItem(row,column++,tableItem);
2135 
2136  double pixelShift = m.GetPixelShift();
2137  if (pixelShift == Null) {
2138  tableItem = new QTableWidgetItem(QString("Null"));
2139  }
2140  else {
2141  tableItem = new QTableWidgetItem();
2142  tableItem->setData(0,pixelShift);
2143  }
2144  m_measureTable->setItem(row,column++,tableItem);
2145 
2146  double goodnessOfFit = m.GetLogData(
2148  if (goodnessOfFit == Null) {
2149  tableItem = new QTableWidgetItem(QString("Null"));
2150  }
2151  else {
2152  tableItem = new QTableWidgetItem();
2153  tableItem->setData(0,goodnessOfFit);
2154  }
2155  m_measureTable->setItem(row,column++,tableItem);
2156 
2157  if (m.IsIgnored()) tableItem = new QTableWidgetItem("True");
2158  if (!m.IsIgnored()) tableItem = new QTableWidgetItem("False");
2159  m_measureTable->setItem(row,column++,tableItem);
2160 
2162  tableItem = new QTableWidgetItem("True");
2164  tableItem = new QTableWidgetItem("False");
2165  m_measureTable->setItem(row,column++,tableItem);
2166 
2167  tableItem = new QTableWidgetItem(
2169  m_measureTable->setItem(row,column,tableItem);
2170 
2171  // If reference measure set font on this row to bold
2172  if (m_editPoint->IsReferenceExplicit() &&
2173  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
2174  QFont font;
2175  font.setBold(true);
2176 
2177  for (int col=0; col<m_measureTable->columnCount(); col++)
2178  m_measureTable->item(row, col)->setFont(font);
2179  }
2180 
2181  }
2182 
2183  m_measureTable->resizeColumnsToContents();
2184  m_measureTable->resizeRowsToContents();
2185  m_measureTable->setSortingEnabled(true);
2186  m_measureWindow->show();
2187  }
2188 
2189 
2190 
2191  QString MatchTool::measureColumnToString(MatchTool::MeasureColumns column) {
2192  switch (column) {
2193  case FILENAME:
2194  return "FileName";
2195  case CUBESN:
2196  return "Serial #";
2197  case SAMPLE:
2198  return "Sample";
2199  case LINE:
2200  return "Line";
2201  case SAMPLERESIDUAL:
2202  return "Sample Residual";
2203  case LINERESIDUAL:
2204  return "Line Residual";
2205  case RESIDUALMAGNITUDE:
2206  return "Residual Magnitude";
2207  case SAMPLESHIFT:
2208  return "Sample Shift";
2209  case LINESHIFT:
2210  return "Line Shift";
2211  case PIXELSHIFT:
2212  return "Pixel Shift";
2213  case GOODNESSOFFIT:
2214  return "Goodness of Fit";
2215  case IGNORED:
2216  return "Ignored";
2217  case EDITLOCK:
2218  return "Edit Lock";
2219  case TYPE:
2220  return "Measure Type";
2221  case APRIORISAMPLE:
2222  return "Apriori Sample";
2223  case APRIORILINE:
2224  return "Apriori Line";
2225  }
2226  throw IException(IException::Programmer,
2227  "Invalid measure column passed to measureColumnToString", _FILEINFO_);
2228  }
2229 
2230 
2231 
2242  int curIndex = m_rightCombo->currentIndex();
2243  if (curIndex < m_rightCombo->count() - 1) {
2244  // update the right measure list index and select that measure
2245  m_rightCombo->setCurrentIndex(curIndex + 1);
2246  selectRightMeasure(curIndex+1);
2247  }
2248  }
2249 
2250 
2261  int curIndex = m_rightCombo->currentIndex();
2262  if (curIndex > 0) {
2263  // update the right measure list index and select that measure
2264  m_rightCombo->setCurrentIndex(curIndex - 1);
2265  selectRightMeasure(curIndex-1);
2266  }
2267  }
2268 
2269 
2270 
2285  QString file = m_pointFiles[index];
2286 
2287  QString serial;
2288  try {
2289  serial = serialNumberList().serialNumber(file);
2290  }
2291  catch (IException &e) {
2292  QString message = "Make sure the correct cube is opened.\n\n";
2293  message += e.toString();
2294  QMessageBox::critical(m_matchTool, "Error", message);
2295 
2296  // Set index of combo back to what it was before user selected new. Find the index
2297  // of current left measure.
2298  QString file = serialNumberList().fileName(m_leftMeasure->GetCubeSerialNumber());
2299  int i = m_leftCombo->findText(FileName(file).name());
2300  if (i < 0) i = 0;
2301  m_leftCombo->setCurrentIndex(i);
2302  return;
2303  }
2304 
2305  // Make sure to clear out leftMeasure before making a copy of the selected
2306  // measure.
2307  if (m_leftMeasure != NULL) {
2308  delete m_leftMeasure;
2309  m_leftMeasure = NULL;
2310  }
2311  m_leftMeasure = new ControlMeasure();
2312  // Find measure for each file
2313  *m_leftMeasure = *((*m_editPoint)[serial]);
2314 
2315  // If m_leftCube is not null, delete before creating new one
2316  if (m_leftCube != NULL) delete m_leftCube;
2317  m_leftCube = new Cube();
2318  m_leftCube->open(file);
2319 
2320  // Update left measure of pointEditor
2321  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube,
2322  m_editPoint->GetId());
2324 
2325  }
2326 
2327 
2340 
2341  QString file = m_pointFiles[index];
2342 
2343  QString serial;
2344  try {
2345  serial = serialNumberList().serialNumber(file);
2346  }
2347  catch (IException &e) {
2348  QString message = "Make sure the correct cube is opened.\n\n";
2349  message += e.toString();
2350  QMessageBox::critical(m_matchTool, "Error", message);
2351 
2352  // Set index of combo back to what it was before user selected new. Find the index
2353  // of current left measure.
2354  QString file = serialNumberList().fileName(m_rightMeasure->GetCubeSerialNumber());
2355  int i = m_rightCombo->findText(FileName(file).name());
2356  if (i < 0) i = 0;
2357  m_rightCombo->setCurrentIndex(i);
2358  return;
2359  }
2360 
2361  // Make sure to clear out rightMeasure before making a copy of the selected
2362  // measure.
2363  if (m_rightMeasure != NULL) {
2364  delete m_rightMeasure;
2365  m_rightMeasure = NULL;
2366  }
2367  m_rightMeasure = new ControlMeasure();
2368  // Find measure for each file
2369  *m_rightMeasure = *((*m_editPoint)[serial]);
2370 
2371  // If m_leftCube is not null, delete before creating new one
2372  if (m_rightCube != NULL) delete m_rightCube;
2373  m_rightCube = new Cube();
2374  m_rightCube->open(file);
2375 
2376  // Update left measure of pointEditor
2377  m_pointEditor->setRightMeasure (m_rightMeasure,m_rightCube,
2378  m_editPoint->GetId());
2380 
2381  }
2382 
2383 
2384 
2385 
2402 
2403  // Set editLock measure box correctly
2404  m_lockLeftMeasure->setChecked(IsMeasureLocked(
2405  m_leftMeasure->GetCubeSerialNumber()));
2406  // Set ignore measure box correctly
2407  m_ignoreLeftMeasure->setChecked(m_leftMeasure->IsIgnored());
2408 
2409  QString s = "Reference: ";
2410  if (m_editPoint->IsReferenceExplicit() &&
2411  (QString(m_leftMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2412  s += "True";
2413  }
2414  else {
2415  s += "False";
2416  }
2417  m_leftReference->setText(s);
2418 
2419  s = "Measure Type: ";
2420  if (m_leftMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2421  if (m_leftMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2422  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2423  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2424  m_leftMeasureType->setText(s);
2425 
2426  if (m_leftMeasure->GetSampleShift() == Null) {
2427  s = "Sample Shift: Null";
2428  }
2429  else {
2430  s = "Sample Shift: " + QString::number(m_leftMeasure->GetSampleShift());
2431  }
2432  m_leftSampShift->setText(s);
2433 
2434  if (m_leftMeasure->GetLineShift() == Null) {
2435  s = "Line Shift: Null";
2436  }
2437  else {
2438  s = "Line Shift: " + QString::number(m_leftMeasure->GetLineShift());
2439  }
2440  m_leftLineShift->setText(s);
2441 
2442  double goodnessOfFit = m_leftMeasure->GetLogData(
2444  if (goodnessOfFit == Null) {
2445  s = "Goodness of Fit: Null";
2446  }
2447  else {
2448  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2449  }
2450  m_leftGoodness->setText(s);
2451 
2452  }
2453 
2454 
2455 
2475 
2476  // Set editLock measure box correctly
2477  m_lockRightMeasure->setChecked(IsMeasureLocked(
2478  m_rightMeasure->GetCubeSerialNumber()));
2479  // Set ignore measure box correctly
2480  m_ignoreRightMeasure->setChecked(m_rightMeasure->IsIgnored());
2481 
2482  QString s = "Reference: ";
2483  if (m_editPoint->IsReferenceExplicit() &&
2484  (QString(m_rightMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2485  s += "True";
2486  }
2487  else {
2488  s += "False";
2489  }
2490 
2491  m_rightReference->setText(s);
2492 
2493  s = "Measure Type: ";
2494  if (m_rightMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2495  if (m_rightMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2496  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2497  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2498  m_rightMeasureType->setText(s);
2499 
2500  if (m_rightMeasure->GetSampleShift() == Null) {
2501  s = "Sample Shift: Null";
2502  }
2503  else {
2504  s = "Sample Shift: " + QString::number(m_rightMeasure->GetSampleShift());
2505  }
2506  m_rightSampShift->setText(s);
2507 
2508  if (m_rightMeasure->GetLineShift() == Null) {
2509  s = "Line Shift: Null";
2510  }
2511  else {
2512  s = "Line Shift: " + QString::number(m_rightMeasure->GetLineShift());
2513  }
2514  m_rightLineShift->setText(s);
2515 
2516  double goodnessOfFit = m_rightMeasure->GetLogData(
2518  if (goodnessOfFit == Null) {
2519  s = "Goodness of Fit: Null";
2520  }
2521  else {
2522  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2523  }
2524  m_rightGoodness->setText(s);
2525 
2526  }
2527 
2528 
2529 
2540  bool MatchTool::eventFilter(QObject *o, QEvent *e) {
2541  if(e->type() != QEvent::Leave) return false;
2542  if(o == m_leftCombo->view()) {
2544  m_leftCombo->hidePopup();
2545  }
2546  if (o == m_rightCombo->view()) {
2548  m_rightCombo->hidePopup();
2549  }
2550  return true;
2551  }
2552 
2553 
2561  void MatchTool::paintViewport(MdiCubeViewport *mvp, QPainter *painter) {
2562  drawAllMeasurments (mvp,painter);
2563 
2564  }
2565 
2566 
2581 
2582  // Take care of drawing things on all viewPorts.
2583  // Calling update will cause the Tool class to call all registered tools
2584  // if point has been deleted, this will remove it from the main window
2585  MdiCubeViewport *mvp;
2586  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
2587  mvp = (*(cubeViewportList()))[i];
2588  mvp->viewport()->update();
2589  }
2590  }
2591 
2614  void MatchTool::drawAllMeasurments(MdiCubeViewport *mvp, QPainter *painter) {
2615 
2616  // Make sure we have points to draw
2617  if ( (m_controlNet == NULL || m_controlNet->GetNumPoints() == 0) && m_newPoint == NULL &&
2618  m_editPoint == NULL)
2619  return;
2620 
2621  QString sn = serialNumber(mvp);
2622 // QString serialNumber = SerialNumber::Compose(*vp->cube(), true);
2623 
2624  // In the middle of creating a new point
2625  if (m_newPoint != NULL) {
2626  // and the selected point is in the image,
2627  if (m_newPoint->HasSerialNumber(sn)) {
2628  // find the measurement
2629  double samp = (*m_newPoint)[sn]->GetSample();
2630  double line = (*m_newPoint)[sn]->GetLine();
2631  int x, y;
2632  mvp->cubeToViewport(samp, line, x, y);
2633  // set point marker red
2634  QBrush brush(Qt::red);
2635  // set point marker bold - line width 2
2636  QPen pen(brush, 2);
2637  // draw the selected point in each image last so it's on top of the rest of the points
2638  painter->setPen(pen);
2639  painter->drawLine(x - 5, y, x + 5, y);
2640  painter->drawLine(x, y - 5, x, y + 5);
2641  }
2642  }
2643 
2644  // If viewport serial number not found in control net, return
2645  if (!m_controlNet->GetCubeSerials().contains(
2646  sn)) return;
2647 
2648 // if (!m_controlNet->GetCubeSerials().contains(
2649 // QString::fromStdString(sn))) return;
2650 // if (!serialNumberList().HasSerialNumber(sn)) return;
2651 
2652  QList<ControlMeasure *> measures =
2653  m_controlNet->GetMeasuresInCube(sn);
2654  // loop through all measures contained in this cube
2655  for (int i = 0; i < measures.count(); i++) {
2656  ControlMeasure *m = measures[i];
2657  // Find the measurments on the viewport
2658  double samp = m->GetSample();
2659  double line = m->GetLine();
2660  int x, y;
2661  mvp->cubeToViewport(samp, line, x, y);
2662  // if the point is ignored,
2663  if (m->Parent()->IsIgnored()) {
2664  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2665  }
2666  // point is not ignored, but measure matching this image is ignored,
2667  else if (m->IsIgnored()) {
2668  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2669  }
2670  else {
2671  painter->setPen(Qt::green); // set all other point markers green
2672  }
2673  // draw points
2674  painter->drawLine(x - 5, y, x + 5, y);
2675  painter->drawLine(x, y - 5, x, y + 5);
2676  }
2677  // if MatchTool is open,
2678  if (m_editPoint != NULL && m_newPoint == NULL) {
2679  // and the selected point is in the image,
2680  if (m_editPoint->HasSerialNumber(sn)) {
2681  // find the measurement
2682  double samp = (*m_editPoint)[sn]->GetSample();
2683  double line = (*m_editPoint)[sn]->GetLine();
2684  int x, y;
2685  mvp->cubeToViewport(samp, line, x, y);
2686  // set point marker red
2687  QBrush brush(Qt::red);
2688  // set point marker bold - line width 2
2689  QPen pen(brush, 2);
2690  // draw the selected point in each image last so it's on top of the rest of the points
2691  painter->setPen(pen);
2692  painter->drawLine(x - 5, y, x + 5, y);
2693  painter->drawLine(x, y - 5, x, y + 5);
2694  }
2695  }
2696  }
2697 
2698 
2699 
2714 
2715  if (m_templateModified) {
2716  int r = QMessageBox::warning(m_matchTool, tr("OK to continue?"),
2717  tr("The currently opened registration template has been modified.\n"
2718  "Save changes?"),
2719  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
2720  QMessageBox::Yes);
2721 
2722  if (r == QMessageBox::Yes)
2724  else if (r == QMessageBox::Cancel)
2725  return false;
2726  }
2727 
2728  return true;
2729  }
2730 
2731 
2732 
2739 
2740  if (!okToContinue())
2741  return;
2742 
2743  QString filename = QFileDialog::getOpenFileName(m_matchTool,
2744  "Select a registration template", ".",
2745  "Registration template files (*.def *.pvl);;All files (*)");
2746 
2747  if (filename.isEmpty())
2748  return;
2749 
2750  if (m_pointEditor->setTemplateFile(filename)) {
2751  loadTemplateFile(filename);
2752  }
2753  }
2754 
2755 
2756 
2762  void MatchTool::loadTemplateFile(QString fn) {
2763 
2764  QFile file(FileName((QString) fn).expanded());
2765  if (!file.open(QIODevice::ReadOnly)) {
2766  QString msg = "Failed to open template file \"" + fn + "\"";
2767  QMessageBox::warning(m_matchTool, "IO Error", msg);
2768  return;
2769  }
2770 
2771  QTextStream stream(&file);
2772  m_templateEditor->setText(stream.readAll());
2773  file.close();
2774 
2775  QScrollBar * sb = m_templateEditor->verticalScrollBar();
2776  sb->setValue(sb->minimum());
2777 
2778  m_templateModified = false;
2779  m_saveTemplateFile->setEnabled(false);
2780  m_templateFileNameLabel->setText("Template File: " + fn);
2781  }
2782 
2783 
2784 
2787  m_templateModified = true;
2788  m_saveTemplateFile->setEnabled(true);
2789  }
2790 
2791 
2792 
2795 
2796  if (!m_templateModified)
2797  return;
2798 
2799  QString filename =
2800  m_pointEditor->templateFileName();
2801 
2802  writeTemplateFile(filename);
2803  }
2804 
2805 
2806 
2809 
2810  QString filename = QFileDialog::getSaveFileName(m_matchTool,
2811  "Save registration template", ".",
2812  "Registration template files (*.def *.pvl);;All files (*)");
2813 
2814  if (filename.isEmpty())
2815  return;
2816 
2817  writeTemplateFile(filename);
2818  }
2819 
2820 
2821 
2827  void MatchTool::writeTemplateFile(QString fn) {
2828 
2829  QString contents = m_templateEditor->toPlainText();
2830 
2831  // catch errors in Pvl format when populating pvl object
2832  stringstream ss;
2833  ss << contents;
2834  try {
2835  Pvl pvl;
2836  ss >> pvl;
2837  }
2838  catch(IException &e) {
2839  QString message = e.toString();
2840  QMessageBox::warning(m_matchTool, "Error", message);
2841  return;
2842  }
2843 
2844  QString expandedFileName(
2845  FileName((QString) fn).expanded());
2846 
2847  QFile file(expandedFileName);
2848 
2849  if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2850  QString msg = "Failed to save template file to \"" + fn + "\"\nDo you "
2851  "have permission?";
2852  QMessageBox::warning(m_matchTool, "IO Error", msg);
2853  return;
2854  }
2855 
2856  // now save contents
2857  QTextStream stream(&file);
2858  stream << contents;
2859  file.close();
2860 
2861  if (m_pointEditor->setTemplateFile(fn)) {
2862  m_templateModified = false;
2863  m_saveTemplateFile->setEnabled(false);
2864  m_templateFileNameLabel->setText("Template File: " + fn);
2865  }
2866  }
2867 
2868 
2869 
2884  try{
2885  // Get the template file from the ControlPointEditor object
2886  Pvl templatePvl(m_pointEditor->templateFileName());
2887  // Create registration dialog window using PvlEditDialog class
2888  // to view and/or edit the template
2889  PvlEditDialog registrationDialog(templatePvl);
2890  registrationDialog.setWindowTitle("View or Edit Template File: "
2891  + templatePvl.fileName());
2892  registrationDialog.resize(550,360);
2893  registrationDialog.exec();
2894  }
2895  catch (IException &e) {
2896  QString message = e.toString();
2897  QMessageBox::information(m_matchTool, "Error", message);
2898  }
2899  }
2900 
2901 
2902 
2910  m_pointEditor->saveChips();
2911  }
2912 
2913 
2914 
2915  void MatchTool::showHideTemplateEditor() {
2916 
2917  if (!m_templateEditorWidget)
2918  return;
2919 
2920  m_templateEditorWidget->setVisible(!m_templateEditorWidget->isVisible());
2921  }
2922 
2923 
2924 
2937  void MatchTool::updatePointInfo(QString pointId) {
2938  if (m_editPoint == NULL) return;
2939  if (pointId != m_editPoint->GetId()) return;
2940  // The edit point has been changed by SetApriori, so m_editPoint needs
2941  // to possibly update some values. Need to retain measures from m_editPoint
2942  // because they might have been updated, but not yet saved to the network
2943  // ("Save Point").
2944  ControlPoint *updatedPoint = m_controlNet->GetPoint(pointId);
2945  m_editPoint->SetEditLock(updatedPoint->IsEditLocked());
2946  m_editPoint->SetIgnored(updatedPoint->IsIgnored());
2947 
2948  // Set EditLock box correctly
2949  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
2950 
2951  // Set ignore box correctly
2952  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
2953 
2954  }
2955 
2956 
2957 
2974 
2975  // Check point being edited, make sure it still exists, if not ???
2976  // Update ignored checkbox??
2977  if (m_editPoint != NULL) {
2978  try {
2979  QString id = m_ptIdValue->text().remove("Point ID: ");
2980  m_controlNet->GetPoint(id);
2981  }
2982  catch (IException &) {
2983  delete m_editPoint;
2984  m_editPoint = NULL;
2985  emit editPointChanged();
2986 // m_matchTool->setVisible(false);
2987 // m_measureWindow->setVisible(false);
2988  }
2989  }
2990 
2992  }
2993 
2994 
2995 
3002 
3003  QColor qc = Qt::red;
3004  QPalette p = m_savePoint->palette();
3005  p.setColor(QPalette::ButtonText,qc);
3006  m_savePoint->setPalette(p);
3007 
3008  }
3009 
3010 
3011 
3024  bool MatchTool::IsMeasureLocked (QString serialNumber) {
3025 
3026  if (m_editPoint == NULL) return false;
3027 
3028  // Reference implicitly editLocked
3029  if (m_editPoint->IsEditLocked() && m_editPoint->IsReferenceExplicit() &&
3030  (m_editPoint->GetReferenceSN() == serialNumber)) {
3031  return true;
3032  }
3033  // Return measures explicit editLocked value
3034  else {
3035  return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
3036  }
3037 
3038  }
3039 
3040 
3041 
3048  FileName config("$HOME/.Isis/qview/MatchTool.config");
3049  QSettings settings(config.expanded(),
3050  QSettings::NativeFormat);
3051  QPoint pos = settings.value("pos", QPoint(300, 100)).toPoint();
3052  QSize size = settings.value("size", QSize(900, 500)).toSize();
3053  m_matchTool->resize(size);
3054  m_matchTool->move(pos);
3055  }
3056 
3057 
3065  /*We do not want to write the settings unless the window is
3066  visible at the time of closing the application*/
3067  if (!m_matchTool->isVisible()) return;
3068  FileName config("$HOME/.Isis/qview/MatchTool.config");
3069  QSettings settings(config.expanded(),
3070  QSettings::NativeFormat);
3071  settings.setValue("pos", m_matchTool->pos());
3072  settings.setValue("size", m_matchTool->size());
3073  }
3074 
3075 
3076 
3077  void MatchTool::enterWhatsThisMode() {
3078  QWhatsThis::enterWhatsThisMode();
3079  }
3080 
3081 
3082  void MatchTool::clearEditPoint() {
3083  m_editPoint = NULL;
3084  }
3085 
3086 
3087 
3088  void MatchTool::showHelp() {
3089 
3090  QDialog *helpDialog = new QDialog(m_matchTool);
3091  helpDialog->setWindowTitle("Match Tool Help");
3092 
3093  QVBoxLayout *mainLayout = new QVBoxLayout;
3094  helpDialog->setLayout(mainLayout);
3095 
3096  QLabel *matchTitle = new QLabel("<h2>Match Tool</h2>");
3097  mainLayout->addWidget(matchTitle);
3098 
3099  QLabel *matchSubtitle = new QLabel("A tool for interactively measuring and editing sample/line "
3100  "registration points between cubes. These "
3101  "points contain sample, line postions only, no latitude or "
3102  "longitude values are used or recorded.");
3103  matchSubtitle->setWordWrap(true);
3104  mainLayout->addWidget(matchSubtitle);
3105 
3106  QTabWidget *tabArea = new QTabWidget;
3107  tabArea->setDocumentMode(true);
3108  mainLayout->addWidget(tabArea);
3109 
3110  // TAB 1 - Overview
3111  QScrollArea *overviewTab = new QScrollArea;
3112  overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3113  overviewTab->setWidgetResizable(true);
3114  QWidget *overviewContainer = new QWidget;
3115  QVBoxLayout *overviewLayout = new QVBoxLayout;
3116  overviewContainer->setLayout(overviewLayout);
3117 
3118  QLabel *purposeTitle = new QLabel("<h2>Purpose</h2>");
3119  overviewLayout->addWidget(purposeTitle);
3120 
3121  QLabel *purposeText = new QLabel("<p>This tool is for recording and editing registration "
3122  "points measured between cubes displayed in the <i>qview</i> main window.</p> <p>The "
3123  "recorded registration points are sample and line pixel coordinates only. Therefore, this "
3124  "tool can be used on any images including ones that do not contain a camera model "
3125  "(i.e, The existence of the Isis Instrument Group on the image labels is not required). "
3126  "This also means that the tool differs from the <i>qnet</i> control point network "
3127  "application in that no latitude or longitude values are ever used or recorded "
3128  "(regardless if the image has a camera model in Isis).</p>"
3129  "<p>The output control point network that this tool generates is primarily used 1) as "
3130  "input for an image-wide sample/line translation to register one image to another by "
3131  "'moving' pixel locations - refer to the documentation for applications such as "
3132  "<i>translate</i> and <i>warp</i>, or 2) to export the file and use the recorded "
3133  "measurements in other spreadsheet or plotting packages to visualize magnitude "
3134  "and direction of varying translations of the images relative to one another.</p> "
3135  "<p>An automated version of this match tool is the <i>coreg</i> application. This tool "
3136  "can be used to visually evaluate and edit the control point network created by "
3137  "<i>coreg</i>.</p> "
3138  "<p>The format of the output point network file is binary. This tool uses the Isis control "
3139  " network framework to create, co-register and save all control points and pixel "
3140  "measurements. The application <i>cnetbin2pvl</i> can be used to convert from binary to "
3141  "a readable PVL format."
3142  "<p>The Mouse Button functions are: (same as <i>qnet</i>)<ul><li>Modify Point=Left</li> "
3143  "<li>Delete Point=Middle</li><li>Create New Point=Right</li></ul></p>"
3144  "<p>Control Points are drawn on the associated displayed cubes with the following colors: "
3145  "Green=Valid registration point; Yellow=Ignored point; Red=Active point being edited");
3146  purposeText->setWordWrap(true);
3147  overviewLayout->addWidget(purposeText);
3148 
3149  overviewTab->setWidget(overviewContainer);
3150 
3151  // TAB 2 - Quick Start
3152  QScrollArea *quickTab = new QScrollArea;
3153  quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3154  quickTab->setWidgetResizable(true);
3155  QWidget *quickContainer = new QWidget;
3156  QVBoxLayout *quickLayout = new QVBoxLayout;
3157  quickContainer->setLayout(quickLayout);
3158 
3159  QLabel *quickTitle = new QLabel("<h2>Quick Start</h2>");
3160  quickLayout->addWidget(quickTitle);
3161 
3162  QLabel *quickSubTitle = new QLabel("<h3>Preparation:</h3>");
3163  quickLayout->addWidget(quickSubTitle);
3164 
3165  QLabel *quickPrep = new QLabel("<p><ul>"
3166  "<li>Open the cubes with overlapping areas for choosing control points</li>"
3167  "<li>Choose the match tool <img src=\"" + toolIconDir() +
3168  "/stock_draw-connector-with-arrows.png\" width=22 height=22> "
3169  "from the toolpad on the right side of the <i>qview</i> main window</li>");
3170  quickPrep->setWordWrap(true);
3171  quickLayout->addWidget(quickPrep);
3172 
3173  QLabel *morePrep = new QLabel("<p>Once the Match tool is activated the tool bar at the top "
3174  "of the main window contains file action buttons and a help button:");
3175  morePrep->setWordWrap(true);
3176  quickLayout->addWidget(morePrep);
3177 
3178  QLabel *fileButtons = new QLabel("<p><ul>"
3179  "<li><img src=\"" + toolIconDir() + "/fileopen.png\" width=22 height=22> Open an existing "
3180  "control network <b>Note:</b> If you do not open an existing network, a new one will "
3181  "be created</li>"
3182  "<li><img src=\"" + toolIconDir() + "/mActionFileSaveAs.png\" width=22 height=22> Save "
3183  "control network as ...</li>"
3184  "<li><img src=\"" + toolIconDir() + "/mActionFileSave.png\" width=22 height=22> Save "
3185  "control network to current file</li>"
3186  "<li><img src=\"" + toolIconDir() + "/help-contents.png\" width=22 height=22> Show Help "
3187  "</li></ul></p>");
3188  fileButtons->setWordWrap(true);
3189  quickLayout->addWidget(fileButtons);
3190 
3191  QLabel *quickFunctionTitle = new QLabel("<h3>Cube Viewport Functions:</h3>");
3192  quickLayout->addWidget(quickFunctionTitle);
3193 
3194  QLabel *quickFunction = new QLabel(
3195  "The match tool window will be shown once "
3196  "you click in a cube viewport window using one of the following "
3197  "mouse functions. <b>Note:</b> Existing control points are drawn on the cube viewports");
3198  quickFunction->setWordWrap(true);
3199  quickLayout->addWidget(quickFunction);
3200 
3201  QLabel *quickDesc = new QLabel("<p><ul>"
3202  "<li>Left Click - Modify the control point closest to the click <b>Note:</b> "
3203  "All cubes in the control point must be displayed before loading the point</li>"
3204  "<li>Middle Click - Delete the control point closest to the click</li>"
3205  "<li>Right Click - Create a new control point at the click location</li></ul></p>");
3206  quickDesc->setWordWrap(true);
3207  quickDesc->setOpenExternalLinks(true);
3208  quickLayout->addWidget(quickDesc);
3209 
3210  quickTab->setWidget(quickContainer);
3211 
3212  // TAB 3 - Control Point Editing
3213  QScrollArea *controlPointTab = new QScrollArea;
3214  controlPointTab->setWidgetResizable(true);
3215  controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3216  QWidget *controlPointContainer = new QWidget;
3217  QVBoxLayout *controlPointLayout = new QVBoxLayout;
3218  controlPointContainer->setLayout(controlPointLayout);
3219 
3220  QLabel *controlPointTitle = new QLabel("<h2>Control Point Editing</h2>");
3221  controlPointLayout->addWidget(controlPointTitle);
3222 
3223  QLabel *mouseLabel = new QLabel("<p><h3>When the \"Match\" tool "
3224  "is activated, the mouse buttons have the following function in the "
3225  "cube viewports of the main qview window:</h3>");
3226  mouseLabel->setWordWrap(true);
3227  mouseLabel->setScaledContents(true);
3228  controlPointLayout->addWidget(mouseLabel);
3229 
3230  QLabel *controlPointDesc = new QLabel("<ul>"
3231  "<li>Left click - Edit the closest control point <b>Note:</b> "
3232  "All cubes in the control point must be displayed before loading the point</li>"
3233  "<li>Middle click - Delete the closest control point</li>"
3234  "<li>Right click - Create new control point at cursor location. This will bring up a new "
3235  "point dialog which allows you to enter a point id and will list all cube viewports, "
3236  "highlighting cubes where the point has been chosen by clicking on the cube's viewport. "
3237  "When the desired cubes have been chosen, select the \"Done\" button which will load the "
3238  "control point into the control point editor window which will allow the control measure "
3239  "positions to be refined.</li>");
3240  controlPointDesc->setWordWrap(true);
3241  controlPointLayout->addWidget(controlPointDesc);
3242 
3243  QLabel *controlPointEditing = new QLabel(
3244  "<h4>Changing Control Measure Locations</h4>"
3245  "<p>Both the left and right control measure positions can be adjusted by:"
3246  "<ul>"
3247  "<li>Move the cursor location under the crosshair by clicking the left mouse "
3248  "button</li>"
3249  "<li>Move 1 pixel at a time by using arrow keys on the keyboard</li>"
3250  "<li>Move 1 pixel at a time by using arrow buttons above the right and left views</li>"
3251  "</ul></p>"
3252  "<h4>Other Point Editor Functions</h4>"
3253  "<p>Along the right border of the window:</p>"
3254  "<ul>"
3255  "<li><strong>Link Zoom</strong> This will link the two small viewports together when "
3256  "zooming (ie. If this is checked, if the left view is zoomed, the right view will "
3257  "match the left view's zoom factor. "
3258  "<b>Note:</b> Zooming is controlled from the left view.</li>"
3259  "<li><strong>No Rotate:</strong> Turn off the rotation and bring right view back to "
3260  "its original orientation</li>"
3261  "<li><strong>Rotate:</strong> Rotate the right view using either the dial "
3262  "or entering degrees </li>"
3263  "<li><strong>Show control points:</strong> Draw crosshairs at all control "
3264  "point locations visible within the view</li>"
3265  "<li><strong>Show crosshair:</strong> Show a red crosshair across the entire "
3266  "view</li>"
3267  "<li><strong>Circle:</strong> Draw circle which may help center measure "
3268  "on a crater</li></ul"
3269  "<p>Below the left view:</p>"
3270  "<ul><li><strong>Blink controls:</strong> Blink the left and right view in the "
3271  "left view window using the \"Blink Start\" button <img src=\"" + toolIconDir() +
3272  "/blinkStart.png\" width=22 height=22> and \"Blink Stop\" button <img src=\"" +
3273  toolIconDir() + "/blinkStop.png\" width=22 height=22>. The arrow keys above the left "
3274  "and right views and the keyboard arrow keys may be used to move the both views while "
3275  "blinking.</li>"
3276  "<li><strong>Register:</strong> Sub-pixel register the right view to "
3277  "the left view. A default registration template is used for setting parameters "
3278  "passed to the sub-pixel registration tool. The user may load in a predefined "
3279  "template or edit the current loaded template to influence successful "
3280  "co-registration results. For more information regarding the pattern matching "
3281  "functionlity or how to create a parameter template, refer to the Isis PatternMatch "
3282  "document and the <i>autoregtemplate</i> application. <strong>Shortcut: R.</strong>"
3283  "</li>"
3284  "<li><strong>Save Measures:</strong> Save the two control measures using the sample, "
3285  "line positions under the crosshairs. <strong>Shortcut: M.</strong></li>"
3286  "<li><strong>Save Point:</strong> Save the control point to the control network. "
3287  "<strong>Shortcut: P.</strong></li>"
3288  "</ul>");
3289  controlPointEditing->setWordWrap(true);
3290  controlPointLayout->addWidget(controlPointEditing);
3291 
3292  controlPointTab->setWidget(controlPointContainer);
3293 
3294  // TAB 4 - Coreg Guidance
3295  QScrollArea *coregTab = new QScrollArea;
3296  coregTab->setWidgetResizable(true);
3297  coregTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3298  QWidget *coregContainer = new QWidget;
3299  QVBoxLayout *coregLayout = new QVBoxLayout;
3300  coregContainer->setLayout(coregLayout);
3301 
3302  QLabel *coregTitle = new QLabel("<h2>Coreg Guidance</h2>");
3303  coregLayout->addWidget(coregTitle);
3304 
3305  QLabel *coregDesc = new QLabel("<p>When opening control networks created by <i>coreg</i>, "
3306  "there are some things to keep in mind. First, all control points must have the same "
3307  "reference measure (this is the image filename passed to the <i>coreg</i> 'match' parameter)."
3308  "<p>In order to retain the integrity of the input <i>coreg</i> network, you cannot change "
3309  "which image is the reference measure on any of the existing points. "
3310  "<p>When creating a new control point to add to the <i>coreg</i> network, this tool will "
3311  "automatically set the reference measure to the same image as the other control points in "
3312  "the network as long as the reference image was one of the images selected with "
3313  "the right mouse button from the new point dialog. If this image was not selected when "
3314  "creating a new point, it "
3315  "does not contain a required measurement, therefore, you will get an error and the new "
3316  "point will not be created.</p> <p>The reference measure is always loaded on the left side "
3317  "of the control point editor. If you load a measure that is not the reference measure "
3318  "on the left side and try to save the point, you will receive an error message. You will "
3319  "need to move the reference measure back to the left side before saving the control point."
3320  "</p><p><b>Note:</b> This error checking will not happen on control networks created by "
3321  "<i>coreg</i> prior to Isis3.4.2. For older <i>coreg</i> control networks the user must be "
3322  "aware and make sure the correct image is set to the same <i>coreg</i> reference measure.");
3323  coregDesc->setWordWrap(true);
3324  coregDesc->setScaledContents(true);
3325  coregLayout->addWidget(coregDesc);
3326 
3327  coregTab->setWidget(coregContainer);
3328 
3329  tabArea->addTab(overviewTab, "&Overview");
3330  tabArea->addTab(quickTab, "&Quick Start");
3331  tabArea->addTab(controlPointTab, "&Control Point Editing");
3332  tabArea->addTab(coregTab, "&Coreg Guidance");
3333 
3334  QHBoxLayout *buttonsLayout = new QHBoxLayout;
3335  // Flush the buttons to the right
3336  buttonsLayout->addStretch();
3337 
3338  QPushButton *closeButton = new QPushButton("&Close");
3339  closeButton->setIcon(QPixmap(toolIconDir() + "/guiStop.png"));
3340  closeButton->setDefault(true);
3341  connect(closeButton, SIGNAL(clicked()),
3342  helpDialog, SLOT(close()));
3343  buttonsLayout->addWidget(closeButton);
3344 
3345  mainLayout->addLayout(buttonsLayout);
3346 
3347  helpDialog->show();
3348 
3349 
3350  }
3351 
3352 
3353 
3361 
3362  if (m_editPoint) {
3363  // If point changed or if a new point, prompt for saving.
3364  if ( m_controlNet->GetNumPoints() == 0 ||
3365  !m_controlNet->ContainsPoint(m_editPoint->GetId())) {
3366  QString message = "\n\nDo you want to save the point in the editor?";
3367  int response = QMessageBox::question(m_matchTool, "Save point in editor", message,
3368  QMessageBox::Yes | QMessageBox::No,
3369  QMessageBox::Yes);
3370  if (response == QMessageBox::Yes) {
3371  savePoint();
3372  }
3373  }
3374  }
3375 
3376  if (m_controlNet && m_controlNet->GetNumPoints() != 0 && m_netChanged) {
3377  QString message = "The currently open control net has changed. Do you want to save?";
3378  int response = QMessageBox::question(m_matchTool, "Save current control net?",
3379  message,
3380  QMessageBox::Yes | QMessageBox::No,
3381  QMessageBox::Yes);
3382  // Yes: Save old net, so return without opening network.
3383  if (response == QMessageBox::Yes) {
3384  saveAsNet();
3385  }
3386  }
3387  }
3388 }
Status SetType(MeasureType type)
Set how the coordinate was obtained.
bool okToContinue()
Allows user to set a new template file.
Definition: MatchTool.cpp:2713
Cube display widget for certain Isis MDI applications.
QGroupBox * createControlPointGroupBox()
Definition: MatchTool.cpp:276
QAction * toolPadAction(ToolPad *pad)
Adds the Tie tool action to the tool pad.
Definition: MatchTool.cpp:614
QGroupBox * createLeftMeasureGroupBox()
Definition: MatchTool.cpp:311
bool HasSerialNumber(QString serialNumber) const
Return true if given serial number exists in point.
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:391
void deletePoint(ControlPoint *point)
Delete control point.
Definition: MatchTool.cpp:1693
QString toolIconDir() const
returns the path to the icon directory.
Definition: Tool.h:127
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
bool IsReferenceExplicit() const
Cube * cube() const
Definition: CubeViewport.h:348
void Add(ControlMeasure *measure)
Add a measurement to the control point, taking ownership of the measure in the process.
(e.g., autoseed, interest) AKA predicted, unmeasured, unverified
QSplitter * createTopSplitter()
creates everything above the ControlPointEdit
Definition: MatchTool.cpp:247
void setIgnoreRightMeasure(bool ignore)
Set the "Ignore" keyword of the measure shown in the right viewport to the value of the input paramet...
Definition: MatchTool.cpp:1283
bool hasSerialNumber(QString sn)
Determines whether or not the requested serial number exists in the list.
File name manipulation and expansion.
Definition: FileName.h:116
void openTemplateFile()
prompt user for a registration template file to open.
Definition: MatchTool.cpp:2738
void updateRightMeasureInfo()
Definition: MatchTool.cpp:2474
void add(const QString &filename, bool def2filename=false)
Adds a new filename / serial number pair to the SerialNumberList.
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube&#39;s serial number.
CubeViewportList * cubeViewportList() const
Return the list of cubeviewports.
Definition: Tool.cpp:390
void saveChips()
Slot which calls ControlPointEditor slot to save chips.
Definition: MatchTool.cpp:2909
Status SetIgnored(bool newIgnoreStatus)
Set whether to ignore or use control point.
void loadPoint()
Load point into MatchTool.
Definition: MatchTool.cpp:1940
void saveAsNet()
Signal to save the control net.
Definition: MatchTool.cpp:1400
QString serialNumber(const QString &filename)
Return a serial number given a filename.
void setTemplateModified()
called when the template file is modified by the template editor
Definition: MatchTool.cpp:2786
double GetResidualMagnitude() const
Return Residual magnitude.
QString GetReferenceSN() const
Namespace for the standard library.
void saveTemplateFileAs()
save the contents of template editor to a file chosen by the user
Definition: MatchTool.cpp:2808
void updateLeftMeasureInfo()
Definition: MatchTool.cpp:2401
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
void modifyPoint(ControlPoint *point)
Modify control point.
Definition: MatchTool.cpp:1874
Status SetChooserName(QString name)
Set the point&#39;s chooser name.
void saveChips()
Slot to save registration chips to files and fire off qview.
Widget to display Isis cubes for qt apps.
Definition: CubeViewport.h:132
void cubeToViewport(double sample, double line, int &x, int &y) const
Turns a cube into a viewport.
Registered to whole pixel (e.g.,pointreg)
SerialNumberList serialNumberList()
Creates a serial number list based on open cube viewports.
Definition: MatchTool.cpp:679
Registered to sub-pixel (e.g., pointreg)
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
Status SetEditLock(bool editLock)
Set the EditLock state.
void createPoint(MdiCubeViewport *mvp, double sample, double line)
Create new control point at given samp, line for viewport.
Definition: MatchTool.cpp:1553
void exiting()
This called when qview is exiting.
Definition: MatchTool.cpp:3360
QGroupBox * createRightMeasureGroupBox()
Creates the right measure group box.
Definition: MatchTool.cpp:371
A Free point is a Control Point that identifies common measurements between two or more cubes...
Definition: ControlPoint.h:399
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
QString fileName(const QString &sn)
Return a filename given a serial number.
This was called the Qisis MainWindow.
void setRightMeasure(ControlMeasure *rightMeasure, Cube *rightCube, QString pointId)
Set the measure displayed in the right ChipViewport.
void colorizeSaveButton()
Turn "Save Point" button text to red.
Definition: MatchTool.cpp:3001
void drawAllMeasurments(MdiCubeViewport *mvp, QPainter *painter)
Draw all measurments which are on this viewPort.
Definition: MatchTool.cpp:2614
a control network
Definition: ControlNet.h:271
bool setTemplateFile(QString)
Allows user to choose a new template file by opening a window from which to select a filename...
Hand Measured (e.g., qnet)
QString GetId() const
Return the Id of the control point.
void createTemplateEditorWidget()
Creates the Widget which contains the template editor and its toolbar.
Definition: MatchTool.cpp:431
bool IsMeasureLocked(QString serialNumber)
Check for implicitly locked measure in m_editPoint.
Definition: MatchTool.cpp:3024
void setIgnorePoint(bool ignore)
Set point&#39;s "Ignore" keyword to the value of the input parameter.
Definition: MatchTool.cpp:1140
Pixel value mapper.
Definition: Stretch.h:72
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
Status SetRefMeasure(ControlMeasure *cm)
Set the point&#39;s reference measure.
void setFiles(QStringList pointFiles)
void writeTemplateFile(QString)
write the contents of the template editor to the file provided.
Definition: MatchTool.cpp:2827
void selectRightMeasure(int index)
Select right measure.
Definition: MatchTool.cpp:2339
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
A single control point.
Definition: ControlPoint.h:369
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Definition: Cube.cpp:544
void readSettings()
This method is called from the constructor so that when the Main window is created, it know&#39;s it&#39;s size and location.
Definition: MatchTool.cpp:3047
bool eventFilter(QObject *o, QEvent *e)
Event filter for MatchTool.
Definition: MatchTool.cpp:2540
void previousRightMeasure()
Selects the previous right measure when activated by key shortcut.
Definition: MatchTool.cpp:2260
void remove(const QString &sn)
Remove the specified serial number from the list.
Container for cube-like labels.
Definition: Pvl.h:135
void loadMeasureTable()
Load measure information into the measure table.
Definition: MatchTool.cpp:2030
void saveTemplateFile()
save the file opened in the template editor
Definition: MatchTool.cpp:2794
void updatePointInfo(QString pointId)
Update the current editPoint information in the Point Editor labels.
Definition: MatchTool.cpp:2937
void saveNet()
Signal to save control net.
Definition: MatchTool.cpp:1373
void writeSettings() const
This method is called when the Main window is closed or hidden to write the size and location setting...
Definition: MatchTool.cpp:3064
void loadTemplateFile(QString)
Updates the current template file being used.
Definition: MatchTool.cpp:2762
void selectLeftMeasure(int index)
Select left measure.
Definition: MatchTool.cpp:2284
Status SetType(PointType newType)
Updates the control point&#39;s type.
void viewTemplateFile()
Allows the user to view the template file that is currently set.
Definition: MatchTool.cpp:2883
Status SetId(QString id)
Sets the Id of the control point.
const ControlMeasure * GetRefMeasure() const
Get the reference control measure.
Status
This is a return status for many of the mutating (setter) method calls.
Definition: ControlPoint.h:408
GoodnessOfFit is pointreg information for reference measures.
QString toString() const
Returns a string representation of this exception.
Definition: IException.cpp:553
int IndexOfRefMeasure() const
void refresh()
Refresh all necessary widgets in MatchTool including the PointEditor and CubeViewports.
Definition: MatchTool.cpp:2973
void measureSaved()
This method is connected with the measureSaved() signal from ControlPointEdit.
Definition: MatchTool.cpp:788
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
void nextRightMeasure()
Selects the next right measure when activated by key shortcut.
Definition: MatchTool.cpp:2241
void paintAllViewports()
This method will repaint the given Point ID in each viewport Note: The pointId parameter is here even...
Definition: MatchTool.cpp:2580
static QString UserName()
Returns the user name.
Isis exception class.
Definition: IException.h:107
void setIgnoreLeftMeasure(bool ignore)
Set the "Ignore" keyword of the measure shown in the left viewport to the value of the input paramete...
Definition: MatchTool.cpp:1213
Status SetChooserName()
Set chooser name to a user who last changed the coordinate.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
bool IsEditLocked() const
Return value for p_editLock or implicit lock on reference measure.
Base class for the Qisis tools.
Definition: Tool.h:81
a control measurement
PvlEditDialog creates a QDialog window in which a QTextEdit box displays the contents of a pvl file...
Definition: PvlEditDialog.h:39
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
Status SetCoordinate(double sample, double line)
Set the coordinate of the measurement.
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition: Tool.h:211
void setLockPoint(bool ignore)
Set point&#39;s "EditLock" keyword to the value of the input parameter.
Definition: MatchTool.cpp:1121
void savePoint()
Save edit point to the Control Network.
Definition: MatchTool.cpp:1079
Point Editor Widget.
int Delete(ControlMeasure *measure)
Remove a measurement from the control point, deleting reference measure is allowed.
Status SetDateTime()
Date Time - Creation Time.
void mouseButtonRelease(QPoint p, Qt::MouseButton s)
Handle mouse events on CubeViewport.
Definition: MatchTool.cpp:1457
void createMenus()
Customize dropdown menus below title bar.
Definition: MatchTool.cpp:569
double GetNumericalValue() const
Get the value associated with this log data.
void setLockRightMeasure(bool ignore)
Set the "EditLock" keyword of the measure shown in the right viewport to the value of the input param...
Definition: MatchTool.cpp:1243
Serial Number list generator.
void paintViewport(MdiCubeViewport *mvp, QPainter *painter)
Take care of drawing things on a viewPort.
Definition: MatchTool.cpp:2561
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
void setLockLeftMeasure(bool ignore)
Set the "EditLock" keyword of the measure shown in the left viewport to the value of the input parame...
Definition: MatchTool.cpp:1172
QString GetCubeSerialNumber() const
Return the serial number of the cube containing the coordinate.
void createMatchTool(QWidget *parent)
create the main window for editing control points
Definition: MatchTool.cpp:165
void createActions()
Creates the menu actions for Match Tool.
Definition: MatchTool.cpp:460
static QString MeasureTypeToString(MeasureType type)
Return the String Control Measure type.
void setLeftMeasure(ControlMeasure *leftMeasure, Cube *leftCube, QString pointId)
Set the measure displayed in the left ChipViewport.
This is returned when the operation requires Edit Lock to be false but it is currently true...
Definition: ControlPoint.h:423
IO Handler for Isis Cubes.
Definition: Cube.h:170