diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index 282fbb5391..329ee2a9fa 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,81 +1,82 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core CommandLine AppUtil DCMTesting RDF LegacyIO DataTypesExt Overlays LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction ImageStatistics LegacyAdaptors SceneSerialization Gizmo GraphAlgorithms Multilabel ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QtWidgets QtWidgetsExt QtWidgetsWeb 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 ) 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..b2931816b9 --- /dev/null +++ b/Modules/RenderWindowManager/files.cmake @@ -0,0 +1,18 @@ +set(H_FILES + include/QmitkVisibilityDelegate.h + include/QmitkRenderWindowDataModel.h + + include/mitkRenderWindowLayerController.h +) + +set(CPP_FILES + QmitkVisibilityDelegate.cpp + QmitkRenderWindowDataModel.cpp + + mitkRenderWindowLayerController.cpp +) + +set(MOC_H_FILES + include/QmitkVisibilityDelegate.h + include/QmitkRenderWindowDataModel.h +) diff --git a/Modules/RenderWindowManager/include/QmitkRenderWindowDataModel.h b/Modules/RenderWindowManager/include/QmitkRenderWindowDataModel.h new file mode 100644 index 0000000000..e963637401 --- /dev/null +++ b/Modules/RenderWindowManager/include/QmitkRenderWindowDataModel.h @@ -0,0 +1,78 @@ +/*=================================================================== + +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 +#include "MitkRenderWindowManagerExports.h" + +//mitk +#include + +// qt +#include + +/* +* @brief This class extends the 'QAbstractItemModel' to meet the specific requirements of the QmitkRenderWindowDataModel. +*/ +class MITKRENDERWINDOWMANAGER_EXPORT QmitkRenderWindowDataModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + + typedef std::string RenderWindowName; + typedef std::vector DataNodeNamesVector; + // TODO: use std::map RenderWindowDataNodesMap; + + QmitkRenderWindowDataModel(QObject* parent = nullptr); + virtual ~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 SetCurrentRenderWindowName(std::string renderWindowName); + + void InsertLayerNode(std::string dataNodeName, std::string renderer); + void MoveNodeUp(int rowIndex, std::string dataNodeName, std::string renderer); + void MoveNodeDown(int rowIndex, std::string dataNodeName, std::string renderer); + +signals: + void VisibilityChanged(int index, bool isDataNodeVisible); + +private: + + mitk::DataStorage::Pointer m_DataStorage; + // map from render window name / id to vector of data node names of the specific render window + RenderWindowDataNodesMap m_RenderWindowDataNodesMap; + RenderWindowName m_CurrentRenderWindowName; + +}; + +#endif // QmitkRenderWindowDataModel_h diff --git a/Modules/RenderWindowManager/include/QmitkVisibilityDelegate.h b/Modules/RenderWindowManager/include/QmitkVisibilityDelegate.h new file mode 100644 index 0000000000..29fdf5a975 --- /dev/null +++ b/Modules/RenderWindowManager/include/QmitkVisibilityDelegate.h @@ -0,0 +1,57 @@ +/*=================================================================== + +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 QmitkVisibilityDelegate_h +#define QmitkVisibilityDelegate_h + +// render window manager +#include "MitkRenderWindowManagerExports.h" + +// qt +#include +#include + +#include + +/* +* @brief +*/ +class MITKRENDERWINDOWMANAGER_EXPORT QmitkVisibilityDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + QmitkVisibilityDelegate(QObject* parent = 0); + + // Create Editor when we construct + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + + //// Then, we set the Editor + //void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE; + // + //// When we modify data, this model reflect the change + //void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE; + + // Give the SpinBox the info on size and location + void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + + void paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + + bool editorEvent(QEvent *event, QAbstractItemModel* model, const QStyleOptionViewItem &option, const QModelIndex &index); +}; + +#endif //QmitkVisabilityDelegate_h diff --git a/Modules/RenderWindowManager/include/mitkRenderWindowLayerController.h b/Modules/RenderWindowManager/include/mitkRenderWindowLayerController.h new file mode 100644 index 0000000000..03c78a2098 --- /dev/null +++ b/Modules/RenderWindowManager/include/mitkRenderWindowLayerController.h @@ -0,0 +1,145 @@ +/*=================================================================== + +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 +#include "MitkRenderWindowManagerExports.h" +#include + +// mitk +#include +#include +#include + +namespace mitk +{ + /* + * TODO: generate layer stack on demand or keep layer stack of each render window on hand + * + * TODO: really layer 0 (zero)? + * 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. + * + * Functions with 'const mitk::BaseRenderer* renderer' have 'nullptr' as their default argument. Using the nullptr + * these functions operate on all base renderer. + */ + class MITKRENDERWINDOWMANAGER_EXPORT RenderWindowLayerController + { + public: + typedef std::vector RendererVector; + typedef std::map LayerStack; + + RenderWindowLayerController(); + RenderWindowLayerController(std::shared_ptr renderWindowDataModel); + + virtual ~RenderWindowLayerController(); + /** + * @brief set the data storage on which to work + */ + void SetDataStorage(DataStorage::Pointer dataStorage); + DataStorage::Pointer GetDataStorage() { return m_DataStorage; }; + /** + * @brief set the controlled base renderer by specifying the corresponding render windows + */ + void SetControlledRenderer(const mitk::RenderingManager::RenderWindowVector &renderWindows); + /** + * @brief set the controlled base renderer + */ + void SetControlledRenderer(RendererVector renderWindows); + RendererVector GetControlledRenderer() { return m_ControlledRenderer; }; + //itkGetMacro(ControlledRenderer, RendererVector); + + // 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 (nullptr = all renderer) + */ + void SetBaseDataNode(DataNode* dataNode, const mitk::BaseRenderer* renderer = nullptr); + /** + * @brief insert the given data node at the specified layer for the given renderer (nullptr = all renderer) + * + * 'layer = -1' (default) inserts the given data node at the top of the node stack (topmost layer) + * new layer nodes have to have their 'fixedLayer' property set to true + */ + void InsertLayerNode(DataNode* dataNode, int layer = -1, const mitk::BaseRenderer* renderer = nullptr); + /** + * @brief + */ + void RemoveLayerNode(int rowIndex, DataNode* dataNode, const mitk::BaseRenderer* renderer = nullptr); + + /** + * @brief set the node in the given renderer as the topmost layer (nullptr = all renderer) + * + * @return true, if the node was successfully moved, false otherwise + */ + bool MoveNodeToFront(DataNode* dataNode, const mitk::BaseRenderer* renderer = nullptr); + /** + * @brief set the node in the given renderer as the lowermost layer (nullptr = all renderer) + * + * @return true, if the node was successfully moved, false otherwise + */ + bool MoveNodeToBack(DataNode* dataNode, const mitk::BaseRenderer* renderer = nullptr); + /** + * @brief move the node in the given renderer one layer down (nullptr = all renderer) + * + * @return true, if the node was successfully moved, false otherwise + */ + bool MoveNodeUp(int rowIndex, DataNode* dataNode, const mitk::BaseRenderer* renderer = nullptr); + /** + * @brief move the node in the given renderer one layer up (nullptr = all renderer) + * + * @return true, if the node was successfully moved, false otherwise + */ + bool MoveNodeDown(int rowIndex, DataNode* dataNode, const mitk::BaseRenderer* renderer = nullptr); + /** + * @brief set the visibility of the given data node for the given renderer (nullptr = all renderer) + */ + void SetVisibilityOfDataNode(bool visiblity, DataNode* dataNode, const mitk::BaseRenderer* renderer = nullptr); + /** + * @brief hide the given data node by setting the 'fixedLayer'property and the 'visible' property of this data node for + * all controlled renderer to false + * + * setting the 'visible' property of a data node for a certain renderer will overwrite the same property of the common renderer + */ + void HideDataNodeInAllRenderer(const DataNode* dataNode); + /** + * @brief reset the given render window (nullptr = all renderer): + * if 'onlyVisibility = true': set all data nodes for the 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 + */ + void ResetRenderer(bool onlyVisibility = true, const mitk::BaseRenderer* renderer = nullptr); + /** + * @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 set their 'fixedLayer' property to true + * + * if 'renderer" = nullptr: a layer stack won't be created and an empty 'LayerStack' will be returned + * if 'withBaseNode' = true: include the base node (layer = 0) in the layer stack, if existing + * if 'withBaseNode' = false: exclude the base node (layer = 0) from the layer stack + */ + LayerStack GetLayerStack(const mitk::BaseRenderer* renderer, bool withBaseNode); + + private: + + void InsertLayerNodeInternal(DataNode* dataNode, int layer, const mitk::BaseRenderer* renderer = nullptr); + + std::shared_ptr m_RenderWindowDataModel; + DataStorage::Pointer m_DataStorage; + RendererVector m_ControlledRenderer; + }; + +} // namespace mitk + +#endif // MITKRENDERWINDOWLAYERCONTROLLER_H diff --git a/Modules/RenderWindowManager/src/QmitkRenderWindowDataModel.cpp b/Modules/RenderWindowManager/src/QmitkRenderWindowDataModel.cpp new file mode 100644 index 0000000000..e871d74f0d --- /dev/null +++ b/Modules/RenderWindowManager/src/QmitkRenderWindowDataModel.cpp @@ -0,0 +1,226 @@ +/*=================================================================== + +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 +#include + +#include "QmitkRenderWindowDataModel.h" + +// mitk +#include + +QmitkRenderWindowDataModel::QmitkRenderWindowDataModel(QObject* parent) + : QAbstractTableModel(parent) +{ + +} + +int QmitkRenderWindowDataModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + { + return 0; + } + + std::map::const_iterator iterator = m_RenderWindowDataNodesMap.find(m_CurrentRenderWindowName); + if (iterator == m_RenderWindowDataNodesMap.end()) + { + return 0; + } + else + { + return iterator->second.size(); + } +} + +int QmitkRenderWindowDataModel::columnCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + { + return 0; + } + + return 2; +} + +QVariant QmitkRenderWindowDataModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + { + return QVariant(); + } + + // find the list of data nodes of the given render window + std::map::const_iterator iterator = m_RenderWindowDataNodesMap.find(m_CurrentRenderWindowName); + if (iterator != m_RenderWindowDataNodesMap.end() + && static_cast(index.row()) < iterator->second.size()) + { + const std::string &dataNodeName = iterator->second.at(iterator->second.size() - index.row() - 1); + // different behavior for the columns + switch (index.column()) + { + case 0: + if (role == Qt::CheckStateRole) + { + const mitk::DataNode* selectedDataNode = m_DataStorage->GetNamedNode(dataNodeName); + const mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(m_CurrentRenderWindowName); + + bool visibility = false; + // TODO: use the current renderer + selectedDataNode->GetVisibility(visibility, selectedRenderer); + if (visibility) + { + return Qt::Checked; + } + else + { + return Qt::Unchecked; + } + } + else if (role == Qt::ToolTipRole) + { + return QVariant("Show/hide data node."); + } + break; + case 1: + if (role == Qt::DisplayRole) + { + return QVariant(QString::fromStdString(dataNodeName)); + } + else if (role == Qt::ToolTipRole) + { + return QVariant("Name of the data node."); + } + } + } + return QVariant(); +} + +Qt::ItemFlags QmitkRenderWindowDataModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + if (index.column() == 0) + { + flags |= Qt::ItemIsUserCheckable; + } + + return flags; +} + +QVariant QmitkRenderWindowDataModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (Qt::Horizontal == orientation && Qt::DisplayRole == role) + { + if (section == 0) + { + return QVariant("Visibility"); + } + else if (section == 1) + { + return QVariant("Data node"); + } + } + return QVariant(); +} + +bool QmitkRenderWindowDataModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + { + return false; + } + + // find the list of data nodes of the given render window + std::map::const_iterator iterator = m_RenderWindowDataNodesMap.find(m_CurrentRenderWindowName); + if (iterator != m_RenderWindowDataNodesMap.end() + && static_cast(index.row()) < iterator->second.size()) + { + + if (Qt::CheckStateRole == role) + { + Qt::CheckState newCheckState = static_cast(value.toInt()); + + // retrieve the data node from the data storage + const std::string &dataNodeName = iterator->second.at(iterator->second.size() - index.row() - 1); + mitk::DataNode* selectedDataNode = m_DataStorage->GetNamedNode(dataNodeName); + const mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(m_CurrentRenderWindowName); + + if (Qt::PartiallyChecked == newCheckState || Qt::Checked == newCheckState) + { + selectedDataNode->SetVisibility(true, selectedRenderer); + } + else + { + selectedDataNode->SetVisibility(false, selectedRenderer); + } + emit dataChanged(index, index); + mitk::RenderingManager::GetInstance()->RequestUpdate(selectedRenderer->GetRenderWindow()); + return true; + } + } + return false; +} + +void QmitkRenderWindowDataModel::SetDataStorage(mitk::DataStorage::Pointer dataStorage) +{ + if (m_DataStorage != dataStorage) + { + // set the new data storage + m_DataStorage = dataStorage; + } +} + +void QmitkRenderWindowDataModel::SetCurrentRenderWindowName(std::string renderWindowName) +{ + m_CurrentRenderWindowName = renderWindowName; + + int numberOfRows = m_RenderWindowDataNodesMap[m_CurrentRenderWindowName].size(); + + // notify view, so that the table will be filled with the nodes information of the newly selected renderer + emit dataChanged(createIndex(0, 0), createIndex(numberOfRows, columnCount())); +} + +void QmitkRenderWindowDataModel::InsertLayerNode(std::string dataNodeName, std::string renderer) +{ + // checking for the node list of the given renderer + // checking with [] creates an empty 'DataNodeNamesVector' if the renderer is currently not used as a key + DataNodeNamesVector &dataNodeNamesVector = m_RenderWindowDataNodesMap[renderer]; + beginInsertRows(QModelIndex(), 0, 0); + dataNodeNamesVector.push_back(dataNodeName); + endInsertRows(); +} + +void QmitkRenderWindowDataModel::MoveNodeUp(int rowIndex, std::string dataNodeName, std::string renderer) +{ + std::map::iterator iterator = m_RenderWindowDataNodesMap.find(renderer); + if (iterator != m_RenderWindowDataNodesMap.end()) + { + // swap item at 'dataNodeName' with the previous data node in the vector + std::swap(iterator->second[rowIndex], iterator->second[rowIndex - 1]); + emit dataChanged(createIndex(rowIndex, 1), createIndex(rowIndex - 1, 1)); + } +} + +void QmitkRenderWindowDataModel::MoveNodeDown(int rowIndex, std::string dataNodeName, std::string renderer) +{ + std::map::iterator iterator = m_RenderWindowDataNodesMap.find(renderer); + if (iterator != m_RenderWindowDataNodesMap.end()) + { + // swap item at 'dataNodeName' with the next data node in the vector + std::swap(iterator->second[rowIndex], iterator->second[rowIndex + 1]); + emit dataChanged(createIndex(rowIndex, 1), createIndex(rowIndex + 1, 1)); + } +} diff --git a/Modules/RenderWindowManager/src/QmitkVisibilityDelegate.cpp b/Modules/RenderWindowManager/src/QmitkVisibilityDelegate.cpp new file mode 100644 index 0000000000..19be4b136b --- /dev/null +++ b/Modules/RenderWindowManager/src/QmitkVisibilityDelegate.cpp @@ -0,0 +1,131 @@ +/*=================================================================== + +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 "QmitkVisibilityDelegate.h" + +// qt +#include +#include +#include +#include +#include +#include +#include + +static QRect CheckBoxRect(const QStyleOptionViewItem &view_item_style_options) +{ + QStyleOptionButton check_box_style_option; + QRect check_box_rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &check_box_style_option); + QPoint check_box_point(view_item_style_options.rect.x() + + view_item_style_options.rect.width() / 2 - + check_box_rect.width() / 2, + view_item_style_options.rect.y() + + view_item_style_options.rect.height() / 2 - + check_box_rect.height() / 2); + return QRect(check_box_point, check_box_rect.size()); +} + +QmitkVisibilityDelegate::QmitkVisibilityDelegate(QObject* parent) + : QStyledItemDelegate(parent) +{ + // nothing here +} + +QWidget* QmitkVisibilityDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const +{ + QCheckBox* editor = new QCheckBox(parent); +// editor->setFrame(false); +// editor->setMinimum(0); +// editor->setMaximum(100); +// + return editor; +} + +//void QmitkVisibilityDelegate::setEditorData(QWidget *editor, +// const QModelIndex &index) const +//{ +// int value = index.model()->data(index, Qt::EditRole).toInt(); +// +// QSpinBox *spinBox = static_cast(editor); +// spinBox->setValue(value); +//} +// +//void QmitkVisabilityDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, +// const QModelIndex &index) const +//{ +// QSpinBox *spinBox = static_cast(editor); +// spinBox->interpretText(); +// int value = spinBox->value(); +// +// model->setData(index, value, Qt::EditRole); +//} + +void QmitkVisibilityDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + +void QmitkVisibilityDelegate::paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + bool checkValue = index.data(Qt::DisplayRole).toBool(); + + QStyleOptionButton BtnStyle; + BtnStyle.state = QStyle::State_Enabled; + + if (checkValue) + { + BtnStyle.state |= QStyle::State_On; + } + else + { + BtnStyle.state |= QStyle::State_Off; + } + + BtnStyle.direction = QApplication::layoutDirection(); + BtnStyle.rect = CheckBoxRect(option); + QApplication::style()->drawControl(QStyle::CE_CheckBox, &BtnStyle, painter); +} + +bool QmitkVisibilityDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem &option, const QModelIndex &index) +{ + Q_ASSERT(event); + Q_ASSERT(model); + + // make sure that the item is checkable + Qt::ItemFlags flags = model->flags(index); + if (!(flags & Qt::ItemIsEditable) || !(flags & Qt::ItemIsEnabled)) + { + return false; + } + + // make sure that we have the right event type + QMouseEvent* mouseEvent = dynamic_cast(event); + if (!mouseEvent) + { + return false; + } + else + { + if (mouseEvent->type() != QEvent::MouseButtonRelease || mouseEvent->button() != Qt::LeftButton) + { + return false; + } + } + + bool newState = !(index.data(Qt::EditRole).toBool()); + + return model->setData(index, QVariant(newState), Qt::EditRole); +} diff --git a/Modules/RenderWindowManager/src/mitkRenderWindowLayerController.cpp b/Modules/RenderWindowManager/src/mitkRenderWindowLayerController.cpp new file mode 100644 index 0000000000..bb1f56b6ab --- /dev/null +++ b/Modules/RenderWindowManager/src/mitkRenderWindowLayerController.cpp @@ -0,0 +1,521 @@ +/*=================================================================== + +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 "mitkRenderWindowLayerController.h" +#include "mitkRenderingManager.h" + +// mitk +#include +#include + +mitk::RenderWindowLayerController::RenderWindowLayerController() + : m_DataStorage(nullptr) +{ + SetDataStorage(RenderingManager::GetInstance()->GetDataStorage()); + SetControlledRenderer(RenderingManager::GetInstance()->GetAllRegisteredRenderWindows()); +} + +mitk::RenderWindowLayerController::RenderWindowLayerController(std::shared_ptr renderWindowDataModel) + : m_RenderWindowDataModel(std::move(renderWindowDataModel)) + , m_DataStorage(nullptr) +{ + SetDataStorage(RenderingManager::GetInstance()->GetDataStorage()); + SetControlledRenderer(RenderingManager::GetInstance()->GetAllRegisteredRenderWindows()); +} + +mitk::RenderWindowLayerController::~RenderWindowLayerController() +{ +} + +void mitk::RenderWindowLayerController::SetDataStorage(DataStorage::Pointer dataStorage) +{ + if (m_DataStorage != dataStorage) + { + // set the new data storage + m_DataStorage = dataStorage; + } + + // TODO: add listener? +} + +void mitk::RenderWindowLayerController::SetControlledRenderer(const mitk::RenderingManager::RenderWindowVector &renderWindows) +{ + BaseRenderer* baseRenderer = nullptr; + for (const auto &renderWindow : renderWindows) + { + baseRenderer = BaseRenderer::GetInstance(renderWindow); + if (nullptr != baseRenderer) + { + m_ControlledRenderer.push_back(baseRenderer); + } + } +} + +void mitk::RenderWindowLayerController::SetControlledRenderer(RendererVector renderWindows) +{ + m_ControlledRenderer = renderWindows; +} + +void mitk::RenderWindowLayerController::SetBaseDataNode(DataNode* dataNode, const mitk::BaseRenderer* renderer /*= nullptr*/) +{ + 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 + LayerStack stackedLayers = GetLayerStack(renderer, true); + if (!stackedLayers.empty()) + { + // see if base layer exists + LayerStack::iterator layerStackIterator = stackedLayers.find(0); + if (layerStackIterator != stackedLayers.end()) + { + // remove the current base data node from the current renderer + layerStackIterator->second->SetBoolProperty("fixedLayer", false, renderer); + layerStackIterator->second->SetVisibility(false, renderer); + } + } + + // 0 indicates the base data node --> set as new background + dataNode->SetIntProperty("layer", 0, renderer); + dataNode->SetBoolProperty("fixedLayer", true, renderer); + dataNode->SetVisibility(true, renderer); + } +} + +void mitk::RenderWindowLayerController::InsertLayerNode(DataNode* dataNode, int layer /*= -1*/, const mitk::BaseRenderer* renderer /*= nullptr*/) +{ + 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 (0 == layer) + { + // 0 indicates the base data node --> set as new background (overwrite current base node if needed) + SetBaseDataNode(dataNode, renderer); + } + else + { + InsertLayerNodeInternal(dataNode, layer, renderer); + } + + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + } +} + +void mitk::RenderWindowLayerController::InsertLayerNodeInternal(DataNode* dataNode, int newLayer, const mitk::BaseRenderer* renderer /*= nullptr*/) +{ + dataNode->SetBoolProperty("fixedLayer", true, renderer); + dataNode->SetVisibility(true, renderer); + + // get the layer stack without the base node of the current renderer + LayerStack stackedLayers = GetLayerStack(renderer, false); + if (stackedLayers.empty()) + { + // no layer stack for the current renderer + if (-1 == 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 (-1 == newLayer) + { + // get the last value (highest int-key -> topmost layer) + // +1 indicates inserting the node above the topmost layer + newLayer = stackedLayers.rbegin()->first + 1; + } + else + { + // see if layer is already taken + 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); + // update render window data model (the "view model") + m_RenderWindowDataModel->InsertLayerNode(dataNode->GetName(), renderer->GetName()); +} + +void mitk::RenderWindowLayerController::RemoveLayerNode(int rowIndex, DataNode* dataNode, const mitk::BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == renderer) + { + // remove data node from all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + // TODO: does not work here: rowIndex is different for different render window node lists + RemoveLayerNode(rowIndex, dataNode, renderer); + } + } + } + else + { + dataNode->SetBoolProperty("fixedLayer", false, renderer); + dataNode->SetVisibility(false, renderer); + + m_RenderWindowDataModel->MoveNodeUp(rowIndex, dataNode->GetName(), renderer->GetName()); + + mitk::RenderingManager::GetInstance()->RequestUpdate(renderer->GetRenderWindow()); + } +} + + +bool mitk::RenderWindowLayerController::MoveNodeToFront(DataNode* dataNode, const mitk::BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == renderer) + { + // move data node to front in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + MoveNodeToFront(dataNode, renderer); + } + } + } + else + { + // get the layer stack without the base node of the current renderer + LayerStack stackedLayers = GetLayerStack(renderer, false); + if (!stackedLayers.empty()) + { + // get the last value (highest int-key -> topmost layer) + int topmostLayer = 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 < topmostLayer) + { + // move the current data node to the current topmost layer + dataNode->SetIntProperty("layer", topmostLayer, renderer); + + for (auto& layer : stackedLayers) + { + if (layer.second != dataNode && layer.first > currentLayer) + { + // move all other data nodes one layer down, if their layer was above the layer of the current node + layer.second->SetIntProperty("layer", layer.first - 1, renderer); + // alternatively: stack all layers below the topmost layer + // this would fill gaps between the layers of the renderer, every time a node is moved to front + // TODO: reverse iteration needed! layer.second->SetIntProperty("layer", --topmostLayer, renderer); + return true; + } + // else: current data node has already been moved to the topmost layer + } + } + // 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 mitk::BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == renderer) + { + // move data node to back in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + MoveNodeToBack(dataNode, renderer); + } + } + } + else + { + // get the layer stack without the base node of the current renderer + LayerStack stackedLayers = GetLayerStack(renderer, false); + if (!stackedLayers.empty()) + { + // get the first value (lowest int-key) + // cannot be the layer 0 (base node) as the base node was excluded by the 'GetLayerStack'-function + int lowermostLayer = 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 > 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.second->SetIntProperty("layer", layer.first + 1, renderer); + // alternatively: stack all layers on top of the lowermost layer + // this would fill gaps between the layers of the renderer, every time a node is moved to back + //layer.second->SetIntProperty("layer", ++lowermostLayer, renderer); + return true; + } + // else: current data node has already been moved to the lowermost layer + } + } + // 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(int rowIndex, DataNode* dataNode, const mitk::BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == renderer) + { + // move data node down in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + // TODO: does not work here: rowIndex is different for different render window node lists + MoveNodeUp(rowIndex, dataNode, renderer); + } + } + } + else + { + // get the layer stack without the base node of the current renderer + LayerStack stackedLayers = GetLayerStack(renderer, false); + if (!stackedLayers.empty()) + { + // get the last value (highest int-key -> topmost layer) + int topmostLayer = 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 < topmostLayer) + { + // 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 + LayerStack::iterator layerStackIterator = stackedLayers.find(currentLayer); + ++layerStackIterator; + DataNode::Pointer higherDataNode = layerStackIterator->second; + dataNode->SetIntProperty("layer", layerStackIterator->first, renderer); + higherDataNode->SetIntProperty("layer", currentLayer, renderer); + + m_RenderWindowDataModel->MoveNodeUp(rowIndex, dataNode->GetName(), renderer->GetName()); + + 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::MoveNodeDown(int rowIndex, DataNode* dataNode, const mitk::BaseRenderer* renderer /*= nullptr*/) +{ + if (nullptr == renderer) + { + // move data node up in all controlled renderer + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + // TODO: does not work here: rowIndex is different for different render window node lists + MoveNodeDown(rowIndex, dataNode, renderer); + } + } + } + else + { + // get the layer stack without the base node of the current renderer + LayerStack stackedLayers = GetLayerStack(renderer, false); + if (!stackedLayers.empty()) + { + // get the first value (lowest int-key) + // cannot be the layer 0 (base node) as the base node was excluded by the 'GetLayerStack'-function + int lowermostLayer = 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 > lowermostLayer) + { + // 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 + LayerStack::iterator layerStackIterator = stackedLayers.find(currentLayer); + --layerStackIterator; + DataNode::Pointer lowerDataNode = layerStackIterator->second; + dataNode->SetIntProperty("layer", layerStackIterator->first, renderer); + lowerDataNode->SetIntProperty("layer", currentLayer, renderer); + + m_RenderWindowDataModel->MoveNodeDown(rowIndex, dataNode->GetName(), renderer->GetName()); + + 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; +} + +void mitk::RenderWindowLayerController::SetVisibilityOfDataNode(bool visibility, DataNode* dataNode, const mitk::BaseRenderer* renderer /*=nullptr*/) +{ + 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); + dataNode->SetVisibility(visibility, renderer); + } + } + } + else + { + dataNode->SetVisibility(visibility, renderer); + } +} + +void mitk::RenderWindowLayerController::HideDataNodeInAllRenderer(const DataNode* dataNode) +{ + for (const auto& renderer : m_ControlledRenderer) + { + if (renderer.IsNotNull()) + { + dataNode->GetPropertyList(renderer)->SetBoolProperty("fixedLayer", false); + dataNode->GetPropertyList(renderer)->SetBoolProperty("visible", false); + } + } + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void mitk::RenderWindowLayerController::ResetRenderer(bool onlyVisibility /*= true*/, const mitk::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 + LayerStack stackedLayers = GetLayerStack(renderer, true); + if (!stackedLayers.empty()) + { + for (const auto& layer : stackedLayers) + { + int layerLevel; + layer.second->GetIntProperty("layer", layerLevel, renderer); + if (0 == layerLevel) + { + // set base data node visibility to true (layer = 0) + layer.second->SetVisibility(true, renderer); + } + else + { + // modify layer node + if (onlyVisibility) + { + // set layer node visibility to false + layer.second->SetVisibility(false, renderer); + } + else + { + + // remove layer node from current renderer + layer.second->SetBoolProperty("fixedLayer", false, renderer); + layer.second->SetVisibility(false, renderer); + } + } + } + } + } +} + +mitk::RenderWindowLayerController::LayerStack mitk::RenderWindowLayerController::GetLayerStack(const mitk::BaseRenderer* renderer, bool withBaseNode) +{ + LayerStack stackedLayers; + if (m_DataStorage.IsNull() || renderer == nullptr) + { + // no nodes to stack or no renderer selected + return stackedLayers; + } + + // see 'QmitkStdMultiWidgetEditor::CreateQtPartControl' for id of GetQmitkRenderWindow + //m_Renderer = this->GetRenderWindowPart()->GetQmitkRenderWindow("axial" /*"sagittal"*/ /*coronal*/)->GetRenderer(); + 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::DataStorage::SetOfObjects::ConstPointer filteredDataNodes = m_DataStorage->GetSubset(notAHelperObject); + + for (DataStorage::SetOfObjects::ConstIterator it = filteredDataNodes->Begin(); it != filteredDataNodes->End(); ++it) + { + DataNode::Pointer dataNode = it->Value(); + if (dataNode.IsNull()) + { + continue; + } + + bool fixedLayer = false; + dataNode->GetBoolProperty("fixedLayer", fixedLayer, renderer); + bool layerFound = dataNode->GetIntProperty("layer", layer, renderer); + if (fixedLayer && layerFound) + { + if (layer != 0 || 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/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..c04c78bb9b --- /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 +) 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..54e3d0e4ba --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/files.cmake @@ -0,0 +1,29 @@ +set(INTERNAL_CPP_FILES + mitkPluginActivator.cpp + QmitkRenderWindowManagerView.cpp + QmitkLayerManagerAddNodeWidget.cpp +) + +set(UI_FILES + src/internal/QmitkRenderWindowManagerControls.ui + src/internal/QmitkLayerManagerAddNodeControls.ui +) + +set(MOC_H_FILES + src/internal/mitkPluginActivator.h + src/internal/QmitkRenderWindowManagerView.h + src/internal/QmitkLayerManagerAddNodeWidget.h +) + +set(CACHED_RESOURCE_FILES + resources/LayerManager_48.png + plugin.xml +) + +set(QRC_FILES + resources/renderwindowmanager.qrc +) + +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/resources/renderwindowmanager.qrc b/Plugins/org.mitk.gui.qt.renderwindowmanager/resources/renderwindowmanager.qrc new file mode 100644 index 0000000000..e996d7d2d9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/resources/renderwindowmanager.qrc @@ -0,0 +1,5 @@ + + + LayerManager_48.png + + diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeControls.ui b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeControls.ui new file mode 100644 index 0000000000..0f5a62e698 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeControls.ui @@ -0,0 +1,70 @@ + + + QmitkLayerManagerAddNodeControls + + + + 0 + 0 + 459 + 844 + + + + + 0 + 0 + + + + + 0 + 0 + + + + QmitkLayerManagerAddNode + + + + + + + 0 + 0 + + + + Add data node + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + Add node to renderer + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeWidget.cpp b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeWidget.cpp new file mode 100644 index 0000000000..21c020c729 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeWidget.cpp @@ -0,0 +1,94 @@ +/*=================================================================== + +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 "QmitkLayerManagerAddNodeWidget.h" + +#include +#include + +const QString QmitkLayerManagerAddNodeWidget::VIEW_ID = "org.mitk.Widgets.QmitkLayerManagerAddNode"; + +QmitkLayerManagerAddNodeWidget::QmitkLayerManagerAddNodeWidget(QWidget* parent /*= nullptr*/) + : QWidget(parent, Qt::Window) + , m_DataStorage(nullptr) +{ + Init(); +} + +QmitkLayerManagerAddNodeWidget::~QmitkLayerManagerAddNodeWidget() +{ + // nothing here +} + +void QmitkLayerManagerAddNodeWidget::Init() +{ + m_Controls.setupUi(this); + m_DataNodeListModel = new QStringListModel(this); + m_Controls.listViewDataNodes->setModel(m_DataNodeListModel); + m_Controls.listViewDataNodes->setEditTriggers(QAbstractItemView::NoEditTriggers); + + connect(m_Controls.pushButtonAddDataNode, SIGNAL(clicked()), this, SLOT(AddDataNodeToRenderer())); + connect(m_Controls.pushButtonAddDataNode, SIGNAL(clicked()), this, SLOT(hide())); + + m_Controls.pushButtonAddDataNode->setEnabled(false); +} + +void QmitkLayerManagerAddNodeWidget::SetDataStorage(mitk::DataStorage::Pointer dataStorage) +{ + m_DataStorage = dataStorage; +} + +void QmitkLayerManagerAddNodeWidget::ListDataNodes() +{ + if (m_DataStorage.IsNotNull()) + { + // get the data nodes from the data storage that are not helper objects + mitk::NodePredicateProperty::Pointer helperObject = mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)); + mitk::NodePredicateNot::Pointer notAHelperObject = mitk::NodePredicateNot::New(helperObject); + mitk::DataStorage::SetOfObjects::ConstPointer filteredDataNodes = m_DataStorage->GetSubset(notAHelperObject); + + QStringList stringList; + for (mitk::DataStorage::SetOfObjects::ConstIterator it = filteredDataNodes->Begin(); it != filteredDataNodes->End(); ++it) + { + stringList << QString::fromStdString(it->Value()->GetName()); + } + + m_DataNodeListModel->setStringList(stringList); + + if (stringList.isEmpty()) + { + m_Controls.pushButtonAddDataNode->setEnabled(false); + } + else + { + m_Controls.pushButtonAddDataNode->setEnabled(true); + } + } +} + +void QmitkLayerManagerAddNodeWidget::AddDataNodeToRenderer() +{ + QModelIndex selectedIndex = m_Controls.listViewDataNodes->currentIndex(); + if (selectedIndex.isValid()) + { + int listRow = selectedIndex.row(); + QString dataNodeName = m_DataNodeListModel->stringList().at(listRow); + + mitk::DataNode* dataNode = m_DataStorage->GetNamedNode(dataNodeName.toStdString()); + + emit NodeToAddSelected(dataNode); + } +} diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeWidget.h b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeWidget.h new file mode 100644 index 0000000000..890dbd2a57 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkLayerManagerAddNodeWidget.h @@ -0,0 +1,70 @@ +/*=================================================================== + +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 QMITKLAYERMANAGERADDNODEWIDGET_H +#define QMITKLAYERMANAGERADDNODEWIDGET_H + +#include "ui_QmitkLayerManagerAddNodeControls.h" + +// mitk +#include + +// Qt includes +#include +#include +#include + +/** +* @brief +* +*/ +class QmitkLayerManagerAddNodeWidget : public QWidget +{ + Q_OBJECT + +public: + static const QString VIEW_ID; + + QmitkLayerManagerAddNodeWidget(QWidget* parent = nullptr); + ~QmitkLayerManagerAddNodeWidget(); + + /** + * @brief set the data storage of the tree model + * + * @param[in] dataStorage the mitk::DataStorage that should be used + */ + void SetDataStorage(mitk::DataStorage::Pointer dataStorage); + + void ListDataNodes(); + +public Q_SLOTS: + void AddDataNodeToRenderer(); + +Q_SIGNALS: + void NodeToAddSelected(mitk::DataNode* dataNode); + +private: + void Init(); + + Ui::QmitkLayerManagerAddNodeControls m_Controls; + + QStringListModel* m_DataNodeListModel; + mitk::DataStorage::Pointer m_DataStorage; + + // TODO: map for nodename (to display) and sopinstanceuid for identifying a data node +}; + +#endif // QMITKLAYERMANAGERADDNODEWIDGET_H 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..00d440a164 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerControls.ui @@ -0,0 +1,105 @@ + + + QmitkRenderWindowManagerControls + + + + 0 + 0 + 263 + 227 + + + + + 0 + 0 + + + + QmitkRenderWindowManager + + + + + + -1 + + + + + + + Render window overview + + + + + + + + + + + + Move up + + + + + + + Move down + + + + + + + Add Node + + + + + + + Remove Node + + + + + + + Set as Base + + + + + + + Axial + + + + + + + Coronal + + + + + + + Sagittal + + + + + + + + + + + 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..15bf448696 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp @@ -0,0 +1,164 @@ +/*=================================================================== + +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 +#include + +// qt +#include +#include +#include + +const std::string QmitkRenderWindowManagerView::VIEW_ID = "org.mitk.views.renderwindowmanager"; + +void QmitkRenderWindowManagerView::SetFocus() +{ + m_Controls.radioButtonAxial->setFocus(); +} + +void QmitkRenderWindowManagerView::CreateQtPartControl(QWidget* parent) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Parent = parent; + m_Controls.setupUi(m_Parent); + + // initialize the render window layer controller and set the controller renderer (in constructor) and the data storage + m_RenderWindowLayerController = new mitk::RenderWindowLayerController(); + m_RenderWindowLayerController->SetDataStorage(GetDataStorage()); + mitk::RenderWindowLayerController::RendererVector controlledRenderer = m_RenderWindowLayerController->GetControlledRenderer(); + for (const auto& renderer : controlledRenderer) + { + m_Controls.comboBoxRenderWindowSelection->addItem(renderer->GetName()); + } + + m_CurrentRendererName = m_Controls.comboBoxRenderWindowSelection->itemText(0); + + // create a new model + m_RenderWindowModel.insert(m_CurrentRendererName, new QmitkRenderWindowDataModel(this)); + m_Controls.renderWindowTableView->setModel(m_RenderWindowModel.value(m_CurrentRendererName)); + m_Controls.renderWindowTableView->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_Controls.renderWindowTableView->horizontalHeader()->setStretchLastSection(true); + + m_RenderWindowModel.value(m_CurrentRendererName)->SetDataStorage(GetDataStorage()); + //m_VisibilityDelegate = new QmitkVisibilityDelegate(this); + //m_Controls.renderWindowTableView->setItemDelegateForColumn(0, m_VisibilityDelegate); + + mitk::BaseRenderer* renderer = mitk::BaseRenderer::GetByName(m_CurrentRendererName.toStdString()); + mitk::RenderWindowLayerController::LayerStack layerStack = m_RenderWindowLayerController->GetLayerStack(renderer, true); + m_RenderWindowModel.value(m_CurrentRendererName)->UpdateTableForRenderWindow(layerStack); + + m_Controls.radioButtonAxial->setChecked(true); + + m_AddDataNodeWidget = new QmitkLayerManagerAddNodeWidget(m_Parent); + m_AddDataNodeWidget->hide(); + m_AddDataNodeWidget->SetDataStorage(GetDataStorage()); + + SetUpConnections(); +} + +void QmitkRenderWindowManagerView::SetUpConnections(void) +{ + connect(m_Controls.comboBoxRenderWindowSelection, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnRenderWindowSelectionChanged(const QString&))); + + QSignalMapper* udSignalMapper = new QSignalMapper(this); + udSignalMapper->setMapping(m_Controls.pushButtonMoveUp, QString("up")); + udSignalMapper->setMapping(m_Controls.pushButtonMoveDown, QString("down")); + + connect(m_Controls.pushButtonMoveUp, SIGNAL(clicked()), udSignalMapper, SLOT(map())); + connect(m_Controls.pushButtonMoveDown, SIGNAL(clicked()), udSignalMapper, SLOT(map())); + connect(udSignalMapper, SIGNAL(mapped(const QString&)), this, SLOT(MoveDataNode(const QString&))); + + connect(m_Controls.pushButtonAddNode, SIGNAL(clicked()), this, SLOT(ShowAddDataNodeWidget())); + connect(m_Controls.pushButtonRemoveNode, SIGNAL(clicked()), this, SLOT(RemoveDataNode())); + connect(m_Controls.pushButtonSetAsBaseNode, SIGNAL(clicked()), this, SLOT(SetAsBaseDataNode())); + + //connect(m_Controls.radioButtonAxial, SIGNAL(clicked()), this, SLOT(DoImageProcessing())); + //connect(m_Controls.radioButtonCoronal, SIGNAL(clicked()), this, SLOT(DoImageProcessing())); + //connect(m_Controls.radioButtonSagittal, SIGNAL(clicked()), this, SLOT(DoImageProcessing())); + + connect(m_AddDataNodeWidget, SIGNAL(NodeToAddSelected(mitk::DataNode*)), this, SLOT(AddDataNode(mitk::DataNode*))); +} + +void QmitkRenderWindowManagerView::OnRenderWindowSelectionChanged(const QString &renderWindowId) +{ + m_CurrentRendererName = renderWindowId; + if (!m_RenderWindowModel.contains(m_CurrentRendererName)) + { + m_RenderWindowModel.insert(m_CurrentRendererName, new QmitkRenderWindowDataModel(this)); + m_RenderWindowModel.value(m_CurrentRendererName)->SetDataStorage(GetDataStorage()); + } + + m_Controls.renderWindowTableView->setModel(m_RenderWindowModel.value(m_CurrentRendererName)); + + mitk::BaseRenderer* renderer = mitk::BaseRenderer::GetByName(m_CurrentRendererName.toStdString()); + mitk::RenderWindowLayerController::LayerStack layerStack = m_RenderWindowLayerController->GetLayerStack(renderer, true); + + m_RenderWindowModel.value(m_CurrentRendererName)->UpdateTableForRenderWindow(layerStack); +} + +void QmitkRenderWindowManagerView::ShowAddDataNodeWidget() +{ + m_AddDataNodeWidget->ListDataNodes(); + m_AddDataNodeWidget->show(); +} + +void QmitkRenderWindowManagerView::AddDataNode(mitk::DataNode* dataNode) +{ + mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(m_CurrentRendererName.toStdString()); + m_RenderWindowLayerController->InsertLayerNode(dataNode, -1, selectedRenderer); + + m_RenderWindowModel.value(m_CurrentRendererName)->UpdateTableForRenderWindow(m_RenderWindowLayerController->GetLayerStack(selectedRenderer, true)); +} + +void QmitkRenderWindowManagerView::RemoveDataNode() +{ + // TODO: not yet implemented +} + +void QmitkRenderWindowManagerView::SetAsBaseDataNode() +{ + // TODO: not yet implemented +} + +void QmitkRenderWindowManagerView::MoveDataNode(const QString &direction) +{ + QModelIndex selectedIndex = m_Controls.renderWindowTableView->currentIndex(); + if (selectedIndex.isValid()) + { + QVariant rowData = m_RenderWindowModel.value(m_CurrentRendererName)->data(selectedIndex, Qt::DisplayRole); + + mitk::DataNode* dataNode = GetDataStorage()->GetNamedNode(rowData.toString().toStdString()); + mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(m_CurrentRendererName.toStdString()); + if ("up" == direction) + { + m_RenderWindowLayerController->MoveNodeUp(dataNode, selectedRenderer); + } + else + { + m_RenderWindowLayerController->MoveNodeDown(dataNode, selectedRenderer); + + } + + m_RenderWindowModel.value(m_CurrentRendererName)->UpdateTableForRenderWindow(m_RenderWindowLayerController->GetLayerStack(selectedRenderer, true)); + } +} 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..a78e78b69b --- /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" +#include "QmitkLayerManagerAddNodeWidget.h" +// render window manager module +#include +#include "QmitkVisibilityDelegate.h" +// core module +#include + +// blueberry +#include + +// qt +#include +#include + +/** +* @brief RenderWindowManager +*/ +class QmitkRenderWindowManagerView : public QmitkAbstractView +{ + Q_OBJECT + +public: + static const std::string VIEW_ID; + +public Q_SLOTS: + /** + * @brief called when the user changes the render window selection in the combo box + */ + void OnRenderWindowSelectionChanged(const QString &renderWindowId); + + void ShowAddDataNodeWidget(); + void AddDataNode(mitk::DataNode* dataNode); + void RemoveDataNode(); + void SetAsBaseDataNode(); + + void MoveDataNode(const QString &direction); + +protected: + + virtual void SetFocus() override; + + virtual void CreateQtPartControl(QWidget* parent) override; + + void SetUpConnections(); + +private: + + // the Qt parent of our GUI + QWidget* m_Parent; + Ui::QmitkRenderWindowManagerControls m_Controls; + + QMap m_RenderWindowModel; + QmitkVisibilityDelegate* m_VisibilityDelegate; + QString m_CurrentRendererName; + + mitk::RenderWindowLayerController* m_RenderWindowLayerController; + QmitkLayerManagerAddNodeWidget* m_AddDataNodeWidget; +}; + +#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