Isis 3 Programmer Reference
Project.cpp
Go to the documentation of this file.
1 
23 #include "IsisDebug.h"
24 #include "Project.h"
25 
26 #include <unistd.h>
27 
28 #include <QApplication>
29 #include <QDateTime>
30 #include <QDir>
31 #include <QDebug>
32 #include <QFile>
33 #include <QFileDialog>
34 #include <QFuture>
35 #include <QFutureWatcher>
36 #include <QMessageBox>
37 #include <QMutex>
38 #include <QMutexLocker>
39 #include <QProgressBar>
40 #include <QRegExp>
41 #include <QSettings>
42 #include <QStringList>
43 #include <QtDebug>
44 #include <QTextStream>
45 #include <QWidget>
46 #include <QXmlStreamWriter>
47 
48 #include "BundleSettings.h"
49 #include "BundleSolutionInfo.h"
50 #include "Camera.h"
51 #include "Control.h"
52 #include "ControlList.h"
53 #include "ControlNet.h"
54 #include "CorrelationMatrix.h"
55 #include "Cube.h"
56 #include "Directory.h"
57 #include "Environment.h"
58 #include "FileName.h"
59 #include "GuiCamera.h"
60 #include "GuiCameraList.h"
61 #include "ImageList.h"
62 #include "ImageReader.h"
63 #include "IException.h"
64 #include "ProgressBar.h"
65 #include "ProjectItem.h"
66 #include "ProjectItemModel.h"
67 #include "SerialNumberList.h"
70 #include "Shape.h"
71 #include "ShapeList.h"
72 #include "ShapeReader.h"
73 #include "Target.h"
74 #include "TargetBodyList.h"
75 #include "Template.h"
76 #include "TemplateList.h"
77 #include "WorkOrder.h"
78 #include "WorkOrderFactory.h"
79 #include "XmlStackedHandlerReader.h"
80 
81 namespace Isis {
82 
83 
84 
88  Project::Project(Directory &directory, QObject *parent) :
89  QObject(parent) {
90  m_bundleSettings = NULL;
91  m_clearing = false;
92  m_directory = &directory;
93  m_projectRoot = NULL;
94  m_cnetRoot = NULL;
95  m_idToControlMap = NULL;
96  m_idToImageMap = NULL;
97  m_idToShapeMap = NULL;
98  m_idToTargetBodyMap = NULL;
99  m_idToGuiCameraMap = NULL;
100  m_images = NULL;
101  m_imageReader = NULL;
102  m_shapeReader = NULL;
103  m_shapes = NULL;
104  m_mapTemplates = NULL;
105  m_regTemplates = NULL;
106  m_warnings = NULL;
107  m_workOrderHistory = NULL;
108  m_isTemporaryProject = true;
109  m_isOpen = false;
110  m_isClean = true;
111  m_activeControl = NULL;
112  m_activeImageList = NULL;
113 
115 
116  m_mutex = NULL;
117  m_workOrderMutex = NULL;
118  m_imageReadingMutex = NULL;
119 
120  m_numShapesCurrentlyReading = 0;
121  m_shapeMutex = NULL;
122  m_shapeReadingMutex = NULL;
123 
125  m_idToImageMap = new QMap<QString, Image *>;
126  m_idToShapeMap = new QMap<QString, Shape *>;
127  m_idToTargetBodyMap = new QMap<QString, TargetBody *>;
128  m_idToGuiCameraMap = new QMap<QString, GuiCamera *>;
129  m_idToBundleSolutionInfoMap = new QMap<QString, BundleSolutionInfo *>;
130 
131  m_name = "Project";
132 
133  // Look for old projects
134  QDir tempDir = QDir::temp();
135  QStringList nameFilters;
136  nameFilters.append(Environment::userName() + "_" +
137  QApplication::applicationName() + "_*");
138  tempDir.setNameFilters(nameFilters);
139 
140  QStringList existingProjects = tempDir.entryList();
141  bool crashedPreviously = false;
142 
143  foreach (QString existingProject, existingProjects) {
144  FileName existingProjectFileName(tempDir.absolutePath() + "/" + existingProject);
145  QString pidString = QString(existingProject).replace(QRegExp(".*_"), "");
146  int otherPid = pidString.toInt();
147 
148  if (otherPid != 0) {
149  if ( !QFile::exists("/proc/" + pidString) ) {
150  crashedPreviously = true;
151  int status = system( ("rm -rf '" +
152  existingProjectFileName.expanded() + "' &").toLatin1().data() );
153  if (status != 0) {
154  QString msg = "Executing command [rm -rf" + existingProjectFileName.expanded() +
155  "' &] failed with return status [" + toString(status) + "]";
157  }
158  }
159  }
160  }
161 
162  if (crashedPreviously && false) {
163  QMessageBox::information( NULL,
164  QObject::tr("Crashed"),
165  QObject::tr("It appears %1 crashed. We're sorry.").
166  arg( QApplication::applicationName() ) );
167  }
168 
169  QCoreApplication* ipce_app = static_cast<QCoreApplication *>(directory.parent());
170 
171  try {
172  QString tmpFolder = QDir::temp().absolutePath() + "/"
173  + Environment::userName() + "_"
174  + QApplication::applicationName() + "_" + QString::number( getpid() );
175  QDir temp(tmpFolder + "/tmpProject");
176  m_projectRoot = new QDir(temp);
177 
178  if (ipce_app->arguments().count() == 1) {
179  createFolders();
180  }
181  }
182  catch (IException &e) {
183  throw IException(e, IException::Programmer, "Error creating project folders.", _FILEINFO_);
184  }
185  catch (std::exception &e) {
186  // e.what()
188  tr("Error creating project folders [%1]").arg( e.what() ), _FILEINFO_);
189  }
190  // TODO TLS 2016-07-13 This seems to only be used by ControlNet when SetTarget is called.
191  // This needs to be better documented, possibly renamed or redesigned??
192  m_mutex = new QMutex;
193  m_workOrderMutex = new QMutex;
194  // image reader
195  m_imageReader = new ImageReader(m_mutex, true);
196 
197  connect( m_imageReader, SIGNAL( imagesReady(ImageList) ),
198  this, SLOT( imagesReady(ImageList) ) );
199 
200  // Project will be listening for when both cnets and images have been added.
201  // It will emit a signal, controlsAndImagesAvailable, when this occurs.
202  // Directory sets up a listener on the JigsawWorkOrder clone to enable itself
203  // when it hears this signal.
204  connect(this, SIGNAL(imagesAdded(ImageList *)),
205  this, SLOT(checkControlsAndImagesAvailable()));
206  connect(this, SIGNAL(controlListAdded(ControlList *)),
207  this, SLOT(checkControlsAndImagesAvailable()));
208  connect(m_directory, SIGNAL(cleanProject(bool)),
209  this, SLOT(setClean(bool)));
210 
211  m_images = new QList<ImageList *>;
212 
213  // Shape reader
214  m_shapeMutex = new QMutex;
215 
216  m_shapeReader = new ShapeReader(m_shapeMutex, false);
217 
218  connect( m_shapeReader, SIGNAL( shapesReady(ShapeList) ),
219  this, SLOT( shapesReady(ShapeList) ) );
220 
221  m_shapes = new QList<ShapeList *>;
222 
223  m_controls = new QList<ControlList *>;
224 
225  m_targets = new TargetBodyList;
226 
227  m_mapTemplates = new QList<TemplateList *>;
228 
229  m_regTemplates = new QList<TemplateList *>;
230 
231  m_guiCameras = new GuiCameraList;
232 
233  m_bundleSolutionInfo = new QList<BundleSolutionInfo *>;
234 
235  m_warnings = new QStringList;
236  m_workOrderHistory = new QList< QPointer<WorkOrder> >;
237 
238  m_imageReadingMutex = new QMutex;
239 
240  m_shapeReadingMutex = new QMutex;
241 
242  // Listen for when an active control is set and when an active image list is set.
243  // This is used for enabling the JigsawWorkOrder (the Bundle Adjustment menu action).
244 // connect(this, &Project::activeControlSet,
245 // this, &Project::checkActiveControlAndImageList);
246 // connect(this, &Project::activeImageListSet,
247 // this, &Project::checkActiveControlAndImageList);
248  // TODO: ken testing
249 // m_bundleSettings = NULL;
250 // m_bundleSettings = new BundleSettings();
251  }
252 
253 
258 
259 
260  if (m_images) {
261  foreach (ImageList *imageList, *m_images) {
262  foreach (Image *image, *imageList) {
263  delete image;
264  }
265 
266  delete imageList;
267  }
268 
269  delete m_images;
270  m_images = NULL;
271  }
272 
273 
274  if (m_shapes) {
275  foreach (ShapeList *shapeList, *m_shapes) {
276  foreach (Shape *shape, *shapeList) {
277  delete shape;
278  }
279 
280  delete shapeList;
281  }
282 
283  delete m_shapes;
284  m_shapes = NULL;
285  }
286 
287 
288  if (m_controls) {
289  foreach (ControlList *controlList, *m_controls) {
290  foreach (Control *control, *controlList) {
291  delete control;
292  }
293 
294  delete controlList;
295  }
296  delete m_controls;
297  m_controls = NULL;
298  }
299 
300 
301  if (m_mapTemplates) {
302  foreach (TemplateList *templateList, *m_mapTemplates) {
303  foreach (Template *templateFile, *templateList) {
304  delete templateFile;
305  }
306 
307  delete templateList;
308  }
309 
310  delete m_mapTemplates;
311  m_mapTemplates = NULL;
312  }
313 
314 
315  if (m_regTemplates) {
316  foreach (TemplateList *templateList, *m_regTemplates) {
317  foreach (Template *templateFile, *templateList) {
318  delete templateFile;
319  }
320 
321  delete templateList;
322  }
323 
324  delete m_regTemplates;
325  m_regTemplates = NULL;
326  }
327 
328 
329  m_activeControl = NULL;
330  m_activeImageList = NULL;
331 
332  if (m_bundleSolutionInfo) {
333  foreach (BundleSolutionInfo *bundleSolutionInfo, *m_bundleSolutionInfo) {
334  delete bundleSolutionInfo;
335  }
336 
337  delete m_bundleSolutionInfo;
338  m_bundleSolutionInfo = NULL;
339  }
340 
341  delete m_idToControlMap;
342  m_idToControlMap = NULL;
343 
344  delete m_idToImageMap;
345  m_idToImageMap = NULL;
346 
347  delete m_idToShapeMap;
348  m_idToShapeMap = NULL;
349 
350  delete m_idToTargetBodyMap;
351  m_idToTargetBodyMap = NULL;
352 
353  delete m_idToGuiCameraMap;
354  m_idToGuiCameraMap = NULL;
355 
356  delete m_idToBundleSolutionInfoMap;
357  m_idToBundleSolutionInfoMap = NULL;
358 
359  m_directory = NULL;
360 
361  delete m_projectRoot;
362  m_projectRoot = NULL;
363 
364  delete m_cnetRoot;
365  m_cnetRoot = NULL;
366 
367  delete m_imageReader;
368  delete m_shapeReader;
369 
370  delete m_warnings;
371  m_warnings = NULL;
372 
373  m_workOrderHistory->removeAll(NULL);
374  m_workOrderHistory = NULL;
375 
376  delete m_bundleSettings;
377  m_bundleSettings = NULL;
378  }
379 
380 
385  QDir dir;
386  if ( !dir.mkpath( m_projectRoot->path() ) ) {
387  warn("Cannot create project directory.");
389  tr("Unable to create folder [%1] when trying to initialize project")
390  .arg(m_projectRoot->path() ),
391  _FILEINFO_);
392  }
393 
394  try {
395  if ( !dir.mkdir( cnetRoot() ) ) {
396  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
397  .arg( cnetRoot() );
398  warn(msg);
399  throw IException(IException::Io, msg, _FILEINFO_);
400  }
401 
402  if ( !dir.mkdir( imageDataRoot() ) ) {
403  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
404  .arg( imageDataRoot() );
405  warn(msg);
406  throw IException(IException::Io, msg, _FILEINFO_);
407  }
408 
409  if ( !dir.mkdir( shapeDataRoot() ) ) {
410  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
411  .arg( shapeDataRoot() );
412  warn(msg);
413  throw IException(IException::Io, msg, _FILEINFO_);
414  }
415 
416  if ( !dir.mkdir( resultsRoot() ) ) {
417  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
418  .arg( resultsRoot() );
419  warn(msg);
420  throw IException(IException::Io, msg, _FILEINFO_);
421  }
422  if ( !dir.mkdir( bundleSolutionInfoRoot() ) ) {
423  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
424  .arg( bundleSolutionInfoRoot() );
425  warn(msg);
426  throw IException(IException::Io, msg, _FILEINFO_);
427  }
428  if ( !dir.mkdir( templateRoot() ) ) {
429  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
430  .arg( templateRoot() );
431  warn(msg);
432  throw IException(IException::Io, msg, _FILEINFO_);
433  }
434  if ( !dir.mkdir( templateRoot() + "/maps" ) ) {
435  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
436  .arg( templateRoot() + "/maps" );
437  warn(msg);
438  throw IException(IException::Io, msg, _FILEINFO_);
439  }
440  if ( !dir.mkdir( templateRoot() + "/registrations" ) ) {
441  QString msg = QString("Unable to create folder [%1] when trying to initialize project")
442  .arg( templateRoot() + "/registrations" );
443  warn(msg);
444  throw IException(IException::Io, msg, _FILEINFO_);
445  }
446  }
447  catch (...) {
448  warn("Failed to create project directory structure");
449  throw;
450  }
451  }
452 
453 
459  void Project::clear() {
460  m_clearing = true;
461 
462  // We need to look through the project.xml and remove every directory not in the project
463  QStringList shapeDirList;
464  bool shapes = false;
465  QStringList imageDirList;
466  bool images = false;
467  QStringList cnetDirList;
468  bool controls = false;
469  QStringList mapTemplateDirList;
470  bool mapTemplates = false;
471  QStringList regTemplateDirList;
472  bool regTemplates = false;
473  QStringList bundleDirList;
474  bool bundles = false;
475  QFile projectXml(projectRoot() + "/project.xml");
476 
477  if (projectXml.open(QIODevice::ReadOnly)) {
478  QTextStream projectXmlInput(&projectXml);
479 
480  while (!projectXmlInput.atEnd() ) {
481 
482  QString line = projectXmlInput.readLine();
483 
484  if (controls || line.contains("<controlNets>") ) {
485  controls = true;
486 
487  if (line.contains("</controlNets>") ) {
488  controls = false;
489  }
490 
491  else if (!line.contains("<controlNets>") ) {
492  cnetDirList.append(line.split('"').at(3));
493  }
494  }
495 
496  else if (images || line.contains("<imageLists>") ) {
497  images = true;
498 
499  if (line.contains("</imageLists>")) {
500  images = false;
501  }
502 
503  else if (!line.contains("<imageLists>") ) {
504  imageDirList.append(line.split('"').at(3).simplified());
505  }
506  }
507 
508  else if (shapes || line.contains("<shapeLists>")) {
509  shapes = true;
510 
511  if (line.contains("</shapeLists>") ) {
512  shapes = false;
513  }
514 
515  else if (!line.contains("<shapeLists>") ) {
516  shapeDirList.append(line.split('"').at(3));
517  }
518  }
519 
520  else if (mapTemplates || line.contains("<mapTemplateLists>") ) {
521  mapTemplates = true;
522 
523  if (line.contains("</mapTemplateLists>") ) {
524  mapTemplates = false;
525  }
526 
527  else if (!line.contains("<mapTemplateLists>") ) {
528  QList<QString> components = line.split('"');
529  mapTemplateDirList.append(components.at(5));
530  }
531  }
532 
533  else if (regTemplates || line.contains("<regTemplateLists>") ) {
534  regTemplates = true;
535 
536  if (line.contains("</regTemplateLists>") ) {
537  regTemplates = false;
538  }
539 
540  else if (!line.contains("<regTemplateLists>") ) {
541  QList<QString> components = line.split('"');
542  regTemplateDirList.append(components.at(5));
543  }
544  }
545 
546  else if (bundles || line.contains("<bundleSolutionInfo>") ) {
547  bundles = true;
548 
549  if (line.contains("</bundleSolutionInfo>") ) {
550  bundles = false;
551  }
552 
553  else if (line.contains("<runTime>") ) {
554  bundleDirList.append(line.split('>').at(1).split('<').at(0));
555  }
556  }
557  }
558 
559  QDir cnetsDir(m_projectRoot->path() + "/cnets/");
560  cnetsDir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
561  QStringList cnetsList = cnetsDir.entryList();
562  foreach (QString dir, cnetsList) {
563  dir = dir.simplified();
564 
565  if ( !cnetDirList.contains(dir) ) {
566  QDir tempDir(cnetsDir.path() + "/" + dir);
567  tempDir.removeRecursively();
568  }
569  }
570 
571  QDir imagesDir(m_projectRoot->path() + "/images/");
572  imagesDir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
573  QStringList imagesList = imagesDir.entryList();
574  foreach (QString dir, imagesList) {
575  dir = dir.simplified();
576 
577  if ( !imageDirList.contains(dir) ) {
578  QDir tempDir(imagesDir.path() + "/" + dir);
579  tempDir.removeRecursively();
580  }
581  }
582 
583  QDir shapesDir(m_projectRoot->path() + "/shapes/");
584  shapesDir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
585  QStringList shapesList = shapesDir.entryList();
586  foreach (QString dir, shapesList) {
587  dir = dir.simplified();
588 
589  if ( !shapeDirList.contains(dir) ) {
590  QDir tempDir(shapesDir.path() + "/" + dir);
591  tempDir.removeRecursively();
592  }
593  }
594 
595  QDir mapTemplatesDir(m_projectRoot->path() + "/templates/maps");
596  mapTemplatesDir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
597  QStringList mapTemplatesList = mapTemplatesDir.entryList();
598  foreach (QString dir, mapTemplatesList) {
599  dir = dir.simplified();
600 
601  if ( !mapTemplateDirList.contains("maps/" + dir) ) {
602  QDir tempDir(mapTemplatesDir.path() + "/" + dir);
603  tempDir.removeRecursively();
604  }
605  }
606 
607  QDir regTemplatesDir(m_projectRoot->path() + "/templates/registrations");
608  regTemplatesDir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
609  QStringList regTemplatesList = regTemplatesDir.entryList();
610  foreach (QString dir, regTemplatesList) {
611  dir = dir.simplified();
612 
613  if ( !regTemplateDirList.contains("registrations/" + dir)) {
614  QDir tempDir(regTemplatesDir.path() + "/" + dir);
615  tempDir.removeRecursively();
616  }
617  }
618 
619  QDir bundlesDir(m_projectRoot->path() + "/results/bundle/");
620  bundlesDir.setFilter(QDir::NoDotAndDotDot | QDir::Dirs);
621  QStringList bundleList = bundlesDir.entryList();
622  foreach (QString dir, bundleList) {
623  dir = dir.simplified();
624 
625  if ( !bundleDirList.contains(dir) ) {
626  QDir tempDir(bundlesDir.path() + "/" + dir);
627  tempDir.removeRecursively();
628  }
629  }
630 
631  projectXml.close();
632  }
633 
634  try {
635  QString tmpFolder = QDir::temp().absolutePath() + "/"
636  + Environment::userName() + "_"
637  + QApplication::applicationName() + "_" + QString::number( getpid() );
638  QDir temp(tmpFolder + "/tmpProject");
639  m_projectRoot = new QDir(temp);
640  }
641 
642  catch (IException &e) {
643  throw IException(e, IException::Programmer, "Error creating project folders.", _FILEINFO_);
644  }
645 
646  catch (std::exception &e) {
648  tr("Error creating project folders [%1]").arg( e.what() ), _FILEINFO_);
649  }
650 
651  m_images->clear();
652  m_shapes->clear();
653  m_controls->clear();
654  m_mapTemplates->clear();
655  m_regTemplates->clear();
656  m_targets->clear();
657  m_guiCameras->clear();
658  m_bundleSolutionInfo->clear();
659  m_workOrderHistory->clear();
660 
661  directory()->clean();
662  setClean(true);
663  }
664 
665 
666  bool Project::clearing() {
667  return m_clearing;
668  }
669 
670 
671  ImageList *Project::createOrRetrieveImageList(QString name, QString path) {
672  ImageList *result = imageList(name);
673  if (!result) {
674  result = new ImageList;
675 
676  result->setName(name);
677  if (path == "") {
678  result->setPath(name);
679  }
680  else {
681  result->setPath(path);
682  }
683 
684  connect( result, SIGNAL( destroyed(QObject *) ),
685  this, SLOT( imageListDeleted(QObject *) ) );
686  m_images->append(result);
687  }
688  return result;
689  }
690 
691 
692  ShapeList *Project::createOrRetrieveShapeList(QString name, QString path) {
693  ShapeList *result = shapeList(name);
694  if (!result) {
695  result = new ShapeList;
696 
697  result->setName(name);
698  if (path == "") {
699  result->setPath(name);
700  }
701  else {
702  result->setPath(path);
703  }
704 
705  connect( result, SIGNAL( destroyed(QObject *) ),
706  this, SLOT( shapeListDeleted(QObject *) ) );
707  m_shapes->append(result);
708  }
709  return result;
710  }
711 
712 
726  void Project::save(QXmlStreamWriter &stream, FileName newProjectRoot) const {
727  stream.writeStartElement("project");
728 
729  stream.writeAttribute("name", m_name);
730 
731  if ( !m_controls->isEmpty() ) {
732  stream.writeStartElement("controlNets");
733 
734  for (int i = 0; i < m_controls->count(); i++) {
735  m_controls->at(i)->save(stream, this, newProjectRoot);
736  }
737 
738  stream.writeEndElement();
739  }
740 
741  if ( !m_images->isEmpty() ) {
742  stream.writeStartElement("imageLists");
743  for (int i = 0; i < m_images->count(); i++) {
744  m_images->at(i)->save(stream, this, newProjectRoot);
745  }
746 
747  stream.writeEndElement();
748  }
749 
750  if ( !m_shapes->isEmpty() ) {
751  stream.writeStartElement("shapeLists");
752 
753  for (int i = 0; i < m_shapes->count(); i++) {
754  m_shapes->at(i)->save(stream, this, newProjectRoot);
755  }
756 
757  stream.writeEndElement();
758  }
759 
760  if ( !m_mapTemplates->isEmpty() ) {
761  stream.writeStartElement("mapTemplateLists");
762 
763  for (int i = 0; i < m_mapTemplates->count(); i++) {
764  m_mapTemplates->at(i)->save(stream, this, newProjectRoot);
765  }
766 
767  stream.writeEndElement();
768  }
769 
770  if ( !m_regTemplates->isEmpty() ) {
771  stream.writeStartElement("regTemplateLists");
772 
773  for (int i = 0; i < m_regTemplates->count(); i++) {
774  m_regTemplates->at(i)->save(stream, this, newProjectRoot);
775  }
776 
777  stream.writeEndElement();
778  }
779 
780  // TODO: Finish implementing serialization of TargetBody & GuiCameras
781 // if (!m_targets->isEmpty()) {
782 // stream.writeStartElement("targets");
783 //
784 // for (int i = 0; i < m_targets->count(); i++) {
785 // m_targets->at(i)->save(stream, this, newProjectRoot);
786 // }
787 //
788 // stream.writeEndElement();
789 // }
790 //
791 // if (!m_guiCameras->isEmpty()) {
792 // stream.writeStartElement("cameras");
793 //
794 // for (int i = 0; i < m_guiCameras->count(); i++) {
795 // m_guiCameras->at(i)->save(stream, this, newProjectRoot);
796 // }
797 //
798 // stream.writeEndElement();
799 // }
800 
801 // Write general look of gui, including docked widges
802 // QVariant geo_data = saveGeometry();
803 // QVariant layout_data = saveState();
804 //
805 // stream.writeStartElement("dockRestore");
806 // stream.writeAttribute("geometry", geo_data.toString());
807 // stream.writeAttribute("state", layout_data.toString());
808 
809 
810  if ( !m_bundleSolutionInfo->isEmpty() ) {
811  stream.writeStartElement("results");
812 
813  for (int i = 0; i < m_bundleSolutionInfo->count(); i++) {
814  m_bundleSolutionInfo->at(i)->save(stream, this, newProjectRoot);
815  }
816 
817  stream.writeEndElement();
818  }
819 
820  if (m_activeImageList) {
821  stream.writeStartElement("activeImageList");
822  stream.writeAttribute("displayName", m_activeImageList->name());
823  stream.writeEndElement();
824  }
825 
826  if (m_activeControl) {
827  stream.writeStartElement("activeControl");
828  stream.writeAttribute("displayName", m_activeControl->displayProperties()->displayName());
829  stream.writeEndElement();
830  }
831 
832  stream.writeEndElement();
833  }
834 
835 
851  void Project::saveHistory(QXmlStreamWriter &stream) const {
852  stream.writeStartElement("history");
853 
854  foreach (WorkOrder *workOrder, *m_workOrderHistory) {
855  if (workOrder) {
856  workOrder->save(stream);
857  }
858  }
859 
860  stream.writeEndElement();
861  }
862 
874  void Project::saveWarnings(QXmlStreamWriter &stream) const {
875  stream.writeStartElement("warnings");
876 
877  foreach (QString warning, *m_warnings) {
878  stream.writeStartElement("warning");
879  stream.writeAttribute("text", warning);
880  stream.writeEndElement();
881  }
882 
883  stream.writeEndElement();
884  }
885 
886 
893  // TODO: thread via ImageReader
895 
896  QStringList result;
897 
898  foreach (QString fileName, fileNames) {
899  try {
900  Cube tmp(fileName);
901  result.append(fileName);
902  }
903  catch (IException &) {
904  }
905  }
906 
907  return result;
908  }
909 
910 
917  return m_imageReader->actions(ImageDisplayProperties::FootprintViewProperties);
918  }
919 
920 
926  QDir Project::addCnetFolder(QString prefix) {
927  QDir cnetFolder = cnetRoot();
928  prefix += "%1";
929  int prefixCounter = 0;
930 
931  QString numberedPrefix;
932  do {
933  prefixCounter++;
934  numberedPrefix = prefix.arg( QString::number(prefixCounter) );
935  }
936  while ( cnetFolder.exists(numberedPrefix) );
937 
938  if ( !cnetFolder.mkpath(numberedPrefix) ) {
940  tr("Could not create control network directory [%1] in [%2].")
941  .arg(numberedPrefix).arg( cnetFolder.absolutePath() ),
942  _FILEINFO_);
943  }
944 
945  cnetFolder.cd(numberedPrefix);
946 
947  m_currentCnetFolder = cnetFolder;
948 
949  return cnetFolder;
950  }
951 
952 
958  void Project::addControl(Control *control) {
959 
960  connect( control, SIGNAL( destroyed(QObject *) ),
961  this, SLOT( controlClosed(QObject *) ) );
962  connect( this, SIGNAL( projectRelocated(Project *) ),
963  control, SLOT( updateFileName(Project *) ) );
964 
965  createOrRetrieveControlList( FileName( control->fileName() ).dir().dirName(), "" )->append(control);
966 
967  (*m_idToControlMap)[control->id()] = control;
968 
969  emit controlAdded(control);
970  }
971 
972 
973  ControlList *Project::createOrRetrieveControlList(QString name, QString path) {
974  ControlList *result = controlList(name);
975 
976  if (!result) {
977  result = new ControlList;
978 
979  result->setName(name);
980  if (path == "") {
981  result->setPath(name);
982  }
983  else {
984  result->setPath(path);
985  }
986 
987  connect( result, SIGNAL( destroyed(QObject *) ),
988  this, SLOT( controlListDeleted(QObject *) ) );
989 
990  m_controls->append(result);
991  emit controlListAdded(result);
992  }
993 
994  return result;
995  }
996 
997 
1003  QDir Project::addImageFolder(QString prefix) {
1004  QDir imageFolder = imageDataRoot();
1005  prefix += "%1";
1006  int prefixCounter = 0;
1007 
1008  QString numberedPrefix;
1009  do {
1010  prefixCounter++;
1011  numberedPrefix = prefix.arg( QString::number(prefixCounter) );
1012  }
1013  while ( imageFolder.exists(numberedPrefix) );
1014 
1015  if ( !imageFolder.mkpath(numberedPrefix) ) {
1016  throw IException(IException::Io,
1017  tr("Could not create image directory [%1] in [%2].")
1018  .arg(numberedPrefix).arg( imageFolder.absolutePath() ),
1019  _FILEINFO_);
1020  }
1021 
1022  imageFolder.cd(numberedPrefix);
1023 
1024  return imageFolder;
1025  }
1026 
1027 
1032  void Project::addImages(QStringList imageFiles) {
1033  if (m_numImagesCurrentlyReading == 0) {
1034  m_imageReadingMutex->lock();
1035  }
1036 
1037  m_numImagesCurrentlyReading += imageFiles.count();
1038  m_imageReader->read(imageFiles);
1039  }
1040 
1041 
1046  void Project::addImages(ImageList newImages) {
1047  imagesReady(newImages);
1048 
1049  // The each
1050  emit guiCamerasAdded(m_guiCameras);
1051  emit targetsAdded(m_targets);
1052  }
1053 
1054 
1060  QDir Project::addShapeFolder(QString prefix) {
1061  QDir shapeFolder = shapeDataRoot();
1062  prefix += "%1";
1063  int prefixCounter = 0;
1064 
1065  QString numberedPrefix;
1066  do {
1067  prefixCounter++;
1068  numberedPrefix = prefix.arg( QString::number(prefixCounter) );
1069  }
1070  while ( shapeFolder.exists(numberedPrefix) );
1071 
1072  if ( !shapeFolder.mkpath(numberedPrefix) ) {
1073  throw IException(IException::Io,
1074  tr("Could not create shape directory [%1] in [%2].")
1075  .arg(numberedPrefix).arg( shapeFolder.absolutePath() ),
1076  _FILEINFO_);
1077  }
1078 
1079  shapeFolder.cd(numberedPrefix);
1080 
1081  return shapeFolder;
1082  }
1083 
1084 
1089  void Project::addShapes(QStringList shapeFiles) {
1090  if (m_numShapesCurrentlyReading == 0) {
1091  m_shapeReadingMutex->lock();
1092  }
1093 
1094  m_numShapesCurrentlyReading += shapeFiles.count();
1095  m_shapeReader->read(shapeFiles);
1096  }
1097 
1098 
1103  void Project::addShapes(ShapeList newShapes) {
1104  shapesReady(newShapes);
1105  }
1106 
1107 
1113  void Project::addTemplates(TemplateList *templateList) {
1114  foreach (Template *templateFile, *templateList) {
1115  connect( this, SIGNAL( projectRelocated(Project *) ),
1116  templateFile, SLOT( updateFileName(Project *) ) );
1117  }
1118  if (templateList->type() == "maps") {
1119  m_mapTemplates->append(templateList);
1120  }
1121  else if (templateList->type() == "registrations") {
1122  m_regTemplates->append(templateList);
1123  }
1124 
1125  emit templatesAdded(templateList);
1126  }
1127 
1128 
1134  QDir Project::addTemplateFolder(QString prefix) {
1135  QDir templateFolder = templateRoot();
1136  prefix += "%1";
1137  int prefixCounter = 0;
1138  QString numberedPrefix;
1139 
1140  do {
1141  prefixCounter++;
1142  numberedPrefix = prefix.arg( QString::number(prefixCounter) );
1143  }
1144  while ( templateFolder.exists(numberedPrefix) );
1145 
1146  if ( !templateFolder.mkpath(numberedPrefix) ) {
1147  throw IException(IException::Io,
1148  tr("Could not create template directory [%1] in [%2].")
1149  .arg(numberedPrefix).arg( templateFolder.absolutePath() ),
1150  _FILEINFO_);
1151  }
1152 
1153  templateFolder.cd(numberedPrefix);
1154 
1155  return templateFolder;
1156  }
1157 
1158 
1163  Control *Project::control(QString id) {
1164  return (*m_idToControlMap)[id];
1165  }
1166 
1167 
1175  QDir bundleSolutionInfoFolder(bundleSolutionInfoRoot());
1176 
1177  if (!bundleSolutionInfoFolder.mkpath(folder)) {
1178  throw IException(IException::Io,
1179  tr("Could not create bundle results directory [%1] in [%2].")
1180  .arg(folder).arg(bundleSolutionInfoFolder.absolutePath()),
1181  _FILEINFO_);
1182  }
1183 
1184  bundleSolutionInfoFolder.cd(folder);
1185  return bundleSolutionInfoFolder;
1186  }
1187 
1188 
1195  connect(bundleSolutionInfo, SIGNAL(destroyed(QObject *)),
1196  this, SLOT(bundleSolutionInfoClosed(QObject *)));//???
1197  connect(this, SIGNAL(projectRelocated(Project *)),
1198  bundleSolutionInfo, SLOT(updateFileName(Project *)));//DNE???
1199 
1200 
1202  }
1203 
1204 
1211  m_bundleSolutionInfo->append(bundleSolutionInfo);
1212 
1213  // add BundleSolutionInfo to project's m_idToBundleSolutionInfoMap
1214  (*m_idToBundleSolutionInfoMap)[bundleSolutionInfo->id()] = bundleSolutionInfo;
1215 
1216  // add BundleSolutionInfo's control to project's m_idToControlMap
1217  (*m_idToControlMap)[bundleSolutionInfo->control()->id()] = bundleSolutionInfo->control();
1218 
1220  }
1221 
1222 
1230  return m_directory;
1231  }
1232 
1233 
1234  void Project::writeSettings() {
1235 
1236  QString appName = QApplication::applicationName();
1237 
1238 
1239  QSettings globalSettings(
1240  FileName("$HOME/.Isis/" + appName + "/" + appName + "_" + "Project.config")
1241  .expanded(),
1242  QSettings::NativeFormat);
1243 
1244  globalSettings.beginGroup("recent_projects");
1245  QStringList keys = globalSettings.allKeys();
1246  QMap<QString,QString> recentProjects;
1247 
1248  foreach (QString key,keys) {
1249 
1250  recentProjects[key]=globalSettings.value(key).toString();
1251 
1252  }
1253 
1254  QList<QString> projectPaths = recentProjects.values();
1255 
1256  if (keys.count() >= m_maxRecentProjects) {
1257 
1258  //Clear out the recent projects before repopulating this group
1259  globalSettings.remove("");
1260 
1261 
1262 
1263  //If the currently open project is a project that has been saved and is not within the current
1264  //list of recently open projects, then remove the oldest project from the list.
1265  if (!this->projectRoot().contains("tmpProject") && !projectPaths.contains(this->projectRoot()) ) {
1266  QString s=keys.first();
1267  recentProjects.remove( s );
1268  }
1269 
1270  //If the currently open project is already contained within the list,
1271  //then remove the earlier reference.
1272 
1273  if (projectPaths.contains(this->projectRoot())) {
1274  QString key = recentProjects.key(this->projectRoot());
1275  recentProjects.remove(key);
1276  }
1277 
1279 
1280  //Iterate through the recentProjects QMap and set the <key,val> pairs.
1281  for (i=recentProjects.begin();i!=recentProjects.end();i++) {
1282 
1283  globalSettings.setValue(i.key(),i.value());
1284 
1285  }
1286 
1287  //Get a unique time value for generating a key
1288  long t0 = QDateTime::currentMSecsSinceEpoch();
1289  QString projName = this->name();
1290 
1291  QString t0String=QString::number(t0);
1292 
1293  //Save the project location
1294  if (!this->projectRoot().contains("tmpProject") ) {
1295  globalSettings.setValue(t0String+"%%%%%"+projName,this->projectRoot());
1296 
1297  }
1298 
1299  }
1300 
1301  //The numer of recent open projects is less than m_maxRecentProjects
1302  else {
1303 
1304  //Clear out the recent projects before repopulating this group
1305  globalSettings.remove("");
1306  if (projectPaths.contains(this->projectRoot())) {
1307  QString key = recentProjects.key(this->projectRoot());
1308  recentProjects.remove(key);
1309  }
1311 
1312  //Iterate through the recentProjects QMap and set the <key,val> pairs.
1313  for ( i=recentProjects.begin(); i!=recentProjects.end(); i++ ) {
1314  globalSettings.setValue(i.key(),i.value());
1315  }
1316 
1317  long t0 = QDateTime::currentMSecsSinceEpoch();
1318  QString projName = this->name();
1319  QString t0String=QString::number(t0);
1320 
1321  //if (!this->projectRoot().contains("tmpProject") && !projectPaths.contains( this->projectRoot() ) ) {
1322  if (!this->projectRoot().contains("tmpProject") ) {
1323  globalSettings.setValue(t0String+"%%%%%"+projName,this->projectRoot());
1324  }
1325 
1326  }
1327 
1328 
1329  globalSettings.endGroup();
1330  }
1331 
1332 
1345  void Project::open(QString projectPathStr) {
1346  // Expand projectPathStr to contain absolute path
1347  QString projectAbsolutePathStr = QDir(projectPathStr).absolutePath();
1348 
1349  QString projectXmlPath = projectAbsolutePathStr + "/project.xml";
1350  QFile file(projectXmlPath);
1351 
1352  if ( !file.open(QFile::ReadOnly) ) {
1353  throw IException(IException::Io,
1354  QString("Unable to open [%1] with read access")
1355  .arg(projectXmlPath),
1356  _FILEINFO_);
1357  }
1358 
1359  QString projectXmlHistoryPath = projectAbsolutePathStr + "/history.xml";
1360  QFile historyFile(projectXmlHistoryPath);
1361 
1362  if ( !historyFile.open(QFile::ReadOnly) ) {
1363  throw IException(IException::Io,
1364  QString("Unable to open [%1] with read access")
1365  .arg(projectXmlHistoryPath),
1366  _FILEINFO_);
1367  }
1368 
1369  QString projectXmlWarningsPath = projectAbsolutePathStr + "/warnings.xml";
1370  QFile warningsFile(projectXmlWarningsPath);
1371 
1372  if (!warningsFile.open(QFile::ReadOnly)) {
1373  throw IException(IException::Io,
1374  QString("Unable to open [%1] with read access")
1375  .arg(projectXmlWarningsPath),
1376  _FILEINFO_);
1377  }
1378 
1379  QString directoryXmlPath = projectAbsolutePathStr + "/directory.xml";
1380  QFile directoryFile(directoryXmlPath);
1381 
1382  if (!directoryFile.open(QFile::ReadOnly)) {
1383  throw IException(IException::Io,
1384  QString("Unable to open [%1] with read access")
1385  .arg(directoryXmlPath),
1386  _FILEINFO_);
1387  }
1388 
1389  if (isOpen() || !isClean()) {
1390  clear();
1391  }
1392  m_clearing = false;
1393  m_isTemporaryProject = false;
1394 
1395  XmlHandler handler(this);
1396 
1397  XmlStackedHandlerReader reader;
1398  reader.pushContentHandler(&handler);
1399  reader.setErrorHandler(&handler);
1400 
1401  QDir oldProjectRoot(*m_projectRoot);
1402  *m_projectRoot = QDir(projectAbsolutePathStr);
1403 
1404  QXmlInputSource xmlInputSource(&file);
1405 
1406  //This prevents the project from not loading if everything
1407  //can't be loaded, and outputs the warnings/errors to the
1408  //Warnings Tab
1409  try {
1410  reader.parse(xmlInputSource);
1411  }
1412  catch (IException &e) {
1413  directory()->showWarning(QString("Failed to open project completely [%1]")
1414  .arg(projectAbsolutePathStr));
1415  directory()->showWarning(e.toString());
1416  }
1417  catch (std::exception &e) {
1418  directory()->showWarning(QString("Failed to open project completely[%1]")
1419  .arg(projectAbsolutePathStr));
1420  directory()->showWarning(e.what());
1421  }
1422 
1423  reader.pushContentHandler(&handler);
1424  QXmlInputSource xmlHistoryInputSource(&historyFile);
1425 
1426  try {
1427  reader.parse(xmlHistoryInputSource);
1428  }
1429 
1430  catch (IException &e) {
1431  directory()->showWarning(QString("Failed to read history from project[%1]")
1432  .arg(projectAbsolutePathStr));
1433  directory()->showWarning(e.toString());
1434  }
1435  catch (std::exception &e) {
1436  directory()->showWarning(QString("Failed to read history from project[%1]")
1437  .arg(projectAbsolutePathStr));
1438  directory()->showWarning(e.what());
1439  }
1440 
1441  reader.pushContentHandler(&handler);
1442 
1443  QXmlInputSource xmlWarningsInputSource(&warningsFile);
1444 
1445  if (!reader.parse(xmlWarningsInputSource)) {
1446  warn(tr("Failed to read warnings from project [%1]").arg(projectAbsolutePathStr));
1447  }
1448 
1449  reader.pushContentHandler(&handler);
1450 
1451  QXmlInputSource xmlDirectoryInputSource(&directoryFile);
1452 
1453  try {
1454  reader.parse(xmlDirectoryInputSource);
1455  }
1456  catch (IException &e) {
1457  directory()->showWarning(QString("Failed to read GUI state from project[%1]")
1458  .arg(projectAbsolutePathStr));
1459  directory()->showWarning(e.toString());
1460 
1461  }
1462  catch (std::exception &e) {
1463  directory()->showWarning(QString("Failed to read GUI state from project[%1]")
1464  .arg(projectAbsolutePathStr));
1465  directory()->showWarning(e.what());
1466  }
1467 
1468  QDir bundleRoot(bundleSolutionInfoRoot());
1469  if (bundleRoot.exists()) {
1470  // get QFileInfo for each directory in the bundle root
1471  bundleRoot.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks); // sym links ok???
1472 
1473  QFileInfoList bundleDirs = bundleRoot.entryInfoList();
1474 
1475  for (int dirListIndex = 0; dirListIndex < bundleDirs.size(); dirListIndex++) {
1476 
1477  // get QFileInfo for each file in this directory
1478  QDir bundleSolutionDir(bundleDirs[dirListIndex].absoluteFilePath());
1479  bundleSolutionDir.setFilter(QDir::Files | QDir::NoSymLinks); // sym links ok???
1480 
1481 // QFileInfoList bundleSolutionFiles = bundleSolutionDir.entryInfoList();
1482 // for (int fileListIndex = 0; fileListIndex < bundleSolutionFiles.size(); fileListIndex++) {
1483 // // if the file is an hdf file with BundleSolutionInfo object, add it to the project tree
1484 // if (bundleSolutionFiles[fileListIndex].fileName().contains("_BundleSolutionInfo.hdf")) {
1485 // QString absoluteFileName = bundleSolutionFiles[fileListIndex].absoluteFilePath();
1486 // FileName solutionFile(bundleSolutionFiles[fileListIndex].absoluteFilePath());
1487 // loadBundleSolutionInfo(new BundleSolutionInfo(solutionFile));
1488 // }
1489 // }
1490  }
1491  }
1492  m_isOpen = true;
1493 
1494  setClean(true);
1495  emit projectLoaded(this);
1496  }
1497 
1498 
1499  QProgressBar *Project::progress() {
1500  return m_imageReader->progress();
1501  }
1502 
1503 
1509  Image *Project::image(QString id) {
1510 
1511  return (*m_idToImageMap)[id];
1512  }
1513 
1514 
1521  QListIterator<ImageList *> it(*m_images);
1522 
1523  ImageList *result = NULL;
1524  while (it.hasNext() && !result) {
1525  ImageList *list = it.next();
1526 
1527  if (list->name() == name) result = list;
1528  }
1529 
1530  return result;
1531  }
1532 
1533 
1539  Shape *Project::shape(QString id) {
1540  return (*m_idToShapeMap)[id];
1541  }
1542 
1543 
1550  QListIterator<ShapeList *> it(*m_shapes);
1551 
1552  ShapeList *result = NULL;
1553  while (it.hasNext() && !result) {
1554  ShapeList *list = it.next();
1555 
1556  if (list->name() == name) result = list;
1557  }
1558 
1559  return result;
1560  }
1561 
1562 
1568  return m_isTemporaryProject;
1569  }
1570 
1571 
1576  return m_isOpen;
1577  }
1578 
1579 
1585  return m_isClean;
1586  }
1587 
1588 
1595  void Project::setClean(bool value) {
1596  m_isClean = value;
1597  m_undoStack.cleanChanged(value);
1598  }
1599 
1600 
1606  WorkOrder *result = NULL;
1607  QListIterator< QPointer<WorkOrder> > it(*m_workOrderHistory);
1608  it.toBack();
1609 
1610  while ( !result && it.hasPrevious() ) {
1611  WorkOrder *workOrder = it.previous();
1612 
1613  if ( !workOrder->isUndone() && !workOrder->isUndoing() ) {
1614  result = workOrder;
1615  }
1616  }
1617 
1618  return result;
1619  }
1620 
1621 
1625  QString Project::name() const {
1626  return m_name;
1627  }
1628 
1629 
1635  const WorkOrder *result = NULL;
1636  QListIterator< QPointer<WorkOrder> > it(*m_workOrderHistory);
1637  it.toBack();
1638 
1639  while ( !result && it.hasPrevious() ) {
1640  WorkOrder *workOrder = it.previous();
1641 
1642  if ( !workOrder->isUndone() && !workOrder->isUndoing() ) {
1643  result = workOrder;
1644  }
1645  }
1646 
1647  return result;
1648  }
1649 
1650 
1658  QMutex *Project::mutex() {
1659  return m_mutex;
1660  }
1661 
1662 
1666  QString Project::projectRoot() const {
1667  return m_projectRoot->path();
1668  }
1669 
1670 
1675  QString Project::newProjectRoot() const {
1676  return m_newProjectRoot;
1677  }
1678 
1679 
1684  void Project::setName(QString newName) {
1685  m_name = newName;
1686  emit nameChanged(m_name);
1687  }
1688 
1689 
1694  QUndoStack *Project::undoStack() {
1695  return &m_undoStack;
1696  }
1697 
1698 
1699  QString Project::nextImageListGroupName() {
1700  int numLists = m_images->size();
1701  QString maxName = "";
1702  QString newGroupName = "Group";
1703 
1704  foreach (ImageList *imageList, *m_images) {
1705  QString name = imageList->name();
1706  if ( !name.contains("Group") ) continue;
1707  if ( maxName.isEmpty() ) {
1708  maxName = name;
1709  }
1710  else if (name > maxName) {
1711  maxName = name;
1712  }
1713  }
1714 
1715  if ( maxName.isEmpty() ) {
1716  newGroupName += QString::number(numLists+1);
1717  }
1718  else {
1719  int maxNum = maxName.remove("Group").toInt();
1720  maxNum++;
1721 
1722  newGroupName += QString::number(maxNum);
1723  }
1724  return newGroupName;
1725 
1726  }
1727 
1728 
1733  QMutexLocker locker(m_imageReadingMutex);
1734  }
1735 
1736 
1741  QMutexLocker locker(m_shapeReadingMutex);
1742  }
1743 
1744 
1749  QList<WorkOrder *> result;
1750  foreach (WorkOrder *workOrder, *m_workOrderHistory) {
1751  result.append(workOrder);
1752  }
1753 
1754  return result;
1755  }
1756 
1757 
1768  if (m_activeControl && m_activeImageList) {
1770  }
1771  }
1772 
1773 
1785  if (controls().count() > 0 && images().count() > 0) {
1787  }
1788  }
1789 
1790 
1819  void Project::setActiveControl(QString displayName) {
1820  Control *previousControl = m_activeControl;
1821  if (m_activeControl) {
1822 
1823  // If the current active control has been modified, ask user if they want to save or discard
1824  // changes.
1825  if (m_activeControl->isModified()) {
1826  QMessageBox msgBox;
1827  msgBox.setText("Save current active control");
1828  msgBox.setInformativeText("The current active control has been modified. Do you want "
1829  "to save before setting a new active control?");
1830  msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
1831  msgBox.setDefaultButton(QMessageBox::Save);
1832  int ret = msgBox.exec();
1833  switch (ret) {
1834  // Save current active control
1835  case QMessageBox::Save:
1836  m_activeControl->write();
1837  break;
1838  // Discard any changes made to cnet
1839  case QMessageBox::Discard:
1840  // Close, then re-open effectively discarding edits
1841  m_activeControl->closeControlNet();
1842  m_activeControl->openControlNet();
1843  emit discardActiveControlEdits();
1844  break;
1845  // Cancel operation
1846  case QMessageBox::Cancel:
1847  return;
1848  }
1849  }
1850  emit activeControlSet(false);
1851  ProjectItem *item = directory()->model()->findItemData(m_activeControl->
1852  displayProperties()->displayName(), Qt::DisplayRole);
1853  item->setTextColor(Qt::black);
1854  // Make sure active not used in a CnetEditorWidget before closing
1855  if (!directory()->controlUsedInCnetEditorWidget(m_activeControl)) {
1856  m_activeControl->closeControlNet();
1857  }
1858  }
1859 
1860  ProjectItem *item = directory()->model()->findItemData(displayName, Qt::DisplayRole);
1861  if (item && item->isControl()) {
1862  m_activeControl = item->control();
1863 
1864  try {
1865  m_activeControl->controlNet()->SetImages(*(activeImageList()->serialNumberList()));
1866  item->setTextColor(Qt::darkGreen);
1867  }
1868  catch(IException &e){
1869  if (previousControl) {
1870  m_activeControl = previousControl;
1871  item = directory()->model()->findItemData(m_activeControl->
1872  displayProperties()->displayName(), Qt::DisplayRole);
1873  item->setTextColor(Qt::darkGreen);
1874  m_activeControl->controlNet()->SetImages(*(activeImageList()->serialNumberList()));
1875  }
1876  else {
1877  m_activeControl = NULL;
1878  }
1879  throw IException(e);
1880  }
1881  }
1882  emit activeControlSet(true);
1883  }
1884 
1885 
1904 
1905  if (!m_activeControl && (m_controls->count() == 1 && m_controls->at(0)->count() ==1)) {
1906  // Can only set a default control if an active imageList exists or if a default can be set
1907  if (activeImageList()) {
1908  QString controlName = m_controls->at(0)->at(0)->displayProperties()->displayName();
1909  setActiveControl(controlName);
1910  }
1911  }
1912 
1913  return m_activeControl;
1914  }
1915 
1916 
1925  if (m_activeControl && m_activeControl->isModified()) {
1926  emit activeControlModified();
1927  }
1928  setClean(false);
1929  }
1930 
1931 
1955  void Project::setActiveImageList(QString displayName) {
1956  ImageList *previousImageList = m_activeImageList;
1957  if (m_activeImageList) {
1958  ProjectItem *item = directory()->model()->findItemData(m_activeImageList->
1959  name(), Qt::DisplayRole);
1960  item->setTextColor(Qt::black);
1961  }
1962  ProjectItem *item = directory()->model()->findItemData(displayName, Qt::DisplayRole);
1963  if (item && item->isImageList()) {
1964  m_activeImageList = item->imageList();
1965 
1966  if (m_activeControl) {
1967  try {
1968  activeControl()->controlNet()->SetImages(*(m_activeImageList->serialNumberList()));
1969  }
1970  catch(IException &e){
1971  if (previousImageList) {
1972  m_activeImageList = previousImageList;
1973  item = directory()->model()->findItemData(m_activeImageList->
1974  name(), Qt::DisplayRole);
1975  item->setTextColor(Qt::darkGreen);
1976  activeControl()->controlNet()->SetImages(*(m_activeImageList->serialNumberList()));
1977  }
1978  else {
1979  m_activeImageList = NULL;
1980  }
1981  throw IException(e);
1982  }
1983  }
1984  item->setTextColor(Qt::darkGreen);
1985  emit activeImageListSet();
1986  }
1987  }
1988 
1989 
2004 
2005  if (!m_activeImageList && m_images->count() == 1) {
2006  QString imageList = m_images->at(0)->name();
2007 
2009  }
2010  return m_activeImageList;
2011  }
2012 
2013 
2019  QString Project::cnetRoot(QString projectRoot) {
2020  return projectRoot + "/cnets";
2021  }
2022 
2023 
2029  QString Project::cnetRoot() const {
2030  return cnetRoot( m_projectRoot->path() );
2031  }
2032 
2033 
2039  return *m_controls;
2040  }
2041 
2042 
2049  QListIterator< ControlList * > it(*m_controls);
2050 
2051  ControlList *result = NULL;
2052  while (it.hasNext() && !result) {
2053  ControlList *list = it.next();
2054 
2055  if (list->name() == name) result = list;
2056  }
2057 
2058  return result;
2059  }
2060 
2061 
2067  QString Project::imageDataRoot(QString projectRoot) {
2068  return projectRoot + "/images";
2069  }
2070 
2071 
2077  QString Project::imageDataRoot() const {
2078  return imageDataRoot( m_projectRoot->path() );
2079  }
2080 
2081 
2087  QString Project::shapeDataRoot(QString projectRoot) {
2088  return projectRoot + "/shapes";
2089  }
2090 
2091 
2097  QString Project::shapeDataRoot() const {
2098  return shapeDataRoot( m_projectRoot->path() );
2099  }
2100 
2101 
2107  return *m_shapes;
2108  }
2109 
2110 
2116  return *m_images;
2117  }
2118 
2119 
2125  QString Project::templateRoot(QString projectRoot) {
2126  return projectRoot + "/templates";
2127  }
2128 
2129 
2135  QString Project::templateRoot() const {
2136  return templateRoot( m_projectRoot->path() );
2137  }
2138 
2139 
2146  QList<TemplateList *> allTemplates = *m_mapTemplates + *m_regTemplates;
2147  return allTemplates;
2148  }
2149 
2150 
2157  return *m_mapTemplates;
2158  }
2159 
2160 
2167  return *m_regTemplates;
2168  }
2169 
2170 
2176  QString Project::targetBodyRoot(QString projectRoot) {
2177  return projectRoot + "/targets";
2178  }
2179 
2180 
2186  QString Project::targetBodyRoot() const {
2187  return targetBodyRoot( m_projectRoot->path() );
2188  }
2189 
2190 
2195  return *m_targets;
2196  }
2197 
2198 
2204  QString Project::resultsRoot(QString projectRoot) {
2205  return projectRoot + "/results";
2206  }
2207 
2208 
2214  QString Project::resultsRoot() const {
2215  return resultsRoot( m_projectRoot->path() );
2216  }
2217 
2218 
2224  return *m_bundleSolutionInfo;
2225  }
2226 
2227 
2233  QString Project::bundleSolutionInfoRoot(QString projectRoot) {
2234  return projectRoot + "/results/bundle";
2235  }
2236 
2237 
2244  return bundleSolutionInfoRoot( m_projectRoot->path() );
2245  }
2246 
2247 
2252 
2253  // Currently the deleteFromDisk methods for Image and Shape delete the Cube if it exists, the
2254  // other objects deleteFromDisk methods simply remove files. This could be achieved easier
2255  // in this method by simply calling QDir::removeRecursively(), but for future functionality
2256  // call each objects deleteFromDisk. Currently there are no cleanup methods for Bundle results
2257  // or templates, so simply remove directory recursively.
2258  foreach (ImageList *imagesInAFolder, *m_images) {
2259  imagesInAFolder->deleteFromDisk(this);
2260  }
2261 
2262  if ( !m_projectRoot->rmdir( imageDataRoot() ) ) {
2263  warn( tr("Did not properly clean up images folder [%1] in project").arg( imageDataRoot() ) );
2264  }
2265 
2266  foreach (ShapeList *shapesInAFolder, *m_shapes) {
2267  shapesInAFolder->deleteFromDisk(this);
2268  }
2269 
2270  if ( !m_projectRoot->rmdir( shapeDataRoot() ) ) {
2271  warn( tr("Did not properly clean up shapes folder [%1] in project").
2272  arg( shapeDataRoot() ) );
2273  }
2274 
2275  foreach (ControlList *controlsInAFolder, *m_controls) {
2276  controlsInAFolder->deleteFromDisk(this);
2277  }
2278 
2279  if ( !m_projectRoot->rmdir( cnetRoot() ) ) {
2280  warn( tr("Did not properly clean up control network folder [%1] in project")
2281  .arg( cnetRoot() ) );
2282  }
2283 
2284  if ( !(QDir(resultsRoot()).removeRecursively()) ) {
2285  warn( tr("Did not properly clean up results folder [%1] in project")
2286  .arg( resultsRoot() ) );
2287  }
2288 
2289  if ( !(QDir(templateRoot()).removeRecursively()) ) {
2290  warn( tr("Did not properly clean up templates folder [%1] in project")
2291  .arg( templateRoot() ) );
2292  }
2293 
2294  if ( !m_projectRoot->rmpath( m_projectRoot->path() ) ) {
2295  warn( tr("Did not properly clean up project in [%1]").arg( m_projectRoot->path() ) );
2296  }
2297  }
2298 
2299 
2305  void Project::relocateProjectRoot(QString newProjectRoot) {
2306  *m_projectRoot = newProjectRoot;
2307  emit projectRelocated(this);
2308  }
2309 
2310 
2324  bool Project::save() {
2325  // Let caller know if the save dialog was cancelled
2326  bool saveDialogCompleted = true;
2327 
2328  if (m_isTemporaryProject) {
2329  QString newDestination = QFileDialog::getSaveFileName(NULL,
2330  QString("Project Location"),
2331  QString("."));
2332 
2333  if ( !newDestination.isEmpty() ) {
2334  m_isTemporaryProject = false;
2335  save( QFileInfo(newDestination + "/").absolutePath() );
2336 
2337  // delete the temporary project
2339  relocateProjectRoot(newDestination);
2340 
2341  // 2014-03-14 kle This is a lame kludge because we think that relocateProjectRoot is not
2342  // working properly. For example, when we save a new project and try to view a control net
2343  // the it thinks it's still in the /tmp area
2344  // see ticket #5292
2345  open(newDestination);
2346  }
2347  // Dialog was cancelled
2348  else {
2349  saveDialogCompleted = false;
2350  }
2351  }
2352  else {
2353  // Save all modified controls. If "Save As" is being processed,
2354  // the controls are written in the Control::copyToNewProjectRoot, so the controls in
2355  // current project are not modified.
2356  foreach (ControlList *controlList, *m_controls) {
2357  foreach (Control *control, *controlList) {
2358  if (control->isModified()) {
2359  control->write();
2360  }
2361  }
2362  }
2363  save(m_projectRoot->absolutePath(), false);
2364  emit cnetSaved(true);
2365  }
2366 
2367  return saveDialogCompleted;
2368  }
2369 
2370 
2371 
2372 
2472  void Project::save(FileName newPath, bool verifyPathDoesntExist) {
2473  if ( verifyPathDoesntExist && QFile::exists( newPath.toString() ) ) {
2474  throw IException(IException::Io,
2475  QString("Projects may not be saved to an existing path [%1]; "
2476  "please select a new path or delete the current folder")
2477  .arg(newPath.original()),
2478  _FILEINFO_);
2479  }
2480 
2481  QDir dir;
2482  if (!dir.mkpath(newPath.toString())) {
2483  throw IException(IException::Io,
2484  QString("Unable to save project at [%1] "
2485  "because we could not create the folder")
2486  .arg(newPath.original()),
2487  _FILEINFO_);
2488  }
2489 
2490  // TODO Set newpath member variable. This is used for some of the data copy methods and is not
2491  // the ideal way to handle this. Maybe change the data copy methods to either take the new
2492  // project root in addition to the data root or put the data root in the dataList (ImageList,
2493  // etc.). If performing a "Save", m_newProjectRoot == m_projectRoot
2494  m_newProjectRoot = newPath.toString();
2495 
2496  // For now set the member variable rather than calling setName which emits signal and updates
2497  // ProjectItemModel & the project name on the tree. This will be updated when the new project
2498  // is opened.
2499  m_name = newPath.name();
2500 
2501  QFile projectSettingsFile(newPath.toString() + "/project.xml");
2502  if (!projectSettingsFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
2503  throw IException(IException::Io,
2504  QString("Unable to save project at [%1] because the file [%2] "
2505  "could not be opened for writing")
2506  .arg(newPath.original()).arg(projectSettingsFile.fileName()),
2507  _FILEINFO_);
2508  }
2509 
2510  QXmlStreamWriter writer(&projectSettingsFile);
2511  writer.setAutoFormatting(true);
2512 
2513  writer.writeStartDocument();
2514 
2515  // Do amazing, fantastical stuff here!!!
2516  save(writer, newPath);
2517 
2518  writer.writeEndDocument();
2519 
2520  QFile projectHistoryFile(newPath.toString() + "/history.xml");
2521  if (!projectHistoryFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
2522  throw IException(IException::Io,
2523  QString("Unable to save project at [%1] because the file [%2] "
2524  "could not be opened for writing")
2525  .arg(newPath.original()).arg(projectHistoryFile.fileName()),
2526  _FILEINFO_);
2527  }
2528 
2529  QXmlStreamWriter historyWriter(&projectHistoryFile);
2530  historyWriter.setAutoFormatting(true);
2531 
2532  historyWriter.writeStartDocument();
2533  saveHistory(historyWriter);
2534  historyWriter.writeEndDocument();
2535 
2536  QFile projectWarningsFile(newPath.toString() + "/warnings.xml");
2537  if (!projectWarningsFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
2538  throw IException(IException::Io,
2539  QString("Unable to save project at [%1] because the file [%2] could not be "
2540  "opened for writing")
2541  .arg(newPath.original()).arg(projectWarningsFile.fileName()),
2542  _FILEINFO_);
2543  }
2544 
2545  QXmlStreamWriter warningsWriter(&projectWarningsFile);
2546  warningsWriter.setAutoFormatting(true);
2547 
2548  warningsWriter.writeStartDocument();
2549  saveWarnings(warningsWriter);
2550  warningsWriter.writeEndDocument();
2551 
2552  // Save the Directory structure
2553  QFile directoryStateFile(newPath.toString() + "/directory.xml");
2554  if (!directoryStateFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
2555  throw IException(IException::Io,
2556  QString("Unable to save project at [%1] because the file [%2] could not be "
2557  "opened for writing")
2558  .arg(newPath.original()).arg(directoryStateFile.fileName()),
2559  _FILEINFO_);
2560  }
2561 
2562  QXmlStreamWriter directoryStateWriter(&directoryStateFile);
2563  directoryStateWriter.setAutoFormatting(true);
2564 
2565  directoryStateWriter.writeStartDocument();
2566 
2567  /*
2568  * TODO: Does Project need to know about Directory?
2569  * This is the only place that project uses m_directory. This makes me wonder if it is
2570  * necessary for project to have a Directory member variable.
2571  */
2572  m_directory->save(directoryStateWriter, newPath);
2573 
2574  directoryStateWriter.writeEndDocument();
2575  m_isOpen = true;
2576 
2577  emit projectSaved(this);
2578 
2579  }
2580 
2581 
2599  if (workOrder) {
2600  connect(workOrder, SIGNAL(finished(WorkOrder *)),
2601  this, SIGNAL(workOrderFinished(WorkOrder *)));
2602 
2603  workOrder->setPrevious(lastNotUndoneWorkOrder());
2604 
2605  if (workOrder->setupExecution()) {
2606  if (workOrder->previous()) workOrder->previous()->setNext(workOrder);
2607 
2608  m_workOrderHistory->append(workOrder);
2609 
2610  if (workOrder->isSavedToHistory()) {
2611  emit workOrderStarting(workOrder);
2612  }
2613 
2614  // Work orders that create clean states (save, save as) don't belong on the undo stack.
2615  // Instead, we tell the undo stack that we're now clean.
2616  if (workOrder->createsCleanState()) {
2617  m_undoStack.setClean();
2618  workOrder->execute();
2619  }
2620  // All other work orders go onto the undo stack, unless specifically told not to
2621  else if (workOrder->isUndoable()) {
2622  // This calls WorkOrder::redo for us through Qt's QUndoStack::push method, redo is only
2623  // implemented in the base class. Child work orders do not implement redo.
2624  m_undoStack.push(workOrder);
2625  }
2626  else {
2627  // If we get this far the WorkOrder is not-undoable therefore we have to call redo by
2628  // hand.
2629 
2630  workOrder->redo();
2631  }
2632  // Clean up deleted work orders (the m_undoStack.push() can delete work orders)
2633  m_workOrderHistory->removeAll(NULL);
2634  }
2635  else {
2636  delete workOrder;
2637  workOrder = NULL;
2638  }
2639  }
2640  }
2641 
2642 
2643  template<typename Data> void Project::warn(QString text, Data relevantData) {
2644  storeWarning(text, relevantData);
2645  directory()->showWarning(text, relevantData);
2646  }
2647 
2648 
2649  void Project::warn(QString text) {
2650  foreach (QString line, text.split("\n")) {
2651  storeWarning(line);
2652  directory()->showWarning(line);
2653  }
2654  }
2655 
2656 
2657  void Project::storeWarning(QString text) {
2658  m_warnings->append(text);
2659  }
2660 
2661 
2667 
2669 
2670  foreach (Image *image, images) {
2671  connect(image, SIGNAL(destroyed(QObject *)),
2672  this, SLOT(imageClosed(QObject *)));
2673  connect(this, SIGNAL(projectRelocated(Project *)),
2674  image, SLOT(updateFileName(Project *)));
2675 
2676  (*m_idToImageMap)[image->id()] = image;
2677  if (images.name() != "") {
2678  createOrRetrieveImageList(images.name(), images.path())->append(image);
2679  }
2680  else {
2681  createOrRetrieveImageList(FileName(images[0]->fileName()).dir().dirName(), "")->append(image);
2682  }
2683  }
2684 
2685  // We really can't have all of the cubes in memory before
2686  // the OS stops letting us open more files.
2687  // Assume cameras are being used in other parts of code since it's
2688  // unknown
2689  QMutexLocker lock(m_mutex);
2690  emit imagesAdded(m_images->last());
2691 
2692  Image *openImage;
2693  foreach (openImage, images) {
2694  openImage->closeCube();
2695  }
2696 
2697 // if(m_projectPvl && m_projectPvl->HasObject("MosaicFileList") )
2698 // m_fileList->fromPvl(m_projectPvl->FindObject("MosaicFileList") );
2699 
2700 // if(m_projectPvl && m_projectPvl->HasObject("MosaicScene") )
2701 // m_scene->fromPvl(m_projectPvl->FindObject("MosaicScene") );
2702 
2703  if (m_numImagesCurrentlyReading == 0) {
2704  m_imageReadingMutex->unlock();
2705  }
2706  }
2707 
2708 
2715  bool Project::hasTarget(QString id) {
2716  foreach (TargetBodyQsp targetBody, *m_targets) {
2717  if (QString::compare(targetBody->targetName(), id, Qt::CaseInsensitive) == 0) {
2718  return true;
2719  }
2720  }
2721  return false;
2722  }
2723 
2724 
2730  void Project::addTarget(Target *target) {
2731 
2732  TargetBodyQsp targetBody = TargetBodyQsp(new TargetBody(target));
2733 
2734  m_targets->append(targetBody);
2735 
2736  }
2737 
2738 
2745  bool Project::hasCamera(QString id) {
2746  foreach (GuiCameraQsp camera, *m_guiCameras) {
2747 
2748  if (QString::compare(camera->instrumentId(), id, Qt::CaseInsensitive) == 0) {
2749  return true;
2750  }
2751  }
2752  return false;
2753  }
2754 
2755 
2761  void Project::addCamera(Camera *camera) {
2762 
2763  GuiCameraQsp guiCamera = GuiCameraQsp(new GuiCamera(camera));
2764 
2765  m_guiCameras->append(guiCamera);
2766 
2767  }
2768 
2769 
2779 
2780  foreach (Image *image, images) {
2781  (*m_idToImageMap)[image->id()] = image;
2782  }
2783  }
2784 
2785 
2786  void Project::removeImages(ImageList &imageList) {
2787  foreach (Image *image, imageList) {
2788  delete image;
2789  }
2790  foreach (ImageList *list, *m_images) {
2791  if (list->name() == imageList.name()) {
2792  m_images->removeOne(list);
2793  }
2794  }
2795  }
2796 
2797 
2802  void Project::imageClosed(QObject *imageObj) {
2803  QMutableListIterator<ImageList *> it(*m_images);
2804  while (it.hasNext()) {
2805  ImageList *list = it.next();
2806 
2807  int foundElement = list->indexOf((Image *)imageObj);
2808 
2809  if (foundElement != -1) {
2810  list->removeAt(foundElement);
2811  }
2812  }
2813 
2814  m_idToImageMap->remove(m_idToImageMap->key((Image *)imageObj));
2815  }
2816 
2817 
2822  void Project::imageListDeleted(QObject *imageListObj) {
2823  int indexToRemove = m_images->indexOf(static_cast<ImageList *>(imageListObj));
2824  if (indexToRemove != -1) {
2825  m_images->removeAt(indexToRemove);
2826  }
2827  }
2828 
2829 
2833  void Project::controlClosed(QObject *controlObj) {
2834  m_idToControlMap->remove(m_idToControlMap->key((Control *)controlObj));
2835  }
2836 
2837 
2841  void Project::controlListDeleted(QObject *controlListObj) {
2842  int indexToRemove = m_controls->indexOf(static_cast<ControlList *>(controlListObj));
2843  if (indexToRemove != -1) {
2844  m_controls->removeAt(indexToRemove);
2845  }
2846 
2847  if (controls().count() == 0) {
2848  emit allControlsRemoved();
2849  }
2850  }
2851 
2852 
2856  void Project::shapeListDeleted(QObject *shapeListObj) {
2857  int indexToRemove = m_shapes->indexOf(static_cast<ShapeList *>(shapeListObj));
2858  if (indexToRemove != -1) {
2859  m_shapes->removeAt(indexToRemove);
2860  }
2861  }
2862 
2863 
2867  void Project::bundleSolutionInfoClosed(QObject *bundleSolutionInfoObj) {
2868  QMutableListIterator<BundleSolutionInfo *> it(*m_bundleSolutionInfo);
2869  while (it.hasNext()) {
2871  if (!bundleSolutionInfo) {
2872  // throw error???
2873  }
2874 
2875  int foundElement = m_bundleSolutionInfo->indexOf(
2876  (BundleSolutionInfo *)bundleSolutionInfoObj);
2877 
2878  if (foundElement != -1) {
2879  m_bundleSolutionInfo->removeAt(foundElement);
2880  }
2881  }
2882 
2883  m_idToBundleSolutionInfoMap->remove(
2884  m_idToBundleSolutionInfoMap->key((BundleSolutionInfo * )bundleSolutionInfoObj));
2885  }
2886 
2887 
2893  void Project::targetBodyClosed(QObject *targetBodyObj) {
2894 // QMutableListIterator<TargetBody *> it(*m_targets);
2895 // while ( it.hasNext() ) {
2896 // TargetBody *targetBody = it.next();
2897 // if (!targetBody) {
2898 // // throw error???
2899 // }
2900 
2901 // int foundElement = m_targets->indexOf( (TargetBody *)targetBodyObj );
2902 
2903 // if (foundElement != -1) {
2904 // m_targets->removeAt(foundElement);
2905 // }
2906 // }
2907 
2908 // m_idToTargetBodyMap->remove(m_idToTargetBodyMap->key((TargetBody *)targetBodyObj));
2909  }
2910 
2911 
2912 
2913  void Project::shapesReady(ShapeList shapes) {
2914 
2915  m_numShapesCurrentlyReading -= shapes.count();
2916 
2917  foreach (Shape *shape, shapes) {
2918  connect(shape, SIGNAL(destroyed(QObject *)),
2919  this, SLOT(shapeClosed(QObject *)));
2920  connect(this, SIGNAL(projectRelocated(Project *)),
2921  shape, SLOT(updateFileName(Project *)));
2922 
2923  (*m_idToShapeMap)[shape->id()] = shape;
2924  if (shapes.name() != "") {
2925  createOrRetrieveShapeList(shapes.name(), shapes.path())->append(shape);
2926  }
2927  else {
2928  createOrRetrieveShapeList(FileName(shapes[0]->fileName()).dir().dirName(), "")->append(shape);
2929  }
2930 
2931  }
2932 
2933  // We really can't have all of the cubes in memory before
2934  // the OS stops letting us open more files.
2935  // Assume cameras are being used in other parts of code since it's
2936  // unknown
2937  QMutexLocker lock(m_shapeMutex);
2938  emit shapesAdded(m_shapes->last());
2939 
2940  Shape *openShape;
2941  foreach (openShape, shapes) {
2942  openShape->closeCube();
2943  }
2944 
2945  if (m_numShapesCurrentlyReading == 0) {
2946  m_shapeReadingMutex->unlock();
2947  }
2948  }
2949 
2950 
2954  void Project::shapeClosed(QObject *imageObj) {
2955  QMutableListIterator<ShapeList *> it(*m_shapes);
2956  while (it.hasNext()) {
2957  ShapeList *list = it.next();
2958 
2959  int foundElement = list->indexOf((Shape *)imageObj);
2960 
2961  if (foundElement != -1) {
2962  list->removeAt(foundElement);
2963  }
2964  }
2965 
2966  m_idToShapeMap->remove(m_idToShapeMap->key((Shape *)imageObj));
2967  }
2968 
2969 
2970  Project::XmlHandler::XmlHandler(Project *project) {
2971  m_project = project;
2972  m_workOrder = NULL;
2973  }
2974 
2975 
2987  return m_workOrderMutex;
2988  }
2989 
2990 
2991  bool Project::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
2992  const QString &qName, const QXmlAttributes &atts) {
2993  if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
2994 
2995  if (localName == "project") {
2996  QString name = atts.value("name");
2997  if (!name.isEmpty()) {
2998  m_project->setName(name);
2999  }
3000  }
3001  else if (localName == "controlNets") {
3002  m_controls.append(new ControlList(m_project, reader()));
3003  }
3004  else if (localName == "imageList") {
3005  m_imageLists.append(new ImageList(m_project, reader()));
3006  }
3007  else if (localName == "shapeList") {
3008  m_shapeLists.append(new ShapeList(m_project, reader()));
3009  }
3010  else if (localName == "mapTemplateList") {
3011  m_mapTemplateLists.append( new TemplateList(m_project, reader()));
3012  }
3013  else if (localName == "regTemplateList") {
3014  m_regTemplateLists.append( new TemplateList(m_project, reader()));
3015  }
3016  // workOrders are stored in history.xml, using same reader as project.xml
3017  else if (localName == "workOrder") {
3018  QString type = atts.value("type");
3019 
3020  m_workOrder = WorkOrderFactory::create(m_project, type);
3021  ASSERT(m_workOrder->metaObject()->className() == type);
3022 
3023  m_workOrder->read(reader());
3024  }
3025  // warnings stored in warning.xml, using same reader as project.xml
3026  else if (localName == "warning") {
3027  QString warningText = atts.value("text");
3028 
3029  if (!warningText.isEmpty()) {
3030  m_project->warn(warningText);
3031  }
3032  }
3033  else if (localName == "directory") {
3034  m_project->directory()->load(reader());
3035  }
3036  else if (localName == "dockRestore") {
3037 // QVariant geo_data = QVariant(atts.value("geometry"));
3038 // restoreGeometry(geo_data);
3039 // QVariant layout_data = QVariant(atts.value("state"));
3040 // restoreState(layout_data);
3041  }
3042 
3043  else if (localName == "bundleSolutionInfo") {
3044  m_bundleSolutionInfos.append(new BundleSolutionInfo(m_project, reader()));
3045  }
3046  else if (localName == "activeImageList") {
3047  QString displayName = atts.value("displayName");
3048  m_project->setActiveImageList(displayName);
3049  }
3050  else if (localName == "activeControl") {
3051  // Find Control
3052  QString displayName = atts.value("displayName");
3053  m_project->setActiveControl(displayName);
3054  }
3055  }
3056 
3057  return true;
3058  }
3059 
3060 
3072  bool Project::XmlHandler::endElement(const QString &namespaceURI, const QString &localName,
3073  const QString &qName) {
3074  if (localName == "imageLists") {
3075  foreach (ImageList *imageList, m_imageLists) {
3076  m_project->imagesReady(*imageList);
3077  }
3078  }
3079  else if (localName == "shapeLists") {
3080  // TODO does this go here under project or should it be under shapes?
3081  foreach (ShapeList *shapeList, m_shapeLists) {
3082  m_project->shapesReady(*shapeList);
3083  }
3084  }
3085  else if (localName == "mapTemplateLists") {
3086  foreach (TemplateList *templateList, m_mapTemplateLists) {
3087  m_project->addTemplates(templateList);
3088  }
3089  }
3090  else if (localName == "regTemplateLists") {
3091  foreach (TemplateList *templateList, m_regTemplateLists) {
3092  m_project->addTemplates(templateList);
3093  }
3094  }
3095  else if (localName == "workOrder") {
3096  m_project->m_workOrderHistory->append(m_workOrder);
3097  m_workOrder = NULL;
3098  }
3099  else if (localName == "controlNets") {
3100  foreach (ControlList *list, m_controls) {
3101  foreach (Control *control, *list) {
3102  m_project->addControl(control);
3103  }
3104  delete list;
3105  }
3106  m_controls.clear();
3107  }
3108  else if (localName == "results") {
3109  foreach (BundleSolutionInfo *bundleInfo, m_bundleSolutionInfos) {
3110  m_project->addBundleSolutionInfo(bundleInfo);
3111 
3112  // If BundleSolutionInfo contains adjusted images, add to the project id map.
3113  if (bundleInfo->adjustedImages().count()) {
3114  foreach (ImageList *adjustedImageList, bundleInfo->adjustedImages()) {
3115  m_project->addImagesToIdMap(*adjustedImageList);
3116  }
3117  }
3118  }
3119  }
3120  return XmlStackedHandler::endElement(namespaceURI, localName, qName);
3121  }
3122 }
This represents an ISIS control net in a project-based GUI interface.
Definition: Control.h:79
Internalizes a list of shapes and allows for operations on the entire list.
Definition: ShapeList.h:33
void waitForImageReaderFinished()
Locks program if another spot in code is still running and called this function.
Definition: Project.cpp:1732
bool isImageList() const
Returns true if an ImageList is stored in the data of the item.
QString name() const
Get the human-readable name of this image list.
Definition: ImageList.cpp:724
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
QDir addImageFolder(QString prefix)
Create and return the name of a folder for placing images.
Definition: Project.cpp:1003
$Date$ $Revision$
QString cnetRoot() const
Get where control networks ought to be stored inside the project.
Definition: Project.cpp:2029
Internalizes a list of images and allows for operations on the entire list.
Definition: ImageList.h:55
void activeControlModified()
Emmited in cnetModified() when the actice control is modified.
QList< ShapeList * > shapes()
Return the projects shapelist.
Definition: Project.cpp:2106
void controlClosed(QObject *control)
A control is being deleted from the project.
Definition: Project.cpp:2833
The main project for ipce.
Definition: Project.h:289
Container class for TargetBody.
Definition: TargetBody.h:80
void closeCube()
Cleans up the Cube *.
Definition: Shape.cpp:343
bool isClean()
Accessor to determine whether the current project is Unsaved.
Definition: Project.cpp:1584
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:257
void projectSaved(Project *)
Emitted when project is saved.
void allControlsRemoved()
Emitted when all controls have been removed from the Project.
File name manipulation and expansion.
Definition: FileName.h:116
QList< WorkOrder * > workOrderHistory()
Get the entire list of work orders that have executed.
Definition: Project.cpp:1748
Container class for BundleAdjustment results.
void deleteFromDisk(Project *project)
Delete all of the contained Shapes from disk.
Definition: ShapeList.cpp:592
bool hasTarget(QString id)
This method checks for the existence of a target based on TargetName.
Definition: Project.cpp:2715
void checkActiveControlAndImageList()
Checks if both an active control and active image list have been set.
Definition: Project.cpp:1767
Control * control(QString id)
Accessor for if the project is clearing or not.
Definition: Project.cpp:1163
void addCamera(Camera *camera)
Adds a new camera to the project.
Definition: Project.cpp:2761
void deleteFromDisk(Project *project)
Delete all of the contained Images from disk.
Definition: ImageList.cpp:747
QMutex * mutex()
Return mutex used for Naif calls.
Definition: Project.cpp:1658
WorkOrder * lastNotUndoneWorkOrder()
Return the last not undone workorder.
Definition: Project.cpp:1605
Shape * shape(QString id)
Return a shape given its id.
Definition: Project.cpp:1539
Maintains a list of Controls so that control nets can easily be copied from one Project to another...
Definition: ControlList.h:36
void setName(QString newName)
Set the human-readable name of this control list.
virtual bool setupExecution()
This sets up the state for the work order.
Definition: WorkOrder.cpp:1275
void controlListDeleted(QObject *controlList)
An control list is being deleted from the project.
Definition: Project.cpp:2841
void open(QString)
Open the project at the given path.
Definition: Project.cpp:1345
void addTarget(Target *target)
Adds a new target to the project.
Definition: Project.cpp:2730
bool m_clearing
used to determine whether a project&#39;s changes are unsaved
Definition: Project.h:667
void addImagesToIdMap(ImageList images)
Add images to the id map which are not under the projects main data area, the Images node on the proj...
Definition: Project.cpp:2778
void showWarning(QString text)
Displays a Warning.
Definition: Directory.cpp:1495
QString targetBodyRoot() const
Accessor for the root directory of the target body data.
Definition: Project.cpp:2186
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:958
void controlsAndImagesAvailable()
Emitted when at least one cnet and image have been added to the project.
void controlListAdded(ControlList *controls)
apparently not used?
void activeControlAndImageListSet()
Emitted when both an active control and active image list have been set.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
ControlList * controlList(QString name)
Return controlslist matching name in Project.
Definition: Project.cpp:2048
void targetBodyClosed(QObject *targetBodyObj)
A target body is being deleted from the project.
Definition: Project.cpp:2893
QList< TemplateList * > regTemplates()
Return registration template FileNames.
Definition: Project.cpp:2166
QList< TemplateList * > templates()
Return all template FileNames.
Definition: Project.cpp:2145
static QString userName()
the user name.
Definition: Environment.cpp:66
void clean()
Cleans directory of everything to do with the current project.
Definition: Directory.cpp:303
QUndoStack * undoStack()
Returns the Projects stack of QUndoCommands.
Definition: Project.cpp:1694
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
List for holding TargetBodies.
bool isTemporaryProject() const
Returns if the project is a temp project or not.
Definition: Project.cpp:1567
bool hasCamera(QString id)
This method checks for the existence of a camera based on InstrumentId.
Definition: Project.cpp:2745
void imagesReady(ImageList)
Prepare new images for opening.
Definition: Project.cpp:2666
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
void removeAt(int i)
Removes the image at an index.
Definition: ImageList.cpp:321
QString imageDataRoot() const
Accessor for the root directory of the image data.
Definition: Project.cpp:2077
ShapeList * shapeList(QString name)
Return a shapelist given its name.
Definition: Project.cpp:1549
void clear()
Function to clear out all values in a project essentially making it a new project object...
Definition: Project.cpp:459
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:171
Container class for GuiCamera.
Definition: GuiCamera.h:72
Control * activeControl()
Return the Active Control (control network)
Definition: Project.cpp:1903
void addTemplates(TemplateList *templateFiles)
Add new templates to m_mapTemplates or m_regTemplates and update project item model.
Definition: Project.cpp:1113
void saveHistory(QXmlStreamWriter &stream) const
Serialize the work orders into the given XML.
Definition: Project.cpp:851
void projectLoaded(Project *)
Emitted when project loaded receivers: IpceMainWindow, Directory, HistoryTreeWidget.
QList< ImageList * > images()
Return projects imagelist.
Definition: Project.cpp:2115
void workOrderStarting(WorkOrder *)
Emitted when work order starts.
ImageList * imageList() const
Returns the ImageList stored in the data of the item.
void waitForShapeReaderFinished()
Locks program if another spot in code is still running and called this function.
Definition: Project.cpp:1740
void setName(QString newName)
Set the human-readable name of this shape list.
Definition: ShapeList.cpp:548
QList< ImageList * > adjustedImages() const
Returns the list of images that were adjusted after a bundle.
void createFolders()
This creates the project root, image root, and control net root directories.
Definition: Project.cpp:384
void relocateProjectRoot(QString newRoot)
This is called when the project is moved.
Definition: Project.cpp:2305
void setActiveControl(QString displayName)
Set the Active Control (control network)
Definition: Project.cpp:1819
QList< TemplateList * > mapTemplates()
Return map template FileNames.
Definition: Project.cpp:2156
ProjectItem * findItemData(const QVariant &data, int role=Qt::UserRole+1)
Returns the first item found that contains the given data in the given role or a null pointer if no i...
void addBundleSolutionInfo(BundleSolutionInfo *bundleSolutionInfo)
Add the given BundleSolutionInfo to the current project.
Definition: Project.cpp:1194
virtual void redo()
Starts (or enqueues) a redo.
Definition: WorkOrder.cpp:1057
QMutex * workOrderMutex()
This function returns a QMutex.
Definition: Project.cpp:2986
bool isModified()
Has this control been modified?
Definition: Control.cpp:221
void clear()
Clears the list.
void saveWarnings(QXmlStreamWriter &stream) const
Serialize the warnings into the given XML.
Definition: Project.cpp:874
Directory * directory() const
Returns the directory associated with this Project.
Definition: Project.cpp:1229
void checkControlsAndImagesAvailable()
Checks if at least one control and image have been added to the project.
Definition: Project.cpp:1784
ProjectItemModel * model()
Gets the ProjectItemModel for this directory.
Definition: Directory.cpp:1105
void addToProject(WorkOrder *)
This executes the WorkOrder and stores it in the project.
Definition: Project.cpp:2598
void imageClosed(QObject *image)
An image is being deleted from the project.
Definition: Project.cpp:2802
Provide Undo/redo abilities, serialization, and history for an operation.
Definition: WorkOrder.h:322
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void removeAt(int i)
Removes the shape at an index.
Definition: ShapeList.cpp:315
bool isSavedToHistory() const
Returns true if this work order is to be shown in History, otherwise false.
Definition: WorkOrder.cpp:844
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
Definition: Project.cpp:2097
void bundleSolutionInfoAdded(BundleSolutionInfo *bundleSolutionInfo)
Emitted when new BundleSolutionInfo available from jigsaw receivers: ProjectTreeWidget (TODO: should ...
bool write()
Write control net to disk.
Definition: Control.cpp:183
void shapeListDeleted(QObject *shapeList)
A shape model list is being deleted from the project.
Definition: Project.cpp:2856
void shapeClosed(QObject *shape)
A shape model is being deleted from the project.
Definition: Project.cpp:2954
QSharedPointer< TargetBody > TargetBodyQsp
Defines A smart pointer to a TargetBody obj.
Definition: TargetBody.h:231
void cnetModified()
When a cnet is modified, set the project state to not clean.
Definition: Project.cpp:1924
bool createsCleanState() const
Returns the CleanState status (whether the Project has been saved to disk or not).
Definition: WorkOrder.cpp:868
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
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 activeImageListSet()
Emitted when an active image list is set.
void deleteAllProjectFiles()
Delete all of the files, that this project stores, from disk.
Definition: Project.cpp:2251
virtual void pushContentHandler(XmlStackedHandler *newHandler)
Push a contentHandler and maybe continue parsing...
void loadBundleSolutionInfo(BundleSolutionInfo *bundleSolutionInfo)
Loads bundle solution info into project.
Definition: Project.cpp:1210
TargetBodyList targetBodies()
Return TargetBodyList in Project.
Definition: Project.cpp:2194
virtual void execute()
Execute the workorder.
Definition: WorkOrder.cpp:1417
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:636
ImageList * activeImageList()
Returns the active ImageList.
Definition: Project.cpp:2003
virtual bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
The xml parser for ending tags.
Definition: Project.cpp:3072
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
QString original() const
Returns the full file name including the file path.
Definition: FileName.cpp:228
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:107
WorkOrder * previous() const
Gets the previous WorkOrder.
Definition: WorkOrder.cpp:958
void setPath(QString newPath)
Set the relative path (from the project root) to this image list&#39;s folder.
Definition: ImageList.cpp:714
QDir addBundleSolutionInfoFolder(QString folder)
Create and return the name of a folder for placing BundleSolutionInfo.
Definition: Project.cpp:1174
QString projectRoot() const
Get the top-level folder of the project.
Definition: Project.cpp:1666
void projectRelocated(Project *)
Emitted when project location moved receivers: Control, BundleSolutionInfo, Image, TargetBody.
QString id() const
Get a unique, identifying string associated with this shape.
Definition: Shape.cpp:460
void imageListDeleted(QObject *imageList)
An image list is being deleted from the project.
Definition: Project.cpp:2822
void SetImages(const QString &imageListFile)
Creates the ControlNet&#39;s image cameras based on an input file.
void addShapes(QStringList shapeFiles)
Read the given shape model cube file names as Images and add them to the project. ...
Definition: Project.cpp:1089
void append(Image *const &value)
Appends an image to the image list.
Definition: ImageList.cpp:153
ControlNet * controlNet()
Open and return a pointer to the ControlNet for this Control.
Definition: Control.cpp:142
QList< QAction * > userPreferenceActions()
Get a list of configuration/settings actions related to reading images into this Project.
Definition: Project.cpp:916
QList< ControlList * > controls()
Return controls in project.
Definition: Project.cpp:2038
Image * image(QString id)
Return an image given its id.
Definition: Project.cpp:1509
void shapesAdded(ShapeList *shapes)
Emitted when new shape model images are available.
QString newProjectRoot() const
Get the top-level folder of the new project.
Definition: Project.cpp:1675
void addImages(QStringList imageFiles)
Read the given cube file names as Images and add them to the project.
Definition: Project.cpp:1032
QString name() const
Get the project&#39;s GUI name.
Definition: Project.cpp:1625
This class is used to create and store valid Isis3 targets.
Definition: Target.h:76
QString templateRoot() const
Accessor for the root directory of the template data.
Definition: Project.cpp:2135
bool isUndoing() const
Returns the WorkOrderUndoing state.
Definition: WorkOrder.cpp:917
QDir addShapeFolder(QString prefix)
Create and return the name of a folder for placing shape models.
Definition: Project.cpp:1060
List of GuiCameras saved as QSharedPointers.
Definition: GuiCameraList.h:35
bool isControl() const
Returns true if a Control is stored in the data of the item.
int m_numImagesCurrentlyReading
used to negate segfaults happening in post undos when clearning project
Definition: Project.h:668
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
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.
bool save()
Generic save method to save the state of the project.
Definition: Project.cpp:2324
void setActiveImageList(QString displayName)
Set the Active ImageList from the displayName which is saved in project.xml.
Definition: Project.cpp:1955
QList< BundleSolutionInfo * > bundleSolutionInfo()
Return BundleSolutionInfo objects in Project.
Definition: Project.cpp:2223
QSharedPointer< GuiCamera > GuiCameraQsp
GuiCameraQsp Represents a smart pointer to a GuiCamera object.
Definition: GuiCamera.h:186
void cnetSaved(bool value)
Emmited in save() when the project is being saved Connected to Directory so that ControlPointEditWidg...
void setName(QString newName)
Change the project&#39;s name (GUI only, doesn&#39;t affect location on disk).
Definition: Project.cpp:1684
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition: FileName.cpp:531
QString name() const
Get the human-readable name of this control list.
QString toString() const
Returns a string representation of this exception.
Definition: IException.cpp:553
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void activeControlSet(bool boolean)
Emitted when an active control is set.
Every display property for footprint views, provided for convenience.
This represents a shape in a project-based GUI interface.
Definition: Shape.h:78
void bundleSolutionInfoClosed(QObject *bundleSolutionInfo)
A BundleSolutionInfo object is being deleted from the project.
Definition: Project.cpp:2867
QString resultsRoot() const
Accessor for the root directory of the results data.
Definition: Project.cpp:2214
void workOrderFinished(WorkOrder *)
Emitted when work order ends.
Control * control() const
Returns the Control stored in the data of the item.
QString id() const
Get a unique, identifying string associated with this image.
Definition: Image.cpp:445
Represents an item of a ProjectItemModel in Qt&#39;s model-view framework.
Definition: ProjectItem.h:146
QString type() const
Get the type of template in this TemplateList.
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:651
bool isUndone() const
Returns the WorkOrder undo status.
Definition: WorkOrder.cpp:927
void append(GuiCameraQsp const &value)
Appends a single GuiCamera to the list.
Isis exception class.
Definition: IException.h:107
void clear()
clears the list.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
QString name() const
Get the human-readable name of this shape list.
Definition: ShapeList.cpp:569
void setNext(WorkOrder *nextWorkOrder)
Sets the next WorkOrder in the sequence.
Definition: WorkOrder.cpp:627
void setPath(QString newPath)
Set the relative path (from the project root) to this control list&#39;s folder.
QString bundleSolutionInfoRoot() const
Accessor for the root directory of the results data.
Definition: Project.cpp:2243
void targetsAdded(TargetBodyList *targets)
Emitted when new TargetBody objects added to project receivers: Directory.
QDir addTemplateFolder(QString prefix)
Create and navigate to the appropriate template type folder in the project directory.
Definition: Project.cpp:1134
QString id() const
Access the unique ID associated with this Control.
Definition: Control.cpp:274
void deleteFromDisk(Project *project)
Delete all of the contained Controls from disk.
void setName(QString newName)
Set the human-readable name of this image list.
Definition: ImageList.cpp:703
Manage a stack of content handlers for reading XML files.
QDir addCnetFolder(QString prefix)
Create and return the name of a folder for placing control networks.
Definition: Project.cpp:926
QString fileName() const
Access the name of the control network file associated with this Control.
Definition: Control.cpp:264
bool isUndoable() const
Returns true if this work order is undoable, otherwise false.
Definition: WorkOrder.cpp:833
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
bool isOpen()
Accessor to determine whether a current project is Open.
Definition: Project.cpp:1575
void closeCube()
Cleans up the Cube pointer.
Definition: Image.cpp:307
void save(QXmlStreamWriter &stream) const
: Saves a WorkOrder to a data stream.
Definition: WorkOrder.cpp:558
void setClean(bool value)
Function to change the clean state of the project.
Definition: Project.cpp:1595
bool m_isClean
used to determine whether a project is currently open
Definition: Project.h:666
IO Handler for Isis Cubes.
Definition: Cube.h:170
ImageList * imageList(QString name)
Return an imagelist given its name.
Definition: Project.cpp:1520
Project(Directory &directory, QObject *parent=0)
Create a new Project.
Definition: Project.cpp:88