Isis 3.0 Programmer Reference
Back | Home
Project.cpp
Go to the documentation of this file.
1 
24 #include "IsisDebug.h"
25 #include "Project.h"
26 
27 #include <unistd.h>
28 
29 #include <QApplication>
30 #include <QDir>
31 #include <QFileDialog>
32 #include <QFuture>
33 #include <QFutureWatcher>
34 #include <QMessageBox>
35 #include <QMutex>
36 #include <QMutexLocker>
37 #include <QProgressBar>
38 #include <QStringList>
39 #include <QtDebug>
40 #include <QXmlStreamWriter>
41 
42 #include "BundleSolutionInfo.h"
43 #include "BundleSettings.h"
44 #include "Camera.h"
45 #include "Control.h"
46 #include "ControlList.h"
47 #include "CorrelationMatrix.h"
48 #include "Cube.h"
49 #include "Directory.h"
50 #include "Environment.h"
51 #include "FileName.h"
52 #include "GuiCamera.h"
53 #include "GuiCameraList.h"
54 #include "IException.h"
55 #include "ImageList.h"
56 #include "ImageReader.h"
57 #include "IException.h"
58 #include "ProgressBar.h"
59 #include "Shape.h"
60 #include "ShapeList.h"
61 #include "ShapeReader.h"
62 #include "Target.h"
63 #include "TargetBodyList.h"
64 #include "WorkOrder.h"
65 #include "WorkOrderFactory.h"
66 #include "XmlStackedHandlerReader.h"
67 
68 namespace Isis {
69 
73  Project::Project(Directory &directory, QObject *parent) :
74  QObject(parent) {
75  //qDebug()<<"Project::Project";
76  m_bundleSettings = NULL;
77  m_directory = &directory;
78  m_projectRoot = NULL;
79  m_cnetRoot = NULL;
80  m_idToControlMap = NULL;
81  m_idToImageMap = NULL;
82  m_idToShapeMap = NULL;
83  m_idToTargetBodyMap = NULL;
84  m_idToGuiCameraMap = NULL;
85  m_images = NULL;
86  m_imageReader = NULL;
87  m_shapeReader = NULL;
88  m_shapes = NULL;
89  m_warnings = NULL;
90  m_workOrderHistory = NULL;
91  m_isTemporaryProject = true;
92  m_activeControl = NULL;
93  m_activeImageList = NULL;
94 
95  m_numImagesCurrentlyReading = 0;
96 
97  m_mutex = NULL;
98  m_imageReadingMutex = NULL;
99 
100  m_numShapesCurrentlyReading = 0;
101  m_shapeMutex = NULL;
102  m_shapeReadingMutex = NULL;
103 
105  m_idToImageMap = new QMap<QString, Image *>;
106  m_idToShapeMap = new QMap<QString, Shape *>;
107  m_idToTargetBodyMap = new QMap<QString, TargetBody *>;
108  m_idToGuiCameraMap = new QMap<QString, GuiCamera *>;
109  m_idToBundleSolutionInfoMap = new QMap<QString, BundleSolutionInfo *>;
110 
111  m_name = "Project";
112 
113  // Look for old projects
114  QDir tempDir = QDir::temp();
115  QStringList nameFilters;
116  nameFilters.append(Environment::userName() + "_" +
117  QApplication::applicationName() + "_*");
118  tempDir.setNameFilters(nameFilters);
119 
120  QStringList existingProjects = tempDir.entryList();
121  bool crashedPreviously = false;
122 
123  foreach (QString existingProject, existingProjects) {
124  FileName existingProjectFileName(tempDir.absolutePath() + "/" + existingProject);
125  QString pidString = QString(existingProject).replace(QRegExp(".*_"), "");
126  int otherPid = pidString.toInt();
127 
128  if (otherPid != 0) {
129  if ( !QFile::exists("/proc/" + pidString) ) {
130  crashedPreviously = true;
131  int status = system( ("rm -rf '" +
132  existingProjectFileName.expanded() + "' &").toLatin1().data() );
133  if (status != 0) {
134  QString msg = "Executing command [rm -rf" + existingProjectFileName.expanded() +
135  "' &] failed with return status [" + toString(status) + "]";
137  }
138  }
139  }
140  }
141 
142  if (crashedPreviously && false) {
143  QMessageBox::information( NULL,
144  QObject::tr("Crashed"),
145  QObject::tr("It appears %1 crashed. We're sorry.").
146  arg( QApplication::applicationName() ) );
147  }
148 
149 
150  try {
151  QString tmpFolder = QDir::temp().absolutePath() + "/"
152  + Environment::userName() + "_"
153  + QApplication::applicationName() + "_" + QString::number( getpid() );
154  QDir temp(tmpFolder + "/tmpProject");
155  m_projectRoot = new QDir(temp);
156  //qDebug()<<" Create temp project";
157  createFolders();
158  }
159  catch (IException &e) {
160  throw IException(e, IException::Programmer, "Error creating project folders.", _FILEINFO_);
161  }
162  catch (std::exception &e) {
163  // e.what()
165  tr("Error creating project folders [%1]").arg( e.what() ), _FILEINFO_);
166  }
167  // TODO TLS 2016-07-13 This seems to only be used by ControlNet when SetTarget is called.
168  // This needs to be better documented, possibly renamed or redesigned??
169  m_mutex = new QMutex;
170 
171  // image reader
172  m_imageReader = new ImageReader(m_mutex, true);
173 
174  connect( m_imageReader, SIGNAL( imagesReady(ImageList) ),
175  this, SLOT( imagesReady(ImageList) ) );
176 
177  connect( this, SIGNAL(imagesAdded(ImageList *) ),
178  this, SLOT(addTargetsFromImportedImagesToProject(ImageList *) ) );
179 
180  connect( this, SIGNAL(imagesAdded(ImageList *) ),
181  this, SLOT(addCamerasFromImportedImagesToProject(ImageList *) ) );
182 
183  m_images = new QList<ImageList *>;
184 
185  // Shape reader
186  m_shapeMutex = new QMutex;
187 
188  m_shapeReader = new ShapeReader(m_shapeMutex, false);
189 
190  connect( m_shapeReader, SIGNAL( shapesReady(ShapeList) ),
191  this, SLOT( shapesReady(ShapeList) ) );
192 
193  m_shapes = new QList<ShapeList *>;
194 
195  m_controls = new QList<ControlList *>;
196 
197  m_targets = new TargetBodyList;
198 
199  m_guiCameras = new GuiCameraList;
200 
201  m_bundleSolutionInfo = new QList<BundleSolutionInfo *>;
202 
203  m_warnings = new QStringList;
204  m_workOrderHistory = new QList< QPointer<WorkOrder> >;
205 
206  m_imageReadingMutex = new QMutex;
207 
208  m_shapeReadingMutex = new QMutex;
209 
210  // TODO: ken testing
211 // m_bundleSettings = NULL;
212 // m_bundleSettings = new BundleSettings();
213  }
214 
215 
220  if (m_isTemporaryProject) {
222  }
223  else {
224  int undoStackIndex = m_undoStack.index();
225  int undoStackCleanIndex = m_undoStack.cleanIndex();
226 
227  int undoNeededToRestoreDiskState = undoStackIndex;
228 
229  for (int i = undoStackIndex - 1; i >= undoStackCleanIndex; i--) {
230  const WorkOrder *currentWorkOrder =
231  dynamic_cast<const WorkOrder *>( m_undoStack.command(i) );
232  if ( currentWorkOrder && currentWorkOrder->modifiesDiskState() ) {
233  undoNeededToRestoreDiskState = i;
234  }
235  }
236 
237  if (undoNeededToRestoreDiskState != undoStackIndex) {
238  m_undoStack.setIndex(undoNeededToRestoreDiskState);
239  }
240  }
241 
242  if (m_images) {
243  foreach (ImageList *imageList, *m_images) {
244  foreach (Image *image, *imageList) {
245  delete image;
246  }
247 
248  delete imageList;
249  }
250 
251  delete m_images;
252  m_images = NULL;
253  }
254 
255  if (m_shapes) {
256  foreach (ShapeList *shapeList, *m_shapes) {
257  foreach (Shape *shape, *shapeList) {
258  delete shape;
259  }
260 
261  delete shapeList;
262  }
263 
264  delete m_shapes;
265  m_shapes = NULL;
266  }
267 
268  if (m_controls) {
269  foreach (ControlList *controlList, *m_controls) {
270  foreach (Control *control, *controlList) {
271  delete control;
272  }
273 
274  delete controlList;
275  }
276  delete m_controls;
277  m_controls = NULL;
278  }
279 
280  m_activeControl = NULL;
281  m_activeImageList = NULL;
282 
283  if (m_bundleSolutionInfo) {
284  foreach (BundleSolutionInfo *bundleSolutionInfo, *m_bundleSolutionInfo) {
285  delete bundleSolutionInfo;
286  }
287 
288  delete m_bundleSolutionInfo;
289  m_bundleSolutionInfo = NULL;
290  }
291 
292  delete m_idToControlMap;
293  m_idToControlMap = NULL;
294 
295  delete m_idToImageMap;
296  m_idToImageMap = NULL;
297 
298  delete m_idToShapeMap;
299  m_idToShapeMap = NULL;
300 
301  delete m_idToTargetBodyMap;
302  m_idToTargetBodyMap = NULL;
303 
304  delete m_idToGuiCameraMap;
305  m_idToGuiCameraMap = NULL;
306 
307  delete m_idToBundleSolutionInfoMap;
308  m_idToBundleSolutionInfoMap = NULL;
309 
310  m_directory = NULL;
311 
312  delete m_projectRoot;
313  m_projectRoot = NULL;
314 
315  delete m_cnetRoot;
316  m_cnetRoot = NULL;
317 
318  delete m_imageReader;
319  delete m_shapeReader;
320 
321  delete m_warnings;
322  m_warnings = NULL;
323 
324  delete m_workOrderHistory;
325  m_workOrderHistory = NULL;
326 
327  delete m_bundleSettings;
328  m_bundleSettings = NULL;
329  }
330 
331 
336  QDir dir;
337  if ( !dir.mkpath( m_projectRoot->path() ) ) {
338  warn("Cannot create project directory.");
340  tr("Unable to create folder [%1] when trying to initialize project")
341  .arg(m_projectRoot->path() ),
342  _FILEINFO_);
343  }
344 
345  try {
346  if ( !dir.mkdir( cnetRoot() ) ) {
347  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
348  .arg( cnetRoot() );
349  warn(msg);
350  throw IException(IException::Io, msg, _FILEINFO_);
351  }
352 
353  if ( !dir.mkdir( imageDataRoot() ) ) {
354  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
355  .arg( imageDataRoot() );
356  warn(msg);
357  throw IException(IException::Io, msg, _FILEINFO_);
358  }
359 // qDebug()<<"shape directory = "<<shapeDataRoot();
360  if ( !dir.mkdir( shapeDataRoot() ) ) {
361  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
362  .arg( shapeDataRoot() );
363  warn(msg);
364  throw IException(IException::Io, msg, _FILEINFO_);
365  }
366 
367  if ( !dir.mkdir( resultsRoot() ) ) {
368  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
369  .arg( resultsRoot() );
370  warn(msg);
371  throw IException(IException::Io, msg, _FILEINFO_);
372  }
373  if ( !dir.mkdir( bundleSolutionInfoRoot() ) ) {
374  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
375  .arg( bundleSolutionInfoRoot() );
376  warn(msg);
377  throw IException(IException::Io, msg, _FILEINFO_);
378  }
379  }
380  catch (...) {
381  warn("Failed to create project directory structure");
382  throw;
383  }
384  }
385 
386 
387  ImageList *Project::createOrRetrieveImageList(QString name) {
388  ImageList *result = imageList(name);
389  if (!result) {
390  result = new ImageList;
391 
392  result->setName(name);
393  result->setPath(name);
394 
395  connect( result, SIGNAL( destroyed(QObject *) ),
396  this, SLOT( imageListDeleted(QObject *) ) );
397  //TODO 07-29-14 Kim & Tracie commented this out. Didn't seem like it was necessary.
398  // If problems, need to understand this code better.
399  m_images->append(result);
400  }
401  return result;
402  }
403 
404 
405  ShapeList *Project::createOrRetrieveShapeList(QString name) {
406  ShapeList *result = shapeList(name);
407  if (!result) {
408  result = new ShapeList;
409 
410  result->setName(name);
411  result->setPath(name);
412 
413  connect( result, SIGNAL( destroyed(QObject *) ),
414  this, SLOT( shapeListDeleted(QObject *) ) );
415  m_shapes->append(result);
416  }
417  return result;
418  }
419 
420 
434  void Project::save(QXmlStreamWriter &stream, FileName newProjectRoot) const {
435  stream.writeStartElement("project");
436 
437  stream.writeAttribute("name", m_name);
438 
439  if ( !m_controls->isEmpty() ) {
440  stream.writeStartElement("controlNets");
441 
442  for (int i = 0; i < m_controls->count(); i++) {
443  m_controls->at(i)->save(stream, this, newProjectRoot);
444  }
445 
446  stream.writeEndElement();
447  }
448 
449  if ( !m_images->isEmpty() ) {
450  stream.writeStartElement("imageLists");
451 
452  for (int i = 0; i < m_images->count(); i++) {
453  m_images->at(i)->save(stream, this, newProjectRoot);
454  }
455 
456  stream.writeEndElement();
457  }
458 
459  if ( !m_shapes->isEmpty() ) {
460  stream.writeStartElement("shapeLists");
461 
462  for (int i = 0; i < m_shapes->count(); i++) {
463  m_shapes->at(i)->save(stream, this, newProjectRoot);
464  }
465 
466  stream.writeEndElement();
467  }
468 
469  // Write general look of gui, including docked widges
470 // QVariant geo_data = saveGeometry();
471 // QVariant layout_data = saveState();
472 //
473 // stream.writeStartElement("dockRestore");
474 // stream.writeAttribute("geometry", geo_data.toString());
475 // stream.writeAttribute("state", layout_data.toString());
476 
477 
478  // if ( !m_bundleSolutionInfo->isEmpty() ) {
479  // stream.writeStartElement("bundleSolutionInfo");
480  //
481  // for (int i = 0; i < m_bundleSolutionInfo->count(); i++) {
482  // m_bundleSolutionInfo->at(i)->save(stream, this, newProjectRoot);
483  // }
484  //
485  // stream.writeEndElement();
486  // }
487 
488  // should we write the runtimes of the runs here???
489  if (!m_bundleSolutionInfo->isEmpty()) {
490  stream.writeStartElement("bundleRuns");
491 
492  for (int i = 0; i < m_bundleSolutionInfo->count(); i++) {
493  m_bundleSolutionInfo->at(i)->runTime();
494  }
495 
496  stream.writeEndElement();
497  }
498 
499  stream.writeEndElement();
500  }
501 
502 
518  void Project::saveHistory(QXmlStreamWriter &stream) const {
519  stream.writeStartElement("history");
520 
521  foreach (WorkOrder *workOrder, *m_workOrderHistory) {
522  if (workOrder) {
523  workOrder->save(stream);
524  }
525  }
526 
527  stream.writeEndElement();
528  }
529 
541  void Project::saveWarnings(QXmlStreamWriter &stream) const {
542  stream.writeStartElement("warnings");
543 
544  foreach (QString warning, *m_warnings) {
545  stream.writeStartElement("warning");
546  stream.writeAttribute("text", warning);
547  stream.writeEndElement();
548  }
549 
550  stream.writeEndElement();
551  }
552 
553 
560  // TODO: thread via ImageReader
561  QStringList Project::images(QStringList fileNames) {
562 
563  QStringList result;
564 
565  foreach (QString fileName, fileNames) {
566  try {
567  Cube tmp(fileName);
568  result.append(fileName);
569  }
570  catch (IException &) {
571  }
572  }
573 
574  return result;
575  }
576 
577 
584  return m_imageReader->actions(ImageDisplayProperties::FootprintViewProperties);
585  }
586 
587 
595  QDir bundleSolutionInfoFolder(bundleSolutionInfoRoot());
596 
597  if (!bundleSolutionInfoFolder.mkpath(folder)) {
599  tr("Could not create bundle results directory [%1] in [%2].")
600  .arg(folder).arg(bundleSolutionInfoFolder.absolutePath()),
601  _FILEINFO_);
602  }
603 
604  bundleSolutionInfoFolder.cd(folder);
605  return bundleSolutionInfoFolder;
606  }
607 
608 
614  QDir Project::addCnetFolder(QString prefix) {
615  QDir cnetFolder = cnetRoot();
616  prefix += "%1";
617  int prefixCounter = 0;
618 
619  QString numberedPrefix;
620  do {
621  prefixCounter++;
622  numberedPrefix = prefix.arg( QString::number(prefixCounter) );
623  }
624  while ( cnetFolder.exists(numberedPrefix) );
625 
626  if ( !cnetFolder.mkpath(numberedPrefix) ) {
628  tr("Could not create control network directory [%1] in [%2].")
629  .arg(numberedPrefix).arg( cnetFolder.absolutePath() ),
630  _FILEINFO_);
631  }
632 
633  cnetFolder.cd(numberedPrefix);
634 
635  m_currentCnetFolder = cnetFolder;
636 
637  return cnetFolder;
638  }
639 
640 
646  void Project::addControl(Control *control) {
647 
648  connect( control, SIGNAL( destroyed(QObject *) ),
649  this, SLOT( controlClosed(QObject *) ) );
650  connect( this, SIGNAL( projectRelocated(Project *) ),
651  control, SLOT( updateFileName(Project *) ) );
652 
653  createOrRetrieveControlList( FileName( control->fileName() ).dir().dirName() )->append(control);
654 
655  (*m_idToControlMap)[control->id()] = control;
656 
657  emit controlAdded(control);
658  }
659 
660 
661  ControlList *Project::createOrRetrieveControlList(QString name) {
662  ControlList *result = controlList(name);
663 
664  if (!result) {
665  result = new ControlList;
666 
667  result->setName(name);
668  result->setPath(name);
669 
670  connect( result, SIGNAL( destroyed(QObject *) ),
671  this, SLOT( controlListDeleted(QObject *) ) );
672 
673  emit controlListAdded(result);
674  m_controls->append(result);
675  }
676 
677  return result;
678  }
679 
680 
686  QDir Project::addImageFolder(QString prefix) {
687  QDir imageFolder = imageDataRoot();
688  prefix += "%1";
689  int prefixCounter = 0;
690 
691  QString numberedPrefix;
692  do {
693  prefixCounter++;
694  numberedPrefix = prefix.arg( QString::number(prefixCounter) );
695  }
696  while ( imageFolder.exists(numberedPrefix) );
697 
698  if ( !imageFolder.mkpath(numberedPrefix) ) {
700  tr("Could not create image directory [%1] in [%2].")
701  .arg(numberedPrefix).arg( imageFolder.absolutePath() ),
702  _FILEINFO_);
703  }
704 
705  imageFolder.cd(numberedPrefix);
706 
707  return imageFolder;
708  }
709 
710 
714  void Project::addImages(QStringList imageFiles) {
715 // qDebug()<<"Project::addImages(QStringList imageFiles)";
716  if (m_numImagesCurrentlyReading == 0) {
717  m_imageReadingMutex->lock();
718  }
719 
720  m_numImagesCurrentlyReading += imageFiles.count();
721  m_imageReader->read(imageFiles);
722  }
723 
724 
725  void Project::addImages(ImageList newImages) {
726 // qDebug()<<"Project::addImages(ImageList newImages";
727  imagesReady(newImages);
728  }
729 
730 
736  QDir Project::addShapeFolder(QString prefix) {
737  QDir shapeFolder = shapeDataRoot();
738  prefix += "%1";
739  int prefixCounter = 0;
740 
741  QString numberedPrefix;
742  do {
743  prefixCounter++;
744  numberedPrefix = prefix.arg( QString::number(prefixCounter) );
745  }
746  while ( shapeFolder.exists(numberedPrefix) );
747 
748  if ( !shapeFolder.mkpath(numberedPrefix) ) {
750  tr("Could not create shape directory [%1] in [%2].")
751  .arg(numberedPrefix).arg( shapeFolder.absolutePath() ),
752  _FILEINFO_);
753  }
754 
755  shapeFolder.cd(numberedPrefix);
756 
757  return shapeFolder;
758  }
759 
760 
764  void Project::addShapes(QStringList shapeFiles) {
765  if (m_numShapesCurrentlyReading == 0) {
766  m_shapeReadingMutex->lock();
767  }
768 
769  m_numShapesCurrentlyReading += shapeFiles.count();
770  m_shapeReader->read(shapeFiles);
771  }
772 
773 
774  void Project::addShapes(ShapeList newShapes) {
775  shapesReady(newShapes);
776  }
777 
778 
779  Control *Project::control(QString id) {
780  return (*m_idToControlMap)[id];
781  }
782 
783 
790 
791  connect(bundleSolutionInfo, SIGNAL(destroyed(QObject *)),
792  this, SLOT(bundleSolutionInfoClosed(QObject *)));//???
793  connect(this, SIGNAL(projectRelocated(Project *)),
794  bundleSolutionInfo, SLOT(updateFileName(Project *)));//DNE???
795 
796  // create bundle results folder
797  QString runTime = bundleSolutionInfo->runTime();
798  QDir bundleDir = addBundleSolutionInfoFolder(runTime); //???
799  // save solution information to a file
800  QString bundleFileName = bundleDir.absolutePath() + "/" + "BundleSolutionInfo.hdf";
801 
802  bundleSolutionInfo->bundleSettings()->setOutputFilePrefix(bundleDir.absolutePath() + "/");
803  bundleSolutionInfo->createH5File(FileName(bundleFileName));
804 
805  loadBundleSolutionInfo(bundleSolutionInfo);
806  }
807 
808 
809  void Project::loadBundleSolutionInfo(BundleSolutionInfo *bundleSolutionInfo) {
810  m_bundleSolutionInfo->append(bundleSolutionInfo);
811 
812  (*m_idToBundleSolutionInfoMap)[bundleSolutionInfo->id()] = bundleSolutionInfo;
813 
814  emit bundleSolutionInfoAdded(bundleSolutionInfo);
815  }
816 
817 
825  return m_directory;
826  }
827 
828 
838  void Project::open(QString projectPathStr) {
839 
840  m_isTemporaryProject = false;
841 
842  FileName projectPath(projectPathStr);
843  XmlHandler handler(this);
844 
846  reader.pushContentHandler(&handler);
847  reader.setErrorHandler(&handler);
848 
849  QString projectXmlPath = projectPath.toString() + "/project.xml";
850  QFile file(projectXmlPath);
851  if ( !file.open(QFile::ReadOnly) ) {
853  QString("Unable to open [%1] with read access")
854  .arg(projectXmlPath),
855  _FILEINFO_);
856  }
857 
858  QDir oldProjectRoot(*m_projectRoot);
859  *m_projectRoot = projectPath.expanded();
860 
861  QXmlInputSource xmlInputSource(&file);
862 
863  //This prevents the project from not loading if everything
864  //can't be loaded, and outputs the warnings/errors to the
865  //Warnings Tab
866  try {
867  reader.parse(xmlInputSource);
868  }
869  catch (IException &e) {
870  directory()->showWarning(QString("Failed to open project completely [%1]")
871  .arg(projectPath.original()));
873  }
874  catch (std::exception &e) {
875  directory()->showWarning(QString("Failed to open project completely[%1]")
876  .arg(projectPath.original()));
877  directory()->showWarning(e.what());
878  }
879 
880  QString projectXmlHistoryPath = projectPath.toString() + "/history.xml";
881  QFile historyFile(projectXmlHistoryPath);
882 
883  if ( !historyFile.open(QFile::ReadOnly) ) {
885  QString("Unable to open [%1] with read access")
886  .arg(projectXmlHistoryPath),
887  _FILEINFO_);
888  }
889 
890  reader.pushContentHandler(&handler);
891  QXmlInputSource xmlHistoryInputSource(&historyFile);
892 
893  try {
894  reader.parse(xmlHistoryInputSource);
895  }
896 
897  catch (IException &e) {
898  directory()->showWarning(QString("Failed to read history from project[%1]")
899  .arg(projectPath.original()));
901  }
902  catch (std::exception &e) {
903  directory()->showWarning(QString("Failed to read history from project[%1]")
904  .arg(projectPath.original()));
905  directory()->showWarning(e.what());
906  }
907 
908  QString projectXmlWarningsPath = projectPath.toString() + "/warnings.xml";
909  QFile warningsFile(projectXmlWarningsPath);
910 
911  if (!warningsFile.open(QFile::ReadOnly)) {
913  QString("Unable to open [%1] with read access")
914  .arg(projectXmlWarningsPath),
915  _FILEINFO_);
916  }
917 
918  reader.pushContentHandler(&handler);
919 
920  QXmlInputSource xmlWarningsInputSource(&warningsFile);
921  if (!reader.parse(xmlWarningsInputSource)) {
922  warn(tr("Failed to read warnings from project [%1]").arg(projectPath.original()));
923  }
924 
925  QString directoryXmlPath = projectPath.toString() + "/directory.xml";
926  QFile directoryFile(directoryXmlPath);
927 
928 
929  if (!directoryFile.open(QFile::ReadOnly)) {
931  QString("Unable to open [%1] with read access")
932  .arg(directoryXmlPath),
933  _FILEINFO_);
934  }
935 
936  reader.pushContentHandler(&handler);
937 
938  QXmlInputSource xmlDirectoryInputSource(&directoryFile);
939 
940  try {
941  reader.parse(xmlDirectoryInputSource);
942  }
943  catch (IException &e) {
944  directory()->showWarning(QString("Failed to read GUI state from project[%1]")
945  .arg(projectPath.original()));
947 
948  }
949  catch (std::exception &e) {
950  directory()->showWarning(QString("Failed to read GUI state from project[%1]")
951  .arg(projectPath.original()));
952  directory()->showWarning(e.what());
953  }
954 
955  QDir bundleRoot(bundleSolutionInfoRoot());
956  if (bundleRoot.exists()) {
957  // get QFileInfo for each directory in the bundle root
958  bundleRoot.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); // sym links ok???
959 
960  QFileInfoList bundleDirs = bundleRoot.entryInfoList();
961  for (int dirListIndex = 0; dirListIndex < bundleDirs.size(); dirListIndex++) {
962  // get QFileInfo for each file in this directory
963  QDir bundleSolutionDir(bundleDirs[dirListIndex].absoluteFilePath());
964  bundleSolutionDir.setFilter(QDir::Files | QDir::NoSymLinks); // sym links ok???
965 
966  QFileInfoList bundleSolutionFiles = bundleSolutionDir.entryInfoList();
967  for (int fileListIndex = 0; fileListIndex < bundleSolutionFiles.size(); fileListIndex++) {
968  // if the file is an hdf file with BundleSolutionInfo object, add it to the project tree
969  if (bundleSolutionFiles[fileListIndex].fileName().contains("_BundleSolutionInfo.hdf")) {
970  QString absoluteFileName = bundleSolutionFiles[fileListIndex].absoluteFilePath();
971  FileName solutionFile(bundleSolutionFiles[fileListIndex].absoluteFilePath());
972  loadBundleSolutionInfo(new BundleSolutionInfo(solutionFile));
973  }
974  }
975  }
976  }
977 
978  emit projectLoaded(this);
979  }
980 
981 
982  QProgressBar *Project::progress() {
983  return m_imageReader->progress();
984  }
985 
986 
987  Image *Project::image(QString id) {
988  return (*m_idToImageMap)[id];
989  }
990 
991 
992  ImageList *Project::imageList(QString name) {
993  QListIterator<ImageList *> it(*m_images);
994 
995  ImageList *result = NULL;
996  while (it.hasNext() && !result) {
997  ImageList *list = it.next();
998 
999  if (list->name() == name) result = list;
1000  }
1001 
1002  return result;
1003  }
1004 
1005 
1006  Shape *Project::shape(QString id) {
1007  return (*m_idToShapeMap)[id];
1008  }
1009 
1010 
1011  ShapeList *Project::shapeList(QString name) {
1012  QListIterator<ShapeList *> it(*m_shapes);
1013 
1014  ShapeList *result = NULL;
1015  while (it.hasNext() && !result) {
1016  ShapeList *list = it.next();
1017 
1018  if (list->name() == name) result = list;
1019  }
1020 
1021  return result;
1022  }
1023 
1024 
1025  bool Project::isTemporaryProject() const {
1026  return m_isTemporaryProject;
1027  }
1028 
1029 
1030  WorkOrder *Project::lastNotUndoneWorkOrder() {
1031  WorkOrder *result = NULL;
1032  QListIterator< QPointer<WorkOrder> > it(*m_workOrderHistory);
1033  it.toBack();
1034 
1035  while ( !result && it.hasPrevious() ) {
1036  WorkOrder *workOrder = it.previous();
1037 
1038  if ( !workOrder->isUndone() && !workOrder->isUndoing() ) {
1039  result = workOrder;
1040  }
1041  }
1042 
1043  return result;
1044  }
1045 
1046 
1050  QString Project::name() const {
1051  return m_name;
1052  }
1053 
1054 
1055  const WorkOrder *Project::lastNotUndoneWorkOrder() const {
1056  const WorkOrder *result = NULL;
1057  QListIterator< QPointer<WorkOrder> > it(*m_workOrderHistory);
1058  it.toBack();
1059 
1060  while ( !result && it.hasPrevious() ) {
1061  WorkOrder *workOrder = it.previous();
1062 
1063  if ( !workOrder->isUndone() && !workOrder->isUndoing() ) {
1064  result = workOrder;
1065  }
1066  }
1067 
1068  return result;
1069  }
1070 
1071 
1079  QMutex *Project::mutex() {
1080  return m_mutex;
1081  }
1082 
1083 
1087  QString Project::projectRoot() const {
1088  return m_projectRoot->path();
1089  }
1090 
1091 
1095  void Project::setName(QString newName) {
1096  m_name = newName;
1097  emit nameChanged(m_name);
1098  }
1099 
1100 
1101  QUndoStack *Project::undoStack() {
1102  return &m_undoStack;
1103  }
1104 
1105 
1106  QString Project::nextImageListGroupName() {
1107  int numLists = m_images->size();
1108  QString maxName = "";
1109  QString newGroupName = "Group";
1110 
1111  foreach (ImageList *imageList, *m_images) {
1112  QString name = imageList->name();
1113  if ( !name.contains("Group") ) continue;
1114  if ( maxName.isEmpty() ) {
1115  maxName = name;
1116  }
1117  else if (name > maxName) {
1118  maxName = name;
1119  }
1120  }
1121 
1122  if ( maxName.isEmpty() ) {
1123  newGroupName += QString::number(numLists+1);
1124  }
1125  else {
1126  int maxNum = maxName.remove("Group").toInt();
1127  maxNum++;
1128 
1129  newGroupName += QString::number(maxNum);
1130  }
1131  return newGroupName;
1132 
1133  }
1134 
1135 
1136  void Project::waitForImageReaderFinished() {
1137  QMutexLocker locker(m_imageReadingMutex);
1138  }
1139 
1140 
1141  void Project::waitForShapeReaderFinished() {
1142  QMutexLocker locker(m_shapeReadingMutex);
1143  }
1144 
1145 
1150  QList<WorkOrder *> result;
1151  foreach (WorkOrder *workOrder, *m_workOrderHistory) {
1152  result.append(workOrder);
1153  }
1154 
1155  return result;
1156  }
1157 
1158 
1169  m_activeControl = control;
1170  }
1171 
1172 
1183  return m_activeControl;
1184  }
1185 
1186 
1197  m_activeImageList = imageList;
1198  }
1199 
1200 
1211  return m_activeImageList;
1212  }
1213 
1214 
1220  QString Project::cnetRoot(QString projectRoot) {
1221  return projectRoot + "/cnets";
1222  }
1223 
1224 
1230  QString Project::cnetRoot() const {
1231  return cnetRoot( m_projectRoot->path() );
1232  }
1233 
1234 
1235  QList<ControlList *> Project::controls() {
1236 
1237  return *m_controls;
1238  }
1239 
1240 
1241  ControlList *Project::controlList(QString name) {
1242  QListIterator< ControlList * > it(*m_controls);
1243 
1244  ControlList *result = NULL;
1245  while (it.hasNext() && !result) {
1246  ControlList *list = it.next();
1247 
1248  if (list->name() == name) result = list;
1249  }
1250 
1251  return result;
1252  }
1253 
1254 
1260  QString Project::imageDataRoot(QString projectRoot) {
1261  return projectRoot + "/images";
1262  }
1263 
1264 
1270  QString Project::imageDataRoot() const {
1271  return imageDataRoot( m_projectRoot->path() );
1272  }
1273 
1274 
1280  QString Project::shapeDataRoot(QString projectRoot) {
1281  return projectRoot + "/shapes";
1282  }
1283 
1284 
1290  QString Project::shapeDataRoot() const {
1291  return shapeDataRoot( m_projectRoot->path() );
1292  }
1293 
1294 
1295  QList<ShapeList *> Project::shapes() {
1296  return *m_shapes;
1297  }
1298 
1299 
1300  QList<ImageList *> Project::images() {
1301  return *m_images;
1302  }
1303 
1304 
1310  QString Project::targetBodyRoot(QString projectRoot) {
1311  return projectRoot + "/targets";
1312  }
1313 
1314 
1320  QString Project::targetBodyRoot() const {
1321  return targetBodyRoot( m_projectRoot->path() );
1322  }
1323 
1324 
1325  TargetBodyList Project::targetBodies() {
1326  return *m_targets;
1327  }
1328 
1329 
1335  QString Project::resultsRoot(QString projectRoot) {
1336  return projectRoot + "/results";
1337  }
1338 
1339 
1345  QString Project::resultsRoot() const {
1346  return resultsRoot( m_projectRoot->path() );
1347  }
1348 
1349 
1350  QList<BundleSolutionInfo *> Project::bundleSolutionInfo() {
1351  return *m_bundleSolutionInfo;
1352  }
1353 
1354 
1360  QString Project::bundleSolutionInfoRoot(QString projectRoot) {
1361  return projectRoot + "/results/bundle";
1362  }
1363 
1364 
1371  return bundleSolutionInfoRoot( m_projectRoot->path() );
1372  }
1373 
1374 
1379  foreach (ImageList *imagesInAFolder, *m_images) {
1380  imagesInAFolder->deleteFromDisk(this);
1381  }
1382 
1383  if ( !m_projectRoot->rmdir( imageDataRoot() ) ) {
1384  warn( tr("Did not properly clean up images folder [%1] in project").arg( imageDataRoot() ) );
1385  }
1386 
1387  if ( !m_projectRoot->rmdir( shapeDataRoot() ) ) {
1388  warn( tr("Did not properly clean up shapes folder [%1] in project").
1389  arg( shapeDataRoot() ) );
1390  }
1391 
1392  if ( !m_projectRoot->rmdir( cnetRoot() ) ) {
1393  warn( tr("Did not properly clean up control network folder [%1] in project")
1394  .arg( cnetRoot() ) );
1395  }
1396 
1397  if ( !m_projectRoot->rmdir( resultsRoot() ) ) {
1398  warn( tr("Did not properly clean up results folder [%1] in project")
1399  .arg( resultsRoot() ) );
1400  }
1401 
1402  if ( !m_projectRoot->rmpath( m_projectRoot->path() ) ) {
1403  warn( tr("Did not properly clean up project in [%1]").arg( m_projectRoot->path() ) );
1404  }
1405  }
1406 
1407 
1413  void Project::relocateProjectRoot(QString newProjectRoot) {
1414  *m_projectRoot = newProjectRoot;
1415  emit projectRelocated(this);
1416  }
1417 
1418 
1419  void Project::save() {
1420  if (m_isTemporaryProject) {
1421  QString newDestination = QFileDialog::getSaveFileName(NULL,
1422  QString("Project Location"),
1423  QString("."));
1424 
1425  if ( !newDestination.isEmpty() ) {
1426  save( QFileInfo(newDestination + "/").absolutePath() );
1427 
1428  // delete the temporary project
1430  relocateProjectRoot(newDestination);
1431  m_isTemporaryProject = false;
1432  }
1433  }
1434  else {
1435  save(m_projectRoot->absolutePath(), false);
1436  }
1437  }
1438 
1439 
1440  void Project::save(FileName newPath, bool verifyPathDoesntExist) {
1441  if ( verifyPathDoesntExist && QFile::exists( newPath.toString() ) ) {
1442  throw IException(IException::Io,
1443  QString("Projects may not be saved to an existing path [%1]; "
1444  "please select a new path or delete the current folder")
1445  .arg(newPath.original()),
1446  _FILEINFO_);
1447  }
1448 
1449  QDir dir;
1450  if (!dir.mkpath(newPath.toString())) {
1451  throw IException(IException::Io,
1452  QString("Unable to save project at [%1] "
1453  "because we could not create the folder")
1454  .arg(newPath.original()),
1455  _FILEINFO_);
1456  }
1457 
1458  QFile projectSettingsFile(newPath.toString() + "/project.xml");
1459  if (!projectSettingsFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
1460  throw IException(IException::Io,
1461  QString("Unable to save project at [%1] because the file [%2] "
1462  "could not be opened for writing")
1463  .arg(newPath.original()).arg(projectSettingsFile.fileName()),
1464  _FILEINFO_);
1465  }
1466 
1467  QXmlStreamWriter writer(&projectSettingsFile);
1468  writer.setAutoFormatting(true);
1469 
1470  writer.writeStartDocument();
1471 
1472  // Do amazing, fantastical stuff here!!!
1473  save(writer, newPath);
1474 
1475  writer.writeEndDocument();
1476 
1477  QFile projectHistoryFile(newPath.toString() + "/history.xml");
1478  if (!projectHistoryFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
1479  throw IException(IException::Io,
1480  QString("Unable to save project at [%1] because the file [%2] "
1481  "could not be opened for writing")
1482  .arg(newPath.original()).arg(projectHistoryFile.fileName()),
1483  _FILEINFO_);
1484  }
1485 
1486  QXmlStreamWriter historyWriter(&projectHistoryFile);
1487  historyWriter.setAutoFormatting(true);
1488 
1489  historyWriter.writeStartDocument();
1490  saveHistory(historyWriter);
1491  historyWriter.writeEndDocument();
1492 
1493  QFile projectWarningsFile(newPath.toString() + "/warnings.xml");
1494  if (!projectWarningsFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
1495  throw IException(IException::Io,
1496  QString("Unable to save project at [%1] because the file [%2] could not be "
1497  "opened for writing")
1498  .arg(newPath.original()).arg(projectWarningsFile.fileName()),
1499  _FILEINFO_);
1500  }
1501 
1502  QXmlStreamWriter warningsWriter(&projectWarningsFile);
1503  warningsWriter.setAutoFormatting(true);
1504 
1505  warningsWriter.writeStartDocument();
1506  saveWarnings(warningsWriter);
1507  warningsWriter.writeEndDocument();
1508 
1509  QFile directoryStateFile(newPath.toString() + "/directory.xml");
1510  if (!directoryStateFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
1511  throw IException(IException::Io,
1512  QString("Unable to save project at [%1] because the file [%2] could not be "
1513  "opened for writing")
1514  .arg(newPath.original()).arg(directoryStateFile.fileName()),
1515  _FILEINFO_);
1516  }
1517 
1518  QXmlStreamWriter directoryStateWriter(&directoryStateFile);
1519  directoryStateWriter.setAutoFormatting(true);
1520 
1521  directoryStateWriter.writeStartDocument();
1522  //qDebug()<<"Project::save Before save Directory";
1523  /*
1524  * TODO: Does Project need to know about Directory?
1525  * This is the only place that project uses m_directory. This makes me wonder if it is
1526  * necessary for project to have a Directory member variable.
1527  */
1528  m_directory->save(directoryStateWriter, newPath);
1529  //qDebug()<<"Project::save After save Directory";
1530  directoryStateWriter.writeEndDocument();
1531  }
1532 
1533 
1547  if (workOrder) {
1548  connect(workOrder, SIGNAL(finished(WorkOrder *)),
1549  this, SIGNAL(workOrderFinished(WorkOrder *)));
1550 
1551  workOrder->setPrevious(lastNotUndoneWorkOrder());
1552 
1553  if (workOrder->execute()) {
1554  if (workOrder->previous()) workOrder->previous()->setNext(workOrder);
1555 
1556  m_workOrderHistory->append(workOrder);
1557 
1558  emit workOrderStarting(workOrder);
1559 
1560  // Work orders that create clean states (save, save as) don't belong on the undo stack.
1561  // Instead, we tell the undo stack that we're now clean.
1562  if (workOrder->createsCleanState()) {
1563  m_undoStack.setClean();
1564  }
1565  else {
1566  // All other work orders go onto the undo stack
1567  m_undoStack.push(workOrder); // This calls redo for us
1568  }
1569 
1570  // Clean up deleted work orders (the m_undoStack.push() can delete work orders)
1571  m_workOrderHistory->removeAll(NULL);
1572  }
1573  else {
1574  delete workOrder;
1575  workOrder = NULL;
1576  }
1577  }
1578  }
1579 
1580 
1581  template<typename Data> void Project::warn(QString text, Data relevantData) {
1582  storeWarning(text, relevantData);
1583  directory()->showWarning(text, relevantData);
1584  }
1585 
1586 
1587  void Project::warn(QString text) {
1588  foreach (QString line, text.split("\n")) {
1589  storeWarning(line);
1590  directory()->showWarning(line);
1591  }
1592  }
1593 
1594 
1595  void Project::storeWarning(QString text) {
1596  m_warnings->append(text);
1597  }
1598 
1599 
1600  void Project::imagesReady(ImageList images) {
1601 
1602  m_numImagesCurrentlyReading -= images.count();
1603 
1604  foreach (Image *image, images) {
1605  connect(image, SIGNAL(destroyed(QObject *)),
1606  this, SLOT(imageClosed(QObject *)));
1607  connect(this, SIGNAL(projectRelocated(Project *)),
1608  image, SLOT(updateFileName(Project *)));
1609 
1610  (*m_idToImageMap)[image->id()] = image;
1611  createOrRetrieveImageList(FileName(images[0]->fileName()).dir().dirName())->append(image);
1612  }
1613 
1614  // We really can't have all of the cubes in memory before
1615  // the OS stops letting us open more files.
1616  // Assume cameras are being used in other parts of code since it's
1617  // unknown
1618  QMutexLocker lock(m_mutex);
1619  emit imagesAdded(m_images->last());
1620 
1621  Image *openImage;
1622  foreach (openImage, images) {
1623  openImage->closeCube();
1624  }
1625 
1626 // if(m_projectPvl && m_projectPvl->HasObject("MosaicFileList") )
1627 // m_fileList->fromPvl(m_projectPvl->FindObject("MosaicFileList") );
1628 
1629 // if(m_projectPvl && m_projectPvl->HasObject("MosaicScene") )
1630 // m_scene->fromPvl(m_projectPvl->FindObject("MosaicScene") );
1631 
1632  if (m_numImagesCurrentlyReading == 0) {
1633  m_imageReadingMutex->unlock();
1634  }
1635  }
1636 
1637 
1638  void Project::addTargetsFromImportedImagesToProject(ImageList *imageList) {
1639 
1640  bool found = false;
1641  foreach (Image *image, *imageList) {
1642 
1643  // TODO - I'm a bit worried about being sure the cube is still open at this point (Ken)
1644  // 2016-07-25 TLS The cube is created if it doesn't exist (or isn't open)
1645  Target *target = image->cube()->camera()->target();
1646 
1647  // construct TargetBody QSharedPointer from this images cameras Target
1648  TargetBodyQsp targetBody = TargetBodyQsp(new TargetBody(target));
1649 
1650  foreach (TargetBodyQsp tb, *m_targets) {
1651  if (*tb == *targetBody) {
1652  found = true;
1653  break;
1654  }
1655  }
1656 
1657  // if this TargetBody is not already in the project, add it
1658  // below is how it probably should work, would have to I think
1659  // override the ::contains() method in the TargetBodyList class
1660 // if (!m_targets->contains(targetBody))
1661 // m_targets->append(targetBody);
1662 
1663  if (!found) {
1664  m_targets->append(targetBody);
1665  connect( targetBody.data(), SIGNAL( destroyed(QObject *) ),
1666  this, SLOT( targetBodyClosed(QObject *) ) );
1667 // connect( this, SIGNAL( projectRelocated(Project *) ),
1668 // targetBody.data(), SLOT( updateFileName(Project *) ) );
1669 
1670  (*m_idToTargetBodyMap)[targetBody->id()] = targetBody.data();
1671  }
1672  }
1673 
1674  emit targetsAdded(m_targets);
1675  }
1676 
1677 
1678 
1679  void Project::addCamerasFromImportedImagesToProject(ImageList *imageList) {
1680  bool found = false;
1681  foreach (Image *image, *imageList) {
1682 
1683  // TODO - I'm a bit worried about being sure the cube is still open at this point (Ken)
1684  Camera *camera = image->cube()->camera();
1685 
1686  // construct guiCamera QSharedPointer from this images cameras Target
1687  GuiCameraQsp guiCamera = GuiCameraQsp(new GuiCamera(camera));
1688 
1689  foreach (GuiCameraQsp gc, *m_guiCameras) {
1690  if (*gc == *guiCamera) {
1691  found = true;
1692  break;
1693  }
1694  }
1695 
1696  // if this guiCamera is not already in the project, add it
1697  // below is how it probably should work, would have to I think
1698  // override the ::contains() method in the GuiCameraList class
1699 // if (!m_guiCameras->contains(guiCamera))
1700 // m_guiCameras->append(guiCamera);
1701 
1702  if (!found) {
1703  m_guiCameras->append(guiCamera);
1704 // connect( guiCamera.data(), SIGNAL( destroyed(QObject *) ),
1705 // this, SLOT( guiCameraClosed(QObject *) ) );
1706 // connect( this, SIGNAL( projectRelocated(Project *) ),
1707 // guiCamera.data(), SLOT( updateFileName(Project *) ) );
1708 
1709  (*m_idToGuiCameraMap)[guiCamera->id()] = guiCamera.data();
1710  }
1711  }
1712 
1713  emit guiCamerasAdded(m_guiCameras);
1714  }
1715 
1716 
1717  void Project::removeImages(ImageList &imageList) {
1718  foreach (Image *image, imageList) {
1719  delete image;
1720  }
1721 
1722  // If imageList part of project, remove list
1723 
1724  }
1725 
1726 
1730  void Project::imageClosed(QObject *imageObj) {
1731 // qDebug()<<"Project::imageClosed";
1732  QMutableListIterator<ImageList *> it(*m_images);
1733  while (it.hasNext()) {
1734  ImageList *list = it.next();
1735 
1736  int foundElement = list->indexOf((Image *)imageObj);
1737 
1738  if (foundElement != -1) {
1739  list->removeAt(foundElement);
1740  }
1741  }
1742 
1743  m_idToImageMap->remove(m_idToImageMap->key((Image *)imageObj));
1744  }
1745 
1746 
1750  void Project::imageListDeleted(QObject *imageListObj) {
1751  int indexToRemove = m_images->indexOf(static_cast<ImageList *>(imageListObj));
1752  if (indexToRemove != -1) {
1753  m_images->removeAt(indexToRemove);
1754  }
1755  }
1756 
1757 
1761  void Project::controlClosed(QObject *controlObj) {
1762  QMutableListIterator<ControlList *> it(*m_controls);
1763  while ( it.hasNext() ) {
1764  ControlList *list = it.next();
1765 
1766  int foundElement = list->indexOf( (Control *)controlObj );
1767 
1768  if (foundElement != -1) {
1769  list->removeAt(foundElement);
1770  }
1771  }
1772 
1773  m_idToControlMap->remove(m_idToControlMap->key((Control *)controlObj));
1774  }
1775 
1776 
1780  void Project::controlListDeleted(QObject *controlListObj) {
1781  int indexToRemove = m_controls->indexOf(static_cast<ControlList *>(controlListObj));
1782  if (indexToRemove != -1) {
1783  m_controls->removeAt(indexToRemove);
1784  }
1785  }
1786 
1787 
1791  void Project::shapeListDeleted(QObject *shapeListObj) {
1792  int indexToRemove = m_shapes->indexOf(static_cast<ShapeList *>(shapeListObj));
1793  if (indexToRemove != -1) {
1794  m_shapes->removeAt(indexToRemove);
1795  }
1796  }
1797 
1798 
1802  void Project::bundleSolutionInfoClosed(QObject *bundleSolutionInfoObj) {
1803  QMutableListIterator<BundleSolutionInfo *> it(*m_bundleSolutionInfo);
1804  while (it.hasNext()) {
1805  BundleSolutionInfo *bundleSolutionInfo = it.next();
1806  if (!bundleSolutionInfo) {
1807  // throw error???
1808  }
1809 
1810  int foundElement = m_bundleSolutionInfo->indexOf(
1811  (BundleSolutionInfo *)bundleSolutionInfoObj);
1812 
1813  if (foundElement != -1) {
1814  m_bundleSolutionInfo->removeAt(foundElement);
1815  }
1816  }
1817 
1818  m_idToBundleSolutionInfoMap->remove(
1819  m_idToBundleSolutionInfoMap->key((BundleSolutionInfo * )bundleSolutionInfoObj));
1820  }
1821 
1822 
1828  void Project::targetBodyClosed(QObject *targetBodyObj) {
1829 // QMutableListIterator<TargetBody *> it(*m_targets);
1830 // while ( it.hasNext() ) {
1831 // TargetBody *targetBody = it.next();
1832 // if (!targetBody) {
1833 // // throw error???
1834 // }
1835 
1836 // int foundElement = m_targets->indexOf( (TargetBody *)targetBodyObj );
1837 
1838 // if (foundElement != -1) {
1839 // m_targets->removeAt(foundElement);
1840 // }
1841 // }
1842 
1843 // m_idToTargetBodyMap->remove(m_idToTargetBodyMap->key((TargetBody *)targetBodyObj));
1844  }
1845 
1846 
1847 
1848  void Project::shapesReady(ShapeList shapes) {
1849 
1850  m_numShapesCurrentlyReading -= shapes.count();
1851 
1852  foreach (Shape *shape, shapes) {
1853  connect(shape, SIGNAL(destroyed(QObject *)),
1854  this, SLOT(shapeClosed(QObject *)));
1855  connect(this, SIGNAL(projectRelocated(Project *)),
1856  shape, SLOT(updateFileName(Project *)));
1857 
1858  (*m_idToShapeMap)[shape->id()] = shape;
1859  createOrRetrieveShapeList(
1860  FileName(shapes[0]->fileName()).dir().dirName())->append(shape);
1861  }
1862 
1863  // We really can't have all of the cubes in memory before
1864  // the OS stops letting us open more files.
1865  // Assume cameras are being used in other parts of code since it's
1866  // unknown
1867  QMutexLocker lock(m_shapeMutex);
1868  emit shapesAdded(m_shapes->last());
1869 
1870  Shape *openShape;
1871  foreach (openShape, shapes) {
1872  openShape->closeCube();
1873  }
1874 
1875  if (m_numShapesCurrentlyReading == 0) {
1876  m_shapeReadingMutex->unlock();
1877  }
1878  }
1879 
1880 
1884  void Project::shapeClosed(QObject *imageObj) {
1885  QMutableListIterator<ShapeList *> it(*m_shapes);
1886  while (it.hasNext()) {
1887  ShapeList *list = it.next();
1888 
1889  int foundElement = list->indexOf((Shape *)imageObj);
1890 
1891  if (foundElement != -1) {
1892  list->removeAt(foundElement);
1893  }
1894  }
1895 
1896  m_idToShapeMap->remove(m_idToShapeMap->key((Shape *)imageObj));
1897  }
1898 
1899 
1900  Project::XmlHandler::XmlHandler(Project *project) {
1901  m_project = project;
1902  m_workOrder = NULL;
1903  }
1904 
1905 
1906  bool Project::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
1907  const QString &qName, const QXmlAttributes &atts) {
1908  if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
1909 
1910  if (localName == "project") {
1911  QString name = atts.value("name");
1912 
1913  if (!name.isEmpty()) {
1914  m_project->setName(name);
1915  }
1916  }
1917  else if (localName == "controlNets") {
1918  m_controls.append(new ControlList(m_project, reader()));
1919  }
1920  else if (localName == "imageList") {
1921 // qDebug()<<"Project::XmlHandler::startElement localName = imageList";
1922  m_imageLists.append(new ImageList(m_project, reader()));
1923  }
1924  else if (localName == "shapeLists") {
1925  m_shapeLists.append(new ShapeList(m_project, reader()));
1926  }
1927  else if (localName == "workOrder") {
1928  QString type = atts.value("type");
1929 
1930  m_workOrder = WorkOrderFactory::create(m_project, type);
1931  ASSERT(m_workOrder->metaObject()->className() == type);
1932 
1933  m_workOrder->read(reader());
1934  }
1935  else if (localName == "warning") {
1936  QString warningText = atts.value("text");
1937 
1938  if (!warningText.isEmpty()) {
1939  m_project->warn(warningText);
1940  }
1941  }
1942  else if (localName == "directory") {
1943  m_project->directory()->load(reader());
1944  }
1945  else if (localName == "dockRestore") {
1946 // QVariant geo_data = QVariant(atts.value("geometry"));
1947 // restoreGeometry(geo_data);
1948 // QVariant layout_data = QVariant(atts.value("state"));
1949 // restoreState(layout_data);
1950  }
1951 
1952  else if (localName == "bundleSettings") {
1953  BundleSettings *bundleSettings = m_project->bundleSettings();
1954  if (!bundleSettings) {
1955  // throw error???
1956  }
1957 // bundleSettings = new BundleSettings(m_project, reader());
1958  }
1959  }
1960 
1961  return true;
1962  }
1963 
1964 
1965  bool Project::XmlHandler::endElement(const QString &namespaceURI, const QString &localName,
1966  const QString &qName) {
1967  if (localName == "project") {
1968  foreach (ImageList *imageList, m_imageLists) {
1969  m_project->imagesReady(*imageList);
1970  }
1971  // TODO does this go here under project or should it be under shapes?
1972  foreach (ShapeList *shapeList, m_shapeLists) {
1973  m_project->shapesReady(*shapeList);
1974  }
1975  }
1976  else if (localName == "workOrder") {
1977  m_project->m_workOrderHistory->append(m_workOrder);
1978  m_workOrder = NULL;
1979  }
1980  else if (localName == "controlNets") {
1981  foreach (ControlList *list, m_controls) {
1982  foreach (Control *control, *list) {
1983  m_project->addControl(control);
1984  }
1985  delete list;
1986  }
1987  m_controls.clear();
1988  }
1989  else if (localName == "bundleSettings") {
1990  // TODO: what to do here????
1991  }
1992 
1993  return XmlStackedHandler::endElement(namespaceURI, localName, qName);
1994  }
1995 }
This represents an ISIS control net in a project-based GUI interface.
Definition: Control.h:57
QString name() const
Get the human-readable name of this shape list.
Definition: ShapeList.cpp:569
Internalizes a list of shapes and allows for operations on the entire list.
Definition: ShapeList.h:33
QString targetBodyRoot() const
Accessor for the root directory of the target body data.
Definition: Project.cpp:1320
QDir addImageFolder(QString prefix)
Create and return the name of a folder for placing images.
Definition: Project.cpp:686
Internalizes a list of images and allows for operations on the entire list.
Definition: ImageList.h:44
void controlClosed(QObject *control)
A control is being deleted from the project.
Definition: Project.cpp:1761
The main project for cnetsuite.
Definition: Project.h:105
Container class for TargetBody.
Definition: TargetBody.h:77
QString id() const
Get a unique, identifying string associated with this image.
Definition: Image.cpp:394
void closeCube()
Cleans up the Cube *.
Definition: Shape.cpp:300
static WorkOrder * create(Project *project, QString type)
This instantiates a work order given a project and a type name (class name in a string).
~Project()
Clean up the project.
Definition: Project.cpp:219
QString name() const
Get the project&#39;s GUI name.
Definition: Project.cpp:1050
File name manipulation and expansion.
Definition: FileName.h:111
QList< WorkOrder * > workOrderHistory()
Get the entire list of work orders that have executed.
Definition: Project.cpp:1149
Container class for BundleAdjustment results.
BundleSettingsQsp bundleSettings()
Returns the bundle settings.
Camera * camera()
Return a camera associated with the cube.
Definition: Cube.cpp:1118
void deleteFromDisk(Project *project)
Delete all of the contained Images from disk.
Definition: ImageList.cpp:742
QMutex * mutex()
Return mutex used for Naif calls.
Definition: Project.cpp:1079
QString bundleSolutionInfoRoot() const
Accessor for the root directory of the results data.
Definition: Project.cpp:1370
Maintains a list of Controls so that control nets can easily be copied from one Project to another...
Definition: ControlList.h:34
void setName(QString newName)
Set the human-readable name of this control list.
void controlListDeleted(QObject *controlList)
An control list is being deleted from the project.
Definition: Project.cpp:1780
QString name() const
Get the human-readable name of this image list.
Definition: ImageList.cpp:719
void open(QString)
Open the project at the given path.
Definition: Project.cpp:838
QString id() const
Get a unique, identifying string associated with this BundleSolutionInfo object.
void saveHistory(QXmlStreamWriter &stream) const
Serialize the work orders into the given XML.
Definition: Project.cpp:518
void showWarning(QString text)
Displays a Warning.
Definition: Directory.cpp:1071
bool createsCleanState() const
Returns the CleanState status (whether the Project has been saved to disk or not).
Definition: WorkOrder.cpp:721
WorkOrder * previous() const
Gets the previous WorkOrder.
Definition: WorkOrder.cpp:803
void setPath(QString newPath)
Set the relative path (from the project root) to this shape list&#39;s folder.
Definition: ShapeList.cpp:559
void addControl(Control *control)
Add the given Control&#39;s to the current project.
Definition: Project.cpp:646
void controlListAdded(ControlList *controls)
apparently not used?
void targetBodyClosed(QObject *targetBodyObj)
A target body is being deleted from the project.
Definition: Project.cpp:1828
static QString userName()
the user name.
QString runTime() const
Returns the run time.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
List for holding TargetBodies.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
QString id() const
Access the unique ID associated with this Control.
Definition: Control.cpp:181
void removeAt(int i)
Removes the image at an index.
Definition: ImageList.cpp:318
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:154
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:163
Container class for GuiCamera.
Definition: GuiCamera.h:70
Control * activeControl()
Return the Active Control (control network)
Definition: Project.cpp:1182
QString cnetRoot() const
Get where control networks ought to be stored inside the project.
Definition: Project.cpp:1230
void projectLoaded(Project *)
Emitted when project loaded receivers: CNetSuiteMainWindow, Directory, HistoryTreeWidget.
QString resultsRoot() const
Accessor for the root directory of the results data.
Definition: Project.cpp:1345
void setName(QString newName)
Set the human-readable name of this shape list.
Definition: ShapeList.cpp:548
void createFolders()
This creates the project root, image root, and control net root directories.
Definition: Project.cpp:335
void relocateProjectRoot(QString newRoot)
This is called when the project is moved.
Definition: Project.cpp:1413
void addBundleSolutionInfo(BundleSolutionInfo *bundleSolutionInfo)
Add the given BundleSolutionInfo to the current project.
Definition: Project.cpp:789
void saveWarnings(QXmlStreamWriter &stream) const
Serialize the warnings into the given XML.
Definition: Project.cpp:541
Target * target() const
Returns a pointer to the target object.
Definition: Spice.cpp:1277
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
Definition: Project.cpp:1290
void addToProject(WorkOrder *)
Run the work order and stores it in the project.
Definition: Project.cpp:1546
void imageClosed(QObject *image)
An image is being deleted from the project.
Definition: Project.cpp:1730
Parent class for anything that performs an action in Project.
Definition: WorkOrder.h:104
void removeAt(int i)
Removes the shape at an index.
Definition: ShapeList.cpp:315
void bundleSolutionInfoAdded(BundleSolutionInfo *bundleSolutionInfo)
Emitted when new BundleSolutionInfo available from jigsaw receivers: ProjectTreeWidget (TODO: should ...
void createH5File(FileName outputFileName) const
Creates a new file using H5F_ACC_EXCL.
void shapeListDeleted(QObject *shapeList)
A shape model list is being deleted from the project.
Definition: Project.cpp:1791
void shapeClosed(QObject *shape)
A shape model is being deleted from the project.
Definition: Project.cpp:1884
QSharedPointer< TargetBody > TargetBodyQsp
Defines A smart pointer to a TargetBody obj.
Definition: TargetBody.h:224
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
void append(Shape *const &value)
Appends an shape to the shape list.
Definition: ShapeList.cpp:147
void append(TargetBodyQsp const &value)
Appends a TargetBody to the list.
void deleteAllProjectFiles()
Delete all of the files, that this project stores, from disk.
Definition: Project.cpp:1378
QString name() const
Get the human-readable name of this control list.
Container class for BundleAdjustment settings.
void guiCamerasAdded(GuiCameraList *targets)
Emitted when new GuiCamera objects added to project receivers: Directory.
void setPrevious(WorkOrder *previousWorkOrder)
Sets the previous WorkOrder in the sequence.
Definition: WorkOrder.cpp:556
ImageList * activeImageList()
Returns the active ImageList.
Definition: Project.cpp:1210
void controlAdded(Control *control)
Emitted when new Control added to Project receivers: ProjectTreeWidget.
This represents a cube in a project-based GUI interface.
Definition: Image.h:91
QString id() const
Get a unique, identifying string associated with this shape.
Definition: Shape.cpp:417
void setPath(QString newPath)
Set the relative path (from the project root) to this image list&#39;s folder.
Definition: ImageList.cpp:709
QDir addBundleSolutionInfoFolder(QString folder)
Create and return the name of a folder for placing BundleSolutionInfo.
Definition: Project.cpp:594
void projectRelocated(Project *)
Emitted when project location moved receivers: Control, BundleSolutionInfo, Image, TargetBody.
Directory * directory() const
Returns the directory associated with this Project.
Definition: Project.cpp:824
QString fileName() const
Access the name of the control network file associated with this Control.
Definition: Control.cpp:171
void imageListDeleted(QObject *imageList)
An image list is being deleted from the project.
Definition: Project.cpp:1750
void addShapes(QStringList shapeFiles)
Read the given shape model cube file names as Images and add them to the project. ...
Definition: Project.cpp:764
void append(Image *const &value)
Appends an image to the image list.
Definition: ImageList.cpp:150
QList< QAction * > userPreferenceActions()
Get a list of configuration/settings actions related to reading images into this Project.
Definition: Project.cpp:583
void shapesAdded(ShapeList *shapes)
Emitted when new shape model images are available.
void addImages(QStringList imageFiles)
Read the given cube file names as Images and add them to the project.
Definition: Project.cpp:714
This class is used to create and store valid Isis3 targets.
Definition: Target.h:63
bool modifiesDiskState() const
Returns the modified disk state.
Definition: WorkOrder.cpp:785
QDir addShapeFolder(QString prefix)
Create and return the name of a folder for placing shape models.
Definition: Project.cpp:736
List of GuiCameras saved as QSharedPointers.
Definition: GuiCameraList.h:35
void nameChanged(QString newName)
Emitted when project name is changed receivers: ProjectTreeWidget.
void imagesAdded(ImageList *images)
Emitted when new images are available.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
QSharedPointer< GuiCamera > GuiCameraQsp
GuiCameraQsp Represents a smart pointer to a GuiCamera object.
Definition: GuiCamera.h:188
void setName(QString newName)
Change the project&#39;s name (GUI only, doesn&#39;t affect location on disk).
Definition: Project.cpp:1095
Every display property for footprint views, provided for convenience.
This represents a shape in a project-based GUI interface.
Definition: Shape.h:70
bool isUndone() const
Returns the WorkOrder undo status.
Definition: WorkOrder.cpp:775
void bundleSolutionInfoClosed(QObject *bundleSolutionInfo)
A BundleSolutionInfo object is being deleted from the project.
Definition: Project.cpp:1802
QString toString() const
Returns a string representation of this exception.
Definition: IException.cpp:553
QMap< QString, Control * > * m_idToControlMap
This variable will probably go away when we add the bundle results object because it will be under: B...
Definition: Project.h:349
void append(GuiCameraQsp const &value)
Appends a single GuiCamera to the list.
Isis exception class.
Definition: IException.h:99
bool isUndoing() const
Returns the WorkOrderUndoing state.
Definition: WorkOrder.cpp:766
Cube * cube()
Get the Cube pointer associated with this display property.
Definition: Image.cpp:254
void setNext(WorkOrder *nextWorkOrder)
Sets the next WorkOrder in the sequence.
Definition: WorkOrder.cpp:547
void setPath(QString newPath)
Set the relative path (from the project root) to this control list&#39;s folder.
void save(QXmlStreamWriter &stream) const
: Saves a WorkOrder to a data stream.
Definition: WorkOrder.cpp:478
void targetsAdded(TargetBodyList *targets)
Emitted when new TargetBody objects added to project receivers: Directory.
void removeAt(int i)
Removes the control pointer at the specified index.
virtual bool execute()
The (child) implementation of this method should prompt the user/gather state by any means necessary...
Definition: WorkOrder.cpp:1078
void setName(QString newName)
Set the human-readable name of this image list.
Definition: ImageList.cpp:698
his enables stack-based XML parsing of XML files.
QString projectRoot() const
Get the top-level folder of the project.
Definition: Project.cpp:1087
QDir addCnetFolder(QString prefix)
Create and return the name of a folder for placing control networks.
Definition: Project.cpp:614
void setActiveImageList(ImageList *)
Set the Active ImageList.
Definition: Project.cpp:1196
void closeCube()
Cleans up the Cube pointer.
Definition: Image.cpp:272
void setActiveControl(Control *)
Set the Active Control (control network)
Definition: Project.cpp:1168
QString imageDataRoot() const
Accessor for the root directory of the image data.
Definition: Project.cpp:1270
IO Handler for Isis Cubes.
Definition: Cube.h:158
Project(Directory &directory, QObject *parent=0)
Create a new Project.
Definition: Project.cpp:73

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:26:42