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