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://oncora1.lyon.fnclcc.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 "vvToolStructureSetManager.h"
21 #include "vvImageReader.h"
22 #include "vvStructureSetActor.h"
24 #include "vvROIActor.h"
27 #include <QFileDialog>
28 #include <QMessageBox>
29 #include <QColorDialog>
32 #include <vtkLookupTable.h>
33 #include <vtkRenderWindow.h>
35 //------------------------------------------------------------------------------
36 // Create the tool and automagically (I like this word) insert it in
37 // the main window menu.
38 ADD_TOOL(vvToolStructureSetManager);
39 //------------------------------------------------------------------------------
41 //------------------------------------------------------------------------------
42 vvToolStructureSetManager::vvToolStructureSetManager(vvMainWindowBase * parent, Qt::WindowFlags f)
43 :vvToolWidgetBase(parent, f),//, true),
44 vvToolBase<vvToolStructureSetManager>(parent),
45 Ui::vvToolStructureSetManager()
49 QWidget * aw = new QWidget(parent, f);
50 QVBoxLayout * verticalLayout = new QVBoxLayout(aw);
51 verticalLayout->addWidget(mToolInputSelectionWidget);
52 verticalLayout->addWidget(mToolWidget);
53 aw->setLayout(verticalLayout);
55 Ui_vvToolStructureSetManager::setupUi(mToolWidget);
60 //int a = mMainWindowBase->GetTab()->addTab(mToolWidget, "Toto");
61 int a = mMainWindowBase->GetTab()->addTab(aw, "Toto");
63 // essai avec mToolWidget ? ok mais frame à cacher ...
64 // Changer le construceur par defautl de widgetbase -> pas dialog, pas parent (cf doc)
65 mMainWindowBase->GetTab()->setCurrentIndex(a);
66 mMainWindowBase->GetTab()->setTabIcon(a, QIcon(vvToolCreator<vvToolStructureSetManager>::GetInstance()->mToolIconFilename));
72 mCurrentStructureSet = NULL;
73 mCurrentStructureSetIndex = -1;
74 mGroupBoxROI->setEnabled(false);
75 mCurrentROIActor = NULL;
76 mIsAllVisibleEnabled = false;
77 mNumberOfVisibleROI = 0;
78 mNumberOfVisibleContourROI = 0;
79 mDefaultLUTColor = vtkLookupTable::New();
80 for(unsigned int i=0; i<mDefaultLUTColor->GetNumberOfTableValues(); i++) {
81 double r = (rand()/(RAND_MAX+1.0));
82 double v = (rand()/(RAND_MAX+1.0));
83 double b = (rand()/(RAND_MAX+1.0));
84 mDefaultLUTColor->SetTableValue(i, r, v, b);
85 // std::cout << "mDefaultLUTColor->SetTableValue(" << i << ", " << r << ", " << v << ", " << b << ");" << std::endl;
87 #include "vvDefaultLut.h"
90 AddInputSelector("Select image");
92 //------------------------------------------------------------------------------
95 //------------------------------------------------------------------------------
96 vvToolStructureSetManager::~vvToolStructureSetManager()
99 //------------------------------------------------------------------------------
102 //------------------------------------------------------------------------------
103 void vvToolStructureSetManager::Initialize() {
104 SetToolName("ROIManager");
105 SetToolMenuName("Display ROI");
106 SetToolIconFilename(":/common/icons/ducky.png");
107 SetToolTip("Display ROI from label image.");
108 SetToolExperimental(true);
110 //------------------------------------------------------------------------------
113 //------------------------------------------------------------------------------
114 void vvToolStructureSetManager::InputIsSelected(vvSlicerManager *m)
117 if (mCurrentImage->GetNumberOfDimensions() != 3) {
118 QMessageBox::information(this,tr("Sorry only 3D yet"), tr("Sorry only 3D yet"));
123 HideInputSelector(); // splitter
124 // mToolInputSelectionWidget->hide();
125 // Connect open menus
126 connect(mOpenBinaryButton, SIGNAL(clicked()), this, SLOT(OpenBinaryImage()));
127 connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
128 connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
129 connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
130 connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
131 connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
132 connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
133 connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
134 connect(mReloadButton, SIGNAL(clicked()), this, SLOT(ReloadCurrentROI()));
135 connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
136 connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
138 //------------------------------------------------------------------------------
141 //------------------------------------------------------------------------------
142 void vvToolStructureSetManager::Open(int type) {
144 case 0: OpenBinaryImage(); return; // Open binary image;
145 case 1: DD("TODO"); return; // Open DICOM RT
146 case 2: DD("TODO"); return; // Open mesh
147 default: std::cerr << "Error ????" << std::endl; exit(0);
150 //------------------------------------------------------------------------------
153 //------------------------------------------------------------------------------
154 void vvToolStructureSetManager::AddRoiInTreeWidget(clitk::DicomRT_ROI * roi, QTreeWidget * ww) {
155 QTreeWidgetItem * w = new QTreeWidgetItem(ww);
156 w->setText(0, QString("%1").arg(roi->GetROINumber()));
157 w->setText(1, QString("%1").arg(roi->GetName().c_str()));
158 QBrush brush(QColor(roi->GetDisplayColor()[0]*255, roi->GetDisplayColor()[1]*255, roi->GetDisplayColor()[2]*255));
159 brush.setStyle(Qt::SolidPattern);
160 w->setBackground(2, brush);
161 mMapROIToTreeWidget[roi] = w;
162 mMapTreeWidgetToROI[w] = roi;
164 //------------------------------------------------------------------------------
167 //------------------------------------------------------------------------------
168 void vvToolStructureSetManager::UpdateStructureSetInTreeWidget(int index, clitk::DicomRT_StructureSet * s) {
170 const std::vector<clitk::DicomRT_ROI*> & rois = s->GetListOfROI();
171 for(unsigned int i=0; i<rois.size(); i++) {
172 if (mMapROIToTreeWidget.find(rois[i]) == mMapROIToTreeWidget.end())
173 AddRoiInTreeWidget(rois[i], mTree); // replace mTree with ss if several SS
176 //------------------------------------------------------------------------------
179 //------------------------------------------------------------------------------
180 int vvToolStructureSetManager::AddStructureSet(clitk::DicomRT_StructureSet * mStructureSet) {
181 // Create actor for this SS
182 vvStructureSetActor * mStructureSetActor = new vvStructureSetActor;
183 mStructureSetActor->SetStructureSet(mStructureSet);
184 mStructureSetActor->SetSlicerManager(mCurrentSlicerManager);
185 // Insert in lists and get index
186 mStructureSetsList.push_back(mStructureSet);
187 mStructureSetActorsList.push_back(mStructureSetActor);
188 int index = mStructureSetsList.size()-1;
192 //------------------------------------------------------------------------------
195 //------------------------------------------------------------------------------
196 void vvToolStructureSetManager::OpenBinaryImage() {
198 if (mCurrentStructureSet == NULL) {
199 if (mStructureSetsList.size() == 0) { // Create a default SS
200 clitk::DicomRT_StructureSet * mStructureSet = new clitk::DicomRT_StructureSet;
201 index = AddStructureSet(mStructureSet);
203 else { // Get first SS
207 index = mCurrentStructureSetIndex;
209 mCurrentStructureSet = mStructureSetsList[index];
210 mCurrentStructureSetActor = mStructureSetActorsList[index];
211 mCurrentStructureSetIndex = index;
213 QString Extensions = "Images files ( *.mhd *.hdr *.his)";
214 Extensions += ";;All Files (*)";
215 QStringList filename =
216 QFileDialog::getOpenFileNames(this,tr("Open binary image"),
217 mMainWindowBase->GetInputPathName(),Extensions);
218 if (filename.size() == 0) return;
219 std::vector<int> mLoadedROIIndex;
220 for(int i=0; i<filename.size(); i++) {
222 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
223 vvImageReader * mReader = new vvImageReader;
224 std::vector<std::string> filenames;
225 filenames.push_back(filename[i].toStdString());
226 mReader->SetInputFilenames(filenames);
227 mReader->Update(IMAGE);
228 QApplication::restoreOverrideCursor();
230 if (mReader->GetLastError().size() != 0) {
231 std::cerr << "Error while reading " << filename[i].toStdString() << std::endl;
232 QString error = "Cannot open file \n";
233 error += mReader->GetLastError().c_str();
234 QMessageBox::information(this,tr("Reading problem"),error);
238 vvImage::Pointer binaryImage = mReader->GetOutput();
241 int dim = mCurrentImage->GetNumberOfDimensions();
242 int bin_dim = binaryImage->GetNumberOfDimensions();
243 if (dim < bin_dim) { ////////// TO CHANGE FOR 3D/4D
244 std::ostringstream os;
245 os << "Error. Loaded binary image is " << bin_dim
246 << "D while selected image is " << dim << "D" << std::endl;
247 QMessageBox::information(this,tr("Reading problem"),os.str().c_str());
251 // Add a new roi to the structure
252 int n = mCurrentStructureSet->AddBinaryImageAsNewROI(binaryImage, filename[i].toStdString());
253 mLoadedROIIndex.push_back(n);
254 mCurrentStructureSet->GetROI(n)->SetBackgroundValueLabelImage(mBackgroundValueSpinBox->value());
257 if (n<mDefaultLUTColor->GetNumberOfTableValues ()) {
258 double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ());
259 mCurrentStructureSet->GetROI(n)->SetDisplayColor(color[0], color[1], color[2]);
262 // Add a new roi actor
263 mCurrentStructureSetActor->CreateNewROIActor(n);
265 // CheckBox for "All"
266 if (mCurrentStructureSetActor->GetROIActor(n)->IsVisible())
267 mNumberOfVisibleROI++;
268 if (mCurrentStructureSetActor->GetROIActor(n)->IsContourVisible())
269 mNumberOfVisibleContourROI++;
270 UpdateAllROIStatus();
271 } // end loop on n selected filenames
273 // Update the TreeWidget
274 UpdateStructureSetInTreeWidget(index, mCurrentStructureSet);
275 // Render loaded ROIs (the first is sufficient)
276 for(unsigned int i=0; i<mLoadedROIIndex.size(); i++) {
277 mCurrentStructureSetActor->GetROIActor(mLoadedROIIndex[i])->Update();
279 for(int i=0; i<mCurrentSlicerManager->NumberOfSlicers(); i++) {
280 mCurrentSlicerManager->GetSlicer(i)->Render();
283 //------------------------------------------------------------------------------
286 //------------------------------------------------------------------------------
287 void vvToolStructureSetManager::apply()
291 //------------------------------------------------------------------------------
294 //------------------------------------------------------------------------------
295 bool vvToolStructureSetManager::close()
297 mCheckBoxShowAll->setCheckState(Qt::Unchecked);
298 mContourCheckBoxShowAll->setCheckState(Qt::Unchecked);
299 if (mCurrentSlicerManager) mCurrentSlicerManager->Render();
300 if (mCurrentStructureSetActor) {
301 for(int i=0; i<mCurrentStructureSetActor->GetNumberOfROIs(); i++) {
302 mCurrentStructureSetActor->GetROIList()[i]->SetVisible(false);
303 mCurrentStructureSetActor->GetROIList()[i]->SetContourVisible(false);
304 delete mCurrentStructureSetActor->GetROIList()[i];
307 return vvToolWidgetBase::close();
309 //------------------------------------------------------------------------------
312 //------------------------------------------------------------------------------
313 // CURRENT ROI INTERACTION
314 //------------------------------------------------------------------------------
317 //------------------------------------------------------------------------------
318 void vvToolStructureSetManager::SelectedItemChangedInTree() {
319 // Search which roi is selected
320 QList<QTreeWidgetItem *> l = mTree->selectedItems();
322 mCurrentROIActor = NULL;
324 mGroupBoxROI->setEnabled(false);
327 QTreeWidgetItem * w = l[0];
328 if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
329 mCurrentROIActor = NULL;
331 mGroupBoxROI->setEnabled(false);
334 clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w];
335 // Get selected roi actor
336 vvROIActor * actor = mStructureSetActorsList[mCurrentStructureSetIndex]->GetROIActor(roi->GetROINumber());
338 mCurrentROIActor = actor;
341 mGroupBoxROI->setEnabled(true);
342 mROInameLabel->setText(roi->GetName().c_str());
343 mCheckBoxShow->setChecked(actor->IsVisible());
344 mContourCheckBoxShow->setChecked(actor->IsContourVisible());
345 mContourWidthSpinBox->setValue(actor->GetContourWidth());
347 // Warning -> avoir unuseful Render here by disconnect slider
348 disconnect(mOpacitySlider, SIGNAL(valueChanged(int)),
349 this, SLOT(OpacityChanged(int)));
350 mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100));
351 mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100));
352 connect(mOpacitySlider, SIGNAL(valueChanged(int)),
353 this, SLOT(OpacityChanged(int)));
357 mCurrentSlicerManager->Render();
359 //------------------------------------------------------------------------------
362 //------------------------------------------------------------------------------
363 void vvToolStructureSetManager::UpdateAllROIStatus() {
365 int nb = mCurrentStructureSetActor->GetROIList().size();
366 for(int i=0; i<nb; i++) {
367 if (mCurrentStructureSetActor->GetROIList()[i]->IsVisible()) {
372 disconnect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
373 disconnect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
374 if (nbVisible == nb) mCheckBoxShowAll->setCheckState(Qt::Checked);
376 if (nbVisible == 0) mCheckBoxShowAll->setCheckState(Qt::Unchecked);
377 else mCheckBoxShowAll->setCheckState(Qt::PartiallyChecked);
379 connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
380 connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
382 //------------------------------------------------------------------------------
384 //------------------------------------------------------------------------------
385 void vvToolStructureSetManager::VisibleROIToggled(bool b) {
386 if (mCurrentROIActor == NULL) return;
387 if (b == mCurrentROIActor->IsVisible()) return; // nothing to do
388 mCurrentROIActor->SetVisible(b);
389 UpdateAllROIStatus();
390 mCurrentSlicerManager->Render();
392 //------------------------------------------------------------------------------
395 //------------------------------------------------------------------------------
396 void vvToolStructureSetManager::VisibleContourROIToggled(bool b) {
397 if (mCurrentROIActor == NULL) return;
398 if (mCurrentROIActor->IsContourVisible() == b) return; // nothing to do
399 mCurrentROIActor->SetContourVisible(b);
400 mCurrentROIActor->UpdateColor();
401 mCurrentSlicerManager->Render();
403 //------------------------------------------------------------------------------
406 //------------------------------------------------------------------------------
407 void vvToolStructureSetManager::OpacityChanged(int v) {
408 if (mCurrentROIActor == NULL) return;
409 mCurrentROIActor->SetOpacity((double)v/100.0);
410 mCurrentROIActor->UpdateColor();
411 mCurrentSlicerManager->Render();
413 //------------------------------------------------------------------------------
416 //------------------------------------------------------------------------------
417 void vvToolStructureSetManager::AllVisibleROIToggled(int b) {
419 if ((mCheckBoxShowAll->checkState() == Qt::Checked) ||
420 (mCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true;
422 for(int i=0; i<mCurrentStructureSetActor->GetNumberOfROIs(); i++) {
423 mCurrentStructureSetActor->GetROIList()[i]->SetVisible(status);
425 if (status) mCheckBoxShowAll->setCheckState(Qt::Checked);
426 else mCheckBoxShowAll->setCheckState(Qt::Unchecked);
427 mCheckBoxShow->setChecked(status);
428 mCurrentSlicerManager->Render();
430 //------------------------------------------------------------------------------
433 //------------------------------------------------------------------------------
434 void vvToolStructureSetManager::AllVisibleContourROIToggled(bool b) {
436 if ((mContourCheckBoxShowAll->checkState() == Qt::Checked) ||
437 (mContourCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true;
439 for(int i=0; i<mCurrentStructureSetActor->GetNumberOfROIs(); i++) {
440 mCurrentStructureSetActor->GetROIList()[i]->SetContourVisible(status);
442 // Update current selection
443 if (status) mContourCheckBoxShowAll->setCheckState(Qt::Checked);
444 else mContourCheckBoxShowAll->setCheckState(Qt::Unchecked);
445 mContourCheckBoxShow->setChecked(status);
446 mCurrentSlicerManager->Render();
448 //------------------------------------------------------------------------------
451 //------------------------------------------------------------------------------
452 void vvToolStructureSetManager::ChangeColor() {
454 color.setRgbF(mCurrentROIActor->GetROI()->GetDisplayColor()[0],
455 mCurrentROIActor->GetROI()->GetDisplayColor()[1],
456 mCurrentROIActor->GetROI()->GetDisplayColor()[2]);
457 QColor c = QColorDialog::getColor(color, this, "Choose the ROI color");
458 mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
459 mCurrentROIActor->UpdateColor();
461 QTreeWidgetItem * w = mMapROIToTreeWidget[mCurrentROI];
462 QBrush brush(QColor(mCurrentROI->GetDisplayColor()[0]*255,
463 mCurrentROI->GetDisplayColor()[1]*255,
464 mCurrentROI->GetDisplayColor()[2]*255));
465 brush.setStyle(Qt::SolidPattern);
466 w->setBackground(2, brush);
468 mCurrentSlicerManager->Render();
470 //------------------------------------------------------------------------------
473 //------------------------------------------------------------------------------
474 void vvToolStructureSetManager::ChangeContourColor() {
476 color.setRgbF(mCurrentROIActor->GetContourColor()[0],
477 mCurrentROIActor->GetContourColor()[1],
478 mCurrentROIActor->GetContourColor()[2]);
479 QColor c = QColorDialog::getColor(color, this, "Choose the contour color");
480 mCurrentROIActor->SetContourColor(c.redF(), c.greenF(), c.blueF());
481 mCurrentROIActor->UpdateColor();
482 mCurrentSlicerManager->Render();
484 //------------------------------------------------------------------------------
487 //------------------------------------------------------------------------------
488 void vvToolStructureSetManager::ChangeContourWidth(int n) {
489 mCurrentROIActor->SetContourWidth(n);
490 mCurrentROIActor->UpdateColor();
491 mCurrentSlicerManager->Render();
493 //------------------------------------------------------------------------------
496 //------------------------------------------------------------------------------
497 void vvToolStructureSetManager::ReloadCurrentROI() {
499 vvImageReader * mReader = new vvImageReader;
500 mReader->SetInputFilename(mCurrentROI->GetFilename());
501 mReader->Update(IMAGE);
502 if (mReader->GetLastError() != "") {
503 QMessageBox::information(mMainWindowBase, tr("Sorry, error. Could not reload"), mReader->GetLastError().c_str());
506 mCurrentROI->SetImage(mReader->GetOutput());
509 mCurrentROIActor->UpdateImage();
510 mCurrentSlicerManager->Render();
512 //------------------------------------------------------------------------------