1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
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
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.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
20 #include "vvToolROIManager.h"
21 #include "vvImageReader.h"
22 #include "vvImageWriter.h"
23 #include "vvROIActor.h"
25 #include "vvMeshReader.h"
26 #include "vvStructSelector.h"
27 #include "vvToolManager.h"
28 #include "vvProgressDialog.h"
31 #include "clitkDicomRTStruct2ImageFilter.h"
32 #include "clitkDicomRT_StructureSet.h"
35 #include <QFileDialog>
36 #include <QMessageBox>
37 #include <QColorDialog>
38 #include <QAbstractEventDispatcher>
39 #include <QXmlStreamReader>
42 #include <vtkLookupTable.h>
43 #include <vtkRenderWindow.h>
45 //------------------------------------------------------------------------------
46 // Create the tool and automagically (I like this word) insert it in
47 // the main window menu.
48 ADD_TOOL(vvToolROIManager);
49 //------------------------------------------------------------------------------
51 int vvToolROIManager::nbTotalROI = 0;
53 //------------------------------------------------------------------------------
54 vvToolROIManager::vvToolROIManager(vvMainWindowBase * parent, Qt::WindowFlags f):
55 QWidget(parent->GetTab()),
56 vvToolBase<vvToolROIManager>(parent),
57 Ui::vvToolROIManager()
62 // Assume the initial tab ROI index is 2
66 Ui_vvToolROIManager::setupUi(this);
67 setAttribute(Qt::WA_DeleteOnClose);
69 mTree->header()->resizeSection(0, 30);
70 mGroupBoxROI->setEnabled(false);
72 // Disable "Load dicom" button -> not useful
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);
83 #include "vvDefaultLut.h"
86 mCurrentSlicerManager = NULL;
87 mNumberOfVisibleROI = 0;
88 mNumberOfVisibleContourROI = 0;
89 mOpenFileBrowserFlag = true; // by default, open the file browser when the tool is launched
91 // InitializeNewTool must be called to start
93 //------------------------------------------------------------------------------
96 //------------------------------------------------------------------------------
97 vvToolROIManager::~vvToolROIManager()
99 mROIActorsList.clear();
101 //------------------------------------------------------------------------------
104 //------------------------------------------------------------------------------
106 void vvToolROIManager::Initialize()
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);
114 //------------------------------------------------------------------------------
118 //------------------------------------------------------------------------------
119 void vvToolROIManager::InitializeNewTool(bool ReadStateFlag)
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);
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);
135 // Read all information in the XML
136 ReadXMLInformation();
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));
146 // Set the attached image
147 mCurrentSlicerManager = mMainWindow->GetSlicerManagers()[mInitialImageIndex];
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.");
164 // Display tool in the correct tab
165 QWidget * tab = mMainWindow->GetTab()->findChild<QWidget*>("ROItab");
166 tab->layout()->addWidget(this);
168 // If not read in a file we start automatically the browser to load
169 // a roi file (binary image)
171 mOpenFileBrowserFlag = false;
172 InputIsSelected(mCurrentSlicerManager);
173 mOpenFileBrowserFlag = true;
175 else InputIsSelected(mCurrentSlicerManager);
177 // Load ROI (if read in the XML files, empty otherwise)
178 OpenBinaryImage(mROIFilenames);
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);
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()));
199 UpdateAllROIStatus();
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()));
222 //------------------------------------------------------------------------------
225 //------------------------------------------------------------------------------
226 void vvToolROIManager::InputIsSelected(vvSlicerManager *m)
229 mCurrentSlicerManager = m;
230 mCurrentImage = mCurrentSlicerManager->GetImage();
233 mLabelInputInfo->setText(QString("%1").arg(m->GetFileName().c_str()));
235 // Auto display browser to select new contours
236 if (mOpenFileBrowserFlag) Open();
238 //------------------------------------------------------------------------------
241 //------------------------------------------------------------------------------
242 void vvToolROIManager::AnImageIsBeingClosed(vvSlicerManager * m)
244 if (m == mCurrentSlicerManager) {
249 //------------------------------------------------------------------------------
251 void vvToolROIManager::RemoveROI()
254 // Search the indice of the selected ROI
255 QList<QTreeWidgetItem *> l = mTree->selectedItems();
259 QTreeWidgetItem * w = l[0];
260 if (w == NULL) return;
262 if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
266 clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w];
267 if (roi == NULL) return;
269 // Get selected roi actor
270 int n = roi->GetROINumber();
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);
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()));
282 connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
283 for(int i=0; i<mCurrentSlicerManager->GetNumberOfSlicers(); i++) {
284 mCurrentSlicerManager->GetSlicer(i)->Render();
287 //------------------------------------------------------------------------------
289 //------------------------------------------------------------------------------
290 void vvToolROIManager::close()
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()));
303 for (unsigned int i = 0; i < mROIActorsList.size(); i++) {
304 mROIActorsList[i]->RemoveActors();
306 mROIActorsList.clear();
309 for(int i=0; i<mCurrentSlicerManager->GetNumberOfSlicers(); i++) {
310 mCurrentSlicerManager->GetSlicer(i)->Render();
313 //------------------------------------------------------------------------------
316 //------------------------------------------------------------------------------
317 void vvToolROIManager::SelectedImageHasChanged(vvSlicerManager * m)
319 if (mCurrentSlicerManager == NULL) return;
320 if (m == NULL) return;
321 if (m != mCurrentSlicerManager) hide();
326 //------------------------------------------------------------------------------
329 //------------------------------------------------------------------------------
330 void vvToolROIManager::Open()
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; }
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);
347 //------------------------------------------------------------------------------
350 //------------------------------------------------------------------------------
351 void vvToolROIManager::OpenBinaryImage(QStringList & filename)
353 if (filename.size() == 0) return;
355 vvProgressDialog p("Reading ROI ...", true);
356 p.SetCancelButtonEnabled(false);
357 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
359 // For each selected file, open the image
360 for(int i=0; i<filename.size(); i++) {
361 p.SetProgress(i, filename.size());
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);
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);
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]);
386 QApplication::restoreOverrideCursor();
388 // Update the contours
391 //------------------------------------------------------------------------------
394 //------------------------------------------------------------------------------
395 void vvToolROIManager::OpenDicomImage(std::string filename)
397 // GUI selector of roi
399 reader.SetFilename(filename);
401 vvStructSelector selector;
402 selector.SetStructures(reader.GetROINames());
403 selector.SetPropagationCheckBoxFlag(false);
405 if (selector.exec()) {
406 vvProgressDialog p("Reading ROI...", true);
407 p.SetCancelButtonEnabled(false);
408 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
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);
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());
422 clitk::DicomRTStruct2ImageFilter filter;
423 filter.SetCropMaskEnabled(true);
424 filter.SetImage(mCurrentImage);
425 filter.SetROI(s->GetROIFromROINumber(list[i]));
426 filter.SetWriteOutputFlag(false);
430 vvImage::Pointer binaryImage = vvImage::New();
431 binaryImage->AddVtkImage(filter.GetOutput());
434 AddImage(binaryImage, s->GetROIFromROINumber(list[i])->GetName(), "", 0, true); // "" = no filename
435 mOpenedBinaryImageFilenames.push_back(filename.c_str());
438 QApplication::restoreOverrideCursor();
440 // Update the contours
443 //------------------------------------------------------------------------------
446 //------------------------------------------------------------------------------
447 void vvToolROIManager::AddImage(vvImage * binaryImage,
449 std::string filename,
450 double BG, bool modeBG)
453 int dim = mCurrentImage->GetNumberOfDimensions();
454 int bin_dim = binaryImage->GetNumberOfDimensions();
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());
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();
473 std::vector<double> color;
479 clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
480 roi->SetFromBinaryImage(binaryImage, mROIList.size(), name, color, filename);
482 // Add a new roi to the list
483 mROIList.push_back(roi);
487 roi->SetBackgroundValueLabelImage(BG);
489 roi->SetForegroundValueLabelImage(BG);
492 if (n<mDefaultLUTColor->GetNumberOfTableValues ()) {
493 double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ());
494 roi->SetDisplayColor(color[0], color[1], color[2]);
497 // Add a new roi actor
498 QSharedPointer<vvROIActor> actor = QSharedPointer<vvROIActor>(new vvROIActor);
499 actor->SetBGMode(modeBG);
501 actor->SetSlicerManager(mCurrentSlicerManager);
502 actor->Initialize(n+1); // depth is n+1 to start at 1
503 mROIActorsList.push_back(actor);
505 // CheckBox for "All"
506 if (actor->IsVisible()) mNumberOfVisibleROI++;
507 if (actor->IsContourVisible()) mNumberOfVisibleContourROI++;
508 AllVisibleContourROIToggled(1);
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);
527 UpdateAllROIStatus();
529 if (mCurrentImage->GetNumberOfDimensions() > 3) {
531 //Modifications to avoid display bug with a 4D image
532 QSharedPointer<vvROIActor> CurrentROIActorTemp;
533 CurrentROIActorTemp = mCurrentROIActor;
534 mCurrentROIActor = actor;
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();
540 VisibleROIToggled(false);
541 VisibleROIToggled(true);
543 mCurrentROIActor = CurrentROIActorTemp;
548 //------------------------------------------------------------------------------
551 //------------------------------------------------------------------------------
552 void vvToolROIManager::UpdateAllContours()
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();
559 //mCurrentSlicerManager->Render();
561 //------------------------------------------------------------------------------
564 //------------------------------------------------------------------------------
565 void vvToolROIManager::UpdateAllROIStatus()
568 int nbContourVisible = 0;
569 int nb = mROIList.size();
570 for(int i=0; i<nb; i++) {
571 if (mROIActorsList[i]->IsVisible()) {
574 if (mROIActorsList[i]->IsContourVisible()) {
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);
584 if (nbVisible == 0) mCheckBoxShowAll->setCheckState(Qt::Unchecked);
585 else mCheckBoxShowAll->setCheckState(Qt::PartiallyChecked);
587 if (nbContourVisible == nb) mContourCheckBoxShowAll->setCheckState(Qt::Checked);
589 if (nbContourVisible == 0) mContourCheckBoxShowAll->setCheckState(Qt::Unchecked);
590 else mContourCheckBoxShowAll->setCheckState(Qt::PartiallyChecked);
592 connect(mContourCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleContourROIToggled(int)));
593 connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
595 //------------------------------------------------------------------------------
598 //------------------------------------------------------------------------------
599 void vvToolROIManager::SelectedItemChangedInTree()
601 // Search which roi is selected
602 QList<QTreeWidgetItem *> l = mTree->selectedItems();
604 // mCurrentROIActor = 0;
606 mGroupBoxROI->setEnabled(false);
609 QTreeWidgetItem * w = l[0];
610 if (w == NULL) return;
612 if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
613 // mCurrentROIActor = 0;
615 mGroupBoxROI->setEnabled(false);
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
622 // Get selected roi actor
623 int n = roi->GetROINumber();
624 QSharedPointer<vvROIActor> actor = mROIActorsList[n];
626 mCurrentROIActor = actor;
628 // Warning -> avoid unuseful Render here by disconnect slider
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()));
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));
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()));
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+"); }");
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);
677 // Enable the group box (in case no selection before)
678 mGroupBoxROI->setEnabled(true);
680 //------------------------------------------------------------------------------
683 //------------------------------------------------------------------------------
684 void vvToolROIManager::VisibleROIToggled(bool b)
686 if (mCurrentROIActor == NULL) return;
687 if (b == mCurrentROIActor->IsVisible()) return; // nothing to do
688 mCurrentROIActor->SetVisible(b);
689 UpdateAllROIStatus();
690 mCurrentSlicerManager->Render();
692 //------------------------------------------------------------------------------
695 //------------------------------------------------------------------------------
696 void vvToolROIManager::VisibleContourROIToggled(bool b)
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();
705 //------------------------------------------------------------------------------
708 //------------------------------------------------------------------------------
709 void vvToolROIManager::OpacityChanged(int v)
711 if (mCurrentROIActor == NULL) return;
712 mCurrentROIActor->SetOpacity((double)v/100.0);
713 mCurrentROIActor->UpdateColor();
714 mCurrentSlicerManager->Render();
716 //------------------------------------------------------------------------------
719 //------------------------------------------------------------------------------
720 void vvToolROIManager::AllVisibleROIToggled(int b)
722 disconnect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
724 if ((mCheckBoxShowAll->checkState() == Qt::Checked) ||
725 (mCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true;
727 for(uint i=0; i<mROIList.size(); i++) {
728 mROIActorsList[i]->SetVisible(status);
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)));
736 //------------------------------------------------------------------------------
739 //------------------------------------------------------------------------------
740 void vvToolROIManager::AllVisibleContourROIToggled(int b)
742 disconnect(mContourCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleContourROIToggled(int)));
744 if ((mContourCheckBoxShowAll->checkState() == Qt::Checked) ||
745 (mContourCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true;
747 for(uint i=0; i<mROIActorsList.size(); i++) {
748 mROIActorsList[i]->SetContourVisible(status);
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)));
757 //------------------------------------------------------------------------------
760 //------------------------------------------------------------------------------
761 void vvToolROIManager::ChangeColor()
763 if (mCurrentROIActor == NULL) return;
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
771 mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
772 mCurrentROIActor->UpdateColor();
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);
781 mCurrentSlicerManager->Render();
783 //------------------------------------------------------------------------------
786 //------------------------------------------------------------------------------
787 void vvToolROIManager::ChangeContourColor()
789 if (mCurrentROIActor == NULL) return;
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();
801 //------------------------------------------------------------------------------
804 //------------------------------------------------------------------------------
805 void vvToolROIManager::ChangeContourWidth(int n)
807 if (mCurrentROIActor == NULL) return;
808 mCurrentROIActor->SetContourWidth(n);
809 mCurrentROIActor->UpdateColor();
810 mCurrentSlicerManager->Render();
812 //------------------------------------------------------------------------------
815 //------------------------------------------------------------------------------
816 void vvToolROIManager::ChangeDepth(int n)
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()));
826 //------------------------------------------------------------------------------
829 //------------------------------------------------------------------------------
830 void vvToolROIManager::ReloadCurrentROI()
832 if (mCurrentROI->GetFilename() == "") {
833 return; // do nothing (contour from rt struct do not reload)
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();
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());
854 // Free the previous image
855 mCurrentROI->GetImage()->GetFirstVTKImageData()->ReleaseData(); // Needed to free
856 mCurrentROI->GetImage()->Reset();
857 mCurrentROI->SetImage(reader->GetOutput());
859 mCurrentROIActor->RemoveActors();
862 mCurrentROIActor->UpdateImage();
863 mCurrentROIActor->SetVisible(visible);
864 mCurrentROIActor->SetContourVisible(cvisible);
865 mCurrentSlicerManager->Render();
867 //------------------------------------------------------------------------------
870 //------------------------------------------------------------------------------
871 #if __cplusplus > 199711L
872 void vvToolROIManager::SaveState(std::shared_ptr<QXmlStreamWriter> & m_XmlWriter)
874 void vvToolROIManager::SaveState(std::auto_ptr<QXmlStreamWriter> & m_XmlWriter)
877 // Get index of the image
878 int n = mMainWindow->GetSlicerManagers().size();
880 for(int i=0; i<n; i++) {
881 if (mCurrentSlicerManager == mMainWindow->GetSlicerManagers()[i]) index = i;
884 std::cerr << "Error while writing state for ROIManager tool no currentimage founded." << std::endl;
887 m_XmlWriter->writeTextElement("Image_Index", QString::number(index));
891 for(uint i=0; i<mROIActorsList.size(); i++) {
892 QSharedPointer<vvROIActor> roi = mROIActorsList[i];
894 m_XmlWriter->writeStartElement("ROI");
895 m_XmlWriter->writeTextElement("Image", mOpenedBinaryImageFilenames[i]);
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();
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();
914 m_XmlWriter->writeEndElement();
917 //------------------------------------------------------------------------------
920 //------------------------------------------------------------------------------
921 void vvToolROIManager::ReadXMLInformation()
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();
929 if (value == "Image_Index")
930 mInitialImageIndex = m_XmlReader->readElementText().toInt();
932 if (m_XmlReader->isStartElement()) {
933 if (value == "ROI") {
934 ReadXMLInformation_ROI();
939 //------------------------------------------------------------------------------
942 //------------------------------------------------------------------------------
943 void vvToolROIManager::ReadXMLInformation_ROI()
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);
953 float r=1.0,g=1.0,b=1.0;
954 float cr=1.0,cg=1.0,cb=1.0;
957 bool cvisible = true;
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();
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();
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();
998 param->SetOverlayColor(r,g,b);
999 param->SetVisible(visible);
1000 param->SetOpacity(opacity);
1001 param->SetDepth(depth);
1003 param->SetContourColor(cr,cg,cb);
1004 param->SetContourVisible(cvisible);
1005 param->SetContourWidth(width);
1007 mROIFilenames.push_back(s);
1008 mROIActorsParamList.push_back(param);
1010 //------------------------------------------------------------------------------