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" 60 #include "XmlStackedHandlerReader.h" 67 bool internalizeToolBarsAndProgress,
Directory *directory,
69 m_projectImageZOrders = NULL;
70 m_projectViewTransform = NULL;
71 m_directory = directory;
89 m_quickMapAction = NULL;
91 m_cubesSelectable =
true;
92 m_customRubberBandEnabled =
false;
93 m_customRubberBand = NULL;
94 m_rubberBandOrigin = NULL;
96 m_blockingSelectionChanged =
false;
97 m_queuedSelectionChanged =
false;
98 m_shouldRequeueSelectionChanged =
false;
100 m_userToolControl =
false;
101 m_ownProjection =
false;
104 m_progress->setVisible(
false);
106 QGridLayout * sceneLayout =
new QGridLayout;
107 sceneLayout->setContentsMargins(0, 0, 0, 0);
108 setLayout(sceneLayout);
111 if (!status && internalizeToolBarsAndProgress)
112 status =
new QStatusBar;
120 m_tools->append(cnetTool);
124 connect(cnetTool, SIGNAL(modifyControlPoint(
ControlPoint *)),
127 connect(cnetTool, SIGNAL(deleteControlPoint(
ControlPoint *)),
130 connect(cnetTool, SIGNAL(createControlPoint(
double,
double)),
131 this, SIGNAL(createControlPoint(
double,
double)));
134 connect(
this, SIGNAL(cnetModified()), cnetTool, SLOT(rebuildPointGraphics()));
142 m_tools->at(0)->activate(
true);
146 if (internalizeToolBarsAndProgress) {
161 QHBoxLayout *horizontalToolBarsLayout =
new QHBoxLayout;
163 m_permToolbar =
new QToolBar(
"Standard Tools");
164 m_permToolbar->setWhatsThis(
"This area contains options that are always present in the " 166 horizontalToolBarsLayout->addWidget(m_permToolbar);
168 m_activeToolbar =
new QToolBar(
"Active Tool",
this);
169 m_activeToolbar->setObjectName(
"Active Tool");
170 m_activeToolbar->setWhatsThis(
"The currently selected tool's options will " 171 "show up here. Not all tools have options.");
172 horizontalToolBarsLayout->addWidget(m_activeToolbar);
174 sceneLayout->addLayout(horizontalToolBarsLayout, 0, 0, 1, 2);
178 m_toolpad =
new ToolPad(
"Tool Pad",
this);
179 m_toolpad->setObjectName(
"Tool Pad");
180 m_toolpad->setOrientation(Qt::Vertical);
181 m_toolpad->setFloatable(
true);
182 sceneLayout->addWidget(m_toolpad, 1, 1, 1, 1);
184 QHBoxLayout *horizontalStatusLayout =
new QHBoxLayout;
185 horizontalStatusLayout->addWidget(m_progress);
186 horizontalStatusLayout->addStretch();
187 horizontalStatusLayout->addWidget(status);
189 sceneLayout->addLayout(horizontalStatusLayout, 2, 0, 1, 2);
191 addToPermanent(m_permToolbar);
192 m_permToolbar->addSeparator();
194 addTo(m_activeToolbar);
201 m_userToolControl =
true;
203 setWhatsThis(
"This is the mosaic scene. The opened cubes will be " 204 "shown here. You can fully interact with the files shown here.");
206 getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
207 getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
209 getView()->enableResizeZooming(
false);
211 connect(getView()->horizontalScrollBar(), SIGNAL(valueChanged(
int)),
212 this, SLOT(sendVisibleRectChanged()));
213 connect(getView()->verticalScrollBar() , SIGNAL(valueChanged(
int)),
214 this, SLOT(sendVisibleRectChanged()));
215 connect(getView()->horizontalScrollBar(), SIGNAL(rangeChanged(
int,
int)),
216 this, SLOT(sendVisibleRectChanged()));
217 connect(getView()->verticalScrollBar() , SIGNAL(rangeChanged(
int,
int)),
218 this, SLOT(sendVisibleRectChanged()));
224 getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
225 getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
227 setWhatsThis(
"This is the mosaic world view. The opened cubes will be " 228 "shown here, but you cannot zoom in. You can select cubes by dragging " 229 "a box over them, zoom to a particular cube by right clicking on it " 230 "and selecting 'Zoom Fit', and many other actions are available.");
235 m_currentMinimumFootprintZ = 0;
236 m_currentMaximumFootprintZ = 0;
238 connect(getScene(), SIGNAL(selectionChanged()),
239 this, SLOT(onSelectionChanged()));
242 connect(
this, SIGNAL(queueSelectionChanged()),
243 this, SLOT(onQueuedSelectionChanged()), Qt::QueuedConnection);
246 MosaicSceneWidget::~MosaicSceneWidget() {
247 m_outlineRect = NULL;
264 delete m_projectImageZOrders;
265 m_projectImageZOrders = NULL;
267 delete m_projectViewTransform;
268 m_projectViewTransform = NULL;
276 if (!mapping.hasKeyword(
"EquatorialRadius")) {
278 tmp.findGroup(
"Mapping") += radii[
"EquatorialRadius"];
279 tmp.findGroup(
"Mapping") += radii[
"PolarRadius"];
283 m_ownProjection =
true;
294 PvlKeyword projectionKeyword = mapping.findKeyword(
"ProjectionName");
295 QString projName = projectionKeyword[0];
296 m_mapButton->setText(tr(
"View/Edit %1 Projection").arg(projName));
305 if (old && m_ownProjection) {
310 m_ownProjection =
false;
315 void MosaicSceneWidget::setOutlineRect(QRectF outline) {
316 if (outline.united(getView()->sceneRect()) != getView()->sceneRect())
319 if (!m_outlineRect) {
320 m_outlineRect = getScene()->addRect(outline,
323 m_outlineRect->setZValue(DBL_MAX);
326 m_outlineRect->setRect(outline);
329 if (!m_userToolControl)
334 PvlGroup MosaicSceneWidget::createInitialProjection(
336 Projection *proj = NULL;
337 Cube *cube = image->cube();
338 Pvl *label = cube->label();
342 return proj->Mapping();
344 catch (IException &) {
345 Pvl mappingPvl(
"$base/templates/maps/equirectangular.map");
346 PvlGroup &mappingGrp = mappingPvl.findGroup(
"Mapping");
347 mappingGrp += PvlKeyword(
"LatitudeType",
"Planetocentric");
348 mappingGrp += PvlKeyword(
"LongitudeDirection",
"PositiveEast");
349 mappingGrp += PvlKeyword(
"LongitudeDomain",
"360");
350 mappingGrp += PvlKeyword(
"CenterLatitude",
"0");
351 mappingGrp += PvlKeyword(
"CenterLongitude",
"180");
352 mappingGrp += PvlKeyword(
"MinimumLatitude",
"-90");
353 mappingGrp += PvlKeyword(
"MaximumLatitude",
"90");
354 mappingGrp += PvlKeyword(
"MinimumLongitude",
"0");
355 mappingGrp += PvlKeyword(
"MaximumLongitude",
"360");
358 Camera * cam = cube->camera();
362 mappingGrp += PvlKeyword(
"TargetName", cam->target()->name());
363 mappingGrp += PvlKeyword(
"EquatorialRadius",
toString(radii[0].meters()),
365 mappingGrp += PvlKeyword(
"PolarRadius",
toString(radii[2].meters()),
369 catch (IException &) {
379 void MosaicSceneWidget::addToPermanent(
QToolBar *perm) {
380 m_mapButton =
new QToolButton(
this);
381 connect(
this, SIGNAL(destroyed()), m_mapButton, SLOT(deleteLater()));
382 m_mapButton->setText(tr(
"View/Edit/Load Map File"));
383 m_mapButton->setToolTip(tr(
"View/Edit/Load Map File"));
384 m_mapButton->setIcon(QIcon(FileName(
"$base/icons/ographic.png").expanded()));
385 m_mapButton->setWhatsThis(tr(
"This is the projection used by the mosaic " 386 "scene. Cubes can not be shown in the scene without a projection, so " 387 "if one is not selected, a default of Equirectangular will be used. " 388 "The selected file should be a map file, examples are available in " 389 "$base/templates/maps."));
390 m_mapButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
394 PvlKeyword projectionKeyword =
396 QString projName = projectionKeyword[0];
397 m_mapButton->setText(projName);
400 m_quickMapAction =
new QAction(tr(
"Quick Load Map"),
this);
401 m_quickMapAction->setToolTip(tr(
"Quick Load Map"));
402 m_quickMapAction->setIcon(QIcon(FileName(
"$base/icons/quickopen.png").expanded()));
403 m_quickMapAction->setWhatsThis(tr(
"This is the projection used by the mosaic " 404 "scene. Cubes can not be shown in the scene without a projection, so " 405 "if one is not selected, a default of Equirectangular will be used."));
406 connect(m_quickMapAction, SIGNAL(triggered()),
this, SLOT(quickConfigProjectionParameters()));
408 perm->addWidget(m_mapButton);
409 perm->addAction(m_quickMapAction);
413 void MosaicSceneWidget::addTo(
QToolBar *toolbar) {
415 foreach(tool, *m_tools) {
416 tool->addTo(toolbar);
421 void MosaicSceneWidget::addTo(
QMenu *menu) {
423 foreach(tool, *m_tools) {
429 void MosaicSceneWidget::addTo(ToolPad *toolPad) {
431 foreach(tool, *m_tools) {
432 tool->addTo(toolPad);
444 bool handled =
false;
448 foreach (
QGraphicsItem *graphicsItem, selectedGraphicsItems) {
451 if (!sceneImageItem) {
452 sceneImageItem =
dynamic_cast<MosaicSceneItem *
>(graphicsItem->parentItem());
455 if (sceneImageItem && sceneImageItem->image()) {
456 selectedImageItems.append(sceneImageItem);
461 if (selectedImageItems.count()) {
465 title->setEnabled(
false);
473 displayActs.append(NULL);
478 foreach(displayAct, displayActs) {
479 if (displayAct == NULL) {
483 menu.addAction(displayAct);
488 menu.exec(event->screenPos());
496 void MosaicSceneWidget::enableRubberBand(
bool enable) {
497 m_customRubberBandEnabled = enable;
501 MosaicSceneItem *MosaicSceneWidget::cubeToMosaic(Image *image) {
503 QString msg = tr(
"Can not find a NULL image in the mosaic");
507 return cubeToMosaic(image->displayProperties());
511 bool MosaicSceneWidget::blockSelectionChange(
bool block) {
512 bool wasBlocking = m_blockingSelectionChanged;
514 m_blockingSelectionChanged = block;
525 PvlObject MosaicSceneWidget::toPvl()
const {
526 PvlObject output(
"MosaicScene");
532 dataBuffer.open(QIODevice::ReadWrite);
533 QDataStream transformStream(&dataBuffer);
534 transformStream << getView()->transform();
537 PvlObject mosaicScenePosition(
"SceneVisiblePosition");
538 mosaicScenePosition += PvlKeyword(
"ViewTransform",
539 QString(dataBuffer.data().toHex()));
540 PvlKeyword scrollPos(
"ScrollPosition");
541 scrollPos +=
toString(getView()->horizontalScrollBar()->value());
542 scrollPos +=
toString(getView()->verticalScrollBar()->value());
543 mosaicScenePosition += scrollPos;
545 output += mosaicScenePosition;
548 foreach(tool, *m_tools) {
549 if (tool->projectPvlObjectName() !=
"") {
550 PvlObject toolObj = tool->toPvl();
551 toolObj.setName(tool->projectPvlObjectName());
556 PvlObject zOrders(
"ZOrdering");
557 foreach(MosaicSceneItem * mosaicSceneItem, *m_mosaicSceneItems) {
558 PvlKeyword zValue(
"ZValue");
559 zValue += mosaicSceneItem->image()->id();
560 zValue +=
toString(mosaicSceneItem->zValue());
568 "Cannot save a scene without a projection to a project file",
586 foreach(tool, *m_tools) {
587 if (tool->projectPvlObjectName() !=
"") {
588 if (project.
hasObject(tool->projectPvlObjectName())) {
590 project.
findObject(tool->projectPvlObjectName()));
591 tool->fromPvl(toolSettings);
598 delete m_projectImageZOrders;
599 m_projectImageZOrders = NULL;
602 for (
int zOrderIndex = 0;
605 const PvlKeyword &zOrder = zOrders[zOrderIndex];
607 (*m_projectImageZOrders)[zOrder[0]] =
toDouble(zOrder[1]);
611 if (project.
hasObject(
"SceneVisiblePosition")) {
615 delete m_projectViewTransform;
616 m_projectViewTransform =
new PvlObject(positionInfo);
627 void MosaicSceneWidget::save(QXmlStreamWriter &stream, Project *, FileName )
const {
629 stream.writeStartElement(
"mosaicScene");
631 stream.writeStartElement(
"projection");
633 std::stringstream strStream;
634 strStream << mapping;
635 stream.writeCharacters(strStream.str().c_str());
636 stream.writeEndElement();
638 stream.writeStartElement(
"images");
639 foreach(MosaicSceneItem * mosaicSceneItem, *m_mosaicSceneItems) {
640 stream.writeStartElement(
"image");
641 stream.writeAttribute(
"id", mosaicSceneItem->image()->id());
642 stream.writeAttribute(
"zValue",
toString(mosaicSceneItem->zValue()));
643 stream.writeEndElement();
645 stream.writeEndElement();
647 stream.writeStartElement(
"viewTransform");
648 stream.writeAttribute(
"scrollBarXValue",
toString(getView()->horizontalScrollBar()->value()));
649 stream.writeAttribute(
"scrollBarYValue",
toString(getView()->verticalScrollBar()->value()));
651 dataBuffer.open(QIODevice::ReadWrite);
652 QDataStream transformStream(&dataBuffer);
653 transformStream << getView()->transform();
655 stream.writeCharacters(dataBuffer.data().toHex());
656 stream.writeEndElement();
658 foreach(MosaicTool *tool, *m_tools) {
659 QString projectPvlObjectName = tool->projectPvlObjectName();
660 if (projectPvlObjectName !=
"") {
661 PvlObject toolObj = tool->toPvl();
662 toolObj.setName(projectPvlObjectName);
664 stream.writeStartElement(
"toolData");
665 stream.writeAttribute(
"objectName", projectPvlObjectName);
666 std::stringstream strStream;
667 strStream << toolObj;
668 stream.writeCharacters(strStream.str().c_str());
669 stream.writeEndElement();
673 stream.writeEndElement();
678 QRectF MosaicSceneWidget::cubesBoundingRect()
const {
681 MosaicSceneItem * mosaicItem;
682 foreach(mosaicItem, *m_mosaicSceneItems) {
683 if (boundingRect.isEmpty())
684 boundingRect = mosaicItem->boundingRect();
686 boundingRect = boundingRect.united(mosaicItem->boundingRect());
690 boundingRect = boundingRect.united(m_outlineRect->boundingRect());
696 MosaicSceneItem *MosaicSceneWidget::cubeToMosaic(DisplayProperties *props) {
698 QString msg = tr(
"Can not find a NULL Display Properties in the mosaic");
702 return m_displayPropsToMosaicSceneItemMap[props];
709 MosaicSceneItem *mosaicSceneItem;
710 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
711 if (mosaicSceneItem->image())
712 cubes.append(mosaicSceneItem->image()->fileName());
719 Directory *MosaicSceneWidget::directory()
const {
724 ImageList MosaicSceneWidget::images() {
727 MosaicSceneItem *mosaicSceneItem;
728 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
729 if (mosaicSceneItem->image())
730 images.
append(mosaicSceneItem->image());
748 foreach (
QGraphicsItem *graphicsItem, selectedGraphicsItems) {
751 if (!sceneImageItem) {
752 sceneImageItem =
dynamic_cast<MosaicSceneItem *
>(graphicsItem->parentItem());
755 if (sceneImageItem && sceneImageItem->image()) {
756 selectedImageItems.append(sceneImageItem);
787 saveList->setText(
"Save Entire Cube List (ordered by &view)...");
788 connect(saveList, SIGNAL(triggered()),
this, SLOT(saveList()));
791 exportActs.append(saveList);
800 foreach(MosaicTool *tool, *m_tools) {
802 viewActs.append(toolViewActs);
814 bool allImagesInView = !images->isEmpty();
816 foreach (
Image *image, *images) {
817 allImagesInView = allImagesInView && (cubeToMosaic(image) != NULL);
820 if (allImagesInView) {
824 results.append(moveToTopAct);
829 results.append(moveUpOneAct);
833 moveToBottomAct->
setData(images);
834 results.append(moveToBottomAct);
838 moveDownOneAct->
setData(images);
839 results.append(moveDownOneAct);
841 results.append(NULL);
844 zoomFitAct->setData(qVariantFromValue(images));
845 connect(zoomFitAct, SIGNAL(triggered()),
this, SLOT(fitInView()));
846 results.append(zoomFitAct);
852 bool MosaicSceneWidget::isControlNetToolActive() {
857 if (cnTool->
isActive())
return true;
864 QWidget * MosaicSceneWidget::getControlNetHelp(
QWidget *cnetToolContainer) {
865 QScrollArea *cnetHelpWidgetScrollArea =
new QScrollArea;
869 QVBoxLayout *cnetHelpLayout =
new QVBoxLayout;
870 cnetHelpWidget->setLayout(cnetHelpLayout);
872 QLabel *title =
new QLabel(
"<h2>Control Networks</h2>");
873 cnetHelpLayout->addWidget(title);
875 QPixmap previewPixmap;
877 if (cnetToolContainer) {
878 previewPixmap = cnetToolContainer->grab().scaled(
879 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
882 ToolPad tmpToolPad(
"Example Tool Pad", NULL);
883 MosaicControlNetTool tmpTool(NULL);
884 tmpTool.addTo(&tmpToolPad);
886 tmpToolPad.resize(QSize(32, 32));
888 previewPixmap = tmpToolPad.grab();
891 QLabel *previewWrapper =
new QLabel;
892 previewWrapper->setPixmap(previewPixmap);
893 cnetHelpLayout->addWidget(previewWrapper);
895 QLabel *overview =
new QLabel(
"The mosaic scene can display control points " 896 "in addition to the usual cube footprints. This feature is currently " 897 "offered as one of the Mosaic Scene's tools. To open a network, click " 898 "on the control network tool. It will immediately prompt you for a " 899 "control network file if one is not open. Only control points for " 900 "which the latitude and longitude can be established will be " 901 "displayed. Other control points will be ignored by qmos.<br><br>" 902 "<b>Warning: Opening large control networks is slow.</b>" 903 "<h3>Control Network Tool Options</h3>" 905 "<li>The control network tool opens control networks in two ways. " 906 "First, if you select the control network tool and no network is " 907 "open, then it will prompt you for one. Second, if there is an open " 908 "network, the buttons for the available options are displayed in the " 909 "active tool area.</li>" 910 "<li>The control network tool can toggle whether or not control " 911 "points are displayed on the screen using the 'Display' button. " 912 "Control points are always on top and colored based on their " 913 "ignored, locked and type values.</li>" 914 "<li>This tool can also change the color of your footprints based on " 915 "connectivity through control points. This is available through the " 916 "'Color Islands' button. When you press color islands, all of the " 917 "current cube coloring information is lost and re-done based on " 918 "how the control network connects the files. Each set of connected " 919 "cubes are colored differently; generally speaking, islands are not " 920 "a good thing to have in your control network.</li>" 921 "<li>This tool will color your footprints on a per-image basis if you " 922 "click color images, effectively reversing color islands.</li>" 923 "<li>The show movement option under 'Configure Movement Display' " 924 "only displays data when the control " 925 "network has adjusted values. This means that show movement only " 926 "works after you have done a jigsaw solution on the control network. " 927 "This displays arrows emanating from the apriori latitude/longitude " 928 "and pointing toward the adjusted latitude/longitude.</li>");
929 overview->setWordWrap(
true);
930 cnetHelpLayout->addWidget(overview);
932 cnetHelpWidgetScrollArea->setWidget(cnetHelpWidget);
934 return cnetHelpWidgetScrollArea;
938 QWidget * MosaicSceneWidget::getGridHelp(
QWidget *gridToolContainer) {
939 QScrollArea *gridHelpWidgetScrollArea =
new QScrollArea;
943 QVBoxLayout *gridHelpLayout =
new QVBoxLayout;
944 gridHelpWidget->setLayout(gridHelpLayout);
946 QLabel *title =
new QLabel(
"<h2>Map Grid Tool</h2>");
947 gridHelpLayout->addWidget(title);
949 QPixmap previewPixmap;
951 if (gridToolContainer) {
952 previewPixmap = gridToolContainer->grab().scaled(
953 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
956 ToolPad tmpToolPad(
"Example Tool Pad", NULL);
957 MosaicGridTool tmpTool(NULL);
958 tmpTool.addTo(&tmpToolPad);
960 tmpToolPad.resize(QSize(32, 32));
962 previewPixmap = tmpToolPad.grab();
965 QLabel *previewWrapper =
new QLabel;
966 previewWrapper->setPixmap(previewPixmap);
967 gridHelpLayout->addWidget(previewWrapper);
969 QLabel *overview =
new QLabel(
"Superimpose a map grid over the area of " 970 "displayed footprints in the 'mosaic scene.'" 973 "<li>The Map Grid Tool is activated by selecting the 'cross-hatch' " 974 "icon or typing 'g' at the keyboard." 976 "<li>The parameter options are displayed below the menubar. " 977 "Clicking the 'Grid Options' button will open the dialog. Checking " 978 "'Auto Grid' will draw a grid based on the open cubes. Hitting " 979 "'Show Grid' will display or hide the grid." 981 "<li>The map grid is defined by the loaded Map File (just as the " 982 "footprints and image data are), the opened cubes, or the grid " 985 "<li>If a Map File has not been selected, the default " 986 "Equirectangular projection will be used. The resulting grid " 987 "lines in the default 'Equi' map file will be drawn for the " 988 "full global range (latitude range = -90,90; longitude range = " 989 "0,360) at the default latitude and longitude increment values." 992 "If the grid lines are not immediately visible, try to " 993 "'zoom out' in the 'mosaic scene' window and modify the " 994 "Latitude and Longitude Increment parameters." 997 "<strong>Options:</strong>" 999 "<li>The 'Show Grid' option draws (checked) or clears (unchecked) the grid." 1001 "<li>The 'Auto Grid' option draws a grid with extents and increments " 1002 "computed from the set of images that are opened. The values displayed in the dialog " 1003 "will reflect those used to draw the grid." 1005 "<li>The expected units for each entry are displayed to the right of the " 1008 "<li>The 'Extent Type' combo boxes allow you to pick the source of the " 1009 "grid extents from the map file, from the open cubes <default>, or manually " 1012 "<li>The 'Auto Apply' checkbox, inside the 'Grid Options' dialog box, allows you to see " 1013 "real time updates in the grid when you change the parameters." 1015 "<li> Depending on the projection, the grid may not behave as expected. For instance, " 1016 "with a polarstereographic projection, the pole will not be included in the 'Auto " 1017 "Grid' if it is not in the cube region. In this case the 'Manual' option for latitude " 1018 "extents allows you to force the grid to the pole." 1021 overview->setWordWrap(
true);
1022 gridHelpLayout->addWidget(overview);
1024 gridHelpWidgetScrollArea->setWidget(gridHelpWidget);
1026 return gridHelpWidgetScrollArea;
1030 QWidget * MosaicSceneWidget::getLongHelp(
QWidget *sceneContainer) {
1031 QScrollArea *longHelpWidgetScrollArea =
new QScrollArea;
1035 QVBoxLayout *longHelpLayout =
new QVBoxLayout;
1036 longHelpWidget->setLayout(longHelpLayout);
1038 QLabel *title =
new QLabel(
"<h2>Mosaic Scene</h2>");
1039 longHelpLayout->addWidget(title);
1041 if (sceneContainer) {
1042 QPixmap previewPixmap = sceneContainer->grab().scaled(
1043 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1045 QLabel *previewWrapper =
new QLabel;
1046 previewWrapper->setPixmap(previewPixmap);
1047 longHelpLayout->addWidget(previewWrapper);
1050 QLabel *overview =
new QLabel(
"The mosaic scene displays cube footprints " 1051 "to show where files are on a target and how they overlap. " 1052 "The scene always represents projected image space and cannot show raw " 1053 "or unprojected images; images will be projected on the fly." 1055 "<p>Interact with the mosaic scene in different ways using " 1056 "the tools. The tools are usually in a toolbar next to the scene. " 1057 "The tools define what is displayed and what happens when you " 1058 "click in the mosaic scene. The tools include</p>" 1059 "<ul><li>Select Tool</li>" 1060 "<li>Zoom Tool</li>" 1062 "<li>Control Network Tool</li>" 1063 "<li>Show Area Tool</li>" 1064 "<li>Find Tool</li>" 1065 "<li>Grid Tool</li></ul>" 1066 "<h3>Context Menus</h3>" 1067 "Right click on anything in the mosaic scene and a context menu will pop up showing " 1068 "a list of actions or information relevant to the item you clicked on. " 1069 "<p>Note: The context menu is not associated with any selection, only the item " 1071 overview->setWordWrap(
true);
1072 longHelpLayout->addWidget(overview);
1074 longHelpWidgetScrollArea->setWidget(longHelpWidget);
1076 return longHelpWidgetScrollArea;
1081 QScrollArea *mapHelpWidgetScrollArea =
new QScrollArea;
1085 QVBoxLayout *mapHelpLayout =
new QVBoxLayout;
1086 mapHelpWidget->setLayout(mapHelpLayout);
1088 QLabel *title =
new QLabel(tr(
"<h2>Map File</h2>"));
1089 mapHelpLayout->addWidget(title);
1092 QPixmap previewPixmap = mapContainer->grab().scaled(
1093 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1095 QLabel *previewWrapper =
new QLabel;
1096 previewWrapper->setPixmap(previewPixmap);
1097 mapHelpLayout->addWidget(previewWrapper);
1100 QLabel *overviewMapIcon =
new QLabel;
1102 overviewMapIcon->setPixmap(
1103 QIcon(FileName(
"$base/icons/ographic.png").expanded()).pixmap(32, 32));
1104 mapHelpLayout->addWidget(overviewMapIcon);
1106 QLabel *defaultMapFile =
new QLabel(tr(
1107 "<h3>Default Map File</h3>" 1108 "The mosaic scene's projection is defined by a \"Map File\" that consists of keywords " 1109 "that describe the map layout to be used. If a cube or a list of cubes are " 1110 "loaded before a map file is selected, the default map file defines the " 1111 "equirectangular projection, planetocentric latitude, positive longitude east, 360 " 1112 "longitude domain, latitude range=90S-90N, longitude range=0-360E. The radius will " 1113 "default to the IAU standards (ellipsoid or sphere) for the specific planetary body " 1114 "defined for the \"TargetName\" in the labels of the image cube(s)."));
1116 defaultMapFile->setWordWrap(
true);
1117 mapHelpLayout->addWidget(defaultMapFile);
1119 QLabel *userDefinedMapFileOverview =
new QLabel(tr(
1120 "<h3>User Defined Map File</h3>" 1121 "You can load an existing \"Map File\" before loading images into %1 by selecting the " 1122 "\"View/Edit/Load Map File\" option. You will be greeted with a dialog box that will " 1123 "enable you to select an existing map file by clicking on \"Load Map File.\" Once " 1124 "the map file is selected, the contents is displayed in the dialog box where " 1125 "modifications can be made as well. If the modified map file is to be used later, " 1126 "save the map file by clicking on \"Save Map File\" button.")
1127 .arg(QCoreApplication::applicationName()));
1129 userDefinedMapFileOverview->setWordWrap(
true);
1130 mapHelpLayout->addWidget(userDefinedMapFileOverview);
1132 QLabel *userDefinedMapFileQuickLoad =
new QLabel(tr(
1133 "The \"Quick Load Map\" option (lightning icon) allows you to efficiently select a " 1134 "prepared \"Map File\" without an immediate need to view or edit the contents."));
1136 userDefinedMapFileQuickLoad->setWordWrap(
true);
1137 mapHelpLayout->addWidget(userDefinedMapFileQuickLoad);
1139 QLabel *userDefinedMapFileAnyTime =
new QLabel(tr(
1140 "At any point, you have access to the \"View/Edit\" functionality to modify or load a " 1141 "different map file."));
1143 userDefinedMapFileAnyTime->setWordWrap(
true);
1144 mapHelpLayout->addWidget(userDefinedMapFileAnyTime);
1146 QString mapProjWorkshopUrl(
"https://isis.astrogeology.usgs.gov/fixit/projects/" 1147 "isis/wiki/Learning_About_Map_Projections");
1148 QLabel *preparingMapFile =
new QLabel(tr(
1149 "<h3>Preparing a Map File</h3>" 1150 "Please refer to Isis applications such as 'maptemplate' or 'mosrange' for more details " 1151 "on creating a custom map file that defines the desired projection, latitude " 1152 "system, and longitude direction and domain. This program will use the latitude range " 1153 "and longitude range if they exist in the loaded file. A choice of map templates that can be used as " 1154 "a starting point for supported map projections can be found in $base/templates/maps (refer " 1155 "to maptemplate or mosrange for more details and information on the required parameters " 1156 "for a projection). Note that through the file name selection box, $base will need " 1157 "to be replaced with the specific Isis3 system path. The website: " 1158 "<a href='%1'>%1</a> also provides useful information about map projections.")
1159 .arg(mapProjWorkshopUrl));
1161 preparingMapFile->setOpenExternalLinks(
true);
1162 preparingMapFile->setWordWrap(
true);
1163 mapHelpLayout->addWidget(preparingMapFile);
1165 QLabel *mapFileDisplayResults =
new QLabel(tr(
1166 "<h3>Display Results with the Map File</h3>" 1167 "The footprints and image data that are displayed in the mosaic scene are defined by the " 1168 "loaded \"Map File\" regardless of whether the opened cubes are Level1 (raw " 1169 "camera space) or Level2 (map projected). The associated footprint polygons for " 1170 "Level2 cubes will be re-mapped as needed based on the loaded map file."));
1172 mapFileDisplayResults->setWordWrap(
true);
1173 mapHelpLayout->addWidget(mapFileDisplayResults);
1175 QLabel *editingMapFileOverview =
new QLabel(tr(
1176 "<h3>Editing a Map File</h3>" 1177 "Editing a map file is possible through the dialog box displayed by clicking on the " 1178 "'View/Edit/Load Map File' icon/button. The edits are " 1179 "applied to the current session and will be included with a 'Saved Project' (refer to " 1180 "the help under File-Save Project or Save Project as)."));
1182 editingMapFileOverview->setWordWrap(
true);
1183 mapHelpLayout->addWidget(editingMapFileOverview);
1185 QLabel *saveMapFileToDiskBullet =
new QLabel(tr(
1188 "To save or write the changes to a map file on disk, choose 'Save Map File' button. " 1189 "Map files can be saved to an existing map file (overwrites) or to a new file. This " 1190 "program always saves <strong>exactly</strong> what you see, the text, in the dialog " 1195 saveMapFileToDiskBullet->setWordWrap(
true);
1196 mapHelpLayout->addWidget(saveMapFileToDiskBullet);
1198 QLabel *mapFileValidityBullet =
new QLabel(tr(
1201 "As you modify the contents of a loaded map file in the dialog box, the entry is " 1202 "verified as you type with a bold black indicator message displaying whether the " 1203 "text is valid or is not valid. If you want to see the actual error messages, " 1204 "select the 'Show Errors' box and the errors will be displayed in red font " 1205 "along with the black bolded message. The errors will update " 1210 mapFileValidityBullet->setWordWrap(
true);
1211 mapHelpLayout->addWidget(mapFileValidityBullet);
1213 QLabel *mapFileCommentsBullet =
new QLabel(tr(
1216 "Map files may contain 'commented-out' lines (text that starts with \"#\" at " 1217 "the beginning of the line). These are referred to as \"unnecessary\"" 1218 "or \"unknown\" keywords, they are simply ignored. If these lines are to be saved to " 1219 "the output map file on disk, click 'Save Map File' BEFORE clicking 'Ok' or 'Apply.' " 1220 "The comments are removed from the dialog box when you hit 'Ok' or 'Apply,' if they " 1221 "are just above \"End_Group\" or follow \"End_Group\" or \"End\".<br/><br/>" 1223 "If you want these comments retained, make sure they are immediately above a valid " 1224 "keyword inside of \"Group = Mapping.\" Note that any lines (commented or not) will " 1225 "not be saved if they are placed outside of \"Group = Mapping\" and \"End_Group\"." 1229 mapFileCommentsBullet->setWordWrap(
true);
1230 mapHelpLayout->addWidget(mapFileCommentsBullet);
1232 mapHelpWidgetScrollArea->setWidget(mapHelpWidget);
1234 return mapHelpWidgetScrollArea;
1238 QWidget * MosaicSceneWidget::getPreviewHelp(
QWidget *worldViewContainer) {
1239 QScrollArea *previewHelpWidgetScrollArea =
new QScrollArea;
1243 QVBoxLayout *previewHelpLayout =
new QVBoxLayout;
1244 previewHelpWidget->setLayout(previewHelpLayout);
1246 QLabel *title =
new QLabel(
"<h2>Mosaic World View</h2>");
1247 previewHelpLayout->addWidget(title);
1249 if (worldViewContainer) {
1250 QPixmap previewPixmap = worldViewContainer->grab().scaled(
1251 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1253 QLabel *previewWrapper =
new QLabel;
1254 previewWrapper->setPixmap(previewPixmap);
1255 previewHelpLayout->addWidget(previewWrapper);
1258 QLabel *overview =
new QLabel(
"The mosaic world view displays cube " 1259 "footprints to show you where your files are on a target and their " 1260 "general arrangement. The world view does not have tools like " 1261 "mosaic scenes, but otherwise they are very similar.");
1262 overview->setWordWrap(
true);
1263 previewHelpLayout->addWidget(overview);
1265 previewHelpWidgetScrollArea->setWidget(previewHelpWidget);
1267 return previewHelpWidgetScrollArea;
1271 MosaicSceneItem *MosaicSceneWidget::addImage(Image *image) {
1273 setProjection(createInitialProjection(image), *image->cube()->label());
1276 MosaicSceneItem *mosItem = NULL;
1279 if (!cubeToMosaic(image)) {
1280 mosItem =
new MosaicSceneItem(image,
this);
1284 connect(mosItem, SIGNAL(mosaicCubeClosed(Image *)),
1285 this, SIGNAL(mosCubeClosed(Image *)));
1289 if (m_projectImageZOrders && m_projectImageZOrders->contains(image->id())) {
1290 double zOrder = m_projectImageZOrders->value(image->id());
1291 m_projectImageZOrders->remove(image->id());
1293 foreach (MosaicSceneItem *mosaicItem, *m_mosaicSceneItems) {
1294 if (mosaicItem->zValue() == zOrder) {
1295 mosaicItem->setZValue(maximumZ() + 1);
1296 m_currentMaximumFootprintZ = maximumZ() + 1;
1300 m_currentMaximumFootprintZ = qMax(zOrder, maximumZ());
1301 mosItem->setZValue(zOrder);
1304 mosItem->setZValue(maximumZ() + 1);
1305 m_currentMaximumFootprintZ = maximumZ() + 1;
1308 getScene()->addItem(mosItem);
1309 m_mosaicSceneItems->append(mosItem);
1310 m_displayPropsToMosaicSceneItemMap[image->displayProperties()] = mosItem;
1312 connect(mosItem, SIGNAL(destroyed(
QObject *)),
1313 this, SLOT(removeMosItem(
QObject *)));
1315 ImageDisplayProperties *prop = image->displayProperties();
1316 connect(prop, SIGNAL(moveDownOne()),
1317 this, SLOT(moveDownOne()));
1320 connect(prop, SIGNAL(moveUpOne()),
1321 this, SLOT(moveUpOne()));
1324 connect(prop, SIGNAL(zoomFit()),
1325 this, SLOT(fitInView()));
1332 double MosaicSceneWidget::maximumZ() {
1333 return m_currentMaximumFootprintZ;
1337 double MosaicSceneWidget::minimumZ() {
1338 return m_currentMinimumFootprintZ;
1341 void MosaicSceneWidget::recalcSceneRect() {
1343 double minX, minY, maxX, maxY;
1346 QRectF projRect(minX, -maxY, maxX - minX, maxY - minY);
1347 QRectF cubesBounding = cubesBoundingRect();
1349 QRectF bounding = projRect.united(cubesBounding);
1351 if (m_outlineRect && m_outlineRect->isVisible())
1352 bounding = bounding.united(m_outlineRect->boundingRect());
1354 getView()->setSceneRect(bounding);
1358 void MosaicSceneWidget::addImages(ImageList images) {
1359 if (m_userToolControl)
1360 m_progress->
setText(
"Loading primary scene");
1362 m_progress->
setText(
"Loading secondary scene");
1364 m_progress->setRange(0, images.size() - 1);
1365 m_progress->setValue(0);
1366 m_progress->setVisible(
true);
1368 foreach(Image *image, images) {
1372 catch (IException &e) {
1376 m_progress->setValue(m_progress->value() + 1);
1381 if (m_projectViewTransform) {
1382 PvlObject &positionInfo = *m_projectViewTransform;
1383 QByteArray hexValues(positionInfo[
"ViewTransform"][0].toLatin1());
1384 QDataStream transformStream(QByteArray::fromHex(hexValues));
1386 QTransform viewTransform;
1387 transformStream >> viewTransform;
1388 getView()->setTransform(viewTransform);
1390 QPoint projectScrollPos(
toInt(positionInfo[
"ScrollPosition"][0]),
1391 toInt(positionInfo[
"ScrollPosition"][1]));
1393 getView()->horizontalScrollBar()->setValue(projectScrollPos.x());
1394 getView()->verticalScrollBar()->setValue(projectScrollPos.y());
1400 if (!m_projectImageZOrders || m_projectImageZOrders->isEmpty()) {
1401 delete m_projectViewTransform;
1402 m_projectViewTransform = NULL;
1405 m_progress->setVisible(
false);
1406 emit cubesChanged();
1410 void MosaicSceneWidget::removeImages(ImageList images) {
1413 foreach(Image *image, images) {
1415 MosaicSceneItem *item = cubeToMosaic(image);
1416 item->deleteLater();
1417 removeMosItem(item);
1419 catch (IException &e) {
1431 QFileDialog::getSaveFileName((
QWidget *)parent(),
1432 "Choose output file",
1433 QDir::currentPath() +
"/untitled.png",
1434 QString(
"Images (*.png *.jpg *.tif)"));
1435 if (output.isEmpty())
return;
1438 if (QFileInfo(output).suffix().isEmpty()) {
1439 output = output +
".png";
1442 QString format = QFileInfo(output).suffix();
1443 QPixmap pm = getScene()->views().last()->grab();
1445 std::string formatString = format.toStdString();
1446 if (!pm.save(output, formatString.c_str())) {
1447 QMessageBox::information(
this,
"Error",
1448 "Unable to save [" + output +
"]");
1453 void MosaicSceneWidget::saveList() {
1455 QFileDialog::getSaveFileName((
QWidget *)parent(),
1456 "Choose output file",
1457 QDir::currentPath() +
"/files.lis",
1458 QString(
"List File (*.lis);;Text File (*.txt);;All Files (*.*)"));
1459 if (output.isEmpty())
return;
1461 TextFile file(output,
"overwrite");
1464 qSort(sorted.begin(), sorted.end(), zOrderGreaterThan);
1467 foreach(sceneItem, sorted) {
1468 file.PutLine( sceneItem->image()->fileName() );
1473 void MosaicSceneWidget::removeMosItem(
QObject *mosItem) {
1474 MosaicSceneItem *castedMosItem = (MosaicSceneItem *) mosItem;
1475 m_mosaicSceneItems->removeAll(castedMosItem);
1476 m_displayPropsToMosaicSceneItemMap.remove(
1477 m_displayPropsToMosaicSceneItemMap.key(castedMosItem));
1479 emit cubesChanged();
1488 QRectF sceneRect = cubesBoundingRect();
1490 if (sceneRect.isEmpty())
1493 double xPadding = sceneRect.width() * 0.10;
1494 double yPadding = sceneRect.height() * 0.10;
1496 sceneRect.adjust(-xPadding, -yPadding, xPadding, yPadding);
1497 getView()->fitInView(sceneRect, Qt::KeepAspectRatio);
1501 void MosaicSceneWidget::setCubesSelectable(
bool selectable) {
1502 if (m_cubesSelectable != selectable) {
1503 m_cubesSelectable = selectable;
1506 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1507 mosaicSceneItem->scenePropertiesChanged();
1519 configDialog.exec();
1523 void MosaicSceneWidget::quickConfigProjectionParameters() {
1525 configDialog.setQuickConfig(
true);
1526 configDialog.exec();
1530 void MosaicSceneWidget::sendVisibleRectChanged() {
1531 QPointF topLeft = getView()->mapToScene(0, 0);
1532 QPointF bottomRight = getView()->mapToScene(
1533 (
int)getView()->width(),
1534 (
int)getView()->height());
1536 QRectF visibleRect(topLeft, bottomRight);
1537 emit visibleRectChanged(visibleRect);
1541 bool MosaicSceneWidget::eventFilter(
QObject *obj, QEvent *event) {
1542 bool stopProcessingEvent =
true;
1544 switch(event->type()) {
1545 case QMouseEvent::GraphicsSceneMousePress: {
1546 if (m_customRubberBandEnabled) {
1548 if (!m_customRubberBand) {
1549 m_customRubberBand =
new QRubberBand(QRubberBand::Rectangle,
1553 if (!m_rubberBandOrigin) {
1554 m_rubberBandOrigin =
new QPoint;
1557 *m_rubberBandOrigin = getView()->mapFromScene(
1558 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1559 m_customRubberBand->setGeometry(QRect(*m_rubberBandOrigin, QSize()));
1560 m_customRubberBand->show();
1563 emit mouseButtonPress(
1564 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1565 ((QGraphicsSceneMouseEvent *)event)->button());
1566 stopProcessingEvent =
false;
1570 case QMouseEvent::GraphicsSceneMouseRelease: {
1571 bool signalEmitted =
false;
1572 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1573 m_customRubberBand) {
1574 if (m_customRubberBand->geometry().width() +
1575 m_customRubberBand->geometry().height() > 10) {
1576 emit rubberBandComplete(
1577 getView()->mapToScene(
1578 m_customRubberBand->geometry()).boundingRect(),
1579 ((QGraphicsSceneMouseEvent *)event)->button());
1580 signalEmitted =
true;
1583 delete m_rubberBandOrigin;
1584 m_rubberBandOrigin = NULL;
1586 delete m_customRubberBand;
1587 m_customRubberBand = NULL;
1590 if (!signalEmitted) {
1591 stopProcessingEvent =
false;
1592 emit mouseButtonRelease(
1593 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1594 ((QGraphicsSceneMouseEvent *)event)->button());
1599 case QMouseEvent::GraphicsSceneMouseDoubleClick:
1600 emit mouseDoubleClick(
1601 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1602 stopProcessingEvent =
false;
1605 case QMouseEvent::GraphicsSceneMouseMove:
1606 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1607 m_customRubberBand) {
1608 QPointF scenePos = ((QGraphicsSceneMouseEvent *)event)->scenePos();
1609 QPoint screenPos = getView()->mapFromScene(scenePos);
1611 QRect rubberBandRect =
1612 QRect(*m_rubberBandOrigin, screenPos).normalized();
1614 m_customRubberBand->setGeometry(rubberBandRect);
1617 stopProcessingEvent =
false;
1621 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1624 case QEvent::GraphicsSceneWheel:
1626 ((QGraphicsSceneWheelEvent *)event)->scenePos(),
1627 ((QGraphicsSceneWheelEvent *)event)->delta());
1629 stopProcessingEvent =
true;
1632 case QMouseEvent::Enter:
1634 stopProcessingEvent =
false;
1637 case QMouseEvent::Leave:
1639 stopProcessingEvent =
false;
1642 case QEvent::GraphicsSceneHelp: {
1644 bool toolTipFound =
false;
1647 foreach(sceneItem, getScene()->items()) {
1648 if (!toolTipFound) {
1649 if (sceneItem->contains(
1650 ((QGraphicsSceneHelpEvent*)event)->scenePos()) &&
1651 sceneItem->toolTip().size() > 0) {
1652 setToolTip(sceneItem->toolTip());
1653 toolTipFound =
true;
1659 stopProcessingEvent =
true;
1661 ((QGraphicsSceneHelpEvent*)event)->screenPos(),
1668 stopProcessingEvent =
false;
1672 return stopProcessingEvent;
1683 if (m_mosaicSceneItems->size() == 0)
1686 if (m_userToolControl)
1687 m_progress->
setText(
"Reprojecting primary scene");
1689 m_progress->
setText(
"Reprojecting secondary scene");
1692 int reprojectsPerUpdate = qMax(1, m_mosaicSceneItems->size() / 20);
1694 m_progress->setRange(0,
1695 (m_mosaicSceneItems->size() - 1) / reprojectsPerUpdate + 1);
1696 m_progress->setValue(0);
1697 m_progress->setVisible(
true);
1701 int progressCountdown = reprojectsPerUpdate;
1702 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1707 QString msg =
"The file [";
1709 if (mosaicSceneItem->image())
1712 msg +=
"] is being removed due to not being able to project onto the scene";
1716 mosaicSceneItem->image()->deleteLater();
1719 progressCountdown --;
1720 if (progressCountdown == 0) {
1721 m_progress->setValue(m_progress->value() + 1);
1722 progressCountdown = reprojectsPerUpdate;
1727 m_progress->setValue(m_progress->maximum());
1731 m_progress->setVisible(
false);
1735 void MosaicSceneWidget::moveDownOne() {
1739 moveDownOne(cubeToMosaic(props));
1746 double MosaicSceneWidget::moveDownOne(MosaicSceneItem *item) {
1747 MosaicSceneItem *nextDown =
getNextItem(item,
false);
1748 double originalZ = item->zValue();
1751 double newZValue = nextDown->zValue() - 1;
1752 moveZ(item, newZValue,
true);
1761 double MosaicSceneWidget::moveDownOne(Image *image) {
1762 return moveDownOne(cubeToMosaic(image));
1768 QList<double> MosaicSceneWidget::moveDownOne(ImageList *images) {
1771 foreach (Image *image, *images) {
1772 results.append(moveDownOne(image));
1779 void MosaicSceneWidget::moveToBottom() {
1780 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1792 double originalZ = item->zValue();
1793 double minZ = minimumZ();
1795 if (originalZ != minZ) {
1797 int newZValue = qRound(minZ - 1);
1798 item->setZValue(newZValue);
1801 m_currentMinimumFootprintZ--;
1812 double MosaicSceneWidget::moveToBottom(
Image *image) {
1824 foreach (
Image *image, *images) {
1832 void MosaicSceneWidget::moveUpOne() {
1836 moveUpOne(cubeToMosaic(props));
1843 double MosaicSceneWidget::moveUpOne(MosaicSceneItem *item) {
1844 MosaicSceneItem *nextUp =
getNextItem(item,
true);
1845 double originalZ = item->zValue();
1848 double newZValue = nextUp->zValue() + 1;
1849 moveZ(item, newZValue,
true);
1858 double MosaicSceneWidget::moveUpOne(Image *image) {
1859 return moveUpOne(cubeToMosaic(image));
1865 QList<double> MosaicSceneWidget::moveUpOne(ImageList *images) {
1868 foreach (Image *image, *images) {
1869 results.append(moveUpOne(image));
1876 void MosaicSceneWidget::moveToTop() {
1877 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1890 double originalZ = item->zValue();
1891 double maxZ = maximumZ();
1893 if (originalZ != maxZ) {
1895 int newZValue = qRound(maxZ + 1);
1896 item->setZValue(newZValue);
1899 m_currentMaximumFootprintZ++;
1920 double MosaicSceneWidget::moveToTop(
Image *image) {
1932 foreach (
Image *image, *images) {
1958 bool newZValueMightExist) {
1959 double originalZ = sceneItem->zValue();
1961 if (newZValueMightExist) {
1963 m_currentMinimumFootprintZ = 0.0;
1964 m_currentMaximumFootprintZ = 0.0;
1967 double otherItemOrigZ = otherItem->zValue();
1968 double otherItemNewZ = otherItemOrigZ;
1971 if (originalZ > newZ && otherItemOrigZ >= newZ && otherItemOrigZ < originalZ) {
1972 otherItemNewZ = otherItemOrigZ + 1;
1975 else if (originalZ < newZ && otherItemOrigZ <= newZ && otherItemOrigZ > originalZ) {
1976 otherItemNewZ = otherItemOrigZ - 1;
1979 m_currentMinimumFootprintZ = qMin(m_currentMinimumFootprintZ, otherItemNewZ);
1980 m_currentMaximumFootprintZ = qMax(m_currentMaximumFootprintZ, otherItemNewZ);
1981 otherItem->setZValue(otherItemNewZ);
1985 sceneItem->setZValue(newZ);
1987 if (!newZValueMightExist) {
1989 if (originalZ == maximumZ() && newZ < originalZ) {
1990 m_currentMaximumFootprintZ--;
1992 else if (originalZ == minimumZ() && newZ > originalZ) {
1993 m_currentMinimumFootprintZ++;
2002 bool newZValueMightExist) {
2003 return moveZ(cubeToMosaic(image), newZ, newZValueMightExist);
2007 void MosaicSceneWidget::fitInView() {
2008 if (m_userToolControl) {
2011 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
2014 MosaicSceneItem *item = cubeToMosaic(props);
2015 boundingBox = item->boundingRect();
2021 ImageList *images = action->data().value<ImageList *>();
2023 foreach (Image *image, *images) {
2024 ASSERT(cubeToMosaic(image));
2025 boundingBox = boundingBox.united(cubeToMosaic(image)->boundingRect());
2030 if (!boundingBox.isNull()) {
2031 double xPadding = boundingBox.width() * 0.10;
2032 double yPadding = boundingBox.height() * 0.10;
2034 boundingBox.setLeft(boundingBox.left() - xPadding);
2035 boundingBox.setRight(boundingBox.right() + xPadding);
2037 boundingBox.setTop(boundingBox.top() - yPadding);
2038 boundingBox.setBottom(boundingBox.bottom() + yPadding);
2040 getView()->fitInView(boundingBox, Qt::KeepAspectRatio);
2041 getView()->centerOn(boundingBox.center());
2047 void MosaicSceneWidget::onSelectionChanged() {
2048 if (!m_blockingSelectionChanged) {
2049 if (!m_queuedSelectionChanged) {
2050 emit queueSelectionChanged();
2051 m_queuedSelectionChanged =
true;
2054 m_shouldRequeueSelectionChanged =
true;
2060 void MosaicSceneWidget::onQueuedSelectionChanged() {
2061 m_queuedSelectionChanged =
false;
2063 if (m_shouldRequeueSelectionChanged) {
2064 m_shouldRequeueSelectionChanged =
false;
2065 onSelectionChanged();
2068 foreach(MosaicSceneItem *mosaicSceneItem, *m_mosaicSceneItems) {
2069 mosaicSceneItem->updateSelection(
true);
2080 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
2081 if (mosaicSceneItem != item &&
2082 mosaicSceneItem->boundingRect().intersects(item->boundingRect())) {
2084 if ( (up && mosaicSceneItem->zValue() > item->zValue()) ||
2085 (!up && mosaicSceneItem->zValue() < item->zValue())) {
2088 if (!nextZValueItem) {
2089 nextZValueItem = mosaicSceneItem;
2094 if ((up && mosaicSceneItem->zValue() < nextZValueItem->zValue()) ||
2095 (!up && mosaicSceneItem->zValue() > nextZValueItem->zValue())) {
2096 nextZValueItem = mosaicSceneItem;
2103 return nextZValueItem;
2109 return first->zValue() > second->zValue();
2113 MosaicSceneWidget::XmlHandler::XmlHandler(MosaicSceneWidget *scene) {
2115 m_scrollBarXValue = -1;
2116 m_scrollBarYValue = -1;
2117 m_imagesToAdd = NULL;
2119 m_imagesToAdd =
new ImageList;
2123 MosaicSceneWidget::XmlHandler::~XmlHandler() {
2124 delete m_imagesToAdd;
2125 m_imagesToAdd = NULL;
2129 bool MosaicSceneWidget::XmlHandler::startElement(
const QString &namespaceURI,
2130 const QString &localName,
const QString &qName,
const QXmlAttributes &atts) {
2131 bool result = XmlStackedHandler::startElement(namespaceURI, localName, qName, atts);
2133 m_characterData =
"";
2136 if (localName ==
"image" && m_scene->m_directory) {
2137 QString
id = atts.value(
"id");
2138 double zValue = atts.value(
"zValue").toDouble();
2139 Image *image = m_scene->m_directory->project()->image(
id);
2143 Shape *shape = m_scene->m_directory->project()->shape(
id);
2145 image =
new Image(shape->cube(), shape->footprint(), id);
2149 m_imagesToAdd->append(image);
2150 m_imageZValues.append(zValue);
2154 else if (localName ==
"viewTransform") {
2155 m_scrollBarXValue = atts.value(
"scrollBarXValue").toInt();
2156 m_scrollBarYValue = atts.value(
"scrollBarYValue").toInt();
2164 bool MosaicSceneWidget::XmlHandler::characters(
const QString &ch) {
2165 bool result = XmlStackedHandler::characters(ch);
2168 m_characterData += ch;
2175 bool MosaicSceneWidget::XmlHandler::endElement(
const QString &namespaceURI,
2176 const QString &localName,
const QString &qName) {
2177 bool result = XmlStackedHandler::endElement(namespaceURI, localName, qName);
2180 if (localName ==
"projection") {
2181 std::stringstream strStream(m_characterData.toStdString());
2182 PvlGroup mappingGroup;
2183 strStream >> mappingGroup;
2184 m_scene->setProjection(mappingGroup);
2186 else if (localName ==
"viewTransform") {
2187 QByteArray hexValues(m_characterData.toLatin1());
2188 QDataStream transformStream(QByteArray::fromHex(hexValues));
2190 QTransform viewTransform;
2191 transformStream >> viewTransform;
2192 m_scene->getView()->show();
2193 QCoreApplication::processEvents();
2194 m_scene->getView()->setTransform(viewTransform);
2195 m_scene->getView()->horizontalScrollBar()->setValue(m_scrollBarXValue);
2196 m_scene->getView()->verticalScrollBar()->setValue(m_scrollBarYValue);
2198 else if (localName ==
"toolData") {
2199 PvlObject toolSettings;
2200 std::stringstream strStream(m_characterData.toStdString());
2201 strStream >> toolSettings;
2203 foreach (MosaicTool *tool, *m_scene->m_tools) {
2204 if (tool->projectPvlObjectName() == toolSettings.name()) {
2205 tool->fromPvl(toolSettings);
2209 else if (localName ==
"images" && m_imagesToAdd->count()) {
2210 ASSERT(m_imagesToAdd->count() == m_imageZValues.count());
2211 m_scene->addImages(*m_imagesToAdd);
2213 for (
int i = 0; i < m_imageZValues.count(); i++) {
2214 m_scene->cubeToMosaic(m_imagesToAdd->at(i))->setZValue(m_imageZValues[i]);
2215 m_scene->m_currentMinimumFootprintZ = qMin(m_scene->m_currentMinimumFootprintZ,
2217 m_scene->m_currentMaximumFootprintZ = qMax(m_scene->m_currentMaximumFootprintZ,
2223 m_characterData =
"";
static Isis::Projection * Create(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a Projection object.
int keywords() const
Returns the number of keywords contained in the PvlContainer.
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 This workorder...
The main project for ipce.
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 toInt(const QString &string)
Global function to convert from a string to an integer.
QString displayName() const
Returns the display name.
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.
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
Move images, one by one, below the immediately-below intersecting image in a scene This workorder is ...
QList< QAction * > supportedActions(Project *project=NULL)
Gets a list of pre-connected actions that have to do with display.
Base class for Map Projections.
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.
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 This workorder is synchronous and undoable...
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
A single keyword-value pair.
virtual void pushContentHandler(XmlStackedHandler *newHandler)
Push a contentHandler and maybe continue parsing...
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.
void print() const
Prints a string representation of this exception to stderr.
Namespace for ISIS/Bullet specific routines.
A graphics scene with improved user-interaction for use with the MosaicSceneWidget.
Project * project() const
Gets the Project for this directory.
Contains Pvl Groups and Pvl Objects.
A single cube in the mosaic scene.
Manage a stack of content handlers for reading 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 This workorder is synchronous and undoable...