diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index afa09b7371..6ee8f22a2b 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,81 +1,83 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core CommandLine AppUtil DCMTesting RDF LegacyIO DataTypesExt Annotation LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction LegacyAdaptors SceneSerialization Gizmo GraphAlgorithms Multilabel ImageStatistics ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QtWidgets QtWidgetsExt C3js QmlItems SegmentationUI DiffusionImaging GPGPU OpenIGTLink IGTBase IGT CameraCalibration RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport QtOverlays ToFHardware ToFProcessing ToFUI US USUI DicomUI Simulation Remeshing Python QtPython Persistence OpenIGTLinkUI IGTUI VtkShaders DicomRT RTUI IOExt XNAT TubeGraph BiophotonicsHardware Classification TumorInvasionAnalysis MatchPointRegistration MatchPointRegistrationUI BoundingShape + RenderWindowManager + RenderWindowManagerUI ) if(MITK_ENABLE_PIC_READER) list(APPEND mitk_modules IpPicSupportIO) endif() diff --git a/Modules/RenderWindowManager/CMakeLists.txt b/Modules/RenderWindowManager/CMakeLists.txt new file mode 100644 index 0000000000..2b876f73bc --- /dev/null +++ b/Modules/RenderWindowManager/CMakeLists.txt @@ -0,0 +1,5 @@ +MITK_CREATE_MODULE( + INCLUDE_DIRS Qmitk + DEPENDS MitkQtWidgets + PACKAGE_DEPENDS PUBLIC CTK Qt5|Core +) diff --git a/Modules/RenderWindowManager/files.cmake b/Modules/RenderWindowManager/files.cmake new file mode 100644 index 0000000000..5e95f08b7a --- /dev/null +++ b/Modules/RenderWindowManager/files.cmake @@ -0,0 +1,19 @@ +set(H_FILES + include/QmitkRenderWindowDataModel.h + + include/mitkRenderWindowLayerController.h + include/mitkRenderWindowViewDirectionController.h + include/mitkRenderWindowLayerUtilities.h +) + +set(CPP_FILES + QmitkRenderWindowDataModel.cpp + + mitkRenderWindowLayerController.cpp + mitkRenderWindowViewDirectionController.cpp + mitkRenderWindowLayerUtilities.cpp +) + +set(MOC_H_FILES + include/QmitkRenderWindowDataModel.h +) diff --git a/Modules/RenderWindowManager/include/QmitkRenderWindowDataModel.h b/Modules/RenderWindowManager/include/QmitkRenderWindowDataModel.h new file mode 100644 index 0000000000..ae9a9562dc --- /dev/null +++ b/Modules/RenderWindowManager/include/QmitkRenderWindowDataModel.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKRENDERWINDOWDATAMODEL_H +#define QMITKRENDERWINDOWDATAMODEL_H + +// render window manager module +#include "MitkRenderWindowManagerExports.h" +#include "mitkRenderWindowLayerUtilities.h" + +//mitk core +#include +#include + +// qt +#include + +/* +* @brief This class extends the 'QAbstractTableModel' to meet the specific requirements of the QmitkRenderWindowDataModel. +*/ +class MITKRENDERWINDOWMANAGER_EXPORT QmitkRenderWindowDataModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + + QmitkRenderWindowDataModel(QObject* parent = nullptr); + ~QmitkRenderWindowDataModel(); + + ////////////////////////////////////////////////////////////////////////// + /// overridden functions from QAbstractItemModel + ////////////////////////////////////////////////////////////////////////// + virtual Qt::ItemFlags flags(const QModelIndex &index) const override; + virtual QVariant data(const QModelIndex &index, int role) const override; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + ////////////////////////////////////////////////////////////////////////// + /// end override + ///////////////////////////////////////////////////////////////////////// + + void SetDataStorage(mitk::DataStorage::Pointer dataStorage); + void SetCurrentRenderer(std::string rendererName); + mitk::BaseRenderer* GetCurrentRenderer() const { return m_BaseRenderer.GetPointer(); } + void DataChanged(const mitk::DataNode* dataNode); + +private: + + mitk::DataStorage::Pointer m_DataStorage; + mitk::BaseRenderer::Pointer m_BaseRenderer; + RenderWindowLayerUtilities::LayerStack m_TempLayerStack; + +}; + +#endif // QMITKRENDERWINDOWDATAMODEL_H diff --git a/Modules/RenderWindowManager/include/mitkRenderWindowLayerController.h b/Modules/RenderWindowManager/include/mitkRenderWindowLayerController.h new file mode 100644 index 0000000000..9000f6f6d3 --- /dev/null +++ b/Modules/RenderWindowManager/include/mitkRenderWindowLayerController.h @@ -0,0 +1,169 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKRENDERWINDOWLAYERCONTROLLER_H +#define MITKRENDERWINDOWLAYERCONTROLLER_H + +// render window manager module +#include "MitkRenderWindowManagerExports.h" +#include "mitkRenderWindowLayerUtilities.h" + +// mitk core +#include +#include +#include + +namespace mitk +{ + /** + * The RenderWindowLayerController is used to manipulate the 'layer', 'fixedLayer' and 'visible' property of a given data node. + * The 'layer' property is used to denote the layer level of a data node. Data from nodes on higher layer level are rendered + * on top of data from nodes on lower layer level. It can be changed using the 'MoveNode*'-functions. + * + * To view the data of a data node only in a specific renderer, the "InsertLayerNode'-function should be used. It inserts the + * given node into the specified renderer and sets the corresponding properties. + * To hide the data in the common renderer view (all renderer), the 'HideDataNodeInAllRenderer'-function can be used. + * Inserting and showing a data node in a specific renderer / render window, will overwrite the properties of the common renderer view. + * + * For more information about the data node properties for specific renderer, see mitk::DataNode- and mitk::PropertyList-classes. + * + * Functions with 'mitk::BaseRenderer* renderer' have 'nullptr' as their default argument. Using the nullptr + * these functions operate on all base renderer. Giving a specific base renderer will modify the node only for the given renderer. + */ + class MITKRENDERWINDOWMANAGER_EXPORT RenderWindowLayerController + { + public: + + RenderWindowLayerController(); + /** + * @brief Set the data storage on which to work. + */ + void SetDataStorage(DataStorage::Pointer dataStorage); + /** + * @brief Set the controlled base renderer. + */ + void SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer); + + // wrapper functions to modify the layer order / visibility of render window data + /** + * @brief Set the given node as the base node of the given renderer. + * + * @param dataNode The data node whose layer is to be modified. + * @param renderer Pointer to the renderer instance for which the data node property should be modified. + * If it is a nullptr (default) all controlled renderer will be affected. + */ + void SetBaseDataNode(DataNode* dataNode, const BaseRenderer* renderer = nullptr); + /** + * @brief Insert the given data node at the specified layer for the given renderer. + * + * @param dataNode The data node that should be inserted. + * @param layer The layer value for the "layer" property of the data node (insertion level). + "layer = RenderWindowLayerUtilities::TOP_LAYER_INDEX" (default) inserts the given data node at the top of the node stack (topmost layer). + * @param renderer Pointer to the renderer instance for which the data node should be inserted. + * If it is a nullptr (default) all controlled renderer will be affected. + * + * @post After a successful call, the "fixedLayer" and "visibility" property will be true and the "layer" property will be set correctly. + */ + void InsertLayerNode(DataNode* dataNode, int layer = RenderWindowLayerUtilities::TOP_LAYER_INDEX, const BaseRenderer* renderer = nullptr); + /** + * @brief Remove the given data node for the given renderer. + * + * @param dataNode The data node that should be removed. + * @param renderer Pointer to the renderer instance for which the data node should be removed. + * If it is a nullptr (default) all controlled renderer will be affected. + * + * @post After a successful call, the "fixedLayer" and "visibility" property will be false and the "layer" property will be deleted. + */ + void RemoveLayerNode(DataNode* dataNode, const BaseRenderer* renderer = nullptr); + /** + * @brief Set the node in the given renderer as the topmost layer. This will change only the "layer" property. + * + * @param dataNode The data node that should be moved. + * @param renderer Pointer to the renderer instance for which the data node should be moved. + * If it is a nullptr (default) all controlled renderer will be affected. + */ + bool MoveNodeToFront(DataNode* dataNode, const BaseRenderer* renderer = nullptr); + /** + * @brief Set the node in the given renderer as the lowermost layer. This will change only the "layer" property. + * + * @param dataNode The data node that should be moved. + * @param renderer Pointer to the renderer instance for which the data node should be moved. + * If it is a nullptr (default) all controlled renderer will be affected. + */ + bool MoveNodeToBack(DataNode* dataNode, const BaseRenderer* renderer = nullptr); + /** + * @brief Move the node in the given renderer one layer down. This will change only the "layer" property. + * + * @param dataNode The data node that should be moved. + * @param renderer Pointer to the renderer instance for which the data node should be moved. + * If it is a nullptr (default) all controlled renderer will be affected. + */ + bool MoveNodeUp(DataNode* dataNode, const BaseRenderer* renderer = nullptr); + /** + * @brief Move the node in the given renderer one layer up. This will change only the "layer" property. + * + * @param dataNode The data node that should be moved. + * @param renderer Pointer to the renderer instance for which the data node should be moved. + * If it is a nullptr (default) all controlled renderer will be affected. + */ + bool MoveNodeDown(DataNode* dataNode, const BaseRenderer* renderer = nullptr); + /** + * @brief Set the visibility of the given data node for the given renderer. + * + * @param visibility Boolean to set the "visible" property of the given data node. + * @param dataNode The data node that should be moved. + * @param renderer Pointer to the renderer instance for which the data node should be modified. + * If it is a nullptr (default) all controlled renderer will be affected. + * + * @post After a successful call , the "visibility" property will be set to the "visibility" value. + */ + void SetVisibilityOfDataNode(bool visiblity, DataNode* dataNode, const BaseRenderer* renderer = nullptr); + /** + * @brief Hide the given data node by setting the "visible" property of the data node for + * all controlled renderer to false. + * Later setting the "visible" property of the data node for a certain renderer will overwrite + * the same property of the common renderer. + * + * @param dataNode The data node that should be hid. + * + * @post After a successful call , the "visibility" property will be set to the false. + */ + void HideDataNodeInAllRenderer(const DataNode* dataNode); + /** + * @brief Reset the given render window: + * If "onlyVisibility = true": set all data nodes for the given render window to invisible, except for the base node. + * If "onlyVisibility = false": remove all data nodes from the render window, except for the base node. + * + * @param visibility Boolean to define the reset mode. + * @param renderer Pointer to the renderer instance for which the data node should be reset. + * If it is a nullptr (default) all controlled renderer will be affected. + * + * @post After a successful call , the "visibility" property will be set to the "false" value (except for the base node). + * If "onlyVisibility = false": additionally the "fixedLayer" property will be false and the "layer" property will be deleted. + */ + void ResetRenderer(bool onlyVisibility = true, const BaseRenderer* renderer = nullptr); + + private: + + void InsertLayerNodeInternal(DataNode* dataNode, int layer, const BaseRenderer* renderer = nullptr); + + DataStorage::Pointer m_DataStorage; + RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; + }; + +} // namespace mitk + +#endif // MITKRENDERWINDOWLAYERCONTROLLER_H diff --git a/Modules/RenderWindowManager/include/mitkRenderWindowLayerUtilities.h b/Modules/RenderWindowManager/include/mitkRenderWindowLayerUtilities.h new file mode 100644 index 0000000000..e119c43c10 --- /dev/null +++ b/Modules/RenderWindowManager/include/mitkRenderWindowLayerUtilities.h @@ -0,0 +1,61 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKRENDERWINDOWLAYERUTILITIES_H +#define MITKRENDERWINDOWLAYERUTILITIES_H + +// render window manager module +#include "MitkRenderWindowManagerExports.h" + +// mitk core +#include +#include +#include + +/** +* @brief Render window layer helper functions to retrieve the currently valid layer stack +*/ +namespace RenderWindowLayerUtilities +{ + typedef std::vector RendererVector; + typedef std::map> LayerStack; + + /** + * The base data node of a renderer is supposed to be on layer 0 (zero), which should be the lowest layer in a render window. + */ + const int BASE_LAYER_INDEX = 0; + /** + * The top layer index, denoting that no valid (positive) layer index is given and therefore the index should be resolved into the topmost layer index. + */ + const int TOP_LAYER_INDEX = -1; + + /** + * @brief Return the stack of layers of the given renderer as std::map, which guarantees ordering of the layers. + * Stacked layers are only included if they have their "fixedLayer" property set to true and their "layer" property set. + * + * If "renderer" = nullptr: a layer stack won't be created and an empty "LayerStack" will be returned. + * If "withBaseNode" = true: include the base node in the layer stack, if existing. + * If "withBaseNode" = false: exclude the base node from the layer stack. + * + * @param dataStorage Pointer to a data storage instance whose data nodes should be checked and possibly be included. + * @param renderer Pointer to the renderer instance for which the layer stack should be generated. + * @param withBaseNode Boolean to decide whether the base node should be included in or excluded from the layer stack. + */ + MITKRENDERWINDOWMANAGER_EXPORT LayerStack GetLayerStack(const mitk::DataStorage* dataStorage, const mitk::BaseRenderer* renderer, bool withBaseNode); + +} // namespace RenderWindowLayerUtilities + +#endif // MITKRENDERWINDOWLAYERUTILITIES_H diff --git a/Modules/RenderWindowManager/include/mitkRenderWindowViewDirectionController.h b/Modules/RenderWindowManager/include/mitkRenderWindowViewDirectionController.h new file mode 100644 index 0000000000..40752c35d4 --- /dev/null +++ b/Modules/RenderWindowManager/include/mitkRenderWindowViewDirectionController.h @@ -0,0 +1,74 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKRENDERWINDOWVIEWDIRECTIONCONTROLLER_H +#define MITKRENDERWINDOWVIEWDIRECTIONCONTROLLER_H + +// render window manager module +#include "MitkRenderWindowManagerExports.h" +#include "mitkRenderWindowLayerUtilities.h" + +// mitk core +#include +#include + +namespace mitk +{ + /** + * The RenderWindowViewDirectionController is used to manipulate the 'sliceNavigationController' of a given base renderer. + * The 'sliceNavigationController' is used to set the view direction / camera perspective of a base renderer. + * The view direction can changed to 'mitk::SliceNavigationController::Axial', 'mitk::SliceNavigationController::Frontal' + * or 'mitk::SliceNavigationController::Sagittal'. + * + * Functions with 'mitk::BaseRenderer* renderer' have 'nullptr' as their default argument. Using the nullptr + * these functions operate on all base renderer. Giving a specific base renderer will modify the node only for the given renderer. + */ + class MITKRENDERWINDOWMANAGER_EXPORT RenderWindowViewDirectionController + { + public: + + RenderWindowViewDirectionController(); + /** + * @brief Set the data storage on which to work. + */ + void SetDataStorage(DataStorage::Pointer dataStorage); + /** + * @brief Set the controlled base renderer. + */ + void SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer); + + // wrapper functions to modify the view direction + /** + * @brief Set the view direction for the given renderer (nullptr = all renderer) + * @param viewDirection The view direction that should be used for this renderer. + * Currently "axial", "coronal" and "sagittal" is supported. + * @param renderer Pointer to the renderer instance for which the view direction should be changed. + * If it is a nullptr (default) nothing happens. The view direction can not be changed + * for all controlled renderer at the moment. + */ + void SetViewDirectionOfRenderer(const std::string &viewDirection, BaseRenderer* renderer = nullptr); + + private: + + void InitializeViewByBoundingObjects(const BaseRenderer* renderer); + + DataStorage::Pointer m_DataStorage; + RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; + }; + +} // namespace mitk + +#endif // MITKRENDERWINDOWVIEWDIRECTIONCONTROLLER_H diff --git a/Modules/RenderWindowManager/src/QmitkRenderWindowDataModel.cpp b/Modules/RenderWindowManager/src/QmitkRenderWindowDataModel.cpp new file mode 100644 index 0000000000..a8888f8042 --- /dev/null +++ b/Modules/RenderWindowManager/src/QmitkRenderWindowDataModel.cpp @@ -0,0 +1,208 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// render window manager UI module +#include "QmitkRenderWindowDataModel.h" + +#include "QmitkCustomVariants.h" + +QmitkRenderWindowDataModel::QmitkRenderWindowDataModel(QObject* parent /*= nullptr*/) + : QAbstractTableModel(parent) +{ + // nothing here +} + +QmitkRenderWindowDataModel::~QmitkRenderWindowDataModel() +{ + if (m_DataStorage.IsNotNull()) + { + m_DataStorage->ChangedNodeEvent.RemoveListener(mitk::MessageDelegate1(this, &QmitkRenderWindowDataModel::DataChanged)); + m_DataStorage->RemoveNodeEvent.RemoveListener(mitk::MessageDelegate1(this, &QmitkRenderWindowDataModel::DataChanged)); + } +} + +int QmitkRenderWindowDataModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const +{ + if (parent.isValid()) + { + return 0; + } + + return static_cast(m_TempLayerStack.size()); +} + +int QmitkRenderWindowDataModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const +{ + if (parent.isValid()) + { + return 0; + } + + return 2; +} + +QVariant QmitkRenderWindowDataModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + { + return QVariant(); + } + + if ((index.row()) < static_cast(m_TempLayerStack.size())) + { + RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIt = m_TempLayerStack.begin(); + std::advance(layerStackIt, index.row()); + mitk::DataNode* dataNode = layerStackIt->second; + if (Qt::CheckStateRole == role && 0 == index.column()) + { + bool visibility = false; + dataNode->GetVisibility(visibility, m_BaseRenderer); + if (visibility) + { + return Qt::Checked; + } + else + { + return Qt::Unchecked; + } + } + else if (Qt::DisplayRole == role && 1 == index.column()) + { + return QVariant(QString::fromStdString(dataNode->GetName())); + } + else if (Qt::ToolTipRole == role) + { + if (0 == index.column()) + { + return QVariant("Show/hide data node."); + } + else if (1 == index.column()) + { + return QVariant("Name of the data node."); + } + } + else if (Qt::UserRole == role) + { + // user role always returns a reference to the data node, + // which can be used to modify the data node in the data storage + return QVariant::fromValue(dataNode); + } + } + return QVariant(); +} + +Qt::ItemFlags QmitkRenderWindowDataModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + if (0 == index.column()) + { + flags |= Qt::ItemIsUserCheckable; + } + + return flags; +} + +QVariant QmitkRenderWindowDataModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (Qt::Horizontal == orientation && Qt::DisplayRole == role) + { + if (0 == section) + { + return QVariant("Visibility"); + } + else if (1 == section) + { + return QVariant("Data node"); + } + } + return QVariant(); +} + +bool QmitkRenderWindowDataModel::setData(const QModelIndex &index, const QVariant &value, int role /*= Qt::EditRole*/) +{ + if (!index.isValid()) + { + return false; + } + + if ((index.row()) < static_cast(m_TempLayerStack.size())) + { + RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIt = m_TempLayerStack.begin(); + std::advance(layerStackIt, index.row()); + mitk::DataNode* dataNode = layerStackIt->second; + if (Qt::CheckStateRole == role) + { + Qt::CheckState newCheckState = static_cast(value.toInt()); + + if (Qt::PartiallyChecked == newCheckState || Qt::Checked == newCheckState) + { + dataNode->SetVisibility(true, m_BaseRenderer); + } + else + { + dataNode->SetVisibility(false, m_BaseRenderer); + } + emit dataChanged(index, index); + mitk::RenderingManager::GetInstance()->RequestUpdate(m_BaseRenderer->GetRenderWindow()); + return true; + } + } + return false; +} + +void QmitkRenderWindowDataModel::SetDataStorage(mitk::DataStorage::Pointer dataStorage) +{ + if (m_DataStorage != dataStorage) + { + // given data storage is a new data storage + if (m_DataStorage.IsNotNull()) + { + // remove listener from old data storage + m_DataStorage->ChangedNodeEvent.RemoveListener(mitk::MessageDelegate1(this, &QmitkRenderWindowDataModel::DataChanged)); + m_DataStorage->RemoveNodeEvent.RemoveListener(mitk::MessageDelegate1(this, &QmitkRenderWindowDataModel::DataChanged)); + } + // set the new data storage + m_DataStorage = dataStorage; + // register new data storage listener + if (m_DataStorage.IsNotNull()) + { + m_DataStorage->ChangedNodeEvent.AddListener(mitk::MessageDelegate1(this, &QmitkRenderWindowDataModel::DataChanged)); + m_DataStorage->RemoveNodeEvent.AddListener(mitk::MessageDelegate1(this, &QmitkRenderWindowDataModel::DataChanged)); + } + DataChanged(nullptr); + } +} + +void QmitkRenderWindowDataModel::SetCurrentRenderer(std::string renderWindowName) +{ + m_BaseRenderer = mitk::BaseRenderer::GetByName(renderWindowName); + if (m_DataStorage.IsNotNull()) + { + DataChanged(nullptr); + } +} + +void QmitkRenderWindowDataModel::DataChanged(const mitk::DataNode* /*dataNode*/) +{ + if (m_BaseRenderer.IsNotNull()) + { + // update the model, so that the table will be filled with the nodes information of the new data storage + beginResetModel(); + // get the current layer stack of the given base renderer + m_TempLayerStack = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, m_BaseRenderer, true); + endResetModel(); + } +} diff --git a/Modules/RenderWindowManager/src/mitkRenderWindowLayerController.cpp b/Modules/RenderWindowManager/src/mitkRenderWindowLayerController.cpp new file mode 100644 index 0000000000..7f47606503 --- /dev/null +++ b/Modules/RenderWindowManager/src/mitkRenderWindowLayerController.cpp @@ -0,0 +1,500 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// render window manager module +#include "mitkRenderWindowLayerController.h" + +mitk::RenderWindowLayerController::RenderWindowLayerController() + : m_DataStorage(nullptr) +{ + // nothing here +} + +void mitk::RenderWindowLayerController::SetDataStorage(DataStorage::Pointer dataStorage) +{ + if (m_DataStorage != dataStorage) + { + // set the new data storage + m_DataStorage = dataStorage; + } +} + +void mitk::RenderWindowLayerController::SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer) +{ + if (m_ControlledRenderer != controlledRenderer) + { + // set the new set of controlled renderer + m_ControlledRenderer = controlledRenderer; + } +} + +void mitk::RenderWindowLayerController::SetBaseDataNode(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == dataNode) + { + return; + } + + if (nullptr == renderer) + { + // set the data node as base data node in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + SetBaseDataNode(dataNode, renderer); + } + } + } + else + { + // get the layer stack with the base data node of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, true); + if (!stackedLayers.empty()) + { + // see if base layer exists + RenderWindowLayerUtilities::LayerStack::iterator layerStackIterator = stackedLayers.find(RenderWindowLayerUtilities::BASE_LAYER_INDEX); + if (layerStackIterator != stackedLayers.end()) + { + // remove the current base data node from the current renderer + layerStackIterator->second->GetPropertyList(renderer)->DeleteProperty("layer"); + layerStackIterator->second->SetBoolProperty("fixedLayer", false, renderer); + layerStackIterator->second->SetVisibility(false, renderer); + } + } + + // "RenderWindowLayerUtilities::BASE_LAYER_INDEX" indicates the base data node --> set as new background + dataNode->SetIntProperty("layer", RenderWindowLayerUtilities::BASE_LAYER_INDEX, renderer); + dataNode->SetBoolProperty("fixedLayer", true, renderer); + dataNode->SetVisibility(true, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + } +} + +void mitk::RenderWindowLayerController::InsertLayerNode(DataNode* dataNode, int layer /*= RenderWindowLayerUtilities::TOP_LAYER_INDEX*/, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == dataNode) + { + return; + } + + if (nullptr == renderer) + { + // insert data node in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + InsertLayerNode(dataNode, layer, renderer); + } + } + } + else + { + if (RenderWindowLayerUtilities::BASE_LAYER_INDEX == layer) + { + // "RenderWindowLayerUtilities::BASE_LAYER_INDEX" indicates the base data node --> set as new background (overwrite current base node if needed) + SetBaseDataNode(dataNode, renderer); + } + else + { + InsertLayerNodeInternal(dataNode, layer, renderer); + } + } +} + +void mitk::RenderWindowLayerController::InsertLayerNodeInternal(DataNode* dataNode, int newLayer, const BaseRenderer* renderer /*= nullptr*/) +{ + dataNode->SetBoolProperty("fixedLayer", true, renderer); + dataNode->SetVisibility(true, renderer); + + // get the layer stack without the base node of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); + if (stackedLayers.empty()) + { + // no layer stack for the current renderer + if (RenderWindowLayerUtilities::TOP_LAYER_INDEX == newLayer) + { + // set given layer as first layer above base layer (= 1) + newLayer = 1; + // alternatively: no layer stack for the current renderer -> insert as background node + //SetBaseDataNode(dataNode, renderer); + } + } + else + { + if (RenderWindowLayerUtilities::TOP_LAYER_INDEX == newLayer) + { + // get the first value (highest int-key -> topmost layer) + // +1 indicates inserting the node above the topmost layer + newLayer = stackedLayers.begin()->first + 1; + } + else + { + // see if layer is already taken + RenderWindowLayerUtilities::LayerStack::iterator layerStackIterator = stackedLayers.find(newLayer); + for (; layerStackIterator != stackedLayers.end(); ++layerStackIterator) + { + // move data nodes after the new layer one layer up + layerStackIterator->second->SetIntProperty("layer", layerStackIterator->first + 1, renderer); + } + } + } + // update data storage (the "data node model") + dataNode->SetIntProperty("layer", newLayer, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); +} + +void mitk::RenderWindowLayerController::RemoveLayerNode(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == dataNode) + { + return; + } + + if (nullptr == renderer) + { + // remove data node from all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + RemoveLayerNode(dataNode, renderer); + } + } + } + else + { + // "remove" node from the renderer list + dataNode->GetPropertyList(renderer)->DeleteProperty("layer"); + dataNode->SetBoolProperty("fixedLayer", false, renderer); + dataNode->SetVisibility(false, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + } +} + +bool mitk::RenderWindowLayerController::MoveNodeToFront(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == dataNode) + { + return false; + } + + if (nullptr == renderer) + { + // move data node to front in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + MoveNodeToFront(dataNode, renderer); + // we don't store/need the returned boolean value + return false; + } + } + } + else + { + // get the layer stack without the base node of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); + if (!stackedLayers.empty()) + { + // get the first value (highest int-key -> topmost layer) + int topmostLayer = stackedLayers.begin()->first; + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound && currentLayer < topmostLayer) + { + // move the current data node above the current topmost layer + dataNode->SetIntProperty("layer", topmostLayer+1, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + return true; + } + // else: data node has no layer information or is already the topmost layer node + } + // else: do not work with empty layer stack + } + return false; +} + +bool mitk::RenderWindowLayerController::MoveNodeToBack(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == dataNode) + { + return false; + } + + if (nullptr == renderer) + { + // move data node to back in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + MoveNodeToBack(dataNode, renderer); + // we don't store/need the returned boolean value + return false; + } + } + } + else + { + // get the layer stack without the base node of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); + if (!stackedLayers.empty()) + { + // get the last value (lowest int-key) + // cannot be the base layer as the base node was excluded by the 'GetLayerStack'-function + int lowermostLayer = stackedLayers.rbegin()->first; + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound && currentLayer > lowermostLayer) + { + // move the current data node to the current lowermost layer + dataNode->SetIntProperty("layer", lowermostLayer, renderer); + // move all other data nodes one layer up + for (auto& layer : stackedLayers) + { + if (layer.second != dataNode && layer.first < currentLayer) + { + layer.second->SetIntProperty("layer", layer.first + 1, renderer); + } + // else: current data node is the selected data node or + // was previously already above the selected data node + } + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + return true; + } + // else: data node has no layer information or is already the lowermost layer node + } + // else: do not work with empty layer stack + } + return false; +} + +bool mitk::RenderWindowLayerController::MoveNodeUp(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == dataNode) + { + return false; + } + + if (nullptr == renderer) + { + // move data node down in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + MoveNodeUp(dataNode, renderer); + // we don't store/need the returned boolean value + return false; + } + } + } + else + { + // get the layer stack without the base node of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); + if (!stackedLayers.empty()) + { + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound) + { + // get the current layer in the map of stacked layers + RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIterator = stackedLayers.find(currentLayer); + if (layerStackIterator != stackedLayers.end() && layerStackIterator != stackedLayers.begin()) + { + // found the element in the map, at different position than 'begin' -> + // current node is not on the topmost layer and therefore can be moved one layer up + // swap the layers of the dataNode and the dataNode on the next higher layer (previous map element) + RenderWindowLayerUtilities::LayerStack::const_iterator prevLayerStackIterator = std::prev(layerStackIterator); + dataNode->SetIntProperty("layer", prevLayerStackIterator->first, renderer); + prevLayerStackIterator->second->SetIntProperty("layer", currentLayer, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + return true; + } + // else: layer stack does not contain a layer with the 'currentLayer'data node or + // layer is already the topmost layer node + } + // else: data node has no layer information + } + // else: do not work with empty layer stack + } + return false; +} + +bool mitk::RenderWindowLayerController::MoveNodeDown(DataNode* dataNode, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == dataNode) + { + return false; + } + + if (nullptr == renderer) + { + // move data node up in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + MoveNodeDown(dataNode, renderer); + // we don't store/need the returned boolean value + return false; + } + } + } + else + { + // get the layer stack without the base node of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, false); + if (!stackedLayers.empty()) + { + // get the current layer value of the given data node + int currentLayer; + bool wasFound = dataNode->GetIntProperty("layer", currentLayer, renderer); + if (wasFound) + { + // get the current layer in the map of stacked layers + RenderWindowLayerUtilities::LayerStack::const_iterator layerStackIterator = stackedLayers.find(currentLayer); + if (layerStackIterator != stackedLayers.end()) + { + // found the element in the map ... + RenderWindowLayerUtilities::LayerStack::const_iterator nextLayerStackIterator = std::next(layerStackIterator); + if (nextLayerStackIterator != stackedLayers.end()) + { + // ... and found a successor -> + // current node is not on the lowermost layer and therefore can be moved one layer down + // swap the layers of the dataNode and the dataNode on the next lower layer (next map element) + dataNode->SetIntProperty("layer", nextLayerStackIterator->first, renderer); + nextLayerStackIterator->second->SetIntProperty("layer", currentLayer, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + return true; + } + // else: data node is already the lowermost layer node + } + // else: layer stack does not contain a layer with the 'currentLayer' + } + // else: data node has no layer information + } + // else: do not work with empty layer stack + } + return false; +} + +void mitk::RenderWindowLayerController::SetVisibilityOfDataNode(bool visibility, DataNode* dataNode, const BaseRenderer* renderer /*=nullptr*/) +{ + if (nullptr == dataNode) + { + return; + } + + if (nullptr == renderer) + { + // set visibility of data node in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + SetVisibilityOfDataNode(visibility, dataNode, renderer); + } + } + } + else + { + dataNode->SetVisibility(visibility, renderer); + dataNode->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + } +} + +void mitk::RenderWindowLayerController::HideDataNodeInAllRenderer(const DataNode* dataNode) +{ + if (nullptr == dataNode) + { + return; + } + + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + dataNode->GetPropertyList(renderer)->SetBoolProperty("visible", false); + } + } + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void mitk::RenderWindowLayerController::ResetRenderer(bool onlyVisibility /*= true*/, const BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == renderer) + { + // reset all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + ResetRenderer(onlyVisibility, renderer); + } + } + } + else + { + // get the layer stack with the base node of the current renderer + RenderWindowLayerUtilities::LayerStack stackedLayers = RenderWindowLayerUtilities::GetLayerStack(m_DataStorage, renderer, true); + if (!stackedLayers.empty()) + { + for (const auto& layer : stackedLayers) + { + int layerLevel; + layer.second->GetIntProperty("layer", layerLevel, renderer); + if (RenderWindowLayerUtilities::BASE_LAYER_INDEX == layerLevel) + { + // set base data node visibility to true + layer.second->SetVisibility(true, renderer); + } + else + { + // set visibility of all other data nodes to false + layer.second->SetVisibility(false, renderer); + + // modify layer node + if (!onlyVisibility) + { + // clear mode: additionally remove layer node from current renderer + layer.second->GetPropertyList(renderer)->DeleteProperty("layer"); + layer.second->SetBoolProperty("fixedLayer", false, renderer); + } + } + layer.second->Modified(); + } + + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + } + } +} diff --git a/Modules/RenderWindowManager/src/mitkRenderWindowLayerUtilities.cpp b/Modules/RenderWindowManager/src/mitkRenderWindowLayerUtilities.cpp new file mode 100644 index 0000000000..29ac67fbd1 --- /dev/null +++ b/Modules/RenderWindowManager/src/mitkRenderWindowLayerUtilities.cpp @@ -0,0 +1,63 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// render window manager module +#include "mitkRenderWindowLayerUtilities.h" + +// mitk core +#include +#include +#include + +RenderWindowLayerUtilities::LayerStack RenderWindowLayerUtilities::GetLayerStack(const mitk::DataStorage* dataStorage, const mitk::BaseRenderer* renderer, bool withBaseNode) +{ + LayerStack stackedLayers; + if (nullptr == dataStorage || nullptr == renderer) + { + // no nodes to stack or no renderer selected + return stackedLayers; + } + + int layer = -1; + mitk::NodePredicateProperty::Pointer helperObject = mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)); + mitk::NodePredicateNot::Pointer notAHelperObject = mitk::NodePredicateNot::New(helperObject); + + mitk::NodePredicateProperty::Pointer fixedLayer = mitk::NodePredicateProperty::New("fixedLayer", mitk::BoolProperty::New(true), renderer); + + // combine node predicates + mitk::NodePredicateAnd::Pointer combinedNodePredicate = mitk::NodePredicateAnd::New(notAHelperObject, fixedLayer); + mitk::DataStorage::SetOfObjects::ConstPointer filteredDataNodes = dataStorage->GetSubset(combinedNodePredicate); + + for (mitk::DataStorage::SetOfObjects::ConstIterator it = filteredDataNodes->Begin(); it != filteredDataNodes->End(); ++it) + { + mitk::DataNode::Pointer dataNode = it->Value(); + if (dataNode.IsNull()) + { + continue; + } + + bool layerFound = dataNode->GetIntProperty("layer", layer, renderer); + if (layerFound) + { + if (BASE_LAYER_INDEX != layer|| withBaseNode) + { + // data node is not on the base layer or the base layer should be included anyway + stackedLayers.insert(std::make_pair(layer, dataNode)); + } + } + } + return stackedLayers; +} diff --git a/Modules/RenderWindowManager/src/mitkRenderWindowViewDirectionController.cpp b/Modules/RenderWindowManager/src/mitkRenderWindowViewDirectionController.cpp new file mode 100644 index 0000000000..63df9a913e --- /dev/null +++ b/Modules/RenderWindowManager/src/mitkRenderWindowViewDirectionController.cpp @@ -0,0 +1,110 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkRenderWindowViewDirectionController.h" + +// mitk +#include +#include +#include + +mitk::RenderWindowViewDirectionController::RenderWindowViewDirectionController() + : m_DataStorage(nullptr) +{ + // nothing here +} + +void mitk::RenderWindowViewDirectionController::SetDataStorage(DataStorage::Pointer dataStorage) +{ + if (m_DataStorage != dataStorage) + { + // set the new data storage + m_DataStorage = dataStorage; + } +} + +void mitk::RenderWindowViewDirectionController::SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer) +{ + if (m_ControlledRenderer != controlledRenderer) + { + // set the new set of controlled renderer + m_ControlledRenderer = controlledRenderer; + } +} + +void mitk::RenderWindowViewDirectionController::SetViewDirectionOfRenderer(const std::string &viewDirection, BaseRenderer* renderer /*=nullptr*/) +{ + if (nullptr == renderer) + { + + // set visibility of data node in all controlled renderer + for (auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + //SetViewDirectionOfRenderer(viewDirection, renderer); + } + } + } + else + { + mitk::SliceNavigationController* sliceNavigationController = renderer->GetSliceNavigationController(); + if ("axial" == viewDirection) + { + sliceNavigationController->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); + } + else if ("coronal" == viewDirection) + { + sliceNavigationController->SetDefaultViewDirection(mitk::SliceNavigationController::Frontal); + } + else if ("sagittal" == viewDirection) + { + sliceNavigationController->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); + } + + // initialize the views to the bounding geometry + InitializeViewByBoundingObjects(renderer); + } +} + +void mitk::RenderWindowViewDirectionController::InitializeViewByBoundingObjects(const BaseRenderer* renderer) +{ + if (nullptr == m_DataStorage || nullptr == renderer) + { + return; + } + + // get all nodes that have not set "includeInBoundingBox" to false + mitk::NodePredicateProperty::Pointer includeInBoundingBox = mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false)); + mitk::NodePredicateNot::Pointer notIncludeInBoundingBox = mitk::NodePredicateNot::New(includeInBoundingBox); + + // get all non-helper objects + mitk::NodePredicateProperty::Pointer helperObject = mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)); + mitk::NodePredicateNot::Pointer notAHelperObject = mitk::NodePredicateNot::New(helperObject); + + // get all nodes that have a fixed layer for the given renderer + mitk::NodePredicateProperty::Pointer fixedLayer = mitk::NodePredicateProperty::New("fixedLayer", mitk::BoolProperty::New(true), renderer); + + // combine node predicates + mitk::NodePredicateAnd::Pointer combinedNodePredicate = mitk::NodePredicateAnd::New(notIncludeInBoundingBox, notAHelperObject, fixedLayer); + mitk::DataStorage::SetOfObjects::ConstPointer filteredDataNodes = m_DataStorage->GetSubset(combinedNodePredicate); + + // calculate bounding geometry of these nodes + mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(filteredDataNodes, "visible", renderer); + + // initialize the views to the bounding geometry + mitk::RenderingManager::GetInstance()->InitializeView(renderer->GetRenderWindow(), bounds); +} \ No newline at end of file diff --git a/Modules/RenderWindowManagerUI/CMakeLists.txt b/Modules/RenderWindowManagerUI/CMakeLists.txt new file mode 100644 index 0000000000..f94ad95c26 --- /dev/null +++ b/Modules/RenderWindowManagerUI/CMakeLists.txt @@ -0,0 +1,5 @@ +MITK_CREATE_MODULE( + INCLUDE_DIRS Qmitk + DEPENDS MitkQtWidgets MitkRenderWindowManager + PACKAGE_DEPENDS PUBLIC CTK Qt5|Core +) diff --git a/Modules/RenderWindowManagerUI/files.cmake b/Modules/RenderWindowManagerUI/files.cmake new file mode 100644 index 0000000000..a998c3cf7f --- /dev/null +++ b/Modules/RenderWindowManagerUI/files.cmake @@ -0,0 +1,15 @@ +set(H_FILES + include/QmitkRenderWindowManipulatorWidget.h +) + +set(CPP_FILES + QmitkRenderWindowManipulatorWidget.cpp +) + +set(MOC_H_FILES + include/QmitkRenderWindowManipulatorWidget.h +) + +set(UI_FILES + src/QmitkRenderWindowManipulatorWidget.ui +) \ No newline at end of file diff --git a/Modules/RenderWindowManagerUI/include/QmitkRenderWindowManipulatorWidget.h b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowManipulatorWidget.h new file mode 100644 index 0000000000..e08edafbce --- /dev/null +++ b/Modules/RenderWindowManagerUI/include/QmitkRenderWindowManipulatorWidget.h @@ -0,0 +1,108 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKRENDERWINDOWMANIPULATORWIDGET_H +#define QMITKRENDERWINDOWMANIPULATORWIDGET_H + +// render window manager UI module +#include "MitkRenderWindowManagerUIExports.h" +#include "ui_QmitkRenderWindowManipulatorWidget.h" + +// render window manager module +#include +#include +#include + +// qt +#include + +/** +* The QmitkRenderWindowManipulatorWidget offers a GUI to manipulate the base renderer / render windows of the MITK workbench. +* The widgets supports adding a layer to an active render window, moving layers up and down, removing layers, +* resetting layers (hiding them) or removing all layers at once. +* +* In order to use this widget, a (e.g.) plugin has to set the controlled renderer, which will be forwarded to +* a render window layer controller and a render window view direction controller. +* The plugin also has to provide a Q_SLOT that is connected to the 'AddLayerButtonClicked'-Q_SIGNAL of this widget. +* This allows for a customized add-layer functionality. +*/ +class MITKRENDERWINDOWMANAGERUI_EXPORT QmitkRenderWindowManipulatorWidget : public QWidget +{ + Q_OBJECT + +public: + + QmitkRenderWindowManipulatorWidget(mitk::DataStorage::Pointer dataStorage, QWidget* parent = nullptr); + /** + * @brief Set the controlled base renderer. + */ + void SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer); + /** + * @brief Set the currently selected render window + * + * @param renderWindowId the text inside the combo box + */ + void SetActiveRenderWindow(const QString &renderWindowId); + /** + * @brief Use the RenderWindowLayerController to insert the given data node into the currently active render window. + * The new node is placed on top of all existing layer nodes in that render window. + * + * @param dataNode The data node that should be inserted. + */ + void AddLayer(mitk::DataNode* dataNode); + /** + * @brief Use the RenderWindowLayerController to insert the given data node into all controlled render windows. + * The new node is placed on top of all existing layer nodes in the render window. + * + * @param dataNode The data node that should be inserted. + */ + void AddLayerToAllRenderer(mitk::DataNode* dataNode); + /** + * @brief Use the RenderWindowLayerController to hide the given data node in the currently active render window. + * + * @param dataNode The data node that should be hid. + */ + void HideDataNodeInAllRenderer(const mitk::DataNode* dataNode); + +Q_SIGNALS: + void AddLayerButtonClicked(); + +private Q_SLOTS: + + void RemoveLayer(); + void SetAsBaseLayer(); + + void MoveLayer(const QString &direction); + + void ResetRenderer(); + void ClearRenderer(); + + void ChangeViewDirection(const QString &viewDirection); + +private: + + void Init(); + void SetUpConnections(); + + Ui::QmitkRenderWindowManipulatorWidget m_Controls; + + mitk::DataStorage::Pointer m_DataStorage; + std::unique_ptr m_RenderWindowDataModel; + std::unique_ptr m_RenderWindowLayerController; + std::unique_ptr m_RenderWindowViewDirectionController; +}; + +#endif // QMITKRENDERWINDOWMANIPULATORWIDGET_H diff --git a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowManipulatorWidget.cpp b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowManipulatorWidget.cpp new file mode 100644 index 0000000000..7bfff148d9 --- /dev/null +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowManipulatorWidget.cpp @@ -0,0 +1,216 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// render window manager UI module +#include "QmitkRenderWindowManipulatorWidget.h" + +#include "QmitkCustomVariants.h" + +// mitk core +#include + +// qt +#include + +QmitkRenderWindowManipulatorWidget::QmitkRenderWindowManipulatorWidget(mitk::DataStorage::Pointer dataStorage, QWidget* parent /*=nullptr*/) + : m_DataStorage(dataStorage) + , QWidget(parent) +{ + Init(); +} + +void QmitkRenderWindowManipulatorWidget::Init() +{ + // create GUI from the Qt Designer's .ui file + m_Controls.setupUi(this); + + // initialize the render window layer controller and the render window view direction controller + // and set the controller renderer (in constructor) and the data storage + m_RenderWindowLayerController = std::make_unique(); + m_RenderWindowViewDirectionController = std::make_unique(); + m_RenderWindowLayerController->SetDataStorage(m_DataStorage); + m_RenderWindowViewDirectionController->SetDataStorage(m_DataStorage); + + // create a new model + m_RenderWindowDataModel = std::make_unique(this); + m_RenderWindowDataModel->SetDataStorage(m_DataStorage); + + m_Controls.renderWindowTableView->setModel(m_RenderWindowDataModel.get()); + m_Controls.renderWindowTableView->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_Controls.renderWindowTableView->horizontalHeader()->setStretchLastSection(true); + m_Controls.renderWindowTableView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_Controls.renderWindowTableView->setSelectionMode(QAbstractItemView::SingleSelection); + + SetUpConnections(); +} + +void QmitkRenderWindowManipulatorWidget::SetUpConnections() +{ + // signal to signal connection + connect(m_Controls.pushButtonAddLayer, SIGNAL(clicked()), this, SIGNAL(AddLayerButtonClicked())); + connect(m_Controls.pushButtonRemoveLayer, SIGNAL(clicked()), this, SLOT(RemoveLayer())); + connect(m_Controls.pushButtonSetAsBaseLayer, SIGNAL(clicked()), this, SLOT(SetAsBaseLayer())); + + QSignalMapper* udSignalMapper = new QSignalMapper(this); + udSignalMapper->setMapping(m_Controls.pushButtonMoveUp, QString("up")); + udSignalMapper->setMapping(m_Controls.pushButtonMoveDown, QString("down")); + connect(udSignalMapper, SIGNAL(mapped(const QString&)), this, SLOT(MoveLayer(const QString&))); + connect(m_Controls.pushButtonMoveUp, SIGNAL(clicked()), udSignalMapper, SLOT(map())); + connect(m_Controls.pushButtonMoveDown, SIGNAL(clicked()), udSignalMapper, SLOT(map())); + + connect(m_Controls.pushButtonResetRenderer, SIGNAL(clicked()), this, SLOT(ResetRenderer())); + connect(m_Controls.pushButtonClearRenderer, SIGNAL(clicked()), this, SLOT(ClearRenderer())); + + QSignalMapper* changeViewDirectionSignalMapper = new QSignalMapper(this); + changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonAxial, QString("axial")); + changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonCoronal, QString("coronal")); + changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonSagittal, QString("sagittal")); + connect(changeViewDirectionSignalMapper, SIGNAL(mapped(const QString&)), this, SLOT(ChangeViewDirection(const QString&))); + connect(m_Controls.radioButtonAxial, SIGNAL(clicked()), changeViewDirectionSignalMapper, SLOT(map())); + connect(m_Controls.radioButtonCoronal, SIGNAL(clicked()), changeViewDirectionSignalMapper, SLOT(map())); + connect(m_Controls.radioButtonSagittal, SIGNAL(clicked()), changeViewDirectionSignalMapper, SLOT(map())); +} + +void QmitkRenderWindowManipulatorWidget::SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer) +{ + m_RenderWindowLayerController->SetControlledRenderer(controlledRenderer); + m_RenderWindowViewDirectionController->SetControlledRenderer(controlledRenderer); +} + +void QmitkRenderWindowManipulatorWidget::SetActiveRenderWindow(const QString &renderWindowId) +{ + std::string currentRendererName = renderWindowId.toStdString(); + m_RenderWindowDataModel->SetCurrentRenderer(currentRendererName); + + mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(currentRendererName); + if (nullptr == selectedRenderer) + { + return; + } + + mitk::SliceNavigationController::ViewDirection viewDirection = selectedRenderer->GetSliceNavigationController()->GetDefaultViewDirection(); + switch (viewDirection) + { + case mitk::SliceNavigationController::Axial: + m_Controls.radioButtonAxial->setChecked(true); + break; + case mitk::SliceNavigationController::Frontal: + m_Controls.radioButtonCoronal->setChecked(true); + break; + case mitk::SliceNavigationController::Sagittal: + m_Controls.radioButtonSagittal->setChecked(true); + break; + default: + break; + } +} + +void QmitkRenderWindowManipulatorWidget::AddLayer(mitk::DataNode* dataNode) +{ + m_RenderWindowLayerController->InsertLayerNode(dataNode, -1, m_RenderWindowDataModel->GetCurrentRenderer()); +} + +void QmitkRenderWindowManipulatorWidget::AddLayerToAllRenderer(mitk::DataNode* dataNode) +{ + m_RenderWindowLayerController->InsertLayerNode(dataNode, -1, nullptr); +} + +void QmitkRenderWindowManipulatorWidget::HideDataNodeInAllRenderer(const mitk::DataNode* dataNode) +{ + m_RenderWindowLayerController->HideDataNodeInAllRenderer(dataNode); +} + +void QmitkRenderWindowManipulatorWidget::RemoveLayer() +{ + QModelIndex selectedIndex = m_Controls.renderWindowTableView->currentIndex(); + if (selectedIndex.isValid()) + { + + QVariant qvariantDataNode = m_RenderWindowDataModel->data(selectedIndex, Qt::UserRole); + if (qvariantDataNode.canConvert()) + { + mitk::DataNode* dataNode = qvariantDataNode.value(); + m_RenderWindowLayerController->RemoveLayerNode(dataNode, m_RenderWindowDataModel->GetCurrentRenderer()); + m_Controls.renderWindowTableView->clearSelection(); + } + } +} + +void QmitkRenderWindowManipulatorWidget::SetAsBaseLayer() +{ + QModelIndex selectedIndex = m_Controls.renderWindowTableView->currentIndex(); + if (selectedIndex.isValid()) + { + QVariant qvariantDataNode = m_RenderWindowDataModel->data(selectedIndex, Qt::UserRole); + if (qvariantDataNode.canConvert()) + { + mitk::DataNode* dataNode = qvariantDataNode.value(); + m_RenderWindowLayerController->SetBaseDataNode(dataNode, m_RenderWindowDataModel->GetCurrentRenderer()); + m_Controls.renderWindowTableView->clearSelection(); + } + } +} + +void QmitkRenderWindowManipulatorWidget::MoveLayer(const QString &direction) +{ + QModelIndex selectedIndex = m_Controls.renderWindowTableView->currentIndex(); + if (selectedIndex.isValid()) + { + QVariant qvariantDataNode = m_RenderWindowDataModel->data(selectedIndex, Qt::UserRole); + if (qvariantDataNode.canConvert()) + { + mitk::DataNode* dataNode = qvariantDataNode.value(); + const mitk::BaseRenderer* selectedRenderer = m_RenderWindowDataModel->GetCurrentRenderer(); + + bool success = false; + if ("up" == direction) + { + success = m_RenderWindowLayerController->MoveNodeUp(dataNode, selectedRenderer); + if (success) + { + // node has been successfully moved up + m_Controls.renderWindowTableView->selectRow(selectedIndex.row() - 1); + } + } + else + { + success = m_RenderWindowLayerController->MoveNodeDown(dataNode, selectedRenderer); + if (success) + { + // node has been successfully moved down + m_Controls.renderWindowTableView->selectRow(selectedIndex.row() + 1); + } + } + } + } +} + +void QmitkRenderWindowManipulatorWidget::ResetRenderer() +{ + m_RenderWindowLayerController->ResetRenderer(true, m_RenderWindowDataModel->GetCurrentRenderer()); + m_Controls.renderWindowTableView->clearSelection(); +} + +void QmitkRenderWindowManipulatorWidget::ClearRenderer() +{ + m_RenderWindowLayerController->ResetRenderer(false, m_RenderWindowDataModel->GetCurrentRenderer()); + m_Controls.renderWindowTableView->clearSelection(); +} + +void QmitkRenderWindowManipulatorWidget::ChangeViewDirection(const QString &viewDirection) +{ + m_RenderWindowViewDirectionController->SetViewDirectionOfRenderer(viewDirection.toStdString(), m_RenderWindowDataModel->GetCurrentRenderer()); +} diff --git a/Modules/RenderWindowManagerUI/src/QmitkRenderWindowManipulatorWidget.ui b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowManipulatorWidget.ui new file mode 100644 index 0000000000..01e6a1b05f --- /dev/null +++ b/Modules/RenderWindowManagerUI/src/QmitkRenderWindowManipulatorWidget.ui @@ -0,0 +1,120 @@ + + + QmitkRenderWindowManipulatorWidget + + + + 0 + 0 + 308 + 246 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Render window manager + + + + + + Render window overview + + + + + + + + + + + + Add Layer + + + + + + + Remove layer + + + + + + + Set as base layer + + + + + + + Move up + + + + + + + Move down + + + + + + + Reset render window + + + + + + + Clear render window + + + + + + + Axial + + + true + + + + + + + Coronal + + + + + + + Sagittal + + + + + + + + + + diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 4cdec681c8..f5510963c0 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,85 +1,86 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:OFF org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF + org.mitk.gui.qt.renderwindowmanager:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.igt.app.echotrack:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF org.mitk.gui.qt.multilabelsegmentation:ON org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF ) diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/CMakeLists.txt b/Plugins/org.mitk.gui.qt.renderwindowmanager/CMakeLists.txt new file mode 100644 index 0000000000..c7fa4849a9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_renderwindowmanager) + +mitk_create_plugin( + EXPORT_DIRECTIVE RENDERWINDOWMANAGER_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkRenderWindowManager MitkRenderWindowManagerUI +) diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..62b08443be --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/UserManual/Manual.dox @@ -0,0 +1,17 @@ +/** +\page org_mitk_gui_qt_renderwindowmanager The Renderwindowmanager + +\imageMacro{icon.png,"Icon of Renderwindowmanager",2.00} + +\tableofcontents + +\section org_mitk_gui_qt_renderwindowmanagerOverview Overview +Describe the features of your awesome plugin here +
    +
  • Increases productivity +
  • Creates beautiful images +
  • Generates PhD thesis +
  • Brings world peace +
