SMILX  1.01
milxQtMain.cpp
1 /*=========================================================================
2  The Software is copyright (c) Commonwealth Scientific and Industrial Research Organisation (CSIRO)
3  ABN 41 687 119 230.
4  All rights reserved.
5 
6  Licensed under the CSIRO BSD 3-Clause License
7  You may not use this file except in compliance with the License.
8  You may obtain a copy of the License in the file LICENSE.md or at
9 
10  https://stash.csiro.au/projects/SMILI/repos/smili/browse/license.txt
11 
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 =========================================================================*/
18 #include "milxQtMain.h"
19 //Qt
20 
21 //VTK
22 #include <vtkWindowToImageFilter.h>
23 #include <vtkRendererCollection.h>
24 #include <vtkCamera.h>
25 #include <vtkLookupTable.h>
26 #include <vtkImageBlend.h>
27 #include <vtkTensor.h>
28 #include <vtkMultiThreader.h>
29 #include <vtkMath.h>
30 //milxQt
31 #include "milxQtFile.h"
32 #include "milxQtPlot.h"
33 
34 //Forms
35 #include "milxQtAboutForm.h"
36 #include "milxQtPreferencesForm.h"
37 
38 milxQtMain::milxQtMain(QWidget *theParent) : QMainWindow(theParent)
39 {
40  debugMode = true;
41 
42  //Settings
43  whiteBackground = false;
44  humanGlyph = true;
45  subWindowSize = minWindowSize*2;
47  if(maxProcessors > 1)
49  magnifyFactor = 1;
50  timestamping = true;
51  interpolationImages = true;
52  orientationImages = true;
53  interpolationModels = false;
54  scalarBarModels = false;
55 
57  windowIterator = 0;
58 
59  saveSupport = extensionsSave.c_str();
60  openSupport = extensionsOpen.c_str();
61 
63  currentUnifiedWindow->setName("Multi-Display");
64  currentUnifiedWindow->setDeletableOnClose(false);
65 
66  Connector = vtkSmartPointer<vtkEventQtSlotConnect>::New();
67 
69  linkProgressEventOf(milx::ProgressUpdates->GetUpdateObject()); //link itk observer propagator
70  linkProgressEventOf(milx::VTKProgressUpdates->GetUpdateObject()); //link itk observer propagator
71 
73  workspaces = new QTabWidget;
74  workspaces->setTabsClosable(true);
75  newTab();
76  QMainWindow::setCentralWidget(workspaces); //Hierachy deletion
77  windowMapper = new QSignalMapper(this);
78 
80  console = new milxQtConsole;
81  actionConsole = console->dockWidget()->toggleViewAction();
82  actionConsole->setIcon(QIcon(":/resources/toolbar/console.png"));
83  dockActions.append(actionConsole);
84  QObject::connect(console->dockWidget(), SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), console, SLOT(setDockDefaultArea(Qt::DockWidgetArea)));
85  addDockWidget(console->dockDefaultArea(), console->dockWidget());
86  console->show();
87 
89  createMenu();
91 
94 
97 
99  setupTooltips();
100 
102  loadPlugins();
103 
106 
107  setAcceptDrops(true);
108 
109  setToolTip("<p style='white-space:pre'>Welcome to SMILX. Use the <b>context menu</b> (right click) for all operations.\n Load data from the <b>File Menu</b>.</p>");
110 
112  readSettings();
113 
115  itk::MultiThreader::SetGlobalDefaultNumberOfThreads(maxProcessors);
116  vtkMultiThreader::SetGlobalDefaultNumberOfThreads(maxProcessors);
117 
119  printInfo("--------------------------------------------------------");
120  printInfo("sMILX Visualisation Tool for Medical Imaging");
121  printInfo("(c) Copyright CSIRO, 2015.");
122  printInfo("University of Queensland, Australia.");
123  printInfo("Australian e-Health Research Centre, CSIRO.");
124  printInfo("SMILI Version: " + QString::number(milx::Version));
125  printInfo("Application Version: " + QString::number(milxQtVersion));
126  printInfo("Processors to be used: " + QString::number(maxProcessors));
127  printInfo("--------------------------------------------------------\n");
128 
130 
131  update();
132 }
133 
135 {
136  foreach (QPointer<milxQtPluginInterface> loadedPlugin, plugins)
137  {
138  if(loadedPlugin->isThreaded() && loadedPlugin->isRunning())
139  loadedPlugin->quit();
140  }
141  plugins.clear();
142  renderExtsActions.clear();
143  modelExtsActions.clear();
144  imageExtsActions.clear();
145  dockActions.clear();
146 
147  modelWindows.clear();
148  imageWindows.clear();
149  printDebug("Main Destroyed.");
150 }
151 
153 {
154  if(qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow() == 0)
155  {
157  return 0;
158  }
159  else
160  {
161  if(isActiveImage())
162  {
163  milxQtImage *childImg = activeImage();
164  return childImg->strippedName();
165  }
166  else if(isActiveModel())
167  {
168  milxQtModel *childMdl = activeModel();
169  return childMdl->strippedName();
170  }
171  else if(isActiveRender())
172  {
173  milxQtRenderWindow *childRnd = activeRender();
174  return childRnd->strippedName();
175  }
176  else
177  return "Unrecognised Display";
178  }
179 }
180 
182 {
183  if(qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow() == 0)
184  {
186  return 0;
187  }
188  else
189  {
190  if(isActiveImage())
191  {
192  milxQtImage *childImg = activeImage();
193  return childImg->strippedNamePrefix();
194  }
195  else if(isActiveModel())
196  {
197  milxQtModel *childMdl = activeModel();
198  return childMdl->strippedNamePrefix();
199  }
200  else if(isActiveRender())
201  {
202  milxQtRenderWindow *childRnd = activeRender();
203  return childRnd->strippedNamePrefix();
204  }
205  else if(isActiveWebView())
206  {
207  QWebView *webViewer = activeWebView();
208  return webViewer->windowTitle();
209  }
210  else
211  return "Unrecognised Display";
212  }
213 }
214 
216 {
217  QWorkspace *tmpPtr = new QWorkspace;
218  workspaces->addTab(tmpPtr, tr("Empty"));
219  workspaces->setCurrentWidget(tmpPtr); //Hierachy deletion
220  tmpPtr->setAttribute(Qt::WA_DeleteOnClose);
221 
222  connect(tmpPtr, SIGNAL(windowActivated(QWidget *)), this, SLOT(setTabName(QWidget *)));
223  connect(tmpPtr, SIGNAL(windowActivated(QWidget *)), this, SLOT(redirectWindowActivated(QWidget *)));
224 }
225 
227 {
228  qobject_cast<QWorkspace *>(workspaces->currentWidget())->addWindow(rnd);
229 
231 
232  rnd->enableUpdates(statusBar());
233 
234  connect(rnd, SIGNAL(nameChanged(const QString &)), this, SLOT(setTabName(const QString &)));
235  connect(rnd, SIGNAL(working(int)), this, SLOT(working(int)));
236  connect(rnd, SIGNAL(done(int)), this, SLOT(done(int)));
237 }
238 
240 {
241  addRender(img);
242 }
243 
245 {
246  mdl->modelInfo();
247 
248  addRender(mdl);
249 }
250 
252 {
253  addRender(uni);
254 }
255 
256 void milxQtMain::cleanUpOnClose(QWidget *win)
257 {
258  if(isImage(win))
259  {
260  milxQtImage *img = qobject_cast<milxQtImage *>(win);
261  printInfo("Removing Image " + img->getName() + " from memory");
262  imageWindows.removeAll(img);
263  img->disconnect(); //disconnect all
265  currentUnifiedWindow->removeFromWindow(img);
266  }
267  else if(isModel(win))
268  {
269  milxQtModel *mdl = qobject_cast<milxQtModel *>(win);
270  printInfo("Removing Model " + mdl->getName() + " from memory");
271  modelWindows.removeAll(mdl);
272  mdl->disconnect(); //disconnect all
274  currentUnifiedWindow->removeFromWindow(mdl);
275  }
276 }
277 
278 //Slots
279 bool milxQtMain::isRender(QWidget *win)
280 {
281  if(qobject_cast<milxQtRenderWindow *>(win) == 0)
282  return false;
283  else
284  return true;
285 }
286 
288 {
289  if(activeRender() == 0)
290  return false;
291  else
292  return true;
293 }
294 
296 {
297  if(QWidget *activeWin = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow())
298  return qobject_cast<milxQtRenderWindow *>(activeWin);
299  return 0;
300 }
301 
302 bool milxQtMain::isImage(QWidget *win)
303 {
304  if(qobject_cast<milxQtImage *>(win) == 0)
305  return false;
306  else
307  return true;
308 }
309 
311 {
312  if(activeImage() == 0)
313  return false;
314  else
315  return true;
316 }
317 
319 {
320  if(QWidget *activeWin = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow())
321  return qobject_cast<milxQtImage *>(activeWin);
322  return 0;
323 }
324 
325 bool milxQtMain::isModel(QWidget *win)
326 {
327  if(qobject_cast<milxQtModel *>(win) == 0)
328  return false;
329  else
330  return true;
331 }
332 
334 {
335  if(activeModel() == 0)
336  return false;
337  else
338  return true;
339 }
340 
342 {
343  if(QWidget *activeWin = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow())
344  return qobject_cast<milxQtModel *>(activeWin);
345  return 0;
346 }
347 
348 bool milxQtMain::isPlot(QWidget *win)
349 {
350  if(qobject_cast<milxQtPlot *>(win) == 0)
351  return false;
352  else
353  return true;
354 }
355 
357 {
358  if(activePlot() == 0)
359  return false;
360  else
361  return true;
362 }
363 
365 {
366  if(QWidget *activeWin = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow())
367  return qobject_cast<milxQtPlot *>(activeWin);
368  return 0;
369 }
370 
371 bool milxQtMain::isUnifiedWindow(QWidget *win)
372 {
373  if(qobject_cast<milxQtUnifiedWindow *>(win) == 0)
374  return false;
375  else
376  return true;
377 }
378 
380 {
381  if(activeUnifiedWindow() == 0)
382  return false;
383  else
384  return true;
385 }
386 
388 {
389  if(QWidget *activeWin = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow())
390  return qobject_cast<milxQtUnifiedWindow *>(activeWin);
391  return 0;
392 }
393 
395 {
396  if(activeWebView() == 0)
397  return false;
398  else
399  return true;
400 }
401 
403 {
404  if(QWidget *activeWin = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow())
405  return qobject_cast<QWebView *>(activeWin);
406  return 0;
407 }
408 
410 {
411  if(!currentWindow)
412  return;
413  else
414  qobject_cast<QWorkspace *>(workspaces->currentWidget())->setActiveWindow(currentWindow);
415 }
416 
418 {
419  QFileDialog *fileOpener = new QFileDialog(this);
420  QSettings settings("Shekhar Chandra", "milxQt");
421 
422  //Add supported file entry
423  QString exts = "Supported Files (" + openSupport + ");;";
424  QString path = settings.value("recentPath").toString();
425 
426  exts += openExts.c_str();
427 
428  foreach (QPointer<milxQtPluginInterface> loadedPlugin, plugins)
429  {
430  if(loadedPlugin->openFileSupport() != "")
431  {
432  exts += ";;";
433  exts += loadedPlugin->openFileSupport();
434  }
435  }
436 
437  QStringList filenames = fileOpener->getOpenFileNames(this,
438  tr("Select File(s) to Open"),
439  path,
440  tr(exts.toStdString().c_str()) );
441 
442  if(filenames.isEmpty())
443  return false;
444 
445  loadFiles(filenames);
446 
447  return true;
448 }
449 
451 {
452  QPointer<milxQtFile> file = new milxQtFile;
453  QStringList filenames;
454 
455  /*QMessageBox msgBox;
456  msgBox.setText("Open an image (DICOM) series instead?");
457  msgBox.setInformativeText("Would you like to open an image (DICOM) series instead of a model collection?.");
458  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
459  msgBox.setDefaultButton(QMessageBox::No);
460  int ret = msgBox.exec();
461 
462  if(ret == QMessageBox::Yes)
463  {
464  printDebug("Opening Image Series.");
465  QPointer<milxQtFile> reader = new milxQtFile;
466  QPointer<milxQtImage> img = new milxQtImage; //list deletion
467 
468  printDebug("Supported Image formats: " + reader->supportedImageFormats());
469  bool success = reader->openImageCollection(img, filenames);
470 
471  if(success)
472  {
473  //name saved internally in openImageCollection
474  img->setConsole(console);
475  img->generateImage();
476 
477  predisplay(img); //do the multi-view stuff if requested
478  }
479  else
480  printError("File format didn't appear to be supported. Check the file or add plugins for support.");
481  }
482  else
483  {*/
484  vtkPolyDataCollection* modelCollection = vtkPolyDataCollection::New();
485 
486  if(!file->openModelCollection(modelCollection, filenames))
487  {
488  printError("Unable to read selected files.");
489  return;
490  }
491 
492  display(modelCollection, filenames);
493 // }
494 }
495 
497 {
498  QPointer<milxQtFile> reader = new milxQtFile;
499  QPointer<milxQtImage> img = new milxQtImage; //list deletion
500 
501  printDebug("Supported Image formats: " + reader->supportedImageFormats());
502  bool success = reader->openImageSeries(img);
503 
504  if(success)
505  {
506  //name saved internally in openImageCollection
507  img->setConsole(console);
508  img->generateImage();
509 
510  predisplay(img); //do the multi-view stuff if requested
511  }
512  else
513  printError("An error was encountered in reading the image series");
514 }
515 
517 {
518  QAction *action = qobject_cast<QAction *>(sender());
519  if(action)
520  loadFile(action->data().toString());
521 }
522 
523 void milxQtMain::loadFiles(const QStringList &filenames)
524 {
525  for(int j = 0; j < filenames.size(); j ++)
526  loadFile(filenames[j]);
527 }
528 
529 bool milxQtMain::loadFile(const QString &filename)
530 {
531  QPointer<milxQtFile> reader = new milxQtFile;
532  bool success = false;
533 
534  if (filename.isEmpty())
535  return success;
536 
537  //Convert string to native paths
538  QString nativeFilename = QDir::toNativeSeparators(filename);
539 
541  printDebug("Check Plugins if they can open the file.");
542  foreach (QPointer<milxQtPluginInterface> loadedPlugin, plugins)
543  {
544  if(!loadedPlugin->hasOpenSupport())
545  continue; //Skip trying to check
546 
547  QStringList extensionsList = loadedPlugin->openExtensions();
548 
549  foreach (QString extension, extensionsList)
550  {
551  printDebug("Exts: " + extension);
552  if(filename.contains(extension, Qt::CaseInsensitive))
553  {
554  loadedPlugin->setFileName(filename);
555  if(loadedPlugin->isThreaded())
556  {
557  printInfo("Using threaded opening for plugin.");
558  loadedPlugin->preStartTasks();
559  loadedPlugin->start();
560  //loadedPlugin->wait();
561  success = true;
562  }
563  else
564  {
565  printInfo("Using standard opening for plugin.");
566  loadedPlugin->open(nativeFilename);
567  }
568 
569  QPointer<milxQtRenderWindow> renWin = loadedPlugin->genericResult();
570  if(renWin)
571  {
572  printInfo("Loading Plugin Generic Result");
573  if(renWin->getName() == "")
574  renWin->setName(filename);
575  renWin->setConsole(console);
576  renWin->generateRender();
577  display(renWin);
578  success = true;
579  }
580 
581  QPointer<milxQtModel> model = loadedPlugin->modelResult();
582  if(model)
583  {
584  printInfo("Loading Plugin Model Result");
585  if(model->getName() == "")
586  model->setName(filename);
587  model->setConsole(console);
588  model->generateModel();
589  display(model);
590  success = true;
591  }
592 
593  QPointer<milxQtImage> image = loadedPlugin->imageResult();
594  if(image)
595  {
596  printInfo("Loading Plugin Image Result");
597  if(image->getName() == "")
598  image->setName(filename);
599  image->setConsole(console);
600  image->generateImage();
601  display(image);
602  success = true;
603  }
604  }
605 
606  if(success)
607  break;
608  }
609 
610  if(success && !loadedPlugin->isThreaded())
611  {
612  printInfo("Loaded File via Plugin, now Updating");
613  loadedPlugin->update();
614  setCurrentFile(nativeFilename);
615  return success;
616  }
617  }
618 
620  printDebug("File format not supported by plugins, load using standard methods.");
621  if(filename.contains(".vtp", Qt::CaseInsensitive) || filename.contains(".vtk", Qt::CaseInsensitive)
622  || filename.contains(".ply", Qt::CaseInsensitive) || filename.contains(".obj", Qt::CaseInsensitive) || filename.contains(".stl", Qt::CaseInsensitive))
623  {
624  printDebug("Opening Model.");
625  QPointer<milxQtModel> model = new milxQtModel; //list deletion
626  success = reader->openModel(nativeFilename, model);
627 
628  if(success)
629  {
630  model->setName(filename);
631  model->setConsole(console);
632  model->generateModel();
633  display(model);
634  }
635  }
636  else if(filename.contains(".csv", Qt::CaseInsensitive) || filename.contains(".dat", Qt::CaseInsensitive) || filename.contains(".txt", Qt::CaseInsensitive))
637  {
638  printDebug("Opening Text Delimited File.");
639  //Load the vertex table from CSV file
640  vtkSmartPointer<vtkTable> table;
641  QPointer<milxQtPlot> plot = new milxQtPlot;
642  success = milx::File::OpenDelimitedText(nativeFilename.toStdString(), table);
643 
644  int surfaceRet = QMessageBox::No, dimensionRet = QMessageBox::No;
645  int xCol = 0, yCol = 1, zCol = 2;
646  if(table->GetNumberOfColumns() > 2)
647  {
648  QMessageBox msgBox;
649  msgBox.setText("Choose Plot Type");
650  msgBox.setInformativeText("Do you want a surface plot instead of a scatter plot?");
651  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
652  msgBox.setDefaultButton(QMessageBox::No);
653  surfaceRet = msgBox.exec();
654 
655  if(surfaceRet == QMessageBox::No)
656  {
657  msgBox.setText("Choose Plot Dimension");
658  msgBox.setInformativeText("Do you want a 3D scatter plot?");
659  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
660  msgBox.setDefaultButton(QMessageBox::No);
661  dimensionRet = msgBox.exec();
662 
663  bool ok1 = true, ok2 = true, ok3 = true;
664  xCol = QInputDialog::getInt(this, tr("Please Provide column number for x axis"),
665  tr("Column:"), 0, 0, numeric_limits<int>::max(), 1, &ok1);
666  yCol = QInputDialog::getInt(this, tr("Please Provide column number for y axis"),
667  tr("Column:"), 1, 0, numeric_limits<int>::max(), 1, &ok2);
668 
669  if(dimensionRet == QMessageBox::Yes) //3D
670  {
671  zCol = QInputDialog::getInt(this, tr("Please Provide column number for z axis"),
672  tr("Column:"), 2, 0, numeric_limits<int>::max(), 1, &ok3);
673  }
674 
675  if(!ok1 || !ok2 || !ok3)
676  return success;
677 
678  if(dimensionRet == QMessageBox::No) //2D
679  plot->setPlotType2D(xCol, yCol);
680  else
681  plot->setPlotType3D(xCol, yCol, zCol);
682  }
683  else
684  {
685  plot->setPlotTypeSurface();
686  }
687  }
688 
689  //Connect for display
690  connect(plot, SIGNAL(resultAvailable(milxQtModel*)), this, SLOT(display(milxQtModel*)));
691  connect(plot, SIGNAL(resultAvailable(milxQtRenderWindow*)), this, SLOT(display(milxQtRenderWindow*)));
692 
693  if(success)
694  {
695  plot->setName(filename);
696  plot->setConsole(console);
697  plot->SetSource(table);
698  plot->generatePlot(); //emits result
699  }
700  }
701  else
702  {
703  printDebug("Opening Image.");
704  QPointer<milxQtImage> img = new milxQtImage; //list deletion
705 
706  printDebug("Supported Image formats: " + reader->supportedImageFormats());
707  success = reader->openImage(nativeFilename, img);
708 
709  printInfo("Image Pixel Type: " + reader->getPixelType());
710  printInfo("Image Component Type: " + reader->getComponentType());
711  printInfo("Image Number of Components: " + QString::number(reader->getNumberOfComponents()));
712  printInfo("Image Dimensions: " + QString::number(reader->getNumberOfDimensions()));
713 
714  if(success)
715  {
716  img->setName(filename);
717  img->setConsole(console);
718  img->generateImage();
719 
720  predisplay(img);
721  }
722  else
723  printError("File format didn't appear to be supported. Check the file or add plugins for support.");
724  }
725 
726  if(success)
727  setCurrentFile(nativeFilename);
728 
729  return success;
730 }
731 
732 void milxQtMain::save(QString filename)
733 {
734  QSettings settings("Shekhar Chandra", "milxQt");
735  QString path = settings.value("recentPath").toString();
736  QWidget *activeWindow = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow();
737  milxQtWindow *currentWindowOpen = qobject_cast<milxQtWindow *>(activeWindow);
738  bool pluginSave = false, success = false;
739 
740  if(!activeWindow)
741  return;
742 
743  //Convert string to native paths
744  filename = QDir::toNativeSeparators(filename);
745 
746  QFileDialog *fileSaver = new QFileDialog(this);
747 
749  foreach (QPointer<milxQtPluginInterface> loadedPlugin, plugins)
750  {
751  if(!loadedPlugin->hasSaveSupport())
752  continue;
753 
754  if(loadedPlugin->isPluginWindow(activeWindow))
755  {
756  printInfo("Window is a " + loadedPlugin->name() + " plugin window");
757  if(filename.isEmpty())
758  {
759  filename = fileSaver->getSaveFileName(this,
760  tr("Select File Name to Save"),
761  currentWindowOpen->getName(),
762  tr(loadedPlugin->saveFileSupport().toStdString().c_str()));
763  }
764 
765  if(!filename.isEmpty())
766  {
767  loadedPlugin->save(filename);
768  success = true;
769  }
770  pluginSave = true;
771  }
772  }
773 
774  if(!pluginSave)
775  {
776  if(isActiveImage())
777  {
778  printDebug("Saving Image with Built-in Capability");
779  milxQtImage* image = qobject_cast<milxQtImage *>(activeWindow);
780 
781  if(filename.isEmpty())
782  {
783  filename = fileSaver->getSaveFileName(this,
784  tr("Select File Name to Save"),
785  image->getName(),
786  tr(saveExtsForImages.c_str()));
787  }
788 
789  if(!filename.isEmpty())
790  {
791  image->setName(filename);
792  QPointer<milxQtFile> writer = new milxQtFile; //Smart deletion
793  writer->saveImage(filename, image);
794  success = true;
795  }
796  }
797  else if(isActivePlot())
798  {
799  printDebug("Saving Plot with Built-in Capability");
800  milxQtPlot* plot = qobject_cast<milxQtPlot *>(activeWindow);
801 
802  if(filename.isEmpty())
803  {
804  filename = fileSaver->getSaveFileName(this,
805  tr("Select File Name to Save"),
806  plot->getName(),
807  tr(saveOtherExts.c_str()));
808  }
809 
810  if(!filename.isEmpty())
811  {
812  plot->setName(filename);
813  success = milx::File::SaveDelimitedText(filename.toStdString(), plot->GetSource());
814  }
815  }
816  else if(isActiveModel())
817  {
818  printDebug("Saving Model with Built-in Capability");
819  milxQtModel* model = qobject_cast<milxQtModel *>(activeWindow);
820 
821  if(filename.isEmpty())
822  {
823  filename = fileSaver->getSaveFileName(this,
824  tr("Select File Name to Save"),
825  model->getName(),
826  tr(saveExtsForModels.c_str()));
827  }
828 
829  if(!filename.isEmpty())
830  {
831  model->setName(filename);
832  QPointer<milxQtFile> writer = new milxQtFile; //Smart deletion
833  writer->saveModel(filename, model, false);
834  success = true;
835  }
836  }
837  else
838  {
839  printError("Window not supported.");
840  return;
841  }
842  }
843 
844  if(success)
845  {
846  setCurrentFile(filename);
847  printInfo("Write Complete.");
848  }
849 }
850 
851 void milxQtMain::saveScreen(QString filename)
852 {
853  QSettings settings("Shekhar Chandra", "milxQt");
854  QString path = settings.value("recentPath").toString();
855  QWidget *activeWindow = qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow();
856 
857  //Convert string to native paths
858  filename = QDir::toNativeSeparators(filename);
859 
860  if(!activeWindow)
861  return;
862  else
863  {
864  QFileDialog *fileSaver = new QFileDialog(this);
865  vtkSmartPointer<vtkWindowToImageFilter> windowToImage = vtkSmartPointer<vtkWindowToImageFilter>::New();
866  QVTKWidget* windowVTK = qobject_cast<QVTKWidget *>(activeWindow);
867 
868  if(windowVTK == 0)
869  return;
870 
871  //Ensure GUI doesnt interfere
872 // windowVTK->GetRenderWindow()->StereoRenderOff();
873 // windowVTK->GetRenderWindow()->OffScreenRenderingOn();
874 // windowVTK->GetRenderWindow()->SetAlphaBitPlanes(1); //Use alpha channel
875  windowVTK->GetRenderWindow()->Render();
876 
877  windowToImage->SetInput(windowVTK->GetRenderWindow());
878  windowToImage->SetMagnification(magnifyFactor);
879 // windowToImage->SetInputBufferTypeToRGBA(); //also record the alpha (transparency) channel
880  windowToImage->ReadFrontBufferOff();
881  windowToImage->Update();
882 
883  if(filename.isEmpty())
884  {
885  filename = fileSaver->getSaveFileName(this,
886  tr("Select File Name to Save"),
887  path,
888  tr(saveExtsForScreens.c_str()));
889  }
890 
891  QPointer<milxQtFile> writer = new milxQtFile; //Smart deletion
892  windowVTK->GetRenderWindow()->Render();
893 
894  //Save screenshot
895  int extent[6];
896  windowToImage->GetOutput()->GetExtent(extent);
897  printDebug("Screenshot Size: " + QString::number(extent[1]-extent[0]) + ", " + QString::number(extent[3]-extent[2]) + ", " + QString::number(extent[5]-extent[4]));
898  bool success = writer->saveImage(filename, windowToImage->GetOutput());
899 
900 // windowVTK->GetRenderWindow()->OffScreenRenderingOff();
901  windowVTK->GetRenderWindow()->Render(); //Restore rendering
902 
903  if(!success)
904  {
905  printError("Unable to save screenshot. Ignoring.");
906  return;
907  }
908 
909  printInfo("Write Complete.");
910  }
911 }
912 
913 void milxQtMain::setTabName(QWidget *fromWindow)
914 {
915  QString tabTitle = activeNamePrefix();
916  int index = workspaces->currentIndex();
917 
918  if(fromWindow == NULL)
919  workspaces->setTabText(index, "Empty");
920  else
921  workspaces->setTabText(index, tabTitle);
922 }
923 
924 void milxQtMain::setTabName(const QString newName)
925 {
926  int index = workspaces->currentIndex();
927 
928  workspaces->setTabText(index, newName);
929 }
930 
931 void milxQtMain::closeTab(int index)
932 {
933  int newIndex = 0;
934 
935  if(workspaces->count() > 1 || index > 0)
936  {
937  QWorkspace *tmpWorkspace = qobject_cast<QWorkspace *>(workspaces->widget(index));
938  disconnect(tmpWorkspace, SIGNAL(windowActivated(QWidget *)), 0, 0);
939  tmpWorkspace->closeAllWindows();
940  tmpWorkspace->close();
941 
942  workspaces->removeTab(index);
943 
944  if(index > 0 && workspaces->currentIndex() == index)
945  newIndex = workspaces->currentIndex();
946  else if(index > 0)
947  newIndex = index-1; //Safe to decrement
948  workspaces->setCurrentIndex(newIndex); //else use zero
949  }
950 }
951 
953 {
954  QWorkspace *wrkSpc = qobject_cast<QWorkspace *>(workspaces->currentWidget());
955  QWidgetList windows = wrkSpc->windowList();
956  if (windows.count() < 2) {
957  tileTab();
958  return;
959  }
960  int wHeight = wrkSpc->height() / windows.count();
961  int y = 0;
962  foreach(QWidget *widget, windows)
963  {
964  widget->parentWidget()->resize(wrkSpc->width(), wHeight);
965  widget->parentWidget()->move(0, y);
966  y += wHeight;
967  }
968 }
969 
971 {
972  QWorkspace *wrkSpc = qobject_cast<QWorkspace *>(workspaces->currentWidget());
973  QWidgetList windows = wrkSpc->windowList();
974  if (windows.count() < 2) {
975  tileTab();
976  return;
977  }
978  int wWidth = wrkSpc->width() / windows.count();
979  int x = 0;
980  foreach(QWidget *widget, windows)
981  {
982  widget->parentWidget()->resize(wWidth, wrkSpc->height());
983  widget->parentWidget()->move(x, 0);
984  x += wWidth;
985  }
986 }
987 
989 {
990  printDebug("Showing Help browser");
991 
992  QFile file(":/resources/smilx_doc/home.html");
993  QWebView *view = new QWebView(this);
994  if(file.open(QIODevice::ReadOnly))
995  view->setHtml(file.readAll());
996  view->setWindowTitle("sMILX Help");
997  qobject_cast<QWorkspace *>(workspaces->currentWidget())->addWindow(view);
998  view->show();
999 
1000  //Quick setup toolbar
1001  QToolBar *toolBar = addToolBar(QObject::tr("Navigation"));
1002  toolBar->addAction(view->pageAction(QWebPage::Back));
1003  toolBar->addAction(view->pageAction(QWebPage::Forward));
1004  toolBar->addAction(view->pageAction(QWebPage::Reload));
1005  toolBar->addAction(view->pageAction(QWebPage::Stop));
1006 }
1007 
1009 {
1013  milxQtPreferencesForm prefsForm(this);
1014 
1015  prefsForm.exec();
1016 }
1017 
1019 {
1020  printDebug("Showing controls available...");
1021  QPixmap pixmap(":resources/controls_splash.png");
1022  QSplashScreen *controlsSplash = new QSplashScreen(this);
1023  controlsSplash->setPixmap(pixmap);
1024  controlsSplash->setMask(pixmap.mask());
1025  controlsSplash->show();
1026 
1027  qApp->processEvents();
1028 }
1029 
1031 {
1032  milxQtAboutForm aboutForm(this);
1033 
1034  aboutForm.exec();
1035 }
1036 
1037 void milxQtMain::working(int value)
1038 {
1039  if(value >= 0)
1040  progressBar->setValue(value);
1041  else
1042  {
1043  progressCallCount ++;
1044  progressBar->setMinimum(0);
1045  progressBar->setMaximum(0);
1046  printDebug("Working ... ");
1047  }
1048 }
1049 
1050 void milxQtMain::done(int value)
1051 {
1052  if(value < 0)
1053  progressCallCount --;
1054 
1055  if(progressCallCount == 0)
1056  {
1057  progressBar->setMinimum(0);
1058  progressBar->setMaximum(100);
1059  progressBar->setValue(100);
1060 // progressBar->reset();
1061  printDebug("Done.");
1062  }
1063 }
1064 
1066 {
1068  addRender(newRender);
1069  newRender->setToolTip("<p style='white-space:pre'>VTK Image Viewer 2 Keys - <b>f:</b> Move to, <b>r:</b> Reset, <b>Shift+r:</b> Reset Camera,\n<b>Shift+Mouse1:</b> Translate, <b>Shift+Ctrl+Mouse1:</b> Zoom</p>");
1070  newRender->setDefaultView(defaultViewBox->currentIndex());
1071  newRender->setView(defaultViewBox->currentIndex());
1072  newRender->setDefaultOrientation(defaultOrientationTypeBox->currentIndex());
1073  newRender->show();
1074 
1075  foreach(QAction *currAct, renderExtsActions)
1076  {
1077  newRender->addExtensionAction(currAct);
1078  }
1079 
1080  connect(this, SIGNAL(updatedImportFromMenu(QMenu*)), newRender, SLOT(createCustomConnections(QMenu*)));
1081  connect(this, SIGNAL(updatedImportFromMenu(QActionGroup*)), newRender, SLOT(setCustomActionGroup(QActionGroup*)));
1082  connect(newRender, SIGNAL(imageAvailable(vtkImageData*, QString )), this, SLOT(display(vtkImageData*, QString )));
1083  connect(newRender, SIGNAL(modelAvailable(vtkPolyData*, QString )), this, SLOT(display(vtkPolyData*, QString )));
1084  Connector->Connect(newRender->GetRenderWindow(),
1085  vtkCommand::ModifiedEvent,
1086  this,
1087  SLOT( transferViewToWindows(vtkObject*, unsigned long, void*, void*, vtkCommand*) ),
1088  NULL, 1.0); //High Priority
1089 
1091  newRender->addToContextMenu(menuWindowList);
1092  newRender->addToContextMenu(importFromMenu);
1093  newRender->addToContextMenu(actionLinkWindows);
1094 
1096  newRender->background(whiteBackground);
1097  if(!humanGlyph)
1098  newRender->disableOrient();
1099 
1100  update();
1101  emit displayed(newRender);
1102 }
1103 
1105 {
1106  const QString filename = newImage->getName();
1107  const size_t numberOfWindows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList().size();
1108 
1109  if(defaultViewTypeBox->currentIndex() != SINGLE && numberOfWindows > 0)
1110  newTab();
1111  else if(defaultViewTypeBox->currentIndex() == SINGLE)
1112  {
1113  newImage->setDefaultOrientation(defaultOrientationTypeBox->currentIndex()); //do not remove, not redundant
1114  display(newImage);
1115  }
1116 
1117  if(defaultViewTypeBox->currentIndex() != SINGLE) //Are we displaying scanner like three views + 3D view?
1118  {
1119  int ret = QMessageBox::Yes;
1120  if (actionLinkWindows->isChecked())
1121  {
1122  QMessageBox msgBox;
1123  msgBox.setText("Linked Views mode detected and has to be disabled for multi-view.");
1124  msgBox.setInformativeText("Do you want to disable link views and continue?");
1125  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1126  msgBox.setDefaultButton(QMessageBox::Yes);
1127  ret = msgBox.exec();
1128  }
1129  if (ret == QMessageBox::No)
1130  return;
1131  else if (actionLinkWindows->isChecked())
1132  actionLinkWindows->setChecked(false);
1133 
1134  //Axial view
1135  newImage->setNamePrefix("Axial: ");
1136  newImage->setName(filename);
1137  newImage->disableDefaultView();//ignore default view
1138  newImage->setDefaultOrientation(defaultOrientationTypeBox->currentIndex()); //do not remove, not redundant
1139  newImage->viewToAxial();
1140  display(newImage);
1141 
1142  //Sagittal view
1143  QPointer<milxQtImage> imgSagittal = new milxQtImage; //list deletion
1144  imgSagittal->setDisplayData(newImage);
1145  imgSagittal->setNamePrefix("Sagittal: ");
1146  imgSagittal->setName(filename);
1147  imgSagittal->setConsole(console);
1148  imgSagittal->disableDefaultView();
1149  imgSagittal->generateImage();
1150  imgSagittal->setDefaultOrientation(defaultOrientationTypeBox->currentIndex()); //do not remove, not redundant
1151  imgSagittal->viewToSagittal();
1152  display(imgSagittal);
1153 
1154  //Coronal view
1155  QPointer<milxQtImage> imgCoronal = new milxQtImage; //list deletion
1156  imgCoronal->setDisplayData(newImage);
1157  imgCoronal->setNamePrefix("Coronal: ");
1158  imgCoronal->setName(filename);
1159  imgCoronal->setConsole(console);
1160  imgCoronal->disableDefaultView();
1161  imgCoronal->generateImage();
1162  imgCoronal->setDefaultOrientation(defaultOrientationTypeBox->currentIndex()); //do not remove, not redundant
1163  imgCoronal->viewToCoronal();
1164  display(imgCoronal);
1165 
1166  //3D view
1167  QPointer<milxQtRenderWindow> slicesView = new milxQtRenderWindow; //list deletion
1168  slicesView->setNamePrefix("3D View: ");
1169  slicesView->setName(filename);
1170  slicesView->setConsole(console);
1171  slicesView->addImageActor(newImage->GetImageActor(), newImage->getTransformMatrix());
1172  slicesView->addImageActor(imgSagittal->GetImageActor(), imgSagittal->getTransformMatrix());
1173  slicesView->addImageActor(imgCoronal->GetImageActor(), imgCoronal->getTransformMatrix());
1174  //slicesView->addActor(newImage->GetCursorActor(), newImage->getTransformMatrix());
1175  slicesView->generateRender();
1176 
1177  //setup tracking slices and crosshairs
1178  newImage->trackView(imgSagittal, AXIAL);
1179  newImage->trackView(imgCoronal, AXIAL);
1180  imgSagittal->trackView(newImage, SAGITTAL);
1181  imgSagittal->trackView(imgCoronal, SAGITTAL);
1182  imgCoronal->trackView(newImage, CORONAL);
1183  imgCoronal->trackView(imgSagittal, CORONAL);
1184 
1187  connect(newImage, SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), slicesView, SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
1188  connect(imgSagittal, SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), slicesView, SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
1189  connect(imgCoronal, SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), slicesView, SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
1191  connect(newImage, SIGNAL(modified(QPointer<milxQtImage> )), imgSagittal, SLOT(updateDisplay(QPointer<milxQtImage>)));
1192  connect(newImage, SIGNAL(modified(QPointer<milxQtImage> )), imgCoronal, SLOT(updateDisplay(QPointer<milxQtImage>)));
1193  connect(imgSagittal, SIGNAL(modified(QPointer<milxQtImage> )), newImage, SLOT(updateDisplay(QPointer<milxQtImage>)));
1194  connect(imgSagittal, SIGNAL(modified(QPointer<milxQtImage> )), imgCoronal, SLOT(updateDisplay(QPointer<milxQtImage>)));
1195  connect(imgCoronal, SIGNAL(modified(QPointer<milxQtImage> )), newImage, SLOT(updateDisplay(QPointer<milxQtImage>)));
1196  connect(imgCoronal, SIGNAL(modified(QPointer<milxQtImage> )), imgSagittal, SLOT(updateDisplay(QPointer<milxQtImage>)));
1197 
1198  display(slicesView);
1199 
1200  updateQtEvents(); //ensure all complete before tiling
1201  tileTab();
1202  }
1203 }
1204 
1206 {
1207  if(!newImage->isLoaded())
1208  {
1209  printError("Image not loaded properly. Aborting Display.");
1210  return; //Check if model is valid
1211  }
1212 
1214  addImage(newImage);
1215  newImage->setToolTip("<p style='white-space:pre'>VTK Image Viewer 2 Keys - <b>f:</b> Move to, <b>r:</b> Reset, <b>Shift+r:</b> Reset Camera,\n<b>Shift+Mouse1:</b> Translate, <b>Shift+Ctrl+Mouse1:</b> Zoom</p>");
1216  if(defaultViewTypeBox->currentIndex() == SINGLE)
1217  {
1218  newImage->setDefaultView(defaultViewBox->currentIndex());
1219  newImage->setView(defaultViewBox->currentIndex());
1220  }
1221  newImage->setDefaultOrientation(defaultOrientationTypeBox->currentIndex());
1222  newImage->show();
1223 
1224  foreach(QAction *currAct, imageExtsActions)
1225  {
1226  newImage->addExtensionAction(currAct);
1227  }
1228 
1230  newImage->addToContextMenu(menuWindowList);
1231 
1233  connect(newImage, SIGNAL( imageToSurface(vtkSmartPointer<vtkImageData>, const float) ), this, SLOT( imageToSurface(vtkSmartPointer<vtkImageData>, const float) ));
1234  connect(newImage, SIGNAL( imageToPolyData(vtkSmartPointer<vtkImageData>) ), this, SLOT( imageToPolyData(vtkSmartPointer<vtkImageData>) ));
1235  connect(newImage, SIGNAL( imageToPseudoImage(vectorImageType::Pointer) ), this, SLOT( imageToPseudoImage(vectorImageType::Pointer) ));
1236  connect(newImage, SIGNAL( imageToVectorField(vectorImageType::Pointer, floatImageType::Pointer, int, float) ), this, SLOT( imageToVectorField(vectorImageType::Pointer, floatImageType::Pointer, int, float) ));
1237  connect(newImage, SIGNAL( imageToTensorField(vectorImageType::Pointer, floatImageType::Pointer, int, float) ), this, SLOT( imageToTensorField(vectorImageType::Pointer, floatImageType::Pointer, int, float) ));
1238  connect(newImage, SIGNAL( imageToStreamLines(vectorImageType::Pointer, floatImageType::Pointer) ), this, SLOT( imageToStreamLines(vectorImageType::Pointer, floatImageType::Pointer) ));
1239  connect(newImage, SIGNAL( imageToVolume(vtkSmartPointer<vtkImageData>, bool) ), this, SLOT( imageToVolume(vtkSmartPointer<vtkImageData>, bool) ));
1240  connect(newImage, SIGNAL( imageToPlot(vtkSmartPointer<vtkImageData>, int) ), this, SLOT( imageToPlot(vtkSmartPointer<vtkImageData>, int) ));
1241  connect(newImage, SIGNAL( tableToPlot(vtkSmartPointer<vtkTable>, QString) ), this, SLOT( tableToPlot(vtkSmartPointer<vtkTable>, QString) ));
1242  connect(newImage, SIGNAL(imageAvailable(vtkImageData*, QString )), this, SLOT(display(vtkImageData*, QString )));
1243  connect(newImage, SIGNAL(modelAvailable(vtkPolyData*, QString )), this, SLOT(display(vtkPolyData*, QString )));
1244  connect(newImage, SIGNAL(closing(QWidget *)), this, SLOT(cleanUpOnClose(QWidget *)));
1245  connect(this, SIGNAL(updatedImportFromMenu(QMenu*)), newImage, SLOT(createCustomConnections(QMenu*)));
1246  connect(this, SIGNAL(updatedImportFromMenu(QActionGroup*)), newImage, SLOT(setCustomActionGroup(QActionGroup*)));
1247  Connector->Connect(newImage->GetRenderWindow(),
1248  vtkCommand::ModifiedEvent,
1249  this,
1250  SLOT( transferViewToWindows(vtkObject*, unsigned long, void*, void*, vtkCommand*) ),
1251  NULL, 1.0); //High Priority
1252 
1253  newImage->addToContextMenu(actionCompare);
1254  newImage->addToContextMenu(menuWindowList);
1255  newImage->addToContextMenu(importFromMenu);
1257  newImage->appendToContextMenu(actionSave);
1258 
1260  if(!humanGlyph)
1261  newImage->disableOrient();
1262  if(!interpolationImages)
1263  newImage->disableInterpolateDisplay();
1264  if(!orientationImages)
1265  newImage->disableApplyOrientDisplay();
1266 
1267  imageWindows.append(newImage);
1268  update();
1269  emit displayed(newImage);
1270 }
1271 
1272 void milxQtMain::display(vtkImageData* newImage, QString nameOfImage)
1273 {
1274  printDebug("Displaying Raw ImageData");
1275  QPointer<milxQtImage> image = new milxQtImage; //List deletion
1276  image->setName(nameOfImage);
1277  if(defaultViewTypeBox->currentIndex() == SINGLE)
1278  {
1279  image->setDefaultView(defaultViewBox->currentIndex());
1280  image->setView(defaultViewBox->currentIndex());
1281  }
1282  image->SetInput(newImage);
1283  image->setDefaultOrientation(defaultOrientationTypeBox->currentIndex());
1284  image->generateImage();
1285  display(image);
1286 }
1287 
1289 {
1290  if(!newModel->isLoaded())
1291  {
1292  printError("Model/Surface not loaded properly. Aborting Display.");
1293  return; //Check if model is valid
1294  }
1295 
1297  addModel(newModel);
1298  newModel->setToolTip("<p style='white-space:pre'>VTK Model Viewer 2 Keys - <b>f:</b> Move to, <b>r:</b> Reset, <b>Shift+r:</b> Reset Camera,\n<b>Shift+Mouse1:</b> Translate, <b>Shift+Ctrl+Mouse1:</b> Zoom</p>");
1299  newModel->setDefaultView(defaultViewBox->currentIndex());
1300  newModel->setDefaultOrientation(defaultOrientationTypeBox->currentIndex());
1301  newModel->setView(defaultViewBox->currentIndex());
1302  newModel->refresh();
1303  if(newModel->GetScalars())
1304  newModel->colourMapToJet();
1305  newModel->show();
1306 
1307  foreach(QAction *currAct, modelExtsActions)
1308  {
1309  newModel->addExtensionAction(currAct);
1310  }
1311 
1313  //newModel->createCustomMenu( windowActionList(importFromMenu, true, false) ); //Virtual call to any model subclasses
1314  //connect(this, SIGNAL(updatedImportFromMenu(QMenu*)), newModel, SLOT(copyToContextMenu(QMenu*)));
1315  connect(this, SIGNAL(updatedImportFromMenu(QMenu*)), newModel, SLOT(createCustomConnections(QMenu*)));
1316  connect(this, SIGNAL(updatedImportFromMenu(QActionGroup*)), newModel, SLOT(setCustomActionGroup(QActionGroup*)));
1317  connect(newModel, SIGNAL(imageAvailable(vtkImageData*, QString )), this, SLOT(display(vtkImageData*, QString )));
1318  connect(newModel, SIGNAL(modelAvailable(vtkPolyData*, QString )), this, SLOT(display(vtkPolyData*, QString )));
1319  connect(newModel, SIGNAL(closing(QWidget *)), this, SLOT(cleanUpOnClose(QWidget *)));
1320  Connector->Connect(newModel->GetRenderWindow(),
1321  vtkCommand::ModifiedEvent,
1322  this,
1323  SLOT( transferViewToWindows(vtkObject*, unsigned long, void*, void*, vtkCommand*) ),
1324  NULL, 1.0); //High Priority
1325 
1327  connect(newModel, SIGNAL( surfaceToImage(vtkSmartPointer<vtkPolyData>) ), this, SLOT( voxeliseSurface(vtkSmartPointer<vtkPolyData>) ));
1328 
1330  newModel->addToContextMenu(actionCompare);
1331  newModel->addToContextMenu(menuWindowList);
1332  newModel->addToContextMenu(importFromMenu);
1334  newModel->appendToContextMenu(actionSave);
1335 
1337  newModel->background(whiteBackground);
1338  if(!humanGlyph)
1339  newModel->disableOrient();
1341  newModel->enableInterpolateDisplay();
1342  if(scalarBarModels)
1343  newModel->scaleDisplay(true);
1344 
1345  modelWindows.append(newModel);
1346  update();
1347  emit displayed(newModel);
1348 }
1349 
1350 void milxQtMain::display(vtkPolyData* newModel, QString nameOfModel)
1351 {
1352  printDebug("Displaying Raw PolyData");
1353  QPointer<milxQtModel> mdl = new milxQtModel; //List deletion
1354  mdl->setName(nameOfModel);
1355  mdl->SetInput(newModel);
1356  mdl->generateModel();
1357  display(mdl);
1358 }
1359 
1361 {
1362  addUnifiedWindow(newUni);
1363  newUni->setToolTip("<p style='white-space:pre'>VTK Model Viewer 2 Keys - <b>f:</b> Move to, <b>r:</b> Reset, <b>Shift+r:</b> Reset Camera,\n<b>Shift+Mouse1:</b> Translate, <b>Shift+Ctrl+Mouse1:</b> Zoom</p>");
1364  newUni->setDefaultView(defaultViewBox->currentIndex());
1365  newUni->setView(defaultViewBox->currentIndex());
1366  newUni->setDefaultOrientation(defaultOrientationTypeBox->currentIndex());
1367  newUni->show();
1368 
1369  connect(newUni, SIGNAL(imageAvailable(milxQtImage *)), this, SLOT(display(milxQtImage *)), Qt::UniqueConnection);
1370  connect(newUni, SIGNAL(modelAvailable(milxQtModel *)), this, SLOT(display(milxQtModel *)), Qt::UniqueConnection);
1371 // connect(newUni, SIGNAL(modelAvailable(QWidget *)), workspaces->currentWidget(), SLOT(setActiveWindow(QWidget *))); ///\todo Temp Fix: model result is not strictly active
1372 
1374  newUni->background(whiteBackground);
1375  if(!humanGlyph)
1376  newUni->disableOrient();
1377 
1378  update();
1379  emit displayed(newUni);
1380 }
1381 
1382 void milxQtMain::display(vtkPolyDataCollection *modelCollection, QStringList &filenames)
1383 {
1384  bool success = false;
1385  size_t n = modelCollection->GetNumberOfItems();
1386 
1388  foreach (QPointer<milxQtPluginInterface> loadedPlugin, plugins)
1389  {
1390  if(loadedPlugin->hasCollectionSupport())
1391  {
1392  printInfo(loadedPlugin->name() + " plugin has collection support.");
1393 
1394  QMessageBox msgBox;
1395  msgBox.setText(loadedPlugin->name() + " plugin has collection support.");
1396  msgBox.setInformativeText("Do you want to load the collection with this plugin?");
1397  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::NoToAll);
1398  msgBox.setDefaultButton(QMessageBox::Yes);
1399  int ret = msgBox.exec();
1400 
1401  if(ret == QMessageBox::No)
1402  continue;
1403  else if(ret == QMessageBox::NoToAll)
1404  break;
1405 
1406  loadedPlugin->SetInputCollection(modelCollection, filenames);
1407 
1408  QPointer<milxQtRenderWindow> renWin = loadedPlugin->genericResult();
1409  if(renWin)
1410  {
1411  renWin->setName("Collection");
1412  renWin->generateRender();
1413  display(renWin);
1414  success = true;
1415  }
1416 
1417  QPointer<milxQtModel> model = loadedPlugin->modelResult();
1418  if(model)
1419  {
1420  model->setName("Collection Model");
1421  model->generateModel();
1422  display(model);
1423  success = true;
1424  }
1425 
1426  QPointer<milxQtImage> image = loadedPlugin->imageResult();
1427  if(image)
1428  {
1429  image->setName("Collection Image");
1430  image->generateImage();
1431  display(image);
1432  success = true;
1433  }
1434  }
1435 
1436  if(success)
1437  {
1438  loadedPlugin->update();
1439  break;
1440  }
1441  }
1442 
1443  if(success)
1444  return;
1445 
1447  vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
1448  lookupTable->SetTableRange(0.0, n+1);
1449  lookupTable->Build();
1450 
1451  QPointer<milxQtRenderWindow> allModels = new milxQtRenderWindow; //hierarchical deletion
1452  QList< QPointer<milxQtModel> > alignedModels;
1453  modelCollection->InitTraversal(); //Must be called before traversing, or crashes
1454  for(size_t j = 0; j < n; j ++)
1455  {
1456  double colour[3];
1457 
1459  lookupTable->GetColor(j, colour);
1460 
1462  QPointer<milxQtModel> alignedModel = new milxQtModel; //smart deletion
1463  alignedModel->setName( QString::number(j) );
1464  alignedModel->setConsole(console);
1465  alignedModel->setDefaultView(defaultViewBox->currentIndex());
1466  alignedModel->setView(defaultViewBox->currentIndex());
1467  alignedModel->SetInput(modelCollection->GetNextItem());
1468  alignedModel->generatePoints(colour[0], colour[2], colour[1]);
1469  alignedModel->SetOpacity(0.2);
1470 
1471  alignedModels.append(alignedModel);
1472 
1473  allModels->AddActor(alignedModel->GetActor());
1474  }
1475 
1477  QMessageBox msgBox;
1478  msgBox.setText("Open the mean data file?");
1479  msgBox.setInformativeText("Would you like to open the mean file?\nThis will be shown as a solid model.");
1480  msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1481  msgBox.setDefaultButton(QMessageBox::Ok);
1482  int ret = msgBox.exec();
1483 
1484  if(ret == QMessageBox::Ok)
1485  {
1486  if(open())
1487  allModels->AddActor(activeModel()->GetActor());
1488  }
1489 
1490  allModels->setName("Collection");
1491  allModels->setConsole(console);
1492  allModels->generateRender();
1493  display(allModels);
1494 }
1495 
1496 //Protected
1497 //From Qt Examples for Recent Files
1498 void milxQtMain::setCurrentFile(const QString &fileName)
1499 {
1500  QFileInfo fi(fileName);
1501 
1502  if(!fileName.isEmpty())
1503  setWindowTitle(tr("%1 - %2").arg(strippedName(fileName)).arg(tr("milxQt")));
1504  else
1505  setWindowTitle(tr("sMILX"));
1506 
1507  QSettings settings("Shekhar Chandra", "milxQt");
1508  QStringList files = settings.value("recentFileList").toStringList();
1509  files.removeAll(fileName);
1510  files.prepend(fileName);
1511  while (files.size() > MaxRecentFiles)
1512  files.removeLast();
1513 
1514  settings.setValue("recentFileList", files);
1515  settings.setValue("recentPath",fi.absolutePath());
1516 
1517  foreach (QWidget *widget, QApplication::topLevelWidgets())
1518  {
1519  milxQtMain *mainWin = qobject_cast<milxQtMain *>(widget);
1520  if (mainWin)
1521  mainWin->updateRecentFileActions();
1522  }
1523 }
1524 
1525 //From Qt Examples for Recent Files
1527 {
1528  QSettings settings("Shekhar Chandra", "milxQt");
1529  QStringList files = settings.value("recentFileList").toStringList();
1530 
1531  int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
1532 
1533  for (int i = 0; i < numRecentFiles; ++i)
1534  {
1535  QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
1536  actionsRecentFile[i]->setText(text);
1537  actionsRecentFile[i]->setData(files[i]);
1538  actionsRecentFile[i]->setToolTip(files[i]);
1539  actionsRecentFile[i]->setStatusTip(files[i]);
1540  actionsRecentFile[i]->setShortcut("Ctrl+" + text.setNum( (i+1)%numRecentFiles ));
1541  actionsRecentFile[i]->setVisible(true);
1542  }
1543  for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
1544  actionsRecentFile[j]->setVisible(false);
1545 
1546  actionRecentFileSeparator->setVisible(numRecentFiles > 0);
1547 }
1548 
1550 {
1551  menuWindows->clear();
1552  menuWindows->addAction(actionCascade);
1553  menuWindows->addAction(actionTile);
1554  menuWindows->addAction(actionTileVertically);
1555  menuWindows->addAction(actionTileHorizontally);
1556  menuWindows->addSeparator()->setText(tr("Docked Windows"));
1557  foreach(QAction *dockAct, dockActions)
1558  {
1559  menuWindows->addAction(dockAct);
1560  }
1561  menuWindows->addSeparator()->setText(tr("Windows"));
1562 
1563  return windowActionList(menuWindows, true, true);
1564 }
1565 
1566 QActionGroup* milxQtMain::updateWindowListMenu(bool applyMapper)
1567 {
1568  menuWindowList->clear();
1569 
1570  printDebug("Update Window List Window");
1571  QActionGroup* grp = windowActionList(menuWindowList, true, applyMapper);
1572  emit updatedWindowListMenu(grp);
1574 
1575  return grp;
1576 }
1577 
1578 QActionGroup* milxQtMain::updateImportFromMenu(bool applyMapper)
1579 {
1580  importFromMenu->clear();
1581 
1582  printDebug("Update Import From Window");
1583  QActionGroup* grp = windowActionList(importFromMenu, true, applyMapper);
1584  emit updatedImportFromMenu(grp);
1586 
1587  return grp;
1588 }
1589 
1591 {
1593 
1594  while(currentWindow())
1595  {
1596  milxQtWindow *win = currentWindow();
1597  if(isImage(win))
1598  {
1599  milxQtImage *img = qobject_cast<milxQtImage *>(win);
1600  img->setLevel(100-value);
1601  }
1602  nextWindow();
1603  }
1604 
1605  imageLevelSlider->setStatusTip("Image Contrast at "+QString::number(value)+"%");
1606  imageLevelSlider->setToolTip(QString::number(value)+"%");
1607 }
1608 
1610 {
1612 
1613  while (currentWindow())
1614  {
1615  milxQtWindow *win = currentWindow();
1616  if (isImage(win))
1617  {
1618  milxQtImage *img = qobject_cast<milxQtImage *>(win);
1619  img->autoLevel();
1620  }
1621  nextWindow();
1622  }
1623 }
1624 
1626 {
1628 
1629  while (currentWindow())
1630  {
1632  if (isImage(win))
1633  {
1634  milxQtImage *img = qobject_cast<milxQtImage *>(win);
1635  img->refresh();
1636  }
1637  else
1638  win->refresh();
1639  }
1640 }
1641 
1643 {
1645 
1646  while (currentWindow())
1647  {
1648  milxQtWindow *win = currentWindow();
1649  if (isImage(win))
1650  {
1651  milxQtImage *img = qobject_cast<milxQtImage *>(win);
1652  img->enableCrosshair();
1653  }
1654  nextWindow();
1655  }
1656 }
1657 
1659 {
1661 
1662  while(currentWindow())
1663  {
1664  milxQtWindow *win = currentWindow();
1665  milxQtRenderWindow *rndWin = qobject_cast<milxQtRenderWindow *>(win);
1666  rndWin->setView(value);
1667  nextWindow();
1668  }
1669 }
1670 
1672 {
1673  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1674 
1675  if(windows.isEmpty())
1676  return;
1677 
1678  QMessageBox msgBox;
1679  if(value == 0)
1680  msgBox.setText("Window View type changed to Single");
1681  else
1682  msgBox.setText("Window View type changed to Multiple");
1683  msgBox.setInformativeText("This will take effect once you reload your data.");
1684  msgBox.setStandardButtons(QMessageBox::Ok);
1685  msgBox.exec();
1686 }
1687 
1689 {
1690  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1691 
1692  if(windows.isEmpty())
1693  return;
1694 
1695  QMessageBox msgBox;
1696  if(value == 0)
1697  msgBox.setText("View Orientation Convention changed to Radiological");
1698  else
1699  msgBox.setText("View Orientation Convention changed to Neurological");
1700  msgBox.setInformativeText("This will take effect once you reload your data.");
1701  msgBox.setStandardButtons(QMessageBox::Ok);
1702  msgBox.exec();
1703 }
1704 
1705 QActionGroup* milxQtMain::windowActionList(QMenu *menuForList, bool groupTogether, bool applyMapper)
1706 {
1707  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1708  milxQtWindow *win = NULL;
1709  QActionGroup *winGp = new QActionGroup(this);
1710  QString text;
1711 
1712  foreach(QWidget *currentWindow, windows)
1713  {
1714  if(!currentWindow)
1715  continue;
1716 
1717  win = qobject_cast<milxQtWindow *>(currentWindow);
1718 
1719  if(win == 0)
1720  continue;
1721 
1722  text = win->strippedNamePrefix();
1723 // text = tr("%1 %2").arg(j + 1).arg(childVPlt->strippedNamePrefix());
1724 
1725 // QAction *action = menuForList->addAction(text);
1726  QAction *action = new QAction(currentWindow); //parent to be used later
1727  action->setText(text);
1728  menuForList->addAction(action);
1729  if(groupTogether)
1730  {
1731  action->setCheckable(true);
1732  action->setChecked(currentWindow == qobject_cast<QWorkspace *>(workspaces->currentWidget())->activeWindow());
1733  winGp->addAction(action);
1734  }
1735 
1736  if(applyMapper)
1737  {
1738  connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
1739  windowMapper->setMapping(action, currentWindow);
1740  }
1741  }
1742 
1743  return winGp;
1744 }
1745 
1747 {
1748  int n = getNumberOfWindows();
1749 
1750  int m = 0;
1752  for(int j = 0; j < n; j ++)
1753  {
1754  milxQtWindow *win = nextWindow();
1755  if(isImage(win))
1756  m ++;
1757  }
1758  printDebug("Number of Image Windows: " + QString::number(m));
1759 
1760  return m;
1761 }
1762 
1764 {
1765  int n = getNumberOfWindows();
1766 
1767  int m = 0;
1769  for(int j = 0; j < n; j ++)
1770  {
1771  milxQtWindow *win = nextWindow();
1772  if(isModel(win))
1773  m ++;
1774  }
1775  printDebug("Number of Model Windows: " + QString::number(m));
1776 
1777  return m;
1778 }
1779 
1781 {
1782  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1783  milxQtWindow *win = NULL;
1784 
1785  if(windowIterator < windows.size())
1786  win = qobject_cast<milxQtWindow *>(windows[windowIterator]);
1787 
1788  return win;
1789 }
1790 
1792 {
1793  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1794  milxQtWindow *win = NULL;
1795 
1796  if(windowIterator < windows.size())
1797  {
1798  win = qobject_cast<milxQtWindow *>(windows[windowIterator]);
1799  windowIterator ++;
1800  }
1801 
1802  return win;
1803 }
1804 
1806 {
1807  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1808  milxQtRenderWindow *win = NULL;
1809 
1810  while(windowIterator < windows.size())
1811  {
1812  if(isRender(windows[windowIterator]))
1813  {
1814  win = qobject_cast<milxQtRenderWindow *>(windows[windowIterator]);
1815  windowIterator ++;
1816  break;
1817  }
1818 
1819  windowIterator ++;
1820  }
1821 
1822  return win;
1823 }
1824 
1826 {
1827  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1828  milxQtModel *win = NULL;
1829 
1830  while(windowIterator < windows.size())
1831  {
1832  if(isModel(windows[windowIterator]))
1833  {
1834  win = qobject_cast<milxQtModel *>(windows[windowIterator]);
1835  windowIterator ++;
1836  break;
1837  }
1838 
1839  windowIterator ++;
1840  }
1841 
1842  return win;
1843 }
1844 
1846 {
1847  QWidgetList windows = qobject_cast<QWorkspace *>(workspaces->currentWidget())->windowList();
1848  milxQtImage *win = NULL;
1849 
1850  printDebug("Number of Windows: " + QString::number(windows.size()));
1851  while(windowIterator < windows.size())
1852  {
1853  if(isImage(windows[windowIterator]))
1854  {
1855  win = qobject_cast<milxQtImage *>(windows[windowIterator]);
1856  windowIterator ++;
1857  break;
1858  }
1859 
1860  windowIterator ++;
1861  }
1862  printDebug("Window Iterator Value: " + QString::number(windowIterator));
1863 
1864  return win;
1865 }
1866 
1867 void milxQtMain::transferViewToWindows(vtkObject *obj, unsigned long, void *client_data, void *, vtkCommand *command)
1868 {
1869  if(!actionLinkWindows->isChecked()) //if all windows not linked, exit
1870  return;
1871 
1872  printDebug("Updating Views in Other Windows");
1873  actionLinkWindows->setChecked(false); //prevent cycle calls
1874  // get render window
1875  vtkRenderWindow* rndWindow = vtkRenderWindow::SafeDownCast(obj);
1876  vtkRenderer* rnd = rndWindow->GetRenderers()->GetFirstRenderer();
1877 
1879  bool srcIsImage = isActiveImage();
1880  bool srcIsModel = isActiveModel();
1881 
1882  if(rnd)
1883  {
1884  vtkCamera* srcCamera = rnd->GetActiveCamera();
1885 
1887 
1888  for(int j = 0; j < getNumberOfWindows(); j ++)
1889  {
1890  QPointer<milxQtRenderWindow> window = nextRenderWindow();
1891  vtkRenderer* distRnd = window->GetRenderWindow()->GetRenderers()->GetFirstRenderer();
1892  vtkCamera* distCamera = distRnd->GetActiveCamera();
1893 
1894  if(distCamera != srcCamera)
1895  {
1896  if(srcIsImage && isImage(window))
1897  {
1898  //Image-to-Image specific
1899  QPointer<milxQtImage> img = qobject_cast<milxQtImage *>(window);
1900  img->setSlice(activeImage()->getSlice());
1901  img->setView(activeImage()->getView());
1902  if(img->isCrosshair() && activeImage()->isCrosshair())
1903  img->setCrosshairPosition(activeImage()->getCrosshairPosition());
1904  }
1905  /*else if(srcIsImage && isModel(window))
1906  {
1907  //Image-to-Model specific
1908  QPointer<milxQtModel> mdl = qobject_cast<milxQtModel *>(window);
1909  mdl->setView(activeImage()->getView());
1910  }*/
1911  /*else if(srcIsModel && isImage(window))
1912  {
1913  //Model-to-Image specific
1914  QPointer<milxQtImage> img = qobject_cast<milxQtImage *>(window);
1915  img->setView(activeModel()->getView());
1916  }*/ //Copy Camera is better
1917 
1918  if( !(srcIsImage && isModel(window)) && !(srcIsModel && isImage(window))) //no image-model
1919  distCamera->DeepCopy(srcCamera);
1920  }
1921 
1922  window->Render();
1923  }
1924 
1925 // rndWindow->Render(); //!< refresh the source display, quick
1926  }
1927 
1928  actionLinkWindows->setChecked(true); //restore
1929 }
1930 
1932 {
1933  milxQtRenderWindow *renWin = activeRender();
1934 
1935  if(renWin)
1936  renWin->createMenu(menuData);
1937 }
1938 
1939 void milxQtMain::imageToSurface(vtkSmartPointer<vtkImageData> img, const float value)
1940 {
1941  //Check if value provided
1942  int contourNumber = 1;
1943  if(value == numeric_limits<float>::max())
1944  contourNumber = -1;
1945  else
1946  printInfo("Using iso value provided");
1947 
1948  QPointer<milxQtModel> model = new milxQtModel; //List deletion
1949  model->setConsole(console);
1950  model->generateIsoSurface(img, contourNumber, value);
1951  model->generateModel();
1952  display(model);
1953 }
1954 
1955 void milxQtMain::imageToPolyData(vtkSmartPointer<vtkImageData> img)
1956 {
1957  QPointer<milxQtModel> model = new milxQtModel; //List deletion
1958  model->setConsole(console);
1959  model->generatePolyDataFromImage(img);
1960  model->generateModel();
1961  display(model);
1962 }
1963 
1964 void milxQtMain::imageToPseudoImage(vectorImageType::Pointer img)
1965 {
1966 // typedef itk::VectorImage<floatPixelType, milx::imgDimension> vectorImageType;
1967 
1969  vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
1970 // vectorImageType::Pointer rescaledImg = milx::Image<vectorImageType>::RescaleIntensities(img, 0, 255);
1971  vtkSmartPointer<vtkImageData> fieldRaw = milx::Image<vectorImageType>::ConvertITKVectorImageToVTKImage(img);
1972  vtkSmartPointer<vtkImageData> field = milx::Image<vectorImageType>::ApplyOrientationToVTKImage(fieldRaw, img, matrix, false, true);
1973 
1974 // field->GetPointData()->SetActiveScalars("ImageScalars");
1975  field->GetPointData()->SetActiveVectors("ImageScalars");
1976 
1977  QPointer<milxQtImage> pseudoimage = new milxQtImage; //List deletion
1978  pseudoimage->setConsole(console);
1979  pseudoimage->SetInput(field);
1980  pseudoimage->generateImage();
1981  display(pseudoimage);
1982 }
1983 
1984 void milxQtMain::imageToVectorField(vectorImageType::Pointer img, floatImageType::Pointer magImg, int subsampleFactor, float scaling)
1985 {
1986  bool ok1 = false;
1987  if(subsampleFactor == 0)
1988  {
1989  subsampleFactor = QInputDialog::getInt(this, tr("Please Provide the sub-sample factor of the data"),
1990  tr("Sub-sample Factor:"), 8, 1, 1000, 1, &ok1);
1991  if(!ok1)
1992  return;
1993  }
1994 
1996  floatImageType::SizeType subsampleSizes;
1997  subsampleSizes.Fill(subsampleFactor);
1998 
1999  vectorImageType::Pointer imgSubSampled = milx::Image<vectorImageType>::SubsampleImage(img, subsampleSizes);
2000  floatImageType::Pointer magImgSubSampled = milx::Image<floatImageType>::SubsampleImage(magImg, subsampleSizes);
2001  std::cout << "Subsampled size: " << imgSubSampled->GetLargestPossibleRegion().GetSize() << std::endl;
2002 
2004 // vectorImageType::Pointer imgRealSpace = milx::Image<vectorImageType>::FlipImage(imgSubSampled, false, true, false);
2005 // floatImageType::Pointer magImgRealSpace = milx::Image<floatImageType>::FlipImage(magImgSubSampled, false, true, false);
2006 
2008  vtkSmartPointer<vtkPoints> fieldPoints = vtkSmartPointer<vtkPoints>::New();
2009  vtkSmartPointer<vtkFloatArray> magnitudes = vtkSmartPointer<vtkFloatArray>::New();
2010  magnitudes->SetNumberOfComponents(1);
2011  vtkSmartPointer<vtkFloatArray> vectors = vtkSmartPointer<vtkFloatArray>::New();
2012  vectors->SetNumberOfComponents(3);
2013 
2014  typedef itk::Point<double, 3> InputImagePointType;
2015  itk::ImageRegionConstIteratorWithIndex<vectorImageType> imageIterator(imgSubSampled, imgSubSampled->GetLargestPossibleRegion());
2016  itk::ImageRegionConstIteratorWithIndex<floatImageType> magImageIterator(magImgSubSampled, magImgSubSampled->GetLargestPossibleRegion());
2017 
2018  InputImagePointType point;
2019  while(!imageIterator.IsAtEnd())
2020  {
2021  coordinate position, direction;
2022  float value;
2023 
2024  //std::cout << "Index: " << imageIterator.GetIndex() << " value: " << imageIterator.Get() << std::endl;
2025  magImgSubSampled->TransformIndexToPhysicalPoint(magImageIterator.GetIndex(), point);
2026 
2027  position[0] = point[0];
2028  position[1] = point[1];
2029  position[2] = point[2];
2030 
2031  direction.fill(0.0);
2032  if(magImageIterator.Get() != 0) //if not masked
2033  {
2034  direction[0] = imageIterator.Get()[0];
2035  direction[1] = imageIterator.Get()[1];
2036  if(img->GetNumberOfComponentsPerPixel() > 2)
2037  direction[2] = imageIterator.Get()[2];
2038  }
2039 
2040  fieldPoints->InsertNextPoint(position.data_block());
2041 
2042  value = magImageIterator.Get();
2043  magnitudes->InsertNextTuple1(value);
2044  vectors->InsertNextTuple3(direction[0], direction[1], direction[2]);
2045 
2046  ++imageIterator;
2047  ++magImageIterator;
2048  }
2049 
2050  vtkSmartPointer<vtkPolyData> field = vtkSmartPointer<vtkPolyData>::New();
2051  field->SetPoints(fieldPoints);
2052  field->GetPointData()->SetScalars(magnitudes);
2053  field->GetPointData()->SetVectors(vectors);
2054  field->Modified();
2055 
2056  QPointer<milxQtModel> model = new milxQtModel; //List deletion
2057  model->setConsole(console);
2058  model->SetInput(field);
2059  model->generateModel();
2060  model->generateVectorField(scaling);
2061 
2062  display(model);
2063 }
2064 
2065 void milxQtMain::imageToTensorField(vectorImageType::Pointer img, floatImageType::Pointer magImg, int subsampleFactor, float scaling)
2066 {
2067  bool ok1 = false;
2068  if(subsampleFactor == 0)
2069  {
2070  subsampleFactor = QInputDialog::getInt(this, tr("Please Provide the sub-sample factor of the data"),
2071  tr("Sub-sample Factor:"), 8, 1, 1000, 1, &ok1);
2072  if(!ok1)
2073  return;
2074  }
2075 
2077  const size_t components = img->GetNumberOfComponentsPerPixel();
2078  floatImageType::SizeType subsampleSizes;
2079  subsampleSizes.Fill(subsampleFactor);
2080 
2081  vectorImageType::Pointer imgSubSampled = milx::Image<vectorImageType>::SubsampleImage(img, subsampleSizes);
2082  floatImageType::Pointer magImgSubSampled = milx::Image<floatImageType>::SubsampleImage(magImg, subsampleSizes);
2083  std::cout << "Subsampled size: " << imgSubSampled->GetLargestPossibleRegion().GetSize() << std::endl;
2084 
2086 // vectorImageType::Pointer imgRealSpace = milx::Image<vectorImageType>::FlipImage(imgSubSampled, false, true, false);
2087 // floatImageType::Pointer magImgRealSpace = milx::Image<floatImageType>::FlipImage(magImgSubSampled, false, true, false);
2088 
2090  vtkSmartPointer<vtkPoints> fieldPoints = vtkSmartPointer<vtkPoints>::New();
2091  vtkSmartPointer<vtkFloatArray> magnitudes = vtkSmartPointer<vtkFloatArray>::New();
2092  magnitudes->SetNumberOfComponents(1);
2093  vtkSmartPointer<vtkFloatArray> tensors = vtkSmartPointer<vtkFloatArray>::New();
2094  tensors->SetNumberOfComponents(9);
2095 
2096  typedef itk::Point<double, 3> InputImagePointType;
2097  itk::ImageRegionConstIteratorWithIndex<vectorImageType> imageIterator(imgSubSampled, imgSubSampled->GetLargestPossibleRegion());
2098  itk::ImageRegionConstIteratorWithIndex<floatImageType> magImageIterator(magImgSubSampled, magImgSubSampled->GetLargestPossibleRegion());
2099 
2100  InputImagePointType point;
2101  while(!imageIterator.IsAtEnd())
2102  {
2103  double position[3];
2104  float value;
2105 
2106  //std::cout << "Index: " << imageIterator.GetIndex() << " value: " << imageIterator.Get() << std::endl;
2107  magImgSubSampled->TransformIndexToPhysicalPoint(magImageIterator.GetIndex(), point);
2108 
2109  position[0] = point[0];
2110  position[1] = point[1];
2111  position[2] = point[2];
2112 
2113  vtkSmartPointer<vtkTensor> tens = vtkSmartPointer<vtkTensor>::New();
2114  if(magImageIterator.Get() != 0) //if not masked
2115  {
2116  if(components == 6)
2117  {
2118  tens->SetComponent(0,0, imageIterator.Get()[0]);
2119  tens->SetComponent(1,1, imageIterator.Get()[1]);
2120  tens->SetComponent(2,2, imageIterator.Get()[2]);
2121  tens->SetComponent(0,1, imageIterator.Get()[3]); //symmetric
2122  tens->SetComponent(1,0, imageIterator.Get()[3]); //symmetric
2123  tens->SetComponent(0,2, imageIterator.Get()[4]); //symmetric
2124  tens->SetComponent(2,0, imageIterator.Get()[4]); //symmetric
2125  tens->SetComponent(1,2, imageIterator.Get()[5]); //symmetric
2126  tens->SetComponent(2,1, imageIterator.Get()[5]); //symmetric
2127  }
2128  else
2129  {
2130  tens->SetComponent(0,0, imageIterator.Get()[0]);
2131  tens->SetComponent(1,1, imageIterator.Get()[1]);
2132  tens->SetComponent(2,2, imageIterator.Get()[2]);
2133  tens->SetComponent(0,1, imageIterator.Get()[3]);
2134  tens->SetComponent(1,0, imageIterator.Get()[4]);
2135  tens->SetComponent(0,2, imageIterator.Get()[5]);
2136  tens->SetComponent(2,0, imageIterator.Get()[6]);
2137  tens->SetComponent(1,2, imageIterator.Get()[7]);
2138  tens->SetComponent(2,1, imageIterator.Get()[8]);
2139  }
2140  }
2141  else //zero vector
2142  {
2143  tens->SetComponent(0,0, 0.0);
2144  tens->SetComponent(1,1, 0.0);
2145  tens->SetComponent(2,2, 0.0);
2146  tens->SetComponent(0,1, 0.0); //symmetric
2147  tens->SetComponent(1,0, 0.0); //symmetric
2148  tens->SetComponent(0,2, 0.0); //symmetric
2149  tens->SetComponent(2,0, 0.0); //symmetric
2150  tens->SetComponent(1,2, 0.0); //symmetric
2151  tens->SetComponent(2,1, 0.0); //symmetric
2152  }
2153 
2154  fieldPoints->InsertNextPoint(position);
2155 
2156  value = magImageIterator.Get();
2157  magnitudes->InsertNextTuple1(value);
2158  tensors->InsertNextTuple(tens->T);
2159 
2160  ++imageIterator;
2161  ++magImageIterator;
2162  }
2163 
2164  vtkSmartPointer<vtkPolyData> field = vtkSmartPointer<vtkPolyData>::New();
2165  field->SetPoints(fieldPoints);
2166  field->GetPointData()->SetScalars(magnitudes);
2167  field->GetPointData()->SetTensors(tensors);
2168 
2169  QPointer<milxQtModel> model = new milxQtModel; //List deletion
2170  model->setConsole(console);
2171  model->SetInput(field);
2172  model->generateModel();
2173  model->generateTensorField(scaling);
2174  display(model);
2175 }
2176 
2177 void milxQtMain::imageToStreamLines(vectorImageType::Pointer img, floatImageType::Pointer magImg, size_t subsampleFactor)
2178 {
2179  bool ok1 = false;
2180  if(subsampleFactor == 0)
2181  {
2182  subsampleFactor = QInputDialog::getInt(this, tr("Please Provide the sub-sample factor of the data"),
2183  tr("Sub-sample Factor:"), 8, 1, 1000, 1, &ok1);
2184  if(!ok1)
2185  return;
2186  }
2187 
2188  //Which dimension is sliced?
2189  floatImageType::SizeType imageSize = magImg->GetLargestPossibleRegion().GetSize();
2190  size_t sliceDimension = 0;
2191  for(size_t j = 0; j < floatImageType::ImageDimension; j ++)
2192  {
2193  if(imageSize[j] == 1)
2194  sliceDimension = j;
2195  }
2196 
2198  const size_t sliceSubsampleFactor = subsampleFactor;
2199  floatImageType::SizeType subsampleSizes;
2200  subsampleSizes.Fill(subsampleFactor);
2201  floatImageType::SizeType sliceSubsampleSizes;
2202  sliceSubsampleSizes.Fill(sliceSubsampleFactor);
2203  sliceSubsampleSizes[sliceDimension] = 1;
2204 
2206 // const size_t components = img->GetNumberOfComponentsPerPixel();
2207  vectorImageType::Pointer imgSubSampled = milx::Image<vectorImageType>::SubsampleImage(img, subsampleSizes);
2208  floatImageType::Pointer magImgSubSampled = milx::Image<floatImageType>::SubsampleImage(magImg, sliceSubsampleSizes);
2209  cout << "Slice Information: " << endl;
2211 
2213 // vectorImageType::Pointer imgRealSpace = milx::Image<vectorImageType>::FlipImage(imgSubSampled, false, true, false);
2214 // floatImageType::Pointer magImgRealSpace = milx::Image<floatImageType>::FlipImage(magImgSubSampled, false, true, false);
2215 
2217  printDebug("Setting up seed points for streamlines using the current slice");
2218  vtkSmartPointer<vtkPoints> slicePoints = vtkSmartPointer<vtkPoints>::New();
2219 
2220  typedef itk::Point<double, 3> InputImagePointType;
2221  typedef itk::Point<double, 2> InputSlicePointType;
2222  itk::ImageRegionConstIteratorWithIndex<vectorImageType> imageIterator(imgSubSampled, imgSubSampled->GetLargestPossibleRegion());
2223  itk::ImageRegionConstIteratorWithIndex<floatImageType> magImageIterator(magImgSubSampled, magImgSubSampled->GetLargestPossibleRegion());
2224 
2226  InputImagePointType point;
2227  while(!magImageIterator.IsAtEnd())
2228  {
2229  double position[3];
2230 
2231  magImgSubSampled->TransformIndexToPhysicalPoint(magImageIterator.GetIndex(), point);
2232 
2233  position[0] = point[0];
2234  position[1] = point[1];
2235  position[2] = point[2];
2236 
2237  slicePoints->InsertNextPoint(position);
2238 
2239  ++magImageIterator;
2240  }
2241 
2242  vtkSmartPointer<vtkPolyData> slice = vtkSmartPointer<vtkPolyData>::New();
2243  slice->SetPoints(slicePoints);
2244 
2246  printDebug("Converting ITK Vector Image to VTK Vector Image");
2247  vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
2248  vtkSmartPointer<vtkImageData> fieldRaw = milx::Image<vectorImageType>::ConvertITKVectorImageToVTKImage(imgSubSampled);
2249  printDebug("Applying orientation to VTK Vector Image");
2250  if(!fieldRaw || fieldRaw->GetNumberOfScalarComponents() < 3)
2251  printWarning("Possible problem with the VTK Vector image");
2252  vtkSmartPointer<vtkImageData> field = milx::Image<vectorImageType>::ApplyOrientationToVTKImage(fieldRaw, imgSubSampled, matrix, false, false);
2253 
2254  field->GetPointData()->SetActiveVectors("ImageScalars");
2255 
2256  printDebug("Computing the streamlines");
2257  QPointer<milxQtModel> model = new milxQtModel; //List deletion
2258  model->setConsole(console);
2259  model->SetInput(slice);
2260  model->generateStreamLines(field);
2261  display(model);
2262 }
2263 
2264 void milxQtMain::imageToVolume(vtkSmartPointer<vtkImageData> img, bool eightbit)
2265 {
2266  printDebug("Attempting Volume Rendering");
2267  QPointer<milxQtPlot> plot = new milxQtPlot; //List deletion
2268  plot->setName("Volume Rendering");
2269  plot->setConsole(console);
2270  plot->setPlotTypeVolume();
2271  plot->SetSource(img, eightbit, false);
2272  plot->generatePlot();//emits result, not connected
2273  printDebug("Successful. Displaying...");
2274  display( qobject_cast<milxQtRenderWindow *>(plot) ); //volume not really model so need rw
2275 }
2276 
2277 void milxQtMain::imageToPlot(vtkSmartPointer<vtkImageData> img, int displaceAxis)
2278 {
2279  printDebug("Attempting Surface plot of image data");
2280  QPointer<milxQtPlot> plot = new milxQtPlot; //List deletion
2281  plot->setName("Image Surface");
2282  plot->setConsole(console);
2283  plot->setPlotTypeSurface(displaceAxis);
2284  plot->SetSource(img, false, true);
2285  plot->generatePlot();//emits result, not connected
2286  printDebug("Successful. Displaying...");
2287  display(plot);
2288 }
2289 
2290 void milxQtMain::tableToPlot(vtkSmartPointer<vtkTable> tbl, QString title)
2291 {
2292  printDebug("Attempting plot of table data");
2293  QPointer<milxQtPlot> plot = new milxQtPlot; //List deletion
2294  plot->setName(title);
2295  plot->setConsole(console);
2296  plot->SetSource(tbl);
2297  plot->generatePlot();//emits result, not connected
2298  printDebug("Successful. Displaying...");
2299 
2300  if(tbl->GetNumberOfColumns() < 10)
2301  display( qobject_cast<milxQtRenderWindow *>(plot) );
2302  else //surface plot
2303  display(plot);
2304 }
2305 
2306 void milxQtMain::voxeliseSurface(vtkSmartPointer<vtkPolyData> surface)
2307 {
2308  QPointer<milxQtImage> image = new milxQtImage; //List deletion
2309  image->generateVoxelisedSurface(surface);
2310  image->setConsole(console);
2311  image->generateImage();
2312  display(image);
2313 }
2314 
2316 {
2317  int n = getNumberOfImageWindows();
2318  if(getNumberOfWindows() < 2 || n < 2)
2319  {
2320  printError("Need more than 1 window open to blend.");
2321  return;
2322  }
2323 
2325  QPointer<milxQtImage> firstImg = nextImage();
2326 
2327  //Create slicers and the dialog
2328  QVector< QSlider* > sliders;
2329  QVector< QCheckBox* > checkBoxes;
2330  QSlider *opacitySldr = new QSlider(this);
2331  opacitySldr->setMinimum(0);
2332  opacitySldr->setMaximum(10);
2333  opacitySldr->setValue(10);
2334  QCheckBox *initialCheckbox = new QCheckBox(this);
2335  initialCheckbox->setChecked(true);
2336 // initialCheckbox->setDisabled(true);
2337  initialCheckbox->setToolTip(firstImg->strippedBaseName());
2338  QVBoxLayout *initialLayout = new QVBoxLayout(this);
2339  initialLayout->addWidget(initialCheckbox);
2340  initialLayout->addWidget(opacitySldr);
2341  QHBoxLayout *sliderLayout = new QHBoxLayout(this);
2342  sliderLayout->addLayout(initialLayout);
2343  sliders.push_back(opacitySldr);
2344  checkBoxes.push_back(initialCheckbox);
2345 
2346  if(firstImg->GetLookupTable() == NULL)
2347  {
2348  QMessageBox msgBox;
2349  msgBox.setText("Colormap not set?");
2350  msgBox.setInformativeText("Image " + firstImg->strippedBaseName() + " has no colormap set. Result could be unexpected.");
2351  msgBox.setStandardButtons(QMessageBox::Ok);
2352  msgBox.setDefaultButton(QMessageBox::Ok);
2353  msgBox.exec();
2354  }
2355 
2356  for(int j = 1; j < n; j ++)
2357  {
2358  QPointer<milxQtImage> secondImg = nextImage();
2359 
2360  if(secondImg->GetLookupTable() == NULL)
2361  {
2362  QMessageBox msgBox;
2363  msgBox.setText("Colormap not set?");
2364  msgBox.setInformativeText("Image " + secondImg->strippedBaseName() + " has no colormap set. Result could be unexpected.");
2365  msgBox.setStandardButtons(QMessageBox::Ok);
2366  msgBox.setDefaultButton(QMessageBox::Ok);
2367  msgBox.exec();
2368  }
2369 
2370  QVBoxLayout *layout = new QVBoxLayout(this);
2371  QSlider *opacitySldr2 = new QSlider(this);
2372  opacitySldr2->setMinimum(0);
2373  opacitySldr2->setMaximum(10);
2374  opacitySldr2->setValue(5);
2375  QCheckBox *checkbox = new QCheckBox(this);
2376  checkbox->setChecked(true);
2377  checkbox->setToolTip(secondImg->strippedBaseName());
2378  layout->addWidget(checkbox);
2379  layout->addWidget(opacitySldr2);
2380  sliderLayout->addLayout(layout);
2381  sliders.push_back(opacitySldr2);
2382  checkBoxes.push_back(checkbox);
2383  }
2384 // QVBoxLayout *btnLayout = new QVBoxLayout(slidersDlg);
2385  QHBoxLayout *dlgLayout = new QHBoxLayout(this);
2386  QVBoxLayout *btnlayout = new QVBoxLayout(this);
2387  QPushButton *btnOK = new QPushButton("OK", this);
2388  QPushButton *btnCancel = new QPushButton("Cancel", this);
2389  btnlayout->addWidget(btnOK);
2390  btnlayout->addWidget(btnCancel);
2391  dlgLayout->addLayout(sliderLayout);
2392  dlgLayout->addLayout(btnlayout);
2393 
2394  QDialog *slidersDlg = new QDialog(this);
2395  slidersDlg->setLayout(dlgLayout);
2396  connect(btnOK, SIGNAL(clicked()), slidersDlg, SLOT(accept()));
2397  connect(btnCancel, SIGNAL(clicked()), slidersDlg, SLOT(reject()));
2398  int ret = slidersDlg->exec();
2399 
2400  if(ret == QDialog::Rejected)
2401  return;
2402 
2403  QVector<float> opacities;
2404  for(size_t j = 0; j < sliders.size(); j ++)
2405  {
2406  float value = sliders[j]->value()*0.1;
2407  if(!checkBoxes[j]->isChecked())
2408  value = 0.0;
2409  opacities.push_back(value);
2410  }
2411 
2412  imagesBlend(opacities);
2413 }
2414 
2415 void milxQtMain::imagesBlend(QVector<float> opacities)
2416 {
2417  int n = getNumberOfImageWindows();
2418  if(getNumberOfWindows() < 2 || n < 2)
2419  {
2420  printError("Need more than 1 window open to blend.");
2421  return;
2422  }
2423 
2424  if(opacities.empty() || opacities.size() < n)
2425  {
2426  printError("Size of opacities list does not match number of open images.");
2427  return;
2428  }
2429 
2431  QPointer<milxQtImage> firstImg = nextImage();
2432  //vtkSmartPointer<vtkImageData> ucharData1 = firstImg->GetWindowLevel()->GetOutput();
2433  vtkSmartPointer<vtkImageMapToColors> filterColorsImage = vtkSmartPointer<vtkImageMapToColors>::New();
2434  filterColorsImage->SetLookupTable(firstImg->GetLookupTable());
2435 #if VTK_MAJOR_VERSION <= 5
2436  filterColorsImage->SetInput(firstImg->GetOutput());
2437 #else
2438  filterColorsImage->SetInputData(firstImg->GetOutput());
2439 #endif
2440  filterColorsImage->PassAlphaToOutputOn();
2441  filterColorsImage->Update();
2442  vtkSmartPointer<vtkImageData> ucharData1 = filterColorsImage->GetOutput();
2443 
2444  int initialExtent[6];
2445  firstImg->GetOutput()->GetExtent(initialExtent);
2446 
2447  // Combine the images (blend takes multiple connections on the 0th input port)
2448  emit working(-1);
2449  vtkSmartPointer<vtkImageBlend> blend = vtkSmartPointer<vtkImageBlend>::New();
2450  linkProgressEventOf(blend);
2451  blend->SetOpacity(0,opacities[0]);
2452  #if VTK_MAJOR_VERSION <= 5
2453  blend->AddInput(ucharData1);
2454  #else
2455  blend->AddInputData(ucharData1);
2456  #endif
2457 // blend->SetBlendModeToCompound();
2458  blend->SetBlendModeToNormal();
2459 
2460  for(int j = 1; j < n; j ++)
2461  {
2462  QPointer<milxQtImage> secondImg = nextImage();
2463 
2464  if(opacities[j] == 0.0)
2465  continue;
2466 
2467  printInfo("Blending with Image: " + secondImg->strippedName() + " with Opacity: " + QString::number(opacities[j]));
2468 // vtkSmartPointer<vtkImageData> ucharData2 = secondImg->GetWindowLevel()->GetOutput();
2469  vtkSmartPointer<vtkImageMapToColors> filterColorsOverlay = vtkSmartPointer<vtkImageMapToColors>::New();
2470  filterColorsOverlay->SetLookupTable(secondImg->GetLookupTable());
2471  #if VTK_MAJOR_VERSION <= 5
2472  filterColorsOverlay->SetInput(secondImg->GetOutput());
2473  #else
2474  filterColorsOverlay->SetInputData(secondImg->GetOutput());
2475  #endif
2476  filterColorsOverlay->PassAlphaToOutputOn();
2477  filterColorsOverlay->Update();
2478  vtkSmartPointer<vtkImageData> ucharData2 = filterColorsOverlay->GetOutput();
2479 
2480  if(!secondImg->GetLookupTable())
2481  printWarning("Colourmap is not set. Please set a colour map to ensure proper blending.");
2482 
2483  int actualExtent[6];
2484  secondImg->GetOutput()->GetExtent(actualExtent);
2485 
2486  if(initialExtent[1] == actualExtent[1] && initialExtent[3] == actualExtent[3] && initialExtent[5] == actualExtent[5])
2487  {
2488  #if VTK_MAJOR_VERSION <= 5
2489  blend->AddInput(ucharData2);
2490  #else
2491  blend->AddInputData(ucharData2);
2492  #endif
2493  blend->SetOpacity(j,opacities[j]);
2494  }
2495  else
2496  printError("Images are not the same size. Skipping.");
2497  }
2498 
2499  printInfo("Blending");
2500  blend->Update();
2501  printDebug("Number of components: " + QString::number(blend->GetOutput()->GetNumberOfScalarComponents()));
2502  emit done(-1);
2503 
2504  QPointer<milxQtImage> blendResult = new milxQtImage;
2505  blendResult->setName("Blended Images");
2506  blendResult->setConsole(console);
2507  blendResult->setData(blend->GetOutput());
2508  blendResult->generateImage();
2509 
2510  display(blendResult);
2511 }
2512 
2514 {
2515  if(getNumberOfWindows() == 0 || imageWindows.size() < 1)
2516  return;
2517 
2518  emit working(-1);
2520  QPointer<milxQtImage> firstImg = nextImage();
2521 
2522  QPointer<milxQtImage> resultImg = new milxQtImage;
2523  printInfo("Assigning " + firstImg->getName());
2524  resultImg->setName("Sum Image");
2525  resultImg->setConsole(console);
2526  resultImg->setData(firstImg, true);
2527  for(int j = 1; j < imageWindows.size(); j ++)
2528  {
2529  QPointer<milxQtImage> img = nextImage();
2530 
2531  printInfo("Adding " + img->getName());
2532  resultImg->add(img);
2533  }
2534  emit done(-1);
2535 
2536  display(resultImg);
2537 }
2538 
2540 {
2541  if(getNumberOfWindows() == 0 || imageWindows.size() < 1)
2542  return;
2543 
2544  emit working(-1);
2546  QPointer<milxQtImage> firstImg = nextImage();
2547 
2548  QPointer<milxQtImage> resultImg = new milxQtImage;
2549  printInfo("Assigning " + firstImg->getName());
2550  resultImg->setName("Difference Image");
2551  resultImg->setConsole(console);
2552  resultImg->setData(firstImg, true);
2553  for(int j = 1; j < imageWindows.size(); j ++)
2554  {
2555  QPointer<milxQtImage> img = nextImage();
2556 
2557  printInfo("Subtracting " + img->getName());
2558  resultImg->subtract(img);
2559  }
2560  emit done(-1);
2561 
2562  display(resultImg);
2563 }
2564 
2566 {
2567  if (getNumberOfWindows() == 0 || imageWindows.size() < 1)
2568  return;
2569 
2570  emit working(-1);
2572  QPointer<milxQtImage> firstImg = nextImage();
2573 
2574  QPointer<milxQtImage> resultImg = new milxQtImage;
2575  printInfo("Assigning " + firstImg->getName());
2576  resultImg->setName("Product Image");
2577  resultImg->setConsole(console);
2578  resultImg->setData(firstImg, true);
2579  for (int j = 1; j < imageWindows.size(); j++)
2580  {
2581  QPointer<milxQtImage> img = nextImage();
2582 
2583  printInfo("Multiplying " + img->getName());
2584  resultImg->multiply(img);
2585  }
2586  emit done(-1);
2587 
2588  display(resultImg);
2589 }
2590 
2592 {
2593  if(getNumberOfWindows() == 0 || imageWindows.size() < 1)
2594  return;
2595 #if (ITK_REVIEW || ITK_VERSION_MAJOR > 3) //Review only members
2596  emit working(-1);
2598  QPointer<milxQtImage> firstImg = nextImage();
2599 
2600  QPointer<milxQtImage> resultImg = new milxQtImage;
2601  printInfo("Assigning " + firstImg->getName());
2602  resultImg->setName("Convolution");
2603  resultImg->setConsole(console);
2604  resultImg->setData(firstImg, true);
2605  for(int j = 1; j < imageWindows.size(); j ++)
2606  {
2607  QPointer<milxQtImage> img = nextImage();
2608 
2609  printInfo("Convolving with " + img->getName());
2610  resultImg->convolve(img);
2611  }
2612  emit done(-1);
2613 
2614  display(resultImg);
2615 #endif
2616 }
2617 
2619 {
2620  if(getNumberOfWindows() == 0 || imageWindows.size() < 1)
2621  return;
2622 #if (ITK_REVIEW || ITK_VERSION_MAJOR > 3) //Review only members
2623  emit working(-1);
2625  std::vector< charImageType::Pointer > images;
2626  std::vector<unsigned char> values;
2627  for(int j = 0; j < imageWindows.size(); j ++)
2628  {
2629  QPointer<milxQtImage> img = nextImage();
2630 
2631  if(!img->is8BitImage() && !img->isFloatingPointImage())
2632  {
2633  printWarning("Ignoring non-labelled or float image " + img->getName());
2634  continue;
2635  }
2636  else if(img->isFloatingPointImage())
2637  {
2638  printWarning("Found float image " + img->getName());
2639  printWarning("Casting to 8-bit image for merge");
2640  images.push_back( milx::Image<floatImageType>::CastImage<charImageType>(img->GetFloatImage()) );
2641  }
2642  else
2643  {
2644  images.push_back(img->GetCharImage());
2645  printInfo("Merging with " + img->getName());
2646  }
2647 
2648  values.push_back(j);
2649  }
2650 
2651  if(images.empty())
2652  {
2653  printError("No labelled image found. Ignoring operation.");
2654  return;
2655  }
2656 
2657  charImageType::Pointer mergedImg = milx::Image<charImageType>::MergeLabelledImages(images);
2658 
2659  QPointer<milxQtImage> resultImg = new milxQtImage;
2660  resultImg->setName("Merged Labels");
2661  resultImg->setData(mergedImg, true);
2662  resultImg->setConsole(console);
2663  resultImg->generateImage();
2664  emit done(-1);
2665 
2666  display(resultImg);
2667 #endif
2668 }
2669 
2671 {
2672  if(getNumberOfWindows() == 0 || imageWindows.size() < 1)
2673  return;
2674 
2675  imagesAdd();
2676  activeImage()->setName("Average Image");
2677  activeImage()->scale( 1.0/(getNumberOfWindows()-1) );
2678 }
2679 
2681 {
2683  printInfo("Updating Multi-display");
2684  if(isActiveImage())
2685  {
2686  printInfo("Adding Image ...");
2688  }
2689  else if(isActiveModel())
2690  {
2691  printInfo("Adding Model ...");
2693  }
2694 
2695  printDebug("Uni Displayed");
2697 }
2698 
2700 {
2701  if(!imageWindows.isEmpty())
2702  menuImages->setDisabled(false);
2703  else
2704  menuImages->setDisabled(true);
2705 
2706  if(!imageWindows.isEmpty() || !modelWindows.isEmpty())
2707  menuData->setDisabled(false);
2708  else
2709  menuData->setDisabled(true);
2710 }
2711 
2712 void milxQtMain::linkProgressEventOf(vtkObject * obj)
2713 {
2714  Connector->Connect(obj,
2715  vtkCommand::ProgressEvent,
2716  this,
2717  SLOT( updateQtEvents() ),
2718  NULL, 1.0); //High Priority
2719 }
2720 
2722 {
2723  milxQtRenderWindow *customWindow = qobject_cast<milxQtRenderWindow *>(widget);
2724 
2725  if(customWindow == 0) //Not milxQt display
2726  widget->setAttribute(Qt::WA_DeleteOnClose);
2727  else
2728  {
2729  if(customWindow->isDeletableOnClose())
2730  customWindow->setAttribute(Qt::WA_DeleteOnClose);
2731  customWindow->setConsole(console);
2732  }
2733 
2734  widget->setFocusPolicy(Qt::StrongFocus);
2735 
2736  customWindow->GetRenderWindow()->SetSize(subWindowSize, subWindowSize);
2737  customWindow->resize(subWindowSize, subWindowSize);
2738 }
2739 
2741 {
2742  menuBar = new QMenuBar(this);
2743  //File
2744  menuFile = new QMenu(menuBar);
2745  actionOpen = new QAction(this);
2746  actionOpenSeries = new QAction(this);
2747  actionOpenCollect = new QAction(this);
2748  actionSave = new QAction(this);
2749  actionSaveScreen = new QAction(this);
2750  actionCloseActive = new QAction(this);
2751  actionCloseAll = new QAction(this);
2752  for (int i = 0; i < MaxRecentFiles; ++i)
2753  {
2754  actionsRecentFile[i] = new QAction(this);
2755  actionsRecentFile[i]->setVisible(false);
2756  connect(actionsRecentFile[i], SIGNAL(triggered()), this, SLOT(openRecentFile()));
2757  }
2758  actionExit = new QAction(this);
2759  //New
2760  actionNewTab = new QAction(this);
2761  //Data
2762  menuData = new QMenu(menuBar);
2763  //Images
2764  menuImages = new QMenu(menuBar);
2765  actionBlendImages = new QAction(this);
2766  actionAddImages = new QAction(this);
2767  actionAverageImages = new QAction(this);
2768  actionSubtractImages = new QAction(this);
2769  actionMultiplyImages = new QAction(this);
2770  actionConvolveImages = new QAction(this);
2771  actionMergeLabels = new QAction(this);
2772  //Window
2773  menuWindows = new QMenu(menuBar);
2774  actionLinkWindows = new QAction(this);
2775  actionCascade = new QAction(this);
2776  actionTile = new QAction(this);
2777  actionTileVertically = new QAction(this);
2778  actionTileHorizontally = new QAction(this);
2779  menuWindowList = new QMenu(menuBar);
2780  importFromMenu = new QMenu(this);
2781  //Help
2782  menuHelp = new QMenu(menuBar);
2783  actionPreferences = new QAction(this);
2784  actionContents = new QAction(this);
2785  actionControls = new QAction(this);
2786  actionAbout = new QAction(this);
2787 
2790  menuBar->addAction(menuFile->menuAction());
2791  menuFile->setTitle(QApplication::translate("MainWindow", "File", 0, QApplication::UnicodeUTF8));
2792  actionNewTab->setIcon(QIcon(":/resources/toolbar/new_tab.png"));
2793  actionNewTab->setText(QApplication::translate("MainWindow", "New Tab", 0, QApplication::UnicodeUTF8));
2794  actionNewTab->setShortcut(tr("Ctrl+t"));
2795  menuFile->addAction(actionNewTab);
2796  actionOpen->setIcon(QIcon(":/resources/toolbar/open.png"));
2797  actionOpen->setText(QApplication::translate("MainWindow", "Open", 0, QApplication::UnicodeUTF8));
2798  actionOpen->setShortcut(tr("Ctrl+o"));
2799  menuFile->addAction(actionOpen);
2800  actionOpenSeries->setIcon(QIcon(":/resources/toolbar/open_series.png"));
2801  actionOpenSeries->setText(QApplication::translate("MainWindow", "Open DICOM Series", 0, QApplication::UnicodeUTF8));
2802  actionOpenSeries->setShortcut(tr("Ctrl+Alt+o"));
2803  menuFile->addAction(actionOpenSeries);
2804  actionOpenCollect->setIcon(QIcon(":/resources/toolbar/open_collection.png"));
2805  actionOpenCollect->setText(QApplication::translate("MainWindow", "Open Model Collection", 0, QApplication::UnicodeUTF8));
2806  actionOpenCollect->setShortcut(tr("Ctrl+Shift+o"));
2807  menuFile->addAction(actionOpenCollect);
2808  actionSave->setIcon(QIcon(":/resources/toolbar/save.png"));
2809  actionSave->setText(QApplication::translate("MainWindow", "Save", 0, QApplication::UnicodeUTF8));
2810  actionSave->setShortcut(tr("Ctrl+s"));
2811  menuFile->addAction(actionSave);
2812  actionSaveScreen->setIcon(QIcon(":/resources/toolbar/screenshot.png"));
2813  actionSaveScreen->setText(QApplication::translate("MainWindow", "Save Screenshot", 0, QApplication::UnicodeUTF8));
2814  actionSaveScreen->setShortcut(tr("Shift+Ctrl+s"));
2815  menuFile->addAction(actionSaveScreen);
2816  menuFile->addSeparator();
2817  //Closing
2818  menuFile->addAction(actionCloseActive);
2819  actionCloseActive->setIcon(QIcon(":/resources/toolbar/close.png"));
2820  actionCloseActive->setText(QApplication::translate("MainWindow", "Close", 0, QApplication::UnicodeUTF8));
2821  actionCloseActive->setShortcut(tr("Ctrl+w"));
2822  menuFile->addAction(actionCloseActive);
2823  actionCloseAll->setIcon(QIcon(":/resources/toolbar/close_all.png"));
2824  actionCloseAll->setText(QApplication::translate("MainWindow", "Close All", 0, QApplication::UnicodeUTF8));
2825  actionCloseAll->setShortcut(tr("Ctrl+Shift+w"));
2826  menuFile->addAction(actionCloseAll);
2827  menuFile->addSeparator();
2828  //Recent file list
2829  for (int i = 0; i < MaxRecentFiles; ++i)
2830  menuFile->addAction(actionsRecentFile[i]);
2831  actionRecentFileSeparator = menuFile->addSeparator();
2832  updateRecentFileActions(); //Do not move up
2833  //Exit
2834  menuFile->addAction(actionPreferences);
2835  actionPreferences->setIcon(QIcon(":/resources/toolbar/settings.png"));
2836  actionPreferences->setText(QApplication::translate("MainWindow", "Preferences ...", 0, QApplication::UnicodeUTF8));
2837  actionPreferences->setShortcut(tr("Ctrl+p"));
2838  actionExit->setIcon(QIcon(":/resources/toolbar/exit.png"));
2839  actionExit->setText(QApplication::translate("MainWindow", "Exit", 0, QApplication::UnicodeUTF8));
2840  actionExit->setShortcut(tr("Ctrl+x"));
2841  menuFile->addAction(actionExit);
2843  menuBar->addAction(menuData->menuAction());
2844  menuData->setTitle(QApplication::translate("MainWindow", "Data", 0, QApplication::UnicodeUTF8));
2846  menuImages->setTitle(QApplication::translate("MainWindow", "Images", 0, QApplication::UnicodeUTF8));
2847  menuBar->addAction(menuImages->menuAction());
2848  actionBlendImages->setText(QApplication::translate("MainWindow", "Blend Images", 0, QApplication::UnicodeUTF8));
2849  actionBlendImages->setShortcut(tr("Ctrl+b"));
2850  menuImages->addAction(actionBlendImages);
2851  actionAddImages->setText(QApplication::translate("MainWindow", "Add Images", 0, QApplication::UnicodeUTF8));
2852  actionAddImages->setShortcut(tr("Ctrl+a"));
2853  menuImages->addAction(actionAddImages);
2854  actionAverageImages->setText(QApplication::translate("MainWindow", "Average Images", 0, QApplication::UnicodeUTF8));
2855  actionAverageImages->setShortcut(tr("Ctrl+Shift+a"));
2856  menuImages->addAction(actionAverageImages);
2857  actionSubtractImages->setText(QApplication::translate("MainWindow", "Difference Images", 0, QApplication::UnicodeUTF8));
2858  actionSubtractImages->setShortcut(tr("Ctrl+d"));
2859  menuImages->addAction(actionSubtractImages);
2860  actionMultiplyImages->setText(QApplication::translate("MainWindow", "Multiply Images", 0, QApplication::UnicodeUTF8));
2861  actionMultiplyImages->setShortcut(tr("Ctrl+d"));
2862  menuImages->addAction(actionMultiplyImages);
2863  actionConvolveImages->setText(QApplication::translate("MainWindow", "Convolve Images", 0, QApplication::UnicodeUTF8));
2864  actionConvolveImages->setShortcut(tr("Ctrl+c"));
2865  menuImages->addAction(actionConvolveImages);
2866  actionMergeLabels->setText(QApplication::translate("MainWindow", "Merge Labels", 0, QApplication::UnicodeUTF8));
2867  actionMergeLabels->setShortcut(tr("Ctrl+l"));
2868  menuImages->addAction(actionMergeLabels);
2870  menuBar->addAction(menuWindows->menuAction());
2871  menuWindows->setTitle(QApplication::translate("MainWindow", "Windows", 0, QApplication::UnicodeUTF8));
2872  actionLinkWindows->setText(QApplication::translate("MainWindow", "Link All Windows", 0, QApplication::UnicodeUTF8));
2873  actionLinkWindows->setIcon(QIcon(":/resources/toolbar/link.png"));
2874  actionLinkWindows->setCheckable(true);
2875  menuWindows->addAction(actionLinkWindows);
2876  actionCascade->setIcon(QIcon(":/resources/toolbar/cascade.png"));
2877  actionCascade->setText(QApplication::translate("MainWindow", "Cascade", 0, QApplication::UnicodeUTF8));
2878  menuWindows->addAction(actionCascade);
2879  actionTile->setIcon(QIcon(":/resources/toolbar/tile.png"));
2880  actionTile->setText(QApplication::translate("MainWindow", "Tile", 0, QApplication::UnicodeUTF8));
2881  menuWindows->addAction(actionTile);
2882  actionTileVertically->setIcon(QIcon(":/resources/toolbar/tilev.png"));
2883  actionTileVertically->setText(QApplication::translate("MainWindow", "Tile Vertically", 0, QApplication::UnicodeUTF8));
2884  menuWindows->addAction(actionTileVertically);
2885  actionTileHorizontally->setIcon(QIcon(":/resources/toolbar/tileh.png"));
2886  actionTileHorizontally->setText(QApplication::translate("MainWindow", "Tile Horizontally", 0, QApplication::UnicodeUTF8));
2887  menuWindows->addAction(actionTileHorizontally);
2888  updateWindowMenu();
2889  connect(menuWindows, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));
2891  menuHelp->setTitle(QApplication::translate("MainWindow", "Help", 0, QApplication::UnicodeUTF8));
2892  menuBar->addAction(menuHelp->menuAction());
2893  actionContents->setText(QApplication::translate("MainWindow", "sMILX Help Contents", 0, QApplication::UnicodeUTF8));
2894  actionContents->setIcon(QIcon(":/resources/toolbar/help.png"));
2895  actionContents->setShortcut(tr("F1"));
2896  menuHelp->addAction(actionContents);
2897  actionControls->setText(QApplication::translate("MainWindow", "Controls", 0, QApplication::UnicodeUTF8));
2898  actionControls->setShortcut(tr("F2"));
2899  actionControls->setIcon(QIcon(":/resources/toolbar/controls.png"));
2900  menuHelp->addAction(actionControls);
2901  actionAbout->setText(QApplication::translate("MainWindow", "About", 0, QApplication::UnicodeUTF8));
2902  actionAbout->setShortcut(tr("Ctrl+h"));
2903  menuHelp->addAction(actionAbout);
2904 
2906  actionCompare = new QAction(this);
2907  actionCompare->setText(QApplication::translate("MainWindow", "Compare", 0, QApplication::UnicodeUTF8));
2908  actionCompare->setShortcut(tr("Ctrl+u"));
2909  actionCompare->setDisabled(true);
2910  menuWindowList->setTitle(QApplication::translate("MainWindow", "Switch Window To", 0, QApplication::UnicodeUTF8));
2911  connect(menuWindowList, SIGNAL(aboutToShow()), this, SLOT(updateWindowListMenu()));
2912  importFromMenu->setTitle(QApplication::translate("MainWindow", "Import View From", 0, QApplication::UnicodeUTF8));
2913  connect(importFromMenu, SIGNAL(aboutToShow()), this, SLOT(updateImportFromMenu()));
2914 
2915 #if !(ITK_REVIEW || ITK_VERSION_MAJOR > 3) //Review only members
2916  actionConvolveImages->setDisabled(true);
2917  actionMergeLabels->setDisabled(true);
2918 #endif
2919 
2921  actionImageText = new QAction(this);
2922  actionImageText->setText(QApplication::translate("MainWindow", "Text", 0, QApplication::UnicodeUTF8));
2923  actionImageText->setShortcut(tr("Ctrl+Alt+t"));
2924 
2925  statusBar()->showMessage(tr("Ready"));
2926  setMenuBar(menuBar);
2927 }
2928 
2930 {
2931  defaultViewBox = new QComboBox(this);
2932  defaultViewBox->insertItem(AXIAL, "View: Axial");
2933  defaultViewBox->insertItem(CORONAL, "View: Coronal");
2934  defaultViewBox->insertItem(SAGITTAL, "View: Sagittal");
2935  defaultViewBox->setEditable(false);
2936  QObject::connect(defaultViewBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateWindowsWithView(int)));
2937 
2938  defaultViewTypeBox = new QComboBox(this);
2939  defaultViewTypeBox->insertItem(SINGLE, "View Type: Single");
2940  defaultViewTypeBox->insertItem(SCANNER, "View Type: Multiple");
2941  defaultViewTypeBox->setEditable(false);
2942  QObject::connect(defaultViewTypeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateWindowsWithViewType(int)));
2943 
2944  defaultOrientationTypeBox = new QComboBox(this);
2945  defaultOrientationTypeBox->insertItem(RADIOLOGICAL, "Orient. Type: Radiological");
2946  defaultOrientationTypeBox->insertItem(NEUROLOGICAL, "Orient. Type: Neurological");
2947  defaultOrientationTypeBox->setEditable(false);
2948  QObject::connect(defaultOrientationTypeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateWindowsWithViewOrientation(int)));
2949 }
2950 
2952 {
2953  fileToolBar = addToolBar(tr("File"));
2954  fileToolBar->addAction(actionNewTab);
2955  fileToolBar->addAction(actionOpen);
2956  fileToolBar->addAction(actionOpenSeries);
2957  fileToolBar->addAction(actionOpenCollect);
2958  fileToolBar->addAction(actionSave);
2959  fileToolBar->addAction(actionSaveScreen);
2960  fileToolBar->addAction(actionCloseActive);
2961  fileToolBar->addAction(actionCloseAll);
2962  fileToolBar->setObjectName("FileToolBar");
2963 
2964 // editToolBar = addToolBar(tr("Edit"));
2965 // editToolBar->addAction(cutAct);
2966 // editToolBar->addAction(copyAct);
2967 // editToolBar->addAction(pasteAct);
2968 
2969  windowToolBar = addToolBar(tr("Window"));
2970  windowToolBar->addAction(actionTile);
2971  windowToolBar->addAction(actionTileVertically);
2973  windowToolBar->addAction(actionCascade);
2974  windowToolBar->addAction(actionLinkWindows);
2975  windowToolBar->addAction(actionConsole);
2976  windowToolBar->addAction(actionContents);
2977  windowToolBar->addAction(actionControls);
2978  windowToolBar->addAction(actionPreferences);
2979  windowToolBar->setObjectName("WindowToolBar");
2980 
2981  defaultToolBar = addToolBar(tr("Default"));
2982  QLabel *defaultBarLabel = new QLabel(this);
2983 // defaultBarLabel->setText("View: ");
2984  defaultToolBar->addWidget(defaultBarLabel);
2985  defaultToolBar->addWidget(defaultViewBox);
2986  defaultToolBar->addWidget(defaultViewTypeBox);
2988  defaultToolBar->setObjectName("DefaultToolBar");
2989 
2990  //Sliders etc.
2991  imageToolBar = new QToolBar(tr("Image"), this);
2992  imageToolBar->setObjectName("Image");
2993  imageLevelSlider = new QSlider(Qt::Vertical, this);
2994  imageLevelSlider->setMinimum(0);
2995  imageLevelSlider->setMaximum(100);
2996  imageLevelSlider->setSingleStep(1);
2997  imageLevelSlider->setValue(50);
2998  imageLevelSlider->setTickPosition(QSlider::TicksRight);
2999  imageLevelSlider->setTickInterval(1);
3000  QObject::connect(imageLevelSlider, SIGNAL(valueChanged(int)), this, SLOT(updateWindowsWithValue(int)));
3001  imageLevelButton = new QPushButton(tr(""), this);
3002  imageLevelButton->setIcon(QIcon(":/resources/toolbar/intensity.png"));
3003  QObject::connect(imageLevelButton, SIGNAL(clicked()), this, SLOT(updateWindowsWithAutoLevel()));
3004  refreshButton = new QPushButton(tr(""), this);
3005  refreshButton->setIcon(QIcon(":/resources/toolbar/refresh.png"));
3006  QObject::connect(refreshButton, SIGNAL(clicked()), this, SLOT(updateWindowsWithRefresh()));
3007  cursorButton = new QPushButton(tr(""), this);
3008  cursorButton->setIcon(QIcon(":/resources/toolbar/crosshairs_2D.png"));
3009  QObject::connect(cursorButton, SIGNAL(clicked()), this, SLOT(updateWindowsWithCursors()));
3010  /*imageLevelDial = new QDial(this);
3011 // imageLevelDial->setFloatable(true);
3012  imageLevelDial->setMinimum(0);
3013  imageLevelDial->setMaximum(100);
3014  imageLevelDial->setSingleStep(1);
3015  imageLevelDial->setValue(50);*/
3016  addToolBar(Qt::LeftToolBarArea, imageToolBar);
3017 // imageToolBar->addAction(actionImageText);
3018  imageToolBar->addWidget(refreshButton);
3019  imageToolBar->addWidget(imageLevelButton);
3020  imageToolBar->addWidget(cursorButton);
3021  imageToolBar->addWidget(imageLevelSlider);
3022 // imageToolBar->addWidget(imageLevelDial);
3023 }
3024 
3026 {
3027  qRegisterMetaType< milxQtRenderWindow* >("milxQtRenderWindow*");
3028  qRegisterMetaType< milxQtModel* >("milxQtModel*");
3029  qRegisterMetaType< milxQtImage* >("milxQtImage*");
3030 
3031  QObject::connect(workspaces, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
3032  QObject::connect(windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(setActiveWindow(QWidget *)));
3035  QObject::connect(actionNewTab, SIGNAL(activated()), this, SLOT(newTab()));
3036  QObject::connect(actionOpen, SIGNAL(activated()), this, SLOT(open()));
3037  QObject::connect(actionOpenSeries, SIGNAL(activated()), this, SLOT(openSeries()));
3038  QObject::connect(actionOpenCollect, SIGNAL(activated()), this, SLOT(openCollection()));
3039  QObject::connect(actionSave, SIGNAL(activated()), this, SLOT(save()));
3040  QObject::connect(actionSaveScreen, SIGNAL(activated()), this, SLOT(saveScreen()));
3041  QObject::connect(actionCloseActive, SIGNAL(activated()), this, SLOT(closeTabActiveWindow()));
3042  QObject::connect(actionCloseAll, SIGNAL(activated()), this, SLOT(closeTabAllWindows()));
3043  QObject::connect(actionExit, SIGNAL(activated()), this, SLOT(close()));
3045  QObject::connect(menuData, SIGNAL(aboutToShow()), this, SLOT(dataMenu()));
3047  QObject::connect(actionBlendImages, SIGNAL(activated()), this, SLOT(imagesMix()));
3048  QObject::connect(actionAddImages, SIGNAL(activated()), this, SLOT(imagesAdd()));
3049  QObject::connect(actionAverageImages, SIGNAL(activated()), this, SLOT(imagesAverage()));
3050  QObject::connect(actionSubtractImages, SIGNAL(activated()), this, SLOT(imagesSubtract()));
3051  QObject::connect(actionMultiplyImages, SIGNAL(activated()), this, SLOT(imagesMultiply()));
3052  #if (ITK_REVIEW || ITK_VERSION_MAJOR > 3) //Review only members
3053  QObject::connect(actionConvolveImages, SIGNAL(activated()), this, SLOT(imagesConvolve()));
3054  #endif
3055  QObject::connect(actionMergeLabels, SIGNAL(activated()), this, SLOT(imagesMergeLabels()));
3057  //actionLinkWindows is not connected because its used as a Boolean in the transferViewToWindows() member
3058  QObject::connect(actionCascade, SIGNAL(activated()), this, SLOT(cascadeTab()));
3059  QObject::connect(actionTile, SIGNAL(activated()), this, SLOT(tileTab()));
3060  QObject::connect(actionTileVertically, SIGNAL(activated()), this, SLOT(tileTabVertically()));
3061  QObject::connect(actionTileHorizontally, SIGNAL(activated()), this, SLOT(tileTabHorizontally()));
3063  QObject::connect(actionContents, SIGNAL(activated()), this, SLOT(helpContents()));
3064  QObject::connect(actionPreferences, SIGNAL(activated()), this, SLOT(preferences()));
3065  QObject::connect(actionControls, SIGNAL(activated()), this, SLOT(controls()));
3066  QObject::connect(actionAbout, SIGNAL(activated()), this, SLOT(about()));
3067 
3069  QObject::connect(actionCompare, SIGNAL(activated()), this, SLOT(unify()));
3070 }
3071 
3073 {
3074  progressCallCount = 1; //done decrements
3075  progressBar = new QProgressBar(this); //hierarchical deletion
3076  progressBar->setMaximumSize(128, progressBar->maximumSize().height());
3077  statusBar()->addPermanentWidget(progressBar);
3078  done(-1);
3079 }
3080 
3082 {
3083  actionNewTab->setToolTip("Create a new tab for display");
3084  actionNewTab->setStatusTip("Create a new tab for display");
3085  actionOpen->setToolTip("Open a file (all supported formats, including those by plugins) for display");
3086  actionOpen->setStatusTip("Open a file (all supported formats, including those by plugins) for display");
3087  actionOpenSeries->setToolTip("Open a DICOM series by choosing a directory");
3088  actionOpenSeries->setStatusTip("Open a DICOM series by choosing a directory");
3089  actionOpenCollect->setToolTip("Open a model collection by choosing a set of files");
3090  actionOpenCollect->setStatusTip("Open a model collection by choosing a set of files");
3091  actionSave->setToolTip("Saves the data in the active window (as a supported file format, including those in plugins)");
3092  actionSave->setStatusTip("Saves the data in the active window (as a supported file format, including those in plugins)");
3093  actionSaveScreen->setToolTip("Save a screenshot of the active window exactly as displayed");
3094  actionSaveScreen->setStatusTip("Save a screenshot of the active window exactly as displayed");
3095  actionCloseActive->setToolTip("Close active window");
3096  actionCloseActive->setStatusTip("Close active window");
3097  actionCloseAll->setToolTip("Close all windows in the tab");
3098  actionCloseAll->setStatusTip("Close all windows in the tab");
3099  actionCascade->setToolTip("Cascade windows in current tab");
3100  actionCascade->setStatusTip("Cascade windows in current tab");
3101  actionTile->setToolTip("Tile windows in current tab");
3102  actionTile->setStatusTip("Tile windows in current tab");
3103  actionTileVertically->setToolTip("Tile windows vertically in current tab");
3104  actionTileVertically->setStatusTip("Tile windows vertically in current tab");
3105  actionTileHorizontally->setToolTip("Tile windows horizontally in current tab");
3106  actionTileHorizontally->setStatusTip("Tile windows horizontally in current tab");
3107  actionConsole->setToolTip("Hide/Show console docking window");
3108  actionConsole->setStatusTip("Hide/Show console docking window");
3109  actionLinkWindows->setToolTip("Link the view in all windows");
3110  actionLinkWindows->setStatusTip("Link the view in all windows");
3111  actionContents->setToolTip("Browse the help");
3112  actionContents->setStatusTip("Browse the help");
3113  actionPreferences->setToolTip("Customise the program settings");
3114  actionPreferences->setStatusTip("Customise the program settings");
3115 
3116  actionCompare->setToolTip("Compare the data in window with others by placing it into a multi-display window");
3117  actionCompare->setStatusTip("Compare the data in window with others by placing it into a multi-display window");
3118 
3119  refreshButton->setToolTip("Refresh the window views, levels and camera to default.");
3120  refreshButton->setStatusTip("Refresh the window views, levels and camera to default.");
3121  imageLevelButton->setToolTip("Auto level the image intensities based on inter-quartile ranges.");
3122  imageLevelButton->setStatusTip("Auto level the image intensities based on inter-quartile ranges.");
3123  cursorButton->setToolTip("Enable crosshairs for all images.");
3124  cursorButton->setStatusTip("Enable crosshairs for all images.");
3125 }
3126 
3127 void milxQtMain::contextMenuEvent(QContextMenuEvent *currentEvent)
3128 {
3129  QMenu* contextMenu = new QMenu(this);
3130 
3131  contextMenu->addAction(actionNewTab);
3132  contextMenu->addAction(actionOpen);
3133  contextMenu->addAction(actionOpenSeries);
3134  contextMenu->addAction(actionOpenCollect);
3135  contextMenu->addAction(actionSave);
3136  contextMenu->addAction(actionSaveScreen);
3137  contextMenu->addSeparator();
3138  contextMenu->addAction(actionPreferences);
3139  contextMenu->addAction(actionCloseActive);
3140  contextMenu->addAction(actionCloseAll);
3141  contextMenu->addSeparator();
3142  contextMenu->addAction(actionCascade);
3143  contextMenu->addAction(actionTile);
3144  contextMenu->addAction(actionTileVertically);
3145  contextMenu->addAction(actionTileHorizontally);
3146  contextMenu->addSeparator();
3147  contextMenu->addAction(actionExit);
3148 
3149  contextMenu->exec(currentEvent->globalPos());
3150 }
3151 
3152 void milxQtMain::dragEnterEvent(QDragEnterEvent *currentEvent)
3153 {
3154  if(currentEvent->mimeData()->hasFormat("text/uri-list") || currentEvent->mimeData()->hasFormat("text/plain"))
3155  currentEvent->acceptProposedAction();
3156 }
3157 
3158 void milxQtMain::dropEvent(QDropEvent *currentEvent)
3159 {
3160  QList<QUrl> urlsList = currentEvent->mimeData()->urls();
3161  QString tmp;
3162 
3163  for(int j = 0; j < urlsList.size(); j ++)
3164  {
3165  if(urlsList[j].isValid())
3166  {
3167 #ifdef Q_WS_WIN
3168  tmp = urlsList[j].path().remove(0,1);
3169 #else
3170  tmp = urlsList[j].path();
3171 #endif
3172  printInfo("Dropped Path: " + tmp);
3173  loadFile(tmp);
3174  }
3175  }
3176 
3177  currentEvent->acceptProposedAction();
3178 }
3179 
3180 void milxQtMain::closeEvent(QCloseEvent *event)
3181 {
3182  writeSettings();
3183  event->accept();
3184 }
3185 
3187 {
3188  QDir pluginsDir(qApp->applicationDirPath());
3189  QString sharedObjectSuffix = "";
3190 #if defined(Q_OS_WIN)
3191  if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
3192  pluginsDir.cdUp();
3193  sharedObjectSuffix = "dll";
3194 #elif defined(Q_OS_MAC)
3195  /*if (pluginsDir.dirName() == "MacOS")
3196  {
3197  pluginsDir.cdUp();
3198  pluginsDir.cdUp();
3199  pluginsDir.cdUp();
3200  }*/
3201  sharedObjectSuffix = "dylib";
3202 #else
3203  sharedObjectSuffix = "so";
3204 #endif
3205  pluginsDir.cdUp();
3206  pluginsDir.cd("plugins");
3207  printInfo("Plugin Path to be searched: " + pluginsDir.path());
3208 
3209  QStringList pluginFileNames = pluginsDir.entryList(QDir::Files);
3210  foreach (QString fileName, pluginFileNames)
3211  {
3212  QFileInfo fi(fileName);
3213 
3214  #if defined(Q_OS_WIN)
3215  if(!fi.completeSuffix().contains(sharedObjectSuffix, Qt::CaseInsensitive))
3216  continue;
3217  #else
3218 // printDebug("File: " + fileName + ", ext: " + fi.completeSuffix());
3219  if(!fi.completeSuffix().contains(sharedObjectSuffix, Qt::CaseSensitive))
3220  continue;
3221  #endif
3222 
3223  printDebug("Attempting to Load " + fileName);
3224  QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
3225  QObject *plugin = pluginLoader.instance();
3226  if (plugin)
3227  {
3228  printDebug("Instanced ... ");
3229  milxQtPluginFactory *pluginFactory = qobject_cast<milxQtPluginFactory *>(plugin);
3230  if (pluginFactory)
3231  {
3232  QPointer<milxQtPluginInterface> loadedPlugin = pluginFactory->newPlugin(this); //hierarchical deletion
3233  plugins.append( loadedPlugin );
3234 
3235  connect(loadedPlugin, SIGNAL(resultAvailable(milxQtRenderWindow*)), this, SLOT(display(milxQtRenderWindow*)));
3236  connect(loadedPlugin, SIGNAL(resultAvailable(milxQtModel*)), this, SLOT(display(milxQtModel*)));
3237  connect(loadedPlugin, SIGNAL(resultAvailable(milxQtImage*)), this, SLOT(display(milxQtImage*)));
3238  connect(loadedPlugin, SIGNAL( resultAvailable(vtkPolyDataCollection*, QStringList&) ), this, SLOT( display(vtkPolyDataCollection*, QStringList&) ));
3239 
3240  if(loadedPlugin->isThreaded())
3241  {
3243  connect(loadedPlugin, SIGNAL(finished()), loadedPlugin, SLOT(postStartTasks()));
3244  }
3245 
3246  if(loadedPlugin->isDockable())
3247  {
3248  if(!loadedPlugin->isConsole())
3249  {
3250  addDockWidget(loadedPlugin->dockDefaultArea(), loadedPlugin->dockWidget());
3251  dockActions.append(loadedPlugin->dockWidget()->toggleViewAction());
3252  // loadedPlugin->start(); //!< Start the plugins event loop
3253  }
3254  else
3255  {
3256  console->setTab(loadedPlugin->dockWidget()->widget());
3257  }
3258  }
3259 
3260  if(loadedPlugin->isExtension())
3261  {
3262  QString tmpName = "[" + loadedPlugin->name() + " Extension]";
3263 
3264  QAction *extAction = new QAction(this);
3265  extAction->setText(QApplication::translate("Plugin", tmpName.toStdString().c_str(), 0, QApplication::UnicodeUTF8));
3266  extAction->setShortcut(tr("Alt+n"));
3267 
3268  if(loadedPlugin->genericResult())
3269  renderExtsActions.append(extAction);
3270 
3271  if(loadedPlugin->modelResult())
3272  modelExtsActions.append(extAction);
3273 
3274  if(loadedPlugin->imageResult())
3275  imageExtsActions.append(extAction);
3276 
3277  connect(extAction, SIGNAL(triggered()), loadedPlugin, SLOT(loadExtension()));
3278  }
3279 
3280  foreach(QMenu *menuToAdd, loadedPlugin->addToMenuBar())
3281  {
3282  menuBar->insertAction(menuWindows->menuAction(), menuToAdd->menuAction());
3283  }
3284 
3285  loadedPlugin->setConsole(console);
3286 
3287  //Update support formats strings
3288  foreach (QString ext, loadedPlugin->saveExtensions())
3289  {
3290  saveSupport += " *" + ext;
3291  }
3292  foreach (QString ext, loadedPlugin->openExtensions())
3293  {
3294  openSupport += " *" + ext;
3295  }
3296 
3297  printInfo(plugins.last()->name() + " plugin was successfully loaded.");
3298  }
3299  //printDebug("Unloading Plugin Loader.");
3300  //pluginLoader.unload();
3301  }
3302  else
3303  printError("Failed to load plugin: " + pluginLoader.errorString());
3304  }
3305  printDebug("Support Save Formats: " + saveSupport);
3306  printDebug("Support Open Formats: " + openSupport);
3307 
3308  return false;
3309 }
3310 
3312 {
3313  QSettings settings("Shekhar Chandra", "milxQt");
3314 
3315  settings.beginGroup("milxQtMain");
3316 
3317  settings.setValue("size", size());
3318  settings.setValue("pos", pos());
3319  settings.setValue("geometry", saveGeometry());
3320  settings.setValue("windowState", saveState());
3321  settings.setValue("defaultView", defaultViewBox->currentIndex());
3322  settings.setValue("defaultViewType", defaultViewTypeBox->currentIndex());
3323  settings.setValue("defaultOrientationType", defaultOrientationTypeBox->currentIndex());
3324  //Options
3325  settings.setValue("whiteBackground", whiteBackground);
3326  settings.setValue("humanGlyph", humanGlyph);
3327  settings.setValue("subWindowSize", subWindowSize);
3328  settings.setValue("maxProcessors", maxProcessors);
3329  settings.setValue("magnifyFactor", magnifyFactor);
3330  settings.setValue("timestamping", timestamping);
3331  settings.setValue("interpolationImages", interpolationImages);
3332  settings.setValue("orientationImages", orientationImages);
3333  settings.setValue("interpolationModels", interpolationModels);
3334  settings.setValue("scalarBarModels", scalarBarModels);
3335 
3336  settings.endGroup();
3337 }
3338 
3340 {
3341  QSettings settings("Shekhar Chandra", "milxQt");
3342 
3343  //New defaults
3344  QSize desktopSize = qApp->desktop()->availableGeometry().size();
3345  int newWidth = 2.0*desktopSize.width()/3.0 + 0.5;
3346  int newHeight = 4.0*desktopSize.height()/5.0 + 0.5;
3347  int xOffset = (desktopSize.width()-newWidth)/2.0;
3348  int yOffset = (desktopSize.height()-newHeight)/2.0;
3349  int defaultViewMode = 2; //axial
3350  int defaultViewTypeMode = 0; //1-multi-view
3351  int defaultOrientationTypeMode = 0; //radiological
3352 
3353  settings.beginGroup("milxQtMain");
3354  resize( settings.value("size", QSize(newWidth, newHeight)).toSize() );
3355  move( settings.value("pos", QPoint(xOffset, yOffset)).toPoint() );
3356  restoreGeometry(settings.value("geometry").toByteArray());
3357  restoreState(settings.value("windowState").toByteArray());
3358  defaultViewBox->setCurrentIndex( settings.value("defaultView", defaultViewMode).toInt() );
3359  defaultViewTypeBox->setCurrentIndex( settings.value("defaultViewType", defaultViewTypeMode).toInt() );
3360  defaultOrientationTypeBox->setCurrentIndex( settings.value("defaultOrientationType", defaultOrientationTypeMode).toInt() );
3361  //Options
3362  whiteBackground = settings.value("whiteBackground", whiteBackground).toBool();
3363  humanGlyph = settings.value("humanGlyph", humanGlyph).toBool();
3364  subWindowSize = settings.value("subWindowSize", subWindowSize).toInt();
3365  maxProcessors = settings.value("maxProcessors", maxProcessors).toInt();
3366  magnifyFactor = settings.value("magnifyFactor", magnifyFactor).toInt();
3367  timestamping = settings.value("timestamping", timestamping).toBool();
3368  interpolationImages = settings.value("interpolationImages", interpolationImages).toBool();
3369  orientationImages = settings.value("orientationImages", orientationImages).toBool();
3370  interpolationModels = settings.value("interpolationModels", interpolationModels).toBool();
3371  scalarBarModels = settings.value("scalarBarModels", scalarBarModels).toBool();
3372 
3374  restoreDockWidget(console->dockWidget());
3375  console->setTimestamps(timestamping);
3376 
3377  settings.endGroup();
3378 }
3379 
virtual void createMenu(QMenu *menu)
Create the menu for the data in this object. Used for context menu and file menus.
void imageToTensorField(vectorImageType::Pointer img, floatImageType::Pointer magImg, int subsampleFactor=0, float scaling=0.0)
Compute tensor field from image.
milxQtRenderWindow * nextRenderWindow()
Get the next render window opened in the current tab.
QString saveSupport
Save file extension support list, cats all known extensions.
Definition: milxQtMain.h:957
void update()
Update the GUI elements, such as menus etc. to most up-to-date status.
bool isPlot(QWidget *win)
Returns true if window is an Plot (milxQtPlot object)
Definition: milxQtMain.cpp:348
bool humanGlyph
Prefer showing human glyph?
Definition: milxQtMain.h:933
void cascadeTab()
Cascade all the windows in the current tab.
Definition: milxQtMain.h:435
QString strippedName(const QString &fullFileName)
Returns the filename with the path stripped.
Definition: milxQtMain.h:1088
void closeTab(int index)
Close the tab.
Definition: milxQtMain.cpp:931
void loadFiles(const QStringList &filenames)
Opens multiple files for viewing in the current tab.
Definition: milxQtMain.cpp:523
QAction * actionSave
save action
Definition: milxQtMain.h:964
void printError(QString msg)
Error message wrapper for console.
Definition: milxQtMain.h:829
void generateVoxelisedSurface(vtkSmartPointer< vtkPolyData > surfaceToVoxelise, double *bounds=NULL, double *spacing=NULL)
Converts or Voxelises a surface (vtkPolyData) to an image.
QAction * actionSubtractImages
subtract images batch operation action
Definition: milxQtMain.h:977
void disableDefaultView()
Disables the default view whenever data is process or displayed. Enabled by default.
void transferViewToWindows(vtkObject *obj, unsigned long, void *client_data, void *, vtkCommand *command)
If the windows are linked, copy viewing options from one window to all others.
QComboBox * defaultViewBox
Box for default view.
Definition: milxQtMain.h:1029
void setCurrentFile(const QString &fileName)
Saves the recent opened/saved file into the recent files list.
int maxProcessors
Max processors to use.
Definition: milxQtMain.h:935
QAction * actionAbout
Action for showing about information.
Definition: milxQtMain.h:992
void setName(const QString filename)
Set the name of the data.
void cleanUpOnClose(QWidget *win)
Removes references to windows that are closed so they are no longer "open".
Definition: milxQtMain.cpp:256
bool loadPlugins()
Loads plugins (which are assumed to be DLLs) according to the milxQtPluginInterface.
bool whiteBackground
Prefer white backgrounds?
Definition: milxQtMain.h:932
void updateWindowsWithView(int value)
Updates the windows view, such as from a combo box etc.
bool scalarBarModels
Show scalar bar for models?
Definition: milxQtMain.h:941
QList< QAction *> imageExtsActions
List of image extenstion actions loaded succesfully.
Definition: milxQtMain.h:1021
QAction * actionCascade
Cascade windows in workspace action.
Definition: milxQtMain.h:983
QAction * actionMergeLabels
Merge labelled images batch operation action.
Definition: milxQtMain.h:980
This class represents the MILX Qt Render Window Display object using QVTK.
vtkSmartPointer< vtkEventQtSlotConnect > Connector
VTK Events to slots convertor.
Definition: milxQtMain.h:1037
void imageToStreamLines(vectorImageType::Pointer img, floatImageType::Pointer magImg, size_t subsampleFactor=0)
Compute streamlines from vector image from the extents supplied (pixels of which are used as start po...
QList< QAction *> renderExtsActions
List of render window extenstion actions loaded succesfully.
Definition: milxQtMain.h:1019
static bool OpenDelimitedText(const std::string filename, vtkSmartPointer< vtkTable > &data, const std::string delimiter=",")
Opens ASCII Delimited text files such as CSV files. Data is loaded into the table.
Definition: milxFile.cxx:738
QAction * actionTile
Tile windows in workspace action.
Definition: milxQtMain.h:984
void updateQtEvents()
Update the Qt events, used to keep UI responsive.
Definition: milxQtMain.h:876
QMenu * menuFile
File menu.
Definition: milxQtMain.h:946
bool saveImage(const QString filename, vtkImageData *data)
Saves data as an image file, which is any of the following: JPEG, PNG, DICOM, TIFF, NIFTI, HDR etc.
Definition: milxQtFile.cpp:531
virtual QString strippedNamePrefix()
Returns the stripped (path removed) name of the data with "Generic" prefix.
Definition: milxQtWindow.h:98
QMenu * menuImages
File menu.
Definition: milxQtMain.h:947
QAction * actionControls
Action for showing about information.
Definition: milxQtMain.h:991
bool isUnifiedWindow(QWidget *win)
Returns true if window is an UnifiedWindow (milxQtUnifiedWindow object)
Definition: milxQtMain.cpp:371
void addToUnifiedWindow(milxQtImage *img)
Adds an image to the unified window and links its results.
Definition: milxQtMain.h:556
void setActiveWindow(QWidget *currentWindow)
Makes the window the active window.
Definition: milxQtMain.cpp:409
void done(int value)
Hide progress bar when done computing.
void createProgressBar()
Creates the progress bar in the status bar within the main window.
void updatedWindowListMenu(QActionGroup *)
Signal for when the window list menu is updated.
This class represents the MILX Qt Image Display object using VTK.
Definition: milxQtImage.h:118
void predisplay(milxQtImage *img)
Handles the pre-displaying tasks for images, such as checking view type and if 3D viewing is needed e...
void setNamePrefix(const QString newPrefix)
Sets the prefix of the name of the data provided.
Definition: milxQtWindow.h:106
int subWindowSize
Window size of child windows to use.
Definition: milxQtMain.h:934
bool orientationImages
Prefer applying orientation to images?
Definition: milxQtMain.h:939
QList< QAction *> modelExtsActions
List of model extenstion actions loaded succesfully.
Definition: milxQtMain.h:1020
QAction * actionTileVertically
Tile vertically windows in workspace action.
Definition: milxQtMain.h:985
void tileTabHorizontally()
Tile all the windows horizontally in the current tab.
Definition: milxQtMain.cpp:970
void setLevel(int level)
Set window level the display to proportion of maxValue.
vtkSmartPointer< vtkTable > GetSource()
Returns the current table source for plot held.
Definition: milxQtPlot.h:143
QToolBar * imageToolBar
Some actions for images, like view etc.
Definition: milxQtMain.h:1004
This class represents the MILX Qt File I/O object using VTK/ITK/Qt.
Definition: milxQtFile.h:60
QToolBar * windowToolBar
Some actions from window menu, like tile, cascade etc.
Definition: milxQtMain.h:1002
QString strippedName()
Returns the stripped (path removed) name of the data.
Definition: milxQtWindow.h:80
QComboBox * defaultViewTypeBox
Box for default view type (1 view or scanner type/4 view)
Definition: milxQtMain.h:1030
bool isRender(QWidget *win)
Returns true if window is a generic render (milxQtRenderWindow object)
Definition: milxQtMain.cpp:279
QAction * actionPreferences
Action for showing program preferences.
Definition: milxQtMain.h:990
void scale(float scaling)
scales the intensities of current images.
static vtkSmartPointer< vtkImageData > ConvertITKVectorImageToVTKImage(itk::SmartPointer< TImage > img)
Converts a ITK Vector image object to an VTK image object. You MUST DeepCopy the result as the ITK sm...
Definition: milxImage.h:900
void closeEvent(QCloseEvent *event)
Tasks to complete when closing.
bool interpolationImages
Prefer showing interpolation for images?
Definition: milxQtMain.h:938
void tileTabVertically()
Tile all the windows vertically in the current tab.
Definition: milxQtMain.cpp:952
QSlider * imageLevelSlider
adjust window level of image display
Definition: milxQtMain.h:1008
static bool SaveDelimitedText(const std::string filename, const vtkSmartPointer< vtkTable > data, const std::string delimiter=",")
Saves table as an ASCII Delimited text files such as a CSV file.
Definition: milxFile.cxx:754
This class represents the MILX Qt Window Display object using QVTK.
Definition: milxQtWindow.h:40
int getNumberOfWindows()
Return the number of windows in the current tab.
Definition: milxQtMain.h:603
void setDisplayData(QPointer< milxQtImage > newImg)
Shares the milxQtImage data to current image. You will need to call generate image after this...
void updateWindowsWithCursors()
Updates the windows with cursors.
vtkImageActor * GetImageActor()
Returns the internal image actor used for display.
Definition: milxQtImage.h:442
bool isActiveImage()
Returns true if active window is an Image (milxQtImage object)
Definition: milxQtMain.cpp:310
void printDebug(QString msg)
Debug message wrapper for console.
Definition: milxQtMain.h:843
QPointer< milxQtUnifiedWindow > currentUnifiedWindow
Current window for multi-display.
Definition: milxQtMain.h:1033
bool saveModel(const QString filename, vtkPolyData *data, const bool binary=false)
Saves a model as a file, which can be a VTK XML or Legacy VTK PolyData File (i.e. either a *...
QList< QAction *> dockActions
List of dock actions of dock widgets loaded succesfully.
Definition: milxQtMain.h:1022
virtual ~milxQtMain()
The standard destructor.
Definition: milxQtMain.cpp:134
void imagesSubtract()
Subtract all open images together to create new image.
QMenu * menuWindows
Windows menu.
Definition: milxQtMain.h:950
void imageToPolyData(vtkSmartPointer< vtkImageData > img)
Compute image to poly data process.
void display(milxQtRenderWindow *rnd)
Handles the displaying of renders as they are produced.
void tileTab()
Tile all the windows in the current tab.
Definition: milxQtMain.h:443
QAction * actionOpenCollect
open collection action
Definition: milxQtMain.h:963
bool open()
Opens data for viewing in the current tab.
Definition: milxQtMain.cpp:417
QAction * actionCompare
Action for comparing data.
Definition: milxQtMain.h:995
QPushButton * refreshButton
window refresh button
Definition: milxQtMain.h:1011
QAction * actionContents
Action for showing contents of help.
Definition: milxQtMain.h:989
bool isActiveUnifiedWindow()
Returns true if active window is an UnifiedWindow (milxQtUnifiedWindow object)
Definition: milxQtMain.cpp:379
void updatedImportFromMenu(QActionGroup *)
Signal for when the import from menu is updated.
void readSettings()
Load the necessary GUI settings/state for the main class.
QAction * actionImageText
toggle text annotate mode
Definition: milxQtMain.h:1007
void controls()
Show the controls information.
QAction * actionTileHorizontally
Tile horizontally windows in workspace action.
Definition: milxQtMain.h:986
void addToContextMenu(QAction *act)
Adds (prepends) the action to the context menu. Connections are assumed to be made before hand...
Definition: milxQtWindow.h:115
QProgressBar * progressBar
Progress bar for computation.
Definition: milxQtMain.h:1024
QString activeNamePrefix()
Returns the name with prefix of the active window regardless of being an image, table or surface plot...
Definition: milxQtMain.cpp:181
void appendToContextMenu(QAction *act)
Adds (appends) the action to the context menu. Connections are assumed to be made before hand...
Definition: milxQtWindow.h:123
int getNumberOfModelWindows()
Return the number of model windows in the current tab.
void imagesMergeLabels()
Merge all open labelled images together to create new labelled image.
This class represents the MILX Qt Model/Mesh Display object using VTK.
Definition: milxQtModel.h:115
QAction * actionOpenSeries
open series action
Definition: milxQtMain.h:962
virtual void scaleDisplay(const bool forceDisplay=false)
Toggles the scale bar display.
bool isImage(QWidget *win)
Returns true if window is an Image (milxQtImage object)
Definition: milxQtMain.cpp:302
void printInfo(QString msg)
Info message wrapper for console.
Definition: milxQtMain.h:850
void setDefaultOrientation(int orientMode)
Change orientation mode to one of the supported standards. Default: Radiological. ...
void setConsole(milxQtConsole *con)
Set the console for log output.
Definition: milxQtWindow.h:195
void enableUpdates(QStatusBar *bar)
Enables the update of coordinates to the status bar provided directly. Update is done on mouse moveme...
void addExtensionAction(QAction *act)
Adds (in extension section) the action as an extension action. Connections are assumed to be made bef...
Definition: milxQtWindow.h:139
void dataMenu()
Create the data menu based on Window selected.
QAction * actionCloseAll
Close all windows in tab action.
Definition: milxQtMain.h:967
void closeTabActiveWindow()
Close active window in the tab.
Definition: milxQtMain.h:419
void refresh()
Refresh the display of the model.
virtual void enableCrosshair()
Enables the cursor/crosshair for marking. Image must be generated before calling. ...
Definition: milxQtImage.h:1128
void setView(int viewMode)
Change view to view mode identified by number. 0-axial, 1-coronal, 2-sagittal.
void modelInfo()
Computes and prints the centroid, centroid size and covariance matrix to standard out...
void imageToVolume(vtkSmartPointer< vtkImageData > img, bool eightbit)
Display image as volume rendering.
QSignalMapper * windowMapper
Mapper of mulit-connections.
Definition: milxQtMain.h:1016
QList< QPointer< milxQtModel > > modelWindows
List of model windows opened.
Definition: milxQtMain.h:1034
void createConnections()
Creates the signals and slots connections within the main window.
The class maintains a state and render of multiple display objects (such as a milxQtModel or milxQtIm...
void newTab()
Creates a new tab for the workspace.
Definition: milxQtMain.cpp:215
void imageToPseudoImage(vectorImageType::Pointer img)
Compute pseudo image from vector image.
void windowActivated(QWidget *win)
Signal for when a window has been activated.
void helpContents()
Show the help contents browser.
Definition: milxQtMain.cpp:988
bool isModel(QWidget *win)
Returns true if window is an Model (milxQtModel object)
Definition: milxQtMain.cpp:325
The class provides 1D/2D and 3D plotting capability. This includes scatter and surface plots...
Definition: milxQtPlot.h:66
bool isCrosshair()
Returns true if cursor shown to the display of the image.
Definition: milxQtImage.h:656
bool loadFile(const QString &filename)
Opens a file for viewing in the current tab.
Definition: milxQtMain.cpp:529
QActionGroup * windowActionList(QMenu *menuForList, bool groupTogether=true, bool applyMapper=false)
Creates an action list of windows currently opened to the menu provided.
void addModel(milxQtModel *mdl)
Adds a model widget and links its results.
Definition: milxQtMain.cpp:244
QAction * actionConsole
toggle action for console
Definition: milxQtMain.h:987
QMenu * menuWindowList
Menu for list of windows.
Definition: milxQtMain.h:996
Represents an image (i.e. an regular rectangular array with scalar values) and their common operation...
Definition: milxImage.h:174
QAction * actionBlendImages
blend images batch operation action
Definition: milxQtMain.h:974
QList< QPointer< milxQtPluginInterface > > plugins
List of plugins loaded succesfully.
Definition: milxQtMain.h:1018
QMenu * importFromMenu
Menu import from data menu.
Definition: milxQtMain.h:997
static vtkSmartPointer< vtkImageData > ApplyOrientationToVTKImage(vtkSmartPointer< vtkImageData > img, itk::SmartPointer< TImage > refImage, vtkSmartPointer< vtkMatrix4x4 > &transformMatrix, const bool labelledImage, const bool flipY=true)
Applies orientation/direction and origin to a VTK image from a reference image.
Definition: milxImage.h:1034
QAction * actionsRecentFile[MaxRecentFiles]
Array of recent file actions.
Definition: milxQtMain.h:968
void addRender(milxQtRenderWindow *rnd)
Adds a generic render widget and links its results.
Definition: milxQtMain.cpp:226
bool interpolationModels
Prefer applying interpolation to models?
Definition: milxQtMain.h:940
void imagesConvolve()
Convolve all open images together to create new image.
QMenuBar * menuBar
Menu bar for the window.
Definition: milxQtMain.h:945
QPushButton * cursorButton
crosshairs button
Definition: milxQtMain.h:1012
QComboBox * defaultOrientationTypeBox
Box for default orientation type (radiological or neurological orientation)
Definition: milxQtMain.h:1031
void contextMenuEvent(QContextMenuEvent *event)
The context menu setup member.
QPushButton * imageLevelButton
auto level button
Definition: milxQtMain.h:1009
void updateWindowsWithValue(int value)
Updates the windows based on single value (in percent), such as from a slider etc.
milxQtWindow * nextWindow()
Get the next window opened in the current tab.
QWebView * activeWebView()
Returns the QWebView object, returns 0 if active window is not a QWebView object. ...
Definition: milxQtMain.cpp:402
void voxeliseSurface(vtkSmartPointer< vtkPolyData > surface)
Convert poly data to an image volume.
void trackView(milxQtImage *windowToTrack, ViewType viewTo)
Enables tracking of the view (axial etc.) to imgToTrack provided.
milxQtImage * activeImage()
Returns the milxQtImage object, returns 0 if active window is not a milxQtImage object.
Definition: milxQtMain.cpp:318
vtkSmartPointer< vtkDataArray > GetScalars()
Returns the scalars of the model currently held.
Definition: milxQtModel.h:299
bool isLoaded()
Is the data successfully loaded? Use this to check if all is ok with data display.
QAction * actionRecentFileSeparator
Pointer to separator so it can be turned on and off.
Definition: milxQtMain.h:969
QAction * actionExit
Exit action.
Definition: milxQtMain.h:970
void imageToVectorField(vectorImageType::Pointer img, floatImageType::Pointer magImg, int subsampleFactor=0, float scaling=0.0)
Compute vector field from image.
void createComboBoxes()
Creates the combo boxes for main window.
QMenu * menuData
Data menu.
Definition: milxQtMain.h:948
milxQtImage * nextImage()
Get the next image opened in the current tab.
void displayed(milxQtRenderWindow *)
Signal for when a render window has been displayed.
QString strippedNamePrefix()
Returns the stripped (path removed) name of the data with "Image" prefix.
Definition: milxQtImage.h:147
QString activeName()
Returns the name of the active window regardless of being an image, table or surface plot...
Definition: milxQtMain.cpp:152
QString getName()
Returns the name of the data.
Definition: milxQtWindow.h:67
QActionGroup * updateWindowListMenu(bool applyMapper=true)
Updates the windows list in the windows list menu. This is a raw list for children to use...
void addUnifiedWindow(milxQtUnifiedWindow *uni)
Adds a unified window and links its results.
Definition: milxQtMain.cpp:251
bool isActiveWebView()
Returns true if active window is a web viewer.
Definition: milxQtMain.cpp:394
QString strippedNamePrefix()
Returns the stripped (path removed) name of the data with "Model" prefix.
Definition: milxQtModel.h:135
bool isDeletableOnClose()
Is the window deletable on close?
Definition: milxQtWindow.h:187
void updateWindowsWithViewType(int value)
Updates the windows view type based on type set, such as from a combo box etc.
void setupTooltips()
Assign tooltips to each action for users benefit. The tooltips explains the function of each action...
void imagesBlend(QVector< float > opacities)
Blend all open images together to create new image. &#39;opacities&#39; would hold a list of floats for blend...
void tableToPlot(vtkSmartPointer< vtkTable > tbl, QString title)
Display table as a plot.
QActionGroup * updateImportFromMenu(bool applyMapper=false)
Updates the Import form menu in the windows list menu. This is a raw list for children to use...
QAction * actionConvolveImages
Convolve images batch operation action.
Definition: milxQtMain.h:979
void commonChildProperties(QWidget *widget)
Sets all the common child properties of the data windows such as images, plots etc.
int getNumberOfImageWindows()
Return the number of image windows in the current tab.
void imagesAverage()
Average all open images together to create new image.
void imagesMix()
Blend all open images together to create new image usaing a mixer dialog.
milxQtModel * activePlot()
Returns the milxQtPlot object, returns 0 if active window is not a milxQtPlot object.
Definition: milxQtMain.cpp:364
static void Information(itk::SmartPointer< TImage > img)
Prints the information of the image to standard output.
Definition: milxImage.h:2067
QToolBar * fileToolBar
Some actions from file menu.
Definition: milxQtMain.h:1000
void updateWindowsWithAutoLevel()
Updates the windows with auto levelling.
void SetSize(int height, int width)
Set the size of the display window.
milxQtWindow * currentWindow()
Get the current window opened in the current tab.
milxQtModel * activeModel()
Returns the milxQtModel object, returns 0 if active window is not a milxQtModel object.
Definition: milxQtMain.cpp:341
QMenu * menuHelp
Help menu.
Definition: milxQtMain.h:951
bool isActiveModel()
Returns true if active window is an Model (milxQtModel object)
Definition: milxQtMain.cpp:333
int windowIterator
Keep track of current window being traversed.
Definition: milxQtMain.h:954
void unify()
Add the active window to the current multi (unified) display.
QString openSupport
Load file extension support list, cats all known extensions.
Definition: milxQtMain.h:958
void setView(int viewMode)
Change view to view mode identified by number. 0-axial, 1-coronal, 2-sagittal.
void openRecentFile()
Opens recent file (from recent file menu) for analysis and display.
Definition: milxQtMain.cpp:516
bool timestamping
Prefer showing timestamp?
Definition: milxQtMain.h:937
void updateWindowsWithViewOrientation(int value)
Updates the windows view orientation based on orientation set, such as from a combo box etc...
void imageToSurface(vtkSmartPointer< vtkImageData > img, const float value=numeric_limits< float >::max())
Compute image to surface process.
bool debugMode
Debug output mode?
Definition: milxQtMain.h:929
void preferences()
Show the preferences for the program.
vtkSmartPointer< vtkMatrix4x4 > getTransformMatrix()
Internal transform matrix used to transform actors appropriately for direction and coordinate systems...
void initialiseWindowTraversal()
Initialise the window iterator to the first window opened.
Definition: milxQtMain.h:629
void linkProgressEventOf(vtkObject *obj)
Link the progress of filters etc to keep the UI responsive.
void background(bool white=false)
Changes background to white.
milxQtMain(QWidget *theParent=0)
The standard constructor.
Definition: milxQtMain.cpp:38
milxQtModel * nextModel()
Get the next model opened in the current tab.
void setDefaultView(int viewMode)
Change default view to view mode identified by number. 0-axial, 1-coronal, 2-sagittal.
QAction * actionAverageImages
average images batch operation action
Definition: milxQtMain.h:976
QAction * actionCloseActive
Close active window in tab action.
Definition: milxQtMain.h:966
QAction * actionNewTab
New Tab action.
Definition: milxQtMain.h:972
void createMenu()
Creates the menu actions.
void about()
Show the about information.
void save(QString filename="")
Saves the data in the current tab to file. The saving is content sensitive and depends on the extensi...
Definition: milxQtMain.cpp:732
void openSeries()
Opens a DICOM series for viewing in the same window.
Definition: milxQtMain.cpp:496
void refresh()
Refresh the display of the model including widgets. Camera remains as is.
milxQtRenderWindow * activeRender()
Returns the milxQtRenderWindow object, returns 0 if active window is not a milxQtRenderWindow object...
Definition: milxQtMain.cpp:295
QAction * actionLinkWindows
Using linked cameras for all windows in a tab?
Definition: milxQtMain.h:982
bool isActivePlot()
Returns true if active window is an Plot (milxQtPlot object)
Definition: milxQtMain.cpp:356
void writeSettings()
Write the necessary GUI settings/state for the main class.
void autoLevel(float percentile=0.99)
Auto window level the display. Uses Otsu threshold value.
void printWarning(QString msg)
Warning message wrapper for console.
Definition: milxQtMain.h:836
bool isActiveRender()
Returns true if active window is a generic render (milxQtRenderWindow object)
Definition: milxQtMain.cpp:287
void saveScreen(QString filename="")
Saves a screenshot of the active window in the current tab to file. The saving is content sensitive a...
Definition: milxQtMain.cpp:851
A console (tabbed) widget class for displaying information such as logs, terminals and consoles...
Definition: milxQtConsole.h:34
This class represents the MILX Qt Main Window object using Qt.
Definition: milxQtMain.h:85
void setTabName(QWidget *fromWindow)
Set the tab name.
Definition: milxQtMain.cpp:913
void updateWindowsWithRefresh()
Updates the windows with default views and window levels.
void dragEnterEvent(QDragEnterEvent *event)
Part of the Drag and Drop feature members. Tells what drags to accept.
QToolBar * defaultToolBar
Some actions from default stuff menu, like view etc.
Definition: milxQtMain.h:1003
void dropEvent(QDropEvent *event)
Part of the Drag and Drop feature members. Opens the dropped files.
QAction * actionMultiplyImages
multiply images batch operation action
Definition: milxQtMain.h:978
QActionGroup * updateWindowMenu()
Updates the windows list in the windows menu.
void openCollection()
Opens a collection of models for viewing in the same window.
Definition: milxQtMain.cpp:450
void imageToPlot(vtkSmartPointer< vtkImageData > img, int displaceAxis=2)
Display image as a surface plot.
void setDefaultOrientation(int orientMode)
Change orientation mode to one of the supported standards. Default: Radiological. ...
void setSlice(int slice)
Sets the slice of the volume to slice value given.
void refresh()
Refresh display.
void updateRecentFileActions()
Updates the recent files list in the file menu.
milxQtUnifiedWindow * activeUnifiedWindow()
Returns the milxQtUnifiedWindow object, returns 0 if active window is not a milxQtUnifiedWindow objec...
Definition: milxQtMain.cpp:387
virtual void background(bool white=false)
Changes background to white.
void createToolBars()
Creates the toolbar for the main window.
void imagesAdd()
Add all open images together to create new image.
QAction * actionAddImages
add images batch operation action
Definition: milxQtMain.h:975
QTabWidget * workspaces
Pointer to the Workspace environment for the user.
Definition: milxQtMain.h:1015
void closeTabAllWindows()
Close all the windows in the current tab.
Definition: milxQtMain.h:427
unsigned NumberOfProcessors()
Number of processors or cores on the machine.
Definition: milxGlobal.h:124
void working(int value)
Show progress bar when computing work. NEgative value shows a busy bar.
static itk::SmartPointer< TImage > SubsampleImage(itk::SmartPointer< TImage > img, typename TImage::SizeType factors)
Subsamples or shrinks the current image using the factors provided.
Definition: milxImage.h:1459
int magnifyFactor
Screenshot magnify factor.
Definition: milxQtMain.h:936
size_t progressCallCount
Takes account of how many calls of working have been made.
Definition: milxQtMain.h:953
void redirectWindowActivated(QWidget *win)
Redirect the workspace signal to milxQtMain object level.
Definition: milxQtMain.h:859
QPointer< milxQtConsole > console
console docked window
Definition: milxQtMain.h:1026
QAction * actionOpen
open action
Definition: milxQtMain.h:961
void disableOrient()
Disables orientation marker.
void imagesMultiply()
Multiply all open images together to create new image.
QList< QPointer< milxQtImage > > imageWindows
List of model windows opened.
Definition: milxQtMain.h:1035
virtual void colourMapToJet(double minRange=0.0, double maxRange=0.0)
Change the colour map to Jet.
QAction * actionSaveScreen
save action
Definition: milxQtMain.h:965
void addImage(milxQtImage *img)
Adds an image widget and links its results.
Definition: milxQtMain.cpp:239