Commit fe6d641e authored by alexy's avatar alexy
Browse files

ENH: added qMRMLWindowLevelWidget, started filling in qVolumes module

git-svn-id: http://svn.slicer.org/Slicer4/trunk@12314 3bd1e089-480b-0410-8dfb-8563597acbee
parent e6ee27fe
......@@ -52,6 +52,8 @@ SET(qMRMLWidgets_SRCS
qMRMLTreeWidget.h
qMRMLUtils.cxx
qMRMLUtils.h
qMRMLWindowLevelWidget.cxx
qMRMLWindowLevelWidget.h
)
# Headers that should run through moc
......@@ -73,6 +75,7 @@ SET(qMRMLWidgets_MOC_SRCS
qMRMLTreeProxyModel_p.h
qMRMLTransformSliders.h
qMRMLTreeWidget.h
qMRMLWindowLevelWidget.h
)
# UI files
......@@ -80,6 +83,7 @@ SET(qMRMLWidgets_UI_SRCS
Resources/UI/qMRMLEventLoggerWidget.ui
Resources/UI/qMRMLSceneFactoryWidget.ui
Resources/UI/qMRMLTransformSliders.ui
Resources/UI/qMRMLWindowLevelWidget.ui
)
QT4_WRAP_CPP(qMRMLWidgets_SRCS ${qMRMLWidgets_MOC_SRCS})
......
......@@ -27,7 +27,9 @@ SET(designer_plugin_SRCS
qMRMLWidgetsAbstractPlugin.cxx
qMRMLWidgetsAbstractPlugin.h
qMRMLWidgetsPlugin.cxx
qMRMLWidgetsPlugin.h
qMRMLWidgetsPlugin.h
qMRMLWindowLevelWidgetPlugin.cxx
qMRMLWindowLevelWidgetPlugin.h
)
# Headers that should run through moc
......@@ -42,6 +44,7 @@ SET(designer_plugin_MOC_SRCS
qMRMLSceneFactoryWidgetPlugin.h
qMRMLTransformSlidersPlugin.h
qMRMLTreeWidgetPlugin.h
qMRMLWindowLevelWidgetPlugin.h
)
SET(designer_plugin_TARGET_LIBRARIES
......
......@@ -9,6 +9,7 @@
#include "qMRMLNodeTreeSelectorPlugin.h"
#include "qMRMLTransformSlidersPlugin.h"
#include "qMRMLTreeWidgetPlugin.h"
#include "qMRMLWindowLevelWidgetPlugin.h"
#include "qMRMLSceneFactoryWidgetPlugin.h"
#include <QDesignerCustomWidgetCollectionInterface>
......@@ -33,6 +34,7 @@ public:
<< new qMRMLNodeTreeSelectorPlugin
<< new qMRMLTransformSlidersPlugin
<< new qMRMLTreeWidgetPlugin
<< new qMRMLWindowLevelWidgetPlugin
<< new qMRMLSceneFactoryWidgetPlugin;
return plugins;
}
......
#include "qMRMLWindowLevelWidgetPlugin.h"
#include "qMRMLWindowLevelWidget.h"
qMRMLWindowLevelWidgetPlugin::qMRMLWindowLevelWidgetPlugin(QObject *_parent)
: QObject(_parent)
{
}
QWidget *qMRMLWindowLevelWidgetPlugin::createWidget(QWidget *_parent)
{
qMRMLWindowLevelWidget* _widget = new qMRMLWindowLevelWidget(_parent);
return _widget;
}
QString qMRMLWindowLevelWidgetPlugin::domXml() const
{
return "<widget class=\"qMRMLWindowLevelWidget\" \
name=\"MRMLWindowLevelWidget\">\n"
" <property name=\"geometry\">\n"
" <rect>\n"
" <x>0</x>\n"
" <y>0</y>\n"
" <width>200</width>\n"
" <height>20</height>\n"
" </rect>\n"
" </property>\n"
"</widget>\n";
}
QIcon qMRMLWindowLevelWidgetPlugin::icon() const
{
return QIcon(":/Icons/combobox.png");
}
QString qMRMLWindowLevelWidgetPlugin::includeFile() const
{
return "qMRMLWindowLevelWidget.h";
}
bool qMRMLWindowLevelWidgetPlugin::isContainer() const
{
return false;
}
QString qMRMLWindowLevelWidgetPlugin::name() const
{
return "qMRMLWindowLevelWidget";
}
#ifndef __qMRMLWindowLevelWidgetPlugin_h
#define __qMRMLWindowLevelWidgetPlugin_h
#include "qMRMLWidgetsAbstractPlugin.h"
class QMRML_WIDGETS_PLUGIN_EXPORT qMRMLWindowLevelWidgetPlugin : public QObject,
public qMRMLWidgetsAbstractPlugin
{
Q_OBJECT
public:
qMRMLWindowLevelWidgetPlugin(QObject *_parent = 0);
QWidget *createWidget(QWidget *_parent);
QString domXml() const;
QIcon icon() const;
QString includeFile() const;
bool isContainer() const;
QString name() const;
};
#endif
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>qMRMLWindowLevelWidget</class>
<widget class="QWidget" name="qMRMLWindowLevelWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>381</width>
<height>137</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>321</width>
<height>80</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Window/Level: </string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="AutoManualComboBox">
<item>
<property name="text">
<string>Manual</string>
</property>
</item>
<item>
<property name="text">
<string>Auto</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="qCTKRangeSlider" name="WindowLevelRangeSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>qCTKRangeSlider</class>
<extends>QSlider</extends>
<header>qCTKRangeSlider.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
#include "qMRMLWindowLevelWidget.h"
#include "ui_qMRMLWindowLevelWidget.h"
// qMRML includes
#include "qMRMLUtils.h"
// MRML includes
#include "vtkMRMLScalarVolumeNode.h"
#include "vtkMRMLScalarVolumeDisplayNode.h"
// VTK includes
#include "vtkSmartPointer.h"
// QT includes
#include <QDebug>
#include <QStack>
//-----------------------------------------------------------------------------
class qMRMLWindowLevelWidgetPrivate: public qCTKPrivate<qMRMLWindowLevelWidget>,
public Ui_qMRMLWindowLevelWidget
{
public:
qMRMLWindowLevelWidgetPrivate()
{
}
};
// --------------------------------------------------------------------------
qMRMLWindowLevelWidget::qMRMLWindowLevelWidget(QWidget* _parent) : Superclass(_parent)
{
QCTK_INIT_PRIVATE(qMRMLWindowLevelWidget);
QCTK_D(qMRMLWindowLevelWidget);
d->setupUi(this);
this->VolumeNode = NULL;
this->VolumeDisplayNode = NULL;
this->setAutoWindowLevel(1);
// TODO replace with double window/level
this->connect(d->WindowLevelRangeSlider, SIGNAL(rangeValuesChanged(int,int)),
SLOT(setWindowLevel(int, int)));
this->connect(d->AutoManualComboBox, SIGNAL(currentIndexChanged(int)),
SLOT(setAutoWindowLevel(int)));
// disable as there is not MRML Node associated with the widget
this->setEnabled(false);
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setAutoWindowLevel(int autoWindowLevel)
{
QCTK_D(qMRMLWindowLevelWidget);
if (this->VolumeDisplayNode)
{
this->VolumeDisplayNode->SetAutoWindowLevel(autoWindowLevel);
if (this->VolumeNode && autoWindowLevel == 1)
{
this->VolumeNode->CalculateAutoLevels();
}
}
}
// --------------------------------------------------------------------------
int qMRMLWindowLevelWidget::autoWindowLevel() const
{
QCTK_D(const qMRMLWindowLevelWidget);
// Assumes settings of the sliders are all the same
return d->AutoManualComboBox->currentIndex();
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setWindowLevel(double window, double level)
{
if (this->VolumeDisplayNode)
{
double oldWindow = this->VolumeDisplayNode->GetWindow();
double oldLevel = this->VolumeDisplayNode->GetLevel();
int disabledModify = this->VolumeDisplayNode->StartModify();
this->VolumeDisplayNode->SetWindow(window);
this->VolumeDisplayNode->SetLevel(level);
if (oldWindow != this->VolumeDisplayNode->GetWindow() ||
oldLevel != this->VolumeDisplayNode->GetLevel())
{
this->VolumeDisplayNode->SetAutoWindowLevel(0);
}
this->VolumeDisplayNode->EndModify(disabledModify);
}
}
// TODO remove when range becomes double
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setWindowLevel(int window, int level)
{
this->setWindowLevel((double)window, (double)level);
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setWindow(double window)
{
if (this->VolumeDisplayNode)
{
double oldWindow = this->VolumeDisplayNode->GetWindow();
int disabledModify = this->VolumeDisplayNode->StartModify();
this->VolumeDisplayNode->SetWindow(window);
if (oldWindow != this->VolumeDisplayNode->GetWindow())
{
this->VolumeDisplayNode->SetAutoWindowLevel(0);
}
this->VolumeDisplayNode->EndModify(disabledModify);
}
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setLevel(double level)
{
if (this->VolumeDisplayNode)
{
double oldLevel = this->VolumeDisplayNode->GetLevel();
int disabledModify = this->VolumeDisplayNode->StartModify();
this->VolumeDisplayNode->SetLevel(level);
if (oldLevel != this->VolumeDisplayNode->GetLevel())
{
this->VolumeDisplayNode->SetAutoWindowLevel(0);
}
this->VolumeDisplayNode->EndModify(disabledModify);
}
}
// --------------------------------------------------------------------------
double qMRMLWindowLevelWidget::window() const
{
QCTK_D(const qMRMLWindowLevelWidget);
double min = d->WindowLevelRangeSlider->rangeMinimum();
double max = d->WindowLevelRangeSlider->rangeMaximum();
return max - min;
}
// --------------------------------------------------------------------------
double qMRMLWindowLevelWidget::level() const
{
QCTK_D(const qMRMLWindowLevelWidget);
double min = d->WindowLevelRangeSlider->rangeMinimum();
double max = d->WindowLevelRangeSlider->rangeMaximum();
return 0.5*(max + min);
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setMRMLVolumeDisplayNode(vtkMRMLScalarVolumeDisplayNode* node)
{
// each time the node is modified, the qt widgets are updated
this->qvtkReconnect(this->VolumeDisplayNode, node,
vtkCommand::ModifiedEvent, this, SLOT(updateWidgetFromMRML()));
this->VolumeDisplayNode = node;
this->setEnabled(node != 0);
this->updateWidgetFromMRML();
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setMRMLVolumeNode(vtkMRMLNode* node)
{
this->setMRMLVolumeNode(vtkMRMLScalarVolumeNode::SafeDownCast(node));
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setMRMLVolumeNode(vtkMRMLScalarVolumeNode* volumeNode)
{
QCTK_D(qMRMLWindowLevelWidget);
if (volumeNode)
{
// TODO: set image data range in the range widget
// d->WindowLevelRangeSlider volumeNode->GetImageData()->GetScalarRange()
this->setMRMLVolumeDisplayNode(vtkMRMLScalarVolumeDisplayNode::SafeDownCast(
volumeNode->GetVolumeDisplayNode()));
}
this->VolumeNode = volumeNode;
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setMinimum(double min)
{
QCTK_D(qMRMLWindowLevelWidget);
// TODO set min in the range widget d->WindowLevelRangeSlider
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::setMaximum(double max)
{
QCTK_D(qMRMLWindowLevelWidget);
// TODO set max in the range widget d->WindowLevelRangeSlider
}
// --------------------------------------------------------------------------
void qMRMLWindowLevelWidget::updateWidgetFromMRML()
{
QCTK_D(qMRMLWindowLevelWidget);
if (this->VolumeDisplayNode)
{
int oldAuto = d->AutoManualComboBox->currentIndex();
double oldMin = d->WindowLevelRangeSlider->rangeMinimum();
double oldMax = d->WindowLevelRangeSlider->rangeMaximum();
double window = this->VolumeDisplayNode->GetWindow();
double level = this->VolumeDisplayNode->GetLevel();
d->AutoManualComboBox->setCurrentIndex(this->VolumeDisplayNode->GetAutoWindowLevel());
d->WindowLevelRangeSlider->setRange(level - 0.5 * window, level + 0.5 * window);
if (oldAuto != d->AutoManualComboBox->currentIndex())
{
emit this->autoWindowLevelValueChanged(d->AutoManualComboBox->currentIndex());
}
if (oldMin != d->WindowLevelRangeSlider->rangeMinimum() ||
oldMax != d->WindowLevelRangeSlider->rangeMaximum() )
{
emit this->windowLevelValuesChanged(window, level);
}
}
}
#ifndef __qMRMLWindowLevelWidget_h
#define __qMRMLWindowLevelWidget_h
/// qVTK includes
#include <qVTKObject.h>
/// qCTK includes
#include <qCTKPimpl.h>
/// QT includes
#include <QWidget>
#include "qMRMLWidgetsExport.h"
class vtkMRMLNode;
class vtkMRMLScalarVolumeDisplayNode;
class vtkMRMLScalarVolumeNode;
class qMRMLWindowLevelWidgetPrivate;
class QMRML_WIDGETS_EXPORT qMRMLWindowLevelWidget : public QWidget
{
Q_OBJECT
QVTK_OBJECT
Q_PROPERTY(int autoWindowLevel READ autoWindowLevel WRITE setAutoWindowLevel)
Q_PROPERTY(double window READ window WRITE setWindow)
Q_PROPERTY(double level READ level WRITE setLevel)
public:
/// Constructors
typedef QWidget Superclass;
explicit qMRMLWindowLevelWidget(QWidget* parent);
virtual ~qMRMLWindowLevelWidget(){}
int autoWindowLevel() const;
///
/// Get window
double window()const;
///
/// Get level
double level()const;
///
/// Return the current MRML node of interest
vtkMRMLScalarVolumeNode* mrmlVolumeNode()const
{ return this->VolumeNode; };
signals:
///
/// Signal sent if the window/level value is updated
void windowLevelValuesChanged(double window, double level);
///
/// Signal sent if the auto/manual value is updated
void autoWindowLevelValueChanged(int value);
public slots:
///
/// Set Auto/Manual mode
void setAutoWindowLevel(int autoWindowLevel);
///
/// Set window
void setWindow(double window);
///
/// Set level
void setLevel(double level);
///
/// Sset window/level in once
void setWindowLevel(double window, double level);
// TODO remove when range becomes double
void setWindowLevel(int window, int level);
///
/// Set the MRML node of interest
void setMRMLVolumeNode(vtkMRMLScalarVolumeNode* displayNode);
void setMRMLVolumeNode(vtkMRMLNode* node);
protected slots:
/// update widget GUI from MRML node
void updateWidgetFromMRML();
protected:
///
/// Return the current MRML display node
vtkMRMLScalarVolumeDisplayNode* mrmlDisplayNode()const
{ return this->VolumeDisplayNode;};
///
/// Set current MRML display node
void setMRMLVolumeDisplayNode(vtkMRMLScalarVolumeDisplayNode* displayNode);
///
/// Set sliders range
void setMinimum(double min);
void setMaximum(double max);
private:
QCTK_DECLARE_PRIVATE(qMRMLWindowLevelWidget);
vtkMRMLScalarVolumeNode* VolumeNode;
vtkMRMLScalarVolumeDisplayNode* VolumeDisplayNode;
};
#endif
......@@ -18,7 +18,7 @@ INCLUDE(${Slicer3_CMAKE_DIR}/Slicer3QTModuleMacros.cmake)
SET(qtmodules
SlicerWelcome
#Volumes
Volumes
Measurements
TractographyFiducialSeeding
)
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>qSlicerVolumesModule</class>
<widget class="QWidget" name="qSlicerVolumesModule">
<widget class="qSlicerWidget" name="qSlicerVolumesModule">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>507</width>
<height>822</height>
<width>681</width>
<height>549</height>
</rect>
</property>
<property name="windowTitle">
<string>Volumes</string>
<string>Form</string>
</property>
<property name="windowIcon">
<iconset resource="../qSlicerVolumesModule.qrc">
<normaloff>:/Icons/Volumes.png</normaloff>:/Icons/Volumes.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<property name="margin">
<number>2</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Active Volume</string>
</property>
</widget>
</item>
<item>
<widget class="qMRMLNodeSelector" name="ActiveVolumeNodeSel