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 
33 namespace 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 }
PvlObject & object(const int index)
Return the object at the specified index.
Definition: PvlObject.cpp:460
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Definition: PvlContainer.h:100
Internalizes a list of images and allows for operations on the entire list.
Definition: ImageList.h:55
File name manipulation and expansion.
Definition: FileName.h:116
int objects() const
Returns the number of objects.
Definition: PvlObject.h:231
void imagesAdded(ImageList images)
Emitted when new images are available.
This widget encompasses the entire mosaic scene.
virtual ~MosaicController()
Free the allocated memory by this object.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
void setName(QString name)
Sets the keyword name.
Definition: PvlKeyword.cpp:136
void setName(const QString &name)
Set the name of the container.
Definition: PvlContainer.h:70
bool isNamed(QString name) const
Determines whether two PvlKeywords have the same name or not.
Definition: PvlKeyword.h:126
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:335
void imageClosed(QObject *image)
An open image is being deleted.
MosaicController(QStatusBar *status, QSettings &settings)
MosaicWidget constructor.
Base class for Map Projections.
Definition: Projection.h:171
void addExportActions(QMenu &fileMenu)
Add actions that are export-related to the menu.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
void convertV1ToV2(Pvl &project)
This converts qmos project files (no other project files existed) from their original version (file n...
A single keyword-value pair.
Definition: PvlKeyword.h:98
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
This represents a cube in a project-based GUI interface.
Definition: Image.h:107
void append(Image *const &value)
Appends an image to the image list.
Definition: ImageList.cpp:153
Container for cube-like labels.
Definition: Pvl.h:135
void openImages(QStringList filenames)
Handle opening cubes by filename.
Every display property for footprint views, provided for convenience.
A colored, grouped cube list.
iterator erase(iterator pos)
Erases a single image from the image list.
Definition: ImageList.cpp:195
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
void deleteKeyword(const QString &name)
Remove a specified keyword.