3 #include "MosaicSceneWidget.h"
8 #include <QGraphicsSceneContextMenuEvent>
10 #include <QHBoxLayout>
12 #include <QMessageBox>
14 #include <QRubberBand>
18 #include <QToolButton>
29 #include "GraphicsView.h"
31 #include "ImageList.h"
34 #include "MosaicAreaTool.h"
35 #include "MosaicControlNetTool.h"
36 #include "MosaicFindTool.h"
37 #include "MosaicGraphicsScene.h"
38 #include "MosaicGraphicsView.h"
39 #include "MosaicGridTool.h"
40 #include "MosaicPanTool.h"
41 #include "MosaicSceneItem.h"
42 #include "MosaicSelectTool.h"
43 #include "MosaicTrackTool.h"
44 #include "MosaicZoomTool.h"
45 #include "MoveDownOneSceneWorkOrder.h"
46 #include "MoveToBottomSceneWorkOrder.h"
47 #include "MoveToTopSceneWorkOrder.h"
48 #include "MoveUpOneSceneWorkOrder.h"
49 #include "ProgressBar.h"
52 #include "ProjectionConfigDialog.h"
59 #include "XmlStackedHandlerReader.h"
66 bool internalizeToolBarsAndProgress,
Directory *directory,
68 m_projectImageZOrders = NULL;
69 m_projectViewTransform = NULL;
70 m_directory = directory;
88 m_quickMapAction = NULL;
90 m_cubesSelectable =
true;
91 m_customRubberBandEnabled =
false;
92 m_customRubberBand = NULL;
93 m_rubberBandOrigin = NULL;
95 m_blockingSelectionChanged =
false;
96 m_queuedSelectionChanged =
false;
97 m_shouldRequeueSelectionChanged =
false;
99 m_userToolControl =
false;
100 m_ownProjection =
false;
103 m_progress->setVisible(
false);
105 QGridLayout * sceneLayout =
new QGridLayout;
106 sceneLayout->setContentsMargins(0, 0, 0, 0);
107 setLayout(sceneLayout);
110 if (!status && internalizeToolBarsAndProgress)
111 status =
new QStatusBar;
119 m_tools->append(cnetTool);
123 connect(cnetTool, SIGNAL(modifyControlPoint(
ControlPoint *)),
126 connect(cnetTool, SIGNAL(deleteControlPoint(
ControlPoint *)),
129 connect(cnetTool, SIGNAL(createControlPoint(
double,
double)),
130 this, SIGNAL(createControlPoint(
double,
double)));
133 connect(
this, SIGNAL(controlPointAdded(QString)),
134 cnetTool, SLOT(displayNewControlPoint(QString)));
157 m_tools->at(0)->activate(
true);
161 if (internalizeToolBarsAndProgress) {
176 QHBoxLayout *horizontalToolBarsLayout =
new QHBoxLayout;
178 m_permToolbar =
new QToolBar(
"Standard Tools");
179 m_permToolbar->setWhatsThis(
"This area contains options that are always present in the "
181 horizontalToolBarsLayout->addWidget(m_permToolbar);
183 m_activeToolbar =
new QToolBar(
"Active Tool",
this);
184 m_activeToolbar->setObjectName(
"Active Tool");
185 m_activeToolbar->setWhatsThis(
"The currently selected tool's options will "
186 "show up here. Not all tools have options.");
187 horizontalToolBarsLayout->addWidget(m_activeToolbar);
189 sceneLayout->addLayout(horizontalToolBarsLayout, 0, 0, 1, 2);
193 m_toolpad =
new ToolPad(
"Tool Pad",
this);
194 m_toolpad->setObjectName(
"Tool Pad");
195 m_toolpad->setOrientation(Qt::Vertical);
196 m_toolpad->setFloatable(
true);
197 sceneLayout->addWidget(m_toolpad, 1, 1, 1, 1);
199 QHBoxLayout *horizontalStatusLayout =
new QHBoxLayout;
200 horizontalStatusLayout->addWidget(m_progress);
201 horizontalStatusLayout->addStretch();
202 horizontalStatusLayout->addWidget(status);
204 sceneLayout->addLayout(horizontalStatusLayout, 2, 0, 1, 2);
206 addToPermanent(m_permToolbar);
207 m_permToolbar->addSeparator();
209 addTo(m_activeToolbar);
216 m_userToolControl =
true;
218 setWhatsThis(
"This is the mosaic scene. The opened cubes will be "
219 "shown here. You can fully interact with the files shown here.");
221 getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
222 getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
224 getView()->enableResizeZooming(
false);
226 connect(getView()->horizontalScrollBar(), SIGNAL(valueChanged(
int)),
227 this, SLOT(sendVisibleRectChanged()));
228 connect(getView()->verticalScrollBar() , SIGNAL(valueChanged(
int)),
229 this, SLOT(sendVisibleRectChanged()));
230 connect(getView()->horizontalScrollBar(), SIGNAL(rangeChanged(
int,
int)),
231 this, SLOT(sendVisibleRectChanged()));
232 connect(getView()->verticalScrollBar() , SIGNAL(rangeChanged(
int,
int)),
233 this, SLOT(sendVisibleRectChanged()));
239 getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
240 getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
242 setWhatsThis(
"This is the mosaic world view. The opened cubes will be "
243 "shown here, but you cannot zoom in. You can select cubes by dragging "
244 "a box over them, zoom to a particular cube by right clicking on it "
245 "and selecting 'Zoom Fit', and many other actions are available.");
250 m_currentMinimumFootprintZ = 0;
251 m_currentMaximumFootprintZ = 0;
253 connect(getScene(), SIGNAL(selectionChanged()),
254 this, SLOT(onSelectionChanged()));
257 connect(
this, SIGNAL(queueSelectionChanged()),
258 this, SLOT(onQueuedSelectionChanged()), Qt::QueuedConnection);
261 MosaicSceneWidget::~MosaicSceneWidget() {
262 m_outlineRect = NULL;
279 delete m_projectImageZOrders;
280 m_projectImageZOrders = NULL;
282 delete m_projectViewTransform;
283 m_projectViewTransform = NULL;
291 if (!mapping.hasKeyword(
"EquatorialRadius")) {
293 tmp.findGroup(
"Mapping") += radii[
"EquatorialRadius"];
294 tmp.findGroup(
"Mapping") += radii[
"PolarRadius"];
298 m_ownProjection =
true;
309 PvlKeyword projectionKeyword = mapping.findKeyword(
"ProjectionName");
310 QString projName = projectionKeyword[0];
311 m_mapButton->setText(tr(
"View/Edit %1 Projection").arg(projName));
320 if (old && m_ownProjection) {
325 m_ownProjection =
false;
330 void MosaicSceneWidget::setOutlineRect(QRectF outline) {
331 if (outline.united(getView()->sceneRect()) != getView()->sceneRect())
334 if (!m_outlineRect) {
335 m_outlineRect = getScene()->addRect(outline,
338 m_outlineRect->setZValue(DBL_MAX);
341 m_outlineRect->setRect(outline);
344 if (!m_userToolControl)
349 PvlGroup MosaicSceneWidget::createInitialProjection(
351 Projection *proj = NULL;
352 Cube *cube = image->cube();
353 Pvl *label = cube->label();
357 return proj->Mapping();
359 catch (IException &) {
360 Pvl mappingPvl(
"$base/templates/maps/equirectangular.map");
361 PvlGroup &mappingGrp = mappingPvl.findGroup(
"Mapping");
362 mappingGrp += PvlKeyword(
"LatitudeType",
"Planetocentric");
363 mappingGrp += PvlKeyword(
"LongitudeDirection",
"PositiveEast");
364 mappingGrp += PvlKeyword(
"LongitudeDomain",
"360");
365 mappingGrp += PvlKeyword(
"CenterLatitude",
"0");
366 mappingGrp += PvlKeyword(
"CenterLongitude",
"180");
367 mappingGrp += PvlKeyword(
"MinimumLatitude",
"-90");
368 mappingGrp += PvlKeyword(
"MaximumLatitude",
"90");
369 mappingGrp += PvlKeyword(
"MinimumLongitude",
"0");
370 mappingGrp += PvlKeyword(
"MaximumLongitude",
"360");
373 Camera * cam = cube->camera();
377 mappingGrp += PvlKeyword(
"TargetName", cam->target()->name());
378 mappingGrp += PvlKeyword(
"EquatorialRadius",
toString(radii[0].meters()),
380 mappingGrp += PvlKeyword(
"PolarRadius",
toString(radii[2].meters()),
384 catch (IException &) {
394 void MosaicSceneWidget::addToPermanent(
QToolBar *perm) {
395 m_mapButton =
new QToolButton(
this);
396 connect(
this, SIGNAL(destroyed()), m_mapButton, SLOT(deleteLater()));
397 m_mapButton->setText(tr(
"View/Edit/Load Map File"));
398 m_mapButton->setToolTip(tr(
"View/Edit/Load Map File"));
399 m_mapButton->setIcon(QIcon(FileName(
"$base/icons/ographic.png").expanded()));
400 m_mapButton->setWhatsThis(tr(
"This is the projection used by the mosaic "
401 "scene. Cubes can not be shown in the scene without a projection, so "
402 "if one is not selected, a default of Equirectangular will be used. "
403 "The selected file should be a map file, examples are available in "
404 "$base/templates/maps."));
405 m_mapButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
409 PvlKeyword projectionKeyword =
411 QString projName = projectionKeyword[0];
412 m_mapButton->setText(projName);
415 m_quickMapAction =
new QAction(tr(
"Quick Load Map"),
this);
416 m_quickMapAction->setToolTip(tr(
"Quick Load Map"));
417 m_quickMapAction->setIcon(QIcon(FileName(
"$base/icons/quickopen.png").expanded()));
418 m_quickMapAction->setWhatsThis(tr(
"This is the projection used by the mosaic "
419 "scene. Cubes can not be shown in the scene without a projection, so "
420 "if one is not selected, a default of Equirectangular will be used."));
421 connect(m_quickMapAction, SIGNAL(triggered()),
this, SLOT(quickConfigProjectionParameters()));
423 perm->addWidget(m_mapButton);
424 perm->addAction(m_quickMapAction);
428 void MosaicSceneWidget::addTo(
QToolBar *toolbar) {
430 foreach(tool, *m_tools) {
431 tool->addTo(toolbar);
436 void MosaicSceneWidget::addTo(QMenu *menu) {
438 foreach(tool, *m_tools) {
444 void MosaicSceneWidget::addTo(ToolPad *toolPad) {
446 foreach(tool, *m_tools) {
447 tool->addTo(toolPad);
459 bool handled =
false;
464 foreach (
QGraphicsItem *graphicsItem, selectedGraphicsItems) {
467 if (!sceneImageItem) {
468 sceneImageItem =
dynamic_cast<MosaicSceneItem *
>(graphicsItem->parentItem());
471 if (sceneImageItem && sceneImageItem->image()) {
472 selectedImageItems.append(sceneImageItem);
473 selectedImages.
append(sceneImageItem->image());
477 if (selectedImageItems.count()) {
480 QAction *title = menu.addAction(tr(
"%L1 Selected Images").arg(selectedImages.count()));
481 title->setEnabled(
false);
489 displayActs.append(NULL);
494 foreach(displayAct, displayActs) {
495 if (displayAct == NULL) {
499 menu.addAction(displayAct);
504 menu.exec(event->screenPos());
512 void MosaicSceneWidget::enableRubberBand(
bool enable) {
513 m_customRubberBandEnabled = enable;
517 MosaicSceneItem *MosaicSceneWidget::cubeToMosaic(Image *image) {
520 QString msg = tr(
"Can not find a NULL image in the mosaic");
524 return cubeToMosaic(image->displayProperties());
528 bool MosaicSceneWidget::blockSelectionChange(
bool block) {
529 bool wasBlocking = m_blockingSelectionChanged;
531 m_blockingSelectionChanged = block;
542 PvlObject MosaicSceneWidget::toPvl()
const {
544 PvlObject output(
"MosaicScene");
550 dataBuffer.open(QIODevice::ReadWrite);
551 QDataStream transformStream(&dataBuffer);
552 transformStream << getView()->transform();
555 PvlObject mosaicScenePosition(
"SceneVisiblePosition");
556 mosaicScenePosition += PvlKeyword(
"ViewTransform",
557 QString(dataBuffer.data().toHex()));
558 PvlKeyword scrollPos(
"ScrollPosition");
559 scrollPos +=
toString(getView()->horizontalScrollBar()->value());
560 scrollPos +=
toString(getView()->verticalScrollBar()->value());
561 mosaicScenePosition += scrollPos;
563 output += mosaicScenePosition;
566 foreach(tool, *m_tools) {
567 if (tool->projectPvlObjectName() !=
"") {
568 PvlObject toolObj = tool->toPvl();
569 toolObj.setName(tool->projectPvlObjectName());
574 PvlObject zOrders(
"ZOrdering");
575 foreach(MosaicSceneItem * mosaicSceneItem, *m_mosaicSceneItems) {
576 PvlKeyword zValue(
"ZValue");
577 zValue += mosaicSceneItem->image()->id();
578 zValue +=
toString(mosaicSceneItem->zValue());
586 "Cannot save a scene without a projection to a project file",
605 foreach(tool, *m_tools) {
606 if (tool->projectPvlObjectName() !=
"") {
607 if (project.
hasObject(tool->projectPvlObjectName())) {
609 project.
findObject(tool->projectPvlObjectName()));
610 tool->fromPvl(toolSettings);
617 delete m_projectImageZOrders;
618 m_projectImageZOrders = NULL;
621 for (
int zOrderIndex = 0;
624 const PvlKeyword &zOrder = zOrders[zOrderIndex];
626 (*m_projectImageZOrders)[zOrder[0]] =
toDouble(zOrder[1]);
630 if (project.
hasObject(
"SceneVisiblePosition")) {
634 delete m_projectViewTransform;
636 m_projectViewTransform =
new PvlObject(positionInfo);
644 xmlReader->pushContentHandler(
new XmlHandler(
this));
648 void MosaicSceneWidget::save(QXmlStreamWriter &stream, Project *, FileName)
const {
651 stream.writeStartElement(
"footprint2DView");
653 stream.writeStartElement(
"projection");
655 std::stringstream strStream;
656 strStream << mapping;
657 stream.writeCharacters(strStream.str().c_str());
658 stream.writeEndElement();
660 stream.writeStartElement(
"images");
661 foreach(MosaicSceneItem * mosaicSceneItem, *m_mosaicSceneItems) {
662 stream.writeStartElement(
"image");
663 stream.writeAttribute(
"id", mosaicSceneItem->image()->id());
664 stream.writeAttribute(
"zValue",
toString(mosaicSceneItem->zValue()));
665 stream.writeEndElement();
667 stream.writeEndElement();
669 stream.writeStartElement(
"viewTransform");
670 stream.writeAttribute(
"scrollBarXValue",
toString(getView()->horizontalScrollBar()->value()));
671 stream.writeAttribute(
"scrollBarYValue",
toString(getView()->verticalScrollBar()->value()));
673 dataBuffer.open(QIODevice::ReadWrite);
674 QDataStream transformStream(&dataBuffer);
676 transformStream << getView()->transform();
678 stream.writeCharacters(dataBuffer.data().toHex());
679 stream.writeEndElement();
681 foreach(MosaicTool *tool, *m_tools) {
682 QString projectPvlObjectName = tool->projectPvlObjectName();
683 if (projectPvlObjectName !=
"") {
684 PvlObject toolObj = tool->toPvl();
685 toolObj.setName(projectPvlObjectName);
687 stream.writeStartElement(
"toolData");
688 stream.writeAttribute(
"objectName", projectPvlObjectName);
689 std::stringstream strStream;
690 strStream << toolObj;
691 stream.writeCharacters(strStream.str().c_str());
692 stream.writeEndElement();
696 stream.writeEndElement();
701 QRectF MosaicSceneWidget::cubesBoundingRect()
const {
704 MosaicSceneItem * mosaicItem;
705 foreach(mosaicItem, *m_mosaicSceneItems) {
706 if (boundingRect.isEmpty())
707 boundingRect = mosaicItem->boundingRect();
709 boundingRect = boundingRect.united(mosaicItem->boundingRect());
713 boundingRect = boundingRect.united(m_outlineRect->boundingRect());
719 MosaicSceneItem *MosaicSceneWidget::cubeToMosaic(DisplayProperties *props) {
722 QString msg = tr(
"Can not find a NULL Display Properties in the mosaic");
726 return m_displayPropsToMosaicSceneItemMap[props];
733 MosaicSceneItem *mosaicSceneItem;
734 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
735 if (mosaicSceneItem->image())
736 cubes.append(mosaicSceneItem->image()->fileName());
743 Directory *MosaicSceneWidget::directory()
const {
748 ImageList MosaicSceneWidget::images() {
751 MosaicSceneItem *mosaicSceneItem;
752 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
753 if (mosaicSceneItem->image())
754 images.
append(mosaicSceneItem->image());
773 foreach (
QGraphicsItem *graphicsItem, selectedGraphicsItems) {
776 if (!sceneImageItem) {
777 sceneImageItem =
dynamic_cast<MosaicSceneItem *
>(graphicsItem->parentItem());
780 if (sceneImageItem && sceneImageItem->image()) {
781 selectedImageItems.append(sceneImageItem);
782 selectedImages.
append(sceneImageItem->image());
810 exportView->setText(
"&Export View...");
811 connect(exportView, SIGNAL(triggered()),
this, SLOT(
exportView()));
814 saveList->setText(
"Save Entire Cube List (ordered by &view)...");
815 connect(saveList, SIGNAL(triggered()),
this, SLOT(saveList()));
817 exportActs.append(exportView);
818 exportActs.append(saveList);
827 foreach(MosaicTool *tool, *m_tools) {
829 viewActs.append(toolViewActs);
842 bool allImagesInView = !images->isEmpty();
844 foreach (
Image *image, *images) {
845 allImagesInView = allImagesInView && (cubeToMosaic(image) != NULL);
848 if (allImagesInView) {
852 results.append(moveToTopAct);
857 results.append(moveUpOneAct);
861 moveToBottomAct->
setData(images);
862 results.append(moveToBottomAct);
866 moveDownOneAct->
setData(images);
867 results.append(moveDownOneAct);
869 results.append(NULL);
872 zoomFitAct->setData(qVariantFromValue(images));
873 connect(zoomFitAct, SIGNAL(triggered()),
this, SLOT(fitInView()));
874 results.append(zoomFitAct);
880 bool MosaicSceneWidget::isControlNetToolActive() {
885 if (cnTool->
isActive())
return true;
892 QWidget * MosaicSceneWidget::getControlNetHelp(
QWidget *cnetToolContainer) {
893 QScrollArea *cnetHelpWidgetScrollArea =
new QScrollArea;
897 QVBoxLayout *cnetHelpLayout =
new QVBoxLayout;
898 cnetHelpWidget->setLayout(cnetHelpLayout);
900 QLabel *title =
new QLabel(
"<h2>Control Networks</h2>");
901 cnetHelpLayout->addWidget(title);
903 QPixmap previewPixmap;
905 if (cnetToolContainer) {
906 previewPixmap = cnetToolContainer->grab().scaled(
907 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
910 ToolPad tmpToolPad(
"Example Tool Pad", NULL);
911 MosaicControlNetTool tmpTool(NULL);
912 tmpTool.addTo(&tmpToolPad);
914 tmpToolPad.resize(QSize(32, 32));
916 previewPixmap = tmpToolPad.grab();
919 QLabel *previewWrapper =
new QLabel;
920 previewWrapper->setPixmap(previewPixmap);
921 cnetHelpLayout->addWidget(previewWrapper);
923 QLabel *overview =
new QLabel(
"The mosaic scene can display control points "
924 "in addition to the usual cube footprints. This feature is currently "
925 "offered as one of the Mosaic Scene's tools. To open a network, click "
926 "on the control network tool. It will immediately prompt you for a "
927 "control network file if one is not open. Only control points for "
928 "which the latitude and longitude can be established will be "
929 "displayed. Other control points will be ignored by qmos.<br><br>"
930 "<b>Warning: Opening large control networks is slow.</b>"
931 "<h3>Control Network Tool Options</h3>"
933 "<li>The control network tool opens control networks in two ways. "
934 "First, if you select the control network tool and no network is "
935 "open, then it will prompt you for one. Second, if there is an open "
936 "network, the buttons for the available options are displayed in the "
937 "active tool area.</li>"
938 "<li>The control network tool can toggle whether or not control "
939 "points are displayed on the screen using the 'Display' button. "
940 "Control points are always on top and colored based on their "
941 "ignored, locked and type values.</li>"
942 "<li>This tool can also change the color of your footprints based on "
943 "connectivity through control points. This is available through the "
944 "'Color Islands' button. When you press color islands, all of the "
945 "current cube coloring information is lost and re-done based on "
946 "how the control network connects the files. Each set of connected "
947 "cubes are colored differently; generally speaking, islands are not "
948 "a good thing to have in your control network.</li>"
949 "<li>This tool will color your footprints on a per-image basis if you "
950 "click color images, effectively reversing color islands.</li>"
951 "<li>The show movement option under 'Configure Movement Display' "
952 "only displays data when the control "
953 "network has adjusted values. This means that show movement only "
954 "works after you have done a jigsaw solution on the control network. "
955 "This displays arrows emanating from the apriori latitude/longitude "
956 "and pointing toward the adjusted latitude/longitude.</li>");
957 overview->setWordWrap(
true);
958 cnetHelpLayout->addWidget(overview);
960 cnetHelpWidgetScrollArea->setWidget(cnetHelpWidget);
962 return cnetHelpWidgetScrollArea;
966 QWidget * MosaicSceneWidget::getGridHelp(
QWidget *gridToolContainer) {
967 QScrollArea *gridHelpWidgetScrollArea =
new QScrollArea;
971 QVBoxLayout *gridHelpLayout =
new QVBoxLayout;
972 gridHelpWidget->setLayout(gridHelpLayout);
974 QLabel *title =
new QLabel(
"<h2>Map Grid Tool</h2>");
975 gridHelpLayout->addWidget(title);
977 QPixmap previewPixmap;
979 if (gridToolContainer) {
980 previewPixmap = gridToolContainer->grab().scaled(
981 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
984 ToolPad tmpToolPad(
"Example Tool Pad", NULL);
985 MosaicGridTool tmpTool(NULL);
986 tmpTool.addTo(&tmpToolPad);
988 tmpToolPad.resize(QSize(32, 32));
990 previewPixmap = tmpToolPad.grab();
993 QLabel *previewWrapper =
new QLabel;
994 previewWrapper->setPixmap(previewPixmap);
995 gridHelpLayout->addWidget(previewWrapper);
997 QLabel *overview =
new QLabel(
"Superimpose a map grid over the area of "
998 "displayed footprints in the 'mosaic scene.'"
1001 "<li>The Map Grid Tool is activated by selecting the 'cross-hatch' "
1002 "icon or typing 'g' at the keyboard."
1004 "<li>The parameter options are displayed below the menubar. "
1005 "Clicking the 'Grid Options' button will open the dialog. Checking "
1006 "'Auto Grid' will draw a grid based on the open cubes. Hitting "
1007 "'Show Grid' will display or hide the grid."
1009 "<li>The map grid is defined by the loaded Map File (just as the "
1010 "footprints and image data are), the opened cubes, or the grid "
1013 "<li>If a Map File has not been selected, the default "
1014 "Equirectangular projection will be used. The resulting grid "
1015 "lines in the default 'Equi' map file will be drawn for the "
1016 "full global range (latitude range = -90,90; longitude range = "
1017 "0,360) at the default latitude and longitude increment values."
1020 "If the grid lines are not immediately visible, try to "
1021 "'zoom out' in the 'mosaic scene' window and modify the "
1022 "Latitude and Longitude Increment parameters."
1025 "<strong>Options:</strong>"
1027 "<li>The 'Show Grid' option draws (checked) or clears (unchecked) the grid."
1029 "<li>The 'Auto Grid' option draws a grid with extents and increments "
1030 "computed from the set of images that are opened. The values displayed in the dialog "
1031 "will reflect those used to draw the grid."
1033 "<li>The expected units for each entry are displayed to the right of the "
1036 "<li>The 'Extent Type' combo boxes allow you to pick the source of the "
1037 "grid extents from the map file, from the open cubes <default>, or manually "
1040 "<li>The 'Auto Apply' checkbox, inside the 'Grid Options' dialog box, allows you to see "
1041 "real time updates in the grid when you change the parameters."
1043 "<li> Depending on the projection, the grid may not behave as expected. For instance, "
1044 "with a polarstereographic projection, the pole will not be included in the 'Auto "
1045 "Grid' if it is not in the cube region. In this case the 'Manual' option for latitude "
1046 "extents allows you to force the grid to the pole."
1049 overview->setWordWrap(
true);
1050 gridHelpLayout->addWidget(overview);
1052 gridHelpWidgetScrollArea->setWidget(gridHelpWidget);
1054 return gridHelpWidgetScrollArea;
1058 QWidget * MosaicSceneWidget::getLongHelp(
QWidget *sceneContainer) {
1059 QScrollArea *longHelpWidgetScrollArea =
new QScrollArea;
1063 QVBoxLayout *longHelpLayout =
new QVBoxLayout;
1064 longHelpWidget->setLayout(longHelpLayout);
1066 QLabel *title =
new QLabel(
"<h2>Mosaic Scene</h2>");
1067 longHelpLayout->addWidget(title);
1069 if (sceneContainer) {
1070 QPixmap previewPixmap = sceneContainer->grab().scaled(
1071 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1073 QLabel *previewWrapper =
new QLabel;
1074 previewWrapper->setPixmap(previewPixmap);
1075 longHelpLayout->addWidget(previewWrapper);
1078 QLabel *overview =
new QLabel(
"The mosaic scene displays cube footprints "
1079 "to show where files are on a target and how they overlap. "
1080 "The scene always represents projected image space and cannot show raw "
1081 "or unprojected images; images will be projected on the fly."
1083 "<p>Interact with the mosaic scene in different ways using "
1084 "the tools. The tools are usually in a toolbar next to the scene. "
1085 "The tools define what is displayed and what happens when you "
1086 "click in the mosaic scene. The tools include</p>"
1087 "<ul><li>Select Tool</li>"
1088 "<li>Zoom Tool</li>"
1090 "<li>Control Network Tool</li>"
1091 "<li>Show Area Tool</li>"
1092 "<li>Find Tool</li>"
1093 "<li>Grid Tool</li></ul>"
1094 "<h3>Context Menus</h3>"
1095 "Right click on anything in the mosaic scene and a context menu will pop up showing "
1096 "a list of actions or information relevant to the item you clicked on. "
1097 "<p>Note: The context menu is not associated with any selection, only the item "
1099 overview->setWordWrap(
true);
1100 longHelpLayout->addWidget(overview);
1102 longHelpWidgetScrollArea->setWidget(longHelpWidget);
1104 return longHelpWidgetScrollArea;
1109 QScrollArea *mapHelpWidgetScrollArea =
new QScrollArea;
1113 QVBoxLayout *mapHelpLayout =
new QVBoxLayout;
1114 mapHelpWidget->setLayout(mapHelpLayout);
1116 QLabel *title =
new QLabel(tr(
"<h2>Map File</h2>"));
1117 mapHelpLayout->addWidget(title);
1120 QPixmap previewPixmap = mapContainer->grab().scaled(
1121 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1123 QLabel *previewWrapper =
new QLabel;
1124 previewWrapper->setPixmap(previewPixmap);
1125 mapHelpLayout->addWidget(previewWrapper);
1128 QLabel *overviewMapIcon =
new QLabel;
1130 overviewMapIcon->setPixmap(
1131 QIcon(FileName(
"$base/icons/ographic.png").expanded()).pixmap(32, 32));
1132 mapHelpLayout->addWidget(overviewMapIcon);
1134 QLabel *defaultMapFile =
new QLabel(tr(
1135 "<h3>Default Map File</h3>"
1136 "The mosaic scene's projection is defined by a \"Map File\" that consists of keywords "
1137 "that describe the map layout to be used. If a cube or a list of cubes are "
1138 "loaded before a map file is selected, the default map file defines the "
1139 "equirectangular projection, planetocentric latitude, positive longitude east, 360 "
1140 "longitude domain, latitude range=90S-90N, longitude range=0-360E. The radius will "
1141 "default to the IAU standards (ellipsoid or sphere) for the specific planetary body "
1142 "defined for the \"TargetName\" in the labels of the image cube(s)."));
1144 defaultMapFile->setWordWrap(
true);
1145 mapHelpLayout->addWidget(defaultMapFile);
1147 QLabel *userDefinedMapFileOverview =
new QLabel(tr(
1148 "<h3>User Defined Map File</h3>"
1149 "You can load an existing \"Map File\" before loading images into %1 by selecting the "
1150 "\"View/Edit/Load Map File\" option. You will be greeted with a dialog box that will "
1151 "enable you to select an existing map file by clicking on \"Load Map File.\" Once "
1152 "the map file is selected, the contents is displayed in the dialog box where "
1153 "modifications can be made as well. If the modified map file is to be used later, "
1154 "save the map file by clicking on \"Save Map File\" button.")
1155 .arg(QCoreApplication::applicationName()));
1157 userDefinedMapFileOverview->setWordWrap(
true);
1158 mapHelpLayout->addWidget(userDefinedMapFileOverview);
1160 QLabel *userDefinedMapFileQuickLoad =
new QLabel(tr(
1161 "The \"Quick Load Map\" option (lightning icon) allows you to efficiently select a "
1162 "prepared \"Map File\" without an immediate need to view or edit the contents."));
1164 userDefinedMapFileQuickLoad->setWordWrap(
true);
1165 mapHelpLayout->addWidget(userDefinedMapFileQuickLoad);
1167 QLabel *userDefinedMapFileAnyTime =
new QLabel(tr(
1168 "At any point, you have access to the \"View/Edit\" functionality to modify or load a "
1169 "different map file."));
1171 userDefinedMapFileAnyTime->setWordWrap(
true);
1172 mapHelpLayout->addWidget(userDefinedMapFileAnyTime);
1174 QString mapProjWorkshopUrl(
"https://isis.astrogeology.usgs.gov/fixit/projects/"
1175 "isis/wiki/Learning_About_Map_Projections");
1176 QLabel *preparingMapFile =
new QLabel(tr(
1177 "<h3>Preparing a Map File</h3>"
1178 "Please refer to Isis applications such as 'maptemplate' or 'mosrange' for more details "
1179 "on creating a custom map file that defines the desired projection, latitude "
1180 "system, and longitude direction and domain. This program will use the latitude range "
1181 "and longitude range if they exist in the loaded file. A choice of map templates that can be used as "
1182 "a starting point for supported map projections can be found in $base/templates/maps (refer "
1183 "to maptemplate or mosrange for more details and information on the required parameters "
1184 "for a projection). Note that through the file name selection box, $base will need "
1185 "to be replaced with the specific Isis3 system path. The website: "
1186 "<a href='%1'>%1</a> also provides useful information about map projections.")
1187 .arg(mapProjWorkshopUrl));
1189 preparingMapFile->setOpenExternalLinks(
true);
1190 preparingMapFile->setWordWrap(
true);
1191 mapHelpLayout->addWidget(preparingMapFile);
1193 QLabel *mapFileDisplayResults =
new QLabel(tr(
1194 "<h3>Display Results with the Map File</h3>"
1195 "The footprints and image data that are displayed in the mosaic scene are defined by the "
1196 "loaded \"Map File\" regardless of whether the opened cubes are Level1 (raw "
1197 "camera space) or Level2 (map projected). The associated footprint polygons for "
1198 "Level2 cubes will be re-mapped as needed based on the loaded map file."));
1200 mapFileDisplayResults->setWordWrap(
true);
1201 mapHelpLayout->addWidget(mapFileDisplayResults);
1203 QLabel *editingMapFileOverview =
new QLabel(tr(
1204 "<h3>Editing a Map File</h3>"
1205 "Editing a map file is possible through the dialog box displayed by clicking on the "
1206 "'View/Edit/Load Map File' icon/button. The edits are "
1207 "applied to the current session and will be included with a 'Saved Project' (refer to "
1208 "the help under File-Save Project or Save Project as)."));
1210 editingMapFileOverview->setWordWrap(
true);
1211 mapHelpLayout->addWidget(editingMapFileOverview);
1213 QLabel *saveMapFileToDiskBullet =
new QLabel(tr(
1216 "To save or write the changes to a map file on disk, choose 'Save Map File' button. "
1217 "Map files can be saved to an existing map file (overwrites) or to a new file. This "
1218 "program always saves <strong>exactly</strong> what you see, the text, in the dialog "
1223 saveMapFileToDiskBullet->setWordWrap(
true);
1224 mapHelpLayout->addWidget(saveMapFileToDiskBullet);
1226 QLabel *mapFileValidityBullet =
new QLabel(tr(
1229 "As you modify the contents of a loaded map file in the dialog box, the entry is "
1230 "verified as you type with a bold black indicator message displaying whether the "
1231 "text is valid or is not valid. If you want to see the actual error messages, "
1232 "select the 'Show Errors' box and the errors will be displayed in red font "
1233 "along with the black bolded message. The errors will update "
1238 mapFileValidityBullet->setWordWrap(
true);
1239 mapHelpLayout->addWidget(mapFileValidityBullet);
1241 QLabel *mapFileCommentsBullet =
new QLabel(tr(
1244 "Map files may contain 'commented-out' lines (text that starts with \"#\" at "
1245 "the beginning of the line). These are referred to as \"unnecessary\""
1246 "or \"unknown\" keywords, they are simply ignored. If these lines are to be saved to "
1247 "the output map file on disk, click 'Save Map File' BEFORE clicking 'Ok' or 'Apply.' "
1248 "The comments are removed from the dialog box when you hit 'Ok' or 'Apply,' if they "
1249 "are just above \"End_Group\" or follow \"End_Group\" or \"End\".<br/><br/>"
1251 "If you want these comments retained, make sure they are immediately above a valid "
1252 "keyword inside of \"Group = Mapping.\" Note that any lines (commented or not) will "
1253 "not be saved if they are placed outside of \"Group = Mapping\" and \"End_Group\"."
1257 mapFileCommentsBullet->setWordWrap(
true);
1258 mapHelpLayout->addWidget(mapFileCommentsBullet);
1260 mapHelpWidgetScrollArea->setWidget(mapHelpWidget);
1262 return mapHelpWidgetScrollArea;
1266 QWidget * MosaicSceneWidget::getPreviewHelp(
QWidget *worldViewContainer) {
1267 QScrollArea *previewHelpWidgetScrollArea =
new QScrollArea;
1271 QVBoxLayout *previewHelpLayout =
new QVBoxLayout;
1272 previewHelpWidget->setLayout(previewHelpLayout);
1274 QLabel *title =
new QLabel(
"<h2>Mosaic World View</h2>");
1275 previewHelpLayout->addWidget(title);
1277 if (worldViewContainer) {
1278 QPixmap previewPixmap = worldViewContainer->grab().scaled(
1279 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1281 QLabel *previewWrapper =
new QLabel;
1282 previewWrapper->setPixmap(previewPixmap);
1283 previewHelpLayout->addWidget(previewWrapper);
1286 QLabel *overview =
new QLabel(
"The mosaic world view displays cube "
1287 "footprints to show you where your files are on a target and their "
1288 "general arrangement. The world view does not have tools like "
1289 "mosaic scenes, but otherwise they are very similar.");
1290 overview->setWordWrap(
true);
1291 previewHelpLayout->addWidget(overview);
1293 previewHelpWidgetScrollArea->setWidget(previewHelpWidget);
1295 return previewHelpWidgetScrollArea;
1299 MosaicSceneItem *MosaicSceneWidget::addImage(Image *image) {
1302 setProjection(createInitialProjection(image), *image->cube()->label());
1305 MosaicSceneItem *mosItem = NULL;
1308 if (!cubeToMosaic(image)) {
1309 mosItem =
new MosaicSceneItem(image,
this);
1316 if (m_projectImageZOrders && m_projectImageZOrders->contains(image->id())) {
1317 double zOrder = m_projectImageZOrders->value(image->id());
1318 m_projectImageZOrders->remove(image->id());
1320 foreach (MosaicSceneItem *mosaicItem, *m_mosaicSceneItems) {
1321 if (mosaicItem->zValue() == zOrder) {
1322 mosaicItem->setZValue(maximumZ() + 1);
1323 m_currentMaximumFootprintZ = maximumZ() + 1;
1327 m_currentMaximumFootprintZ = qMax(zOrder, maximumZ());
1328 mosItem->setZValue(zOrder);
1331 mosItem->setZValue(maximumZ() + 1);
1332 m_currentMaximumFootprintZ = maximumZ() + 1;
1335 getScene()->addItem(mosItem);
1336 m_mosaicSceneItems->append(mosItem);
1337 m_displayPropsToMosaicSceneItemMap[image->displayProperties()] = mosItem;
1339 connect(mosItem, SIGNAL(destroyed(
QObject *)),
1340 this, SLOT(removeMosItem(
QObject *)));
1342 ImageDisplayProperties *prop = image->displayProperties();
1343 connect(prop, SIGNAL(moveDownOne()),
1344 this, SLOT(moveDownOne()));
1347 connect(prop, SIGNAL(moveUpOne()),
1348 this, SLOT(moveUpOne()));
1351 connect(prop, SIGNAL(zoomFit()),
1352 this, SLOT(fitInView()));
1360 double MosaicSceneWidget::maximumZ() {
1361 return m_currentMaximumFootprintZ;
1365 double MosaicSceneWidget::minimumZ() {
1366 return m_currentMinimumFootprintZ;
1369 void MosaicSceneWidget::recalcSceneRect() {
1371 double minX, minY, maxX, maxY;
1374 QRectF projRect(minX, -maxY, maxX - minX, maxY - minY);
1375 QRectF cubesBounding = cubesBoundingRect();
1377 QRectF bounding = projRect.united(cubesBounding);
1379 if (m_outlineRect && m_outlineRect->isVisible())
1380 bounding = bounding.united(m_outlineRect->boundingRect());
1382 getView()->setSceneRect(bounding);
1386 void MosaicSceneWidget::addImages(ImageList images) {
1387 if (m_userToolControl)
1388 m_progress->
setText(
"Loading primary scene");
1390 m_progress->
setText(
"Loading secondary scene");
1392 m_progress->setRange(0, images.size() - 1);
1393 m_progress->setValue(0);
1394 m_progress->setVisible(
true);
1396 foreach(Image *image, images) {
1400 catch (IException &e) {
1404 m_progress->setValue(m_progress->value() + 1);
1409 if (m_projectViewTransform) {
1411 PvlObject &positionInfo = *m_projectViewTransform;
1412 QByteArray hexValues(positionInfo[
"ViewTransform"][0].toLatin1());
1413 QDataStream transformStream(QByteArray::fromHex(hexValues));
1415 QTransform viewTransform;
1416 transformStream >> viewTransform;
1417 getView()->setTransform(viewTransform);
1419 QPoint projectScrollPos(
toInt(positionInfo[
"ScrollPosition"][0]),
1420 toInt(positionInfo[
"ScrollPosition"][1]));
1422 getView()->horizontalScrollBar()->setValue(projectScrollPos.x());
1423 getView()->verticalScrollBar()->setValue(projectScrollPos.y());
1429 if (!m_projectImageZOrders || m_projectImageZOrders->isEmpty()) {
1430 delete m_projectViewTransform;
1431 m_projectViewTransform = NULL;
1434 m_progress->setVisible(
false);
1435 emit cubesChanged();
1439 void MosaicSceneWidget::removeImages(ImageList images) {
1442 foreach(Image *image, images) {
1444 MosaicSceneItem *item = cubeToMosaic(image);
1445 item->deleteLater();
1446 removeMosItem(item);
1448 catch (IException &e) {
1460 QFileDialog::getSaveFileName((
QWidget *)parent(),
1461 "Choose output file",
1462 QDir::currentPath() +
"/untitled.png",
1463 QString(
"Images (*.png *.jpg *.tif)"));
1464 if (output.isEmpty())
return;
1467 if (QFileInfo(output).suffix().isEmpty()) {
1468 output = output +
".png";
1471 QString format = QFileInfo(output).suffix();
1472 QPixmap pm = getScene()->views().last()->grab();
1474 std::string formatString = format.toStdString();
1475 if (!pm.save(output, formatString.c_str())) {
1476 QMessageBox::information(
this,
"Error",
1477 "Unable to save [" + output +
"]");
1482 void MosaicSceneWidget::saveList() {
1484 QFileDialog::getSaveFileName((
QWidget *)parent(),
1485 "Choose output file",
1486 QDir::currentPath() +
"/files.lis",
1487 QString(
"List File (*.lis);;Text File (*.txt);;All Files (*.*)"));
1488 if (output.isEmpty())
return;
1490 TextFile file(output,
"overwrite");
1493 qSort(sorted.begin(), sorted.end(), zOrderGreaterThan);
1496 foreach(sceneItem, sorted) {
1497 file.PutLine( sceneItem->image()->fileName() );
1502 void MosaicSceneWidget::removeMosItem(
QObject *mosItem) {
1503 MosaicSceneItem *castedMosItem = (MosaicSceneItem *) mosItem;
1505 m_mosaicSceneItems->removeAll(castedMosItem);
1506 m_displayPropsToMosaicSceneItemMap.remove(
1507 m_displayPropsToMosaicSceneItemMap.key(castedMosItem));
1509 emit cubesChanged();
1518 QRectF sceneRect = cubesBoundingRect();
1520 if (sceneRect.isEmpty())
1523 double xPadding = sceneRect.width() * 0.10;
1524 double yPadding = sceneRect.height() * 0.10;
1526 sceneRect.adjust(-xPadding, -yPadding, xPadding, yPadding);
1527 getView()->fitInView(sceneRect, Qt::KeepAspectRatio);
1531 void MosaicSceneWidget::setCubesSelectable(
bool selectable) {
1532 if (m_cubesSelectable != selectable) {
1533 m_cubesSelectable = selectable;
1536 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1537 mosaicSceneItem->scenePropertiesChanged();
1549 configDialog.exec();
1553 void MosaicSceneWidget::quickConfigProjectionParameters() {
1555 configDialog.setQuickConfig(
true);
1556 configDialog.exec();
1560 void MosaicSceneWidget::sendVisibleRectChanged() {
1561 QPointF topLeft = getView()->mapToScene(0, 0);
1562 QPointF bottomRight = getView()->mapToScene(
1563 (
int)getView()->width(),
1564 (
int)getView()->height());
1566 QRectF visibleRect(topLeft, bottomRight);
1567 emit visibleRectChanged(visibleRect);
1571 bool MosaicSceneWidget::eventFilter(
QObject *obj, QEvent *event) {
1572 bool stopProcessingEvent =
true;
1574 switch(event->type()) {
1575 case QMouseEvent::GraphicsSceneMousePress: {
1577 if (m_customRubberBandEnabled) {
1580 if (!m_customRubberBand) {
1581 m_customRubberBand =
new QRubberBand(QRubberBand::Rectangle,
1585 if (!m_rubberBandOrigin) {
1586 m_rubberBandOrigin =
new QPoint;
1589 *m_rubberBandOrigin = getView()->mapFromScene(
1590 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1591 m_customRubberBand->setGeometry(QRect(*m_rubberBandOrigin, QSize()));
1592 m_customRubberBand->show();
1595 emit mouseButtonPress(
1596 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1597 ((QGraphicsSceneMouseEvent *)event)->button());
1599 stopProcessingEvent =
false;
1603 case QMouseEvent::GraphicsSceneMouseRelease: {
1605 bool signalEmitted =
false;
1606 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1607 m_customRubberBand) {
1608 if (m_customRubberBand->geometry().width() +
1609 m_customRubberBand->geometry().height() > 10) {
1611 emit rubberBandComplete(
1612 getView()->mapToScene(
1613 m_customRubberBand->geometry()).boundingRect(),
1614 ((QGraphicsSceneMouseEvent *)event)->button());
1615 signalEmitted =
true;
1618 delete m_rubberBandOrigin;
1619 m_rubberBandOrigin = NULL;
1621 delete m_customRubberBand;
1622 m_customRubberBand = NULL;
1625 if (!signalEmitted) {
1627 stopProcessingEvent =
false;
1628 emit mouseButtonRelease(
1629 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1630 ((QGraphicsSceneMouseEvent *)event)->button());
1635 case QMouseEvent::GraphicsSceneMouseDoubleClick:
1636 emit mouseDoubleClick(
1637 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1638 stopProcessingEvent =
false;
1641 case QMouseEvent::GraphicsSceneMouseMove:
1642 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1643 m_customRubberBand) {
1644 QPointF scenePos = ((QGraphicsSceneMouseEvent *)event)->scenePos();
1645 QPoint screenPos = getView()->mapFromScene(scenePos);
1647 QRect rubberBandRect =
1648 QRect(*m_rubberBandOrigin, screenPos).normalized();
1650 m_customRubberBand->setGeometry(rubberBandRect);
1653 stopProcessingEvent =
false;
1657 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1660 case QEvent::GraphicsSceneWheel:
1662 ((QGraphicsSceneWheelEvent *)event)->scenePos(),
1663 ((QGraphicsSceneWheelEvent *)event)->delta());
1665 stopProcessingEvent =
true;
1668 case QMouseEvent::Enter:
1670 stopProcessingEvent =
false;
1673 case QMouseEvent::Leave:
1675 stopProcessingEvent =
false;
1678 case QEvent::GraphicsSceneHelp: {
1680 bool toolTipFound =
false;
1683 foreach(sceneItem, getScene()->items()) {
1684 if (!toolTipFound) {
1685 if (sceneItem->contains(
1686 ((QGraphicsSceneHelpEvent*)event)->scenePos()) &&
1687 sceneItem->toolTip().size() > 0) {
1688 setToolTip(sceneItem->toolTip());
1689 toolTipFound =
true;
1695 stopProcessingEvent =
true;
1697 ((QGraphicsSceneHelpEvent*)event)->screenPos(),
1704 stopProcessingEvent =
false;
1708 return stopProcessingEvent;
1719 if (m_mosaicSceneItems->size() == 0)
1722 if (m_userToolControl)
1723 m_progress->
setText(
"Reprojecting primary scene");
1725 m_progress->
setText(
"Reprojecting secondary scene");
1728 int reprojectsPerUpdate = qMax(1, m_mosaicSceneItems->size() / 20);
1730 m_progress->setRange(0,
1731 (m_mosaicSceneItems->size() - 1) / reprojectsPerUpdate + 1);
1732 m_progress->setValue(0);
1733 m_progress->setVisible(
true);
1737 int progressCountdown = reprojectsPerUpdate;
1738 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1743 QString msg =
"The file [";
1745 if (mosaicSceneItem->image())
1748 msg +=
"] is being removed due to not being able to project onto the scene";
1752 mosaicSceneItem->image()->deleteLater();
1755 progressCountdown --;
1756 if (progressCountdown == 0) {
1757 m_progress->setValue(m_progress->value() + 1);
1758 progressCountdown = reprojectsPerUpdate;
1763 m_progress->setValue(m_progress->maximum());
1767 m_progress->setVisible(
false);
1771 void MosaicSceneWidget::moveDownOne() {
1775 moveDownOne(cubeToMosaic(props));
1782 double MosaicSceneWidget::moveDownOne(MosaicSceneItem *item) {
1783 MosaicSceneItem *nextDown =
getNextItem(item,
false);
1784 double originalZ = item->zValue();
1787 double newZValue = nextDown->zValue() - 1;
1788 moveZ(item, newZValue,
true);
1797 double MosaicSceneWidget::moveDownOne(Image *image) {
1798 return moveDownOne(cubeToMosaic(image));
1804 QList<double> MosaicSceneWidget::moveDownOne(ImageList *images) {
1807 foreach (Image *image, *images) {
1808 results.append(moveDownOne(image));
1815 void MosaicSceneWidget::moveToBottom() {
1816 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1830 double originalZ = item->zValue();
1831 double minZ = minimumZ();
1833 if (originalZ != minZ) {
1835 int newZValue = qRound(minZ - 1);
1836 item->setZValue(newZValue);
1839 m_currentMinimumFootprintZ--;
1850 double MosaicSceneWidget::moveToBottom(
Image *image) {
1864 foreach (
Image *image, *images) {
1872 void MosaicSceneWidget::moveUpOne() {
1876 moveUpOne(cubeToMosaic(props));
1883 double MosaicSceneWidget::moveUpOne(MosaicSceneItem *item) {
1884 MosaicSceneItem *nextUp =
getNextItem(item,
true);
1885 double originalZ = item->zValue();
1888 double newZValue = nextUp->zValue() + 1;
1889 moveZ(item, newZValue,
true);
1898 double MosaicSceneWidget::moveUpOne(Image *image) {
1899 return moveUpOne(cubeToMosaic(image));
1905 QList<double> MosaicSceneWidget::moveUpOne(ImageList *images) {
1908 foreach (Image *image, *images) {
1909 results.append(moveUpOne(image));
1916 void MosaicSceneWidget::moveToTop() {
1917 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1930 double originalZ = item->zValue();
1931 double maxZ = maximumZ();
1933 if (originalZ != maxZ) {
1935 int newZValue = qRound(maxZ + 1);
1936 item->setZValue(newZValue);
1939 m_currentMaximumFootprintZ++;
1960 double MosaicSceneWidget::moveToTop(
Image *image) {
1974 foreach (
Image *image, *images) {
2000 bool newZValueMightExist) {
2001 double originalZ = sceneItem->zValue();
2003 if (newZValueMightExist) {
2005 m_currentMinimumFootprintZ = 0.0;
2006 m_currentMaximumFootprintZ = 0.0;
2009 double otherItemOrigZ = otherItem->zValue();
2010 double otherItemNewZ = otherItemOrigZ;
2013 if (originalZ > newZ && otherItemOrigZ >= newZ && otherItemOrigZ < originalZ) {
2014 otherItemNewZ = otherItemOrigZ + 1;
2017 else if (originalZ < newZ && otherItemOrigZ <= newZ && otherItemOrigZ > originalZ) {
2018 otherItemNewZ = otherItemOrigZ - 1;
2021 m_currentMinimumFootprintZ = qMin(m_currentMinimumFootprintZ, otherItemNewZ);
2022 m_currentMaximumFootprintZ = qMax(m_currentMaximumFootprintZ, otherItemNewZ);
2023 otherItem->setZValue(otherItemNewZ);
2027 sceneItem->setZValue(newZ);
2029 if (!newZValueMightExist) {
2031 if (originalZ == maximumZ() && newZ < originalZ) {
2032 m_currentMaximumFootprintZ--;
2034 else if (originalZ == minimumZ() && newZ > originalZ) {
2035 m_currentMinimumFootprintZ++;
2044 bool newZValueMightExist) {
2045 return moveZ(cubeToMosaic(image), newZ, newZValueMightExist);
2049 void MosaicSceneWidget::fitInView() {
2050 if (m_userToolControl) {
2053 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
2056 MosaicSceneItem *item = cubeToMosaic(props);
2057 boundingBox = item->boundingRect();
2063 ImageList *images = action->data().value<ImageList *>();
2065 foreach (Image *image, *images) {
2066 ASSERT(cubeToMosaic(image));
2067 boundingBox = boundingBox.united(cubeToMosaic(image)->boundingRect());
2072 if (!boundingBox.isNull()) {
2073 double xPadding = boundingBox.width() * 0.10;
2074 double yPadding = boundingBox.height() * 0.10;
2076 boundingBox.setLeft(boundingBox.left() - xPadding);
2077 boundingBox.setRight(boundingBox.right() + xPadding);
2079 boundingBox.setTop(boundingBox.top() - yPadding);
2080 boundingBox.setBottom(boundingBox.bottom() + yPadding);
2082 getView()->fitInView(boundingBox, Qt::KeepAspectRatio);
2083 getView()->centerOn(boundingBox.center());
2089 void MosaicSceneWidget::onSelectionChanged() {
2090 if (!m_blockingSelectionChanged) {
2091 if (!m_queuedSelectionChanged) {
2092 emit queueSelectionChanged();
2093 m_queuedSelectionChanged =
true;
2096 m_shouldRequeueSelectionChanged =
true;
2102 void MosaicSceneWidget::onQueuedSelectionChanged() {
2103 m_queuedSelectionChanged =
false;
2105 if (m_shouldRequeueSelectionChanged) {
2106 m_shouldRequeueSelectionChanged =
false;
2107 onSelectionChanged();
2110 foreach(MosaicSceneItem *mosaicSceneItem, *m_mosaicSceneItems) {
2111 mosaicSceneItem->updateSelection(
true);
2122 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
2123 if (mosaicSceneItem != item &&
2124 mosaicSceneItem->boundingRect().intersects(item->boundingRect())) {
2126 if ( (up && mosaicSceneItem->zValue() > item->zValue()) ||
2127 (!up && mosaicSceneItem->zValue() < item->zValue())) {
2130 if (!nextZValueItem) {
2131 nextZValueItem = mosaicSceneItem;
2136 if ((up && mosaicSceneItem->zValue() < nextZValueItem->zValue()) ||
2137 (!up && mosaicSceneItem->zValue() > nextZValueItem->zValue())) {
2138 nextZValueItem = mosaicSceneItem;
2145 return nextZValueItem;
2151 return first->zValue() > second->zValue();
2155 MosaicSceneWidget::XmlHandler::XmlHandler(MosaicSceneWidget *scene) {
2157 m_scrollBarXValue = -1;
2158 m_scrollBarYValue = -1;
2159 m_imagesToAdd = NULL;
2161 m_imagesToAdd =
new ImageList;
2165 MosaicSceneWidget::XmlHandler::~XmlHandler() {
2166 delete m_imagesToAdd;
2167 m_imagesToAdd = NULL;
2171 bool MosaicSceneWidget::XmlHandler::startElement(
const QString &namespaceURI,
2172 const QString &localName,
const QString &qName,
const QXmlAttributes &atts) {
2173 bool result = XmlStackedHandler::startElement(namespaceURI, localName, qName, atts);
2175 m_characterData =
"";
2178 if (localName ==
"image" && m_scene->m_directory) {
2179 QString
id = atts.value(
"id");
2180 double zValue = atts.value(
"zValue").toDouble();
2181 Image *image = m_scene->m_directory->project()->image(
id);
2183 m_imagesToAdd->append(image);
2184 m_imageZValues.append(zValue);
2188 else if (localName ==
"viewTransform") {
2189 m_scrollBarXValue = atts.value(
"scrollBarXValue").toInt();
2190 m_scrollBarYValue = atts.value(
"scrollBarYValue").toInt();
2198 bool MosaicSceneWidget::XmlHandler::characters(
const QString &ch) {
2199 bool result = XmlStackedHandler::characters(ch);
2202 m_characterData += ch;
2209 bool MosaicSceneWidget::XmlHandler::endElement(
const QString &namespaceURI,
2210 const QString &localName,
const QString &qName) {
2211 bool result = XmlStackedHandler::endElement(namespaceURI, localName, qName);
2214 if (localName ==
"projection") {
2215 std::stringstream strStream(m_characterData.toStdString());
2216 PvlGroup mappingGroup;
2217 strStream >> mappingGroup;
2218 m_scene->setProjection(mappingGroup);
2220 else if (localName ==
"viewTransform") {
2221 QByteArray hexValues(m_characterData.toLatin1());
2222 QDataStream transformStream(QByteArray::fromHex(hexValues));
2224 QTransform viewTransform;
2225 transformStream >> viewTransform;
2226 m_scene->getView()->show();
2227 QCoreApplication::processEvents();
2228 m_scene->getView()->setTransform(viewTransform);
2229 m_scene->getView()->horizontalScrollBar()->setValue(m_scrollBarXValue);
2230 m_scene->getView()->verticalScrollBar()->setValue(m_scrollBarYValue);
2232 else if (localName ==
"toolData") {
2233 PvlObject toolSettings;
2234 std::stringstream strStream(m_characterData.toStdString());
2235 strStream >> toolSettings;
2237 foreach (MosaicTool *tool, *m_scene->m_tools) {
2238 if (tool->projectPvlObjectName() == toolSettings.name()) {
2239 tool->fromPvl(toolSettings);
2243 else if (localName ==
"images" && m_imagesToAdd->count()) {
2244 ASSERT(m_imagesToAdd->count() == m_imageZValues.count());
2245 qDebug()<<
"MosaicSceneWidget::endElement before m_scene->addImages";
2246 m_scene->addImages(*m_imagesToAdd);
2248 for (
int i = 0; i < m_imageZValues.count(); i++) {
2249 m_scene->cubeToMosaic(m_imagesToAdd->at(i))->setZValue(m_imageZValues[i]);
2250 m_scene->m_currentMinimumFootprintZ = qMin(m_scene->m_currentMinimumFootprintZ,
2252 m_scene->m_currentMaximumFootprintZ = qMax(m_scene->m_currentMaximumFootprintZ,
2258 m_characterData =
"";
static Isis::Projection * Create(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a Projection object.
Internalizes a list of images and allows for operations on the entire list.
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
void reproject()
Called anytime the user reprojects the cube.
Move images, one by one, on top of the immediately-above intersecting image in a scene.
The main project for cnetsuite.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
QList< QAction * > supportedActions(DataType data)
Returns a list of supported actions for a WorkOrder.
A graphics view that resizes in a more friendly way.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
int keywords() const
Returns the number of keywords contained in the PvlContainer.
int toInt(const QString &string)
Global function to convert from a string to an integer.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double toDouble(const QString &string)
Global function to convert from a string to a double.
This error is for when a programmer made an API call that was illegal.
Project * project() const
Gets the Project for this directory.
Move images, one by one, below the immediately-below intersecting image in a scene.
QList< QAction * > supportedActions(Project *project=NULL)
Gets a list of pre-connected actions that have to do with display.
Base class for Map Projections.
QString displayName() const
Returns the display name.
void setText(QString text)
Set custom text for this progress bar.
This is the configuration dialog for the MosaicSceneWidget's projection parameters (map file)...
Contains multiple PvlContainers.
#define _FILEINFO_
Macro for the filename and line number.
void print() const
Prints a string representation of this exception to stderr.
A type of error that could only have occurred due to a mistake on the user's part (e...
Move images on top of all other images in a mosaic scene.
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
A single keyword-value pair.
This represents a cube in a project-based GUI interface.
ImageDisplayProperties * displayProperties()
Get the display (GUI) properties (information) associated with this image.
virtual void setData(Context)
Sets the context data for this WorkOrder.
void append(Image *const &value)
Appends an image to the image list.
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Provides access to sequential ASCII stream I/O.
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
A graphics scene with improved user-interaction for use with the MosaicSceneWidget.
QProgressBar with customizable text.
Contains Pvl Groups and Pvl Objects.
A single cube in the mosaic scene.
his enables stack-based XML parsing of XML files.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Move images below all other images in a mosaic scene.