diff --git a/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp b/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp index bf8a7f9abe..5936b5fa48 100644 --- a/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp +++ b/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp @@ -1,951 +1,951 @@ /*=================================================================== 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 "mitkDisplayInteractor.h" #include "mitkBaseRenderer.h" #include "mitkCameraController.h" #include "mitkInteractionPositionEvent.h" #include "mitkPropertyList.h" #include #include #include // level window #include "mitkLevelWindow.h" #include "mitkLevelWindowProperty.h" #include "mitkLine.h" #include "mitkNodePredicateDataType.h" #include "mitkStandaloneDataStorage.h" #include "vtkRenderWindowInteractor.h" // Rotation #include "mitkInteractionConst.h" #include "rotate_cursor.xpm" #include #include #include "mitkImage.h" #include "mitkImagePixelReadAccessor.h" #include "mitkPixelTypeMultiplex.h" #include "mitkStatusBar.h" #include void mitk::DisplayInteractor::Notify(InteractionEvent *interactionEvent, bool isHandled) { // to use the state machine pattern, // the event is passed to the state machine interface to be handled if (!isHandled || m_AlwaysReact) { HandleEvent(interactionEvent, nullptr); } } mitk::DisplayInteractor::DisplayInteractor() : m_IndexToSliceModifier(4) , m_AutoRepeat(false) , m_InvertScrollDirection(false) , m_InvertZoomDirection(false) , m_InvertMoveDirection(false) , m_InvertLevelWindowDirection(false) , m_AlwaysReact(false) , m_ZoomFactor(2) , m_LinkPlanes(true) { m_StartCoordinateInMM.Fill(0); m_LastDisplayCoordinate.Fill(0); m_LastCoordinateInMM.Fill(0); m_CurrentDisplayCoordinate.Fill(0); } mitk::DisplayInteractor::~DisplayInteractor() { // nothing here } void mitk::DisplayInteractor::ConnectActionsAndFunctions() { CONNECT_CONDITION("check_position_event", CheckPositionEvent); CONNECT_CONDITION("check_can_rotate", CheckRotationPossible); CONNECT_CONDITION("check_can_swivel", CheckSwivelPossible); CONNECT_FUNCTION("init", Init); CONNECT_FUNCTION("move", Move); CONNECT_FUNCTION("zoom", Zoom); CONNECT_FUNCTION("scroll", Scroll); CONNECT_FUNCTION("ScrollOneDown", ScrollOneDown); CONNECT_FUNCTION("ScrollOneUp", ScrollOneUp); CONNECT_FUNCTION("levelWindow", AdjustLevelWindow); CONNECT_FUNCTION("setCrosshair", SetCrosshair); CONNECT_FUNCTION("updateStatusbar", UpdateStatusbar) CONNECT_FUNCTION("startRotation", StartRotation); CONNECT_FUNCTION("endRotation", EndRotation); CONNECT_FUNCTION("rotate", Rotate); CONNECT_FUNCTION("swivel", Swivel); CONNECT_FUNCTION("IncreaseTimeStep", IncreaseTimeStep); CONNECT_FUNCTION("DecreaseTimeStep", DecreaseTimeStep); } bool mitk::DisplayInteractor::CheckPositionEvent(const InteractionEvent *interactionEvent) { const auto *positionEvent = dynamic_cast(interactionEvent); if (positionEvent == nullptr) { return false; } return true; } bool mitk::DisplayInteractor::CheckRotationPossible(const mitk::InteractionEvent *interactionEvent) { // Decide between moving and rotation slices. /* Detailed logic: 1. Find the SliceNavigationController that has sent the event: this one defines our rendering plane and will NOT be rotated. Needs not even be counted or checked. 2. Inspect every other SliceNavigationController - calculate the line intersection of this SliceNavigationController's plane with our rendering plane - if there is NO interesection, ignore and continue - IF there is an intersection - check the mouse cursor's distance from that line. 0. if the line is NOT near the cursor, remember the plane as "one of the other planes" (which can be rotated in "locked" mode) 1. on first line near the cursor, just remember this intersection line as THE other plane that we want to rotate 2. on every consecutive line near the cursor, check if the line is geometrically identical to the line that we want to rotate - if yes, we just push this line to the "other" lines and rotate it along - if no, then we have a situation where the mouse is near two other lines (e.g. crossing point) and don't want to rotate */ const auto *posEvent = dynamic_cast(interactionEvent); if (posEvent == nullptr) return false; BaseRenderer *clickedRenderer = posEvent->GetSender(); const PlaneGeometry *ourViewportGeometry = (clickedRenderer->GetCurrentWorldPlaneGeometry()); if (!ourViewportGeometry) return false; Point3D cursorPosition = posEvent->GetPositionInWorld(); const auto spacing = ourViewportGeometry->GetSpacing(); const PlaneGeometry *geometryToBeRotated = nullptr; // this one is under the mouse cursor const PlaneGeometry *anyOtherGeometry = nullptr; // this is also visible (for calculation of intersection ONLY) Line3D intersectionLineWithGeometryToBeRotated; bool hitMultipleLines(false); m_SNCsToBeRotated.clear(); const double threshholdDistancePixels = 12.0; auto renWindows = interactionEvent->GetSender()->GetRenderingManager()->GetAllRegisteredRenderWindows(); for (auto renWin : renWindows) { SliceNavigationController *snc = BaseRenderer::GetInstance(renWin)->GetSliceNavigationController(); // If the mouse cursor is in 3D Renderwindow, do not check for intersecting planes. if (BaseRenderer::GetInstance(renWin)->GetMapperID() == BaseRenderer::Standard3D) continue; const PlaneGeometry *otherRenderersRenderPlane = snc->GetCurrentPlaneGeometry(); if (otherRenderersRenderPlane == nullptr) continue; // ignore, we don't see a plane // check if there is an intersection Line3D intersectionLine; // between rendered/clicked geometry and the one being analyzed if (!ourViewportGeometry->IntersectionLine(otherRenderersRenderPlane, intersectionLine)) { continue; // we ignore this plane, it's parallel to our plane } // check distance from intersection line const double distanceFromIntersectionLine = intersectionLine.Distance(cursorPosition) / spacing[snc->GetDefaultViewDirection()]; // far away line, only remember for linked rotation if necessary if (distanceFromIntersectionLine > threshholdDistancePixels) { anyOtherGeometry = otherRenderersRenderPlane; // we just take the last one, so overwrite each iteration (we just // need some crossing point) // TODO what about multiple crossings? NOW we have undefined behavior / random crossing point is used if (m_LinkPlanes) { m_SNCsToBeRotated.push_back(snc); } } else // close to cursor { if (geometryToBeRotated == nullptr) // first one close to the cursor { geometryToBeRotated = otherRenderersRenderPlane; intersectionLineWithGeometryToBeRotated = intersectionLine; m_SNCsToBeRotated.push_back(snc); } else { // compare to the line defined by geometryToBeRotated: if identical, just rotate this otherRenderersRenderPlane // together with the primary one // if different, DON'T rotate if (intersectionLine.IsParallel(intersectionLineWithGeometryToBeRotated) && intersectionLine.Distance(intersectionLineWithGeometryToBeRotated.GetPoint1()) < mitk::eps) { m_SNCsToBeRotated.push_back(snc); } else { hitMultipleLines = true; } } } } bool moveSlices(true); if (geometryToBeRotated && anyOtherGeometry && ourViewportGeometry && !hitMultipleLines) { // assure all three are valid, so calculation of center of rotation can be done moveSlices = false; } // question in state machine is: "rotate?" if (moveSlices) // i.e. NOT rotate { return false; } else { // we DO have enough information for rotation m_LastCursorPosition = intersectionLineWithGeometryToBeRotated.Project( cursorPosition); // remember where the last cursor position ON THE LINE has been observed if (anyOtherGeometry->IntersectionPoint( intersectionLineWithGeometryToBeRotated, m_CenterOfRotation)) // find center of rotation by intersection with any of the OTHER lines { return true; } else { return false; } } return false; } bool mitk::DisplayInteractor::CheckSwivelPossible(const mitk::InteractionEvent *interactionEvent) { const ScalarType ThresholdDistancePixels = 6.0; // Decide between moving and rotation: if we're close to the crossing // point of the planes, moving mode is entered, otherwise // rotation/swivel mode const auto *posEvent = dynamic_cast(interactionEvent); BaseRenderer *renderer = interactionEvent->GetSender(); if (!posEvent || !renderer) return false; const Point3D &cursor = posEvent->GetPositionInWorld(); m_SNCsToBeRotated.clear(); const PlaneGeometry *clickedGeometry(nullptr); const PlaneGeometry *otherGeometry1(nullptr); const PlaneGeometry *otherGeometry2(nullptr); auto renWindows = interactionEvent->GetSender()->GetRenderingManager()->GetAllRegisteredRenderWindows(); for (auto renWin : renWindows) { SliceNavigationController *snc = BaseRenderer::GetInstance(renWin)->GetSliceNavigationController(); // If the mouse cursor is in 3D Renderwindow, do not check for intersecting planes. if (BaseRenderer::GetInstance(renWin)->GetMapperID() == BaseRenderer::Standard3D) continue; // unsigned int slice = (*iter)->GetSlice()->GetPos(); // unsigned int time = (*iter)->GetTime()->GetPos(); const PlaneGeometry *planeGeometry = snc->GetCurrentPlaneGeometry(); if (!planeGeometry) continue; if (snc == renderer->GetSliceNavigationController()) { clickedGeometry = planeGeometry; m_SNCsToBeRotated.push_back(snc); } else { if (otherGeometry1 == nullptr) { otherGeometry1 = planeGeometry; } else { otherGeometry2 = planeGeometry; } if (m_LinkPlanes) { // If planes are linked, apply rotation to all planes m_SNCsToBeRotated.push_back(snc); } } } mitk::Line3D line; mitk::Point3D point; if ((clickedGeometry != nullptr) && (otherGeometry1 != nullptr) && (otherGeometry2 != nullptr) && clickedGeometry->IntersectionLine(otherGeometry1, line) && otherGeometry2->IntersectionPoint(line, point)) { m_CenterOfRotation = point; if (m_CenterOfRotation.EuclideanDistanceTo(cursor) < ThresholdDistancePixels) { return false; } else { m_ReferenceCursor = posEvent->GetPointerPositionOnScreen(); // Get main axes of rotation plane and store it for rotation step m_RotationPlaneNormal = clickedGeometry->GetNormal(); ScalarType xVector[] = {1.0, 0.0, 0.0}; ScalarType yVector[] = {0.0, 1.0, 0.0}; clickedGeometry->BaseGeometry::IndexToWorld(Vector3D(xVector), m_RotationPlaneXVector); clickedGeometry->BaseGeometry::IndexToWorld(Vector3D(yVector), m_RotationPlaneYVector); m_RotationPlaneNormal.Normalize(); m_RotationPlaneXVector.Normalize(); m_RotationPlaneYVector.Normalize(); m_PreviousRotationAxis.Fill(0.0); m_PreviousRotationAxis[2] = 1.0; m_PreviousRotationAngle = 0.0; return true; } } else { return false; } return false; } void mitk::DisplayInteractor::Init(StateMachineAction *, InteractionEvent *interactionEvent) { auto *positionEvent = static_cast(interactionEvent); m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); m_CurrentDisplayCoordinate = m_LastDisplayCoordinate; positionEvent->GetSender()->DisplayToPlane(m_LastDisplayCoordinate, m_StartCoordinateInMM); m_LastCoordinateInMM = m_StartCoordinateInMM; } void mitk::DisplayInteractor::Move(StateMachineAction *, InteractionEvent *interactionEvent) { BaseRenderer *sender = interactionEvent->GetSender(); auto *positionEvent = static_cast(interactionEvent); float invertModifier = -1.0; if (m_InvertMoveDirection) { invertModifier = 1.0; } // perform translation Vector2D moveVector = (positionEvent->GetPointerPositionOnScreen() - m_LastDisplayCoordinate) * invertModifier; moveVector *= sender->GetScaleFactorMMPerDisplayUnit(); sender->GetCameraController()->MoveBy(moveVector); sender->GetRenderingManager()->RequestUpdate(sender->GetRenderWindow()); m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); } void mitk::DisplayInteractor::SetCrosshair(mitk::StateMachineAction *, mitk::InteractionEvent *interactionEvent) { auto* positionEvent = static_cast(interactionEvent); Point3D pos = positionEvent->GetPositionInWorld(); const BaseRenderer::Pointer sender = interactionEvent->GetSender(); auto renWindows = sender->GetRenderingManager()->GetAllRegisteredRenderWindows(); for (auto renWin : renWindows) { if (BaseRenderer::GetInstance(renWin)->GetMapperID() == BaseRenderer::Standard2D && renWin != sender->GetRenderWindow()) { BaseRenderer::GetInstance(renWin)->GetSliceNavigationController()->SelectSliceByPoint(pos); } } } void mitk::DisplayInteractor::IncreaseTimeStep(StateMachineAction *, InteractionEvent *interactionEvent) { auto sliceNaviController = interactionEvent->GetSender()->GetRenderingManager()->GetTimeNavigationController(); auto stepper = sliceNaviController->GetTime(); stepper->SetAutoRepeat(true); stepper->Next(); } void mitk::DisplayInteractor::DecreaseTimeStep(StateMachineAction *, InteractionEvent *interactionEvent) { auto sliceNaviController = interactionEvent->GetSender()->GetRenderingManager()->GetTimeNavigationController(); auto stepper = sliceNaviController->GetTime(); stepper->SetAutoRepeat(true); stepper->Previous(); } void mitk::DisplayInteractor::Zoom(StateMachineAction *, InteractionEvent *interactionEvent) { float factor = 1.0; float distance = 0; if (m_ZoomDirection == "updown") { distance = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1]; } else { distance = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0]; } if (m_InvertZoomDirection) { distance *= -1.0; } // set zooming speed if (distance < 0.0) { factor = 1.0 / m_ZoomFactor; } else if (distance > 0.0) { factor = 1.0 * m_ZoomFactor; } auto* positionEvent = static_cast(interactionEvent); m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); if (factor != 1.0) { const BaseRenderer::Pointer sender = interactionEvent->GetSender(); sender->GetCameraController()->Zoom(factor, m_StartCoordinateInMM); sender->GetRenderingManager()->RequestUpdate(sender->GetRenderWindow()); } } void mitk::DisplayInteractor::Scroll(StateMachineAction *, InteractionEvent *interactionEvent) { auto* positionEvent = static_cast(interactionEvent); mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (sliceNaviController) { int delta = 0; // Scrolling direction if (m_ScrollDirection == "updown") { delta = static_cast(m_LastDisplayCoordinate[1] - positionEvent->GetPointerPositionOnScreen()[1]); } else { delta = static_cast(m_LastDisplayCoordinate[0] - positionEvent->GetPointerPositionOnScreen()[0]); } if (m_InvertScrollDirection) { delta *= -1; } // Set how many pixels the mouse has to be moved to scroll one slice // if we moved less than 'm_IndexToSliceModifier' pixels slice ONE slice only if (delta > 0 && delta < m_IndexToSliceModifier) { delta = m_IndexToSliceModifier; } else if (delta < 0 && delta > -m_IndexToSliceModifier) { delta = -m_IndexToSliceModifier; } delta /= m_IndexToSliceModifier; int newPos = sliceNaviController->GetSlice()->GetPos() + delta; // if auto repeat is on, start at first slice if you reach the last slice and vice versa int maxSlices = sliceNaviController->GetSlice()->GetSteps(); if (m_AutoRepeat) { while (newPos < 0) { newPos += maxSlices; } while (newPos >= maxSlices) { newPos -= maxSlices; } } else { // if the new slice is below 0 we still show slice 0 // due to the stepper using unsigned int we have to do this ourselves if (newPos < 1) { newPos = 0; } } m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); // set the new position sliceNaviController->GetSlice()->SetPos(newPos); } } void mitk::DisplayInteractor::ScrollOneDown(StateMachineAction *, InteractionEvent *interactionEvent) { mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (!sliceNaviController->GetSliceLocked()) { mitk::Stepper *stepper = sliceNaviController->GetSlice(); if (stepper->GetSteps() <= 1) { stepper = sliceNaviController->GetTime(); } stepper->Next(); } } void mitk::DisplayInteractor::ScrollOneUp(StateMachineAction *, InteractionEvent *interactionEvent) { mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (!sliceNaviController->GetSliceLocked()) { mitk::Stepper *stepper = sliceNaviController->GetSlice(); if (stepper->GetSteps() <= 1) { stepper = sliceNaviController->GetTime(); } stepper->Previous(); } } void mitk::DisplayInteractor::AdjustLevelWindow(StateMachineAction *, InteractionEvent *interactionEvent) { BaseRenderer::Pointer sender = interactionEvent->GetSender(); auto *positionEvent = static_cast(interactionEvent); m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); // search for active image mitk::DataStorage::Pointer storage = sender->GetDataStorage(); mitk::DataNode::Pointer node = nullptr; mitk::DataStorage::SetOfObjects::ConstPointer allImageNodes = storage->GetSubset(mitk::NodePredicateDataType::New("Image")); for (unsigned int i = 0; i < allImageNodes->size(); ++i) { bool isActiveImage = false; bool propFound = allImageNodes->at(i)->GetBoolProperty("imageForLevelWindow", isActiveImage); if (propFound && isActiveImage) { node = allImageNodes->at(i); continue; } } if (node.IsNull()) { node = storage->GetNode(mitk::NodePredicateDataType::New("Image")); } if (node.IsNull()) { return; } mitk::LevelWindow lv = mitk::LevelWindow(); node->GetLevelWindow(lv); ScalarType level = lv.GetLevel(); ScalarType window = lv.GetWindow(); int levelIndex = 0; int windowIndex = 1; if (m_LevelDirection != "leftright") { levelIndex = 1; windowIndex = 0; } int directionModifier = 1; if (m_InvertLevelWindowDirection) { directionModifier = -1; } // calculate adjustments from mouse movements level += (m_CurrentDisplayCoordinate[levelIndex] - m_LastDisplayCoordinate[levelIndex]) * static_cast(2) * directionModifier; window += (m_CurrentDisplayCoordinate[windowIndex] - m_LastDisplayCoordinate[windowIndex]) * static_cast(2) * directionModifier; lv.SetLevelWindow(level, window); dynamic_cast(node->GetProperty("levelwindow"))->SetLevelWindow(lv); sender->GetRenderingManager()->RequestUpdateAll(); } void mitk::DisplayInteractor::StartRotation(mitk::StateMachineAction *, mitk::InteractionEvent *) { this->SetMouseCursor(rotate_cursor_xpm, 0, 0); } void mitk::DisplayInteractor::EndRotation(mitk::StateMachineAction *, mitk::InteractionEvent *) { this->ResetMouseCursor(); } void mitk::DisplayInteractor::Rotate(mitk::StateMachineAction *, mitk::InteractionEvent *event) { const auto *posEvent = dynamic_cast(event); if (posEvent == nullptr) return; Point3D cursor = posEvent->GetPositionInWorld(); Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation; Vector3D toCursor = cursor - m_CenterOfRotation; // cross product: | A x B | = |A| * |B| * sin(angle) Vector3D axisOfRotation; vnl_vector_fixed vnlDirection = vnl_cross_3d(toCursor.GetVnlVector(), toProjected.GetVnlVector()); axisOfRotation.SetVnlVector(vnlDirection); // scalar product: A * B = |A| * |B| * cos(angle) // tan = sin / cos ScalarType angle = -atan2((double)(axisOfRotation.GetNorm()), (double)(toCursor * toProjected)); angle *= 180.0 / vnl_math::pi; m_LastCursorPosition = cursor; // create RotationOperation and apply to all SNCs that should be rotated RotationOperation rotationOperation(OpROTATE, m_CenterOfRotation, axisOfRotation, angle); // iterate the OTHER slice navigation controllers: these are filled in DoDecideBetweenRotationAndSliceSelection for (auto iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter) { TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; timeGeometry->ExecuteOperation(&rotationOperation); (*iter)->SendCreatedWorldGeometryUpdate(); } RenderingManager::GetInstance()->RequestUpdateAll(); } void mitk::DisplayInteractor::Swivel(mitk::StateMachineAction *, mitk::InteractionEvent *event) { const auto *posEvent = dynamic_cast(event); if (!posEvent) return; // Determine relative mouse movement projected onto world space Point2D cursor = posEvent->GetPointerPositionOnScreen(); Vector2D relativeCursor = cursor - m_ReferenceCursor; Vector3D relativeCursorAxis = m_RotationPlaneXVector * relativeCursor[0] + m_RotationPlaneYVector * relativeCursor[1]; // Determine rotation axis (perpendicular to rotation plane and cursor // movement) Vector3D rotationAxis = itk::CrossProduct(m_RotationPlaneNormal, relativeCursorAxis); ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0; // Restore the initial plane pose by undoing the previous rotation // operation RotationOperation op(OpROTATE, m_CenterOfRotation, m_PreviousRotationAxis, -m_PreviousRotationAngle); SNCVector::iterator iter; for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter) { if (!(*iter)->GetSliceRotationLocked()) { TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; timeGeometry->ExecuteOperation(&op); (*iter)->SendCreatedWorldGeometryUpdate(); } } // Apply new rotation operation to all relevant SNCs RotationOperation op2(OpROTATE, m_CenterOfRotation, rotationAxis, rotationAngle); for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter) { if (!(*iter)->GetSliceRotationLocked()) { // Retrieve the TimeGeometry of this SliceNavigationController TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; // Execute the new rotation timeGeometry->ExecuteOperation(&op2); // Notify listeners (*iter)->SendCreatedWorldGeometryUpdate(); } } m_PreviousRotationAxis = rotationAxis; m_PreviousRotationAngle = rotationAngle; RenderingManager::GetInstance()->RequestUpdateAll(); return; } void mitk::DisplayInteractor::UpdateStatusbar(mitk::StateMachineAction *, mitk::InteractionEvent *event) { const auto* posEvent = dynamic_cast(event); if (nullptr == posEvent) { return; } const mitk::BaseRenderer::Pointer baseRenderer = posEvent->GetSender(); TNodePredicateDataType::Pointer isImageData = TNodePredicateDataType::New(); auto globalCurrentTimePoint = baseRenderer->GetTime(); mitk::DataStorage::SetOfObjects::ConstPointer nodes = baseRenderer->GetDataStorage()->GetSubset(isImageData).GetPointer(); if (nodes.IsNull()) { return; } // posEvent->GetPositionInWorld() would return the world position at the // time of initiating the interaction. However, we need to update the // status bar with the position after changing slice. Therefore, we // translate the same display position with the renderer again to // get the new world position. Point3D worldposition; baseRenderer->DisplayToWorld(posEvent->GetPointerPositionOnScreen(), worldposition); mitk::Image::Pointer image3D; mitk::DataNode::Pointer node; mitk::DataNode::Pointer topSourceNode; int component = 0; node = FindTopmostVisibleNode(nodes, worldposition, globalCurrentTimePoint, baseRenderer); if (node.IsNull()) { return; } bool isBinary(false); node->GetBoolProperty("binary", isBinary); if (isBinary) { mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = baseRenderer->GetDataStorage()->GetSources(node, nullptr, true); if (!sourcenodes->empty()) { - topSourceNode = mitk::FindTopmostVisibleNode(sourcenodes, worldposition, globalCurrentTimePoint, baseRenderer); - } - if (topSourceNode.IsNotNull()) - { - image3D = dynamic_cast(topSourceNode->GetData()); - topSourceNode->GetIntProperty("Image.Displayed Component", component); - } - else - { - image3D = dynamic_cast(node->GetData()); - node->GetIntProperty("Image.Displayed Component", component); - } - } - else - { - image3D = dynamic_cast(node->GetData()); - node->GetIntProperty("Image.Displayed Component", component); - } + topSourceNode = mitk::FindTopmostVisibleNode(sourcenodes, worldposition, globalCurrentTimePoint, baseRenderer); + } + if (topSourceNode.IsNotNull()) + { + image3D = dynamic_cast(topSourceNode->GetData()); + topSourceNode->GetIntProperty("Image.Displayed Component", component); + } + else + { + image3D = dynamic_cast(node->GetData()); + node->GetIntProperty("Image.Displayed Component", component); + } + } + else + { + image3D = dynamic_cast(node->GetData()); + node->GetIntProperty("Image.Displayed Component", component); + } // get the position and gray value from the image and build up status bar text auto statusBar = StatusBar::GetInstance(); if (image3D.IsNotNull() && statusBar != nullptr) { itk::Index<3> p; image3D->GetGeometry()->WorldToIndex(worldposition, p); auto pixelType = image3D->GetChannelDescriptor().GetPixelType().GetPixelType(); if (pixelType == itk::ImageIOBase::RGB || pixelType == itk::ImageIOBase::RGBA) { std::string pixelValue = "Pixel RGB(A) value: "; pixelValue.append(ConvertCompositePixelValueToString(image3D, p)); statusBar->DisplayImageInfo(worldposition, p, globalCurrentTimePoint, pixelValue.c_str()); } else if (pixelType == itk::ImageIOBase::DIFFUSIONTENSOR3D || pixelType == itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR) { std::string pixelValue = "See ODF Details view. "; statusBar->DisplayImageInfo(worldposition, p, globalCurrentTimePoint, pixelValue.c_str()); } else { mitk::ScalarType pixelValue; mitkPixelTypeMultiplex5(mitk::FastSinglePixelAccess, image3D->GetChannelDescriptor().GetPixelType(), image3D, image3D->GetVolumeData(image3D->GetTimeGeometry()->TimePointToTimeStep(globalCurrentTimePoint)), p, pixelValue, component); statusBar->DisplayImageInfo(worldposition, p, globalCurrentTimePoint, pixelValue); } } else { statusBar->DisplayImageInfoInvalid(); } } void mitk::DisplayInteractor::ConfigurationChanged() { mitk::PropertyList::Pointer properties = GetAttributes(); // auto repeat std::string strAutoRepeat = ""; if (properties->GetStringProperty("autoRepeat", strAutoRepeat)) { if (strAutoRepeat == "true") { m_AutoRepeat = true; } else { m_AutoRepeat = false; } } // pixel movement for scrolling one slice std::string strPixelPerSlice = ""; if (properties->GetStringProperty("pixelPerSlice", strPixelPerSlice)) { m_IndexToSliceModifier = atoi(strPixelPerSlice.c_str()); } else { m_IndexToSliceModifier = 4; } // scroll direction if (!properties->GetStringProperty("scrollDirection", m_ScrollDirection)) { m_ScrollDirection = "updown"; } m_InvertScrollDirection = GetBoolProperty(properties, "invertScrollDirection", false); // zoom direction if (!properties->GetStringProperty("zoomDirection", m_ZoomDirection)) { m_ZoomDirection = "updown"; } m_InvertZoomDirection = GetBoolProperty(properties, "invertZoomDirection", false); m_InvertMoveDirection = GetBoolProperty(properties, "invertMoveDirection", false); if (!properties->GetStringProperty("levelWindowDirection", m_LevelDirection)) { m_LevelDirection = "leftright"; } m_InvertLevelWindowDirection = GetBoolProperty(properties, "invertLevelWindowDirection", false); // coupled rotation std::string strCoupled = ""; if (properties->GetStringProperty("coupled", strCoupled)) { if (strCoupled == "true") m_LinkPlanes = true; else m_LinkPlanes = false; } // zoom factor std::string strZoomFactor = ""; properties->GetStringProperty("zoomFactor", strZoomFactor); m_ZoomFactor = .05; if (atoi(strZoomFactor.c_str()) > 0) { m_ZoomFactor = 1.0 + (atoi(strZoomFactor.c_str()) / 100.0); } // allwaysReact std::string strAlwaysReact = ""; if (properties->GetStringProperty("alwaysReact", strAlwaysReact)) { if (strAlwaysReact == "true") { m_AlwaysReact = true; } else { m_AlwaysReact = false; } } else { m_AlwaysReact = false; } } bool mitk::DisplayInteractor::FilterEvents(InteractionEvent *interactionEvent, DataNode * /*dataNode*/) { if (interactionEvent->GetSender() == nullptr) return false; if (interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard3D) return false; return true; } bool mitk::DisplayInteractor::GetBoolProperty(mitk::PropertyList::Pointer propertyList, const char *propertyName, bool defaultValue) { std::string valueAsString; if (!propertyList->GetStringProperty(propertyName, valueAsString)) { return defaultValue; } else { if (valueAsString == "true") { return true; } else { return false; } } } diff --git a/Modules/QtWidgets/files.cmake b/Modules/QtWidgets/files.cmake index ec5e57aa47..dc2f4a6e64 100644 --- a/Modules/QtWidgets/files.cmake +++ b/Modules/QtWidgets/files.cmake @@ -1,124 +1,126 @@ 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 QmitkDnDDataNodeWidget.cpp QmitkFileReaderOptionsDialog.cpp QmitkFileReaderWriterOptionsWidget.cpp QmitkFileWriterOptionsDialog.cpp QmitkInteractionSchemeToolBar.cpp QmitkIOUtil.cpp QmitkLevelWindowPresetDefinitionDialog.cpp QmitkLevelWindowRangeChangeDialog.cpp QmitkLevelWindowWidgetContextMenu.cpp QmitkLevelWindowWidget.cpp QmitkLineEditLevelWindowWidget.cpp QmitkMemoryUsageIndicatorView.cpp QmitkMouseModeSwitcher.cpp QmitkMimeTypes.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 QmitkMxNMultiWidget.cpp QmitkDataStorageComboBoxWithSelectNone.cpp QmitkDataStorageFilterProxyModel.cpp QmitkPropertyItem.cpp QmitkPropertyItemDelegate.cpp QmitkPropertyItemModel.cpp QmitkStyleManager.cpp QmitkAbstractDataStorageInspector.cpp QmitkDataStorageListInspector.cpp QmitkDataStorageTreeInspector.cpp QmitkModelViewSelectionConnector.cpp mitkIDataStorageInspectorProvider.cpp mitkQtWidgetsActivator.cpp mitkDataStorageInspectorGenerator.cpp QmitkOverlayWidget.cpp QmitkNodeDetailsDialog.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/QmitkDnDDataNodeWidget.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/QmitkProgressBar.h include/QmitkPropertiesTableEditor.h include/QmitkPropertyDelegate.h include/QmitkRenderingManager.h include/QmitkRenderWindow.h include/QmitkRenderWindowMenu.h include/QmitkRenderWindowWidget.h include/QmitkServiceListWidget.h include/QmitkSliderLevelWindowWidget.h include/QmitkStdMultiWidget.h include/QmitkMxNMultiWidget.h include/QmitkDataStorageComboBoxWithSelectNone.h include/QmitkPropertyItemDelegate.h include/QmitkPropertyItemModel.h include/QmitkDataStorageListInspector.h include/QmitkAbstractDataStorageInspector.h include/QmitkDataStorageTreeInspector.h include/QmitkModelViewSelectionConnector.h include/QmitkOverlayWidget.h include/QmitkNodeDetailsDialog.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..e836836b0a --- /dev/null +++ b/Modules/QtWidgets/include/QmitkAbstractMultiWidget.h @@ -0,0 +1,147 @@ +/*=================================================================== + +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 +#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 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 a 'QmitkAbstractMultiWidgetEditor'. +* +* The class uses the 'DisplayActionEventBroadcast' and 'DisplayActionEventHandler' classes to +* load a state machine and set an event configuration. +* +* Using the 'Synchronize' function the user can enable or disable the synchronization of display action events. +* See 'DisplayActionEventFunctions'-class for the different synchronized and non-synchronized functions used. +*/ +class MITKQTWIDGETS_EXPORT QmitkAbstractMultiWidget : public QWidget +{ + Q_OBJECT + +public: + + using RenderWindowWidgetPointer = std::shared_ptr; + using RenderWindowWidgetMap = std::map>; + using RenderWindowHash = QHash; + + 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(); + + virtual void InitializeMultiWidget() = 0; + virtual void MultiWidgetOpened() { } + virtual void MultiWidgetClosed() { } + + virtual void SetDataStorage(mitk::DataStorage* dataStorage); + mitk::DataStorage* GetDataStorage() const; + + int GetRowCount() const; + int GetColumnCount() const; + virtual void SetLayout(int row, int column); + + virtual void Synchronize(bool synchronized); + virtual void SetInteractionScheme(mitk::InteractionSchemeSwitcher::InteractionScheme scheme); + + 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; + + virtual void SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget); + RenderWindowWidgetPointer GetActiveRenderWindowWidget() const; + RenderWindowWidgetPointer GetFirstRenderWindowWidget() const; + RenderWindowWidgetPointer GetLastRenderWindowWidget() const; + + virtual QString GetNameFromIndex(int row, int column) const; + virtual QString GetNameFromIndex(size_t index) const; + + unsigned int GetNumberOfRenderWindowWidgets() const; + + void RequestUpdate(const QString& widgetName); + void RequestUpdateAll(); + void ForceImmediateUpdate(const QString& widgetName); + void ForceImmediateUpdateAll(); + + virtual void SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) = 0; + virtual const mitk::Point3D GetSelectedPosition(const QString& widgetName) const = 0; + +Q_SIGNALS: + + void ActiveRenderWindowChanged(); + +protected: + + virtual void AddRenderWindowWidget(const QString& widgetName, RenderWindowWidgetPointer renderWindowWidget); + virtual void RemoveRenderWindowWidget(); + +private: + + /** + * @brief This function will be called by the function 'SetLayout' and + * can be implemented and customized in the subclasses. + */ + virtual void SetLayoutImpl() = 0; + /** + * @brief This function will be called by the function 'Synchronize' and + * can be implemented and customized in the subclasses. + */ + virtual void SynchronizeImpl() = 0; + /** + * @brief This function will be called by the function 'SetInteractionScheme' and + * can be implemented and customized in the subclasses. + */ + virtual void SetInteractionSchemeImpl() = 0; + + struct Impl; + std::unique_ptr m_Impl; + +}; + +#endif // QMITKABSTRACTMULTIWIDGET_H diff --git a/Modules/QtWidgets/include/QmitkMultiWidgetConfigurationToolBar.h b/Modules/QtWidgets/include/QmitkMultiWidgetConfigurationToolBar.h index 89ca170d5b..647cea7d6f 100644 --- a/Modules/QtWidgets/include/QmitkMultiWidgetConfigurationToolBar.h +++ b/Modules/QtWidgets/include/QmitkMultiWidgetConfigurationToolBar.h @@ -1,62 +1,65 @@ /*=================================================================== 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 QMITKMULTIWIDGETCONFIGURATIONTOOLBAR_H #define QMITKMULTIWIDGETCONFIGURATIONTOOLBAR_H #include "MitkQtWidgetsExports.h" +// qt #include -// mitk qtwidgets -#include "QmitkMultiWidgetLayoutSelectionWidget.h" +class QmitkAbstractMultiWidget; +class QmitkMultiWidgetLayoutSelectionWidget; /** * @brief * * */ class MITKQTWIDGETS_EXPORT QmitkMultiWidgetConfigurationToolBar : public QToolBar { Q_OBJECT public: - QmitkMultiWidgetConfigurationToolBar(); + QmitkMultiWidgetConfigurationToolBar(QmitkAbstractMultiWidget* multiWidget); ~QmitkMultiWidgetConfigurationToolBar() override; Q_SIGNALS: void LayoutSet(int row, int column); void Synchronized(bool synchronized); protected Q_SLOTS: void OnSetLayout(); void OnSynchronize(); private: void InitializeToolBar();; void AddButtons(); + QmitkAbstractMultiWidget* m_MultiWidget; + QAction* m_SynchronizeAction; QmitkMultiWidgetLayoutSelectionWidget* m_LayoutSelectionPopup; }; #endif // QMITKMULTIWIDGETCONFIGURATIONTOOLBAR_H diff --git a/Modules/QtWidgets/include/QmitkMxNMultiWidget.h b/Modules/QtWidgets/include/QmitkMxNMultiWidget.h index f89321d5fb..24df9dcd01 100644 --- a/Modules/QtWidgets/include/QmitkMxNMultiWidget.h +++ b/Modules/QtWidgets/include/QmitkMxNMultiWidget.h @@ -1,153 +1,88 @@ /*=================================================================== 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 QMITKMXNMULTIWIDGET_H #define QMITKMXNMULTIWIDGET_H // qt widgets module #include "MitkQtWidgetsExports.h" -#include "QmitkRenderWindowWidget.h" +#include "QmitkAbstractMultiWidget.h" -// mitk core -#include -#include -#include -#include - -// qt -#include - -class QHBoxLayout; -class QVBoxLayout; class QGridLayout; -class QSpacerItem; -class QmitkRenderWindow; namespace mitk { class RenderingManager; } /** -* @brief The 'QmitkMxNMultiWidget' is a QWidget that is used to display multiple render windows at once. +* @brief The 'QmitkMxNMultiWidget' is a 'QmitkAbstractMultiWidget' 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. This * is done by using the 'ResetLayout'-function to define a layout. This will automatically add or remove * the appropriate number of render window widgets. -* Several functions exist to retrieve specific render window(s) (widgets) by their position or name. -* -* The class uses the 'DisplayActionEventBroadcast' and 'DisplayActionEventHandler' classes to -* load a state machine and set an event configuration. PACS mode is used per default. -* Using the 'Synchronize' function the user can enable or disable the synchronization of display action events. -* See 'DisplayActionEventFunctions'-class for the different synchronized and non-synchronized functions used. */ -class MITKQTWIDGETS_EXPORT QmitkMxNMultiWidget : public QWidget +class MITKQTWIDGETS_EXPORT QmitkMxNMultiWidget : public QmitkAbstractMultiWidget { Q_OBJECT public: - using RenderWindowWidgetPointer = std::shared_ptr; - using RenderWindowWidgetMap = std::map>; - using RenderWindowHash = QHash; - QmitkMxNMultiWidget(QWidget* parent = 0, - Qt::WindowFlags f = 0, - mitk::RenderingManager* renderingManager = nullptr, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard, - const QString& multiWidgetName = "mxnmulti"); + Qt::WindowFlags f = 0, + mitk::RenderingManager* renderingManager = nullptr, + mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard, + const QString& multiWidgetName = "mxnmulti"); virtual ~QmitkMxNMultiWidget() = default; - - 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); - - 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; - - unsigned int GetNumberOfRenderWindowWidgets() const; - - void RequestUpdate(const QString& widgetName); - void RequestUpdateAll(); - void ForceImmediateUpdate(const QString& widgetName); - void ForceImmediateUpdateAll(); - void ActivateAllCrosshairs(bool activate); - const mitk::Point3D GetSelectedPosition(const QString& widgetName) const; + virtual void InitializeMultiWidget() override; + virtual void MultiWidgetOpened() override; + virtual void MultiWidgetClosed() override; -public Q_SLOTS: + virtual void SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget) override; - void SetSelectedPosition(const QString& widgetName, const mitk::Point3D& newPosition); + virtual void SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) override; + virtual const mitk::Point3D GetSelectedPosition(const QString& widgetName) const override; - // mouse events - void wheelEvent(QWheelEvent* e) override; + void ActivateAllCrosshairs(bool activate); - void mousePressEvent(QMouseEvent* e) override; +public Q_SLOTS: - void moveEvent(QMoveEvent* e) override; + // mouse events + virtual void wheelEvent(QWheelEvent* e) override; + virtual void mousePressEvent(QMouseEvent* e) override; + virtual void moveEvent(QMoveEvent* e) override; Q_SIGNALS: void WheelMoved(QWheelEvent *); void Moved(); - void ActiveRenderWindowChanged(); private: - void InitializeGUI(); - void InitializeDisplayActionEventHandling(); + virtual void SetLayoutImpl() override; + virtual void SynchronizeImpl() override { } + virtual void SetInteractionSchemeImpl() override { } + void InitializeLayout(); void CreateRenderWindowWidget(); - void DestroyRenderWindowWidget(); void FillMultiWidgetLayout(); - QString GetNameFromIndex(int row, int column) const; - QString GetNameFromIndex(size_t index) const; - - QGridLayout* m_MxNMultiWidgetLayout; - RenderWindowWidgetMap m_RenderWindowWidgets; - - RenderWindowWidgetPointer m_ActiveRenderWindowWidget; - - int m_MultiWidgetRows; - int m_MultiWidgetColumns; - - 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; + QGridLayout* m_GridLayout; - mitk::DataStorage::Pointer m_DataStorage; }; #endif // QMITKMXNMULTIWIDGET_H diff --git a/Modules/QtWidgets/include/QmitkRenderWindowWidget.h b/Modules/QtWidgets/include/QmitkRenderWindowWidget.h index d316d399ad..ee59a1e945 100644 --- a/Modules/QtWidgets/include/QmitkRenderWindowWidget.h +++ b/Modules/QtWidgets/include/QmitkRenderWindowWidget.h @@ -1,115 +1,115 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERWINDOWWIDGET_H #define QMITKRENDERWINDOWWIDGET_H // qt widgets module #include "MitkQtWidgetsExports.h" #include "QmitkRenderWindow.h" // mitk core #include #include #include #include // qt -#include +#include #include #include /** * @brief The 'QmitkRenderWindowWidget' is a QFrame that holds a render window * and some associates properties, like a crosshair (pointset) and decorations. * Decorations are corner annotation (text and color) or background color and can be set using this class. -* The 'QmitkRenderWindowWidget' is used inside the 'QmitkMxNMultiWidget', where a map contains -* several render window widgets to create the MxN display. +* The 'QmitkRenderWindowWidget' is used inside a 'QmitkAbstractMultiWidget', where a map contains +* several render window widgets to create the multi widget display. */ class MITKQTWIDGETS_EXPORT QmitkRenderWindowWidget : public QFrame { Q_OBJECT public: QmitkRenderWindowWidget( QWidget* parent = nullptr, const QString& widgetName = "", mitk::DataStorage* dataStorage = nullptr, mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard ); virtual ~QmitkRenderWindowWidget(); void SetDataStorage(mitk::DataStorage* dataStorage); const QString& GetWidgetName() const { return m_WidgetName; }; QmitkRenderWindow* GetRenderWindow() const { return m_RenderWindow; }; mitk::SliceNavigationController* GetSliceNavigationController() const; void RequestUpdate(); void ForceImmediateUpdate(); void SetGradientBackgroundColors(const mitk::Color& upper, const mitk::Color& lower); void ShowGradientBackground(bool enable); std::pair GetGradientBackgroundColors() const { return m_GradientBackgroundColors; }; bool IsGradientBackgroundOn() const; void SetDecorationColor(const mitk::Color& color); mitk::Color GetDecorationColor() const { return m_DecorationColor; }; void ShowColoredRectangle(bool show); bool IsColoredRectangleVisible() const; void ShowCornerAnnotation(bool show); bool IsCornerAnnotationVisible() const; void SetCornerAnnotationText(const std::string& cornerAnnotation); std::string GetCornerAnnotationText() const; bool IsRenderWindowMenuActivated() const; void ActivateCrosshair(bool activate); Q_SIGNALS: void MouseEvent(QMouseEvent* e); private: void InitializeGUI(); void InitializeDecorations(); void SetCrosshair(mitk::Point3D selectedPoint); QString m_WidgetName; QHBoxLayout* m_Layout; mitk::DataStorage* m_DataStorage; QmitkRenderWindow* m_RenderWindow; mitk::RenderingManager::Pointer m_RenderingManager; mitk::BaseRenderer::RenderingMode::Type m_RenderingMode; mitk::DataNode::Pointer m_PointSetNode; mitk::PointSet::Pointer m_PointSet; std::pair m_GradientBackgroundColors; mitk::Color m_DecorationColor; vtkSmartPointer m_CornerAnnotation; }; #endif // QMITKRENDERWINDOWWIDGET_H diff --git a/Modules/QtWidgets/src/QmitkAbstractMultiWidget.cpp b/Modules/QtWidgets/src/QmitkAbstractMultiWidget.cpp new file mode 100644 index 0000000000..ba84f63462 --- /dev/null +++ b/Modules/QtWidgets/src/QmitkAbstractMultiWidget.cpp @@ -0,0 +1,371 @@ +/*=================================================================== + +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 + +// qt +#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; + + 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_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_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; +} + +int QmitkAbstractMultiWidget::GetRowCount() const +{ + return m_Impl->m_MultiWidgetRows; +} + +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); + SynchronizeImpl(); +} + +void QmitkAbstractMultiWidget::SetInteractionScheme(mitk::InteractionSchemeSwitcher::InteractionScheme scheme) +{ + auto interactionSchemeSwitcher = mitk::InteractionSchemeSwitcher::New(); + auto interactionEventHandler = GetInteractionEventHandler(); + try + { + interactionSchemeSwitcher->SetInteractionScheme(interactionEventHandler, scheme); + } + catch (const mitk::Exception&) + { + return; + } + + SetInteractionSchemeImpl(); +} + +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; + emit ActiveRenderWindowChanged(); +} + +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; + } +} + +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(); + } +} + +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 + RenderWindowWidgetPointer renderWindowWidgetToRemove = iterator->second; + disconnect(renderWindowWidgetToRemove.get(), 0, 0, 0); + + // erase the render window from the map + m_Impl->m_RenderWindowWidgets.erase(iterator); +} diff --git a/Modules/QtWidgets/src/QmitkMultiWidgetConfigurationToolBar.cpp b/Modules/QtWidgets/src/QmitkMultiWidgetConfigurationToolBar.cpp index e5a695957e..3cabf57423 100644 --- a/Modules/QtWidgets/src/QmitkMultiWidgetConfigurationToolBar.cpp +++ b/Modules/QtWidgets/src/QmitkMultiWidgetConfigurationToolBar.cpp @@ -1,82 +1,90 @@ /*=================================================================== 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 "QmitkMultiWidgetConfigurationToolBar.h" -QmitkMultiWidgetConfigurationToolBar::QmitkMultiWidgetConfigurationToolBar() - : QToolBar() +// mitk qt widgets module +#include "QmitkAbstractMultiWidget.h" +#include "QmitkMultiWidgetLayoutSelectionWidget.h" + +QmitkMultiWidgetConfigurationToolBar::QmitkMultiWidgetConfigurationToolBar(QmitkAbstractMultiWidget* multiWidget) + : QToolBar(multiWidget) + , m_MultiWidget(multiWidget) { QToolBar::setOrientation(Qt::Vertical); QToolBar::setIconSize(QSize(17, 17)); InitializeToolBar(); } QmitkMultiWidgetConfigurationToolBar::~QmitkMultiWidgetConfigurationToolBar() { // nothing here } void QmitkMultiWidgetConfigurationToolBar::InitializeToolBar() { // create popup to show a widget to modify the multi widget layout m_LayoutSelectionPopup = new QmitkMultiWidgetLayoutSelectionWidget(this); m_LayoutSelectionPopup->hide(); AddButtons(); connect(m_LayoutSelectionPopup, &QmitkMultiWidgetLayoutSelectionWidget::LayoutSet, this, &QmitkMultiWidgetConfigurationToolBar::LayoutSet); } void QmitkMultiWidgetConfigurationToolBar::AddButtons() { QAction* setLayoutAction = new QAction(QIcon(":/Qmitk/mwLayout.png"), tr("Set multi widget layout"), this); connect(setLayoutAction, &QAction::triggered, this, &QmitkMultiWidgetConfigurationToolBar::OnSetLayout); QToolBar::addAction(setLayoutAction); m_SynchronizeAction = new QAction(QIcon(":/Qmitk/mwSynchronized.png"), tr("Desynchronize render windows"), this); m_SynchronizeAction->setCheckable(true); m_SynchronizeAction->setChecked(true); connect(m_SynchronizeAction, &QAction::triggered, this, &QmitkMultiWidgetConfigurationToolBar::OnSynchronize); QToolBar::addAction(m_SynchronizeAction); } void QmitkMultiWidgetConfigurationToolBar::OnSetLayout() { - m_LayoutSelectionPopup->setWindowFlags(Qt::Popup); - m_LayoutSelectionPopup->move(this->cursor().pos().x() - m_LayoutSelectionPopup->width(), this->cursor().pos().y()); - m_LayoutSelectionPopup->show(); + if (nullptr != m_MultiWidget) + { + m_LayoutSelectionPopup->setWindowFlags(Qt::Popup); + m_LayoutSelectionPopup->move(this->cursor().pos().x() - m_LayoutSelectionPopup->width(), this->cursor().pos().y()); + m_LayoutSelectionPopup->show(); + } } void QmitkMultiWidgetConfigurationToolBar::OnSynchronize() { bool synchronized = m_SynchronizeAction->isChecked(); if (synchronized) { m_SynchronizeAction->setIcon(QIcon(":/Qmitk/mwSynchronized.png")); m_SynchronizeAction->setText(tr("Desynchronize render windows")); } else { m_SynchronizeAction->setIcon(QIcon(":/Qmitk/mwDesynchronized.png")); m_SynchronizeAction->setText(tr("Synchronize render windows")); } m_SynchronizeAction->setChecked(synchronized); emit Synchronized(synchronized); } diff --git a/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp b/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp index 981130faeb..432b536bca 100644 --- a/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp +++ b/Modules/QtWidgets/src/QmitkMxNMultiWidget.cpp @@ -1,470 +1,211 @@ /*=================================================================== 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 "QmitkMxNMultiWidget.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 +#include "QmitkRenderWindowWidget.h" // qt #include QmitkMxNMultiWidget::QmitkMxNMultiWidget(QWidget* parent, - Qt::WindowFlags f/* = 0*/, - mitk::RenderingManager* renderingManager/* = nullptr*/, - mitk::BaseRenderer::RenderingMode::Type renderingMode/* = mitk::BaseRenderer::RenderingMode::Standard*/, - const QString& multiWidgetName/* = "mxnmulti"*/) - : QWidget(parent, f) - , m_MxNMultiWidgetLayout(nullptr) - , m_MultiWidgetRows(0) - , m_MultiWidgetColumns(0) - , m_PlaneMode(0) - , m_RenderingManager(renderingManager) - , m_RenderingMode(renderingMode) - , m_MultiWidgetName(multiWidgetName) - , m_DisplayActionEventBroadcast(nullptr) - , m_DisplayActionEventHandler(nullptr) - , m_DataStorage(nullptr) -{ - InitializeGUI(); - InitializeDisplayActionEventHandling(); - resize(QSize(364, 477).expandedTo(minimumSizeHint())); -} - -void QmitkMxNMultiWidget::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 QmitkMxNMultiWidget::InitializeRenderWindowWidgets() -{ - m_MultiWidgetRows = 1; - m_MultiWidgetColumns = 1; - CreateRenderWindowWidget(); - InitializeGUI(); -} - -void QmitkMxNMultiWidget::ResetLayout(int row, int column) -{ - m_MultiWidgetRows = row; - m_MultiWidgetColumns = column; - - int requiredRenderWindowWidgets = m_MultiWidgetRows * m_MultiWidgetColumns; - int existingRenderWindowWidgets = m_RenderWindowWidgets.size(); - - int difference = requiredRenderWindowWidgets - existingRenderWindowWidgets; - while(0 < difference) - { - // more render window widgets needed - CreateRenderWindowWidget(); - --difference; - } - while(0 > difference) - { - // less render window widgets needed - DestroyRenderWindowWidget(); - ++difference; - } - - InitializeGUI(); -} - -void QmitkMxNMultiWidget::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); -} - -QmitkMxNMultiWidget::RenderWindowWidgetMap QmitkMxNMultiWidget::GetRenderWindowWidgets() const + Qt::WindowFlags f/* = 0*/, + mitk::RenderingManager* renderingManager/* = nullptr*/, + mitk::BaseRenderer::RenderingMode::Type renderingMode/* = mitk::BaseRenderer::RenderingMode::Standard*/, + const QString& multiWidgetName/* = "mxnmulti"*/) + : QmitkAbstractMultiWidget(parent, f, renderingManager, renderingMode, multiWidgetName) + , m_GridLayout(nullptr) { - return m_RenderWindowWidgets; + // nothing here } -QmitkMxNMultiWidget::RenderWindowWidgetPointer QmitkMxNMultiWidget::GetRenderWindowWidget(int row, int column) const +void QmitkMxNMultiWidget::InitializeMultiWidget() { - return GetRenderWindowWidget(GetNameFromIndex(row, column)); + SetLayout(1, 1); } -QmitkMxNMultiWidget::RenderWindowWidgetPointer QmitkMxNMultiWidget::GetRenderWindowWidget(const QString& widgetName) const +void QmitkMxNMultiWidget::MultiWidgetOpened() { - RenderWindowWidgetMap::const_iterator it = m_RenderWindowWidgets.find(widgetName); - if (it != m_RenderWindowWidgets.end()) - { - return it->second; - } - - return nullptr; + ActivateAllCrosshairs(true); } -QmitkMxNMultiWidget::RenderWindowHash QmitkMxNMultiWidget::GetRenderWindows() const +void QmitkMxNMultiWidget::MultiWidgetClosed() { - RenderWindowHash result; - // create QHash on demand - auto renderWindowWidgets = GetRenderWindowWidgets(); - for (const auto& renderWindowWidget : renderWindowWidgets) - { - result.insert(renderWindowWidget.first, renderWindowWidget.second->GetRenderWindow()); - } - - return result; -} - -QmitkRenderWindow* QmitkMxNMultiWidget::GetRenderWindow(int row, int column) const -{ - return GetRenderWindow(GetNameFromIndex(row, column)); -} - -QmitkRenderWindow* QmitkMxNMultiWidget::GetRenderWindow(const QString& widgetName) const -{ - RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); - if (nullptr != renderWindowWidget) - { - return renderWindowWidget->GetRenderWindow(); - } - - return nullptr; + ActivateAllCrosshairs(false); } void QmitkMxNMultiWidget::SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget) { - if (m_ActiveRenderWindowWidget == activeRenderWindowWidget) + auto currentActiveRenderWindowWidget = GetActiveRenderWindowWidget(); + if (currentActiveRenderWindowWidget == activeRenderWindowWidget) { return; } // reset the decoration color of the previously active render window widget - if (nullptr != m_ActiveRenderWindowWidget) + if (nullptr != currentActiveRenderWindowWidget) { - m_ActiveRenderWindowWidget->setStyleSheet("border: 2px solid white"); + currentActiveRenderWindowWidget->setStyleSheet("border: 2px solid white"); } // set the new decoration color of the currently active render window widget - m_ActiveRenderWindowWidget = activeRenderWindowWidget; - if (nullptr != m_ActiveRenderWindowWidget) + if (nullptr != activeRenderWindowWidget) { - m_ActiveRenderWindowWidget->setStyleSheet("border: 2px solid #FF6464"); + activeRenderWindowWidget->setStyleSheet("border: 2px solid #FF6464"); } - - emit ActiveRenderWindowChanged(); -} - -QmitkMxNMultiWidget::RenderWindowWidgetPointer QmitkMxNMultiWidget::GetActiveRenderWindowWidget() const -{ - return m_ActiveRenderWindowWidget; -} - -QmitkMxNMultiWidget::RenderWindowWidgetPointer QmitkMxNMultiWidget::GetFirstRenderWindowWidget() const -{ - if (!m_RenderWindowWidgets.empty()) - { - return m_RenderWindowWidgets.begin()->second; - } - else - { - return nullptr; - } + QmitkAbstractMultiWidget::SetActiveRenderWindowWidget(activeRenderWindowWidget); } -QmitkMxNMultiWidget::RenderWindowWidgetPointer QmitkMxNMultiWidget::GetLastRenderWindowWidget() const +void QmitkMxNMultiWidget::SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) { - if (!m_RenderWindowWidgets.empty()) + RenderWindowWidgetPointer renderWindowWidget; + if (widgetName.isNull()) { - return m_RenderWindowWidgets.rbegin()->second; + renderWindowWidget = GetActiveRenderWindowWidget(); } else { - return nullptr; - } -} - -unsigned int QmitkMxNMultiWidget::GetNumberOfRenderWindowWidgets() const -{ - return m_RenderWindowWidgets.size(); -} - -void QmitkMxNMultiWidget::RequestUpdate(const QString& widgetName) -{ - RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); - if (nullptr != renderWindowWidget) - { - return renderWindowWidget->RequestUpdate(); - } -} - -void QmitkMxNMultiWidget::RequestUpdateAll() -{ - for (const auto& renderWindowWidget : m_RenderWindowWidgets) - { - renderWindowWidget.second->RequestUpdate(); + renderWindowWidget = GetRenderWindowWidget(widgetName); } -} -void QmitkMxNMultiWidget::ForceImmediateUpdate(const QString& widgetName) -{ - RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); if (nullptr != renderWindowWidget) { - renderWindowWidget->ForceImmediateUpdate(); - } -} - -void QmitkMxNMultiWidget::ForceImmediateUpdateAll() -{ - for (const auto& renderWindowWidget : m_RenderWindowWidgets) - { - renderWindowWidget.second->ForceImmediateUpdate(); + renderWindowWidget->GetSliceNavigationController()->SelectSliceByPoint(newPosition); + renderWindowWidget->RequestUpdate(); + return; } -} -void QmitkMxNMultiWidget::ActivateAllCrosshairs(bool activate) -{ - for (const auto& renderWindowWidget : m_RenderWindowWidgets) - { - renderWindowWidget.second->ActivateCrosshair(activate); - } + MITK_ERROR << "Position can not be set for an unknown render window widget."; } const mitk::Point3D QmitkMxNMultiWidget::GetSelectedPosition(const QString& /*widgetName*/) const { // see T26208 return mitk::Point3D(); } -////////////////////////////////////////////////////////////////////////// -// PUBLIC SLOTS -////////////////////////////////////////////////////////////////////////// -void QmitkMxNMultiWidget::SetSelectedPosition(const QString& widgetName, const mitk::Point3D& newPosition) +void QmitkMxNMultiWidget::ActivateAllCrosshairs(bool activate) { - RenderWindowWidgetPointer renderWindowWidget; - if (widgetName.isNull()) - { - renderWindowWidget = GetActiveRenderWindowWidget(); - } - else - { - renderWindowWidget = GetRenderWindowWidget(widgetName); - } - - if (nullptr != renderWindowWidget) + auto renderWindowWidgets = GetRenderWindowWidgets(); + for (const auto& renderWindowWidget : renderWindowWidgets) { - renderWindowWidget->GetSliceNavigationController()->SelectSliceByPoint(newPosition); - renderWindowWidget->RequestUpdate(); - return; + renderWindowWidget.second->ActivateCrosshair(activate); } - - MITK_ERROR << "Position can not be set for an unknown render window widget."; } ////////////////////////////////////////////////////////////////////////// +// PUBLIC SLOTS // MOUSE EVENTS ////////////////////////////////////////////////////////////////////////// void QmitkMxNMultiWidget::wheelEvent(QWheelEvent* e) { emit WheelMoved(e); } void QmitkMxNMultiWidget::mousePressEvent(QMouseEvent* e) { if (QEvent::MouseButtonPress != e->type()) { return; } auto renderWindowWidget = dynamic_cast(this->sender()); if (nullptr == renderWindowWidget) { return; } auto renderWindowWidgetPointer = GetRenderWindowWidget(renderWindowWidget->GetWidgetName()); SetActiveRenderWindowWidget(renderWindowWidgetPointer); } void QmitkMxNMultiWidget::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 QmitkMxNMultiWidget::InitializeGUI() +void QmitkMxNMultiWidget::SetLayoutImpl() { - delete m_MxNMultiWidgetLayout; - m_MxNMultiWidgetLayout = new QGridLayout(this); - m_MxNMultiWidgetLayout->setContentsMargins(0, 0, 0, 0); - setLayout(m_MxNMultiWidgetLayout); - - FillMultiWidgetLayout(); + int requiredRenderWindowWidgets = GetRowCount() * GetColumnCount(); + int existingRenderWindowWidgets = GetRenderWindowWidgets().size(); - auto firstRenderWindowWidget = GetFirstRenderWindowWidget(); - if (nullptr != firstRenderWindowWidget) + int difference = requiredRenderWindowWidgets - existingRenderWindowWidgets; + while (0 < difference) { - SetActiveRenderWindowWidget(firstRenderWindowWidget); + // more render window widgets needed + CreateRenderWindowWidget(); + --difference; + } + while (0 > difference) + { + // less render window widgets needed + RemoveRenderWindowWidget(); + ++difference; } + + InitializeLayout(); } -void QmitkMxNMultiWidget::InitializeDisplayActionEventHandling() +void QmitkMxNMultiWidget::InitializeLayout() { - m_DisplayActionEventBroadcast = mitk::DisplayActionEventBroadcast::New(); - m_DisplayActionEventBroadcast->LoadStateMachine("DisplayInteraction.xml"); - m_DisplayActionEventBroadcast->SetEventConfig("DisplayConfigPACS.xml"); + delete m_GridLayout; + m_GridLayout = new QGridLayout(this); + m_GridLayout->setContentsMargins(0, 0, 0, 0); + setLayout(m_GridLayout); - m_DisplayActionEventHandler = std::make_unique(); - m_DisplayActionEventHandler->SetObservableBroadcast(m_DisplayActionEventBroadcast); + FillMultiWidgetLayout(); + resize(QSize(364, 477).expandedTo(minimumSizeHint())); - Synchronize(true); + auto firstRenderWindowWidget = GetFirstRenderWindowWidget(); + if (nullptr != firstRenderWindowWidget) + { + SetActiveRenderWindowWidget(firstRenderWindowWidget); + } } void QmitkMxNMultiWidget::CreateRenderWindowWidget() { // create the render window widget and connect signal / slot - QString renderWindowWidgetName = GetNameFromIndex(m_RenderWindowWidgets.size()); - RenderWindowWidgetPointer renderWindowWidget = std::make_shared(this, renderWindowWidgetName, m_DataStorage); + QString renderWindowWidgetName = GetNameFromIndex(GetNumberOfRenderWindowWidgets()); + RenderWindowWidgetPointer renderWindowWidget = std::make_shared(this, renderWindowWidgetName, GetDataStorage()); renderWindowWidget->SetCornerAnnotationText(renderWindowWidgetName.toStdString()); - connect(renderWindowWidget.get(), &QmitkRenderWindowWidget::MouseEvent, - this, &QmitkMxNMultiWidget::mousePressEvent); - // store the newly created render window widget with the UID - m_RenderWindowWidgets.insert(std::make_pair(renderWindowWidgetName, renderWindowWidget)); -} + connect(renderWindowWidget.get(), &QmitkRenderWindowWidget::MouseEvent, this, &QmitkMxNMultiWidget::mousePressEvent); -void QmitkMxNMultiWidget::DestroyRenderWindowWidget() -{ - auto iterator = m_RenderWindowWidgets.find(GetNameFromIndex(m_RenderWindowWidgets.size() - 1)); - if (iterator == m_RenderWindowWidgets.end()) - { - return; - } - - // disconnect each signal of this render window widget - RenderWindowWidgetPointer renderWindowWidgetToRemove = iterator->second; - disconnect(renderWindowWidgetToRemove.get(), 0, 0, 0); - - // erase the render window from the map - m_RenderWindowWidgets.erase(iterator); + AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget); } void QmitkMxNMultiWidget::FillMultiWidgetLayout() { - for (int row = 0; row < m_MultiWidgetRows; ++row) + for (int row = 0; row < GetRowCount(); ++row) { - for (int column = 0; column < m_MultiWidgetColumns; ++column) + for (int column = 0; column < GetColumnCount(); ++column) { RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(row, column); if (nullptr != renderWindowWidget) { - m_MxNMultiWidgetLayout->addWidget(renderWindowWidget.get(), row, column); + m_GridLayout->addWidget(renderWindowWidget.get(), row, column); } } } } - -QString QmitkMxNMultiWidget::GetNameFromIndex(int row, int column) const -{ - if (0 <= row && m_MultiWidgetRows > row && 0 <= column && m_MultiWidgetColumns > column) - { - return GetNameFromIndex(row * m_MultiWidgetColumns + column); - } - - return QString(); -} - -QString QmitkMxNMultiWidget::GetNameFromIndex(size_t index) const -{ - if (index <= m_RenderWindowWidgets.size()) - { - return m_MultiWidgetName + ".widget" + QString::number(index); - } - - return QString(); -} diff --git a/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp b/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp index 60342c3403..219f7e0d2b 100644 --- a/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp +++ b/Modules/QtWidgets/src/QmitkRenderWindowWidget.cpp @@ -1,247 +1,244 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRenderWindowWidget.h" -// mitk qt widgets -#include - // vtk #include QmitkRenderWindowWidget::QmitkRenderWindowWidget(QWidget* parent/* = nullptr*/, const QString& widgetName/* = ""*/, mitk::DataStorage* dataStorage/* = nullptr*/, mitk::BaseRenderer::RenderingMode::Type renderingMode/* = mitk::BaseRenderer::RenderingMode::Standard*/) : QFrame(parent) , m_WidgetName(widgetName) , m_DataStorage(dataStorage) , m_RenderWindow(nullptr) , m_RenderingMode(renderingMode) , m_PointSetNode(nullptr) , m_PointSet(nullptr) { InitializeGUI(); } QmitkRenderWindowWidget::~QmitkRenderWindowWidget() { auto sliceNavigationController = m_RenderWindow->GetSliceNavigationController(); if (nullptr != sliceNavigationController) { sliceNavigationController->SetCrosshairEvent.RemoveListener(mitk::MessageDelegate1(this, &QmitkRenderWindowWidget::SetCrosshair)); } if (nullptr != m_DataStorage) { m_DataStorage->Remove(m_PointSetNode); } } void QmitkRenderWindowWidget::SetDataStorage(mitk::DataStorage* dataStorage) { if (dataStorage == m_DataStorage) { return; } m_DataStorage = dataStorage; if (nullptr != m_RenderWindow) { mitk::BaseRenderer::GetInstance(m_RenderWindow->GetRenderWindow())->SetDataStorage(dataStorage); } } mitk::SliceNavigationController* QmitkRenderWindowWidget::GetSliceNavigationController() const { return m_RenderWindow->GetSliceNavigationController(); } void QmitkRenderWindowWidget::RequestUpdate() { m_RenderingManager->RequestUpdate(m_RenderWindow->GetRenderWindow()); } void QmitkRenderWindowWidget::ForceImmediateUpdate() { m_RenderingManager->ForceImmediateUpdate(m_RenderWindow->GetRenderWindow()); } void QmitkRenderWindowWidget::SetGradientBackgroundColors(const mitk::Color& upper, const mitk::Color& lower) { vtkRenderer* vtkRenderer = m_RenderWindow->GetRenderer()->GetVtkRenderer(); if (nullptr == vtkRenderer) { return; } m_GradientBackgroundColors.first = upper; m_GradientBackgroundColors.second = lower; vtkRenderer->SetBackground(lower[0], lower[1], lower[2]); vtkRenderer->SetBackground2(upper[0], upper[1], upper[2]); ShowGradientBackground(true); } void QmitkRenderWindowWidget::ShowGradientBackground(bool show) { m_RenderWindow->GetRenderer()->GetVtkRenderer()->SetGradientBackground(show); } bool QmitkRenderWindowWidget::IsGradientBackgroundOn() const { return m_RenderWindow->GetRenderer()->GetVtkRenderer()->GetGradientBackground(); } void QmitkRenderWindowWidget::SetDecorationColor(const mitk::Color& color) { m_DecorationColor = color; m_CornerAnnotation->GetTextProperty()->SetColor(color[0], color[1], color[2]); } void QmitkRenderWindowWidget::ShowColoredRectangle(bool show) { // Not implemented for now. Colored rectangle is defined via qt border stylesheet } bool QmitkRenderWindowWidget::IsColoredRectangleVisible() const { return false; } void QmitkRenderWindowWidget::ShowCornerAnnotation(bool show) { m_CornerAnnotation->SetVisibility(show); } bool QmitkRenderWindowWidget::IsCornerAnnotationVisible() const { return m_CornerAnnotation->GetVisibility() > 0; } void QmitkRenderWindowWidget::SetCornerAnnotationText(const std::string& cornerAnnotation) { m_CornerAnnotation->SetText(0, cornerAnnotation.c_str()); } std::string QmitkRenderWindowWidget::GetCornerAnnotationText() const { return std::string(m_CornerAnnotation->GetText(0)); } bool QmitkRenderWindowWidget::IsRenderWindowMenuActivated() const { return m_RenderWindow->GetActivateMenuWidgetFlag(); } void QmitkRenderWindowWidget::ActivateCrosshair(bool activate) { if (nullptr == m_DataStorage) { return; } if (activate) { try { m_DataStorage->Add(m_PointSetNode); } catch(std::invalid_argument& /*e*/) { // crosshair already existing return; } } else { m_DataStorage->Remove(m_PointSetNode); } } void QmitkRenderWindowWidget::InitializeGUI() { m_Layout = new QHBoxLayout(this); m_Layout->setMargin(0); setLayout(m_Layout); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // create render window for this render window widget m_RenderingManager = mitk::RenderingManager::GetInstance(); //m_RenderingManager = mitk::RenderingManager::New(); m_RenderingManager->SetDataStorage(m_DataStorage); m_RenderWindow = new QmitkRenderWindow(this, m_WidgetName, nullptr, m_RenderingManager, m_RenderingMode); m_RenderWindow->SetLayoutIndex(mitk::SliceNavigationController::Sagittal); m_RenderWindow->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); m_RenderWindow->GetSliceNavigationController()->SetRenderingManager(m_RenderingManager); m_RenderWindow->GetSliceNavigationController()->SetCrosshairEvent.AddListener(mitk::MessageDelegate1(this, &QmitkRenderWindowWidget::SetCrosshair)); connect(m_RenderWindow, &QVTKOpenGLWidget::mouseEvent, this, &QmitkRenderWindowWidget::MouseEvent); mitk::TimeGeometry::ConstPointer timeGeometry = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()); m_RenderingManager->InitializeViews(timeGeometry); m_Layout->addWidget(m_RenderWindow); // add point set as a crosshair m_PointSetNode = mitk::DataNode::New(); m_PointSetNode->SetProperty("name", mitk::StringProperty::New("Crosshair of render window " + m_WidgetName.toStdString())); m_PointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true)); // crosshair-node should typically be invisible // set the crosshair only visible for this specific renderer m_PointSetNode->SetBoolProperty("fixedLayer", true, m_RenderWindow->GetRenderer()); m_PointSetNode->SetVisibility(true, m_RenderWindow->GetRenderer()); m_PointSetNode->SetVisibility(false); m_PointSet = mitk::PointSet::New(); m_PointSetNode->SetData(m_PointSet); // set colors and corner annotation InitializeDecorations(); } void QmitkRenderWindowWidget::InitializeDecorations() { vtkRenderer* vtkRenderer = m_RenderWindow->GetRenderer()->GetVtkRenderer(); if (nullptr == vtkRenderer) { return; } // initialize background color gradients float black[3] = { 0.0f, 0.0f, 0.0f }; SetGradientBackgroundColors(black, black); // initialize decoration color, rectangle and annotation text float white[3] = { 1.0f, 1.0f, 1.0f }; m_DecorationColor = white; setStyleSheet("border: 2px solid white"); m_CornerAnnotation = vtkSmartPointer::New(); m_CornerAnnotation->SetText(0, "Sagittal"); m_CornerAnnotation->SetMaximumFontSize(12); m_CornerAnnotation->GetTextProperty()->SetColor(m_DecorationColor[0], m_DecorationColor[1], m_DecorationColor[2]); if (0 == vtkRenderer->HasViewProp(m_CornerAnnotation)) { vtkRenderer->AddViewProp(m_CornerAnnotation); } } void QmitkRenderWindowWidget::SetCrosshair(mitk::Point3D selectedPoint) { m_PointSet->SetPoint(1, selectedPoint, 0); mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow->GetRenderWindow()); } diff --git a/Plugins/org.mitk.gui.qt.common/files.cmake b/Plugins/org.mitk.gui.qt.common/files.cmake index c3b68caa5d..67e72c7578 100755 --- a/Plugins/org.mitk.gui.qt.common/files.cmake +++ b/Plugins/org.mitk.gui.qt.common/files.cmake @@ -1,69 +1,72 @@ 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 + QmitkMultiWidgetDecorationManager.cpp QmitkNodeSelectionPreferenceHelper.cpp QmitkNodeSelectionButton.cpp QmitkSimpleTextOverlayWidget.cpp ) set(INTERNAL_CPP_FILES QmitkCommonActivator.cpp QmitkDataNodeItemModel.cpp QmitkDataNodeSelection.cpp QmitkViewCoordinator.cpp QmitkNodeSelectionConstants.cpp QmitkNodeSelectionPreferencePage.cpp QmitkNodeSelectionListItemWidget.cpp ) set(UI_FILES src/QmitkSingleNodeSelectionWidget.ui src/QmitkMultiNodeSelectionWidget.ui src/QmitkNodeSelectionDialog.ui src/internal/QmitkNodeSelectionPreferencePage.ui src/internal/QmitkNodeSelectionListItemWidget.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/QmitkSimpleTextOverlayWidget.h src/internal/QmitkCommonActivator.h src/internal/QmitkNodeSelectionPreferencePage.h src/internal/QmitkNodeSelectionListItemWidget.h ) set(CACHED_RESOURCE_FILES plugin.xml resources/times.svg ) set(QRC_FILES resources/common.qrc ) 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..501701bec0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractMultiWidgetEditor.cpp @@ -0,0 +1,241 @@ +/*=================================================================== + +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" + +// mitk qt widgets module +#include +#include + +// mitk gui qt common plugin +#include "QmitkMultiWidgetDecorationManager.h" + +// berry +#include + +const QString QmitkAbstractMultiWidgetEditor::EDITOR_ID = "org.mitk.editors.abstractmultiwidget"; + +struct QmitkAbstractMultiWidgetEditor::Impl final +{ + Impl(); + ~Impl() = default; + + 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 m_Impl->m_MultiWidgetDecorationManager->IsDecorationVisible(decoration); +} + +QStringList QmitkAbstractMultiWidgetEditor::GetDecorations() const +{ + return m_Impl->m_MultiWidgetDecorationManager->GetDecorations(); +} + +berry::IPartListener::Events::Types QmitkAbstractMultiWidgetEditor::GetPartEventTypes() const +{ + return Events::CLOSED | Events::OPENED; +} + +void QmitkAbstractMultiWidgetEditor::PartOpened(const berry::IWorkbenchPartReference::Pointer& partRef) +{ + if (partRef->GetId() == QmitkAbstractMultiWidgetEditor::EDITOR_ID) + { + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) + { + multiWidget->MultiWidgetOpened(); + } + } +} + +void QmitkAbstractMultiWidgetEditor::PartClosed(const berry::IWorkbenchPartReference::Pointer& partRef) +{ + if (partRef->GetId() == QmitkAbstractMultiWidgetEditor::EDITOR_ID) + { + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) + { + multiWidget->MultiWidgetClosed(); + } + } +} + +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; + m_Impl->m_MultiWidgetDecorationManager.reset(new QmitkMultiWidgetDecorationManager(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::OnLayoutSet(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); + } + } + + void QmitkAbstractMultiWidgetEditor::OnInteractionSchemeChanged(mitk::InteractionSchemeSwitcher::InteractionScheme scheme) + { + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) + { + multiWidget->SetInteractionScheme(scheme); + } + } 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..355e2b87d3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractMultiWidgetEditor.h @@ -0,0 +1,136 @@ +/*=================================================================== + +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 + +// mitk core +#include + +// berry +#include + +// c++ +#include + +class QmitkAbstractMultiWidget; + +class MITK_QT_COMMON QmitkAbstractMultiWidgetEditor : public QmitkAbstractRenderEditor, public berry::IPartListener +{ + Q_OBJECT + +public: + + berryObjectMacro(QmitkAbstractMultiWidgetEditor, QmitkAbstractRenderEditor, IPartListener) + + static const QString EDITOR_ID; + + 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 + */ + virtual mitk::Point3D GetSelectedPosition(const QString& id = QString()) const override; + /** + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart + */ + virtual 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 Overridden from berry::IPartListener + */ + virtual berry::IPartListener::Events::Types GetPartEventTypes() const override; + /** + * @brief Overridden from berry::IPartListener + */ + virtual void PartOpened(const berry::IWorkbenchPartReference::Pointer& partRef) override; + /** + * @brief Overridden from berry::IPartListener + */ + virtual void PartClosed(const berry::IWorkbenchPartReference::Pointer& partRef) 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 function 'SetLayout' of the multi widget where + * custom behavior can be implemented. + * Finally 'FirePropertyChange' is called to inform the workbench about an input change. + */ + virtual void OnLayoutSet(int row, int column); + virtual void OnSynchronize(bool synchronized); + virtual void OnInteractionSchemeChanged(mitk::InteractionSchemeSwitcher::InteractionScheme scheme); + +private: + + struct Impl; + std::unique_ptr m_Impl; + +}; + +#endif // QMITKABSTRACTMULTIWIDGETEDITOR_H diff --git a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMultiWidgetDecorationManager.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiWidgetDecorationManager.cpp similarity index 87% rename from Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMultiWidgetDecorationManager.cpp rename to Plugins/org.mitk.gui.qt.common/src/QmitkMultiWidgetDecorationManager.cpp index 6fe8154201..b152b3f85b 100644 --- a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMultiWidgetDecorationManager.cpp +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiWidgetDecorationManager.cpp @@ -1,456 +1,461 @@ /*=================================================================== 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 "QmitkMultiWidgetDecorationManager.h" -// org_mitk_gui_common +// org mitk gui common plugin #include -// mitk annotation +// mitk annotation module #include +// mitk qt widgets module +#include + // vtk #include // qt #include -QmitkMultiWidgetDecorationManager::QmitkMultiWidgetDecorationManager(QmitkMxNMultiWidget* mxnMultiWidget) - : m_MxNMultiWidget(mxnMultiWidget) +QmitkMultiWidgetDecorationManager::QmitkMultiWidgetDecorationManager(QmitkAbstractMultiWidget* multiWidget) + : m_MultiWidget(multiWidget) , m_LogoAnnotation(mitk::LogoAnnotation::New()) -{} +{ + // nothing here +} void QmitkMultiWidgetDecorationManager::DecorationPreferencesChanged(const berry::IBerryPreferences* preferences) { - // Enable change of logo. If no DepartmentLogo was set explicitly, MITK Logo is used. + // Enable change of logo. If no DepartmentLogo was set explicitly, MBILogo is used. // Set new department logo by prefs->Set("DepartmentLogo", "PathToImage"); // If no logo was set for this plug-in specifically, walk the parent preference nodes // and lookup a logo value there. // Disable the logo first, otherwise setting a new logo will have no effect due to how mitkManufacturerLogo works ShowLogo(false); - SetupLogo(qPrintable(":/org.mitk.gui.qt.mxnmultiwidgeteditor/defaultWatermark.png")); + SetupLogo(qPrintable(":/org.mitk.gui.qt.stdmultiwidgeteditor/defaultWatermark.png")); ShowLogo(true); const berry::IPreferences* currentNode = preferences; while (currentNode) { bool logoFound = false; foreach(const QString& key, currentNode->Keys()) { if (key == "DepartmentLogo") { ShowLogo(false); QString departmentLogoLocation = currentNode->Get("DepartmentLogo", ""); if (!departmentLogoLocation.isEmpty()) { SetupLogo(qPrintable(departmentLogoLocation)); ShowLogo(true); } logoFound = true; break; } } if (logoFound) { break; } currentNode = currentNode->Parent().GetPointer(); } QmitkMultiWidgetDecorationManager::Colormap colormap = static_cast(preferences->GetInt("Render window widget colormap", 0)); SetColormap(colormap); // show colored rectangle ShowAllColoredRectangles(true); // show corner annotations ShowAllCornerAnnotations(true); } void QmitkMultiWidgetDecorationManager::ShowDecorations(bool show, const QStringList& decorations) { - if (nullptr != m_MxNMultiWidget) + if (nullptr != m_MultiWidget) { return; } if (decorations.isEmpty() || decorations.contains(mitk::IRenderWindowPart::DECORATION_BORDER)) { ShowAllColoredRectangles(show); } if (decorations.isEmpty() || decorations.contains(mitk::IRenderWindowPart::DECORATION_LOGO)) { ShowLogo(show); } if (decorations.isEmpty() || decorations.contains(mitk::IRenderWindowPart::DECORATION_MENU)) { - //m_MxNMultiWidget->ActivateAllRenderWindowMenus(show); + //m_MultiWidget->ActivateAllRenderWindowMenus(show); } if (decorations.isEmpty() || decorations.contains(mitk::IRenderWindowPart::DECORATION_BACKGROUND)) { ShowAllGradientBackgrounds(show); } if (decorations.isEmpty() || decorations.contains(mitk::IRenderWindowPart::DECORATION_CORNER_ANNOTATION)) { ShowAllCornerAnnotations(show); } } bool QmitkMultiWidgetDecorationManager::IsDecorationVisible(const QString& decoration) const { if (mitk::IRenderWindowPart::DECORATION_BORDER == decoration) { return AreAllColoredRectanglesVisible(); } else if (mitk::IRenderWindowPart::DECORATION_LOGO == decoration) { return IsLogoVisible(); } else if (mitk::IRenderWindowPart::DECORATION_MENU == decoration) { //return IsMenuWidgetEnabled(); } else if (mitk::IRenderWindowPart::DECORATION_BACKGROUND == decoration) { return AreAllGradientBackgroundsOn(); } else if (mitk::IRenderWindowPart::DECORATION_CORNER_ANNOTATION == decoration) { return AreAllCornerAnnotationsVisible(); } return false; } QStringList QmitkMultiWidgetDecorationManager::GetDecorations() const { QStringList decorations; decorations << mitk::IRenderWindowPart::DECORATION_BORDER << mitk::IRenderWindowPart::DECORATION_LOGO << mitk::IRenderWindowPart::DECORATION_MENU << mitk::IRenderWindowPart::DECORATION_BACKGROUND << mitk::IRenderWindowPart::DECORATION_CORNER_ANNOTATION; return decorations; } ////////////////////////////////////////////////////////////////////////// // PRIVATE ////////////////////////////////////////////////////////////////////////// void QmitkMultiWidgetDecorationManager::SetupLogo(const char* path) { m_LogoAnnotation->SetOpacity(0.5); mitk::Point2D offset; offset.Fill(0.03); m_LogoAnnotation->SetOffsetVector(offset); m_LogoAnnotation->SetRelativeSize(0.25); m_LogoAnnotation->SetCornerPosition(1); vtkSmartPointer vtkLogo = GetVtkLogo(path); SetLogo(vtkLogo); } vtkSmartPointer QmitkMultiWidgetDecorationManager::GetVtkLogo(const char* path) { QImage* qimage = new QImage(path); vtkSmartPointer qImageToVtk; qImageToVtk = vtkSmartPointer::New(); qImageToVtk->SetQImage(qimage); qImageToVtk->Update(); vtkSmartPointer vtkLogo = qImageToVtk->GetOutput(); return vtkLogo; } void QmitkMultiWidgetDecorationManager::SetLogo(vtkSmartPointer vtkLogo) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetLastRenderWindowWidget(); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetLastRenderWindowWidget(); if (nullptr != renderWindowWidget && m_LogoAnnotation.IsNotNull()) { mitk::ManualPlacementAnnotationRenderer::AddAnnotation(m_LogoAnnotation.GetPointer(), renderWindowWidget->GetRenderWindow()->GetRenderer()); m_LogoAnnotation->SetLogoImage(vtkLogo); mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(renderWindowWidget->GetRenderWindow()->GetVtkRenderWindow()); m_LogoAnnotation->Update(renderer); renderWindowWidget->RequestUpdate(); return; } MITK_ERROR << "Logo can not be set for an unknown widget."; } void QmitkMultiWidgetDecorationManager::ShowLogo(bool show) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetLastRenderWindowWidget(); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetLastRenderWindowWidget(); if (nullptr != renderWindowWidget) { m_LogoAnnotation->SetVisibility(show); renderWindowWidget->RequestUpdate(); return; } MITK_ERROR << "Logo can not be shown for an unknown widget."; } bool QmitkMultiWidgetDecorationManager::IsLogoVisible() const { return m_LogoAnnotation->IsVisible(); } void QmitkMultiWidgetDecorationManager::SetColormap(QmitkMultiWidgetDecorationManager::Colormap colormap) { switch (colormap) { case Colormap::BlackAndWhite: { FillAllGradientBackgroundColorsWithBlack(); float white[3] = { 1.0f, 1.0f, 1.0f }; SetAllDecorationColors(white); break; } } } void QmitkMultiWidgetDecorationManager::SetDecorationColor(const QString& widgetID, const mitk::Color& color) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->SetDecorationColor(color); return; } MITK_ERROR << "Decoration color can not be set for an unknown widget."; } void QmitkMultiWidgetDecorationManager::SetAllDecorationColors(const mitk::Color& color) { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { renderWindowWidget.second->SetDecorationColor(color); } } mitk::Color QmitkMultiWidgetDecorationManager::GetDecorationColor(const QString& widgetID) const { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->GetDecorationColor(); } MITK_ERROR << "Decoration color can not be retrieved for an unknown widget. Returning black color!"; float black[3] = { 0.0f, 0.0f, 0.0f }; return mitk::Color(black); } void QmitkMultiWidgetDecorationManager::ShowColoredRectangle(const QString& widgetID, bool show) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->ShowColoredRectangle(show); return; } MITK_ERROR << "Colored rectangle can not be set for an unknown widget."; } void QmitkMultiWidgetDecorationManager::ShowAllColoredRectangles(bool show) { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { renderWindowWidget.second->ShowColoredRectangle(show); } } bool QmitkMultiWidgetDecorationManager::IsColoredRectangleVisible(const QString& widgetID) const { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->IsColoredRectangleVisible(); } MITK_ERROR << "Colored rectangle visibility can not be retrieved for an unknown widget. Returning 'false'."; return false; } bool QmitkMultiWidgetDecorationManager::AreAllColoredRectanglesVisible() const { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); bool allTrue = true; for (const auto& renderWindowWidget : renderWindowWidgets) { allTrue = allTrue && renderWindowWidget.second->IsColoredRectangleVisible(); } return allTrue; } void QmitkMultiWidgetDecorationManager::SetGradientBackgroundColors(const mitk::Color& upper, const mitk::Color& lower, const QString& widgetID) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->SetGradientBackgroundColors(upper, lower); return; } MITK_ERROR << "Background color gradient can not be set for an unknown widget."; } void QmitkMultiWidgetDecorationManager::SetAllGradientBackgroundColors(const mitk::Color& upper, const mitk::Color& lower) { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { renderWindowWidget.second->SetGradientBackgroundColors(upper, lower); } } void QmitkMultiWidgetDecorationManager::FillAllGradientBackgroundColorsWithBlack() { float black[3] = { 0.0f, 0.0f, 0.0f }; SetAllGradientBackgroundColors(black, black); } void QmitkMultiWidgetDecorationManager::ShowGradientBackground(const QString& widgetID, bool show) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->ShowGradientBackground(show); return; } MITK_ERROR << "Background color gradient can not be shown for an unknown widget."; } void QmitkMultiWidgetDecorationManager::ShowAllGradientBackgrounds(bool show) { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { renderWindowWidget.second->ShowGradientBackground(show); } } std::pair QmitkMultiWidgetDecorationManager::GetGradientBackgroundColors(const QString& widgetID) const { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->GetGradientBackgroundColors(); } MITK_ERROR << "Background color gradient can not be retrieved for an unknown widget. Returning black color pair."; float black[3] = { 0.0f, 0.0f, 0.0f }; return std::make_pair(mitk::Color(black), mitk::Color(black)); } bool QmitkMultiWidgetDecorationManager::IsGradientBackgroundOn(const QString& widgetID) const { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->IsGradientBackgroundOn(); } MITK_ERROR << "Background color gradient flag can not be retrieved for an unknown widget. Returning 'false'."; return false; } bool QmitkMultiWidgetDecorationManager::AreAllGradientBackgroundsOn() const { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); bool allTrue = true; for (const auto& renderWindowWidget : renderWindowWidgets) { allTrue = allTrue && renderWindowWidget.second->IsGradientBackgroundOn(); } return allTrue; } void QmitkMultiWidgetDecorationManager::SetCornerAnnotationText(const QString& widgetID, const std::string& cornerAnnotation) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->SetCornerAnnotationText(cornerAnnotation); return; } MITK_ERROR << "Corner annotation text can not be retrieved for an unknown widget."; } std::string QmitkMultiWidgetDecorationManager::GetCornerAnnotationText(const QString& widgetID) const { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->GetCornerAnnotationText(); } MITK_ERROR << "Corner annotation text can not be retrieved for an unknown widget."; return ""; } void QmitkMultiWidgetDecorationManager::ShowCornerAnnotation(const QString& widgetID, bool show) { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { renderWindowWidget->ShowCornerAnnotation(show); return; } MITK_ERROR << "Corner annotation can not be set for an unknown widget."; } void QmitkMultiWidgetDecorationManager::ShowAllCornerAnnotations(bool show) { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { renderWindowWidget.second->ShowCornerAnnotation(show); } } bool QmitkMultiWidgetDecorationManager::IsCornerAnnotationVisible(const QString& widgetID) const { - std::shared_ptr renderWindowWidget = m_MxNMultiWidget->GetRenderWindowWidget(widgetID); + std::shared_ptr renderWindowWidget = m_MultiWidget->GetRenderWindowWidget(widgetID); if (nullptr != renderWindowWidget) { return renderWindowWidget->IsCornerAnnotationVisible(); } MITK_ERROR << "Corner annotation visibility can not be retrieved for an unknown widget. Returning 'false'."; return false; } bool QmitkMultiWidgetDecorationManager::AreAllCornerAnnotationsVisible() const { - QmitkMxNMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MxNMultiWidget->GetRenderWindowWidgets(); + QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = m_MultiWidget->GetRenderWindowWidgets(); bool allTrue = true; for (const auto& renderWindowWidget : renderWindowWidgets) { allTrue = allTrue && renderWindowWidget.second->IsCornerAnnotationVisible(); } return allTrue; } diff --git a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMultiWidgetDecorationManager.h b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiWidgetDecorationManager.h similarity index 88% rename from Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMultiWidgetDecorationManager.h rename to Plugins/org.mitk.gui.qt.common/src/QmitkMultiWidgetDecorationManager.h index 8cc45cf9fa..ab96b72465 100644 --- a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMultiWidgetDecorationManager.h +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkMultiWidgetDecorationManager.h @@ -1,144 +1,143 @@ /*=================================================================== 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 QMITKMXNMULTIWIDGETDECORATIONMANAGER_H -#define QMITKMXNMULTIWIDGETDECORATIONMANAGER_H +#ifndef QMITKMULTIWIDGETDECORATIONMANAGER_H +#define QMITKMULTIWIDGETDECORATIONMANAGER_H -// mxn multi widget editor -#include +#include // mitk core #include // mitk annotation #include -// mitk qtwidgets -#include +// mitk qt widgets +#include // berry #include // vtk #include #include // qt #include #include /** * @brief * * */ -class MXNMULTIWIDGETEDITOR_EXPORT QmitkMultiWidgetDecorationManager +class MITK_QT_COMMON QmitkMultiWidgetDecorationManager { public: - QmitkMultiWidgetDecorationManager(QmitkMxNMultiWidget* mxnMultiWidget); + QmitkMultiWidgetDecorationManager(QmitkAbstractMultiWidget* multiWidget); enum class Colormap { BlackAndWhite = 0 // black background, white decoration }; void DecorationPreferencesChanged(const berry::IBerryPreferences* preferences); /** * @brief Show or hide decorations like like colored borders or background, logos, menu widgets, logos and * text annotations. * * \@par Show the decorations specified in decorations if true. Hide them, if not. * \@par A list of decoration names. If empty, all supported decorations are affected. */ void ShowDecorations(bool show, const QStringList& decorations); /** * @brief Return if a specific decoration is visible. * * \return True, if the specified decoration is shown, false if not. */ bool IsDecorationVisible(const QString &decoration) const; QStringList GetDecorations() const; private: void SetupLogo(const char* path); vtkSmartPointer GetVtkLogo(const char* path); void SetLogo(vtkSmartPointer vtkLogo); void ShowLogo(bool show); bool IsLogoVisible() const; void SetColormap(Colormap colormap); void SetDecorationColor(const QString& widgetID, const mitk::Color& color); void SetAllDecorationColors(const mitk::Color& color); mitk::Color GetDecorationColor(const QString& widgetID) const; void ShowColoredRectangle(const QString& widgetID, bool show); void ShowAllColoredRectangles(bool show); bool IsColoredRectangleVisible(const QString& widgetID) const; bool AreAllColoredRectanglesVisible() const; /** * @brief Set a background color gradient for a specific render window. * * If two different input colors are used, a gradient background is generated. * * @param upper The color of the gradient background. * @param lower The color of the gradient background. * @param widgetID The widget identifier. */ void SetGradientBackgroundColors(const mitk::Color& upper, const mitk::Color& lower, const QString& widgetID); /** * @brief Set a background color gradient for all available render windows. * * If two different input colors are used, a gradient background is generated. * * @param upper The color of the gradient background. * @param lower The color of the gradient background. */ void SetAllGradientBackgroundColors(const mitk::Color& upper, const mitk::Color& lower); void FillAllGradientBackgroundColorsWithBlack(); void ShowGradientBackground(const QString& widgetID, bool show); void ShowAllGradientBackgrounds(bool show); /** - * @brief Return a render window (widget) specific background color gradient + * @rief Return a render window (widget) specific background color gradient * * @param widgetID The widget identifier. * * @return A color gradient as a pair of colors. * First entry: upper color value * Second entry: lower color value */ std::pair GetGradientBackgroundColors(const QString& widgetID) const; bool IsGradientBackgroundOn(const QString& widgetID) const; bool AreAllGradientBackgroundsOn() const; void SetCornerAnnotationText(const QString& widgetID, const std::string& cornerAnnotation); std::string GetCornerAnnotationText(const QString& widgetID) const; void ShowCornerAnnotation(const QString& widgetID, bool show); void ShowAllCornerAnnotations(bool show); bool IsCornerAnnotationVisible(const QString& widgetID) const; bool AreAllCornerAnnotationsVisible() const; - QmitkMxNMultiWidget* m_MxNMultiWidget; + QmitkAbstractMultiWidget* m_MultiWidget; mitk::LogoAnnotation::Pointer m_LogoAnnotation; }; -#endif // QMITKMXNMULTIWIDGETDECORATIONMANAGER_H +#endif // QMITKMULTIWIDGETDECORATIONMANAGER_H diff --git a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/files.cmake b/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/files.cmake index fce4919a70..6fc8f9b490 100644 --- a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/files.cmake +++ b/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/files.cmake @@ -1,37 +1,36 @@ set(SRC_CPP_FILES QmitkMxNMultiWidgetEditor.cpp - QmitkMultiWidgetDecorationManager.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkMxNMultiWidgetEditorPreferencePage.cpp ) set(UI_FILES src/internal/QmitkMxNMultiWidgetEditorPreferencePage.ui ) set(MOC_H_FILES src/QmitkMxNMultiWidgetEditor.h src/internal/mitkPluginActivator.h src/internal/QmitkMxNMultiWidgetEditorPreferencePage.h ) set(CACHED_RESOURCE_FILES resources/MxNMultiWidgetEditor.svg plugin.xml ) set(QRC_FILES resources/QmitkMxNMultiWidgetEditor.qrc ) 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.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.cpp b/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.cpp index bf802f1d33..71eb9cd82a 100644 --- a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.cpp +++ b/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.cpp @@ -1,248 +1,152 @@ /*=================================================================== 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 "QmitkMxNMultiWidgetEditor.h" #include #include #include #include #include // mxn multi widget editor plugin #include "QmitkMultiWidgetDecorationManager.h" // mitk qt widgets module #include #include #include +// qt +#include + const QString QmitkMxNMultiWidgetEditor::EDITOR_ID = "org.mitk.editors.mxnmultiwidget"; -class QmitkMxNMultiWidgetEditor::Impl final +struct QmitkMxNMultiWidgetEditor::Impl final { - -public: - Impl(); ~Impl() = default; - QmitkMxNMultiWidget* m_MxNMultiWidget; QmitkInteractionSchemeToolBar* m_InteractionSchemeToolBar; QmitkMultiWidgetConfigurationToolBar* m_ConfigurationToolBar; - - std::unique_ptr m_MultiWidgetDecorationManager; }; QmitkMxNMultiWidgetEditor::Impl::Impl() - : m_MxNMultiWidget(nullptr) - , m_InteractionSchemeToolBar(nullptr) + : m_InteractionSchemeToolBar(nullptr) , m_ConfigurationToolBar(nullptr) { // nothing here } ////////////////////////////////////////////////////////////////////////// // QmitkMxNMultiWidgetEditor ////////////////////////////////////////////////////////////////////////// QmitkMxNMultiWidgetEditor::QmitkMxNMultiWidgetEditor() - : m_Impl(new Impl()) + : m_Impl(std::make_unique()) {} QmitkMxNMultiWidgetEditor::~QmitkMxNMultiWidgetEditor() { GetSite()->GetPage()->RemovePartListener(this); } -QmitkRenderWindow* QmitkMxNMultiWidgetEditor::GetActiveQmitkRenderWindow() const -{ - if (nullptr != m_Impl->m_MxNMultiWidget) - { - auto activeRenderWindowWidget = m_Impl->m_MxNMultiWidget->GetActiveRenderWindowWidget(); - if (nullptr != activeRenderWindowWidget) - { - return activeRenderWindowWidget->GetRenderWindow(); - } - } - - return nullptr; -} - -QHash QmitkMxNMultiWidgetEditor::GetQmitkRenderWindows() const -{ - QHash result; - if (nullptr == m_Impl->m_MxNMultiWidget) - { - return result; - } - - result = m_Impl->m_MxNMultiWidget->GetRenderWindows(); - return result; -} - -QmitkRenderWindow* QmitkMxNMultiWidgetEditor::GetQmitkRenderWindow(const QString& id) const -{ - if (nullptr == m_Impl->m_MxNMultiWidget) - { - return nullptr; - } - - return m_Impl->m_MxNMultiWidget->GetRenderWindow(id); -} - -mitk::Point3D QmitkMxNMultiWidgetEditor::GetSelectedPosition(const QString& id) const -{ - if (nullptr == m_Impl->m_MxNMultiWidget) - { - return mitk::Point3D(); - } - - return m_Impl->m_MxNMultiWidget->GetSelectedPosition(id); -} - -void QmitkMxNMultiWidgetEditor::SetSelectedPosition(const mitk::Point3D& pos, const QString& id) -{ - if (nullptr != m_Impl->m_MxNMultiWidget) - { - m_Impl->m_MxNMultiWidget->SetSelectedPosition(id, pos); - } -} - -void QmitkMxNMultiWidgetEditor::EnableDecorations(bool enable, const QStringList& decorations) -{ - m_Impl->m_MultiWidgetDecorationManager->ShowDecorations(enable, decorations); -} - -bool QmitkMxNMultiWidgetEditor::IsDecorationEnabled(const QString& decoration) const -{ - return m_Impl->m_MultiWidgetDecorationManager->IsDecorationVisible(decoration); -} - -QStringList QmitkMxNMultiWidgetEditor::GetDecorations() const -{ - return m_Impl->m_MultiWidgetDecorationManager->GetDecorations(); -} - -berry::IPartListener::Events::Types QmitkMxNMultiWidgetEditor::GetPartEventTypes() const -{ - return Events::CLOSED | Events::OPENED; -} - -void QmitkMxNMultiWidgetEditor::PartOpened(const berry::IWorkbenchPartReference::Pointer& partRef) -{ - if (partRef->GetId() == QmitkMxNMultiWidgetEditor::EDITOR_ID) - { - m_Impl->m_MxNMultiWidget->ActivateAllCrosshairs(true); - } -} - -void QmitkMxNMultiWidgetEditor::PartClosed(const berry::IWorkbenchPartReference::Pointer& partRef) +void QmitkMxNMultiWidgetEditor::OnLayoutSet(int row, int column) { - if (partRef->GetId() == QmitkMxNMultiWidgetEditor::EDITOR_ID) + const auto& multiWidget = dynamic_cast(GetMultiWidget()); + if (nullptr != multiWidget) { - m_Impl->m_MxNMultiWidget->ActivateAllCrosshairs(false); + multiWidget->SetLayout(row, column); + multiWidget->ActivateAllCrosshairs(true); + FirePropertyChange(berry::IWorkbenchPartConstants::PROP_INPUT); } } -QmitkMxNMultiWidget* QmitkMxNMultiWidgetEditor::GetMxNMultiWidget() -{ - return m_Impl->m_MxNMultiWidget; -} - -void QmitkMxNMultiWidgetEditor::OnLayoutSet(int row, int column) -{ - m_Impl->m_MxNMultiWidget->ResetLayout(row, column); - m_Impl->m_MxNMultiWidget->ActivateAllCrosshairs(true); - FirePropertyChange(berry::IWorkbenchPartConstants::PROP_INPUT); -} - -void QmitkMxNMultiWidgetEditor::OnSynchronize(bool synchronized) -{ - m_Impl->m_MxNMultiWidget->Synchronize(synchronized); -} - ////////////////////////////////////////////////////////////////////////// // PRIVATE ////////////////////////////////////////////////////////////////////////// void QmitkMxNMultiWidgetEditor::SetFocus() { - if (nullptr != m_Impl->m_MxNMultiWidget) + const auto& multiWidget = GetMultiWidget(); + if (nullptr != multiWidget) { - m_Impl->m_MxNMultiWidget->setFocus(); + multiWidget->setFocus(); } } void QmitkMxNMultiWidgetEditor::CreateQtPartControl(QWidget* parent) { - if (nullptr == m_Impl->m_MxNMultiWidget) + auto multiWidget = GetMultiWidget(); + if (nullptr == multiWidget|| nullptr == dynamic_cast(multiWidget)) { 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_Impl->m_MxNMultiWidget = new QmitkMxNMultiWidget(parent, 0, 0, renderingMode); + multiWidget = new QmitkMxNMultiWidget(parent, 0, 0, renderingMode); // create left toolbar: interaction scheme toolbar to switch how the render window navigation behaves if (nullptr == m_Impl->m_InteractionSchemeToolBar) { m_Impl->m_InteractionSchemeToolBar = new QmitkInteractionSchemeToolBar(parent); layout->addWidget(m_Impl->m_InteractionSchemeToolBar); } - m_Impl->m_InteractionSchemeToolBar->SetInteractionEventHandler(m_Impl->m_MxNMultiWidget->GetInteractionEventHandler()); + m_Impl->m_InteractionSchemeToolBar->SetInteractionEventHandler(multiWidget->GetInteractionEventHandler()); // add center widget: the mxn multi widget - layout->addWidget(m_Impl->m_MxNMultiWidget); + layout->addWidget(multiWidget); - m_Impl->m_MxNMultiWidget->SetDataStorage(GetDataStorage()); - m_Impl->m_MxNMultiWidget->InitializeRenderWindowWidgets(); + multiWidget->SetDataStorage(GetDataStorage()); + multiWidget->InitializeMultiWidget(); + SetMultiWidget(multiWidget); // create right toolbar: configuration toolbar to change the render window widget layout if (nullptr == m_Impl->m_ConfigurationToolBar) { - m_Impl->m_ConfigurationToolBar = new QmitkMultiWidgetConfigurationToolBar(); + m_Impl->m_ConfigurationToolBar = new QmitkMultiWidgetConfigurationToolBar(multiWidget); layout->addWidget(m_Impl->m_ConfigurationToolBar); } connect(m_Impl->m_ConfigurationToolBar, &QmitkMultiWidgetConfigurationToolBar::LayoutSet, this, &QmitkMxNMultiWidgetEditor::OnLayoutSet); connect(m_Impl->m_ConfigurationToolBar, &QmitkMultiWidgetConfigurationToolBar::Synchronized, this, &QmitkMxNMultiWidgetEditor::OnSynchronize); - m_Impl->m_MultiWidgetDecorationManager = std::make_unique(m_Impl->m_MxNMultiWidget); + //m_Impl->m_MultiWidgetDecorationManager = std::make_unique(multiWidget); GetSite()->GetPage()->AddPartListener(this); OnPreferencesChanged(preferences); } } void QmitkMxNMultiWidgetEditor::OnPreferencesChanged(const berry::IBerryPreferences* preferences) { - if (m_Impl->m_MxNMultiWidget->GetRenderWindowWidgets().empty()) + const auto& multiWidget = GetMultiWidget(); + if (nullptr == multiWidget) { return; } // update decoration preferences - m_Impl->m_MultiWidgetDecorationManager->DecorationPreferencesChanged(preferences); + //m_Impl->m_MultiWidgetDecorationManager->DecorationPreferencesChanged(preferences); // zooming and panning preferences bool constrainedZooming = preferences->GetBool("Use constrained zooming and panning", true); mitk::RenderingManager::GetInstance()->SetConstrainedPanningZooming(constrainedZooming); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.h b/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.h index ea9db18593..9703c5ec36 100644 --- a/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.h +++ b/Plugins/org.mitk.gui.qt.mxnmultiwidgeteditor/src/QmitkMxNMultiWidgetEditor.h @@ -1,118 +1,64 @@ /*=================================================================== 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 QMITKMXNMULTIWIDGETEDITOR_H #define QMITKMXNMULTIWIDGETEDITOR_H -#include -#include +#include #include // berry #include +// c++ #include class QmitkMxNMultiWidget; -class MXNMULTIWIDGETEDITOR_EXPORT QmitkMxNMultiWidgetEditor final : public QmitkAbstractRenderEditor, public berry::IPartListener +class MXNMULTIWIDGETEDITOR_EXPORT QmitkMxNMultiWidgetEditor final : public QmitkAbstractMultiWidgetEditor { Q_OBJECT public: - berryObjectMacro(QmitkMxNMultiWidgetEditor) - static const QString EDITOR_ID; QmitkMxNMultiWidgetEditor(); - virtual ~QmitkMxNMultiWidgetEditor(); + virtual ~QmitkMxNMultiWidgetEditor() 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 - */ - virtual mitk::Point3D GetSelectedPosition(const QString& id = QString()) const override; - /** - * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart - */ - virtual 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 Overridden from berry::IPartListener - */ - berry::IPartListener::Events::Types GetPartEventTypes() const override; - /** - * @brief Overridden from berry::IPartListener - */ - void PartOpened(const berry::IWorkbenchPartReference::Pointer& partRef) override; - /** - * @brief Overridden from berry::IPartListener - */ - void PartClosed(const berry::IWorkbenchPartReference::Pointer& partRef) override; - - /** - * @brief Return the current MxN multi widget of this editor. - */ - QmitkMxNMultiWidget* GetMxNMultiWidget(); - -private Q_SLOTS: - - void OnLayoutSet(int row, int column); - void OnSynchronize(bool synchronized); + virtual void OnLayoutSet(int row, int column) override; private: /** * @brief Overridden from QmitkAbstractRenderEditor */ virtual void SetFocus() override; /** * @brief Overridden from QmitkAbstractRenderEditor */ virtual void CreateQtPartControl(QWidget* parent) override; /** * @brief Overridden from QmitkAbstractRenderEditor */ virtual void OnPreferencesChanged(const berry::IBerryPreferences* preferences) override; - class Impl; - const std::unique_ptr m_Impl; + struct Impl; + std::unique_ptr m_Impl; + }; #endif // QMITKMXNMULTIWIDGETEDITOR_H