USGS

Isis 3.0 Object Programmers' Reference

Home

MatchTool.cpp
1 #include "MatchTool.h"
2 
3 #include <sstream>
4 #include <vector>
5 #include <iomanip>
6 
7 #include <QtGui>
8 #include <QMessageBox>
9 
10 #include "Application.h"
11 #include "ControlMeasure.h"
12 #include "ControlMeasureLogData.h"
13 #include "ControlNet.h"
14 #include "ControlPoint.h"
15 #include "ControlPointEdit.h"
16 #include "FileName.h"
17 #include "IException.h"
18 #include "MainWindow.h"
19 #include "MatchToolDeletePointDialog.h"
20 #include "MatchToolNewPointDialog.h"
21 #include "MdiCubeViewport.h"
22 #include "Pvl.h"
23 #include "PvlEditDialog.h"
24 #include "SerialNumber.h"
25 #include "SerialNumberList.h"
26 #include "SpecialPixel.h"
27 #include "ToolPad.h"
28 #include "ViewportMainWindow.h"
29 #include "Workspace.h"
30 
31 using namespace std;
32 
33 namespace Isis {
34 
35  const int VIEWSIZE = 301;
36  const int CHIPVIEWPORT_WIDTH = 310;
37 
38 
48  MatchTool::MatchTool (QWidget *parent) : Tool(parent) {
49  m_controlNet = NULL;
50  m_coregNet = false;
51  m_netChanged = false;
52  m_pointEditor = NULL;
53  m_newPointDialog = NULL;
54  m_newPoint = NULL;
55  m_leftCube = NULL;
56  m_rightCube = NULL;
57  m_editPoint = NULL;
58  m_createPoint = NULL;
59  m_modifyPoint = NULL;
60  m_deletePoint = NULL;
61  m_whatsThis = NULL;
62  m_showHelp = NULL;
63  m_ptIdValue = NULL;
64  m_numMeasures = NULL;
65  m_lockPoint = NULL;
66  m_ignorePoint = NULL;
67  m_leftReference = NULL;
68  m_leftMeasureType = NULL;
69  m_leftGoodness = NULL;
70  m_rightReference = NULL;
71  m_rightMeasureType = NULL;
72  m_rightGoodness = NULL;
73  m_lockLeftMeasure = NULL;
74  m_ignoreLeftMeasure = NULL;
75  m_lockRightMeasure = NULL;
76  m_ignoreRightMeasure = NULL;
77  m_leftCombo = NULL;
78  m_rightCombo = NULL;
79  m_leftMeasure = NULL;
80  m_rightMeasure = NULL;
81  m_templateModified = false;
82  m_measureWindow = NULL;
83  m_measureTable = NULL;
84 
85  // try to get status bar from viewportmain window which is parent
86 // QStatusBar *m_statusBar = qobject_cast<QMainWindow *>(parent)->statusBar();
87 // m_statusBar->showMessage("STATUS BAR TEST");
88 
89 // QString warn = "TEST TEST TEST";
90 // QString warn2 = "JUNK";
91 // qobject_cast<ViewportMainWindow *>(parent)->displayWarning(warn,warn2);
92  m_parent = parent;
93  connect(this, SIGNAL(toolActivated()), this, SLOT(activateTool()));
94 
95  // Connect the ViewportMainWindow's (parent) closeWindow signal to a exit slot for
96  // prompting user to save net
97  ViewportMainWindow *parentMainWindow = qobject_cast<ViewportMainWindow *>(parent);
98 
99  if (parentMainWindow) {
100  connect(parent, SIGNAL(closeWindow()), this, SLOT(exiting()));
101  }
102 
103  createMatchTool(parent);
104 
105  }
106 
107 
108  MatchTool::~MatchTool () {
109  // FIXME: Don't write settings in destructor, must do this earlier in close event
110  writeSettings();
111 
112  delete m_controlNet;
113  m_controlNet = NULL;
114  delete m_pointEditor;
115  m_pointEditor = NULL;
116  delete m_newPointDialog;
117  m_newPointDialog = NULL;
118  delete m_newPoint;
119  m_newPoint = NULL;
120  delete m_leftMeasure;
121  m_leftMeasure = NULL;
122  delete m_rightMeasure;
123  m_rightMeasure = NULL;
124  delete m_leftCube;
125  m_leftCube = NULL;
126  delete m_rightCube;
127  m_rightCube = NULL;
128  }
129 
130 
131 
157 
158  m_matchTool = new QMainWindow(parent);
159  m_matchTool->setWindowTitle("Match Tool");
160  m_matchTool->setObjectName("MatchTool");
161  connect(m_matchTool, SIGNAL(destroyed(QObject *)), this, SLOT(clearEditPoint()));
162 
163  createActions();
164  createMenus();
165  createToolBars();
166 
167  // create m_pointEditor first since we need to get its templateFileName
168  // later
169  m_pointEditor = new ControlPointEdit(m_controlNet, parent, true, false);
170  connect(this, SIGNAL(newControlNetwork(ControlNet *)),
171  m_pointEditor, SIGNAL(newControlNetwork(ControlNet *)));
172  connect(this, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)),
173  m_pointEditor, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)));
174  connect(m_pointEditor, SIGNAL(measureSaved()), this, SLOT(measureSaved()));
175  connect(this, SIGNAL(measureChanged()),
176  m_pointEditor, SLOT(colorizeSaveButton()));
177 
178  m_savePoint = new QPushButton ("Save Point");
179  m_savePoint->setShortcut(Qt::Key_P);
180  m_savePoint->setToolTip("Save the edit control point to the control network. "
181  "<strong>Shortcut: P</strong>");
182  m_savePoint->setWhatsThis("Save the edit control point to the control "
183  "network which is loaded into memory in its entirety. "
184  "When a control point is selected for editing, "
185  "a copy of the point is made so that the original control "
186  "point remains in the network.");
187  m_saveDefaultPalette = m_savePoint->palette();
188  connect (m_savePoint,SIGNAL(clicked()),this,SLOT(savePoint()));
189 
190  QHBoxLayout * addMeasureLayout = new QHBoxLayout;
191  addMeasureLayout->addStretch();
192  addMeasureLayout->addWidget(m_savePoint);
193 // addMeasureLayout->addStretch();
194 
195  m_cnetFileNameLabel = new QLabel("Control Network: " + m_cnetFileName);
196  m_cnetFileNameLabel->setToolTip("Name of opened control network file.");
197  m_cnetFileNameLabel->setWhatsThis("Name of opened control network file.");
198 
199  m_templateFileNameLabel = new QLabel("Template File: " +
200  m_pointEditor->templateFileName());
201  m_templateFileNameLabel->setToolTip("Sub-pixel registration template File.");
202 // QString patternMatchDoc =
203 // FileName("$ISISROOT/doc/documents/PatternMatch/PatternMatch.html").fileName();
204 // m_templateFileNameLabel->setOpenExternalLinks(true);
205  m_templateFileNameLabel->setWhatsThis("FileName of the sub-pixel "
206  "registration template. Refer to $ISISROOT/doc/documents/"
207  "PatternMatch/PatternMatch.html for a description of the "
208  "contents of this file.");
209 
210  QVBoxLayout * centralLayout = new QVBoxLayout;
211 
212  centralLayout->addWidget(m_cnetFileNameLabel);
213  centralLayout->addWidget(m_templateFileNameLabel);
214  centralLayout->addWidget(createTopSplitter());
215  centralLayout->addStretch();
216  centralLayout->addWidget(m_pointEditor);
217  centralLayout->addLayout(addMeasureLayout);
218  QWidget * centralWidget = new QWidget;
219  centralWidget->setLayout(centralLayout);
220 
221  QScrollArea *scrollArea = new QScrollArea();
222  scrollArea->setObjectName("MatchToolScroll");
223  scrollArea->setWidget(centralWidget);
224  scrollArea->setWidgetResizable(true);
225  centralWidget->adjustSize();
226  m_matchTool->setCentralWidget(scrollArea);
227 // m_matchTool->setCentralWidget(centralWidget);
228 
229 
230  connect(this, SIGNAL(editPointChanged()),
231  this, SLOT(paintAllViewports()));
232 
233  readSettings();
234  }
235 
236 
239 
240  QHBoxLayout * measureLayout = new QHBoxLayout;
241  measureLayout->addWidget(createLeftMeasureGroupBox());
242  measureLayout->addWidget(createRightMeasureGroupBox());
243 
244  QVBoxLayout * groupBoxesLayout = new QVBoxLayout;
245  groupBoxesLayout->addWidget(createControlPointGroupBox());
246  groupBoxesLayout->addStretch();
247  groupBoxesLayout->addLayout(measureLayout);
248 
249  QWidget * groupBoxesWidget = new QWidget;
250  groupBoxesWidget->setLayout(groupBoxesLayout);
251 
253 
254  QSplitter * topSplitter = new QSplitter;
255  topSplitter->addWidget(groupBoxesWidget);
256  topSplitter->addWidget(m_templateEditorWidget);
257  topSplitter->setStretchFactor(0, 4);
258  topSplitter->setStretchFactor(1, 3);
259 
260  m_templateEditorWidget->hide();
261 
262  return topSplitter;
263  }
264 
265 
268 
269  // create left vertical layout
270  m_ptIdValue = new QLabel;
271  m_numMeasures = new QLabel;
272  QVBoxLayout * leftLayout = new QVBoxLayout;
273  leftLayout->addWidget(m_ptIdValue);
274  leftLayout->addWidget(m_numMeasures);
275 
276  // create right vertical layout's top layout
277  m_lockPoint = new QCheckBox("Edit Lock Point");
278  connect(m_lockPoint, SIGNAL(clicked(bool)), this, SLOT(setLockPoint(bool)));
279  m_ignorePoint = new QCheckBox("Ignore Point");
280  connect(m_ignorePoint, SIGNAL(clicked(bool)),
281  this, SLOT(setIgnorePoint(bool)));
282  connect(this, SIGNAL(ignorePointChanged()), m_ignorePoint, SLOT(toggle()));
283 
284  QVBoxLayout * rightLayout = new QVBoxLayout;
285  rightLayout->addWidget(m_lockPoint);
286  rightLayout->addWidget(m_ignorePoint);
287 
288  QHBoxLayout * mainLayout = new QHBoxLayout;
289  mainLayout->addLayout(leftLayout);
290  mainLayout->addStretch();
291  mainLayout->addLayout(rightLayout);
292 
293  // create the groupbox
294  QGroupBox * groupBox = new QGroupBox("Control Point");
295  groupBox->setLayout(mainLayout);
296 
297  return groupBox;
298  }
299 
300 
303 
304  m_leftCombo = new QComboBox;
305  m_leftCombo->view()->installEventFilter(this);
306  m_leftCombo->setToolTip("Choose left control measure");
307  m_leftCombo->setWhatsThis("Choose left control measure identified by "
308  "cube filename.");
309  connect(m_leftCombo, SIGNAL(activated(int)),
310  this, SLOT(selectLeftMeasure(int)));
311  m_lockLeftMeasure = new QCheckBox("Edit Lock Measure");
312  connect(m_lockLeftMeasure, SIGNAL(clicked(bool)),
313  this, SLOT(setLockLeftMeasure(bool)));
314  m_ignoreLeftMeasure = new QCheckBox("Ignore Measure");
315  connect(m_ignoreLeftMeasure, SIGNAL(clicked(bool)),
316  this, SLOT(setIgnoreLeftMeasure(bool)));
317  connect(this, SIGNAL(ignoreLeftChanged()),
318  m_ignoreLeftMeasure, SLOT(toggle()));
319  m_leftReference = new QLabel();
320  m_leftMeasureType = new QLabel();
321  m_leftSampShift = new QLabel();
322  m_leftSampShift->setToolTip("Sample shift between apriori and current");
323  m_leftSampShift->setWhatsThis("The shift between the apriori sample and "
324  "the current sample. The apriori sample is set "
325  "when creating a new measure.");
326  m_leftLineShift = new QLabel();
327  m_leftLineShift->setToolTip("Line shift between apriori and current");
328  m_leftLineShift->setWhatsThis("The shift between the apriori line and "
329  "the current line. The apriori line is set "
330  "when creating a new measure.");
331  m_leftGoodness = new QLabel();
332  m_leftGoodness->setToolTip("Goodness of Fit result from sub-pixel "
333  "registration.");
334  m_leftGoodness->setWhatsThis("Resulting Goodness of Fit from sub-pixel "
335  "registration.");
336  QVBoxLayout * leftLayout = new QVBoxLayout;
337  leftLayout->addWidget(m_leftCombo);
338  leftLayout->addWidget(m_lockLeftMeasure);
339  leftLayout->addWidget(m_ignoreLeftMeasure);
340  leftLayout->addWidget(m_leftReference);
341  leftLayout->addWidget(m_leftMeasureType);
342  leftLayout->addWidget(m_leftSampShift);
343  leftLayout->addWidget(m_leftLineShift);
344  leftLayout->addWidget(m_leftGoodness);
345 
346  QGroupBox * leftGroupBox = new QGroupBox("Left Measure");
347  leftGroupBox->setLayout(leftLayout);
348 
349  return leftGroupBox;
350  }
351 
352 
363 
364  // create widgets for the right groupbox
365  m_rightCombo = new QComboBox;
366  m_rightCombo->view()->installEventFilter(this);
367 
368  // Attach shortcuts to Match TOol's window for selecting right measures
369  // Note: Qt handles this memory for us since m_matchTool is the parent of these shortcuts
370  QShortcut *nextMeasure = new QShortcut(Qt::Key_PageDown, m_matchTool);
371  connect(nextMeasure, SIGNAL(activated()), this, SLOT(nextRightMeasure()));
372  QShortcut *prevMeasure = new QShortcut(Qt::Key_PageUp, m_matchTool);
373  connect(prevMeasure, SIGNAL(activated()), this, SLOT(previousRightMeasure()));
374 
375  m_rightCombo->setToolTip("Choose right control measure. "
376  "<strong>Shorcuts: PageUp/PageDown</strong>");
377  m_rightCombo->setWhatsThis("Choose right control measure identified by "
378  "cube filename. "
379  "Note: PageUp selects previous measure; "
380  "PageDown selects next measure.");
381  connect(m_rightCombo, SIGNAL(activated(int)),
382  this, SLOT(selectRightMeasure(int)));
383  m_lockRightMeasure = new QCheckBox("Edit Lock Measure");
384  connect(m_lockRightMeasure, SIGNAL(clicked(bool)),
385  this, SLOT(setLockRightMeasure(bool)));
386  m_ignoreRightMeasure = new QCheckBox("Ignore Measure");
387  connect(m_ignoreRightMeasure, SIGNAL(clicked(bool)),
388  this, SLOT(setIgnoreRightMeasure(bool)));
389  connect(this, SIGNAL(ignoreRightChanged()),
390  m_ignoreRightMeasure, SLOT(toggle()));
391  m_rightReference = new QLabel();
392  m_rightMeasureType = new QLabel();
393  m_rightSampShift = new QLabel();
394  m_rightSampShift->setToolTip(m_leftSampShift->toolTip());
395  m_rightSampShift->setWhatsThis(m_leftSampShift->whatsThis());
396  m_rightLineShift = new QLabel();
397  m_rightLineShift->setToolTip(m_leftLineShift->toolTip());
398  m_rightLineShift->setWhatsThis(m_leftLineShift->whatsThis());
399  m_rightGoodness = new QLabel();
400  m_rightGoodness->setToolTip(m_leftGoodness->toolTip());
401  m_rightGoodness->setWhatsThis(m_leftGoodness->whatsThis());
402 
403  // create right groupbox
404  QVBoxLayout * rightLayout = new QVBoxLayout;
405  rightLayout->addWidget(m_rightCombo);
406  rightLayout->addWidget(m_lockRightMeasure);
407  rightLayout->addWidget(m_ignoreRightMeasure);
408  rightLayout->addWidget(m_rightReference);
409  rightLayout->addWidget(m_rightMeasureType);
410  rightLayout->addWidget(m_rightSampShift);
411  rightLayout->addWidget(m_rightLineShift);
412  rightLayout->addWidget(m_rightGoodness);
413 
414  QGroupBox * rightGroupBox = new QGroupBox("Right Measure");
415  rightGroupBox->setLayout(rightLayout);
416 
417  return rightGroupBox;
418  }
419 
420 
423 
424  QToolBar *toolBar = new QToolBar("Template Editor ToolBar");
425 
426  toolBar->addAction(m_openTemplateFile);
427  toolBar->addSeparator();
428  toolBar->addAction(m_saveTemplateFile);
429  toolBar->addAction(m_saveTemplateFileAs);
430 
431  m_templateEditor = new QTextEdit;
432  connect(m_templateEditor, SIGNAL(textChanged()), this,
433  SLOT(setTemplateModified()));
434 
435  QVBoxLayout *mainLayout = new QVBoxLayout;
436  mainLayout->addWidget(toolBar);
437  mainLayout->addWidget(m_templateEditor);
438 
439  m_templateEditorWidget = new QWidget;
440  m_templateEditorWidget->setLayout(mainLayout);
441  }
442 
443 
452 
453  m_saveNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSave.png"),
454  "Save Control Network ...",
455  m_matchTool);
456  m_saveNet->setShortcut(Qt::CTRL + Qt::Key_S);
457  m_saveNet->setToolTip("Save current control network");
458  m_saveNet->setStatusTip("Save current control network");
459  QString whatsThis = "<b>Function:</b> Saves the current <i>"
460  "control network</i>";
461  m_saveNet->setWhatsThis(whatsThis);
462  connect(m_saveNet, SIGNAL(activated()), this, SLOT(saveNet()));
463 
464  m_saveAsNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"),
465  "Save Control Network &As...",
466  m_matchTool);
467  m_saveAsNet->setToolTip("Save current control network to chosen file");
468  m_saveAsNet->setStatusTip("Save current control network to chosen file");
469  whatsThis = "<b>Function:</b> Saves the current <i>"
470  "control network</i> under chosen filename";
471  m_saveAsNet->setWhatsThis(whatsThis);
472  connect(m_saveAsNet, SIGNAL(activated()), this, SLOT(saveAsNet()));
473 
474  m_closeMatchTool = new QAction(QPixmap(toolIconDir() + "/fileclose.png"),
475  "&Close",
476  m_matchTool);
477  m_closeMatchTool->setToolTip("Close this window");
478  m_closeMatchTool->setStatusTip("Close this window");
479  m_closeMatchTool->setShortcut(Qt::ALT + Qt::Key_F4);
480  whatsThis = "<b>Function:</b> Closes the Match Tool window for this point "
481  "<p><b>Shortcut:</b> Alt+F4 </p>";
482  m_closeMatchTool->setWhatsThis(whatsThis);
483  connect(m_closeMatchTool, SIGNAL(activated()), m_matchTool, SLOT(close()));
484 
485  m_showHideTemplateEditor = new QAction(QPixmap(toolIconDir() + "/view_text.png"),
486  "&View/edit registration template",
487  m_matchTool);
488  m_showHideTemplateEditor->setCheckable(true);
489  m_showHideTemplateEditor->setToolTip("View and/or edit the registration template");
490  m_showHideTemplateEditor->setStatusTip("View and/or edit the registration template");
491  whatsThis = "<b>Function:</b> Displays the curent registration template. "
492  "The user may edit and save changes under a chosen filename.";
493  m_showHideTemplateEditor->setWhatsThis(whatsThis);
494  connect(m_showHideTemplateEditor, SIGNAL(activated()), this,
495  SLOT(showHideTemplateEditor()));
496 
497  m_saveChips = new QAction(QPixmap(toolIconDir() + "/window_new.png"),
498  "Save registration chips",
499  m_matchTool);
500  m_saveChips->setToolTip("Save registration chips");
501  m_saveChips->setStatusTip("Save registration chips");
502  whatsThis = "<b>Function:</b> Save registration chips to file. "
503  "Each chip: pattern, search, fit will be saved to a separate file.";
504  m_saveChips->setWhatsThis(whatsThis);
505  connect(m_saveChips, SIGNAL(activated()), this, SLOT(saveChips()));
506 
507  m_openTemplateFile = new QAction(QPixmap(toolIconDir() + "/fileopen.png"),
508  "&Open registration template",
509  m_matchTool);
510  m_openTemplateFile->setToolTip("Set registration template");
511  m_openTemplateFile->setStatusTip("Set registration template");
512  whatsThis = "<b>Function:</b> Allows user to select a new file to set as "
513  "the registration template";
514  m_openTemplateFile->setWhatsThis(whatsThis);
515  connect(m_openTemplateFile, SIGNAL(activated()), this, SLOT(openTemplateFile()));
516 
517  m_saveTemplateFile = new QAction(QPixmap(toolIconDir() + "/mActionFileSave.png"),
518  "&Save template file",
519  m_matchTool);
520  m_saveTemplateFile->setToolTip("Save the template file");
521  m_saveTemplateFile->setStatusTip("Save the template file");
522  m_saveTemplateFile->setWhatsThis("Save the registration template file");
523  connect(m_saveTemplateFile, SIGNAL(triggered()), this,
524  SLOT(saveTemplateFile()));
525 
526  m_saveTemplateFileAs = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"),
527  "&Save template as...",
528  m_matchTool);
529  m_saveTemplateFileAs->setToolTip("Save the template file as");
530  m_saveTemplateFileAs->setStatusTip("Save the template file as");
531  m_saveTemplateFileAs->setWhatsThis("Save the registration template file as");
532  connect(m_saveTemplateFileAs, SIGNAL(triggered()), this,
533  SLOT(saveTemplateFileAs()));
534 
535  m_whatsThis = new QAction(QPixmap(toolIconDir() + "/contexthelp.png"),
536  "&Whats's This",
537  m_matchTool);
538  m_whatsThis->setShortcut(Qt::SHIFT | Qt::Key_F1);
539  m_whatsThis->setToolTip("Activate What's This and click on items on "
540  "user interface to see more information.");
541  connect(m_whatsThis, SIGNAL(activated()), this, SLOT(enterWhatsThisMode()));
542 
543  m_showHelp = new QAction(QPixmap(toolIconDir() + "/help-contents.png"), "Help", m_matchTool);
544  m_showHelp->setToolTip("Help");
545  connect(m_showHelp, SIGNAL(activated()), this, SLOT(showHelp()));
546 
547  }
548 
549 
550 
561 
562  QMenu *fileMenu = m_matchTool->menuBar()->addMenu("&File");
563  fileMenu->addAction(m_saveNet);
564  fileMenu->addAction(m_saveAsNet);
565  fileMenu->addAction(m_closeMatchTool);
566 
567  QMenu * regMenu = m_matchTool->menuBar()->addMenu("&Registration");
568  regMenu->addAction(m_openTemplateFile);
569  regMenu->addAction(m_showHideTemplateEditor);
570  regMenu->addAction(m_saveChips);
571 
572  QMenu *helpMenu = m_matchTool->menuBar()->addMenu("&Help");
573  helpMenu->addAction(m_whatsThis);
574  }
575 
576 
577  void MatchTool::createToolBars() {
578 
579  QToolBar * toolBar = new QToolBar;
580  toolBar->setObjectName("TemplateEditorToolBar");
581  toolBar->setFloatable(false);
582  toolBar->addAction(m_saveNet);
583  toolBar->addSeparator();
584  toolBar->addAction(m_showHideTemplateEditor);
585  toolBar->addAction(m_saveChips);
586  toolBar->addAction(m_showHelp);
587  toolBar->addAction(m_whatsThis);
588 
589  m_matchTool->addToolBar(Qt::TopToolBarArea, toolBar);
590  }
591 
592 
593 
606  QAction *action = new QAction(pad);
607  action->setIcon(QPixmap(toolIconDir()+"/stock_draw-connector-with-arrows.png"));
608  action->setToolTip("Match Tool - Control Point Editor (T)");
609  action->setShortcut(Qt::Key_T);
610  return action;
611  }
612 
613 
614 
615  QWidget *MatchTool::createToolBarWidget(QStackedWidget *parent) {
616 
617  QWidget *hbox = new QWidget(parent);
618 
619  QToolButton *openNetButton = new QToolButton(hbox);
620  openNetButton->setIcon(QPixmap(toolIconDir() + "/fileopen.png"));
621  openNetButton->setIconSize(QSize(22,22));
622  openNetButton->setToolTip("Open control network");
623  openNetButton->setEnabled(true);
624  connect(openNetButton, SIGNAL(clicked()), this, SLOT(openNet()));
625 
626  QToolButton *saveAsNetButton = new QToolButton(hbox);
627  saveAsNetButton->setDefaultAction(m_saveAsNet);
628  saveAsNetButton->setIconSize(QSize(22,22));
629 
630  QToolButton *saveNetButton = new QToolButton(hbox);
631  saveNetButton->setDefaultAction(m_saveNet);
632  saveNetButton->setIconSize(QSize(22,22));
633 
634  QToolButton *helpButton = new QToolButton(hbox);
635  helpButton->setDefaultAction(m_showHelp);
636  helpButton->setIconSize(QSize(22, 22));
637 
638  QHBoxLayout *layout = new QHBoxLayout;
639  layout->setMargin(0);
640  layout->addWidget(openNetButton);
641  layout->addWidget(saveAsNetButton);
642  layout->addWidget(saveNetButton);
643  layout->addStretch();
644  layout->addWidget(helpButton);
645  hbox->setLayout(layout);
646 
647  return hbox;
648  }
649 
650 
651 
652  void MatchTool::activateTool() {
653 
654  if (!m_controlNet) {
655  m_controlNet = new ControlNet();
656  }
657  }
658 
659 
660 
671 
672  SerialNumberList list(false);
673  foreach (MdiCubeViewport *mvp, *cubeViewportList()) {
674  try {
675  // Attempt to Compose Serial number and see if list already has duplicate. If so,
676  // use filenames as serial numbers for both cubes. This needs to be checked because
677  // coreg networks will often have 2 cubes with the same serial number.make cl
678  QString sn = SerialNumber::Compose(mvp->cube()->fileName(), true);
679  if (list.hasSerialNumber(sn)) {
680  // TODO Before removing serial number, make sure current network does not have
681  // measures with old serial number. If it does, now what? Print error?
682  //
683  // Remove old serial number & change to filename
684  FileName fileName = Isis::FileName(list.fileName(sn));
685  list.Delete(sn);
686  list.add(fileName.name(),fileName.expanded());
687  // Add new serial number as filename
688  list.add(Isis::FileName(mvp->cube()->fileName()).name(),
689  mvp->cube()->fileName());
690  }
691  else {
692  list.add(mvp->cube()->fileName(), true);
693  }
694  }
695  catch (...) {
696  }
697  }
698  return list;
699  }
700 
701 
702 
703  QString MatchTool::serialNumber(MdiCubeViewport *mvp) {
704 
705  QString serialNumber;
706  try {
708  serialNumber = list.serialNumber(mvp->cube()->fileName());
709 // serialNumber = serialNumberList().SerialNumber(mvp->cube()->fileName());
710  }
711  catch (IException &e) {
712  serialNumber = "Unknown";
713  }
714  return serialNumber;
715 
716  }
717 
718 
719 
780 
781  // Read original measures from the network for comparison with measures
782  // that have been edited
783  ControlMeasure *origLeftMeasure =
784  m_editPoint->GetMeasure(m_leftMeasure->GetCubeSerialNumber());
785  ControlMeasure *origRightMeasure =
786  m_editPoint->GetMeasure(m_rightMeasure->GetCubeSerialNumber());
787  // Neither measure has changed, return
788  if (*origLeftMeasure == *m_leftMeasure && *origRightMeasure == *m_rightMeasure) {
789  return;
790  }
791 
792  if (m_editPoint->IsIgnored()) {
793  QString message = "You are saving changes to a measure on an ignored ";
794  message += "point. Do you want to set Ignore = False on the point and ";
795  message += "both measures?";
796  switch (QMessageBox::question(m_matchTool, "Match Tool Save Measure",
797  message, "&Yes", "&No", 0, 0)) {
798  // Yes: set Ignore=false for the point and measures and save point
799  case 0:
800  m_editPoint->SetIgnored(false);
801  emit ignorePointChanged();
802  if (m_leftMeasure->IsIgnored()) {
803  m_leftMeasure->SetIgnored(false);
804  emit ignoreLeftChanged();
805  }
806  if (m_rightMeasure->IsIgnored()) {
807  m_rightMeasure->SetIgnored(false);
808  emit ignoreRightChanged();
809  }
810  // No: keep Ignore=true and save measure
811  case 1:
812  break;
813  }
814  }
815 
816  bool savedAMeasure = false;
817  // Error check both measures for edit lock, ignore status and reference
818  bool leftChangeOk = validateMeasureChange(m_leftMeasure);
819  if (leftChangeOk) {
820  m_leftMeasure->SetChooserName(Application::UserName());
821  *origLeftMeasure = *m_leftMeasure;
822  savedAMeasure = true;
823  }
824  bool rightChangeOk = validateMeasureChange(m_rightMeasure);
825  if (rightChangeOk) {
826  m_rightMeasure->SetChooserName(Application::UserName());
827  *origRightMeasure = *m_rightMeasure;
828  savedAMeasure = true;
829  }
830 
831  // If left measure == right measure, update left
832  if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
833  *m_leftMeasure = *m_rightMeasure;
834  // Update left measure of pointEditor
835  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube,
836  m_editPoint->GetId());
837  }
838 
839  // Change Save Point button text to red
840  if (savedAMeasure) {
842  }
843 
844  emit editPointChanged();
845 
846  // Update measure info
850 
851  }
852 
853 
854 
855  bool MatchTool::validateMeasureChange(ControlMeasure *m) {
856 
857 
858  // Read original measures from the network for comparison with measures
859  // that have been edited
860  ControlMeasure *origMeasure =
861  m_editPoint->GetMeasure(m->GetCubeSerialNumber());
862 
863  // If measure hasn't changed, return false, to keep original
864 
865  if (*m == *origMeasure) return false;
866 
867  // Is measure on Left or Right? This is needed to print correct information
868  // to users in identifying the measure and for updating information widgets.
869  QString side = "right";
870  if (m->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
871  side = "left";
872  }
873 
874  // Only print error if both original measure in network and the current
875  // edit measure are both editLocked and measure has changed. If only the edit measure is
876  // locked, then user just locked and it needs to be saved.
877  // Do not use this classes IsMeasureLocked since we actually want to
878  // check the original againsted the edit measure and we don't care
879  // if this is a reference measure. The check for moving a reference is
880  // done below.
881  if (origMeasure->IsEditLocked() && m->IsEditLocked()) {
882  QString message = "The " + side + " measure is editLocked ";
883  message += "for editing. Do you want to set EditLock = False for this ";
884  message += "measure?";
885  int response = QMessageBox::question(m_matchTool, "Match Tool Save Measure",
886  message, QMessageBox::Yes | QMessageBox::No);
887  // Yes: set EditLock=false for the right measure
888  if (response == QMessageBox::Yes) {
889  m->SetEditLock(false);
890  if (side == "left") {
891  m_lockLeftMeasure->setChecked(false);
892  }
893  else {
894  m_lockRightMeasure->setChecked(false);
895  }
896  }
897  // No: keep EditLock=true and do NOT save measure
898  else {
899  return false;
900  }
901  }
902 
903  if (origMeasure->IsIgnored() && m->IsIgnored()) {
904  QString message = "The " + side + "measure is ignored. ";
905  message += "Do you want to set Ignore = False on the measure?";
906  switch(QMessageBox::question(m_matchTool, "Match Tool Save Measure",
907  message, "&Yes", "&No", 0, 0)){
908  // Yes: set Ignore=false for the right measure and save point
909  case 0:
910  m->SetIgnored(false);
911  if (side == "left") {
912  emit ignoreLeftChanged();
913  }
914  else {
915  emit ignoreRightChanged();
916  }
917  // No: keep Ignore=true and save point
918  case 1:
919  break;;
920  }
921  }
922 
923  // If measure is explicit reference and it has moved,warn user
924  ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
925  if (m_editPoint->IsReferenceExplicit()) {
926  if (refMeasure->GetCubeSerialNumber() == m->GetCubeSerialNumber()) {
927  if (m->GetSample() != origMeasure->GetSample() || m->GetLine() != origMeasure->GetLine()) {
928  QString message = "You are making a change to the reference measure. You ";
929  message += "may need to move all of the other measures to match the new ";
930  message += " coordinate of the reference measure. Do you really want to ";
931  message += " change the reference measure's location? ";
932  switch(QMessageBox::question(m_matchTool, "Match Tool Save Measure",
933  message, "&Yes", "&No", 0, 0)){
934  // Yes: Save measure
935  case 0:
936  break;
937  // No: keep original reference, return without saving
938  case 1:
939  loadPoint();
940  return false;
941  }
942  }
943  }
944  // New reference measure
945  else if (side == "left" && (refMeasure->GetCubeSerialNumber() != m->GetCubeSerialNumber())) {
946  if (m_coregNet) {
947  QString message = "This control network was created by the <i>coreg</i> program, and the "
948  "reference measure needs to remain the same as what <i>coreg</i> set. "
949  "Therefore, you cannot change which measure is the reference. To "
950  "save this point, move the reference measure (measure in BOLD) back "
951  "to the left side.";
952  QMessageBox::information(m_matchTool, "Cannot change reference", message);
953  }
954  else {
955  QString message = "This point already contains a reference measure. ";
956  message += "Would you like to replace it with the measure on the left?";
957  int response = QMessageBox::question(m_matchTool,
958  "Match Tool Save Measure", message,
959  QMessageBox::Yes | QMessageBox::No,
960  QMessageBox::Yes);
961  // Replace reference measure
962  if (response == QMessageBox::Yes) {
963  // Update measure file combo boxes: old reference normal font,
964  // new reference bold font
965  QString file = serialNumberList().fileName(m_leftMeasure->GetCubeSerialNumber());
966  QString fname = FileName(file).name();
967  int iref = m_leftCombo->findText(fname);
968 
969  // Save normal font from new reference measure
970  QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
971  m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
972  iref = m_rightCombo->findText(fname);
973  m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
974 
975  file = serialNumberList().fileName(refMeasure->GetCubeSerialNumber());
976  fname = FileName(file).name();
977  iref = m_leftCombo->findText(fname);
978  m_leftCombo->setItemData(iref,font,Qt::FontRole);
979  iref = m_rightCombo->findText(fname);
980  m_rightCombo->setItemData(iref,font,Qt::FontRole);
981 
982  m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
983  }
984  }
985  }
986  }
987  else {
988  // No explicit reference, If left, set explicit reference
989  if (side == "left") {
990  m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
991  }
992  }
993 
994  // All test pass, return true (ok to change measure)
995  return true;
996 
997 
998  }
999 
1000 
1001 
1002  /*
1003  * Change which measure is the reference.
1004  *
1005  * @author 2012-04-26 Tracie Sucharski - moved funcitonality from measureSaved
1006  *
1007  * @internal
1008  * @history 2012-06-12 Tracie Sucharski - Moved check for ground loaded on left from the
1009  * measureSaved method.
1010  */
1011  void MatchTool::checkReference() {
1012 
1013  // Check if ControlPoint has reference measure, if reference Measure is
1014  // not the same measure that is on the left chip viewport, set left
1015  // measure as reference.
1016  ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
1017  if (refMeasure->GetCubeSerialNumber() != m_leftMeasure->GetCubeSerialNumber()) {
1018  QString message = "This point already contains a reference measure. ";
1019  message += "Would you like to replace it with the measure on the left?";
1020  int response = QMessageBox::question(m_matchTool,
1021  "Match Tool Save Measure", message,
1022  QMessageBox::Yes | QMessageBox::No,
1023  QMessageBox::Yes);
1024  // Replace reference measure
1025  if (response == QMessageBox::Yes) {
1026  // Update measure file combo boxes: old reference normal font,
1027  // new reference bold font
1028  QString file = serialNumberList().fileName(m_leftMeasure->GetCubeSerialNumber());
1029  QString fname = FileName(file).name();
1030  int iref = m_leftCombo->findText(fname);
1031 
1032  // Save normal font from new reference measure
1033  QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
1034  m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1035  iref = m_rightCombo->findText(fname);
1036  m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1037 
1038  file = serialNumberList().fileName(refMeasure->GetCubeSerialNumber());
1039  fname = FileName(file).name();
1040  iref = m_leftCombo->findText(fname);
1041  m_leftCombo->setItemData(iref,font,Qt::FontRole);
1042  iref = m_rightCombo->findText(fname);
1043  m_rightCombo->setItemData(iref,font,Qt::FontRole);
1044 
1045  m_editPoint->SetRefMeasure(m_leftMeasure->GetCubeSerialNumber());
1046  }
1047 
1048  // ??? Need to set rest of measures to Candiate and add more warning. ???//
1049  }
1050 
1051 
1052  }
1053 
1054 
1055 
1071 
1072  // Make a copy of edit point for updating the control net since the edit
1073  // point is still loaded in the point editor.
1074  ControlPoint *updatePoint = new ControlPoint;
1075  *updatePoint = *m_editPoint;
1076 
1077  // If edit point exists in the network, save the updated point. If it
1078  // does not exist, add it.
1079  if (m_controlNet->ContainsPoint(updatePoint->GetId())) {
1080  ControlPoint *p;
1081  p = m_controlNet->GetPoint(QString(updatePoint->GetId()));
1082  *p = *updatePoint;
1083  delete updatePoint;
1084  updatePoint = NULL;
1085  }
1086  else {
1087  m_controlNet->AddPoint(updatePoint);
1088  }
1089 
1090  // Change Save Measure button text back to default
1091  m_savePoint->setPalette(m_saveDefaultPalette);
1092 
1093  // emit signal so the nav tool can update edit point
1094  emit editPointChanged();
1095  // At exit, or when opening new net, use for prompting user for a save
1096  m_netChanged = true;
1097  // Refresh chipViewports to show new positions of controlPoints
1098  m_pointEditor->refreshChips();
1099  }
1100 
1101 
1102 
1112  void MatchTool::setLockPoint (bool lock) {
1113  if (m_editPoint == NULL) return;
1114 
1115  m_editPoint->SetEditLock(lock);
1117  }
1118 
1119 
1120 
1131  void MatchTool::setIgnorePoint (bool ignore) {
1132  if (m_editPoint == NULL) return;
1133 
1134  ControlPoint::Status status = m_editPoint->SetIgnored(ignore);
1135  if (status == ControlPoint::PointLocked) {
1136  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1137  QString message = "Unable to change Ignored on point. Set EditLock ";
1138  message += " to False.";
1139  QMessageBox::critical(m_matchTool, "Error", message);
1140  return;
1141  }
1143  }
1144 
1145 
1146 
1147 
1164 
1165  if (m_editPoint->IsEditLocked()) {
1166  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1167  QMessageBox::warning(m_matchTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1168  " before changing a measure.");
1169  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1170  return;
1171  }
1172 
1173  if (m_leftMeasure != NULL) m_leftMeasure->SetEditLock(lock);
1174 
1175  // If the right chip is the same as the left chip , update the right editLock
1176  // box.
1177  if (m_rightMeasure != NULL) {
1178  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1179  m_rightMeasure->SetEditLock(lock);
1180  m_lockRightMeasure->setChecked(lock);
1181  }
1182  }
1183  emit measureChanged();
1184  }
1185 
1186 
1204  void MatchTool::setIgnoreLeftMeasure (bool ignore) {
1205  if (m_leftMeasure != NULL) m_leftMeasure->SetIgnored(ignore);
1206 
1207  // If the right chip is the same as the left chip , update the right
1208  // ignore box.
1209  if (m_rightMeasure != NULL) {
1210  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1211  m_rightMeasure->SetIgnored(ignore);
1212  m_ignoreRightMeasure->setChecked(ignore);
1213  }
1214  }
1215  emit measureChanged();
1216  }
1217 
1218 
1235 
1236  if (m_editPoint->IsEditLocked()) {
1237  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1238  QMessageBox::warning(m_matchTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1239  " before changing a measure.");
1240  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1241  return;
1242  }
1243 
1244  if (m_rightMeasure != NULL) m_rightMeasure->SetEditLock(lock);
1245 
1246  // If the left chip is the same as the right chip , update the left editLock box.
1247  if (m_leftMeasure != NULL) {
1248  if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
1249  m_leftMeasure->SetEditLock(lock);
1250  m_lockLeftMeasure->setChecked(lock);
1251  }
1252  }
1253  emit measureChanged();
1254  }
1255 
1256 
1275  if (m_rightMeasure != NULL) m_rightMeasure->SetIgnored(ignore);
1276 
1277  // If the right chip is the same as the left chip , update the right
1278  // ignore blox.
1279  if (m_leftMeasure != NULL) {
1280  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1281  m_leftMeasure->SetIgnored(ignore);
1282  m_ignoreLeftMeasure->setChecked(ignore);
1283  }
1284  }
1285  emit measureChanged();
1286  }
1287 
1288 
1289 
1290  void MatchTool::openNet() {
1291 
1292  if (m_controlNet) {
1293  if (m_controlNet->GetNumPoints() != 0 && m_netChanged) {
1294  QString message = "A control net has already been created. Do you want to save before "
1295  "opening a new control net?";
1296  int response = QMessageBox::question(m_matchTool, "Save current control net?",
1297  message,
1298  QMessageBox::Yes | QMessageBox::No,
1299  QMessageBox::Yes);
1300  // Yes: Save old net, so return without opening network.
1301  if (response == QMessageBox::Yes) {
1302  saveAsNet();
1303  }
1304  m_matchTool->setShown(false);
1305  }
1306  delete m_controlNet;
1307  m_controlNet = NULL;
1308  m_editPoint = NULL;
1309  m_newPoint = NULL;
1310  m_newPointDialog = NULL;
1311  }
1312 
1313  // At exit, or when opening new net, use for prompting user for a save
1314  m_netChanged = false;
1315 
1316  QApplication::restoreOverrideCursor();
1317  QString filter = "Control net (*.net *.cnet *.ctl);;";
1318  filter += "Pvl file (*.pvl);;";
1319  filter += "Text file (*.txt);;";
1320  filter += "All (*)";
1321  m_cnetFileName = QFileDialog::getOpenFileName((QWidget *)parent(),
1322  "Select a control network",
1323  ".",
1324  filter);
1325  QApplication::setOverrideCursor(Qt::WaitCursor);
1326  if (!m_cnetFileName.isEmpty()) {
1327  try {
1328  Progress progress;
1329  m_controlNet = new ControlNet(m_cnetFileName, &progress);
1330  m_coregNet = false;
1331  m_coregReferenceSN = "";
1332  if (m_controlNet->GetNetworkId() == "Coreg") {
1333  m_coregNet = true;
1334  // Find reference image of first point, the rest of the points will have the same
1335  // reference. When creating new point, use the same reference.
1336  m_coregReferenceSN = m_controlNet->GetPoint(0)->GetReferenceSN();
1337  }
1338  }
1339  catch (IException &e) {
1340  QApplication::restoreOverrideCursor();
1341  QString message = "Invalid control network. \n";
1342  message += e.toString();
1343  QMessageBox::critical(m_matchTool, "Error", message);
1344  m_cnetFileName.clear();
1345  delete m_controlNet;
1346  m_controlNet = NULL;
1347  return;
1348  }
1349  }
1350  QApplication::restoreOverrideCursor();
1351  m_matchTool->setWindowTitle("Match Tool - Control Network File: " + m_cnetFileName);
1352  m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName);
1353 
1355  }
1356 
1357 
1358 
1365  if (m_cnetFileName.isEmpty()) {
1366  QString message = "This is a new network, you must select "
1367  "\"Save As\" under the File Menu or on the toolbar.";
1368  QMessageBox::critical(m_matchTool, "Error", message);
1369  return;
1370  }
1371  try {
1372  m_controlNet->Write(m_cnetFileName);
1373  m_netChanged = false;
1374  }
1375  catch (IException &e) {
1376  QMessageBox::critical(m_matchTool, tr("Error Writing Control Net"), e.what());
1377  return;
1378  }
1379  }
1380 
1381 
1382 
1387 
1388  QString fn = QFileDialog::getSaveFileName(m_matchTool,
1389  "Choose filename to save under",
1390  ".",
1391  "Control Files (*.net)");
1392 
1393  //Make sure the filename is valid
1394  if(!fn.isEmpty()) {
1395  try {
1396  m_controlNet->Write(fn);
1397  m_netChanged = false;
1398  }
1399  catch (IException &e) {
1400  QMessageBox::critical(m_matchTool, tr("Error Writing Control Net"), e.what());
1401  return;
1402  }
1403  m_cnetFileName = fn;
1404  }
1405  //The user cancelled, or the filename is empty
1406  else {
1407  return;
1408  }
1409 
1410  }
1411 
1412 
1413 
1441  void MatchTool::mouseButtonRelease(QPoint p, Qt::MouseButton s) {
1442  MdiCubeViewport *mvp = cubeViewport();
1443  if (mvp == NULL) return;
1444 
1445  QString file = mvp->cube()->fileName();
1446  QString sn = serialNumberList().serialNumber(file);
1447 
1448  double samp,line;
1449  mvp->viewportToCube(p.x(),p.y(),samp,line);
1450 
1451  if (s == Qt::LeftButton) {
1452 
1453  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1454  QString message = "No points exist for editing. Create points ";
1455  message += "using the right mouse button.";
1456  QMessageBox::warning(m_matchTool, "Warning", message);
1457  return;
1458  }
1459 
1460  // Find closest control point in network
1461  QString sn = serialNumberList().serialNumber(file);
1462  ControlPoint *point = NULL;
1463  try {
1464  point = m_controlNet->FindClosest(sn, samp, line);
1465  }
1466  catch (IException &e) {
1467  QString message = "Cannot find point for editing.";
1468  message += e.toString();
1469  QMessageBox::warning(m_matchTool, "Warning", message);
1470  return;
1471  }
1472 
1473  modifyPoint(point);
1474  }
1475  else if (s == Qt::MidButton) {
1476  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1477  QString message = "No points exist for deleting. Create points ";
1478  message += "using the right mouse button.";
1479  QMessageBox::warning(m_matchTool, "Warning", message);
1480  return;
1481  }
1482 
1483  // Find closest control point in network
1484  ControlPoint *point = m_controlNet->FindClosest(sn, samp, line);
1485 
1486  if (point == NULL) {
1487  QString message = "No points exist for deleting. Create points ";
1488  message += "using the right mouse button.";
1489  QMessageBox::warning(m_matchTool, "Warning", message);
1490  return;
1491  }
1492 
1493  deletePoint(point);
1494  }
1495  else if (s == Qt::RightButton) {
1496  if (m_newPointDialog) {
1497  addMeasure(mvp, samp, line);
1498  }
1499  else {
1500  try {
1501  createPoint(mvp, samp, line);
1502  m_leftFile = mvp->cube()->fileName();
1503  }
1504  catch (IException &e) {
1505  QString message = "Cannot create control point.\n\n";
1506  message += e.toString();
1507  QMessageBox::critical(m_matchTool, "Error", message);
1508  return;
1509  }
1510  }
1511  }
1512  }
1513 
1514 
1515 
1516  QStringList MatchTool::missingCubes(ControlPoint *point) {
1517 
1518  // Make sure all measures are loaded into viewports, otherwise we cannot edit this point
1519  QStringList missingCubes;
1520  for (int i=0; i<point->GetNumMeasures(); i++) {
1521  ControlMeasure &m = *(*point)[i];
1523  missingCubes << m.GetCubeSerialNumber();
1524  }
1525  }
1526  return missingCubes;
1527  }
1528 
1529 
1530 
1537  void MatchTool::createPoint(MdiCubeViewport *cvp, double sample, double line) {
1538 
1539  m_newPointDialog = new MatchToolNewPointDialog(*m_controlNet, m_lastUsedPointId, m_matchTool);
1540  connect(m_newPointDialog, SIGNAL(measuresFinished()), this, SLOT(doneWithMeasures()));
1541  connect(m_newPointDialog, SIGNAL(newPointCanceled()), this, SLOT(cancelNewPoint()));
1542 
1543  QStringList images;
1544  for (int i = 0; i < (int)cubeViewportList()->size(); i++) {
1545  FileName cubeFile = (*(cubeViewportList()))[i]->cube()->fileName();
1546  images<<cubeFile.name();
1547  }
1548  m_newPointDialog->setFiles(images);
1549  m_newPointDialog->show();
1550 
1551  // Highlight the current cubeViewport
1552  QString current = FileName(cvp->cube()->fileName()).name();
1553  m_newPointDialog->highlightFile(current);
1554 
1555  m_newPoint = new ControlPoint();
1556  m_newPoint->SetType(ControlPoint::Free);
1557  m_newPoint->SetChooserName(Application::UserName());
1558 
1559  ControlMeasure *m = new ControlMeasure;
1560  m->SetCubeSerialNumber(serialNumber(cvp));
1561  m->SetCoordinate(sample, line);
1563  m->SetDateTime();
1565  m_newPoint->Add(m);
1566 
1568  }
1569 
1570 
1571 
1572  void MatchTool::addMeasure(MdiCubeViewport *cvp, double sample, double line) {
1573 
1574  // Highlight the current cubeViewport
1575  QString current = FileName(cvp->cube()->fileName()).name();
1576  m_newPointDialog->highlightFile(current);
1577  m_newPointDialog->raise();
1578 
1579  ControlMeasure *m = new ControlMeasure;
1580  m->SetCubeSerialNumber(serialNumber(cvp));
1581 
1582  // If serial number already exists, delete old measure before creating new
1583  if (m_newPoint->HasSerialNumber(serialNumber(cvp))) {
1584  m_newPoint->Delete(m_newPoint->GetMeasure(serialNumber(cvp)));
1585  }
1586  m->SetCoordinate(sample, line);
1588  m->SetDateTime();
1590  m_newPoint->Add(m);
1591 
1593  }
1594 
1595 
1596 
1597  void MatchTool::doneWithMeasures() {
1598 
1599  m_lastUsedPointId = m_newPointDialog->pointId();
1600  m_newPoint->SetId(m_lastUsedPointId);
1601 // // Add new control point to control network
1602 // m_controlNet->AddPoint(m_newPoint);
1603 // // Read newly added point
1604 // // TODO Make sure pt exists
1605 // m_editPoint = m_controlNet->GetPoint((QString) m_newPoint->GetId());
1606 
1607  // If this is a coreg network, make sure the reference SN exists in the new point
1608  // and set it to the reference measure.
1609  if (m_coregNet) {
1610  if (!m_newPoint->HasSerialNumber(m_coregReferenceSN)) {
1611  QString message = "This is a coreg network which needs the cube with serial number " +
1612  m_coregReferenceSN + " as the reference measure. This new control point does "
1613  "not have a measure for that serial number, so this point cannot be created until "
1614  "the cube listed above is added (Right-click on cube).";
1615  QMessageBox::critical(m_matchTool, "Error", message);
1616  m_newPointDialog->show();
1617  return;
1618  }
1619  // Set the reference measure to match the rest of the points
1620  m_newPoint->SetRefMeasure(m_newPoint->GetMeasure(m_coregReferenceSN));
1621  }
1622 
1623  // If the editPoint has been used, but there is not currently a network, delete the editPoint
1624  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1625  delete m_editPoint;
1626  m_editPoint = NULL;
1627  }
1628  m_editPoint = m_newPoint;
1629 
1630  m_newPoint = NULL;
1631  delete m_newPointDialog;
1632  m_newPointDialog = NULL;
1633 
1634  // Load new point in MatchTool
1635  loadPoint();
1636  m_matchTool->setShown(true);
1637  m_matchTool->raise();
1638 
1639  emit editPointChanged();
1641  }
1642 
1643 
1644 
1645  void MatchTool::cancelNewPoint() {
1646 
1647  delete m_newPointDialog;
1648  m_newPointDialog = NULL;
1649  delete m_newPoint;
1650  m_newPoint = NULL;
1651  m_leftFile.clear();
1652 
1654 
1655  }
1656 
1657 
1658 
1678 
1679  QStringList mCubes = missingCubes(point);
1680  if (mCubes.size() > 0) {
1681  QString msgTitle = "Missing Cubes";
1682  QString message = "This point is missing cubes for the following measures and cannot be ";
1683  message += "loaded into the editor. Do you still want to delete this point?\n\n";
1684  for (int i=0; i<mCubes.size(); i++) {
1685  message += mCubes.at(i) + "\n";
1686  }
1687  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1688  Qt::Dialog);
1689  QPushButton *yesButton = msgBox.addButton("Yes", QMessageBox::AcceptRole);
1690  QPushButton *noButton = msgBox.addButton("No", QMessageBox::RejectRole);
1691  msgBox.setDefaultButton(yesButton);
1692  msgBox.exec();
1693  if (msgBox.clickedButton() == noButton) {
1694  return;
1695  }
1696  else {
1697  m_matchTool->setShown(false);
1698  }
1699 
1700  }
1701 
1702  // Make a copy and make sure editPoint is a copy (which means it does not
1703  // have a parent network.
1704  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1705  delete m_editPoint;
1706  m_editPoint = NULL;
1707  }
1708  m_editPoint = new ControlPoint;
1709  *m_editPoint = *point;
1710 
1711  // No missing cubes, load edit point as usual
1712  if (mCubes.size() == 0) {
1713  loadPoint();
1714 
1715  // Change point in viewport to red so user can see what point they are
1716  // about to delete.
1717  // the nav tool will update edit point
1718  emit editPointChanged();
1719  }
1720 
1721  MatchToolDeletePointDialog *deletePointDialog = new MatchToolDeletePointDialog;
1722  QString CPId = m_editPoint->GetId();
1723  deletePointDialog->pointIdValue->setText(CPId);
1724  // Need all files for this point
1725  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1726  ControlMeasure &m = *(*m_editPoint)[i];
1727  QString file;
1730  }
1731  else {
1732  file = m.GetCubeSerialNumber();
1733  }
1734  deletePointDialog->fileList->addItem(file);
1735  }
1736 
1737  if (deletePointDialog->exec()) {
1738 
1739  int numDeleted = deletePointDialog->fileList->selectedItems().count();
1740 
1741  // Delete entire control point, either through deleteAllCheckBox or all measures selected
1742  if (deletePointDialog->deleteAllCheckBox->isChecked() ||
1743  numDeleted == m_editPoint->GetNumMeasures()) {
1744 
1745  // If all measures being deleted, let user know and give them the option to quit operation
1746  if (!deletePointDialog->deleteAllCheckBox->isChecked()) {
1747  QString message = "You have selected all measures in this point to be deleted. This "
1748  "control point will be deleted. Do you want to delete this control point?";
1749  int response = QMessageBox::question(m_matchTool,
1750  "Delete control point", message,
1751  QMessageBox::Yes | QMessageBox::No,
1752  QMessageBox::Yes);
1753  // If No, do nothing
1754  if (response == QMessageBox::No) {
1755  return;
1756  }
1757  }
1758 
1759  m_matchTool->setShown(false);
1760  // remove this point from the control network
1761  if (m_controlNet->DeletePoint(m_editPoint->GetId()) == ControlPoint::PointLocked) {
1762  QMessageBox::information(m_matchTool, "EditLocked Point",
1763  "This point is EditLocked and cannot be deleted.");
1764  return;
1765  }
1766  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1767  delete m_editPoint;
1768  m_editPoint = NULL;
1769  }
1770  }
1771 
1772  // Delete specific measures from control point
1773  else {
1774  // Keep track of editLocked measures for reporting
1775  int lockedMeasures = 0;
1776  for (int i=0; i<deletePointDialog->fileList->count(); i++) {
1777  QListWidgetItem *item = deletePointDialog->fileList->item(i);
1778  if (!deletePointDialog->fileList->isItemSelected(item)) continue;
1779 
1780  // Do not delete reference without asking user
1781  if (m_editPoint->IsReferenceExplicit() &&
1782  (m_editPoint->GetRefMeasure()->GetCubeSerialNumber() ==
1783  (*m_editPoint)[i]->GetCubeSerialNumber())) {
1784  QString message = "You are trying to delete the Reference measure."
1785  " Do you really want to delete the Reference measure?";
1786  switch (QMessageBox::question(m_matchTool,
1787  "Delete Reference measure?", message,
1788  "&Yes", "&No", 0, 0)) {
1789  // Yes: skip to end of switch to delete the measure
1790  case 0:
1791  break;
1792  // No: continue to next measure in the loop
1793  case 1:
1794  // if only a single measure and it's reference and user chooses not to delete,
1795  // simply return. The point has not changed.
1796  if (numDeleted == 1) {
1797  return;
1798  }
1799  continue;
1800  }
1801  }
1802 
1803  if (m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
1804  lockedMeasures++;
1805  }
1806  }
1807 
1808  if (lockedMeasures > 0) {
1809  QMessageBox::information(m_matchTool,"EditLocked Measures",
1810  QString::number(lockedMeasures) + " / "
1811  + QString::number(
1812  deletePointDialog->fileList->selectedItems().size()) +
1813  " measures are EditLocked and were not deleted.");
1814  }
1815 
1816  if (mCubes.size() == 0) {
1817  loadPoint();
1818  m_matchTool->setShown(true);
1819  m_matchTool->raise();
1820 
1822  m_pointEditor->templateFileName());
1823  }
1824  // Since the delete point is not loaded into the editor for saving by the user, we need
1825  // to save the point.
1826  else {
1827  ControlPoint *p = m_controlNet->GetPoint(QString(m_editPoint->GetId()));
1828  *p = *m_editPoint;
1829 
1830  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1831  delete m_editPoint;
1832  m_editPoint = NULL;
1833  }
1834  }
1835  }
1836 
1837  // emit a signal to alert user to save when exiting
1838  // At exit, or when opening new net, use for prompting user for a save
1839  m_netChanged = true;
1840 
1841  if (m_editPoint) {
1843  }
1844  emit editPointChanged();
1845  }
1846  }
1847 
1848 
1849 
1859 
1860  // If no measures, print info and return
1861  if (point->GetNumMeasures() == 0) {
1862  QString message = "This point has no measures.";
1863  QMessageBox::warning(m_matchTool, "Warning", message);
1864  emit editPointChanged();
1865  return;
1866  }
1867 
1868  // Make sure all measures have a cube loaded
1869  QStringList mCubes = missingCubes(point);
1870  if (mCubes.size() > 0) {
1871  QString msgTitle = "Missing Cubes";
1872  QString message = "This point is missing cubes and cannot be loaded into the editor. Open ";
1873  message += "the cubes for the following measures before selecting this point.\n\n";
1874  for (int i=0; i<mCubes.size(); i++) {
1875  message += mCubes.at(i) + "\n";
1876  }
1877  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1878  Qt::Dialog);
1879  msgBox.exec();
1880  return;
1881  }
1882 
1883  // Make a copy of point for editing, first make sure memory not already
1884  // allocated
1885  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1886  delete m_editPoint;
1887  m_editPoint = NULL;
1888  }
1889  m_editPoint = new ControlPoint;
1890  *m_editPoint = *point;
1891 
1892  loadPoint();
1893  m_matchTool->setShown(true);
1894  m_matchTool->raise();
1896  m_pointEditor->templateFileName());
1897 
1898  // emit signal so the nav tool can update edit point
1899  emit editPointChanged();
1900 
1901  // New point loaded, make sure Save Measure Button text is default
1902  m_savePoint->setPalette(m_saveDefaultPalette);
1903  }
1904 
1905 
1906 
1925 
1926  // Write pointId
1927  QString CPId = m_editPoint->GetId();
1928  QString ptId("Point ID: ");
1929  ptId += (QString) CPId;
1930  m_ptIdValue->setText(ptId);
1931 
1932  // Write number of measures
1933  QString ptsize = "Number of Measures: " +
1934  QString::number(m_editPoint->GetNumMeasures());
1935  m_numMeasures->setText(ptsize);
1936 
1937  // Set EditLock box correctly
1938  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
1939 
1940  // Set ignore box correctly
1941  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1942 
1943  // Clear combo boxes
1944  m_leftCombo->clear();
1945  m_rightCombo->clear();
1946  m_pointFiles.clear();
1947 
1948  // Need all files for this point
1949  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1950  ControlMeasure &m = *(*m_editPoint)[i];
1951  QString file = serialNumberList().fileName(m.GetCubeSerialNumber());
1952  m_pointFiles<<file;
1953  QString tempFileName = FileName(file).name();
1954  m_leftCombo->addItem(tempFileName);
1955  m_rightCombo->addItem(tempFileName);
1956  if (m_editPoint->IsReferenceExplicit() &&
1957  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
1958  m_leftCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1959  m_rightCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1960  }
1961  }
1962 
1963  // TODO: WHAT HAPPENS IF THERE IS ONLY ONE MEASURE IN THIS CONTROLPOINT??
1964  // Assuming combo loaded in same order as measures in the control point-is
1965  // this a safe assumption???
1966  //
1967  // Find the file from the cubeViewport that was originally used to select
1968  // the point, this will be displayed on the left ChipViewport, unless the
1969  // point was selected on the ground source image. In this case, simply
1970  // load the first measure on the left.
1971  int leftIndex = 0;
1972  int rightIndex = 0;
1973  // Check for reference
1974  if (m_editPoint->IsReferenceExplicit()) {
1975  leftIndex = m_editPoint->IndexOfRefMeasure();
1976  }
1977  else {
1978  if (!m_leftFile.isEmpty()) {
1979  leftIndex = m_leftCombo->findText(FileName(m_leftFile).name());
1980  // Sanity check
1981  if (leftIndex < 0 ) leftIndex = 0;
1982  m_leftFile.clear();
1983  }
1984  }
1985 
1986  if (leftIndex == 0) {
1987  rightIndex = 1;
1988  }
1989  else {
1990  rightIndex = 0;
1991  }
1992 
1993  // Handle pts with a single measure, for now simply put measure on left/right
1994  // Evenutally put on left with black on right??
1995  if (rightIndex > m_editPoint->GetNumMeasures()-1) rightIndex = 0;
1996  m_rightCombo->setCurrentIndex(rightIndex);
1997  m_leftCombo->setCurrentIndex(leftIndex);
1998  // Initialize pointEditor with measures
1999  selectLeftMeasure(leftIndex);
2000  selectRightMeasure(rightIndex);
2001 
2002  loadMeasureTable();
2003  }
2004 
2005 
2006 
2015  if (m_measureWindow == NULL) {
2016  m_measureWindow = new QMainWindow(m_parent);
2017  m_measureTable = new QTableWidget();
2018  m_measureTable->setMinimumWidth(1600);
2019  m_measureTable->setAlternatingRowColors(true);
2020  m_measureWindow->setCentralWidget(m_measureTable);
2021  }
2022  else {
2023  m_measureTable->clear();
2024  m_measureTable->setSortingEnabled(false);
2025  }
2026  m_measureTable->setRowCount(m_editPoint->GetNumMeasures());
2027  m_measureTable->setColumnCount(NUMCOLUMNS);
2028 
2029  QStringList labels;
2030  for (int i=0; i<NUMCOLUMNS; i++) {
2031  labels<<measureColumnToString((MeasureColumns)i);
2032  }
2033  m_measureTable->setHorizontalHeaderLabels(labels);
2034 
2035  // Fill in values
2036  for (int row=0; row<m_editPoint->GetNumMeasures(); row++) {
2037  int column = 0;
2038  ControlMeasure &m = *(*m_editPoint)[row];
2039 
2040  QString file = serialNumberList().fileName(m.GetCubeSerialNumber());
2041  QTableWidgetItem *tableItem = new QTableWidgetItem(QString(file));
2042  m_measureTable->setItem(row,column++,tableItem);
2043 
2044  tableItem = new QTableWidgetItem(QString(m.GetCubeSerialNumber()));
2045  m_measureTable->setItem(row,column++,tableItem);
2046 
2047  tableItem = new QTableWidgetItem();
2048  tableItem->setData(0,m.GetSample());
2049  m_measureTable->setItem(row,column++,tableItem);
2050 
2051  tableItem = new QTableWidgetItem();
2052  tableItem->setData(0,m.GetLine());
2053  m_measureTable->setItem(row,column++,tableItem);
2054 
2055  if (m.GetAprioriSample() == Null) {
2056  tableItem = new QTableWidgetItem("Null");
2057  }
2058  else {
2059  tableItem = new QTableWidgetItem();
2060  tableItem->setData(0,m.GetAprioriSample());
2061  }
2062  m_measureTable->setItem(row,column++,tableItem);
2063 
2064  if (m.GetAprioriLine() == Null) {
2065  tableItem = new QTableWidgetItem("Null");
2066  }
2067  else {
2068  tableItem = new QTableWidgetItem();
2069  tableItem->setData(0,m.GetAprioriLine());
2070  }
2071  m_measureTable->setItem(row,column++,tableItem);
2072 
2073  if (m.GetSampleResidual() == Null) {
2074  tableItem = new QTableWidgetItem(QString("Null"));
2075  }
2076  else {
2077  tableItem = new QTableWidgetItem();
2078  tableItem->setData(0,m.GetSampleResidual());
2079  }
2080  m_measureTable->setItem(row,column++,tableItem);
2081 
2082  if (m.GetLineResidual() == Null) {
2083  tableItem = new QTableWidgetItem(QString("Null"));
2084  }
2085  else {
2086  tableItem = new QTableWidgetItem();
2087  tableItem->setData(0,m.GetLineResidual());
2088  }
2089  m_measureTable->setItem(row,column++,tableItem);
2090 
2091  if (m.GetResidualMagnitude() == Null) {
2092  tableItem = new QTableWidgetItem(QString("Null"));
2093  }
2094  else {
2095  tableItem = new QTableWidgetItem();
2096  tableItem->setData(0,m.GetResidualMagnitude());
2097  }
2098  m_measureTable->setItem(row,column++,tableItem);
2099 
2100  double sampleShift = m.GetSampleShift();
2101  if (sampleShift == Null) {
2102  tableItem = new QTableWidgetItem(QString("Null"));
2103  }
2104  else {
2105  tableItem = new QTableWidgetItem();
2106  tableItem->setData(0,sampleShift);
2107  }
2108  m_measureTable->setItem(row,column++,tableItem);
2109 
2110  double lineShift = m.GetLineShift();
2111  if (lineShift == Null) {
2112  tableItem = new QTableWidgetItem(QString("Null"));
2113  }
2114  else {
2115  tableItem = new QTableWidgetItem();
2116  tableItem->setData(0,lineShift);
2117  }
2118  m_measureTable->setItem(row,column++,tableItem);
2119 
2120  double pixelShift = m.GetPixelShift();
2121  if (pixelShift == Null) {
2122  tableItem = new QTableWidgetItem(QString("Null"));
2123  }
2124  else {
2125  tableItem = new QTableWidgetItem();
2126  tableItem->setData(0,pixelShift);
2127  }
2128  m_measureTable->setItem(row,column++,tableItem);
2129 
2130  double goodnessOfFit = m.GetLogData(
2132  if (goodnessOfFit == Null) {
2133  tableItem = new QTableWidgetItem(QString("Null"));
2134  }
2135  else {
2136  tableItem = new QTableWidgetItem();
2137  tableItem->setData(0,goodnessOfFit);
2138  }
2139  m_measureTable->setItem(row,column++,tableItem);
2140 
2141  if (m.IsIgnored()) tableItem = new QTableWidgetItem("True");
2142  if (!m.IsIgnored()) tableItem = new QTableWidgetItem("False");
2143  m_measureTable->setItem(row,column++,tableItem);
2144 
2146  tableItem = new QTableWidgetItem("True");
2148  tableItem = new QTableWidgetItem("False");
2149  m_measureTable->setItem(row,column++,tableItem);
2150 
2151  tableItem = new QTableWidgetItem(
2153  m_measureTable->setItem(row,column,tableItem);
2154 
2155  // If reference measure set font on this row to bold
2156  if (m_editPoint->IsReferenceExplicit() &&
2157  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
2158  QFont font;
2159  font.setBold(true);
2160 
2161  for (int col=0; col<m_measureTable->columnCount(); col++)
2162  m_measureTable->item(row, col)->setFont(font);
2163  }
2164 
2165  }
2166 
2167  m_measureTable->resizeColumnsToContents();
2168  m_measureTable->resizeRowsToContents();
2169  m_measureTable->setSortingEnabled(true);
2170  m_measureWindow->show();
2171  }
2172 
2173 
2174 
2175  QString MatchTool::measureColumnToString(MatchTool::MeasureColumns column) {
2176  switch (column) {
2177  case FILENAME:
2178  return "FileName";
2179  case CUBESN:
2180  return "Serial #";
2181  case SAMPLE:
2182  return "Sample";
2183  case LINE:
2184  return "Line";
2185  case SAMPLERESIDUAL:
2186  return "Sample Residual";
2187  case LINERESIDUAL:
2188  return "Line Residual";
2189  case RESIDUALMAGNITUDE:
2190  return "Residual Magnitude";
2191  case SAMPLESHIFT:
2192  return "Sample Shift";
2193  case LINESHIFT:
2194  return "Line Shift";
2195  case PIXELSHIFT:
2196  return "Pixel Shift";
2197  case GOODNESSOFFIT:
2198  return "Goodness of Fit";
2199  case IGNORED:
2200  return "Ignored";
2201  case EDITLOCK:
2202  return "Edit Lock";
2203  case TYPE:
2204  return "Measure Type";
2205  case APRIORISAMPLE:
2206  return "Apriori Sample";
2207  case APRIORILINE:
2208  return "Apriori Line";
2209  }
2210  throw IException(IException::Programmer,
2211  "Invalid measure column passed to measureColumnToString", _FILEINFO_);
2212  }
2213 
2214 
2215 
2226  int curIndex = m_rightCombo->currentIndex();
2227  if (curIndex < m_rightCombo->count() - 1) {
2228  // update the right measure list index and select that measure
2229  m_rightCombo->setCurrentIndex(curIndex + 1);
2230  selectRightMeasure(curIndex+1);
2231  }
2232  }
2233 
2234 
2245  int curIndex = m_rightCombo->currentIndex();
2246  if (curIndex > 0) {
2247  // update the right measure list index and select that measure
2248  m_rightCombo->setCurrentIndex(curIndex - 1);
2249  selectRightMeasure(curIndex-1);
2250  }
2251  }
2252 
2253 
2254 
2269  QString file = m_pointFiles[index];
2270 
2271  QString serial;
2272  try {
2273  serial = serialNumberList().serialNumber(file);
2274  }
2275  catch (IException &e) {
2276  QString message = "Make sure the correct cube is opened.\n\n";
2277  message += e.toString();
2278  QMessageBox::critical(m_matchTool, "Error", message);
2279 
2280  // Set index of combo back to what it was before user selected new. Find the index
2281  // of current left measure.
2282  QString file = serialNumberList().fileName(m_leftMeasure->GetCubeSerialNumber());
2283  int i = m_leftCombo->findText(FileName(file).name());
2284  if (i < 0) i = 0;
2285  m_leftCombo->setCurrentIndex(i);
2286  return;
2287  }
2288 
2289  // Make sure to clear out leftMeasure before making a copy of the selected
2290  // measure.
2291  if (m_leftMeasure != NULL) {
2292  delete m_leftMeasure;
2293  m_leftMeasure = NULL;
2294  }
2295  m_leftMeasure = new ControlMeasure();
2296  // Find measure for each file
2297  *m_leftMeasure = *((*m_editPoint)[serial]);
2298 
2299  // If m_leftCube is not null, delete before creating new one
2300  if (m_leftCube != NULL) delete m_leftCube;
2301  m_leftCube = new Cube();
2302  m_leftCube->open(file);
2303 
2304  // Update left measure of pointEditor
2305  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube,
2306  m_editPoint->GetId());
2308 
2309  }
2310 
2311 
2324 
2325  QString file = m_pointFiles[index];
2326 
2327  QString serial;
2328  try {
2329  serial = serialNumberList().serialNumber(file);
2330  }
2331  catch (IException &e) {
2332  QString message = "Make sure the correct cube is opened.\n\n";
2333  message += e.toString();
2334  QMessageBox::critical(m_matchTool, "Error", message);
2335 
2336  // Set index of combo back to what it was before user selected new. Find the index
2337  // of current left measure.
2338  QString file = serialNumberList().fileName(m_rightMeasure->GetCubeSerialNumber());
2339  int i = m_rightCombo->findText(FileName(file).name());
2340  if (i < 0) i = 0;
2341  m_rightCombo->setCurrentIndex(i);
2342  return;
2343  }
2344 
2345  // Make sure to clear out rightMeasure before making a copy of the selected
2346  // measure.
2347  if (m_rightMeasure != NULL) {
2348  delete m_rightMeasure;
2349  m_rightMeasure = NULL;
2350  }
2351  m_rightMeasure = new ControlMeasure();
2352  // Find measure for each file
2353  *m_rightMeasure = *((*m_editPoint)[serial]);
2354 
2355  // If m_leftCube is not null, delete before creating new one
2356  if (m_rightCube != NULL) delete m_rightCube;
2357  m_rightCube = new Cube();
2358  m_rightCube->open(file);
2359 
2360  // Update left measure of pointEditor
2361  m_pointEditor->setRightMeasure (m_rightMeasure,m_rightCube,
2362  m_editPoint->GetId());
2364 
2365  }
2366 
2367 
2368 
2369 
2386 
2387  // Set editLock measure box correctly
2388  m_lockLeftMeasure->setChecked(IsMeasureLocked(
2389  m_leftMeasure->GetCubeSerialNumber()));
2390  // Set ignore measure box correctly
2391  m_ignoreLeftMeasure->setChecked(m_leftMeasure->IsIgnored());
2392 
2393  QString s = "Reference: ";
2394  if (m_editPoint->IsReferenceExplicit() &&
2395  (QString(m_leftMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2396  s += "True";
2397  }
2398  else {
2399  s += "False";
2400  }
2401  m_leftReference->setText(s);
2402 
2403  s = "Measure Type: ";
2404  if (m_leftMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2405  if (m_leftMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2406  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2407  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2408  m_leftMeasureType->setText(s);
2409 
2410  if (m_leftMeasure->GetSampleShift() == Null) {
2411  s = "Sample Shift: Null";
2412  }
2413  else {
2414  s = "Sample Shift: " + QString::number(m_leftMeasure->GetSampleShift());
2415  }
2416  m_leftSampShift->setText(s);
2417 
2418  if (m_leftMeasure->GetLineShift() == Null) {
2419  s = "Line Shift: Null";
2420  }
2421  else {
2422  s = "Line Shift: " + QString::number(m_leftMeasure->GetLineShift());
2423  }
2424  m_leftLineShift->setText(s);
2425 
2426  double goodnessOfFit = m_leftMeasure->GetLogData(
2428  if (goodnessOfFit == Null) {
2429  s = "Goodness of Fit: Null";
2430  }
2431  else {
2432  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2433  }
2434  m_leftGoodness->setText(s);
2435 
2436  }
2437 
2438 
2439 
2459 
2460  // Set editLock measure box correctly
2461  m_lockRightMeasure->setChecked(IsMeasureLocked(
2462  m_rightMeasure->GetCubeSerialNumber()));
2463  // Set ignore measure box correctly
2464  m_ignoreRightMeasure->setChecked(m_rightMeasure->IsIgnored());
2465 
2466  QString s = "Reference: ";
2467  if (m_editPoint->IsReferenceExplicit() &&
2468  (QString(m_rightMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2469  s += "True";
2470  }
2471  else {
2472  s += "False";
2473  }
2474 
2475  m_rightReference->setText(s);
2476 
2477  s = "Measure Type: ";
2478  if (m_rightMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2479  if (m_rightMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2480  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2481  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2482  m_rightMeasureType->setText(s);
2483 
2484  if (m_rightMeasure->GetSampleShift() == Null) {
2485  s = "Sample Shift: Null";
2486  }
2487  else {
2488  s = "Sample Shift: " + QString::number(m_rightMeasure->GetSampleShift());
2489  }
2490  m_rightSampShift->setText(s);
2491 
2492  if (m_rightMeasure->GetLineShift() == Null) {
2493  s = "Line Shift: Null";
2494  }
2495  else {
2496  s = "Line Shift: " + QString::number(m_rightMeasure->GetLineShift());
2497  }
2498  m_rightLineShift->setText(s);
2499 
2500  double goodnessOfFit = m_rightMeasure->GetLogData(
2502  if (goodnessOfFit == Null) {
2503  s = "Goodness of Fit: Null";
2504  }
2505  else {
2506  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2507  }
2508  m_rightGoodness->setText(s);
2509 
2510  }
2511 
2512 
2513 
2524  bool MatchTool::eventFilter(QObject *o, QEvent *e) {
2525  if(e->type() != QEvent::Leave) return false;
2526  if(o == m_leftCombo->view()) {
2528  m_leftCombo->hidePopup();
2529  }
2530  if (o == m_rightCombo->view()) {
2532  m_rightCombo->hidePopup();
2533  }
2534  return true;
2535  }
2536 
2537 
2545  void MatchTool::paintViewport(MdiCubeViewport *mvp, QPainter *painter) {
2546  drawAllMeasurments (mvp,painter);
2547 
2548  }
2549 
2550 
2565 
2566  // Take care of drawing things on all viewPorts.
2567  // Calling update will cause the Tool class to call all registered tools
2568  // if point has been deleted, this will remove it from the main window
2569  MdiCubeViewport *mvp;
2570  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
2571  mvp = (*(cubeViewportList()))[i];
2572  mvp->viewport()->update();
2573  }
2574  }
2575 
2598  void MatchTool::drawAllMeasurments(MdiCubeViewport *mvp, QPainter *painter) {
2599 
2600  // Make sure we have points to draw
2601  if ( (m_controlNet == NULL || m_controlNet->GetNumPoints() == 0) && m_newPoint == NULL &&
2602  m_editPoint == NULL)
2603  return;
2604 
2605  QString sn = serialNumber(mvp);
2606 // QString serialNumber = SerialNumber::Compose(*vp->cube(), true);
2607 
2608  // In the middle of creating a new point
2609  if (m_newPoint != NULL) {
2610  // and the selected point is in the image,
2611  if (m_newPoint->HasSerialNumber(sn)) {
2612  // find the measurement
2613  double samp = (*m_newPoint)[sn]->GetSample();
2614  double line = (*m_newPoint)[sn]->GetLine();
2615  int x, y;
2616  mvp->cubeToViewport(samp, line, x, y);
2617  // set point marker red
2618  QBrush brush(Qt::red);
2619  // set point marker bold - line width 2
2620  QPen pen(brush, 2);
2621  // draw the selected point in each image last so it's on top of the rest of the points
2622  painter->setPen(pen);
2623  painter->drawLine(x - 5, y, x + 5, y);
2624  painter->drawLine(x, y - 5, x, y + 5);
2625  }
2626  }
2627 
2628  // If viewport serial number not found in control net, return
2629  if (!m_controlNet->GetCubeSerials().contains(
2630  sn)) return;
2631 
2632 // if (!m_controlNet->GetCubeSerials().contains(
2633 // QString::fromStdString(sn))) return;
2634 // if (!serialNumberList().HasSerialNumber(sn)) return;
2635 
2636  QList<ControlMeasure *> measures =
2637  m_controlNet->GetMeasuresInCube(sn);
2638  // loop through all measures contained in this cube
2639  for (int i = 0; i < measures.count(); i++) {
2640  ControlMeasure *m = measures[i];
2641  // Find the measurments on the viewport
2642  double samp = m->GetSample();
2643  double line = m->GetLine();
2644  int x, y;
2645  mvp->cubeToViewport(samp, line, x, y);
2646  // if the point is ignored,
2647  if (m->Parent()->IsIgnored()) {
2648  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2649  }
2650  // point is not ignored, but measure matching this image is ignored,
2651  else if (m->IsIgnored()) {
2652  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2653  }
2654  else {
2655  painter->setPen(Qt::green); // set all other point markers green
2656  }
2657  // draw points
2658  painter->drawLine(x - 5, y, x + 5, y);
2659  painter->drawLine(x, y - 5, x, y + 5);
2660  }
2661  // if MatchTool is open,
2662  if (m_editPoint != NULL && m_newPoint == NULL) {
2663  // and the selected point is in the image,
2664  if (m_editPoint->HasSerialNumber(sn)) {
2665  // find the measurement
2666  double samp = (*m_editPoint)[sn]->GetSample();
2667  double line = (*m_editPoint)[sn]->GetLine();
2668  int x, y;
2669  mvp->cubeToViewport(samp, line, x, y);
2670  // set point marker red
2671  QBrush brush(Qt::red);
2672  // set point marker bold - line width 2
2673  QPen pen(brush, 2);
2674  // draw the selected point in each image last so it's on top of the rest of the points
2675  painter->setPen(pen);
2676  painter->drawLine(x - 5, y, x + 5, y);
2677  painter->drawLine(x, y - 5, x, y + 5);
2678  }
2679  }
2680  }
2681 
2682 
2683 
2698 
2699  if (m_templateModified) {
2700  int r = QMessageBox::warning(m_matchTool, tr("OK to continue?"),
2701  tr("The currently opened registration template has been modified.\n"
2702  "Save changes?"),
2703  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
2704  QMessageBox::Yes);
2705 
2706  if (r == QMessageBox::Yes)
2708  else if (r == QMessageBox::Cancel)
2709  return false;
2710  }
2711 
2712  return true;
2713  }
2714 
2715 
2716 
2723 
2724  if (!okToContinue())
2725  return;
2726 
2727  QString filename = QFileDialog::getOpenFileName(m_matchTool,
2728  "Select a registration template", ".",
2729  "Registration template files (*.def *.pvl);;All files (*)");
2730 
2731  if (filename.isEmpty())
2732  return;
2733 
2734  if (m_pointEditor->setTemplateFile(filename)) {
2735  loadTemplateFile(filename);
2736  }
2737  }
2738 
2739 
2740 
2746  void MatchTool::loadTemplateFile(QString fn) {
2747 
2748  QFile file(FileName((QString) fn).expanded());
2749  if (!file.open(QIODevice::ReadOnly)) {
2750  QString msg = "Failed to open template file \"" + fn + "\"";
2751  QMessageBox::warning(m_matchTool, "IO Error", msg);
2752  return;
2753  }
2754 
2755  QTextStream stream(&file);
2756  m_templateEditor->setText(stream.readAll());
2757  file.close();
2758 
2759  QScrollBar * sb = m_templateEditor->verticalScrollBar();
2760  sb->setValue(sb->minimum());
2761 
2762  m_templateModified = false;
2763  m_saveTemplateFile->setEnabled(false);
2764  m_templateFileNameLabel->setText("Template File: " + fn);
2765  }
2766 
2767 
2768 
2771  m_templateModified = true;
2772  m_saveTemplateFile->setEnabled(true);
2773  }
2774 
2775 
2776 
2779 
2780  if (!m_templateModified)
2781  return;
2782 
2783  QString filename =
2784  m_pointEditor->templateFileName();
2785 
2786  writeTemplateFile(filename);
2787  }
2788 
2789 
2790 
2793 
2794  QString filename = QFileDialog::getSaveFileName(m_matchTool,
2795  "Save registration template", ".",
2796  "Registration template files (*.def *.pvl);;All files (*)");
2797 
2798  if (filename.isEmpty())
2799  return;
2800 
2801  writeTemplateFile(filename);
2802  }
2803 
2804 
2805 
2811  void MatchTool::writeTemplateFile(QString fn) {
2812 
2813  QString contents = m_templateEditor->toPlainText();
2814 
2815  // catch errors in Pvl format when populating pvl object
2816  stringstream ss;
2817  ss << contents;
2818  try {
2819  Pvl pvl;
2820  ss >> pvl;
2821  }
2822  catch(IException &e) {
2823  QString message = e.toString();
2824  QMessageBox::warning(m_matchTool, "Error", message);
2825  return;
2826  }
2827 
2828  QString expandedFileName(
2829  FileName((QString) fn).expanded());
2830 
2831  QFile file(expandedFileName);
2832 
2833  if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2834  QString msg = "Failed to save template file to \"" + fn + "\"\nDo you "
2835  "have permission?";
2836  QMessageBox::warning(m_matchTool, "IO Error", msg);
2837  return;
2838  }
2839 
2840  // now save contents
2841  QTextStream stream(&file);
2842  stream << contents;
2843  file.close();
2844 
2845  if (m_pointEditor->setTemplateFile(fn)) {
2846  m_templateModified = false;
2847  m_saveTemplateFile->setEnabled(false);
2848  m_templateFileNameLabel->setText("Template File: " + fn);
2849  }
2850  }
2851 
2852 
2853 
2868  try{
2869  // Get the template file from the ControlPointEditor object
2870  Pvl templatePvl(m_pointEditor->templateFileName());
2871  // Create registration dialog window using PvlEditDialog class
2872  // to view and/or edit the template
2873  PvlEditDialog registrationDialog(templatePvl);
2874  registrationDialog.setWindowTitle("View or Edit Template File: "
2875  + templatePvl.fileName());
2876  registrationDialog.resize(550,360);
2877  registrationDialog.exec();
2878  }
2879  catch (IException &e) {
2880  QString message = e.toString();
2881  QMessageBox::information(m_matchTool, "Error", message);
2882  }
2883  }
2884 
2885 
2886 
2894  m_pointEditor->saveChips();
2895  }
2896 
2897 
2898 
2899  void MatchTool::showHideTemplateEditor() {
2900 
2901  if (!m_templateEditorWidget)
2902  return;
2903 
2904  m_templateEditorWidget->setVisible(!m_templateEditorWidget->isVisible());
2905  }
2906 
2907 
2908 
2921  void MatchTool::updatePointInfo(QString pointId) {
2922  if (m_editPoint == NULL) return;
2923  if (pointId != m_editPoint->GetId()) return;
2924  // The edit point has been changed by SetApriori, so m_editPoint needs
2925  // to possibly update some values. Need to retain measures from m_editPoint
2926  // because they might have been updated, but not yet saved to the network
2927  // ("Save Point").
2928  ControlPoint *updatedPoint = m_controlNet->GetPoint(pointId);
2929  m_editPoint->SetEditLock(updatedPoint->IsEditLocked());
2930  m_editPoint->SetIgnored(updatedPoint->IsIgnored());
2931 
2932  // Set EditLock box correctly
2933  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
2934 
2935  // Set ignore box correctly
2936  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
2937 
2938  }
2939 
2940 
2941 
2958 
2959  // Check point being edited, make sure it still exists, if not ???
2960  // Update ignored checkbox??
2961  if (m_editPoint != NULL) {
2962  try {
2963  QString id = m_ptIdValue->text().remove("Point ID: ");
2964  m_controlNet->GetPoint(id);
2965  }
2966  catch (IException &) {
2967  delete m_editPoint;
2968  m_editPoint = NULL;
2969  emit editPointChanged();
2970 // m_matchTool->setShown(false);
2971 // m_measureWindow->setShown(false);
2972  }
2973  }
2974 
2976  }
2977 
2978 
2979 
2986 
2987  QColor qc = Qt::red;
2988  QPalette p = m_savePoint->palette();
2989  p.setColor(QPalette::ButtonText,qc);
2990  m_savePoint->setPalette(p);
2991 
2992  }
2993 
2994 
2995 
3008  bool MatchTool::IsMeasureLocked (QString serialNumber) {
3009 
3010  if (m_editPoint == NULL) return false;
3011 
3012  // Reference implicitly editLocked
3013  if (m_editPoint->IsEditLocked() && m_editPoint->IsReferenceExplicit() &&
3014  (m_editPoint->GetReferenceSN() == serialNumber)) {
3015  return true;
3016  }
3017  // Return measures explicit editLocked value
3018  else {
3019  return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
3020  }
3021 
3022  }
3023 
3024 
3025 
3032  FileName config("$HOME/.Isis/qview/MatchTool.config");
3033  QSettings settings(config.expanded(),
3034  QSettings::NativeFormat);
3035  QPoint pos = settings.value("pos", QPoint(300, 100)).toPoint();
3036  QSize size = settings.value("size", QSize(900, 500)).toSize();
3037  m_matchTool->resize(size);
3038  m_matchTool->move(pos);
3039  }
3040 
3041 
3049  /*We do not want to write the settings unless the window is
3050  visible at the time of closing the application*/
3051  if (!m_matchTool->isVisible()) return;
3052  FileName config("$HOME/.Isis/qview/MatchTool.config");
3053  QSettings settings(config.expanded(),
3054  QSettings::NativeFormat);
3055  settings.setValue("pos", m_matchTool->pos());
3056  settings.setValue("size", m_matchTool->size());
3057  }
3058 
3059 
3060 
3061  void MatchTool::enterWhatsThisMode() {
3062  QWhatsThis::enterWhatsThisMode();
3063  }
3064 
3065 
3066  void MatchTool::clearEditPoint() {
3067  m_editPoint = NULL;
3068  }
3069 
3070 
3071 
3072  void MatchTool::showHelp() {
3073 
3074  QDialog *helpDialog = new QDialog(m_matchTool);
3075  helpDialog->setWindowTitle("Match Tool Help");
3076 
3077  QVBoxLayout *mainLayout = new QVBoxLayout;
3078  helpDialog->setLayout(mainLayout);
3079 
3080  QLabel *matchTitle = new QLabel("<h2>Match Tool</h2>");
3081  mainLayout->addWidget(matchTitle);
3082 
3083  QLabel *matchSubtitle = new QLabel("A tool for interactively measuring and editing sample/line "
3084  "registration points between cubes. These "
3085  "points contain sample, line postions only, no latitude or "
3086  "longitude values are used or recorded.");
3087  matchSubtitle->setWordWrap(true);
3088  mainLayout->addWidget(matchSubtitle);
3089 
3090  QTabWidget *tabArea = new QTabWidget;
3091  tabArea->setDocumentMode(true);
3092  mainLayout->addWidget(tabArea);
3093 
3094  // TAB 1 - Overview
3095  QScrollArea *overviewTab = new QScrollArea;
3096  overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3097  overviewTab->setWidgetResizable(true);
3098  QWidget *overviewContainer = new QWidget;
3099  QVBoxLayout *overviewLayout = new QVBoxLayout;
3100  overviewContainer->setLayout(overviewLayout);
3101 
3102  QLabel *purposeTitle = new QLabel("<h2>Purpose</h2>");
3103  overviewLayout->addWidget(purposeTitle);
3104 
3105  QLabel *purposeText = new QLabel("<p>This tool is for recording and editing registration "
3106  "points measured between cubes displayed in the <i>qview</i> main window.</p> <p>The "
3107  "recorded registration points are sample and line pixel coordinates only. Therefore, this "
3108  "tool can be used on any images including ones that do not contain a camera model "
3109  "(i.e, The existence of the Isis Instrument Group on the image labels is not required). "
3110  "This also means that the tool differs from the <i>qnet</i> control point network "
3111  "application in that no latitude or longitude values are ever used or recorded "
3112  "(regardless if the image has a camera model in Isis).</p>"
3113  "<p>The output control point network that this tool generates is primarily used 1) as "
3114  "input for an image-wide sample/line translation to register one image to another by "
3115  "'moving' pixel locations - refer to the documentation for applications such as "
3116  "<i>translate</i> and <i>warp</i>, or 2) to export the file and use the recorded "
3117  "measurements in other spreadsheet or plotting packages to visualize magnitude "
3118  "and direction of varying translations of the images relative to one another.</p> "
3119  "<p>An automated version of this match tool is the <i>coreg</i> application. This tool "
3120  "can be used to visually evaluate and edit the control point network created by "
3121  "<i>coreg</i>.</p> "
3122  "<p>The format of the output point network file is binary. This tool uses the Isis control "
3123  " network framework to create, co-register and save all control points and pixel "
3124  "measurements. The application <i>cnetbin2pvl</i> can be used to convert from binary to "
3125  "a readable PVL format."
3126  "<p>The Mouse Button functions are: (same as <i>qnet</i>)<ul><li>Modify Point=Left</li> "
3127  "<li>Delete Point=Middle</li><li>Create New Point=Right</li></ul></p>"
3128  "<p>Control Points are drawn on the associated displayed cubes with the following colors: "
3129  "Green=Valid registration point; Yellow=Ignored point; Red=Active point being edited");
3130  purposeText->setWordWrap(true);
3131  overviewLayout->addWidget(purposeText);
3132 
3133  overviewTab->setWidget(overviewContainer);
3134 
3135  // TAB 2 - Quick Start
3136  QScrollArea *quickTab = new QScrollArea;
3137  quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3138  quickTab->setWidgetResizable(true);
3139  QWidget *quickContainer = new QWidget;
3140  QVBoxLayout *quickLayout = new QVBoxLayout;
3141  quickContainer->setLayout(quickLayout);
3142 
3143  QLabel *quickTitle = new QLabel("<h2>Quick Start</h2>");
3144  quickLayout->addWidget(quickTitle);
3145 
3146  QLabel *quickSubTitle = new QLabel("<h3>Preparation:</h3>");
3147  quickLayout->addWidget(quickSubTitle);
3148 
3149  QLabel *quickPrep = new QLabel("<p><ul>"
3150  "<li>Open the cubes with overlapping areas for choosing control points</li>"
3151  "<li>Choose the match tool <img src=\"" + toolIconDir() +
3152  "/stock_draw-connector-with-arrows.png\" width=22 height=22> "
3153  "from the toolpad on the right side of the <i>qview</i> main window</li>");
3154  quickPrep->setWordWrap(true);
3155  quickLayout->addWidget(quickPrep);
3156 
3157  QLabel *morePrep = new QLabel("<p>Once the Match tool is activated the tool bar at the top "
3158  "of the main window contains file action buttons and a help button:");
3159  morePrep->setWordWrap(true);
3160  quickLayout->addWidget(morePrep);
3161 
3162  QLabel *fileButtons = new QLabel("<p><ul>"
3163  "<li><img src=\"" + toolIconDir() + "/fileopen.png\" width=22 height=22> Open an existing "
3164  "control network <b>Note:</b> If you do not open an existing network, a new one will "
3165  "be created</li>"
3166  "<li><img src=\"" + toolIconDir() + "/mActionFileSaveAs.png\" width=22 height=22> Save "
3167  "control network as ...</li>"
3168  "<li><img src=\"" + toolIconDir() + "/mActionFileSave.png\" width=22 height=22> Save "
3169  "control network to current file</li>"
3170  "<li><img src=\"" + toolIconDir() + "/help-contents.png\" width=22 height=22> Show Help "
3171  "</li></ul></p>");
3172  fileButtons->setWordWrap(true);
3173  quickLayout->addWidget(fileButtons);
3174 
3175  QLabel *quickFunctionTitle = new QLabel("<h3>Cube Viewport Functions:</h3>");
3176  quickLayout->addWidget(quickFunctionTitle);
3177 
3178  QLabel *quickFunction = new QLabel(
3179  "The match tool window will be shown once "
3180  "you click in a cube viewport window using one of the following "
3181  "mouse functions. <b>Note:</b> Existing control points are drawn on the cube viewports");
3182  quickFunction->setWordWrap(true);
3183  quickLayout->addWidget(quickFunction);
3184 
3185  QLabel *quickDesc = new QLabel("<p><ul>"
3186  "<li>Left Click - Modify the control point closest to the click <b>Note:</b> "
3187  "All cubes in the control point must be displayed before loading the point</li>"
3188  "<li>Middle Click - Delete the control point closest to the click</li>"
3189  "<li>Right Click - Create a new control point at the click location</li></ul></p>");
3190  quickDesc->setWordWrap(true);
3191  quickDesc->setOpenExternalLinks(true);
3192  quickLayout->addWidget(quickDesc);
3193 
3194  quickTab->setWidget(quickContainer);
3195 
3196  // TAB 3 - Control Point Editing
3197  QScrollArea *controlPointTab = new QScrollArea;
3198  controlPointTab->setWidgetResizable(true);
3199  controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3200  QWidget *controlPointContainer = new QWidget;
3201  QVBoxLayout *controlPointLayout = new QVBoxLayout;
3202  controlPointContainer->setLayout(controlPointLayout);
3203 
3204  QLabel *controlPointTitle = new QLabel("<h2>Control Point Editing</h2>");
3205  controlPointLayout->addWidget(controlPointTitle);
3206 
3207  QLabel *mouseLabel = new QLabel("<p><h3>When the \"Match\" tool "
3208  "is activated, the mouse buttons have the following function in the "
3209  "cube viewports of the main qview window:</h3>");
3210  mouseLabel->setWordWrap(true);
3211  mouseLabel->setScaledContents(true);
3212  controlPointLayout->addWidget(mouseLabel);
3213 
3214  QLabel *controlPointDesc = new QLabel("<ul>"
3215  "<li>Left click - Edit the closest control point <b>Note:</b> "
3216  "All cubes in the control point must be displayed before loading the point</li>"
3217  "<li>Middle click - Delete the closest control point</li>"
3218  "<li>Right click - Create new control point at cursor location. This will bring up a new "
3219  "point dialog which allows you to enter a point id and will list all cube viewports, "
3220  "highlighting cubes where the point has been chosen by clicking on the cube's viewport. "
3221  "When the desired cubes have been chosen, select the \"Done\" button which will load the "
3222  "control point into the control point editor window which will allow the control measure "
3223  "positions to be refined.</li>");
3224  controlPointDesc->setWordWrap(true);
3225  controlPointLayout->addWidget(controlPointDesc);
3226 
3227  QLabel *controlPointEditing = new QLabel(
3228  "<h4>Changing Control Measure Locations</h4>"
3229  "<p>Both the left and right control measure positions can be adjusted by:"
3230  "<ul>"
3231  "<li>Move the cursor location under the crosshair by clicking the left mouse "
3232  "button</li>"
3233  "<li>Move 1 pixel at a time by using arrow keys on the keyboard</li>"
3234  "<li>Move 1 pixel at a time by using arrow buttons above the right and left views</li>"
3235  "</ul></p>"
3236  "<h4>Other Point Editor Functions</h4>"
3237  "<p>Along the right border of the window:</p>"
3238  "<ul>"
3239  "<li><strong>Link Zoom</strong> This will link the two small viewports together when "
3240  "zooming (ie. If this is checked, if the left view is zoomed, the right view will "
3241  "match the left view's zoom factor. "
3242  "<b>Note:</b> Zooming is controlled from the left view.</li>"
3243  "<li><strong>No Rotate:</strong> Turn off the rotation and bring right view back to "
3244  "its original orientation</li>"
3245  "<li><strong>Rotate:</strong> Rotate the right view using either the dial "
3246  "or entering degrees </li>"
3247  "<li><strong>Show control points:</strong> Draw crosshairs at all control "
3248  "point locations visible within the view</li>"
3249  "<li><strong>Show crosshair:</strong> Show a red crosshair across the entire "
3250  "view</li>"
3251  "<li><strong>Circle:</strong> Draw circle which may help center measure "
3252  "on a crater</li></ul"
3253  "<p>Below the left view:</p>"
3254  "<ul><li><strong>Blink controls:</strong> Blink the left and right view in the "
3255  "left view window using the \"Blink Start\" button <img src=\"" + toolIconDir() +
3256  "/blinkStart.png\" width=22 height=22> and \"Blink Stop\" button <img src=\"" +
3257  toolIconDir() + "/blinkStop.png\" width=22 height=22>. The arrow keys above the left "
3258  "and right views and the keyboard arrow keys may be used to move the both views while "
3259  "blinking.</li>"
3260  "<li><strong>Register:</strong> Sub-pixel register the right view to "
3261  "the left view. A default registration template is used for setting parameters "
3262  "passed to the sub-pixel registration tool. The user may load in a predefined "
3263  "template or edit the current loaded template to influence successful "
3264  "co-registration results. For more information regarding the pattern matching "
3265  "functionlity or how to create a parameter template, refer to the Isis PatternMatch "
3266  "document and the <i>autoregtemplate</i> application. <strong>Shortcut: R.</strong>"
3267  "</li>"
3268  "<li><strong>Save Measures:</strong> Save the two control measures using the sample, "
3269  "line positions under the crosshairs. <strong>Shortcut: M.</strong></li>"
3270  "<li><strong>Save Point:</strong> Save the control point to the control network. "
3271  "<strong>Shortcut: P.</strong></li>"
3272  "</ul>");
3273  controlPointEditing->setWordWrap(true);
3274  controlPointLayout->addWidget(controlPointEditing);
3275 
3276  controlPointTab->setWidget(controlPointContainer);
3277 
3278  // TAB 4 - Coreg Guidance
3279  QScrollArea *coregTab = new QScrollArea;
3280  coregTab->setWidgetResizable(true);
3281  coregTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3282  QWidget *coregContainer = new QWidget;
3283  QVBoxLayout *coregLayout = new QVBoxLayout;
3284  coregContainer->setLayout(coregLayout);
3285 
3286  QLabel *coregTitle = new QLabel("<h2>Coreg Guidance</h2>");
3287  coregLayout->addWidget(coregTitle);
3288 
3289  QLabel *coregDesc = new QLabel("<p>When opening control networks created by <i>coreg</i>, "
3290  "there are some things to keep in mind. First, all control points must have the same "
3291  "reference measure (this is the image filename passed to the <i>coreg</i> 'match' parameter)."
3292  "<p>In order to retain the integrity of the input <i>coreg</i> network, you cannot change "
3293  "which image is the reference measure on any of the existing points. "
3294  "<p>When creating a new control point to add to the <i>coreg</i> network, this tool will "
3295  "automatically set the reference measure to the same image as the other control points in "
3296  "the network as long as the reference image was one of the images selected with "
3297  "the right mouse button from the new point dialog. If this image was not selected when "
3298  "creating a new point, it "
3299  "does not contain a required measurement, therefore, you will get an error and the new "
3300  "point will not be created.</p> <p>The reference measure is always loaded on the left side "
3301  "of the control point editor. If you load a measure that is not the reference measure "
3302  "on the left side and try to save the point, you will receive an error message. You will "
3303  "need to move the reference measure back to the left side before saving the control point."
3304  "</p><p><b>Note:</b> This error checking will not happen on control networks created by "
3305  "<i>coreg</i> prior to Isis3.4.2. For older <i>coreg</i> control networks the user must be "
3306  "aware and make sure the correct image is set to the same <i>coreg</i> reference measure.");
3307  coregDesc->setWordWrap(true);
3308  coregDesc->setScaledContents(true);
3309  coregLayout->addWidget(coregDesc);
3310 
3311  coregTab->setWidget(coregContainer);
3312 
3313  tabArea->addTab(overviewTab, "&Overview");
3314  tabArea->addTab(quickTab, "&Quick Start");
3315  tabArea->addTab(controlPointTab, "&Control Point Editing");
3316  tabArea->addTab(coregTab, "&Coreg Guidance");
3317 
3318  QHBoxLayout *buttonsLayout = new QHBoxLayout;
3319  // Flush the buttons to the right
3320  buttonsLayout->addStretch();
3321 
3322  QPushButton *closeButton = new QPushButton("&Close");
3323  closeButton->setIcon(QPixmap(toolIconDir() + "/guiStop.png"));
3324  closeButton->setDefault(true);
3325  connect(closeButton, SIGNAL(clicked()),
3326  helpDialog, SLOT(close()));
3327  buttonsLayout->addWidget(closeButton);
3328 
3329  mainLayout->addLayout(buttonsLayout);
3330 
3331  helpDialog->show();
3332 
3333 
3334  }
3335 
3336 
3337 
3345 
3346  if (m_editPoint) {
3347  // If point changed or if a new point, prompt for saving.
3348  if ( m_controlNet->GetNumPoints() == 0 ||
3349  !m_controlNet->ContainsPoint(m_editPoint->GetId())) {
3350  QString message = "\n\nDo you want to save the point in the editor?";
3351  int response = QMessageBox::question(m_matchTool, "Save point in editor", message,
3352  QMessageBox::Yes | QMessageBox::No,
3353  QMessageBox::Yes);
3354  if (response == QMessageBox::Yes) {
3355  savePoint();
3356  }
3357  }
3358  }
3359 
3360  if (m_controlNet && m_controlNet->GetNumPoints() != 0 && m_netChanged) {
3361  QString message = "The currently open control net has changed. Do you want to save?";
3362  int response = QMessageBox::question(m_matchTool, "Save current control net?",
3363  message,
3364  QMessageBox::Yes | QMessageBox::No,
3365  QMessageBox::Yes);
3366  // Yes: Save old net, so return without opening network.
3367  if (response == QMessageBox::Yes) {
3368  saveAsNet();
3369  }
3370  }
3371  }
3372 }
3373