Skip to content

Commit

Permalink
ENH: Add option for displaying vertical slice controller
Browse files Browse the repository at this point in the history
The slice controller currently can only display the slice offset slider, but more controls can be added later.

Vertical slice offset slider is implemented because:
- it has become the standard for slice browsing in medical image viewers.
- it allows saving some precious screen real estate vertically: the horizontal slice controller at the top of the slice view can be hidden in custom applications that do not require sophisticated slice manipulation.
- if the slice offset slider is displayed on the side then there is space for more buttons in the slice view controller at the top - reducing the need to push the little push-pin icon to access certain features

The feature is still being developed, so there is no GUI yet for enabling vertical slice offset slider and hide slice view controller at the top, but these can be activated in Python in custom modules and applications:

for slice in ['Red', 'Yellow', 'Green']:
    sw = slicer.app.layoutManager().sliceWidget(slice)
    sw.setSliceOffsetSliderOrientation(qt.Qt.Vertical)
    #sw.setSliceOffsetSliderOrientation(qt.Qt.Horizontal)
    sw.sliceController().setVisible(False)
    #sw.sliceController().setVisible(True)
  • Loading branch information
Punzo authored and lassoan committed Dec 8, 2022
1 parent 8d1ff64 commit 2ed9451
Show file tree
Hide file tree
Showing 19 changed files with 894 additions and 60 deletions.
40 changes: 40 additions & 0 deletions Libs/MRML/Logic/vtkMRMLSliceLogic.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2525,3 +2525,43 @@ vtkMRMLSliceDisplayNode* vtkMRMLSliceLogic::GetSliceDisplayNode()
{
return vtkMRMLSliceDisplayNode::SafeDownCast(this->GetSliceModelDisplayNode());
}


//----------------------------------------------------------------------------
bool vtkMRMLSliceLogic::GetSliceOffsetRangeResolution(double range[2], double& resolution)
{
// Calculate the number of slices in the current range.
// Extent is between the farthest voxel centers (not voxel sides).
double sliceBounds[6] = {0, -1, 0, -1, 0, -1};
this->GetLowestVolumeSliceBounds(sliceBounds, true);

const double * sliceSpacing = this->GetLowestVolumeSliceSpacing();
if (!sliceSpacing)
{
range[0] = -1.0;
range[1] = 1.0;
resolution = 1.0;
return false;
}

// Set the scale increments to match the z spacing (rotated into slice space)
resolution = sliceSpacing ? sliceSpacing[2] : 1.0;

bool singleSlice = ((sliceBounds[5] - sliceBounds[4]) < resolution);
if (singleSlice)
{
// add one blank slice before and after the current slice to make the slider appear in the center when
// we are centered on the slice
double centerPos = (sliceBounds[4] + sliceBounds[5]) / 2.0;
range[0] = centerPos - resolution;
range[1] = centerPos + resolution;
}
else
{
// there are at least two slices in the range
range[0] = sliceBounds[4];
range[1] = sliceBounds[5];
}

return true;
}
4 changes: 4 additions & 0 deletions Libs/MRML/Logic/vtkMRMLSliceLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ class VTK_MRML_LOGIC_EXPORT vtkMRMLSliceLogic : public vtkMRMLAbstractLogic
/// a volume is not editable (even if it is visible at the given position).
int GetEditableLayerAtWorldPosition(double worldPos[3], bool backgroundVolumeEditable = true, bool foregroundVolumeEditable = true);

/// Get range and resolution for slice offset sliders.
/// Returns false if the information cannot be determined.
bool GetSliceOffsetRangeResolution(double range[2], double& resolution);

protected:

