Isis 3.0 Programmer Reference
Back | Home
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.Delete(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 
1396 
1397  QString fn = QFileDialog::getSaveFileName(m_matchTool,
1398  "Choose filename to save under",
1399  ".",
1400  "Control Files (*.net)");
1401 
1402  //Make sure the filename is valid
1403  if(!fn.isEmpty()) {
1404  try {
1405  m_controlNet->Write(fn);
1406  m_netChanged = false;
1407  }
1408  catch (IException &e) {
1409  QMessageBox::critical(m_matchTool, tr("Error Writing Control Net"), e.what());
1410  return;
1411  }
1412  m_cnetFileName = fn;
1413  }
1414  //The user cancelled, or the filename is empty
1415  else {
1416  return;
1417  }
1418 
1419  }
1420 
1421 
1422 
1450  void MatchTool::mouseButtonRelease(QPoint p, Qt::MouseButton s) {
1451  MdiCubeViewport *mvp = cubeViewport();
1452  if (mvp == NULL) return;
1453 
1454  QString file = mvp->cube()->fileName();
1455  QString sn = serialNumberList().serialNumber(file);
1456 
1457  double samp,line;
1458  mvp->viewportToCube(p.x(),p.y(),samp,line);
1459 
1460  if (s == Qt::LeftButton) {
1461 
1462  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1463  QString message = "No points exist for editing. Create points ";
1464  message += "using the right mouse button.";
1465  QMessageBox::warning(m_matchTool, "Warning", message);
1466  return;
1467  }
1468 
1469  // Find closest control point in network
1470  QString sn = serialNumberList().serialNumber(file);
1471  ControlPoint *point = NULL;
1472  try {
1473  point = m_controlNet->FindClosest(sn, samp, line);
1474  }
1475  catch (IException &e) {
1476  QString message = "Cannot find point for editing.";
1477  message += e.toString();
1478  QMessageBox::warning(m_matchTool, "Warning", message);
1479  return;
1480  }
1481 
1482  modifyPoint(point);
1483  }
1484  else if (s == Qt::MidButton) {
1485  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1486  QString message = "No points exist for deleting. Create points ";
1487  message += "using the right mouse button.";
1488  QMessageBox::warning(m_matchTool, "Warning", message);
1489  return;
1490  }
1491 
1492  // Find closest control point in network
1493  ControlPoint *point = m_controlNet->FindClosest(sn, samp, line);
1494 
1495  if (point == NULL) {
1496  QString message = "No points exist for deleting. Create points ";
1497  message += "using the right mouse button.";
1498  QMessageBox::warning(m_matchTool, "Warning", message);
1499  return;
1500  }
1501 
1502  deletePoint(point);
1503  }
1504  else if (s == Qt::RightButton) {
1505  if (m_newPointDialog) {
1506  addMeasure(mvp, samp, line);
1507  }
1508  else {
1509  try {
1510  createPoint(mvp, samp, line);
1511  m_leftFile = mvp->cube()->fileName();
1512  }
1513  catch (IException &e) {
1514  QString message = "Cannot create control point.\n\n";
1515  message += e.toString();
1516  QMessageBox::critical(m_matchTool, "Error", message);
1517  return;
1518  }
1519  }
1520  }
1521  }
1522 
1523 
1524 
1525  QStringList MatchTool::missingCubes(ControlPoint *point) {
1526 
1527  // Make sure all measures are loaded into viewports, otherwise we cannot edit this point
1528  QStringList missingCubes;
1529  for (int i=0; i<point->GetNumMeasures(); i++) {
1530  ControlMeasure &m = *(*point)[i];
1532  missingCubes << m.GetCubeSerialNumber();
1533  }
1534  }
1535  return missingCubes;
1536  }
1537 
1538 
1539 
1546  void MatchTool::createPoint(MdiCubeViewport *cvp, double sample, double line) {
1547 
1548  m_newPointDialog = new MatchToolNewPointDialog(*m_controlNet, m_lastUsedPointId, m_matchTool);
1549  connect(m_newPointDialog, SIGNAL(measuresFinished()), this, SLOT(doneWithMeasures()));
1550  connect(m_newPointDialog, SIGNAL(newPointCanceled()), this, SLOT(cancelNewPoint()));
1551 
1552  QStringList images;
1553  for (int i = 0; i < (int)cubeViewportList()->size(); i++) {
1554  FileName cubeFile = (*(cubeViewportList()))[i]->cube()->fileName();
1555  images<<cubeFile.name();
1556  }
1557  m_newPointDialog->setFiles(images);
1558  m_newPointDialog->show();
1559 
1560  // Highlight the current cubeViewport
1561  QString current = FileName(cvp->cube()->fileName()).name();
1562  m_newPointDialog->highlightFile(current);
1563 
1564  m_newPoint = new ControlPoint();
1565  m_newPoint->SetType(ControlPoint::Free);
1566  m_newPoint->SetChooserName(Application::UserName());
1567 
1568  ControlMeasure *m = new ControlMeasure;
1569  m->SetCubeSerialNumber(serialNumber(cvp));
1570  m->SetCoordinate(sample, line);
1572  m->SetDateTime();
1574  m_newPoint->Add(m);
1575 
1577  }
1578 
1579 
1580 
1581  void MatchTool::addMeasure(MdiCubeViewport *cvp, double sample, double line) {
1582 
1583  // Highlight the current cubeViewport
1584  QString current = FileName(cvp->cube()->fileName()).name();
1585  m_newPointDialog->highlightFile(current);
1586  m_newPointDialog->raise();
1587 
1588  ControlMeasure *m = new ControlMeasure;
1589  m->SetCubeSerialNumber(serialNumber(cvp));
1590 
1591  // If serial number already exists, delete old measure before creating new
1592  if (m_newPoint->HasSerialNumber(serialNumber(cvp))) {
1593  m_newPoint->Delete(m_newPoint->GetMeasure(serialNumber(cvp)));
1594  }
1595  m->SetCoordinate(sample, line);
1597  m->SetDateTime();
1599  m_newPoint->Add(m);
1600 
1602  }
1603 
1604 
1605 
1606  void MatchTool::doneWithMeasures() {
1607 
1608  m_lastUsedPointId = m_newPointDialog->pointId();
1609  m_newPoint->SetId(m_lastUsedPointId);
1610 // // Add new control point to control network
1611 // m_controlNet->AddPoint(m_newPoint);
1612 // // Read newly added point
1613 // // TODO Make sure pt exists
1614 // m_editPoint = m_controlNet->GetPoint((QString) m_newPoint->GetId());
1615 
1616  // If this is a coreg network, make sure the reference SN exists in the new point
1617  // and set it to the reference measure.
1618  if (m_coregNet) {
1619  if (!m_newPoint->HasSerialNumber(m_coregReferenceSN)) {
1620  QString message = "This is a coreg network which needs the cube with serial number " +
1621  m_coregReferenceSN + " as the reference measure. This new control point does "
1622  "not have a measure for that serial number, so this point cannot be created until "
1623  "the cube listed above is added (Right-click on cube).";
1624  QMessageBox::critical(m_matchTool, "Error", message);
1625  m_newPointDialog->show();
1626  return;
1627  }
1628  // Set the reference measure to match the rest of the points
1629  m_newPoint->SetRefMeasure(m_newPoint->GetMeasure(m_coregReferenceSN));
1630  }
1631 
1632  // If the editPoint has been used, but there is not currently a network, delete the editPoint
1633  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1634  delete m_editPoint;
1635  m_editPoint = NULL;
1636  }
1637  m_editPoint = m_newPoint;
1638 
1639  m_newPoint = NULL;
1640  delete m_newPointDialog;
1641  m_newPointDialog = NULL;
1642 
1643  // Load new point in MatchTool
1644  loadPoint();
1645  m_matchTool->setVisible(true);
1646  m_matchTool->raise();
1647 
1648  emit editPointChanged();
1650  }
1651 
1652 
1653 
1654  void MatchTool::cancelNewPoint() {
1655 
1656  delete m_newPointDialog;
1657  m_newPointDialog = NULL;
1658  delete m_newPoint;
1659  m_newPoint = NULL;
1660  m_leftFile.clear();
1661 
1663 
1664  }
1665 
1666 
1667 
1687 
1688  QStringList mCubes = missingCubes(point);
1689  if (mCubes.size() > 0) {
1690  QString msgTitle = "Missing Cubes";
1691  QString message = "This point is missing cubes for the following measures and cannot be ";
1692  message += "loaded into the editor. Do you still want to delete this point?\n\n";
1693  for (int i=0; i<mCubes.size(); i++) {
1694  message += mCubes.at(i) + "\n";
1695  }
1696  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1697  Qt::Dialog);
1698  QPushButton *yesButton = msgBox.addButton("Yes", QMessageBox::AcceptRole);
1699  QPushButton *noButton = msgBox.addButton("No", QMessageBox::RejectRole);
1700  msgBox.setDefaultButton(yesButton);
1701  msgBox.exec();
1702  if (msgBox.clickedButton() == noButton) {
1703  return;
1704  }
1705  else {
1706  m_matchTool->setVisible(false);
1707  }
1708 
1709  }
1710 
1711  // Make a copy and make sure editPoint is a copy (which means it does not
1712  // have a parent network.
1713  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1714  delete m_editPoint;
1715  m_editPoint = NULL;
1716  }
1717  m_editPoint = new ControlPoint;
1718  *m_editPoint = *point;
1719 
1720  // No missing cubes, load edit point as usual
1721  if (mCubes.size() == 0) {
1722  loadPoint();
1723 
1724  // Change point in viewport to red so user can see what point they are
1725  // about to delete.
1726  // the nav tool will update edit point
1727  emit editPointChanged();
1728  }
1729 
1730  MatchToolDeletePointDialog *deletePointDialog = new MatchToolDeletePointDialog;
1731  QString CPId = m_editPoint->GetId();
1732  deletePointDialog->pointIdValue->setText(CPId);
1733  // Need all files for this point
1734  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1735  ControlMeasure &m = *(*m_editPoint)[i];
1736  QString file;
1739  }
1740  else {
1741  file = m.GetCubeSerialNumber();
1742  }
1743  deletePointDialog->fileList->addItem(file);
1744  }
1745 
1746  if (deletePointDialog->exec()) {
1747 
1748  int numDeleted = deletePointDialog->fileList->selectedItems().count();
1749 
1750  // Delete entire control point, either through deleteAllCheckBox or all measures selected
1751  if (deletePointDialog->deleteAllCheckBox->isChecked() ||
1752  numDeleted == m_editPoint->GetNumMeasures()) {
1753 
1754  // If all measures being deleted, let user know and give them the option to quit operation
1755  if (!deletePointDialog->deleteAllCheckBox->isChecked()) {
1756  QString message = "You have selected all measures in this point to be deleted. This "
1757  "control point will be deleted. Do you want to delete this control point?";
1758  int response = QMessageBox::question(m_matchTool,
1759  "Delete control point", message,
1760  QMessageBox::Yes | QMessageBox::No,
1761  QMessageBox::Yes);
1762  // If No, do nothing
1763  if (response == QMessageBox::No) {
1764  return;
1765  }
1766  }
1767 
1768  m_matchTool->setVisible(false);
1769  // remove this point from the control network
1770  if (m_controlNet->DeletePoint(m_editPoint->GetId()) == ControlPoint::PointLocked) {
1771  QMessageBox::information(m_matchTool, "EditLocked Point",
1772  "This point is EditLocked and cannot be deleted.");
1773  return;
1774  }
1775  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1776  delete m_editPoint;
1777  m_editPoint = NULL;
1778  }
1779  }
1780 
1781  // Delete specific measures from control point
1782  else {
1783  // Keep track of editLocked measures for reporting
1784  int lockedMeasures = 0;
1785  for (int i=0; i<deletePointDialog->fileList->count(); i++) {
1786  QListWidgetItem *item = deletePointDialog->fileList->item(i);
1787  if (!deletePointDialog->fileList->isItemSelected(item)) continue;
1788 
1789  // Do not delete reference without asking user
1790  if (m_editPoint->IsReferenceExplicit() &&
1791  (m_editPoint->GetRefMeasure()->GetCubeSerialNumber() ==
1792  (*m_editPoint)[i]->GetCubeSerialNumber())) {
1793  QString message = "You are trying to delete the Reference measure."
1794  " Do you really want to delete the Reference measure?";
1795  switch (QMessageBox::question(m_matchTool,
1796  "Delete Reference measure?", message,
1797  "&Yes", "&No", 0, 0)) {
1798  // Yes: skip to end of switch to delete the measure
1799  case 0:
1800  break;
1801  // No: continue to next measure in the loop
1802  case 1:
1803  // if only a single measure and it's reference and user chooses not to delete,
1804  // simply return. The point has not changed.
1805  if (numDeleted == 1) {
1806  return;
1807  }
1808  continue;
1809  }
1810  }
1811 
1812  if (m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
1813  lockedMeasures++;
1814  }
1815  }
1816 
1817  if (lockedMeasures > 0) {
1818  QMessageBox::information(m_matchTool,"EditLocked Measures",
1819  QString::number(lockedMeasures) + " / "
1820  + QString::number(
1821  deletePointDialog->fileList->selectedItems().size()) +
1822  " measures are EditLocked and were not deleted.");
1823  }
1824 
1825  if (mCubes.size() == 0) {
1826  loadPoint();
1827  m_matchTool->setVisible(true);
1828  m_matchTool->raise();
1829 
1831  m_pointEditor->templateFileName());
1832  }
1833  // Since the delete point is not loaded into the editor for saving by the user, we need
1834  // to save the point.
1835  else {
1836  ControlPoint *p = m_controlNet->GetPoint(QString(m_editPoint->GetId()));
1837  *p = *m_editPoint;
1838 
1839  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1840  delete m_editPoint;
1841  m_editPoint = NULL;
1842  }
1843  }
1844  }
1845 
1846  // emit a signal to alert user to save when exiting
1847  // At exit, or when opening new net, use for prompting user for a save
1848  m_netChanged = true;
1849 
1850  if (m_editPoint) {
1852  }
1853  emit editPointChanged();
1854  }
1855  }
1856 
1857 
1858 
1868 
1869  // If no measures, print info and return
1870  if (point->GetNumMeasures() == 0) {
1871  QString message = "This point has no measures.";
1872  QMessageBox::warning(m_matchTool, "Warning", message);
1873  emit editPointChanged();
1874  return;
1875  }
1876 
1877  // Make sure all measures have a cube loaded
1878  QStringList mCubes = missingCubes(point);
1879  if (mCubes.size() > 0) {
1880  QString msgTitle = "Missing Cubes";
1881  QString message = "This point is missing cubes and cannot be loaded into the editor. Open ";
1882  message += "the cubes for the following measures before selecting this point.\n\n";
1883  for (int i=0; i<mCubes.size(); i++) {
1884  message += mCubes.at(i) + "\n";
1885  }
1886  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1887  Qt::Dialog);
1888  msgBox.exec();
1889  return;
1890  }
1891 
1892  // Make a copy of point for editing, first make sure memory not already
1893  // allocated
1894  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1895  delete m_editPoint;
1896  m_editPoint = NULL;
1897  }
1898  m_editPoint = new ControlPoint;
1899  *m_editPoint = *point;
1900 
1901  loadPoint();
1902  m_matchTool->setVisible(true);
1903  m_matchTool->raise();
1905  m_pointEditor->templateFileName());
1906 
1907  // emit signal so the nav tool can update edit point
1908  emit editPointChanged();
1909 
1910  // New point loaded, make sure Save Measure Button text is default
1911  m_savePoint->setPalette(m_saveDefaultPalette);
1912  }
1913 
1914 
1915 
1934 
1935  // Write pointId
1936  QString CPId = m_editPoint->GetId();
1937  QString ptId("Point ID: ");
1938  ptId += (QString) CPId;
1939  m_ptIdValue->setText(ptId);
1940 
1941  // Write number of measures
1942  QString ptsize = "Number of Measures: " +
1943  QString::number(m_editPoint->GetNumMeasures());
1944  m_numMeasures->setText(ptsize);
1945 
1946  // Set EditLock box correctly
1947  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
1948 
1949  // Set ignore box correctly
1950  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1951 
1952  // Clear combo boxes
1953  m_leftCombo->clear();
1954  m_rightCombo->clear();
1955  m_pointFiles.clear();
1956 
1957  // Need all files for this point
1958  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1959  ControlMeasure &m = *(*m_editPoint)[i];
1960  QString file = serialNumberList().fileName(m.GetCubeSerialNumber());
1961  m_pointFiles<<file;
1962  QString tempFileName = FileName(file).name();
1963  m_leftCombo->addItem(tempFileName);
1964  m_rightCombo->addItem(tempFileName);
1965  if (m_editPoint->IsReferenceExplicit() &&
1966  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
1967  m_leftCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1968  m_rightCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1969  }
1970  }
1971 
1972  // TODO: WHAT HAPPENS IF THERE IS ONLY ONE MEASURE IN THIS CONTROLPOINT??
1973  // Assuming combo loaded in same order as measures in the control point-is
1974  // this a safe assumption???
1975  //
1976  // Find the file from the cubeViewport that was originally used to select
1977  // the point, this will be displayed on the left ChipViewport, unless the
1978  // point was selected on the ground source image. In this case, simply
1979  // load the first measure on the left.
1980  int leftIndex = 0;
1981  int rightIndex = 0;
1982  // Check for reference
1983  if (m_editPoint->IsReferenceExplicit()) {
1984  leftIndex = m_editPoint->IndexOfRefMeasure();
1985  }
1986  else {
1987  if (!m_leftFile.isEmpty()) {
1988  leftIndex = m_leftCombo->findText(FileName(m_leftFile).name());
1989  // Sanity check
1990  if (leftIndex < 0 ) leftIndex = 0;
1991  m_leftFile.clear();
1992  }
1993  }
1994 
1995  if (leftIndex == 0) {
1996  rightIndex = 1;
1997  }
1998  else {
1999  rightIndex = 0;
2000  }
2001 
2002  // Handle pts with a single measure, for now simply put measure on left/right
2003  // Evenutally put on left with black on right??
2004  if (rightIndex > m_editPoint->GetNumMeasures()-1) rightIndex = 0;
2005  m_rightCombo->setCurrentIndex(rightIndex);
2006  m_leftCombo->setCurrentIndex(leftIndex);
2007  // Initialize pointEditor with measures
2008  selectLeftMeasure(leftIndex);
2009  selectRightMeasure(rightIndex);
2010 
2011  loadMeasureTable();
2012  }
2013 
2014 
2015 
2024  if (m_measureWindow == NULL) {
2025  m_measureWindow = new QMainWindow(m_parent);
2026  m_measureTable = new QTableWidget();
2027  m_measureTable->setMinimumWidth(1600);
2028  m_measureTable->setAlternatingRowColors(true);
2029  m_measureWindow->setCentralWidget(m_measureTable);
2030  }
2031  else {
2032  m_measureTable->clear();
2033  m_measureTable->setSortingEnabled(false);
2034  }
2035  m_measureTable->setRowCount(m_editPoint->GetNumMeasures());
2036  m_measureTable->setColumnCount(NUMCOLUMNS);
2037 
2038  QStringList labels;
2039  for (int i=0; i<NUMCOLUMNS; i++) {
2040  labels<<measureColumnToString((MeasureColumns)i);
2041  }
2042  m_measureTable->setHorizontalHeaderLabels(labels);
2043 
2044  // Fill in values
2045  for (int row=0; row<m_editPoint->GetNumMeasures(); row++) {
2046  int column = 0;
2047  ControlMeasure &m = *(*m_editPoint)[row];
2048 
2049  QString file = serialNumberList().fileName(m.GetCubeSerialNumber());
2050  QTableWidgetItem *tableItem = new QTableWidgetItem(QString(file));
2051  m_measureTable->setItem(row,column++,tableItem);
2052 
2053  tableItem = new QTableWidgetItem(QString(m.GetCubeSerialNumber()));
2054  m_measureTable->setItem(row,column++,tableItem);
2055 
2056  tableItem = new QTableWidgetItem();
2057  tableItem->setData(0,m.GetSample());
2058  m_measureTable->setItem(row,column++,tableItem);
2059 
2060  tableItem = new QTableWidgetItem();
2061  tableItem->setData(0,m.GetLine());
2062  m_measureTable->setItem(row,column++,tableItem);
2063 
2064  if (m.GetAprioriSample() == Null) {
2065  tableItem = new QTableWidgetItem("Null");
2066  }
2067  else {
2068  tableItem = new QTableWidgetItem();
2069  tableItem->setData(0,m.GetAprioriSample());
2070  }
2071  m_measureTable->setItem(row,column++,tableItem);
2072 
2073  if (m.GetAprioriLine() == Null) {
2074  tableItem = new QTableWidgetItem("Null");
2075  }
2076  else {
2077  tableItem = new QTableWidgetItem();
2078  tableItem->setData(0,m.GetAprioriLine());
2079  }
2080  m_measureTable->setItem(row,column++,tableItem);
2081 
2082  if (m.GetSampleResidual() == Null) {
2083  tableItem = new QTableWidgetItem(QString("Null"));
2084  }
2085  else {
2086  tableItem = new QTableWidgetItem();
2087  tableItem->setData(0,m.GetSampleResidual());
2088  }
2089  m_measureTable->setItem(row,column++,tableItem);
2090 
2091  if (m.GetLineResidual() == Null) {
2092  tableItem = new QTableWidgetItem(QString("Null"));
2093  }
2094  else {
2095  tableItem = new QTableWidgetItem();
2096  tableItem->setData(0,m.GetLineResidual());
2097  }
2098  m_measureTable->setItem(row,column++,tableItem);
2099 
2100  if (m.GetResidualMagnitude() == Null) {
2101  tableItem = new QTableWidgetItem(QString("Null"));
2102  }
2103  else {
2104  tableItem = new QTableWidgetItem();
2105  tableItem->setData(0,m.GetResidualMagnitude());
2106  }
2107  m_measureTable->setItem(row,column++,tableItem);
2108 
2109  double sampleShift = m.GetSampleShift();
2110  if (sampleShift == Null) {
2111  tableItem = new QTableWidgetItem(QString("Null"));
2112  }
2113  else {
2114  tableItem = new QTableWidgetItem();
2115  tableItem->setData(0,sampleShift);
2116  }
2117  m_measureTable->setItem(row,column++,tableItem);
2118 
2119  double lineShift = m.GetLineShift();
2120  if (lineShift == Null) {
2121  tableItem = new QTableWidgetItem(QString("Null"));
2122  }
2123  else {
2124  tableItem = new QTableWidgetItem();
2125  tableItem->setData(0,lineShift);
2126  }
2127  m_measureTable->setItem(row,column++,tableItem);
2128 
2129  double pixelShift = m.GetPixelShift();
2130  if (pixelShift == Null) {
2131  tableItem = new QTableWidgetItem(QString("Null"));
2132  }
2133  else {
2134  tableItem = new QTableWidgetItem();
2135  tableItem->setData(0,pixelShift);
2136  }
2137  m_measureTable->setItem(row,column++,tableItem);
2138 
2139  double goodnessOfFit = m.GetLogData(
2141  if (goodnessOfFit == Null) {
2142  tableItem = new QTableWidgetItem(QString("Null"));
2143  }
2144  else {
2145  tableItem = new QTableWidgetItem();
2146  tableItem->setData(0,goodnessOfFit);
2147  }
2148  m_measureTable->setItem(row,column++,tableItem);
2149 
2150  if (m.IsIgnored()) tableItem = new QTableWidgetItem("True");
2151  if (!m.IsIgnored()) tableItem = new QTableWidgetItem("False");
2152  m_measureTable->setItem(row,column++,tableItem);
2153 
2155  tableItem = new QTableWidgetItem("True");
2157  tableItem = new QTableWidgetItem("False");
2158  m_measureTable->setItem(row,column++,tableItem);
2159 
2160  tableItem = new QTableWidgetItem(
2162  m_measureTable->setItem(row,column,tableItem);
2163 
2164  // If reference measure set font on this row to bold
2165  if (m_editPoint->IsReferenceExplicit() &&
2166  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
2167  QFont font;
2168  font.setBold(true);
2169 
2170  for (int col=0; col<m_measureTable->columnCount(); col++)
2171  m_measureTable->item(row, col)->setFont(font);
2172  }
2173 
2174  }
2175 
2176  m_measureTable->resizeColumnsToContents();
2177  m_measureTable->resizeRowsToContents();
2178  m_measureTable->setSortingEnabled(true);
2179  m_measureWindow->show();
2180  }
2181 
2182 
2183 
2184  QString MatchTool::measureColumnToString(MatchTool::MeasureColumns column) {
2185  switch (column) {
2186  case FILENAME:
2187  return "FileName";
2188  case CUBESN:
2189  return "Serial #";
2190  case SAMPLE:
2191  return "Sample";
2192  case LINE:
2193  return "Line";
2194  case SAMPLERESIDUAL:
2195  return "Sample Residual";
2196  case LINERESIDUAL:
2197  return "Line Residual";
2198  case RESIDUALMAGNITUDE:
2199  return "Residual Magnitude";
2200  case SAMPLESHIFT:
2201  return "Sample Shift";
2202  case LINESHIFT:
2203  return "Line Shift";
2204  case PIXELSHIFT:
2205  return "Pixel Shift";
2206  case GOODNESSOFFIT:
2207  return "Goodness of Fit";
2208  case IGNORED:
2209  return "Ignored";
2210  case EDITLOCK:
2211  return "Edit Lock";
2212  case TYPE:
2213  return "Measure Type";
2214  case APRIORISAMPLE:
2215  return "Apriori Sample";
2216  case APRIORILINE:
2217  return "Apriori Line";
2218  }
2219  throw IException(IException::Programmer,
2220  "Invalid measure column passed to measureColumnToString", _FILEINFO_);
2221  }
2222 
2223 
2224 
2235  int curIndex = m_rightCombo->currentIndex();
2236  if (curIndex < m_rightCombo->count() - 1) {
2237  // update the right measure list index and select that measure
2238  m_rightCombo->setCurrentIndex(curIndex + 1);
2239  selectRightMeasure(curIndex+1);
2240  }
2241  }
2242 
2243 
2254  int curIndex = m_rightCombo->currentIndex();
2255  if (curIndex > 0) {
2256  // update the right measure list index and select that measure
2257  m_rightCombo->setCurrentIndex(curIndex - 1);
2258  selectRightMeasure(curIndex-1);
2259  }
2260  }
2261 
2262 
2263 
2278  QString file = m_pointFiles[index];
2279 
2280  QString serial;
2281  try {
2282  serial = serialNumberList().serialNumber(file);
2283  }
2284  catch (IException &e) {
2285  QString message = "Make sure the correct cube is opened.\n\n";
2286  message += e.toString();
2287  QMessageBox::critical(m_matchTool, "Error", message);
2288 
2289  // Set index of combo back to what it was before user selected new. Find the index
2290  // of current left measure.
2291  QString file = serialNumberList().fileName(m_leftMeasure->GetCubeSerialNumber());
2292  int i = m_leftCombo->findText(FileName(file).name());
2293  if (i < 0) i = 0;
2294  m_leftCombo->setCurrentIndex(i);
2295  return;
2296  }
2297 
2298  // Make sure to clear out leftMeasure before making a copy of the selected
2299  // measure.
2300  if (m_leftMeasure != NULL) {
2301  delete m_leftMeasure;
2302  m_leftMeasure = NULL;
2303  }
2304  m_leftMeasure = new ControlMeasure();
2305  // Find measure for each file
2306  *m_leftMeasure = *((*m_editPoint)[serial]);
2307 
2308  // If m_leftCube is not null, delete before creating new one
2309  if (m_leftCube != NULL) delete m_leftCube;
2310  m_leftCube = new Cube();
2311  m_leftCube->open(file);
2312 
2313  // Update left measure of pointEditor
2314  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube,
2315  m_editPoint->GetId());
2317 
2318  }
2319 
2320 
2333 
2334  QString file = m_pointFiles[index];
2335 
2336  QString serial;
2337  try {
2338  serial = serialNumberList().serialNumber(file);
2339  }
2340  catch (IException &e) {
2341  QString message = "Make sure the correct cube is opened.\n\n";
2342  message += e.toString();
2343  QMessageBox::critical(m_matchTool, "Error", message);
2344 
2345  // Set index of combo back to what it was before user selected new. Find the index
2346  // of current left measure.
2347  QString file = serialNumberList().fileName(m_rightMeasure->GetCubeSerialNumber());
2348  int i = m_rightCombo->findText(FileName(file).name());
2349  if (i < 0) i = 0;
2350  m_rightCombo->setCurrentIndex(i);
2351  return;
2352  }
2353 
2354  // Make sure to clear out rightMeasure before making a copy of the selected
2355  // measure.
2356  if (m_rightMeasure != NULL) {
2357  delete m_rightMeasure;
2358  m_rightMeasure = NULL;
2359  }
2360  m_rightMeasure = new ControlMeasure();
2361  // Find measure for each file
2362  *m_rightMeasure = *((*m_editPoint)[serial]);
2363 
2364  // If m_leftCube is not null, delete before creating new one
2365  if (m_rightCube != NULL) delete m_rightCube;
2366  m_rightCube = new Cube();
2367  m_rightCube->open(file);
2368 
2369  // Update left measure of pointEditor
2370  m_pointEditor->setRightMeasure (m_rightMeasure,m_rightCube,
2371  m_editPoint->GetId());
2373 
2374  }
2375 
2376 
2377 
2378 
2395 
2396  // Set editLock measure box correctly
2397  m_lockLeftMeasure->setChecked(IsMeasureLocked(
2398  m_leftMeasure->GetCubeSerialNumber()));
2399  // Set ignore measure box correctly
2400  m_ignoreLeftMeasure->setChecked(m_leftMeasure->IsIgnored());
2401 
2402  QString s = "Reference: ";
2403  if (m_editPoint->IsReferenceExplicit() &&
2404  (QString(m_leftMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2405  s += "True";
2406  }
2407  else {
2408  s += "False";
2409  }
2410  m_leftReference->setText(s);
2411 
2412  s = "Measure Type: ";
2413  if (m_leftMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2414  if (m_leftMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2415  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2416  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2417  m_leftMeasureType->setText(s);
2418 
2419  if (m_leftMeasure->GetSampleShift() == Null) {
2420  s = "Sample Shift: Null";
2421  }
2422  else {
2423  s = "Sample Shift: " + QString::number(m_leftMeasure->GetSampleShift());
2424  }
2425  m_leftSampShift->setText(s);
2426 
2427  if (m_leftMeasure->GetLineShift() == Null) {
2428  s = "Line Shift: Null";
2429  }
2430  else {
2431  s = "Line Shift: " + QString::number(m_leftMeasure->GetLineShift());
2432  }
2433  m_leftLineShift->setText(s);
2434 
2435  double goodnessOfFit = m_leftMeasure->GetLogData(
2437  if (goodnessOfFit == Null) {
2438  s = "Goodness of Fit: Null";
2439  }
2440  else {
2441  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2442  }
2443  m_leftGoodness->setText(s);
2444 
2445  }
2446 
2447 
2448 
2468 
2469  // Set editLock measure box correctly
2470  m_lockRightMeasure->setChecked(IsMeasureLocked(
2471  m_rightMeasure->GetCubeSerialNumber()));
2472  // Set ignore measure box correctly
2473  m_ignoreRightMeasure->setChecked(m_rightMeasure->IsIgnored());
2474 
2475  QString s = "Reference: ";
2476  if (m_editPoint->IsReferenceExplicit() &&
2477  (QString(m_rightMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2478  s += "True";
2479  }
2480  else {
2481  s += "False";
2482  }
2483 
2484  m_rightReference->setText(s);
2485 
2486  s = "Measure Type: ";
2487  if (m_rightMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2488  if (m_rightMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2489  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2490  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2491  m_rightMeasureType->setText(s);
2492 
2493  if (m_rightMeasure->GetSampleShift() == Null) {
2494  s = "Sample Shift: Null";
2495  }
2496  else {
2497  s = "Sample Shift: " + QString::number(m_rightMeasure->GetSampleShift());
2498  }
2499  m_rightSampShift->setText(s);
2500 
2501  if (m_rightMeasure->GetLineShift() == Null) {
2502  s = "Line Shift: Null";
2503  }
2504  else {
2505  s = "Line Shift: " + QString::number(m_rightMeasure->GetLineShift());
2506  }
2507  m_rightLineShift->setText(s);
2508 
2509  double goodnessOfFit = m_rightMeasure->GetLogData(
2511  if (goodnessOfFit == Null) {
2512  s = "Goodness of Fit: Null";
2513  }
2514  else {
2515  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2516  }
2517  m_rightGoodness->setText(s);
2518 
2519  }
2520 
2521 
2522 
2533  bool MatchTool::eventFilter(QObject *o, QEvent *e) {
2534  if(e->type() != QEvent::Leave) return false;
2535  if(o == m_leftCombo->view()) {
2537  m_leftCombo->hidePopup();
2538  }
2539  if (o == m_rightCombo->view()) {
2541  m_rightCombo->hidePopup();
2542  }
2543  return true;
2544  }
2545 
2546 
2554  void MatchTool::paintViewport(MdiCubeViewport *mvp, QPainter *painter) {
2555  drawAllMeasurments (mvp,painter);
2556 
2557  }
2558 
2559 
2574 
2575  // Take care of drawing things on all viewPorts.
2576  // Calling update will cause the Tool class to call all registered tools
2577  // if point has been deleted, this will remove it from the main window
2578  MdiCubeViewport *mvp;
2579  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
2580  mvp = (*(cubeViewportList()))[i];
2581  mvp->viewport()->update();
2582  }
2583  }
2584 
2607  void MatchTool::drawAllMeasurments(MdiCubeViewport *mvp, QPainter *painter) {
2608 
2609  // Make sure we have points to draw
2610  if ( (m_controlNet == NULL || m_controlNet->GetNumPoints() == 0) && m_newPoint == NULL &&
2611  m_editPoint == NULL)
2612  return;
2613 
2614  QString sn = serialNumber(mvp);
2615 // QString serialNumber = SerialNumber::Compose(*vp->cube(), true);
2616 
2617  // In the middle of creating a new point
2618  if (m_newPoint != NULL) {
2619  // and the selected point is in the image,
2620  if (m_newPoint->HasSerialNumber(sn)) {
2621  // find the measurement
2622  double samp = (*m_newPoint)[sn]->GetSample();
2623  double line = (*m_newPoint)[sn]->GetLine();
2624  int x, y;
2625  mvp->cubeToViewport(samp, line, x, y);
2626  // set point marker red
2627  QBrush brush(Qt::red);
2628  // set point marker bold - line width 2
2629  QPen pen(brush, 2);
2630  // draw the selected point in each image last so it's on top of the rest of the points
2631  painter->setPen(pen);
2632  painter->drawLine(x - 5, y, x + 5, y);
2633  painter->drawLine(x, y - 5, x, y + 5);
2634  }
2635  }
2636 
2637  // If viewport serial number not found in control net, return
2638  if (!m_controlNet->GetCubeSerials().contains(
2639  sn)) return;
2640 
2641 // if (!m_controlNet->GetCubeSerials().contains(
2642 // QString::fromStdString(sn))) return;
2643 // if (!serialNumberList().HasSerialNumber(sn)) return;
2644 
2645  QList<ControlMeasure *> measures =
2646  m_controlNet->GetMeasuresInCube(sn);
2647  // loop through all measures contained in this cube
2648  for (int i = 0; i < measures.count(); i++) {
2649  ControlMeasure *m = measures[i];
2650  // Find the measurments on the viewport
2651  double samp = m->GetSample();
2652  double line = m->GetLine();
2653  int x, y;
2654  mvp->cubeToViewport(samp, line, x, y);
2655  // if the point is ignored,
2656  if (m->Parent()->IsIgnored()) {
2657  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2658  }
2659  // point is not ignored, but measure matching this image is ignored,
2660  else if (m->IsIgnored()) {
2661  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2662  }
2663  else {
2664  painter->setPen(Qt::green); // set all other point markers green
2665  }
2666  // draw points
2667  painter->drawLine(x - 5, y, x + 5, y);
2668  painter->drawLine(x, y - 5, x, y + 5);
2669  }
2670  // if MatchTool is open,
2671  if (m_editPoint != NULL && m_newPoint == NULL) {
2672  // and the selected point is in the image,
2673  if (m_editPoint->HasSerialNumber(sn)) {
2674  // find the measurement
2675  double samp = (*m_editPoint)[sn]->GetSample();
2676  double line = (*m_editPoint)[sn]->GetLine();
2677  int x, y;
2678  mvp->cubeToViewport(samp, line, x, y);
2679  // set point marker red
2680  QBrush brush(Qt::red);
2681  // set point marker bold - line width 2
2682  QPen pen(brush, 2);
2683  // draw the selected point in each image last so it's on top of the rest of the points
2684  painter->setPen(pen);
2685  painter->drawLine(x - 5, y, x + 5, y);
2686  painter->drawLine(x, y - 5, x, y + 5);
2687  }
2688  }
2689  }
2690 
2691 
2692 
2707 
2708  if (m_templateModified) {
2709  int r = QMessageBox::warning(m_matchTool, tr("OK to continue?"),
2710  tr("The currently opened registration template has been modified.\n"
2711  "Save changes?"),
2712  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
2713  QMessageBox::Yes);
2714 
2715  if (r == QMessageBox::Yes)
2717  else if (r == QMessageBox::Cancel)
2718  return false;
2719  }
2720 
2721  return true;
2722  }
2723 
2724 
2725 
2732 
2733  if (!okToContinue())
2734  return;
2735 
2736  QString filename = QFileDialog::getOpenFileName(m_matchTool,
2737  "Select a registration template", ".",
2738  "Registration template files (*.def *.pvl);;All files (*)");
2739 
2740  if (filename.isEmpty())
2741  return;
2742 
2743  if (m_pointEditor->setTemplateFile(filename)) {
2744  loadTemplateFile(filename);
2745  }
2746  }
2747 
2748 
2749 
2755  void MatchTool::loadTemplateFile(QString fn) {
2756 
2757  QFile file(FileName((QString) fn).expanded());
2758  if (!file.open(QIODevice::ReadOnly)) {
2759  QString msg = "Failed to open template file \"" + fn + "\"";
2760  QMessageBox::warning(m_matchTool, "IO Error", msg);
2761  return;
2762  }
2763 
2764  QTextStream stream(&file);
2765  m_templateEditor->setText(stream.readAll());
2766  file.close();
2767 
2768  QScrollBar * sb = m_templateEditor->verticalScrollBar();
2769  sb->setValue(sb->minimum());
2770 
2771  m_templateModified = false;
2772  m_saveTemplateFile->setEnabled(false);
2773  m_templateFileNameLabel->setText("Template File: " + fn);
2774  }
2775 
2776 
2777 
2780  m_templateModified = true;
2781  m_saveTemplateFile->setEnabled(true);
2782  }
2783 
2784 
2785 
2788 
2789  if (!m_templateModified)
2790  return;
2791 
2792  QString filename =
2793  m_pointEditor->templateFileName();
2794 
2795  writeTemplateFile(filename);
2796  }
2797 
2798 
2799 
2802 
2803  QString filename = QFileDialog::getSaveFileName(m_matchTool,
2804  "Save registration template", ".",
2805  "Registration template files (*.def *.pvl);;All files (*)");
2806 
2807  if (filename.isEmpty())
2808  return;
2809 
2810  writeTemplateFile(filename);
2811  }
2812 
2813 
2814 
2820  void MatchTool::writeTemplateFile(QString fn) {
2821 
2822  QString contents = m_templateEditor->toPlainText();
2823 
2824  // catch errors in Pvl format when populating pvl object
2825  stringstream ss;
2826  ss << contents;
2827  try {
2828  Pvl pvl;
2829  ss >> pvl;
2830  }
2831  catch(IException &e) {
2832  QString message = e.toString();
2833  QMessageBox::warning(m_matchTool, "Error", message);
2834  return;
2835  }
2836 
2837  QString expandedFileName(
2838  FileName((QString) fn).expanded());
2839 
2840  QFile file(expandedFileName);
2841 
2842  if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2843  QString msg = "Failed to save template file to \"" + fn + "\"\nDo you "
2844  "have permission?";
2845  QMessageBox::warning(m_matchTool, "IO Error", msg);
2846  return;
2847  }
2848 
2849  // now save contents
2850  QTextStream stream(&file);
2851  stream << contents;
2852  file.close();
2853 
2854  if (m_pointEditor->setTemplateFile(fn)) {
2855  m_templateModified = false;
2856  m_saveTemplateFile->setEnabled(false);
2857  m_templateFileNameLabel->setText("Template File: " + fn);
2858  }
2859  }
2860 
2861 
2862 
2877  try{
2878  // Get the template file from the ControlPointEditor object
2879  Pvl templatePvl(m_pointEditor->templateFileName());
2880  // Create registration dialog window using PvlEditDialog class
2881  // to view and/or edit the template
2882  PvlEditDialog registrationDialog(templatePvl);
2883  registrationDialog.setWindowTitle("View or Edit Template File: "
2884  + templatePvl.fileName());
2885  registrationDialog.resize(550,360);
2886  registrationDialog.exec();
2887  }
2888  catch (IException &e) {
2889  QString message = e.toString();
2890  QMessageBox::information(m_matchTool, "Error", message);
2891  }
2892  }
2893 
2894 
2895 
2903  m_pointEditor->saveChips();
2904  }
2905 
2906 
2907 
2908  void MatchTool::showHideTemplateEditor() {
2909 
2910  if (!m_templateEditorWidget)
2911  return;
2912 
2913  m_templateEditorWidget->setVisible(!m_templateEditorWidget->isVisible());
2914  }
2915 
2916 
2917 
2930  void MatchTool::updatePointInfo(QString pointId) {
2931  if (m_editPoint == NULL) return;
2932  if (pointId != m_editPoint->GetId()) return;
2933  // The edit point has been changed by SetApriori, so m_editPoint needs
2934  // to possibly update some values. Need to retain measures from m_editPoint
2935  // because they might have been updated, but not yet saved to the network
2936  // ("Save Point").
2937  ControlPoint *updatedPoint = m_controlNet->GetPoint(pointId);
2938  m_editPoint->SetEditLock(updatedPoint->IsEditLocked());
2939  m_editPoint->SetIgnored(updatedPoint->IsIgnored());
2940 
2941  // Set EditLock box correctly
2942  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
2943 
2944  // Set ignore box correctly
2945  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
2946 
2947  }
2948 
2949 
2950 
2967 
2968  // Check point being edited, make sure it still exists, if not ???
2969  // Update ignored checkbox??
2970  if (m_editPoint != NULL) {
2971  try {
2972  QString id = m_ptIdValue->text().remove("Point ID: ");
2973  m_controlNet->GetPoint(id);
2974  }
2975  catch (IException &) {
2976  delete m_editPoint;
2977  m_editPoint = NULL;
2978  emit editPointChanged();
2979 // m_matchTool->setVisible(false);
2980 // m_measureWindow->setVisible(false);
2981  }
2982  }
2983 
2985  }
2986 
2987 
2988 
2995 
2996  QColor qc = Qt::red;
2997  QPalette p = m_savePoint->palette();
2998  p.setColor(QPalette::ButtonText,qc);
2999  m_savePoint->setPalette(p);
3000 
3001  }
3002 
3003 
3004 
3017  bool MatchTool::IsMeasureLocked (QString serialNumber) {
3018 
3019  if (m_editPoint == NULL) return false;
3020 
3021  // Reference implicitly editLocked
3022  if (m_editPoint->IsEditLocked() && m_editPoint->IsReferenceExplicit() &&
3023  (m_editPoint->GetReferenceSN() == serialNumber)) {
3024  return true;
3025  }
3026  // Return measures explicit editLocked value
3027  else {
3028  return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
3029  }
3030 
3031  }
3032 
3033 
3034 
3041  FileName config("$HOME/.Isis/qview/MatchTool.config");
3042  QSettings settings(config.expanded(),
3043  QSettings::NativeFormat);
3044  QPoint pos = settings.value("pos", QPoint(300, 100)).toPoint();
3045  QSize size = settings.value("size", QSize(900, 500)).toSize();
3046  m_matchTool->resize(size);
3047  m_matchTool->move(pos);
3048  }
3049 
3050 
3058  /*We do not want to write the settings unless the window is
3059  visible at the time of closing the application*/
3060  if (!m_matchTool->isVisible()) return;
3061  FileName config("$HOME/.Isis/qview/MatchTool.config");
3062  QSettings settings(config.expanded(),
3063  QSettings::NativeFormat);
3064  settings.setValue("pos", m_matchTool->pos());
3065  settings.setValue("size", m_matchTool->size());
3066  }
3067 
3068 
3069 
3070  void MatchTool::enterWhatsThisMode() {
3071  QWhatsThis::enterWhatsThisMode();
3072  }
3073 
3074 
3075  void MatchTool::clearEditPoint() {
3076  m_editPoint = NULL;
3077  }
3078 
3079 
3080 
3081  void MatchTool::showHelp() {
3082 
3083  QDialog *helpDialog = new QDialog(m_matchTool);
3084  helpDialog->setWindowTitle("Match Tool Help");
3085 
3086  QVBoxLayout *mainLayout = new QVBoxLayout;
3087  helpDialog->setLayout(mainLayout);
3088 
3089  QLabel *matchTitle = new QLabel("<h2>Match Tool</h2>");
3090  mainLayout->addWidget(matchTitle);
3091 
3092  QLabel *matchSubtitle = new QLabel("A tool for interactively measuring and editing sample/line "
3093  "registration points between cubes. These "
3094  "points contain sample, line postions only, no latitude or "
3095  "longitude values are used or recorded.");
3096  matchSubtitle->setWordWrap(true);
3097  mainLayout->addWidget(matchSubtitle);
3098 
3099  QTabWidget *tabArea = new QTabWidget;
3100  tabArea->setDocumentMode(true);
3101  mainLayout->addWidget(tabArea);
3102 
3103  // TAB 1 - Overview
3104  QScrollArea *overviewTab = new QScrollArea;
3105  overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3106  overviewTab->setWidgetResizable(true);
3107  QWidget *overviewContainer = new QWidget;
3108  QVBoxLayout *overviewLayout = new QVBoxLayout;
3109  overviewContainer->setLayout(overviewLayout);
3110 
3111  QLabel *purposeTitle = new QLabel("<h2>Purpose</h2>");
3112  overviewLayout->addWidget(purposeTitle);
3113 
3114  QLabel *purposeText = new QLabel("<p>This tool is for recording and editing registration "
3115  "points measured between cubes displayed in the <i>qview</i> main window.</p> <p>The "
3116  "recorded registration points are sample and line pixel coordinates only. Therefore, this "
3117  "tool can be used on any images including ones that do not contain a camera model "
3118  "(i.e, The existence of the Isis Instrument Group on the image labels is not required). "
3119  "This also means that the tool differs from the <i>qnet</i> control point network "
3120  "application in that no latitude or longitude values are ever used or recorded "
3121  "(regardless if the image has a camera model in Isis).</p>"
3122  "<p>The output control point network that this tool generates is primarily used 1) as "
3123  "input for an image-wide sample/line translation to register one image to another by "
3124  "'moving' pixel locations - refer to the documentation for applications such as "
3125  "<i>translate</i> and <i>warp</i>, or 2) to export the file and use the recorded "
3126  "measurements in other spreadsheet or plotting packages to visualize magnitude "
3127  "and direction of varying translations of the images relative to one another.</p> "
3128  "<p>An automated version of this match tool is the <i>coreg</i> application. This tool "
3129  "can be used to visually evaluate and edit the control point network created by "
3130  "<i>coreg</i>.</p> "
3131  "<p>The format of the output point network file is binary. This tool uses the Isis control "
3132  " network framework to create, co-register and save all control points and pixel "
3133  "measurements. The application <i>cnetbin2pvl</i> can be used to convert from binary to "
3134  "a readable PVL format."
3135  "<p>The Mouse Button functions are: (same as <i>qnet</i>)<ul><li>Modify Point=Left</li> "
3136  "<li>Delete Point=Middle</li><li>Create New Point=Right</li></ul></p>"
3137  "<p>Control Points are drawn on the associated displayed cubes with the following colors: "
3138  "Green=Valid registration point; Yellow=Ignored point; Red=Active point being edited");
3139  purposeText->setWordWrap(true);
3140  overviewLayout->addWidget(purposeText);
3141 
3142  overviewTab->setWidget(overviewContainer);
3143 
3144  // TAB 2 - Quick Start
3145  QScrollArea *quickTab = new QScrollArea;
3146  quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3147  quickTab->setWidgetResizable(true);
3148  QWidget *quickContainer = new QWidget;
3149  QVBoxLayout *quickLayout = new QVBoxLayout;
3150  quickContainer->setLayout(quickLayout);
3151 
3152  QLabel *quickTitle = new QLabel("<h2>Quick Start</h2>");
3153  quickLayout->addWidget(quickTitle);
3154 
3155  QLabel *quickSubTitle = new QLabel("<h3>Preparation:</h3>");
3156  quickLayout->addWidget(quickSubTitle);
3157 
3158  QLabel *quickPrep = new QLabel("<p><ul>"
3159  "<li>Open the cubes with overlapping areas for choosing control points</li>"
3160  "<li>Choose the match tool <img src=\"" + toolIconDir() +
3161  "/stock_draw-connector-with-arrows.png\" width=22 height=22> "
3162  "from the toolpad on the right side of the <i>qview</i> main window</li>");
3163  quickPrep->setWordWrap(true);
3164  quickLayout->addWidget(quickPrep);
3165 
3166  QLabel *morePrep = new QLabel("<p>Once the Match tool is activated the tool bar at the top "
3167  "of the main window contains file action buttons and a help button:");
3168  morePrep->setWordWrap(true);
3169  quickLayout->addWidget(morePrep);
3170 
3171  QLabel *fileButtons = new QLabel("<p><ul>"
3172  "<li><img src=\"" + toolIconDir() + "/fileopen.png\" width=22 height=22> Open an existing "
3173  "control network <b>Note:</b> If you do not open an existing network, a new one will "
3174  "be created</li>"
3175  "<li><img src=\"" + toolIconDir() + "/mActionFileSaveAs.png\" width=22 height=22> Save "
3176  "control network as ...</li>"
3177  "<li><img src=\"" + toolIconDir() + "/mActionFileSave.png\" width=22 height=22> Save "
3178  "control network to current file</li>"
3179  "<li><img src=\"" + toolIconDir() + "/help-contents.png\" width=22 height=22> Show Help "
3180  "</li></ul></p>");
3181  fileButtons->setWordWrap(true);
3182  quickLayout->addWidget(fileButtons);
3183 
3184  QLabel *quickFunctionTitle = new QLabel("<h3>Cube Viewport Functions:</h3>");
3185  quickLayout->addWidget(quickFunctionTitle);
3186 
3187  QLabel *quickFunction = new QLabel(
3188  "The match tool window will be shown once "
3189  "you click in a cube viewport window using one of the following "
3190  "mouse functions. <b>Note:</b> Existing control points are drawn on the cube viewports");
3191  quickFunction->setWordWrap(true);
3192  quickLayout->addWidget(quickFunction);
3193 
3194  QLabel *quickDesc = new QLabel("<p><ul>"
3195  "<li>Left Click - Modify the control point closest to the click <b>Note:</b> "
3196  "All cubes in the control point must be displayed before loading the point</li>"
3197  "<li>Middle Click - Delete the control point closest to the click</li>"
3198  "<li>Right Click - Create a new control point at the click location</li></ul></p>");
3199  quickDesc->setWordWrap(true);
3200  quickDesc->setOpenExternalLinks(true);
3201  quickLayout->addWidget(quickDesc);
3202 
3203  quickTab->setWidget(quickContainer);
3204 
3205  // TAB 3 - Control Point Editing
3206  QScrollArea *controlPointTab = new QScrollArea;
3207  controlPointTab->setWidgetResizable(true);
3208  controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3209  QWidget *controlPointContainer = new QWidget;
3210  QVBoxLayout *controlPointLayout = new QVBoxLayout;
3211  controlPointContainer->setLayout(controlPointLayout);
3212 
3213  QLabel *controlPointTitle = new QLabel("<h2>Control Point Editing</h2>");
3214  controlPointLayout->addWidget(controlPointTitle);
3215 
3216  QLabel *mouseLabel = new QLabel("<p><h3>When the \"Match\" tool "
3217  "is activated, the mouse buttons have the following function in the "
3218  "cube viewports of the main qview window:</h3>");
3219  mouseLabel->setWordWrap(true);
3220  mouseLabel->setScaledContents(true);
3221  controlPointLayout->addWidget(mouseLabel);
3222 
3223  QLabel *controlPointDesc = new QLabel("<ul>"
3224  "<li>Left click - Edit the closest control point <b>Note:</b> "
3225  "All cubes in the control point must be displayed before loading the point</li>"
3226  "<li>Middle click - Delete the closest control point</li>"
3227  "<li>Right click - Create new control point at cursor location. This will bring up a new "
3228  "point dialog which allows you to enter a point id and will list all cube viewports, "
3229  "highlighting cubes where the point has been chosen by clicking on the cube's viewport. "
3230  "When the desired cubes have been chosen, select the \"Done\" button which will load the "
3231  "control point into the control point editor window which will allow the control measure "
3232  "positions to be refined.</li>");
3233  controlPointDesc->setWordWrap(true);
3234  controlPointLayout->addWidget(controlPointDesc);
3235 
3236  QLabel *controlPointEditing = new QLabel(
3237  "<h4>Changing Control Measure Locations</h4>"
3238  "<p>Both the left and right control measure positions can be adjusted by:"
3239  "<ul>"
3240  "<li>Move the cursor location under the crosshair by clicking the left mouse "
3241  "button</li>"
3242  "<li>Move 1 pixel at a time by using arrow keys on the keyboard</li>"
3243  "<li>Move 1 pixel at a time by using arrow buttons above the right and left views</li>"
3244  "</ul></p>"
3245  "<h4>Other Point Editor Functions</h4>"
3246  "<p>Along the right border of the window:</p>"
3247  "<ul>"
3248  "<li><strong>Link Zoom</strong> This will link the two small viewports together when "
3249  "zooming (ie. If this is checked, if the left view is zoomed, the right view will "
3250  "match the left view's zoom factor. "
3251  "<b>Note:</b> Zooming is controlled from the left view.</li>"
3252  "<li><strong>No Rotate:</strong> Turn off the rotation and bring right view back to "
3253  "its original orientation</li>"
3254  "<li><strong>Rotate:</strong> Rotate the right view using either the dial "
3255  "or entering degrees </li>"
3256  "<li><strong>Show control points:</strong> Draw crosshairs at all control "
3257  "point locations visible within the view</li>"
3258  "<li><strong>Show crosshair:</strong> Show a red crosshair across the entire "
3259  "view</li>"
3260  "<li><strong>Circle:</strong> Draw circle which may help center measure "
3261  "on a crater</li></ul"
3262  "<p>Below the left view:</p>"
3263  "<ul><li><strong>Blink controls:</strong> Blink the left and right view in the "
3264  "left view window using the \"Blink Start\" button <img src=\"" + toolIconDir() +
3265  "/blinkStart.png\" width=22 height=22> and \"Blink Stop\" button <img src=\"" +
3266  toolIconDir() + "/blinkStop.png\" width=22 height=22>. The arrow keys above the left "
3267  "and right views and the keyboard arrow keys may be used to move the both views while "
3268  "blinking.</li>"
3269  "<li><strong>Register:</strong> Sub-pixel register the right view to "
3270  "the left view. A default registration template is used for setting parameters "
3271  "passed to the sub-pixel registration tool. The user may load in a predefined "
3272  "template or edit the current loaded template to influence successful "
3273  "co-registration results. For more information regarding the pattern matching "
3274  "functionlity or how to create a parameter template, refer to the Isis PatternMatch "
3275  "document and the <i>autoregtemplate</i> application. <strong>Shortcut: R.</strong>"
3276  "</li>"
3277  "<li><strong>Save Measures:</strong> Save the two control measures using the sample, "
3278  "line positions under the crosshairs. <strong>Shortcut: M.</strong></li>"
3279  "<li><strong>Save Point:</strong> Save the control point to the control network. "
3280  "<strong>Shortcut: P.</strong></li>"
3281  "</ul>");
3282  controlPointEditing->setWordWrap(true);
3283  controlPointLayout->addWidget(controlPointEditing);
3284 
3285  controlPointTab->setWidget(controlPointContainer);
3286 
3287  // TAB 4 - Coreg Guidance
3288  QScrollArea *coregTab = new QScrollArea;
3289  coregTab->setWidgetResizable(true);
3290  coregTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3291  QWidget *coregContainer = new QWidget;
3292  QVBoxLayout *coregLayout = new QVBoxLayout;
3293  coregContainer->setLayout(coregLayout);
3294 
3295  QLabel *coregTitle = new QLabel("<h2>Coreg Guidance</h2>");
3296  coregLayout->addWidget(coregTitle);
3297 
3298  QLabel *coregDesc = new QLabel("<p>When opening control networks created by <i>coreg</i>, "
3299  "there are some things to keep in mind. First, all control points must have the same "
3300  "reference measure (this is the image filename passed to the <i>coreg</i> 'match' parameter)."
3301  "<p>In order to retain the integrity of the input <i>coreg</i> network, you cannot change "
3302  "which image is the reference measure on any of the existing points. "
3303  "<p>When creating a new control point to add to the <i>coreg</i> network, this tool will "
3304  "automatically set the reference measure to the same image as the other control points in "
3305  "the network as long as the reference image was one of the images selected with "
3306  "the right mouse button from the new point dialog. If this image was not selected when "
3307  "creating a new point, it "
3308  "does not contain a required measurement, therefore, you will get an error and the new "
3309  "point will not be created.</p> <p>The reference measure is always loaded on the left side "
3310  "of the control point editor. If you load a measure that is not the reference measure "
3311  "on the left side and try to save the point, you will receive an error message. You will "
3312  "need to move the reference measure back to the left side before saving the control point."
3313  "</p><p><b>Note:</b> This error checking will not happen on control networks created by "
3314  "<i>coreg</i> prior to Isis3.4.2. For older <i>coreg</i> control networks the user must be "
3315  "aware and make sure the correct image is set to the same <i>coreg</i> reference measure.");
3316  coregDesc->setWordWrap(true);
3317  coregDesc->setScaledContents(true);
3318  coregLayout->addWidget(coregDesc);
3319 
3320  coregTab->setWidget(coregContainer);
3321 
3322  tabArea->addTab(overviewTab, "&Overview");
3323  tabArea->addTab(quickTab, "&Quick Start");
3324  tabArea->addTab(controlPointTab, "&Control Point Editing");
3325  tabArea->addTab(coregTab, "&Coreg Guidance");
3326 
3327  QHBoxLayout *buttonsLayout = new QHBoxLayout;
3328  // Flush the buttons to the right
3329  buttonsLayout->addStretch();
3330 
3331  QPushButton *closeButton = new QPushButton("&Close");
3332  closeButton->setIcon(QPixmap(toolIconDir() + "/guiStop.png"));
3333  closeButton->setDefault(true);
3334  connect(closeButton, SIGNAL(clicked()),
3335  helpDialog, SLOT(close()));
3336  buttonsLayout->addWidget(closeButton);
3337 
3338  mainLayout->addLayout(buttonsLayout);
3339 
3340  helpDialog->show();
3341 
3342 
3343  }
3344 
3345 
3346 
3354 
3355  if (m_editPoint) {
3356  // If point changed or if a new point, prompt for saving.
3357  if ( m_controlNet->GetNumPoints() == 0 ||
3358  !m_controlNet->ContainsPoint(m_editPoint->GetId())) {
3359  QString message = "\n\nDo you want to save the point in the editor?";
3360  int response = QMessageBox::question(m_matchTool, "Save point in editor", message,
3361  QMessageBox::Yes | QMessageBox::No,
3362  QMessageBox::Yes);
3363  if (response == QMessageBox::Yes) {
3364  savePoint();
3365  }
3366  }
3367  }
3368 
3369  if (m_controlNet && m_controlNet->GetNumPoints() != 0 && m_netChanged) {
3370  QString message = "The currently open control net has changed. Do you want to save?";
3371  int response = QMessageBox::question(m_matchTool, "Save current control net?",
3372  message,
3373  QMessageBox::Yes | QMessageBox::No,
3374  QMessageBox::Yes);
3375  // Yes: Save old net, so return without opening network.
3376  if (response == QMessageBox::Yes) {
3377  saveAsNet();
3378  }
3379  }
3380  }
3381 }
Status SetType(MeasureType type)
Set how the coordinate was obtained.
bool okToContinue()
Allows user to set a new template file.
Definition: MatchTool.cpp:2706
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
CubeViewportList * cubeViewportList() const
Return the list of cubeviewports.
Definition: Tool.cpp:390
QGroupBox * createLeftMeasureGroupBox()
Definition: MatchTool.cpp:311
void deletePoint(ControlPoint *point)
Delete control point.
Definition: MatchTool.cpp:1686
void Delete(const QString &sn)
Remove the specified serial number from the list.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:109
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 &quot;Ignore&quot; 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:111
void openTemplateFile()
prompt user for a registration template file to open.
Definition: MatchTool.cpp:2731
void updateRightMeasureInfo()
Definition: MatchTool.cpp:2467
void add(const QString &filename, bool def2filename=false)
Adds a new filename / serial number pair to the SerialNumberList.
double GetResidualMagnitude() const
Return Residual magnitude.
void saveChips()
Slot which calls ControlPointEditor slot to save chips.
Definition: MatchTool.cpp:2902
Status SetIgnored(bool newIgnoreStatus)
Set whether to ignore or use control point.
void loadPoint()
Load point into MatchTool.
Definition: MatchTool.cpp:1933
void saveAsNet()
Signal to save the control net.
Definition: MatchTool.cpp:1395
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:2779
void saveTemplateFileAs()
save the contents of template editor to a file chosen by the user
Definition: MatchTool.cpp:2801
void updateLeftMeasureInfo()
Definition: MatchTool.cpp:2394
void modifyPoint(ControlPoint *point)
Modify control point.
Definition: MatchTool.cpp:1867
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:3057
double GetNumericalValue() const
Get the value associated with this log data.
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:121
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:154
Status SetEditLock(bool editLock)
Set the EditLock state.
const ControlMeasure * GetRefMeasure() const
Get the reference control measure.
void createPoint(MdiCubeViewport *mvp, double sample, double line)
Create new control point at given samp, line for viewport.
Definition: MatchTool.cpp:1546
void exiting()
This called when qview is exiting.
Definition: MatchTool.cpp:3353
QString GetReferenceSN() const
QGroupBox * createRightMeasureGroupBox()
Creates the right measure group box.
Definition: MatchTool.cpp:371
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:391
A Free point is a Control Point that identifies common measurements between two or more cubes...
Definition: ControlPoint.h:369
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
bool HasSerialNumber(QString serialNumber) const
Return true if given serial number exists in point.
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 &quot;Save Point&quot; button text to red.
Definition: MatchTool.cpp:2994
void drawAllMeasurments(MdiCubeViewport *mvp, QPainter *painter)
Draw all measurments which are on this viewPort.
Definition: MatchTool.cpp:2607
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition: Tool.h:211
Cube * cube() const
Return the cube associated with viewport.
Definition: CubeViewport.h:228
a control network
Definition: ControlNet.h:207
bool setTemplateFile(QString)
Allows user to choose a new template file by opening a window from which to select a filename...
QString GetId() const
Return the Id of the control point.
Hand Measured (e.g., qnet)
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:3017
void setIgnorePoint(bool ignore)
Set point&#39;s &quot;Ignore&quot; 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:38
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:2820
void selectRightMeasure(int index)
Select right measure.
Definition: MatchTool.cpp:2332
A single control point.
Definition: ControlPoint.h:339
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Definition: Cube.cpp:509
void viewportToCube(int x, int y, double &sample, double &line) const
Convert a viewport x/y to a cube sample/line (may be outside the cube)
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:3040
bool eventFilter(QObject *o, QEvent *e)
Event filter for MatchTool.
Definition: MatchTool.cpp:2533
void previousRightMeasure()
Selects the previous right measure when activated by key shortcut.
Definition: MatchTool.cpp:2253
Container for cube-like labels.
Definition: Pvl.h:135
bool IsReferenceExplicit() const
void loadMeasureTable()
Load measure information into the measure table.
Definition: MatchTool.cpp:2023
void saveTemplateFile()
save the file opened in the template editor
Definition: MatchTool.cpp:2787
bool IsEditLocked() const
Return value for p_editLock or implicit lock on reference measure.
void updatePointInfo(QString pointId)
Update the current editPoint information in the Point Editor labels.
Definition: MatchTool.cpp:2930
void saveNet()
Signal to save control net.
Definition: MatchTool.cpp:1373
void loadTemplateFile(QString)
Updates the current template file being used.
Definition: MatchTool.cpp:2755
void selectLeftMeasure(int index)
Select left measure.
Definition: MatchTool.cpp:2277
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:2876
Status SetId(QString id)
Sets the Id of the control point.
Status
This is a return status for many of the mutating (setter) method calls.
Definition: ControlPoint.h:378
GoodnessOfFit is pointreg information for reference measures.
void refresh()
Refresh all necessary widgets in MatchTool including the PointEditor and CubeViewports.
Definition: MatchTool.cpp:2966
void measureSaved()
This method is connected with the measureSaved() signal from ControlPointEdit.
Definition: MatchTool.cpp:788
void cubeToViewport(double sample, double line, int &x, int &y) const
Convert a cube sample/line to a viewport x/y (may be outside the viewport)
void nextRightMeasure()
Selects the next right measure when activated by key shortcut.
Definition: MatchTool.cpp:2234
void paintAllViewports()
This method will repaint the given Point ID in each viewport Note: The pointId parameter is here even...
Definition: MatchTool.cpp:2573
QString toString() const
Returns a string representation of this exception.
Definition: IException.cpp:553
static QString UserName()
Returns the user name.
Isis exception class.
Definition: IException.h:99
void setIgnoreLeftMeasure(bool ignore)
Set the &quot;Ignore&quot; keyword of the measure shown in the left viewport to the value of the input paramete...
Definition: MatchTool.cpp:1213
QString toolIconDir() const
returns the path to the icon directory.
Definition: Tool.h:127
Status SetChooserName()
Set chooser name to a user who last changed the coordinate.
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
QString GetCubeSerialNumber() const
Return the serial number of the cube containing the coordinate.
Status SetCubeSerialNumber(QString newSerialNumber)
Set cube serial number.
Status SetCoordinate(double sample, double line)
Set the coordinate of the measurement.
QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1160
void setLockPoint(bool ignore)
Set point&#39;s &quot;EditLock&quot; 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:1450
void createMenus()
Customize dropdown menus below title bar.
Definition: MatchTool.cpp:569
void setLockRightMeasure(bool ignore)
Set the &quot;EditLock&quot; 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:2554
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube&#39;s serial number.
void setLockLeftMeasure(bool ignore)
Set the &quot;EditLock&quot; keyword of the measure shown in the left viewport to the value of the input parame...
Definition: MatchTool.cpp:1172
int IndexOfRefMeasure() const
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:393
IO Handler for Isis Cubes.
Definition: Cube.h:158

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:23:00