]> Creatis software - clitk.git/blob - vv/vvToolROIManager.cxx
Debug RTStruct conversion with empty struc
[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     vtkSmartPointer<vtkMatrix4x4> transformMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
413     transformMatrix = mCurrentImage->GetTransform()[0]->GetMatrix();
414     s->SetTransformMatrix(transformMatrix);
415     s->Read(filename);
416
417     // Loop on selected struct
418     std::vector<int> list = selector.getSelectedItems();
419     for (uint i=0; i<list.size(); i++) {
420       p.SetProgress(i, list.size());
421
422       clitk::DicomRTStruct2ImageFilter filter;
423       filter.SetCropMaskEnabled(true);
424       filter.SetImage(mCurrentImage);
425       filter.SetROI(s->GetROIFromROINumber(list[i]));
426       filter.SetWriteOutputFlag(false);
427       filter.Update();
428
429       // Get image
430       vvImage::Pointer binaryImage = vvImage::New();
431       binaryImage->AddVtkImage(filter.GetOutput());
432
433       // Add to gui
434       AddImage(binaryImage, s->GetROIFromROINumber(list[i])->GetName(), "", 0, true); // "" = no filename
435       mOpenedBinaryImageFilenames.push_back(filename.c_str());
436     }
437
438     QApplication::restoreOverrideCursor();
439   }
440   // Update the contours
441   UpdateAllContours();
442 }
443 //------------------------------------------------------------------------------
444
445
446 //------------------------------------------------------------------------------
447 void vvToolROIManager::AddImage(vvImage * binaryImage,
448                                 std::string name,
449                                 std::string filename,
450                                 double BG, bool modeBG)
451 {
452   // Check Dimension
453   int dim = mCurrentImage->GetNumberOfDimensions();
454   int bin_dim = binaryImage->GetNumberOfDimensions();
455   if (dim < bin_dim) {
456     std::ostringstream os;
457     os << "Error. Loaded binary image is " << bin_dim
458        << "D while selected image is " << dim << "D" << std::endl;
459     QMessageBox::information(this,tr("Reading problem"),os.str().c_str());
460     return;
461   }
462
463   // Compute roi index
464   
465   int n = nbTotalROI;
466   ++nbTotalROI;
467   // Compute the name of the new ROI
468   // std::ostringstream oss;
469   // oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(filename));
470   // std::string name = oss.str();
471
472   // Set color
473   std::vector<double> color;
474   color.push_back(1);
475   color.push_back(0);
476   color.push_back(0);
477
478   // Create ROI
479   clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
480   roi->SetFromBinaryImage(binaryImage, mROIList.size(), name, color, filename);
481
482   // Add a new roi to the list
483   mROIList.push_back(roi);
484
485   // Set BG or FG mode
486   if (modeBG)
487     roi->SetBackgroundValueLabelImage(BG);
488   else
489     roi->SetForegroundValueLabelImage(BG);
490
491   // Change color
492   if (n<mDefaultLUTColor->GetNumberOfTableValues ()) {
493     double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ());
494     roi->SetDisplayColor(color[0], color[1], color[2]);
495   }
496
497   // Add a new roi actor
498   QSharedPointer<vvROIActor> actor = QSharedPointer<vvROIActor>(new vvROIActor);
499   actor->SetBGMode(modeBG);
500   actor->SetROI(roi);
501   actor->SetSlicerManager(mCurrentSlicerManager);
502   actor->Initialize(n+1); // depth is n+1 to start at 1
503   mROIActorsList.push_back(actor);
504
505   // CheckBox for "All"
506   if (actor->IsVisible()) mNumberOfVisibleROI++;
507   if (actor->IsContourVisible()) mNumberOfVisibleContourROI++;
508   AllVisibleContourROIToggled(1);
509   
510   // Add ROI in tree
511   mTreeWidgetList.push_back(QSharedPointer<QTreeWidgetItem>(new QTreeWidgetItem(mTree)));
512   QTreeWidgetItem * w = mTreeWidgetList.back().data();
513   w->setText(0, QString("%1").arg(roi->GetROINumber()));
514   w->setText(1, QString("%1").arg(roi->GetName().c_str()));
515   w->setText(3, QString("%1").arg(actor->GetDepth()));
516   QBrush brush(QColor(roi->GetDisplayColor()[0]*255,
517                       roi->GetDisplayColor()[1]*255,
518                       roi->GetDisplayColor()[2]*255));
519   brush.setStyle(Qt::SolidPattern);
520   w->setBackground(2, brush);
521   mMapROIToTreeWidget[roi] = w;
522   mMapTreeWidgetToROI[w] = roi;
523   mTree->resizeColumnToContents(0);
524   mTree->resizeColumnToContents(1);
525
526   // Update
527   UpdateAllROIStatus();
528   
529   if (mCurrentImage->GetNumberOfDimensions() > 3) {
530       
531     //Modifications to avoid display bug with a 4D image
532     QSharedPointer<vvROIActor> CurrentROIActorTemp;
533     CurrentROIActorTemp = mCurrentROIActor;
534     mCurrentROIActor = actor;
535   
536     int VisibleInWindow(0);
537     mCurrentSlicerManager->GetSlicer(VisibleInWindow)->SetCurrentPosition(-VTK_DOUBLE_MAX,-VTK_DOUBLE_MAX,-VTK_DOUBLE_MAX,mCurrentSlicerManager->GetSlicer(VisibleInWindow)->GetMaxCurrentTSlice());
538     mCurrentSlicerManager->GetSlicer(VisibleInWindow)->Render();
539   
540     VisibleROIToggled(false);
541     VisibleROIToggled(true);
542   
543     mCurrentROIActor = CurrentROIActorTemp;
544   
545   }
546   
547 }
548 //------------------------------------------------------------------------------
549
550
551 //------------------------------------------------------------------------------
552 void vvToolROIManager::UpdateAllContours()
553 {
554   if (mCurrentSlicerManager == NULL) return;
555   // Render loaded ROIs (the first is sufficient)
556   for(unsigned int i=0; i<mROIList.size(); i++) {
557     mROIActorsList[i]->Update();
558   }
559   //mCurrentSlicerManager->Render();
560 }
561 //------------------------------------------------------------------------------
562
563
564 //------------------------------------------------------------------------------
565 void vvToolROIManager::UpdateAllROIStatus()
566 {
567   int nbVisible = 0;
568   int nbContourVisible = 0;
569   int nb = mROIList.size();
570   for(int i=0; i<nb; i++) {
571     if (mROIActorsList[i]->IsVisible()) {
572       nbVisible++;
573     }
574     if (mROIActorsList[i]->IsContourVisible()) {
575       nbContourVisible++;
576     }
577   }
578
579   // change the states
580   disconnect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
581   disconnect(mContourCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleContourROIToggled(int)));
582   if (nbVisible == nb) mCheckBoxShowAll->setCheckState(Qt::Checked);
583   else {
584     if (nbVisible == 0) mCheckBoxShowAll->setCheckState(Qt::Unchecked);
585     else mCheckBoxShowAll->setCheckState(Qt::PartiallyChecked);
586   }
587   if (nbContourVisible == nb) mContourCheckBoxShowAll->setCheckState(Qt::Checked);
588   else {
589     if (nbContourVisible == 0) mContourCheckBoxShowAll->setCheckState(Qt::Unchecked);
590     else mContourCheckBoxShowAll->setCheckState(Qt::PartiallyChecked);
591   }
592   connect(mContourCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleContourROIToggled(int)));
593   connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
594 }
595 //------------------------------------------------------------------------------
596
597
598 //------------------------------------------------------------------------------
599 void vvToolROIManager::SelectedItemChangedInTree()
600 {
601   // Search which roi is selected
602   QList<QTreeWidgetItem *> l = mTree->selectedItems();
603   if (l.size() == 0) {
604     //    mCurrentROIActor = 0;
605     mCurrentROI = NULL;
606     mGroupBoxROI->setEnabled(false);
607     return;
608   }
609   QTreeWidgetItem * w = l[0];
610   if (w == NULL) return;
611   if (w == 0) return;
612   if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
613     //    mCurrentROIActor = 0;
614     mCurrentROI = NULL;
615     mGroupBoxROI->setEnabled(false);
616     return;
617   }
618   if (w == NULL) return;
619   clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w];
620   if (roi == NULL) return; // sometimes it is called while there is no roi anymore
621
622   // Get selected roi actor
623   int n = roi->GetROINumber();
624   QSharedPointer<vvROIActor> actor = mROIActorsList[n];
625   mCurrentROI = roi;
626   mCurrentROIActor = actor;
627
628   // Warning -> avoid unuseful Render here by disconnect slider
629   // Update GUI
630   disconnect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
631   disconnect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
632   disconnect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
633   disconnect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
634   disconnect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
635   disconnect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
636   disconnect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
637   disconnect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
638   disconnect(mRemoveButton, SIGNAL(clicked()), this, SLOT(RemoveROI()));
639
640   mROInameLabel->setText(roi->GetName().c_str());
641   mCheckBoxShow->setChecked(actor->IsVisible());
642   mContourCheckBoxShow->setChecked(actor->IsContourVisible());
643   mContourWidthSpinBox->setValue(actor->GetContourWidth());
644   mDepthSpinBox->setValue(actor->GetDepth());
645   w->setText(3, QString("%1").arg(actor->GetDepth()));
646   mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100));
647   mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100));
648
649   connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
650   connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
651   connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
652   connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
653   connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
654   connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
655   connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
656   connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
657   connect(mRemoveButton, SIGNAL(clicked()), this, SLOT(RemoveROI()));
658
659
660   // Set the current color to the selected ROI name
661   mROInameLabel->setAutoFillBackground(true);// # This is important!!
662   // mROInameLabel->setStyleSheet("QLabel { background-color : red; color : blue; }");
663   QColor color = QColor(mCurrentROI->GetDisplayColor()[0]*255,
664                         mCurrentROI->GetDisplayColor()[1]*255,
665                         mCurrentROI->GetDisplayColor()[2]*255);
666   // QString values = QString("%1, %2, %3").arg(color.red()).arg(color.green()).arg(color.blue());
667   // mROInameLabel->setStyleSheet("QLabel { background-color: rgb("+values+"); }");
668
669   QPalette* palette = new QPalette();
670   QColor colorFG = QColor((1-mCurrentROI->GetDisplayColor()[0])*255,
671                           (1-mCurrentROI->GetDisplayColor()[1])*255,
672                           (1-mCurrentROI->GetDisplayColor()[2])*255);
673   palette->setColor(QPalette::WindowText,colorFG);
674   palette->setColor(QPalette::Background, color);
675   mROInameLabel->setPalette(*palette);
676
677   // Enable the group box (in case no selection before)
678   mGroupBoxROI->setEnabled(true);
679 }
680 //------------------------------------------------------------------------------
681
682
683 //------------------------------------------------------------------------------
684 void vvToolROIManager::VisibleROIToggled(bool b)
685 {
686   if (mCurrentROIActor == NULL) return;
687   if (b == mCurrentROIActor->IsVisible()) return; // nothing to do
688   mCurrentROIActor->SetVisible(b);
689   UpdateAllROIStatus();
690   mCurrentSlicerManager->Render();
691 }
692 //------------------------------------------------------------------------------
693
694
695 //------------------------------------------------------------------------------
696 void vvToolROIManager::VisibleContourROIToggled(bool b)
697 {
698   if (mCurrentROIActor == NULL) return;
699   if (mCurrentROIActor->IsContourVisible() == b) return; // nothing to do
700   mCurrentROIActor->SetContourVisible(b);
701   mCurrentROIActor->UpdateColor();
702   UpdateAllROIStatus(); 
703   mCurrentSlicerManager->Render();
704 }
705 //------------------------------------------------------------------------------
706
707
708 //------------------------------------------------------------------------------
709 void vvToolROIManager::OpacityChanged(int v)
710 {
711   if (mCurrentROIActor == NULL) return;
712   mCurrentROIActor->SetOpacity((double)v/100.0);
713   mCurrentROIActor->UpdateColor();
714   mCurrentSlicerManager->Render();
715 }
716 //------------------------------------------------------------------------------
717
718
719 //------------------------------------------------------------------------------
720 void vvToolROIManager::AllVisibleROIToggled(int b)
721 {
722   disconnect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
723   bool status = false;
724   if ((mCheckBoxShowAll->checkState() == Qt::Checked) ||
725       (mCheckBoxShowAll->checkState() == Qt::PartiallyChecked))  status = true;
726
727   for(uint i=0; i<mROIList.size(); i++) {
728     mROIActorsList[i]->SetVisible(status);
729   }
730   if (status) mCheckBoxShowAll->setCheckState(Qt::Checked);
731   else  mCheckBoxShowAll->setCheckState(Qt::Unchecked);
732   mCheckBoxShow->setChecked(status);
733   mCurrentSlicerManager->Render();
734   connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
735 }
736 //------------------------------------------------------------------------------
737
738
739 //------------------------------------------------------------------------------
740 void vvToolROIManager::AllVisibleContourROIToggled(int b)
741 {
742   disconnect(mContourCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleContourROIToggled(int)));
743   bool status = false;
744   if ((mContourCheckBoxShowAll->checkState() == Qt::Checked) ||
745       (mContourCheckBoxShowAll->checkState() == Qt::PartiallyChecked))  status = true;
746   // Update current
747   for(uint i=0; i<mROIActorsList.size(); i++) {
748     mROIActorsList[i]->SetContourVisible(status);
749   }
750   // Update current selection
751   if (status) mContourCheckBoxShowAll->setCheckState(Qt::Checked);
752   else  mContourCheckBoxShowAll->setCheckState(Qt::Unchecked);
753   mContourCheckBoxShow->setChecked(status);
754   mCurrentSlicerManager->Render();
755   connect(mContourCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleContourROIToggled(int)));
756 }
757 //------------------------------------------------------------------------------
758
759
760 //------------------------------------------------------------------------------
761 void vvToolROIManager::ChangeColor()
762 {
763   if (mCurrentROIActor == NULL) return;
764   QColor color;
765   color.setRgbF(mCurrentROIActor->GetROI()->GetDisplayColor()[0],
766                 mCurrentROIActor->GetROI()->GetDisplayColor()[1],
767                 mCurrentROIActor->GetROI()->GetDisplayColor()[2]);
768   QColor c = QColorDialog::getColor(color, this, "Choose the ROI color");
769   if (!c.isValid()) return;// User cancel
770
771   mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
772   mCurrentROIActor->UpdateColor();
773
774   QTreeWidgetItem * w = mMapROIToTreeWidget[mCurrentROI];
775   QBrush brush(QColor(mCurrentROI->GetDisplayColor()[0]*255,
776                       mCurrentROI->GetDisplayColor()[1]*255,
777                       mCurrentROI->GetDisplayColor()[2]*255));
778   brush.setStyle(Qt::SolidPattern);
779   w->setBackground(2, brush);
780   // Render
781   mCurrentSlicerManager->Render();
782 }
783 //------------------------------------------------------------------------------
784
785
786 //------------------------------------------------------------------------------
787 void vvToolROIManager::ChangeContourColor()
788 {
789   if (mCurrentROIActor == NULL) return;
790   QColor color;
791   color.setRgbF(mCurrentROIActor->GetContourColor()[0],
792                 mCurrentROIActor->GetContourColor()[1],
793                 mCurrentROIActor->GetContourColor()[2]);
794   //  QColorDialog d(color);
795   QColor c = QColorDialog::getColor(color, this, "Choose the contour color");
796   if (!c.isValid()) return; // User cancel
797   mCurrentROIActor->SetContourColor(c.redF(), c.greenF(), c.blueF());
798   mCurrentROIActor->UpdateColor();
799   mCurrentSlicerManager->Render();
800 }
801 //------------------------------------------------------------------------------
802
803
804 //------------------------------------------------------------------------------
805 void vvToolROIManager::ChangeContourWidth(int n)
806 {
807   if (mCurrentROIActor == NULL) return;
808   mCurrentROIActor->SetContourWidth(n);
809   mCurrentROIActor->UpdateColor();
810   mCurrentSlicerManager->Render();
811 }
812 //------------------------------------------------------------------------------
813
814
815 //------------------------------------------------------------------------------
816 void vvToolROIManager::ChangeDepth(int n)
817 {
818   if (mCurrentROIActor == NULL) return;
819   mCurrentROIActor->SetDepth(n);
820   // mCurrentROIActor->UpdateImage(); // FIXME
821   mCurrentSlicerManager->Render();
822   QList<QTreeWidgetItem *> l = mTree->selectedItems();
823   QTreeWidgetItem * w = l[0];
824   w->setText(3, QString("%1").arg(mCurrentROIActor->GetDepth()));
825 }
826 //------------------------------------------------------------------------------
827
828
829 //------------------------------------------------------------------------------
830 void vvToolROIManager::ReloadCurrentROI()
831 {
832   if (mCurrentROI->GetFilename() == "") {
833     return; // do nothing (contour from rt struct do not reload)
834   }
835
836   // Remove all contours/overlay first
837   bool visible = mCurrentROIActor->IsVisible();
838   bool cvisible = mCurrentROIActor->IsContourVisible();
839   mCurrentROIActor->SetVisible(false);
840   mCurrentROIActor->SetContourVisible(false);
841   mCurrentSlicerManager->Render();
842
843   // Reload image
844   vvImageReader::Pointer reader = vvImageReader::New();
845   reader->SetInputFilename(mCurrentROI->GetFilename());
846   reader->Update(vvImageReader::IMAGE);
847   if (reader->GetLastError() != "") {
848     // No message just ignore (because can be from dicom)
849     // QMessageBox::information(mMainWindowBase, tr("Sorry, error. Could not reload"),
850     //                          reader->GetLastError().c_str());
851     return;
852   }
853
854   // Free the previous image
855   mCurrentROI->GetImage()->GetFirstVTKImageData()->ReleaseData(); // Needed to free
856   mCurrentROI->GetImage()->Reset();
857   mCurrentROI->SetImage(reader->GetOutput());
858
859   mCurrentROIActor->RemoveActors();
860
861   // Update visu
862   mCurrentROIActor->UpdateImage();
863   mCurrentROIActor->SetVisible(visible);
864   mCurrentROIActor->SetContourVisible(cvisible);
865   mCurrentSlicerManager->Render();
866 }
867 //------------------------------------------------------------------------------
868
869
870 //------------------------------------------------------------------------------
871 #if __cplusplus > 199711L
872 void  vvToolROIManager::SaveState(std::shared_ptr<QXmlStreamWriter> & m_XmlWriter)
873 #else
874 void  vvToolROIManager::SaveState(std::auto_ptr<QXmlStreamWriter> & m_XmlWriter)
875 #endif
876 {
877   // Get index of the image
878   int n = mMainWindow->GetSlicerManagers().size();
879   int index=-1;
880   for(int i=0; i<n; i++) {
881     if (mCurrentSlicerManager == mMainWindow->GetSlicerManagers()[i]) index = i;
882   }
883   if (index == -1) {
884     std::cerr << "Error while writing state for ROIManager tool no currentimage founded." << std::endl;
885     return;
886   }
887   m_XmlWriter->writeTextElement("Image_Index", QString::number(index));
888
889
890   // Write ROI
891   for(uint i=0; i<mROIActorsList.size(); i++) {
892     QSharedPointer<vvROIActor> roi = mROIActorsList[i];
893
894     m_XmlWriter->writeStartElement("ROI");
895     m_XmlWriter->writeTextElement("Image", mOpenedBinaryImageFilenames[i]);
896
897     m_XmlWriter->writeStartElement("Overlay");
898     m_XmlWriter->writeAttribute("Red",  QString("%1").arg(roi->GetOverlayColor()[0]));
899     m_XmlWriter->writeAttribute("Green",QString("%1").arg(roi->GetOverlayColor()[1]));
900     m_XmlWriter->writeAttribute("Blue", QString("%1").arg(roi->GetOverlayColor()[2]));
901     m_XmlWriter->writeAttribute("Visible", QString("%1").arg(roi->IsVisible()));
902     m_XmlWriter->writeAttribute("Opacity", QString("%1").arg(roi->GetOpacity()));
903     m_XmlWriter->writeAttribute("Depth", QString("%1").arg(roi->GetDepth()));
904     m_XmlWriter->writeEndElement();
905
906     m_XmlWriter->writeStartElement("Contour");
907     m_XmlWriter->writeAttribute("Red",  QString("%1").arg(roi->GetContourColor()[0]));
908     m_XmlWriter->writeAttribute("Green",QString("%1").arg(roi->GetContourColor()[1]));
909     m_XmlWriter->writeAttribute("Blue", QString("%1").arg(roi->GetContourColor()[2]));
910     m_XmlWriter->writeAttribute("Visible", QString("%1").arg(roi->IsContourVisible()));
911     m_XmlWriter->writeAttribute("Width", QString("%1").arg(roi->GetContourWidth()));
912     m_XmlWriter->writeEndElement();
913
914     m_XmlWriter->writeEndElement();
915   }
916 }
917 //------------------------------------------------------------------------------
918
919
920 //------------------------------------------------------------------------------
921 void vvToolROIManager::ReadXMLInformation()
922 {
923   std::string value="";
924   mInitialImageIndex = -1;
925   while (!(m_XmlReader->isEndElement() && value == GetToolName().toStdString())) {
926     m_XmlReader->readNext();
927     value = m_XmlReader->qualifiedName().toString().toStdString();
928
929     if (value == "Image_Index")
930       mInitialImageIndex = m_XmlReader->readElementText().toInt();
931
932     if (m_XmlReader->isStartElement()) {
933       if (value == "ROI") {
934         ReadXMLInformation_ROI();
935       }
936     }
937   }
938 }
939 //------------------------------------------------------------------------------
940
941
942 //------------------------------------------------------------------------------
943 void vvToolROIManager::ReadXMLInformation_ROI()
944 {
945   QString s;
946   std::string value="";
947   QSharedPointer<vvROIActor> param = QSharedPointer<vvROIActor>(new vvROIActor);
948   param->SetVisible(true);
949   clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
950   // r->SetDisplayColor(1,1,1);
951   param->SetROI(roi);
952
953   float r=1.0,g=1.0,b=1.0;
954   float cr=1.0,cg=1.0,cb=1.0;
955   float opacity = 0.7;
956   bool visible = true;
957   bool cvisible = true;
958   int width = 1;
959   int depth=1;
960
961   while (!(m_XmlReader->isEndElement() && value == "ROI")) {
962     m_XmlReader->readNext();
963     value = m_XmlReader->qualifiedName().toString().toStdString();
964     if (value == "Image") {
965       s = m_XmlReader->readElementText();
966     }
967
968     if (value == "Overlay" && m_XmlReader->isStartElement()) {
969       QXmlStreamAttributes attributes = m_XmlReader->attributes();
970       if (!m_XmlReader->hasError())
971         r = attributes.value("Red").toString().toFloat();
972       if (!m_XmlReader->hasError())
973         g = attributes.value("Green").toString().toFloat();
974       if (!m_XmlReader->hasError())
975         b = attributes.value("Blue").toString().toFloat();
976       if (!m_XmlReader->hasError())
977         visible = attributes.value("Visible").toString().toInt();
978       if (!m_XmlReader->hasError())
979         opacity = attributes.value("Opacity").toString().toFloat();
980       if (!m_XmlReader->hasError())
981         depth = attributes.value("Depth").toString().toFloat();
982     }
983
984
985     if (value == "Contour" && m_XmlReader->isStartElement()) {
986       QXmlStreamAttributes attributes = m_XmlReader->attributes();
987       if (!m_XmlReader->hasError())
988         cr = attributes.value("Red").toString().toFloat();
989       if (!m_XmlReader->hasError())
990         cg = attributes.value("Green").toString().toFloat();
991       if (!m_XmlReader->hasError())
992         cb = attributes.value("Blue").toString().toFloat();
993       if (!m_XmlReader->hasError())
994         cvisible = attributes.value("Visible").toString().toInt();
995       if (!m_XmlReader->hasError())
996         width = attributes.value("Width").toString().toFloat();
997     }
998     param->SetOverlayColor(r,g,b);
999     param->SetVisible(visible);
1000     param->SetOpacity(opacity);
1001     param->SetDepth(depth);
1002
1003     param->SetContourColor(cr,cg,cb);
1004     param->SetContourVisible(cvisible);
1005     param->SetContourWidth(width);
1006   }
1007   mROIFilenames.push_back(s);
1008   mROIActorsParamList.push_back(param);
1009 }
1010 //------------------------------------------------------------------------------