1 #include "MosaicMainWindow.h"
3 #include <QApplication>
10 #include <QProgressBar>
11 #include <QPushButton>
13 #include <QScrollArea>
15 #include <QVBoxLayout>
19 #include "FileDialog.h"
20 #include "MosaicController.h"
21 #include "ImageFileListWidget.h"
22 #include "ImageTreeWidgetItem.h"
24 #include "MosaicSceneWidget.h"
25 #include "Projection.h"
26 #include "ProjectionFactory.h"
32 MosaicMainWindow::MosaicMainWindow(QString title,
QWidget *parent) :
33 MainWindow(title, parent),
34 m_settings(FileName(
"$HOME/.Isis/qmos/qmos.config").expanded(),
35 QSettings::NativeFormat) {
38 m_settingsMenu = NULL;
41 setObjectName(
"MosaicMainWindow");
43 m_controllerVisible =
false;
45 setWindowTitle(title);
47 m_permToolbar =
new QToolBar(
"Standard Tools",
this);
48 m_permToolbar->setObjectName(
"Standard Tools");
49 m_permToolbar->setWhatsThis(
"This area contains options that are always "
50 "present in qmos, regardless of whether or not a project is open. "
51 "These options are also found in the File menu.");
52 addToolBar(m_permToolbar);
54 m_activeToolbar =
new QToolBar(
"Active Tool",
this);
55 m_activeToolbar->setObjectName(
"Active Tool");
56 m_activeToolbar->setWhatsThis(
"The currently selected tool's options will "
57 "show up here. Not all tools have options.");
58 addToolBar(m_activeToolbar);
60 statusBar()->showMessage(
"Ready");
62 m_toolpad =
new ToolPad(
"Tool Pad",
this);
63 m_toolpad->setObjectName(
"Tool Pad");
66 addToolBar(Qt::RightToolBarArea, m_toolpad);
70 m_fileListDock =
new QDockWidget(
"File List",
this, Qt::SubWindow);
71 m_fileListDock->setObjectName(
"FileListDock");
72 m_fileListDock->setFeatures(QDockWidget::DockWidgetFloatable |
73 QDockWidget::DockWidgetMovable |
74 QDockWidget::DockWidgetClosable);
75 m_fileListDock->setWhatsThis(
"This contains the mosaic file list.");
77 m_mosaicPreviewDock =
new QDockWidget(
"Mosaic World View",
79 m_mosaicPreviewDock->setObjectName(
"MosaicPreviewDock");
80 m_mosaicPreviewDock->setFeatures(QDockWidget::DockWidgetFloatable |
81 QDockWidget::DockWidgetMovable |
82 QDockWidget::DockWidgetClosable);
83 m_mosaicPreviewDock->setWhatsThis(
"This contains a zoomed out view of the "
86 addDockWidget(Qt::LeftDockWidgetArea, m_fileListDock);
87 addDockWidget(Qt::LeftDockWidgetArea, m_mosaicPreviewDock);
91 setCentralWidget(
new QWidget());
92 centralWidget()->setLayout(
new QHBoxLayout());
94 m_mosaicController = NULL;
97 installEventFilter(
this);
103 bool projectLoaded =
false;
105 foreach (QString argument, args) {
106 QRegExp cubeName(
".*\\.cub$", Qt::CaseInsensitive);
107 QRegExp cubeListName(
".*\\.(lis|txt)$", Qt::CaseInsensitive);
108 QRegExp projectName(
".*\\.mos$", Qt::CaseInsensitive);
111 if (cubeName.exactMatch(argument)) {
112 filesToOpen.append(argument);
114 else if (cubeListName.exactMatch(argument)) {
115 TextFile fileList(argument);
118 while(fileList.GetLine(line)) {
119 filesToOpen.append(line);
122 else if (projectName.exactMatch(argument)) {
123 if (!projectLoaded) {
124 loadProject(argument);
125 projectLoaded =
true;
128 QMessageBox::warning(
this,
"Multiple Projects Specified",
129 "qmos can only open one project at a time. The first project "
130 "specified is the one that will be used.");
134 catch (IException &e) {
135 QMessageBox::warning(
this,
"Problem Loading File", e.what());
139 m_lastOpenedFile = QFileInfo(
".");
141 if (!filesToOpen.isEmpty())
142 openFiles(filesToOpen);
174 m_fileMenu = menuBar()->addMenu(
"&File");
179 open->setText(
"Open Cube...");
180 open->setIcon(QPixmap(QString::fromStdString(iconDir.c_str()) +
"/fileopen.png"));
181 connect(
open, SIGNAL(triggered()),
this, SLOT(
open()));
184 openList->setText(
"Open Cube List...");
185 openList->setIcon(QPixmap(QString::fromStdString(iconDir.c_str()) +
"/mActionHelpContents.png"));
191 saveProject->setIcon(QPixmap(QString::fromStdString(iconDir.c_str()) +
"/mActionFileSave.png"));
197 saveProjectAs->setIcon(QPixmap(QString::fromStdString(iconDir.c_str()) +
"/mActionFileSaveAs.png"));
203 loadProject->setIcon(QPixmap(QString::fromStdString(iconDir.c_str()) +
"/mActionExportMapServer.png"));
207 closeProject->setText(
"Close Project");
208 m_actionsRequiringOpen.append(closeProject);
209 connect(closeProject, SIGNAL(triggered()),
this, SLOT(closeMosaic()));
212 exit->setText(
"Exit");
213 exit->setIcon(QIcon::fromTheme(
"window-close"));
214 connect(exit, SIGNAL(triggered()),
this, SLOT(close()));
216 QAction *actionRequiringOpen = NULL;
217 foreach(actionRequiringOpen, m_actionsRequiringOpen) {
218 actionRequiringOpen->setEnabled(
false);
221 QAction *actionRequiringClosed = NULL;
222 foreach(actionRequiringClosed, m_actionsRequiringClosed) {
223 actionRequiringClosed->setEnabled(
true);
226 m_fileMenu->addAction(
open);
228 m_fileMenu->addSeparator();
232 m_fileMenu->addAction(closeProject);
233 m_fileMenu->addSeparator();
234 m_exportMenu = m_fileMenu->addMenu(
"&Export");
235 m_fileMenu->addAction(exit);
240 permanentToolBar()->addSeparator();
241 permanentToolBar()->addAction(
open);
242 permanentToolBar()->addAction(
openList);
243 permanentToolBar()->addSeparator();
245 m_viewMenu = menuBar()->addMenu(
"&View");
246 m_settingsMenu = menuBar()->addMenu(
"&Settings");
247 QMenu *helpMenu = menuBar()->addMenu(
"&Help");
249 QAction *activateWhatsThisAct =
new QAction(
"&What's This",
this);
250 activateWhatsThisAct->setShortcut(Qt::SHIFT | Qt::Key_F1);
251 activateWhatsThisAct->setIcon(
252 QPixmap(
FileName(
"$ISISROOT/appdata/images/icons/contexthelp.png").expanded()));
253 activateWhatsThisAct->setToolTip(
"Activate What's This and click on parts "
254 "this program to see more information about them");
255 connect(activateWhatsThisAct, SIGNAL(triggered()),
256 this, SLOT(enterWhatsThisMode()));
259 showHelpAct->setIcon(QIcon::fromTheme(
"help-contents"));
260 connect(showHelpAct, SIGNAL(triggered()),
261 this, SLOT(showHelp()));
263 helpMenu->addAction(activateWhatsThisAct);
264 helpMenu->addAction(showHelpAct);
266 updateMenuVisibility();
277 filterList.append(
"Isis cubes (*.cub)");
278 filterList.append(
"All Files (*)");
280 QDir directory = m_lastOpenedFile.dir();
281 QStringList selected = QFileDialog::getOpenFileNames(
this,
"Open Cubes",
282 directory.path(), filterList.join(
";;"));
284 if (!selected.empty()) {
285 m_lastOpenedFile = QFileInfo(selected.last());
291 void MosaicMainWindow::enterWhatsThisMode() {
292 QWhatsThis::enterWhatsThisMode();
296 void MosaicMainWindow::showHelp() {
299 QVBoxLayout *mainLayout =
new QVBoxLayout;
300 helpDialog->setLayout(mainLayout);
303 QLabel *qmosTitle =
new QLabel(
"<h1>qmos</h1>");
305 mainLayout->addWidget(qmosTitle);
307 QLabel *qmosSubtitle =
new QLabel(
"A tool for visualizing image "
308 "footprints for a mosaic.");
309 mainLayout->addWidget(qmosSubtitle);
311 QTabWidget *tabArea =
new QTabWidget;
312 mainLayout->addWidget(tabArea);
314 QScrollArea *overviewTab =
new QScrollArea;
318 QVBoxLayout *overviewLayout =
new QVBoxLayout;
319 overviewContainer->setLayout(overviewLayout);
321 QLabel *purposeTitle =
new QLabel(
"<h2>Purpose</h2>");
322 overviewLayout->addWidget(purposeTitle);
324 QLabel *purposeText =
new QLabel(
"<p>qmos is designed "
325 "specifically for visualizing large amounts of images, how images "
326 "overlap, where control points lie on the images, and how jigsaw has "
327 "moved control points.");
328 purposeText->setWordWrap(
true);
329 overviewLayout->addWidget(purposeText);
331 QLabel *shortcomingsTitle =
new QLabel(
"<h2>Known Issues</h2>");
332 overviewLayout->addWidget(shortcomingsTitle);
334 QLabel *shortcomingsText =
new QLabel(
"<p>The known shortcomings of qmos "
336 "<li>All input files are read-only, you cannot edit your input "
338 "<li>Large control networks are slow and memory intensive to load</li>"
339 "<li>Show cube DN data is extremely slow</li>"
340 "<li>Warnings are not displayed graphically</li>"
341 "<li>Zooming in too far causes you to pan off of your data</li></ul>");
342 shortcomingsText->setWordWrap(
true);
343 overviewLayout->addWidget(shortcomingsText);
345 overviewTab->setWidget(overviewContainer);
347 QScrollArea *preparationsTab =
new QScrollArea;
350 QVBoxLayout *preparationsLayout =
new QVBoxLayout;
351 preparationsContainer->setLayout(preparationsLayout);
353 QLabel *preparationTitle =
new QLabel(
"<h2>Before Using qmos</h2>");
354 preparationsLayout->addWidget(preparationTitle);
356 QLabel *preparationText =
new QLabel(
"<p>qmos only supports files which "
357 "have latitude and longitude information associated with them. Global "
358 "projections are also not supported. If your files meet these "
359 "requirements, it is beneficial to run a couple of Isis programs on "
360 "your files before loading them into qmos. The programs you should run "
362 "<li><i>camstats from=future_input_to_qmos.cub attach=true "
363 "sinc=... linc=...</i></li>"
364 " <br>This enables qmos to give you the emission angle, incidence "
365 "angle, phase angle, and resolution in the <b>File List</b>"
366 "<li><i>footprintinit from=future_input_to_qmos.cub "
367 "sinc=... linc=...</i></li>"
368 " <br>Running <i>footprintinit</i> beforehand will significantly speed up loading images "
369 "into qmos.<br/><br/>"
370 "The footprint is created by \"walking\" around the valid image data, and qmos reprojects "
371 "the footprint according to the loaded map file.<br/><br/>"
372 "Qmos displays the footprints, and optionally the image data and map grid to the default "
373 "IAU radius, unless the radius is specified within the loaded map file.<br/><br/>"
374 "For Level1 (raw camera space) images, when calculating the "
375 "footprint polygons, footprintinit refers to the image labels "
376 "and uses the SPICE kernels and the shape model (DEM if one "
377 "exists and is specified, otherwise, the IAU sphere or "
378 "ellipsoid is used). Refer to spiceinit for more information "
379 "on loading SPICE onto Level0 and Level1 images. This enables "
380 "qmos to use the given footprints instead of trying to "
381 "calculate its own. The 'linc' and 'sinc' parameters can have a "
382 "significant effect on your image's footprint. Also, images "
383 "without footprints cannot be opened more than one at a time. "
384 "Running footprintinit will significantly speed up loading "
385 "images into qmos.<br>"
386 "For Level2 images, do not run footprintinit. The footprint "
387 "polygon is created by 'walking' around the valid image data. "
388 "qmos 'reprojects' the footprint polygons according to the "
389 "loaded Map File.<br>"
391 preparationText->setWordWrap(
true);
392 preparationsLayout->addWidget(preparationText);
394 preparationsTab->setWidget(preparationsContainer);
396 QScrollArea *projectsTab =
new QScrollArea;
399 QVBoxLayout *projectsLayout =
new QVBoxLayout;
400 projectsContainer->setLayout(projectsLayout);
402 QLabel *projectsTitle =
new QLabel(
"<h2>Projects</h2>");
403 projectsLayout->addWidget(projectsTitle);
405 QLabel *projectsText =
new QLabel(
"<p>The contents of qmos can be saved as a project file, "
406 "which allows the user to restore back to the previous state at any given time. The stored "
407 "files or qmos project files must have a \".mos\" extension.<br/><br/>"
408 "These project files store the input file location information and their qmos properties "
409 "(color, group information, and other attributes).<br/><br/>"
410 "When you initially open qmos you start with a blank project. "
411 "To load a project, you can specify the project "
412 "file's name on the command line (qmos myProject.mos) or go to "
413 "File -> Load Project after qmos is started. When "
414 "loading a project, all current data in the qmos window is lost (your cubes are closed)."
415 "These project files are relatively small files. You can "
416 "save your current project any time by going to File -> Save Project. ");
417 projectsText->setWordWrap(
true);
418 projectsLayout->addWidget(projectsText);
420 projectsTab->setWidget(projectsContainer);
422 if (m_controllerVisible) {
423 tabArea->addTab(overviewTab,
"&Overview");
424 tabArea->addTab(preparationsTab,
"Preparing &Input Cubes");
428 tabArea->addTab(MosaicSceneWidget::getLongHelp(centralWidget()),
430 tabArea->addTab(MosaicSceneWidget::getPreviewHelp(m_mosaicPreviewDock),
431 "Mosaic &World View");
433 tabArea->addTab(MosaicSceneWidget::getMapHelp(),
435 tabArea->addTab(projectsTab,
"&Project Files");
437 tabArea->addTab(MosaicSceneWidget::getControlNetHelp(),
438 "&Control Networks");
439 tabArea->addTab(MosaicSceneWidget::getGridHelp(),
443 tabArea->addTab(overviewTab,
"&Overview");
444 tabArea->addTab(preparationsTab,
"Preparing &Input Cubes");
448 tabArea->addTab(MosaicSceneWidget::getLongHelp(),
450 tabArea->addTab(MosaicSceneWidget::getPreviewHelp(),
451 "Mosaic &World View");
453 tabArea->addTab(MosaicSceneWidget::getMapHelp(),
455 tabArea->addTab(projectsTab,
"&Project Files");
457 tabArea->addTab(MosaicSceneWidget::getControlNetHelp(),
458 "&Control Networks");
459 tabArea->addTab(MosaicSceneWidget::getGridHelp(),
465 mainLayout->addWidget(buttonsArea);
467 QHBoxLayout *buttonsLayout =
new QHBoxLayout;
468 buttonsArea->setLayout(buttonsLayout);
471 buttonsLayout->addStretch();
473 QPushButton *closeButton =
new QPushButton(QIcon::fromTheme(
"window-close"),
475 closeButton->setDefault(
true);
476 connect(closeButton, SIGNAL(clicked()),
477 helpDialog, SLOT(close()));
478 buttonsLayout->addWidget(closeButton);
484 void MosaicMainWindow::updateMenuVisibility() {
485 QMenuBar *rootMenu = menuBar();
488 foreach(rootAction, rootMenu->actions()) {
489 QMenu *rootMenu = rootAction->menu();
492 rootAction->setVisible(updateMenuVisibility(rootAction->menu()));
498 void MosaicMainWindow::createController() {
499 if (m_mosaicController == NULL) {
500 m_mosaicController =
new MosaicController(statusBar(), m_settings);
505 foreach(settingsAct, settingsActs) {
506 connect(settingsAct, SIGNAL(destroyed(
QObject *)),
507 this, SLOT(updateMenuVisibility()));
509 m_settingsMenu->addAction(settingsAct);
512 updateMenuVisibility();
517 void MosaicMainWindow::displayController() {
518 if (m_mosaicController && !m_controllerVisible) {
519 m_controllerVisible =
true;
522 m_fileListDock->setWidget(m_mosaicController->getImageFileList());
523 m_mosaicPreviewDock->setWidget(m_mosaicController->getMosaicWorldScene());
525 centralWidget()->layout()->addWidget(
526 m_mosaicController->getMosaicScene());
528 QAction *actionRequiringOpen = NULL;
529 foreach(actionRequiringOpen, m_actionsRequiringOpen) {
530 actionRequiringOpen->setEnabled(
true);
533 QAction *actionRequiringClosed = NULL;
534 foreach(actionRequiringClosed, m_actionsRequiringClosed) {
535 actionRequiringClosed->setEnabled(
false);
538 m_mosaicController->getMosaicScene()->addTo(
m_toolpad);
539 m_mosaicController->getMosaicScene()->addToPermanent(
m_permToolbar);
542 statusBar()->addWidget(m_mosaicController->getProgress());
543 statusBar()->addWidget(
544 m_mosaicController->getMosaicScene()->getProgress());
545 statusBar()->addWidget(
546 m_mosaicController->getMosaicWorldScene()->getProgress());
547 statusBar()->addWidget(
548 m_mosaicController->getImageFileList()->
getProgress());
551 m_mosaicController->getMosaicScene()->getViewActions();
553 foreach(
QAction *viewAct, sceneViewActs) {
554 connect(viewAct, SIGNAL(destroyed(
QObject *)),
555 this, SLOT(updateMenuVisibility()));
557 m_viewMenu->addAction(viewAct);
560 m_viewMenu->addSeparator();
566 foreach(
QAction *viewAct, fileListViewActs) {
567 connect(viewAct, SIGNAL(destroyed(
QObject *)),
568 this, SLOT(updateMenuVisibility()));
570 m_viewMenu->addAction(viewAct);
573 updateMenuVisibility();
578 bool MosaicMainWindow::updateMenuVisibility(
QMenu *menu) {
579 bool anythingVisible =
false;
587 foreach(menuAction, menu->actions()) {
588 bool thisVisible =
true;
590 if (menuAction->menu() != NULL) {
591 thisVisible = updateMenuVisibility(menuAction->menu());
594 thisVisible = menuAction->isVisible();
598 anythingVisible =
true;
601 menu->menuAction()->setVisible(anythingVisible);
604 return anythingVisible;
615 filterList.append(
"List Files (*.lis)");
616 filterList.append(
"Text Files (*.txt)");
617 filterList.append(
"All files (*)");
619 QDir directory = m_lastOpenedFile.dir();
621 QString selected = QFileDialog::getOpenFileName(
this,
"Open Cube List",
622 directory.path(), filterList.join(
";;"));
624 if (selected !=
"") {
625 m_lastOpenedFile = QFileInfo(selected);
626 TextFile fileList((QString) selected);
631 while(fileList.
GetLine(line)) {
632 filesInList.append(line);
635 if (filesInList.empty()) {
636 IString msg =
"No files were found inside the file list";
640 openFiles(filesInList);
656 void MosaicMainWindow::openFiles(
QStringList cubeNames) {
658 if (!cubeNames.empty()) {
662 if (m_mosaicController)
682 if (m_mosaicController) {
683 QString fn = QFileDialog::getSaveFileName(
this,
"Save Project",
684 QDir::currentPath() +
"/untitled.mos",
686 if (fn.isEmpty())
return;
688 m_mosaicController->saveProject(fn);
699 if (m_filename ==
"") {
703 m_mosaicController->saveProject(m_filename);
714 QString fn = QFileDialog::getOpenFileName(
this,
"Load Project",
721 m_lastOpenedFile = QFileInfo(fn);
732 if (m_mosaicController)
733 m_mosaicController->readProject(fn);
740 void MosaicMainWindow::closeMosaic() {
741 if (m_mosaicController) {
742 QAction *actionRequiringOpen = NULL;
743 foreach(actionRequiringOpen, m_actionsRequiringOpen) {
744 actionRequiringOpen->setEnabled(
false);
747 QAction *actionRequiringClosed = NULL;
748 foreach(actionRequiringClosed, m_actionsRequiringClosed) {
749 actionRequiringClosed->setEnabled(
true);
752 m_mosaicController->saveSettings(m_settings);
753 delete m_mosaicController;
754 m_mosaicController = NULL;
757 m_controllerVisible =
false;