Isis 3 Programmer Reference
MosaicController.cpp
1#include "MosaicController.h"
2
3#include <QAction>
4#include <QApplication>
5#include <QBuffer>
6#include <QFileDialog>
7#include <QFuture>
8#include <QFutureWatcher>
9#include <QGraphicsScene>
10#include <QGraphicsView>
11#include <QInputDialog>
12#include <QMenu>
13#include <QMessageBox>
14#include <QProgressBar>
15#include <QSettings>
16#include <QUuid>
17#include <QtConcurrentMap>
18
19#include "ControlNet.h"
20#include "Cube.h"
21#include "DisplayProperties.h"
22#include "FileName.h"
23#include "IException.h"
24#include "ImageFileListWidget.h"
25#include "ImageReader.h"
26#include "MosaicSceneWidget.h"
27#include "ProgressBar.h"
28#include "Pvl.h"
29#include "PvlObject.h"
30#include "TextFile.h"
31
32
33namespace Isis {
34
44 MosaicController::MosaicController(QStatusBar *status, QSettings &settings) {
45 m_fileList = NULL;
46 m_scene = NULL;
47 m_worldScene = NULL;
48 m_imageReader = NULL;
49
50 m_mutex = new QMutex;
51
52 m_imageReader = new ImageReader(m_mutex);
53
54 connect(m_imageReader, SIGNAL(imagesReady(ImageList)), this, SLOT(imagesReady(ImageList)));
55
56 m_fileList = new ImageFileListWidget;
57 m_scene = new MosaicSceneWidget(status, true, false, NULL);
58 m_worldScene = new MosaicSceneWidget(status, false, false, NULL);
59
60 connect(this, SIGNAL(imagesAdded(ImageList)), m_scene, SLOT(addImages(ImageList)));
61 connect(this, SIGNAL(imagesAdded(ImageList)), m_worldScene, SLOT(addImages(ImageList)));
62 connect(this, SIGNAL(imagesAdded(ImageList *)), m_fileList, SLOT(addImages(ImageList *)));
63
64 connect(m_scene, SIGNAL(projectionChanged(Projection *)),
65 m_worldScene, SLOT(setProjection(Projection *)));
66 connect(m_scene, SIGNAL(visibleRectChanged(QRectF)),
67 m_worldScene, SLOT(setOutlineRect(QRectF)));
68
69 settings.beginGroup("MosaicController");
70 m_maxThreads = settings.value("maxThreads", 0).toInt();
71 settings.endGroup();
72
73 applyMaxThreadCount();
74 }
75
76
81 delete m_fileList;
82 delete m_scene;
83 delete m_worldScene;
84 delete m_imageReader;
85 }
86
87
92 QList<QAction *> exportActions = m_scene->getExportActions();
93
94 foreach (QAction * exportAct, exportActions) {
95 fileMenu.addAction(exportAct);
96 }
97
98 exportActions = m_fileList->getExportActions();
99
100 foreach (QAction * exportAct, exportActions) {
101 fileMenu.addAction(exportAct);
102 }
103 }
104
105
109 QProgressBar *MosaicController::getProgress() {
110 return m_imageReader->progress();
111 }
112
113
114 void MosaicController::saveProject(QString projFileName) {
115 Pvl projFile;
116
117 PvlObject imageProps("Images");
118
119 foreach (Image *image, m_images) {
120 imageProps += image->toPvl();
121 }
122
123 projFile += imageProps;
124 projFile += m_fileList->toPvl();
125 projFile += m_scene->toPvl();
126
127 projFile.write(projFileName);
128 }
129
130
131 QList<QAction *> MosaicController::getSettingsActions() {
132 QList<QAction *> settingsActs;
133
134 settingsActs.append(m_imageReader->actions(ImageDisplayProperties::FootprintViewProperties));
135 settingsActs.append(m_fileList->actions());
136
137 QAction *setThreads = new QAction("Set &Thread Limit", this);
138 connect(setThreads, SIGNAL(triggered(bool)),
139 this, SLOT(changeMaxThreads()));
140 settingsActs.append(setThreads);
141
142 return settingsActs;
143 }
144
145
146 void MosaicController::saveSettings(QSettings &settings) {
147 settings.beginGroup("MosaicController");
148 settings.setValue("maxThreads", m_maxThreads);
149 settings.endGroup();
150 }
151
152
158 m_imageReader->read(cubeNames);
159 }
160
161
162 void MosaicController::openProjectImages(PvlObject projectImages) {
163 m_imageReader->read(projectImages);
164 }
165
166
167 void MosaicController::imagesReady(ImageList images) {
168 m_images.append(images);
169
170 foreach (Image *image, images) {
171 connect(image, SIGNAL(destroyed(QObject *)),
172 this, SLOT(imageClosed(QObject *)));
173 }
174
175 // We really can't have all of the cubes in memory before
176 // the OS stops letting us open more files.
177 // Assume cameras are being used in other parts of code since it's
178 // unknown
179 QMutexLocker lock(m_mutex);
180 emit imagesAdded(images);
181 emit imagesAdded(&images);
182
183 Image *openImage;
184 foreach (openImage, images) {
185 openImage->closeCube();
186 }
187 }
188
189
190 void MosaicController::changeMaxThreads() {
191 bool ok = false;
192
193 QStringList options;
194
195 int current = 0;
196 options << tr("Use all available");
197
198 for(int i = 1; i < 24; i++) {
199 QString option = tr("Use %1 threads").arg(i + 1);
200
201 options << option;
202 if(m_maxThreads == i + 1)
203 current = i;
204 }
205
206 QString res = QInputDialog::getItem(NULL, tr("Concurrency"),
207 tr("Set the number of threads to use"),
208 options, current, false, &ok);
209
210 if (ok) {
211 m_maxThreads = options.indexOf(res) + 1;
212
213 applyMaxThreadCount();
214 }
215 }
216
217
222 Image *image = (Image *)imageObj;
223
224 if (image) {
225 ImageList::iterator foundElement;
226 foundElement = qFind(m_images.begin(), m_images.end(), image);
227 m_images.erase(foundElement);
228
229 if(m_images.empty())
230 emit allImagesClosed();
231 }
232 }
233
234
235 void MosaicController::readProject(QString filename) {
236 try {
237 Pvl projectPvl(filename);
238
239 // Convert versions <= isis3.4.1 to newer
240 if (projectPvl.hasObject("Cubes")) {
241 convertV1ToV2(projectPvl);
242 }
243
244 PvlObject &projImages(projectPvl.findObject("Images"));
245
246 if (projectPvl.hasObject("MosaicScene"))
247 m_scene->fromPvl(projectPvl.findObject("MosaicScene"));
248
249 if (projectPvl.hasObject("ImageFileList"))
250 m_fileList->fromPvl(projectPvl.findObject("ImageFileList"));
251
252 openProjectImages(projImages);
253 }
254 catch(IException &e) {
255 throw IException(e, IException::Unknown,
256 "Input file is not a valid qmos project", _FILEINFO_);
257 }
258 }
259
260
261 void MosaicController::saveList() {
262 QString output =
263 QFileDialog::getSaveFileName((QWidget *)parent(),
264 "Choose output file",
265 QDir::currentPath() + "/files.lis",
266 QString("List File (*.lis);;Text File (*.txt);;All Files (*.*)"));
267 if(output.isEmpty()) return;
268
269 TextFile file(output, "output");
270
271 Image *image;
272 foreach (image, m_images) {
273 file.PutLine( image->fileName() );
274 }
275 }
276
277
278 void MosaicController::applyMaxThreadCount() {
279 if (m_maxThreads <= 1) {
280 QThreadPool::globalInstance()->setMaxThreadCount(QThread::idealThreadCount());
281 }
282 else {
283 QThreadPool::globalInstance()->setMaxThreadCount(m_maxThreads - 1);
284 }
285 }
286
287
298 PvlObject &images = project.findObject("Cubes");
299
300 images.setName("Images");
301
302 QMap<QString, QString> imageFileToNewId;
303
304 for (int imgObjIndex = 0; imgObjIndex < images.objects(); imgObjIndex++) {
305 PvlObject &image = images.object(imgObjIndex);
306 image.setName("Image");
307
308
309 QBuffer idDataBuffer;
310 idDataBuffer.open(QIODevice::ReadWrite);
311
312 QDataStream idStream(&idDataBuffer);
313
314 QUuid newId = QUuid::createUuid();
315 QString fileName = image["FileName"][0];
316 idStream << newId;
317
318 idDataBuffer.seek(0);
319
320 QString idHex;
321 image += PvlKeyword("ID", QString(idDataBuffer.data().toHex()));
322
323 PvlKeyword oldDisplayPropsValues = image["Values"];
324 image.deleteKeyword("Values");
325
326 PvlObject displayProps("DisplayProperties");
327 displayProps += PvlKeyword("DisplayName", FileName(fileName).name());
328
329 // Convert display properties over
330 enum OldDispProps {
331 OldDispPropColor,
332 OldDispPropUntransferred1, // Selected
333 OldDispPropShowDNs,
334 OldDispPropShowFill,
335 OldDispPropShowLabel,
336 OldDispPropShowOutline,
337 OldDispPropUntransferred2, // Zooming
338 OldDispPropUntransferred3 // ZOrdering
339 };
340
341 QMap<int, QVariant> oldProps;
342 QByteArray oldHexValues(oldDisplayPropsValues[0].toLatin1());
343 QDataStream oldValuesStream(QByteArray::fromHex(oldHexValues));
344 oldValuesStream >> oldProps;
345
346 enum V2DispProps {
347 V2DispPropColor = 1,
348 V2DispPropShowDNs = 4,
349 V2DispPropShowFill = 8,
350 V2DispPropShowLabel = 16,
351 V2DispPropShowOutline = 32
352 };
353
354 QMap<int, QVariant> newProps;
355 newProps[V2DispPropColor] = oldProps[OldDispPropColor];
356 newProps[V2DispPropShowDNs] = oldProps[OldDispPropShowDNs];
357 newProps[V2DispPropShowFill] = oldProps[OldDispPropShowFill];
358 newProps[V2DispPropShowLabel] = oldProps[OldDispPropShowLabel];
359 newProps[V2DispPropShowOutline] = oldProps[OldDispPropShowOutline];
360
361 QBuffer newPropsDataBuffer;
362 newPropsDataBuffer.open(QIODevice::ReadWrite);
363
364 QDataStream newPropsStream(&newPropsDataBuffer);
365 newPropsStream << newProps;
366 newPropsDataBuffer.seek(0);
367
368 displayProps += PvlKeyword("Values", newPropsDataBuffer.data().toHex().data());
369 // Finished converting display properties from V1->V2
370
371
372 image += displayProps;
373
374 imageFileToNewId[fileName] = newId.toString().replace(QRegExp("[{}]"), "");
375 }
376
377 PvlObject &fileListOpts = project.findObject("MosaicFileList");
378 fileListOpts.setName("ImageFileList");
379
380 for (int fileListIndex = 0; fileListIndex < fileListOpts.objects(); fileListIndex++) {
381 PvlObject &fileListOrderObj = fileListOpts.object(fileListIndex);
382
383 for (int i = 0; i < fileListOrderObj.keywords(); i++) {
384 PvlKeyword &key = fileListOrderObj[i];
385
386 if (key.isNamed("Cube")) {
387 key.setName("Image");
388 key[0] = imageFileToNewId[key[0]];
389 }
390 }
391 }
392
393 PvlObject &sceneOpts = project.findObject("MosaicScene");
394
395 if (sceneOpts.hasObject("ZOrdering")) {
396 PvlObject &zOrdering = sceneOpts.findObject("ZOrdering");
397
398
399 for (int i = 0; i < zOrdering.keywords(); i++) {
400 PvlKeyword &key = zOrdering[i];
401
402 if (key.isNamed("ZValue")) {
403 key[0] = imageFileToNewId[key[0]];
404 }
405 }
406 }
407 }
408}
File name manipulation and expansion.
Definition FileName.h:100
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ FootprintViewProperties
Every display property for footprint views, provided for convenience.
A colored, grouped cube list.
This represents a cube in a project-based GUI interface.
Definition Image.h:107
Internalizes a list of images and allows for operations on the entire list.
Definition ImageList.h:55
iterator erase(iterator pos)
Erases a single image from the image list.
void append(Image *const &value)
Appends an image to the image list.
void convertV1ToV2(Pvl &project)
This converts qmos project files (no other project files existed) from their original version (file n...
MosaicController(QStatusBar *status, QSettings &settings)
MosaicWidget constructor.
void openImages(QStringList filenames)
Handle opening cubes by filename.
void addExportActions(QMenu &fileMenu)
Add actions that are export-related to the menu.
void imageClosed(QObject *image)
An open image is being deleted.
void imagesAdded(ImageList images)
Emitted when new images are available.
virtual ~MosaicController()
Free the allocated memory by this object.
This widget encompasses the entire mosaic scene.
Base class for Map Projections.
Definition Projection.h:155
void setName(const QString &name)
Set the name of the container.
void deleteKeyword(const QString &name)
Remove a specified keyword.
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
void setName(QString name)
Sets the keyword name.
bool isNamed(QString name) const
Determines whether two PvlKeywords have the same name or not.
Definition PvlKeyword.h:115
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
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
int objects() const
Returns the number of objects.
Definition PvlObject.h:221
PvlObject & object(const int index)
Return the object at the specified index.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16