vtkMRMLSliceLogic();
Expand Down
4 changes: 4 additions & 0 deletions Libs/MRML/Widgets/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ set(MRMLWidgets_SRCS
qMRMLSliceInformationWidget.cxx
qMRMLSliceInformationWidget.h
qMRMLSliceInformationWidget_p.h
qMRMLSliceVerticalControllerWidget.cxx
qMRMLSliceVerticalControllerWidget.h
qMRMLSliceView.cxx
qMRMLSliceView.h
qMRMLSliceView_p.h
Expand Down Expand Up @@ -294,6 +296,7 @@ set(MRMLWidgets_MOC_SRCS
qMRMLSliceControllerWidget_p.h
qMRMLSliceInformationWidget.h
qMRMLSliceInformationWidget_p.h
qMRMLSliceVerticalControllerWidget.h
qMRMLSliceView.h
qMRMLSliceView_p.h
qMRMLSliceWidget.h
Expand Down Expand Up @@ -351,6 +354,7 @@ set(MRMLWidgets_UI_SRCS
Resources/UI/qMRMLSegmentSelectorWidget.ui
Resources/UI/qMRMLSliceControllerWidget.ui
Resources/UI/qMRMLSliceInformationWidget.ui
Resources/UI/qMRMLSliceVerticalControllerWidget.ui
Resources/UI/qMRMLSliceWidget.ui
Resources/UI/qMRMLTableViewControllerWidget.ui
Resources/UI/qMRMLThreeDViewControllerWidget.ui
Expand Down
3 changes: 3 additions & 0 deletions Libs/MRML/Widgets/DesignerPlugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ set(${KIT}_SRCS
qMRMLSliceControllerWidgetPlugin.h
qMRMLSliceInformationWidgetPlugin.cxx
qMRMLSliceInformationWidgetPlugin.h
qMRMLSliceVerticalControllerWidgetPlugin.cxx
qMRMLSliceVerticalControllerWidgetPlugin.h
qMRMLSliceWidgetPlugin.cxx
qMRMLSliceWidgetPlugin.h
qMRMLSliderWidgetPlugin.cxx
Expand Down Expand Up @@ -142,6 +144,7 @@ set(${KIT}_MOC_SRCS
qMRMLSceneFactoryWidgetPlugin.h
qMRMLSliceControllerWidgetPlugin.h
qMRMLSliceInformationWidgetPlugin.h
qMRMLSliceVerticalControllerWidgetPlugin.h
qMRMLSliceWidgetPlugin.h
qMRMLSliderWidgetPlugin.h
qMRMLSpinBoxPlugin.h
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "qMRMLSliceVerticalControllerWidgetPlugin.h"
#include "qMRMLSliceVerticalControllerWidget.h"

// --------------------------------------------------------------------------
qMRMLSliceVerticalControllerWidgetPlugin::qMRMLSliceVerticalControllerWidgetPlugin(QObject *_parent)
: QObject(_parent)
{
}

// --------------------------------------------------------------------------
QWidget *qMRMLSliceVerticalControllerWidgetPlugin::createWidget(QWidget *_parent)
{
qMRMLSliceVerticalControllerWidget* _widget = new qMRMLSliceVerticalControllerWidget(_parent);
return _widget;
}

// --------------------------------------------------------------------------
QString qMRMLSliceVerticalControllerWidgetPlugin::domXml() const
{
return "<ui language=\"c++\">\n"
"<widget class=\"qMRMLSliceVerticalControllerWidget\" name=\"MRMLSliceVerticalControllerWidget\">\n"
"</widget>\n"
"</ui>\n";
}

// --------------------------------------------------------------------------
QIcon qMRMLSliceVerticalControllerWidgetPlugin::icon() const
{
return QIcon();
}

// --------------------------------------------------------------------------
QString qMRMLSliceVerticalControllerWidgetPlugin::includeFile() const
{
return "qMRMLSliceVerticalControllerWidget.h";
}

// --------------------------------------------------------------------------
bool qMRMLSliceVerticalControllerWidgetPlugin::isContainer() const
{
return false;
}

// --------------------------------------------------------------------------
QString qMRMLSliceVerticalControllerWidgetPlugin::name() const
{
return "qMRMLSliceVerticalControllerWidget";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef __qMRMLSliceVerticalControllerWidgetPlugin_h
#define __qMRMLSliceVerticalControllerWidgetPlugin_h

#include "qMRMLWidgetsAbstractPlugin.h"

class QMRML_WIDGETS_PLUGINS_EXPORT qMRMLSliceVerticalControllerWidgetPlugin : public QObject,
public qMRMLWidgetsAbstractPlugin
{
Q_OBJECT

public:
qMRMLSliceVerticalControllerWidgetPlugin(QObject *_parent = nullptr);

QWidget *createWidget(QWidget *_parent) override;
QString domXml() const override;
QIcon icon() const override;
QString includeFile() const override;
bool isContainer() const override;
QString name() const override;

};

#endif
2 changes: 2 additions & 0 deletions Libs/MRML/Widgets/DesignerPlugins/qMRMLWidgetsPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include "qMRMLScalarsDisplayWidgetPlugin.h"
#include "qMRMLSliceControllerWidgetPlugin.h"
#include "qMRMLSliceInformationWidgetPlugin.h"
#include "qMRMLSliceVerticalControllerWidgetPlugin.h"
#include "qMRMLSliceWidgetPlugin.h"
#include "qMRMLSliderWidgetPlugin.h"
#include "qMRMLSpinBoxPlugin.h"
Expand Down Expand Up @@ -124,6 +125,7 @@ class QMRML_WIDGETS_PLUGINS_EXPORT qMRMLWidgetsPlugin
<< new qMRMLSceneFactoryWidgetPlugin
<< new qMRMLSliceControllerWidgetPlugin
<< new qMRMLSliceInformationWidgetPlugin
<< new qMRMLSliceVerticalControllerWidgetPlugin
<< new qMRMLSliceWidgetPlugin
<< new qMRMLSliderWidgetPlugin
<< new qMRMLSpinBoxPlugin
Expand Down
118 changes: 118 additions & 0 deletions Libs/MRML/Widgets/Resources/UI/qMRMLSliceVerticalControllerWidget.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>qMRMLSliceVerticalControllerWidget</class>
<widget class="qMRMLWidget" name="qMRMLSliceVerticalControllerWidget">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>84</width>
<height>319</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Vertical Slice Controller</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="qMRMLSliderWidget" name="SliceVerticalOffsetSlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">QSlider::groove:vertical {
background-color: black;
margin: 0px 0px 0px 0px;
border: none;
width: 12px;
}

QSlider::handle:vertical {
background-color: rgba(200, 200, 200, 200);;
border-width: 1px;
margin-top: -5px;
margin-bottom: -5px;
height: 50px;
border-radius: 5px;
}

QSlider::handle:vertical:hover {
background-color: rgba(150, 150, 150, 200);
border-radius: 5px;
}

QSlider::handle:vertical:pressed {
background-color: rgba(0, 150, 150, 200);
border-radius: 5px;
}</string>
</property>
<property name="spinBoxVisible">
<bool>false</bool>
</property>
<property name="quantity">
<string notr="true">length</string>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>qMRMLSliderWidget</class>
<extends>ctkSliderWidget</extends>
<header>qMRMLSliderWidget.h</header>
</customwidget>
<customwidget>
<class>qMRMLWidget</class>
<extends>QWidget</extends>
<header>qMRMLWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ctkSliderWidget</class>
<extends>QWidget</extends>
<header>ctkSliderWidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

0 comments on commit 2ed9451

Please sign in to comment.