USGS

Isis 3.0 Object Programmers' Reference

Home

Directory.cpp
Go to the documentation of this file.
1 
23 #include "Directory.h"
24 
25 #include <QtDebug>
26 
27 #include <QAction>
28 #include <QApplication>
29 #include <QDockWidget>
30 #include <QGridLayout>
31 #include <QMenu>
32 #include <QMenuBar>
33 #include <QSettings>
34 #include <QSplitter>
35 #include <QStringList>
36 #include <QXmlStreamWriter>
37 
39 #include "CnetEditorWidget.h"
40 #include "Control.h"
42 #include "ControlList.h"
44 #include "ExportControlNetWorkOrder.h"
45 #include "ExportImagesWorkOrder.h"
46 #include "FileName.h"
48 #include "HistoryTreeWidget.h"
49 #include "IException.h"
50 #include "IString.h"
53 #include "ImportImagesWorkOrder.h"
54 #include "ImageFileListWidget.h"
55 #include "MosaicSceneWidget.h"
56 #include "OpenProjectWorkOrder.h"
57 #include "Project.h"
58 #include "ProjectTreeWidget.h"
59 #include "RenameProjectWorkOrder.h"
60 #include "SaveProjectWorkOrder.h"
61 #include "SaveProjectAsWorkOrder.h"
62 #include "WarningTreeWidget.h"
63 #include "WorkOrder.h"
64 #include "Workspace.h"
65 #include "XmlStackedHandler.h"
66 #include "XmlStackedHandlerReader.h"
67 
68 namespace Isis {
69 
70  Directory::Directory(QObject *parent) : QObject(parent) {
71 
72  try {
73  m_project = new Project(*this);
74  }
75  catch (IException &e) {
76  throw IException(e, IException::Programmer,
77  "Could not create directory because Project could not be created.",
78  _FILEINFO_);
79  }
80 
81  connect(m_project, SIGNAL(imagesAdded(ImageList *)),
82  this, SLOT(imagesAddedToProject(ImageList *)));
83 
84  m_projectTreeWidget = new ProjectTreeWidget(this);
85 
86  try {
87  createWorkOrder<CnetEditorViewWorkOrder>();
88  createWorkOrder<CubeViewportViewWorkOrder>();
89  createWorkOrder<Footprint2DViewWorkOrder>();
90  createWorkOrder<ImageFileListViewWorkOrder>();
91 
92  m_exportControlNetWorkOrder = createWorkOrder<ExportControlNetWorkOrder>();
93  m_exportImagesWorkOrder = createWorkOrder<ExportImagesWorkOrder>();
94  m_importControlNetWorkOrder = createWorkOrder<ImportControlNetWorkOrder>();
95  m_importImagesWorkOrder = createWorkOrder<ImportImagesWorkOrder>();
96  m_openProjectWorkOrder = createWorkOrder<OpenProjectWorkOrder>();
97  m_saveProjectWorkOrder = createWorkOrder<SaveProjectWorkOrder>();
98  m_saveProjectAsWorkOrder = createWorkOrder<SaveProjectAsWorkOrder>();
99 
100  m_renameProjectWorkOrder = createWorkOrder<RenameProjectWorkOrder>();
101  }
102  catch (IException &e) {
103  throw IException(e, IException::Programmer,
104  "Could not create directory because work orders are corrupt.",
105  _FILEINFO_);
106  }
107  }
108 
109 
110  Directory::~Directory() {
111  delete m_projectTreeWidget;
112  delete m_project;
113 
114  foreach (WorkOrder *workOrder, m_workOrders) {
115  delete workOrder;
116  }
117 
118  m_workOrders.clear();
119  }
120 
121 
122  void Directory::populateMainMenu(QMenuBar *menuBar) {
123  QMenu *fileMenu = menuBar->findChild<QMenu *>("fileMenu");
124  if (fileMenu) {
125  fileMenu->addAction(m_importControlNetWorkOrder->clone());
126  fileMenu->addAction(m_importImagesWorkOrder->clone());
127  fileMenu->addSeparator();
128  fileMenu->addAction(m_openProjectWorkOrder->clone());
129  fileMenu->addSeparator();
130 
131  QAction *saveAction = m_saveProjectWorkOrder->clone();
132  saveAction->setShortcut(Qt::Key_S | Qt::CTRL);
133 
134  connect(project()->undoStack(), SIGNAL(cleanChanged(bool)),
135  saveAction, SLOT(setDisabled(bool)));
136 
137  fileMenu->addAction(saveAction);
138 
139  fileMenu->addAction(m_saveProjectAsWorkOrder->clone());
140 
141  fileMenu->addSeparator();
142  fileMenu->addAction(m_exportControlNetWorkOrder->clone());
143  fileMenu->addAction(m_exportImagesWorkOrder->clone());
144  fileMenu->addSeparator();
145  }
146 
147  QMenu *projectMenu = menuBar->findChild<QMenu *>("projectMenu");
148  if (projectMenu) {
149  projectMenu->addAction(m_renameProjectWorkOrder->clone());
150  }
151  }
152 
153 
154  void Directory::setHistoryContainer(QDockWidget *historyContainer) {
155  if (!m_historyTreeWidget) {
156  m_historyTreeWidget = new HistoryTreeWidget(project());
157  }
158  historyContainer->setWidget(m_historyTreeWidget);
159  }
160 
161 
162  void Directory::setWarningContainer(QDockWidget *warningContainer) {
163  if (!m_warningTreeWidget) {
164  m_warningTreeWidget = new WarningTreeWidget;
165  }
166  warningContainer->setWidget(m_warningTreeWidget);
167  }
168 
169 
170  CnetEditorWidget *Directory::addCnetEditorView(Control *network) {
171  QString title = tr("Cnet Editor View %1").arg(network->displayProperties()->displayName());
172 
173  FileName configFile("$HOME/.Isis/" + QApplication::applicationName() + "/" + title + ".config");
174 
175  // TODO: This layout should be inside of the cnet editor widget, but I put it here to not
176  // conflict with current work in the cnet editor widget code.
177  QWidget *result = new QWidget;
178  QGridLayout *resultLayout = new QGridLayout;
179  result->setLayout(resultLayout);
180 
181  int row = 0;
182 
183  QMenuBar *menuBar = new QMenuBar;
184  resultLayout->addWidget(menuBar, row, 0, 1, 2);
185  row++;
186 
187  CnetEditorWidget *mainWidget =
188  new CnetEditorWidget(network->controlNet(), configFile.expanded());
189  resultLayout->addWidget(mainWidget, row, 0, 1, 2);
190  row++;
191 
192  // Populate the menu...
193  QMap< QAction *, QList< QString > > actionMap = mainWidget->menuActions();
194  QMapIterator< QAction *, QList< QString > > actionMapIterator(actionMap);
195 
196  QMap<QString, QMenu *> topLevelMenus;
197 
198  while (actionMapIterator.hasNext()) {
199  actionMapIterator.next();
200  QAction *actionToAdd = actionMapIterator.key();
201  QList< QString > location = actionMapIterator.value();
202 
203  QMenu *menuToPutActionInto = NULL;
204 
205  if (location.count()) {
206  QString topLevelMenuTitle = location.takeFirst();
207  if (!topLevelMenus[topLevelMenuTitle]) {
208  topLevelMenus[topLevelMenuTitle] = menuBar->addMenu(topLevelMenuTitle);
209  }
210 
211  menuToPutActionInto = topLevelMenus[topLevelMenuTitle];
212  }
213 
214  foreach (QString menuName, location) {
215  bool foundSubMenu = false;
216  foreach (QAction *possibleSubMenu, menuToPutActionInto->actions()) {
217  if (!foundSubMenu &&
218  possibleSubMenu->menu() && possibleSubMenu->menu()->title() == menuName) {
219  foundSubMenu = true;
220  menuToPutActionInto = possibleSubMenu->menu();
221  }
222  }
223 
224  if (!foundSubMenu) {
225  menuToPutActionInto = menuToPutActionInto->addMenu(menuName);
226  }
227  }
228 
229  menuToPutActionInto->addAction(actionToAdd);
230  }
231 
232  QTabWidget *treeViews = new QTabWidget;
233  treeViews->addTab(mainWidget->pointTreeView(), tr("Point View"));
234  treeViews->addTab(mainWidget->serialTreeView(), tr("Serial View"));
235  treeViews->addTab(mainWidget->connectionTreeView(), tr("Connection View"));
236  resultLayout->addWidget(treeViews, row, 0, 1, 1);
237 
238  QTabWidget *filterViews = new QTabWidget;
239  filterViews->addTab(mainWidget->pointFilterWidget(), tr("Filter Points and Measures"));
240  filterViews->addTab(mainWidget->serialFilterWidget(), tr("Filter Images and Points"));
241  filterViews->addTab(mainWidget->connectionFilterWidget(), tr("Filter Connections"));
242  resultLayout->addWidget(filterViews, row, 1, 1, 1);
243  row++;
244 
245  connect(result, SIGNAL(destroyed(QObject *)),
246  this, SLOT(cleanupCnetEditorViewWidgets()));
247 
248  m_cnetEditorViewWidgets.append(mainWidget);
249 
250  result->setWindowTitle(title);
251  result->setObjectName(title);
252 
253  emit newWidgetAvailable(result, Qt::RightDockWidgetArea, Qt::Horizontal);
254 
255  return mainWidget;
256  }
257 
258 
259  Workspace *Directory::addCubeDnView() {
260  Workspace *result = new Workspace(true);
261 
262  connect(result, SIGNAL(destroyed(QObject *)),
263  this, SLOT(cleanupCubeDnViewWidgets()));
264 
265  m_cubeDnViewWidgets.append(result);
266 
267  result->setWindowTitle(tr("Cube DN View %1").arg(m_cubeDnViewWidgets.count()));
268  result->setObjectName(result->windowTitle());
269 
270  emit newWidgetAvailable(result, Qt::RightDockWidgetArea, Qt::Horizontal);
271 
272  return result;
273  }
274 
275 
276  MosaicSceneWidget *Directory::addFootprint2DView() {
277  MosaicSceneWidget *result = new MosaicSceneWidget(NULL, true, true, this);
278 
279  connect(result, SIGNAL(destroyed(QObject *)),
280  this, SLOT(cleanupFootprint2DViewWidgets()));
281 
282  m_footprint2DViewWidgets.append(result);
283 
284  result->setWindowTitle(tr("Footprint View %1").arg(m_footprint2DViewWidgets.count()));
285  result->setObjectName(result->windowTitle());
286 
287  emit newWidgetAvailable(result, Qt::RightDockWidgetArea, Qt::Horizontal);
288 
289  return result;
290  }
291 
292 
293  ImageFileListWidget *Directory::addImageFileListView() {
294  ImageFileListWidget *result = new ImageFileListWidget(this);
295 
296  connect(result, SIGNAL(destroyed(QObject *)),
297  this, SLOT(cleanupFileListWidgets()));
298 
299  m_fileListWidgets.append(result);
300 
301  result->setWindowTitle(tr("File List %1").arg(m_fileListWidgets.count()));
302  result->setObjectName(result->windowTitle());
303 
304  emit newWidgetAvailable(result, Qt::LeftDockWidgetArea, Qt::Horizontal);
305 
306  return result;
307  }
308 
309 
310  QWidget *Directory::warningWidget() {
311  return m_warningTreeWidget;
312  }
313 
314 
315  QWidget *Directory::projectTreeWidget() {
316  return m_projectTreeWidget;
317  }
318 
319 
320  void Directory::cleanupCnetEditorViewWidgets() {
321  m_cnetEditorViewWidgets.removeAll(NULL);
322  }
323 
324 
325  void Directory::cleanupCubeDnViewWidgets() {
326  m_cubeDnViewWidgets.removeAll(NULL);
327  }
328 
329 
330  void Directory::cleanupFileListWidgets() {
331  m_fileListWidgets.removeAll(NULL);
332  }
333 
334 
335  void Directory::cleanupFootprint2DViewWidgets() {
336  m_footprint2DViewWidgets.removeAll(NULL);
337  }
338 
339 
340  void Directory::imagesAddedToProject(ImageList *imageList) {
341  m_projectTreeWidget->addImageGroup(imageList);
342  }
343 
344 
345  Project *Directory::project() const {
346  return m_project;
347  }
348 
349 
350  QList<CnetEditorWidget *> Directory::cnetEditorViews() {
352 
353  foreach (CnetEditorWidget *widget, m_cnetEditorViewWidgets) {
354  results.append(widget);
355  }
356 
357  return results;
358  }
359 
360 
361  QList<Workspace *> Directory::cubeDnViews() {
362  QList<Workspace *> results;
363 
364  foreach (Workspace *widget, m_cubeDnViewWidgets) {
365  results.append(widget);
366  }
367 
368  return results;
369  }
370 
371 
372  QList<MosaicSceneWidget *> Directory::footprint2DViews() {
374 
375  foreach (MosaicSceneWidget *widget, m_footprint2DViewWidgets) {
376  results.append(widget);
377  }
378 
379  return results;
380  }
381 
382 
383  QList<ImageFileListWidget *> Directory::imageFileListViews() {
385 
386  foreach (ImageFileListWidget *widget, m_fileListWidgets) {
387  results.append(widget);
388  }
389 
390  return results;
391  }
392 
393 
394  QList<QProgressBar *> Directory::progressBars() {
395  QList<QProgressBar *> result;
396  return result;
397  }
398 
399 
400  void Directory::showWarning(QString text) {
401  m_warningTreeWidget->showWarning(text);
402  }
403 
404 
405  QAction *Directory::redoAction() {
406  return project()->undoStack()->createRedoAction(this);
407  }
408 
409 
410  QAction *Directory::undoAction() {
411  return project()->undoStack()->createUndoAction(this);
412  }
413 
414 
415  void Directory::load(XmlStackedHandlerReader *xmlReader) {
416  xmlReader->pushContentHandler(new XmlHandler(this));
417  }
418 
419 
420  void Directory::save(QXmlStreamWriter &stream, FileName newProjectRoot) const {
421  stream.writeStartElement("directory");
422 
423  if (!m_fileListWidgets.isEmpty()) {
424  stream.writeStartElement("fileListWidgets");
425 
426  foreach (ImageFileListWidget *fileListWidget, m_fileListWidgets) {
427  fileListWidget->save(stream, project(), newProjectRoot);
428  }
429 
430  stream.writeEndElement();
431  }
432 
433 
434  if (!m_footprint2DViewWidgets.isEmpty()) {
435  stream.writeStartElement("footprintViews");
436 
437  foreach (MosaicSceneWidget *footprint2DViewWidget, m_footprint2DViewWidgets) {
438  footprint2DViewWidget->save(stream, project(), newProjectRoot);
439  }
440 
441  stream.writeEndElement();
442  }
443 
444  stream.writeEndElement();
445  }
446 
447 
448  Directory::XmlHandler::XmlHandler(Directory *directory) {
449  m_directory = directory;
450  }
451 
452 
453  Directory::XmlHandler::~XmlHandler() {
454  }
455 
456 
457  bool Directory::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
458  const QString &qName, const QXmlAttributes &atts) {
459  bool result = XmlStackedHandler::startElement(namespaceURI, localName, qName, atts);
460 
461  if (result) {
462  if (localName == "footprint2DView") {
463  m_directory->addFootprint2DView()->load(reader());
464  }
465  else if (localName == "imageFileList") {
466  m_directory->addImageFileListView()->load(reader());
467  }
468  }
469 
470  return result;
471  }
472 
473 
532  QList< QPair< QString, QList<QAction *> > > actionPairings) {
533  QList<QAction *> results;
534 
535  QStringList sortedActionTexts;
536 
537  // This is a map from the Action Text to the actions and their widget titles
539 
540  QPair< QString, QList<QAction *> > singleWidgetPairing;
541  foreach (singleWidgetPairing, actionPairings) {
542  QString widgetTitle = singleWidgetPairing.first;
543  QList<QAction *> widgetActions = singleWidgetPairing.second;
544 
545  foreach (QAction *widgetAction, widgetActions) {
546  if (widgetAction) {
547  QString actionText = widgetAction->text();
548 
549  restructuredData[actionText].append(qMakePair(widgetTitle, widgetAction));
550 
551  if (!sortedActionTexts.contains(actionText)) {
552  sortedActionTexts.append(actionText);
553  }
554  }
555  else {
556  // Add separator
557  if (!sortedActionTexts.isEmpty() && !sortedActionTexts.last().isEmpty()) {
558  sortedActionTexts.append("");
559  }
560  }
561  }
562  }
563 
564  if (sortedActionTexts.count() && sortedActionTexts.last().isEmpty()) {
565  sortedActionTexts.removeLast();
566  }
567 
568  foreach (QString actionText, sortedActionTexts) {
569  if (actionText.isEmpty()) {
570  results.append(NULL);
571  }
572  else {
573  // We know this list isn't empty because we always appended to the value when we
574  // accessed a particular key.
575  QList< QPair<QString, QAction *> > actions = restructuredData[actionText];
576 
577  if (actions.count() == 1) {
578  QAction *finalAct = actions.first().second;
579  QString widgetTitle = actions.first().first;
580 
581  finalAct->setText(tr("%1 on %2").arg(actionText).arg(widgetTitle));
582  results.append(finalAct);
583  }
584  else {
585  QAction *menuAct = new QAction(actionText, NULL);
586 
587  QMenu *menu = new QMenu;
588  menuAct->setMenu(menu);
589 
590  QList<QAction *> actionsInsideMenu;
591 
592  QPair<QString, QAction *> widgetTitleAndAction;
593  foreach (widgetTitleAndAction, actions) {
594  QString widgetTitle = widgetTitleAndAction.first;
595  QAction *action = widgetTitleAndAction.second;
596 
597  action->setText(widgetTitle);
598  actionsInsideMenu.append(action);
599  }
600 
601  qSort(actionsInsideMenu.begin(), actionsInsideMenu.end(), &actionTextLessThan);
602 
603  QAction *allAct = new QAction(tr("All"), NULL);
604 
605  foreach (QAction *actionInMenu, actionsInsideMenu) {
606  connect(allAct, SIGNAL(triggered()), actionInMenu, SIGNAL(triggered()));
607  menu->addAction(actionInMenu);
608  }
609 
610  menu->addSeparator();
611  menu->addAction(allAct);
612 
613  results.append(menuAct);
614  }
615  }
616  }
617 
618  return results;
619  }
620 
621 
622  bool Directory::actionTextLessThan(QAction *lhs, QAction *rhs) {
623  return lhs->text().localeAwareCompare(rhs->text()) < 0;
624  }
625 }