]> Creatis software - clitk.git/blob - vv/vvToolROIManager.cxx
First version of dicom-rt reader in the roi tool.
[clitk.git] / vv / vvToolROIManager.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 // vv
20 #include "vvToolROIManager.h"
21 #include "vvImageReader.h"
22 #include "vvImageWriter.h"
23 #include "vvROIActor.h"
24 #include "vvSlicer.h"
25 #include "vvROIActor.h"
26 #include "vvMeshReader.h"
27 #include "vvStructSelector.h"
28 #include "vvToolManager.h"
29
30 // clitk
31 #include "clitkDicomRTStruct2ImageFilter.h"
32 #include "clitkDicomRT_StructureSet.h"
33
34 // Qt
35 #include <QFileDialog>
36 #include <QMessageBox>
37 #include <QColorDialog>
38 #include <QAbstractEventDispatcher>
39 #include <QXmlStreamReader>
40  
41 // vtk
42 #include <vtkLookupTable.h>
43 #include <vtkRenderWindow.h>
44
45 //------------------------------------------------------------------------------
46 // Create the tool and automagically (I like this word) insert it in
47 // the main window menu.
48 ADD_TOOL(vvToolROIManager);
49 //------------------------------------------------------------------------------
50
51 //------------------------------------------------------------------------------
52 vvToolROIManager::vvToolROIManager(vvMainWindowBase * parent, Qt::WindowFlags f):
53   QWidget(parent->GetTab()), 
54   vvToolBase<vvToolROIManager>(parent),
55   Ui::vvToolROIManager()
56 {
57   // Store parent
58   mMainWindow = parent;
59   
60   // Assume the initial tab ROI index is 2
61   mIndexFirstTab = 2;
62
63   // Build the UI
64   Ui_vvToolROIManager::setupUi(this);
65   setAttribute(Qt::WA_DeleteOnClose);
66   mTree->clear();
67   mTree->header()->resizeSection(0, 30);
68   mGroupBoxROI->setEnabled(false);
69   
70   // Temporary disable "Load dicom" button
71   //  frame_4->hide();
72
73   // Set default LUT
74   mDefaultLUTColor = vtkSmartPointer<vtkLookupTable>::New();
75   for(int i=0; i<mDefaultLUTColor->GetNumberOfTableValues(); i++) {
76     double r = (rand()/(RAND_MAX+1.0));
77     double v = (rand()/(RAND_MAX+1.0));
78     double b = (rand()/(RAND_MAX+1.0));
79     mDefaultLUTColor->SetTableValue(i, r, v, b);
80   }
81 #include "vvDefaultLut.h"
82
83   // Initialization
84   mCurrentSlicerManager = NULL;
85   mNumberOfVisibleROI = 0;
86   mNumberOfVisibleContourROI = 0;
87   mOpenFileBrowserFlag = true; // by default, open the file browser when the tool is launched
88
89   // InitializeNewTool must be called to start
90 }
91 //------------------------------------------------------------------------------
92
93
94 //------------------------------------------------------------------------------
95 vvToolROIManager::~vvToolROIManager()
96 {
97   mROIActorsList.clear();
98 }
99 //------------------------------------------------------------------------------
100
101
102 //------------------------------------------------------------------------------
103 // STATIC
104 void vvToolROIManager::Initialize() {
105   SetToolName("ROIManager");
106   SetToolMenuName("Display ROI (binary image)");
107   SetToolIconFilename(":/common/icons/tool-roi.png");
108   SetToolTip("Display ROI from a binary image.");
109   SetToolExperimental(false);
110 }
111 //------------------------------------------------------------------------------
112
113
114
115 //------------------------------------------------------------------------------
116 void  vvToolROIManager::InitializeNewTool(bool ReadStateFlag) 
117 {
118   // Check if we need to start a new tool or read in the state file to load
119   if (ReadStateFlag == false) {
120     // Select the current image as the target
121     int i = mMainWindow->GetSlicerManagerCurrentIndex();
122     mCurrentSlicerManager = mMainWindow->GetSlicerManagers()[i];
123     // Set it as current (only if not ReadStateFlag)
124     mMainWindow->GetTab()->setCurrentIndex(mIndexFirstTab);
125   }
126   else {
127     // Set the first tab in front to avoid displaying two roimanager
128     // in the same tab. Because toolcreatorBase do show() and I am too
129     // lazy to find another solution now.
130     mMainWindow->GetTab()->setCurrentIndex(0);
131
132     // Read all information in the XML
133     ReadXMLInformation();
134     
135     // Check that a ROI is not already present 
136     mInitialImageIndex += mImageIndex;
137     if (mInitialImageIndex >= mMainWindow->GetSlicerManagers().size()) {
138       QMessageBox::warning(this, "ROIManager tool", QString("Image index %1 not found, abort.").arg(mInitialImageIndex));
139       close();
140       return;
141     }
142     
143     // Set the attached image
144     mCurrentSlicerManager = mMainWindow->GetSlicerManagers()[mInitialImageIndex];
145   }
146
147   // Tab insertion, check that another tool does not already exist for this image
148   std::vector<vvToolBaseBase*> & tools = 
149     vvToolManager::GetInstance()->GetToolCreatorFromName(GetToolName())->GetListOfTool();
150   if (tools.size() > 0) {
151     for(uint i=0; i<tools.size()-1; i++) { // current tool is last
152       vvToolROIManager * t = dynamic_cast<vvToolROIManager*>(tools[i]);
153       if (mCurrentSlicerManager == t->GetCurrentSlicerManager()) {
154         QMessageBox::warning(this, "ROIManager tool", "Already a ROI for this image, abort.");
155         close();
156         return;
157       }
158     }
159   }
160
161   // Display tool in the correct tab
162   QWidget * tab = qFindChild<QWidget*>(mMainWindow->GetTab(), "ROItab");
163   tab->layout()->addWidget(this);
164  
165   // If not read in a file we start automatically the browser to load
166   // a roi file (binary image)
167   if (ReadStateFlag) {    
168     mOpenFileBrowserFlag = false;
169     InputIsSelected(mCurrentSlicerManager);
170     mOpenFileBrowserFlag = true;
171   }
172   else InputIsSelected(mCurrentSlicerManager);
173
174   // Load ROI (if read in the XML files, empty otherwise)
175   OpenBinaryImage(mROIFilenames);
176
177   // Set the options to the open roi
178   for(uint i=0; i<mROIActorsParamList.size(); i++) {
179     QSharedPointer<vvROIActor> roi = mROIActorsList[i];
180     QSharedPointer<vvROIActor> roi_param = mROIActorsParamList[i];
181     roi->CopyParameters(roi_param);
182
183     // Update Tree
184     QTreeWidgetItem * w = mMapROIToTreeWidget[roi->GetROI()];
185     QBrush brush(QColor(roi->GetROI()->GetDisplayColor()[0]*255,
186                         roi->GetROI()->GetDisplayColor()[1]*255,
187                         roi->GetROI()->GetDisplayColor()[2]*255));
188     brush.setStyle(Qt::SolidPattern);
189     w->setBackground(2, brush);
190     w->setText(3, QString("%1").arg(roi->GetDepth()));  
191     roi->UpdateColor();
192   }
193
194   // Display the ROI
195   UpdateAllContours();
196   UpdateAllROIStatus(); 
197
198   // Connect event from mainwindow to this widget
199   connect(mMainWindow, SIGNAL(AnImageIsBeingClosed(vvSlicerManager *)), 
200           this, SLOT(AnImageIsBeingClosed(vvSlicerManager *)));
201   connect(mMainWindow, SIGNAL(SelectedImageHasChanged(vvSlicerManager *)), 
202           this, SLOT(SelectedImageHasChanged(vvSlicerManager *)));
203   connect(mOpenBinaryButton, SIGNAL(clicked()), this, SLOT(OpenBinaryImage()));
204   connect(mOpenDicomButton, SIGNAL(clicked()), this, SLOT(OpenDicomImage()));
205   connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
206   connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
207   connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
208   connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
209   connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));  
210   connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
211   connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
212   connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
213   connect(mReloadButton, SIGNAL(clicked()), this, SLOT(ReloadCurrentROI()));
214   connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
215   connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
216   connect(mCloseButton, SIGNAL(clicked()), this, SLOT(close()));
217 }
218 //------------------------------------------------------------------------------
219
220
221 //------------------------------------------------------------------------------
222 void vvToolROIManager::InputIsSelected(vvSlicerManager *m)
223 {
224   // Initialization
225   mCurrentSlicerManager = m;
226   mCurrentImage = mCurrentSlicerManager->GetImage();
227
228   // Refuse if non 3D image
229   if (mCurrentImage->GetNumberOfDimensions() != 3) {
230     QMessageBox::information(this,tr("Sorry only 3D yet"), tr("Sorry only 3D yet"));
231     close();
232     return;
233   }
234
235   // Change gui
236   mLabelInputInfo->setText(QString("%1").arg(m->GetFileName().c_str()));
237
238   // Auto display browser to select new contours 
239   if (mOpenFileBrowserFlag) OpenBinaryImage();
240 }
241 //------------------------------------------------------------------------------
242
243
244 //------------------------------------------------------------------------------
245 void vvToolROIManager::AnImageIsBeingClosed(vvSlicerManager * m)
246 {
247   if (m == mCurrentSlicerManager) { 
248     close();
249     return;
250   }
251 }
252 //------------------------------------------------------------------------------
253
254
255 //------------------------------------------------------------------------------
256 void vvToolROIManager::close()
257 {
258   disconnect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
259   disconnect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
260   disconnect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
261   disconnect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
262   disconnect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));  
263   disconnect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
264   disconnect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
265   disconnect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
266
267   // Remove actors
268   for (unsigned int i = 0; i < mROIActorsList.size(); i++) {
269     mROIActorsList[i]->RemoveActors();
270   }
271   mROIActorsList.clear();
272
273   QWidget::close();
274   for(int i=0; i<mCurrentSlicerManager->GetNumberOfSlicers(); i++) {
275     mCurrentSlicerManager->GetSlicer(i)->Render();
276   }
277 }
278 //------------------------------------------------------------------------------
279
280
281 //------------------------------------------------------------------------------
282 void vvToolROIManager::SelectedImageHasChanged(vvSlicerManager * m) {
283
284   if (mCurrentSlicerManager == NULL) return;
285   if (m == NULL) return;
286   if (m != mCurrentSlicerManager) hide(); 
287   else {
288     show();
289   }
290 }
291 //------------------------------------------------------------------------------
292
293
294 //------------------------------------------------------------------------------
295 void vvToolROIManager::OpenBinaryImage() 
296 {
297   // Open images
298   QString Extensions = "Images or Dicom-Struct files ( *.mha *.mhd *.hdr *.his *.dcm RS*)";
299   Extensions += ";;All Files (*)";
300   QStringList filename =
301     QFileDialog::getOpenFileNames(this,tr("Open binary image"),
302                                   mMainWindowBase->GetInputPathName(),Extensions);
303   if (filename.size() > 1) OpenBinaryImage(filename);
304   if (filename.size() == 0) return;
305   
306 }
307 //------------------------------------------------------------------------------
308
309
310 //------------------------------------------------------------------------------
311 void vvToolROIManager::OpenBinaryImage(QStringList & filename) 
312 {
313   if (filename.size() == 0) return;
314   
315   // For each selected file, open the image
316   for(int i=0; i<filename.size(); i++) {
317     // Open Image
318     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
319     vvImageReader::Pointer reader = vvImageReader::New();
320     std::vector<std::string> filenames;
321     filenames.push_back(filename[i].toStdString());
322     reader->SetInputFilenames(filenames);
323     reader->Update(vvImageReader::IMAGE);
324     QApplication::restoreOverrideCursor();
325
326     if (reader->GetLastError().size() != 0) {
327       std::cerr << "Error while reading " << filename[i].toStdString() << std::endl;
328       QString error = "Cannot open file \n";
329       error += reader->GetLastError().c_str();
330       QMessageBox::information(this,tr("Reading problem"),error);
331       return;
332     }
333     vvImage::Pointer binaryImage = reader->GetOutput();
334     AddImage(binaryImage, filename[i].toStdString(), mBackgroundValueSpinBox->value(),
335              (!mBGModeCheckBox->isChecked()));
336     //    mOpenedBinaryImage.push_back(binaryImage);
337     mOpenedBinaryImageFilenames.push_back(filename[i]);
338     //mMapImageToIndex[binaryImage]=mOpenedBinaryImageFilenames.size()-1;
339   }
340
341   // Update the contours
342   UpdateAllContours(); 
343 }
344 //------------------------------------------------------------------------------
345
346
347 //------------------------------------------------------------------------------
348 void vvToolROIManager::OpenDicomImage() 
349 {
350   DD("OpenDicomImage");
351   QString Extensions = "Dicom Files ( *.dcm RS*)";
352   Extensions += ";;All Files (*)";
353   QString file = QFileDialog::getOpenFileName(this,tr("Merge Images"), 
354                                               mMainWindow->GetInputPathName(), 
355                                               Extensions);
356   if (file.isNull()) return;
357
358   //  AddDCStructContour(index, file);
359   vvMeshReader reader;
360   reader.SetFilename(file.toStdString());
361   vvStructSelector selector;
362   selector.SetStructures(reader.GetROINames());
363   // selector.EnablePropagationCheckBox(); FIXME Disable
364
365   // FIXME : change text -> allow to save binary image
366
367   if (selector.exec()) {
368     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
369     reader.SetSelectedItems(selector.getSelectedItems());
370     reader.SetImage(mCurrentSlicerManager->GetImage());
371     // reader.Update();
372     
373     // Read and display information
374     clitk::DicomRT_StructureSet::Pointer s = clitk::DicomRT_StructureSet::New();
375     s->Read(file.toStdString());
376     s->Print(std::cout);
377
378     // FIXME -> selection
379
380     DD("here");
381     clitk::DicomRTStruct2ImageFilter filter;
382     filter.SetCropMaskEnabled(true); // FIXME
383     filter.SetImage(mCurrentImage);  // Used FIXME -> change to set IMAGE
384     filter.SetROI(s->GetROIFromROINumber(1));  // FIXME selection
385     filter.SetWriteOutputFlag(false);
386     filter.Update();  
387
388     DD("debug");
389     typedef itk::Image<unsigned char, 3> ImageType;
390     typedef itk::VTKImageToImageFilter<ImageType> ConnectorType;
391     ConnectorType::Pointer connector = ConnectorType::New();
392     connector->SetInput(filter.GetOutput());
393     connector->Update();
394     clitk::writeImage<ImageType>(connector->GetOutput(), "toto.mha");
395
396     // Get image
397     DD("filter done");
398     vvImage::Pointer binaryImage = vvImage::New();
399     binaryImage->AddVtkImage(filter.GetOutput());
400     
401     // DEBUG  write image
402     DD("write debug");
403     vvImageWriter::Pointer writer = vvImageWriter::New();
404     writer->SetOutputFileName("bidon.mha");
405     writer->SetInput(binaryImage);
406     writer->Update();
407     
408     // Add to gui
409     DD("gui");
410     AddImage(binaryImage, file.toStdString(), mBackgroundValueSpinBox->value(),
411              (!mBGModeCheckBox->isChecked()));
412     mOpenedBinaryImageFilenames.push_back(file);
413
414     // std::vector<vvMesh::Pointer> contours=reader.GetOutput();
415     // for (std::vector<vvMesh::Pointer>::iterator i=contours.begin();
416     //      i!=contours.end(); i++)
417     //   AddContour(index,*i,selector.PropagationEnabled());
418     QApplication::restoreOverrideCursor();
419   }
420
421
422
423 }
424 //------------------------------------------------------------------------------
425
426
427 //------------------------------------------------------------------------------
428 void vvToolROIManager::AddImage(vvImage * binaryImage, std::string filename, 
429                                 double BG, bool modeBG) 
430 {
431   // Check Dimension
432   int dim = mCurrentImage->GetNumberOfDimensions();
433   int bin_dim = binaryImage->GetNumberOfDimensions();
434   if (dim < bin_dim) {
435     std::ostringstream os;
436     os << "Error. Loaded binary image is " << bin_dim
437        << "D while selected image is " << dim << "D" << std::endl;
438     QMessageBox::information(this,tr("Reading problem"),os.str().c_str());
439     return;
440   }
441   
442   // Compute roi index
443   int n = mROIList.size();
444   
445   // Compute the name of the new ROI
446   std::ostringstream oss;
447   oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(filename));
448   std::string name = oss.str();
449   
450   // Set color
451   std::vector<double> color;
452   color.push_back(1);
453   color.push_back(0);
454   color.push_back(0);
455
456   // Create ROI
457   clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
458   roi->SetFromBinaryImage(binaryImage, n, name, color, filename);
459
460   // Add a new roi to the list
461   mROIList.push_back(roi);
462  
463   // Set BG or FG mode
464   if (modeBG) 
465     roi->SetBackgroundValueLabelImage(BG);
466   else 
467     roi->SetForegroundValueLabelImage(BG);
468   
469   // Change color
470   if (n<mDefaultLUTColor->GetNumberOfTableValues ()) {
471     double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ());
472     roi->SetDisplayColor(color[0], color[1], color[2]);
473   }
474   
475   // Add a new roi actor
476   QSharedPointer<vvROIActor> actor = QSharedPointer<vvROIActor>(new vvROIActor);
477   actor->SetBGMode(modeBG);
478   actor->SetROI(roi);
479   actor->SetSlicerManager(mCurrentSlicerManager);
480   actor->Initialize(n+1); // depth is n+1 to start at 1
481   mROIActorsList.push_back(actor);
482   
483   // CheckBox for "All"
484   if (actor->IsVisible()) mNumberOfVisibleROI++;
485   if (actor->IsContourVisible()) mNumberOfVisibleContourROI++;
486   
487   // Add ROI in tree
488   mTreeWidgetList.push_back(QSharedPointer<QTreeWidgetItem>(new QTreeWidgetItem(mTree)));
489   QTreeWidgetItem * w = mTreeWidgetList.back().data();
490   w->setText(0, QString("%1").arg(roi->GetROINumber()));
491   w->setText(1, QString("%1").arg(roi->GetName().c_str()));
492   w->setText(3, QString("%1").arg(actor->GetDepth()));  
493   QBrush brush(QColor(roi->GetDisplayColor()[0]*255, 
494                       roi->GetDisplayColor()[1]*255, 
495                       roi->GetDisplayColor()[2]*255));
496   brush.setStyle(Qt::SolidPattern);
497   w->setBackground(2, brush);
498   mMapROIToTreeWidget[roi] = w;
499   mMapTreeWidgetToROI[w] = roi;
500   mTree->resizeColumnToContents(0);
501   mTree->resizeColumnToContents(1);
502
503   // Update 
504   UpdateAllROIStatus(); 
505 }
506 //------------------------------------------------------------------------------
507
508
509 //------------------------------------------------------------------------------
510 void vvToolROIManager::UpdateAllContours() 
511 {
512   if (mCurrentSlicerManager == NULL) return;
513   // Render loaded ROIs (the first is sufficient)
514   for(unsigned int i=0; i<mROIList.size(); i++) {
515     mROIActorsList[i]->Update();
516   }
517   for(int i=0; i<mCurrentSlicerManager->GetNumberOfSlicers(); i++) {
518     mCurrentSlicerManager->GetSlicer(i)->Render();
519   }
520 }
521 //------------------------------------------------------------------------------
522
523
524 //------------------------------------------------------------------------------
525 void vvToolROIManager::UpdateAllROIStatus() {
526   int nbVisible = 0;
527   int nb = mROIList.size();
528   for(int i=0; i<nb; i++) {
529     if (mROIActorsList[i]->IsVisible()) {
530       nbVisible++;
531     }
532   }
533
534   // change the states
535   disconnect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));  
536   disconnect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
537   if (nbVisible == nb) mCheckBoxShowAll->setCheckState(Qt::Checked);
538   else {
539     if (nbVisible == 0) mCheckBoxShowAll->setCheckState(Qt::Unchecked);
540     else mCheckBoxShowAll->setCheckState(Qt::PartiallyChecked);
541   }
542   connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
543   connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
544 }
545 //------------------------------------------------------------------------------
546
547
548 //------------------------------------------------------------------------------
549 void vvToolROIManager::SelectedItemChangedInTree() {
550   // Search which roi is selected
551   QList<QTreeWidgetItem *> l = mTree->selectedItems();
552   if (l.size() == 0) {
553     //    mCurrentROIActor = 0;
554     mCurrentROI = NULL;
555     mGroupBoxROI->setEnabled(false);
556     return;
557   }
558   QTreeWidgetItem * w = l[0];
559   if (w == NULL) return;
560   if (w == 0) return;
561   if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
562     //    mCurrentROIActor = 0;
563     mCurrentROI = NULL;
564     mGroupBoxROI->setEnabled(false);
565     return;
566   }
567   if (w == NULL) return;
568   clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w];
569   if (roi == NULL) return; // sometimes it is called while there is no roi anymore
570
571   // Get selected roi actor
572   int n = roi->GetROINumber();
573   QSharedPointer<vvROIActor> actor = mROIActorsList[n];
574   mCurrentROI = roi;
575   mCurrentROIActor = actor;
576
577   // Warning -> avoid unuseful Render here by disconnect slider 
578   // Update GUI
579   disconnect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
580   disconnect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
581   disconnect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
582   disconnect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
583   disconnect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));  
584   disconnect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
585   disconnect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
586   disconnect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
587
588   mROInameLabel->setText(roi->GetName().c_str());
589   mCheckBoxShow->setChecked(actor->IsVisible());
590   mContourCheckBoxShow->setChecked(actor->IsContourVisible());
591   mContourWidthSpinBox->setValue(actor->GetContourWidth());
592   mDepthSpinBox->setValue(actor->GetDepth());
593   w->setText(3, QString("%1").arg(actor->GetDepth()));
594   mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100));
595   mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100));
596
597   connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
598   connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
599   connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
600   connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
601   connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));  
602   connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
603   connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
604   connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
605
606   
607   // Set the current color to the selected ROI name
608   mROInameLabel->setAutoFillBackground(true);// # This is important!!
609   // mROInameLabel->setStyleSheet("QLabel { background-color : red; color : blue; }");
610   QColor color = QColor(mCurrentROI->GetDisplayColor()[0]*255,
611                         mCurrentROI->GetDisplayColor()[1]*255,
612                         mCurrentROI->GetDisplayColor()[2]*255);
613   // QString values = QString("%1, %2, %3").arg(color.red()).arg(color.green()).arg(color.blue());
614   // mROInameLabel->setStyleSheet("QLabel { background-color: rgb("+values+"); }");
615
616   QPalette* palette = new QPalette();
617   QColor colorFG = QColor((1-mCurrentROI->GetDisplayColor()[0])*255,
618                           (1-mCurrentROI->GetDisplayColor()[1])*255,
619                           (1-mCurrentROI->GetDisplayColor()[2])*255);
620   palette->setColor(QPalette::WindowText,colorFG);
621   palette->setColor(QPalette::Background, color);
622   mROInameLabel->setPalette(*palette);  
623
624   // Enable the group box (in case no selection before)
625   mGroupBoxROI->setEnabled(true);
626 }
627 //------------------------------------------------------------------------------
628
629
630 //------------------------------------------------------------------------------
631 void vvToolROIManager::VisibleROIToggled(bool b) {
632   if (mCurrentROIActor == NULL) return;
633   if (b == mCurrentROIActor->IsVisible()) return; // nothing to do
634   mCurrentROIActor->SetVisible(b);
635   UpdateAllROIStatus();
636   mCurrentSlicerManager->Render(); 
637 }
638 //------------------------------------------------------------------------------
639
640
641 //------------------------------------------------------------------------------
642 void vvToolROIManager::VisibleContourROIToggled(bool b) {
643   if (mCurrentROIActor == NULL) return;
644   if (mCurrentROIActor->IsContourVisible() == b) return; // nothing to do
645   mCurrentROIActor->SetContourVisible(b);
646   mCurrentROIActor->UpdateColor();
647   mCurrentSlicerManager->Render(); 
648 }
649 //------------------------------------------------------------------------------
650
651
652 //------------------------------------------------------------------------------
653 void vvToolROIManager::OpacityChanged(int v) {
654   if (mCurrentROIActor == NULL) return;
655   mCurrentROIActor->SetOpacity((double)v/100.0);
656   mCurrentROIActor->UpdateColor();
657   mCurrentSlicerManager->Render(); 
658 }
659 //------------------------------------------------------------------------------
660
661
662 //------------------------------------------------------------------------------
663 void vvToolROIManager::AllVisibleROIToggled(int b) {
664   bool status = false;
665   if ((mCheckBoxShowAll->checkState() == Qt::Checked) ||
666       (mCheckBoxShowAll->checkState() == Qt::PartiallyChecked))  status = true;
667
668   for(uint i=0; i<mROIList.size(); i++) {
669     mROIActorsList[i]->SetVisible(status);
670   }
671   if (status) mCheckBoxShowAll->setCheckState(Qt::Checked);
672   else  mCheckBoxShowAll->setCheckState(Qt::Unchecked);
673   mCheckBoxShow->setChecked(status);
674   mCurrentSlicerManager->Render(); 
675 }
676 //------------------------------------------------------------------------------
677
678
679 //------------------------------------------------------------------------------
680 void vvToolROIManager::AllVisibleContourROIToggled(bool b) {
681   bool status = false;
682   if ((mContourCheckBoxShowAll->checkState() == Qt::Checked) ||
683       (mContourCheckBoxShowAll->checkState() == Qt::PartiallyChecked))  status = true;
684   // Update current 
685   for(uint i=0; i<mROIActorsList.size(); i++) {
686     mROIActorsList[i]->SetContourVisible(status);
687   }
688   // Update current selection
689   if (status) mContourCheckBoxShowAll->setCheckState(Qt::Checked);
690   else  mContourCheckBoxShowAll->setCheckState(Qt::Unchecked);
691   mContourCheckBoxShow->setChecked(status);
692   mCurrentSlicerManager->Render(); 
693 }
694 //------------------------------------------------------------------------------
695
696
697 //------------------------------------------------------------------------------
698 void vvToolROIManager::ChangeColor() {
699   if (mCurrentROIActor == NULL) return;
700   QColor color;
701   color.setRgbF(mCurrentROIActor->GetROI()->GetDisplayColor()[0],
702                 mCurrentROIActor->GetROI()->GetDisplayColor()[1],
703                 mCurrentROIActor->GetROI()->GetDisplayColor()[2]);
704   QColor c = QColorDialog::getColor(color, this, "Choose the ROI color");
705   mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
706   mCurrentROIActor->UpdateColor();
707
708   QTreeWidgetItem * w = mMapROIToTreeWidget[mCurrentROI];
709   QBrush brush(QColor(mCurrentROI->GetDisplayColor()[0]*255,
710                       mCurrentROI->GetDisplayColor()[1]*255,
711                       mCurrentROI->GetDisplayColor()[2]*255));
712   brush.setStyle(Qt::SolidPattern);
713   w->setBackground(2, brush);
714   // Render
715   mCurrentSlicerManager->Render();
716 }
717 //------------------------------------------------------------------------------
718
719
720 //------------------------------------------------------------------------------
721 void vvToolROIManager::ChangeContourColor() {
722   if (mCurrentROIActor == NULL) return;
723   QColor color;
724   color.setRgbF(mCurrentROIActor->GetContourColor()[0], 
725                 mCurrentROIActor->GetContourColor()[1], 
726                 mCurrentROIActor->GetContourColor()[2]);
727   //  QColorDialog d(color);
728   QColor c = QColorDialog::getColor(color, this, "Choose the contour color");
729   if (!c.isValid()) return; // User cancel
730   mCurrentROIActor->SetContourColor(c.redF(), c.greenF(), c.blueF());
731   mCurrentROIActor->UpdateColor();
732   mCurrentSlicerManager->Render();
733 }
734 //------------------------------------------------------------------------------
735
736
737 //------------------------------------------------------------------------------
738 void vvToolROIManager::ChangeContourWidth(int n) {
739   if (mCurrentROIActor == NULL) return;
740     mCurrentROIActor->SetContourWidth(n);
741     mCurrentROIActor->UpdateColor();
742     mCurrentSlicerManager->Render();
743 }
744 //------------------------------------------------------------------------------
745
746
747 //------------------------------------------------------------------------------
748 void vvToolROIManager::ChangeDepth(int n) {
749   if (mCurrentROIActor == NULL) return;
750   mCurrentROIActor->SetDepth(n);
751   // mCurrentROIActor->UpdateImage(); // FIXME  
752   mCurrentSlicerManager->Render();
753   QList<QTreeWidgetItem *> l = mTree->selectedItems();
754   QTreeWidgetItem * w = l[0];
755   w->setText(3, QString("%1").arg(mCurrentROIActor->GetDepth()));
756 }
757 //------------------------------------------------------------------------------
758
759
760 //------------------------------------------------------------------------------
761 void vvToolROIManager::ReloadCurrentROI() {
762
763   // Remove all contours/overlay first
764   bool visible = mCurrentROIActor->IsVisible();
765   bool cvisible = mCurrentROIActor->IsContourVisible();
766   mCurrentROIActor->SetVisible(false);
767   mCurrentROIActor->SetContourVisible(false);
768   mCurrentSlicerManager->Render();
769   
770   // Reload image
771   vvImageReader::Pointer reader = vvImageReader::New();
772   reader->SetInputFilename(mCurrentROI->GetFilename());
773   reader->Update(vvImageReader::IMAGE);
774   if (reader->GetLastError() != "") {
775     QMessageBox::information(mMainWindowBase, tr("Sorry, error. Could not reload"), 
776                              reader->GetLastError().c_str());
777     return;
778   }
779
780   // Free the previous image
781   mCurrentROI->GetImage()->GetFirstVTKImageData()->ReleaseData(); // Needed to free
782   mCurrentROI->GetImage()->Reset();
783   mCurrentROI->SetImage(reader->GetOutput());
784
785   mCurrentROIActor->RemoveActors();
786
787   // Update visu
788   mCurrentROIActor->UpdateImage();
789   mCurrentROIActor->SetVisible(visible);
790   mCurrentROIActor->SetContourVisible(cvisible);
791   mCurrentSlicerManager->Render();    
792 }
793 //------------------------------------------------------------------------------
794
795
796 //------------------------------------------------------------------------------
797 void  vvToolROIManager::SaveState(std::auto_ptr<QXmlStreamWriter> & m_XmlWriter)
798 {
799   // Get index of the image
800   int n = mMainWindow->GetSlicerManagers().size();
801   int index=-1;
802   for(int i=0; i<n; i++) {
803     if (mCurrentSlicerManager == mMainWindow->GetSlicerManagers()[i]) index = i;
804   }
805   if (index == -1) {
806     std::cerr << "Error while writing state for ROIManager tool no currentimage founded." << std::endl;
807     return;
808   }
809   m_XmlWriter->writeTextElement("Image_Index", QString::number(index));
810
811
812   // Write ROI
813   for(uint i=0; i<mROIActorsList.size(); i++) {
814     QSharedPointer<vvROIActor> roi = mROIActorsList[i];
815
816     m_XmlWriter->writeStartElement("ROI");
817     m_XmlWriter->writeTextElement("Image", mOpenedBinaryImageFilenames[i]);
818
819     m_XmlWriter->writeStartElement("Overlay");
820     m_XmlWriter->writeAttribute("Red",  QString("%1").arg(roi->GetOverlayColor()[0]));
821     m_XmlWriter->writeAttribute("Green",QString("%1").arg(roi->GetOverlayColor()[1]));
822     m_XmlWriter->writeAttribute("Blue", QString("%1").arg(roi->GetOverlayColor()[2]));
823     m_XmlWriter->writeAttribute("Visible", QString("%1").arg(roi->IsVisible()));
824     m_XmlWriter->writeAttribute("Opacity", QString("%1").arg(roi->GetOpacity()));
825     m_XmlWriter->writeAttribute("Depth", QString("%1").arg(roi->GetDepth()));
826     m_XmlWriter->writeEndElement();
827    
828     m_XmlWriter->writeStartElement("Contour");
829     m_XmlWriter->writeAttribute("Red",  QString("%1").arg(roi->GetContourColor()[0]));
830     m_XmlWriter->writeAttribute("Green",QString("%1").arg(roi->GetContourColor()[1]));
831     m_XmlWriter->writeAttribute("Blue", QString("%1").arg(roi->GetContourColor()[2]));
832     m_XmlWriter->writeAttribute("Visible", QString("%1").arg(roi->IsContourVisible()));
833     m_XmlWriter->writeAttribute("Width", QString("%1").arg(roi->GetContourWidth()));
834     m_XmlWriter->writeEndElement();
835
836     m_XmlWriter->writeEndElement();
837   }
838 }
839 //------------------------------------------------------------------------------
840
841
842 //------------------------------------------------------------------------------
843 void vvToolROIManager::ReadXMLInformation() 
844 {
845   std::string value="";
846   mInitialImageIndex = -1;
847   while (!(m_XmlReader->isEndElement() && value == GetToolName().toStdString())) { 
848     m_XmlReader->readNext();
849     value = m_XmlReader->qualifiedName().toString().toStdString();
850     
851     if (value == "Image_Index") 
852       mInitialImageIndex = m_XmlReader->readElementText().toInt();
853     
854     if (m_XmlReader->isStartElement()) {
855       if (value == "ROI") {
856         ReadXMLInformation_ROI();
857       }      
858     }
859   }
860 }
861 //------------------------------------------------------------------------------
862
863
864 //------------------------------------------------------------------------------
865 void vvToolROIManager::ReadXMLInformation_ROI() 
866 {
867   QString s;
868   std::string value="";
869   QSharedPointer<vvROIActor> param = QSharedPointer<vvROIActor>(new vvROIActor);
870   param->SetVisible(true);
871   clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
872   // r->SetDisplayColor(1,1,1);
873   param->SetROI(roi);
874
875   float r=1.0,g=1.0,b=1.0;
876   float cr=1.0,cg=1.0,cb=1.0;
877   float opacity = 0.7;
878   bool visible = true;
879   bool cvisible = true;
880   int width = 1;
881   int depth=1;
882
883   while (!(m_XmlReader->isEndElement() && value == "ROI")) { 
884     m_XmlReader->readNext();
885     value = m_XmlReader->qualifiedName().toString().toStdString();
886     if (value == "Image") {
887       s = m_XmlReader->readElementText();
888     }
889     
890     if (value == "Overlay" && m_XmlReader->isStartElement()) {
891       QXmlStreamAttributes attributes = m_XmlReader->attributes();
892       if (!m_XmlReader->hasError())
893          r = attributes.value("Red").toString().toFloat();
894       if (!m_XmlReader->hasError())
895          g = attributes.value("Green").toString().toFloat();
896       if (!m_XmlReader->hasError())
897          b = attributes.value("Blue").toString().toFloat();
898       if (!m_XmlReader->hasError())
899          visible = attributes.value("Visible").toString().toInt();
900       if (!m_XmlReader->hasError())
901          opacity = attributes.value("Opacity").toString().toFloat();
902      if (!m_XmlReader->hasError())
903          depth = attributes.value("Depth").toString().toFloat();
904     }
905
906
907     if (value == "Contour" && m_XmlReader->isStartElement()) {
908       QXmlStreamAttributes attributes = m_XmlReader->attributes();
909       if (!m_XmlReader->hasError())
910          cr = attributes.value("Red").toString().toFloat();
911       if (!m_XmlReader->hasError())
912          cg = attributes.value("Green").toString().toFloat();
913       if (!m_XmlReader->hasError())
914          cb = attributes.value("Blue").toString().toFloat();
915       if (!m_XmlReader->hasError())
916          cvisible = attributes.value("Visible").toString().toInt();
917       if (!m_XmlReader->hasError())
918          width = attributes.value("Width").toString().toFloat();
919     }
920     param->SetOverlayColor(r,g,b);
921     param->SetVisible(visible);
922     param->SetOpacity(opacity); 
923     param->SetDepth(depth); 
924
925     param->SetContourColor(cr,cg,cb);
926     param->SetContourVisible(cvisible);
927     param->SetContourWidth(width);
928   }
929   mROIFilenames.push_back(s);
930   mROIActorsParamList.push_back(param);
931 }
932 //------------------------------------------------------------------------------