diff --git a/Modules/QtWidgets/include/QmitkCustomMultiWidget.h b/Modules/QtWidgets/include/QmitkCustomMultiWidget.h index 05d162ef32..89cafac7bd 100644 --- a/Modules/QtWidgets/include/QmitkCustomMultiWidget.h +++ b/Modules/QtWidgets/include/QmitkCustomMultiWidget.h @@ -1,171 +1,174 @@ /*=================================================================== 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 #include // qt #include class QHBoxLayout; class QVBoxLayout; class QGridLayout; class QSpacerItem; class QmitkLevelWindowWidget; class QmitkRenderWindow; 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: + using RenderWindowWidgetPointer = std::shared_ptr; + using RenderWindowWidgetMap = std::map>; + using RenderWindowHash = QHash; + QmitkCustomMultiWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, mitk::RenderingManager* renderingManager = nullptr, mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard, const QString& multiWidgetName = "custommulti"); virtual ~QmitkCustomMultiWidget(); void SetDataStorage(mitk::DataStorage* dataStorage); void InitializeRenderWindowWidgets(); mitk::InteractionEventHandler::Pointer GetInteractionEventHandler() { return m_DisplayActionEventBroadcast.GetPointer(); }; void ResetLayout(int row, int column); void Synchronize(bool synchronized); - using RenderWindowWidgetMap = std::map>; - using RenderWindowHash = QHash; RenderWindowWidgetMap GetRenderWindowWidgets() const; - std::shared_ptr GetRenderWindowWidget(const QString& widgetID) const; + RenderWindowWidgetPointer GetRenderWindowWidget(const QString& widgetID) const; QString CreateRenderWindowWidget(const std::string& cornerAnnotation = ""); void AddToMultiWidgetLayout(int row, int column, const QString& widgetID); void RemoveRenderWindowWidget(const QString& widgetID); QmitkRenderWindow* GetRenderWindow(const QString& widgetID) const; - std::shared_ptr GetActiveRenderWindowWidget() const; - std::shared_ptr GetFirstRenderWindowWidget() const; - std::shared_ptr GetLastRenderWindowWidget() const; + void SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget); + RenderWindowWidgetPointer GetActiveRenderWindowWidget() const; + RenderWindowWidgetPointer GetFirstRenderWindowWidget() const; + RenderWindowWidgetPointer GetLastRenderWindowWidget() const; unsigned int GetNumberOfRenderWindowWidgets() const; void RequestUpdate(const QString& widgetID); void RequestUpdateAll(); void ForceImmediateUpdate(const QString& widgetID); void ForceImmediateUpdateAll(); const mitk::Point3D GetCrossPosition(const QString& widgetID) const; public slots: void ShowLevelWindowWidget(const QString& widgetID, bool show); void ShowAllLevelWindowWidgets(bool show); /** * @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 MoveCrossToPosition(const QString& widgetID, const mitk::Point3D& newPosition); void ResetCrosshair(); // mouse events void wheelEvent(QWheelEvent* e) override; void mousePressEvent(QMouseEvent* e) override; void moveEvent(QMoveEvent* e) override; signals: void WheelMoved(QWheelEvent *); void Moved(); public: enum { AXIAL, SAGITTAL, CORONAL, THREE_D }; private: void InitializeGUI(); void InitializeWidget(); void InitializeDisplayActionEventHandling(); void FillLayout(int row, int column); // #TODO: see T24173 mitk::DataNode::Pointer GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes); QGridLayout* m_CustomMultiWidgetLayout; RenderWindowWidgetMap m_RenderWindowWidgets; - QmitkRenderWindowWidget* m_ActiveRenderWindowWidget; + RenderWindowWidgetPointer m_ActiveRenderWindowWidget; int m_PlaneMode; mitk::RenderingManager* m_RenderingManager; mitk::BaseRenderer::RenderingMode::Type m_RenderingMode; QString m_MultiWidgetName; mitk::DisplayActionEventBroadcast::Pointer m_DisplayActionEventBroadcast; std::unique_ptr m_DisplayActionEventHandler; mitk::DataStorage::Pointer m_DataStorage; bool m_PendingCrosshairPositionEvent; bool m_CrosshairNavigationEnabled; }; #endif // QMITKCUSTOMMULTIWIDGET_H diff --git a/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp b/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp index 5fd62ccd7e..c5f81c7fd6 100644 --- a/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp +++ b/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp @@ -1,564 +1,569 @@ /*=================================================================== 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 "QmitkCustomMultiWidget.h" #include #include #include #include // mitk core #include #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/* = 0*/, mitk::RenderingManager* renderingManager/* = nullptr*/, mitk::BaseRenderer::RenderingMode::Type renderingMode/* = mitk::BaseRenderer::RenderingMode::Standard*/, const QString& multiWidgetName/* = "custommulti"*/) : QWidget(parent, f) , m_CustomMultiWidgetLayout(nullptr) , m_RenderingManager(renderingManager) , m_RenderingMode(renderingMode) , m_MultiWidgetName(multiWidgetName) , m_PendingCrosshairPositionEvent(false) , m_CrosshairNavigationEnabled(false) , m_DisplayActionEventBroadcast(nullptr) , m_DisplayActionEventHandler(nullptr) , m_DataStorage(nullptr) { // create widget manually // create and set layout InitializeGUI(); InitializeWidget(); InitializeDisplayActionEventHandling(); resize(QSize(364, 477).expandedTo(minimumSizeHint())); } QmitkCustomMultiWidget::~QmitkCustomMultiWidget() { // nothing here } void QmitkCustomMultiWidget::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 QmitkCustomMultiWidget::InitializeRenderWindowWidgets() { // create render window (widgets) initially //QString UID = CreateRenderWindowWidget("2015-01-14 - CT"); //AddToMultiWidgetLayout(0, 0, UID); /* AddRenderWindowWidget(0, 1, "2015-08-19 - CT"); AddRenderWindowWidget(0, 2, "2016-06-29 - CT"); AddRenderWindowWidget(1, 0, "2015-01-14 - MR"); AddRenderWindowWidget(1, 1, "2015-08-19 - MR"); AddRenderWindowWidget(1, 2, "2016-06-29 - MR"); */ } void QmitkCustomMultiWidget::ResetLayout(int row, int column) { int neededRenderWindowWidgets = (row + 1) * (column + 1); int existingRenderWindowWidgets = m_RenderWindowWidgets.size(); int difference = neededRenderWindowWidgets - existingRenderWindowWidgets; while(0 < difference) { // more render window widgets needed CreateRenderWindowWidget(); --difference; } while(0 > difference) { // less render window widgets needed RemoveRenderWindowWidget(m_RenderWindowWidgets.rbegin()->first); ++difference; } InitializeGUI(); if (0 == difference) { FillLayout(row, column); } } void QmitkCustomMultiWidget::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); } QmitkCustomMultiWidget::RenderWindowWidgetMap QmitkCustomMultiWidget::GetRenderWindowWidgets() const { return m_RenderWindowWidgets; } -std::shared_ptr QmitkCustomMultiWidget::GetRenderWindowWidget(const QString& widgetID) const +QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetRenderWindowWidget(const QString& widgetID) const { RenderWindowWidgetMap::const_iterator it = m_RenderWindowWidgets.find(widgetID); if (it == m_RenderWindowWidgets.end()) { return nullptr; } return it->second; } QString QmitkCustomMultiWidget::CreateRenderWindowWidget(const std::string& cornerAnnotation/* = ""*/) { // create the render window widget and connect signals / slots mitk::UIDGenerator generator; std::string renderWindowUID = generator.GetUID(); QString UID = m_MultiWidgetName + "_" + QString::fromStdString(renderWindowUID); - std::shared_ptr renderWindowWidget = std::make_shared(this, UID, m_DataStorage); + RenderWindowWidgetPointer renderWindowWidget = std::make_shared(this, UID, m_DataStorage); renderWindowWidget->SetCornerAnnotationText(cornerAnnotation); // store the newly created render window widget with the UID m_RenderWindowWidgets.insert(std::make_pair(UID, renderWindowWidget)); return UID; } void QmitkCustomMultiWidget::AddToMultiWidgetLayout(int row, int column, const QString& widgetID) { - std::shared_ptr renderWindowWidget = GetRenderWindowWidget(widgetID); + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { m_CustomMultiWidgetLayout->addWidget(renderWindowWidget.get(), row, column); + SetActiveRenderWindowWidget(renderWindowWidget); } } void QmitkCustomMultiWidget::RemoveRenderWindowWidget(const QString& widgetID) { auto iterator = m_RenderWindowWidgets.find(widgetID); if (iterator == m_RenderWindowWidgets.end()) { return; } - std::shared_ptr renderWindowWidgetToRemove = iterator->second; + RenderWindowWidgetPointer renderWindowWidgetToRemove = iterator->second; disconnect(renderWindowWidgetToRemove.get(), 0, 0, 0); // erase the render window from the map m_RenderWindowWidgets.erase(iterator); // remove from layout // #TODO } QmitkRenderWindow* QmitkCustomMultiWidget::GetRenderWindow(const QString& widgetID) const { - std::shared_ptr renderWindowWidget = GetRenderWindowWidget(widgetID); + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->GetRenderWindow(); } return nullptr; } -std::shared_ptr QmitkCustomMultiWidget::GetActiveRenderWindowWidget() const +void QmitkCustomMultiWidget::SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget) { - //return m_ActiveRenderWindowWidget; - return m_RenderWindowWidgets.begin()->second; + m_ActiveRenderWindowWidget = activeRenderWindowWidget; } -std::shared_ptr QmitkCustomMultiWidget::GetFirstRenderWindowWidget() const +QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetActiveRenderWindowWidget() const +{ + return m_ActiveRenderWindowWidget; +} + +QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetFirstRenderWindowWidget() const { if (!m_RenderWindowWidgets.empty()) { return m_RenderWindowWidgets.begin()->second; } else { return nullptr; } } -std::shared_ptr QmitkCustomMultiWidget::GetLastRenderWindowWidget() const +QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetLastRenderWindowWidget() const { if (!m_RenderWindowWidgets.empty()) { return m_RenderWindowWidgets.rbegin()->second; } else { return nullptr; } } unsigned int QmitkCustomMultiWidget::GetNumberOfRenderWindowWidgets() const { return m_RenderWindowWidgets.size(); } void QmitkCustomMultiWidget::RequestUpdate(const QString& widgetID) { - std::shared_ptr renderWindowWidget = GetRenderWindowWidget(widgetID); + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->RequestUpdate(); } } void QmitkCustomMultiWidget::RequestUpdateAll() { for (const auto& renderWindowWidget : m_RenderWindowWidgets) { renderWindowWidget.second->RequestUpdate(); } } void QmitkCustomMultiWidget::ForceImmediateUpdate(const QString& widgetID) { - std::shared_ptr renderWindowWidget = GetRenderWindowWidget(widgetID); + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->ForceImmediateUpdate(); } } void QmitkCustomMultiWidget::ForceImmediateUpdateAll() { for (const auto& renderWindowWidget : m_RenderWindowWidgets) { renderWindowWidget.second->ForceImmediateUpdate(); } } const mitk::Point3D QmitkCustomMultiWidget::GetCrossPosition(const QString& widgetID) 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 QmitkCustomMultiWidget::ShowLevelWindowWidget(const QString& widgetID, bool show) { - std::shared_ptr renderWindowWidget = GetRenderWindowWidget(widgetID); + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->ShowLevelWindowWidget(show); return; } MITK_ERROR << "Level window widget can not be shown for an unknown widget."; } void QmitkCustomMultiWidget::ShowAllLevelWindowWidgets(bool show) { for (const auto& renderWindowWidget : m_RenderWindowWidgets) { renderWindowWidget.second->ShowLevelWindowWidget(show); } } void QmitkCustomMultiWidget::HandleCrosshairPositionEvent() { /* if (!m_PendingCrosshairPositionEvent) { m_PendingCrosshairPositionEvent = true; QTimer::singleShot(0, this, SLOT(HandleCrosshairPositionEventDelayed())); } */ } 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::MoveCrossToPosition(const QString& widgetID, const mitk::Point3D& newPosition) { - std::shared_ptr renderWindowWidget = GetRenderWindowWidget(widgetID); + RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->GetSliceNavigationController()->SelectSliceByPoint(newPosition); renderWindowWidget->RequestUpdate(); return; } MITK_ERROR << "Geometry plane can not be shown for an unknown widget."; } void QmitkCustomMultiWidget::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 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 MultiWidget has moved // unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here emit Moved(); } ////////////////////////////////////////////////////////////////////////// // PRIVATE ////////////////////////////////////////////////////////////////////////// void QmitkCustomMultiWidget::InitializeGUI() { delete m_CustomMultiWidgetLayout; m_CustomMultiWidgetLayout = new QGridLayout(this); m_CustomMultiWidgetLayout->setContentsMargins(0, 0, 0, 0); setLayout(m_CustomMultiWidgetLayout); } 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 + // analyze those things and design a controlling mechanism } void QmitkCustomMultiWidget::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); } void QmitkCustomMultiWidget::FillLayout(int row, int column) { int r = 0; int c = 0; for (const auto& renderWindowWidget : m_RenderWindowWidgets) { AddToMultiWidgetLayout(r, c, renderWindowWidget.first); c += 1; if (c > column) { // first column c = 0; // next row r += 1; if (r > row) { return; } } } } mitk::DataNode::Pointer QmitkCustomMultiWidget::GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes) { // #TODO: see T24173 return nodes->front(); } diff --git a/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp b/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp index 2fd94fc0fa..41fa5e69e2 100644 --- a/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp +++ b/Modules/QtWidgets/src/QmitkRenderWindowMenu.cpp @@ -1,1019 +1,1019 @@ /*=================================================================== 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 "QmitkRenderWindowMenu.h" #include "mitkProperties.h" #include "mitkResliceMethodProperty.h" #include #include #include #include - +#include #include #include #include #include #include #include #include #include "QmitkStdMultiWidget.h" //#include"iconClose.xpm" #include "iconCrosshairMode.xpm" #include "iconFullScreen.xpm" //#include"iconHoriSplit.xpm" #include "iconSettings.xpm" //#include"iconVertiSplit.xpm" #include "iconLeaveFullScreen.xpm" #include #ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU QmitkRenderWindowMenu::QmitkRenderWindowMenu(QWidget *parent, Qt::WindowFlags f, mitk::BaseRenderer *b, QmitkStdMultiWidget *mw) : QWidget(nullptr, Qt::Tool | Qt::FramelessWindowHint), #else QmitkRenderWindowMenu::QmitkRenderWindowMenu(QWidget *parent, Qt::WindowFlags f, mitk::BaseRenderer *b, QmitkStdMultiWidget *mw) : QWidget(parent, f), #endif m_Settings(nullptr), m_CrosshairMenu(nullptr), m_Layout(0), m_LayoutDesign(0), m_OldLayoutDesign(0), m_FullScreenMode(false), m_Entered(false), m_Renderer(b), m_MultiWidget(mw), m_Parent(parent) { MITK_DEBUG << "creating renderwindow menu on baserenderer " << b; // Create Menu Widget this->CreateMenuWidget(); this->setMinimumWidth(61); // DIRTY.. If you add or remove a button, you need to change the size. this->setMaximumWidth(61); this->setAutoFillBackground(true); // Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows // for Mac OS see bug 3192 // for Windows see bug 12130 //... so Mac OS and Windows must be treated differently: #if defined(Q_OS_MAC) this->show(); this->setWindowOpacity(0.0f); #else this->setVisible(false); #endif // this->setAttribute( Qt::WA_NoSystemBackground ); // this->setBackgroundRole( QPalette::Dark ); // this->update(); // SetOpacity -- its just posible if the widget is a window. // Windows indicates that the widget is a window, usually with a window system frame and a title bar, // irrespective of whether the widget has a parent or not. /* this->setWindowFlags( Qt::Window | Qt::FramelessWindowHint); */ // this->setAttribute(Qt::WA_TranslucentBackground); // this->setWindowOpacity(0.75); currentCrosshairRotationMode = 0; // for autorotating m_AutoRotationTimer.setInterval(75); connect(&m_AutoRotationTimer, SIGNAL(timeout()), this, SLOT(AutoRotateNextStep())); m_HideTimer.setSingleShot(true); connect(&m_HideTimer, SIGNAL(timeout()), this, SLOT(DeferredHideMenu())); connect(m_Parent, SIGNAL(destroyed()), this, SLOT(deleteLater())); } QmitkRenderWindowMenu::~QmitkRenderWindowMenu() { if (m_AutoRotationTimer.isActive()) m_AutoRotationTimer.stop(); } void QmitkRenderWindowMenu::CreateMenuWidget() { QHBoxLayout *layout = new QHBoxLayout(this); layout->setAlignment(Qt::AlignRight); layout->setContentsMargins(1, 1, 1, 1); QSize size(13, 13); m_CrosshairMenu = new QMenu(this); connect(m_CrosshairMenu, SIGNAL(aboutToShow()), this, SLOT(OnCrossHairMenuAboutToShow())); // button for changing rotation mode m_CrosshairModeButton = new QToolButton(this); m_CrosshairModeButton->setMaximumSize(15, 15); m_CrosshairModeButton->setIconSize(size); m_CrosshairModeButton->setMenu(m_CrosshairMenu); m_CrosshairModeButton->setIcon(QIcon(QPixmap(iconCrosshairMode_xpm))); m_CrosshairModeButton->setPopupMode(QToolButton::InstantPopup); m_CrosshairModeButton->setStyleSheet("QToolButton::menu-indicator { image: none; }"); m_CrosshairModeButton->setAutoRaise(true); layout->addWidget(m_CrosshairModeButton); // fullScreenButton m_FullScreenButton = new QToolButton(this); m_FullScreenButton->setMaximumSize(15, 15); m_FullScreenButton->setIconSize(size); m_FullScreenButton->setIcon(QIcon(QPixmap(iconFullScreen_xpm))); m_FullScreenButton->setAutoRaise(true); layout->addWidget(m_FullScreenButton); // settingsButton m_SettingsButton = new QToolButton(this); m_SettingsButton->setMaximumSize(15, 15); m_SettingsButton->setIconSize(size); m_SettingsButton->setIcon(QIcon(QPixmap(iconSettings_xpm))); m_SettingsButton->setAutoRaise(true); layout->addWidget(m_SettingsButton); // Create Connections -- coming soon? connect(m_FullScreenButton, SIGNAL(clicked(bool)), this, SLOT(OnFullScreenButton(bool))); connect(m_SettingsButton, SIGNAL(clicked(bool)), this, SLOT(OnSettingsButton(bool))); } void QmitkRenderWindowMenu::CreateSettingsWidget() { m_Settings = new QMenu(this); m_DefaultLayoutAction = new QAction("standard layout", m_Settings); m_DefaultLayoutAction->setDisabled(true); m_2DImagesUpLayoutAction = new QAction("2D images top, 3D bottom", m_Settings); m_2DImagesUpLayoutAction->setDisabled(false); m_2DImagesLeftLayoutAction = new QAction("2D images left, 3D right", m_Settings); m_2DImagesLeftLayoutAction->setDisabled(false); m_Big3DLayoutAction = new QAction("Big 3D", m_Settings); m_Big3DLayoutAction->setDisabled(false); m_Widget1LayoutAction = new QAction("Axial plane", m_Settings); m_Widget1LayoutAction->setDisabled(false); m_Widget2LayoutAction = new QAction("Sagittal plane", m_Settings); m_Widget2LayoutAction->setDisabled(false); m_Widget3LayoutAction = new QAction("Coronal plane", m_Settings); m_Widget3LayoutAction->setDisabled(false); m_RowWidget3And4LayoutAction = new QAction("Coronal top, 3D bottom", m_Settings); m_RowWidget3And4LayoutAction->setDisabled(false); m_ColumnWidget3And4LayoutAction = new QAction("Coronal left, 3D right", m_Settings); m_ColumnWidget3And4LayoutAction->setDisabled(false); m_SmallUpperWidget2Big3and4LayoutAction = new QAction("Sagittal top, Coronal n 3D bottom", m_Settings); m_SmallUpperWidget2Big3and4LayoutAction->setDisabled(false); m_2x2Dand3DWidgetLayoutAction = new QAction("Axial n Sagittal left, 3D right", m_Settings); m_2x2Dand3DWidgetLayoutAction->setDisabled(false); m_Left2Dand3DRight2DLayoutAction = new QAction("Axial n 3D left, Sagittal right", m_Settings); m_Left2Dand3DRight2DLayoutAction->setDisabled(false); m_Settings->addAction(m_DefaultLayoutAction); m_Settings->addAction(m_2DImagesUpLayoutAction); m_Settings->addAction(m_2DImagesLeftLayoutAction); m_Settings->addAction(m_Big3DLayoutAction); m_Settings->addAction(m_Widget1LayoutAction); m_Settings->addAction(m_Widget2LayoutAction); m_Settings->addAction(m_Widget3LayoutAction); m_Settings->addAction(m_RowWidget3And4LayoutAction); m_Settings->addAction(m_ColumnWidget3And4LayoutAction); m_Settings->addAction(m_SmallUpperWidget2Big3and4LayoutAction); m_Settings->addAction(m_2x2Dand3DWidgetLayoutAction); m_Settings->addAction(m_Left2Dand3DRight2DLayoutAction); m_Settings->setVisible(false); connect(m_DefaultLayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToDefault(bool))); connect(m_2DImagesUpLayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutTo2DImagesUp(bool))); connect(m_2DImagesLeftLayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutTo2DImagesLeft(bool))); connect(m_Big3DLayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToBig3D(bool))); connect(m_Widget1LayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToWidget1(bool))); connect(m_Widget2LayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToWidget2(bool))); connect(m_Widget3LayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToWidget3(bool))); connect(m_RowWidget3And4LayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToRowWidget3And4(bool))); connect( m_ColumnWidget3And4LayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToColumnWidget3And4(bool))); connect(m_SmallUpperWidget2Big3and4LayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToSmallUpperWidget2Big3and4(bool))); connect(m_2x2Dand3DWidgetLayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutTo2x2Dand3DWidget(bool))); connect( m_Left2Dand3DRight2DLayoutAction, SIGNAL(triggered(bool)), this, SLOT(OnChangeLayoutToLeft2Dand3DRight2D(bool))); } void QmitkRenderWindowMenu::paintEvent(QPaintEvent * /*e*/) { QPainter painter(this); QColor semiTransparentColor = Qt::black; semiTransparentColor.setAlpha(255); painter.fillRect(rect(), semiTransparentColor); } void QmitkRenderWindowMenu::SetLayoutIndex(unsigned int layoutIndex) { m_Layout = layoutIndex; } void QmitkRenderWindowMenu::HideMenu() { MITK_DEBUG << "menu hideEvent"; DeferredHideMenu(); } void QmitkRenderWindowMenu::ShowMenu() { MITK_DEBUG << "menu showMenu"; DeferredShowMenu(); } void QmitkRenderWindowMenu::enterEvent(QEvent * /*e*/) { MITK_DEBUG << "menu enterEvent"; DeferredShowMenu(); m_Entered = true; } void QmitkRenderWindowMenu::DeferredHideMenu() { MITK_DEBUG << "menu deferredhidemenu"; // Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows // for Mac OS see bug 3192 // for Windows see bug 12130 //... so Mac OS and Windows must be treated differently: #if defined(Q_OS_MAC) this->setWindowOpacity(0.0f); #else this->setVisible(false); #endif // setVisible(false); // setWindowOpacity(0.0f); /// hide(); } void QmitkRenderWindowMenu::leaveEvent(QEvent * /*e*/) { MITK_DEBUG << "menu leaveEvent"; m_Entered = false; smoothHide(); } /* This method is responsible for non fluttering of the renderWindowMenu when mouse cursor moves along the renderWindowMenu*/ void QmitkRenderWindowMenu::smoothHide() { MITK_DEBUG << "menu leaveEvent"; m_HideTimer.start(10); } void QmitkRenderWindowMenu::ChangeFullScreenMode(bool state) { this->OnFullScreenButton(state); } /// \brief void QmitkRenderWindowMenu::OnFullScreenButton(bool /*checked*/) { if (!m_FullScreenMode) { m_FullScreenMode = true; m_OldLayoutDesign = m_LayoutDesign; switch (m_Layout) { case AXIAL: { emit SignalChangeLayoutDesign(LAYOUT_AXIAL); break; } case SAGITTAL: { emit SignalChangeLayoutDesign(LAYOUT_SAGITTAL); break; } case CORONAL: { emit SignalChangeLayoutDesign(LAYOUT_CORONAL); break; } case THREE_D: { emit SignalChangeLayoutDesign(LAYOUT_BIG3D); break; } } // Move Widget and show again this->MoveWidgetToCorrectPos(1.0f); // change icon this->ChangeFullScreenIcon(); } else { m_FullScreenMode = false; emit SignalChangeLayoutDesign(m_OldLayoutDesign); // Move Widget and show again this->MoveWidgetToCorrectPos(1.0f); // change icon this->ChangeFullScreenIcon(); } DeferredShowMenu(); } /// \brief void QmitkRenderWindowMenu::OnSettingsButton(bool /*checked*/) { if (m_Settings == nullptr) this->CreateSettingsWidget(); QPoint point = this->mapToGlobal(m_SettingsButton->geometry().topLeft()); m_Settings->setVisible(true); m_Settings->exec(point); } void QmitkRenderWindowMenu::OnChangeLayoutTo2DImagesUp(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_2DIMAGEUP; emit SignalChangeLayoutDesign(LAYOUT_2DIMAGEUP); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutTo2DImagesLeft(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_2DIMAGELEFT; emit SignalChangeLayoutDesign(LAYOUT_2DIMAGELEFT); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToDefault(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_DEFAULT; emit SignalChangeLayoutDesign(LAYOUT_DEFAULT); DeferredShowMenu(); } void QmitkRenderWindowMenu::DeferredShowMenu() { MITK_DEBUG << "deferred show menu"; m_HideTimer.stop(); // Else part fixes the render window menu issue on Linux bug but caused bugs on Mac OS and Windows // for Mac OS see bug 3192 // for Windows see bug 12130 //... so Mac OS and Windows must be treated differently: #if defined(Q_OS_MAC) this->setWindowOpacity(1.0f); #else this->setVisible(true); this->raise(); #endif } void QmitkRenderWindowMenu::OnChangeLayoutToBig3D(bool) { MITK_DEBUG << "OnChangeLayoutToBig3D"; // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_BIG3D; emit SignalChangeLayoutDesign(LAYOUT_BIG3D); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToWidget1(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_AXIAL; emit SignalChangeLayoutDesign(LAYOUT_AXIAL); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToWidget2(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_SAGITTAL; emit SignalChangeLayoutDesign(LAYOUT_SAGITTAL); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToWidget3(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_CORONAL; emit SignalChangeLayoutDesign(LAYOUT_CORONAL); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToRowWidget3And4(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_ROWWIDGET3AND4; emit SignalChangeLayoutDesign(LAYOUT_ROWWIDGET3AND4); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToColumnWidget3And4(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_COLUMNWIDGET3AND4; emit SignalChangeLayoutDesign(LAYOUT_COLUMNWIDGET3AND4); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToSmallUpperWidget2Big3and4(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_SMALLUPPERWIDGET2BIGAND4; emit SignalChangeLayoutDesign(LAYOUT_SMALLUPPERWIDGET2BIGAND4); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutTo2x2Dand3DWidget(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_2X2DAND3DWIDGET; emit SignalChangeLayoutDesign(LAYOUT_2X2DAND3DWIDGET); DeferredShowMenu(); } void QmitkRenderWindowMenu::OnChangeLayoutToLeft2Dand3DRight2D(bool) { // set Full Screen Mode to false, if Layout Design was changed by the LayoutDesign_List m_FullScreenMode = false; this->ChangeFullScreenIcon(); m_LayoutDesign = LAYOUT_LEFT2DAND3DRIGHT2D; emit SignalChangeLayoutDesign(LAYOUT_LEFT2DAND3DRIGHT2D); DeferredShowMenu(); } void QmitkRenderWindowMenu::UpdateLayoutDesignList(int layoutDesignIndex) { m_LayoutDesign = layoutDesignIndex; if (m_Settings == nullptr) this->CreateSettingsWidget(); switch (m_LayoutDesign) { case LAYOUT_DEFAULT: { m_DefaultLayoutAction->setEnabled(false); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_2DIMAGEUP: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(false); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_2DIMAGELEFT: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(false); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_BIG3D: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(false); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_AXIAL: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(false); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_SAGITTAL: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(false); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_CORONAL: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(false); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_2X2DAND3DWIDGET: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(false); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_ROWWIDGET3AND4: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(false); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_COLUMNWIDGET3AND4: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(false); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_SMALLUPPERWIDGET2BIGAND4: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(false); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(true); break; } case LAYOUT_LEFT2DAND3DRIGHT2D: { m_DefaultLayoutAction->setEnabled(true); m_2DImagesUpLayoutAction->setEnabled(true); m_2DImagesLeftLayoutAction->setEnabled(true); m_Big3DLayoutAction->setEnabled(true); m_Widget1LayoutAction->setEnabled(true); m_Widget2LayoutAction->setEnabled(true); m_Widget3LayoutAction->setEnabled(true); m_RowWidget3And4LayoutAction->setEnabled(true); m_ColumnWidget3And4LayoutAction->setEnabled(true); m_SmallUpperWidget2Big3and4LayoutAction->setEnabled(true); m_2x2Dand3DWidgetLayoutAction->setEnabled(true); m_Left2Dand3DRight2DLayoutAction->setEnabled(false); break; } } } #ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU void QmitkRenderWindowMenu::MoveWidgetToCorrectPos(float opacity) #else void QmitkRenderWindowMenu::MoveWidgetToCorrectPos(float /*opacity*/) #endif { #ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU int X = floor(double(this->m_Parent->width() - this->width() - 8.0)); int Y = 7; QPoint pos = this->m_Parent->mapToGlobal(QPoint(0, 0)); this->move(X + pos.x(), Y + pos.y()); if (opacity < 0) opacity = 0; else if (opacity > 1) opacity = 1; this->setWindowOpacity(opacity); #else int moveX = floor(double(this->m_Parent->width() - this->width() - 4.0)); this->move(moveX, 3); this->show(); #endif } void QmitkRenderWindowMenu::ChangeFullScreenIcon() { m_FullScreenButton->setIcon(m_FullScreenMode ? QPixmap(iconLeaveFullScreen_xpm) : QPixmap(iconFullScreen_xpm)); } void QmitkRenderWindowMenu::OnCrosshairRotationModeSelected(QAction *action) { MITK_DEBUG << "selected crosshair mode " << action->data().toInt(); emit ChangeCrosshairRotationMode(action->data().toInt()); } void QmitkRenderWindowMenu::SetCrossHairVisibility(bool state) { if (m_Renderer.IsNotNull()) { mitk::DataNode *n; if (this->m_MultiWidget) { n = this->m_MultiWidget->GetWidgetPlane1(); if (n) n->SetVisibility(state); n = this->m_MultiWidget->GetWidgetPlane2(); if (n) n->SetVisibility(state); n = this->m_MultiWidget->GetWidgetPlane3(); if (n) n->SetVisibility(state); m_Renderer->GetRenderingManager()->RequestUpdateAll(); } } } void QmitkRenderWindowMenu::OnTSNumChanged(int num) { MITK_DEBUG << "Thickslices num: " << num << " on renderer " << m_Renderer.GetPointer(); if (m_Renderer.IsNotNull()) { if (num == 0) { m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New(0)); m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(num)); m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.showarea", mitk::BoolProperty::New(false)); } else { m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New(1)); m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(num)); m_Renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.showarea", mitk::BoolProperty::New(true)); } m_TSLabel->setText(QString::number(num * 2 + 1)); m_Renderer->SendUpdateSlice(); m_Renderer->GetRenderingManager()->RequestUpdateAll(); } } void QmitkRenderWindowMenu::OnCrossHairMenuAboutToShow() { QMenu *crosshairModesMenu = m_CrosshairMenu; crosshairModesMenu->clear(); QAction *resetViewAction = new QAction(crosshairModesMenu); resetViewAction->setText("Reset view"); crosshairModesMenu->addAction(resetViewAction); connect(resetViewAction, SIGNAL(triggered()), this, SIGNAL(ResetView())); // Show hide crosshairs { bool currentState = true; if (m_Renderer.IsNotNull()) { mitk::DataStorage *ds = m_Renderer->GetDataStorage(); mitk::DataNode *n; if (ds) { n = this->m_MultiWidget->GetWidgetPlane1(); if (n) { bool v; if (n->GetVisibility(v, 0)) currentState &= v; } n = this->m_MultiWidget->GetWidgetPlane2(); if (n) { bool v; if (n->GetVisibility(v, 0)) currentState &= v; } n = this->m_MultiWidget->GetWidgetPlane3(); if (n) { bool v; if (n->GetVisibility(v, 0)) currentState &= v; } } } QAction *showHideCrosshairVisibilityAction = new QAction(crosshairModesMenu); showHideCrosshairVisibilityAction->setText("Show crosshair"); showHideCrosshairVisibilityAction->setCheckable(true); showHideCrosshairVisibilityAction->setChecked(currentState); crosshairModesMenu->addAction(showHideCrosshairVisibilityAction); connect(showHideCrosshairVisibilityAction, SIGNAL(toggled(bool)), this, SLOT(SetCrossHairVisibility(bool))); } // Rotation mode { QAction *rotationGroupSeparator = new QAction(crosshairModesMenu); rotationGroupSeparator->setSeparator(true); rotationGroupSeparator->setText("Rotation mode"); crosshairModesMenu->addAction(rotationGroupSeparator); QActionGroup *rotationModeActionGroup = new QActionGroup(crosshairModesMenu); rotationModeActionGroup->setExclusive(true); QAction *noCrosshairRotation = new QAction(crosshairModesMenu); noCrosshairRotation->setActionGroup(rotationModeActionGroup); noCrosshairRotation->setText("No crosshair rotation"); noCrosshairRotation->setCheckable(true); noCrosshairRotation->setChecked(currentCrosshairRotationMode == 0); noCrosshairRotation->setData(0); crosshairModesMenu->addAction(noCrosshairRotation); QAction *singleCrosshairRotation = new QAction(crosshairModesMenu); singleCrosshairRotation->setActionGroup(rotationModeActionGroup); singleCrosshairRotation->setText("Crosshair rotation"); singleCrosshairRotation->setCheckable(true); singleCrosshairRotation->setChecked(currentCrosshairRotationMode == 1); singleCrosshairRotation->setData(1); crosshairModesMenu->addAction(singleCrosshairRotation); QAction *coupledCrosshairRotation = new QAction(crosshairModesMenu); coupledCrosshairRotation->setActionGroup(rotationModeActionGroup); coupledCrosshairRotation->setText("Coupled crosshair rotation"); coupledCrosshairRotation->setCheckable(true); coupledCrosshairRotation->setChecked(currentCrosshairRotationMode == 2); coupledCrosshairRotation->setData(2); crosshairModesMenu->addAction(coupledCrosshairRotation); QAction *swivelMode = new QAction(crosshairModesMenu); swivelMode->setActionGroup(rotationModeActionGroup); swivelMode->setText("Swivel mode"); swivelMode->setCheckable(true); swivelMode->setChecked(currentCrosshairRotationMode == 3); swivelMode->setData(3); crosshairModesMenu->addAction(swivelMode); connect( rotationModeActionGroup, SIGNAL(triggered(QAction *)), this, SLOT(OnCrosshairRotationModeSelected(QAction *))); } // auto rotation support if (m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard3D) { QAction *autoRotationGroupSeparator = new QAction(crosshairModesMenu); autoRotationGroupSeparator->setSeparator(true); crosshairModesMenu->addAction(autoRotationGroupSeparator); QAction *autoRotationAction = crosshairModesMenu->addAction("Auto Rotation"); autoRotationAction->setCheckable(true); autoRotationAction->setChecked(m_AutoRotationTimer.isActive()); connect(autoRotationAction, SIGNAL(triggered()), this, SLOT(OnAutoRotationActionTriggered())); } // Thickslices support if (m_Renderer.IsNotNull() && m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { QAction *thickSlicesGroupSeparator = new QAction(crosshairModesMenu); thickSlicesGroupSeparator->setSeparator(true); thickSlicesGroupSeparator->setText("ThickSlices mode"); crosshairModesMenu->addAction(thickSlicesGroupSeparator); QActionGroup *thickSlicesActionGroup = new QActionGroup(crosshairModesMenu); thickSlicesActionGroup->setExclusive(true); int currentMode = 0; { mitk::ResliceMethodProperty::Pointer m = dynamic_cast( m_Renderer->GetCurrentWorldPlaneGeometryNode()->GetProperty("reslice.thickslices")); if (m.IsNotNull()) currentMode = m->GetValueAsId(); } int currentNum = 1; { mitk::IntProperty::Pointer m = dynamic_cast( m_Renderer->GetCurrentWorldPlaneGeometryNode()->GetProperty("reslice.thickslices.num")); if (m.IsNotNull()) { currentNum = m->GetValue(); if (currentNum < 1) currentNum = 1; if (currentNum > 10) currentNum = 10; } } if (currentMode == 0) currentNum = 0; QSlider *m_TSSlider = new QSlider(crosshairModesMenu); m_TSSlider->setMinimum(0); m_TSSlider->setMaximum(9); m_TSSlider->setValue(currentNum); m_TSSlider->setOrientation(Qt::Horizontal); connect(m_TSSlider, SIGNAL(valueChanged(int)), this, SLOT(OnTSNumChanged(int))); QHBoxLayout *_TSLayout = new QHBoxLayout; _TSLayout->setContentsMargins(4, 4, 4, 4); _TSLayout->addWidget(new QLabel("TS: ")); _TSLayout->addWidget(m_TSSlider); _TSLayout->addWidget(m_TSLabel = new QLabel(QString::number(currentNum * 2 + 1), this)); QWidget *_TSWidget = new QWidget; _TSWidget->setLayout(_TSLayout); QWidgetAction *m_TSSliderAction = new QWidgetAction(crosshairModesMenu); m_TSSliderAction->setDefaultWidget(_TSWidget); crosshairModesMenu->addAction(m_TSSliderAction); } } void QmitkRenderWindowMenu::NotifyNewWidgetPlanesMode(int mode) { currentCrosshairRotationMode = mode; } void QmitkRenderWindowMenu::OnAutoRotationActionTriggered() { if (m_AutoRotationTimer.isActive()) { m_AutoRotationTimer.stop(); m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOff(); } else { m_Renderer->GetCameraRotationController()->GetSlice()->PingPongOn(); m_AutoRotationTimer.start(); } } void QmitkRenderWindowMenu::AutoRotateNextStep() { if (m_Renderer->GetCameraRotationController()) m_Renderer->GetCameraRotationController()->GetSlice()->Next(); } diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp index 22ad689ebc..1dfeae5836 100644 --- a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp @@ -1,267 +1,271 @@ /*=================================================================== 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 // mitk core #include #include const QString QmitkCustomMultiWidgetEditor::EDITOR_ID = "org.mitk.editors.custommultiwidget"; QmitkCustomMultiWidgetEditor::QmitkCustomMultiWidgetEditor() : m_CustomMultiWidget(nullptr) , m_InteractionSchemeToolBar(nullptr) , m_ConfigurationToolBar(nullptr) { // nothing here } QmitkCustomMultiWidgetEditor::~QmitkCustomMultiWidgetEditor() { // nothing here } void QmitkCustomMultiWidgetEditor::Activated() { // nothing here } void QmitkCustomMultiWidgetEditor::Deactivated() { // nothing here } void QmitkCustomMultiWidgetEditor::Visible() { // nothing here } void QmitkCustomMultiWidgetEditor::Hidden() { // nothing here } QmitkRenderWindow* QmitkCustomMultiWidgetEditor::GetActiveQmitkRenderWindow() const { if (nullptr != m_CustomMultiWidget) { - return m_CustomMultiWidget->GetActiveRenderWindowWidget()->GetRenderWindow(); + auto activeRenderWindowWidget = m_CustomMultiWidget->GetActiveRenderWindowWidget(); + if (nullptr != activeRenderWindowWidget) + { + return activeRenderWindowWidget->GetRenderWindow(); + } } return nullptr; } QHash QmitkCustomMultiWidgetEditor::GetQmitkRenderWindows() const { QHash result; if (nullptr == m_CustomMultiWidget) { return result; } // create QHash on demand QmitkCustomMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_CustomMultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { result.insert(renderWindowWidget.first, renderWindowWidget.second->GetRenderWindow()); } return result; } QmitkRenderWindow* QmitkCustomMultiWidgetEditor::GetQmitkRenderWindow(const QString& id) const { if (nullptr == m_CustomMultiWidget) { return nullptr; } return m_CustomMultiWidget->GetRenderWindow(id); } mitk::Point3D QmitkCustomMultiWidgetEditor::GetSelectedPosition(const QString& id) const { if (nullptr == m_CustomMultiWidget) { return mitk::Point3D(); } return m_CustomMultiWidget->GetCrossPosition(id); } void QmitkCustomMultiWidgetEditor::SetSelectedPosition(const mitk::Point3D& pos, const QString& id) { if (nullptr != m_CustomMultiWidget) { m_CustomMultiWidget->MoveCrossToPosition(id, pos); } } void QmitkCustomMultiWidgetEditor::EnableDecorations(bool enable, const QStringList& decorations) { m_MultiWidgetDecorationManager->ShowDecorations(enable, decorations); } bool QmitkCustomMultiWidgetEditor::IsDecorationEnabled(const QString& decoration) const { return m_MultiWidgetDecorationManager->IsDecorationVisible(decoration); } QStringList QmitkCustomMultiWidgetEditor::GetDecorations() const { return m_MultiWidgetDecorationManager->GetDecorations(); } void QmitkCustomMultiWidgetEditor::EnableSlicingPlanes(bool enable) { // #TODO: nothing here } bool QmitkCustomMultiWidgetEditor::IsSlicingPlanesEnabled() const { // #TODO: nothing here return false; } QmitkCustomMultiWidget* QmitkCustomMultiWidgetEditor::GetCustomMultiWidget() { return m_CustomMultiWidget; } void QmitkCustomMultiWidgetEditor::OnLayoutSet(int row, int column) { m_CustomMultiWidget->ResetLayout(row, column); SetControlledRenderer(); } void QmitkCustomMultiWidgetEditor::OnSynchronize(bool synchronized) { m_CustomMultiWidget->Synchronize(synchronized); } void QmitkCustomMultiWidgetEditor::OnViewDirectionChanged(mitk::SliceNavigationController::ViewDirection viewDirection) { m_RenderWindowViewDirectionController->SetViewDirectionOfRenderer(viewDirection); } ////////////////////////////////////////////////////////////////////////// // PRIVATE ////////////////////////////////////////////////////////////////////////// void QmitkCustomMultiWidgetEditor::SetFocus() { if (nullptr != m_CustomMultiWidget) { m_CustomMultiWidget->setFocus(); } } void QmitkCustomMultiWidgetEditor::CreateQtPartControl(QWidget* parent) { if (nullptr == m_CustomMultiWidget) { QHBoxLayout* layout = new QHBoxLayout(parent); layout->setContentsMargins(0, 0, 0, 0); berry::IBerryPreferences* preferences = dynamic_cast(GetPreferences().GetPointer()); mitk::BaseRenderer::RenderingMode::Type renderingMode = static_cast(preferences->GetInt("Rendering Mode", 0)); m_CustomMultiWidget = new QmitkCustomMultiWidget(parent, 0, 0, renderingMode); // create left toolbar: interaction scheme toolbar to switch how the render window navigation behaves if (nullptr == m_InteractionSchemeToolBar) { m_InteractionSchemeToolBar = new QmitkInteractionSchemeToolBar(parent); layout->addWidget(m_InteractionSchemeToolBar); } m_InteractionSchemeToolBar->SetInteractionEventHandler(m_CustomMultiWidget->GetInteractionEventHandler()); // add center widget: the custom multi widget layout->addWidget(m_CustomMultiWidget); m_CustomMultiWidget->SetDataStorage(GetDataStorage()); m_CustomMultiWidget->InitializeRenderWindowWidgets(); // create right toolbar: configuration toolbar to change the render window widget layout if (nullptr == m_ConfigurationToolBar) { m_ConfigurationToolBar = new QmitkMultiWidgetConfigurationToolBar(m_CustomMultiWidget); layout->addWidget(m_ConfigurationToolBar); } connect(m_ConfigurationToolBar, SIGNAL(LayoutSet(int, int)), SLOT(OnLayoutSet(int, int))); connect(m_ConfigurationToolBar, SIGNAL(Synchronized(bool)), SLOT(OnSynchronize(bool))); connect(m_ConfigurationToolBar, SIGNAL(ViewDirectionChanged(mitk::SliceNavigationController::ViewDirection)), SLOT(OnViewDirectionChanged(mitk::SliceNavigationController::ViewDirection))); m_MultiWidgetDecorationManager = std::make_unique(m_CustomMultiWidget); m_RenderWindowViewDirectionController = std::make_unique(); m_RenderWindowViewDirectionController->SetDataStorage(GetDataStorage()); SetControlledRenderer(); OnPreferencesChanged(preferences); } } void QmitkCustomMultiWidgetEditor::OnPreferencesChanged(const berry::IBerryPreferences* preferences) { if (m_CustomMultiWidget->GetRenderWindowWidgets().empty()) { return; } // update decoration preferences m_MultiWidgetDecorationManager->DecorationPreferencesChanged(preferences); // zooming and panning preferences bool constrainedZooming = preferences->GetBool("Use constrained zooming and panning", true); mitk::RenderingManager::GetInstance()->SetConstrainedPanningZooming(constrainedZooming); // level window preferences bool showLevelWindowWidget = preferences->GetBool("Show level-window widget", true); m_CustomMultiWidget->ShowAllLevelWindowWidgets(showLevelWindowWidget); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkCustomMultiWidgetEditor::SetControlledRenderer() { if (nullptr == m_RenderWindowViewDirectionController || nullptr == m_CustomMultiWidget) { return; } RenderWindowLayerUtilities::RendererVector controlledRenderer; auto renderWindowWidgets = m_CustomMultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { auto renderWindow = renderWindowWidget.second->GetRenderWindow(); auto vtkRenderWindow = renderWindow->GetRenderWindow(); mitk::BaseRenderer* baseRenderer = mitk::BaseRenderer::GetInstance(vtkRenderWindow); if (nullptr != baseRenderer) { controlledRenderer.push_back(baseRenderer); } } m_RenderWindowViewDirectionController->SetControlledRenderer(controlledRenderer); }