diff --git a/Modules/QtWidgets/files.cmake b/Modules/QtWidgets/files.cmake index 3154b5690a..79e69a0ecc 100644 --- a/Modules/QtWidgets/files.cmake +++ b/Modules/QtWidgets/files.cmake @@ -1,118 +1,120 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES QmitkAbstractDataStorageModel.cpp + QmitkAbstractMultiWidget.cpp QmitkApplicationCursor.cpp QmitkDataStorageComboBox.cpp QmitkDataStorageDefaultListModel.cpp QmitkDataStorageListModel.cpp QmitkDataStorageTableModel.cpp QmitkDataStorageSimpleTreeModel.cpp QmitkDataStorageTreeModel.cpp QmitkDataStorageTreeModelInternalItem.cpp QmitkFileReaderOptionsDialog.cpp QmitkFileReaderWriterOptionsWidget.cpp QmitkFileWriterOptionsDialog.cpp QmitkInteractionSchemeToolBar.cpp QmitkIOUtil.cpp QmitkLevelWindowPresetDefinitionDialog.cpp QmitkLevelWindowRangeChangeDialog.cpp QmitkLevelWindowWidgetContextMenu.cpp QmitkLevelWindowWidget.cpp QmitkLineEditLevelWindowWidget.cpp QmitkMemoryUsageIndicatorView.cpp QmitkMimeTypes.cpp QmitkMouseModeSwitcher.cpp QmitkMultiWidgetConfigurationToolBar.cpp QmitkMultiWidgetLayoutSelectionWidget.cpp QmitkNodeDescriptor.cpp QmitkColoredNodeDescriptor.cpp QmitkNodeDescriptorManager.cpp QmitkProgressBar.cpp QmitkPropertiesTableEditor.cpp QmitkPropertiesTableModel.cpp QmitkPropertyDelegate.cpp QmitkRegisterClasses.cpp QmitkRenderingManager.cpp QmitkRenderingManagerFactory.cpp QmitkRenderWindow.cpp QmitkRenderWindowMenu.cpp QmitkRenderWindowWidget.cpp QmitkServiceListWidget.cpp QmitkSliderLevelWindowWidget.cpp QmitkStdMultiWidget.cpp QmitkCustomMultiWidget.cpp QmitkDataStorageFilterProxyModel.cpp QmitkDataStorageComboBoxWithSelectNone.cpp QmitkPropertyItem.cpp QmitkPropertyItemDelegate.cpp QmitkPropertyItemModel.cpp QmitkStyleManager.cpp QmitkAbstractDataStorageInspector.cpp QmitkDataStorageListInspector.cpp QmitkDataStorageTreeInspector.cpp QmitkModelViewSelectionConnector.cpp mitkIDataStorageInspectorProvider.cpp mitkQtWidgetsActivator.cpp mitkDataStorageInspectorGenerator.cpp ) set(MOC_H_FILES include/QmitkAbstractDataStorageModel.h + include/QmitkAbstractMultiWidget.h include/QmitkDataStorageComboBox.h include/QmitkDataStorageTableModel.h include/QmitkDataStorageTreeModel.h include/QmitkDataStorageSimpleTreeModel.h include/QmitkDataStorageDefaultListModel.h include/QmitkFileReaderOptionsDialog.h include/QmitkFileReaderWriterOptionsWidget.h include/QmitkFileWriterOptionsDialog.h include/QmitkInteractionSchemeToolBar.h include/QmitkLevelWindowPresetDefinitionDialog.h include/QmitkLevelWindowRangeChangeDialog.h include/QmitkLevelWindowWidgetContextMenu.h include/QmitkLevelWindowWidget.h include/QmitkLineEditLevelWindowWidget.h include/QmitkMemoryUsageIndicatorView.h include/QmitkMouseModeSwitcher.h include/QmitkMultiWidgetConfigurationToolBar.h include/QmitkMultiWidgetLayoutSelectionWidget.h include/QmitkNodeDescriptor.h include/QmitkColoredNodeDescriptor.h include/QmitkNodeDescriptorManager.h include/QmitkRenderWindowMenu.h include/QmitkRenderWindowWidget.h 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/QmitkDataStorageComboBoxWithSelectNone.h include/QmitkPropertyItemDelegate.h include/QmitkPropertyItemModel.h include/QmitkDataStorageListInspector.h include/QmitkAbstractDataStorageInspector.h include/QmitkDataStorageTreeInspector.h include/QmitkModelViewSelectionConnector.h ) set(UI_FILES src/QmitkFileReaderOptionsDialog.ui src/QmitkFileWriterOptionsDialog.ui src/QmitkLevelWindowPresetDefinition.ui src/QmitkLevelWindowWidget.ui src/QmitkLevelWindowRangeChange.ui src/QmitkMemoryUsageIndicator.ui src/QmitkMultiWidgetLayoutSelectionWidget.ui src/QmitkServiceListWidgetControls.ui src/QmitkDataStorageListInspector.ui src/QmitkDataStorageTreeInspector.ui ) set(QRC_FILES resource/Qmitk.qrc ) diff --git a/Modules/QtWidgets/include/QmitkAbstractMultiWidget.h b/Modules/QtWidgets/include/QmitkAbstractMultiWidget.h new file mode 100644 index 0000000000..8f63a94642 --- /dev/null +++ b/Modules/QtWidgets/include/QmitkAbstractMultiWidget.h @@ -0,0 +1,163 @@ +/*=================================================================== + +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 QMITKABSTRACTMULTIWIDGET_H +#define QMITKABSTRACTMULTIWIDGET_H + +// mitk qt widgets module +#include "MitkQtWidgetsExports.h" + +// mitk core +#include +#include + +// qt +#include + +// c++ +#include +#include + +class QmitkRenderWindow; +class QmitkRenderWindowWidget; + +namespace mitk +{ + class DataStorage; + class InteractionEventHandler; + class RenderingManager; +} + +/** +* @brief The 'QmitkAbstractMultiWidget' is a 'QWidget' that is can be subclassed to display multiple render windows at once. +* Render windows can dynamically be added and removed to change the layout of the multi widget. +* A subclass of this multi widget can be used inside an 'QmitkAbstractMultiWidgetEditor'. +*/ +class MITKQTWIDGETS_EXPORT QmitkAbstractMultiWidget : public QWidget +{ + Q_OBJECT + +public: + + using RenderWindowWidgetPointer = std::shared_ptr; + using RenderWindowWidgetMap = std::map>; + using RenderWindowHash = QHash; + + enum + { + AXIAL, + SAGITTAL, + CORONAL, + THREE_D + }; + + QmitkAbstractMultiWidget(QWidget* parent = 0, + Qt::WindowFlags f = 0, + mitk::RenderingManager* renderingManager = nullptr, + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard, + const QString& multiWidgetName = "multiwidget"); + + virtual ~QmitkAbstractMultiWidget(); + + void SetDataStorage(mitk::DataStorage* dataStorage); + mitk::DataStorage* GetDataStorage() const; + + void SetRowCount(int row); + int GetRowCount() const; + void SetColumnCount(int column); + int GetColumnCount() const; + void SetLayout(int row, int column); + void Synchronize(bool synchronized); + mitk::InteractionEventHandler* GetInteractionEventHandler(); + + RenderWindowWidgetMap GetRenderWindowWidgets() const; + RenderWindowWidgetPointer GetRenderWindowWidget(int row, int column) const; + RenderWindowWidgetPointer GetRenderWindowWidget(const QString& widgetName) const; + RenderWindowHash GetRenderWindows() const; + QmitkRenderWindow* GetRenderWindow(int row, int column) const; + QmitkRenderWindow* GetRenderWindow(const QString& widgetName) const; + + void SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget); + RenderWindowWidgetPointer GetActiveRenderWindowWidget() const; + RenderWindowWidgetPointer GetFirstRenderWindowWidget() const; + RenderWindowWidgetPointer GetLastRenderWindowWidget() const; + + void AddRenderWindowWidget(const QString& widgetName, RenderWindowWidgetPointer renderWindowWidget); + void RemoveRenderWindowWidget(); + + QString GetNameFromIndex(int row, int column) const; + QString GetNameFromIndex(size_t index) const; + + unsigned int GetNumberOfRenderWindowWidgets() const; + + void RequestUpdate(const QString& widgetName); + void RequestUpdateAll(); + void ForceImmediateUpdate(const QString& widgetName); + void ForceImmediateUpdateAll(); + + const mitk::Point3D GetSelectedPosition(const QString& widgetName) const; + +public Q_SLOTS: + + /** + * @brief Listener to the CrosshairPositionEvent + * + * Ensures the CrosshairPositionEvent is handled only once and at the end of the Qt-Event loop + */ + void HandleCrosshairPositionEvent(); + /** + * @brief Receives the signal from HandleCrosshairPositionEvent, executes the StatusBar update + * + */ + void HandleCrosshairPositionEventDelayed(); + + void SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName); + + void ResetCrosshair(); + + // mouse events + void wheelEvent(QWheelEvent* e) override; + + void mousePressEvent(QMouseEvent* e) override; + + void moveEvent(QMoveEvent* e) override; + +Q_SIGNALS: + + void WheelMoved(QWheelEvent *); + void Moved(); + +private: + + virtual void InitializeGUI() = 0; + + /** + * @brief This function will be called by the function 'SetLayout' and + * needs to be implemented and customized in the subclasses. + */ + virtual void SetLayoutImpl() = 0; + + int m_PlaneMode; + + bool m_PendingCrosshairPositionEvent; + bool m_CrosshairNavigationEnabled; + + struct Impl; + std::unique_ptr m_Impl; + +}; + +#endif // QMITKABSTRACTMULTIWIDGET_H diff --git a/Modules/QtWidgets/src/QmitkAbstractMultiWidget.cpp b/Modules/QtWidgets/src/QmitkAbstractMultiWidget.cpp new file mode 100644 index 0000000000..378b6af083 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkAbstractMultiWidget.cpp @@ -0,0 +1,562 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// mitk qt widgets module +#include "QmitkAbstractMultiWidget.h" +#include "QmitkRenderWindowWidget.h" + +// mitk core +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// qt +#include +#include +#include + +// c++ +#include + +struct QmitkAbstractMultiWidget::Impl final +{ + Impl(mitk::RenderingManager* renderingManager, + mitk::BaseRenderer::RenderingMode::Type renderingMode, + const QString& multiWidgetName); + + void SetDataStorage(mitk::DataStorage* dataStorage) + { + if (dataStorage == m_DataStorage) + { + return; + } + + m_DataStorage = dataStorage; + // set new data storage for the render window widgets + for (const auto& renderWindowWidget : m_RenderWindowWidgets) + { + renderWindowWidget.second->SetDataStorage(m_DataStorage); + } + } + + void Synchronize(bool synchronized) + { + auto allObserverTags = m_DisplayActionEventHandler->GetAllObserverTags(); + for (auto observerTag : allObserverTags) + { + m_DisplayActionEventHandler->DisconnectObserver(observerTag); + } + + if (synchronized) + { + mitk::StdFunctionCommand::ActionFunction actionFunction = mitk::DisplayActionEventFunctions::MoveCameraSynchronizedAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayMoveEvent(nullptr, mitk::Vector2D()), actionFunction); + + actionFunction = mitk::DisplayActionEventFunctions::SetCrosshairSynchronizedAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplaySetCrosshairEvent(nullptr, mitk::Point3D()), actionFunction); + + actionFunction = mitk::DisplayActionEventFunctions::ZoomCameraSynchronizedAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayZoomEvent(nullptr, 0.0, mitk::Point2D()), actionFunction); + + actionFunction = mitk::DisplayActionEventFunctions::ScrollSliceStepperSynchronizedAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayScrollEvent(nullptr, 0), actionFunction); + } + else + { + mitk::StdFunctionCommand::ActionFunction actionFunction = mitk::DisplayActionEventFunctions::MoveSenderCameraAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayMoveEvent(nullptr, mitk::Vector2D()), actionFunction); + + actionFunction = mitk::DisplayActionEventFunctions::SetCrosshairAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplaySetCrosshairEvent(nullptr, mitk::Point3D()), actionFunction); + + actionFunction = mitk::DisplayActionEventFunctions::ZoomSenderCameraAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayZoomEvent(nullptr, 0.0, mitk::Point2D()), actionFunction); + + actionFunction = mitk::DisplayActionEventFunctions::ScrollSliceStepperAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayScrollEvent(nullptr, 0), actionFunction); + } + + // use the standard 'set level window' action for both modes + mitk::StdFunctionCommand::ActionFunction actionFunction = mitk::DisplayActionEventFunctions::SetLevelWindowAction(); + m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplaySetLevelWindowEvent(nullptr, mitk::ScalarType(), mitk::ScalarType()), actionFunction); + } + + void InitializeDisplayActionEventHandling() + { + m_DisplayActionEventBroadcast = mitk::DisplayActionEventBroadcast::New(); + m_DisplayActionEventBroadcast->LoadStateMachine("DisplayInteraction.xml"); + m_DisplayActionEventBroadcast->SetEventConfig("DisplayConfigPACS.xml"); + + m_DisplayActionEventHandler = std::make_unique(); + m_DisplayActionEventHandler->SetObservableBroadcast(m_DisplayActionEventBroadcast); + + Synchronize(true); + } + + mitk::DataStorage::Pointer m_DataStorage; + + mitk::RenderingManager* m_RenderingManager; + mitk::BaseRenderer::RenderingMode::Type m_RenderingMode; + QString m_MultiWidgetName; + + RenderWindowWidgetMap m_RenderWindowWidgets; + RenderWindowWidgetPointer m_ActiveRenderWindowWidget; + + QGridLayout* m_CustomMultiWidgetLayout; + int m_MultiWidgetRows; + int m_MultiWidgetColumns; + + // interaction + mitk::DisplayActionEventBroadcast::Pointer m_DisplayActionEventBroadcast; + std::unique_ptr m_DisplayActionEventHandler; +}; + +QmitkAbstractMultiWidget::Impl::Impl(mitk::RenderingManager* renderingManager, + mitk::BaseRenderer::RenderingMode::Type renderingMode, + const QString& multiWidgetName) + : m_DataStorage(nullptr) + , m_RenderingManager(renderingManager) + , m_RenderingMode(renderingMode) + , m_MultiWidgetName(multiWidgetName) + , m_CustomMultiWidgetLayout(nullptr) + , m_MultiWidgetRows(0) + , m_MultiWidgetColumns(0) + , m_DisplayActionEventBroadcast(nullptr) + , m_DisplayActionEventHandler(nullptr) +{ + InitializeDisplayActionEventHandling(); +} + +QmitkAbstractMultiWidget::QmitkAbstractMultiWidget(QWidget* parent, + Qt::WindowFlags f/* = 0*/, + mitk::RenderingManager* renderingManager/* = nullptr*/, + mitk::BaseRenderer::RenderingMode::Type renderingMode/* = mitk::BaseRenderer::RenderingMode::Standard*/, + const QString& multiWidgetName/* = "multiwidget"*/) + : QWidget(parent, f) + , m_PlaneMode(0) + , m_PendingCrosshairPositionEvent(false) + , m_CrosshairNavigationEnabled(false) + , m_Impl(std::make_unique(renderingManager, renderingMode, multiWidgetName)) +{ + // nothing here +} + +QmitkAbstractMultiWidget::~QmitkAbstractMultiWidget() { } + +void QmitkAbstractMultiWidget::SetDataStorage(mitk::DataStorage* dataStorage) +{ + m_Impl->SetDataStorage(dataStorage); +} + +mitk::DataStorage* QmitkAbstractMultiWidget::GetDataStorage() const +{ + return m_Impl->m_DataStorage; +} + +void QmitkAbstractMultiWidget::SetRowCount(int row) +{ + m_Impl->m_MultiWidgetRows = row; +} + +int QmitkAbstractMultiWidget::GetRowCount() const +{ + return m_Impl->m_MultiWidgetRows; +} + +void QmitkAbstractMultiWidget::SetColumnCount(int column) +{ + m_Impl->m_MultiWidgetColumns = column ; +} + +int QmitkAbstractMultiWidget::GetColumnCount() const +{ + return m_Impl->m_MultiWidgetColumns; +} + +void QmitkAbstractMultiWidget::SetLayout(int row, int column) +{ + m_Impl->m_MultiWidgetRows = row; + m_Impl->m_MultiWidgetColumns = column; + + SetLayoutImpl(); +} + +void QmitkAbstractMultiWidget::Synchronize(bool synchronized) +{ + m_Impl->Synchronize(synchronized); +} + +mitk::InteractionEventHandler* QmitkAbstractMultiWidget::GetInteractionEventHandler() +{ + return m_Impl->m_DisplayActionEventBroadcast.GetPointer(); +} + +QmitkAbstractMultiWidget::RenderWindowWidgetMap QmitkAbstractMultiWidget::GetRenderWindowWidgets() const +{ + return m_Impl->m_RenderWindowWidgets; +} + +QmitkAbstractMultiWidget::RenderWindowWidgetPointer QmitkAbstractMultiWidget::GetRenderWindowWidget(int row, int column) const +{ + return GetRenderWindowWidget(GetNameFromIndex(row, column)); +} + +QmitkAbstractMultiWidget::RenderWindowWidgetPointer QmitkAbstractMultiWidget::GetRenderWindowWidget(const QString& widgetName) const +{ + RenderWindowWidgetMap::const_iterator it = m_Impl->m_RenderWindowWidgets.find(widgetName); + if (it != m_Impl->m_RenderWindowWidgets.end()) + { + return it->second; + } + + return nullptr; +} + +QmitkAbstractMultiWidget::RenderWindowHash QmitkAbstractMultiWidget::GetRenderWindows() const +{ + RenderWindowHash result; + // create QHash on demand + auto renderWindowWidgets = GetRenderWindowWidgets(); + for (const auto& renderWindowWidget : renderWindowWidgets) + { + result.insert(renderWindowWidget.first, renderWindowWidget.second->GetRenderWindow()); + } + + return result; +} + +QmitkRenderWindow* QmitkAbstractMultiWidget::GetRenderWindow(int row, int column) const +{ + return GetRenderWindow(GetNameFromIndex(row, column)); +} + +QmitkRenderWindow* QmitkAbstractMultiWidget::GetRenderWindow(const QString& widgetName) const +{ + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); + if (nullptr != renderWindowWidget) + { + return renderWindowWidget->GetRenderWindow(); + } + + return nullptr; +} + +void QmitkAbstractMultiWidget::SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget) +{ + m_Impl->m_ActiveRenderWindowWidget = activeRenderWindowWidget; +} + +QmitkAbstractMultiWidget::RenderWindowWidgetPointer QmitkAbstractMultiWidget::GetActiveRenderWindowWidget() const +{ + return m_Impl->m_ActiveRenderWindowWidget; +} + +QmitkAbstractMultiWidget::RenderWindowWidgetPointer QmitkAbstractMultiWidget::GetFirstRenderWindowWidget() const +{ + if (!m_Impl->m_RenderWindowWidgets.empty()) + { + return m_Impl->m_RenderWindowWidgets.begin()->second; + } + else + { + return nullptr; + } +} + +QmitkAbstractMultiWidget::RenderWindowWidgetPointer QmitkAbstractMultiWidget::GetLastRenderWindowWidget() const +{ + if (!m_Impl->m_RenderWindowWidgets.empty()) + { + return m_Impl->m_RenderWindowWidgets.rbegin()->second; + } + else + { + return nullptr; + } +} + +void QmitkAbstractMultiWidget::AddRenderWindowWidget(const QString& widgetName, RenderWindowWidgetPointer renderWindowWidget) +{ + m_Impl->m_RenderWindowWidgets.insert(std::make_pair(widgetName, renderWindowWidget)); +} + +void QmitkAbstractMultiWidget::RemoveRenderWindowWidget() +{ + auto iterator = m_Impl->m_RenderWindowWidgets.find(GetNameFromIndex(GetRenderWindowWidgets().size() - 1)); + if (iterator == m_Impl->m_RenderWindowWidgets.end()) + { + return; + } + + // disconnect each signal of this render window widget + QmitkRenderWindowWidget* renderWindowWidgetToRemove = iterator->second.get(); + disconnect(renderWindowWidgetToRemove, 0, 0, 0); + + // erase the render window from the map + m_Impl->m_RenderWindowWidgets.erase(iterator); +} + +QString QmitkAbstractMultiWidget::GetNameFromIndex(int row, int column) const +{ + if (0 <= row && m_Impl->m_MultiWidgetRows > row && 0 <= column && m_Impl->m_MultiWidgetColumns > column) + { + return GetNameFromIndex(row * m_Impl->m_MultiWidgetColumns + column); + } + + return QString(); +} + +QString QmitkAbstractMultiWidget::GetNameFromIndex(size_t index) const +{ + if (index <= m_Impl->m_RenderWindowWidgets.size()) + { + return m_Impl->m_MultiWidgetName + ".widget" + QString::number(index); + } + + return QString(); +} + +unsigned int QmitkAbstractMultiWidget::GetNumberOfRenderWindowWidgets() const +{ + return m_Impl->m_RenderWindowWidgets.size(); +} + +void QmitkAbstractMultiWidget::RequestUpdate(const QString& widgetName) +{ + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); + if (nullptr != renderWindowWidget) + { + return renderWindowWidget->RequestUpdate(); + } +} + +void QmitkAbstractMultiWidget::RequestUpdateAll() +{ + for (const auto& renderWindowWidget : m_Impl->m_RenderWindowWidgets) + { + renderWindowWidget.second->RequestUpdate(); + } +} + +void QmitkAbstractMultiWidget::ForceImmediateUpdate(const QString& widgetName) +{ + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); + if (nullptr != renderWindowWidget) + { + renderWindowWidget->ForceImmediateUpdate(); + } +} + +void QmitkAbstractMultiWidget::ForceImmediateUpdateAll() +{ + for (const auto& renderWindowWidget : m_Impl->m_RenderWindowWidgets) + { + renderWindowWidget.second->ForceImmediateUpdate(); + } +} + +const mitk::Point3D QmitkAbstractMultiWidget::GetSelectedPosition(const QString& widgetName) 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(); +} + +////////////////////////////////////////////////////////////////////////// +// PUBLIC SLOTS +////////////////////////////////////////////////////////////////////////// +void QmitkAbstractMultiWidget::HandleCrosshairPositionEvent() +{ + /* + if (!m_PendingCrosshairPositionEvent) + { + m_PendingCrosshairPositionEvent = true; + QTimer::singleShot(0, this, SLOT(HandleCrosshairPositionEventDelayed())); + } + */ +} + +void QmitkAbstractMultiWidget::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 QmitkAbstractMultiWidget::SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) +{ + // #TODO: check parameter and see if this should be implemented here + /* + RenderWindowWidgetPointer renderWindowWidget; + if (widgetName.isNull()) + { + renderWindowWidget = GetActiveRenderWindowWidget(); + } + else + { + renderWindowWidget = GetRenderWindowWidget(widgetName); + } + + if (nullptr != renderWindowWidget) + { + renderWindowWidget->GetSliceNavigationController()->SelectSliceByPoint(newPosition); + renderWindowWidget->RequestUpdate(); + return; + } + + MITK_ERROR << "Position can not be set for an unknown render window widget."; + */ +} + +void QmitkAbstractMultiWidget::ResetCrosshair() +{ + // #TODO: new concept: we do not want to initialize all views; + // we do not want to rely on the geometry planes + /* + if (m_DataStorage.IsNotNull()) + { + m_RenderingManager->InitializeViewsByBoundingObjects(m_DataStorage); + // m_RenderingManager->InitializeViews( m_DataStorage->ComputeVisibleBoundingGeometry3D() ); + // reset interactor to normal slicing + SetWidgetPlaneMode(PLANE_MODE_SLICING); + } + */ +} + +////////////////////////////////////////////////////////////////////////// +// MOUSE EVENTS +////////////////////////////////////////////////////////////////////////// +void QmitkAbstractMultiWidget::wheelEvent(QWheelEvent* e) +{ + emit WheelMoved(e); +} + +void QmitkAbstractMultiWidget::mousePressEvent(QMouseEvent* e) +{ + // nothing here +} + +void QmitkAbstractMultiWidget::moveEvent(QMoveEvent* e) +{ + QWidget::moveEvent(e); + + // it is necessary to readjust the position of the overlays as the MultiWidget has moved + // unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here + emit Moved(); +} diff --git a/Plugins/org.mitk.gui.qt.common/files.cmake b/Plugins/org.mitk.gui.qt.common/files.cmake index 00eee0b30e..e93dd9a7ff 100755 --- a/Plugins/org.mitk.gui.qt.common/files.cmake +++ b/Plugins/org.mitk.gui.qt.common/files.cmake @@ -1,63 +1,65 @@ set(SRC_CPP_FILES + QmitkAbstractMultiWidgetEditor.cpp QmitkAbstractRenderEditor.cpp QmitkAbstractView.cpp QmitkDataNodeSelectionProvider.cpp QmitkDnDFrameWidget.cpp QmitkSelectionServiceConnector.cpp QmitkSliceNavigationListener.cpp QmitkSingleNodeSelectionWidget.cpp QmitkNodeSelectionDialog.cpp QmitkAbstractNodeSelectionWidget.cpp QmitkMultiNodeSelectionWidget.cpp QmitkNodeSelectionPreferenceHelper.cpp QmitkNodeSelectionButton.cpp ) set(INTERNAL_CPP_FILES QmitkCommonActivator.cpp QmitkDataNodeItemModel.cpp QmitkDataNodeSelection.cpp QmitkViewCoordinator.cpp QmitkNodeSelectionConstants.cpp QmitkNodeSelectionPreferencePage.cpp ) set(UI_FILES src/QmitkSingleNodeSelectionWidget.ui src/QmitkMultiNodeSelectionWidget.ui src/QmitkNodeSelectionDialog.ui src/internal/QmitkNodeSelectionPreferencePage.ui ) set(MOC_H_FILES + src/QmitkAbstractMultiWidgetEditor.h src/QmitkAbstractRenderEditor.h src/QmitkDnDFrameWidget.h src/QmitkSelectionServiceConnector.h src/QmitkSliceNavigationListener.h src/ImporterUtil.h src/QmitkSingleNodeSelectionWidget.h src/QmitkNodeSelectionDialog.h src/QmitkAbstractNodeSelectionWidget.h src/QmitkMultiNodeSelectionWidget.h src/QmitkNodeSelectionButton.h src/internal/QmitkCommonActivator.h src/internal/QmitkNodeSelectionPreferencePage.h ) set(CACHED_RESOURCE_FILES plugin.xml resources/times.svg ) set(QRC_FILES ) set(CPP_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.common/src/QmitkAbstractMultiWidgetEditor.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractMultiWidgetEditor.cpp new file mode 100644 index 0000000000..b9305792dc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractMultiWidgetEditor.cpp @@ -0,0 +1,198 @@ +/*=================================================================== + +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 "QmitkAbstractMultiWidgetEditor.h" + +#include + +// mitk qt widgets module +#include +#include + +// custom multi widget editor plugin +//#include "QmitkMultiWidgetDecorationManager.h" + +struct QmitkAbstractMultiWidgetEditor::Impl final +{ + Impl(); + + QmitkAbstractMultiWidget* m_MultiWidget; + + //std::unique_ptr m_MultiWidgetDecorationManager; +}; + +QmitkAbstractMultiWidgetEditor::Impl::Impl() + : m_MultiWidget(nullptr) +{ + // nothing here +} + +QmitkAbstractMultiWidgetEditor::QmitkAbstractMultiWidgetEditor() + : m_Impl(std::make_unique()) +{ + // nothing here +} + +QmitkAbstractMultiWidgetEditor::~QmitkAbstractMultiWidgetEditor() {} + +QmitkRenderWindow* QmitkAbstractMultiWidgetEditor::GetActiveQmitkRenderWindow() const +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) + { + auto activeRenderWindowWidget = multiWidget->GetActiveRenderWindowWidget(); + if (nullptr != activeRenderWindowWidget) + { + return activeRenderWindowWidget->GetRenderWindow(); + } + } + + return nullptr; +} + +QHash QmitkAbstractMultiWidgetEditor::GetQmitkRenderWindows() const +{ + QHash result; + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) + { + return result; + } + + result = multiWidget->GetRenderWindows(); + return result; +} + +QmitkRenderWindow* QmitkAbstractMultiWidgetEditor::GetQmitkRenderWindow(const QString& id) const +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) + { + return nullptr; + } + + return multiWidget->GetRenderWindow(id); +} + +mitk::Point3D QmitkAbstractMultiWidgetEditor::GetSelectedPosition(const QString& id/* = QString()*/) const +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) + { + return mitk::Point3D(); + } + + return multiWidget->GetSelectedPosition(id); +} + +void QmitkAbstractMultiWidgetEditor::SetSelectedPosition(const mitk::Point3D& pos, const QString& id/* = QString()*/) +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) + { + return multiWidget->SetSelectedPosition(pos, id); + } +} + +void QmitkAbstractMultiWidgetEditor::EnableDecorations(bool enable, const QStringList& decorations) +{ + //m_Impl->m_MultiWidgetDecorationManager->ShowDecorations(enable, decorations); +} + +bool QmitkAbstractMultiWidgetEditor::IsDecorationEnabled(const QString& decoration) const +{ + return false;// m_Impl->m_MultiWidgetDecorationManager->IsDecorationVisible(decoration); +} + +QStringList QmitkAbstractMultiWidgetEditor::GetDecorations() const +{ + return QStringList();// m_Impl->m_MultiWidgetDecorationManager->GetDecorations(); +} + +QmitkRenderWindow* QmitkAbstractMultiWidgetEditor::GetQmitkRenderWindowByIndex(int index) const +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) + { + return nullptr; + } + + QString renderWindowName = multiWidget->GetNameFromIndex(index); + return multiWidget->GetRenderWindow(renderWindowName); +} + +QmitkRenderWindow* QmitkAbstractMultiWidgetEditor::GetQmitkRenderWindowByIndex(int row, int column) const +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) + { + return nullptr; + } + + QString renderWindowName = multiWidget->GetNameFromIndex(row, column); + return multiWidget->GetRenderWindow(renderWindowName); +} + +void QmitkAbstractMultiWidgetEditor::SetMultiWidget(QmitkAbstractMultiWidget* multiWidget) +{ + m_Impl->m_MultiWidget = multiWidget; +} + +QmitkAbstractMultiWidget* QmitkAbstractMultiWidgetEditor::GetMultiWidget() const +{ + return m_Impl->m_MultiWidget; +} + +int QmitkAbstractMultiWidgetEditor::GetRowCount() const +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) + { + return 0; + } + + return multiWidget->GetRowCount(); +} + +int QmitkAbstractMultiWidgetEditor::GetColumnCount() const +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) + { + return 0; + } + + return multiWidget->GetColumnCount(); +} + +void QmitkAbstractMultiWidgetEditor::OnLayoutChanged(int row, int column) +{ + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) + { + multiWidget->SetLayout(row, column); + FirePropertyChange(berry::IWorkbenchPartConstants::PROP_INPUT); + } +} + + void QmitkAbstractMultiWidgetEditor::OnSynchronize(bool synchronized) + { + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) + { + multiWidget->Synchronize(synchronized); + } + } diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractMultiWidgetEditor.h b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractMultiWidgetEditor.h new file mode 100644 index 0000000000..fcca50fc2c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractMultiWidgetEditor.h @@ -0,0 +1,113 @@ +/*=================================================================== + +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 QMITKABSTRACTMULTIWIDGETEDITOR_H +#define QMITKABSTRACTMULTIWIDGETEDITOR_H + +#include + +// org mitk gui qt common plugin +#include + +// c++ +#include + +class QmitkAbstractMultiWidget; + +class MITK_QT_COMMON QmitkAbstractMultiWidgetEditor : public QmitkAbstractRenderEditor +{ + Q_OBJECT + +public: + + QmitkAbstractMultiWidgetEditor(); + virtual ~QmitkAbstractMultiWidgetEditor() override; + + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + virtual QmitkRenderWindow* GetActiveQmitkRenderWindow() const override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + virtual QHash GetQmitkRenderWindows() const override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + virtual QmitkRenderWindow* GetQmitkRenderWindow(const QString& id) const override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + mitk::Point3D GetSelectedPosition(const QString& id = QString()) const override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + void SetSelectedPosition(const mitk::Point3D& pos, const QString& id = QString()) override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + virtual void EnableDecorations(bool enable, const QStringList& decorations = QStringList()) override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + virtual bool IsDecorationEnabled(const QString& decoration) const override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + virtual QStringList GetDecorations() const override; + /** + * @brief Retrieve a QmitkRenderWindow by it's index. + */ + virtual QmitkRenderWindow* GetQmitkRenderWindowByIndex(int index) const; + /** + * @brief Retrieve a QmitkRenderWindow by the row and column position. + */ + virtual QmitkRenderWindow* GetQmitkRenderWindowByIndex(int row, int column) const; + /** + * @brief Set the current multi widget of this editor. + */ + virtual void SetMultiWidget(QmitkAbstractMultiWidget* multiWidget); + /** + * @brief Return the current multi widget of this editor. + */ + virtual QmitkAbstractMultiWidget* GetMultiWidget() const; + /** + * @brief Return the number of rows of the underlying multi widget. + */ + virtual int GetRowCount() const; + /** + * @brief Return the number of columns of the underlying multi widget. + */ + virtual int GetColumnCount() const; + +public Q_SLOTS: + /** + * @brief A slot that can be called if the layout has been changed. + * This function will call the private virtual function 'LayoutChanged' where + * custom behavior can be implemented by subclasses. + * Finally 'FirePropertyChange' is called to inform the workbench about an input change. + */ + void OnLayoutChanged(int row, int column); + void OnSynchronize(bool synchronized); + +private: + + struct Impl; + std::unique_ptr m_Impl; + +}; + +#endif // QMITKABSTRACTMULTIWIDGETEDITOR_H