Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

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
578 void MosaicSceneWidget::fromPvl(const PvlObject &project) {
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 m_projectViewTransform->addKeyword(project.findKeyword("QtVersion"));
615 }
616 }
617 }
618
619
620 void MosaicSceneWidget::save(QXmlStreamWriter &stream, Project *, FileName ) const {
621 if (m_projection) {
622 stream.writeStartElement("mosaicScene");
623
624 stream.writeStartElement("projection");
625 PvlGroup mapping = m_projection->Mapping();
626 std::stringstream strStream;
627 strStream << mapping;
628 stream.writeCharacters(strStream.str().c_str());
629 stream.writeEndElement();
630
631 stream.writeStartElement("images");
632 foreach(MosaicSceneItem * mosaicSceneItem, *m_mosaicSceneItems) {
633 stream.writeStartElement("image");
634 stream.writeAttribute("id", mosaicSceneItem->image()->id());
635 stream.writeAttribute("zValue", toString(mosaicSceneItem->zValue()));
636 stream.writeEndElement();
637 }
638 stream.writeEndElement();
639
640 stream.writeStartElement("viewTransform");
641 stream.writeAttribute("scrollBarXValue", toString(getView()->horizontalScrollBar()->value()));
642 stream.writeAttribute("scrollBarYValue", toString(getView()->verticalScrollBar()->value()));
643 QBuffer dataBuffer;
644 dataBuffer.open(QIODevice::ReadWrite);
645 QDataStream transformStream(&dataBuffer);
646 transformStream << getView()->transform();
647 dataBuffer.seek(0);
648 stream.writeCharacters(dataBuffer.data().toHex());
649 stream.writeEndElement();
650
651 foreach(MosaicTool *tool, *m_tools) {
652 QString projectPvlObjectName = tool->projectPvlObjectName();
653 if (projectPvlObjectName != "") {
654 PvlObject toolObj = tool->toPvl();
655 toolObj.setName(projectPvlObjectName);
656
657 stream.writeStartElement("toolData");
658 stream.writeAttribute("objectName", projectPvlObjectName);
659 std::stringstream strStream;
660 strStream << toolObj;
661 stream.writeCharacters(strStream.str().c_str());
662 stream.writeEndElement();
663 }
664 }
665
666 stream.writeEndElement();
667 }
668 }
669
670
671 QRectF MosaicSceneWidget::cubesBoundingRect() const {
672 QRectF boundingRect;
673
674 MosaicSceneItem * mosaicItem;
675 foreach(mosaicItem, *m_mosaicSceneItems) {
676 if (boundingRect.isEmpty())
677 boundingRect = mosaicItem->boundingRect();
678 else
679 boundingRect = boundingRect.united(mosaicItem->boundingRect());
680 }
681
682 if (m_outlineRect)
683 boundingRect = boundingRect.united(m_outlineRect->boundingRect());
684
685 return boundingRect;
686 }
687
688
689 MosaicSceneItem *MosaicSceneWidget::cubeToMosaic(DisplayProperties *props) {
690 if (props == NULL) {
691 QString msg = tr("Can not find a NULL Display Properties in the mosaic");
692 throw IException(IException::Programmer, msg, _FILEINFO_);
693 }
694
695 return m_displayPropsToMosaicSceneItemMap[props];
696 }
697
698
699 QStringList MosaicSceneWidget::cubeFileNames() {
700 QStringList cubes;
701
702 MosaicSceneItem *mosaicSceneItem;
703 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
704 if (mosaicSceneItem->image())
705 cubes.append(mosaicSceneItem->image()->fileName());
706 }
707
708 return cubes;
709 }
710
711
712 Directory *MosaicSceneWidget::directory() const {
713 return m_directory;
714 }
715
716
717 ImageList MosaicSceneWidget::images() {
718 ImageList images;
719
720 MosaicSceneItem *mosaicSceneItem;
721 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
722 if (mosaicSceneItem->image())
723 images.append(mosaicSceneItem->image());
724 }
725
726 return images;
727 }
728
729
736
737 QList<QGraphicsItem *> selectedGraphicsItems = getScene()->selectedItems();
738 QList<MosaicSceneItem *> selectedImageItems;
740
741 foreach (QGraphicsItem *graphicsItem, selectedGraphicsItems) {
742 MosaicSceneItem *sceneImageItem = dynamic_cast<MosaicSceneItem *>(graphicsItem);
743
744 if (!sceneImageItem) {
745 sceneImageItem = dynamic_cast<MosaicSceneItem *>(graphicsItem->parentItem());
746 }
747
748 if (sceneImageItem && sceneImageItem->image()) {
749 selectedImageItems.append(sceneImageItem);
750 selectedImages.append(sceneImageItem->image());
751 }
752 }
753 return selectedImages;
754
755
756
757
758
759// ImageList images;
760// //qDebug()<<"MosaicSceneWidget::selectedImages TotalItems = "<<m_mosaicSceneItems->size();
761// MosaicSceneItem *mosaicItem;
762// foreach(mosaicItem, *m_mosaicSceneItems) {
763// if (mosaicItem->isSelected()) {
764// images.append(mosaicItem->image());
765// }
766// }
767//
768// return images;
769 }
770
771
772 QList<QAction *> MosaicSceneWidget::getExportActions() {
773 QList<QAction *> exportActs;
774
775 QAction *exportView = new QAction(this);
776 exportView->setText("&Export View...");
777 connect(exportView, SIGNAL(triggered()), this, SLOT(exportView()));
778
779 QAction *saveList = new QAction(this);
780 saveList->setText("Save Entire Cube List (ordered by &view)...");
781 connect(saveList, SIGNAL(triggered()), this, SLOT(saveList()));
782
783 exportActs.append(exportView);
784 exportActs.append(saveList);
785
786 return exportActs;
787 }
788
789
790 QList<QAction *> MosaicSceneWidget::getViewActions() {
791 QList<QAction *> viewActs;
792
793 foreach(MosaicTool *tool, *m_tools) {
794 QList<QAction *> toolViewActs = tool->getViewActions();
795 viewActs.append(toolViewActs);
796 }
797
798 return viewActs;
799 }
800
801
806 QList<QAction *> results;
807 bool allImagesInView = !images->isEmpty();
808
809 foreach (Image *image, *images) {
810 allImagesInView = allImagesInView && (cubeToMosaic(image) != NULL);
811 }
812
813 if (allImagesInView) {
814 MoveToTopSceneWorkOrder *moveToTopAct =
815 new MoveToTopSceneWorkOrder(this, m_directory->project());
816 moveToTopAct->setData(images);
817 results.append(moveToTopAct);
818
819 MoveUpOneSceneWorkOrder *moveUpOneAct =
820 new MoveUpOneSceneWorkOrder(this, m_directory->project());
821 moveUpOneAct->setData(images);
822 results.append(moveUpOneAct);
823
824 MoveToBottomSceneWorkOrder *moveToBottomAct =
825 new MoveToBottomSceneWorkOrder(this, m_directory->project());
826 moveToBottomAct->setData(images);
827 results.append(moveToBottomAct);
828
829 MoveDownOneSceneWorkOrder *moveDownOneAct =
830 new MoveDownOneSceneWorkOrder(this, m_directory->project());
831 moveDownOneAct->setData(images);
832 results.append(moveDownOneAct);
833
834 results.append(NULL);
835
836 QAction *zoomFitAct = new QAction(tr("Zoom Fit"), this);
837 zoomFitAct->setData(QVariant::fromValue(images));
838 connect(zoomFitAct, SIGNAL(triggered()), this, SLOT(fitInView()));
839 results.append(zoomFitAct);
840 }
841 return results;
842 }
843
844
845 bool MosaicSceneWidget::isControlNetToolActive() {
846
847 foreach(MosaicTool *tool, *m_tools) {
848 MosaicControlNetTool *cnTool = dynamic_cast<MosaicControlNetTool *>(tool);
849 if (cnTool) {
850 if (cnTool->isActive()) return true;
851 }
852 }
853 return false;
854 }
855
856
857 QWidget * MosaicSceneWidget::getControlNetHelp(QWidget *cnetToolContainer) {
858 QScrollArea *cnetHelpWidgetScrollArea = new QScrollArea;
859
860 QWidget *cnetHelpWidget = new QWidget;
861
862 QVBoxLayout *cnetHelpLayout = new QVBoxLayout;
863 cnetHelpWidget->setLayout(cnetHelpLayout);
864
865 QLabel *title = new QLabel("<h2>Control Networks</h2>");
866 cnetHelpLayout->addWidget(title);
867
868 QPixmap previewPixmap;
869
870 if (cnetToolContainer) {
871 previewPixmap = cnetToolContainer->grab().scaled(
872 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
873 }
874 else {
875 ToolPad tmpToolPad("Example Tool Pad", NULL);
876 MosaicControlNetTool tmpTool(NULL);
877 tmpTool.addTo(&tmpToolPad);
878
879 tmpToolPad.resize(QSize(32, 32));
880
881 previewPixmap = tmpToolPad.grab();
882 }
883
884 QLabel *previewWrapper = new QLabel;
885 previewWrapper->setPixmap(previewPixmap);
886 cnetHelpLayout->addWidget(previewWrapper);
887
888 QLabel *overview = new QLabel("The mosaic scene can display control points "
889 "in addition to the usual cube footprints. This feature is currently "
890 "offered as one of the Mosaic Scene's tools. To open a network, click "
891 "on the control network tool. It will immediately prompt you for a "
892 "control network file if one is not open. Only control points for "
893 "which the latitude and longitude can be established will be "
894 "displayed. Other control points will be ignored by qmos.<br><br>"
895 "<b>Warning: Opening large control networks is slow.</b>"
896 "<h3>Control Network Tool Options</h3>"
897 "<ul>"
898 "<li>The control network tool opens control networks in two ways. "
899 "First, if you select the control network tool and no network is "
900 "open, then it will prompt you for one. Second, if there is an open "
901 "network, the buttons for the available options are displayed in the "
902 "active tool area.</li>"
903 "<li>The control network tool can toggle whether or not control "
904 "points are displayed on the screen using the 'Display' button. "
905 "Control points are always on top and colored based on their "
906 "ignored, locked and type values.</li>"
907 "<li>This tool can also change the color of your footprints based on "
908 "connectivity through control points. This is available through the "
909 "'Color Islands' button. When you press color islands, all of the "
910 "current cube coloring information is lost and re-done based on "
911 "how the control network connects the files. Each set of connected "
912 "cubes are colored differently; generally speaking, islands are not "
913 "a good thing to have in your control network.</li>"
914 "<li>This tool will color your footprints on a per-image basis if you "
915 "click color images, effectively reversing color islands.</li>"
916 "<li>The show movement option under 'Configure Movement Display' "
917 "only displays data when the control "
918 "network has adjusted values. This means that show movement only "
919 "works after you have done a jigsaw solution on the control network. "
920 "This displays arrows emanating from the apriori latitude/longitude "
921 "and pointing toward the adjusted latitude/longitude.</li>");
922 overview->setWordWrap(true);
923 cnetHelpLayout->addWidget(overview);
924
925 cnetHelpWidgetScrollArea->setWidget(cnetHelpWidget);
926
927 return cnetHelpWidgetScrollArea;
928 }
929
930
931 QWidget * MosaicSceneWidget::getGridHelp(QWidget *gridToolContainer) {
932 QScrollArea *gridHelpWidgetScrollArea = new QScrollArea;
933
934 QWidget *gridHelpWidget = new QWidget;
935
936 QVBoxLayout *gridHelpLayout = new QVBoxLayout;
937 gridHelpWidget->setLayout(gridHelpLayout);
938
939 QLabel *title = new QLabel("<h2>Map Grid Tool</h2>");
940 gridHelpLayout->addWidget(title);
941
942 QPixmap previewPixmap;
943
944 if (gridToolContainer) {
945 previewPixmap = gridToolContainer->grab().scaled(
946 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
947 }
948 else {
949 ToolPad tmpToolPad("Example Tool Pad", NULL);
950 MosaicGridTool tmpTool(NULL);
951 tmpTool.addTo(&tmpToolPad);
952
953 tmpToolPad.resize(QSize(32, 32));
954
955 previewPixmap = tmpToolPad.grab();
956 }
957
958 QLabel *previewWrapper = new QLabel;
959 previewWrapper->setPixmap(previewPixmap);
960 gridHelpLayout->addWidget(previewWrapper);
961
962 QLabel *overview = new QLabel("Superimpose a map grid over the area of "
963 "displayed footprints in the 'mosaic scene.'"
964 "<h2>Overview</h2>"
965 "<ul>"
966 "<li>The Map Grid Tool is activated by selecting the 'cross-hatch' "
967 "icon or typing 'g' at the keyboard."
968 "</li>"
969 "<li>The parameter options are displayed below the menubar. "
970 "Clicking the 'Grid Options' button will open the dialog. Checking "
971 "'Auto Grid' will draw a grid based on the open cubes. Hitting "
972 "'Show Grid' will display or hide the grid."
973 "</li>"
974 "<li>The map grid is defined by the loaded Map File (just as the "
975 "footprints and image data are), the opened cubes, or the grid "
976 "tool parameters."
977 "</li>"
978 "<li>If a Map File has not been selected, the default "
979 "Equirectangular projection will be used. The resulting grid "
980 "lines in the default 'Equi' map file will be drawn for the "
981 "full global range (latitude range = -90,90; longitude range = "
982 "0,360) at the default latitude and longitude increment values."
983 "</li>"
984 "<li>"
985 "If the grid lines are not immediately visible, try to "
986 "'zoom out' in the 'mosaic scene' window and modify the "
987 "Latitude and Longitude Increment parameters."
988 "</li>"
989 "</ul>"
990 "<strong>Options:</strong>"
991 "<ul>"
992 "<li>The 'Show Grid' option draws (checked) or clears (unchecked) the grid."
993 "</li>"
994 "<li>The 'Auto Grid' option draws a grid with extents and increments "
995 "computed from the set of images that are opened. The values displayed in the dialog "
996 "will reflect those used to draw the grid."
997 "</li>"
998 "<li>The expected units for each entry are displayed to the right of the "
999 "dialog box."
1000 "</li>"
1001 "<li>The 'Extent Type' combo boxes allow you to pick the source of the "
1002 "grid extents from the map file, from the open cubes <default>, or manually "
1003 "entered."
1004 "</li>"
1005 "<li>The 'Auto Apply' checkbox, inside the 'Grid Options' dialog box, allows you to see "
1006 "real time updates in the grid when you change the parameters."
1007 "</li>"
1008 "<li> Depending on the projection, the grid may not behave as expected. For instance, "
1009 "with a polarstereographic projection, the pole will not be included in the 'Auto "
1010 "Grid' if it is not in the cube region. In this case the 'Manual' option for latitude "
1011 "extents allows you to force the grid to the pole."
1012 "</li>"
1013 "</ul>");
1014 overview->setWordWrap(true);
1015 gridHelpLayout->addWidget(overview);
1016
1017 gridHelpWidgetScrollArea->setWidget(gridHelpWidget);
1018
1019 return gridHelpWidgetScrollArea;
1020 }
1021
1022
1023 QWidget * MosaicSceneWidget::getLongHelp(QWidget *sceneContainer) {
1024 QScrollArea *longHelpWidgetScrollArea = new QScrollArea;
1025
1026 QWidget *longHelpWidget = new QWidget;
1027
1028 QVBoxLayout *longHelpLayout = new QVBoxLayout;
1029 longHelpWidget->setLayout(longHelpLayout);
1030
1031 QLabel *title = new QLabel("<h2>Mosaic Scene</h2>");
1032 longHelpLayout->addWidget(title);
1033
1034 if (sceneContainer) {
1035 QPixmap previewPixmap = sceneContainer->grab().scaled(
1036 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1037
1038 QLabel *previewWrapper = new QLabel;
1039 previewWrapper->setPixmap(previewPixmap);
1040 longHelpLayout->addWidget(previewWrapper);
1041 }
1042
1043 QLabel *overview = new QLabel("The mosaic scene displays cube footprints "
1044 "to show where files are on a target and how they overlap. "
1045 "The scene always represents projected image space and cannot show raw "
1046 "or unprojected images; images will be projected on the fly."
1047 "<h3>Tools</h3>"
1048 "<p>Interact with the mosaic scene in different ways using "
1049 "the tools. The tools are usually in a toolbar next to the scene. "
1050 "The tools define what is displayed and what happens when you "
1051 "click in the mosaic scene. The tools include</p>"
1052 "<ul><li>Select Tool</li>"
1053 "<li>Zoom Tool</li>"
1054 "<li>Pan Tool</li>"
1055 "<li>Control Network Tool</li>"
1056 "<li>Show Area Tool</li>"
1057 "<li>Find Tool</li>"
1058 "<li>Grid Tool</li></ul>"
1059 "<h3>Context Menus</h3>"
1060 "Right click on anything in the mosaic scene and a context menu will pop up showing "
1061 "a list of actions or information relevant to the item you clicked on. "
1062 "<p>Note: The context menu is not associated with any selection, only the item "
1063 "clicked on.</p>");
1064 overview->setWordWrap(true);
1065 longHelpLayout->addWidget(overview);
1066
1067 longHelpWidgetScrollArea->setWidget(longHelpWidget);
1068
1069 return longHelpWidgetScrollArea;
1070 }
1071
1072
1073 QWidget * MosaicSceneWidget::getMapHelp(QWidget *mapContainer) {
1074 QScrollArea *mapHelpWidgetScrollArea = new QScrollArea;
1075
1076 QWidget *mapHelpWidget = new QWidget;
1077
1078 QVBoxLayout *mapHelpLayout = new QVBoxLayout;
1079 mapHelpWidget->setLayout(mapHelpLayout);
1080
1081 QLabel *title = new QLabel(tr("<h2>Map File</h2>"));
1082 mapHelpLayout->addWidget(title);
1083
1084 if (mapContainer) {
1085 QPixmap previewPixmap = mapContainer->grab().scaled(
1086 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1087
1088 QLabel *previewWrapper = new QLabel;
1089 previewWrapper->setPixmap(previewPixmap);
1090 mapHelpLayout->addWidget(previewWrapper);
1091 }
1092
1093 QLabel *overviewMapIcon = new QLabel;
1094
1095 overviewMapIcon->setPixmap(
1096 QIcon(FileName("$ISISROOT/appdata/images/icons/ographic.png").expanded()).pixmap(32, 32));
1097 mapHelpLayout->addWidget(overviewMapIcon);
1098
1099 QLabel *defaultMapFile = new QLabel(tr(
1100 "<h3>Default Map File</h3>"
1101 "The mosaic scene's projection is defined by a \"Map File\" that consists of keywords "
1102 "that describe the map layout to be used. If a cube or a list of cubes are "
1103 "loaded before a map file is selected, the default map file defines the "
1104 "equirectangular projection, planetocentric latitude, positive longitude east, 360 "
1105 "longitude domain, latitude range=90S-90N, longitude range=0-360E. The radius will "
1106 "default to the IAU standards (ellipsoid or sphere) for the specific planetary body "
1107 "defined for the \"TargetName\" in the labels of the image cube(s)."));
1108
1109 defaultMapFile->setWordWrap(true);
1110 mapHelpLayout->addWidget(defaultMapFile);
1111
1112 QLabel *userDefinedMapFileOverview = new QLabel(tr(
1113 "<h3>User Defined Map File</h3>"
1114 "You can load an existing \"Map File\" before loading images into %1 by selecting the "
1115 "\"View/Edit/Load Map File\" option. You will be greeted with a dialog box that will "
1116 "enable you to select an existing map file by clicking on \"Load Map File.\" Once "
1117 "the map file is selected, the contents is displayed in the dialog box where "
1118 "modifications can be made as well. If the modified map file is to be used later, "
1119 "save the map file by clicking on \"Save Map File\" button.")
1120 .arg(QCoreApplication::applicationName()));
1121
1122 userDefinedMapFileOverview->setWordWrap(true);
1123 mapHelpLayout->addWidget(userDefinedMapFileOverview);
1124
1125 QLabel *userDefinedMapFileQuickLoad = new QLabel(tr(
1126 "The \"Quick Load Map\" option (lightning icon) allows you to efficiently select a "
1127 "prepared \"Map File\" without an immediate need to view or edit the contents."));
1128
1129 userDefinedMapFileQuickLoad->setWordWrap(true);
1130 mapHelpLayout->addWidget(userDefinedMapFileQuickLoad);
1131
1132 QLabel *userDefinedMapFileAnyTime = new QLabel(tr(
1133 "At any point, you have access to the \"View/Edit\" functionality to modify or load a "
1134 "different map file."));
1135
1136 userDefinedMapFileAnyTime->setWordWrap(true);
1137 mapHelpLayout->addWidget(userDefinedMapFileAnyTime);
1138
1139 QString mapProjWorkshopUrl("https://github.com/USGS-Astrogeology/ISIS3/wiki/Learning_About_Map_Projections");
1140 QLabel *preparingMapFile = new QLabel(tr(
1141 "<h3>Preparing a Map File</h3>"
1142 "Please refer to Isis applications such as 'maptemplate' or 'mosrange' for more details "
1143 "on creating a custom map file that defines the desired projection, latitude "
1144 "system, and longitude direction and domain. This program will use the latitude range "
1145 "and longitude range if they exist in the loaded file. A choice of map templates that can be used as "
1146 "a starting point for supported map projections can be found in $ISISROOT/appdata/templates/maps (refer "
1147 "to maptemplate or mosrange for more details and information on the required parameters "
1148 "for a projection). The website: "
1149 "<a href='%1'>%1</a> also provides useful information about map projections.")
1150 .arg(mapProjWorkshopUrl));
1151
1152 preparingMapFile->setOpenExternalLinks(true);
1153 preparingMapFile->setWordWrap(true);
1154 mapHelpLayout->addWidget(preparingMapFile);
1155
1156 QLabel *mapFileDisplayResults = new QLabel(tr(
1157 "<h3>Display Results with the Map File</h3>"
1158 "The footprints and image data that are displayed in the mosaic scene are defined by the "
1159 "loaded \"Map File\" regardless of whether the opened cubes are Level1 (raw "
1160 "camera space) or Level2 (map projected). The associated footprint polygons for "
1161 "Level2 cubes will be re-mapped as needed based on the loaded map file."));
1162
1163 mapFileDisplayResults->setWordWrap(true);
1164 mapHelpLayout->addWidget(mapFileDisplayResults);
1165
1166 QLabel *editingMapFileOverview = new QLabel(tr(
1167 "<h3>Editing a Map File</h3>"
1168 "Editing a map file is possible through the dialog box displayed by clicking on the "
1169 "'View/Edit/Load Map File' icon/button. The edits are "
1170 "applied to the current session and will be included with a 'Saved Project' (refer to "
1171 "the help under File-Save Project or Save Project as)."));
1172
1173 editingMapFileOverview->setWordWrap(true);
1174 mapHelpLayout->addWidget(editingMapFileOverview);
1175
1176 QLabel *saveMapFileToDiskBullet = new QLabel(tr(
1177 "<ul>"
1178 "<li>"
1179 "To save or write the changes to a map file on disk, choose 'Save Map File' button. "
1180 "Map files can be saved to an existing map file (overwrites) or to a new file. This "
1181 "program always saves <strong>exactly</strong> what you see, the text, in the dialog "
1182 "box."
1183 "</li>"
1184 "</ul>"));
1185
1186 saveMapFileToDiskBullet->setWordWrap(true);
1187 mapHelpLayout->addWidget(saveMapFileToDiskBullet);
1188
1189 QLabel *mapFileValidityBullet = new QLabel(tr(
1190 "<ul>"
1191 "<li>"
1192 "As you modify the contents of a loaded map file in the dialog box, the entry is "
1193 "verified as you type with a bold black indicator message displaying whether the "
1194 "text is valid or is not valid. If you want to see the actual error messages, "
1195 "select the 'Show Errors' box and the errors will be displayed in red font "
1196 "along with the black bolded message. The errors will update "
1197 "as you type."
1198 "</li>"
1199 "</ul>"));
1200
1201 mapFileValidityBullet->setWordWrap(true);
1202 mapHelpLayout->addWidget(mapFileValidityBullet);
1203
1204 QLabel *mapFileCommentsBullet = new QLabel(tr(
1205 "<ul>"
1206 "<li>"
1207 "Map files may contain 'commented-out' lines (text that starts with \"#\" at "
1208 "the beginning of the line). These are referred to as \"unnecessary\""
1209 "or \"unknown\" keywords, they are simply ignored. If these lines are to be saved to "
1210 "the output map file on disk, click 'Save Map File' BEFORE clicking 'Ok' or 'Apply.' "
1211 "The comments are removed from the dialog box when you hit 'Ok' or 'Apply,' if they "
1212 "are just above \"End_Group\" or follow \"End_Group\" or \"End\".<br/><br/>"
1213
1214 "If you want these comments retained, make sure they are immediately above a valid "
1215 "keyword inside of \"Group = Mapping.\" Note that any lines (commented or not) will "
1216 "not be saved if they are placed outside of \"Group = Mapping\" and \"End_Group\"."
1217 "</li>"
1218 "</ul>"));
1219
1220 mapFileCommentsBullet->setWordWrap(true);
1221 mapHelpLayout->addWidget(mapFileCommentsBullet);
1222
1223 mapHelpWidgetScrollArea->setWidget(mapHelpWidget);
1224
1225 return mapHelpWidgetScrollArea;
1226 }
1227
1228
1229 QWidget * MosaicSceneWidget::getPreviewHelp(QWidget *worldViewContainer) {
1230 QScrollArea *previewHelpWidgetScrollArea = new QScrollArea;
1231
1232 QWidget *previewHelpWidget = new QWidget;
1233
1234 QVBoxLayout *previewHelpLayout = new QVBoxLayout;
1235 previewHelpWidget->setLayout(previewHelpLayout);
1236
1237 QLabel *title = new QLabel("<h2>Mosaic World View</h2>");
1238 previewHelpLayout->addWidget(title);
1239
1240 if (worldViewContainer) {
1241 QPixmap previewPixmap = worldViewContainer->grab().scaled(
1242 QSize(500, 200), Qt::KeepAspectRatio, Qt::SmoothTransformation);
1243
1244 QLabel *previewWrapper = new QLabel;
1245 previewWrapper->setPixmap(previewPixmap);
1246 previewHelpLayout->addWidget(previewWrapper);
1247 }
1248
1249 QLabel *overview = new QLabel("The mosaic world view displays cube "
1250 "footprints to show you where your files are on a target and their "
1251 "general arrangement. The world view does not have tools like "
1252 "mosaic scenes, but otherwise they are very similar.");
1253 overview->setWordWrap(true);
1254 previewHelpLayout->addWidget(overview);
1255
1256 previewHelpWidgetScrollArea->setWidget(previewHelpWidget);
1257
1258 return previewHelpWidgetScrollArea;
1259 }
1260
1261
1262 MosaicSceneItem *MosaicSceneWidget::addImage(Image *image) {
1263 if (m_projection == NULL) {
1264 setProjection(createInitialProjection(image), *image->cube()->label());
1265 }
1266
1267 MosaicSceneItem *mosItem = NULL;
1268
1269 // Verify we don't have this cube already... if we do, ignore the add request
1270 if (!cubeToMosaic(image)) {
1271 mosItem = new MosaicSceneItem(image, this);
1272
1273 connect(mosItem, SIGNAL(changed(const QList<QRectF> &)),
1274 m_graphicsView, SLOT(updateScene(const QList<QRectF> &)));
1275 connect(mosItem, SIGNAL(mosaicCubeClosed(Image *)),
1276 this, SIGNAL(mosCubeClosed(Image *)));
1277
1278 // We want everything to have a unique Z value so we can manage the z order
1279 // well.
1280 if (m_projectImageZOrders && m_projectImageZOrders->contains(image->id())) {
1281 double zOrder = m_projectImageZOrders->value(image->id());
1282 m_projectImageZOrders->remove(image->id());
1283
1284 foreach (MosaicSceneItem *mosaicItem, *m_mosaicSceneItems) {
1285 if (mosaicItem->zValue() == zOrder) {
1286 mosaicItem->setZValue(maximumZ() + 1);
1287 m_currentMaximumFootprintZ = maximumZ() + 1;
1288 }
1289 }
1290
1291 m_currentMaximumFootprintZ = qMax(zOrder, maximumZ());
1292 mosItem->setZValue(zOrder);
1293 }
1294 else {
1295 mosItem->setZValue(maximumZ() + 1);
1296 m_currentMaximumFootprintZ = maximumZ() + 1;
1297 }
1298
1299 getScene()->addItem(mosItem);
1300 m_mosaicSceneItems->append(mosItem);
1301 m_displayPropsToMosaicSceneItemMap[image->displayProperties()] = mosItem;
1302
1303 connect(mosItem, SIGNAL(destroyed(QObject *)),
1304 this, SLOT(removeMosItem(QObject *)));
1305
1306 ImageDisplayProperties *prop = image->displayProperties();
1307 connect(prop, SIGNAL(moveDownOne()),
1308 this, SLOT(moveDownOne()));
1309 connect(prop, SIGNAL(moveToBottom()),
1310 this, SLOT(moveToBottom()));
1311 connect(prop, SIGNAL(moveUpOne()),
1312 this, SLOT(moveUpOne()));
1313 connect(prop, SIGNAL(moveToTop()),
1314 this, SLOT(moveToTop()));
1315 connect(prop, SIGNAL(zoomFit()),
1316 this, SLOT(fitInView()));
1317 }
1318
1319 return mosItem;
1320 }
1321
1322
1323 double MosaicSceneWidget::maximumZ() {
1324 return m_currentMaximumFootprintZ;
1325 }
1326
1327
1328 double MosaicSceneWidget::minimumZ() {
1329 return m_currentMinimumFootprintZ;
1330 }
1331
1332 void MosaicSceneWidget::recalcSceneRect() {
1333 if (m_projection) {
1334 double minX, minY, maxX, maxY;
1335 m_projection->XYRange(minX, maxX, minY, maxY);
1336
1337 QRectF projRect(minX, -maxY, maxX - minX, maxY - minY);
1338 QRectF cubesBounding = cubesBoundingRect();
1339
1340 QRectF bounding = projRect.united(cubesBounding);
1341
1342 if (m_outlineRect && m_outlineRect->isVisible())
1343 bounding = bounding.united(m_outlineRect->boundingRect());
1344
1345 getView()->setSceneRect(bounding);
1346 }
1347 }
1348
1349 void MosaicSceneWidget::addImages(ImageList images) {
1350 if (m_userToolControl)
1351 m_progress->setText("Loading primary scene");
1352 else
1353 m_progress->setText("Loading secondary scene");
1354
1355 m_progress->setRange(0, images.size() - 1);
1356 m_progress->setValue(0);
1357 m_progress->setVisible(true);
1358
1359 foreach(Image *image, images) {
1360 try {
1361 addImage(image);
1362 }
1363 catch (IException &e) {
1364 e.print();
1365 }
1366
1367 m_progress->setValue(m_progress->value() + 1);
1368 }
1369
1370 recalcSceneRect();
1371
1372 if (m_projectViewTransform) {
1373 PvlObject &positionInfo = *m_projectViewTransform;
1374 QByteArray hexValues(positionInfo["ViewTransform"][0].toLatin1());
1375 QDataStream transformStream(QByteArray::fromHex(hexValues));
1376 transformStream.setVersion(int(positionInfo["QtVersion"]));
1377
1378 QTransform viewTransform;
1379 transformStream >> viewTransform;
1380 getView()->setTransform(viewTransform);
1381
1382 QPoint projectScrollPos(toInt(positionInfo["ScrollPosition"][0]),
1383 toInt(positionInfo["ScrollPosition"][1]));
1384
1385 getView()->horizontalScrollBar()->setValue(projectScrollPos.x());
1386 getView()->verticalScrollBar()->setValue(projectScrollPos.y());
1387 }
1388 else {
1389 refit();
1390 }
1391
1392 if (!m_projectImageZOrders || m_projectImageZOrders->isEmpty()) {
1393 delete m_projectViewTransform;
1394 m_projectViewTransform = NULL;
1395 }
1396
1397 m_progress->setVisible(false);
1398 emit cubesChanged();
1399 }
1400
1401
1402 void MosaicSceneWidget::removeImages(ImageList images) {
1403 // TODO: 2016-08-02 TLS Should this be done similarly to addImages. Re-do Image list
1404 // then redo scene?
1405 foreach(Image *image, images) {
1406 try {
1407 MosaicSceneItem *item = cubeToMosaic(image);
1408 item->deleteLater();
1409 removeMosItem(item);
1410 }
1411 catch (IException &e) {
1412 e.print();
1413 }
1414 }
1415 }
1416
1417
1422 QString output =
1423 QFileDialog::getSaveFileName((QWidget *)parent(),
1424 "Choose output file",
1425 QDir::currentPath() + "/untitled.png",
1426 QString("Images (*.png *.jpg *.tif)"));
1427 if (output.isEmpty()) return;
1428
1429 // Use png format is the user did not add a suffix to their output filename.
1430 if (QFileInfo(output).suffix().isEmpty()) {
1431 output = output + ".png";
1432 }
1433
1434 QString format = QFileInfo(output).suffix();
1435 QPixmap pm = getScene()->views().last()->grab();
1436
1437 std::string formatString = format.toStdString();
1438 if (!pm.save(output, formatString.c_str())) {
1439 QMessageBox::information(this, "Error",
1440 "Unable to save [" + output + "]");
1441 }
1442 }
1443
1444
1445 void MosaicSceneWidget::saveList() {
1446 QString output =
1447 QFileDialog::getSaveFileName((QWidget *)parent(),
1448 "Choose output file",
1449 QDir::currentPath() + "/files.lis",
1450 QString("List File (*.lis);;Text File (*.txt);;All Files (*.*)"));
1451 if (output.isEmpty()) return;
1452
1453 TextFile file(output, "overwrite");
1454
1455 QList<MosaicSceneItem *> sorted = *m_mosaicSceneItems;
1456 std::sort(sorted.begin(), sorted.end(), zOrderGreaterThan);
1457
1458 MosaicSceneItem *sceneItem;
1459 foreach(sceneItem, sorted) {
1460 file.PutLine( sceneItem->image()->fileName() );
1461 }
1462 }
1463
1464
1465 void MosaicSceneWidget::removeMosItem(QObject *mosItem) {
1466 MosaicSceneItem *castedMosItem = (MosaicSceneItem *) mosItem;
1467 m_mosaicSceneItems->removeAll(castedMosItem);
1468 m_displayPropsToMosaicSceneItemMap.remove(
1469 m_displayPropsToMosaicSceneItemMap.key(castedMosItem));
1470 recalcSceneRect();
1471 emit cubesChanged();
1472 }
1473
1474
1480 QRectF sceneRect = cubesBoundingRect();
1481
1482 if (sceneRect.isEmpty())
1483 return;
1484
1485 double xPadding = sceneRect.width() * 0.10;
1486 double yPadding = sceneRect.height() * 0.10;
1487
1488 sceneRect.adjust(-xPadding, -yPadding, xPadding, yPadding);
1489 getView()->fitInView(sceneRect, Qt::KeepAspectRatio);
1490 }
1491
1492
1493 void MosaicSceneWidget::setCubesSelectable(bool selectable) {
1494 if (m_cubesSelectable != selectable) {
1495 m_cubesSelectable = selectable;
1496
1497 MosaicSceneItem *mosaicSceneItem;
1498 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1499 mosaicSceneItem->scenePropertiesChanged();
1500 }
1501 }
1502 }
1503
1504
1510 ProjectionConfigDialog configDialog(this);
1511 configDialog.exec();
1512 }
1513
1514
1515 void MosaicSceneWidget::quickConfigProjectionParameters() {
1516 ProjectionConfigDialog configDialog(this);
1517 configDialog.setQuickConfig(true);
1518 configDialog.exec();
1519 }
1520
1521
1522 void MosaicSceneWidget::sendVisibleRectChanged() {
1523 QPointF topLeft = getView()->mapToScene(0, 0);
1524 QPointF bottomRight = getView()->mapToScene(
1525 (int)getView()->width(),
1526 (int)getView()->height());
1527
1528 QRectF visibleRect(topLeft, bottomRight);
1529 emit visibleRectChanged(visibleRect);
1530 }
1531
1532
1533 bool MosaicSceneWidget::eventFilter(QObject *obj, QEvent *event) {
1534 bool stopProcessingEvent = true;
1535
1536 switch(event->type()) {
1537 case QMouseEvent::GraphicsSceneMousePress: {
1538 if (m_customRubberBandEnabled) {
1539 // Intiate the rubber banding!
1540 if (!m_customRubberBand) {
1541 m_customRubberBand = new QRubberBand(QRubberBand::Rectangle,
1542 getView());
1543 }
1544
1545 if (!m_rubberBandOrigin) {
1546 m_rubberBandOrigin = new QPoint;
1547 }
1548
1549 *m_rubberBandOrigin = getView()->mapFromScene(
1550 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1551 m_customRubberBand->setGeometry(QRect(*m_rubberBandOrigin, QSize()));
1552 m_customRubberBand->show();
1553 }
1554
1555 emit mouseButtonPress(
1556 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1557 ((QGraphicsSceneMouseEvent *)event)->button());
1558 stopProcessingEvent = false;
1559 break;
1560 }
1561
1562 case QMouseEvent::GraphicsSceneMouseRelease: {
1563 bool signalEmitted = false;
1564 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1565 m_customRubberBand) {
1566 if (m_customRubberBand->geometry().width() +
1567 m_customRubberBand->geometry().height() > 10) {
1568 emit rubberBandComplete(
1569 getView()->mapToScene(
1570 m_customRubberBand->geometry()).boundingRect(),
1571 ((QGraphicsSceneMouseEvent *)event)->button());
1572 signalEmitted = true;
1573 }
1574
1575 delete m_rubberBandOrigin;
1576 m_rubberBandOrigin = NULL;
1577
1578 delete m_customRubberBand;
1579 m_customRubberBand = NULL;
1580 }
1581
1582 if (!signalEmitted) {
1583 stopProcessingEvent = false;
1584 emit mouseButtonRelease(
1585 ((QGraphicsSceneMouseEvent *)event)->scenePos(),
1586 ((QGraphicsSceneMouseEvent *)event)->button());
1587 }
1588 break;
1589 }
1590
1591 case QMouseEvent::GraphicsSceneMouseDoubleClick:
1592 emit mouseDoubleClick(
1593 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1594 stopProcessingEvent = false;
1595 break;
1596
1597 case QMouseEvent::GraphicsSceneMouseMove:
1598 if (m_customRubberBandEnabled && m_rubberBandOrigin &&
1599 m_customRubberBand) {
1600 QPointF scenePos = ((QGraphicsSceneMouseEvent *)event)->scenePos();
1601 QPoint screenPos = getView()->mapFromScene(scenePos);
1602
1603 QRect rubberBandRect =
1604 QRect(*m_rubberBandOrigin, screenPos).normalized();
1605
1606 m_customRubberBand->setGeometry(rubberBandRect);
1607 }
1608 else {
1609 stopProcessingEvent = false;
1610 }
1611
1612 emit mouseMove(
1613 ((QGraphicsSceneMouseEvent *)event)->scenePos());
1614 break;
1615
1616 case QEvent::GraphicsSceneWheel:
1617 emit mouseWheel(
1618 ((QGraphicsSceneWheelEvent *)event)->scenePos(),
1619 ((QGraphicsSceneWheelEvent *)event)->delta());
1620 event->accept();
1621 stopProcessingEvent = true;
1622 break;
1623
1624 case QMouseEvent::Enter:
1625 emit mouseEnter();
1626 stopProcessingEvent = false;
1627 break;
1628
1629 case QMouseEvent::Leave:
1630 emit mouseLeave();
1631 stopProcessingEvent = false;
1632 break;
1633
1634 case QEvent::GraphicsSceneHelp: {
1635 setToolTip("");
1636 bool toolTipFound = false;
1637
1638 QGraphicsItem *sceneItem;
1639 foreach(sceneItem, getScene()->items()) {
1640 if (!toolTipFound) {
1641 if (sceneItem->contains(
1642 ((QGraphicsSceneHelpEvent*)event)->scenePos()) &&
1643 sceneItem->toolTip().size() > 0) {
1644 setToolTip(sceneItem->toolTip());
1645 toolTipFound = true;
1646 }
1647 }
1648 }
1649
1650 if (toolTipFound) {
1651 stopProcessingEvent = true;
1652 QToolTip::showText(
1653 ((QGraphicsSceneHelpEvent*)event)->screenPos(),
1654 toolTip());
1655 }
1656 break;
1657 }
1658
1659 default:
1660 stopProcessingEvent = false;
1661 break;
1662 }
1663
1664 return stopProcessingEvent;
1665 }
1666
1667
1675 if (m_mosaicSceneItems->size() == 0)
1676 return;
1677
1678 if (m_userToolControl)
1679 m_progress->setText("Reprojecting primary scene");
1680 else
1681 m_progress->setText("Reprojecting secondary scene");
1682
1683 // This gives some pretty graphics as thing work
1684 int reprojectsPerUpdate = qMax(1, m_mosaicSceneItems->size() / 20);
1685
1686 m_progress->setRange(0,
1687 (m_mosaicSceneItems->size() - 1) / reprojectsPerUpdate + 1);
1688 m_progress->setValue(0);
1689 m_progress->setVisible(true);
1690
1691 MosaicSceneItem *mosaicSceneItem;
1692
1693 int progressCountdown = reprojectsPerUpdate;
1694 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
1695 try {
1696 mosaicSceneItem->reproject();
1697 }
1698 catch (IException &e) {
1699 QString msg = "The file [";
1700
1701 if (mosaicSceneItem->image())
1702 msg += mosaicSceneItem->image()->displayProperties()->displayName();
1703
1704 msg += "] is being removed due to not being able to project onto the scene";
1705
1706 IException tmp(e, IException::Programmer, msg, _FILEINFO_);
1707 tmp.print();
1708 mosaicSceneItem->image()->deleteLater();
1709 }
1710
1711 progressCountdown --;
1712 if (progressCountdown == 0) {
1713 m_progress->setValue(m_progress->value() + 1);
1714 progressCountdown = reprojectsPerUpdate;
1715 refit();
1716 }
1717 }
1718
1719 m_progress->setValue(m_progress->maximum());
1720
1721 recalcSceneRect();
1722 refit();
1723 m_progress->setVisible(false);
1724 }
1725
1726
1727 void MosaicSceneWidget::moveDownOne() {
1728 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1729
1730 if (props) {
1731 moveDownOne(cubeToMosaic(props));
1732 }
1733 }
1734
1735
1738 double MosaicSceneWidget::moveDownOne(MosaicSceneItem *item) {
1739 MosaicSceneItem *nextDown = getNextItem(item, false);
1740 double originalZ = item->zValue();
1741
1742 if (nextDown) {
1743 double newZValue = nextDown->zValue() - 1;
1744 moveZ(item, newZValue, true);
1745 }
1746
1747 return originalZ;
1748 }
1749
1750
1753 double MosaicSceneWidget::moveDownOne(Image *image) {
1754 return moveDownOne(cubeToMosaic(image));
1755 }
1756
1757
1760 QList<double> MosaicSceneWidget::moveDownOne(ImageList *images) {
1761 QList<double> results;
1762
1763 foreach (Image *image, *images) {
1764 results.append(moveDownOne(image));
1765 }
1766
1767 return results;
1768 }
1769
1770
1772 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1773 if (props) {
1774 moveToBottom(cubeToMosaic(props));
1775 }
1776 }
1777
1778
1784 double originalZ = item->zValue();
1785 double minZ = minimumZ();
1786
1787 if (originalZ != minZ) {
1788 // We know min-1 isn't already used
1789 int newZValue = qRound(minZ - 1);
1790 item->setZValue(newZValue);
1791
1792 // Remove this if we enable the compress
1793 m_currentMinimumFootprintZ--;
1794 }
1795
1796 return originalZ;
1797 }
1798
1799
1805 return moveToBottom(cubeToMosaic(image));
1806 }
1807
1808
1814 QList<double> results;
1815
1816 foreach (Image *image, *images) {
1817 results.append(moveToBottom(image));
1818 }
1819
1820 return results;
1821 }
1822
1823
1824 void MosaicSceneWidget::moveUpOne() {
1825 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1826
1827 if (props) {
1828 moveUpOne(cubeToMosaic(props));
1829 }
1830 }
1831
1832
1835 double MosaicSceneWidget::moveUpOne(MosaicSceneItem *item) {
1836 MosaicSceneItem *nextUp = getNextItem(item, true);
1837 double originalZ = item->zValue();
1838
1839 if (nextUp) {
1840 double newZValue = nextUp->zValue() + 1;
1841 moveZ(item, newZValue, true);
1842 }
1843
1844 return originalZ;
1845 }
1846
1847
1850 double MosaicSceneWidget::moveUpOne(Image *image) {
1851 return moveUpOne(cubeToMosaic(image));
1852 }
1853
1854
1857 QList<double> MosaicSceneWidget::moveUpOne(ImageList *images) {
1858 QList<double> results;
1859
1860 foreach (Image *image, *images) {
1861 results.append(moveUpOne(image));
1862 }
1863
1864 return results;
1865 }
1866
1867
1869 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
1870
1871 if (props) {
1872 moveToTop(cubeToMosaic(props));
1873 }
1874 }
1875
1876
1882 double originalZ = item->zValue();
1883 double maxZ = maximumZ();
1884
1885 if (originalZ != maxZ) {
1886 // We know max+1 isn't already used
1887 int newZValue = qRound(maxZ + 1);
1888 item->setZValue(newZValue);
1889
1890 // Remove this if we enable the compress
1891 m_currentMaximumFootprintZ++;
1892 }
1893
1894 // Compress... this makes this method have a time complexity of N instead of constant; there
1895 // isn't really a good justification for the slow down. I'm leaving this (working) code here
1896 // for reference and in case it's needed later.
1897 // foreach (MosaicSceneItem *otherItem, *m_mosaicSceneItems) {
1898 // double otherItemZ = otherItem->zValue();
1899 // if (otherItemZ > originalZ) {
1900 // otherItem->setZValue(otherItemZ - 1.0);
1901 // }
1902 // }
1903
1904 return originalZ;
1905 }
1906
1907
1913 return moveToTop(cubeToMosaic(image));
1914 }
1915
1916
1922 QList<double> results;
1923
1924 foreach (Image *image, *images) {
1925 results.append(moveToTop(image));
1926 }
1927
1928
1929// printZ(m_mosaicSceneItems);
1930 return results;
1931 }
1932
1933
1949 double MosaicSceneWidget::moveZ(MosaicSceneItem *sceneItem, double newZ,
1950 bool newZValueMightExist) {
1951 double originalZ = sceneItem->zValue();
1952
1953 if (newZValueMightExist) {
1954 // Adjust items between original and new position, recalculate min/max - time complexity=N
1955 m_currentMinimumFootprintZ = 0.0;
1956 m_currentMaximumFootprintZ = 0.0;
1957
1958 foreach (MosaicSceneItem *otherItem, *m_mosaicSceneItems) {
1959 double otherItemOrigZ = otherItem->zValue();
1960 double otherItemNewZ = otherItemOrigZ;
1961
1962 // Moving downwards (new Z is lower than current Z) and item is in the middle
1963 if (originalZ > newZ && otherItemOrigZ >= newZ && otherItemOrigZ < originalZ) {
1964 otherItemNewZ = otherItemOrigZ + 1;
1965 }
1966 // Moving upwards (new Z is higher than current Z) and item is in the middle
1967 else if (originalZ < newZ && otherItemOrigZ <= newZ && otherItemOrigZ > originalZ) {
1968 otherItemNewZ = otherItemOrigZ - 1;
1969 }
1970
1971 m_currentMinimumFootprintZ = qMin(m_currentMinimumFootprintZ, otherItemNewZ);
1972 m_currentMaximumFootprintZ = qMax(m_currentMaximumFootprintZ, otherItemNewZ);
1973 otherItem->setZValue(otherItemNewZ);
1974 }
1975 }
1976
1977 sceneItem->setZValue(newZ);
1978
1979 if (!newZValueMightExist) {
1980 // If we moved the max or min item, adjust the max down or min up respectively
1981 if (originalZ == maximumZ() && newZ < originalZ) {
1982 m_currentMaximumFootprintZ--;
1983 }
1984 else if (originalZ == minimumZ() && newZ > originalZ) {
1985 m_currentMinimumFootprintZ++;
1986 }
1987 }
1988
1989 return originalZ;
1990 }
1991
1992
1993 double MosaicSceneWidget::moveZ(Image *image, double newZ,
1994 bool newZValueMightExist) {
1995 return moveZ(cubeToMosaic(image), newZ, newZValueMightExist);
1996 }
1997
1998
1999 void MosaicSceneWidget::fitInView() {
2000 if (m_userToolControl) {
2001 QRectF boundingBox;
2002
2003 DisplayProperties *props = qobject_cast<DisplayProperties *>(sender());
2004
2005 if (props) {
2006 MosaicSceneItem *item = cubeToMosaic(props);
2007 boundingBox = item->boundingRect();
2008 }
2009 else {
2010 QAction *action = qobject_cast<QAction *>(sender());
2011
2012 if (action) {
2013 ImageList *images = action->data().value<ImageList *>();
2014
2015 foreach (Image *image, *images) {
2016 boundingBox = boundingBox.united(cubeToMosaic(image)->boundingRect());
2017 }
2018 }
2019 }
2020
2021 if (!boundingBox.isNull()) {
2022 double xPadding = boundingBox.width() * 0.10;
2023 double yPadding = boundingBox.height() * 0.10;
2024
2025 boundingBox.setLeft(boundingBox.left() - xPadding);
2026 boundingBox.setRight(boundingBox.right() + xPadding);
2027
2028 boundingBox.setTop(boundingBox.top() - yPadding);
2029 boundingBox.setBottom(boundingBox.bottom() + yPadding);
2030
2031 getView()->fitInView(boundingBox, Qt::KeepAspectRatio);
2032 getView()->centerOn(boundingBox.center());
2033 }
2034 }
2035 }
2036
2037
2038 void MosaicSceneWidget::onSelectionChanged() {
2039 if (!m_blockingSelectionChanged) {
2040 if (!m_queuedSelectionChanged) {
2041 emit queueSelectionChanged();
2042 m_queuedSelectionChanged = true;
2043 }
2044 else {
2045 m_shouldRequeueSelectionChanged = true;
2046 }
2047 }
2048 }
2049
2050
2051 void MosaicSceneWidget::onQueuedSelectionChanged() {
2052 m_queuedSelectionChanged = false;
2053
2054 if (m_shouldRequeueSelectionChanged) {
2055 m_shouldRequeueSelectionChanged = false;
2056 onSelectionChanged();
2057 }
2058 else {
2059 foreach(MosaicSceneItem *mosaicSceneItem, *m_mosaicSceneItems) {
2060 mosaicSceneItem->updateSelection(true);
2061 }
2062 }
2063 }
2064
2065
2068 MosaicSceneItem *nextZValueItem = NULL;
2069 MosaicSceneItem *mosaicSceneItem;
2070
2071 foreach(mosaicSceneItem, *m_mosaicSceneItems) {
2072 if (mosaicSceneItem != item &&
2073 mosaicSceneItem->boundingRect().intersects(item->boundingRect())) {
2074 // Does this item qualify as above or below at all?
2075 if ( (up && mosaicSceneItem->zValue() > item->zValue()) ||
2076 (!up && mosaicSceneItem->zValue() < item->zValue())) {
2077 // It is in the correct direction, set the initial guess if we don't
2078 // have one or test if it's better
2079 if (!nextZValueItem) {
2080 nextZValueItem = mosaicSceneItem;
2081 }
2082 else {
2083 // We know it qualifies, we want to know if it's closer than
2084 // nextZValueItem
2085 if ((up && mosaicSceneItem->zValue() < nextZValueItem->zValue()) ||
2086 (!up && mosaicSceneItem->zValue() > nextZValueItem->zValue())) {
2087 nextZValueItem = mosaicSceneItem;
2088 }
2089 }
2090 }
2091 }
2092 }
2093
2094 return nextZValueItem;
2095 }
2096
2097
2098 bool MosaicSceneWidget::zOrderGreaterThan(MosaicSceneItem *first,
2099 MosaicSceneItem *second) {
2100 return first->zValue() > second->zValue();
2101 }
2102}
A single control point.
QString displayName() const
Returns the display name.
This represents a cube in a project-based GUI interface.
Definition Image.h:105
ImageDisplayProperties * displayProperties()
Get the display (GUI) properties (information) associated with this image.
Definition Image.cpp:296
QString fileName() const
Get the file name of the cube that this image represents.
Definition Image.cpp:316
QString id() const
Get a unique, identifying string associated with this image.
Definition Image.cpp:421
Internalizes a list of images and allows for operations on the entire list.
Definition ImageList.h:52
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
bool isActive() const
Returns the activeness of this toool.
Definition MosaicTool.h:50
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...
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:154
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
virtual void setData(Context)
Sets the context data for this WorkOrder.
This is free and unencumbered software released into the public domain.
Definition ControlNet.h:32
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(const LinearAlgebra::Vector &vector, int precision)
A global function to format LinearAlgebra::Vector as a QString with the given precision.