diff --git a/Modules/QtWidgets/files.cmake b/Modules/QtWidgets/files.cmake index fd248df801..7fabcf25c3 100644 --- a/Modules/QtWidgets/files.cmake +++ b/Modules/QtWidgets/files.cmake @@ -1,83 +1,87 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES -QmitkApplicationCursor.cpp -QmitkDataStorageComboBox.cpp -QmitkDataStorageListModel.cpp -QmitkDataStorageTableModel.cpp -QmitkDataStorageTreeModel.cpp -QmitkFileReaderOptionsDialog.cpp -QmitkFileReaderWriterOptionsWidget.cpp -QmitkFileWriterOptionsDialog.cpp -QmitkIOUtil.cpp -QmitkLevelWindowPresetDefinitionDialog.cpp -QmitkLevelWindowRangeChangeDialog.cpp -QmitkLevelWindowWidgetContextMenu.cpp -QmitkLevelWindowWidget.cpp -QmitkLineEditLevelWindowWidget.cpp -QmitkMemoryUsageIndicatorView.cpp -QmitkMimeTypes.cpp -QmitkNodeDescriptor.cpp -QmitkNodeDescriptorManager.cpp -QmitkRenderWindowMenu.cpp -QmitkProgressBar.cpp -QmitkPropertiesTableEditor.cpp -QmitkPropertiesTableModel.cpp -QmitkPropertyDelegate.cpp -QmitkRegisterClasses.cpp -QmitkRenderingManager.cpp -QmitkRenderingManagerFactory.cpp -QmitkRenderWindow.cpp -QmitkServiceListWidget.cpp -QmitkSliderLevelWindowWidget.cpp -QmitkStdMultiWidget.cpp -QmitkMouseModeSwitcher.cpp -QmitkDataStorageFilterProxyModel.cpp -QmitkDataStorageComboBoxWithSelectNone.cpp -QmitkPropertyItem.cpp -QmitkPropertyItemDelegate.cpp -QmitkPropertyItemModel.cpp + QmitkApplicationCursor.cpp + QmitkDataStorageComboBox.cpp + QmitkDataStorageListModel.cpp + QmitkDataStorageTableModel.cpp + QmitkDataStorageTreeModel.cpp + QmitkFileReaderOptionsDialog.cpp + QmitkFileReaderWriterOptionsWidget.cpp + QmitkFileWriterOptionsDialog.cpp + QmitkIOUtil.cpp + QmitkLevelWindowPresetDefinitionDialog.cpp + QmitkLevelWindowRangeChangeDialog.cpp + QmitkLevelWindowWidgetContextMenu.cpp + QmitkLevelWindowWidget.cpp + QmitkLineEditLevelWindowWidget.cpp + QmitkMemoryUsageIndicatorView.cpp + QmitkMimeTypes.cpp + QmitkNodeDescriptor.cpp + QmitkNodeDescriptorManager.cpp + QmitkRenderWindowMenu.cpp + QmitkProgressBar.cpp + QmitkPropertiesTableEditor.cpp + QmitkPropertiesTableModel.cpp + QmitkPropertyDelegate.cpp + QmitkRegisterClasses.cpp + QmitkRenderingManager.cpp + QmitkRenderingManagerFactory.cpp + QmitkRenderWindow.cpp + QmitkRenderWindowWidget.cpp + QmitkServiceListWidget.cpp + QmitkSliderLevelWindowWidget.cpp + QmitkStdMultiWidget.cpp + QmitkCustomMultiWidget.cpp + QmitkMouseModeSwitcher.cpp + QmitkDataStorageFilterProxyModel.cpp + QmitkDataStorageComboBoxWithSelectNone.cpp + QmitkPropertyItem.cpp + QmitkPropertyItemDelegate.cpp + QmitkPropertyItemModel.cpp ) set(MOC_H_FILES include/QmitkDataStorageComboBox.h include/QmitkDataStorageTableModel.h include/QmitkFileReaderOptionsDialog.h include/QmitkFileReaderWriterOptionsWidget.h include/QmitkFileWriterOptionsDialog.h include/QmitkLevelWindowPresetDefinitionDialog.h include/QmitkLevelWindowRangeChangeDialog.h include/QmitkLevelWindowWidgetContextMenu.h include/QmitkLevelWindowWidget.h include/QmitkLineEditLevelWindowWidget.h include/QmitkMemoryUsageIndicatorView.h include/QmitkNodeDescriptor.h include/QmitkNodeDescriptorManager.h include/QmitkRenderWindowMenu.h + include/QmitkRenderWindowWidget. include/QmitkProgressBar.h include/QmitkPropertiesTableEditor.h include/QmitkPropertyDelegate.h include/QmitkRenderingManager.h include/QmitkRenderWindow.h include/QmitkServiceListWidget.h include/QmitkSliderLevelWindowWidget.h include/QmitkStdMultiWidget.h + include/QmitkCustomMultiWidget.h include/QmitkMouseModeSwitcher.h include/QmitkDataStorageComboBoxWithSelectNone.h include/QmitkPropertyItemDelegate.h include/QmitkPropertyItemModel.h ) set(UI_FILES src/QmitkFileReaderOptionsDialog.ui src/QmitkFileWriterOptionsDialog.ui src/QmitkLevelWindowPresetDefinition.ui src/QmitkLevelWindowWidget.ui src/QmitkLevelWindowRangeChange.ui src/QmitkMemoryUsageIndicator.ui src/QmitkServiceListWidgetControls.ui ) set(QRC_FILES resource/Qmitk.qrc ) diff --git a/Modules/QtWidgets/include/QmitkCustomMultiWidget.h b/Modules/QtWidgets/include/QmitkCustomMultiWidget.h new file mode 100644 index 0000000000..964d237e90 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkCustomMultiWidget.h @@ -0,0 +1,249 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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 QMITKCUSTOMMULTIWIDGET_H +#define QMITKCUSTOMMULTIWIDGET_H + +// qt widgets module +#include "MitkQtWidgetsExports.h" +#include "QmitkRenderWindowWidget.h" + +// mitk core +#include +#include +#include + +// qt +#include +#include +#include + +class QHBoxLayout; +class QVBoxLayout; +class QGridLayout; +class QSpacerItem; +class QmitkLevelWindowWidget; +class QmitkRenderWindow; +class vtkCornerAnnotation; + +namespace mitk +{ + class RenderingManager; +} + +/* +* @brief The 'QmitkCustomMultiWidget' is a 'QWidget' that is used to display multiple render windows at once. +* +* Render windows can dynamically be added and removed to change the layout of the multi widget. +*/ +class MITKQTWIDGETS_EXPORT QmitkCustomMultiWidget : public QWidget +{ + Q_OBJECT + +public: + + QmitkCustomMultiWidget(QWidget *parent = 0, Qt::WindowFlags f = 0, mitk::RenderingManager *renderingManager = 0, mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard, const QString& name = "custommulti"); + virtual ~QmitkCustomMultiWidget(); + + void SetDataStorage(mitk::DataStorage* dataStorage); + + mitk::MouseModeSwitcher* GetMouseModeSwitcher(); + + std::map GetRenderWindowWidgets() const; + QmitkRenderWindowWidget* GetRenderWindowWidget(unsigned int id) const; + QmitkRenderWindowWidget* GetActiveRenderWindowWidget() const; + QmitkRenderWindowWidget* GetFirstRenderWindowWidget() const; + QmitkRenderWindowWidget* GetLastRenderWindowWidget() const; + + unsigned int GetNumberOfRenderWindowWidgets() const; + + const mitk::Point3D GetCrossPosition() const; + + void RequestUpdate(unsigned int id); + void RequestUpdateAll(); + void ForceImmediateUpdate(unsigned int id); + void ForceImmediateUpdateAll(); + + // color and style settings + + /** \brief Listener to the CrosshairPositionEvent + + Ensures the CrosshairPositionEvent is handled only once and at the end of the Qt-Event loop + */ + void HandleCrosshairPositionEvent(); + +protected: + + mitk::DataNode::Pointer GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes); + +public slots: + + void ShowLevelWindowWidget(unsigned int widgetNumber, bool show); + void ShowAllLevelWindowWidgets(bool show); + + /* + * @brief Set a background color gradient for a specific render window. + * + * If two different input colors are used, a gradient background is generated. + * + * @param upper The color of the gradient background. + * @param lower The color of the gradient background. + * @param widgetNumber The widget identifier. + */ + void SetBackgroundColorGradient(const mitk::Color& upper, const mitk::Color& lower, unsigned int widgetNumber); + /* + * @brief Set a background color gradient for all available render windows. + * + * If two different input colors are used, a gradient background is generated. + * + * @param upper The color of the gradient background. + * @param lower The color of the gradient background. + */ + // #TODO: 'backgroundgradientcolor' + void SetAllBackgroundColorGradients(const mitk::Color& upper, const mitk::Color& lower); + void FillAllBackgroundColorGradientsWithBlack(); + void ShowBackgroundColorGradient(unsigned int widgetNumber, bool show); + void ShowAllBackgroundColorGradients(bool show); + /* + * @rief Return a render window (widget) specific background color gradient + * + * @param widgetNumber The widget identifier. + * + * @return A color gradient as a pair of colors. + * First entry: upper color value + * Second entry: lower color value + */ + std::pair GetBackgroundColorGradient(unsigned int widgetNumber) const; + bool GetBackgroundColorGradientFlag(unsigned int widgetNumber) const; + + void SetDepartmentLogoPath(const char* path); + void ShowDepartmentLogo(unsigned int widgetNumber, bool show); + void ShowAllDepartmentLogos(bool show); + + void SetDecorationColor(unsigned int widgetNumber, const mitk::Color& color); + mitk::Color GetDecorationColor(unsigned int widgetNumber) const; + + void ShowColoredRectangle(unsigned int widgetNumber, bool show); + void ShowAllColoredRectangles(bool show); + bool IsColoredRectangleVisible(unsigned int widgetNumber) const; + + void ShowCornerAnnotation(unsigned int widgetNumber, bool show); + void ShowAllCornerAnnotations(bool show); + bool IsCornerAnnotationVisible(unsigned int widgetNumber) const; + void SetCornerAnnotationText(unsigned int widgetNumber, const std::string& cornerAnnotation); + std::string GetCornerAnnotationText(unsigned int widgetNumber) const; + + void ActivateRenderWindowMenu(unsigned int widgetNumber, bool state); + void ActivateAllRenderWindowMenus(bool state); + bool IsRenderWindowMenuActivated(unsigned int widgetNumber) const; + + void ShowGeometryPlanes(unsigned int widgetNumber, bool state); + void ShowAllGeometryPlanes(bool state); + mitk::DataNode::Pointer GetGeometryPlane(unsigned int widgetNumber, unsigned int planeNumber) const; + + + + + /// Receives the signal from HandleCrosshairPositionEvent, executes the StatusBar update + void HandleCrosshairPositionEventDelayed(); + + void Fit(); + + void wheelEvent(QWheelEvent *e) override; + + void mousePressEvent(QMouseEvent *e) override; + + void moveEvent(QMoveEvent *e) override; + + void EnsureDisplayContainsPoint(mitk::BaseRenderer *renderer, const mitk::Point3D &p); + + void MoveCrossToPosition(const mitk::Point3D &newPosition); + + void SetWidgetPlanesLocked(bool locked); + + void SetWidgetPlanesRotationLocked(bool locked); + + void SetWidgetPlanesRotationLinked(bool link); + + void SetWidgetPlaneMode(int mode); + + void SetWidgetPlaneModeToSlicing(bool activate); + + void SetWidgetPlaneModeToRotation(bool activate); + + void SetWidgetPlaneModeToSwivel(bool activate); + + void ResetCrosshair(); + +signals: + + void LeftMouseClicked(mitk::Point3D pointValue); + void WheelMoved(QWheelEvent *); + void WidgetPlanesRotationLinked(bool); + void WidgetPlanesRotationEnabled(bool); + void ViewsInitialized(); + void WidgetPlaneModeSlicing(bool); + void WidgetPlaneModeRotation(bool); + void WidgetPlaneModeSwivel(bool); + void WidgetPlaneModeChange(int); + void WidgetNotifyNewCrossHairMode(int); + void Moved(); + +public: + + enum + { + PLANE_MODE_SLICING = 0, + PLANE_MODE_ROTATION, + PLANE_MODE_SWIVEL + }; + + enum + { + AXIAL, + SAGITTAL, + CORONAL, + THREE_D + }; + +private: + + void InitializeGUI(); + void AddRenderWindowWidget(); + void InitializeWidget(); + + QGridLayout* m_CustomMultiWidgetLayout; + std::map m_RenderWindowWidgets; + + QmitkRenderWindowWidget* m_ActiveRenderWindowWidget; + + int m_PlaneMode; + + mitk::RenderingManager* m_RenderingManager; + mitk::BaseRenderer::RenderingMode::Type m_RenderingMode; + QString m_MultiWidgetName; + + mitk::MouseModeSwitcher::Pointer m_MouseModeSwitcher; + mitk::SliceNavigationController *m_TimeNavigationController; + + mitk::DataStorage::Pointer m_DataStorage; + + bool m_PendingCrosshairPositionEvent; + bool m_CrosshairNavigationEnabled; + +}; + +#endif // QMITKCUSTOMMULTIWIDGET_H diff --git a/Modules/QtWidgets/include/QmitkRenderWindowWidget.h b/Modules/QtWidgets/include/QmitkRenderWindowWidget.h new file mode 100644 index 0000000000..7dd2e58a05 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkRenderWindowWidget.h @@ -0,0 +1,134 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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 QMITKRENDERWINDOWWIDGET_H +#define QMITKRENDERWINDOWWIDGET_H + +// mitk core +#include +#include +//#include +#include +#include + +// annotations module +#include + +// qt widgets module +#include +#include +#include + +// qt +#include +#include + +/* +* @brief +* +* +*/ +class MITKQTWIDGETS_EXPORT QmitkRenderWindowWidget : public QWidget +{ + Q_OBJECT + +public: + + QmitkRenderWindowWidget(QWidget* parent = nullptr, const std::string& UID = "", mitk::DataStorage* dataStorage = nullptr); + ~QmitkRenderWindowWidget() override; + + void SetDataStorage(mitk::DataStorage* dataStorage); + + QmitkRenderWindow* GetRenderWindow() const { return m_RenderWindow; }; + QmitkLevelWindowWidget* GetlevelWindowWidget() const { return m_LevelWindowWidget; }; + + mitk::SliceNavigationController* GetSliceNavigationController() const; + + void RequestUpdate(); + void ForceImmediateUpdate(); + + // #TODO: 'backroundgradientcolor' + void SetBackgroundColorGradient(const mitk::Color& upper, const mitk::Color& lower); + void ShowBackgroundColorGradient(bool enable); + std::pair GetRendererBackgroundColorGradient() const { return m_BackgroundColorGradient; }; + bool GetBackgroundColorGradientFlag() const { return m_BackgroundColorGradientFlag; }; + + void ShowLevelWindowWidget(bool enable); + void ShowDepartmentLogo(bool show); + + void SetDecorationColor(const mitk::Color& color); + mitk::Color GetDecorationColor() const { return m_DecorationColor; }; + + void ShowColoredRectangle(bool show); + bool IsColoredRectangleVisible() const; + void ShowCornerAnnotation(bool show); + bool IsCornerAnnotationVisible() const; + void SetCornerAnnotationText(const std::string& cornerAnnotation); + std::string GetCornerAnnotationText() const; + + /* + * @brief Create a corner annotation and a colored rectangle for this widget. + * + * @par text The text of the corner annotation. + * @par color The color of the text and the rectangle. + */ + void SetDecorationProperties(std::string text, mitk::Color color); + + void ActivateMenuWidget(bool state, QmitkCustomMultiWidget* multiWidget); + bool IsRenderWindowMenuActivated() const; + + void ShowGeometryPlanes(bool show); + mitk::DataNode::Pointer GetGeometryPlane(unsigned int planeNumber) const; + + void AddGeometryPlanesToDataStorage(); + void RemoveGeometryPlanesFromDataStorage(); + +private: + + void InitializeGUI(); + void InitializeGeometryPlanes(); + void InitializeDecorations(); + + std::string m_UID; + QHBoxLayout* m_Layout; + + mitk::DataStorage* m_DataStorage; + QmitkRenderWindow* m_RenderWindow; + QmitkLevelWindowWidget* m_LevelWindowWidget; + + mitk::RenderingManager* m_RenderingManager; + mitk::BaseRenderer::RenderingMode::Type m_RenderingMode; + + std::pair m_BackgroundColorGradient; + bool m_BackgroundColorGradientFlag; + mitk::LogoAnnotation::Pointer m_LogoAnnotation; + mitk::Color m_DecorationColor; + vtkSmartPointer m_RectangleProp; + vtkSmartPointer m_CornerAnnotation; + + /* + * @brief The 3 helper objects which contain the plane geometry (crosshair and 3D planes). + */ + mitk::DataNode::Pointer m_GeometryPlane1; + mitk::DataNode::Pointer m_GeometryPlane2; + mitk::DataNode::Pointer m_GeometryPlane3; + /* + * @brief This helper object is added to the data storage as a parent node for the 3 geometry plane nodes. + */ + mitk::DataNode::Pointer m_GeometryPlanes; +}; + +#endif // QMITKRENDERWINDOWWIDGET_H diff --git a/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp b/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp new file mode 100644 index 0000000000..c0e1888376 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp @@ -0,0 +1,829 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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. + +===================================================================*/ + +#define SMW_INFO MITK_INFO("widget.custommulti") + +#include "QmitkCustomMultiWidget.h" + +#include +#include +#include +#include + +#include "mitkImagePixelReadAccessor.h" +#include "mitkPixelTypeMultiplex.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// qt +#include + +QmitkCustomMultiWidget::QmitkCustomMultiWidget(QWidget* parent, Qt::WindowFlags f, mitk::RenderingManager* renderingManager, mitk::BaseRenderer::RenderingMode::Type renderingMode, const QString& multWidgetName) + : QWidget(parent, f) + , m_CustomMultiWidgetLayout(nullptr) + , m_PlaneMode(PLANE_MODE_SLICING) + , m_RenderingManager(renderingManager) + , m_RenderingMode(renderingMode) + , m_MultiWidgetName(multWidgetName) + , m_TimeNavigationController(nullptr) + , m_PendingCrosshairPositionEvent(false) + , m_CrosshairNavigationEnabled(false) +{ + if (nullptr == m_RenderingManager) + { + m_RenderingManager = mitk::RenderingManager::GetInstance(); + } + m_TimeNavigationController = m_RenderingManager->GetTimeNavigationController(); + + // create widget manually + // create and set layout + InitializeGUI(); + // create at least one render window initially + AddRenderWindowWidget(); + + resize(QSize(364, 477).expandedTo(minimumSizeHint())); + + InitializeWidget(); + ActivateAllRenderWindowMenus(true); +} + +QmitkCustomMultiWidget::~QmitkCustomMultiWidget() +{ + for (const auto& mapEntry : m_RenderWindowWidgets) + { + m_TimeNavigationController->Disconnect(mapEntry.second->GetRenderWindow()->GetSliceNavigationController()); + } +} + +void QmitkCustomMultiWidget::SetDataStorage(mitk::DataStorage* dataStorage) +{ + if (dataStorage == m_DataStorage) + { + return; + } + + m_DataStorage = dataStorage; + for (const auto& renderWindowWidget : m_RenderWindowWidgets) + { + renderWindowWidget.second->SetDataStorage(m_DataStorage); + } +} + +std::map QmitkCustomMultiWidget::GetRenderWindowWidgets() const +{ + return m_RenderWindowWidgets; +} + +QmitkRenderWindowWidget* QmitkCustomMultiWidget::GetRenderWindowWidget(unsigned int id) const +{ + return m_RenderWindowWidgets.find(std::to_string(id))->second; +} + +QmitkRenderWindowWidget* QmitkCustomMultiWidget::GetActiveRenderWindowWidget() const +{ + return m_ActiveRenderWindowWidget; +} + +QmitkRenderWindowWidget* QmitkCustomMultiWidget::GetFirstRenderWindowWidget() const +{ + return m_RenderWindowWidgets.begin()->second; +} + +QmitkRenderWindowWidget* QmitkCustomMultiWidget::GetLastRenderWindowWidget() const +{ + return m_RenderWindowWidgets.rbegin()->second; +} + +unsigned int QmitkCustomMultiWidget::GetNumberOfRenderWindowWidgets() const +{ + return m_RenderWindowWidgets.size(); +} + +void QmitkCustomMultiWidget::InitializeWidget() +{ + // #TODO: some things have to be handled globally (hold for all render window (widgets) + // analyse those things and design a controlling mechanism + + // Set plane mode (slicing/rotation behavior) to slicing (default) + m_PlaneMode = PLANE_MODE_SLICING; + + m_MouseModeSwitcher = mitk::MouseModeSwitcher::New(); + + // setup the department logo rendering + /* + m_LogoRendering = mitk::LogoOverlay::New(); + mitk::BaseRenderer::Pointer renderer4 = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()); + m_LogoRendering->SetOpacity(0.5); + mitk::Point2D offset; + offset.Fill(0.03); + m_LogoRendering->SetOffsetVector(offset); + m_LogoRendering->SetRelativeSize(0.15); + m_LogoRendering->SetCornerPosition(1); + m_LogoRendering->SetLogoImagePath("DefaultLogo"); + renderer4->GetOverlayManager()->AddOverlay(m_LogoRendering.GetPointer(), renderer4); + */ +} + +const mitk::Point3D QmitkCustomMultiWidget::GetCrossPosition() const +{ + /* + const mitk::PlaneGeometry *plane1 = mitkWidget1->GetSliceNavigationController()->GetCurrentPlaneGeometry(); + const mitk::PlaneGeometry *plane2 = mitkWidget2->GetSliceNavigationController()->GetCurrentPlaneGeometry(); + const mitk::PlaneGeometry *plane3 = mitkWidget3->GetSliceNavigationController()->GetCurrentPlaneGeometry(); + + mitk::Line3D line; + if ((plane1 != NULL) && (plane2 != NULL) && (plane1->IntersectionLine(plane2, line))) + { + mitk::Point3D point; + if ((plane3 != NULL) && (plane3->IntersectionPoint(line, point))) + { + return point; + } + } + // TODO BUG POSITIONTRACKER; + mitk::Point3D p; + return p; + // return m_LastLeftClickPositionSupplier->GetCurrentPoint(); + */ + return mitk::Point3D(); +} + +void QmitkCustomMultiWidget::RequestUpdate(unsigned int widgetNumber) +{ + GetRenderWindowWidget(widgetNumber)->RequestUpdate(); +} + +void QmitkCustomMultiWidget::RequestUpdateAll() +{ + // #TODO: Update only render windows that show the same image? + // #TODO: Update only type specific render windows (2D / 3D)? + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + RequestUpdate(i); + } +} + +void QmitkCustomMultiWidget::ForceImmediateUpdate(unsigned int widgetNumber) +{ + GetRenderWindowWidget(widgetNumber)->ForceImmediateUpdate(); +} + +void QmitkCustomMultiWidget::ForceImmediateUpdateAll() +{ + // #TODO: Update only render windows that show the same image? + // #TODO: Update only type specific render windows (2D / 3D)? + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ForceImmediateUpdate(i); + } +} + +void QmitkCustomMultiWidget::EnsureDisplayContainsPoint(mitk::BaseRenderer *renderer, const mitk::Point3D &p) +{ + mitk::Point2D pointOnDisplay; + renderer->WorldToDisplay(p, pointOnDisplay); + + if (pointOnDisplay[0] < renderer->GetVtkRenderer()->GetOrigin()[0] || + pointOnDisplay[1] < renderer->GetVtkRenderer()->GetOrigin()[1] || + pointOnDisplay[0] > renderer->GetVtkRenderer()->GetOrigin()[0] + renderer->GetViewportSize()[0] || + pointOnDisplay[1] > renderer->GetVtkRenderer()->GetOrigin()[1] + renderer->GetViewportSize()[1]) + { + mitk::Point2D pointOnPlane; + renderer->GetCurrentWorldPlaneGeometry()->Map(p, pointOnPlane); + renderer->GetCameraController()->MoveCameraToPoint(pointOnPlane); + } +} + +void QmitkCustomMultiWidget::MoveCrossToPosition(const mitk::Point3D &newPosition) +{ + GetRenderWindow()->GetSliceNavigationController()->SelectSliceByPoint(newPosition); + + m_RenderingManager->RequestUpdateAll(); +} + +void QmitkCustomMultiWidget::HandleCrosshairPositionEvent() +{ + if (!m_PendingCrosshairPositionEvent) + { + m_PendingCrosshairPositionEvent = true; + QTimer::singleShot(0, this, SLOT(HandleCrosshairPositionEventDelayed())); + } +} + +mitk::DataNode::Pointer QmitkCustomMultiWidget::GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes) +{ + mitk::Point3D crosshairPos = GetCrossPosition(); + mitk::DataNode::Pointer node; + int maxlayer = -32768; + + if (nodes.IsNotNull()) + { + mitk::BaseRenderer *baseRenderer = GetRenderWindow()->GetSliceNavigationController()->GetRenderer(); + // find node with largest layer, that is the node shown on top in the render window + for (unsigned int x = 0; x < nodes->size(); x++) + { + if ((nodes->at(x)->GetData()->GetGeometry() != NULL) && + nodes->at(x)->GetData()->GetGeometry()->IsInside(crosshairPos)) + { + int layer = 0; + if (!(nodes->at(x)->GetIntProperty("layer", layer))) + { + continue; + } + if (layer > maxlayer) + { + if (static_cast(nodes->at(x))->IsVisible(baseRenderer)) + { + node = nodes->at(x); + maxlayer = layer; + } + } + } + } + } + return node; +} + +void QmitkCustomMultiWidget::HandleCrosshairPositionEventDelayed() +{ + m_PendingCrosshairPositionEvent = false; + + // find image with highest layer + mitk::TNodePredicateDataType::Pointer isImageData = mitk::TNodePredicateDataType::New(); + mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->m_DataStorage->GetSubset(isImageData).GetPointer(); + + mitk::DataNode::Pointer node; + mitk::DataNode::Pointer topSourceNode; + mitk::Image::Pointer image; + bool isBinary = false; + node = this->GetTopLayerNode(nodes); + int component = 0; + if (node.IsNotNull()) + { + node->GetBoolProperty("binary", isBinary); + if (isBinary) + { + mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = m_DataStorage->GetSources(node, NULL, true); + if (!sourcenodes->empty()) + { + topSourceNode = this->GetTopLayerNode(sourcenodes); + } + if (topSourceNode.IsNotNull()) + { + image = dynamic_cast(topSourceNode->GetData()); + topSourceNode->GetIntProperty("Image.Displayed Component", component); + } + else + { + image = dynamic_cast(node->GetData()); + node->GetIntProperty("Image.Displayed Component", component); + } + } + else + { + image = dynamic_cast(node->GetData()); + node->GetIntProperty("Image.Displayed Component", component); + } + } + + mitk::Point3D crosshairPos = this->GetCrossPosition(); + std::string statusText; + std::stringstream stream; + itk::Index<3> p; + mitk::BaseRenderer *baseRenderer = GetRenderWindow()->GetSliceNavigationController()->GetRenderer(); + unsigned int timestep = baseRenderer->GetTimeStep(); + + if (image.IsNotNull() && (image->GetTimeSteps() > timestep)) + { + image->GetGeometry()->WorldToIndex(crosshairPos, p); + stream.precision(2); + stream << "Position: <" << std::fixed << crosshairPos[0] << ", " << std::fixed << crosshairPos[1] << ", " + << std::fixed << crosshairPos[2] << "> mm"; + stream << "; Index: <" << p[0] << ", " << p[1] << ", " << p[2] << "> "; + + mitk::ScalarType pixelValue; + + mitkPixelTypeMultiplex5(mitk::FastSinglePixelAccess, + image->GetChannelDescriptor().GetPixelType(), + image, + image->GetVolumeData(baseRenderer->GetTimeStep()), + p, + pixelValue, + component); + + if (fabs(pixelValue) > 1000000 || fabs(pixelValue) < 0.01) + { + stream << "; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << std::scientific << pixelValue << " "; + } + else + { + stream << "; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << pixelValue << " "; + } + } + else + { + stream << "No image information at this position!"; + } + + statusText = stream.str(); + mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str()); +} + +void QmitkCustomMultiWidget::Fit() +{ + vtkSmartPointer vtkrenderer; + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + vtkRenderer* renderer = GetRenderWindow(widgetNumber)->GetRenderer()->GetVtkRenderer(); + mitk::BaseRenderer* baseRenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow(i)->GetRenderWindow()); + vtkrenderer = baseRenderer->GetVtkRenderer(); + if (nullptr != vtkrenderer) + { + vtkrenderer->ResetCamera(); + } + + baseRenderer->GetCameraController()->Fit(); + } + + + + int w = vtkObject::GetGlobalWarningDisplay(); + vtkObject::GlobalWarningDisplayOff(); + vtkObject::SetGlobalWarningDisplay(w); +} + +////////////////////////////////////////////////////////////////////////// +// PUBLIC SLOTS +////////////////////////////////////////////////////////////////////////// +// TODO: Use widget directly instead of number? +void QmitkCustomMultiWidget::ShowLevelWindowWidget(unsigned int widgetNumber, bool show) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Level window widget can not be shown for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->ShowLevelWindowWidget(show); +} + +// TODO: Use foreach on widgets map instead of iterator i and "widget number"? +void QmitkCustomMultiWidget::ShowAllLevelWindowWidgets(bool show) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ShowLevelWindowWidget(i, show); + } +} + +void QmitkCustomMultiWidget::SetBackgroundColorGradient(const mitk::Color& upper, const mitk::Color& lower, unsigned int widgetNumber) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Background color gradient can not be set for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->SetBackgroundColorGradient(upper, lower); +} + +void QmitkCustomMultiWidget::SetAllBackgroundColorGradients(const mitk::Color& upper, const mitk::Color& lower) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + SetBackgroundColorGradient(upper, lower, i); + } +} + +void QmitkCustomMultiWidget::FillAllBackgroundColorGradientsWithBlack() +{ + float black[3] = { 0.0f, 0.0f, 0.0f }; + SetAllBackgroundColorGradients(black, black); +} + +void QmitkCustomMultiWidget::ShowBackgroundColorGradient(unsigned int widgetNumber, bool show) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Background color gradient can not be shown for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->ShowBackgroundColorGradient(show); +} + +void QmitkCustomMultiWidget::ShowAllBackgroundColorGradients(bool show) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ShowBackgroundColorGradient(i, show); + } +} + +std::pair QmitkCustomMultiWidget::GetBackgroundColorGradient(unsigned int widgetNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Background color gradient can not be retrieved for an unknown widget. Returning black color pair."; + float black[3] = { 0.0f, 0.0f, 0.0f }; + return std::make_pair(mitk::Color(black), mitk::Color(black)); + } + + return GetRenderWindowWidget(widgetNumber)->GetRendererBackgroundColorGradient(); +} + +bool QmitkCustomMultiWidget::GetBackgroundColorGradientFlag(unsigned int widgetNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Background color gradient flag can not be retrieved for an unknown widget. Returning 'false'."; + return false; + } + + return GetRenderWindowWidget(widgetNumber)->GetBackgroundColorGradientFlag(); +} + +void QmitkCustomMultiWidget::SetDepartmentLogoPath(const char* path) +{ + /* old + m_LogoRendering->SetLogoImagePath(path); + mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()); + m_LogoRendering->Update(renderer); + RequestUpdate(); + */ + /* new + QImage* qimage = new QImage(path); + vtkSmartPointer qImageToVtk; + qImageToVtk = vtkSmartPointer::New(); + + qImageToVtk->SetQImage(qimage); + qImageToVtk->Update(); + + m_LogoRendering->SetLogoImage(qImageToVtk->GetOutput()); + mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()); + m_LogoRendering->Update(renderer); + RequestUpdate(); + */ +} + +void QmitkCustomMultiWidget::ShowDepartmentLogo(unsigned int widgetNumber, bool show) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Department logo can not be shown for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->ShowDepartmentLogo(show); + RequestUpdate(widgetNumber); +} + +void QmitkCustomMultiWidget::ShowAllDepartmentLogos(bool show) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ShowDepartmentLogo(i, show); + } +} + +void QmitkCustomMultiWidget::SetDecorationColor(unsigned int widgetNumber, const mitk::Color& color) +{ + // #TODO: change specific plane color of a render window widget (parameter: unsigned int planeNumber)? + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Decoration color can not be set for an unknown widget."; + return; + } + GetRenderWindowWidget(widgetNumber)->SetDecorationColor(color); +} + +mitk::Color QmitkCustomMultiWidget::GetDecorationColor(unsigned int widgetNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Decoration color can not be retrieved for an unknown widget. Returning black color!"; + float black[3] = { 0.0f, 0.0f, 0.0f }; + return mitk::Color(black); + } + + return GetRenderWindowWidget(widgetNumber)->GetDecorationColor(); +} + +void QmitkCustomMultiWidget::ShowColoredRectangle(unsigned int widgetNumber, bool show) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Colored rectangle can not be set for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->ShowColoredRectangle(show); +} + +void QmitkCustomMultiWidget::ShowAllColoredRectangles(bool show) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ShowColoredRectangle(i, show); + } +} + +bool QmitkCustomMultiWidget::IsColoredRectangleVisible(unsigned int widgetNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Colored rectangle visibility can not be retrieved for an unknown widget. Returning 'false'."; + return false; + } + + return GetRenderWindowWidget(widgetNumber)->IsColoredRectangleVisible(); +} + +void QmitkCustomMultiWidget::SetCornerAnnotationText(unsigned int widgetNumber, const std::string& cornerAnnotation) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Corner annotation text can not be retrieved for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->SetCornerAnnotationText(cornerAnnotation); +} + +std::string QmitkCustomMultiWidget::GetCornerAnnotationText(unsigned int widgetNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Corner annotation text can not be retrieved for an unknown widget."; + return ""; + } + + return GetRenderWindowWidget(widgetNumber)->GetCornerAnnotationText(); +} + +void QmitkCustomMultiWidget::ShowCornerAnnotation(unsigned int widgetNumber, bool show) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Corner annotation can not be set for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->ShowCornerAnnotation(show); +} + +void QmitkCustomMultiWidget::ShowAllCornerAnnotations(bool show) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ShowCornerAnnotation(i, show); + } +} + +bool QmitkCustomMultiWidget::IsCornerAnnotationVisible(unsigned int widgetNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Corner annotation visibility can not be retrieved for an unknown widget. Returning 'false'."; + return false; + } + + return GetRenderWindowWidget(widgetNumber)->IsCornerAnnotationVisible(); +} + +void QmitkCustomMultiWidget::ActivateRenderWindowMenu(unsigned int widgetNumber, bool state) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Level window widget can not be shown for an unknown widget."; + return; + } + + GetRenderWindowWidget(widgetNumber)->ActivateMenuWidget(state, this); +} + +void QmitkCustomMultiWidget::ActivateAllRenderWindowMenus(bool state) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ActivateRenderWindowMenu(i, state); + } +} + +bool QmitkCustomMultiWidget::IsRenderWindowMenuActivated(unsigned int widgetNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Render window menu activation status can not be retrieved for an unknown widget. Returning 'false'."; + return false; + } + + return GetRenderWindowWidget(widgetNumber)->IsRenderWindowMenuActivated(); +} + +void QmitkCustomMultiWidget::ShowGeometryPlanes(unsigned int widgetNumber, bool state) +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Geometry plane can not be shown for an unknown widget."; + return; + } + + return GetRenderWindowWidget(widgetNumber)->ShowGeometryPlanes(state); +} + +void QmitkCustomMultiWidget::ShowAllGeometryPlanes(bool state) +{ + size_t numberOfRenderWindowWidgets = m_RenderWindowWidgets.size(); + for (size_t i = 0; i < numberOfRenderWindowWidgets; ++i) + { + ShowGeometryPlanes(i, state); + } +} + +mitk::DataNode::Pointer QmitkCustomMultiWidget::GetGeometryPlane(unsigned int widgetNumber, unsigned int planeNumber) const +{ + if (widgetNumber > m_RenderWindowWidgets.size()) + { + MITK_ERROR << "Geometry plane can not be received for an unknown widget."; + return nullptr; + } + + return GetRenderWindowWidget(widgetNumber)->GetGeometryPlane(planeNumber); +} + + + +void QmitkCustomMultiWidget::wheelEvent(QWheelEvent *e) +{ + emit WheelMoved(e); +} + +void QmitkCustomMultiWidget::mousePressEvent(QMouseEvent *e) +{ +} + +void QmitkCustomMultiWidget::moveEvent(QMoveEvent *e) +{ + QWidget::moveEvent(e); + + // it is necessary to readjust the position of the overlays as the StdMultiWidget has moved + // unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here + emit Moved(); +} + +void QmitkCustomMultiWidget::SetWidgetPlanesLocked(bool locked) +{ + GetRenderWindow()->GetSliceNavigationController()->SetSliceLocked(locked); +} + +void QmitkCustomMultiWidget::SetWidgetPlanesRotationLocked(bool locked) +{ + GetRenderWindow()->GetSliceNavigationController()->SetSliceRotationLocked(locked); +} + +void QmitkCustomMultiWidget::SetWidgetPlanesRotationLinked(bool link) +{ + emit WidgetPlanesRotationLinked(link); +} + +void QmitkCustomMultiWidget::SetWidgetPlaneMode(int userMode) +{ + MITK_DEBUG << "Changing crosshair mode to " << userMode; + + emit WidgetNotifyNewCrossHairMode(userMode); + // Convert user interface mode to actual mode + { + switch (userMode) + { + case 0: + m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::MITK); + break; + case 1: + m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::ROTATION); + break; + case 2: + m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::ROTATIONLINKED); + break; + case 3: + m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::SWIVEL); + break; + } + } +} + +void QmitkCustomMultiWidget::SetWidgetPlaneModeToSlicing(bool activate) +{ + if (activate) + { + SetWidgetPlaneMode(PLANE_MODE_SLICING); + } +} + +void QmitkCustomMultiWidget::SetWidgetPlaneModeToRotation(bool activate) +{ + if (activate) + { + SetWidgetPlaneMode(PLANE_MODE_ROTATION); + } +} + +void QmitkCustomMultiWidget::SetWidgetPlaneModeToSwivel(bool activate) +{ + if (activate) + { + SetWidgetPlaneMode(PLANE_MODE_SWIVEL); + } +} + +void QmitkCustomMultiWidget::ResetCrosshair() +{ + if (m_DataStorage.IsNotNull()) + { + m_RenderingManager->InitializeViewsByBoundingObjects(m_DataStorage); + // m_RenderingManager->InitializeViews( m_DataStorage->ComputeVisibleBoundingGeometry3D() ); + // reset interactor to normal slicing + SetWidgetPlaneMode(PLANE_MODE_SLICING); + } +} + +mitk::MouseModeSwitcher* QmitkCustomMultiWidget::GetMouseModeSwitcher() +{ + return m_MouseModeSwitcher; +} + +void QmitkCustomMultiWidget::InitializeGUI() +{ + m_CustomMultiWidgetLayout = new QGridLayout(this); + m_CustomMultiWidgetLayout->setContentsMargins(0, 0, 0, 0); + setLayout(m_CustomMultiWidgetLayout); +} + +void QmitkCustomMultiWidget::AddRenderWindowWidget() +{ + // #TODO: add QSplitter? + // #TODO: include technique, to set the image to level-slide on using the render window manager + + // create the render window widget and connect signals / slots + std::string UID = "UID"; + QmitkRenderWindowWidget* renderWindowWidget = new QmitkRenderWindowWidget(this, UID, m_DataStorage); + + // create connections + connect(renderWindowWidget, SIGNAL(ResetView()), this, SLOT(ResetCrosshair())); + connect(renderWindowWidget, SIGNAL(ChangeCrosshairRotationMode(int)), this, SLOT(SetWidgetPlaneMode(int))); + connect(this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), renderWindowWidget, SLOT(OnWidgetPlaneModeChanged(int))); + + // store the newly created render window widget with the UID + m_RenderWindowWidgets.insert(std::pair(UID, renderWindowWidget)); + + mitk::SliceNavigationController* sliceNavigationController = renderWindowWidget->GetSliceNavigationController(); + if (nullptr != sliceNavigationController) + { + m_TimeNavigationController->ConnectGeometryTimeEvent(sliceNavigationController, false); + sliceNavigationController->ConnectGeometryTimeEvent(m_TimeNavigationController, false); + } + + // #TODO: define the grid cell to add the new render window widget + // add the newly created render window widget to this multi widget + m_CustomMultiWidgetLayout->addWidget(renderWindowWidget); +} diff --git a/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp b/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp new file mode 100644 index 0000000000..ee4ae2bef6 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp @@ -0,0 +1,354 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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 "QmitkRenderWindowWidget.h" + +// mitk core +#include + +// vtk +#include + +QmitkRenderWindowWidget::QmitkRenderWindowWidget(QWidget* parent/* = nullptr*/, const std::string& UID/* = ""*/, mitk::DataStorage* dataStorage/* = nullptr*/) + : QWidget(parent) + , m_UID(UID) + , m_DataStorage(dataStorage) + , m_RenderWindow(nullptr) + , m_LevelWindowWidget(nullptr) +{ + InitializeGUI(); + // TODO: signals / slots +} + +QmitkRenderWindowWidget::~QmitkRenderWindowWidget() +{ + // nothing here +} + +void QmitkRenderWindowWidget::SetDataStorage(mitk::DataStorage* dataStorage) +{ + if (dataStorage == m_DataStorage) + { + return; + } + + m_DataStorage = dataStorage; + if (nullptr != m_RenderWindow) + { + mitk::BaseRenderer::GetInstance(m_RenderWindow->GetRenderWindow())->SetDataStorage(ds); + } +} + +mitk::SliceNavigationController* QmitkRenderWindowWidget::GetSliceNavigationController() const +{ + if (nullptr == m_RenderWindow) + { + return nullptr; + } + + return m_RenderWindow->GetSliceNavigationController(); +} + +void QmitkRenderWindowWidget::RequestUpdate() +{ + m_RenderingManager->RequestUpdate(m_RenderWindow->GetRenderWindow()); +} + +void QmitkRenderWindowWidget::ForceImmediateUpdate() +{ + m_RenderingManager->ForceImmediateUpdate(m_RenderWindow->GetRenderWindow()); +} + +void QmitkRenderWindowWidget::SetBackgroundColorGradient(const mitk::Color& upper, const mitk::Color& lower) +{ + vtkRenderer* vtkRenderer = m_RenderWindow->GetRenderer()->GetVtkRenderer(); + if (nullptr == vtkRenderer) + { + return; + } + + m_BackgroundColorGradient.first = upper; + m_BackgroundColorGradient.second = lower; + vtkRenderer->SetBackground(lower[0], lower[1], lower[2]); + vtkRenderer->SetBackground2(upper[0], upper[1], upper[2]); + + ShowBackgroundColorGradient(true); +} + +void QmitkRenderWindowWidget::ShowBackgroundColorGradient(bool show) +{ + if (show) + { + m_RenderWindow->GetRenderer()->GetVtkRenderer()->GradientBackgroundOn(); + } + else + { + m_RenderWindow->GetRenderer()->GetVtkRenderer()->GradientBackgroundOff(); + + } + m_BackgroundColorGradientFlag = show; +} + +void QmitkRenderWindowWidget::ShowLevelWindowWidget(bool show) +{ + m_LevelWindowWidget->disconnect(this); + if (show) + { + m_LevelWindowWidget->SetDataStorage(m_DataStorage); + m_LevelWindowWidget->show(); + } + else + { + m_LevelWindowWidget->disconnect(this); + m_LevelWindowWidget->hide(); + } +} + +void QmitkRenderWindowWidget::ShowDepartmentLogo(bool show) +{ + m_LogoAnnotation->SetVisibility(show); +} + +void QmitkRenderWindowWidget::SetDecorationColor(const mitk::Color& color) +{ + m_DecorationColor = color; + m_RectangleProp->SetColor(m_DecorationColor[0], m_DecorationColor[1], m_DecorationColor[2]); + m_CornerAnnotation->GetTextProperty()->SetColor(color[0], color[1], color[2]); + + // #TODO: change color of geometry planes +} + +void QmitkRenderWindowWidget::ShowColoredRectangle(bool show) +{ + m_RectangleProp->SetVisibility(show); +} + +bool QmitkRenderWindowWidget::IsColoredRectangleVisible() const +{ + return m_RectangleProp->GetVisibility() > 0; +} + +void QmitkRenderWindowWidget::ShowCornerAnnotation(bool show) +{ + m_CornerAnnotation->SetVisibility(show); +} + +bool QmitkRenderWindowWidget::IsCornerAnnotationVisible() const +{ + return m_CornerAnnotation->GetVisibility() > 0; +} + +void QmitkRenderWindowWidget::SetCornerAnnotationText(const std::string& cornerAnnotation) +{ + m_CornerAnnotation->SetText(0, cornerAnnotation.c_str()); +} + +std::string QmitkRenderWindowWidget::GetCornerAnnotationText() const +{ + return std::string(m_CornerAnnotation->GetText(0)); +} + +void QmitkRenderWindowWidget::ActivateMenuWidget(bool state, QmitkCustomMultiWidget* multiWidget) +{ + // TODO: need to define an interface for multi widgets + //m_RenderWindow->ActivateMenuWidget(state, multiWidget); +} + +bool QmitkRenderWindowWidget::IsRenderWindowMenuActivated() const +{ + return m_RenderWindow->GetActivateMenuWidgetFlag(); +} + +void QmitkRenderWindowWidget::ShowGeometryPlanes(bool show) +{ + if (m_GeometryPlane1.IsNotNull()) + { + m_GeometryPlane1->SetVisibility(show); // TODO: parameter renderer? + } + if (m_GeometryPlane2.IsNotNull()) + { + m_GeometryPlane2->SetVisibility(show); + } + if (m_GeometryPlane3.IsNotNull()) + { + m_GeometryPlane3->SetVisibility(show); + } + m_RenderingManager->RequestUpdate(m_RenderWindow->GetRenderWindow()); +} + +mitk::DataNode::Pointer QmitkRenderWindowWidget::GetGeometryPlane(unsigned int planeNumber) const +{ + switch (planeNumber) + { + case 1: + return m_GeometryPlane1; + case 2: + return m_GeometryPlane2; + case 3: + return m_GeometryPlane3; + default: + return nullptr; + } +} + +void QmitkRenderWindowWidget::AddGeometryPlanesToDataStorage() +{ + if (m_GeometryPlane1.IsNotNull() && m_GeometryPlane2.IsNotNull() && m_GeometryPlane3.IsNotNull() && + m_GeometryPlanes.IsNotNull()) + { + if (nullptr != m_DataStorage) + { + m_DataStorage->Add(m_GeometryPlanes); + m_DataStorage->Add(m_GeometryPlane1, m_GeometryPlanes); + m_DataStorage->Add(m_GeometryPlane2, m_GeometryPlanes); + m_DataStorage->Add(m_GeometryPlane3, m_GeometryPlanes); + } + } +} + +void QmitkRenderWindowWidget::RemoveGeometryPlanesFromDataStorage() +{ + if (m_GeometryPlane1.IsNotNull() && m_GeometryPlane2.IsNotNull() && m_GeometryPlane3.IsNotNull() && + m_GeometryPlanes.IsNotNull()) + { + if (nullptr != m_DataStorage) + { + m_DataStorage->Remove(m_GeometryPlane1); + m_DataStorage->Remove(m_GeometryPlane2); + m_DataStorage->Remove(m_GeometryPlane3); + m_DataStorage->Remove(m_GeometryPlanes); + } + } +} + +void QmitkRenderWindowWidget::InitializeGUI() +{ + m_Layout = new QHBoxLayout(this); + m_Layout->setMargin(0); + setLayout(m_Layout); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + // create render window for this render window widget + m_RenderingManager = mitk::RenderingManager::GetInstance(); // TODO: do not always use the standard global rendering manager + m_RenderingMode = mitk::BaseRenderer::RenderingMode::Standard; // TODO: do not always use the standard rendering mode + m_RenderWindow = new QmitkRenderWindow(this, "widget - " + m_UID, nullptr, m_RenderingManager, m_RenderingMode); + m_RenderWindow->SetLayoutIndex(QmitkCustomMultiWidget::SAGITTAL); // TODO: allow to change layout type later + m_RenderWindow->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); + + // create level window widget for this render window widget + m_LevelWindowWidget = new QmitkLevelWindowWidget(this); + //m_LevelWindowWidget->setObjectName(QString::fromUtf8("levelWindowWidget")); + QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(m_LevelWindowWidget->sizePolicy().hasHeightForWidth()); + m_LevelWindowWidget->setSizePolicy(sizePolicy); + m_LevelWindowWidget->setMaximumWidth(50); + + m_Layout->addWidget(m_RenderWindow); + m_Layout->addWidget(m_LevelWindowWidget); + + // add geometry planes + InitializeGeometryPlanes(); + // set colors, add logo etc. + InitializeDecorations(); + + // connect to the "time navigation controller": send time via sliceNavigationControllers + m_TimeNavigationController->ConnectGeometryTimeEvent(GetRenderWindow()->GetSliceNavigationController(), false); + + // reverse connection between sliceNavigationControllers and m_TimeNavigationController + GetRenderWindow()->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); +} + +void QmitkRenderWindowWidget::InitializeGeometryPlanes() +{ + // #TODO: all have same geometry plane / all have same color + mitk::BaseRenderer* renderer = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetRenderWindow()); + if (nullptr == renderer) + { + return; + } + + mitk::PlaneGeometryDataMapper2D::Pointer mapper; + + m_GeometryPlane1 = renderer->GetCurrentWorldPlaneGeometryNode(); + m_GeometryPlane1->SetColor(m_DecorationColor); + m_GeometryPlane1->SetProperty("layer", mitk::IntProperty::New(1000)); + m_GeometryPlane1->SetProperty("visible", mitk::BoolProperty::New(true)); + m_GeometryPlane1->SetProperty("name", mitk::StringProperty::New(std::string(renderer->GetName()) + ".plane")); + m_GeometryPlane1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); + m_GeometryPlane1->SetProperty("helper object", mitk::BoolProperty::New(true)); + mapper = mitk::PlaneGeometryDataMapper2D::New(); + m_GeometryPlane1->SetMapper(mitk::BaseRenderer::Standard2D, mapper); + + m_GeometryPlane2 = renderer->GetCurrentWorldPlaneGeometryNode(); + m_GeometryPlane2->SetColor(m_DecorationColor); + m_GeometryPlane2->SetProperty("layer", mitk::IntProperty::New(1000)); + m_GeometryPlane2->SetProperty("visible", mitk::BoolProperty::New(true)); + m_GeometryPlane2->SetProperty("name", mitk::StringProperty::New(std::string(renderer->GetName()) + ".plane")); + m_GeometryPlane2->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); + m_GeometryPlane2->SetProperty("helper object", mitk::BoolProperty::New(true)); + mapper = mitk::PlaneGeometryDataMapper2D::New(); + m_GeometryPlane2->SetMapper(mitk::BaseRenderer::Standard2D, mapper); + + m_GeometryPlane3 = renderer->GetCurrentWorldPlaneGeometryNode(); + m_GeometryPlane3->SetColor(m_DecorationColor); + m_GeometryPlane3->SetProperty("layer", mitk::IntProperty::New(1000)); + m_GeometryPlane3->SetProperty("visible", mitk::BoolProperty::New(true)); + m_GeometryPlane3->SetProperty("name", mitk::StringProperty::New(std::string(renderer->GetName()) + ".plane")); + m_GeometryPlane3->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); + m_GeometryPlane3->SetProperty("helper object", mitk::BoolProperty::New(true)); + mapper = mitk::PlaneGeometryDataMapper2D::New(); + m_GeometryPlane2->SetMapper(mitk::BaseRenderer::Standard2D, mapper); + + // the parent node + m_ParentNodeForGeometryPlanes = mitk::DataNode::New(); + m_ParentNodeForGeometryPlanes->SetProperty("layer", mitk::IntProperty::New(1000)); + m_ParentNodeForGeometryPlanes->SetProperty("name", mitk::StringProperty::New("Widgets")); + m_ParentNodeForGeometryPlanes->SetProperty("helper object", mitk::BoolProperty::New(true)); +} + +void QmitkRenderWindowWidget::InitializeDecorations() +{ + vtkRenderer* vtkRenderer = m_RenderWindow->GetRenderer()->GetVtkRenderer(); + if (nullptr == vtkRenderer) + { + return; + } + + // initialize background color gradients + float black[3] = { 0.0f, 0.0f, 0.0f }; + SetBackgroundColorGradient(black, black); + + // initialize decoration color, rectangle and annotation text + float white[3] = { 1.0f, 1.0f, 1.0f }; + m_DecorationColor = white; + m_RectangleProp = vtkSmartPointer::New(); + m_RectangleProp->SetColor(m_DecorationColor[0], m_DecorationColor[1], m_DecorationColor[2]); + if (0 == vtkRenderer->HasViewProp(m_RectangleProp)) + { + vtkRenderer->AddViewProp(m_RectangleProp); + } + + m_CornerAnnotation = vtkSmartPointer::New(); + m_CornerAnnotation->SetText(0, "Sagittal"); + m_CornerAnnotation->SetMaximumFontSize(12); + m_CornerAnnotation->GetTextProperty()->SetColor(m_DecorationColor[0], m_DecorationColor[1], m_DecorationColor[2]); + if (0 == vtkRenderer->HasViewProp(m_CornerAnnotation)) + { + vtkRenderer->AddViewProp(m_CornerAnnotation); + } +} \ No newline at end of file diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index eeed58f1f1..ccc800437c 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,100 +1,101 @@ # 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:ON 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.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.custommultiwidgeteditor: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.diffusionimaging.connectomics:OFF org.mitk.gui.qt.diffusionimaging.denoising:OFF org.mitk.gui.qt.diffusionimaging.fiberfox:OFF org.mitk.gui.qt.diffusionimaging.fiberprocessing:OFF org.mitk.gui.qt.diffusionimaging.ivim:OFF org.mitk.gui.qt.diffusionimaging.odfpeaks:OFF org.mitk.gui.qt.diffusionimaging.partialvolume:OFF org.mitk.gui.qt.diffusionimaging.preprocessing:OFF org.mitk.gui.qt.diffusionimaging.reconstruction:OFF org.mitk.gui.qt.diffusionimaging.registration:OFF org.mitk.gui.qt.diffusionimaging.tbss:OFF org.mitk.gui.qt.diffusionimaging.tractography: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.lasercontrol: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.remeshing:OFF org.mitk.gui.qt.segmentation: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.photoacoustics.pausviewer:OFF org.mitk.gui.qt.photoacoustics.imageprocessing:OFF org.mitk.gui.qt.photoacoustics.simulation: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.igt.app.hummelprotocolmeasurements:OFF org.mitk.gui.qt.multilabelsegmentation:OFF 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 org.mitk.gui.qt.cest:OFF ) diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/CMakeLists.txt b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/CMakeLists.txt new file mode 100644 index 0000000000..c75e38d7a8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_custommultiwidgeteditor) + +mitk_create_plugin( + EXPORT_DIRECTIVE CUSTOMMULTIWIDGETEDITOR_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgets +) diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/files.cmake b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/files.cmake new file mode 100644 index 0000000000..c90583e4b3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/files.cmake @@ -0,0 +1,35 @@ +set(SRC_CPP_FILES + QmitkCustomMultiWidgetEditor.cpp +) + +set(INTERNAL_CPP_FILES + mitkPluginActivator.cpp + QmitkCustomMultiWidgetEditorPreferencePage.cpp +) + +set(UI_FILES + src/internal/QmitkCustomMultiWidgetEditorPreferencePage.ui +) + +set(MOC_H_FILES + src/QmitkCustomMultiWidgetEditor.h + + src/internal/mitkPluginActivator.h + src/internal/QmitkCustomMultiWidgetEditorPreferencePage.h +) + +set(CACHED_RESOURCE_FILES + resources/CustomMultiWidgetEditor.svg + plugin.xml +) + +set(QRC_FILES +) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_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.custommultiwidgeteditor/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/manifest_headers.cmake new file mode 100644 index 0000000000..a9b763fa3a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/manifest_headers.cmake @@ -0,0 +1,6 @@ +set(Plugin-Name "MITK Custom Multi Widget Editor") +set(Plugin-Version "1.0.0") +set(Plugin-Vendor "DKFZ, Division of Medical Image Computing") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common) + diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/plugin.xml b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/plugin.xml new file mode 100644 index 0000000000..60fb64cacd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/plugin.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/resources/CustomMultiWidgetEditor.svg b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/resources/CustomMultiWidgetEditor.svg new file mode 100644 index 0000000000..31d6ae02ac --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/resources/CustomMultiWidgetEditor.svg @@ -0,0 +1,55 @@ + + + + + + + image/svg+xml + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp new file mode 100644 index 0000000000..abea580144 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp @@ -0,0 +1,504 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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 "QmitkCustomMultiWidgetEditor.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include + + +//#TODO: create different default views (different layouts of the render window widgets) +class QmitkCustomMultiWidgetEditor::Impl final +{ +public: + + Impl(); + ~Impl(); + + QmitkCustomMultiWidget* m_CustomMultiWidget; + QmitkMouseModeSwitcher* m_MouseModeToolbar; + /* + * @brief Members for the MultiWidget decoration + */ + QString m_WidgetBackgroundColor1[4]; + QString m_WidgetBackgroundColor2[4]; + QString m_WidgetDecorationColor[4]; + QString m_WidgetAnnotation[4]; + bool m_MenuWidgetsEnabled; + + QHash m_RenderWindows; + +}; + +QmitkCustomMultiWidgetEditor::Impl::Impl() + : m_CustomMultiWidget(nullptr) + , m_MouseModeToolbar(nullptr) + , m_MenuWidgetsEnabled(false) +{ + // nothing here +} + +QmitkCustomMultiWidgetEditor::Impl::~Impl() +{ + // nothing here +} + +const QString QmitkCustomMultiWidgetEditor::EDITOR_ID = "org.mitk.editors.custommultiwidget"; + +QmitkCustomMultiWidgetEditor::QmitkCustomMultiWidgetEditor() + : m_Impl(new Impl()) // this? +{ + m_Impl->m_CustomMultiWidget->AddPlanesToDataStorage(); + RequestActivateMenuWidget(true); +} + +QmitkCustomMultiWidgetEditor::~QmitkCustomMultiWidgetEditor() +{ + m_Impl->m_CustomMultiWidget->RemovePlanesFromDataStorage(); + RequestActivateMenuWidget(false); +} + +void QmitkCustomMultiWidgetEditor::Activated() +{ + // nothing here +} + +void QmitkCustomMultiWidgetEditor::Deactivated() +{ + // nothing here +} + +void QmitkCustomMultiWidgetEditor::Visible() +{ + RequestActivateMenuWidget(true); +} + +void QmitkCustomMultiWidgetEditor::Hidden() +{ + RequestActivateMenuWidget(false); +} + +QmitkRenderWindow* QmitkCustomMultiWidgetEditor::GetActiveQmitkRenderWindow() const +{ + if (m_Impl->m_CustomMultiWidget) + { + return m_Impl->m_CustomMultiWidget->GetActiveRenderWindowWidget(); + } + + return nullptr; +} + +QHash QmitkCustomMultiWidgetEditor::GetQmitkRenderWindows() const +{ + return m_Impl->m_RenderWindows; +} + +QmitkRenderWindow* QmitkCustomMultiWidgetEditor::GetQmitkRenderWindow(const QString &id) const +{ + if (m_Impl->m_RenderWindows.contains(id)) + { + return m_Impl->m_RenderWindows[id]; + } + + return nullptr; +} + +mitk::Point3D QmitkCustomMultiWidgetEditor::GetSelectedPosition(const QString & /*id*/) const +{ + return m_Impl->m_CustomMultiWidget->GetCrossPosition(); +} + +void QmitkCustomMultiWidgetEditor::SetSelectedPosition(const mitk::Point3D &pos, const QString &/*id*/) +{ + m_Impl->m_CustomMultiWidget->MoveCrossToPosition(pos); +} + +void QmitkCustomMultiWidgetEditor::EnableDecorations(bool enable, const QStringList &decorations) +{ + if (decorations.isEmpty() || decorations.contains(DECORATION_BORDER)) + { + enable ? m_Impl->m_CustomMultiWidget->EnableColoredRectangles() + : m_Impl->m_CustomMultiWidget->DisableColoredRectangles(); + } + if (decorations.isEmpty() || decorations.contains(DECORATION_LOGO)) + { + enable ? m_Impl->m_CustomMultiWidget->EnableDepartmentLogo() + : m_Impl->m_CustomMultiWidget->DisableDepartmentLogo(); + } + if (decorations.isEmpty() || decorations.contains(DECORATION_MENU)) + { + m_Impl->m_CustomMultiWidget->ActivateRenderWindowWidgetMenu(enable); + } + if (decorations.isEmpty() || decorations.contains(DECORATION_BACKGROUND)) + { + enable ? m_Impl->m_CustomMultiWidget->EnableGradientBackground() + : m_Impl->m_CustomMultiWidget->DisableGradientBackground(); + } + if (decorations.isEmpty() || decorations.contains(DECORATION_CORNER_ANNOTATION)) + { + enable ? m_Impl->m_CustomMultiWidget->SetCornerAnnotationVisibility(true) + : m_Impl->m_CustomMultiWidget->SetCornerAnnotationVisibility(false); + } +} + +bool QmitkCustomMultiWidgetEditor::IsDecorationEnabled(const QString &decoration) const +{ + if (decoration == DECORATION_BORDER) + { + return m_Impl->m_CustomMultiWidget->IsColoredRectanglesEnabled(); + } + else if (decoration == DECORATION_LOGO) + { + return m_Impl->m_CustomMultiWidget->IsColoredRectanglesEnabled(); + } + else if (decoration == DECORATION_MENU) + { + return m_Impl->m_CustomMultiWidget->IsRenderWindowWidgetMenuEnabled(); + } + else if (decoration == DECORATION_BACKGROUND) + { + return m_Impl->m_CustomMultiWidget->GetGradientBackgroundFlag(); + } + else if (decoration == DECORATION_CORNER_ANNOTATION) + { + return m_Impl->m_CustomMultiWidget->IsCornerAnnotationVisible(); + } + + return false; +} + +QStringList QmitkCustomMultiWidgetEditor::GetDecorations() const +{ + QStringList decorations; + decorations << DECORATION_BORDER << DECORATION_LOGO << DECORATION_MENU << DECORATION_BACKGROUND << DECORATION_CORNER_ANNOTATION; + return decorations; +} + +void QmitkCustomMultiWidgetEditor::EnableSlicingPlanes(bool enable) +{ + m_Impl->m_CustomMultiWidget->SetWidgetPlanesVisibility(enable); +} + +bool QmitkCustomMultiWidgetEditor::IsSlicingPlanesEnabled() const +{ + mitk::DataNode::Pointer node = m_Impl->m_CustomMultiWidget->GetWidgetPlane1(); + if (node.IsNotNull()) + { + bool visible = false; + node->GetVisibility(visible, 0); + return visible; + } + else + { + return false; + } +} + +QmitkCustomMultiWidget* QmitkCustomMultiWidgetEditor::GetCustomMultiWidget() +{ + return m_Impl->m_CustomMultiWidget; +} + +void QmitkCustomMultiWidgetEditor::SetFocus() +{ + if (nullptr != m_Impl->m_CustomMultiWidget) + { + m_Impl->m_CustomMultiWidget->setFocus(); + } +} + +void QmitkCustomMultiWidgetEditor::OnPreferencesChanged(const berry::IBerryPreferences* preferences) +{ + // Enable change of logo. If no DepartmentLogo was set explicitly, MBILogo is used. + // Set new department logo by prefs->Set("DepartmentLogo", "PathToImage"); + + // If no logo was set for this plug-in specifically, walk the parent preference nodes + // and lookup a logo value there. + + const berry::IPreferences* currentNode = preferences; + + while(currentNode) + { + bool logoFound = false; + foreach (const QString& key, currentNode->Keys()) + { + if( key == "DepartmentLogo") + { + QString departmentLogoLocation = currentNode->Get("DepartmentLogo", ""); + + if (departmentLogoLocation.isEmpty()) + { + m_Impl->m_CustomMultiWidget->DisableDepartmentLogo(); + } + else + { + // we need to disable the logo first, otherwise setting a new logo will have + // no effect due to how mitkManufacturerLogo works... + m_Impl->m_CustomMultiWidget->DisableDepartmentLogo(); + m_Impl->m_CustomMultiWidget->SetDepartmentLogoPath(qPrintable(departmentLogoLocation)); + m_Impl->m_CustomMultiWidget->EnableDepartmentLogo(); + } + logoFound = true; + break; + } + } + + if (logoFound) break; + currentNode = currentNode->Parent().GetPointer(); + } + + // Update internal members + FillMembersWithCurrentDecorations(); + GetPreferenceDecorations(preferences); + // Now the members can be used to modify the custom multi widget + mitk::Color upper = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor1[0]); + mitk::Color lower = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor2[0]); + m_Impl->m_CustomMultiWidget->SetBackgroundColorGradient(upper, lower, 0); + m_Impl->m_CustomMultiWidget->ShowBackgroundColorGradient(0, true); + upper = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor1[1]); + lower = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor2[1]); + m_Impl->m_CustomMultiWidget->SetBackgroundColorGradient(upper, lower, 1); + m_Impl->m_CustomMultiWidget->ShowBackgroundColorGradient(1, true); + upper = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor1[2]); + lower = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor2[2]); + m_Impl->m_CustomMultiWidget->SetBackgroundColorGradient(upper, lower, 2); + m_Impl->m_CustomMultiWidget->ShowBackgroundColorGradient(2, true); + upper = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor1[3]); + lower = HexColorToMitkColor(m_Impl->m_WidgetBackgroundColor2[3]); + m_Impl->m_CustomMultiWidget->SetBackgroundColorGradient(upper, lower, 3); + m_Impl->m_CustomMultiWidget->ShowBackgroundColorGradient(3, true); + + // preferences for renderWindows + mitk::Color colorDecorationWidget1 = HexColorToMitkColor(m_Impl->m_WidgetDecorationColor[0]); + mitk::Color colorDecorationWidget2 = HexColorToMitkColor(m_Impl->m_WidgetDecorationColor[1]); + mitk::Color colorDecorationWidget3 = HexColorToMitkColor(m_Impl->m_WidgetDecorationColor[2]); + mitk::Color colorDecorationWidget4 = HexColorToMitkColor(m_Impl->m_WidgetDecorationColor[3]); + m_Impl->m_CustomMultiWidget->SetDecorationColor(0, colorDecorationWidget1); + m_Impl->m_CustomMultiWidget->SetDecorationColor(1, colorDecorationWidget2); + m_Impl->m_CustomMultiWidget->SetDecorationColor(2, colorDecorationWidget3); + m_Impl->m_CustomMultiWidget->SetDecorationColor(3, colorDecorationWidget4); + + for(unsigned int i = 0; i < 4; ++i) + { + m_Impl->m_CustomMultiWidget->SetDecorationProperties(m_Impl->m_WidgetAnnotation[i].toStdString(), HexColorToMitkColor(m_Impl->m_WidgetDecorationColor[i]), i); + } + // The crosshair gap + int crosshairgapsize = preferences->GetInt("crosshair gap size", 32); + m_Impl->m_CustomMultiWidget->GetWidgetPlane1()->SetIntProperty("Crosshair.Gap Size", crosshairgapsize); + m_Impl->m_CustomMultiWidget->GetWidgetPlane2()->SetIntProperty("Crosshair.Gap Size", crosshairgapsize); + m_Impl->m_CustomMultiWidget->GetWidgetPlane3()->SetIntProperty("Crosshair.Gap Size", crosshairgapsize); + + //refresh colors of rectangles + m_Impl->m_CustomMultiWidget->EnableColoredRectangles(); + + // Set preferences respecting zooming and panning + bool constrainedZooming = preferences->GetBool("Use constrained zooming and panning", true); + + mitk::RenderingManager::GetInstance()->SetConstrainedPanningZooming(constrainedZooming); + + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + // level window setting + bool showLevelWindowWidget = preferences->GetBool("Show level/window widget", true); + if (showLevelWindowWidget) + { + m_Impl->m_CustomMultiWidget->ShowAllLevelWindowWidgets(true); + } + else + { + m_Impl->m_CustomMultiWidget->ShowAllLevelWindowWidgets(false); + } + + // mouse modes toolbar + bool newMode = preferences->GetBool("PACS like mouse interaction", false); + m_Impl->m_MouseModeToolbar->setVisible( newMode ); + m_Impl->m_CustomMultiWidget->GetMouseModeSwitcher()->SetInteractionScheme( newMode ? mitk::MouseModeSwitcher::PACS : mitk::MouseModeSwitcher::MITK ); +} + +void QmitkCustomMultiWidgetEditor::CreateQtPartControl(QWidget* parent) +{ + if (nullptr == m_Impl->m_CustomMultiWidget) + { + QHBoxLayout* layout = new QHBoxLayout(parent); + layout->setContentsMargins(0, 0, 0, 0); + + if (nullptr == m_Impl->m_MouseModeToolbar) + { + m_Impl->m_MouseModeToolbar = new QmitkMouseModeSwitcher(parent); + layout->addWidget(m_Impl->m_MouseModeToolbar); + } + + berry::IPreferences::Pointer prefs = GetPreferences(); + mitk::BaseRenderer::RenderingMode::Type renderingMode = static_cast(prefs->GetInt("Rendering Mode", 0)); + + m_Impl->m_CustomMultiWidget = new QmitkCustomMultiWidget(parent, 0, 0, renderingMode); + m_Impl->m_RenderWindows.insert("axial", m_Impl->m_CustomMultiWidget->GetRenderWindowWidget()); + layout->addWidget(m_Impl->m_CustomMultiWidget); + + m_Impl->m_MouseModeToolbar->setMouseModeSwitcher(m_Impl->m_CustomMultiWidget->GetMouseModeSwitcher()); + + mitk::DataStorage::Pointer dataStorage = GetDataStorage(); + m_Impl->m_CustomMultiWidget->SetDataStorage(dataStorage); + + mitk::TimeGeometry::Pointer timeGeometry = dataStorage->ComputeBoundingGeometry3D(dataStorage->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews(timeGeometry); + + m_Impl->m_CustomMultiWidget->ShowAllLevelWindowWidgets(true); + + // Add the displayed views to the tree to see their positions + // in 2D and 3D + m_Impl->m_CustomMultiWidget->AddDisplayPlaneSubTree(); + + //m_Impl->m_StdMultiWidget->EnableNavigationControllerEventListening(); + + // Store the initial visibility status of the menu widget. + m_Impl->m_MenuWidgetsEnabled = m_Impl->m_CustomMultiWidget->IsRenderWindowWidgetMenuEnabled(); + + berry::IBerryPreferences* berryprefs = dynamic_cast(prefs.GetPointer()); + InitializePreferences(berryprefs); + OnPreferencesChanged(berryprefs); + + RequestUpdate(); + } +} + +void QmitkCustomMultiWidgetEditor::RequestActivateMenuWidget(bool on) +{ + if (nullptr == m_Impl->m_CustomMultiWidget) + { + return; + } + + if (on) + { + m_Impl->m_CustomMultiWidget->ActivateAllRenderWindowMenus(m_Impl->m_MenuWidgetsEnabled); + } + else + { + m_Impl->m_MenuWidgetsEnabled = m_Impl->m_CustomMultiWidget->IsRenderWindowWidgetMenuEnabled(); + m_Impl->m_CustomMultiWidget->ActivateAllRenderWindowMenus(false); + } +} + +void QmitkCustomMultiWidgetEditor::InitializePreferences(berry::IBerryPreferences* preferences) +{ + FillMembersWithCurrentDecorations(); // fill members + GetPreferenceDecorations(preferences); // overwrite if preferences are defined + + //create new preferences + preferences->Put("widget1 corner annotation", m_Impl->m_WidgetAnnotation[0]); + preferences->Put("widget2 corner annotation", m_Impl->m_WidgetAnnotation[1]); + preferences->Put("widget3 corner annotation", m_Impl->m_WidgetAnnotation[2]); + preferences->Put("widget4 corner annotation", m_Impl->m_WidgetAnnotation[3]); + + preferences->Put("widget1 decoration color", m_Impl->m_WidgetDecorationColor[0]); + preferences->Put("widget2 decoration color", m_Impl->m_WidgetDecorationColor[1]); + preferences->Put("widget3 decoration color", m_Impl->m_WidgetDecorationColor[2]); + preferences->Put("widget4 decoration color", m_Impl->m_WidgetDecorationColor[3]); + + preferences->Put("widget1 first background color", m_Impl->m_WidgetBackgroundColor1[0]); + preferences->Put("widget2 first background color", m_Impl->m_WidgetBackgroundColor1[1]); + preferences->Put("widget3 first background color", m_Impl->m_WidgetBackgroundColor1[2]); + preferences->Put("widget4 first background color", m_Impl->m_WidgetBackgroundColor1[3]); + preferences->Put("widget1 second background color", m_Impl->m_WidgetBackgroundColor2[0]); + preferences->Put("widget2 second background color", m_Impl->m_WidgetBackgroundColor2[1]); + preferences->Put("widget3 second background color", m_Impl->m_WidgetBackgroundColor2[2]); + preferences->Put("widget4 second background color", m_Impl->m_WidgetBackgroundColor2[3]); +} + +void QmitkCustomMultiWidgetEditor::FillMembersWithCurrentDecorations() +{ + //fill members with current values (or default values) from the std multi widget + for(unsigned int i = 0; i < 4; ++i) + { + m_Impl->m_WidgetDecorationColor[i] = MitkColorToHexColor(m_Impl->m_CustomMultiWidget->GetDecorationColor(i)); + m_Impl->m_WidgetBackgroundColor1[i] = MitkColorToHexColor(m_Impl->m_CustomMultiWidget->GetGradientColors(i).first); + m_Impl->m_WidgetBackgroundColor2[i] = MitkColorToHexColor(m_Impl->m_CustomMultiWidget->GetGradientColors(i).second); + m_Impl->m_WidgetAnnotation[i] = QString::fromStdString(m_Impl->m_CustomMultiWidget->GetCornerAnnotationText(i)); + } +} + +void QmitkCustomMultiWidgetEditor::GetPreferenceDecorations(const berry::IBerryPreferences * preferences) +{ + //overwrite members with values from the preferences, if they the preference is defined + m_Impl->m_WidgetBackgroundColor1[0] = preferences->Get("widget1 first background color", m_Impl->m_WidgetBackgroundColor1[0]); + m_Impl->m_WidgetBackgroundColor2[0] = preferences->Get("widget1 second background color", m_Impl->m_WidgetBackgroundColor2[0]); + m_Impl->m_WidgetBackgroundColor1[1] = preferences->Get("widget2 first background color", m_Impl->m_WidgetBackgroundColor1[1]); + m_Impl->m_WidgetBackgroundColor2[1] = preferences->Get("widget2 second background color", m_Impl->m_WidgetBackgroundColor2[1]); + m_Impl->m_WidgetBackgroundColor1[2] = preferences->Get("widget3 first background color", m_Impl->m_WidgetBackgroundColor1[2]); + m_Impl->m_WidgetBackgroundColor2[2] = preferences->Get("widget3 second background color", m_Impl->m_WidgetBackgroundColor2[2]); + m_Impl->m_WidgetBackgroundColor1[3] = preferences->Get("widget4 first background color", m_Impl->m_WidgetBackgroundColor1[3]); + m_Impl->m_WidgetBackgroundColor2[3] = preferences->Get("widget4 second background color", m_Impl->m_WidgetBackgroundColor2[3]); + + m_Impl->m_WidgetDecorationColor[0] = preferences->Get("widget1 decoration color", m_Impl->m_WidgetDecorationColor[0]); + m_Impl->m_WidgetDecorationColor[1] = preferences->Get("widget2 decoration color", m_Impl->m_WidgetDecorationColor[1]); + m_Impl->m_WidgetDecorationColor[2] = preferences->Get("widget3 decoration color", m_Impl->m_WidgetDecorationColor[2]); + m_Impl->m_WidgetDecorationColor[3] = preferences->Get("widget4 decoration color", m_Impl->m_WidgetDecorationColor[3]); + + m_Impl->m_WidgetAnnotation[0] = preferences->Get("widget1 corner annotation", m_Impl->m_WidgetAnnotation[0]); + m_Impl->m_WidgetAnnotation[1] = preferences->Get("widget2 corner annotation", m_Impl->m_WidgetAnnotation[1]); + m_Impl->m_WidgetAnnotation[2] = preferences->Get("widget3 corner annotation", m_Impl->m_WidgetAnnotation[2]); + m_Impl->m_WidgetAnnotation[3] = preferences->Get("widget4 corner annotation", m_Impl->m_WidgetAnnotation[3]); +} + +mitk::Color QmitkCustomMultiWidgetEditor::HexColorToMitkColor(const QString& hexColor) +{ + QColor qColor(hexColor); + mitk::Color returnColor; + float colorMax = 255.0f; + if (hexColor.isEmpty()) // default value + { + returnColor[0] = 1.0; + returnColor[1] = 1.0; + returnColor[2] = 1.0; + MITK_ERROR << "Using default color for unknown hex string " << qPrintable(hexColor); + } + else + { + returnColor[0] = qColor.red() / colorMax; + returnColor[1] = qColor.green() / colorMax; + returnColor[2] = qColor.blue() / colorMax; + } + + return returnColor; +} + +QString QmitkCustomMultiWidgetEditor::MitkColorToHexColor(const mitk::Color& mitkColor) +{ + QColor returnColor; + float colorMax = 255.0f; + returnColor.setRed(static_cast(mitkColor[0] * colorMax + 0.5)); + returnColor.setGreen(static_cast(mitkColor[1] * colorMax + 0.5)); + returnColor.setBlue(static_cast(mitkColor[2] * colorMax + 0.5)); + + return returnColor.name(); +} diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.h b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.h new file mode 100644 index 0000000000..6e6921b053 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.h @@ -0,0 +1,164 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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 QMITKCUSTOMMULTIWIDGETEDITOR_H +#define QMITKCUSTOMMULTIWIDGETEDITOR_H + +#include +#include +#include + +// custom multi widget editor +#include + +#include + +class QmitkCustomMultiWidget; +class QmitkMouseModeSwitcher; + +class CUSTOMMULTIWIDGETEDITOR_EXPORT QmitkCustomMultiWidgetEditor final : public QmitkAbstractRenderEditor, public mitk::ILifecycleAwarePart, public mitk::ILinkedRenderWindowPart +{ + Q_OBJECT + +public: + + berryObjectMacro(QmitkCustomMultiWidgetEditor) + + static const QString EDITOR_ID; + + QmitkCustomMultiWidgetEditor(); + ~QmitkCustomMultiWidgetEditor(); + + /* + * @brief Overridden from mitk::ILifecycleAwarePart + */ + virtual void Activated() override; + /* + * @brief Overridden from mitk::ILifecycleAwarePart + */ + virtual void Deactivated() override; + /* + * @brief Overridden from mitk::ILifecycleAwarePart + */ + virtual void Visible() override; + /* + * @brief Overridden from mitk::ILifecycleAwarePart + */ + virtual void Hidden() override; + + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual QmitkRenderWindow* GetActiveQmitkRenderWindow() const override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual QHash GetQmitkRenderWindows() const override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual QmitkRenderWindow* GetQmitkRenderWindow(const QString& id) const override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual mitk::Point3D GetSelectedPosition(const QString& id = QString()) const override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual void SetSelectedPosition(const mitk::Point3D& pos, const QString& id = QString()) override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual void EnableDecorations(bool enable, const QStringList& decorations = QStringList()) override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual bool IsDecorationEnabled(const QString& decoration) const override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + */ + virtual QStringList GetDecorations() const override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart + */ + virtual void EnableSlicingPlanes(bool enable) override; + /* + * @brief Overridden from mitk::ILinkedRenderWindowPart + */ + virtual bool IsSlicingPlanesEnabled() const override; + + QmitkCustomMultiWidget* GetCustomMultiWidget(); + +private: + /* + * @brief Overridden from QmitkAbstractRenderEditor + */ + virtual void SetFocus() override; + /* + * @brief Overridden from QmitkAbstractRenderEditor + */ + virtual void OnPreferencesChanged(const berry::IBerryPreferences* preferences) override; + /* + * @brief Overridden from QmitkAbstractRenderEditor + */ + virtual void CreateQtPartControl(QWidget* parent) override; + + /* + * @brief + * + * + */ + void RequestActivateMenuWidget(bool on); + /* + * @brief Set the default preferences. This method is used to show the current preferences + * in the first call of the preference page (the GUI). + * + * @param preferences The berry preferences. + */ + void InitializePreferences(berry::IBerryPreferences* preferences); + /* + * @brief FillMembersWithCurrentDecorations Helper method to fill internal members with + * current values of the std multi widget. + */ + void FillMembersWithCurrentDecorations(); + /* + * @brief GetPreferenceDecorations Getter to fill internal members with values of preferences. + * @param preferences The berry preferences. + * + * If a preference is set, the value will overwrite the current value. If it does not exist, + * the value will not change. + */ + void GetPreferenceDecorations(const berry::IBerryPreferences* preferences); + /* + * @brief Convert a hex color string to mitk::Color. + * + * @param widgetColorInHex The color in hex format (#RRGGBB) where each digit is in the form (0-F). + * @return The color in mitk format. + */ + mitk::Color HexColorToMitkColor(const QString& hexColor); + /* + * @brief Convert an mitk::Color to a hex color string. + * + * @param color The color in mitk format. + * @return The color as string in hex (#RRGGBB). + */ + QString MitkColorToHexColor(const mitk::Color& mitkColor); + + class Impl; + std::unique_ptr m_Impl; +}; + +#endif // QMITKCUSTOMMULTIWIDGETEDITOR_H diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.cpp b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.cpp new file mode 100644 index 0000000000..ce76599e71 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.cpp @@ -0,0 +1,256 @@ +/*=================================================================== + +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 "QmitkCustomMultiWidgetEditorPreferencePage.h" +#include + +#include +#include + +#include + +QmitkCustomMultiWidgetEditorPreferencePage::QmitkCustomMultiWidgetEditorPreferencePage() + : m_Preferences(nullptr) +{ + // nothing here +} + +QmitkCustomMultiWidgetEditorPreferencePage::~QmitkCustomMultiWidgetEditorPreferencePage() +{ + //nothing here +} + +void QmitkCustomMultiWidgetEditorPreferencePage::CreateQtControl(QWidget* parent) +{ + m_MainControl = new QWidget(parent); + + m_Ui.setupUi(m_MainControl); + + berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); + Q_ASSERT(prefService); + + m_Preferences = prefService->GetSystemPreferences()->Node(QmitkCustomMultiWidgetEditor::EDITOR_ID); + + connect(m_Ui.m_ColorButton1, SIGNAL(clicked()), SLOT(ColorChooserButtonClicked())); + connect(m_Ui.m_ColorButton2, SIGNAL(clicked()), SLOT(ColorChooserButtonClicked())); + connect(m_Ui.m_ResetButton, SIGNAL(clicked()), SLOT(ResetPreferencesAndGUI())); + connect(m_Ui.m_RenderingMode, SIGNAL(activated(int)), SLOT(ChangeRenderingMode(int))); + connect(m_Ui.m_RenderWindowDecorationColor, SIGNAL(clicked()), SLOT(ColorChooserButtonClicked())); + connect(m_Ui.m_RenderWindowChooser, SIGNAL(activated(int)), SLOT(OnWidgetComboBoxChanged(int))); + connect(m_Ui.m_RenderWindowDecorationText, SIGNAL(textChanged(QString)), SLOT(AnnotationTextChanged(QString))); + + Update(); +} + +QWidget* QmitkCustomMultiWidgetEditorPreferencePage::GetQtControl() const +{ + return m_MainControl; +} + +void QmitkCustomMultiWidgetEditorPreferencePage::Init(berry::IWorkbench::Pointer) +{ +} + +void QmitkCustomMultiWidgetEditorPreferencePage::PerformCancel() +{ +} + +bool QmitkCustomMultiWidgetEditorPreferencePage::PerformOk() +{ + m_Preferences->Put("widget1 corner annotation", m_WidgetAnnotation[0]); + m_Preferences->Put("widget2 corner annotation", m_WidgetAnnotation[1]); + m_Preferences->Put("widget3 corner annotation", m_WidgetAnnotation[2]); + m_Preferences->Put("widget4 corner annotation", m_WidgetAnnotation[3]); + + m_Preferences->Put("widget1 decoration color", m_WidgetDecorationColor[0]); + m_Preferences->Put("widget2 decoration color", m_WidgetDecorationColor[1]); + m_Preferences->Put("widget3 decoration color", m_WidgetDecorationColor[2]); + m_Preferences->Put("widget4 decoration color", m_WidgetDecorationColor[3]); + + m_Preferences->Put("widget1 first background color", m_WidgetBackgroundColor1[0]); + m_Preferences->Put("widget2 first background color", m_WidgetBackgroundColor1[1]); + m_Preferences->Put("widget3 first background color", m_WidgetBackgroundColor1[2]); + m_Preferences->Put("widget4 first background color", m_WidgetBackgroundColor1[3]); + m_Preferences->Put("widget1 second background color", m_WidgetBackgroundColor2[0]); + m_Preferences->Put("widget2 second background color", m_WidgetBackgroundColor2[1]); + m_Preferences->Put("widget3 second background color", m_WidgetBackgroundColor2[2]); + m_Preferences->Put("widget4 second background color", m_WidgetBackgroundColor2[3]); + m_Preferences->PutInt("crosshair gap size", m_Ui.m_CrosshairGapSize->value()); + + m_Preferences->PutBool("Use constrained zooming and panning", m_Ui.m_EnableFlexibleZooming->isChecked()); + m_Preferences->PutBool("Show level/window widget", m_Ui.m_ShowLevelWindowWidget->isChecked()); + m_Preferences->PutBool("PACS like mouse interaction", m_Ui.m_PACSLikeMouseMode->isChecked()); + m_Preferences->PutInt("Rendering Mode", m_Ui.m_RenderingMode->currentIndex()); + + return true; +} + +void QmitkCustomMultiWidgetEditorPreferencePage::Update() +{ + //Note: there should be default preferences already defined in the + //QmitkStdMultiWidgetEditor::InitializePreferences(). Therefore, + //all default values here are not relevant. + //gradient background colors + m_WidgetBackgroundColor1[0] = m_Preferences->Get("widget1 first background color", "#000000"); + m_WidgetBackgroundColor2[0] = m_Preferences->Get("widget1 second background color", "#000000"); + m_WidgetBackgroundColor1[1] = m_Preferences->Get("widget2 first background color", "#000000"); + m_WidgetBackgroundColor2[1] = m_Preferences->Get("widget2 second background color", "#000000"); + m_WidgetBackgroundColor1[2] = m_Preferences->Get("widget3 first background color", "#000000"); + m_WidgetBackgroundColor2[2] = m_Preferences->Get("widget3 second background color", "#000000"); + m_WidgetBackgroundColor1[3] = m_Preferences->Get("widget4 first background color", "#191919"); + m_WidgetBackgroundColor2[3] = m_Preferences->Get("widget4 second background color", "#7F7F7F"); + + //decoration colors + m_WidgetDecorationColor[0] = m_Preferences->Get("widget1 decoration color", "#FF0000"); + m_WidgetDecorationColor[1] = m_Preferences->Get("widget2 decoration color", "#00FF00"); + m_WidgetDecorationColor[2] = m_Preferences->Get("widget3 decoration color", "#0000FF"); + m_WidgetDecorationColor[3] = m_Preferences->Get("widget4 decoration color", "#FFFF00"); + + //annotation text + m_WidgetAnnotation[0] = m_Preferences->Get("widget1 corner annotation", "Axial"); + m_WidgetAnnotation[1] = m_Preferences->Get("widget2 corner annotation", "Sagittal"); + m_WidgetAnnotation[2] = m_Preferences->Get("widget3 corner annotation", "Coronal"); + m_WidgetAnnotation[3] = m_Preferences->Get("widget4 corner annotation", "3D"); + + + //Ui stuff + int index = m_Ui.m_RenderWindowChooser->currentIndex(); + QColor firstBackgroundColor(m_WidgetBackgroundColor1[index]); + QColor secondBackgroundColor(m_WidgetBackgroundColor2[index]); + QColor widgetColor(m_WidgetDecorationColor[index]); + + this->SetStyleSheetToColorChooserButton(firstBackgroundColor, m_Ui.m_ColorButton1); + this->SetStyleSheetToColorChooserButton(secondBackgroundColor, m_Ui.m_ColorButton2); + this->SetStyleSheetToColorChooserButton(widgetColor, m_Ui.m_RenderWindowDecorationColor); + + m_Ui.m_RenderWindowDecorationText->setText(m_WidgetAnnotation[index]); + + m_Ui.m_EnableFlexibleZooming->setChecked(m_Preferences->GetBool("Use constrained zooming and panning", true)); + m_Ui.m_ShowLevelWindowWidget->setChecked(m_Preferences->GetBool("Show level/window widget", true)); + m_Ui.m_PACSLikeMouseMode->setChecked(m_Preferences->GetBool("PACS like mouse interaction", false)); + int mode= m_Preferences->GetInt("Rendering Mode",0); + m_Ui.m_RenderingMode->setCurrentIndex(mode); + m_Ui.m_CrosshairGapSize->setValue(m_Preferences->GetInt("crosshair gap size", 32)); +} + +void QmitkCustomMultiWidgetEditorPreferencePage::ColorChooserButtonClicked() +{ + unsigned int widgetIndex = m_Ui.m_RenderWindowChooser->currentIndex(); + if(widgetIndex > 3) + { + MITK_ERROR << "Selected index for unknown."; + return; + } + QObject *senderObj = sender(); // This will give Sender button + //find out last used color and set it + QColor initialColor; + if( senderObj->objectName() == m_Ui.m_ColorButton1->objectName()) + { + initialColor = QColor(m_WidgetBackgroundColor1[widgetIndex]); + }else if( senderObj->objectName() == m_Ui.m_ColorButton2->objectName()) + { + initialColor = QColor(m_WidgetBackgroundColor2[widgetIndex]); + }else if( senderObj->objectName() == m_Ui.m_RenderWindowDecorationColor->objectName()) + { + initialColor = QColor(m_WidgetDecorationColor[widgetIndex]); + } + + //get the new color + QColor newcolor = QColorDialog::getColor(initialColor); + if(!newcolor.isValid()) + { + newcolor = initialColor; + } + this->SetStyleSheetToColorChooserButton(newcolor, static_cast(senderObj)); + + //convert it to std string and apply it + if( senderObj->objectName() == m_Ui.m_ColorButton1->objectName()) + { + m_WidgetBackgroundColor1[widgetIndex] = newcolor.name(); + } + else if( senderObj->objectName() == m_Ui.m_ColorButton2->objectName()) + { + m_WidgetBackgroundColor2[widgetIndex] = newcolor.name(); + } + else if( senderObj->objectName() == m_Ui.m_RenderWindowDecorationColor->objectName()) + { + m_WidgetDecorationColor[widgetIndex] = newcolor.name(); + } +} + +void QmitkCustomMultiWidgetEditorPreferencePage::SetStyleSheetToColorChooserButton(QColor backgroundcolor, QPushButton* button) +{ + button->setAutoFillBackground(true); + QString styleSheet = "background-color:rgb("; + + styleSheet.append(QString::number(backgroundcolor.red())); + styleSheet.append(","); + styleSheet.append(QString::number(backgroundcolor.green())); + styleSheet.append(","); + styleSheet.append(QString::number(backgroundcolor.blue())); + styleSheet.append(")"); + button->setStyleSheet(styleSheet); +} + +void QmitkCustomMultiWidgetEditorPreferencePage::AnnotationTextChanged(QString text) +{ + unsigned int widgetIndex = m_Ui.m_RenderWindowChooser->currentIndex(); + if( widgetIndex > 3) + { + MITK_INFO << "Selected index for unknown widget."; + return; + } + m_WidgetAnnotation[widgetIndex] = text; +} + +void QmitkCustomMultiWidgetEditorPreferencePage::ResetPreferencesAndGUI() +{ + m_Preferences->Clear(); + this->Update(); +} + +void QmitkCustomMultiWidgetEditorPreferencePage::OnWidgetComboBoxChanged(int i) +{ + if( i > 3) + { + MITK_ERROR << "Selected unknown widget."; + return; + } + QColor widgetColor(m_WidgetDecorationColor[i]); + QColor gradientBackground1(m_WidgetBackgroundColor1[i]); + QColor gradientBackground2(m_WidgetBackgroundColor2[i]); + SetStyleSheetToColorChooserButton(widgetColor, m_Ui.m_RenderWindowDecorationColor); + SetStyleSheetToColorChooserButton(gradientBackground1, m_Ui.m_ColorButton1); + SetStyleSheetToColorChooserButton(gradientBackground2, m_Ui.m_ColorButton2); + m_Ui.m_RenderWindowDecorationText->setText(m_WidgetAnnotation[i]); +} + +void QmitkCustomMultiWidgetEditorPreferencePage::ChangeRenderingMode(int i) +{ + if( i == 0 ) + { + m_CurrentRenderingMode = "Standard"; + } + else if( i == 1 ) + { + m_CurrentRenderingMode = "Multisampling"; + } + else if( i == 2 ) + { + m_CurrentRenderingMode = "DepthPeeling"; + } +} diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.h b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.h new file mode 100644 index 0000000000..181d5b3635 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.h @@ -0,0 +1,121 @@ +/*=================================================================== + +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 QMITKCUSTOMMULTIWIDGETEDITORPREFERENCEPAGE_H +#define QMITKCUSTOMMULTIWIDGETEDITORPREFERENCEPAGE_H + +// custom multi widget editor +#include "ui_QmitkCustomMultiWidgetEditorPreferencePage.h" + +#include +#include +#include +#include +#include + +class QmitkCustomMultiWidgetEditorPreferencePage : public QObject, public berry::IQtPreferencePage +{ + Q_OBJECT + Q_INTERFACES(berry::IPreferencePage) + +public: + QmitkCustomMultiWidgetEditorPreferencePage(); + ~QmitkCustomMultiWidgetEditorPreferencePage(); + + void CreateQtControl(QWidget* parent) override; + QWidget* GetQtControl() const override; + void Init(berry::IWorkbench::Pointer) override; + void PerformCancel() override; + bool PerformOk() override; + void Update() override; + +public slots: + /** + * @brief ResetColors set default colors and refresh the GUI. + */ + void ResetPreferencesAndGUI(); + + /** + * @brief ChangeRenderingMode slot to chose the rendering mode via QComboBox. + * @param i index of the box. + */ + void ChangeRenderingMode(int i); + + /** + * @brief OnWidgetComboBoxChanged slot called when the QComboBox to chose the widget was modified. + * @param i index of the combobox to select the widget (1-4). + */ + void OnWidgetComboBoxChanged(int i); + + /** + * @brief AnnotationTextChanged called when QLineEdit for the annotation was changed. + * @param text The new text. + */ + void AnnotationTextChanged(QString text); + +protected: + /** + * @brief m_CurrentRenderingMode String for the rendering mode. + */ + std::string m_CurrentRenderingMode; + + /** + * @brief m_WidgetBackgroundColor1 the background colors. + * + * If two different colors are chosen, a gradient background appears. + */ + QString m_WidgetBackgroundColor1[4]; + QString m_WidgetBackgroundColor2[4]; + + /** + * @brief m_WidgetDecorationColor the decoration color. + * + * The rectangle prop, the crosshair, the 3D planes and the corner annotation use this. + */ + QString m_WidgetDecorationColor[4]; + + /** + * @brief m_Widget1Annotation the text of the corner annotation. + */ + QString m_WidgetAnnotation[4]; + + /** + * @brief m_Preferences the berry preferences. + */ + berry::IPreferences::Pointer m_Preferences; + + /** + * @brief SetStyleSheetToColorChooserButton colorize a button. + * @param backgroundcolor color for the button. + * @param button the button. + */ + void SetStyleSheetToColorChooserButton(QColor backgroundcolor, QPushButton* button); + +protected slots: + + /** + * @brief ColorChooserButtonClicked slot called when a button to choose color was clicked. + */ + void ColorChooserButtonClicked(); + +private: + + Ui::QmitkCustomMultiWidgetEditorPreferencePage m_Ui; + QWidget* m_MainControl; + +}; + +#endif // QMITKCUSTOMMULTIWIDGETEDITORPREFERENCEPAGE_H diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.ui b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.ui new file mode 100644 index 0000000000..71878f5ea0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/QmitkCustomMultiWidgetEditorPreferencePage.ui @@ -0,0 +1,225 @@ + + + QmitkCustomMultiWidgetEditorPreferencePage + + + + 0 + 0 + 518 + 431 + + + + External Programs + + + + + + + stdmulti.widget1 + + + + + stdmulti.widget2 + + + + + stdmulti.widget3 + + + + + stdmulti.widget4 + + + + + + + + <html><head/><body><p>If two colors are set, a gradient background is generated.</p></body></html> + + + Background color + + + + + + + Reset preferences + + + + + + + + Standard Rendering + + + + + Enable Multisampling (Antialiasing) + + + + + Enable Depth Peeling + + + + + + + + * Changes require restart of MITK. + Depth Peeling is only supported by Windows. + For other OS, use Standard Rendering and enable + the property 'Depth Sorting' in the property list of the surface data node. + + + + + + + 32 + + + + + + + Qt::Horizontal + + + + + + + The small text on the button left of each renderwindow. + + + Corner annotation + + + + + + + <html><head/><body><p>The gap in the middle of the crosshair in pixels.</p></body></html> + + + Crosshair gap size + + + + + + + <html><head/><body><p>The color is used for the following decorations (of each renderwindow):</p><p>Rectangle border</p><p>Corner annotation</p><p>Crosshair</p><p>Plane geometry helper objects (3D Planes)</p><p>Image navigator borders</p><p><br/></p></body></html> + + + Decoration color + + + + + + + + + + + + + + <html><head/><body><p>Choose the renderwindow from the multi widget.</p></body></html> + + + Render windows + + + + + + + Qt::LeftToRight + + + Show level/window widget + + + true + + + + + + + Qt::LeftToRight + + + Use PACS like mouse interaction (select left mouse button action) + + + false + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + Rendering Mode* + + + + + + + + + + + + + + + + + <html><head/><body><p>If activated, zooming and panning is limited to a certain space arround each image.</p></body></html> + + + Qt::LeftToRight + + + Use constraint zooming and panning + + + true + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/mitkPluginActivator.cpp new file mode 100644 index 0000000000..76a4cb77aa --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/mitkPluginActivator.cpp @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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 +#include "QmitkCustomMultiWidgetEditorPreferencePage.h" + +namespace mitk +{ + ctkPluginContext* CustomMultiWidgetActivator::m_Context = nullptr; + + void CustomMultiWidgetActivator::start(ctkPluginContext* context) + { + m_Context = context; + + BERRY_REGISTER_EXTENSION_CLASS(QmitkCustomMultiWidgetEditor, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkCustomMultiWidgetEditorPreferencePage, context) + } + + void CustomMultiWidgetActivator::stop(ctkPluginContext* context) + { + Q_UNUSED(context) + + m_Context = nullptr; + } + + ctkPluginContext* CustomMultiWidgetActivator::GetContext() + { + return m_Context; + } +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/mitkPluginActivator.h new file mode 100644 index 0000000000..b25c98fb6b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/internal/mitkPluginActivator.h @@ -0,0 +1,43 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical Image Computing. +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 CustomMultiWidgetActivator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_custommultiwidgeteditor") + Q_INTERFACES(ctkPluginActivator) + + public: + + void start(ctkPluginContext* context) override; + void stop(ctkPluginContext* context) override; + + static ctkPluginContext* GetContext(); + + private: + + static ctkPluginContext* m_Context; + + }; +} +#endif // MITKPLUGINACTIVATOR_H