]> Creatis software - clitk.git/blob - vv/vvMainWindow.cxx
Allow to retrieve and display multiple series.
[clitk.git] / vv / vvMainWindow.cxx
1 /*=========================================================================
2 Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4 Authors belong to:
5 - University of LYON              http://www.universite-lyon.fr/
6 - Léon Bérard cancer center       http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE.  See the copyright notices for more information.
12
13 It is distributed under dual licence
14
15 - BSD        See included LICENSE.txt file
16 - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18
19 #include <algorithm>
20 #include <QMessageBox>
21 #include <QInputDialog>
22 #include <QTimer>
23 #include "QTreePushButton.h"
24 #include <QUrl>
25 #include <QSettings>
26
27 // VV include
28 #include "vvMainWindow.h"
29 #include "vvHelpDialog.h"
30 #include "vvRegisterForm.h"
31 #include "vvDocumentation.h"
32 #include "vvProgressDialog.h"
33 #include "vvQDicomSeriesSelector.h"
34 #include "vvSlicerManager.h"
35 #include "clitkImageCommon.h"
36 #include "vvSlicer.h"
37 #include "vvInteractorStyleNavigator.h"
38 #include "vvImageWriter.h"
39 #include "vvSegmentationDialog.h"
40 #include "vvSurfaceViewerDialog.h"
41 #include "vvDeformationDialog.h"
42 #include "vvImageWarp.h"
43 #include "vvUtils.h"
44 #include "vvMidPosition.h"
45 #include "vvMesh.h"
46 #include "vvStructSelector.h"
47 #include "vvMeshReader.h"
48 #include "vvSaveState.h"
49 #include "vvReadState.h"
50 #ifdef CLITK_USE_PACS_CONNECTION
51 #include "vvQPacsConnection.h"
52 #endif
53 #include "clitkConfiguration.h"
54 #include "clitkMatrix.h"
55
56 // ITK include
57 #include <itkImage.h>
58 #include <itkImageFileReader.h>
59 #include <itkByteSwapper.h>
60 #include <itkCommand.h>
61 #include <itkNumericSeriesFileNames.h>
62
63 // VTK include
64 #include <vtkImageData.h>
65 #include <vtkImageActor.h>
66 #include <vtkCornerAnnotation.h>
67 #include <vtkRenderWindow.h>
68 #include <vtkRenderWindowInteractor.h>
69 #include <vtkRenderer.h>
70 #include <vtkRendererCollection.h>
71 #include <vtkWindowToImageFilter.h>
72 #include <vtkBMPWriter.h>
73 #include <vtkTIFFWriter.h>
74 #include <vtkPNMWriter.h>
75 #include <vtkPNGWriter.h>
76 #include <vtkJPEGWriter.h>
77 #include <vtkGenericMovieWriter.h>
78 #ifdef CLITK_EXPERIMENTAL
79 #  include <vvAnimatedGIFWriter.h>
80 #endif
81 #ifdef VTK_USE_VIDEO_FOR_WINDOWS
82 #  include <vtkAVIWriter.h>
83 #endif
84 #ifdef VTK_USE_FFMPEG_ENCODER
85 #  include <vtkFFMPEGWriter.h>
86 #endif
87 #ifdef VTK_USE_MPEG2_ENCODER
88 #  include <vtkMPEG2Writer.h>
89 #endif
90 #include <vtkMatrix4x4.h>
91 #include <vtkTransform.h>
92
93 // Standard includes
94 #include <iostream>
95 #include <fstream>
96 #include <sstream>
97 #include <iomanip>
98
99 #define COLUMN_TREE 0
100 #define COLUMN_UL_VIEW 1
101 #define COLUMN_UR_VIEW 2
102 #define COLUMN_DL_VIEW 3
103 #define COLUMN_DR_VIEW 4
104 #define COLUMN_CLOSE_IMAGE 5
105 #define COLUMN_RELOAD_IMAGE 6
106 #define COLUMN_IMAGE_NAME 7
107
108 #ifdef CLITK_PRIVATE_FEATURES
109 #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz *.usf *.svl)"
110 #else
111 #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz)"
112 #endif
113
114
115 /*Data Tree values
116 0,Qt::UserRole full filename
117 1,Qt::CheckStateRole checkbutton UL View
118 1,Qt::UserRole overlay, fusion or vector
119 2,Qt::CheckStateRole checkbutton UR View
120 3,Qt::CheckStateRole checkbutton DL View
121 4,Qt::CheckStateRole checkbutton DR View
122 5,0  short filename
123 5,Qt::UserRole mSlicerManager id*/
124
125 //------------------------------------------------------------------------------
126 vvMainWindow::vvMainWindow():vvMainWindowBase()
127 {
128   setupUi(this); // this sets up the GUI
129   setDicomClient();
130   mInputPathName = "";
131   mMenuTools = menuTools;
132   //  mMenuSegmentation = menuSegmentation;
133   mContextMenu = &contextMenu;
134   mMenuExperimentalTools = menuExperimental;
135   mMainWidget = this;
136   mCurrentTime = -1;
137   mCurrentSelectedImageId = "";
138   mCurrentPickedImageId = "";
139   mCurrentPickedImageIndex = 0;
140
141   //Init the contextMenu
142   this->setContextMenuPolicy(Qt::CustomContextMenu);
143   contextActions.resize(0);
144   QAction* actionOpen_new_image = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/fileopen.png")),
145     tr("O&pen new Image"));
146   actionOpen_new_image->setShortcut(QKeySequence(tr("Ctrl+O")));
147   connect(actionOpen_new_image,SIGNAL(triggered()),this,SLOT(OpenImages()));
148   contextActions.push_back(actionOpen_new_image);
149   contextMenu.addSeparator();
150
151   QAction* actionClose_Image = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/exit.png")),
152     tr("Close Current Image"));
153   connect(actionClose_Image,SIGNAL(triggered()),this,SLOT(CloseImage()));
154   contextActions.push_back(actionClose_Image);
155
156   QAction* actionReload_image = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")),
157     tr("Reload Current Image"));
158   connect(actionReload_image,SIGNAL(triggered()),this,SLOT(ReloadImage()));
159   contextActions.push_back(actionReload_image);
160
161   QAction* actionSave_image = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/filesave.png")),
162     tr("Save Current Image"));
163   connect(actionSave_image,SIGNAL(triggered()),this,SLOT(SaveAs()));
164   contextActions.push_back(actionSave_image);
165
166   QAction* actionSave_state = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/filesave.png")),
167     tr("Save Current State"));
168   connect(actionSave_state,SIGNAL(triggered()),this,SLOT(SaveCurrentState()));
169   contextActions.push_back(actionSave_state);
170
171   QAction* actionRead_state = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/filesave.png")),
172     tr("Read Saved State"));
173   connect(actionRead_state,SIGNAL(triggered()),this,SLOT(ReadSavedState()));
174   contextActions.push_back(actionRead_state);
175
176   contextMenu.addSeparator();
177
178   contextMenu.addAction(actionAdd_VF_to_current_Image);
179   contextActions.push_back(actionAdd_VF_to_current_Image);
180
181   //QAction* actionAdd_Overlay_to_current_Image = menuOverlay->addAction(QIcon(QString::fromUtf8(":/common/icons/GPSup.png")),
182   //    tr("Add overlay image to current image"));
183   contextMenu.addAction(actionAdd_overlay_image_to_current_image);
184   contextActions.push_back(actionAdd_overlay_image_to_current_image);
185
186   contextMenu.addAction(actionAdd_fusion_image);
187   contextActions.push_back(actionAdd_fusion_image);
188
189 #ifdef CLITK_EXPERIMENTAL
190   contextMenu.addAction(actionAdd_USSequence_toCT);
191   contextActions.push_back(actionAdd_USSequence_toCT);
192 #endif
193
194
195   contextMenu.addSeparator();
196   QAction* actionResetMatrix = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/identity.png")),
197     tr("Reset transformation to identity"));
198   connect(actionResetMatrix, SIGNAL(triggered()), this,SLOT(ResetTransformationToIdentity()));
199
200   // TRIAL DS
201   /*
202   QMenu * m = new QMenu(menubar);
203   m->setTitle("TOTO");
204   //  m->setObjectName(QString::fromUtf8("TOTOTO"));
205   contextMenu.addMenu(m);
206   QAction * a = m->addAction(QIcon(QString::fromUtf8(":/common/icons/GPSup.png")),
207   tr("BIDON"));
208   QAction * b = m->addAction(QIcon(QString::fromUtf8(":/common/icons/GPSup.png")),
209   tr("BIDON2"));
210   m->addAction(a);
211   m->addAction(b);
212   connect(a,SIGNAL(triggered()),this,SLOT(AddFusionImage()));
213   */
214
215   //init the DataTree
216   mSlicerManagers.resize(0);
217
218   QStringList header;
219   header.append("");
220   header.append("TL");
221   header.append("TR");
222   header.append("BL");
223   header.append("BR");
224   header.append("");
225   header.append("");
226   header.append("Name");
227
228   DataTree->setHeaderLabels(header);
229   DataTree->resizeColumnToContents(COLUMN_TREE);
230   DataTree->resizeColumnToContents(COLUMN_UL_VIEW);
231   DataTree->resizeColumnToContents(COLUMN_UR_VIEW);
232   DataTree->resizeColumnToContents(COLUMN_DL_VIEW);
233   DataTree->resizeColumnToContents(COLUMN_DR_VIEW);
234   DataTree->resizeColumnToContents(COLUMN_CLOSE_IMAGE);
235   DataTree->resizeColumnToContents(COLUMN_RELOAD_IMAGE);
236   DataTree->resizeColumnToContents(COLUMN_IMAGE_NAME);
237
238   viewMode = 1;
239   documentation = new vvDocumentation();
240   help_dialog = new vvHelpDialog();
241   dicomSeriesSelector = new vvDicomSeriesSelector();
242 #ifdef CLITK_USE_PACS_CONNECTION
243      PacsConnection = new vvQPacsConnection();
244 #endif
245
246   inverseButton->setEnabled(0);
247   actionAdd_overlay_image_to_current_image->setEnabled(0);
248   actionSave_As->setEnabled(0);
249   actionAdd_VF_to_current_Image->setEnabled(0);
250   actionAdd_fusion_image->setEnabled(0);
251   actionAdd_USSequence_toCT->setEnabled(0);
252
253   //init the sliders
254   verticalSliders.push_back(NOVerticalSlider);
255   verticalSliders.push_back(NEVerticalSlider);
256   verticalSliders.push_back(SOVerticalSlider);
257   verticalSliders.push_back(SEVerticalSlider);
258
259   for (int i =0; i < 4; i++)
260     verticalSliders[i]->hide();
261
262   horizontalSliders.push_back(NOHorizontalSlider);
263   horizontalSliders.push_back(NEHorizontalSlider);
264   horizontalSliders.push_back(SOHorizontalSlider);
265   horizontalSliders.push_back(SEHorizontalSlider);
266
267   for (int i =0; i < 4; i++)
268     horizontalSliders[i]->hide();
269
270
271   connect(NOVerticalSlider,SIGNAL(valueChanged(int)),this,SLOT(NOVerticalSliderChanged()));
272   connect(NEVerticalSlider,SIGNAL(valueChanged(int)),this,SLOT(NEVerticalSliderChanged()));
273   connect(SOVerticalSlider,SIGNAL(valueChanged(int)),this,SLOT(SOVerticalSliderChanged()));
274   connect(SEVerticalSlider,SIGNAL(valueChanged(int)),this,SLOT(SEVerticalSliderChanged()));
275
276   connect(NOHorizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(NOHorizontalSliderMoved()));
277   connect(NEHorizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(NEHorizontalSliderMoved()));
278   connect(SOHorizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(SOHorizontalSliderMoved()));
279   connect(SEHorizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(SEHorizontalSliderMoved()));
280
281   //connect everything
282   connect(actionCompute_mid_position_image,SIGNAL(triggered()),this,SLOT(ComputeMidPosition()));
283   connect(actionDeformable_Registration,SIGNAL(triggered()),this,SLOT(ComputeDeformableRegistration()));
284   connect(actionWarp_image_with_vector_field,SIGNAL(triggered()),this,SLOT(WarpImage()));
285   connect(actionLoad_images,SIGNAL(triggered()),this,SLOT(OpenImages()));
286   connect(actionOpen_Dicom,SIGNAL(triggered()),this,SLOT(OpenDicom()));
287   #ifdef CLITK_USE_PACS_CONNECTION
288 connect(actionConnect_Pacs,SIGNAL(triggered()),this,SLOT(ConnectPacs()));
289 #endif
290   //  connect(actionOpen_Dicom_Struct,SIGNAL(triggered()),this,SLOT(OpenDCStructContour()));
291   connect(actionOpen_VTK_contour,SIGNAL(triggered()),this,SLOT(OpenVTKContour()));
292   connect(actionOpen_Multiple_Images_As_One,SIGNAL(triggered()),this,SLOT(MergeImages()));
293   connect(actionSlice_Image_As_Multiple_Images,SIGNAL(triggered()),this,SLOT(SliceImages()));
294   connect(actionOpen_Image_With_Time,SIGNAL(triggered()),this,SLOT(OpenImageWithTime()));
295   connect(actionMerge_images_as_n_dim_t, SIGNAL(triggered()), this, SLOT(MergeImagesWithTime()));
296   connect(actionSave_As,SIGNAL(triggered()),this,SLOT(SaveAs()));
297   connect(actionSave_current_state,SIGNAL(triggered()),this,SLOT(SaveCurrentState()));
298   connect(actionRead_saved_state,SIGNAL(triggered()),this,SLOT(ReadSavedState()));
299   connect(actionExit,SIGNAL(triggered()),this,SLOT(close()));
300   connect(actionAdd_VF_to_current_Image,SIGNAL(triggered()),this,SLOT(OpenField()));
301   connect(actionAdd_fusion_image,SIGNAL(triggered()),this,SLOT(SelectFusionImage()));
302   connect(actionAdd_overlay_image_to_current_image,SIGNAL(triggered()), this,SLOT(SelectOverlayImage()));
303   connect(actionAdd_USSequence_toCT,SIGNAL(triggered()), this,SLOT(SelectFusionSequence()));
304   connect(actionNavigation_Help,SIGNAL(triggered()),this,SLOT(ShowHelpDialog()));
305   connect(actionDocumentation,SIGNAL(triggered()),this,SLOT(ShowDocumentation()));
306   connect(actionRegister_vv,SIGNAL(triggered()),this,SLOT(PopupRegisterForm()));
307
308   connect(overlayPanel, SIGNAL(FusionSequenceCorrespondancesButtonPressed()), this, SLOT(SelectFusionSequenceCorrespondances()));
309
310
311   ///////////////////////////////////////////////
312   connect(actionSegmentation,SIGNAL(triggered()),this,SLOT(SegmentationOnCurrentImage()));
313   connect(actionSurface_Viewer,SIGNAL(triggered()),this,SLOT(SurfaceViewerLaunch()));
314   ///////////////////////////////////////////////
315
316   actionNorth_East_Window->setEnabled(0);
317   actionNorth_West_Window->setEnabled(0);
318   actionSouth_East_Window->setEnabled(0);
319   actionSouth_West_Window->setEnabled(0);
320
321   connect(actionNorth_East_Window,SIGNAL(triggered()),this,SLOT(SaveNEScreenshot()));
322   connect(actionNorth_West_Window,SIGNAL(triggered()),this,SLOT(SaveNOScreenshot()));
323   connect(actionSouth_East_Window,SIGNAL(triggered()),this,SLOT(SaveSEScreenshot()));
324   connect(actionSouth_West_Window,SIGNAL(triggered()),this,SLOT(SaveSOScreenshot()));
325   connect(actionSave_all_slices,SIGNAL(triggered()),this,SLOT(SaveScreenshotAllSlices()));
326
327   connect(DataTree,SIGNAL(itemSelectionChanged()),this,SLOT(ImageInfoChanged()));
328   connect(DataTree,SIGNAL(itemClicked(QTreeWidgetItem*, int)),this,
329     SLOT(DisplayChanged(QTreeWidgetItem*, int)));
330
331   connect(viewButton,SIGNAL(clicked()),this, SLOT(ChangeViewMode()) );
332   connect(windowSpinBox,SIGNAL(editingFinished()),this,SLOT(WindowLevelEdited()));
333   connect(levelSpinBox,SIGNAL(editingFinished()),this,SLOT(WindowLevelEdited()));
334   connect(colorMapComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateColorMap()));
335   connect(presetComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateWindowLevel()));
336   connect(slicingPresetComboBox, SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateSlicingPreset()));
337   connect(inverseButton,SIGNAL(clicked()),this,SLOT(SwitchWindowLevel()));
338   connect(applyWindowLevelToAllButton,SIGNAL(clicked()),this,SLOT(ApplyWindowLevelToAllImages()));
339
340   connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ShowContextMenu(QPoint)));
341
342   connect(linkPanel,SIGNAL(addLink(QString,QString,bool)),this,SLOT(AddLink(QString,QString,bool)));
343   connect(linkPanel,SIGNAL(removeLink(QString,QString)),this,SLOT(RemoveLink(QString,QString)));
344   connect(overlayPanel,SIGNAL(VFPropertyUpdated(int,int,int,int,double,double,double)),this,SLOT(SetVFProperty(int,int,int,int,double,double,double)));
345   connect(overlayPanel,SIGNAL(OverlayPropertyUpdated(int,int,double,double)),
346     this,SLOT(SetOverlayProperty(int,int,double,double)));
347   connect(overlayPanel,SIGNAL(FusionPropertyUpdated(int,int,int,double,double, bool)),
348     this,SLOT(SetFusionProperty(int,int,int,double,double, bool)));
349   connect(landmarksPanel,SIGNAL(UpdateRenderWindows()),this,SLOT(UpdateRenderWindows()));
350   connect(landmarksPanel,SIGNAL(SelectedPointChanged()),this,SLOT(GoToLandmark()));
351
352   connect(overlayPanel,SIGNAL(FusionSequencePropertyUpdated(int, bool, unsigned int, bool)),
353     this,SLOT(SetFusionSequenceProperty(int, bool,unsigned int, bool)));
354
355
356   playMode = 0;//pause
357   mFrameRate = 10;
358   playButton->setEnabled(0);
359   frameRateLabel->setEnabled(0);
360   frameRateSpinBox->setEnabled(0);
361   connect(playButton, SIGNAL(clicked()),this,SLOT(PlayPause()));
362   connect(frameRateSpinBox, SIGNAL(valueChanged(int)),this,SLOT(ChangeFrameRate(int)));
363
364   goToCursorPushButton->setEnabled(0);
365   connect(goToCursorPushButton, SIGNAL(clicked()),this,SLOT(GoToCursor()));
366
367   NOViewWidget->hide();
368   NEViewWidget->hide();
369   SOViewWidget->hide();
370   SEViewWidget->hide();
371
372   //Recently opened files
373   std::list<std::string> recent_files = GetRecentlyOpenedImages();
374   recentlyOpenedFilesMenu=NULL;
375   if ( !recent_files.empty() ) {
376     createRecentlyOpenedFilesMenu();
377     updateRecentlyOpenedFilesMenu(recent_files);
378   }
379
380   // Adding all new tools (insertion in the menu)
381   vvToolManager::GetInstance()->InsertToolsInMenu(this);
382   vvToolManager::GetInstance()->EnableToolsInMenu(this, false);
383
384   if (!CLITK_EXPERIMENTAL)
385     menuExperimental->menuAction()->setVisible(false);
386
387
388   QTimer * timerMemory = new QTimer(this);
389   //timerMemory->setInterval(5);
390   connect(timerMemory, SIGNAL(timeout()), this, SLOT(UpdateMemoryUsage()));
391   timerMemory->start(2000);
392
393 }
394 //------------------------------------------------------------------------------
395 void vvMainWindow::show()
396 {
397   vvMainWindowBase::show();
398   PopupRegisterForm(true);
399 }
400 //------------------------------------------------------------------------------
401 void vvMainWindow::UpdateMemoryUsage()
402 {
403   //  clitk::PrintMemory(true);
404   if (clitk::GetMemoryUsageInMb() == 0) infoPanel->setMemoryInMb("NA");
405   else infoPanel->setMemoryInMb(QString::number(clitk::GetMemoryUsageInMb())+" MiB");
406 }
407 //------------------------------------------------------------------------------
408
409
410 //------------------------------------------------------------------------------
411 void vvMainWindow::createRecentlyOpenedFilesMenu()
412 {
413   recentlyOpenedFilesMenu = new QMenu("Recently opened files...");
414   recentlyOpenedFilesMenu->setIcon(QIcon(QString::fromUtf8(":/common/icons/open.png")));
415   menuFile->insertMenu(actionOpen_Image_With_Time,recentlyOpenedFilesMenu);
416   menuFile->insertSeparator(actionOpen_Image_With_Time);
417 }
418 //------------------------------------------------------------------------------
419
420
421 //------------------------------------------------------------------------------
422
423 void vvMainWindow::updateRecentlyOpenedFilesMenu(const std::list<std::string> &recent_files)
424 {
425   if(recentlyOpenedFilesMenu==NULL) {
426     createRecentlyOpenedFilesMenu();
427   } else {
428     recentlyOpenedFilesMenu->clear();
429   }
430   for (std::list<std::string>::const_iterator i = recent_files.begin(); i!=recent_files.end(); i++) {
431     QAction* current=new QAction(QIcon(QString::fromUtf8(":/common/icons/open.png")), i->c_str(),this);
432     recentlyOpenedFilesMenu->addAction(current);
433     connect(current,SIGNAL(triggered()),this,SLOT(OpenRecentImage()));
434   }
435 }
436 //------------------------------------------------------------------------------
437
438
439 //------------------------------------------------------------------------------
440 void vvMainWindow::ComputeMidPosition()
441 {
442   bool ok;
443   int index=GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
444   int ref = QInputDialog::getInteger(this,"Chose reference phase","Reference phase",0,0,\
445     mSlicerManagers[index]->GetImage()->GetVTKImages().size()-1,1,&ok);
446   if (ok) {
447     vvMidPosition midp;
448     midp.slicer_manager = mSlicerManagers[index];
449     midp.reference_image_index = ref;
450     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
451     midp.Update();
452     if (midp.error)
453       QMessageBox::warning(this, "Error computing midposition image",midp.error_message.c_str());
454     else {
455       QFileInfo info(midp.slicer_manager->GetFileName().c_str());
456       AddImage(midp.output,info.path().toStdString()+"/"+info.completeBaseName().toStdString()+"_midposition.mhd");
457     }
458     QApplication::restoreOverrideCursor();
459   }
460 }
461 //------------------------------------------------------------------------------
462
463
464 //------------------------------------------------------------------------------
465 void vvMainWindow::AddContour(int image_index, vvMesh::Pointer contour, bool propagation)
466 {
467   QTreeWidgetItem *item = new QTreeWidgetItem();
468   item->setData(0,Qt::UserRole,"filename.vtk");
469   item->setData(1,Qt::UserRole,tr("contour"));
470   QBrush brush;
471   brush.setColor(QColor(contour->r*255,contour->g*255,contour->b*255));
472   brush.setStyle(Qt::SolidPattern);
473   item->setData(COLUMN_IMAGE_NAME,Qt::BackgroundRole,brush);
474   //  item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,contour->structure_name.c_str());
475
476   for (int j = 1; j <= 4; j++)
477     item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(image_index)->data(j,Qt::CheckStateRole));
478
479   QTreePushButton* cButton = new QTreePushButton;
480   cButton->setItem(item);
481   cButton->setColumn(COLUMN_CLOSE_IMAGE);
482   cButton->setToolTip(tr("close image"));
483   cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
484   connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
485     this,SLOT(CloseImage(QTreeWidgetItem*, int)));
486
487   QTreePushButton* rButton = new QTreePushButton;
488   rButton->setItem(item);
489   rButton->setColumn(COLUMN_RELOAD_IMAGE);
490   rButton->setToolTip(tr("reload image"));
491   rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
492   rButton->setEnabled(false);
493   //Not implemented
494   //connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
495   //this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
496
497   DataTree->topLevelItem(image_index)->setExpanded(1);
498   DataTree->topLevelItem(image_index)->addChild(item);
499   DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
500   DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
501   QString id = DataTree->topLevelItem(image_index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
502   item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
503
504   UpdateTree();
505   mSlicerManagers[image_index]->AddContour(contour,propagation);
506   mSlicerManagers[image_index]->Render();
507 }
508 //------------------------------------------------------------------------------
509
510
511 //------------------------------------------------------------------------------
512 void vvMainWindow::OpenVTKContour()
513 {
514   if (mSlicerManagers.size() > 0) {
515     QString Extensions = "Images ( *.vtk *.obj)";
516     Extensions += ";;All Files (*)";
517     QString file = QFileDialog::getOpenFileName(this,tr("Open vtkPolyData"),mInputPathName,Extensions);
518     if (file.isNull())
519       return;
520     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
521     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
522     vvMeshReader reader;
523     reader.SetImage(mSlicerManagers[index]->GetImage());
524     reader.SetModeToVTK();
525     reader.SetFilename(file.toStdString());
526     reader.Update();
527     AddContour(index,reader.GetOutput()[0],false);
528     QApplication::restoreOverrideCursor();
529   }
530 }
531 //------------------------------------------------------------------------------
532
533
534 //------------------------------------------------------------------------------
535 void vvMainWindow::AddDCStructContour(int index, QString file)
536 {
537   vvMeshReader reader;
538   reader.SetFilename(file.toStdString());
539   vvStructSelector selector;
540   selector.SetStructures(reader.GetROINames());
541   if (!mSlicerManagers[index]->GetVF().IsNull())
542     selector.EnablePropagationCheckBox();
543   if (selector.exec()) {
544     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
545     reader.SetSelectedItems(selector.getSelectedItems());
546     reader.SetImage(mSlicerManagers[index]->GetImage());
547     if (selector.PropagationEnabled())
548       reader.SetPropagationVF(mSlicerManagers[index]->GetVF());
549     reader.Update();
550     std::vector<vvMesh::Pointer> contours=reader.GetOutput();
551     for (std::vector<vvMesh::Pointer>::iterator i=contours.begin();
552       i!=contours.end(); i++)
553       AddContour(index,*i,selector.PropagationEnabled());
554     QApplication::restoreOverrideCursor();
555   }
556 }
557
558 //------------------------------------------------------------------------------
559 void vvMainWindow::OpenDCStructContour()
560 {
561   if (mSlicerManagers.size() > 0) {
562     QString Extensions = "Dicom Files ( *.dcm RS*)";
563     Extensions += ";;All Files (*)";
564     QString file = QFileDialog::getOpenFileName(this,tr("Merge Images"),mInputPathName,Extensions);
565     if (file.isNull())
566       return;
567     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
568     AddDCStructContour(index, file);
569   }
570 }
571 //------------------------------------------------------------------------------
572
573
574 //------------------------------------------------------------------------------
575 void vvMainWindow::ComputeDeformableRegistration()
576 {
577   if (mSlicerManagers.size() > 0) {
578     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
579     vvDeformationDialog dialog(index,mSlicerManagers);
580     if (dialog.exec()) {
581       std::string base_name=itksys::SystemTools::GetFilenameWithoutExtension(mSlicerManagers[dialog.GetInputFileIndex()]->GetFileName());
582       AddField(dialog.GetOutput(),dialog.getFieldFile(),dialog.GetInputFileIndex());
583       WarpImage(dialog.GetSelectedSlicer(),dialog.GetReferenceFrameIndex());
584     } else
585       std::cout << "Error or user cancellation while computing deformation field..." << std::endl;
586   } else QMessageBox::information(this, "Need to open image","You must open an image first.");
587 }
588 //------------------------------------------------------------------------------
589
590
591 //------------------------------------------------------------------------------
592 void vvMainWindow::WarpImage()
593 {
594   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
595   if (!mSlicerManagers[index]->GetVF().IsNull()) {
596     bool ok;
597     int ref = QInputDialog::getInteger(this,"Chose reference phase","Reference phase",0,0,\
598       mSlicerManagers[index]->GetImage()->GetVTKImages().size()-1,1,&ok);
599     if (ok) {
600       WarpImage(mSlicerManagers[index],ref);
601     }
602   } else
603     QMessageBox::warning(this,tr("No vector field"),tr("Sorry, can't warp without a vector field"));
604 }
605 //------------------------------------------------------------------------------
606
607
608 //------------------------------------------------------------------------------
609 void vvMainWindow::WarpImage(vvSlicerManager* selected_slicer,int reference_phase)
610 {
611   if (!selected_slicer->GetVF().IsNull()) {
612     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
613     QFileInfo info(selected_slicer->GetFileName().c_str());
614     vvImageWarp warp(selected_slicer->GetImage(),selected_slicer->GetVF(),
615       reference_phase,this);
616     if (warp.ComputeWarpedImage()) {
617       AddImage(warp.GetWarpedImage(),info.path().toStdString()+"/"+info.completeBaseName().toStdString()+"_warped.mhd");
618       AddImage(warp.GetDiffImage()  ,info.path().toStdString()+"/"+info.completeBaseName().toStdString()+"_diff.mhd");
619       AddImage(warp.GetJacobianImage()  ,info.path().toStdString()+"/"+info.completeBaseName().toStdString()+"_jacobian.mhd");
620       QApplication::restoreOverrideCursor();
621     } else {
622       QApplication::restoreOverrideCursor();
623       QMessageBox::warning(this,tr("Different spacings"),tr("The vector field and image spacings must be the same in order to warp."));
624     }
625   } else
626     QMessageBox::warning(this,tr("No vector field"),tr("Sorry, can't warp without a vector field."));
627 }
628 //------------------------------------------------------------------------------
629
630
631 //------------------------------------------------------------------------------
632 vvMainWindow::~vvMainWindow()
633 {
634   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
635     if (mSlicerManagers[i] != NULL)
636       delete mSlicerManagers[i];
637   }
638 }
639 //------------------------------------------------------------------------------
640
641 //------------------------------------------------------------------------------
642 QTabWidget * vvMainWindow::GetTab()
643 {
644   return tabWidget;
645 }
646 //------------------------------------------------------------------------------
647
648
649 //------------------------------------------------------------------------------
650 void vvMainWindow::MergeImages()
651 {
652   QString Extensions = EXTENSIONS;
653   Extensions += ";;All Files (*)";
654   QStringList files = QFileDialog::getOpenFileNames(this,tr("Merge Images"),mInputPathName,Extensions);
655   if (files.isEmpty())
656     return;
657   mInputPathName = itksys::SystemTools::GetFilenamePath(files[0].toStdString()).c_str();
658   std::vector<std::string> vector;
659
660   unsigned int currentDim = 0;
661   std::vector<double> currentSpacing;
662   std::vector<int> currentSize;
663   std::vector<double> currentOrigin;
664
665   for (int i = 0; i < files.size(); i++) {
666     itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
667       files[i].toStdString().c_str(), itk::ImageIOFactory::ReadMode);
668     reader->SetFileName(files[i].toStdString().c_str());
669     reader->ReadImageInformation();
670     if (reader)        {
671       //NOViewWidget->hide();
672       //NEViewWidget->hide();
673       //SOViewWidget->hide();
674       //SEViewWidget->hide();
675       if (i == 0)
676         currentDim = reader->GetNumberOfDimensions();
677       bool IsOk = true;
678       for (unsigned int j = 0; j < currentDim; j++) {
679         if (i == 0) {
680           if (j == 0) {
681             currentSpacing.resize(currentDim);
682             currentSize.resize(currentDim);
683             currentOrigin.resize(currentDim);
684           }
685           currentOrigin[j] = reader->GetOrigin(j);
686           currentSpacing[j] = reader->GetSpacing(j);
687           currentSize[j] = reader->GetDimensions(j);
688         } else if (currentDim != reader->GetNumberOfDimensions()
689           || currentSpacing[j] != reader->GetSpacing(j)
690           || currentSize[j] != (int)reader->GetDimensions(j)
691           || currentOrigin[j] != reader->GetOrigin(j)) {
692             QString error = "Cannot read file (too different from others ";
693             error += files[i].toStdString().c_str();
694             QMessageBox::information(this,tr("Reading problem"),error);
695             IsOk = false;
696             break;
697         }
698       }
699       if (IsOk)
700         vector.push_back(files[i].toStdString());
701     }
702   }
703   if (vector.size() > 0)
704     LoadImages(vector, vvImageReader::MERGED);
705 }
706 //------------------------------------------------------------------------------
707
708 //------------------------------------------------------------------------------
709 void vvMainWindow::SliceImages()
710 {
711   QString Extensions = EXTENSIONS;
712   Extensions += ";;All Files (*)";
713
714   QStringList files = QFileDialog::getOpenFileNames(this,tr("Slice Images"),mInputPathName,Extensions);
715   if (files.isEmpty())
716     return;
717   mInputPathName = itksys::SystemTools::GetFilenamePath(files[0].toStdString()).c_str();
718   std::vector<std::string> vector;
719   for (int i = 0; i < files.size(); i++)
720     vector.push_back(files[i].toStdString());
721   LoadImages(vector, vvImageReader::SLICED);
722 }
723 //------------------------------------------------------------------------------
724
725 //------------------------------------------------------------------------------
726 void vvMainWindow::MergeImagesWithTime()
727 {
728   QString Extensions = EXTENSIONS;
729   Extensions += ";;All Files (*)";
730   QStringList files = QFileDialog::getOpenFileNames(this,tr("Merge Images With Time"),mInputPathName,Extensions);
731   if (files.isEmpty())
732     return;
733   mInputPathName = itksys::SystemTools::GetFilenamePath(files[0].toStdString()).c_str();
734   std::vector<std::string> vector;
735
736   for (int i = 0; i < files.size(); i++)
737     vector.push_back(files[i].toStdString());
738   sort(vector.begin(),vector.end());
739   if (vector.size() > 1)
740     LoadImages(vector, vvImageReader::MERGEDWITHTIME);
741   else
742     QMessageBox::warning(this,tr("Reading problem"),"You need to select at least two images to merge images with time.\nIf you only want to open one image, please use the \"Open Image\" function.");
743 }
744 //------------------------------------------------------------------------------
745
746
747 //------------------------------------------------------------------------------
748 void vvMainWindow::OpenDicom()
749 {
750   std::vector<std::string> files;
751
752   //std::cout << "dicomSeriesSelector " << std::endl;
753   if (dicomSeriesSelector->exec() == QDialog::Accepted) {
754     files = *(dicomSeriesSelector->GetFilenames());
755     LoadImages(files, vvImageReader::DICOM);
756   }
757 }  
758 #ifdef CLITK_USE_PACS_CONNECTION
759 void vvMainWindow::ConnectPacs()
760 {
761   std::vector<std::string> files;
762
763   //std::cout << "dicomSeriesSelector " << std::endl;
764 if (PacsConnection->exec() == QDialog::Accepted) {
765         for (int i = 0; i < PacsConnection->getSeriesCount(); i++)
766         {
767                 files = PacsConnection->getFileNames(i);
768                 LoadImages(files, vvImageReader::DICOM);
769         }
770         PacsConnection->clearMove();
771   }
772   }
773
774 #endif
775 //------------------------------------------------------------------------------
776
777 //------------------------------------------------------------------------------
778 void vvMainWindow::OpenImages()
779 {
780   QString Extensions = EXTENSIONS;
781   Extensions += ";;All Files (*)";
782
783   QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Images"),mInputPathName,Extensions);
784   if (files.isEmpty())
785     return;
786   mInputPathName = itksys::SystemTools::GetFilenamePath(files[0].toStdString()).c_str();
787   std::vector<std::string> vector;
788   for (int i = 0; i < files.size(); i++)
789     vector.push_back(files[i].toStdString());
790   LoadImages(vector, vvImageReader::IMAGE);
791 }
792 //------------------------------------------------------------------------------
793 void vvMainWindow::OpenRecentImage()
794 {
795   QAction * caller = qobject_cast<QAction*>(sender());
796   std::vector<std::string> images;
797   images.push_back(caller->text().toStdString());
798   mInputPathName = itksys::SystemTools::GetFilenamePath(images[0]).c_str();
799   LoadImages(images, vvImageReader::IMAGE);
800 }
801 //------------------------------------------------------------------------------
802
803
804 //------------------------------------------------------------------------------
805 void vvMainWindow::OpenImageWithTime()
806 {
807   QString Extensions = EXTENSIONS;
808   Extensions += ";;All Files (*)";
809
810   QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Images With Time"),mInputPathName,Extensions);
811   if (files.isEmpty())
812     return;
813   mInputPathName = itksys::SystemTools::GetFilenamePath(files[0].toStdString()).c_str();
814   std::vector<std::string> vector;
815   for (int i = 0; i < files.size(); i++) {
816     vector.push_back(files[i].toStdString());
817   }
818   LoadImages(vector, vvImageReader::IMAGEWITHTIME);
819 }
820 //------------------------------------------------------------------------------
821
822
823 //------------------------------------------------------------------------------
824 void vvMainWindow::LoadImages(std::vector<std::string> files, vvImageReader::LoadedImageType filetype)
825 {
826   //Separate the way to open images and dicoms
827   int fileSize;
828   if (filetype == vvImageReader::IMAGE || filetype == vvImageReader::IMAGEWITHTIME)
829     fileSize = files.size();
830   else
831     fileSize = 1;
832
833   // For SLICED, we need the number of slices (ndim and #slices)
834   std::vector<unsigned int> nSlices;
835   nSlices.resize(files.size());
836   std::fill(nSlices.begin(), nSlices.end(), 1);
837   if (filetype == vvImageReader::SLICED) {
838     for (int i = 0; i < fileSize; i++) {
839       itk::ImageIOBase::Pointer header = clitk::readImageHeader(files[i]);
840       QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
841       if (!header) {
842         nSlices[i] = 0;
843         QString error = "Cannot open file \n";
844         error += files[i].c_str();
845         QMessageBox::information(this,tr("Reading problem"),error);
846         return;
847       }
848       if (header->GetNumberOfDimensions() < 3) {
849         nSlices[i] = 0;
850         QString error = "Dimension problem. Cannot slice \n";
851         error += files[i].c_str();
852         QMessageBox::information(this,tr("Reading problem"),error);
853         return;
854       }
855       nSlices[i] = header->GetDimensions( header->GetNumberOfDimensions()-1 );
856     }
857   }
858
859   //Only add to the list of recently opened files when a single file is opened,
860   //to avoid polluting the list of recently opened files
861   if (files.size() == 1) {
862     QFileInfo finfo=tr(files[0].c_str());
863     AddToRecentlyOpenedImages(finfo.absoluteFilePath().toStdString());
864     updateRecentlyOpenedFilesMenu(GetRecentlyOpenedImages());
865   }
866   //init the progress events
867   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
868   vvProgressDialog progress("Opening " + files[0],fileSize>1);
869   qApp->processEvents();
870
871   int numberofsuccesulreads=0;
872   //open images as 1 or multiples
873   for (int i = 0; i < fileSize; i++) {
874     progress.SetText("Opening " + files[i]);
875     progress.SetProgress(i,fileSize);
876     qApp->processEvents();
877
878     for (unsigned int j = 0; j < nSlices[i]; j++) {
879       //read the image and put it in mSlicerManagers
880       vvSlicerManager* imageManager = new vvSlicerManager(4);
881       qApp->processEvents();
882
883       bool SetImageSucceed=false;
884
885       // Change filename if an image with the same already exist
886       int number = GetImageDuplicateFilenameNumber(files[i] + std::string("_slice"));
887
888       if (filetype == vvImageReader::IMAGE || filetype == vvImageReader::IMAGEWITHTIME || filetype == vvImageReader::SLICED)
889         SetImageSucceed = imageManager->SetImage(files[i],filetype, number, j);
890       else {
891         SetImageSucceed = imageManager->SetImages(files,filetype, number);
892       }
893
894       if (!SetImageSucceed) {
895         QApplication::restoreOverrideCursor();
896         QString error = "Cannot open file \n";
897         error += imageManager->GetLastError().c_str();
898         QMessageBox::information(this,tr("Reading problem"),error);
899         delete imageManager;
900       } else {
901         mSlicerManagers.push_back(imageManager);
902
903         //create an item in the tree with good settings
904         QTreeWidgetItem *item = new QTreeWidgetItem();
905         item->setData(0,Qt::UserRole,files[i].c_str());
906         QFileInfo fileinfo(imageManager->GetFileName().c_str()); //Do not show the path
907         item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
908         item->setData(1,Qt::UserRole,tr("image"));
909         item->setToolTip(COLUMN_IMAGE_NAME, imageManager->GetListOfAbsoluteFilePathInOneString("image").c_str());
910         qApp->processEvents();
911
912         //Create the buttons for reload and close
913         qApp->processEvents();
914         QTreePushButton* cButton = new QTreePushButton;
915         cButton->setItem(item);
916         cButton->setColumn(COLUMN_CLOSE_IMAGE);
917         cButton->setToolTip(tr("close image"));
918         cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
919         connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
920           this,SLOT(CloseImage(QTreeWidgetItem*, int)));
921
922         QTreePushButton* rButton = new QTreePushButton;
923         rButton->setItem(item);
924         rButton->setColumn(COLUMN_RELOAD_IMAGE);
925         rButton->setToolTip(tr("reload image"));
926         rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
927         connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
928           this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
929
930         DataTree->addTopLevelItem(item);
931         DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
932         DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
933
934         //set the id of the image
935         QString id = QDir::current().absoluteFilePath(files[i].c_str()) + QString::number(mSlicerManagers.size()-1);
936         item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
937         mSlicerManagers.back()->SetId(id.toStdString());
938
939         linkPanel->addImage(imageManager->GetFileName(), id.toStdString());
940
941         connect(mSlicerManagers.back(), SIGNAL(currentImageChanged(std::string)),
942           this,SLOT(CurrentImageChanged(std::string)));
943         connect(mSlicerManagers.back(), SIGNAL(currentPickedImageChanged(std::string)),
944           this, SLOT(CurrentPickedImageChanged(std::string)));
945         connect(mSlicerManagers.back(), SIGNAL(UpdatePosition(int, double, double, double, double, double, double, double)),
946           this,SLOT(MousePositionChanged(int,double, double, double, double, double, double, double)));
947         connect(mSlicerManagers.back(), SIGNAL(UpdateVector(int, double, double, double, double)),
948           this, SLOT(VectorChanged(int,double,double,double, double)));
949         connect(mSlicerManagers.back(), SIGNAL(UpdateOverlay(int, double, double)),
950           this, SLOT(OverlayChanged(int,double,double)));
951         connect(mSlicerManagers.back(), SIGNAL(UpdateFusion(int, double)),
952           this, SLOT(FusionChanged(int,double)));
953         connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged()),
954           this,SLOT(WindowLevelChanged()));
955         connect(mSlicerManagers.back(), SIGNAL(UpdateSlice(int,int)),
956           this,SLOT(UpdateSlice(int,int)));
957         connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int, int)),
958           this,SLOT(UpdateTSlice(int, int, int)));
959         connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int, int)),
960           this,SLOT(ImageInfoChanged()));
961         connect(mSlicerManagers.back(), SIGNAL(UpdateSliceRange(int,int,int,int,int)),
962           this,SLOT(UpdateSliceRange(int,int,int,int,int)));
963         connect(mSlicerManagers.back(), SIGNAL(UpdateLinkManager(std::string,int,double,double,double,int)),
964           this,SLOT(UpdateLinkManager(std::string,int,double,double,double,int)));
965         connect(mSlicerManagers.back(), SIGNAL(UpdateLinkedNavigation(std::string,vvSlicerManager*,vvSlicer*)),
966           this,SLOT(UpdateLinkedNavigation(std::string,vvSlicerManager*,vvSlicer*)));
967         connect(mSlicerManagers.back(), SIGNAL(ChangeImageWithIndexOffset(vvSlicerManager*,int,int)),
968           this,SLOT(ChangeImageWithIndexOffset(vvSlicerManager*,int,int)));
969         connect(mSlicerManagers.back(),SIGNAL(LandmarkAdded()),landmarksPanel,SLOT(AddPoint()));
970
971         InitSlicers();
972         numberofsuccesulreads++;
973       }
974     }
975   }
976   if (numberofsuccesulreads) {
977     NOViewWidget->show();
978     NEViewWidget->show();
979     SOViewWidget->show();
980     SEViewWidget->show();
981     UpdateTree();
982     InitDisplay();
983     ShowLastImage();
984
985     // Try to guess default WindowLevel
986     double range[2];
987     mSlicerManagers.back()->GetImage()->GetFirstVTKImageData()->GetScalarRange(range);
988     if ((range[0] == 0) && (range[1] == 1)) {
989       presetComboBox->setCurrentIndex(WL_BINARY);// binary
990     } else {
991       // TODO
992     }
993   }
994   QApplication::restoreOverrideCursor();
995 }
996 //------------------------------------------------------------------------------
997
998 //------------------------------------------------------------------------------
999 void vvMainWindow::UpdateTree()
1000 {
1001   DataTree->resizeColumnToContents(COLUMN_TREE);
1002   DataTree->resizeColumnToContents(COLUMN_UL_VIEW);
1003   DataTree->resizeColumnToContents(COLUMN_UR_VIEW);
1004   DataTree->resizeColumnToContents(COLUMN_DL_VIEW);
1005   DataTree->resizeColumnToContents(COLUMN_DR_VIEW);
1006   DataTree->resizeColumnToContents(COLUMN_IMAGE_NAME);
1007   DataTree->resizeColumnToContents(COLUMN_CLOSE_IMAGE);
1008   DataTree->resizeColumnToContents(COLUMN_RELOAD_IMAGE);
1009 }
1010 //------------------------------------------------------------------------------
1011
1012 //------------------------------------------------------------------------------
1013 void vvMainWindow::CurrentImageChanged(std::string id)
1014 {
1015   if (id == mCurrentSelectedImageId) return; // Do nothing
1016   int selected = 0;
1017   for (int i = 0; i < DataTree->topLevelItemCount(); i++) {
1018     if (DataTree->topLevelItem(i)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString().toStdString() == id) {
1019       selected = i;
1020     } else {
1021       DataTree->topLevelItem(i)->setSelected(0);
1022     }
1023     for (int child = 0; child < DataTree->topLevelItem(i)->childCount(); child++)
1024       DataTree->topLevelItem(i)->child(child)->setSelected(0);
1025
1026   }
1027   DataTree->topLevelItem(selected)->setSelected(1);
1028   mCurrentSelectedImageId = id;
1029
1030   landmarksPanel->SetCurrentLandmarks(mSlicerManagers[selected]->GetLandmarks(),
1031                                       mSlicerManagers[selected]->GetTSlice());
1032   landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
1033   landmarksPanel->SetCurrentImage(mSlicerManagers[selected]->GetFileName().c_str());
1034   
1035   emit SelectedImageHasChanged(mSlicerManagers[selected]);
1036 }
1037 //------------------------------------------------------------------------------
1038
1039 //------------------------------------------------------------------------------
1040 void vvMainWindow::CurrentPickedImageChanged(std::string id)
1041 {
1042   if (id == mCurrentPickedImageId) return; // Do nothing
1043   int selected = 0;
1044   for (int i = 0; i < DataTree->topLevelItemCount(); i++) {
1045     if (DataTree->topLevelItem(i)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString().toStdString() == id) {
1046       selected = i;
1047     } else {
1048       DataTree->topLevelItem(i)->setSelected(0);
1049     }
1050     for (int child = 0; child < DataTree->topLevelItem(i)->childCount(); child++)
1051       DataTree->topLevelItem(i)->child(child)->setSelected(0);
1052
1053   }
1054   DataTree->topLevelItem(selected)->setSelected(1);
1055   mCurrentPickedImageId = id;
1056   mCurrentPickedImageIndex = selected;
1057 }
1058 //------------------------------------------------------------------------------
1059
1060 //------------------------------------------------------------------------------
1061 void vvMainWindow::ImageInfoChanged()
1062 {
1063   contextActions[6]->setEnabled(1);
1064   contextActions[5]->setEnabled(1);
1065   actionSave_As->setEnabled(1);
1066   actionAdd_VF_to_current_Image->setEnabled(1);
1067   actionAdd_fusion_image->setEnabled(1);
1068   actionAdd_overlay_image_to_current_image->setEnabled(1);
1069   actionAdd_USSequence_toCT->setEnabled(1);
1070   actionNorth_East_Window->setEnabled(1);
1071   actionNorth_West_Window->setEnabled(1);
1072   actionSouth_East_Window->setEnabled(1);
1073   actionSouth_West_Window->setEnabled(1);
1074   vvToolManager::GetInstance()->EnableToolsInMenu(this, true);
1075   inverseButton->setEnabled(1);
1076
1077   goToCursorPushButton->setEnabled(1);
1078
1079   if (DataTree->selectedItems().size()) {
1080     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1081
1082     colorMapComboBox->setEnabled(1);
1083     for (int i = 0; i < DataTree->topLevelItem(index)->childCount(); i++) {
1084       if (DataTree->topLevelItem(index)->child(i)->data(1,Qt::UserRole).toString() == "overlay" ||
1085         DataTree->topLevelItem(index)->child(i)->data(1,Qt::UserRole).toString() == "fusion" ||
1086         DataTree->topLevelItem(index)->child(i)->data(1,Qt::UserRole).toString() == "fusionSequence") {
1087           colorMapComboBox->setEnabled(0);
1088           break;
1089       }
1090     }
1091
1092     std::vector<double> origin;
1093     std::vector<double> inputSpacing;
1094     std::vector<int> inputSize;
1095     std::vector<double> sizeMM;
1096     vtkSmartPointer<vtkMatrix4x4> transformation;
1097     int dimension=0;
1098     QString pixelType;
1099     QString inputSizeInBytes;
1100     QString image = DataTree->selectedItems()[0]->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
1101
1102     int nframes = mSlicerManagers[index]->GetSlicer(0)->GetTMax();
1103
1104     if (nframes > 1 || playMode == 1) {
1105       playButton->setEnabled(1);
1106       frameRateLabel->setEnabled(1);
1107       frameRateSpinBox->setEnabled(1);
1108     } else {
1109       playButton->setEnabled(0);
1110       frameRateLabel->setEnabled(0);
1111       frameRateSpinBox->setEnabled(0);
1112     }
1113
1114     //read image header
1115     int NPixel = 1;
1116
1117     int tSlice = 0;
1118     vvImage::Pointer imageSelected;
1119     if (DataTree->topLevelItem(index) == DataTree->selectedItems()[0]) {
1120       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage();
1121       tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice();
1122     } else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "vector") {
1123       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetVF();
1124       tSlice = mSlicerManagers[index]->GetSlicer(0)->GetOverlayTSlice();
1125     } else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "overlay") {
1126       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetOverlay();
1127       tSlice = mSlicerManagers[index]->GetSlicer(0)->GetOverlayTSlice();
1128     } else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "fusion") {
1129       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetFusion();
1130       tSlice = mSlicerManagers[index]->GetSlicer(0)->GetFusionTSlice();
1131     }
1132     else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "fusionSequence") {
1133       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetFusion();
1134       tSlice = mSlicerManagers[index]->GetSlicer(0)->GetFusionTSlice();
1135     }
1136     else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "contour") {
1137       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage();
1138       tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice();
1139     }
1140     else {
1141       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage();
1142       tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice();
1143     }
1144
1145     dimension = imageSelected->GetNumberOfDimensions();
1146     origin.resize(dimension);
1147     inputSpacing.resize(dimension);
1148     inputSize.resize(dimension);
1149     sizeMM.resize(dimension);
1150     pixelType = mSlicerManagers[index]->GetImage()->GetScalarTypeAsITKString().c_str();
1151     for (int i = 0; i < dimension; i++) {
1152       origin[i] = imageSelected->GetOrigin()[i];
1153       inputSpacing[i] = imageSelected->GetSpacing()[i];
1154       inputSize[i] = imageSelected->GetSize()[i];
1155       sizeMM[i] = inputSize[i]*inputSpacing[i];
1156       NPixel *= inputSize[i];
1157     }
1158     inputSizeInBytes = GetSizeInBytes(imageSelected->GetActualMemorySize()*1000);
1159
1160     QString dim = QString::number(dimension) + " (";
1161     dim += pixelType + ")";
1162
1163     infoPanel->setFileName(image);
1164     std::string creationImageTimeValue("No creation time");
1165     itk::ExposeMetaData< std::string > (*imageSelected->GetFirstMetaDataDictionary(), "creationImageTime", creationImageTimeValue);
1166     infoPanel->setImageCreationTime(QString(creationImageTimeValue.c_str()));
1167     infoPanel->setDimension(dim);
1168     infoPanel->setSizePixel(GetVectorIntAsString(inputSize));
1169     infoPanel->setSizeMM(GetVectorDoubleAsString(sizeMM));
1170     infoPanel->setOrigin(GetVectorDoubleAsString(origin));
1171     infoPanel->setSpacing(GetVectorDoubleAsString(inputSpacing));
1172     infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")");
1173
1174     transformation = imageSelected->GetTransform()[tSlice]->GetMatrix();
1175     infoPanel->setTransformation(clitk::Get4x4MatrixDoubleAsString(transformation).c_str());
1176
1177     landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(),
1178                                         mSlicerManagers[index]->GetTSlice());
1179     landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
1180     landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str());
1181
1182     overlayPanel->getCurrentImageName(mSlicerManagers[index]->GetFileName().c_str());
1183     for (int i = 0; i < 4; i++) {
1184       if (DataTree->selectedItems()[0]->data(i+1,Qt::CheckStateRole).toInt() > 0 || i == 3) {
1185         mSlicerManagers[index]->UpdateInfoOnCursorPosition(i);
1186         break;
1187       }
1188     }
1189
1190 //     infoPanel->setFileName(image);
1191 //     infoPanel->setDimension(dim);
1192 //     infoPanel->setSizePixel(GetVectorIntAsString(inputSize));
1193 //     infoPanel->setSizeMM(GetVectorDoubleAsString(sizeMM));
1194 //     infoPanel->setOrigin(GetVectorDoubleAsString(origin));
1195 //     infoPanel->setSpacing(GetVectorDoubleAsString(inputSpacing));
1196 //     infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")");
1197 // 
1198 //     landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(),
1199 //                                         mSlicerManagers[index]->GetTSlice());
1200 //     landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
1201 //     landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str());
1202 // 
1203 //     overlayPanel->getCurrentImageName(mSlicerManagers[index]->GetFileName().c_str());
1204 //     for (int i = 0; i < 4; i++) {
1205 //       if (DataTree->selectedItems()[0]->data(i+1,Qt::CheckStateRole).toInt() > 0 || i == 3) {
1206 //         mSlicerManagers[index]->UpdateInfoOnCursorPosition(i);
1207 //         break;
1208 //       }
1209 //     }
1210     WindowLevelChanged();
1211
1212     slicingPresetComboBox->setCurrentIndex(mSlicerManagers[index]->GetSlicingPreset());
1213
1214     if (mSlicerManagers[index]->GetSlicer(0)->GetVF()) {
1215       overlayPanel->getVFName(mSlicerManagers[index]->GetVFName().c_str());
1216       overlayPanel->getVFProperty(mSlicerManagers[index]->GetSlicer(0)->GetVFSubSampling(),
1217         mSlicerManagers[index]->GetSlicer(0)->GetVFScale(),
1218         mSlicerManagers[index]->GetSlicer(0)->GetVFLog());
1219     } else {
1220       overlayPanel->getVFName(mSlicerManagers[index]->GetVFName().c_str());
1221       overlayPanel->getVFProperty(-1,-1,-1);
1222     }
1223     if (mSlicerManagers[index]->GetSlicer(0)->GetOverlay()) {
1224       overlayPanel->getOverlayName(mSlicerManagers[index]->GetOverlayName().c_str());
1225     } else {
1226       overlayPanel->getOverlayName(mSlicerManagers[index]->GetOverlayName().c_str());
1227     }
1228
1229     if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) {
1230       overlayPanel->getFusionName(mSlicerManagers[index]->GetFusionName().c_str());
1231     } else {
1232       overlayPanel->getFusionName(mSlicerManagers[index]->GetFusionName().c_str());
1233     }
1234   }
1235 }
1236 //------------------------------------------------------------------------------
1237
1238 //------------------------------------------------------------------------------
1239 void vvMainWindow::ShowDocumentation()
1240 {
1241   documentation->show();
1242 }
1243 //------------------------------------------------------------------------------
1244
1245 //------------------------------------------------------------------------------
1246 void vvMainWindow::PopupRegisterForm(bool checkCanPush)
1247 {
1248   vvRegisterForm* registerForm = new vvRegisterForm(QUrl("http://www.creatis.insa-lyon.fr/~dsarrut/vvregister/write.php"), getVVSettingsPath(), getSettingsOptionFormat());
1249   if(!checkCanPush) {
1250     registerForm->show();
1251   } else {
1252     if(registerForm->canPush()) {
1253       registerForm->show();
1254       registerForm->acquitPushed();//too bad if there is not internet connection anymore.
1255     }
1256   }
1257 }
1258 //------------------------------------------------------------------------------
1259
1260 //------------------------------------------------------------------------------
1261 void vvMainWindow::ShowHelpDialog()
1262 {
1263   help_dialog->show();
1264 }
1265 //------------------------------------------------------------------------------
1266
1267 //------------------------------------------------------------------------------
1268 void vvMainWindow::ChangeViewMode()
1269 {
1270   typedef struct _SIZE{
1271     QSplitter* splitter;
1272     QList<int> size1, size2;
1273     int cols[3];
1274   }SplitterSize;
1275   SplitterSize sizes[4];
1276   sizes[0].splitter = OSplitter;
1277   sizes[0].size1.push_back(1);
1278   sizes[0].size1.push_back(0);
1279   sizes[0].size2.push_back(1);
1280   sizes[0].size2.push_back(0);
1281   sizes[0].cols[0] = 2;
1282   sizes[0].cols[1] = 3;
1283   sizes[0].cols[2] = 4;
1284
1285   sizes[1].splitter = ESplitter;
1286   sizes[1].size1.push_back(0);
1287   sizes[1].size1.push_back(1);
1288   sizes[1].size2.push_back(1);
1289   sizes[1].size2.push_back(0);
1290   sizes[1].cols[0] = 1;
1291   sizes[1].cols[1] = 3;
1292   sizes[1].cols[2] = 4;
1293
1294   sizes[2].splitter = OSplitter;
1295   sizes[2].size1.push_back(1);
1296   sizes[2].size1.push_back(0);
1297   sizes[2].size2.push_back(0);
1298   sizes[2].size2.push_back(1);
1299   sizes[2].cols[0] = 1;
1300   sizes[2].cols[1] = 2;
1301   sizes[2].cols[2] = 4;
1302
1303   sizes[3].splitter = ESplitter;
1304   sizes[3].size1.push_back(0);
1305   sizes[3].size1.push_back(1);
1306   sizes[3].size2.push_back(0);
1307   sizes[3].size2.push_back(1);
1308   sizes[3].cols[0] = 1;
1309   sizes[3].cols[1] = 2;
1310   sizes[3].cols[2] = 3;
1311
1312   int slicer = mSlicerManagers[mCurrentPickedImageIndex]->GetSelectedSlicer();
1313   if (viewMode == 1) {
1314     if (slicer >= 0) {
1315       viewMode = 0;
1316       splitter_3->setSizes(sizes[slicer].size1);
1317       sizes[slicer].splitter->setSizes(sizes[slicer].size2);
1318       DataTree->setColumnHidden(sizes[slicer].cols[0],1);
1319       DataTree->setColumnHidden(sizes[slicer].cols[1],1);
1320       DataTree->setColumnHidden(sizes[slicer].cols[2],1);
1321     }
1322   } else {
1323     QList<int> size;
1324     if (slicer >= 0) {
1325       viewMode = 1;
1326       size.push_back(1);
1327       size.push_back(1);
1328       splitter_3->setSizes(size);
1329       sizes[slicer].splitter->setSizes(size);
1330       DataTree->setColumnHidden(sizes[slicer].cols[0],0);
1331       DataTree->setColumnHidden(sizes[slicer].cols[1],0);
1332       DataTree->setColumnHidden(sizes[slicer].cols[2],0);
1333     }
1334   }
1335   UpdateRenderWindows();
1336   /*
1337   ** I don't know why but for both resized QVTKWidget we also need to render
1338   ** the associated Slicer to redraw crosses.
1339   */
1340   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
1341     //     if (DataTree->topLevelItem(i)->data(COLUMN_UL_VIEW,Qt::CheckStateRole).toInt() > 1)
1342     mSlicerManagers[i]->GetSlicer(0)->Render();
1343     mSlicerManagers[i]->GetSlicer(1)->Render();
1344     //     if (DataTree->topLevelItem(i)->data(COLUMN_DL_VIEW,Qt::CheckStateRole).toInt() > 1)
1345     mSlicerManagers[i]->GetSlicer(2)->Render();
1346     mSlicerManagers[i]->GetSlicer(3)->Render();
1347   }
1348 }
1349 //------------------------------------------------------------------------------
1350
1351 //------------------------------------------------------------------------------
1352 QString vvMainWindow::GetSizeInBytes(unsigned long size)
1353 {
1354   QString result = "";// QString::number(size);
1355   //result += " bytes (";
1356   if (size > 1000000000) {
1357     size /= 1000000000;
1358     result += QString::number(size);
1359     result += "Gb";//)";
1360   } else if (size > 1000000) {
1361     size /= 1000000;
1362     result += QString::number(size);
1363     result += "Mb";//)";
1364   } else if (size > 1000) {
1365     size /= 1000;
1366     result += QString::number(size);
1367     result += "kb";//)";
1368   }
1369   return result;
1370 }
1371 //------------------------------------------------------------------------------
1372
1373 //------------------------------------------------------------------------------
1374 QString vvMainWindow::GetVectorDoubleAsString(std::vector<double> vectorDouble)
1375 {
1376   QString result;
1377   for (unsigned int i= 0; i < vectorDouble.size(); i++) {
1378     if (i != 0)
1379       result += " ";
1380     result += QString::number(vectorDouble[i]);
1381   }
1382   return result;
1383 }
1384 //------------------------------------------------------------------------------
1385
1386 //------------------------------------------------------------------------------
1387 QString vvMainWindow::GetVectorIntAsString(std::vector<int> vectorInt)
1388 {
1389   QString result;
1390   for (unsigned int i= 0; i < vectorInt.size(); i++) {
1391     if (i != 0)
1392       result += " ";
1393     result += QString::number(vectorInt[i]);
1394   }
1395   return result;
1396 }
1397 //------------------------------------------------------------------------------
1398
1399 //------------------------------------------------------------------------------
1400 //this actually returns the SlicerManager index!
1401 int vvMainWindow::GetSlicerIndexFromItem(QTreeWidgetItem* item)
1402 {
1403   QString id = item->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
1404   for (int i = 0; i < DataTree->topLevelItemCount(); i++) {
1405     if (DataTree->topLevelItem(i)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString() == id)
1406       return i;
1407   }
1408   return -1;
1409 }
1410 //------------------------------------------------------------------------------
1411
1412 //------------------------------------------------------------------------------
1413 QTreeWidgetItem* vvMainWindow::GetItemFromSlicerManager(vvSlicerManager* sm)
1414 {
1415   QString id = sm->GetId().c_str();
1416   for (int i = 0; i < DataTree->topLevelItemCount(); i++) {
1417     if (DataTree->topLevelItem(i)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString() == id)
1418       return DataTree->topLevelItem(i);
1419   }
1420   return NULL;
1421 }
1422 //------------------------------------------------------------------------------
1423
1424 //------------------------------------------------------------------------------
1425 void vvMainWindow::DisplayChanged(QTreeWidgetItem *clickedItem, int column)
1426 {
1427   if ( column >= COLUMN_CLOSE_IMAGE || column <= 0)
1428     return;
1429
1430   // Get parent information (might be the same item)
1431   int slicerManagerIndex = GetSlicerIndexFromItem(clickedItem);
1432   QTreeWidgetItem* clickedParentItem = DataTree->topLevelItem(slicerManagerIndex);
1433   vvSlicer* clickedSlicer = mSlicerManagers[slicerManagerIndex]->GetSlicer(column-1);
1434
1435   // Go over the complete item tree (only 2 levels, parents and children)
1436   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
1437     // Trick to avoid redoing twice the job for a key (sr)
1438     mSlicerManagers[i]->GetSlicer(column-1)->GetRenderWindow()->GetInteractor()->SetKeySym("Crap");
1439
1440     QTreeWidgetItem* currentParentItem = DataTree->topLevelItem(i);
1441     if(currentParentItem != clickedParentItem) {
1442       // Not the branch of the clicked item, uncheck all
1443
1444       // Parent
1445       currentParentItem->setData(column,Qt::CheckStateRole, 0);
1446       mSlicerManagers[i]->UpdateSlicer(column-1, false);
1447
1448       // Children
1449       for (int iChild = 0; iChild < currentParentItem->childCount(); iChild++) {
1450         currentParentItem->child(iChild)->setData(column,Qt::CheckStateRole, 0);
1451       }
1452     }
1453     else {
1454       // Branch of the clicked one: get check status from actor visibility in slicer
1455       // and toggle the clicked one
1456
1457       // Parent
1458       bool vis = clickedSlicer->GetActorVisibility("image", 0);
1459       bool draw = clickedSlicer->GetRenderer()->GetDraw();
1460
1461       // Update slicer (after getting visibility)
1462       mSlicerManagers[slicerManagerIndex]->UpdateSlicer(column-1, true);
1463       mSlicerManagers[slicerManagerIndex]->UpdateInfoOnCursorPosition(column-1);
1464       DisplaySliders(slicerManagerIndex, column-1);
1465       if(clickedParentItem == clickedItem) {
1466         // Toggle
1467         vis = !draw || !vis;
1468       }
1469       clickedSlicer->SetActorVisibility("image", 0, vis);
1470       clickedParentItem->setData(column, Qt::CheckStateRole, vis?2:0);
1471
1472       // Children
1473       std::map<std::string, int> actorTypeCounts;      
1474       for (int iChild = 0; iChild < clickedParentItem->childCount(); iChild++) {
1475         QTreeWidgetItem* currentChildItem = clickedParentItem->child(iChild);
1476         std::string actorType = currentChildItem->data(1,Qt::UserRole).toString().toStdString();
1477         vis = clickedSlicer->GetActorVisibility(actorType, actorTypeCounts[actorType]);
1478         if(currentChildItem == clickedItem) {
1479           // Toggle or force visibility if it was not on this branch so far
1480           vis = !draw || !vis;
1481           clickedSlicer->SetActorVisibility(actorType, actorTypeCounts[actorType], vis);
1482         }
1483         currentChildItem->setData(column, Qt::CheckStateRole, vis?2:0);
1484         actorTypeCounts[actorType]++;
1485       }
1486     }
1487   }
1488
1489   clickedSlicer->Render();
1490 }
1491 //------------------------------------------------------------------------------
1492
1493 void vvMainWindow::InitSlicers()
1494 {
1495   if (mSlicerManagers.size()) {
1496     mSlicerManagers.back()->GenerateDefaultLookupTable();
1497
1498     mSlicerManagers.back()->SetSlicerWindow(0,NOViewWidget->GetRenderWindow());
1499     mSlicerManagers.back()->SetSlicerWindow(1,NEViewWidget->GetRenderWindow());
1500     mSlicerManagers.back()->SetSlicerWindow(2,SOViewWidget->GetRenderWindow());
1501     mSlicerManagers.back()->SetSlicerWindow(3,SEViewWidget->GetRenderWindow());
1502   }
1503 }
1504
1505 //------------------------------------------------------------------------------
1506 void vvMainWindow::InitDisplay()
1507 {
1508   if (mSlicerManagers.size()) {
1509     //BE CAREFUL : this is absolutely necessary to set the interactor style
1510     //in order to have the same style instanciation for all SlicerManagers in
1511     // a same window
1512     for (int j = 0; j < 4; j++) {
1513       vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
1514       style->SetAutoAdjustCameraClippingRange(1);
1515       bool AlreadySelected = false;
1516       for (int i = 0; i < DataTree->topLevelItemCount(); i++) {
1517         mSlicerManagers[i]->SetInteractorStyleNavigator(j,style);
1518
1519         //select the image only if previous are not selected
1520         if (DataTree->topLevelItem(i)->data(j+1,Qt::CheckStateRole).toInt() > 1) {
1521           mSlicerManagers[i]->UpdateSlicer(j,1);
1522           AlreadySelected = true;
1523         } else if (i == DataTree->topLevelItemCount()-1 && !AlreadySelected) {
1524           if (DataTree->selectedItems().size() == 0)
1525             DataTree->topLevelItem(i)->setSelected(1);
1526           DataTree->topLevelItem(i)->setData(j+1,Qt::CheckStateRole,2);
1527           mSlicerManagers[i]->UpdateSlicer(j,1);
1528           DisplaySliders(i,j);
1529         } else {
1530           DataTree->topLevelItem(i)->setData(j+1,Qt::CheckStateRole,0);
1531           mSlicerManagers[i]->UpdateSlicer(j,0);
1532         }
1533       }
1534       style->Delete();
1535     }
1536   }
1537 }
1538 //------------------------------------------------------------------------------
1539
1540 //------------------------------------------------------------------------------
1541 void vvMainWindow::DisplaySliders(int slicer, int window)
1542 {
1543   if(!mSlicerManagers[slicer]->GetSlicer(window)->GetRenderer()->GetDraw())
1544     return;
1545
1546   int range[2];
1547   mSlicerManagers[slicer]->GetSlicer(window)->GetSliceRange(range);
1548   int position = mSlicerManagers[slicer]->GetSlicer(window)->GetSlice();
1549   if (range[1]>0)
1550     verticalSliders[window]->show();
1551   else
1552     verticalSliders[window]->hide();
1553   verticalSliders[window]->setRange(range[0],range[1]);
1554   verticalSliders[window]->setValue(position);
1555
1556   int tRange[2];
1557   tRange[0] = 0;
1558   tRange[1] = mSlicerManagers[slicer]->GetSlicer(window)->GetTMax();
1559   if (tRange[1]>0)
1560     horizontalSliders[window]->show();
1561   else
1562     horizontalSliders[window]->hide();
1563   horizontalSliders[window]->setRange(tRange[0],tRange[1]);
1564   int tPosition = mSlicerManagers[slicer]->GetSlicer(window)->GetMaxCurrentTSlice();
1565   horizontalSliders[window]->setValue(tPosition);
1566 }
1567 //------------------------------------------------------------------------------
1568
1569 //------------------------------------------------------------------------------
1570 void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column)
1571 {
1572   int index = GetSlicerIndexFromItem(item);
1573
1574   if (DataTree->topLevelItem(index) != item) {
1575     QString warning = "Do you really want to close the overlay : ";
1576     warning += item->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
1577     QMessageBox msgBox(QMessageBox::Warning, tr("Close Overlay"),
1578       warning, 0, this);
1579     msgBox.addButton(tr("Close"), QMessageBox::AcceptRole);
1580     msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
1581     if (msgBox.exec() == QMessageBox::AcceptRole) {
1582       std::string overlay_type=item->data(1,Qt::UserRole).toString().toStdString();
1583       int overlay_index=0;
1584       for (int child = 0; child < DataTree->topLevelItem(index)->childCount(); child++) {
1585         if (DataTree->topLevelItem(index)->\
1586           child(child)->data(1,Qt::UserRole).toString().toStdString() == overlay_type)
1587           overlay_index++;
1588         if (DataTree->topLevelItem(index)->child(child) == item) break;
1589       }
1590       if (overlay_type=="fusionSequence") {
1591         //removing the overlay sequence in a fusion sequence visualization mode 
1592         //reset the transforms
1593         overlayPanel->getFusionSequenceProperty(-1, false, 0, false);
1594
1595         //unlink and untie the slicer managers
1596         RemoveLink(mSlicerManagers[index]->GetId().c_str(), mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetId().c_str());
1597         mSlicerManagers[index]->SetFusionSequenceInvolvmentCode(-1);
1598         mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->SetFusionSequenceInvolvmentCode(-1);
1599         for (unsigned i=0 ; i<4 ; i++) {
1600             mSlicerManagers[index]->GetSlicer(i)->SetFusionSequenceCode(-1);
1601             mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetSlicer(i)->SetFusionSequenceCode(-1);
1602         }
1603
1604       }
1605       mSlicerManagers[index]->RemoveActor(overlay_type, overlay_index-1);
1606       mSlicerManagers[index]->SetColorMap(0);
1607       DataTree->topLevelItem(index)->takeChild(DataTree->topLevelItem(index)->indexOfChild(item));
1608       mSlicerManagers[index]->Render();
1609     }
1610   } else if (DataTree->topLevelItemCount() <= 1) {
1611     QString warning = "Do you really want to close the image : ";
1612     warning += item->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
1613     warning += "\nThis is the last image, you're about to close vv !!!";
1614     QMessageBox msgBox(QMessageBox::Warning, tr("Close Image"),
1615       warning, 0, this);
1616     msgBox.addButton(tr("Close vv"), QMessageBox::AcceptRole);
1617     msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
1618     if (msgBox.exec() == QMessageBox::AcceptRole) {
1619       this->close();
1620     }
1621   } else {
1622     QString warning = "Do you really want to close the image : ";
1623     warning += item->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
1624     QMessageBox msgBox(QMessageBox::Warning, tr("Close Image"),
1625       warning, 0, this);
1626     msgBox.addButton(tr("Close"), QMessageBox::AcceptRole);
1627     msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
1628     if (msgBox.exec() == QMessageBox::AcceptRole) {
1629
1630       // Tell tools that we close an image
1631       emit AnImageIsBeingClosed(mSlicerManagers[index]);
1632
1633       std::vector<vvSlicerManager*>::iterator Manageriter = mSlicerManagers.begin();
1634       DataTree->takeTopLevelItem(index);
1635       for (int i = 0; i < index; i++) {
1636         Manageriter++;
1637       }
1638       //if the slicer manager was involved in a fusion sequence visualization...
1639       if ( mSlicerManagers[index]->IsInvolvedInFusionSequence() ) {
1640         //in both cases, close the overlay: find it... and close it
1641         //ideally, I should duplicate the code, and avoid calling CloseImage, since this pops up another interactive box
1642         QTreeWidgetItem* overlayItem;
1643         if (mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) {
1644           for (unsigned i=0 ; i<item->childCount() ; i++) {
1645             overlayItem = item->child(i);
1646             this->CloseImage( overlayItem, 0 );
1647           }
1648         }
1649         else {
1650           QTreeWidgetItem* linkedItem = this->GetItemFromSlicerManager( mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()] );
1651           for (unsigned i=0 ; i<linkedItem->childCount() ; i++) {
1652             overlayItem = linkedItem->child(i);
1653             this->CloseImage( overlayItem, 0 );
1654           }
1655         }
1656
1657         /* -- this is normally already done when closing the overlay.
1658         //reset the transforms
1659         overlayPanel->getFusionSequenceProperty(-1, false, 0, false);
1660
1661         //unlink and untie the slicer managers
1662         RemoveLink(mSlicerManagers[index]->GetId().c_str(), mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetId().c_str());
1663         mSlicerManagers[index]->SetFusionSequenceInvolvmentCode(-1);
1664         mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->SetFusionSequenceInvolvmentCode(-1);
1665         for (unsigned i=0 ; i<4 ; i++) {
1666             mSlicerManagers[index]->GetSlicer(i)->SetFusionSequenceCode(-1);
1667             mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetSlicer(i)->SetFusionSequenceCode(-1);
1668         }
1669         */
1670       }
1671
1672       linkPanel->removeImage(index);
1673       mSlicerManagers[index]->RemoveActors();
1674
1675       //remove the slicer manager
1676       delete mSlicerManagers[index];
1677       mSlicerManagers.erase(Manageriter);
1678
1679       //
1680       InitDisplay();
1681     }
1682   }
1683   ImageInfoChanged();
1684 }
1685 //------------------------------------------------------------------------------
1686
1687 //------------------------------------------------------------------------------
1688 void vvMainWindow::ReloadImage(QTreeWidgetItem* item, int column)
1689 {
1690   // int index = GetSlicerIndexFromItem(item);
1691   //   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1692   //   if (item->data(1,Qt::UserRole).toString() == "vector")
1693   //     mSlicerManagers[index]->ReloadVF();
1694   //   else
1695   //     mSlicerManagers[index]->Reload();
1696
1697   //   QApplication::restoreOverrideCursor();
1698   int index = GetSlicerIndexFromItem(item);
1699   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1700   QString role=item->data(1,Qt::UserRole).toString();
1701   if ( role == "vector") {
1702     mSlicerManagers[index]->ReloadVF();
1703   }
1704   else if (role == "overlay") {
1705     mSlicerManagers[index]->ReloadOverlay();
1706   }
1707   else if (role == "fusion") {
1708     mSlicerManagers[index]->ReloadFusion();
1709   }
1710   else if (role == "fusionSequence") {
1711     //both versions of the secondary sequence must be updated.
1712     mSlicerManagers[index]->ReloadFusionSequence();
1713     mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->Reload(); 
1714   }
1715   else {
1716     mSlicerManagers[index]->Reload();
1717     //if we update the secondary sequence, then the overlay of the main sequence should also be updated
1718     if (mSlicerManagers[index]->IsSecondarySequenceOfFusionSequence()) mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->ReloadFusionSequence(); 
1719   }
1720   // Update view and info
1721   ImageInfoChanged();
1722   mSlicerManagers[index]->Render();
1723   QApplication::restoreOverrideCursor();
1724 }
1725 //------------------------------------------------------------------------------
1726
1727 //------------------------------------------------------------------------------
1728 void vvMainWindow::MousePositionChanged(int visibility,double x, double y, double z, double X, double Y, double Z , double value)
1729 {
1730   infoPanel->setCurrentInfo(visibility,x,y,z,X,Y,Z,value);
1731 }
1732 //------------------------------------------------------------------------------
1733
1734 //------------------------------------------------------------------------------
1735 void vvMainWindow::VectorChanged(int visibility,double x, double y, double z, double value)
1736 {
1737   overlayPanel->getCurrentVectorInfo(visibility,x,y,z,value);
1738 }
1739 //------------------------------------------------------------------------------
1740
1741 //------------------------------------------------------------------------------
1742 void vvMainWindow::OverlayChanged(int visibility, double valueOver, double valueRef)
1743 {
1744   overlayPanel->getCurrentOverlayInfo(visibility,valueOver, valueRef);
1745 }
1746 //------------------------------------------------------------------------------
1747
1748 //------------------------------------------------------------------------------
1749 void vvMainWindow::FusionChanged(int visibility, double value)
1750 {
1751   overlayPanel->getCurrentFusionInfo(visibility,value);
1752 }
1753 //------------------------------------------------------------------------------
1754
1755 //------------------------------------------------------------------------------
1756 //called when AddOverlayImage, AddFusionSequence
1757 //or when UpdateWindowLevel() is called ; when slicerManager emits WindowLevelChanged
1758 //when ImageInfoChanged() is called
1759 void vvMainWindow::WindowLevelChanged()
1760 {
1761   // Base image
1762   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1763   if(index==-1) return;
1764   windowSpinBox->setValue(mSlicerManagers[index]->GetColorWindow());
1765   levelSpinBox->setValue(mSlicerManagers[index]->GetColorLevel());
1766   colorMapComboBox->setCurrentIndex(mSlicerManagers[index]->GetColorMap());
1767   presetComboBox->setCurrentIndex(mSlicerManagers[index]->GetPreset());
1768
1769   // Overlay image
1770   if (mSlicerManagers[index]->GetSlicer(0)->GetOverlay())
1771     overlayPanel->getOverlayProperty(mSlicerManagers[index]->GetOverlayColor(),
1772     mSlicerManagers[index]->GetLinkOverlayWindowLevel(),
1773     mSlicerManagers[index]->GetOverlayColorWindow(),
1774     mSlicerManagers[index]->GetOverlayColorLevel());
1775   else
1776     overlayPanel->getOverlayProperty(-1,0,0.,0.);
1777
1778   // Fusion & SequenceFusion image
1779   if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) {
1780     overlayPanel->getFusionProperty(mSlicerManagers[index]->GetFusionOpacity(),
1781       mSlicerManagers[index]->GetFusionThresholdOpacity(),
1782       mSlicerManagers[index]->GetFusionColorMap(),
1783       mSlicerManagers[index]->GetFusionWindow(),
1784       mSlicerManagers[index]->GetFusionLevel());
1785     if (mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) {
1786       overlayPanel->getFusionSequenceProperty(mSlicerManagers[index]->GetFusionSequenceFrameIndex(),
1787         mSlicerManagers[index]->GetFusionSequenceSpatialSyncFlag(), 
1788         mSlicerManagers[index]->GetFusionSequenceNbFrames(),
1789         mSlicerManagers[index]->GetFusionSequenceTemporalSyncFlag());
1790     }
1791   }
1792   else if ( mSlicerManagers[index]->IsSecondarySequenceOfFusionSequence() ) {
1793     //if the image is involved in a fusion sequence, preserve the overlay panel!
1794     int ind = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager();
1795     overlayPanel->getFusionProperty(mSlicerManagers[ind]->GetFusionOpacity(),
1796       mSlicerManagers[ind]->GetFusionThresholdOpacity(),
1797       mSlicerManagers[ind]->GetFusionColorMap(),
1798       mSlicerManagers[ind]->GetFusionWindow(),
1799       mSlicerManagers[ind]->GetFusionLevel());
1800     overlayPanel->getFusionSequenceProperty(mSlicerManagers[ind]->GetFusionSequenceFrameIndex(),
1801       mSlicerManagers[ind]->GetFusionSequenceSpatialSyncFlag(), 
1802       mSlicerManagers[ind]->GetFusionSequenceNbFrames(),
1803       mSlicerManagers[ind]->GetFusionSequenceTemporalSyncFlag());
1804   }
1805   else
1806   {
1807     overlayPanel->getFusionProperty(-1, -1, -1, -1, -1);
1808     overlayPanel->getFusionSequenceProperty(-1, false, 0, false);
1809   }
1810 }
1811 //------------------------------------------------------------------------------
1812
1813 //------------------------------------------------------------------------------
1814 void vvMainWindow::WindowLevelEdited()
1815 {
1816   presetComboBox->setCurrentIndex(WL_USER);
1817   UpdateWindowLevel();
1818 }
1819 //------------------------------------------------------------------------------
1820
1821 //------------------------------------------------------------------------------
1822 void vvMainWindow::SetWindowLevel(double w, double l)
1823 {
1824   windowSpinBox->setValue(w);
1825   levelSpinBox->setValue(l);
1826   presetComboBox->setCurrentIndex(WL_USER);
1827   colorMapComboBox->setCurrentIndex(0);
1828   UpdateWindowLevel();
1829 }
1830 //------------------------------------------------------------------------------
1831
1832 //------------------------------------------------------------------------------
1833 void vvMainWindow::UpdateWindowLevel()
1834 {
1835   if (DataTree->selectedItems().size()) {
1836     if (presetComboBox->currentIndex() == WL_VENTILATION) //For ventilation
1837       colorMapComboBox->setCurrentIndex(5);
1838     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1839     mSlicerManagers[index]->SetColorWindow(windowSpinBox->value());
1840     mSlicerManagers[index]->SetColorLevel(levelSpinBox->value());
1841     mSlicerManagers[index]->SetPreset(presetComboBox->currentIndex());
1842     mSlicerManagers[index]->Render();
1843     WindowLevelChanged();
1844   }
1845 }
1846 //------------------------------------------------------------------------------
1847
1848 //------------------------------------------------------------------------------
1849 void vvMainWindow::UpdateSlicingPreset()
1850 {
1851   if (DataTree->selectedItems().size()) {
1852     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1853     mSlicerManagers[index]->SetSlicingPreset(vvSlicerManager::SlicingPresetType(slicingPresetComboBox->currentIndex()));
1854   }
1855 }
1856 //------------------------------------------------------------------------------
1857
1858 //------------------------------------------------------------------------------
1859 void vvMainWindow::UpdateColorMap()
1860 {
1861   if (DataTree->selectedItems().size()) {
1862     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1863     mSlicerManagers[index]->SetColorMap(colorMapComboBox->currentIndex());
1864     mSlicerManagers[index]->Render();
1865   }
1866 }
1867 //------------------------------------------------------------------------------
1868 void vvMainWindow::SwitchWindowLevel()
1869 {
1870   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1871   int window = mSlicerManagers[index]->GetColorWindow();
1872   presetComboBox->setCurrentIndex(WL_USER);
1873   windowSpinBox->setValue(-window);
1874   UpdateWindowLevel();
1875 }
1876 //------------------------------------------------------------------------------
1877
1878 //------------------------------------------------------------------------------
1879 void vvMainWindow::ApplyWindowLevelToAllImages()
1880 {
1881   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1882   if(index==-1) return;
1883   double window = mSlicerManagers[index]->GetColorWindow();
1884   double level = mSlicerManagers[index]->GetColorLevel();
1885
1886   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
1887     if (mSlicerManagers[i] == NULL)
1888       continue;
1889     mSlicerManagers[i]->SetColorWindow(window);
1890     mSlicerManagers[i]->SetColorLevel(level);
1891     mSlicerManagers[i]->SetPreset(WL_USER);
1892     mSlicerManagers[i]->Render();
1893   }
1894 }
1895 //------------------------------------------------------------------------------
1896
1897 //------------------------------------------------------------------------------
1898 void vvMainWindow::ApplyWindowToSetOfImages(double window, unsigned int indexMin, unsigned int indexMax)
1899 {
1900   for (unsigned int i = indexMin; i <= indexMax && i < mSlicerManagers.size(); i++) {
1901     if (mSlicerManagers[i] == NULL)
1902       continue;
1903     mSlicerManagers[i]->SetColorWindow(window);
1904     mSlicerManagers[i]->SetPreset(WL_USER);
1905     mSlicerManagers[i]->Render();
1906   }
1907 }
1908 //------------------------------------------------------------------------------
1909
1910 //------------------------------------------------------------------------------
1911 void vvMainWindow::ApplyLevelToSetOfImages(double level, unsigned int indexMin, unsigned int indexMax)
1912 {
1913   for (unsigned int i = indexMin; i <= indexMax && i < mSlicerManagers.size(); i++) {
1914     if (mSlicerManagers[i] == NULL)
1915       continue;
1916     mSlicerManagers[i]->SetColorLevel(level);
1917     mSlicerManagers[i]->SetPreset(WL_USER);
1918     mSlicerManagers[i]->Render();
1919   }
1920 }
1921 //------------------------------------------------------------------------------
1922
1923 //------------------------------------------------------------------------------
1924 void vvMainWindow::UpdateLinkManager(std::string id, int slicer, double x, double y, double z, int temps)
1925 {
1926   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
1927     if (mSlicerManagers[i]->GetId() == id) {
1928       mSlicerManagers[i]->GetSlicer(slicer)->SetCurrentPosition(x,y,z,temps);
1929       mSlicerManagers[i]->UpdateViews(0,slicer);
1930       break;
1931     }
1932   }
1933 }
1934 //------------------------------------------------------------------------------
1935
1936 //------------------------------------------------------------------------------
1937 void vvMainWindow::UpdateLinkedNavigation(std::string id, vvSlicerManager * sm, vvSlicer* refSlicer)
1938 {
1939   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
1940     if (id == mSlicerManagers[i]->GetId()) {
1941       mSlicerManagers[i]->UpdateLinkedNavigation(refSlicer);
1942     }
1943   }
1944 }
1945 //------------------------------------------------------------------------------
1946
1947 //------------------------------------------------------------------------------
1948 void vvMainWindow::ShowContextMenu(QPoint point)
1949 {
1950   if (!DataTree->selectedItems().size()) {
1951     contextActions[1]->setEnabled(0);
1952     contextActions[2]->setEnabled(0);
1953     contextActions[3]->setEnabled(0);
1954     contextActions[4]->setEnabled(0);
1955     contextActions[5]->setEnabled(0);
1956     contextActions[6]->setEnabled(0);
1957   } else {
1958     int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1959     contextActions[1]->setEnabled(1);
1960     contextActions[2]->setEnabled(
1961       DataTree->itemWidget(DataTree->selectedItems()[0],
1962       COLUMN_RELOAD_IMAGE)->isEnabled());
1963     contextActions[3]->setEnabled(1);
1964     contextActions[5]->setEnabled(1);
1965     contextActions[6]->setEnabled(1);
1966
1967     if (mSlicerManagers[index]->GetDimension() < 3)
1968       contextActions[4]->setEnabled(0);
1969     else
1970       contextActions[4]->setEnabled(1);
1971   }
1972   contextMenu.exec(QCursor::pos());
1973 }
1974 //------------------------------------------------------------------------------
1975
1976 //------------------------------------------------------------------------------
1977 void vvMainWindow::CloseImage()
1978 {
1979   CloseImage(DataTree->selectedItems()[0],0);
1980 }
1981 //------------------------------------------------------------------------------
1982
1983 //------------------------------------------------------------------------------
1984 void vvMainWindow::ReloadImage()
1985 {
1986   ReloadImage(DataTree->selectedItems()[0],0);
1987 }
1988 //------------------------------------------------------------------------------
1989
1990 //------------------------------------------------------------------------------
1991 void vvMainWindow::SelectOverlayImage()
1992 {
1993   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
1994
1995   //check if one overlay image is added
1996   for (int child = 0; child < DataTree->topLevelItem(index)->childCount(); child++)
1997     if (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "overlay") {
1998       QString error = "Cannot add more than one compared image\n";
1999       error += "Please remove first ";
2000       error += DataTree->topLevelItem(index)->child(child)->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
2001       QMessageBox::information(this,tr("Problem adding compared image !"),error);
2002       return;
2003     }
2004
2005     QString Extensions = EXTENSIONS;
2006     Extensions += ";;All Files (*)";
2007     QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Overlay image"),mInputPathName,Extensions);
2008     if (files.isEmpty())
2009       return;
2010
2011     std::vector<std::string> vecFileNames;
2012     for (int i = 0; i < files.size(); i++) {
2013       vecFileNames.push_back(files[i].toStdString());
2014     }
2015     AddOverlayImage(index,vecFileNames,vvImageReader::IMAGE);
2016 }
2017 //------------------------------------------------------------------------------
2018
2019 //------------------------------------------------------------------------------
2020 void vvMainWindow::AddOverlayImage(int index, std::vector<std::string> fileNames, vvImageReader::LoadedImageType type)
2021 {
2022   QString file(fileNames[0].c_str());
2023   if (QFile::exists(file))
2024   {
2025     mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
2026     itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
2027       file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
2028     reader->SetFileName(fileNames[0].c_str());
2029     reader->ReadImageInformation();
2030     std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
2031     int dimension = reader->GetNumberOfDimensions();
2032     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2033     vvProgressDialog progress("Opening " + file.toStdString());
2034     qApp->processEvents();
2035
2036     std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
2037     if (mSlicerManagers[index]->SetOverlay(fileNames,dimension, component,type)) {
2038       //create an item in the tree with good settings
2039       QTreeWidgetItem *item = new QTreeWidgetItem();
2040       item->setData(0,Qt::UserRole,file.toStdString().c_str());
2041       item->setData(1,Qt::UserRole,tr("overlay"));
2042       QFileInfo fileinfo(file); //Do not show the path
2043       item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
2044       item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("overlay").c_str());
2045       qApp->processEvents();
2046
2047       for (int j = 1; j <= 4; j++) {
2048         item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
2049       }
2050
2051       //Create the buttons for reload and close
2052       qApp->processEvents();
2053       QTreePushButton* cButton = new QTreePushButton;
2054       cButton->setItem(item);
2055       cButton->setColumn(COLUMN_CLOSE_IMAGE);
2056       cButton->setToolTip(tr("close image"));
2057       cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
2058       connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2059         this,SLOT(CloseImage(QTreeWidgetItem*, int)));
2060
2061       QTreePushButton* rButton = new QTreePushButton;
2062       rButton->setItem(item);
2063       rButton->setColumn(COLUMN_RELOAD_IMAGE);
2064       rButton->setToolTip(tr("reload image"));
2065       rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
2066       connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2067         this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
2068
2069       DataTree->topLevelItem(index)->setExpanded(1);
2070       DataTree->topLevelItem(index)->addChild(item);
2071       DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
2072       DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
2073
2074       //set the id of the image
2075       QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
2076       item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
2077       UpdateTree();
2078       qApp->processEvents();
2079       ImageInfoChanged();
2080       QApplication::restoreOverrideCursor();
2081
2082       // Update the display to update, e.g., the sliders
2083       for(int i=0; i<4; i++)
2084         DisplaySliders(index, i);
2085     } else {
2086       QApplication::restoreOverrideCursor();
2087       QString error = "Cannot import the new image.\n";
2088       error += mSlicerManagers[index]->GetLastError().c_str();
2089       QMessageBox::information(this,tr("Problem reading image !"),error);
2090     }
2091     WindowLevelChanged();
2092   }
2093   else
2094     QMessageBox::information(this,tr("Problem reading Overlay !"),"File doesn't exist!");
2095 }
2096 //------------------------------------------------------------------------------
2097
2098
2099 //------------------------------------------------------------------------------
2100 void vvMainWindow::AddROI(int index, QString file)
2101 {
2102   /*
2103   // Get slice manager
2104
2105   // Load image
2106
2107   vvImageReader * mReader = new vvImageReader;
2108   mReader->SetInputFilename(filename.toStdString());
2109   mReader->Update(IMAGE);
2110   if (mReader->GetLastError().size() != 0) {
2111   std::cerr << "Error while reading " << filename.toStdString() << std::endl;
2112   QString error = "Cannot open file \n";
2113   error += mReader->GetLastError().c_str();
2114   QMessageBox::information(this,tr("Reading problem"),error);
2115   delete mReader;
2116   return;
2117   }
2118   vvImage::Pointer roi = mReader->GetOutput();
2119
2120   // Create roi in new tool
2121   vvToolStructureSetManager::AddImage(mCurrentSlicerManager, roi);
2122   */
2123 }
2124 //------------------------------------------------------------------------------
2125
2126 //------------------------------------------------------------------------------
2127 void vvMainWindow::SelectFusionImage()
2128 {
2129   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2130
2131   //check if one fusion image is added
2132   for (int child = 0; child < DataTree->topLevelItem(index)->childCount(); child++)
2133     if ( (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusion") ||
2134       (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusionSequence") ) {
2135         QString error = "Cannot add more than one fusion image\n";
2136         error += "Please remove first ";
2137         error += DataTree->topLevelItem(index)->child(child)->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
2138         QMessageBox::information(this,tr("Problem adding fusion image !"),error);
2139         return;
2140     }
2141
2142     QString Extensions = EXTENSIONS;
2143     Extensions += ";;All Files (*)";
2144     QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Fusion image"),mInputPathName,Extensions);
2145     if (files.isEmpty())
2146       return;
2147
2148     std::vector<std::string> vecFileNames;
2149     for (int i = 0; i < files.size(); i++) {
2150       vecFileNames.push_back(files[i].toStdString());
2151     }
2152     AddFusionImage(index,vecFileNames,vvImageReader::IMAGE);
2153 }
2154 //------------------------------------------------------------------------------
2155
2156 //------------------------------------------------------------------------------
2157 void vvMainWindow::ResetTransformationToIdentity()
2158 {
2159   std::string actorType = DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString().toStdString();
2160   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2161   mSlicerManagers[index]->ResetTransformationToIdentity(actorType);
2162   ImageInfoChanged();
2163 }
2164 //------------------------------------------------------------------------------
2165
2166 //------------------------------------------------------------------------------
2167 void vvMainWindow::AddFusionImage(int index, std::vector<std::string> fileNames, vvImageReader::LoadedImageType type)
2168 {
2169   QString file(fileNames[0].c_str());
2170   if (QFile::exists(file))
2171   {
2172     mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
2173     itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
2174       file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
2175     reader->SetFileName(fileNames[0].c_str());
2176     reader->ReadImageInformation();
2177     std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
2178     int dimension = reader->GetNumberOfDimensions();
2179     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2180     vvProgressDialog progress("Opening fusion");
2181     qApp->processEvents();
2182
2183     std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
2184     if (mSlicerManagers[index]->SetFusion(fileNames,dimension, component,type)) {
2185       //create an item in the tree with good settings
2186       QTreeWidgetItem *item = new QTreeWidgetItem();
2187       item->setData(0,Qt::UserRole,file.toStdString().c_str());
2188       item->setData(1,Qt::UserRole,tr("fusion"));
2189       QFileInfo fileinfo(file); //Do not show the path
2190           item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
2191           item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("fusion").c_str());
2192           qApp->processEvents();
2193
2194       for (int j = 1; j <= 4; j++) {
2195         item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
2196       }
2197
2198       //Create the buttons for reload and close
2199       qApp->processEvents();
2200       QTreePushButton* cButton = new QTreePushButton;
2201       cButton->setItem(item);
2202       cButton->setColumn(COLUMN_CLOSE_IMAGE);
2203       cButton->setToolTip(tr("close image"));
2204       cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
2205       connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2206         this,SLOT(CloseImage(QTreeWidgetItem*, int)));
2207
2208       QTreePushButton* rButton = new QTreePushButton;
2209       rButton->setItem(item);
2210       rButton->setColumn(COLUMN_RELOAD_IMAGE);
2211       rButton->setToolTip(tr("reload image"));
2212       rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
2213       connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2214         this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
2215
2216       DataTree->topLevelItem(index)->setExpanded(1);
2217       DataTree->topLevelItem(index)->addChild(item);
2218       DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
2219       DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
2220
2221       //set the id of the image
2222       QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
2223       item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
2224       UpdateTree();
2225       qApp->processEvents();
2226       ImageInfoChanged();
2227       QApplication::restoreOverrideCursor();
2228
2229       // Update the display to update, e.g., the sliders
2230       for(int i=0; i<4; i++)
2231         DisplaySliders(index, i);
2232     } else {
2233       QApplication::restoreOverrideCursor();
2234       QString error = "Cannot import the new image.\n";
2235       error += mSlicerManagers[index]->GetLastError().c_str();
2236       QMessageBox::information(this,tr("Problem reading image !"),error);
2237     }
2238     WindowLevelChanged();
2239   }
2240   else
2241     QMessageBox::information(this,tr("Problem reading Fusion !"),"File doesn't exist!");
2242 }
2243 //------------------------------------------------------------------------------
2244 //------------------------------------------------------------------------------
2245 void vvMainWindow::AddLandmarks(int index, std::vector<std::string> files)
2246 {
2247     if (!landmarksPanel->LoadFromFile(files))
2248       QMessageBox::information(this,tr("Problem reading Landmarks !"),"File doesn't exist!");
2249     
2250     landmarksPanel->SetCurrentPath(mInputPathName.toStdString());
2251     landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str());
2252 }
2253
2254 //------------------------------------------------------------------------------
2255 void vvMainWindow::OpenField()
2256 {
2257   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2258   //check if a vector field has already been added
2259   for (int child = 0; child < DataTree->topLevelItem(index)->childCount(); child++)
2260     if (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "vector") {
2261       QString error = "Cannot add more than one vector field\n";
2262       error += "Please remove first ";
2263       error += DataTree->topLevelItem(index)->child(child)->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
2264       QMessageBox::information(this,tr("Problem adding vector field!"),error);
2265       return;
2266     }
2267
2268     QString Extensions = "Images ( *.mhd)";
2269     Extensions += ";;Images ( *.mha)";
2270     Extensions += ";;VF Images ( *.vf)";
2271     Extensions += ";;nii Images ( *.nii)";
2272     Extensions += ";;nrrd Images ( *.nrrd)";
2273     Extensions += ";;nhdr Images ( *.nhdr)";
2274     Extensions += ";;All Files (*)";
2275     QString file = QFileDialog::getOpenFileName(this,tr("Load deformation field"),mInputPathName,Extensions);
2276     if (!file.isEmpty())
2277       AddField(file,index);
2278 }
2279 //------------------------------------------------------------------------------
2280
2281
2282 //------------------------------------------------------------------------------
2283 void vvMainWindow::AddFieldEntry(QString filename,int index,bool from_disk)
2284 {
2285   //create an item in the tree with good settings
2286   QTreeWidgetItem *item = new QTreeWidgetItem();
2287   item->setData(0,Qt::UserRole,filename.toStdString().c_str());
2288   item->setData(1,Qt::UserRole,tr("vector"));
2289   QFileInfo fileinfo(filename); //Do not show the path
2290   item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
2291   item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("vector").c_str());
2292   qApp->processEvents();
2293
2294   for (int j = 1; j <= 4; j++) {
2295     item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
2296   }
2297
2298   //Create the buttons for reload and close
2299   qApp->processEvents();
2300   QTreePushButton* cButton = new QTreePushButton;
2301   cButton->setItem(item);
2302   cButton->setColumn(COLUMN_CLOSE_IMAGE);
2303   cButton->setToolTip(tr("close vector field"));
2304   cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
2305   connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2306     this,SLOT(CloseImage(QTreeWidgetItem*, int)));
2307
2308   QTreePushButton* rButton = new QTreePushButton;
2309   rButton->setItem(item);
2310   rButton->setColumn(COLUMN_RELOAD_IMAGE);
2311   rButton->setToolTip(tr("reload vector field"));
2312   rButton->setEnabled(from_disk);
2313   rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
2314   connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2315     this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
2316
2317   DataTree->topLevelItem(index)->setExpanded(1);
2318   DataTree->topLevelItem(index)->addChild(item);
2319   DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
2320   DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
2321
2322   //set the id of the image
2323   QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
2324   item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
2325   UpdateTree();
2326   qApp->processEvents();
2327   ImageInfoChanged();
2328   QApplication::restoreOverrideCursor();
2329 }
2330 //------------------------------------------------------------------------------
2331
2332
2333 //------------------------------------------------------------------------------
2334 void vvMainWindow::AddField(vvImage::Pointer vf,QString file,int index)
2335 {
2336   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2337   vvSlicerManager* imageManager = mSlicerManagers[index];
2338   if (imageManager->SetVF(vf,file.toStdString())) {
2339     AddFieldEntry(file,index,false);
2340   } else {
2341     QString error = "Cannot import the vector field for this image.\n";
2342     error += imageManager->GetLastError().c_str();
2343     QMessageBox::information(this,tr("Problem reading VF !"),error);
2344   }
2345   QApplication::restoreOverrideCursor();
2346 }
2347 //------------------------------------------------------------------------------
2348
2349
2350 //------------------------------------------------------------------------------
2351 void vvMainWindow::AddField(QString file,int index)
2352 {
2353   if (QFile::exists(file)) {
2354     mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
2355
2356     //init the progress events
2357     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2358     vvProgressDialog progress("Opening " + file.toStdString());
2359     qApp->processEvents();
2360
2361     //read the vector and put it in the current mSlicerManager
2362     vvSlicerManager* imageManager = mSlicerManagers[index];
2363     qApp->processEvents();
2364
2365     std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
2366     if (imageManager->SetVF(file.toStdString())) {
2367       imageManager->Render();
2368       AddFieldEntry(file,index,true);
2369     } else {
2370       QApplication::restoreOverrideCursor();
2371       QString error = "Cannot import the vector field for this image.\n";
2372       error += imageManager->GetLastError().c_str();
2373       QMessageBox::information(this,tr("Problem reading VF !"),error);
2374     }
2375   } else
2376     QMessageBox::information(this,tr("Problem reading VF !"),"File doesn't exist!");
2377
2378 }
2379 //------------------------------------------------------------------------------
2380
2381
2382 //------------------------------------------------------------------------------
2383 void vvMainWindow::SetVFProperty(int subsampling, int scale, int log, int width, double r, double g, double b)
2384 {
2385   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2386   if (mSlicerManagers[index]->GetSlicer(0)->GetVF()) {
2387     for (int i = 0; i < 4; i++) {
2388       mSlicerManagers[index]->GetSlicer(i)->SetVFSubSampling(subsampling);
2389       mSlicerManagers[index]->GetSlicer(i)->SetVFScale(scale);
2390       mSlicerManagers[index]->GetSlicer(i)->SetVFWidth(width);
2391       mSlicerManagers[index]->GetSlicer(i)->SetVFColor(r,g,b);
2392       if (log > 0)
2393         mSlicerManagers[index]->GetSlicer(i)->SetVFLog(1);
2394       else
2395         mSlicerManagers[index]->GetSlicer(i)->SetVFLog(0);
2396     }
2397   }
2398 }
2399 //------------------------------------------------------------------------------
2400
2401
2402 //------------------------------------------------------------------------------
2403 void vvMainWindow::SetOverlayProperty(int color, int linked, double window, double level)
2404 {
2405   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2406   if (mSlicerManagers[index]->GetSlicer(0)->GetOverlay()) {
2407     mSlicerManagers[index]->SetOverlayColor(color);
2408     mSlicerManagers[index]->SetColorMap(0);
2409     mSlicerManagers[index]->SetLinkOverlayWindowLevel(linked);
2410     mSlicerManagers[index]->SetOverlayColorWindow(window);
2411     mSlicerManagers[index]->SetOverlayColorLevel(level);
2412     mSlicerManagers[index]->Render();
2413   }
2414 }
2415 //------------------------------------------------------------------------------
2416
2417 //------------------------------------------------------------------------------
2418 void vvMainWindow::SetFusionProperty(int opacity, int thresOpacity, int colormap,double window, double level, bool showLegend)
2419 {
2420   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2421   if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) {
2422     mSlicerManagers[index]->SetFusionColorMap(colormap);
2423     mSlicerManagers[index]->SetFusionOpacity(opacity);
2424     mSlicerManagers[index]->SetFusionThresholdOpacity(thresOpacity);
2425     mSlicerManagers[index]->SetFusionWindow(window);
2426     mSlicerManagers[index]->SetFusionLevel(level);
2427     mSlicerManagers[index]->SetFusionShowLegend(showLegend);
2428     mSlicerManagers[index]->SetColorMap(0);
2429     mSlicerManagers[index]->Render();
2430   }
2431 }
2432 //------------------------------------------------------------------------------
2433
2434
2435 //------------------------------------------------------------------------------
2436 void vvMainWindow::SelectFusionSequence()
2437 {
2438   //get the index of the slicer manager of the main sequence (CT)
2439   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2440   //check if one overlay image is already associated
2441   for (int child = 0; child < DataTree->topLevelItem(index)->childCount(); child++)
2442     if ( (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusion") ||
2443       (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusionSequence") ) {
2444         QString error = "Cannot add more than one compared image\n";
2445         error += "Please remove first ";
2446         error += DataTree->topLevelItem(index)->child(child)->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
2447         QMessageBox::information(this,tr("Problem adding compared image !"),error);
2448         return;
2449     }
2450
2451     QString Extensions = EXTENSIONS;
2452     Extensions += ";;All Files (*)";
2453     QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Overlay image sequence"),mInputPathName,Extensions);
2454     if (files.isEmpty())
2455       return;
2456
2457     std::vector<std::string> vecFileNames;
2458     for (int i = 0; i < files.size(); i++) {
2459       vecFileNames.push_back(files[i].toStdString());
2460     }
2461
2462     //associate the secondary sequence (US) to the main one
2463     AddFusionSequence(index,vecFileNames,vvImageReader::MERGEDWITHTIME);
2464 }
2465 //------------------------------------------------------------------------------
2466
2467
2468 //------------------------------------------------------------------------------
2469 void vvMainWindow::SelectFusionSequenceCorrespondances() {
2470
2471   //make sure the index is right?
2472   //in the end, I should attach the temporal data to the right sequence!
2473   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2474   //in case the other sequence got selected, make sure we select the primary sequence
2475   if ( (!mSlicerManagers[index]->GetSlicer(0)->GetFusion()) && mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()>=0 ) {
2476     index = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager();
2477   }
2478
2479   //open a dialog box to find a file
2480   //QString Extensions = EXTENSIONS;
2481   QString Extensions = ";;All Files (*)";
2482   QString fileName = QFileDialog::getOpenFileName(this,tr("Load respiratory signal for fused sequence"),mInputPathName,Extensions);
2483   if (fileName.isNull())
2484     return;
2485
2486   //read it as a vector of values
2487   vnl_vector<double> tmpVect;
2488
2489   std::ifstream file;
2490   file.open(fileName.toStdString().c_str());
2491   tmpVect.read_ascii(file);
2492   file.close();
2493
2494   //if compatible with the fused image sequence (number of entries = nb of entries in main sequence + nb of entries in joint sequence), enable the temporalSync
2495   bool signalOK = true;
2496   unsigned nbFrameMain = mSlicerManagers[index]->GetImage()->GetTransform().size();
2497   unsigned nbFrameSecondary = mSlicerManagers[index]->GetFusionSequenceNbFrames();
2498 std::cout<<"nbFrameMain = "<<nbFrameMain<<", nbFrameSecondary= "<<nbFrameSecondary<<", signal size: "<<tmpVect.size()<<std::endl;
2499   std::vector<unsigned> temporalCorrespondances;
2500   if ( tmpVect.size() == nbFrameMain + nbFrameSecondary ) {
2501     for (unsigned i=0 ; i<tmpVect.size() ; i++) {
2502       if (i<nbFrameMain) { //first part of the file: i -> index in secondary seq.
2503         if ( tmpVect(i)<nbFrameSecondary ) temporalCorrespondances.push_back(tmpVect(i));
2504         else { signalOK=false; break; } //pointing outside the secondary sequence...
2505       }
2506       else { //first part of the file -> index in secondary seq.
2507         if ( tmpVect(i)<nbFrameMain ) temporalCorrespondances.push_back(tmpVect(i));
2508         else { signalOK=false; break; } //pointing outside the secondary sequence...      
2509       }      
2510     }
2511   }
2512   else {signalOK=false;}
2513   if (!signalOK) {//else, send a message to signal the failure...
2514     QString error = "The provided temporal correspondances is invalid - check tooltip.\n";
2515     error += "Ignoring file: " + fileName;
2516     QMessageBox::information(this,tr("Problem adding temporal correspondances!"),error);
2517     return;
2518   }
2519   else {
2520     //for convenience, associate this sequence to both the current slicer manager, and to the linked one
2521     mSlicerManagers[index]->SetFusionSequenceCorrespondances(temporalCorrespondances);
2522     mSlicerManagers[ mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager() ]->SetFusionSequenceCorrespondances(temporalCorrespondances);
2523     overlayPanel->enableFusionSequenceTemporalSync();
2524   }
2525
2526 }
2527 //------------------------------------------------------------------------------
2528
2529
2530 //------------------------------------------------------------------------------
2531 //when this function is called index is the slicer manager index corresponding to the main sequence (CT)
2532 //the files behind fileNames points to the data for the secondary sequence
2533 void vvMainWindow::AddFusionSequence(int index, std::vector<std::string> fileNames, vvImageReader::LoadedImageType type)
2534 {
2535   QString file(fileNames[0].c_str());
2536   if (QFile::exists(file))
2537   {
2538     mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
2539     itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
2540       file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
2541     std::sort (fileNames.begin(), fileNames.end());//make sure the files are sorted.
2542     reader->SetFileName(fileNames[0].c_str());
2543     reader->ReadImageInformation();
2544     std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
2545     int dimension = reader->GetNumberOfDimensions();
2546     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2547     vvProgressDialog progress("Opening " + file.toStdString());
2548     qApp->processEvents();
2549
2550     std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
2551
2552     if (mSlicerManagers[index]->SetFusionSequence(fileNames,dimension, component,type)) {
2553       //create an item in the tree with good settings
2554       QTreeWidgetItem *item = new QTreeWidgetItem();
2555       item->setData(0,Qt::UserRole,file.toStdString().c_str());
2556       item->setData(1,Qt::UserRole,tr("fusionSequence"));
2557
2558       QFileInfo fileinfo(file); //Do not show the path
2559       item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
2560       item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("fusionSequence").c_str());
2561       qApp->processEvents();
2562       for (int j = 1; j <= 4; j++) {
2563         item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
2564       }
2565
2566       //Create the buttons for reload and close
2567       qApp->processEvents();
2568       QTreePushButton* cButton = new QTreePushButton;
2569       cButton->setItem(item);
2570       cButton->setColumn(COLUMN_CLOSE_IMAGE);
2571       cButton->setToolTip(tr("close image"));
2572       cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
2573       connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2574         this,SLOT(CloseImage(QTreeWidgetItem*, int)));
2575
2576       QTreePushButton* rButton = new QTreePushButton;
2577       rButton->setItem(item);
2578       rButton->setColumn(COLUMN_RELOAD_IMAGE);
2579       rButton->setToolTip(tr("reload image"));
2580       rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
2581       connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
2582         this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
2583
2584       DataTree->topLevelItem(index)->setExpanded(1);
2585       DataTree->topLevelItem(index)->addChild(item);
2586       DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
2587       DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
2588
2589       //store the original transform matrix
2590       int indexParent = GetSlicerIndexFromItem( DataTree->topLevelItem(index) );
2591       mSlicerManagers[indexParent]->SetFusionSequenceMainTransformMatrix( mSlicerManagers[indexParent]->GetSlicer(0)->GetImage()->GetTransform()[0]->GetMatrix() );
2592
2593       //set the id of the image
2594       QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
2595       item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
2596       UpdateTree();
2597       qApp->processEvents();
2598
2599       //ImageInfoChanged();
2600
2601       QApplication::restoreOverrideCursor();
2602       // Update the display to update, e.g., the sliders
2603       for(int i=0; i<4; i++)
2604         DisplaySliders(index, i);
2605
2606
2607       //This loads the secondary sequence (US) as an independent sequence
2608       LoadImages(fileNames, type);
2609       //reset the transforms to identity
2610       //FIX -- and set the thickness of the US slices to a large value (necessary for visualization purposes...)
2611       double sp_x, sp_y, sp_z;
2612       mSlicerManagers[indexParent]->GetImage()->GetVTKImages()[0]->GetSpacing(sp_x, sp_y, sp_z);
2613       sp_z = std::max(sp_x, std::max(sp_y, sp_z)) + 0.5; //
2614       for (unsigned i=0 ; i<mSlicerManagers.back()->GetImage()->GetTransform().size() ; i++) {
2615         sp_x = mSlicerManagers.back()->GetImage()->GetVTKImages()[i]->GetSpacing()[0];
2616         sp_y = mSlicerManagers.back()->GetImage()->GetVTKImages()[i]->GetSpacing()[1];
2617         mSlicerManagers.back()->GetImage()->GetVTKImages()[i]->SetSpacing( sp_x, sp_y, sp_z);
2618         mSlicerManagers.back()->GetImage()->GetTransform()[i]->Identity();
2619         mSlicerManagers.back()->GetImage()->GetTransform()[i]->Update();
2620       }
2621
2622       //automatically link both images...
2623       AddLink(mSlicerManagers[indexParent]->GetId().c_str(), mSlicerManagers.back()->GetId().c_str(), false);
2624
2625       //tie the main and secondary sequences by raising flags and informing each another of their respective SlicerManager indices
2626       mSlicerManagers[indexParent]->SetFusionSequenceIndexOfLinkedManager(mSlicerManagers.size()-1);
2627       mSlicerManagers[indexParent]->SetFusionSequenceInvolvmentCode(0); //main sequence
2628       mSlicerManagers.back()->SetFusionSequenceIndexOfLinkedManager(indexParent);
2629       mSlicerManagers.back()->SetFusionSequenceInvolvmentCode(1); //secondary sequence
2630       for (unsigned i=0 ; i<4 ; i++) {
2631         mSlicerManagers.back()->GetSlicer(i)->SetFusionSequenceCode(1); //flag the slicers of the secondary sequence
2632       }
2633
2634     } else {
2635       QApplication::restoreOverrideCursor();
2636       QString error = "Cannot import the new image.\n";
2637       error += mSlicerManagers[index]->GetLastError().c_str();
2638       QMessageBox::information(this,tr("Problem reading image !"),error);
2639     }
2640     WindowLevelChanged();
2641     ImageInfoChanged(); //this internally calls WindowLevelChanged...
2642   }
2643   else {
2644     QMessageBox::information(this,tr("Problem reading fusion sequence !"),"File doesn't exist!");
2645     return;
2646   }
2647
2648 }
2649 //------------------------------------------------------------------------------
2650
2651
2652 //------------------------------------------------------------------------------
2653 //fusionSequenceFrameIndex and fusionSequenceNbFrames are relative to the secondary sequence (US)
2654 void vvMainWindow::SetFusionSequenceProperty(int fusionSequenceFrameIndex, bool spatialSyncFlag, unsigned int fusionSequenceNbFrames, bool temporalSyncFlag)
2655 {
2656   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2657
2658   if (!mSlicerManagers[index]->IsInvolvedInFusionSequence()) return; 
2659
2660   //check if the focus moved to the linked sequence, and in this case, select the master sequence instead
2661   if (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) {
2662     index = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager();
2663   }
2664   int secondaryIndex = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager();
2665   if (secondaryIndex==-1) return; //this should never happen
2666   if ( (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) || 
2667     (!mSlicerManagers[secondaryIndex]->IsSecondarySequenceOfFusionSequence()) ) 
2668   {return;} //this should never happen, raise an exception?
2669
2670   if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) {
2671
2672     //First, if the spatialSync button is unchecked, then reposition the parent sequence (CT) in its original coordinate frame
2673     if ( (!spatialSyncFlag) && (mSlicerManagers[index]->GetFusionSequenceSpatialSyncFlag()) ) {
2674       for ( unsigned i=0 ; i<mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform().size() ; i++ ) {
2675         mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->SetMatrix( mSlicerManagers[index]->GetFusionSequenceMainTransformMatrix() );
2676         mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->Update();
2677       }
2678
2679       for (int i=0; i<mSlicerManagers[index]->GetNumberOfSlicers(); i++) {
2680         mSlicerManagers[index]->GetSlicer(i)->ForceUpdateDisplayExtent();
2681         mSlicerManagers[index]->GetSlicer(i)->Render();
2682       }
2683     }
2684
2685     //then, update the property values in the slicer manager
2686     mSlicerManagers[index]->SetFusionSequenceLength(fusionSequenceNbFrames);
2687     mSlicerManagers[index]->SetFusionSequenceSpatialSyncFlag(spatialSyncFlag);
2688     mSlicerManagers[index]->SetFusionSequenceTemporalSyncFlag(temporalSyncFlag);
2689     mSlicerManagers[index]->SetFusionSequenceFrameIndex(fusionSequenceFrameIndex);
2690
2691     //select the right frame of the US sequence
2692     mSlicerManagers[index]->SetFusionSequenceTSlice(fusionSequenceFrameIndex); //here, I should only update the overlayed sequence
2693     mSlicerManagers[secondaryIndex]->SetTSlice(fusionSequenceFrameIndex, false); //this should update the secondary sequence (individual version)
2694
2695     //update the horizontal sliders of the main window
2696     overlayPanel->updateFusionSequenceSliderValueFromWindow(fusionSequenceFrameIndex, false);
2697
2698     if (spatialSyncFlag) { //reslice the CT
2699
2700       if (temporalSyncFlag) { //do the temporal synchronisation
2701         int mainSequenceFrameIndex=0;
2702         //estimate the TSlice to set to the CT
2703         unsigned nbFramesMain = mSlicerManagers[index]->GetImage()->GetTransform().size();
2704         mainSequenceFrameIndex = mSlicerManagers[index]->GetFusionSequenceCorrespondances()[ nbFramesMain + fusionSequenceFrameIndex];
2705         //and set it!
2706         mSlicerManagers[index]->SetTSlice(mainSequenceFrameIndex, false);
2707         //warning, there is a loopback, and modification of the TSlice in main sequence forces an update of the TSlice in secondary, etc... 
2708       }
2709
2710
2711       //Set the transform matrix of the parent sequence (typically CT / 4DCT)
2712       vtkSmartPointer<vtkMatrix4x4> tmpMat = vtkSmartPointer<vtkMatrix4x4>::New();
2713       vtkMatrix4x4::Invert( mSlicerManagers[index]->GetFusionSequenceInitialTransformMatrixAtFrame(fusionSequenceFrameIndex), tmpMat );
2714       for ( unsigned i=0 ; i<mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform().size() ; i++ ) {
2715         mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->SetMatrix( mSlicerManagers[index]->GetFusionSequenceMainTransformMatrix() );
2716         mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->PreMultiply();
2717         mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->Concatenate( tmpMat );
2718         mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetTransform()[i]->Update();
2719       }
2720
2721       for (int i=0; i<mSlicerManagers[index]->GetNumberOfSlicers(); i++) {
2722         mSlicerManagers[index]->GetSlicer(i)->ForceUpdateDisplayExtent();
2723         mSlicerManagers[index]->GetSlicer(i)->Render();
2724       }
2725
2726     }
2727
2728   }
2729 }
2730 //------------------------------------------------------------------------------
2731
2732
2733 //------------------------------------------------------------------------------
2734 void vvMainWindow::SaveAs()
2735 {
2736   if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "vector") {
2737     QMessageBox::warning(this,tr("Unsupported type"),tr("Sorry, saving a vector field is unsupported for the moment"));
2738     return;
2739   }
2740
2741   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
2742   int dimension = mSlicerManagers[index]->GetDimension();
2743   QStringList OutputListeFormat;
2744   OutputListeFormat.clear();
2745   if (dimension == 1) {
2746     OutputListeFormat.push_back(".mhd");
2747     OutputListeFormat.push_back(".mha");
2748   }
2749   if (dimension == 2) {
2750     OutputListeFormat.push_back(".bmp");
2751     OutputListeFormat.push_back(".png");
2752     OutputListeFormat.push_back(".jpeg");
2753     OutputListeFormat.push_back(".tif");
2754     OutputListeFormat.push_back(".mhd");
2755     OutputListeFormat.push_back(".mha");
2756     OutputListeFormat.push_back(".hdr");
2757     OutputListeFormat.push_back(".vox");
2758   } else if (dimension == 3) {
2759     OutputListeFormat.push_back(".mhd");
2760     OutputListeFormat.push_back(".mha");
2761     OutputListeFormat.push_back(".nii");
2762     OutputListeFormat.push_back(".nrrd");
2763     OutputListeFormat.push_back(".nhdr");
2764     OutputListeFormat.push_back(".hdr");
2765     OutputListeFormat.push_back(".vox");
2766   } else if (dimension == 4) {
2767     OutputListeFormat.push_back(".mhd");
2768     OutputListeFormat.push_back(".mha");
2769     OutputListeFormat.push_back(".nii");
2770     OutputListeFormat.push_back(".nrrd");
2771     OutputListeFormat.push_back(".nhdr");
2772   }
2773   QString Extensions = "AllFiles(*.*)";
2774   for (int i = 0; i < OutputListeFormat.count(); i++) {
2775     Extensions += ";;Images ( *";
2776     Extensions += OutputListeFormat[i];
2777     Extensions += ")";
2778   }
2779   QString fileName = QFileDialog::getSaveFileName(this,
2780     tr("Save As"),
2781     mSlicerManagers[index]->GetFileName().c_str(),
2782     Extensions);
2783   if (!fileName.isEmpty()) {
2784     std::string fileformat = itksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
2785     if (OutputListeFormat.contains(
2786       fileformat.c_str())) {
2787         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2788         std::string action = "Saving";
2789         vvProgressDialog progress("Saving "+fileName.toStdString());
2790         qApp->processEvents();
2791         vvImageWriter::Pointer writer = vvImageWriter::New();
2792         writer->SetOutputFileName(fileName.toStdString());
2793         writer->SetInput(mSlicerManagers[index]->GetImage());
2794
2795         // Check on transform and prompt user
2796         writer->SetSaveTransform(false);
2797         bool bId = true;
2798         for(int i=0; i<4; i++)
2799           for(int j=0; j<4; j++) {
2800             // TODO SR and BP: check on the list of transforms and not the first only
2801             double elt = mSlicerManagers[index]->GetImage()->GetTransform()[0]->GetMatrix()->GetElement(i,j);
2802             if(i==j && elt!=1.)
2803               bId = false;
2804             if(i!=j && elt!=0.)
2805               bId = false;
2806           }
2807           if( !bId ) {
2808             QString warning = "The image has an associated linear transform. Do you want to save it along?";
2809             QMessageBox msgBox(QMessageBox::Warning, tr("Save transform"), warning, 0, this);
2810             msgBox.addButton(tr("Yes"), QMessageBox::AcceptRole);
2811             msgBox.addButton(tr("No"), QMessageBox::RejectRole);
2812             if (msgBox.exec() == QMessageBox::AcceptRole)
2813               writer->SetSaveTransform(true);
2814           }
2815
2816           writer->Update();
2817           QApplication::restoreOverrideCursor();
2818           if (writer->GetLastError().size()) {
2819             QString error = "Saving did not succeed\n";
2820             error += writer->GetLastError().c_str();
2821             QMessageBox::information(this,tr("Saving Problem"),error);
2822             SaveAs();
2823           }
2824     } else {
2825       QString error = fileformat.c_str();
2826       if (error.isEmpty())
2827         error += "no file format specified !";
2828       else
2829         error += " format unknown !!!\n";
2830       QMessageBox::information(this,tr("Saving Problem"),error);
2831       SaveAs();
2832     }
2833   }
2834 }
2835 //------------------------------------------------------------------------------
2836
2837 //------------------------------------------------------------------------------
2838 void vvMainWindow::SaveCurrentState()
2839 {
2840   QString Extensions = "XML Files(*.xml)";
2841   QString fileName = QFileDialog::getSaveFileName(this,
2842     tr("Save Current Window State"),
2843     "",
2844     Extensions);
2845
2846   SaveCurrentStateAs(fileName.toStdString());
2847 }
2848 //------------------------------------------------------------------------------
2849
2850 //------------------------------------------------------------------------------
2851 void vvMainWindow::SaveCurrentStateAs(const std::string& stateFile)
2852 {
2853   vvSaveState save_state;
2854   save_state.Run(this, stateFile);
2855 }
2856
2857 //------------------------------------------------------------------------------
2858 void vvMainWindow::ReadSavedState()
2859 {
2860   QString Extensions = "XML Files(*.xml)";
2861   QString fileName = QFileDialog::getOpenFileName(this,
2862     tr("Load Window State"),
2863     "",
2864     Extensions);
2865
2866   ReadSavedStateFile(fileName.toStdString());
2867 }
2868 //------------------------------------------------------------------------------
2869
2870 //------------------------------------------------------------------------------
2871 void vvMainWindow::ReadSavedStateFile(const std::string& stateFile)
2872 {
2873   vvReadState read_state;
2874   read_state.Run(this, stateFile);
2875 }
2876 //------------------------------------------------------------------------------
2877
2878 //------------------------------------------------------------------------------
2879 void vvMainWindow::LinkAllImages()
2880 {
2881   linkPanel->linkAll();
2882 }
2883
2884 //------------------------------------------------------------------------------
2885 void vvMainWindow::AddLink(QString image1,QString image2,bool fromPanel)
2886 {
2887   if (!fromPanel) {
2888     // delegate to linkPanel if call came from elsewhere...
2889     linkPanel->addLinkFromIds(image1, image2);
2890     return;
2891   }
2892
2893   unsigned int sm1 = 0;
2894   unsigned int sm2 = 0;
2895
2896   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
2897     if (image1.toStdString() == mSlicerManagers[i]->GetId()) {
2898       mSlicerManagers[i]->AddLink(image2.toStdString());
2899       sm1 = i;
2900     }
2901     if (image2.toStdString() == mSlicerManagers[i]->GetId()) {
2902       mSlicerManagers[i]->AddLink(image1.toStdString());
2903       sm2 = i;
2904     }
2905   }
2906
2907   if (linkPanel->isLinkAll())   {
2908     emit UpdateLinkedNavigation(mSlicerManagers[sm1]->GetId(), mSlicerManagers[mCurrentPickedImageIndex], mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0));
2909     emit UpdateLinkedNavigation(mSlicerManagers[sm2]->GetId(), mSlicerManagers[mCurrentPickedImageIndex], mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(0));
2910   } else {
2911     emit UpdateLinkedNavigation(mSlicerManagers[sm2]->GetId(), mSlicerManagers[sm1], mSlicerManagers[sm1]->GetSlicer(0));
2912   }
2913 }
2914
2915 //------------------------------------------------------------------------------
2916
2917
2918 //------------------------------------------------------------------------------
2919 void vvMainWindow::RemoveLink(QString image1,QString image2)
2920 {
2921   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
2922     if (image1.toStdString() == mSlicerManagers[i]->GetId()) {
2923       mSlicerManagers[i]->RemoveLink(image2.toStdString());
2924     }
2925     if (image2.toStdString() == mSlicerManagers[i]->GetId()) {
2926       mSlicerManagers[i]->RemoveLink(image1.toStdString());
2927     }
2928   }
2929 }
2930 //------------------------------------------------------------------------------
2931
2932 //------------------------------------------------------------------------------
2933 void vvMainWindow::ChangeImageWithIndexOffset(vvSlicerManager *sm, int slicer, int offset)
2934 {
2935   if(mSlicerManagers.size()==1)
2936     return;
2937
2938   int index = 0;
2939   while(sm != mSlicerManagers[index])
2940     index++;
2941   index = (index+offset+mSlicerManagers.size()) % mSlicerManagers.size();
2942
2943   QTreeWidgetItem* item = GetItemFromSlicerManager(mSlicerManagers[index]);
2944   item->setData(slicer+1,Qt::CheckStateRole,2);         //change checkbox
2945   CurrentImageChanged(mSlicerManagers[index]->GetId()); //select new image
2946   DisplayChanged(item,slicer+1);
2947 }
2948 //------------------------------------------------------------------------------
2949 void vvMainWindow::HorizontalSliderMoved(int value,int column, int slicer_index)
2950 {
2951   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
2952     if (DataTree->topLevelItem(i)->data(column,Qt::CheckStateRole).toInt() > 1) {
2953       //i is the SlicerManager that is in charge of this slicer.
2954       if (mSlicerManagers[i]->IsInvolvedInFusionSequence()) {
2955         //if the slicerManager is involved in a fusionSequence as the secondary sequence, then update the slider position in the overlay panel and everything accordingly
2956         if (mSlicerManagers[i]->IsSecondarySequenceOfFusionSequence()) { 
2957           overlayPanel->updateFusionSequenceSliderValueFromWindow(value, true); 
2958         }
2959         else { //if this is the primary sequence that has been modified
2960           if (mSlicerManagers[i]->GetFusionSequenceTemporalSyncFlag()) {            
2961             //WARNING: for some obscure reason, there are problems when accessing mSlicerManagers[mSlicerManagers[i]->GetFusionSequenceIndexOfLinkedManager()]->GetFusionSequenceFrameIndex();
2962
2963             int estimatedValue=0;
2964             //estimate a corresponding time index for the secondary (US) sequence, and update it accordingly.
2965             estimatedValue = mSlicerManagers[i]->GetFusionSequenceCorrespondances()[ value ];       
2966             //TODO: at the moment, there is a loop in TSlice modifications
2967             //modifying sequence 1 causes seq 2 to update, which in turns update seq1...
2968             //I disable control on seq1 at the moment.
2969             //overlayPanel->updateFusionSequenceSliderValueFromWindow(estimatedValue, true);
2970           }
2971         }
2972       }
2973
2974       for (int j = 0; j < 4; j++) {
2975         mSlicerManagers[i]->SetTSliceInSlicer(value,j);
2976       }
2977       mSlicerManagers[i]->GetSlicer(slicer_index)->Render();
2978       break;
2979     }
2980   }
2981 }
2982 //------------------------------------------------------------------------------
2983
2984
2985 //------------------------------------------------------------------------------
2986 void vvMainWindow::NOHorizontalSliderMoved()
2987 {
2988   // if (mCurrentTime == NOHorizontalSlider->value()) return;
2989   HorizontalSliderMoved(NOHorizontalSlider->value(),COLUMN_UL_VIEW,0);
2990   //  mCurrentTime = NOHorizontalSlider->value();
2991 }
2992 //------------------------------------------------------------------------------
2993
2994
2995 //------------------------------------------------------------------------------
2996 void vvMainWindow::NEHorizontalSliderMoved()
2997 {
2998   // if (mCurrentTime == NEHorizontalSlider->value()) return;
2999   HorizontalSliderMoved(NEHorizontalSlider->value(),COLUMN_UR_VIEW,1);
3000   //  mCurrentTime = NEHorizontalSlider->value();
3001 }
3002 //------------------------------------------------------------------------------
3003
3004
3005 //------------------------------------------------------------------------------
3006 void vvMainWindow::SOHorizontalSliderMoved()
3007 {
3008   // if (mCurrentTime == SOHorizontalSlider->value()) return;
3009   HorizontalSliderMoved(SOHorizontalSlider->value(),COLUMN_DL_VIEW,2);
3010   // mCurrentTime = SOHorizontalSlider->value();
3011 }
3012 //------------------------------------------------------------------------------
3013
3014
3015 //------------------------------------------------------------------------------
3016 void vvMainWindow::SEHorizontalSliderMoved()
3017 {
3018   // if (mCurrentTime == SEHorizontalSlider->value()) return;
3019   HorizontalSliderMoved(SEHorizontalSlider->value(),COLUMN_DR_VIEW,3);
3020   // mCurrentTime = SEHorizontalSlider->value();
3021 }
3022 //------------------------------------------------------------------------------
3023
3024 //------------------------------------------------------------------------------
3025 void vvMainWindow::NOVerticalSliderChanged()
3026 {
3027   static int value=-1;
3028   if (value == NOVerticalSlider->value()) return;
3029   else value = NOVerticalSlider->value();
3030   //  int value = NOVerticalSlider->value();
3031   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
3032     if (DataTree->topLevelItem(i)->data(COLUMN_UL_VIEW,Qt::CheckStateRole).toInt() > 1) {
3033       if (mSlicerManagers[i]->GetSlicer(0)->GetSlice() != value) {
3034         mSlicerManagers[i]->GetSlicer(0)->SetSlice(value);
3035         mSlicerManagers[i]->VerticalSliderHasChanged(0, value);
3036
3037         // If nor Update/Render -> slider not work
3038         // only render = ok navigation, but for contour Update needed but slower ?
3039
3040         mSlicerManagers[i]->UpdateSlice(0);  // <-- DS add this. Not too much update ? YES. but needed for ImageContour ...
3041         //mSlicerManagers[i]->GetSlicer(0)->Render(); // <-- DS add this, needed for contour, seems ok ? not too slow ?
3042       }
3043       break;
3044     }
3045   }
3046 }
3047 //------------------------------------------------------------------------------
3048
3049
3050 //------------------------------------------------------------------------------
3051 void vvMainWindow::NEVerticalSliderChanged()
3052 {
3053   static int value=-1;
3054   if (value == NEVerticalSlider->value()) return;
3055   else value = NEVerticalSlider->value();
3056   //  int value = NEVerticalSlider->value();
3057   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
3058     if (DataTree->topLevelItem(i)->data(COLUMN_UR_VIEW,Qt::CheckStateRole).toInt() > 1) {
3059       if (mSlicerManagers[i]->GetSlicer(1)->GetSlice() != value) {
3060         mSlicerManagers[i]->GetSlicer(1)->SetSlice(value);
3061         mSlicerManagers[i]->VerticalSliderHasChanged(1, value);
3062         mSlicerManagers[i]->UpdateSlice(1);
3063         //mSlicerManagers[i]->GetSlicer(1)->Render(); // <-- DS add this, needed for contour, seems ok ? not too slow ?
3064       }
3065       break;
3066     }
3067   }
3068 }
3069 //------------------------------------------------------------------------------
3070
3071
3072 //------------------------------------------------------------------------------
3073 void vvMainWindow::SOVerticalSliderChanged()
3074 {
3075   static int value=-1;
3076   if (value == SOVerticalSlider->value()) return;
3077   else value = SOVerticalSlider->value();
3078   //int value = SOVerticalSlider->value();
3079   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
3080     if (DataTree->topLevelItem(i)->data(COLUMN_DL_VIEW,Qt::CheckStateRole).toInt() > 1) {
3081       if (mSlicerManagers[i]->GetSlicer(2)->GetSlice() != value) {
3082         mSlicerManagers[i]->GetSlicer(2)->SetSlice(value);
3083         mSlicerManagers[i]->VerticalSliderHasChanged(2, value);
3084         mSlicerManagers[i]->UpdateSlice(2);
3085         //mSlicerManagers[i]->GetSlicer(2)->Render(); // <-- DS add this, needed for contour, seems ok ? not too slow ?
3086       }
3087       // else { DD("avoid SOVerticalSlider slicer update"); }
3088       break;
3089     }
3090   }
3091 }
3092 //------------------------------------------------------------------------------
3093
3094
3095 //------------------------------------------------------------------------------
3096 void vvMainWindow::SEVerticalSliderChanged()
3097 {
3098   static int value=-1;
3099   if (value == SEVerticalSlider->value()) return;
3100   else value = SEVerticalSlider->value();
3101   // int value = SEVerticalSlider->value();
3102   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
3103     if (DataTree->topLevelItem(i)->data(COLUMN_DR_VIEW,Qt::CheckStateRole).toInt() > 1) {
3104       if (mSlicerManagers[i]->GetSlicer(3)->GetSlice() != value) {
3105         mSlicerManagers[i]->GetSlicer(3)->SetSlice(value);
3106         mSlicerManagers[i]->VerticalSliderHasChanged(3, value);
3107         mSlicerManagers[i]->UpdateSlice(3);
3108         //mSlicerManagers[i]->GetSlicer(3)->Render(); // <-- DS add this, needed for contour, seems ok ? not too slow ?
3109       }
3110       break;
3111     }
3112   }
3113 }
3114 //------------------------------------------------------------------------------
3115
3116
3117 //------------------------------------------------------------------------------
3118 void vvMainWindow::UpdateSlice(int slicer, int slice)
3119 {
3120   // DD("vvMainWindow::UpdateSlice");
3121   //   DD(slicer);
3122   //   DD(slice);
3123   if (slicer == 0) {
3124     //    if (slice != NOVerticalSlider->value())
3125     NOVerticalSlider->setValue(slice);
3126   } else {
3127     if (slicer == 1)
3128       NEVerticalSlider->setValue(slice);
3129     else {
3130       if (slicer == 2)
3131         SOVerticalSlider->setValue(slice);
3132       else {
3133         if (slicer == 3)
3134           SEVerticalSlider->setValue(slice);
3135       }
3136     }
3137   }
3138   // DD("vvMainWindow:UpdateSlice END");
3139 }
3140 //------------------------------------------------------------------------------
3141
3142
3143 //------------------------------------------------------------------------------
3144 void vvMainWindow::UpdateTSlice(int slicer, int slice, int code)
3145 {
3146   //FusionSequence: the slider value should be updated for slicers which show the same sequence as requested
3147   bool doUpdate=false;
3148   if (code==-1) doUpdate=true;
3149   else {
3150     for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
3151       if (DataTree->topLevelItem(i)->data(slicer+1,Qt::CheckStateRole).toInt() > 1) {
3152         //i is the active SlicerManager
3153         if (mSlicerManagers[i]->GetFusionSequenceInvolvmentCode()==code) doUpdate=true;
3154         break;
3155       }
3156     }
3157   }
3158   if (!doUpdate) return;
3159
3160   switch (slicer) {
3161   case 0:
3162     if (NOHorizontalSlider->value()==slice) return;
3163     NOHorizontalSlider->setValue(slice);
3164     break;
3165   case 1:
3166     if (NEHorizontalSlider->value()==slice) return;
3167     NEHorizontalSlider->setValue(slice);
3168     break;
3169   case 2:
3170     if (SOHorizontalSlider->value()==slice) return;
3171     SOHorizontalSlider->setValue(slice);
3172     break;
3173   case 3:
3174     if (SEHorizontalSlider->value()==slice) return;
3175     SEHorizontalSlider->setValue(slice);
3176     break;
3177   }
3178 }
3179 //------------------------------------------------------------------------------
3180
3181
3182 //------------------------------------------------------------------------------
3183 void vvMainWindow::UpdateSliceRange(int slicer, int min, int max, int tmin, int tmax)
3184 {
3185   //int position = int((min+max)/2);
3186   int position = mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(slicer)->GetSlice();
3187   if (slicer == 0) {
3188     NOVerticalSlider->setRange(min,max);
3189     NOHorizontalSlider->setRange(tmin,tmax);
3190     NOVerticalSlider->setValue(position);
3191   } else if (slicer == 1) {
3192     NEVerticalSlider->setRange(min,max);
3193     NEHorizontalSlider->setRange(tmin,tmax);
3194     NEVerticalSlider->setValue(position);
3195   } else if (slicer == 2) {
3196     SOVerticalSlider->setRange(min,max);
3197     SOHorizontalSlider->setRange(tmin,tmax);
3198     SOVerticalSlider->setValue(position);
3199   } else if (slicer == 3) {
3200     SEVerticalSlider->setRange(min,max);
3201     SEHorizontalSlider->setRange(tmin,tmax);
3202     SEVerticalSlider->setValue(position);
3203   }
3204 }
3205 //------------------------------------------------------------------------------
3206
3207
3208 //------------------------------------------------------------------------------
3209 void vvMainWindow::SaveNOScreenshot()
3210 {
3211   SaveScreenshot(NOViewWidget);
3212 }
3213 //------------------------------------------------------------------------------
3214
3215
3216 //------------------------------------------------------------------------------
3217 void vvMainWindow::SaveNEScreenshot()
3218 {
3219   SaveScreenshot(NEViewWidget);
3220 }
3221 //------------------------------------------------------------------------------
3222
3223
3224 //------------------------------------------------------------------------------
3225 void vvMainWindow::SaveSOScreenshot()
3226 {
3227   SaveScreenshot(SOViewWidget);
3228 }
3229 //------------------------------------------------------------------------------
3230
3231
3232 //------------------------------------------------------------------------------
3233 void vvMainWindow::SaveSEScreenshot()
3234 {
3235   SaveScreenshot(SEViewWidget);
3236 }
3237 //------------------------------------------------------------------------------
3238
3239
3240 //------------------------------------------------------------------------------
3241 void vvMainWindow::SaveScreenshotAllSlices()
3242 {
3243   QVTKWidget *widget = NOViewWidget;
3244
3245   int index = 0;// GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
3246   vvSlicerManager * SM = mSlicerManagers[index];
3247   vvImage * image = SM->GetImage();
3248   vvSlicer * slicer = SM->GetSlicer(0);
3249   int orientation = slicer->GetOrientation();
3250   int nbSlices = image->GetSize()[orientation];
3251   vtkSmartPointer<vtkRenderWindow>  renderWindow = widget->GetRenderWindow();
3252
3253   // Select filename base
3254   QString filename = QFileDialog::getSaveFileName(this,
3255     tr("Save As (filename will be completed by slice number)"),
3256     itksys::SystemTools::GetFilenamePath(mSlicerManagers[index]->GetFileName()).c_str(),
3257     "Images( *.png);;Images( *.jpg)");
3258
3259   // Loop on slices
3260   for(int i=0; i<nbSlices; i++) {
3261     // Change the slice
3262     slicer->SetSlice(i); // -> change the slice of the current slicer
3263     SM->UpdateSlice(0); // --> this one emit UpdateSlice
3264     QCoreApplication::flush(); // -> needed to force display of contours 
3265
3266     // Screenshot  
3267     vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
3268     windowToImageFilter->SetInput(renderWindow);
3269     windowToImageFilter->SetMagnification(1);
3270     windowToImageFilter->SetInputBufferTypeToRGBA(); //also record the alpha (transparency) channel
3271     windowToImageFilter->Update();
3272
3273     vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
3274     std::string fn = itksys::SystemTools::GetFilenameWithoutLastExtension(filename.toStdString());
3275     std::string num = clitk::toString(i);
3276     if (i<10) num = "0"+num;
3277     if (i<100) num = "0"+num;
3278     if (i<1000) num = "0"+num;
3279
3280     fn = itksys::SystemTools::GetFilenamePath(filename.toStdString()) + "/"+ fn 
3281       + "_" + num + itksys::SystemTools::GetFilenameLastExtension(filename.toStdString());
3282     writer->SetFileName(fn.c_str());
3283     writer->SetInput(windowToImageFilter->GetOutput());
3284     writer->Write();
3285   }
3286 }
3287 //------------------------------------------------------------------------------
3288
3289
3290 //------------------------------------------------------------------------------
3291 void vvMainWindow::SaveScreenshot(QVTKWidget *widget)
3292 {
3293   QString Extensions = "Images( *.png);;";
3294   Extensions += "Images( *.jpg);;";
3295   Extensions += "Images( *.bmp);;";
3296   Extensions += "Images( *.tif);;";
3297   Extensions += "Images( *.ppm)";
3298 #if defined(VTK_USE_FFMPEG_ENCODER) || defined(VTK_USE_VIDEO_FOR_WINDOWS)
3299   Extensions += ";;Video( *.avi)";
3300 #endif
3301 #ifdef VTK_USE_MPEG2_ENCODER
3302   Extensions += ";;Video( *.mpg)";
3303 #endif
3304 #ifdef CLITK_EXPERIMENTAL
3305   Extensions += ";;Video( *.gif)";
3306 #endif
3307
3308   int smIndex=GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
3309   QString fileName = QFileDialog::getSaveFileName(this,
3310     tr("Save As"),
3311     itksys::SystemTools::GetFilenamePath(mSlicerManagers[smIndex]->GetFileName()).c_str(),
3312     Extensions);
3313
3314   if (!fileName.isEmpty()) {
3315     vtkSmartPointer<vtkWindowToImageFilter> w2i = vtkSmartPointer<vtkWindowToImageFilter>::New();
3316     w2i->SetInput(widget->GetRenderWindow());
3317     w2i->Update();
3318     vtkImageData *image = w2i->GetOutput();
3319
3320     std::string ext(itksys::SystemTools::GetFilenameLastExtension(fileName.toStdString()));
3321
3322     // Image
3323     vtkImageWriter *imgwriter = NULL;
3324     if (ext==".bmp")
3325       imgwriter = vtkBMPWriter::New();
3326     else if (ext==".tif")
3327       imgwriter = vtkTIFFWriter::New();
3328     else if (ext==".ppm")
3329       imgwriter = vtkPNMWriter::New();
3330     else if (ext==".png")
3331       imgwriter = vtkPNGWriter::New();
3332     else if (ext==".jpg")
3333       imgwriter = vtkJPEGWriter::New();
3334
3335     // Snapshot image if not null
3336     if(imgwriter!=NULL) {
3337       imgwriter->SetInput(image);
3338       imgwriter->SetFileName(fileName.toStdString().c_str());
3339       imgwriter->Write();
3340       return;
3341     }
3342
3343     // Video
3344     vtkGenericMovieWriter *vidwriter = NULL;
3345 #if CLITK_EXPERIMENTAL == 1
3346     if (ext==".gif") {
3347       vvAnimatedGIFWriter *gif = vvAnimatedGIFWriter::New();
3348       vidwriter = gif;
3349
3350       // FPS
3351       bool ok;
3352       int fps = QInputDialog::getInteger(this, tr("Number of frames per second"),
3353         tr("FPS:"), 5, 0, 1000, 1, &ok);
3354       if(ok)
3355         gif->SetRate(fps);
3356
3357       // Loops
3358       int loops = QInputDialog::getInteger(this, tr("Loops"),
3359         tr("Number of loops (0 means infinite):"), 0, 0, 1000000000, 1, &ok);
3360       if(ok)
3361         gif->SetLoops(loops);
3362
3363       // Dithering
3364       QString msg = "Would you like to activate dithering?";
3365       QMessageBox msgBox(QMessageBox::Question, tr("Dithering"),msg, 0, this);
3366       msgBox.addButton(tr("Yes"), QMessageBox::AcceptRole);
3367       msgBox.addButton(tr("No"), QMessageBox::RejectRole);
3368       gif->SetDither(msgBox.exec() == QMessageBox::AcceptRole);
3369     }
3370 #endif
3371 #ifdef VTK_USE_VIDEO_FOR_WINDOWS
3372     if (ext==".avi") {
3373       vtkAVIWriter *mpg = vtkAVIWriter::New();
3374       vidwriter = mpg;
3375       mpg->SetQuality(2);
3376       bool ok;
3377       int fps = QInputDialog::getInteger(this, tr("Number of frames per second"),
3378         tr("FPS:"), 5, 0, 1024, 1, &ok);
3379       if(!ok)
3380         fps = 5;
3381       mpg->SetRate(fps);
3382     }
3383 #endif
3384 #ifdef VTK_USE_FFMPEG_ENCODER
3385     if (ext==".avi") {
3386       vtkFFMPEGWriter *mpg = vtkFFMPEGWriter::New();
3387       vidwriter = mpg;
3388       mpg->SetQuality(2);
3389       bool ok;
3390       int fps = QInputDialog::getInteger(this, tr("Number of frames per second"),
3391         tr("FPS:"), 5, 0, 1024, 1, &ok);
3392       if(!ok)
3393         fps = 5;
3394       mpg->SetRate(fps);
3395       mpg->SetBitRateTolerance(int(ceil(12.0*1024*1024/fps)));
3396     }
3397 #endif
3398 #ifdef VTK_USE_MPEG2_ENCODER
3399     if (ext==".mpg") {
3400       vtkMPEG2Writer *mpg = vtkMPEG2Writer::New();
3401       vidwriter = mpg;
3402     }
3403 #endif
3404
3405     // Take video if not null
3406     if(vidwriter!=NULL){
3407       vidwriter->SetInput(image);
3408       vidwriter->SetFileName(fileName.toStdString().c_str());
3409       vidwriter->Start();
3410       int nSlice = mSlicerManagers[smIndex]->GetSlicer(0)->GetTMax();
3411       for(int i=0; i<=nSlice; i++) {
3412         mSlicerManagers[smIndex]->SetNextTSlice(0);
3413         vtkSmartPointer<vtkWindowToImageFilter> w2i = vtkSmartPointer<vtkWindowToImageFilter>::New();
3414         w2i->SetInput(widget->GetRenderWindow());
3415         w2i->Update();
3416         vidwriter->SetInput(w2i->GetOutput());
3417         vidwriter->Write();
3418       }
3419       vidwriter->End();
3420       vidwriter->Delete();
3421       return;
3422     }
3423
3424     QMessageBox::information(this,tr("Problem saving screenshot !"),tr("Cannot save image.\nPlease set a file extension !!!"));
3425   }
3426 }
3427 //------------------------------------------------------------------------------
3428
3429
3430 //------------------------------------------------------------------------------
3431 void vvMainWindow::GoToCursor()
3432 {
3433   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
3434   for (int column = 1; column < 5; column++) {
3435     if (DataTree->selectedItems()[0]->data(column,Qt::CheckStateRole).toInt() > 1) {
3436       double* cursorPos = mSlicerManagers[index]->GetSlicer(column-1)->GetCursorPosition();
3437       mSlicerManagers[index]->GetSlicer(column-1)->SetCurrentPosition(
3438         cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]);
3439       mSlicerManagers[index]->UpdateViews(1,column-1);
3440       mSlicerManagers[index]->UpdateLinked(column-1);
3441       break;
3442     }
3443   }
3444 }
3445 //------------------------------------------------------------------------------
3446
3447 //------------------------------------------------------------------------------
3448 void vvMainWindow::GoToLandmark()
3449 {
3450   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
3451   for (int column = 1; column < 5; column++) {
3452     if (DataTree->selectedItems()[0]->data(column,Qt::CheckStateRole).toInt() > 1) {
3453       double* cursorPos = landmarksPanel->GetSelectedPoint();
3454       mSlicerManagers[index]->GetSlicer(column-1)->SetCurrentPosition(
3455         cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]);
3456       mSlicerManagers[index]->UpdateViews(1,column-1);
3457       mSlicerManagers[index]->UpdateLinked(column-1);
3458       break;
3459     }
3460   }
3461 }
3462 //------------------------------------------------------------------------------
3463
3464 //------------------------------------------------------------------------------
3465 void vvMainWindow::PlayPause()
3466 {
3467   if (playMode) {
3468     playMode = 0;
3469     playButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/player_play.png")));
3470     ImageInfoChanged();
3471     return;
3472   } else {
3473     int image_number=DataTree->topLevelItemCount();
3474     bool has_temporal;
3475     for (int i=0; i<image_number; i++)
3476       if (mSlicerManagers[i]->GetSlicer(0)->GetTMax() > 0) {
3477         has_temporal=true;
3478         break;
3479       }
3480       if (has_temporal) {
3481         playMode = 1;
3482         playButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/player_pause.png")));
3483         QTimer::singleShot(1000/mFrameRate, this, SLOT(PlayNext()));
3484       }
3485   }
3486 }
3487 //------------------------------------------------------------------------------
3488
3489 //------------------------------------------------------------------------------
3490 void vvMainWindow::PlayNext()
3491 {
3492   if (playMode && !this->isHidden()) {
3493     int image_number=DataTree->topLevelItemCount();
3494     ///Only play one slicer per SM, and only if the SM is being displayed
3495     for (int i=0; i<image_number; i++)
3496       for (int j=0; j<4; j++)
3497         if (mSlicerManagers[i]->GetSlicer(0)->GetTMax() > 0 &&
3498           DataTree->topLevelItem(i)->data(j+1,Qt::CheckStateRole).toInt() > 0) {
3499             mSlicerManagers[i]->SetNextTSlice(j);
3500             break;
3501         }
3502         QTimer::singleShot(1000/mFrameRate, this, SLOT(PlayNext()));
3503   }
3504 }
3505 //------------------------------------------------------------------------------
3506
3507 void vvMainWindow::ShowLastImage()
3508 {
3509   if (mSlicerManagers.size() > 1) {
3510     QTreeWidgetItem * item=DataTree->topLevelItem(DataTree->topLevelItemCount()-1);
3511     CurrentImageChanged(mSlicerManagers.back()->GetId()); //select new image
3512     item->setData(1,Qt::CheckStateRole,2); //show the new image in the first panel
3513     DisplayChanged(item,1);
3514   }
3515 }
3516
3517 //------------------------------------------------------------------------------
3518 void vvMainWindow::UpdateRenderWindows()
3519 {
3520   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
3521     mSlicerManagers[i]->GetSlicer(0)->UpdateLandmarks();
3522     mSlicerManagers[i]->GetSlicer(1)->UpdateLandmarks();
3523     mSlicerManagers[i]->GetSlicer(2)->UpdateLandmarks();
3524     mSlicerManagers[i]->GetSlicer(3)->UpdateLandmarks();
3525   }
3526   if (NOViewWidget->GetRenderWindow()) NOViewWidget->GetRenderWindow()->Render();
3527   if (NEViewWidget->GetRenderWindow()) NEViewWidget->GetRenderWindow()->Render();
3528   if (SOViewWidget->GetRenderWindow()) SOViewWidget->GetRenderWindow()->Render();
3529   if (SEViewWidget->GetRenderWindow()) SEViewWidget->GetRenderWindow()->Render();
3530 }
3531 //------------------------------------------------------------------------------
3532
3533 //------------------------------------------------------------------------------
3534 void vvMainWindow::SegmentationOnCurrentImage()
3535 {
3536   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
3537
3538   vvSegmentationDialog segmentation;
3539   segmentation.SetImage(mSlicerManagers[index]->GetSlicer(0)->GetImage());
3540   segmentation.exec();
3541 }
3542 //------------------------------------------------------------------------------
3543
3544 void vvMainWindow::SurfaceViewerLaunch()
3545 {
3546   vvSurfaceViewerDialog surfaceViewer;
3547   surfaceViewer.exec();
3548 }
3549 //------------------------------------------------------------------------------
3550
3551
3552 //------------------------------------------------------------------------------
3553 int vvMainWindow::GetImageDuplicateFilenameNumber(std::string filename)
3554 {
3555   int number=0;
3556   for(unsigned int l=0; l<mSlicerManagers.size(); l++) {
3557     vvSlicerManager * v = mSlicerManagers[l];
3558     if (v->GetBaseFileName() ==
3559       vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(filename))) {
3560         number = std::max(number, v->GetBaseFileNameNumber()+1);
3561     }
3562   }
3563   return number;
3564 }
3565 //------------------------------------------------------------------------------
3566
3567
3568 //------------------------------------------------------------------------------
3569 vvSlicerManager* vvMainWindow::AddImage(vvImage::Pointer image,std::string filename)
3570 {
3571   // Change filename if another image exist with the same name
3572   int number = GetImageDuplicateFilenameNumber(filename);
3573
3574   // Create new SliceManager
3575   vvSlicerManager* slicer_manager = new vvSlicerManager(4);
3576   slicer_manager->SetImage(image);//, IMAGE, number);
3577   //  filename = filename+"_"+clitk::toString(number);
3578   slicer_manager->SetFilename(filename, number);
3579   mSlicerManagers.push_back(slicer_manager);
3580
3581   //create an item in the tree with good settings
3582   QTreeWidgetItem *item = new QTreeWidgetItem();
3583   item->setData(0,Qt::UserRole,slicer_manager->GetFileName().c_str());//files[i].c_str());
3584   item->setData(1,Qt::UserRole,tr("image"));
3585   item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,slicer_manager->GetFileName().c_str());//filename.c_str());
3586   qApp->processEvents();
3587
3588   for (int j = 1; j <= 4; j++) item->setData(j,Qt::CheckStateRole,1);
3589
3590   //Create the buttons for reload and close
3591   qApp->processEvents();
3592   QTreePushButton* cButton = new QTreePushButton;
3593   cButton->setItem(item);
3594   cButton->setColumn(COLUMN_CLOSE_IMAGE);
3595   cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
3596   connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
3597     this,SLOT(CloseImage(QTreeWidgetItem*, int)));
3598
3599   QTreePushButton* rButton = new QTreePushButton;
3600   rButton->setItem(item);
3601   rButton->setColumn(COLUMN_RELOAD_IMAGE);
3602   rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
3603   rButton->setEnabled(0);
3604   connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
3605     this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
3606
3607   DataTree->addTopLevelItem(item);
3608   DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
3609   DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
3610
3611   //set the id of the image
3612   QString id = QDir::current().absoluteFilePath(slicer_manager->GetFileName().c_str()) + QString::number(mSlicerManagers.size()-1);
3613   item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
3614   mSlicerManagers.back()->SetId(id.toStdString());
3615
3616   linkPanel->addImage(slicer_manager->GetFileName().c_str()// filename
3617     , id.toStdString());
3618
3619   connect(mSlicerManagers.back(), SIGNAL(currentImageChanged(std::string)),
3620     this, SLOT(CurrentImageChanged(std::string)));
3621   connect(mSlicerManagers.back(), SIGNAL(currentPickedImageChanged(std::string)),
3622     this, SLOT(CurrentPickedImageChanged(std::string)));
3623   connect(mSlicerManagers.back(), SIGNAL(UpdatePosition(int, double, double, double, double, double, double, double)),
3624     this, SLOT(MousePositionChanged(int,double, double, double, double, double, double, double)));
3625   connect(mSlicerManagers.back(), SIGNAL(UpdateVector(int, double, double, double, double)),
3626     this, SLOT(VectorChanged(int,double,double,double, double)));
3627   connect(mSlicerManagers.back(), SIGNAL(UpdateOverlay(int, double, double)),
3628     this, SLOT(OverlayChanged(int,double,double)));
3629   connect(mSlicerManagers.back(), SIGNAL(UpdateFusion(int, double)),
3630     this, SLOT(FusionChanged(int,double)));
3631   //connect(mSlicerManagers.back(), SIGNAL(UpdateFusionSequence(int, bool, unsigned int)),
3632   //  this, SLOT(FusionSequenceChanged(int, bool, unsigned int)));
3633   connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged()),
3634     this,SLOT(WindowLevelChanged()));
3635   connect(mSlicerManagers.back(), SIGNAL(UpdateSlice(int,int)),
3636     this,SLOT(UpdateSlice(int,int)));
3637   connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int, int)),
3638     this,SLOT(UpdateTSlice(int, int, int)));
3639   connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int, int)),
3640     this,SLOT(ImageInfoChanged()));
3641   connect(mSlicerManagers.back(), SIGNAL(UpdateSliceRange(int,int,int,int,int)),
3642     this,SLOT(UpdateSliceRange(int,int,int,int,int)));
3643   connect(mSlicerManagers.back(), SIGNAL(UpdateLinkManager(std::string,int,double,double,double,int)),
3644     this,SLOT(UpdateLinkManager(std::string,int,double,double,double,int)));
3645   connect(mSlicerManagers.back(), SIGNAL(UpdateLinkedNavigation(std::string,vvSlicerManager*,vvSlicer*)),
3646     this,SLOT(UpdateLinkedNavigation(std::string,vvSlicerManager*,vvSlicer*)));
3647   connect(mSlicerManagers.back(), SIGNAL(ChangeImageWithIndexOffset(vvSlicerManager*,int,int)),
3648     this,SLOT(ChangeImageWithIndexOffset(vvSlicerManager*,int,int)));
3649   connect(mSlicerManagers.back(), SIGNAL(LandmarkAdded()),landmarksPanel,SLOT(AddPoint()));
3650
3651
3652   UpdateTree();
3653   qApp->processEvents();
3654   InitSlicers();
3655   ShowLastImage();
3656   InitDisplay();
3657   qApp->processEvents();
3658
3659   // End
3660   ImageInfoChanged();
3661   return slicer_manager;
3662 }
3663 //------------------------------------------------------------------------------
3664
3665
3666 //------------------------------------------------------------------------------
3667 void vvMainWindow::UpdateCurrentSlicer()
3668 {
3669   int index = -1;
3670   if (DataTree->selectedItems().size() > 0) {
3671     index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
3672   }
3673   mSlicerManagerCurrentIndex = index;
3674 }
3675 //------------------------------------------------------------------------------
3676