+ +*/ diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/UserManual/icon.xpm new file mode 100644 index 0000000000..9057c20bc6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/UserManual/icon.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static const char * icon_xpm[] = { +"16 16 2 1", +" c #FF0000", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..be02fac9a8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_renderwindowmanager org.mitk.gui.qt.renderwindowmanager + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_renderwindowmanager_internal Internal + \ingroup org_mitk_gui_qt_renderwindowmanager + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.renderwindowmanager plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/files.cmake b/Plugins/org.mitk.gui.qt.renderwindowmanager/files.cmake new file mode 100644 index 0000000000..b6d60fcc37 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/files.cmake @@ -0,0 +1,25 @@ +set(INTERNAL_CPP_FILES + mitkPluginActivator.cpp + QmitkRenderWindowManagerView.cpp +) + +set(UI_FILES + src/internal/QmitkRenderWindowManagerControls.ui +) + +set(MOC_H_FILES + src/internal/mitkPluginActivator.h + src/internal/QmitkRenderWindowManagerView.h +) + +set(CACHED_RESOURCE_FILES + resources/LayerManager_48.png + plugin.xml +) + +set(QRC_FILES +) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.renderwindowmanager/manifest_headers.cmake new file mode 100644 index 0000000000..047fb72062 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "MITK Render window layer manager") +set(Plugin-Version "0.1") +set(Plugin-Vendor "DKFZ") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/plugin.xml b/Plugins/org.mitk.gui.qt.renderwindowmanager/plugin.xml new file mode 100644 index 0000000000..7faa5bd630 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/plugin.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/resources/LayerManager_48.png b/Plugins/org.mitk.gui.qt.renderwindowmanager/resources/LayerManager_48.png new file mode 100644 index 0000000000..6c0185156b Binary files /dev/null and b/Plugins/org.mitk.gui.qt.renderwindowmanager/resources/LayerManager_48.png differ diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerControls.ui b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerControls.ui new file mode 100644 index 0000000000..5951ce01ed --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerControls.ui @@ -0,0 +1,34 @@ + + + QmitkRenderWindowManagerControls + + + + 0 + 0 + 386 + 572 + + + + + 0 + 0 + + + + Render window manager plugin + + + + + + -1 + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp new file mode 100644 index 0000000000..1307b4045e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp @@ -0,0 +1,114 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// render window manager plugin +#include "QmitkRenderWindowManagerView.h" + +// blueberry +#include +#include + +// mitk core +#include +#include + +const std::string QmitkRenderWindowManagerView::VIEW_ID = "org.mitk.views.renderwindowmanager"; + +void QmitkRenderWindowManagerView::SetFocus() +{ + // nothing here +} + +void QmitkRenderWindowManagerView::CreateQtPartControl(QWidget* parent) +{ + // create GUI widgets + m_Controls.setupUi(parent); + // add custom render window manager UI widget to the 'renderWindowManagerTab' + m_RenderWindowManipulatorWidget = new QmitkRenderWindowManipulatorWidget(GetDataStorage(), parent); + m_RenderWindowManipulatorWidget->setObjectName(QStringLiteral("m_RenderWindowManipulatorWidget")); + m_Controls.verticalLayout->addWidget(m_RenderWindowManipulatorWidget); + + SetControlledRenderer(); + + for (const auto& renderer : m_ControlledRenderer) + { + m_Controls.comboBoxRenderWindowSelection->addItem(renderer->GetName()); + } + + OnRenderWindowSelectionChanged(m_Controls.comboBoxRenderWindowSelection->itemText(0)); + + connect(m_Controls.comboBoxRenderWindowSelection, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnRenderWindowSelectionChanged(const QString&))); + connect(m_RenderWindowManipulatorWidget, SIGNAL(AddLayerButtonClicked()), this, SLOT(OnAddLayerButtonClicked())); +} + +void QmitkRenderWindowManagerView::SetControlledRenderer() +{ + const mitk::RenderingManager::RenderWindowVector allRegisteredRenderWindows = mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); + mitk::BaseRenderer* baseRenderer = nullptr; + for (const auto &renderWindow : allRegisteredRenderWindows) + { + baseRenderer = mitk::BaseRenderer::GetInstance(renderWindow); + if (nullptr != baseRenderer) + { + m_ControlledRenderer.push_back(baseRenderer); + } + } + + m_RenderWindowManipulatorWidget->SetControlledRenderer(m_ControlledRenderer); +} + +void QmitkRenderWindowManagerView::OnRenderWindowSelectionChanged(const QString &renderWindowId) +{ + m_RenderWindowManipulatorWidget->SetActiveRenderWindow(renderWindowId); +} + +void QmitkRenderWindowManagerView::OnAddLayerButtonClicked() +{ + QList nodes = GetDataManagerSelection(); + for (mitk::DataNode* dataNode : nodes) + { + if (nullptr != dataNode) + { + m_RenderWindowManipulatorWidget->AddLayer(dataNode); + + // get child nodes of the current node + mitk::DataStorage::SetOfObjects::ConstPointer derivedNodes = GetDataStorage()->GetDerivations(dataNode, nullptr, false); + for (mitk::DataStorage::SetOfObjects::ConstIterator it = derivedNodes->Begin(); it != derivedNodes->End(); ++it) + { + m_RenderWindowManipulatorWidget->AddLayer(it->Value()); + } + } + } +} + +void QmitkRenderWindowManagerView::NodeAdded(const mitk::DataNode* node) +{ + bool global = false; + node->GetBoolProperty("globalObject_RWM", global); + if (global) + { + // initially insert new point set node into the node list of all render windows + // the node object of a new point set won't be visible due to its "helper object" property set to true + m_RenderWindowManipulatorWidget->AddLayerToAllRenderer(const_cast(node)); + } + else + { + // initially set new node as invisible in all render windows + // this way, each single renderer overwrites the common renderer and the node is invisible + // until it is inserted into the node list of a render windows + m_RenderWindowManipulatorWidget->HideDataNodeInAllRenderer(node); + } +} diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.h b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.h new file mode 100644 index 0000000000..ba9743fb77 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.h @@ -0,0 +1,82 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKRENDERWINDOWMANAGERVIEW_H +#define QMITKRENDERWINDOWMANAGERVIEW_H + +// render window manager plugin +#include "ui_QmitkRenderWindowManagerControls.h" + +// render window manager UI module +#include + +// blueberry +#include + +// qt +#include + +/** +* @brief RenderWindowManager +*/ +class QmitkRenderWindowManagerView : public QmitkAbstractView +{ + Q_OBJECT + +public: + + static const std::string VIEW_ID; + +protected: + + virtual void SetFocus() override; + + virtual void CreateQtPartControl(QWidget* parent) override; + +private Q_SLOTS: + + /** + * @brief Called when the user changes the render window selection in the combo box. + * + * @param renderWindowId The text inside the combo box. + */ + void OnRenderWindowSelectionChanged(const QString &renderWindowId); + /** + * @brief Called when the 'AddLayer'-button of he render window manipulator widget has been pushed. + */ + void OnAddLayerButtonClicked(); + +private: + + void SetControlledRenderer(); + + /** + * @brief Reacts to a node that has been added to the data storage. + * 1. Insert new node into the node list of all render windows, if it is an "globalObject_RWM"-node. + * or else + * 2. Set data node invisible in all render windows, as soon as the node is added to the data storage. + */ + void NodeAdded(const mitk::DataNode* node) override; + + // the Qt parent of our GUI + QWidget* m_Parent; + Ui::QmitkRenderWindowManagerControls m_Controls; + + QmitkRenderWindowManipulatorWidget* m_RenderWindowManipulatorWidget; + RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; +}; + +#endif // QMITKRENDERWINDOWMANAGERVIEW_H diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/mitkPluginActivator.cpp new file mode 100644 index 0000000000..460e788f1d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/mitkPluginActivator.cpp @@ -0,0 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkPluginActivator.h" +#include "QmitkRenderWindowManagerView.h" + +namespace mitk +{ + void RenderWindowManagerActivator::start(ctkPluginContext *context) + { + BERRY_REGISTER_EXTENSION_CLASS(QmitkRenderWindowManagerView, context) + } + + void RenderWindowManagerActivator::stop(ctkPluginContext *context) { Q_UNUSED(context) } +} diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/mitkPluginActivator.h new file mode 100644 index 0000000000..e391a68f8d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/mitkPluginActivator.h @@ -0,0 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKPLUGINACTIVATOR_H +#define MITKPLUGINACTIVATOR_H + +#include + +namespace mitk +{ + class RenderWindowManagerActivator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_renderwindowmanager") + Q_INTERFACES(ctkPluginActivator) + + public: + void start(ctkPluginContext* context) override; + void stop(ctkPluginContext* context) override; + + }; +} + +#endif // MITKPLUGINACTIVATOR_H