Isis 3 Programmer Reference
MosaicSceneWidget.cpp
1#include "MosaicSceneWidget.h"
2
3#include <sstream>
4
5#include <QFileDialog>
6#include <QGraphicsSceneContextMenuEvent>
7#include <QGridLayout>
8#include <QHBoxLayout>
9#include <QLabel>
10#include <QMessageBox>
11#include <QMenu>
12#include <QRubberBand>
13#include <QScrollBar>
14#include <QStatusBar>
15#include <QString>
16#include <QToolButton>
17#include <QToolTip>
18#include <QtCore>
19#include <QtWidgets>
20#include <QtXml>
21
22#include "Camera.h"
23#include "Cube.h"
24#include "Directory.h"
25#include "Distance.h"
26#include "FileName.h"
27#include "GraphicsView.h"
28#include "Image.h"
29#include "ImageList.h"
30#include "Latitude.h"
31#include "Longitude.h"
32#include "MosaicAreaTool.h"
33#include "MosaicControlNetTool.h"
34#include "MosaicFindTool.h"
35#include "MosaicGraphicsScene.h"
36#include "MosaicGraphicsView.h"
37#include "MosaicGridTool.h"
38#include "MosaicPanTool.h"
39#include "MosaicSceneItem.h"
40#include "MosaicSelectTool.h"
41#include "MosaicTrackTool.h"
42#include "MosaicZoomTool.h"
43#include "MoveDownOneSceneWorkOrder.h"
44#include "MoveToBottomSceneWorkOrder.h"
45#include "MoveToTopSceneWorkOrder.h"
46#include "MoveUpOneSceneWorkOrder.h"
47#include "ProgressBar.h"
48#include "Project.h"
49#include "Projection.h"
50#include "ProjectionConfigDialog.h"
51#include "ProjectionFactory.h"
52#include "PvlObject.h"
53#include "Pvl.h"
54#include "Shape.h"
55#include "TextFile.h"
56#include "Target.h"
57#include "ToolPad.h"
58
59namespace Isis {
63 MosaicSceneWidget::MosaicSceneWidget(QStatusBar *status, bool showTools,
64 bool internalizeToolBarsAndProgress, Directory *directory,
65 QWidget *parent) : QWidget(parent) {
66 m_projectImageZOrders = NULL;
67 m_projectViewTransform = NULL;
68 m_directory = directory;
69
70 m_mosaicSceneItems = new QList<MosaicSceneItem *>;
71
73 m_graphicsScene->installEventFilter(this);
74
77 m_graphicsView->setInteractive(true);
78// m_graphicsView->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
79 m_graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter);
80 // This enables OpenGL acceleration
81// m_graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
82// QPixmapCache::setCacheLimit(1024 * 1024);
83
84 m_projection = NULL;
85 m_mapButton = NULL;
86 m_quickMapAction = NULL;
87
88 m_cubesSelectable = true;
89 m_customRubberBandEnabled = false;
90 m_customRubberBand = NULL;
91 m_rubberBandOrigin = NULL;
92 m_outlineRect = NULL;
93 m_blockingSelectionChanged = false;
94 m_queuedSelectionChanged = false;
95 m_shouldRequeueSelectionChanged = false;
96
97 m_userToolControl = false;
98 m_ownProjection = false;
99
100 m_progress = new ProgressBar;
101 m_progress->setVisible(false);
102
103 QGridLayout * sceneLayout = new QGridLayout;
104 sceneLayout->setContentsMargins(0, 0, 0, 0);
105 setLayout(sceneLayout);
106
107 // If we are making our own layout, we can create our own status area.
108 if (!status && internalizeToolBarsAndProgress)
109 status = new QStatusBar;
110
111 // Create the tools we want
112 m_tools = new QList<MosaicTool *>;
113 m_tools->append(new MosaicSelectTool(this));
114 m_tools->append(new MosaicZoomTool(this));
115 m_tools->append(new MosaicPanTool(this));
116 MosaicControlNetTool *cnetTool = new MosaicControlNetTool(this);
117 m_tools->append(cnetTool);
118
119 // Pass on Signals emitted from MosaicControlNetTool
120 // TODO 2016-09-09 TLS Design: Use a proxy model instead of signals?
121 connect(cnetTool, SIGNAL(modifyControlPoint(ControlPoint *)),
122 this, SIGNAL(modifyControlPoint(ControlPoint *)));
123
124 connect(cnetTool, SIGNAL(deleteControlPoint(ControlPoint *)),
125 this, SIGNAL(deleteControlPoint(ControlPoint *)));
126
127 connect(cnetTool, SIGNAL(createControlPoint(double, double)),
128 this, SIGNAL(createControlPoint(double, double)));
129
130 // Pass on signals to the MosaicControlNetTool
131 connect(this, SIGNAL(cnetModified()), cnetTool, SLOT(rebuildPointGraphics()));
132
133 m_tools->append(new MosaicAreaTool(this));
134 m_tools->append(new MosaicFindTool(this));
135 m_tools->append(new MosaicGridTool(this));
136 if (status)
137 m_tools->append(new MosaicTrackTool(this, status));
138
139 m_tools->at(0)->activate(true);
140
141 if (showTools) {
142
143 if (internalizeToolBarsAndProgress) {
144 // Internalized Toolbar Layout:
145 /*
146 * -------TOOLBARS------ Colspan=2, Rowspan=1
147 * | SCENE | T |
148 * | CS=1, RS=1 | O |
149 * | | O |
150 * | | L |
151 * | | B |
152 * | | A |
153 * | | R |*Vertical tool bar CS=1, RS=1
154 * ----PROGRESS---STATUS- Colspan=2, Rowspan=1
155 *
156 *
157 */
158 QHBoxLayout *horizontalToolBarsLayout = new QHBoxLayout;
159
160 m_permToolbar = new QToolBar("Standard Tools");
161 m_permToolbar->setWhatsThis("This area contains options that are always present in the "
162 "footprint view");
163 horizontalToolBarsLayout->addWidget(m_permToolbar);
164
165 m_activeToolbar = new QToolBar("Active Tool", this);
166 m_activeToolbar->setObjectName("Active Tool");
167 m_activeToolbar->setWhatsThis("The currently selected tool's options will "
168 "show up here. Not all tools have options.");
169 horizontalToolBarsLayout->addWidget(m_activeToolbar);
170
171 sceneLayout->addLayout(horizontalToolBarsLayout, 0, 0, 1, 2);
172
173 sceneLayout->addWidget(m_graphicsView, 1, 0, 1, 1);
174
175 m_toolpad = new ToolPad("Tool Pad", this);
176 m_toolpad->setObjectName("Tool Pad");
177 m_toolpad->setOrientation(Qt::Vertical);
178 m_toolpad->setFloatable(true);
179 sceneLayout->addWidget(m_toolpad, 1, 1, 1, 1);
180
181 QHBoxLayout *horizontalStatusLayout = new QHBoxLayout;
182 horizontalStatusLayout->addWidget(m_progress);
183 horizontalStatusLayout->addStretch();
184 horizontalStatusLayout->addWidget(status);
185
186 sceneLayout->addLayout(horizontalStatusLayout, 2, 0, 1, 2);
187
188 addToPermanent(m_permToolbar);
189 m_permToolbar->addSeparator();
190
191 addTo(m_activeToolbar);
192 addTo(m_toolpad);
193 }
194 else {
195 sceneLayout->addWidget(m_graphicsView, 0, 0, 1, 1);
196 }
197
198 m_userToolControl = true;
199
200 setWhatsThis("This is the mosaic scene. The opened cubes will be "
201 "shown here. You can fully interact with the files shown here.");
202
203 getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
204 getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
205
206 getView()->enableResizeZooming(false);
207
208 connect(getView()->horizontalScrollBar(), SIGNAL(valueChanged(int)),
209 this, SLOT(sendVisibleRectChanged()));
210 connect(getView()->verticalScrollBar() , SIGNAL(valueChanged(int)),
211 this, SLOT(sendVisibleRectChanged()));
212 connect(getView()->horizontalScrollBar(), SIGNAL(rangeChanged(int, int)),
213 this, SLOT(sendVisibleRectChanged()));
214 connect(getView()->verticalScrollBar() , SIGNAL(rangeChanged(int, int)),
215 this, SLOT(sendVisibleRectChanged()));
216
217 }
218 else {
219 sceneLayout->addWidget(m_graphicsView, 0, 0, 1, 1);
220
221 getView()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
222 getView()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
223
224 setWhatsThis("This is the mosaic world view. The opened cubes will be "
225 "shown here, but you cannot zoom in. You can select cubes by dragging "
226 "a box over them, zoom to a particular cube by right clicking on it "
227 "and selecting 'Zoom Fit', and many other actions are available.");
228 }
229
230 // These values are OK as long as they are less than the min/greater than the max. No footprints
231 // are available yet, so 0 qualifies for both (makes a good starting point).
232 m_currentMinimumFootprintZ = 0;
233 m_currentMaximumFootprintZ = 0;
234
235 connect(getScene(), SIGNAL(selectionChanged()),
236 this, SLOT(onSelectionChanged()));
237 // This is set up to do a single selection changed after all selections have changed, instead
238 // of 1 selection changed per 1 changed item.
239 connect(this, SIGNAL(queueSelectionChanged()),
240 this, SLOT(onQueuedSelectionChanged()), Qt::QueuedConnection);
241 }
242
243 MosaicSceneWidget::~MosaicSceneWidget() {
244 m_outlineRect = NULL; // The scene will clean this up
245
246 if (m_tools) {
247 foreach(MosaicTool *tool, *m_tools) {
248 delete tool;
249 tool = NULL;
250 }
251
252 delete m_tools;
253 m_tools = NULL;
254 }
255
256 if (m_ownProjection && m_projection) {
257 delete m_projection;
258 }
259 m_projection = NULL;
260
261 delete m_projectImageZOrders;
262 m_projectImageZOrders = NULL;
263
264 delete m_projectViewTransform;
265 m_projectViewTransform = NULL;
266 }
267
268
269 void MosaicSceneWidget::setProjection(const PvlGroup &mapping, Pvl label) {
270 Pvl tmp;
271 tmp += mapping;
272
273 if (!mapping.hasKeyword("EquatorialRadius")) {
274 PvlGroup radii = Target::radiiGroup(label, mapping);
275 tmp.findGroup("Mapping") += radii["EquatorialRadius"];
276 tmp.findGroup("Mapping") += radii["PolarRadius"];
277 }
278
280 m_ownProjection = true;
281 }
282
283
288 PvlGroup mapping(proj->Mapping());
289
290 if (m_mapButton) {
291 PvlKeyword projectionKeyword = mapping.findKeyword("ProjectionName");
292 QString projName = projectionKeyword[0];
293 m_mapButton->setText(tr("View/Edit %1 Projection").arg(projName));
294 }
295
297 m_projection = proj;
298
300 emit projectionChanged(m_projection);
301
302 if (old && m_ownProjection) {
303 delete old;
304 old = NULL;
305 }
306
307 m_ownProjection = false;
308 }
309
310
311
312 void MosaicSceneWidget::setOutlineRect(QRectF outline) {
313 if (outline.united(getView()->sceneRect()) != getView()->sceneRect())
314 outline = QRectF();
315
316 if (!m_outlineRect) {
317 m_outlineRect = getScene()->addRect(outline,
318 QPen(Qt::black),
319 Qt::NoBrush);
320 m_outlineRect->setZValue(DBL_MAX);
321 }
322 else {
323 m_outlineRect->setRect(outline);
324 }
325
326 if (!m_userToolControl)
327 refit();
328 }
329
330
331 PvlGroup MosaicSceneWidget::createInitialProjection(
332 Image *image) {
333 Projection *proj = NULL;
334 Cube *cube = image->cube();
335 Pvl *label = cube->label();
336
337 try {
339 return proj->Mapping();
340 }
341 catch (IException &) {
342 Pvl mappingPvl("$ISISROOT/appdata/templates/maps/equirectangular.map");
343 PvlGroup &mappingGrp = mappingPvl.findGroup("Mapping");
344 mappingGrp += PvlKeyword("LatitudeType", "Planetocentric");
345 mappingGrp += PvlKeyword("LongitudeDirection", "PositiveEast");
346 mappingGrp += PvlKeyword("LongitudeDomain", "360");
347 mappingGrp += PvlKeyword("CenterLatitude", "0");
348 mappingGrp += PvlKeyword("CenterLongitude", "180");
349 mappingGrp += PvlKeyword("MinimumLatitude", "-90");
350 mappingGrp += PvlKeyword("MaximumLatitude", "90");
351 mappingGrp += PvlKeyword("MinimumLongitude", "0");
352 mappingGrp += PvlKeyword("MaximumLongitude", "360");
353
354 try {
355 Camera * cam = cube->camera();
356 Distance radii[3];
357 cam->radii(radii);
358
359 mappingGrp += PvlKeyword("TargetName", cam->target()->name());
360 mappingGrp += PvlKeyword("EquatorialRadius", toString(radii[0].meters()),
361 "meters");
362 mappingGrp += PvlKeyword("PolarRadius", toString(radii[2].meters()),
363 "meters");
364
365 }
366 catch (IException &) {
367 mappingGrp +=
368 label->findGroup("Instrument", Pvl::Traverse)["TargetName"];
369 }
370
371 return mappingGrp;
372 }
373 }
374
375
376 void MosaicSceneWidget::addToPermanent(QToolBar *perm) {
377 m_mapButton = new QToolButton(this);
378 connect(this, SIGNAL(destroyed()), m_mapButton, SLOT(deleteLater()));
379 m_mapButton->setText(tr("View/Edit/Load Map File"));
380 m_mapButton->setToolTip(tr("View/Edit/Load Map File"));
381 m_mapButton->setIcon(QIcon(FileName("$ISISROOT/appdata/images/icons/ographic.png").expanded()));
382 m_mapButton->setWhatsThis(tr("This is the projection used by the mosaic "
383 "scene. Cubes can not be shown in the scene without a projection, so "
384 "if one is not selected, a default of Equirectangular will be used. "
385 "The selected file should be a map file, examples are available in "
386 "$ISISROOT/appdata/templates/maps."));
387 m_mapButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
388 connect(m_mapButton, SIGNAL(clicked()), this, SLOT(configProjectionParameters()));
389
390 if (m_projection) {
391 PvlKeyword projectionKeyword =
392 m_projection->Mapping().findKeyword("ProjectionName");
393 QString projName = projectionKeyword[0];
394 m_mapButton->setText(projName);
395 }
396
397 m_quickMapAction = new QAction(tr("Quick Load Map"), this);
398 m_quickMapAction->setToolTip(tr("Quick Load Map"));
399 m_quickMapAction->setIcon(QIcon(FileName("$ISISROOT/appdata/images/icons/quickopen.png").expanded()));
400 m_quickMapAction->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 connect(m_quickMapAction, SIGNAL(triggered()), this, SLOT(quickConfigProjectionParameters()));
404
405 perm->addWidget(m_mapButton);
406 perm->addAction(m_quickMapAction);
407 }
408
409
410 void MosaicSceneWidget::addTo(QToolBar *toolbar) {
411 MosaicTool *tool;
412 foreach(tool, *m_tools) {
413 tool->addTo(toolbar);
414 }
415 }
416
417
418 void MosaicSceneWidget::addTo(QMenu *menu) {
419 MosaicTool *tool;
420 foreach(tool, *m_tools) {
421 tool->addTo(menu);
422 }
423 }
424
425
426 void MosaicSceneWidget::addTo(ToolPad *toolPad) {
427 MosaicTool *tool;
428 foreach(tool, *m_tools) {
429 tool->addTo(toolPad);
430 }
431 }
432
433
439 bool MosaicSceneWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
440
441 bool handled = false;
442 QList<QGraphicsItem *> selectedGraphicsItems = getScene()->selectedItems();
443 QList<MosaicSceneItem *> selectedImageItems;
445 foreach (QGraphicsItem *graphicsItem, selectedGraphicsItems) {
446 MosaicSceneItem *sceneImageItem = dynamic_cast<MosaicSceneItem *>(graphicsItem);
447
448 if (!sceneImageItem) {
449 sceneImageItem = dynamic_cast<MosaicSceneItem *>(graphicsItem->parentItem());
450 }
451
452 if (sceneImageItem && sceneImageItem->image()) {
453 selectedImageItems.append(sceneImageItem);
454 selectedImages.append(sceneImageItem->image());
455 }
456 }
457
458 if (selectedImageItems.count()) {
459 QMenu menu;
460
461 QAction *title = menu.addAction(tr("%L1 Selected Images").arg(selectedImages.count()));
462 title->setEnabled(false);
463 menu.addSeparator();
464
465 Project *project = m_directory ? m_directory->project() : NULL;
466
467 QList<QAction *> displayActs = selectedImages.supportedActions(project);
468
469 if (m_directory) {
470 displayActs.append(NULL);
471 displayActs.append(m_directory->supportedActions(new ImageList(selectedImages)));
472 }
473
474 QAction *displayAct;
475 foreach(displayAct, displayActs) {
476 if (displayAct == NULL) {
477 menu.addSeparator();
478 }
479 else {
480 menu.addAction(displayAct);
481 }
482 }
483
484 handled = true;
485 menu.exec(event->screenPos());
486 }
487
488 return handled;
489
490 }
491
492
493 void MosaicSceneWidget::enableRubberBand(bool enable) {
494 m_customRubberBandEnabled = enable;
495 }
496
497
498 MosaicSceneItem *MosaicSceneWidget::cubeToMosaic(Image *image) {
499 if (image == NULL) {
500 QString msg = tr("Can not find a NULL image in the mosaic");
501 throw IException(IException::Programmer, msg, _FILEINFO_);
502 }
503
504 return cubeToMosaic(image->displayProperties());
505 }
506
507
508 bool MosaicSceneWidget::blockSelectionChange(bool block) {
509 bool wasBlocking = m_blockingSelectionChanged;
510
511 m_blockingSelectionChanged = block;
512
513 return wasBlocking;
514 }
515
516
517 QProgressBar *MosaicSceneWidget::getProgress() {
518 return m_progress;
519 }
520
521
522 PvlObject MosaicSceneWidget::toPvl() const {
523 PvlObject output("MosaicScene");
524
525 if (m_projection) {
526 output += m_projection->Mapping();
527
528 QBuffer dataBuffer;
529 dataBuffer.open(QIODevice::ReadWrite);
530 QDataStream transformStream(&dataBuffer);
531 transformStream << getView()->transform();
532 dataBuffer.seek(0);
533
534 PvlObject mosaicScenePosition("SceneVisiblePosition");
535 mosaicScenePosition += PvlKeyword("ViewTransform",
536 QString(dataBuffer.data().toHex()));
537 PvlKeyword scrollPos("ScrollPosition");
538 scrollPos += toString(getView()->horizontalScrollBar()->value());
539 scrollPos += toString(getView()->verticalScrollBar()->value());
540 mosaicScenePosition += scrollPos;
541
542 output += mosaicScenePosition;
543
544 MosaicTool *tool;
545 foreach(tool, *m_tools) {
546 if (tool->projectPvlObjectName() != "") {
547 PvlObject toolObj = tool->toPvl();
548 toolObj.setName(tool->projectPvlObjectName());
549 output += toolObj;
550 }
551 }
552
553 PvlObject zOrders("ZOrdering");
554 foreach(MosaicSceneItem * mosaicSceneItem, *m_mosaicSceneItems) {
555 PvlKeyword zValue("ZValue");
556 zValue += mosaicSceneItem->image()->id();
557 zValue += toString(mosaicSceneItem->zValue());
558 zOrders += zValue;
559 }
560
561 output += zOrders;
562 }
563 else {
564 throw IException(IException::User,
565 "Cannot save a scene without a projection to a project file",
566 _FILEINFO_);
567 }
568
569 return output;
570 }
571
572
579 setProjection(project.findGroup("Mapping"));
580 recalcSceneRect();
581
582 MosaicTool *tool;
583 foreach(tool, *m_tools) {
584 if (tool->projectPvlObjectName() != "") {
585 if (project.hasObject(tool->projectPvlObjectName())) {
586 const PvlObject &toolSettings(
587 project.findObject(tool->projectPvlObjectName()));
588 tool->fromPvl(toolSettings);
589 }
590 }
591
592 if (project.hasObject("ZOrdering")) {
593 const PvlObject &zOrders = project.findObject("ZOrdering");
594
595 delete m_projectImageZOrders;
596 m_projectImageZOrders = NULL;
597 m_projectImageZOrders = new QHash<QString, double>;
598
599 for (int zOrderIndex = 0;
600 zOrderIndex < zOrders.keywords();
601 zOrderIndex ++) {
602 const PvlKeyword &zOrder = zOrders[zOrderIndex];
603
604 (*m_projectImageZOrders)[zOrder[0]] = toDouble(zOrder[1]);
605 }
606 }
607
608 if (project.hasObject("SceneVisiblePosition")) {
609 const PvlObject &positionInfo =
610 project.findObject("SceneVisiblePosition");
611
612 delete m_projectViewTransform;
613 m_projectViewTransform = new PvlObject(positionInfo);
614 }
615 }
616 }
617
618
619 void MosaicSceneWidget::save(QXmlStreamWriter &stream, Project *, FileName ) const {
620 if (m_projection) {
621 stream.writeStartElement("mosaicScene");
622
623 stream.writeStartElement("projection");
624 PvlGroup mapping = m_projection->Mapping();
625 std::stringstream strStream;
626 strStream << mapping;
627 stream.writeCharacters(strStream.str().c_str());
628 stream.writeEndElement();
629
630 stream.writeStartElement("images");
631 foreach(MosaicSceneItem * mosaicSceneItem, *m_mosaicSceneItems) {
632 stream.writeStartElement("image");
633 stream.writeAttribute("id", mosaicSceneItem->image()->id());
634 stream.writeAttribute("zValue", toString(mosaicSceneItem->zValue()));
635 stream.writeEndElement();
636 }
637 stream.writeEndElement();
638
639 stream.writeStartElement("viewTransform");
640 stream.writeAttribute("scrollBarXValue", toString(getView()->horizontalScrollBar()->value()));
641 stream.writeAttribute("scrollBarYValue", toString(getView()->verticalScrollBar()->value()));
642 QBuffer dataBuffer;
643 dataBuffer.open(QIODevice::ReadWrite);
644 QDataStream transformStream(&dataBuffer);
645 transformStream << getView()->transform();
646 dataBuffer.seek(0);
647 stream.writeCharacters(dataBuffer.data().toHex());
648 stream.writeEndElement();
649
650 foreach(MosaicTool *tool, *m_tools) {
651 QString projectPvlObjectName = tool->projectPvlObjectName();
652 if (projectPvlObjectName != "") {
653 PvlObject toolObj = tool->toPvl();
654 toolObj.setName(projectPvlObjectName);
655
656 stream.writeStartElement("toolData");
657 stream.writeAttribute("objectName", projectPvlObjectName);
658 std::stringstream strStream;
659 strStream << toolObj;
660 stream.writeCharacters(strStream.str().c_str());
661 stream.writeEndElement();
662 }
663 }
664
665 stream.writeEndElement();
666 }
667 }
668
669
670 QRectF MosaicSceneWidget::cubesBoundingRect() const {
671 QRectF boundingRect;
672
673 MosaicSceneItem * mosaicItem;
674 foreach(mosaicItem, *m_mosaicSceneItems) {
675 if (boundingRect.isEmpty())
676 boundingRect = mosaicItem->boundingRect();
677 else
678 boundingRect = boundingRect.united(mosaicItem->boundingRect());
679 }
680
681 if (m_outlineRect)
682 boundingRect = boundingRect.united(m_outlineRect->boundingRect());
683
684 return boundingRect;
685 }
686
687
688 MosaicSceneItem *MosaicSceneWidget::cubeToMosaic(DisplayProperties *props) {
689 if (props == NULL) {
690 QString msg = tr("Can not find a NULL Display Properties in the mosaic");
691 throw IException(IException::Programmer, msg, _FILEINFO_);
692 }
693
694 return m_displayPropsToMosaicSceneItemMap[props];
695 }
696
697
698 QStringList MosaicSceneWidget::cubeFileNames() {
699 QStringList cubes;
700
701 MosaicSceneItem *mosaicSceneItem;
702 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
703 if (mosaicSceneItem->image())
704 cubes.append(mosaicSceneItem->image()->fileName());
705 }
706
707 return cubes;
708 }
709
710
711 Directory *MosaicSceneWidget::directory() const {
712 return m_directory;
713 }
714
715
716 ImageList MosaicSceneWidget::images() {
717 ImageList images;
718
719 MosaicSceneItem *mosaicSceneItem;
720 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
721 if (mosaicSceneItem->image())
722 images.append(mosaicSceneItem->image());
723 }
724
725 return images;
726 }
727
728
735
736 QList<QGraphicsItem *> selectedGraphicsItems = getScene()->selectedItems();
737 QList<MosaicSceneItem *> selectedImageItems;
739
740 foreach (QGraphicsItem *graphicsItem, selectedGraphicsItems) {
741 MosaicSceneItem *sceneImageItem = dynamic_cast<MosaicSceneItem *>(graphicsItem);
742
743 if (!sceneImageItem) {
744 sceneImageItem = dynamic_cast<MosaicSceneItem *>(graphicsItem->parentItem());
745 }
746
747 if (sceneImageItem && sceneImageItem->image()) {
748 selectedImageItems.append(sceneImageItem);
749 selectedImages.append(sceneImageItem->image());
750 }
751 }
752 return selectedImages;
753
754
755
756
757
758// ImageList images;
759// //qDebug()<<"MosaicSceneWidget::selectedImages TotalItems = "<<m_mosaicSceneItems->size();
760// MosaicSceneItem *mosaicItem;
761// foreach(mosaicItem, *m_mosaicSceneItems) {
762// if (mosaicItem->isSelected()) {
763// images.append(mosaicItem->image());
764// }
765// }
766//
767// return images;
768 }
769
770
771 QList<QAction *> MosaicSceneWidget::getExportActions() {
772 QList<QAction *> exportActs;
773
774 QAction *exportView = new QAction(this);
775 exportView->setText("&Export View...");
776 connect(exportView, SIGNAL(triggered()), this, SLOT(exportView()));
777
778 QAction *saveList = new QAction(this);
779 saveList->setText("Save Entire Cube List (ordered by &view)...");
780 connect(saveList, SIGNAL(triggered()), this, SLOT(saveList()));
781
782 exportActs.append(exportView);
783 exportActs.append(saveList);
784
785 return exportActs;
786 }
787
788
789 QList<QAction *> MosaicSceneWidget::getViewActions() {
790 QList<QAction *> viewActs;
791
792 foreach(MosaicTool *tool, *m_tools) {
793 QList<QAction *> toolViewActs = tool->getViewActions();
794 viewActs.append(toolViewActs);
795 }
796
797 return viewActs;
798 }
799
800
805 QList<QAction *> results;
806 bool allImagesInView = !images->isEmpty();
807
808 foreach (Image *image, *images) {
809 allImagesInView = allImagesInView && (cubeToMosaic(image) != NULL);
810 }
811
812 if (allImagesInView) {
813 MoveToTopSceneWorkOrder *moveToTopAct =
814 new MoveToTopSceneWorkOrder(this, m_directory->project());
815 moveToTopAct->setData(images);
816 results.append(moveToTopAct);
817
818 MoveUpOneSceneWorkOrder *moveUpOneAct =
819 new MoveUpOneSceneWorkOrder(this, m_directory->project());
820 moveUpOneAct->setData(images);
821 results.append(moveUpOneAct);
822
823 MoveToBottomSceneWorkOrder *moveToBottomAct =
824 new MoveToBottomSceneWorkOrder(this, m_directory->project());
825 moveToBottomAct->setData(images);
826 results.append(moveToBottomAct);
827
828 MoveDownOneSceneWorkOrder *moveDownOneAct =
829 new MoveDownOneSceneWorkOrder(this, m_directory->project());
830 moveDownOneAct->setData(images);
831 results.append(moveDownOneAct);
832
833 results.append(NULL);
834
835 QAction *zoomFitAct = new QAction(tr("Zoom Fit"), this);
836 zoomFitAct->setData(QVariant::fromValue(images));
837 connect(zoomFitAct, SIGNAL(triggered()), this, SLOT(fitInView()));
838 results.append(zoomFitAct);
839 }
840 return results;
841 }
842
843
844 bool MosaicSceneWidget::isControlNetToolActive() {
845
846 foreach(MosaicTool *tool, *m_tools) {
847 MosaicControlNetTool *cnTool = dynamic_cast<MosaicControlNetTool *>(tool);
848 if (cnTool) {
849 if (cnTool->isActive()) return true;
850 }
851 }
852 return false;
853 }
854
855
856 QWidget * MosaicSceneWidget::getControlNetHelp(QWidget *cnetToolContainer) {
857 QScrollArea *cnetHelpWidgetScrollArea = new QScrollArea;
858
859 QWidget *cnetHelpWidget = new QWidget;
860
861 QVBoxLayout *cnetHelpLayout = new QVBoxLayout;
862 cnetHelpWidget->setLayout(cnetHelpLayout);
863
864 QLabel *title = new QLabel("<h2>Control Networks</h2>");
865 cnetHelpLayout->addWidget(title);
866
867 QPixmap previewPixmap;
868
869 if (cnetToolContainer) {
870 previewPixmap = cnetToolContainer->grab().scaled(
871 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
872 }
873 else {
874 ToolPad tmpToolPad("Example Tool Pad", NULL);
875 MosaicControlNetTool tmpTool(NULL);
876 tmpTool.addTo(&tmpToolPad);
877
878 tmpToolPad.resize(QSize(32, 32));
879
880 previewPixmap = tmpToolPad.grab();
881 }
882
883 QLabel *previewWrapper = new QLabel;
884 previewWrapper->setPixmap(previewPixmap);
885 cnetHelpLayout->addWidget(previewWrapper);
886
887 QLabel *overview = new QLabel("The mosaic scene can display control points "
888 "in addition to the usual cube footprints. This feature is currently "
889 "offered as one of the Mosaic Scene's tools. To open a network, click "
890 "on the control network tool. It will immediately prompt you for a "
891 "control network file if one is not open. Only control points for "
892 "which the latitude and longitude can be established will be "
893 "displayed. Other control points will be ignored by qmos.<br><br>"
894 "<b>Warning: Opening large control networks is slow.</b>"
895 "<h3>Control Network Tool Options</h3>"
896 "<ul>"
897 "<li>The control network tool opens control networks in two ways. "
898 "First, if you select the control network tool and no network is "
899 "open, then it will prompt you for one. Second, if there is an open "
900 "network, the buttons for the available options are displayed in the "
901 "active tool area.</li>"
902 "<li>The control network tool can toggle whether or not control "
903 "points are displayed on the screen using the 'Display' button. "
904 "Control points are always on top and colored based on their "
905 "ignored, locked and type values.</li>"
906 "<li>This tool can also change the color of your footprints based on "
907 "connectivity through control points. This is available through the "
908 "'Color Islands' button. When you press color islands, all of the "
909 "current cube coloring information is lost and re-done based on "
910 "how the control network connects the files. Each set of connected "
911 "cubes are colored differently; generally speaking, islands are not "
912 "a good thing to have in your control network.</li>"
913 "<li>This tool will color your footprints on a per-image basis if you "
914 "click color images, effectively reversing color islands.</li>"
915 "<li>The show movement option under 'Configure Movement Display' "
916 "only displays data when the control "
917 "network has adjusted values. This means that show movement only "
918 "works after you have done a jigsaw solution on the control network. "
919 "This displays arrows emanating from the apriori latitude/longitude "
920 "and pointing toward the adjusted latitude/longitude.</li>");
921 overview->setWordWrap(true);
922 cnetHelpLayout->addWidget(overview);
923
924 cnetHelpWidgetScrollArea->setWidget(cnetHelpWidget);
925
926 return cnetHelpWidgetScrollArea;
927 }
928
929
930 QWidget * MosaicSceneWidget::getGridHelp(QWidget *gridToolContainer) {
931 QScrollArea *gridHelpWidgetScrollArea = new QScrollArea;
932
933 QWidget *gridHelpWidget = new QWidget;
934
935 QVBoxLayout *gridHelpLayout = new QVBoxLayout;
936 gridHelpWidget->setLayout(gridHelpLayout);
937
938 QLabel *title = new QLabel("<h2>Map Grid Tool</h2>");
939 gridHelpLayout->addWidget(title);
940
941 QPixmap previewPixmap;
942
943 if (gridToolContainer) {
944 previewPixmap = gridToolContainer->grab().scaled(
945 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
946 }
947 else {
948 ToolPad tmpToolPad("Example Tool Pad", NULL);
949 MosaicGridTool tmpTool(NULL);
950 tmpTool.addTo(&tmpToolPad);
951
952 tmpToolPad.resize(QSize(32, 32));
953
954 previewPixmap = tmpToolPad.grab();
955 }
956
957 QLabel *previewWrapper = new QLabel;
958 previewWrapper->setPixmap(previewPixmap);
959 gridHelpLayout->addWidget(previewWrapper);
960
961 QLabel *overview = new QLabel("Superimpose a map grid over the area of "
962 "displayed footprints in the 'mosaic scene.'"
963 "<h2>Overview</h2>"
964 "<ul>"
965 "<li>The Map Grid Tool is activated by selecting the 'cross-hatch' "
966 "icon or typing 'g' at the keyboard."
967 "</li>"
968 "<li>The parameter options are displayed below the menubar. "
969 "Clicking the 'Grid Options' button will open the dialog. Checking "
970 "'Auto Grid' will draw a grid based on the open cubes. Hitting "
971 "'Show Grid' will display or hide the grid."
972 "</li>"
973 "<li>The map grid is defined by the loaded Map File (just as the "
974 "footprints and image data are), the opened cubes, or the grid "
975 "tool parameters."
976 "</li>"
977 "<li>If a Map File has not been selected, the default "
978 "Equirectangular projection will be used. The resulting grid "
979 "lines in the default 'Equi' map file will be drawn for the "
980 "full global range (latitude range = -90,90; longitude range = "
981 "0,360) at the default latitude and longitude increment values."
982 "</li>"
983 "<li>"
984 "If the grid lines are not immediately visible, try to "
985 "'zoom out' in the 'mosaic scene' window and modify the "
986 "Latitude and Longitude Increment parameters."
987 "</li>"
988 "</ul>"
989 "<strong>Options:</strong>"
990 "<ul>"
991 "<li>The 'Show Grid' option draws (checked) or clears (unchecked) the grid."
992 "</li>"
993 "<li>The 'Auto Grid' option draws a grid with extents and increments "
994 "computed from the set of images that are opened. The values displayed in the dialog "
995 "will reflect those used to draw the grid."
996 "</li>"
997 "<li>The expected units for each entry are displayed to the right of the "
998 "dialog box."
999 "</li>"
1000 "<li>The 'Extent Type' combo boxes allow you to pick the source of the "
1001 "grid extents from the map file, from the open cubes <default>, or manually "
1002 "entered."
1003 "</li>"
1004 "<li>The 'Auto Apply' checkbox, inside the 'Grid Options' dialog box, allows you to see "
1005 "real time updates in the grid when you change the parameters."
1006 "</li>"
1007 "<li> Depending on the projection, the grid may not behave as expected. For instance, "
1008 "with a polarstereographic projection, the pole will not be included in the 'Auto "
1009 "Grid' if it is not in the cube region. In this case the 'Manual' option for latitude "
1010 "extents allows you to force the grid to the pole."
1011 "</li>"
1012 "</ul>");
1013 overview->setWordWrap(true);
1014 gridHelpLayout->addWidget(overview);
1015
1016 gridHelpWidgetScrollArea->setWidget(gridHelpWidget);
1017
1018 return gridHelpWidgetScrollArea;
1019 }
1020
1021
1022 QWidget * MosaicSceneWidget::getLongHelp(QWidget *sceneContainer) {
1023 QScrollArea *longHelpWidgetScrollArea = new QScrollArea;
1024
1025 QWidget *longHelpWidget = new QWidget;
1026
1027 QVBoxLayout *longHelpLayout = new QVBoxLayout;
1028 longHelpWidget->setLayout(longHelpLayout);
1029
1030 QLabel *title = new QLabel("<h2>Mosaic Scene</h2>");
1031 longHelpLayout->addWidget(title);
1032
1033 if (sceneContainer) {
1034 QPixmap previewPixmap = sceneContainer->grab().scaled(
1035 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1036
1037 QLabel *previewWrapper = new QLabel;
1038 previewWrapper->setPixmap(previewPixmap);
1039 longHelpLayout->addWidget(previewWrapper);
1040 }
1041
1042 QLabel *overview = new QLabel("The mosaic scene displays cube footprints "
1043 "to show where files are on a target and how they overlap. "
1044 "The scene always represents projected image space and cannot show raw "
1045 "or unprojected images; images will be projected on the fly."
1046 "<h3>Tools</h3>"
1047 "<p>Interact with the mosaic scene in different ways using "
1048 "the tools. The tools are usually in a toolbar next to the scene. "
1049 "The tools define what is displayed and what happens when you "
1050 "click in the mosaic scene. The tools include</p>"
1051 "<ul><li>Select Tool</li>"
1052 "<li>Zoom Tool</li>"
1053 "<li>Pan Tool</li>"
1054 "<li>Control Network Tool</li>"
1055 "<li>Show Area Tool</li>"
1056 "<li>Find Tool</li>"
1057 "<li>Grid Tool</li></ul>"
1058 "<h3>Context Menus</h3>"
1059 "Right click on anything in the mosaic scene and a context menu will pop up showing "
1060 "a list of actions or information relevant to the item you clicked on. "
1061 "<p>Note: The context menu is not associated with any selection, only the item "
1062 "clicked on.</p>");
1063 overview->setWordWrap(true);
1064 longHelpLayout->addWidget(overview);
1065
1066 longHelpWidgetScrollArea->setWidget(longHelpWidget);
1067
1068 return longHelpWidgetScrollArea;
1069 }
1070
1071
1072 QWidget * MosaicSceneWidget::getMapHelp(QWidget *mapContainer) {
1073 QScrollArea *mapHelpWidgetScrollArea = new QScrollArea;
1074
1075 QWidget *mapHelpWidget = new QWidget;
1076
1077 QVBoxLayout *mapHelpLayout = new QVBoxLayout;
1078 mapHelpWidget->setLayout(mapHelpLayout);
1079
1080 QLabel *title = new QLabel(tr("<h2>Map File</h2>"));
1081 mapHelpLayout->addWidget(title);
1082
1083 if (mapContainer) {
1084 QPixmap previewPixmap = mapContainer->grab().scaled(
1085 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1086
1087 QLabel *previewWrapper = new QLabel;
1088 previewWrapper->setPixmap(previewPixmap);
1089 mapHelpLayout->addWidget(previewWrapper);
1090 }
1091
1092 QLabel *overviewMapIcon = new QLabel;
1093
1094 overviewMapIcon->setPixmap(
1095 QIcon(FileName("$ISISROOT/appdata/images/icons/ographic.png").expanded()).pixmap(32, 32));
1096 mapHelpLayout->addWidget(overviewMapIcon);
1097
1098 QLabel *defaultMapFile = new QLabel(tr(
1099 "<h3>Default Map File</h3>"
1100 "The mosaic scene's projection is defined by a \"Map File\" that consists of keywords "
1101 "that describe the map layout to be used. If a cube or a list of cubes are "
1102 "loaded before a map file is selected, the default map file defines the "
1103 "equirectangular projection, planetocentric latitude, positive longitude east, 360 "
1104 "longitude domain, latitude range=90S-90N, longitude range=0-360E. The radius will "
1105 "default to the IAU standards (ellipsoid or sphere) for the specific planetary body "
1106 "defined for the \"TargetName\" in the labels of the image cube(s)."));
1107
1108 defaultMapFile->setWordWrap(true);
1109 mapHelpLayout->addWidget(defaultMapFile);
1110
1111 QLabel *userDefinedMapFileOverview = new QLabel(tr(
1112 "<h3>User Defined Map File</h3>"
1113 "You can load an existing \"Map File\" before loading images into %1 by selecting the "
1114 "\"View/Edit/Load Map File\" option. You will be greeted with a dialog box that will "
1115 "enable you to select an existing map file by clicking on \"Load Map File.\" Once "
1116 "the map file is selected, the contents is displayed in the dialog box where "
1117 "modifications can be made as well. If the modified map file is to be used later, "
1118 "save the map file by clicking on \"Save Map File\" button.")
1119 .arg(QCoreApplication::applicationName()));
1120
1121 userDefinedMapFileOverview->setWordWrap(true);
1122 mapHelpLayout->addWidget(userDefinedMapFileOverview);
1123
1124 QLabel *userDefinedMapFileQuickLoad = new QLabel(tr(
1125 "The \"Quick Load Map\" option (lightning icon) allows you to efficiently select a "
1126 "prepared \"Map File\" without an immediate need to view or edit the contents."));
1127
1128 userDefinedMapFileQuickLoad->setWordWrap(true);
1129 mapHelpLayout->addWidget(userDefinedMapFileQuickLoad);
1130
1131 QLabel *userDefinedMapFileAnyTime = new QLabel(tr(
1132 "At any point, you have access to the \"View/Edit\" functionality to modify or load a "
1133 "different map file."));
1134
1135 userDefinedMapFileAnyTime->setWordWrap(true);
1136 mapHelpLayout->addWidget(userDefinedMapFileAnyTime);
1137
1138 QString mapProjWorkshopUrl("https://github.com/USGS-Astrogeology/ISIS3/wiki/Learning_About_Map_Projections");
1139 QLabel *preparingMapFile = new QLabel(tr(
1140 "<h3>Preparing a Map File</h3>"
1141 "Please refer to Isis applications such as 'maptemplate' or 'mosrange' for more details "
1142 "on creating a custom map file that defines the desired projection, latitude "
1143 "system, and longitude direction and domain. This program will use the latitude range "
1144 "and longitude range if they exist in the loaded file. A choice of map templates that can be used as "
1145 "a starting point for supported map projections can be found in $ISISROOT/appdata/templates/maps (refer "
1146 "to maptemplate or mosrange for more details and information on the required parameters "
1147 "for a projection). The website: "
1148 "<a href='%1'>%1</a> also provides useful information about map projections.")
1149 .arg(mapProjWorkshopUrl));
1150
1151 preparingMapFile->setOpenExternalLinks(true);
1152 preparingMapFile->setWordWrap(true);
1153 mapHelpLayout->addWidget(preparingMapFile);
1154
1155 QLabel *mapFileDisplayResults = new QLabel(tr(
1156 "<h3>Display Results with the Map File</h3>"
1157 "The footprints and image data that are displayed in the mosaic scene are defined by the "
1158 "loaded \"Map File\" regardless of whether the opened cubes are Level1 (raw "
1159 "camera space) or Level2 (map projected). The associated footprint polygons for "
1160 "Level2 cubes will be re-mapped as needed based on the loaded map file."));
1161
1162 mapFileDisplayResults->setWordWrap(true);
1163 mapHelpLayout->addWidget(mapFileDisplayResults);
1164
1165 QLabel *editingMapFileOverview = new QLabel(tr(
1166 "<h3>Editing a Map File</h3>"
1167 "Editing a map file is possible through the dialog box displayed by clicking on the "
1168 "'View/Edit/Load Map File' icon/button. The edits are "
1169 "applied to the current session and will be included with a 'Saved Project' (refer to "
1170 "the help under File-Save Project or Save Project as)."));
1171
1172 editingMapFileOverview->setWordWrap(true);
1173 mapHelpLayout->addWidget(editingMapFileOverview);
1174
1175 QLabel *saveMapFileToDiskBullet = new QLabel(tr(
1176 "<ul>"
1177 "<li>"
1178 "To save or write the changes to a map file on disk, choose 'Save Map File' button. "
1179 "Map files can be saved to an existing map file (overwrites) or to a new file. This "
1180 "program always saves <strong>exactly</strong> what you see, the text, in the dialog "
1181 "box."
1182 "</li>"
1183 "</ul>"));
1184
1185 saveMapFileToDiskBullet->setWordWrap(true);
1186 mapHelpLayout->addWidget(saveMapFileToDiskBullet);
1187
1188 QLabel *mapFileValidityBullet = new QLabel(tr(
1189 "<ul>"
1190 "<li>"
1191 "As you modify the contents of a loaded map file in the dialog box, the entry is "
1192 "verified as you type with a bold black indicator message displaying whether the "
1193 "text is valid or is not valid. If you want to see the actual error messages, "
1194 "select the 'Show Errors' box and the errors will be displayed in red font "
1195 "along with the black bolded message. The errors will update "
1196 "as you type."
1197 "</li>"
1198 "</ul>"));
1199
1200 mapFileValidityBullet->setWordWrap(true);
1201 mapHelpLayout->addWidget(mapFileValidityBullet);
1202
1203 QLabel *mapFileCommentsBullet = new QLabel(tr(
1204 "<ul>"
1205 "<li>"
1206 "Map files may contain 'commented-out' lines (text that starts with \"#\" at "
1207 "the beginning of the line). These are referred to as \"unnecessary\""
1208 "or \"unknown\" keywords, they are simply ignored. If these lines are to be saved to "
1209 "the output map file on disk, click 'Save Map File' BEFORE clicking 'Ok' or 'Apply.' "
1210 "The comments are removed from the dialog box when you hit 'Ok' or 'Apply,' if they "
1211 "are just above \"End_Group\" or follow \"End_Group\" or \"End\".<br/><br/>"
1212
1213 "If you want these comments retained, make sure they are immediately above a valid "
1214 "keyword inside of \"Group = Mapping.\" Note that any lines (commented or not) will "
1215 "not be saved if they are placed outside of \"Group = Mapping\" and \"End_Group\"."
1216 "</li>"
1217 "</ul>"));
1218
1219 mapFileCommentsBullet->setWordWrap(true);
1220 mapHelpLayout->addWidget(mapFileCommentsBullet);
1221
1222 mapHelpWidgetScrollArea->setWidget(mapHelpWidget);
1223
1224 return mapHelpWidgetScrollArea;
1225 }
1226
1227
1228 QWidget * MosaicSceneWidget::getPreviewHelp(QWidget *worldViewContainer) {
1229 QScrollArea *previewHelpWidgetScrollArea = new QScrollArea;
1230
1231 QWidget *previewHelpWidget = new QWidget;
1232
1233 QVBoxLayout *previewHelpLayout = new QVBoxLayout;
1234 previewHelpWidget->setLayout(previewHelpLayout);
1235
1236 QLabel *title = new QLabel("<h2>Mosaic World View</h2>");
1237 previewHelpLayout->addWidget(title);
1238
1239 if (worldViewContainer) {
1240 QPixmap previewPixmap = worldViewContainer->grab().scaled(
1241 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1242
1243 QLabel *previewWrapper = new QLabel;
1244 previewWrapper->setPixmap(previewPixmap);
1245 previewHelpLayout->addWidget(previewWrapper);
1246 }
1247
1248 QLabel *overview = new QLabel("The mosaic world view displays cube "
1249 "footprints to show you where your files are on a target and their "
1250 "general arrangement. The world view does not have tools like "
1251 "mosaic scenes, but otherwise they are very similar.");
1252 overview->setWordWrap(true);
1253 previewHelpLayout->addWidget(overview);
1254
1255 previewHelpWidgetScrollArea->setWidget(previewHelpWidget);
1256
1257 return previewHelpWidgetScrollArea;
1258 }
1259
1260
1261 MosaicSceneItem *MosaicSceneWidget::addImage(Image *image) {
1262 if (m_projection == NULL) {
1263 setProjection(createInitialProjection(image), *image->cube()->label());
1264 }
1265
1266 MosaicSceneItem *mosItem = NULL;
1267
1268 // Verify we don't have this cube already... if we do, ignore the add request
1269 if (!cubeToMosaic(image)) {
1270 mosItem = new MosaicSceneItem(image, this);
1271
1272 connect(mosItem, SIGNAL(changed(const QList<QRectF> &)),
1273 m_graphicsView, SLOT(updateScene(const QList<QRectF> &)));
1274 connect(mosItem, SIGNAL(mosaicCubeClosed(Image *)),
1275 this, SIGNAL(mosCubeClosed(Image *)));
1276
1277 // We want everything to have a unique Z value so we can manage the z order
1278 // well.
1279 if (m_projectImageZOrders && m_projectImageZOrders->contains(image->id())) {
1280 double zOrder = m_projectImageZOrders->value(image->id());
1281 m_projectImageZOrders->remove(image->id());
1282
1283 foreach (MosaicSceneItem *mosaicItem, *m_mosaicSceneItems) {
1284 if (mosaicItem->zValue() == zOrder) {
1285 mosaicItem->setZValue(maximumZ() + 1);
1286 m_currentMaximumFootprintZ = maximumZ() + 1;
1287 }
1288 }
1289
1290 m_currentMaximumFootprintZ = qMax(zOrder, maximumZ());
1291 mosItem->setZValue(zOrder);
1292 }
1293 else {
1294 mosItem->setZValue(maximumZ() + 1);
1295 m_currentMaximumFootprintZ = maximumZ() + 1;
1296 }
1297
1298 getScene()->addItem(mosItem);
1299 m_mosaicSceneItems->append(mosItem);
1300 m_displayPropsToMosaicSceneItemMap[image->displayProperties()] = mosItem;
1301
1302 connect(mosItem, SIGNAL(destroyed(QObject *)),
1303 this, SLOT(removeMosItem(QObject *)));
1304
1305 ImageDisplayProperties *prop = image->displayProperties();
1306 connect(prop, SIGNAL(moveDownOne()),
1307 this, SLOT(moveDownOne()));
1308 connect(prop, SIGNAL(moveToBottom()),
1309 this, SLOT(moveToBottom()));
1310 connect(prop, SIGNAL(moveUpOne()),
1311 this, SLOT(moveUpOne()));
1312 connect(prop, SIGNAL(moveToTop()),
1313 this, SLOT(moveToTop()));
1314 connect(prop, SIGNAL(zoomFit()),
1315 this, SLOT(fitInView()));
1316 }
1317
1318 return mosItem;
1319 }
1320
1321
1322 double MosaicSceneWidget::maximumZ() {
1323 return m_currentMaximumFootprintZ;
1324 }
1325
1326
1327 double MosaicSceneWidget::minimumZ() {
1328 return m_currentMinimumFootprintZ;
1329 }
1330
1331 void MosaicSceneWidget::recalcSceneRect() {
1332 if (m_projection) {
1333 double minX, minY, maxX, maxY;
1334 m_projection->XYRange(minX, maxX, minY, maxY);
1335
1336 QRectF projRect(minX, -maxY, maxX - minX, maxY - minY);
1337 QRectF cubesBounding = cubesBoundingRect();
1338
1339 QRectF bounding = projRect.united(cubesBounding);
1340
1341 if (m_outlineRect && m_outlineRect->isVisible())
1342 bounding = bounding.united(m_outlineRect->boundingRect());
1343
1344 getView()->setSceneRect(bounding);
1345 }
1346 }
1347
1348 void MosaicSceneWidget::addImages(ImageList images) {
1349 if (m_userToolControl)
1350 m_progress->setText("Loading primary scene");
1351 else
1352 m_progress->setText("Loading secondary scene");
1353
1354 m_progress->setRange(0, images.size() - 1);
1355 m_progress->setValue(0);
1356 m_progress->setVisible(true);
1357
1358 foreach(Image *image, images) {
1359 try {
1360 addImage(image);
1361 }
1362 catch (IException &e) {
1363 e.print();
1364 }
1365
1366 m_progress->setValue(m_progress->value() + 1);
1367 }
1368
1369 recalcSceneRect();
1370
1371 if (m_projectViewTransform) {
1372 PvlObject &positionInfo = *m_projectViewTransform;
1373 QByteArray hexValues(positionInfo["ViewTransform"][0].toLatin1());
1374 QDataStream transformStream(QByteArray::fromHex(hexValues));
1375
1376 QTransform viewTransform;
1377 transformStream >> viewTransform;
1378 getView()->setTransform(viewTransform);
1379
1380 QPoint projectScrollPos(toInt(positionInfo["ScrollPosition"][0]),
1381 toInt(positionInfo["ScrollPosition"][1]));
1382
1383 getView()->horizontalScrollBar()->setValue(projectScrollPos.x());
1384 getView()->verticalScrollBar()->setValue(projectScrollPos.y());
1385 }
1386 else {
1387 refit();
1388 }
1389
1390 if (!m_projectImageZOrders || m_projectImageZOrders->isEmpty()) {
1391 delete m_projectViewTransform;
1392 m_projectViewTransform = NULL;
1393 }
1394
1395 m_progress->setVisible(false);
1396 emit cubesChanged();
1397 }
1398
1399
1400 void MosaicSceneWidget::removeImages(ImageList images) {
1401 // TODO: 2016-08-02 TLS Should this be done similarly to addImages. Re-do Image list
1402 // then redo scene?
1403 foreach(Image *image, images) {
1404 try {
1405 MosaicSceneItem *item = cubeToMosaic(image);
1406 item->deleteLater();
1407 removeMosItem(item);
1408 }
1409 catch (IException &e) {
1410 e.print();
1411 }
1412 }
1413 }
1414
1415
1420 QString output =
1421 QFileDialog::getSaveFileName((QWidget *)parent(),
1422 "Choose output file",
1423 QDir::currentPath() + "/untitled.png",
1424 QString("Images (*.png *.jpg *.tif)"));
1425 if (output.isEmpty()) return;
1426
1427 // Use png format is the user did not add a suffix to their output filename.
1428 if (QFileInfo(output).suffix().isEmpty()) {
1429 output = output + ".png";
1430 }
1431
1432 QString format = QFileInfo(output).suffix();
1433 QPixmap pm = getScene()->views().last()->grab();
1434
1435 std::string formatString = format.toStdString();
1436 if (!pm.save(output, formatString.c_str())) {
1437 QMessageBox::information(this, "Error",
1438 "Unable to save [" + output + "]");
1439 }
1440 }
1441
1442
1443 void MosaicSceneWidget::saveList() {
1444 QString output =
1445 QFileDialog::getSaveFileName((QWidget *)parent(),
1446 "Choose output file",
1447 QDir::currentPath() + "/files.lis",
1448 QString("List File (*.lis);;Text File (*.txt);;All Files (*.*)"));
1449 if (output.isEmpty()) return;
1450
1451 TextFile file(output, "overwrite");
1452
1453 QList<MosaicSceneItem *> sorted = *m_mosaicSceneItems;
1454 std::sort(sorted.begin(), sorted.end(), zOrderGreaterThan);
1455
1456 MosaicSceneItem *sceneItem;
1457 foreach(sceneItem, sorted) {
1458 file.PutLine( sceneItem->image()->fileName() );
1459 }
1460 }
1461
1462
1463 void MosaicSceneWidget::removeMosItem(QObject *mosItem) {
1464 MosaicSceneItem *castedMosItem = (MosaicSceneItem *) mosItem;
1465 m_mosaicSceneItems->removeAll(castedMosItem);
1466 m_displayPropsToMosaicSceneItemMap.remove(
1467 m_displayPropsToMosaicSceneItemMap.key(castedMosItem));
1468 recalcSceneRect();
1469 emit cubesChanged();
1470 }
1471
1472
1478 QRectF sceneRect = cubesBoundingRect();
1479
1480 if (sceneRect.isEmpty())
1481 return;
1482
1483 double xPadding = sceneRect.width() * 0.10;
1484 double yPadding = sceneRect.height() * 0.10;
1485
1486 sceneRect.adjust(-xPadding, -yPadding, xPadding, yPadding);
1487 getView()->fitInView(sceneRect, Qt::KeepAspectRatio);
1488 }
1489
1490
1491 void MosaicSceneWidget::setCubesSelectable(bool selectable) {
1492 if (m_cubesSelectable != selectable) {
1493 m_cubesSelectable = selectable;
1494
1495 MosaicSceneItem *mosaicSceneItem;
1496 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1497 mosaicSceneItem->scenePropertiesChanged();
1498 }
1499 }
1500 }
1501
1502
1508 ProjectionConfigDialog configDialog(this);
1509 configDialog.exec();
1510 }
1511
1512
1513 void MosaicSceneWidget::quickConfigProjectionParameters() {
1514 ProjectionConfigDialog configDialog(this);
1515 configDialog.setQuickConfig(true);
1516 configDialog.exec();
1517 }
1518
1519
1520 void MosaicSceneWidget::sendVisibleRectChanged() {
1521 QPointF topLeft = getView()->mapToScene(0, 0);
1522 QPointF bottomRight = getView()->mapToScene(
1523 (int)getView()->width(),
1524 (int)getView()->height());
1525
1526 QRectF visibleRect(topLeft, bottomRight);
1527 emit visibleRectChanged(visibleRect);
1528 }
1529
1530
1531 bool MosaicSceneWidget::eventFilter(QObject *obj, QEvent *event) {
1532 bool stopProcessingEvent = true;
1533
1534 switch(event->type()) {
1535 case QMouseEvent::GraphicsSceneMousePress: {
1536 if (m_customRubberBandEnabled) {
1537 // Intiate the rubber banding!
1538 if (!m_customRubberBand) {
1539 m_customRubberBand = new QRubberBand(QRubberBand::Rectangle,
1540 getView());
1541 }
1542
1543 if (!m_rubberBandOrigin) {
1544 m_rubberBandOrigin = new QPoint;
1545 }
1546
1547 *m_rubberBandOrigin = getView()->mapFromScene(
1548 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1549 m_customRubberBand->setGeometry(QRect(*m_rubberBandOrigin, QSize()));
1550 m_customRubberBand->show();
1551 }
1552
1553 emit mouseButtonPress(
1554 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1555 ((QGraphicsSceneMouseEvent *)event)->button());
1556 stopProcessingEvent = false;
1557 break;
1558 }
1559
1560 case QMouseEvent::GraphicsSceneMouseRelease: {
1561 bool signalEmitted = false;
1562 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1563 m_customRubberBand) {
1564 if (m_customRubberBand->geometry().width() +
1565 m_customRubberBand->geometry().height() > 10) {
1566 emit rubberBandComplete(
1567 getView()->mapToScene(
1568 m_customRubberBand->geometry()).boundingRect(),
1569 ((QGraphicsSceneMouseEvent *)event)->button());
1570 signalEmitted = true;
1571 }
1572
1573 delete m_rubberBandOrigin;
1574 m_rubberBandOrigin = NULL;
1575
1576 delete m_customRubberBand;
1577 m_customRubberBand = NULL;
1578 }
1579
1580 if (!signalEmitted) {
1581 stopProcessingEvent = false;
1582 emit mouseButtonRelease(
1583 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1584 ((QGraphicsSceneMouseEvent *)event)->button());
1585 }
1586 break;
1587 }
1588
1589 case QMouseEvent::GraphicsSceneMouseDoubleClick:
1590 emit mouseDoubleClick(
1591 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1592 stopProcessingEvent = false;
1593 break;
1594
1595 case QMouseEvent::GraphicsSceneMouseMove:
1596 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1597 m_customRubberBand) {
1598 QPointF scenePos = ((QGraphicsSceneMouseEvent *)event)->scenePos();
1599 QPoint screenPos = getView()->mapFromScene(scenePos);
1600
1601 QRect rubberBandRect =
1602 QRect(*m_rubberBandOrigin, screenPos).normalized();
1603
1604 m_customRubberBand->setGeometry(rubberBandRect);
1605 }
1606 else {
1607 stopProcessingEvent = false;
1608 }
1609
1610 emit mouseMove(
1611 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1612 break;
1613
1614 case QEvent::GraphicsSceneWheel:
1615 emit mouseWheel(
1616 ((QGraphicsSceneWheelEvent *)event)->scenePos(),
1617 ((QGraphicsSceneWheelEvent *)event)->delta());
1618 event->accept();
1619 stopProcessingEvent = true;
1620 break;
1621
1622 case QMouseEvent::Enter:
1623 emit mouseEnter();
1624 stopProcessingEvent = false;
1625 break;
1626
1627 case QMouseEvent::Leave:
1628 emit mouseLeave();
1629 stopProcessingEvent = false;
1630 break;
1631
1632 case QEvent::GraphicsSceneHelp: {
1633 setToolTip("");
1634 bool toolTipFound = false;
1635
1636 QGraphicsItem *sceneItem;
1637 foreach(sceneItem, getScene()->items()) {
1638 if (!toolTipFound) {
1639 if (sceneItem->contains(
1640 ((QGraphicsSceneHelpEvent*)event)->scenePos()) &&
1641 sceneItem->toolTip().size() > 0) {
1642 setToolTip(sceneItem->toolTip());
1643 toolTipFound = true;
1644 }
1645 }
1646 }
1647
1648 if (toolTipFound) {
1649 stopProcessingEvent = true;
1650 QToolTip::showText(
1651 ((QGraphicsSceneHelpEvent*)event)->screenPos(),
1652 toolTip());
1653 }
1654 break;
1655 }
1656
1657 default:
1658 stopProcessingEvent = false;
1659 break;
1660 }
1661
1662 return stopProcessingEvent;
1663 }
1664
1665
1673 if (m_mosaicSceneItems->size() == 0)
1674 return;
1675
1676 if (m_userToolControl)
1677 m_progress->setText("Reprojecting primary scene");
1678 else
1679 m_progress->setText("Reprojecting secondary scene");
1680
1681 // This gives some pretty graphics as thing work
1682 int reprojectsPerUpdate = qMax(1, m_mosaicSceneItems->size() / 20);
1683
1684 m_progress->setRange(0,
1685 (m_mosaicSceneItems->size() - 1) / reprojectsPerUpdate + 1);
1686 m_progress->setValue(0);
1687 m_progress->setVisible(true);
1688
1689 MosaicSceneItem *mosaicSceneItem;
1690
1691 int progressCountdown = reprojectsPerUpdate;
1692 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1693 try {
1694 mosaicSceneItem->reproject();
1695 }
1696 catch (IException &e) {
1697 QString msg = "The file [";
1698
1699 if (mosaicSceneItem->image())
1700 msg += mosaicSceneItem->image()->displayProperties()->displayName();
1701
1702 msg += "] is being removed due to not being able to project onto the scene";
1703
1704 IException tmp(e, IException::Programmer, msg, _FILEINFO_);
1705 tmp.print();
1706 mosaicSceneItem->image()->deleteLater();
1707 }
1708
1709 progressCountdown --;
1710 if (progressCountdown == 0) {
1711 m_progress->setValue(m_progress->value() + 1);
1712 progressCountdown = reprojectsPerUpdate;
1713 refit();
1714 }
1715 }
1716
1717 m_progress->setValue(m_progress->maximum());
1718
1719 recalcSceneRect();
1720 refit();
1721 m_progress->setVisible(false);
1722 }
1723
1724
1725 void MosaicSceneWidget::moveDownOne() {
1726 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1727
1728 if (props) {
1729 moveDownOne(cubeToMosaic(props));
1730 }
1731 }
1732
1733
1736 double MosaicSceneWidget::moveDownOne(MosaicSceneItem *item) {
1737 MosaicSceneItem *nextDown = getNextItem(item, false);
1738 double originalZ = item->zValue();
1739
1740 if (nextDown) {
1741 double newZValue = nextDown->zValue() - 1;
1742 moveZ(item, newZValue, true);
1743 }
1744
1745 return originalZ;
1746 }
1747
1748
1751 double MosaicSceneWidget::moveDownOne(Image *image) {
1752 return moveDownOne(cubeToMosaic(image));
1753 }
1754
1755
1758 QList<double> MosaicSceneWidget::moveDownOne(ImageList *images) {
1759 QList<double> results;
1760
1761 foreach (Image *image, *images) {
1762 results.append(moveDownOne(image));
1763 }
1764
1765 return results;
1766 }
1767
1768
1769 void MosaicSceneWidget::moveToBottom() {
1770 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1771 if (props) {
1772 moveToBottom(cubeToMosaic(props));
1773 }
1774 }
1775
1776
1781 double MosaicSceneWidget::moveToBottom(MosaicSceneItem *item) {
1782 double originalZ = item->zValue();
1783 double minZ = minimumZ();
1784
1785 if (originalZ != minZ) {
1786 // We know min-1 isn't already used
1787 int newZValue = qRound(minZ - 1);
1788 item->setZValue(newZValue);
1789
1790 // Remove this if we enable the compress
1791 m_currentMinimumFootprintZ--;
1792 }
1793
1794 return originalZ;
1795 }
1796
1797
1802 double MosaicSceneWidget::moveToBottom(Image *image) {
1803 return moveToBottom(cubeToMosaic(image));
1804 }
1805
1806
1811 QList<double> MosaicSceneWidget::moveToBottom(ImageList *images) {
1812 QList<double> results;
1813
1814 foreach (Image *image, *images) {
1815 results.append(moveToBottom(image));
1816 }
1817
1818 return results;
1819 }
1820
1821
1822 void MosaicSceneWidget::moveUpOne() {
1823 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1824
1825 if (props) {
1826 moveUpOne(cubeToMosaic(props));
1827 }
1828 }
1829
1830
1833 double MosaicSceneWidget::moveUpOne(MosaicSceneItem *item) {
1834 MosaicSceneItem *nextUp = getNextItem(item, true);
1835 double originalZ = item->zValue();
1836
1837 if (nextUp) {
1838 double newZValue = nextUp->zValue() + 1;
1839 moveZ(item, newZValue, true);
1840 }
1841
1842 return originalZ;
1843 }
1844
1845
1848 double MosaicSceneWidget::moveUpOne(Image *image) {
1849 return moveUpOne(cubeToMosaic(image));
1850 }
1851
1852
1855 QList<double> MosaicSceneWidget::moveUpOne(ImageList *images) {
1856 QList<double> results;
1857
1858 foreach (Image *image, *images) {
1859 results.append(moveUpOne(image));
1860 }
1861
1862 return results;
1863 }
1864
1865
1866 void MosaicSceneWidget::moveToTop() {
1867 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1868
1869 if (props) {
1870 moveToTop(cubeToMosaic(props));
1871 }
1872 }
1873
1874
1879 double MosaicSceneWidget::moveToTop(MosaicSceneItem *item) {
1880 double originalZ = item->zValue();
1881 double maxZ = maximumZ();
1882
1883 if (originalZ != maxZ) {
1884 // We know max+1 isn't already used
1885 int newZValue = qRound(maxZ + 1);
1886 item->setZValue(newZValue);
1887
1888 // Remove this if we enable the compress
1889 m_currentMaximumFootprintZ++;
1890 }
1891
1892 // Compress... this makes this method have a time complexity of N instead of constant; there
1893 // isn't really a good justification for the slow down. I'm leaving this (working) code here
1894 // for reference and in case it's needed later.
1895 // foreach (MosaicSceneItem *otherItem, *m_mosaicSceneItems) {
1896 // double otherItemZ = otherItem->zValue();
1897 // if (otherItemZ > originalZ) {
1898 // otherItem->setZValue(otherItemZ - 1.0);
1899 // }
1900 // }
1901
1902 return originalZ;
1903 }
1904
1905
1910 double MosaicSceneWidget::moveToTop(Image *image) {
1911 return moveToTop(cubeToMosaic(image));
1912 }
1913
1914
1919 QList<double> MosaicSceneWidget::moveToTop(ImageList *images) {
1920 QList<double> results;
1921
1922 foreach (Image *image, *images) {
1923 results.append(moveToTop(image));
1924 }
1925
1926
1927// printZ(m_mosaicSceneItems);
1928 return results;
1929 }
1930
1931
1947 double MosaicSceneWidget::moveZ(MosaicSceneItem *sceneItem, double newZ,
1948 bool newZValueMightExist) {
1949 double originalZ = sceneItem->zValue();
1950
1951 if (newZValueMightExist) {
1952 // Adjust items between original and new position, recalculate min/max - time complexity=N
1953 m_currentMinimumFootprintZ = 0.0;
1954 m_currentMaximumFootprintZ = 0.0;
1955
1956 foreach (MosaicSceneItem *otherItem, *m_mosaicSceneItems) {
1957 double otherItemOrigZ = otherItem->zValue();
1958 double otherItemNewZ = otherItemOrigZ;
1959
1960 // Moving downwards (new Z is lower than current Z) and item is in the middle
1961 if (originalZ > newZ && otherItemOrigZ >= newZ && otherItemOrigZ < originalZ) {
1962 otherItemNewZ = otherItemOrigZ + 1;
1963 }
1964 // Moving upwards (new Z is higher than current Z) and item is in the middle
1965 else if (originalZ < newZ && otherItemOrigZ <= newZ && otherItemOrigZ > originalZ) {
1966 otherItemNewZ = otherItemOrigZ - 1;
1967 }
1968
1969 m_currentMinimumFootprintZ = qMin(m_currentMinimumFootprintZ, otherItemNewZ);
1970 m_currentMaximumFootprintZ = qMax(m_currentMaximumFootprintZ, otherItemNewZ);
1971 otherItem->setZValue(otherItemNewZ);
1972 }
1973 }
1974
1975 sceneItem->setZValue(newZ);
1976
1977 if (!newZValueMightExist) {
1978 // If we moved the max or min item, adjust the max down or min up respectively
1979 if (originalZ == maximumZ() && newZ < originalZ) {
1980 m_currentMaximumFootprintZ--;
1981 }
1982 else if (originalZ == minimumZ() && newZ > originalZ) {
1983 m_currentMinimumFootprintZ++;
1984 }
1985 }
1986
1987 return originalZ;
1988 }
1989
1990
1991 double MosaicSceneWidget::moveZ(Image *image, double newZ,
1992 bool newZValueMightExist) {
1993 return moveZ(cubeToMosaic(image), newZ, newZValueMightExist);
1994 }
1995
1996
1997 void MosaicSceneWidget::fitInView() {
1998 if (m_userToolControl) {
1999 QRectF boundingBox;
2000
2001 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
2002
2003 if (props) {
2004 MosaicSceneItem *item = cubeToMosaic(props);
2005 boundingBox = item->boundingRect();
2006 }
2007 else {
2008 QAction *action = qobject_cast<QAction *>(sender());
2009
2010 if (action) {
2011 ImageList *images = action->data().value<ImageList *>();
2012
2013 foreach (Image *image, *images) {
2014 boundingBox = boundingBox.united(cubeToMosaic(image)->boundingRect());
2015 }
2016 }
2017 }
2018
2019 if (!boundingBox.isNull()) {
2020 double xPadding = boundingBox.width() * 0.10;
2021 double yPadding = boundingBox.height() * 0.10;
2022
2023 boundingBox.setLeft(boundingBox.left() - xPadding);
2024 boundingBox.setRight(boundingBox.right() + xPadding);
2025
2026 boundingBox.setTop(boundingBox.top() - yPadding);
2027 boundingBox.setBottom(boundingBox.bottom() + yPadding);
2028
2029 getView()->fitInView(boundingBox, Qt::KeepAspectRatio);
2030 getView()->centerOn(boundingBox.center());
2031 }
2032 }
2033 }
2034
2035
2036 void MosaicSceneWidget::onSelectionChanged() {
2037 if (!m_blockingSelectionChanged) {
2038 if (!m_queuedSelectionChanged) {
2039 emit queueSelectionChanged();
2040 m_queuedSelectionChanged = true;
2041 }
2042 else {
2043 m_shouldRequeueSelectionChanged = true;
2044 }
2045 }
2046 }
2047
2048
2049 void MosaicSceneWidget::onQueuedSelectionChanged() {
2050 m_queuedSelectionChanged = false;
2051
2052 if (m_shouldRequeueSelectionChanged) {
2053 m_shouldRequeueSelectionChanged = false;
2054 onSelectionChanged();
2055 }
2056 else {
2057 foreach(MosaicSceneItem *mosaicSceneItem, *m_mosaicSceneItems) {
2058 mosaicSceneItem->updateSelection(true);
2059 }
2060 }
2061 }
2062
2063
2066 MosaicSceneItem *nextZValueItem = NULL;
2067 MosaicSceneItem *mosaicSceneItem;
2068
2069 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
2070 if (mosaicSceneItem != item &&
2071 mosaicSceneItem->boundingRect().intersects(item->boundingRect())) {
2072 // Does this item qualify as above or below at all?
2073 if ( (up && mosaicSceneItem->zValue() > item->zValue()) ||
2074 (!up && mosaicSceneItem->zValue() < item->zValue())) {
2075 // It is in the correct direction, set the initial guess if we don't
2076 // have one or test if it's better
2077 if (!nextZValueItem) {
2078 nextZValueItem = mosaicSceneItem;
2079 }
2080 else {
2081 // We know it qualifies, we want to know if it's closer than
2082 // nextZValueItem
2083 if ((up && mosaicSceneItem->zValue() < nextZValueItem->zValue()) ||
2084 (!up && mosaicSceneItem->zValue() > nextZValueItem->zValue())) {
2085 nextZValueItem = mosaicSceneItem;
2086 }
2087 }
2088 }
2089 }
2090 }
2091
2092 return nextZValueItem;
2093 }
2094
2095
2096 bool MosaicSceneWidget::zOrderGreaterThan(MosaicSceneItem *first,
2097 MosaicSceneItem *second) {
2098 return first->zValue() > second->zValue();
2099 }
2100}
A single control point.
QList< QAction * > supportedActions(DataType data)
Returns a list of supported actions for a WorkOrder.
Definition Directory.h:345
Project * project() const
Gets the Project for this directory.
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
This represents a cube in a project-based GUI interface.
Definition Image.h:105
Internalizes a list of images and allows for operations on the entire list.
Definition ImageList.h:53
void append(Image *const &value)
Appends an image to the image list.
QList< QAction * > supportedActions(Project *project=NULL)
Gets a list of pre-connected actions that have to do with display.
This displays a box with a given distance from a point.
//TODO: Remove debug printout & comment // 2016-08-25 Tracie Sucharski - Checking Directory pointer f...
This controls the 'Find' abilities in the MosaicSceneWidget.
A graphics scene with improved user-interaction for use with the MosaicSceneWidget.
A graphics view that resizes in a more friendly way.
This controls the 'Grid' abilities in the MosaicSceneWidget.
Handles panning operations for Isis qt apps.
A single cube in the mosaic scene.
void reproject()
Called anytime the user reprojects the cube.
void configProjectionParameters()
This happens when the user clicks on the map action (the button that is named after the current proje...
QList< QAction * > supportedActions(ImageList *)
Get a list of actions this scene can perform given "images".
bool contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
This is called by MosaicGraphicsScene::contextMenuEvent.
MosaicGraphicsView * m_graphicsView
The graphics view.
double moveToBottom(MosaicSceneItem *)
This doesn't compress the Z values - the original Z values of this scene item is guaranteed to be emp...
QGraphicsScene * m_graphicsScene
The graphics scene that makes up this widget.
MosaicSceneItem * getNextItem(MosaicSceneItem *item, bool up)
Implemented because we want invisible items too.
void refit()
This method refits t:he items in the graphics view.
MosaicSceneWidget(QStatusBar *status, bool showTools, bool internalizeToolBarsAndProgress, Directory *directory, QWidget *parent=0)
Create a scene widget.
ImageList selectedImages()
Returns a list of all the cubes selected in the scene.
void fromPvl(const PvlObject &)
Call this method after loading any cubes when loading a project.
Projection * m_projection
The current projection type.
double moveToTop(MosaicSceneItem *)
This doesn't compress the Z values - the original Z values of this scene item is guaranteed to be emp...
double moveZ(MosaicSceneItem *sceneItem, double newZ, bool newZValueMightExist=true)
This method moves the given scene item to the given Z value.
void setProjection(Projection *)
This method takes ownership of proj.
void reprojectItems()
Reprojects all the items in the view.
void exportView()
Saves the scene as a png, jpg, or tif file.
Handles selection operations for Isis qt apps.
Base class for the MosaicTools.
Definition MosaicTool.h:37
Handles zoom operations for Isis qt apps.
Move images, one by one, below the immediately-below intersecting image in a scene This workorder is ...
Move images below all other images in a mosaic scene This workorder is synchronous and undoable.
Move images on top of all other images in a mosaic scene This workorder is synchronous and undoable.
Move images, one by one, on top of the immediately-above intersecting image in a scene This workorder...
void setText(QString text)
Set custom text for this progress bar.
The main project for ipce.
Definition Project.h:287
This is the configuration dialog for the MosaicSceneWidget's projection parameters (map file).
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
static Isis::Projection * Create(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a Projection object.
Base class for Map Projections.
Definition Projection.h:155
Contains multiple PvlContainers.
Definition PvlGroup.h:41
A single keyword-value pair.
Definition PvlKeyword.h:87
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not.
Definition PvlObject.h:325
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition PvlObject.h:276
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition PvlObject.h:129
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
Definition Target.cpp:428
Provides access to sequential ASCII stream I/O.
Definition TextFile.h:38
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149