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 
156 
157  m_matchTool = new QMainWindow(parent);
158  m_matchTool->setWindowTitle("Match Tool");
159  m_matchTool->setObjectName("MatchTool");
160  connect(m_matchTool, SIGNAL(destroyed(QObject *)), this, SLOT(clearEditPoint()));
161 
162  createActions();
163  createMenus();
164  createToolBars();
165 
166  // create m_pointEditor first since we need to get its templateFileName
167  // later
168  m_pointEditor = new ControlPointEdit(m_controlNet, parent, true, false);
169  connect(this, SIGNAL(newControlNetwork(ControlNet *)),
170  m_pointEditor, SIGNAL(newControlNetwork(ControlNet *)));
171  connect(this, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)),
172  m_pointEditor, SIGNAL(stretchChipViewport(Stretch *, CubeViewport *)));
173  connect(m_pointEditor, SIGNAL(measureSaved()), this, SLOT(measureSaved()));
174  connect(this, SIGNAL(measureChanged()),
175  m_pointEditor, SLOT(colorizeSaveButton()));
176 
177  m_savePoint = new QPushButton ("Save Point");
178  m_savePoint->setToolTip("Save the edit control point to the control "
179  "network.");
180  m_savePoint->setWhatsThis("Save the edit control point to the control "
181  "network which is loaded into memory in its entirety. "
182  "When a control point is selected for editing, "
183  "a copy of the point is made so that the original control "
184  "point remains in the network.");
185  m_saveDefaultPalette = m_savePoint->palette();
186  connect (m_savePoint,SIGNAL(clicked()),this,SLOT(savePoint()));
187 
188  QHBoxLayout * addMeasureLayout = new QHBoxLayout;
189  addMeasureLayout->addStretch();
190  addMeasureLayout->addWidget(m_savePoint);
191 // addMeasureLayout->addStretch();
192 
193  m_cnetFileNameLabel = new QLabel("Control Network: " + m_cnetFileName);
194  m_cnetFileNameLabel->setToolTip("Name of opened control network file.");
195  m_cnetFileNameLabel->setWhatsThis("Name of opened control network file.");
196 
197  m_templateFileNameLabel = new QLabel("Template File: " +
198  m_pointEditor->templateFileName());
199  m_templateFileNameLabel->setToolTip("Sub-pixel registration template File.");
200 // QString patternMatchDoc =
201 // FileName("$ISISROOT/doc/documents/PatternMatch/PatternMatch.html").fileName();
202 // m_templateFileNameLabel->setOpenExternalLinks(true);
203  m_templateFileNameLabel->setWhatsThis("FileName of the sub-pixel "
204  "registration template. Refer to $ISISROOT/doc/documents/"
205  "PatternMatch/PatternMatch.html for a description of the "
206  "contents of this file.");
207 
208  QVBoxLayout * centralLayout = new QVBoxLayout;
209 
210  centralLayout->addWidget(m_cnetFileNameLabel);
211  centralLayout->addWidget(m_templateFileNameLabel);
212  centralLayout->addWidget(createTopSplitter());
213  centralLayout->addStretch();
214  centralLayout->addWidget(m_pointEditor);
215  centralLayout->addLayout(addMeasureLayout);
216  QWidget * centralWidget = new QWidget;
217  centralWidget->setLayout(centralLayout);
218 
219  QScrollArea *scrollArea = new QScrollArea();
220  scrollArea->setObjectName("MatchToolScroll");
221  scrollArea->setWidget(centralWidget);
222  scrollArea->setWidgetResizable(true);
223  centralWidget->adjustSize();
224  m_matchTool->setCentralWidget(scrollArea);
225 // m_matchTool->setCentralWidget(centralWidget);
226 
227 
228  connect(this, SIGNAL(editPointChanged()),
229  this, SLOT(paintAllViewports()));
230 
231  readSettings();
232  }
233 
234 
237 
238  QHBoxLayout * measureLayout = new QHBoxLayout;
239  measureLayout->addWidget(createLeftMeasureGroupBox());
240  measureLayout->addWidget(createRightMeasureGroupBox());
241 
242  QVBoxLayout * groupBoxesLayout = new QVBoxLayout;
243  groupBoxesLayout->addWidget(createControlPointGroupBox());
244  groupBoxesLayout->addStretch();
245  groupBoxesLayout->addLayout(measureLayout);
246 
247  QWidget * groupBoxesWidget = new QWidget;
248  groupBoxesWidget->setLayout(groupBoxesLayout);
249 
251 
252  QSplitter * topSplitter = new QSplitter;
253  topSplitter->addWidget(groupBoxesWidget);
254  topSplitter->addWidget(m_templateEditorWidget);
255  topSplitter->setStretchFactor(0, 4);
256  topSplitter->setStretchFactor(1, 3);
257 
258  m_templateEditorWidget->hide();
259 
260  return topSplitter;
261  }
262 
263 
266 
267  // create left vertical layout
268  m_ptIdValue = new QLabel;
269  m_numMeasures = new QLabel;
270  QVBoxLayout * leftLayout = new QVBoxLayout;
271  leftLayout->addWidget(m_ptIdValue);
272  leftLayout->addWidget(m_numMeasures);
273 
274  // create right vertical layout's top layout
275  m_lockPoint = new QCheckBox("Edit Lock Point");
276  connect(m_lockPoint, SIGNAL(clicked(bool)), this, SLOT(setLockPoint(bool)));
277  m_ignorePoint = new QCheckBox("Ignore Point");
278  connect(m_ignorePoint, SIGNAL(clicked(bool)),
279  this, SLOT(setIgnorePoint(bool)));
280  connect(this, SIGNAL(ignorePointChanged()), m_ignorePoint, SLOT(toggle()));
281 
282  QVBoxLayout * rightLayout = new QVBoxLayout;
283  rightLayout->addWidget(m_lockPoint);
284  rightLayout->addWidget(m_ignorePoint);
285 
286  QHBoxLayout * mainLayout = new QHBoxLayout;
287  mainLayout->addLayout(leftLayout);
288  mainLayout->addStretch();
289  mainLayout->addLayout(rightLayout);
290 
291  // create the groupbox
292  QGroupBox * groupBox = new QGroupBox("Control Point");
293  groupBox->setLayout(mainLayout);
294 
295  return groupBox;
296  }
297 
298 
301 
302  m_leftCombo = new QComboBox;
303  m_leftCombo->view()->installEventFilter(this);
304  m_leftCombo->setToolTip("Choose left control measure");
305  m_leftCombo->setWhatsThis("Choose left control measure identified by "
306  "cube filename.");
307  connect(m_leftCombo, SIGNAL(activated(int)),
308  this, SLOT(selectLeftMeasure(int)));
309  m_lockLeftMeasure = new QCheckBox("Edit Lock Measure");
310  connect(m_lockLeftMeasure, SIGNAL(clicked(bool)),
311  this, SLOT(setLockLeftMeasure(bool)));
312  m_ignoreLeftMeasure = new QCheckBox("Ignore Measure");
313  connect(m_ignoreLeftMeasure, SIGNAL(clicked(bool)),
314  this, SLOT(setIgnoreLeftMeasure(bool)));
315  connect(this, SIGNAL(ignoreLeftChanged()),
316  m_ignoreLeftMeasure, SLOT(toggle()));
317  m_leftReference = new QLabel();
318  m_leftMeasureType = new QLabel();
319  m_leftSampShift = new QLabel();
320  m_leftSampShift->setToolTip("Sample shift between apriori and current");
321  m_leftSampShift->setWhatsThis("The shift between the apriori sample and "
322  "the current sample. The apriori sample is set "
323  "when creating a new measure.");
324  m_leftLineShift = new QLabel();
325  m_leftLineShift->setToolTip("Line shift between apriori and current");
326  m_leftLineShift->setWhatsThis("The shift between the apriori line and "
327  "the current line. The apriori line is set "
328  "when creating a new measure.");
329  m_leftGoodness = new QLabel();
330  m_leftGoodness->setToolTip("Goodness of Fit result from sub-pixel "
331  "registration.");
332  m_leftGoodness->setWhatsThis("Resulting Goodness of Fit from sub-pixel "
333  "registration.");
334  QVBoxLayout * leftLayout = new QVBoxLayout;
335  leftLayout->addWidget(m_leftCombo);
336  leftLayout->addWidget(m_lockLeftMeasure);
337  leftLayout->addWidget(m_ignoreLeftMeasure);
338  leftLayout->addWidget(m_leftReference);
339  leftLayout->addWidget(m_leftMeasureType);
340  leftLayout->addWidget(m_leftSampShift);
341  leftLayout->addWidget(m_leftLineShift);
342  leftLayout->addWidget(m_leftGoodness);
343 
344  QGroupBox * leftGroupBox = new QGroupBox("Left Measure");
345  leftGroupBox->setLayout(leftLayout);
346 
347  return leftGroupBox;
348  }
349 
350 
353 
354  // create widgets for the right groupbox
355  m_rightCombo = new QComboBox;
356  m_rightCombo->view()->installEventFilter(this);
357  m_rightCombo->setToolTip("Choose right control measure");
358  m_rightCombo->setWhatsThis("Choose right control measure identified by "
359  "cube filename.");
360  connect(m_rightCombo, SIGNAL(activated(int)),
361  this, SLOT(selectRightMeasure(int)));
362  m_lockRightMeasure = new QCheckBox("Edit Lock Measure");
363  connect(m_lockRightMeasure, SIGNAL(clicked(bool)),
364  this, SLOT(setLockRightMeasure(bool)));
365  m_ignoreRightMeasure = new QCheckBox("Ignore Measure");
366  connect(m_ignoreRightMeasure, SIGNAL(clicked(bool)),
367  this, SLOT(setIgnoreRightMeasure(bool)));
368  connect(this, SIGNAL(ignoreRightChanged()),
369  m_ignoreRightMeasure, SLOT(toggle()));
370  m_rightReference = new QLabel();
371  m_rightMeasureType = new QLabel();
372  m_rightSampShift = new QLabel();
373  m_rightSampShift->setToolTip(m_leftSampShift->toolTip());
374  m_rightSampShift->setWhatsThis(m_leftSampShift->whatsThis());
375  m_rightLineShift = new QLabel();
376  m_rightLineShift->setToolTip(m_leftLineShift->toolTip());
377  m_rightLineShift->setWhatsThis(m_leftLineShift->whatsThis());
378  m_rightGoodness = new QLabel();
379  m_rightGoodness->setToolTip(m_leftGoodness->toolTip());
380  m_rightGoodness->setWhatsThis(m_leftGoodness->whatsThis());
381 
382  // create right groupbox
383  QVBoxLayout * rightLayout = new QVBoxLayout;
384  rightLayout->addWidget(m_rightCombo);
385  rightLayout->addWidget(m_lockRightMeasure);
386  rightLayout->addWidget(m_ignoreRightMeasure);
387  rightLayout->addWidget(m_rightReference);
388  rightLayout->addWidget(m_rightMeasureType);
389  rightLayout->addWidget(m_rightSampShift);
390  rightLayout->addWidget(m_rightLineShift);
391  rightLayout->addWidget(m_rightGoodness);
392 
393  QGroupBox * rightGroupBox = new QGroupBox("Right Measure");
394  rightGroupBox->setLayout(rightLayout);
395 
396  return rightGroupBox;
397  }
398 
399 
402 
403  QToolBar *toolBar = new QToolBar("Template Editor ToolBar");
404 
405  toolBar->addAction(m_openTemplateFile);
406  toolBar->addSeparator();
407  toolBar->addAction(m_saveTemplateFile);
408  toolBar->addAction(m_saveTemplateFileAs);
409 
410  m_templateEditor = new QTextEdit;
411  connect(m_templateEditor, SIGNAL(textChanged()), this,
412  SLOT(setTemplateModified()));
413 
414  QVBoxLayout *mainLayout = new QVBoxLayout;
415  mainLayout->addWidget(toolBar);
416  mainLayout->addWidget(m_templateEditor);
417 
418  m_templateEditorWidget = new QWidget;
419  m_templateEditorWidget->setLayout(mainLayout);
420  }
421 
422 
423 
424  void MatchTool::createActions() {
425 
426  m_saveNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSave.png"),
427  "Save Control Network ...",
428  m_matchTool);
429  m_saveNet->setToolTip("Save current control network");
430  m_saveNet->setStatusTip("Save current control network");
431  QString whatsThis = "<b>Function:</b> Saves the current <i>"
432  "control network</i>";
433  m_saveNet->setWhatsThis(whatsThis);
434  connect(m_saveNet, SIGNAL(activated()), this, SLOT(saveNet()));
435 
436  m_saveAsNet = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"),
437  "Save Control Network &As...",
438  m_matchTool);
439  m_saveAsNet->setToolTip("Save current control network to chosen file");
440  m_saveAsNet->setStatusTip("Save current control network to chosen file");
441  whatsThis = "<b>Function:</b> Saves the current <i>"
442  "control network</i> under chosen filename";
443  m_saveAsNet->setWhatsThis(whatsThis);
444  connect(m_saveAsNet, SIGNAL(activated()), this, SLOT(saveAsNet()));
445 
446  m_closeMatchTool = new QAction(QPixmap(toolIconDir() + "/fileclose.png"),
447  "&Close",
448  m_matchTool);
449  m_closeMatchTool->setToolTip("Close this window");
450  m_closeMatchTool->setStatusTip("Close this window");
451  m_closeMatchTool->setShortcut(Qt::ALT + Qt::Key_F4);
452  whatsThis = "<b>Function:</b> Closes the Match Tool window for this point "
453  "<p><b>Shortcut:</b> Alt+F4 </p>";
454  m_closeMatchTool->setWhatsThis(whatsThis);
455  connect(m_closeMatchTool, SIGNAL(activated()), m_matchTool, SLOT(close()));
456 
457  m_showHideTemplateEditor = new QAction(QPixmap(toolIconDir() + "/view_text.png"),
458  "&View/edit registration template",
459  m_matchTool);
460  m_showHideTemplateEditor->setCheckable(true);
461  m_showHideTemplateEditor->setToolTip("View and/or edit the registration template");
462  m_showHideTemplateEditor->setStatusTip("View and/or edit the registration template");
463  whatsThis = "<b>Function:</b> Displays the curent registration template. "
464  "The user may edit and save changes under a chosen filename.";
465  m_showHideTemplateEditor->setWhatsThis(whatsThis);
466  connect(m_showHideTemplateEditor, SIGNAL(activated()), this,
467  SLOT(showHideTemplateEditor()));
468 
469  m_saveChips = new QAction(QPixmap(toolIconDir() + "/window_new.png"),
470  "Save registration chips",
471  m_matchTool);
472  m_saveChips->setToolTip("Save registration chips");
473  m_saveChips->setStatusTip("Save registration chips");
474  whatsThis = "<b>Function:</b> Save registration chips to file. "
475  "Each chip: pattern, search, fit will be saved to a separate file.";
476  m_saveChips->setWhatsThis(whatsThis);
477  connect(m_saveChips, SIGNAL(activated()), this, SLOT(saveChips()));
478 
479  m_openTemplateFile = new QAction(QPixmap(toolIconDir() + "/fileopen.png"),
480  "&Open registration template",
481  m_matchTool);
482  m_openTemplateFile->setToolTip("Set registration template");
483  m_openTemplateFile->setStatusTip("Set registration template");
484  whatsThis = "<b>Function:</b> Allows user to select a new file to set as "
485  "the registration template";
486  m_openTemplateFile->setWhatsThis(whatsThis);
487  connect(m_openTemplateFile, SIGNAL(activated()), this, SLOT(openTemplateFile()));
488 
489  m_saveTemplateFile = new QAction(QPixmap(toolIconDir() + "/mActionFileSave.png"),
490  "&Save template file",
491  m_matchTool);
492  m_saveTemplateFile->setToolTip("Save the template file");
493  m_saveTemplateFile->setStatusTip("Save the template file");
494  m_saveTemplateFile->setWhatsThis("Save the registration template file");
495  connect(m_saveTemplateFile, SIGNAL(triggered()), this,
496  SLOT(saveTemplateFile()));
497 
498  m_saveTemplateFileAs = new QAction(QPixmap(toolIconDir() + "/mActionFileSaveAs.png"),
499  "&Save template as...",
500  m_matchTool);
501  m_saveTemplateFileAs->setToolTip("Save the template file as");
502  m_saveTemplateFileAs->setStatusTip("Save the template file as");
503  m_saveTemplateFileAs->setWhatsThis("Save the registration template file as");
504  connect(m_saveTemplateFileAs, SIGNAL(triggered()), this,
505  SLOT(saveTemplateFileAs()));
506 
507  m_whatsThis = new QAction(QPixmap(toolIconDir() + "/contexthelp.png"),
508  "&Whats's This",
509  m_matchTool);
510  m_whatsThis->setShortcut(Qt::SHIFT | Qt::Key_F1);
511  m_whatsThis->setToolTip("Activate What's This and click on items on "
512  "user interface to see more information.");
513  connect(m_whatsThis, SIGNAL(activated()), this, SLOT(enterWhatsThisMode()));
514 
515  m_showHelp = new QAction(QPixmap(toolIconDir() + "/help-contents.png"), "Help", m_matchTool);
516  m_showHelp->setToolTip("Help");
517  connect(m_showHelp, SIGNAL(activated()), this, SLOT(showHelp()));
518 
519  }
520 
521 
522 
533 
534  QMenu *fileMenu = m_matchTool->menuBar()->addMenu("&File");
535  fileMenu->addAction(m_saveNet);
536  fileMenu->addAction(m_saveAsNet);
537  fileMenu->addAction(m_closeMatchTool);
538 
539  QMenu * regMenu = m_matchTool->menuBar()->addMenu("&Registration");
540  regMenu->addAction(m_openTemplateFile);
541  regMenu->addAction(m_showHideTemplateEditor);
542  regMenu->addAction(m_saveChips);
543 
544  QMenu *helpMenu = m_matchTool->menuBar()->addMenu("&Help");
545  helpMenu->addAction(m_whatsThis);
546  }
547 
548 
549  void MatchTool::createToolBars() {
550 
551  QToolBar * toolBar = new QToolBar;
552  toolBar->setObjectName("TemplateEditorToolBar");
553  toolBar->setFloatable(false);
554  toolBar->addAction(m_saveNet);
555  toolBar->addSeparator();
556  toolBar->addAction(m_showHideTemplateEditor);
557  toolBar->addAction(m_saveChips);
558  toolBar->addAction(m_showHelp);
559  toolBar->addAction(m_whatsThis);
560 
561  m_matchTool->addToolBar(Qt::TopToolBarArea, toolBar);
562  }
563 
564 
565 
578  QAction *action = new QAction(pad);
579  action->setIcon(QPixmap(toolIconDir()+"/stock_draw-connector-with-arrows.png"));
580  action->setToolTip("Match Tool - Control Point Editor (T)");
581  action->setShortcut(Qt::Key_T);
582  return action;
583  }
584 
585 
586 
587  QWidget *MatchTool::createToolBarWidget(QStackedWidget *parent) {
588 
589  QWidget *hbox = new QWidget(parent);
590 
591  QToolButton *openNetButton = new QToolButton(hbox);
592  openNetButton->setIcon(QPixmap(toolIconDir() + "/fileopen.png"));
593  openNetButton->setIconSize(QSize(22,22));
594  openNetButton->setToolTip("Open control network");
595  openNetButton->setEnabled(true);
596  connect(openNetButton, SIGNAL(clicked()), this, SLOT(openNet()));
597 
598  QToolButton *saveAsNetButton = new QToolButton(hbox);
599  saveAsNetButton->setDefaultAction(m_saveAsNet);
600  saveAsNetButton->setIconSize(QSize(22,22));
601 
602  QToolButton *saveNetButton = new QToolButton(hbox);
603  saveNetButton->setDefaultAction(m_saveNet);
604  saveNetButton->setIconSize(QSize(22,22));
605 
606  QToolButton *helpButton = new QToolButton(hbox);
607  helpButton->setDefaultAction(m_showHelp);
608  helpButton->setIconSize(QSize(22, 22));
609 
610  QHBoxLayout *layout = new QHBoxLayout;
611  layout->setMargin(0);
612  layout->addWidget(openNetButton);
613  layout->addWidget(saveAsNetButton);
614  layout->addWidget(saveNetButton);
615  layout->addStretch();
616  layout->addWidget(helpButton);
617  hbox->setLayout(layout);
618 
619  return hbox;
620  }
621 
622 
623 
624  void MatchTool::activateTool() {
625 
626  if (!m_controlNet) {
627  m_controlNet = new ControlNet();
628  }
629  }
630 
631 
632 
643 
644  SerialNumberList list(false);
645  foreach (MdiCubeViewport *mvp, *cubeViewportList()) {
646  try {
647  // Attempt to Compose Serial number and see if list already has duplicate. If so,
648  // use filenames as serial numbers for both cubes. This needs to be checked because
649  // coreg networks will often have 2 cubes with the same serial number.make cl
650  QString sn = SerialNumber::Compose(mvp->cube()->fileName(), true);
651  if (list.HasSerialNumber(sn)) {
652  // TODO Before removing serial number, make sure current network does not have
653  // measures with old serial number. If it does, now what? Print error?
654  //
655  // Remove old serial number & change to filename
656  FileName fileName = Isis::FileName(list.FileName(sn));
657  list.Delete(sn);
658  list.Add(fileName.name(),fileName.expanded());
659  // Add new serial number as filename
660  list.Add(Isis::FileName(mvp->cube()->fileName()).name(),
661  mvp->cube()->fileName());
662  }
663  else {
664  list.Add(mvp->cube()->fileName(), true);
665  }
666  }
667  catch (...) {
668  }
669  }
670  return list;
671  }
672 
673 
674 
675  QString MatchTool::serialNumber(MdiCubeViewport *mvp) {
676 
677  QString serialNumber;
678  try {
680  serialNumber = list.SerialNumber(mvp->cube()->fileName());
681 // serialNumber = serialNumberList().SerialNumber(mvp->cube()->fileName());
682  }
683  catch (IException &e) {
684  serialNumber = "Unknown";
685  }
686  return serialNumber;
687 
688  }
689 
690 
691 
752 
753  // Read original measures from the network for comparison with measures
754  // that have been edited
755  ControlMeasure *origLeftMeasure =
756  m_editPoint->GetMeasure(m_leftMeasure->GetCubeSerialNumber());
757  ControlMeasure *origRightMeasure =
758  m_editPoint->GetMeasure(m_rightMeasure->GetCubeSerialNumber());
759  // Neither measure has changed, return
760  if (*origLeftMeasure == *m_leftMeasure && *origRightMeasure == *m_rightMeasure) {
761  return;
762  }
763 
764  if (m_editPoint->IsIgnored()) {
765  QString message = "You are saving changes to a measure on an ignored ";
766  message += "point. Do you want to set Ignore = False on the point and ";
767  message += "both measures?";
768  switch (QMessageBox::question(m_matchTool, "Match Tool Save Measure",
769  message, "&Yes", "&No", 0, 0)) {
770  // Yes: set Ignore=false for the point and measures and save point
771  case 0:
772  m_editPoint->SetIgnored(false);
773  emit ignorePointChanged();
774  if (m_leftMeasure->IsIgnored()) {
775  m_leftMeasure->SetIgnored(false);
776  emit ignoreLeftChanged();
777  }
778  if (m_rightMeasure->IsIgnored()) {
779  m_rightMeasure->SetIgnored(false);
780  emit ignoreRightChanged();
781  }
782  // No: keep Ignore=true and save measure
783  case 1:
784  break;
785  }
786  }
787 
788  bool savedAMeasure = false;
789  // Error check both measures for edit lock, ignore status and reference
790  bool leftChangeOk = validateMeasureChange(m_leftMeasure);
791  if (leftChangeOk) {
792  m_leftMeasure->SetChooserName(Application::UserName());
793  *origLeftMeasure = *m_leftMeasure;
794  savedAMeasure = true;
795  }
796  bool rightChangeOk = validateMeasureChange(m_rightMeasure);
797  if (rightChangeOk) {
798  m_rightMeasure->SetChooserName(Application::UserName());
799  *origRightMeasure = *m_rightMeasure;
800  savedAMeasure = true;
801  }
802 
803  // If left measure == right measure, update left
804  if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
805  *m_leftMeasure = *m_rightMeasure;
806  // Update left measure of pointEditor
807  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube,
808  m_editPoint->GetId());
809  }
810 
811  // Change Save Point button text to red
812  if (savedAMeasure) {
814  }
815 
816  emit editPointChanged();
817 
818  // Update measure info
822 
823  }
824 
825 
826 
827  bool MatchTool::validateMeasureChange(ControlMeasure *m) {
828 
829 
830  // Read original measures from the network for comparison with measures
831  // that have been edited
832  ControlMeasure *origMeasure =
833  m_editPoint->GetMeasure(m->GetCubeSerialNumber());
834 
835  // If measure hasn't changed, return false, to keep original
836 
837  if (*m == *origMeasure) return false;
838 
839  // Is measure on Left or Right? This is needed to print correct information
840  // to users in identifying the measure and for updating information widgets.
841  QString side = "right";
842  if (m->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
843  side = "left";
844  }
845 
846  // Only print error if both original measure in network and the current
847  // edit measure are both editLocked and measure has changed. If only the edit measure is
848  // locked, then user just locked and it needs to be saved.
849  // Do not use this classes IsMeasureLocked since we actually want to
850  // check the original againsted the edit measure and we don't care
851  // if this is a reference measure. The check for moving a reference is
852  // done below.
853  if (origMeasure->IsEditLocked() && m->IsEditLocked()) {
854  QString message = "The " + side + " measure is editLocked ";
855  message += "for editing. Do you want to set EditLock = False for this ";
856  message += "measure?";
857  int response = QMessageBox::question(m_matchTool, "Match Tool Save Measure",
858  message, QMessageBox::Yes | QMessageBox::No);
859  // Yes: set EditLock=false for the right measure
860  if (response == QMessageBox::Yes) {
861  m->SetEditLock(false);
862  if (side == "left") {
863  m_lockLeftMeasure->setChecked(false);
864  }
865  else {
866  m_lockRightMeasure->setChecked(false);
867  }
868  }
869  // No: keep EditLock=true and do NOT save measure
870  else {
871  return false;
872  }
873  }
874 
875  if (origMeasure->IsIgnored() && m->IsIgnored()) {
876  QString message = "The " + side + "measure is ignored. ";
877  message += "Do you want to set Ignore = False on the measure?";
878  switch(QMessageBox::question(m_matchTool, "Match Tool Save Measure",
879  message, "&Yes", "&No", 0, 0)){
880  // Yes: set Ignore=false for the right measure and save point
881  case 0:
882  m->SetIgnored(false);
883  if (side == "left") {
884  emit ignoreLeftChanged();
885  }
886  else {
887  emit ignoreRightChanged();
888  }
889  // No: keep Ignore=true and save point
890  case 1:
891  break;;
892  }
893  }
894 
895  // If measure is explicit reference and it has moved,warn user
896  ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
897  if (m_editPoint->IsReferenceExplicit()) {
898  if (refMeasure->GetCubeSerialNumber() == m->GetCubeSerialNumber()) {
899  if (m->GetSample() != origMeasure->GetSample() || m->GetLine() != origMeasure->GetLine()) {
900  QString message = "You are making a change to the reference measure. You ";
901  message += "may need to move all of the other measures to match the new ";
902  message += " coordinate of the reference measure. Do you really want to ";
903  message += " change the reference measure's location? ";
904  switch(QMessageBox::question(m_matchTool, "Match Tool Save Measure",
905  message, "&Yes", "&No", 0, 0)){
906  // Yes: Save measure
907  case 0:
908  break;
909  // No: keep original reference, return without saving
910  case 1:
911  loadPoint();
912  return false;
913  }
914  }
915  }
916  // New reference measure
917  else if (side == "left" && (refMeasure->GetCubeSerialNumber() != m->GetCubeSerialNumber())) {
918  if (m_coregNet) {
919  QString message = "This control network was created by the <i>coreg</i> program, and the "
920  "reference measure needs to remain the same as what <i>coreg</i> set. "
921  "Therefore, you cannot change which measure is the reference. To "
922  "save this point, move the reference measure (measure in BOLD) back "
923  "to the left side.";
924  QMessageBox::information(m_matchTool, "Cannot change reference", message);
925  }
926  else {
927  QString message = "This point already contains a reference measure. ";
928  message += "Would you like to replace it with the measure on the left?";
929  int response = QMessageBox::question(m_matchTool,
930  "Match Tool Save Measure", message,
931  QMessageBox::Yes | QMessageBox::No,
932  QMessageBox::Yes);
933  // Replace reference measure
934  if (response == QMessageBox::Yes) {
935  // Update measure file combo boxes: old reference normal font,
936  // new reference bold font
937  QString file = serialNumberList().FileName(m_leftMeasure->GetCubeSerialNumber());
938  QString fname = FileName(file).name();
939  int iref = m_leftCombo->findText(fname);
940 
941  // Save normal font from new reference measure
942  QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
943  m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
944  iref = m_rightCombo->findText(fname);
945  m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
946 
947  file = serialNumberList().FileName(refMeasure->GetCubeSerialNumber());
948  fname = FileName(file).name();
949  iref = m_leftCombo->findText(fname);
950  m_leftCombo->setItemData(iref,font,Qt::FontRole);
951  iref = m_rightCombo->findText(fname);
952  m_rightCombo->setItemData(iref,font,Qt::FontRole);
953 
954  m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
955  }
956  }
957  }
958  }
959  else {
960  // No explicit reference, If left, set explicit reference
961  if (side == "left") {
962  m_editPoint->SetRefMeasure(m->GetCubeSerialNumber());
963  }
964  }
965 
966  // All test pass, return true (ok to change measure)
967  return true;
968 
969 
970  }
971 
972 
973 
974  /*
975  * Change which measure is the reference.
976  *
977  * @author 2012-04-26 Tracie Sucharski - moved funcitonality from measureSaved
978  *
979  * @internal
980  * @history 2012-06-12 Tracie Sucharski - Moved check for ground loaded on left from the
981  * measureSaved method.
982  */
983  void MatchTool::checkReference() {
984 
985  // Check if ControlPoint has reference measure, if reference Measure is
986  // not the same measure that is on the left chip viewport, set left
987  // measure as reference.
988  ControlMeasure *refMeasure = m_editPoint->GetRefMeasure();
989  if (refMeasure->GetCubeSerialNumber() != m_leftMeasure->GetCubeSerialNumber()) {
990  QString message = "This point already contains a reference measure. ";
991  message += "Would you like to replace it with the measure on the left?";
992  int response = QMessageBox::question(m_matchTool,
993  "Match Tool Save Measure", message,
994  QMessageBox::Yes | QMessageBox::No,
995  QMessageBox::Yes);
996  // Replace reference measure
997  if (response == QMessageBox::Yes) {
998  // Update measure file combo boxes: old reference normal font,
999  // new reference bold font
1000  QString file = serialNumberList().FileName(m_leftMeasure->GetCubeSerialNumber());
1001  QString fname = FileName(file).name();
1002  int iref = m_leftCombo->findText(fname);
1003 
1004  // Save normal font from new reference measure
1005  QVariant font = m_leftCombo->itemData(iref,Qt::FontRole);
1006  m_leftCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1007  iref = m_rightCombo->findText(fname);
1008  m_rightCombo->setItemData(iref,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1009 
1010  file = serialNumberList().FileName(refMeasure->GetCubeSerialNumber());
1011  fname = FileName(file).name();
1012  iref = m_leftCombo->findText(fname);
1013  m_leftCombo->setItemData(iref,font,Qt::FontRole);
1014  iref = m_rightCombo->findText(fname);
1015  m_rightCombo->setItemData(iref,font,Qt::FontRole);
1016 
1017  m_editPoint->SetRefMeasure(m_leftMeasure->GetCubeSerialNumber());
1018  }
1019 
1020  // ??? Need to set rest of measures to Candiate and add more warning. ???//
1021  }
1022 
1023 
1024  }
1025 
1026 
1027 
1043 
1044  // Make a copy of edit point for updating the control net since the edit
1045  // point is still loaded in the point editor.
1046  ControlPoint *updatePoint = new ControlPoint;
1047  *updatePoint = *m_editPoint;
1048 
1049  // If edit point exists in the network, save the updated point. If it
1050  // does not exist, add it.
1051  if (m_controlNet->ContainsPoint(updatePoint->GetId())) {
1052  ControlPoint *p;
1053  p = m_controlNet->GetPoint(QString(updatePoint->GetId()));
1054  *p = *updatePoint;
1055  delete updatePoint;
1056  updatePoint = NULL;
1057  }
1058  else {
1059  m_controlNet->AddPoint(updatePoint);
1060  }
1061 
1062  // Change Save Measure button text back to default
1063  m_savePoint->setPalette(m_saveDefaultPalette);
1064 
1065  // emit signal so the nav tool can update edit point
1066  emit editPointChanged();
1067  // At exit, or when opening new net, use for prompting user for a save
1068  m_netChanged = true;
1069  // Refresh chipViewports to show new positions of controlPoints
1070  m_pointEditor->refreshChips();
1071  }
1072 
1073 
1074 
1084  void MatchTool::setLockPoint (bool lock) {
1085  if (m_editPoint == NULL) return;
1086 
1087  m_editPoint->SetEditLock(lock);
1089  }
1090 
1091 
1092 
1103  void MatchTool::setIgnorePoint (bool ignore) {
1104  if (m_editPoint == NULL) return;
1105 
1106  ControlPoint::Status status = m_editPoint->SetIgnored(ignore);
1107  if (status == ControlPoint::PointLocked) {
1108  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1109  QString message = "Unable to change Ignored on point. Set EditLock ";
1110  message += " to False.";
1111  QMessageBox::critical(m_matchTool, "Error", message);
1112  return;
1113  }
1115  }
1116 
1117 
1118 
1119 
1136 
1137  if (m_editPoint->IsEditLocked()) {
1138  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1139  QMessageBox::warning(m_matchTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1140  " before changing a measure.");
1141  m_lockLeftMeasure->setChecked(m_leftMeasure->IsEditLocked());
1142  return;
1143  }
1144 
1145  if (m_leftMeasure != NULL) m_leftMeasure->SetEditLock(lock);
1146 
1147  // If the right chip is the same as the left chip , update the right editLock
1148  // box.
1149  if (m_rightMeasure != NULL) {
1150  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1151  m_rightMeasure->SetEditLock(lock);
1152  m_lockRightMeasure->setChecked(lock);
1153  }
1154  }
1155  emit measureChanged();
1156  }
1157 
1158 
1176  void MatchTool::setIgnoreLeftMeasure (bool ignore) {
1177  if (m_leftMeasure != NULL) m_leftMeasure->SetIgnored(ignore);
1178 
1179  // If the right chip is the same as the left chip , update the right
1180  // ignore box.
1181  if (m_rightMeasure != NULL) {
1182  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1183  m_rightMeasure->SetIgnored(ignore);
1184  m_ignoreRightMeasure->setChecked(ignore);
1185  }
1186  }
1187  emit measureChanged();
1188  }
1189 
1190 
1207 
1208  if (m_editPoint->IsEditLocked()) {
1209  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1210  QMessageBox::warning(m_matchTool, "Point Locked","Point is Edit Locked. You must un-lock point"
1211  " before changing a measure.");
1212  m_lockRightMeasure->setChecked(m_rightMeasure->IsEditLocked());
1213  return;
1214  }
1215 
1216  if (m_rightMeasure != NULL) m_rightMeasure->SetEditLock(lock);
1217 
1218  // If the left chip is the same as the right chip , update the left editLock box.
1219  if (m_leftMeasure != NULL) {
1220  if (m_leftMeasure->GetCubeSerialNumber() == m_rightMeasure->GetCubeSerialNumber()) {
1221  m_leftMeasure->SetEditLock(lock);
1222  m_lockLeftMeasure->setChecked(lock);
1223  }
1224  }
1225  emit measureChanged();
1226  }
1227 
1228 
1247  if (m_rightMeasure != NULL) m_rightMeasure->SetIgnored(ignore);
1248 
1249  // If the right chip is the same as the left chip , update the right
1250  // ignore blox.
1251  if (m_leftMeasure != NULL) {
1252  if (m_rightMeasure->GetCubeSerialNumber() == m_leftMeasure->GetCubeSerialNumber()) {
1253  m_leftMeasure->SetIgnored(ignore);
1254  m_ignoreLeftMeasure->setChecked(ignore);
1255  }
1256  }
1257  emit measureChanged();
1258  }
1259 
1260 
1261 
1262  void MatchTool::openNet() {
1263 
1264  if (m_controlNet) {
1265  if (m_controlNet->GetNumPoints() != 0 && m_netChanged) {
1266  QString message = "A control net has already been created. Do you want to save before "
1267  "opening a new control net?";
1268  int response = QMessageBox::question(m_matchTool, "Save current control net?",
1269  message,
1270  QMessageBox::Yes | QMessageBox::No,
1271  QMessageBox::Yes);
1272  // Yes: Save old net, so return without opening network.
1273  if (response == QMessageBox::Yes) {
1274  saveAsNet();
1275  }
1276  m_matchTool->setShown(false);
1277  }
1278  delete m_controlNet;
1279  m_controlNet = NULL;
1280  m_editPoint = NULL;
1281  m_newPoint = NULL;
1282  m_newPointDialog = NULL;
1283  }
1284 
1285  // At exit, or when opening new net, use for prompting user for a save
1286  m_netChanged = false;
1287 
1288  QApplication::restoreOverrideCursor();
1289  QString filter = "Control net (*.net *.cnet *.ctl);;";
1290  filter += "Pvl file (*.pvl);;";
1291  filter += "Text file (*.txt);;";
1292  filter += "All (*)";
1293  m_cnetFileName = QFileDialog::getOpenFileName((QWidget *)parent(),
1294  "Select a control network",
1295  ".",
1296  filter);
1297  QApplication::setOverrideCursor(Qt::WaitCursor);
1298  if (!m_cnetFileName.isEmpty()) {
1299  try {
1300  Progress progress;
1301  m_controlNet = new ControlNet(m_cnetFileName, &progress);
1302  m_coregNet = false;
1303  m_coregReferenceSN = "";
1304  if (m_controlNet->GetNetworkId() == "Coreg") {
1305  m_coregNet = true;
1306  // Find reference image of first point, the rest of the points will have the same
1307  // reference. When creating new point, use the same reference.
1308  m_coregReferenceSN = m_controlNet->GetPoint(0)->GetReferenceSN();
1309  }
1310  }
1311  catch (IException &e) {
1312  QApplication::restoreOverrideCursor();
1313  QString message = "Invalid control network. \n";
1314  message += e.toString();
1315  QMessageBox::critical(m_matchTool, "Error", message);
1316  m_cnetFileName.clear();
1317  delete m_controlNet;
1318  m_controlNet = NULL;
1319  return;
1320  }
1321  }
1322  QApplication::restoreOverrideCursor();
1323  m_matchTool->setWindowTitle("Match Tool - Control Network File: " + m_cnetFileName);
1324  m_cnetFileNameLabel->setText("Control Network: " + m_cnetFileName);
1325 
1327  }
1328 
1329 
1330 
1337  if (m_cnetFileName.isEmpty()) {
1338  QString message = "This is a new network, you must select "
1339  "\"Save As\" under the File Menu or on the toolbar.";
1340  QMessageBox::critical(m_matchTool, "Error", message);
1341  return;
1342  }
1343  try {
1344  m_controlNet->Write(m_cnetFileName);
1345  m_netChanged = false;
1346  }
1347  catch (IException &e) {
1348  QMessageBox::critical(m_matchTool, tr("Error Writing Control Net"), e.what());
1349  return;
1350  }
1351  }
1352 
1353 
1354 
1359 
1360  QString fn = QFileDialog::getSaveFileName(m_matchTool,
1361  "Choose filename to save under",
1362  ".",
1363  "Control Files (*.net)");
1364 
1365  //Make sure the filename is valid
1366  if(!fn.isEmpty()) {
1367  try {
1368  m_controlNet->Write(fn);
1369  m_netChanged = false;
1370  }
1371  catch (IException &e) {
1372  QMessageBox::critical(m_matchTool, tr("Error Writing Control Net"), e.what());
1373  return;
1374  }
1375  m_cnetFileName = fn;
1376  }
1377  //The user cancelled, or the filename is empty
1378  else {
1379  return;
1380  }
1381 
1382  }
1383 
1384 
1385 
1413  void MatchTool::mouseButtonRelease(QPoint p, Qt::MouseButton s) {
1414  MdiCubeViewport *mvp = cubeViewport();
1415  if (mvp == NULL) return;
1416 
1417  QString file = mvp->cube()->fileName();
1418  QString sn = serialNumberList().SerialNumber(file);
1419 
1420  double samp,line;
1421  mvp->viewportToCube(p.x(),p.y(),samp,line);
1422 
1423  if (s == Qt::LeftButton) {
1424 
1425  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1426  QString message = "No points exist for editing. Create points ";
1427  message += "using the right mouse button.";
1428  QMessageBox::warning(m_matchTool, "Warning", message);
1429  return;
1430  }
1431 
1432  // Find closest control point in network
1433  QString sn = serialNumberList().SerialNumber(file);
1434  ControlPoint *point = NULL;
1435  try {
1436  point = m_controlNet->FindClosest(sn, samp, line);
1437  }
1438  catch (IException &e) {
1439  QString message = "Cannot find point for editing.";
1440  message += e.toString();
1441  QMessageBox::warning(m_matchTool, "Warning", message);
1442  return;
1443  }
1444 
1445  modifyPoint(point);
1446  }
1447  else if (s == Qt::MidButton) {
1448  if (!m_controlNet || m_controlNet->GetNumPoints() == 0) {
1449  QString message = "No points exist for deleting. Create points ";
1450  message += "using the right mouse button.";
1451  QMessageBox::warning(m_matchTool, "Warning", message);
1452  return;
1453  }
1454 
1455  // Find closest control point in network
1456  ControlPoint *point = m_controlNet->FindClosest(sn, samp, line);
1457 
1458  if (point == NULL) {
1459  QString message = "No points exist for deleting. Create points ";
1460  message += "using the right mouse button.";
1461  QMessageBox::warning(m_matchTool, "Warning", message);
1462  return;
1463  }
1464 
1465  deletePoint(point);
1466  }
1467  else if (s == Qt::RightButton) {
1468  if (m_newPointDialog) {
1469  addMeasure(mvp, samp, line);
1470  }
1471  else {
1472  try {
1473  createPoint(mvp, samp, line);
1474  m_leftFile = mvp->cube()->fileName();
1475  }
1476  catch (IException &e) {
1477  QString message = "Cannot create control point.\n\n";
1478  message += e.toString();
1479  QMessageBox::critical(m_matchTool, "Error", message);
1480  return;
1481  }
1482  }
1483  }
1484  }
1485 
1486 
1487 
1488  QStringList MatchTool::missingCubes(ControlPoint *point) {
1489 
1490  // Make sure all measures are loaded into viewports, otherwise we cannot edit this point
1491  QStringList missingCubes;
1492  for (int i=0; i<point->GetNumMeasures(); i++) {
1493  ControlMeasure &m = *(*point)[i];
1495  missingCubes << m.GetCubeSerialNumber();
1496  }
1497  }
1498  return missingCubes;
1499  }
1500 
1501 
1502 
1509  void MatchTool::createPoint(MdiCubeViewport *cvp, double sample, double line) {
1510 
1511  m_newPointDialog = new MatchToolNewPointDialog(*m_controlNet, m_lastUsedPointId, m_matchTool);
1512  connect(m_newPointDialog, SIGNAL(measuresFinished()), this, SLOT(doneWithMeasures()));
1513  connect(m_newPointDialog, SIGNAL(newPointCanceled()), this, SLOT(cancelNewPoint()));
1514 
1515  QStringList images;
1516  for (int i = 0; i < (int)cubeViewportList()->size(); i++) {
1517  FileName cubeFile = (*(cubeViewportList()))[i]->cube()->fileName();
1518  images<<cubeFile.name();
1519  }
1520  m_newPointDialog->setFiles(images);
1521  m_newPointDialog->show();
1522 
1523  // Highlight the current cubeViewport
1524  QString current = FileName(cvp->cube()->fileName()).name();
1525  m_newPointDialog->highlightFile(current);
1526 
1527  m_newPoint = new ControlPoint();
1528  m_newPoint->SetType(ControlPoint::Free);
1529  m_newPoint->SetChooserName(Application::UserName());
1530 
1531  ControlMeasure *m = new ControlMeasure;
1532  m->SetCubeSerialNumber(serialNumber(cvp));
1533  m->SetCoordinate(sample, line);
1535  m->SetDateTime();
1537  m_newPoint->Add(m);
1538 
1540  }
1541 
1542 
1543 
1544  void MatchTool::addMeasure(MdiCubeViewport *cvp, double sample, double line) {
1545 
1546  // Highlight the current cubeViewport
1547  QString current = FileName(cvp->cube()->fileName()).name();
1548  m_newPointDialog->highlightFile(current);
1549  m_newPointDialog->raise();
1550 
1551  ControlMeasure *m = new ControlMeasure;
1552  m->SetCubeSerialNumber(serialNumber(cvp));
1553 
1554  // If serial number already exists, delete old measure before creating new
1555  if (m_newPoint->HasSerialNumber(serialNumber(cvp))) {
1556  m_newPoint->Delete(m_newPoint->GetMeasure(serialNumber(cvp)));
1557  }
1558  m->SetCoordinate(sample, line);
1560  m->SetDateTime();
1562  m_newPoint->Add(m);
1563 
1565  }
1566 
1567 
1568 
1569  void MatchTool::doneWithMeasures() {
1570 
1571  m_lastUsedPointId = m_newPointDialog->pointId();
1572  m_newPoint->SetId(m_lastUsedPointId);
1573 // // Add new control point to control network
1574 // m_controlNet->AddPoint(m_newPoint);
1575 // // Read newly added point
1576 // // TODO Make sure pt exists
1577 // m_editPoint = m_controlNet->GetPoint((QString) m_newPoint->GetId());
1578 
1579  // If this is a coreg network, make sure the reference SN exists in the new point
1580  // and set it to the reference measure.
1581  if (m_coregNet) {
1582  if (!m_newPoint->HasSerialNumber(m_coregReferenceSN)) {
1583  QString message = "This is a coreg network which needs the cube with serial number " +
1584  m_coregReferenceSN + " as the reference measure. This new control point does "
1585  "not have a measure for that serial number, so this point cannot be created until "
1586  "the cube listed above is added (Right-click on cube).";
1587  QMessageBox::critical(m_matchTool, "Error", message);
1588  m_newPointDialog->show();
1589  return;
1590  }
1591  // Set the reference measure to match the rest of the points
1592  m_newPoint->SetRefMeasure(m_newPoint->GetMeasure(m_coregReferenceSN));
1593  }
1594 
1595  // If the editPoint has been used, but there is not currently a network, delete the editPoint
1596  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1597  delete m_editPoint;
1598  m_editPoint = NULL;
1599  }
1600  m_editPoint = m_newPoint;
1601 
1602  m_newPoint = NULL;
1603  delete m_newPointDialog;
1604  m_newPointDialog = NULL;
1605 
1606  // Load new point in MatchTool
1607  loadPoint();
1608  m_matchTool->setShown(true);
1609  m_matchTool->raise();
1610 
1611  emit editPointChanged();
1613  }
1614 
1615 
1616 
1617  void MatchTool::cancelNewPoint() {
1618 
1619  delete m_newPointDialog;
1620  m_newPointDialog = NULL;
1621  delete m_newPoint;
1622  m_newPoint = NULL;
1623  m_leftFile.clear();
1624 
1626 
1627  }
1628 
1629 
1630 
1650 
1651  QStringList mCubes = missingCubes(point);
1652  if (mCubes.size() > 0) {
1653  QString msgTitle = "Missing Cubes";
1654  QString message = "This point is missing cubes for the following measures and cannot be ";
1655  message += "loaded into the editor. Do you still want to delete this point?\n\n";
1656  for (int i=0; i<mCubes.size(); i++) {
1657  message += mCubes.at(i) + "\n";
1658  }
1659  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1660  Qt::Dialog);
1661  QPushButton *yesButton = msgBox.addButton("Yes", QMessageBox::AcceptRole);
1662  QPushButton *noButton = msgBox.addButton("No", QMessageBox::RejectRole);
1663  msgBox.setDefaultButton(yesButton);
1664  msgBox.exec();
1665  if (msgBox.clickedButton() == noButton) {
1666  return;
1667  }
1668  else {
1669  m_matchTool->setShown(false);
1670  }
1671 
1672  }
1673 
1674  // Make a copy and make sure editPoint is a copy (which means it does not
1675  // have a parent network.
1676  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1677  delete m_editPoint;
1678  m_editPoint = NULL;
1679  }
1680  m_editPoint = new ControlPoint;
1681  *m_editPoint = *point;
1682 
1683  // No missing cubes, load edit point as usual
1684  if (mCubes.size() == 0) {
1685  loadPoint();
1686 
1687  // Change point in viewport to red so user can see what point they are
1688  // about to delete.
1689  // the nav tool will update edit point
1690  emit editPointChanged();
1691  }
1692 
1693  MatchToolDeletePointDialog *deletePointDialog = new MatchToolDeletePointDialog;
1694  QString CPId = m_editPoint->GetId();
1695  deletePointDialog->pointIdValue->setText(CPId);
1696  // Need all files for this point
1697  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1698  ControlMeasure &m = *(*m_editPoint)[i];
1699  QString file;
1702  }
1703  else {
1704  file = m.GetCubeSerialNumber();
1705  }
1706  deletePointDialog->fileList->addItem(file);
1707  }
1708 
1709  if (deletePointDialog->exec()) {
1710 
1711  int numDeleted = deletePointDialog->fileList->selectedItems().count();
1712 
1713  // Delete entire control point, either through deleteAllCheckBox or all measures selected
1714  if (deletePointDialog->deleteAllCheckBox->isChecked() ||
1715  numDeleted == m_editPoint->GetNumMeasures()) {
1716 
1717  // If all measures being deleted, let user know and give them the option to quit operation
1718  if (!deletePointDialog->deleteAllCheckBox->isChecked()) {
1719  QString message = "You have selected all measures in this point to be deleted. This "
1720  "control point will be deleted. Do you want to delete this control point?";
1721  int response = QMessageBox::question(m_matchTool,
1722  "Delete control point", message,
1723  QMessageBox::Yes | QMessageBox::No,
1724  QMessageBox::Yes);
1725  // If No, do nothing
1726  if (response == QMessageBox::No) {
1727  return;
1728  }
1729  }
1730 
1731  m_matchTool->setShown(false);
1732  // remove this point from the control network
1733  if (m_controlNet->DeletePoint(m_editPoint->GetId()) == ControlPoint::PointLocked) {
1734  QMessageBox::information(m_matchTool, "EditLocked Point",
1735  "This point is EditLocked and cannot be deleted.");
1736  return;
1737  }
1738  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1739  delete m_editPoint;
1740  m_editPoint = NULL;
1741  }
1742  }
1743 
1744  // Delete specific measures from control point
1745  else {
1746  // Keep track of editLocked measures for reporting
1747  int lockedMeasures = 0;
1748  for (int i=0; i<deletePointDialog->fileList->count(); i++) {
1749  QListWidgetItem *item = deletePointDialog->fileList->item(i);
1750  if (!deletePointDialog->fileList->isItemSelected(item)) continue;
1751 
1752  // Do not delete reference without asking user
1753  if (m_editPoint->IsReferenceExplicit() &&
1754  (m_editPoint->GetRefMeasure()->GetCubeSerialNumber() ==
1755  (*m_editPoint)[i]->GetCubeSerialNumber())) {
1756  QString message = "You are trying to delete the Reference measure."
1757  " Do you really want to delete the Reference measure?";
1758  switch (QMessageBox::question(m_matchTool,
1759  "Delete Reference measure?", message,
1760  "&Yes", "&No", 0, 0)) {
1761  // Yes: skip to end of switch to delete the measure
1762  case 0:
1763  break;
1764  // No: continue to next measure in the loop
1765  case 1:
1766  // if only a single measure and it's reference and user chooses not to delete,
1767  // simply return. The point has not changed.
1768  if (numDeleted == 1) {
1769  return;
1770  }
1771  continue;
1772  }
1773  }
1774 
1775  if (m_editPoint->Delete(i) == ControlMeasure::MeasureLocked) {
1776  lockedMeasures++;
1777  }
1778  }
1779 
1780  if (lockedMeasures > 0) {
1781  QMessageBox::information(m_matchTool,"EditLocked Measures",
1782  QString::number(lockedMeasures) + " / "
1783  + QString::number(
1784  deletePointDialog->fileList->selectedItems().size()) +
1785  " measures are EditLocked and were not deleted.");
1786  }
1787 
1788  if (mCubes.size() == 0) {
1789  loadPoint();
1790  m_matchTool->setShown(true);
1791  m_matchTool->raise();
1792 
1794  m_pointEditor->templateFileName());
1795  }
1796  // Since the delete point is not loaded into the editor for saving by the user, we need
1797  // to save the point.
1798  else {
1799  ControlPoint *p = m_controlNet->GetPoint(QString(m_editPoint->GetId()));
1800  *p = *m_editPoint;
1801 
1802  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1803  delete m_editPoint;
1804  m_editPoint = NULL;
1805  }
1806  }
1807  }
1808 
1809  // emit a signal to alert user to save when exiting
1810  // At exit, or when opening new net, use for prompting user for a save
1811  m_netChanged = true;
1812 
1813  if (m_editPoint) {
1815  }
1816  emit editPointChanged();
1817  }
1818  }
1819 
1820 
1821 
1831 
1832  // If no measures, print info and return
1833  if (point->GetNumMeasures() == 0) {
1834  QString message = "This point has no measures.";
1835  QMessageBox::warning(m_matchTool, "Warning", message);
1836  emit editPointChanged();
1837  return;
1838  }
1839 
1840  // Make sure all measures have a cube loaded
1841  QStringList mCubes = missingCubes(point);
1842  if (mCubes.size() > 0) {
1843  QString msgTitle = "Missing Cubes";
1844  QString message = "This point is missing cubes and cannot be loaded into the editor. Open ";
1845  message += "the cubes for the following measures before selecting this point.\n\n";
1846  for (int i=0; i<mCubes.size(); i++) {
1847  message += mCubes.at(i) + "\n";
1848  }
1849  QMessageBox msgBox(QMessageBox::Critical, msgTitle, message, 0, m_matchTool,
1850  Qt::Dialog);
1851  msgBox.exec();
1852  return;
1853  }
1854 
1855  // Make a copy of point for editing, first make sure memory not already
1856  // allocated
1857  if (m_editPoint != NULL && m_editPoint->Parent() == NULL) {
1858  delete m_editPoint;
1859  m_editPoint = NULL;
1860  }
1861  m_editPoint = new ControlPoint;
1862  *m_editPoint = *point;
1863 
1864  loadPoint();
1865  m_matchTool->setShown(true);
1866  m_matchTool->raise();
1868  m_pointEditor->templateFileName());
1869 
1870  // emit signal so the nav tool can update edit point
1871  emit editPointChanged();
1872 
1873  // New point loaded, make sure Save Measure Button text is default
1874  m_savePoint->setPalette(m_saveDefaultPalette);
1875  }
1876 
1877 
1878 
1897 
1898  // Write pointId
1899  QString CPId = m_editPoint->GetId();
1900  QString ptId("Point ID: ");
1901  ptId += (QString) CPId;
1902  m_ptIdValue->setText(ptId);
1903 
1904  // Write number of measures
1905  QString ptsize = "Number of Measures: " +
1906  QString::number(m_editPoint->GetNumMeasures());
1907  m_numMeasures->setText(ptsize);
1908 
1909  // Set EditLock box correctly
1910  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
1911 
1912  // Set ignore box correctly
1913  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
1914 
1915  // Clear combo boxes
1916  m_leftCombo->clear();
1917  m_rightCombo->clear();
1918  m_pointFiles.clear();
1919 
1920  // Need all files for this point
1921  for (int i=0; i<m_editPoint->GetNumMeasures(); i++) {
1922  ControlMeasure &m = *(*m_editPoint)[i];
1923  QString file = serialNumberList().FileName(m.GetCubeSerialNumber());
1924  m_pointFiles<<file;
1925  QString tempFileName = FileName(file).name();
1926  m_leftCombo->addItem(tempFileName);
1927  m_rightCombo->addItem(tempFileName);
1928  if (m_editPoint->IsReferenceExplicit() &&
1929  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
1930  m_leftCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1931  m_rightCombo->setItemData(i,QFont("DejaVu Sans", 12, QFont::Bold), Qt::FontRole);
1932  }
1933  }
1934 
1935  // TODO: WHAT HAPPENS IF THERE IS ONLY ONE MEASURE IN THIS CONTROLPOINT??
1936  // Assuming combo loaded in same order as measures in the control point-is
1937  // this a safe assumption???
1938  //
1939  // Find the file from the cubeViewport that was originally used to select
1940  // the point, this will be displayed on the left ChipViewport, unless the
1941  // point was selected on the ground source image. In this case, simply
1942  // load the first measure on the left.
1943  int leftIndex = 0;
1944  int rightIndex = 0;
1945  // Check for reference
1946  if (m_editPoint->IsReferenceExplicit()) {
1947  leftIndex = m_editPoint->IndexOfRefMeasure();
1948  }
1949  else {
1950  if (!m_leftFile.isEmpty()) {
1951  leftIndex = m_leftCombo->findText(FileName(m_leftFile).name());
1952  // Sanity check
1953  if (leftIndex < 0 ) leftIndex = 0;
1954  m_leftFile.clear();
1955  }
1956  }
1957 
1958  if (leftIndex == 0) {
1959  rightIndex = 1;
1960  }
1961  else {
1962  rightIndex = 0;
1963  }
1964 
1965  // Handle pts with a single measure, for now simply put measure on left/right
1966  // Evenutally put on left with black on right??
1967  if (rightIndex > m_editPoint->GetNumMeasures()-1) rightIndex = 0;
1968  m_rightCombo->setCurrentIndex(rightIndex);
1969  m_leftCombo->setCurrentIndex(leftIndex);
1970  // Initialize pointEditor with measures
1971  selectLeftMeasure(leftIndex);
1972  selectRightMeasure(rightIndex);
1973 
1974  loadMeasureTable();
1975  }
1976 
1977 
1978 
1987  if (m_measureWindow == NULL) {
1988  m_measureWindow = new QMainWindow(m_parent);
1989  m_measureTable = new QTableWidget();
1990  m_measureTable->setMinimumWidth(1600);
1991  m_measureTable->setAlternatingRowColors(true);
1992  m_measureWindow->setCentralWidget(m_measureTable);
1993  }
1994  else {
1995  m_measureTable->clear();
1996  m_measureTable->setSortingEnabled(false);
1997  }
1998  m_measureTable->setRowCount(m_editPoint->GetNumMeasures());
1999  m_measureTable->setColumnCount(NUMCOLUMNS);
2000 
2001  QStringList labels;
2002  for (int i=0; i<NUMCOLUMNS; i++) {
2003  labels<<measureColumnToString((MeasureColumns)i);
2004  }
2005  m_measureTable->setHorizontalHeaderLabels(labels);
2006 
2007  // Fill in values
2008  for (int row=0; row<m_editPoint->GetNumMeasures(); row++) {
2009  int column = 0;
2010  ControlMeasure &m = *(*m_editPoint)[row];
2011 
2012  QString file = serialNumberList().FileName(m.GetCubeSerialNumber());
2013  QTableWidgetItem *tableItem = new QTableWidgetItem(QString(file));
2014  m_measureTable->setItem(row,column++,tableItem);
2015 
2016  tableItem = new QTableWidgetItem(QString(m.GetCubeSerialNumber()));
2017  m_measureTable->setItem(row,column++,tableItem);
2018 
2019  tableItem = new QTableWidgetItem();
2020  tableItem->setData(0,m.GetSample());
2021  m_measureTable->setItem(row,column++,tableItem);
2022 
2023  tableItem = new QTableWidgetItem();
2024  tableItem->setData(0,m.GetLine());
2025  m_measureTable->setItem(row,column++,tableItem);
2026 
2027  if (m.GetAprioriSample() == Null) {
2028  tableItem = new QTableWidgetItem("Null");
2029  }
2030  else {
2031  tableItem = new QTableWidgetItem();
2032  tableItem->setData(0,m.GetAprioriSample());
2033  }
2034  m_measureTable->setItem(row,column++,tableItem);
2035 
2036  if (m.GetAprioriLine() == Null) {
2037  tableItem = new QTableWidgetItem("Null");
2038  }
2039  else {
2040  tableItem = new QTableWidgetItem();
2041  tableItem->setData(0,m.GetAprioriLine());
2042  }
2043  m_measureTable->setItem(row,column++,tableItem);
2044 
2045  if (m.GetSampleResidual() == Null) {
2046  tableItem = new QTableWidgetItem(QString("Null"));
2047  }
2048  else {
2049  tableItem = new QTableWidgetItem();
2050  tableItem->setData(0,m.GetSampleResidual());
2051  }
2052  m_measureTable->setItem(row,column++,tableItem);
2053 
2054  if (m.GetLineResidual() == Null) {
2055  tableItem = new QTableWidgetItem(QString("Null"));
2056  }
2057  else {
2058  tableItem = new QTableWidgetItem();
2059  tableItem->setData(0,m.GetLineResidual());
2060  }
2061  m_measureTable->setItem(row,column++,tableItem);
2062 
2063  if (m.GetResidualMagnitude() == Null) {
2064  tableItem = new QTableWidgetItem(QString("Null"));
2065  }
2066  else {
2067  tableItem = new QTableWidgetItem();
2068  tableItem->setData(0,m.GetResidualMagnitude());
2069  }
2070  m_measureTable->setItem(row,column++,tableItem);
2071 
2072  double sampleShift = m.GetSampleShift();
2073  if (sampleShift == Null) {
2074  tableItem = new QTableWidgetItem(QString("Null"));
2075  }
2076  else {
2077  tableItem = new QTableWidgetItem();
2078  tableItem->setData(0,sampleShift);
2079  }
2080  m_measureTable->setItem(row,column++,tableItem);
2081 
2082  double lineShift = m.GetLineShift();
2083  if (lineShift == Null) {
2084  tableItem = new QTableWidgetItem(QString("Null"));
2085  }
2086  else {
2087  tableItem = new QTableWidgetItem();
2088  tableItem->setData(0,lineShift);
2089  }
2090  m_measureTable->setItem(row,column++,tableItem);
2091 
2092  double pixelShift = m.GetPixelShift();
2093  if (pixelShift == Null) {
2094  tableItem = new QTableWidgetItem(QString("Null"));
2095  }
2096  else {
2097  tableItem = new QTableWidgetItem();
2098  tableItem->setData(0,pixelShift);
2099  }
2100  m_measureTable->setItem(row,column++,tableItem);
2101 
2102  double goodnessOfFit = m.GetLogData(
2104  if (goodnessOfFit == Null) {
2105  tableItem = new QTableWidgetItem(QString("Null"));
2106  }
2107  else {
2108  tableItem = new QTableWidgetItem();
2109  tableItem->setData(0,goodnessOfFit);
2110  }
2111  m_measureTable->setItem(row,column++,tableItem);
2112 
2113  if (m.IsIgnored()) tableItem = new QTableWidgetItem("True");
2114  if (!m.IsIgnored()) tableItem = new QTableWidgetItem("False");
2115  m_measureTable->setItem(row,column++,tableItem);
2116 
2118  tableItem = new QTableWidgetItem("True");
2120  tableItem = new QTableWidgetItem("False");
2121  m_measureTable->setItem(row,column++,tableItem);
2122 
2123  tableItem = new QTableWidgetItem(
2125  m_measureTable->setItem(row,column,tableItem);
2126 
2127  // If reference measure set font on this row to bold
2128  if (m_editPoint->IsReferenceExplicit() &&
2129  (QString)m.GetCubeSerialNumber() == m_editPoint->GetReferenceSN()) {
2130  QFont font;
2131  font.setBold(true);
2132 
2133  for (int col=0; col<m_measureTable->columnCount(); col++)
2134  m_measureTable->item(row, col)->setFont(font);
2135  }
2136 
2137  }
2138 
2139  m_measureTable->resizeColumnsToContents();
2140  m_measureTable->resizeRowsToContents();
2141  m_measureTable->setSortingEnabled(true);
2142  m_measureWindow->show();
2143  }
2144 
2145 
2146 
2147  QString MatchTool::measureColumnToString(MatchTool::MeasureColumns column) {
2148  switch (column) {
2149  case FILENAME:
2150  return "FileName";
2151  case CUBESN:
2152  return "Serial #";
2153  case SAMPLE:
2154  return "Sample";
2155  case LINE:
2156  return "Line";
2157  case SAMPLERESIDUAL:
2158  return "Sample Residual";
2159  case LINERESIDUAL:
2160  return "Line Residual";
2161  case RESIDUALMAGNITUDE:
2162  return "Residual Magnitude";
2163  case SAMPLESHIFT:
2164  return "Sample Shift";
2165  case LINESHIFT:
2166  return "Line Shift";
2167  case PIXELSHIFT:
2168  return "Pixel Shift";
2169  case GOODNESSOFFIT:
2170  return "Goodness of Fit";
2171  case IGNORED:
2172  return "Ignored";
2173  case EDITLOCK:
2174  return "Edit Lock";
2175  case TYPE:
2176  return "Measure Type";
2177  case APRIORISAMPLE:
2178  return "Apriori Sample";
2179  case APRIORILINE:
2180  return "Apriori Line";
2181  }
2182  throw IException(IException::Programmer,
2183  "Invalid measure column passed to measureColumnToString", _FILEINFO_);
2184  }
2185 
2186 
2187 
2202  QString file = m_pointFiles[index];
2203 
2204  QString serial;
2205  try {
2206  serial = serialNumberList().SerialNumber(file);
2207  }
2208  catch (IException &e) {
2209  QString message = "Make sure the correct cube is opened.\n\n";
2210  message += e.toString();
2211  QMessageBox::critical(m_matchTool, "Error", message);
2212 
2213  // Set index of combo back to what it was before user selected new. Find the index
2214  // of current left measure.
2215  QString file = serialNumberList().FileName(m_leftMeasure->GetCubeSerialNumber());
2216  int i = m_leftCombo->findText(FileName(file).name());
2217  if (i < 0) i = 0;
2218  m_leftCombo->setCurrentIndex(i);
2219  return;
2220  }
2221 
2222  // Make sure to clear out leftMeasure before making a copy of the selected
2223  // measure.
2224  if (m_leftMeasure != NULL) {
2225  delete m_leftMeasure;
2226  m_leftMeasure = NULL;
2227  }
2228  m_leftMeasure = new ControlMeasure();
2229  // Find measure for each file
2230  *m_leftMeasure = *((*m_editPoint)[serial]);
2231 
2232  // If m_leftCube is not null, delete before creating new one
2233  if (m_leftCube != NULL) delete m_leftCube;
2234  m_leftCube = new Cube();
2235  m_leftCube->open(file);
2236 
2237  // Update left measure of pointEditor
2238  m_pointEditor->setLeftMeasure (m_leftMeasure, m_leftCube,
2239  m_editPoint->GetId());
2241 
2242  }
2243 
2244 
2257 
2258  QString file = m_pointFiles[index];
2259 
2260  QString serial;
2261  try {
2262  serial = serialNumberList().SerialNumber(file);
2263  }
2264  catch (IException &e) {
2265  QString message = "Make sure the correct cube is opened.\n\n";
2266  message += e.toString();
2267  QMessageBox::critical(m_matchTool, "Error", message);
2268 
2269  // Set index of combo back to what it was before user selected new. Find the index
2270  // of current left measure.
2271  QString file = serialNumberList().FileName(m_rightMeasure->GetCubeSerialNumber());
2272  int i = m_rightCombo->findText(FileName(file).name());
2273  if (i < 0) i = 0;
2274  m_rightCombo->setCurrentIndex(i);
2275  return;
2276  }
2277 
2278  // Make sure to clear out rightMeasure before making a copy of the selected
2279  // measure.
2280  if (m_rightMeasure != NULL) {
2281  delete m_rightMeasure;
2282  m_rightMeasure = NULL;
2283  }
2284  m_rightMeasure = new ControlMeasure();
2285  // Find measure for each file
2286  *m_rightMeasure = *((*m_editPoint)[serial]);
2287 
2288  // If m_leftCube is not null, delete before creating new one
2289  if (m_rightCube != NULL) delete m_rightCube;
2290  m_rightCube = new Cube();
2291  m_rightCube->open(file);
2292 
2293  // Update left measure of pointEditor
2294  m_pointEditor->setRightMeasure (m_rightMeasure,m_rightCube,
2295  m_editPoint->GetId());
2297 
2298  }
2299 
2300 
2301 
2302 
2319 
2320  // Set editLock measure box correctly
2321  m_lockLeftMeasure->setChecked(IsMeasureLocked(
2322  m_leftMeasure->GetCubeSerialNumber()));
2323  // Set ignore measure box correctly
2324  m_ignoreLeftMeasure->setChecked(m_leftMeasure->IsIgnored());
2325 
2326  QString s = "Reference: ";
2327  if (m_editPoint->IsReferenceExplicit() &&
2328  (QString(m_leftMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2329  s += "True";
2330  }
2331  else {
2332  s += "False";
2333  }
2334  m_leftReference->setText(s);
2335 
2336  s = "Measure Type: ";
2337  if (m_leftMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2338  if (m_leftMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2339  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2340  if (m_leftMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2341  m_leftMeasureType->setText(s);
2342 
2343  if (m_leftMeasure->GetSampleShift() == Null) {
2344  s = "Sample Shift: Null";
2345  }
2346  else {
2347  s = "Sample Shift: " + QString::number(m_leftMeasure->GetSampleShift());
2348  }
2349  m_leftSampShift->setText(s);
2350 
2351  if (m_leftMeasure->GetLineShift() == Null) {
2352  s = "Line Shift: Null";
2353  }
2354  else {
2355  s = "Line Shift: " + QString::number(m_leftMeasure->GetLineShift());
2356  }
2357  m_leftLineShift->setText(s);
2358 
2359  double goodnessOfFit = m_leftMeasure->GetLogData(
2361  if (goodnessOfFit == Null) {
2362  s = "Goodness of Fit: Null";
2363  }
2364  else {
2365  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2366  }
2367  m_leftGoodness->setText(s);
2368 
2369  }
2370 
2371 
2372 
2392 
2393  // Set editLock measure box correctly
2394  m_lockRightMeasure->setChecked(IsMeasureLocked(
2395  m_rightMeasure->GetCubeSerialNumber()));
2396  // Set ignore measure box correctly
2397  m_ignoreRightMeasure->setChecked(m_rightMeasure->IsIgnored());
2398 
2399  QString s = "Reference: ";
2400  if (m_editPoint->IsReferenceExplicit() &&
2401  (QString(m_rightMeasure->GetCubeSerialNumber()) == m_editPoint->GetReferenceSN())) {
2402  s += "True";
2403  }
2404  else {
2405  s += "False";
2406  }
2407 
2408  m_rightReference->setText(s);
2409 
2410  s = "Measure Type: ";
2411  if (m_rightMeasure->GetType() == ControlMeasure::Candidate) s+= "Candidate";
2412  if (m_rightMeasure->GetType() == ControlMeasure::Manual) s+= "Manual";
2413  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredPixel) s+= "RegisteredPixel";
2414  if (m_rightMeasure->GetType() == ControlMeasure::RegisteredSubPixel) s+= "RegisteredSubPixel";
2415  m_rightMeasureType->setText(s);
2416 
2417  if (m_rightMeasure->GetSampleShift() == Null) {
2418  s = "Sample Shift: Null";
2419  }
2420  else {
2421  s = "Sample Shift: " + QString::number(m_rightMeasure->GetSampleShift());
2422  }
2423  m_rightSampShift->setText(s);
2424 
2425  if (m_rightMeasure->GetLineShift() == Null) {
2426  s = "Line Shift: Null";
2427  }
2428  else {
2429  s = "Line Shift: " + QString::number(m_rightMeasure->GetLineShift());
2430  }
2431  m_rightLineShift->setText(s);
2432 
2433  double goodnessOfFit = m_rightMeasure->GetLogData(
2435  if (goodnessOfFit == Null) {
2436  s = "Goodness of Fit: Null";
2437  }
2438  else {
2439  s = "Goodness of Fit: " + QString::number(goodnessOfFit);
2440  }
2441  m_rightGoodness->setText(s);
2442 
2443  }
2444 
2445 
2446 
2457  bool MatchTool::eventFilter(QObject *o, QEvent *e) {
2458  if(e->type() != QEvent::Leave) return false;
2459  if(o == m_leftCombo->view()) {
2461  m_leftCombo->hidePopup();
2462  }
2463  if (o == m_rightCombo->view()) {
2465  m_rightCombo->hidePopup();
2466  }
2467  return true;
2468  }
2469 
2470 
2478  void MatchTool::paintViewport(MdiCubeViewport *mvp, QPainter *painter) {
2479  drawAllMeasurments (mvp,painter);
2480 
2481  }
2482 
2483 
2498 
2499  // Take care of drawing things on all viewPorts.
2500  // Calling update will cause the Tool class to call all registered tools
2501  // if point has been deleted, this will remove it from the main window
2502  MdiCubeViewport *mvp;
2503  for (int i=0; i<(int)cubeViewportList()->size(); i++) {
2504  mvp = (*(cubeViewportList()))[i];
2505  mvp->viewport()->update();
2506  }
2507  }
2508 
2531  void MatchTool::drawAllMeasurments(MdiCubeViewport *mvp, QPainter *painter) {
2532 
2533  // Make sure we have points to draw
2534  if ( (m_controlNet == NULL || m_controlNet->GetNumPoints() == 0) && m_newPoint == NULL &&
2535  m_editPoint == NULL)
2536  return;
2537 
2538  QString sn = serialNumber(mvp);
2539 // QString serialNumber = SerialNumber::Compose(*vp->cube(), true);
2540 
2541  // In the middle of creating a new point
2542  if (m_newPoint != NULL) {
2543  // and the selected point is in the image,
2544  if (m_newPoint->HasSerialNumber(sn)) {
2545  // find the measurement
2546  double samp = (*m_newPoint)[sn]->GetSample();
2547  double line = (*m_newPoint)[sn]->GetLine();
2548  int x, y;
2549  mvp->cubeToViewport(samp, line, x, y);
2550  // set point marker red
2551  QBrush brush(Qt::red);
2552  // set point marker bold - line width 2
2553  QPen pen(brush, 2);
2554  // draw the selected point in each image last so it's on top of the rest of the points
2555  painter->setPen(pen);
2556  painter->drawLine(x - 5, y, x + 5, y);
2557  painter->drawLine(x, y - 5, x, y + 5);
2558  }
2559  }
2560 
2561  // If viewport serial number not found in control net, return
2562  if (!m_controlNet->GetCubeSerials().contains(
2563  sn)) return;
2564 
2565 // if (!m_controlNet->GetCubeSerials().contains(
2566 // QString::fromStdString(sn))) return;
2567 // if (!serialNumberList().HasSerialNumber(sn)) return;
2568 
2569  QList<ControlMeasure *> measures =
2570  m_controlNet->GetMeasuresInCube(sn);
2571  // loop through all measures contained in this cube
2572  for (int i = 0; i < measures.count(); i++) {
2573  ControlMeasure *m = measures[i];
2574  // Find the measurments on the viewport
2575  double samp = m->GetSample();
2576  double line = m->GetLine();
2577  int x, y;
2578  mvp->cubeToViewport(samp, line, x, y);
2579  // if the point is ignored,
2580  if (m->Parent()->IsIgnored()) {
2581  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2582  }
2583  // point is not ignored, but measure matching this image is ignored,
2584  else if (m->IsIgnored()) {
2585  painter->setPen(QColor(255, 255, 0)); // set point marker yellow
2586  }
2587  else {
2588  painter->setPen(Qt::green); // set all other point markers green
2589  }
2590  // draw points
2591  painter->drawLine(x - 5, y, x + 5, y);
2592  painter->drawLine(x, y - 5, x, y + 5);
2593  }
2594  // if MatchTool is open,
2595  if (m_editPoint != NULL && m_newPoint == NULL) {
2596  // and the selected point is in the image,
2597  if (m_editPoint->HasSerialNumber(sn)) {
2598  // find the measurement
2599  double samp = (*m_editPoint)[sn]->GetSample();
2600  double line = (*m_editPoint)[sn]->GetLine();
2601  int x, y;
2602  mvp->cubeToViewport(samp, line, x, y);
2603  // set point marker red
2604  QBrush brush(Qt::red);
2605  // set point marker bold - line width 2
2606  QPen pen(brush, 2);
2607  // draw the selected point in each image last so it's on top of the rest of the points
2608  painter->setPen(pen);
2609  painter->drawLine(x - 5, y, x + 5, y);
2610  painter->drawLine(x, y - 5, x, y + 5);
2611  }
2612  }
2613  }
2614 
2615 
2616 
2631 
2632  if (m_templateModified) {
2633  int r = QMessageBox::warning(m_matchTool, tr("OK to continue?"),
2634  tr("The currently opened registration template has been modified.\n"
2635  "Save changes?"),
2636  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
2637  QMessageBox::Yes);
2638 
2639  if (r == QMessageBox::Yes)
2641  else if (r == QMessageBox::Cancel)
2642  return false;
2643  }
2644 
2645  return true;
2646  }
2647 
2648 
2649 
2656 
2657  if (!okToContinue())
2658  return;
2659 
2660  QString filename = QFileDialog::getOpenFileName(m_matchTool,
2661  "Select a registration template", ".",
2662  "Registration template files (*.def *.pvl);;All files (*)");
2663 
2664  if (filename.isEmpty())
2665  return;
2666 
2667  if (m_pointEditor->setTemplateFile(filename)) {
2668  loadTemplateFile(filename);
2669  }
2670  }
2671 
2672 
2673 
2679  void MatchTool::loadTemplateFile(QString fn) {
2680 
2681  QFile file(FileName((QString) fn).expanded());
2682  if (!file.open(QIODevice::ReadOnly)) {
2683  QString msg = "Failed to open template file \"" + fn + "\"";
2684  QMessageBox::warning(m_matchTool, "IO Error", msg);
2685  return;
2686  }
2687 
2688  QTextStream stream(&file);
2689  m_templateEditor->setText(stream.readAll());
2690  file.close();
2691 
2692  QScrollBar * sb = m_templateEditor->verticalScrollBar();
2693  sb->setValue(sb->minimum());
2694 
2695  m_templateModified = false;
2696  m_saveTemplateFile->setEnabled(false);
2697  m_templateFileNameLabel->setText("Template File: " + fn);
2698  }
2699 
2700 
2701 
2704  m_templateModified = true;
2705  m_saveTemplateFile->setEnabled(true);
2706  }
2707 
2708 
2709 
2712 
2713  if (!m_templateModified)
2714  return;
2715 
2716  QString filename =
2717  m_pointEditor->templateFileName();
2718 
2719  writeTemplateFile(filename);
2720  }
2721 
2722 
2723 
2726 
2727  QString filename = QFileDialog::getSaveFileName(m_matchTool,
2728  "Save registration template", ".",
2729  "Registration template files (*.def *.pvl);;All files (*)");
2730 
2731  if (filename.isEmpty())
2732  return;
2733 
2734  writeTemplateFile(filename);
2735  }
2736 
2737 
2738 
2744  void MatchTool::writeTemplateFile(QString fn) {
2745 
2746  QString contents = m_templateEditor->toPlainText();
2747 
2748  // catch errors in Pvl format when populating pvl object
2749  stringstream ss;
2750  ss << contents;
2751  try {
2752  Pvl pvl;
2753  ss >> pvl;
2754  }
2755  catch(IException &e) {
2756  QString message = e.toString();
2757  QMessageBox::warning(m_matchTool, "Error", message);
2758  return;
2759  }
2760 
2761  QString expandedFileName(
2762  FileName((QString) fn).expanded());
2763 
2764  QFile file(expandedFileName);
2765 
2766  if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2767  QString msg = "Failed to save template file to \"" + fn + "\"\nDo you "
2768  "have permission?";
2769  QMessageBox::warning(m_matchTool, "IO Error", msg);
2770  return;
2771  }
2772 
2773  // now save contents
2774  QTextStream stream(&file);
2775  stream << contents;
2776  file.close();
2777 
2778  if (m_pointEditor->setTemplateFile(fn)) {
2779  m_templateModified = false;
2780  m_saveTemplateFile->setEnabled(false);
2781  m_templateFileNameLabel->setText("Template File: " + fn);
2782  }
2783  }
2784 
2785 
2786 
2801  try{
2802  // Get the template file from the ControlPointEditor object
2803  Pvl templatePvl(m_pointEditor->templateFileName());
2804  // Create registration dialog window using PvlEditDialog class
2805  // to view and/or edit the template
2806  PvlEditDialog registrationDialog(templatePvl);
2807  registrationDialog.setWindowTitle("View or Edit Template File: "
2808  + templatePvl.fileName());
2809  registrationDialog.resize(550,360);
2810  registrationDialog.exec();
2811  }
2812  catch (IException &e) {
2813  QString message = e.toString();
2814  QMessageBox::information(m_matchTool, "Error", message);
2815  }
2816  }
2817 
2818 
2819 
2827  m_pointEditor->saveChips();
2828  }
2829 
2830 
2831 
2832  void MatchTool::showHideTemplateEditor() {
2833 
2834  if (!m_templateEditorWidget)
2835  return;
2836 
2837  m_templateEditorWidget->setVisible(!m_templateEditorWidget->isVisible());
2838  }
2839 
2840 
2841 
2854  void MatchTool::updatePointInfo(QString pointId) {
2855  if (m_editPoint == NULL) return;
2856  if (pointId != m_editPoint->GetId()) return;
2857  // The edit point has been changed by SetApriori, so m_editPoint needs
2858  // to possibly update some values. Need to retain measures from m_editPoint
2859  // because they might have been updated, but not yet saved to the network
2860  // ("Save Point").
2861  ControlPoint *updatedPoint = m_controlNet->GetPoint(pointId);
2862  m_editPoint->SetEditLock(updatedPoint->IsEditLocked());
2863  m_editPoint->SetIgnored(updatedPoint->IsIgnored());
2864 
2865  // Set EditLock box correctly
2866  m_lockPoint->setChecked(m_editPoint->IsEditLocked());
2867 
2868  // Set ignore box correctly
2869  m_ignorePoint->setChecked(m_editPoint->IsIgnored());
2870 
2871  }
2872 
2873 
2874 
2891 
2892  // Check point being edited, make sure it still exists, if not ???
2893  // Update ignored checkbox??
2894  if (m_editPoint != NULL) {
2895  try {
2896  QString id = m_ptIdValue->text().remove("Point ID: ");
2897  m_controlNet->GetPoint(id);
2898  }
2899  catch (IException &) {
2900  delete m_editPoint;
2901  m_editPoint = NULL;
2902  emit editPointChanged();
2903 // m_matchTool->setShown(false);
2904 // m_measureWindow->setShown(false);
2905  }
2906  }
2907 
2909  }
2910 
2911 
2912 
2919 
2920  QColor qc = Qt::red;
2921  QPalette p = m_savePoint->palette();
2922  p.setColor(QPalette::ButtonText,qc);
2923  m_savePoint->setPalette(p);
2924 
2925  }
2926 
2927 
2928 
2941  bool MatchTool::IsMeasureLocked (QString serialNumber) {
2942 
2943  if (m_editPoint == NULL) return false;
2944 
2945  // Reference implicitly editLocked
2946  if (m_editPoint->IsEditLocked() && m_editPoint->IsReferenceExplicit() &&
2947  (m_editPoint->GetReferenceSN() == serialNumber)) {
2948  return true;
2949  }
2950  // Return measures explicit editLocked value
2951  else {
2952  return m_editPoint->GetMeasure(serialNumber)->IsEditLocked();
2953  }
2954 
2955  }
2956 
2957 
2958 
2965  FileName config("$HOME/.Isis/qview/MatchTool.config");
2966  QSettings settings(config.expanded(),
2967  QSettings::NativeFormat);
2968  QPoint pos = settings.value("pos", QPoint(300, 100)).toPoint();
2969  QSize size = settings.value("size", QSize(900, 500)).toSize();
2970  m_matchTool->resize(size);
2971  m_matchTool->move(pos);
2972  }
2973 
2974 
2982  /*We do not want to write the settings unless the window is
2983  visible at the time of closing the application*/
2984  if (!m_matchTool->isVisible()) return;
2985  FileName config("$HOME/.Isis/qview/MatchTool.config");
2986  QSettings settings(config.expanded(),
2987  QSettings::NativeFormat);
2988  settings.setValue("pos", m_matchTool->pos());
2989  settings.setValue("size", m_matchTool->size());
2990  }
2991 
2992 
2993 
2994  void MatchTool::enterWhatsThisMode() {
2995  QWhatsThis::enterWhatsThisMode();
2996  }
2997 
2998 
2999  void MatchTool::clearEditPoint() {
3000  m_editPoint = NULL;
3001  }
3002 
3003 
3004 
3005  void MatchTool::showHelp() {
3006 
3007  QDialog *helpDialog = new QDialog(m_matchTool);
3008  helpDialog->setWindowTitle("Match Tool Help");
3009 
3010  QVBoxLayout *mainLayout = new QVBoxLayout;
3011  helpDialog->setLayout(mainLayout);
3012 
3013  QLabel *matchTitle = new QLabel("<h2>Match Tool</h2>");
3014  mainLayout->addWidget(matchTitle);
3015 
3016  QLabel *matchSubtitle = new QLabel("A tool for interactively measuring and editing sample/line "
3017  "registration points between cubes. These "
3018  "points contain sample, line postions only, no latitude or "
3019  "longitude values are used or recorded.");
3020  matchSubtitle->setWordWrap(true);
3021  mainLayout->addWidget(matchSubtitle);
3022 
3023  QTabWidget *tabArea = new QTabWidget;
3024  tabArea->setDocumentMode(true);
3025  mainLayout->addWidget(tabArea);
3026 
3027  // TAB 1 - Overview
3028  QScrollArea *overviewTab = new QScrollArea;
3029  overviewTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3030  overviewTab->setWidgetResizable(true);
3031  QWidget *overviewContainer = new QWidget;
3032  QVBoxLayout *overviewLayout = new QVBoxLayout;
3033  overviewContainer->setLayout(overviewLayout);
3034 
3035  QLabel *purposeTitle = new QLabel("<h2>Purpose</h2>");
3036  overviewLayout->addWidget(purposeTitle);
3037 
3038  QLabel *purposeText = new QLabel("<p>This tool is for recording and editing registration "
3039  "points measured between cubes displayed in the <i>qview</i> main window.</p> <p>The "
3040  "recorded registration points are sample and line pixel coordinates only. Therefore, this "
3041  "tool can be used on any images including ones that do not contain a camera model "
3042  "(i.e, The existence of the Isis Instrument Group on the image labels is not required). "
3043  "This also means that the tool differs from the <i>qnet</i> control point network "
3044  "application in that no latitude or longitude values are ever used or recorded "
3045  "(regardless if the image has a camera model in Isis).</p>"
3046  "<p>The output control point network that this tool generates is primarily used 1) as "
3047  "input for an image-wide sample/line translation to register one image to another by "
3048  "'moving' pixel locations - refer to the documentation for applications such as "
3049  "<i>translate</i> and <i>warp</i>, or 2) to export the file and use the recorded "
3050  "measurements in other spreadsheet or plotting packages to visualize magnitude "
3051  "and direction of varying translations of the images relative to one another.</p> "
3052  "<p>An automated version of this match tool is the <i>coreg</i> application. This tool "
3053  "can be used to visually evaluate and edit the control point network created by "
3054  "<i>coreg</i>.</p> "
3055  "<p>The format of the output point network file is binary. This tool uses the Isis control "
3056  " network framework to create, co-register and save all control points and pixel "
3057  "measurements. The application <i>cnetbin2pvl</i> can be used to convert from binary to "
3058  "a readable PVL format."
3059  "<p>The Mouse Button functions are: (same as <i>qnet</i>)<ul><li>Modify Point=Left</li> "
3060  "<li>Delete Point=Middle</li><li>Create New Point=Right</li></ul></p>"
3061  "<p>Control Points are drawn on the associated displayed cubes with the following colors: "
3062  "Green=Valid registration point; Yellow=Ignored point; Red=Active point being edited");
3063  purposeText->setWordWrap(true);
3064  overviewLayout->addWidget(purposeText);
3065 
3066  overviewTab->setWidget(overviewContainer);
3067 
3068  // TAB 2 - Quick Start
3069  QScrollArea *quickTab = new QScrollArea;
3070  quickTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3071  quickTab->setWidgetResizable(true);
3072  QWidget *quickContainer = new QWidget;
3073  QVBoxLayout *quickLayout = new QVBoxLayout;
3074  quickContainer->setLayout(quickLayout);
3075 
3076  QLabel *quickTitle = new QLabel("<h2>Quick Start</h2>");
3077  quickLayout->addWidget(quickTitle);
3078 
3079  QLabel *quickSubTitle = new QLabel("<h3>Preparation:</h3>");
3080  quickLayout->addWidget(quickSubTitle);
3081 
3082  QLabel *quickPrep = new QLabel("<p><ul>"
3083  "<li>Open the cubes with overlapping areas for choosing control points</li>"
3084  "<li>Choose the match tool <img src=\"" + toolIconDir() +
3085  "/stock_draw-connector-with-arrows.png\" width=22 height=22> "
3086  "from the toolpad on the right side of the <i>qview</i> main window</li>");
3087  quickPrep->setWordWrap(true);
3088  quickLayout->addWidget(quickPrep);
3089 
3090  QLabel *morePrep = new QLabel("<p>Once the Match tool is activated the tool bar at the top "
3091  "of the main window contains file action buttons and a help button:");
3092  morePrep->setWordWrap(true);
3093  quickLayout->addWidget(morePrep);
3094 
3095  QLabel *fileButtons = new QLabel("<p><ul>"
3096  "<li><img src=\"" + toolIconDir() + "/fileopen.png\" width=22 height=22> Open an existing "
3097  "control network <b>Note:</b> If you do not open an existing network, a new one will "
3098  "be created</li>"
3099  "<li><img src=\"" + toolIconDir() + "/mActionFileSaveAs.png\" width=22 height=22> Save "
3100  "control network as ...</li>"
3101  "<li><img src=\"" + toolIconDir() + "/mActionFileSave.png\" width=22 height=22> Save "
3102  "control network to current file</li>"
3103  "<li><img src=\"" + toolIconDir() + "/help-contents.png\" width=22 height=22> Show Help "
3104  "</li></ul></p>");
3105  fileButtons->setWordWrap(true);
3106  quickLayout->addWidget(fileButtons);
3107 
3108  QLabel *quickFunctionTitle = new QLabel("<h3>Cube Viewport Functions:</h3>");
3109  quickLayout->addWidget(quickFunctionTitle);
3110 
3111  QLabel *quickFunction = new QLabel(
3112  "The match tool window will be shown once "
3113  "you click in a cube viewport window using one of the following "
3114  "mouse functions. <b>Note:</b> Existing control points are drawn on the cube viewports");
3115  quickFunction->setWordWrap(true);
3116  quickLayout->addWidget(quickFunction);
3117 
3118  QLabel *quickDesc = new QLabel("<p><ul>"
3119  "<li>Left Click - Modify the control point closest to the click <b>Note:</b> "
3120  "All cubes in the control point must be displayed before loading the point</li>"
3121  "<li>Middle Click - Delete the control point closest to the click</li>"
3122  "<li>Right Click - Create a new control point at the click location</li></ul></p>");
3123  quickDesc->setWordWrap(true);
3124  quickDesc->setOpenExternalLinks(true);
3125  quickLayout->addWidget(quickDesc);
3126 
3127  quickTab->setWidget(quickContainer);
3128 
3129  // TAB 3 - Control Point Editing
3130  QScrollArea *controlPointTab = new QScrollArea;
3131  controlPointTab->setWidgetResizable(true);
3132  controlPointTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3133  QWidget *controlPointContainer = new QWidget;
3134  QVBoxLayout *controlPointLayout = new QVBoxLayout;
3135  controlPointContainer->setLayout(controlPointLayout);
3136 
3137  QLabel *controlPointTitle = new QLabel("<h2>Control Point Editing</h2>");
3138  controlPointLayout->addWidget(controlPointTitle);
3139 
3140  QLabel *mouseLabel = new QLabel("<p><h3>When the \"Match\" tool "
3141  "is activated, the mouse buttons have the following function in the "
3142  "cube viewports of the main qview window:</h3>");
3143  mouseLabel->setWordWrap(true);
3144  mouseLabel->setScaledContents(true);
3145  controlPointLayout->addWidget(mouseLabel);
3146 
3147  QLabel *controlPointDesc = new QLabel("<ul>"
3148  "<li>Left click - Edit the closest control point <b>Note:</b> "
3149  "All cubes in the control point must be displayed before loading the point</li>"
3150  "<li>Middle click - Delete the closest control point</li>"
3151  "<li>Right click - Create new control point at cursor location. This will bring up a new "
3152  "point dialog which allows you to enter a point id and will list all cube viewports, "
3153  "highlighting cubes where the point has been chosen by clicking on the cube's viewport. "
3154  "When the desired cubes have been chosen, select the \"Done\" button which will load the "
3155  "control point into the control point editor window which will allow the control measure "
3156  "positions to be refined.</li>");
3157  controlPointDesc->setWordWrap(true);
3158  controlPointLayout->addWidget(controlPointDesc);
3159 
3160  QLabel *controlPointEditing = new QLabel(
3161  "<h4>Changing Control Measure Locations</h4>"
3162  "<p>Both the left and right control measure positions can be adjusted by:"
3163  "<ul>"
3164  "<li>Move the cursor location under the crosshair by clicking the left mouse "
3165  "button</li>"
3166  "<li>Move 1 pixel at a time by using arrow keys on the keyboard</li>"
3167  "<li>Move 1 pixel at a time by using arrow buttons above the right and left views</li>"
3168  "</ul></p>"
3169  "<h4>Other Point Editor Functions</h4>"
3170  "<p>Along the right border of the window:</p>"
3171  "<ul>"
3172  "<li><strong>Link Zoom</strong> This will link the two small viewports together when "
3173  "zooming (ie. If this is checked, if the left view is zoomed, the right view will "
3174  "match the left view's zoom factor. "
3175  "<b>Note:</b> Zooming is controlled from the left view.</li>"
3176  "<li><strong>No Rotate:</strong> Turn off the rotation and bring right view back to "
3177  "its original orientation</li>"
3178  "<li><strong>Rotate:</strong> Rotate the right view using either the dial "
3179  "or entering degrees </li>"
3180  "<li><strong>Show control points:</strong> Draw crosshairs at all control "
3181  "point locations visible within the view</li>"
3182  "<li><strong>Show crosshair:</strong> Show a red crosshair across the entire "
3183  "view</li>"
3184  "<li><strong>Circle:</strong> Draw circle which may help center measure "
3185  "on a crater</li></ul"
3186  "<p>Below the left view:</p>"
3187  "<ul><li><strong>Blink controls:</strong> Blink the left and right view in the "
3188  "left view window using the \"Blink Start\" button <img src=\"" + toolIconDir() +
3189  "/blinkStart.png\" width=22 height=22> and \"Blink Stop\" button <img src=\"" +
3190  toolIconDir() + "/blinkStop.png\" width=22 height=22>. The arrow keys above the left "
3191  "and right views and the keyboard arrow keys may be used to move the both views while "
3192  "blinking.</li>"
3193  "<li><strong>Register:</strong> Sub-pixel register the right view to "
3194  "the left view. A default registration template is used for setting parameters "
3195  "passed to the sub-pixel registration tool. The user may load in a predefined "
3196  "template or edit the current loaded template to influence successful "
3197  "co-registration results. For more information regarding the pattern matching "
3198  "functionlity or how to create a parameter template, refer to the Isis PatternMatch "
3199  "document and the <i>autoregtemplate</i> application.</li>"
3200  "<li><strong>Save Measures:</strong> Save the two control measures using the sample, "
3201  "line positions under the crosshairs.</li>"
3202  "<li><strong>Save Point:</strong> Save the control point to the control network.</li>"
3203  "</ul>");
3204  controlPointEditing->setWordWrap(true);
3205  controlPointLayout->addWidget(controlPointEditing);
3206 
3207  controlPointTab->setWidget(controlPointContainer);
3208 
3209  // TAB 4 - Coreg Guidance
3210  QScrollArea *coregTab = new QScrollArea;
3211  coregTab->setWidgetResizable(true);
3212  coregTab->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3213  QWidget *coregContainer = new QWidget;
3214  QVBoxLayout *coregLayout = new QVBoxLayout;
3215  coregContainer->setLayout(coregLayout);
3216 
3217  QLabel *coregTitle = new QLabel("<h2>Coreg Guidance</h2>");
3218  coregLayout->addWidget(coregTitle);
3219 
3220  QLabel *coregDesc = new QLabel("<p>When opening control networks created by <i>coreg</i>, "
3221  "there are some things to keep in mind. First, all control points must have the same "
3222  "reference measure (this is the image filename passed to the <i>coreg</i> 'match' parameter)."
3223  "<p>In order to retain the integrity of the input <i>coreg</i> network, you cannot change "
3224  "which image is the reference measure on any of the existing points. "
3225  "<p>When creating a new control point to add to the <i>coreg</i> network, this tool will "
3226  "automatically set the reference measure to the same image as the other control points in "
3227  "the network as long as the reference image was one of the images selected with "
3228  "the right mouse button from the new point dialog. If this image was not selected when "
3229  "creating a new point, it "
3230  "does not contain a required measurement, therefore, you will get an error and the new "
3231  "point will not be created.</p> <p>The reference measure is always loaded on the left side "
3232  "of the control point editor. If you load a measure that is not the reference measure "
3233  "on the left side and try to save the point, you will receive an error message. You will "
3234  "need to move the reference measure back to the left side before saving the control point."
3235  "</p><p><b>Note:</b> This error checking will not happen on control networks created by "
3236  "<i>coreg</i> prior to Isis3.4.2. For older <i>coreg</i> control networks the user must be "
3237  "aware and make sure the correct image is set to the same <i>coreg</i> reference measure.");
3238  coregDesc->setWordWrap(true);
3239  coregDesc->setScaledContents(true);
3240  coregLayout->addWidget(coregDesc);
3241 
3242  coregTab->setWidget(coregContainer);
3243 
3244  tabArea->addTab(overviewTab, "&Overview");
3245  tabArea->addTab(quickTab, "&Quick Start");
3246  tabArea->addTab(controlPointTab, "&Control Point Editing");
3247  tabArea->addTab(coregTab, "&Coreg Guidance");
3248 
3249  QHBoxLayout *buttonsLayout = new QHBoxLayout;
3250  // Flush the buttons to the right
3251  buttonsLayout->addStretch();
3252 
3253  QPushButton *closeButton = new QPushButton("&Close");
3254  closeButton->setIcon(QPixmap(toolIconDir() + "/guiStop.png"));
3255  closeButton->setDefault(true);
3256  connect(closeButton, SIGNAL(clicked()),
3257  helpDialog, SLOT(close()));
3258  buttonsLayout->addWidget(closeButton);
3259 
3260  mainLayout->addLayout(buttonsLayout);
3261 
3262  helpDialog->show();
3263 
3264 
3265  }
3266 
3267 
3268 
3276 
3277  if (m_editPoint) {
3278  // If point changed or if a new point, prompt for saving.
3279  if ( m_controlNet->GetNumPoints() == 0 ||
3280  !m_controlNet->ContainsPoint(m_editPoint->GetId())) {
3281  QString message = "\n\nDo you want to save the point in the editor?";
3282  int response = QMessageBox::question(m_matchTool, "Save point in editor", message,
3283  QMessageBox::Yes | QMessageBox::No,
3284  QMessageBox::Yes);
3285  if (response == QMessageBox::Yes) {
3286  savePoint();
3287  }
3288  }
3289  }
3290 
3291  if (m_controlNet && m_controlNet->GetNumPoints() != 0 && m_netChanged) {
3292  QString message = "The currently open control net has changed. Do you want to save?";
3293  int response = QMessageBox::question(m_matchTool, "Save current control net?",
3294  message,
3295  QMessageBox::Yes | QMessageBox::No,
3296  QMessageBox::Yes);
3297  // Yes: Save old net, so return without opening network.
3298  if (response == QMessageBox::Yes) {
3299  saveAsNet();
3300  }
3301  }
3302  }
3303 }
3304