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