Commit d9058894 authored by finetjul's avatar finetjul
Browse files

ENH: Add advanced options to the slice views

git-svn-id: http://svn.slicer.org/Slicer4/trunk@14695 3bd1e089-480b-0410-8dfb-8563597acbee
parent 857481ea
......@@ -208,6 +208,7 @@ QWidget* qSlicerLayoutManagerPrivate::createSliceWidget(vtkMRMLSliceNode* sliceN
sliceWidget->setSliceViewName(sliceLayoutName);
sliceWidget->setMRMLScene(this->MRMLScene);
sliceWidget->setMRMLSliceNode(sliceNode);
sliceWidget->setSliceLogics(this->MRMLSliceLogics);
this->SliceWidgetList.push_back(sliceWidget);
this->MRMLSliceLogics->AddItem(sliceWidget->sliceLogic());
......
......@@ -96,7 +96,6 @@ void qSlicerModuleSelectorToolBarPrivate::init()
this->PreviousButton->setIcon(previousIcon);
this->PreviousButton->setText(QObject::tr("Previous"));
this->PreviousButton->setMenu(this->PreviousHistoryMenu);
this->PreviousButton->setArrowType(Qt::NoArrow);
// selectPreviousModule is called only if the toolbutton is clicked not if an
// action in the history is triggered
QObject::connect(this->PreviousButton, SIGNAL(clicked(bool)),
......@@ -110,7 +109,6 @@ void qSlicerModuleSelectorToolBarPrivate::init()
this->NextButton->setIcon(nextIcon);
this->NextButton->setText(QObject::tr("Next"));
this->NextButton->setMenu(this->NextHistoryMenu);
this->NextButton->setArrowType(Qt::NoArrow);
// selectNextModule is called only if the toolbutton is clicked not if an
// action in the history is triggered
QObject::connect(this->NextButton, SIGNAL(clicked(bool)),
......
......@@ -237,6 +237,9 @@
<iconset resource="../qMRMLWidgets.qrc">
<normaloff>:/Icons/SliceViewerBG.png</normaloff>:/Icons/SliceViewerBG.png</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item row="1" column="3">
......@@ -272,7 +275,7 @@
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="SliceLinkToggle">
<widget class="QToolButton" name="SliceLinkButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
......@@ -299,7 +302,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="SliceVisibilityToggle">
<widget class="QToolButton" name="SliceVisibilityButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
......@@ -340,6 +343,9 @@
<iconset resource="../qMRMLWidgets.qrc">
<normaloff>:/Icons/SliceMoreOptions.png</normaloff>:/Icons/SliceMoreOptions.png</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
......@@ -394,25 +400,16 @@ Use this display to cross-reference to filmed images or other displays.</string>
<string>Adjusts the Slice Viewer's field of view to match the extent of lowest non-None volume layer (bg, then fg, then label).</string>
</property>
</action>
<action name="actionRotate_to_Volume_Plane">
<action name="actionRotate_to_volume_plane">
<property name="icon">
<iconset resource="../qMRMLWidgets.qrc">
<normaloff>:/Icons/SlicerRotateToPixelSpace.png</normaloff>:/Icons/SlicerRotateToPixelSpace.png</iconset>
</property>
<property name="text">
<string>Rotate to Volume Plane</string>
</property>
</action>
<action name="actionAdjust_labelmap_opacity">
<property name="icon">
<iconset resource="../qMRMLWidgets.qrc">
<normaloff>:/Icons/SlicesLabelOpacity.png</normaloff>:/Icons/SlicesLabelOpacity.png</iconset>
</property>
<property name="text">
<string>Adjust labelmap opacity</string>
<string>Rotate to volume vlane</string>
</property>
<property name="toolTip">
<string>Popup scale to adjust opacity of label layer.</string>
<string>Rotate to volume plane</string>
</property>
</action>
<action name="actionShow_label_volume_outline">
......@@ -679,5 +676,347 @@ Use this display to cross-reference to filmed images or other displays.</string>
</hint>
</hints>
</connection>
<connection>
<sender>actionFit_to_window</sender>
<signal>activated()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>fitSliceToBackground()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>62</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionRotate_to_volume_plane</sender>
<signal>activated()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>rotateSliceToBackground()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>62</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionShow_label_volume_outline</sender>
<signal>toggled(bool)</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>showLabelOutline(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>62</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionShow_reformat_widget</sender>
<signal>toggled(bool)</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>showReformatWidget(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCompositingAlpha_blend</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setCompositingToAlphaBlend()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCompositingReverse_alpha_blend</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setCompositingToReverseAlphaBlend()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCompositingAdd</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setCompositingToAdd()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCompositingSubtract</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setCompositingToSubtract()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionSliceSpacingModeAutomatic</sender>
<signal>toggled(bool)</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setSliceSpacingMode(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox1x1_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo1x1()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox1x2_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo1x2()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox1x3_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo1x3()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox1x4_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo1x4()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox1x6_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo1x6()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox1x8_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo1x8()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox2x2_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo2x2()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox3x3_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo3x3()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionLightbox6x6_view</sender>
<signal>triggered()</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setLightboxTo6x6()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionForegroundInterpolation</sender>
<signal>toggled(bool)</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setForegroundInterpolation(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionBackgroundInterpolation</sender>
<signal>toggled(bool)</signal>
<receiver>qMRMLSliceControllerWidget</receiver>
<slot>setBackgroundInterpolation(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>195</x>
<y>54</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>fitSliceToBackground()</slot>
<slot>rotateSliceToBackground()</slot>
<slot>showLabelOutline(bool)</slot>
<slot>showReformatWidget(bool)</slot>
<slot>setCompositingToAlphaBlend()</slot>
<slot>setCompositingToReverseAlphaBlend()</slot>
<slot>setCompositingToAdd()</slot>
<slot>setCompositingToSubtract()</slot>
<slot>setSliceSpacingMode(bool)</slot>
<slot>setLightboxTo1x1()</slot>
<slot>setLightboxTo1x2()</slot>
<slot>setLightboxTo1x4()</slot>
<slot>setLightboxTo1x6()</slot>
<slot>setLightboxTo1x8()</slot>
<slot>setLightboxTo2x2()</slot>
<slot>setLightboxTo3x3()</slot>
<slot>setLightboxTo6x6()</slot>
<slot>setLightboxTo1x3()</slot>
<slot>setForegroundInterpolation(bool)</slot>
<slot>setBackgroundInterpolation(bool)</slot>
</slots>
</ui>
......@@ -13,16 +13,20 @@
#include "qMRMLWidgetsExport.h"
class QButtonGroup;
class ctkVTKSliceView;
class qMRMLSliceControllerWidgetPrivate;
class vtkMRMLScene;
class vtkCollection;
class vtkImageData;
class vtkMRMLNode;
class vtkMRMLSliceNode;
class vtkMRMLScene;
class vtkMRMLSliceCompositeNode;
class vtkImageData;
class ctkVTKSliceView;
class vtkMRMLSliceLogic;
class vtkMRMLSliceNode;
///
/// qMRMLSliceControllerWidget offers controls to a slice view (vtkMRMLSliceNode
/// and vtkMRMLSliceCompositeNode). It internally creates a slice logic that
/// be changed.
class QMRML_WIDGETS_EXPORT qMRMLSliceControllerWidget : public qMRMLWidget
{
Q_OBJECT
......@@ -35,6 +39,12 @@ public:
explicit qMRMLSliceControllerWidget(QWidget* parent = 0);
virtual ~qMRMLSliceControllerWidget(){}
/// Are the slices linked to each other
bool isLinked()const;
/// Is the view a compare view
bool isCompareView()const;
/// Get slice orientation
/// \sa setSliceOrientation(QString);
QString sliceOrientation();
......@@ -75,6 +85,11 @@ public:
/// one of the sliceCollapsibleButton of the group is clicked.
void setControllerButtonGroup(QButtonGroup* group);
/// TODO:
/// Ideally the slice logics should be retrieved by the sliceLogic
/// until then, we manually set them.
void setSliceLogics(vtkCollection* logics);
public slots:
virtual void setMRMLScene(vtkMRMLScene* newScene);
......@@ -105,6 +120,38 @@ public slots:
/// Link/Unlink the slice controls across all slice viewer
void setSliceLink(bool linked);
// Advanced options
/// Rotate to volume plane
void rotateSliceToBackground();
/// Label opacity
void setLabelOpacity(double opacity);
/// Label outline
void showLabelOutline(bool show);
/// Reformat widget
void showReformatWidget(bool show);
/// Compositing
void setCompositing(int mode);
void setCompositingToAlphaBlend();
void setCompositingToReverseAlphaBlend();
void setCompositingToAdd();
void setCompositingToSubtract();
/// Slice spacing
void setSliceSpacingMode(bool automatic);
void setSliceSpacing(double);
// Lightbox
void setLightbox(int rows, int columns);
void setLightboxTo1x1();
void setLightboxTo1x2();
void setLightboxTo1x3();
void setLightboxTo1x4();
void setLightboxTo1x6();
void setLightboxTo1x8();
void setLightboxTo2x2();
void setLightboxTo3x3();
void setLightboxTo6x6();
// interpolation
void setForegroundInterpolation(bool);
void setBackgroundInterpolation(bool);
signals:
/// This signal is emitted when the giben \a imageData is modified.
......
#ifndef __qMRMLSliceControllerWidget_p_h
#define __qMRMLSliceControllerWidget_p_h
/// CTK includes
// CTK includes
#include <ctkPimpl.h>
#include <ctkVTKObject.h>
......@@ -13,11 +13,13 @@
#include <vtkMRMLSliceLogic.h>
/// VTK includes
#include <vtkCollection.h>
#include <vtkImageData.h>
#include <vtkSmartPointer.h>
#include <vtkWeakPointer.h>
#include <vtkImageData.h>
class QAction;
class QSpinBox;
class QDoubleSpinBox;
class ctkVTKSliceView;
class vtkMRMLSliceNode;
class vtkObject;
......@@ -36,8 +38,15 @@ public:
void setupUi(qMRMLWidget* widget);
void setupMoreOptionMenu();
void setupMoreOptionsMenu();
vtkSmartPointer<vtkCollection> saveNodesForUndo(const QString& nodeTypes);
vtkMRMLSliceLogic* compositeNodeLogic(vtkMRMLSliceCompositeNode* node);
vtkMRMLSliceLogic* sliceNodeLogic(vtkMRMLSliceNode* node);
void setForegroundInterpolation(vtkMRMLSliceLogic* logic, bool interpolate);
void setBackgroundInterpolation(vtkMRMLSliceLogic* logic, bool interpolate);
public slots:
/// Update widget state using the associated MRML slice node
void updateWidgetFromMRMLSliceNode();
......@@ -56,7 +65,7 @@ public slots:
/// Called after a backgound layer volume node is selected
/// using the associated qMRMLNodeComboBox
void onLabelMapNodeSelected(vtkMRMLNode* node);
/// Called after the SliceLogic is modified
void onSliceLogicModifiedEvent();
......@@ -65,44 +74,29 @@ public slots:
void toggleControllerWidgetGroupVisibility();
void toggleLabelOpacity(bool toggle);
void applyCustomLightbox();
public:
vtkMRMLSliceNode* MRMLSliceNode;
vtkMRMLSliceCompositeNode* MRMLSliceCompositeNode;
vtkSmartPointer<vtkMRMLSliceLogic> SliceLogic;
vtkCollection* SliceLogics;
vtkWeakPointer<vtkImageData> ImageData;
QString SliceOrientation;
QHash<QString, QString> SliceOrientationToDescription;
QString SliceViewName;
QButtonGroup* ControllerButtonGroup;
QAction* actionFitToWindow;
QAction* actionTotateToVolumePlane;
QAction* actionAdjustLabelMapOpacity;
QAction* actionShowLabelVolumeOutlines;
QAction* actionShowReformatWidget;
QAction* actionCompositingAlphaBlend;
QAction* actionCompositingRevserseAlphaBlend;
QAction* actionCompositingAdd;
QAction* actionCompositingSubtract;
QAction* actionSliceSpacingModeAutomatic;
QAction* actionSliceSpacingModeManual;