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