diff --git a/Modules/Core/src/Interactions/mitkDisplayActionEventHandler.cpp b/Modules/Core/src/Interactions/mitkDisplayActionEventHandler.cpp index c5e450ee87..084f995cd7 100644 --- a/Modules/Core/src/Interactions/mitkDisplayActionEventHandler.cpp +++ b/Modules/Core/src/Interactions/mitkDisplayActionEventHandler.cpp @@ -1,76 +1,75 @@ /*=================================================================== 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 "mitkDisplayActionEventHandler.h" void mitk::DisplayActionEventHandler::SetObservableBroadcast(mitk::DisplayActionEventBroadcast* observableBroadcast) { if (m_ObservableBroadcast == observableBroadcast) { // no need to update the broadcast class return; } if (!m_ObservableBroadcast.IsExpired()) { auto observableBroadcastPtr = m_ObservableBroadcast.Lock(); // remove current observer for (const auto& tag : m_ObserverTags) { observableBroadcastPtr->RemoveObserver(tag); } m_ObserverTags.clear(); } // set new broadcast class m_ObservableBroadcast = observableBroadcast; } mitk::DisplayActionEventHandler::OberserverTagType mitk::DisplayActionEventHandler::ConnectDisplayActionEvent(const mitk::DisplayActionEvent& displayActionEvent, const mitk::StdFunctionCommand::ActionFunction& actionFunction, const mitk::StdFunctionCommand::FilterFunction& filterFunction) { if (m_ObservableBroadcast.IsExpired()) { mitkThrow() << "No display action event broadcast class set to observe. Use 'SetObservableBroadcast' before connecting events."; } auto observableBroadcast = m_ObservableBroadcast.Lock(); auto command = mitk::StdFunctionCommand::New(); command->SetCommandAction(actionFunction); command->SetCommandFilter(filterFunction); OberserverTagType tag = observableBroadcast->AddObserver(displayActionEvent, command); m_ObserverTags.push_back(tag); return tag; } void mitk::DisplayActionEventHandler::DisconnectObserver(OberserverTagType observerTag) { - // #TODO: change function call for new mitk::WeakPointer if (m_ObservableBroadcast.IsExpired()) { mitkThrow() << "No display action event broadcast class set to observe. Use 'SetObservableBroadcast' before disconnecting observer."; } auto observableBroadcast = m_ObservableBroadcast.Lock(); std::vector::iterator observerTagPosition = std::find(m_ObserverTags.begin(), m_ObserverTags.end(), observerTag); if (observerTagPosition != m_ObserverTags.end()) { observableBroadcast->RemoveObserver(observerTag); m_ObserverTags.erase(observerTagPosition); } } diff --git a/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp b/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp index 5dbc785dd8..1dbf37a76f 100644 --- a/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp +++ b/Modules/Core/src/Interactions/mitkDisplayInteractor.cpp @@ -1,993 +1,993 @@ /*=================================================================== 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 #include "mitkDisplayActionEvents.h" 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()); /* auto renWindows = sender->GetRenderingManager()->GetAllRegisteredRenderWindows(); for (auto renWin : renWindows) { if (BaseRenderer::GetInstance(renWin)->GetMapperID() == BaseRenderer::Standard2D) { BaseRenderer::GetInstance(renWin)->GetCameraController()->MoveBy(moveVector); BaseRenderer::GetInstance(renWin)->GetRenderingManager()->RequestUpdate(renWin); } } */ 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()); //InvokeEvent(DisplayZoomEvent(interactionEvent, factor, m_StartCoordinateInMM)); /* auto renWindows = sender->GetRenderingManager()->GetAllRegisteredRenderWindows(); for (auto renWin : renWindows) { if (BaseRenderer::GetInstance(renWin)->GetMapperID() == BaseRenderer::Standard2D && renWin != sender->GetRenderWindow()) { BaseRenderer::GetInstance(renWin)->GetCameraController()->Zoom(factor, m_StartCoordinateInMM); BaseRenderer::GetInstance(renWin)->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); /* 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()->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.IsNotNull()) + 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); } // 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/include/QmitkCustomMultiWidget.h b/Modules/QtWidgets/include/QmitkCustomMultiWidget.h index 7b39e35f3a..4a50199cb4 100644 --- a/Modules/QtWidgets/include/QmitkCustomMultiWidget.h +++ b/Modules/QtWidgets/include/QmitkCustomMultiWidget.h @@ -1,176 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKCUSTOMMULTIWIDGET_H #define QMITKCUSTOMMULTIWIDGET_H // qt widgets module #include "MitkQtWidgetsExports.h" #include "QmitkRenderWindowWidget.h" // mitk core #include #include #include #include // qt #include class QHBoxLayout; class QVBoxLayout; class QGridLayout; class QSpacerItem; class QmitkRenderWindow; namespace mitk { class RenderingManager; } /** * @brief The 'QmitkCustomMultiWidget' is a 'QWidget' that is used to display multiple render windows at once. * * Render windows can dynamically be added and removed to change the layout of the multi widget. */ class MITKQTWIDGETS_EXPORT QmitkCustomMultiWidget : public QWidget { Q_OBJECT public: using RenderWindowWidgetPointer = std::shared_ptr; using RenderWindowWidgetMap = std::map>; using RenderWindowHash = QHash; QmitkCustomMultiWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, mitk::RenderingManager* renderingManager = nullptr, mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::Standard, const QString& multiWidgetName = "custommulti"); virtual ~QmitkCustomMultiWidget(); void SetDataStorage(mitk::DataStorage* dataStorage); void InitializeRenderWindowWidgets(); mitk::InteractionEventHandler::Pointer GetInteractionEventHandler() { return m_DisplayActionEventBroadcast.GetPointer(); }; void ResetLayout(int row, int column); void Synchronize(bool synchronized); 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(); const mitk::Point3D GetSelectedPosition(const QString& widgetName) const; public Q_SLOTS: /** * @brief Listener to the CrosshairPositionEvent * * Ensures the CrosshairPositionEvent is handled only once and at the end of the Qt-Event loop */ void HandleCrosshairPositionEvent(); /** * @brief Receives the signal from HandleCrosshairPositionEvent, executes the StatusBar update * */ void HandleCrosshairPositionEventDelayed(); void SetSelectedPosition(const QString& widgetName, const mitk::Point3D& newPosition); void ResetCrosshair(); // mouse events void wheelEvent(QWheelEvent* e) override; void mousePressEvent(QMouseEvent* e) override; void moveEvent(QMoveEvent* e) override; Q_SIGNALS: void WheelMoved(QWheelEvent *); void Moved(); public: enum { AXIAL, SAGITTAL, CORONAL, THREE_D }; private: void InitializeGUI(); - void InitializeWidget(); void InitializeDisplayActionEventHandling(); void CreateRenderWindowWidget(const std::string& cornerAnnotation = ""); void DestroyRenderWindowWidget(); void FillMultiWidgetLayout(); QString GetNameFromIndex(int row, int column) const; QString GetNameFromIndex(size_t index) const; // #TODO: see T24173 mitk::DataNode::Pointer GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes); QGridLayout* m_CustomMultiWidgetLayout; 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; mitk::DataStorage::Pointer m_DataStorage; bool m_PendingCrosshairPositionEvent; bool m_CrosshairNavigationEnabled; }; #endif // QMITKCUSTOMMULTIWIDGET_H diff --git a/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp b/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp index 80976d7c91..0a9d0bb49d 100644 --- a/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp +++ b/Modules/QtWidgets/src/QmitkCustomMultiWidget.cpp @@ -1,577 +1,570 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkCustomMultiWidget.h" #include #include #include #include // mitk core #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // qt #include QmitkCustomMultiWidget::QmitkCustomMultiWidget(QWidget* parent, Qt::WindowFlags f/* = 0*/, mitk::RenderingManager* renderingManager/* = nullptr*/, mitk::BaseRenderer::RenderingMode::Type renderingMode/* = mitk::BaseRenderer::RenderingMode::Standard*/, const QString& multiWidgetName/* = "custommulti"*/) : QWidget(parent, f) , m_CustomMultiWidgetLayout(nullptr) , m_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) , m_PendingCrosshairPositionEvent(false) , m_CrosshairNavigationEnabled(false) { // create widget manually // create and set layout InitializeGUI(); - InitializeWidget(); InitializeDisplayActionEventHandling(); resize(QSize(364, 477).expandedTo(minimumSizeHint())); } QmitkCustomMultiWidget::~QmitkCustomMultiWidget() { // nothing here } void QmitkCustomMultiWidget::SetDataStorage(mitk::DataStorage* dataStorage) { if (dataStorage == m_DataStorage) { return; } m_DataStorage = dataStorage; // set new data storage for the render window widgets for (const auto& renderWindowWidget : m_RenderWindowWidgets) { renderWindowWidget.second->SetDataStorage(m_DataStorage); } } void QmitkCustomMultiWidget::InitializeRenderWindowWidgets() { // create render window widget initially m_MultiWidgetRows = 1; m_MultiWidgetColumns = 1; CreateRenderWindowWidget("2015-01-14 - CT"); InitializeGUI(); } void QmitkCustomMultiWidget::ResetLayout(int row, int column) { - m_MultiWidgetRows = row + 1; - m_MultiWidgetColumns = column + 1; + 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 QmitkCustomMultiWidget::Synchronize(bool synchronized) { auto allObserverTags = m_DisplayActionEventHandler->GetAllObserverTags(); for (auto observerTag : allObserverTags) { m_DisplayActionEventHandler->DisconnectObserver(observerTag); } if (synchronized) { mitk::StdFunctionCommand::ActionFunction actionFunction = mitk::DisplayActionEventFunctions::MoveCameraSynchronizedAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayMoveEvent(nullptr, mitk::Vector2D()), actionFunction); actionFunction = mitk::DisplayActionEventFunctions::SetCrosshairSynchronizedAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplaySetCrosshairEvent(nullptr, mitk::Point3D()), actionFunction); actionFunction = mitk::DisplayActionEventFunctions::ZoomCameraSynchronizedAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayZoomEvent(nullptr, 0.0, mitk::Point2D()), actionFunction); actionFunction = mitk::DisplayActionEventFunctions::ScrollSliceStepperSynchronizedAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayScrollEvent(nullptr, 0), actionFunction); } else { mitk::StdFunctionCommand::ActionFunction actionFunction = mitk::DisplayActionEventFunctions::MoveSenderCameraAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayMoveEvent(nullptr, mitk::Vector2D()), actionFunction); actionFunction = mitk::DisplayActionEventFunctions::SetCrosshairAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplaySetCrosshairEvent(nullptr, mitk::Point3D()), actionFunction); actionFunction = mitk::DisplayActionEventFunctions::ZoomSenderCameraAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayZoomEvent(nullptr, 0.0, mitk::Point2D()), actionFunction); actionFunction = mitk::DisplayActionEventFunctions::ScrollSliceStepperAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplayScrollEvent(nullptr, 0), actionFunction); } // use the standard 'set level window' action for both modes mitk::StdFunctionCommand::ActionFunction actionFunction = mitk::DisplayActionEventFunctions::SetLevelWindowAction(); m_DisplayActionEventHandler->ConnectDisplayActionEvent(mitk::DisplaySetLevelWindowEvent(nullptr, mitk::ScalarType(), mitk::ScalarType()), actionFunction); } QmitkCustomMultiWidget::RenderWindowWidgetMap QmitkCustomMultiWidget::GetRenderWindowWidgets() const { return m_RenderWindowWidgets; } QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetRenderWindowWidget(int row, int column) const { return GetRenderWindowWidget(GetNameFromIndex(row, column)); } QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetRenderWindowWidget(const QString& widgetName) const { RenderWindowWidgetMap::const_iterator it = m_RenderWindowWidgets.find(widgetName); if (it != m_RenderWindowWidgets.end()) { return it->second; } return nullptr; } QmitkCustomMultiWidget::RenderWindowHash QmitkCustomMultiWidget::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* QmitkCustomMultiWidget::GetRenderWindow(int row, int column) const { return GetRenderWindow(GetNameFromIndex(row, column)); } QmitkRenderWindow* QmitkCustomMultiWidget::GetRenderWindow(const QString& widgetName) const { RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); if (nullptr != renderWindowWidget) { return renderWindowWidget->GetRenderWindow(); } return nullptr; } void QmitkCustomMultiWidget::SetActiveRenderWindowWidget(RenderWindowWidgetPointer activeRenderWindowWidget) { m_ActiveRenderWindowWidget = activeRenderWindowWidget; } QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetActiveRenderWindowWidget() const { return m_ActiveRenderWindowWidget; } QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetFirstRenderWindowWidget() const { if (!m_RenderWindowWidgets.empty()) { return m_RenderWindowWidgets.begin()->second; } else { return nullptr; } } QmitkCustomMultiWidget::RenderWindowWidgetPointer QmitkCustomMultiWidget::GetLastRenderWindowWidget() const { if (!m_RenderWindowWidgets.empty()) { return m_RenderWindowWidgets.rbegin()->second; } else { return nullptr; } } unsigned int QmitkCustomMultiWidget::GetNumberOfRenderWindowWidgets() const { return m_RenderWindowWidgets.size(); } void QmitkCustomMultiWidget::RequestUpdate(const QString& widgetName) { RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); if (nullptr != renderWindowWidget) { return renderWindowWidget->RequestUpdate(); } } void QmitkCustomMultiWidget::RequestUpdateAll() { for (const auto& renderWindowWidget : m_RenderWindowWidgets) { renderWindowWidget.second->RequestUpdate(); } } void QmitkCustomMultiWidget::ForceImmediateUpdate(const QString& widgetName) { RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(widgetName); if (nullptr != renderWindowWidget) { renderWindowWidget->ForceImmediateUpdate(); } } void QmitkCustomMultiWidget::ForceImmediateUpdateAll() { for (const auto& renderWindowWidget : m_RenderWindowWidgets) { renderWindowWidget.second->ForceImmediateUpdate(); } } const mitk::Point3D QmitkCustomMultiWidget::GetSelectedPosition(const QString& widgetName) const { /* const mitk::PlaneGeometry *plane1 = mitkWidget1->GetSliceNavigationController()->GetCurrentPlaneGeometry(); const mitk::PlaneGeometry *plane2 = mitkWidget2->GetSliceNavigationController()->GetCurrentPlaneGeometry(); const mitk::PlaneGeometry *plane3 = mitkWidget3->GetSliceNavigationController()->GetCurrentPlaneGeometry(); mitk::Line3D line; if ((plane1 != NULL) && (plane2 != NULL) && (plane1->IntersectionLine(plane2, line))) { mitk::Point3D point; if ((plane3 != NULL) && (plane3->IntersectionPoint(line, point))) { return point; } } // TODO BUG POSITIONTRACKER; mitk::Point3D p; return p; // return m_LastLeftClickPositionSupplier->GetCurrentPoint(); */ return mitk::Point3D(); } ////////////////////////////////////////////////////////////////////////// // PUBLIC SLOTS ////////////////////////////////////////////////////////////////////////// void QmitkCustomMultiWidget::HandleCrosshairPositionEvent() { /* if (!m_PendingCrosshairPositionEvent) { m_PendingCrosshairPositionEvent = true; QTimer::singleShot(0, this, SLOT(HandleCrosshairPositionEventDelayed())); } */ } void QmitkCustomMultiWidget::HandleCrosshairPositionEventDelayed() { /* m_PendingCrosshairPositionEvent = false; // find image with highest layer mitk::TNodePredicateDataType::Pointer isImageData = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->m_DataStorage->GetSubset(isImageData).GetPointer(); mitk::DataNode::Pointer node; mitk::DataNode::Pointer topSourceNode; mitk::Image::Pointer image; bool isBinary = false; node = this->GetTopLayerNode(nodes); int component = 0; if (node.IsNotNull()) { node->GetBoolProperty("binary", isBinary); if (isBinary) { mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = m_DataStorage->GetSources(node, NULL, true); if (!sourcenodes->empty()) { topSourceNode = this->GetTopLayerNode(sourcenodes); } if (topSourceNode.IsNotNull()) { image = dynamic_cast(topSourceNode->GetData()); topSourceNode->GetIntProperty("Image.Displayed Component", component); } else { image = dynamic_cast(node->GetData()); node->GetIntProperty("Image.Displayed Component", component); } } else { image = dynamic_cast(node->GetData()); node->GetIntProperty("Image.Displayed Component", component); } } mitk::Point3D crosshairPos = this->GetCrossPosition(); std::string statusText; std::stringstream stream; itk::Index<3> p; mitk::BaseRenderer *baseRenderer = GetRenderWindow()->GetSliceNavigationController()->GetRenderer(); unsigned int timestep = baseRenderer->GetTimeStep(); if (image.IsNotNull() && (image->GetTimeSteps() > timestep)) { image->GetGeometry()->WorldToIndex(crosshairPos, p); stream.precision(2); stream << "Position: <" << std::fixed << crosshairPos[0] << ", " << std::fixed << crosshairPos[1] << ", " << std::fixed << crosshairPos[2] << "> mm"; stream << "; Index: <" << p[0] << ", " << p[1] << ", " << p[2] << "> "; mitk::ScalarType pixelValue; mitkPixelTypeMultiplex5(mitk::FastSinglePixelAccess, image->GetChannelDescriptor().GetPixelType(), image, image->GetVolumeData(baseRenderer->GetTimeStep()), p, pixelValue, component); if (fabs(pixelValue) > 1000000 || fabs(pixelValue) < 0.01) { stream << "; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << std::scientific << pixelValue << " "; } else { stream << "; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << pixelValue << " "; } } else { stream << "No image information at this position!"; } statusText = stream.str(); mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str()); */ } void QmitkCustomMultiWidget::SetSelectedPosition(const QString& widgetName, const mitk::Point3D& newPosition) { RenderWindowWidgetPointer renderWindowWidget; if (widgetName.isNull()) { renderWindowWidget = GetActiveRenderWindowWidget(); } else { renderWindowWidget = GetRenderWindowWidget(widgetName); } if (nullptr != renderWindowWidget) { renderWindowWidget->GetSliceNavigationController()->SelectSliceByPoint(newPosition); renderWindowWidget->RequestUpdate(); return; } MITK_ERROR << "Position can not be set for an unknown render window widget."; } void QmitkCustomMultiWidget::ResetCrosshair() { // #TODO: new concept: we do not want to initialize all views; // we do not want to rely on the geometry planes /* if (m_DataStorage.IsNotNull()) { m_RenderingManager->InitializeViewsByBoundingObjects(m_DataStorage); // m_RenderingManager->InitializeViews( m_DataStorage->ComputeVisibleBoundingGeometry3D() ); // reset interactor to normal slicing SetWidgetPlaneMode(PLANE_MODE_SLICING); } */ } ////////////////////////////////////////////////////////////////////////// // MOUSE EVENTS ////////////////////////////////////////////////////////////////////////// void QmitkCustomMultiWidget::wheelEvent(QWheelEvent* e) { emit WheelMoved(e); } void QmitkCustomMultiWidget::mousePressEvent(QMouseEvent* e) { } void QmitkCustomMultiWidget::moveEvent(QMoveEvent* e) { QWidget::moveEvent(e); // it is necessary to readjust the position of the overlays as the MultiWidget has moved // unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here emit Moved(); } ////////////////////////////////////////////////////////////////////////// // PRIVATE ////////////////////////////////////////////////////////////////////////// void QmitkCustomMultiWidget::InitializeGUI() { delete m_CustomMultiWidgetLayout; m_CustomMultiWidgetLayout = new QGridLayout(this); m_CustomMultiWidgetLayout->setContentsMargins(0, 0, 0, 0); setLayout(m_CustomMultiWidgetLayout); FillMultiWidgetLayout(); } -void QmitkCustomMultiWidget::InitializeWidget() -{ - // #TODO: some things have to be handled globally (hold for all render window (widgets) - // analyze those things and design a controlling mechanism -} - void QmitkCustomMultiWidget::InitializeDisplayActionEventHandling() { m_DisplayActionEventBroadcast = mitk::DisplayActionEventBroadcast::New(); m_DisplayActionEventBroadcast->LoadStateMachine("DisplayInteraction.xml"); m_DisplayActionEventBroadcast->SetEventConfig("DisplayConfigPACS.xml"); m_DisplayActionEventHandler = std::make_unique(); m_DisplayActionEventHandler->SetObservableBroadcast(m_DisplayActionEventBroadcast); Synchronize(true); } void QmitkCustomMultiWidget::CreateRenderWindowWidget(const std::string& cornerAnnotation/* = ""*/) { // create the render window widget and connect signals / slots QString renderWindowWidgetName = GetNameFromIndex(m_RenderWindowWidgets.size()); RenderWindowWidgetPointer renderWindowWidget = std::make_shared(this, renderWindowWidgetName, m_DataStorage); renderWindowWidget->SetCornerAnnotationText(renderWindowWidgetName.toStdString()/*cornerAnnotation*/); // store the newly created render window widget with the UID m_RenderWindowWidgets.insert(std::make_pair(renderWindowWidgetName, renderWindowWidget)); } void QmitkCustomMultiWidget::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); } void QmitkCustomMultiWidget::FillMultiWidgetLayout() { for (int row = 0; row < m_MultiWidgetRows; ++row) { for (int column = 0; column < m_MultiWidgetColumns; ++column) { RenderWindowWidgetPointer renderWindowWidget = GetRenderWindowWidget(row, column); if (nullptr != renderWindowWidget) { m_CustomMultiWidgetLayout->addWidget(renderWindowWidget.get(), row, column); SetActiveRenderWindowWidget(renderWindowWidget); } } } } QString QmitkCustomMultiWidget::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 QmitkCustomMultiWidget::GetNameFromIndex(size_t index) const { if (index <= m_RenderWindowWidgets.size()) { return m_MultiWidgetName + ".widget" + QString::number(index); } return QString(); } mitk::DataNode::Pointer QmitkCustomMultiWidget::GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes) { // #TODO: see T24173 return nodes->front(); } diff --git a/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp b/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp index 89d05d28b7..687ad5a934 100644 --- a/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp +++ b/Modules/QtWidgets/src/QmitkMultiWidgetLayoutSelectionWidget.cpp @@ -1,76 +1,76 @@ /*=================================================================== 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 "QmitkMultiWidgetLayoutSelectionWidget.h" QmitkMultiWidgetLayoutSelectionWidget::QmitkMultiWidgetLayoutSelectionWidget(QWidget* parent/* = 0*/) : QWidget(parent) { Init(); } void QmitkMultiWidgetLayoutSelectionWidget::Init() { ui.setupUi(this); connect(ui.tableWidget, &QTableWidget::itemSelectionChanged, this, &QmitkMultiWidgetLayoutSelectionWidget::OnTableItemSelectionChanged); connect(ui.setLayoutPushButton, &QPushButton::clicked, this, &QmitkMultiWidgetLayoutSelectionWidget::OnSetLayoutButtonClicked); } void QmitkMultiWidgetLayoutSelectionWidget::OnTableItemSelectionChanged() { QItemSelectionModel* selectionModel = ui.tableWidget->selectionModel(); int row = 0; int column = 0; QModelIndexList indices = selectionModel->selectedIndexes(); if (indices.size() > 0) { row = indices[0].row(); column = indices[0].column(); QModelIndex topLeft = ui.tableWidget->model()->index(0, 0, QModelIndex()); QModelIndex bottomRight = ui.tableWidget->model()->index(row, column, QModelIndex()); QItemSelection cellSelection; cellSelection.select(topLeft, bottomRight); selectionModel->select(cellSelection, QItemSelectionModel::Select); } } void QmitkMultiWidgetLayoutSelectionWidget::OnSetLayoutButtonClicked() { int row = 0; int column = 0; QModelIndexList indices = ui.tableWidget->selectionModel()->selectedIndexes(); if (indices.size() > 0) { // find largest row and column for (const QModelIndex modelIndex : indices) { if (modelIndex.row() > row) { row = modelIndex.row(); } if (modelIndex.column() > column) { column = modelIndex.column(); } } close(); - emit LayoutSet(row, column); + emit LayoutSet(row+1, column+1); } } diff --git a/Modules/RenderWindowManager/CMakeLists.txt b/Modules/RenderWindowManager/CMakeLists.txt index 2b876f73bc..f2a2a480bc 100644 --- a/Modules/RenderWindowManager/CMakeLists.txt +++ b/Modules/RenderWindowManager/CMakeLists.txt @@ -1,5 +1,3 @@ MITK_CREATE_MODULE( - INCLUDE_DIRS Qmitk - DEPENDS MitkQtWidgets - PACKAGE_DEPENDS PUBLIC CTK Qt5|Core + DEPENDS MitkCore ) diff --git a/Modules/RenderWindowManager/include/mitkRenderWindowViewDirectionController.h b/Modules/RenderWindowManager/include/mitkRenderWindowViewDirectionController.h index 95007119b3..c158658eef 100644 --- a/Modules/RenderWindowManager/include/mitkRenderWindowViewDirectionController.h +++ b/Modules/RenderWindowManager/include/mitkRenderWindowViewDirectionController.h @@ -1,86 +1,86 @@ /*=================================================================== 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 MITKRENDERWINDOWVIEWDIRECTIONCONTROLLER_H #define MITKRENDERWINDOWVIEWDIRECTIONCONTROLLER_H // render window manager module #include "MitkRenderWindowManagerExports.h" #include "mitkRenderWindowLayerUtilities.h" // mitk core #include #include namespace mitk { /** * The RenderWindowViewDirectionController is used to manipulate the 'sliceNavigationController' of a given base renderer. * The 'sliceNavigationController' is used to set the view direction / camera perspective of a base renderer. * The view direction can changed to 'mitk::SliceNavigationController::Axial', 'mitk::SliceNavigationController::Frontal' * or 'mitk::SliceNavigationController::Sagittal'. * * Functions with 'mitk::BaseRenderer* renderer' have 'nullptr' as their default argument. Using the nullptr - * these functions operate on all base renderer. Giving a specific base renderer will modify the node only for the given renderer. + * these functions operate on all base renderer. Giving a specific base renderer will modify the view direction only for the given renderer. */ class MITKRENDERWINDOWMANAGER_EXPORT RenderWindowViewDirectionController { public: using ViewDirection = mitk::SliceNavigationController::ViewDirection; RenderWindowViewDirectionController(); /** * @brief Set the data storage on which to work. */ void SetDataStorage(DataStorage::Pointer dataStorage); /** * @brief Set the controlled base renderer. */ void SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer); // wrapper functions to modify the view direction /** * @brief Set the view direction for the given renderer (nullptr = all renderer) * @param viewDirection The view direction that should be used for this renderer as a string. * Currently "axial", "coronal" and "sagittal" is supported. * @param renderer Pointer to the renderer instance for which the view direction should be changed. - * If it is a nullptr (default) nothing happens. + * If it is a nullptr (default) all controlled renderer will be affected. */ void SetViewDirectionOfRenderer(const std::string &viewDirection, BaseRenderer* renderer = nullptr); /** * @brief Set the view direction for the given renderer (nullptr = all renderer) * @param viewDirection The view direction that should be used for this renderer. * @param renderer Pointer to the renderer instance for which the view direction should be changed. * If it is a nullptr (default) nothing happens. */ void SetViewDirectionOfRenderer(ViewDirection viewDirection, BaseRenderer* renderer = nullptr); /** * @brief Reinitialize the given renderer with the currently visible nodes. * @param renderer Pointer to the renderer instance for which the view direction should be changed. - * If it is a nullptr (default) nothing happens. + * If it is a nullptr (default) all controlled renderer will be affected. */ void InitializeViewByBoundingObjects(const BaseRenderer* renderer); private: DataStorage::Pointer m_DataStorage; RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; }; } // namespace mitk #endif // MITKRENDERWINDOWVIEWDIRECTIONCONTROLLER_H diff --git a/Modules/RenderWindowManager/src/mitkRenderWindowViewDirectionController.cpp b/Modules/RenderWindowManager/src/mitkRenderWindowViewDirectionController.cpp index 7768e90cd7..1e9a92774d 100644 --- a/Modules/RenderWindowManager/src/mitkRenderWindowViewDirectionController.cpp +++ b/Modules/RenderWindowManager/src/mitkRenderWindowViewDirectionController.cpp @@ -1,132 +1,132 @@ /*=================================================================== 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 "mitkRenderWindowViewDirectionController.h" -// mitk +// mitk core #include #include #include mitk::RenderWindowViewDirectionController::RenderWindowViewDirectionController() : m_DataStorage(nullptr) { // nothing here } void mitk::RenderWindowViewDirectionController::SetDataStorage(DataStorage::Pointer dataStorage) { if (m_DataStorage != dataStorage) { // set the new data storage m_DataStorage = dataStorage; } } void mitk::RenderWindowViewDirectionController::SetControlledRenderer(RenderWindowLayerUtilities::RendererVector controlledRenderer) { if (m_ControlledRenderer != controlledRenderer) { // set the new set of controlled renderer m_ControlledRenderer = controlledRenderer; } } void mitk::RenderWindowViewDirectionController::SetViewDirectionOfRenderer(const std::string &viewDirection, BaseRenderer* renderer/* =nullptr*/) { if (nullptr == renderer) { // set visibility of data node in all controlled renderer for (auto& renderer : m_ControlledRenderer) { if (renderer.IsNotNull()) { SetViewDirectionOfRenderer(viewDirection, renderer); } } } else { mitk::SliceNavigationController* sliceNavigationController = renderer->GetSliceNavigationController(); if ("axial" == viewDirection) { sliceNavigationController->SetDefaultViewDirection(ViewDirection::Axial); } else if ("coronal" == viewDirection) { sliceNavigationController->SetDefaultViewDirection(ViewDirection::Frontal); } else if ("sagittal" == viewDirection) { sliceNavigationController->SetDefaultViewDirection(ViewDirection::Sagittal); } // initialize the views to the bounding geometry InitializeViewByBoundingObjects(renderer); } } void mitk::RenderWindowViewDirectionController::SetViewDirectionOfRenderer(ViewDirection viewDirection , BaseRenderer* renderer/* =nullptr*/) { if (nullptr == renderer) { // set visibility of data node in all controlled renderer for (auto& renderer : m_ControlledRenderer) { if (renderer.IsNotNull()) { SetViewDirectionOfRenderer(viewDirection, renderer); } } } else { mitk::SliceNavigationController* sliceNavigationController = renderer->GetSliceNavigationController(); sliceNavigationController->SetDefaultViewDirection(viewDirection); // initialize the views to the bounding geometry InitializeViewByBoundingObjects(renderer); } } void mitk::RenderWindowViewDirectionController::InitializeViewByBoundingObjects(const BaseRenderer* renderer) { if (nullptr == m_DataStorage || nullptr == renderer) { return; } // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateProperty::Pointer includeInBoundingBox = mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false)); mitk::NodePredicateNot::Pointer notIncludeInBoundingBox = mitk::NodePredicateNot::New(includeInBoundingBox); // get all non-helper objects mitk::NodePredicateProperty::Pointer helperObject = mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer notAHelperObject = mitk::NodePredicateNot::New(helperObject); // get all nodes that have a fixed layer for the given renderer mitk::NodePredicateProperty::Pointer fixedLayer = mitk::NodePredicateProperty::New("fixedLayer", mitk::BoolProperty::New(true), renderer); // combine node predicates mitk::NodePredicateAnd::Pointer combinedNodePredicate = mitk::NodePredicateAnd::New(notIncludeInBoundingBox, notAHelperObject, fixedLayer); mitk::DataStorage::SetOfObjects::ConstPointer filteredDataNodes = m_DataStorage->GetSubset(combinedNodePredicate); // calculate bounding geometry of these nodes auto bounds = m_DataStorage->ComputeBoundingGeometry3D(filteredDataNodes, "visible", renderer); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeView(renderer->GetRenderWindow(), bounds); -} \ No newline at end of file +} diff --git a/Modules/RenderWindowManagerUI/CMakeLists.txt b/Modules/RenderWindowManagerUI/CMakeLists.txt index f94ad95c26..7f5d63fa95 100644 --- a/Modules/RenderWindowManagerUI/CMakeLists.txt +++ b/Modules/RenderWindowManagerUI/CMakeLists.txt @@ -1,5 +1,4 @@ MITK_CREATE_MODULE( - INCLUDE_DIRS Qmitk DEPENDS MitkQtWidgets MitkRenderWindowManager - PACKAGE_DEPENDS PUBLIC CTK Qt5|Core + PACKAGE_DEPENDS PUBLIC Qt5|Core ) diff --git a/Modules/RenderWindowManagerUI/src/QmitkDataStorageRenderWindowInspector.cpp b/Modules/RenderWindowManagerUI/src/QmitkDataStorageRenderWindowInspector.cpp index 7f9a37659d..e1eb52f893 100644 --- a/Modules/RenderWindowManagerUI/src/QmitkDataStorageRenderWindowInspector.cpp +++ b/Modules/RenderWindowManagerUI/src/QmitkDataStorageRenderWindowInspector.cpp @@ -1,164 +1,163 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // render window manager UI module #include "QmitkDataStorageRenderWindowInspector.h" #include "QmitkCustomVariants.h" // mitk core #include // qt #include QmitkDataStorageRenderWindowInspector::QmitkDataStorageRenderWindowInspector(QWidget* parent /*=nullptr*/) : QmitkAbstractDataStorageInspector(parent) { m_Controls.setupUi(this); // initialize the render window view direction controller // and set the controlled renderer (in constructor) and the data storage m_RenderWindowViewDirectionController = std::make_unique(); // create a new model m_StorageModel = std::make_unique(this); m_Controls.renderWindowListView->setModel(m_StorageModel.get()); m_Controls.renderWindowListView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_Controls.renderWindowListView->setSelectionBehavior(QAbstractItemView::SelectRows); m_Controls.renderWindowListView->setSelectionMode(QAbstractItemView::ExtendedSelection); m_Controls.renderWindowListView->setAlternatingRowColors(true); m_Controls.renderWindowListView->setDragEnabled(true); m_Controls.renderWindowListView->setDropIndicatorShown(true); m_Controls.renderWindowListView->setAcceptDrops(true); m_Controls.renderWindowListView->setContextMenuPolicy(Qt::CustomContextMenu); SetUpConnections(); } QAbstractItemView* QmitkDataStorageRenderWindowInspector::GetView() { return m_Controls.renderWindowListView; -}; +} const QAbstractItemView* QmitkDataStorageRenderWindowInspector::GetView() const { return m_Controls.renderWindowListView; -}; +} void QmitkDataStorageRenderWindowInspector::SetSelectionMode(SelectionMode mode) { m_Controls.renderWindowListView->setSelectionMode(mode); } QmitkDataStorageRenderWindowInspector::SelectionMode QmitkDataStorageRenderWindowInspector::GetSelectionMode() const { return m_Controls.renderWindowListView->selectionMode(); } void QmitkDataStorageRenderWindowInspector::Initialize() { m_StorageModel->SetDataStorage(m_DataStorage.Lock()); m_StorageModel->SetNodePredicate(m_NodePredicate); m_RenderWindowViewDirectionController->SetDataStorage(m_DataStorage.Lock()); m_Connector->SetView(m_Controls.renderWindowListView); } void QmitkDataStorageRenderWindowInspector::SetUpConnections() { connect(m_Controls.pushButtonSetAsBaseLayer, SIGNAL(clicked()), this, SLOT(SetAsBaseLayer())); - connect(m_Controls.pushButtonResetRenderer, SIGNAL(clicked()), this, SLOT(ResetRenderer())); connect(m_Controls.pushButtonClearRenderer, SIGNAL(clicked()), this, SLOT(ClearRenderer())); QSignalMapper* changeViewDirectionSignalMapper = new QSignalMapper(this); changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonAxial, QString("axial")); changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonCoronal, QString("coronal")); changeViewDirectionSignalMapper->setMapping(m_Controls.radioButtonSagittal, QString("sagittal")); connect(changeViewDirectionSignalMapper, SIGNAL(mapped(const QString&)), this, SLOT(ChangeViewDirection(const QString&))); connect(m_Controls.radioButtonAxial, SIGNAL(clicked()), changeViewDirectionSignalMapper, SLOT(map())); connect(m_Controls.radioButtonCoronal, SIGNAL(clicked()), changeViewDirectionSignalMapper, SLOT(map())); connect(m_Controls.radioButtonSagittal, SIGNAL(clicked()), changeViewDirectionSignalMapper, SLOT(map())); } void QmitkDataStorageRenderWindowInspector::SetControlledRenderer(mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer) { m_StorageModel->SetControlledRenderer(controlledRenderer); m_RenderWindowViewDirectionController->SetControlledRenderer(controlledRenderer); } void QmitkDataStorageRenderWindowInspector::SetActiveRenderWindow(const QString& renderWindowId) { mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(renderWindowId.toStdString()); if (nullptr == selectedRenderer) { return; } m_StorageModel->SetCurrentRenderer(selectedRenderer); mitk::SliceNavigationController::ViewDirection viewDirection = selectedRenderer->GetSliceNavigationController()->GetDefaultViewDirection(); switch (viewDirection) { case mitk::SliceNavigationController::Axial: m_Controls.radioButtonAxial->setChecked(true); break; case mitk::SliceNavigationController::Frontal: m_Controls.radioButtonCoronal->setChecked(true); break; case mitk::SliceNavigationController::Sagittal: m_Controls.radioButtonSagittal->setChecked(true); break; default: break; } } void QmitkDataStorageRenderWindowInspector::SetAsBaseLayer() { /* QModelIndex selectedIndex = m_Controls.renderWindowListView->currentIndex(); if (selectedIndex.isValid()) { QVariant qvariantDataNode = m_StorageModel->data(selectedIndex, Qt::UserRole); if (qvariantDataNode.canConvert()) { mitk::DataNode* dataNode = qvariantDataNode.value(); m_RenderWindowLayerController->SetBaseDataNode(dataNode, m_StorageModel->GetCurrentRenderer()); m_Controls.renderWindowListView->clearSelection(); } } */ } void QmitkDataStorageRenderWindowInspector::ResetRenderer() { //m_RenderWindowLayerController->ResetRenderer(true, m_StorageModel->GetCurrentRenderer()); m_Controls.renderWindowListView->clearSelection(); } void QmitkDataStorageRenderWindowInspector::ClearRenderer() { //m_RenderWindowLayerController->ResetRenderer(false, m_StorageModel->GetCurrentRenderer()); m_Controls.renderWindowListView->clearSelection(); } void QmitkDataStorageRenderWindowInspector::ChangeViewDirection(const QString& viewDirection) { m_RenderWindowViewDirectionController->SetViewDirectionOfRenderer(viewDirection.toStdString(), m_StorageModel->GetCurrentRenderer()); } diff --git a/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeContextMenu.cpp b/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeContextMenu.cpp index 6bf724edea..d8167fd46d 100644 --- a/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeContextMenu.cpp +++ b/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeContextMenu.cpp @@ -1,555 +1,549 @@ /*=================================================================== 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 "QmitkDataNodeContextMenu.h" // mitk gui qt application plugin #include "mitkIContextMenuAction.h" #include "QmitkFileSaveAction.h" // mitk gui common plugin #include // qt widgets module #include #include // berry #include #include #include #include #include QmitkDataNodeContextMenu::QmitkDataNodeContextMenu(berry::IWorkbenchPartSite::Pointer workbenchPartSite, QWidget* parent) : QMenu(parent) { m_Parent = parent; m_WorkbenchPartSite = workbenchPartSite; InitNodeDescriptors(); InitDefaultActions(); InitExtensionPointActions(); } QmitkDataNodeContextMenu::~QmitkDataNodeContextMenu() { // remove the registered actions from each descriptor for (DescriptorActionListType::const_iterator it = m_DescriptorActionList.begin(); it != m_DescriptorActionList.end(); ++it) { (it->first)->RemoveAction(it->second); } } void QmitkDataNodeContextMenu::SetDataStorage(mitk::DataStorage* dataStorage) { - if (m_DataStorage != dataStorage) + // set the new data storage - also for all actions + m_DataStorage = dataStorage; + for (DescriptorActionListType::const_iterator it = m_DescriptorActionList.begin(); it != m_DescriptorActionList.end(); ++it) { - // set the new data storage - also for all actions - m_DataStorage = dataStorage; - for (DescriptorActionListType::const_iterator it = m_DescriptorActionList.begin(); it != m_DescriptorActionList.end(); ++it) + QmitkAbstractDataNodeAction *abstractDataNodeAction = dynamic_cast(it->second); + if (nullptr != abstractDataNodeAction) { - QmitkAbstractDataNodeAction* abstractDataNodeAction = dynamic_cast(it->second); - if(nullptr != abstractDataNodeAction) - { - abstractDataNodeAction->SetDataStorage(m_DataStorage.Lock()); - } + abstractDataNodeAction->SetDataStorage(m_DataStorage.Lock()); } } } -void QmitkDataNodeContextMenu::SetBaseRenderer(mitk::BaseRenderer* baseRenderer) +void QmitkDataNodeContextMenu::SetBaseRenderer(mitk::BaseRenderer *baseRenderer) { - if (m_BaseRenderer != baseRenderer) + // set the new base renderer - also for all actions + m_BaseRenderer = baseRenderer; + for (DescriptorActionListType::const_iterator it = m_DescriptorActionList.begin(); it != m_DescriptorActionList.end(); ++it) { - // set the new base renderer - also for all actions - m_BaseRenderer = baseRenderer; - for (DescriptorActionListType::const_iterator it = m_DescriptorActionList.begin(); it != m_DescriptorActionList.end(); ++it) + QmitkAbstractDataNodeAction *abstractDataNodeAction = dynamic_cast(it->second); + if (nullptr != abstractDataNodeAction) { - QmitkAbstractDataNodeAction* abstractDataNodeAction = dynamic_cast(it->second); - if (nullptr != abstractDataNodeAction) - { - abstractDataNodeAction->SetBaseRenderer(m_BaseRenderer.Lock()); - } + abstractDataNodeAction->SetBaseRenderer(m_BaseRenderer.Lock()); } } } void QmitkDataNodeContextMenu::SetSurfaceDecimation(bool surfaceDecimation) { m_SurfaceDecimation = surfaceDecimation; } void QmitkDataNodeContextMenu::InitNodeDescriptors() { m_UnknownDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetUnknownDataNodeDescriptor(); m_ImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Image"); m_MultiComponentImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("MultiComponentImage"); m_DiffusionImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("DiffusionImage"); m_FiberBundleDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("FiberBundle"); m_PeakImageDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PeakImage"); m_SegmentDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Segment"); m_SurfaceDataNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("Surface"); m_PointSetNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PointSet"); m_PlanarLineNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarLine"); m_PlanarCircleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarCircle"); m_PlanarEllipseNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarEllipse"); m_PlanarAngleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarAngle"); m_PlanarFourPointAngleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarFourPointAngle"); m_PlanarRectangleNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarRectangle"); m_PlanarPolygonNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarPolygon"); m_PlanarPathNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarPath"); m_PlanarDoubleEllipseNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarDoubleEllipse"); m_PlanarBezierCurveNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarBezierCurve"); m_PlanarSubdivisionPolygonNodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor("PlanarSubdivisionPolygon"); } void QmitkDataNodeContextMenu::InitDefaultActions() { m_GlobalReinitAction = new QmitkDataNodeGlobalReinitAction(m_Parent, m_WorkbenchPartSite.Lock()); m_GlobalReinitAction->setIcon(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png")); m_UnknownDataNodeDescriptor->AddAction(m_GlobalReinitAction, true); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, m_GlobalReinitAction)); m_ReinitAction = new QmitkDataNodeReinitAction(m_Parent, m_WorkbenchPartSite.Lock()); m_ReinitAction->setIcon(QIcon(":/org.mitk.gui.qt.datamanager/Refresh_48.png")); m_UnknownDataNodeDescriptor->AddAction(m_ReinitAction, true); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, m_ReinitAction)); QAction* saveAction = new QmitkFileSaveAction(QIcon(":/org.mitk.gui.qt.datamanager/Save_48.png"), m_WorkbenchPartSite.Lock()->GetWorkbenchWindow()); m_UnknownDataNodeDescriptor->AddAction(saveAction, true); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, saveAction)); m_RemoveAction = new QmitkDataNodeRemoveAction(m_Parent, m_WorkbenchPartSite.Lock()); m_RemoveAction->setIcon(QIcon(":/org.mitk.gui.qt.datamanager/Remove_48.png")); m_UnknownDataNodeDescriptor->AddAction(m_RemoveAction, true); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, m_RemoveAction)); m_ShowSelectedNodesAction = new QmitkDataNodeShowSelectedNodesAction(m_Parent, m_WorkbenchPartSite.Lock()); m_RemoveAction->setIcon(QIcon(":/org.mitk.gui.qt.datamanager/ShowSelectedNode_48.png")); m_UnknownDataNodeDescriptor->AddAction(m_ShowSelectedNodesAction, true); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, m_ShowSelectedNodesAction)); m_ToggleVisibilityAction = new QmitkDataNodeToggleVisibilityAction(m_Parent, m_WorkbenchPartSite.Lock()); m_ToggleVisibilityAction->setIcon(QIcon(":/org.mitk.gui.qt.datamanager/InvertShowSelectedNode_48.png")); m_UnknownDataNodeDescriptor->AddAction(m_ToggleVisibilityAction, true); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, m_ToggleVisibilityAction)); m_ShowDetailsAction = new QmitkDataNodeShowDetailsAction(m_Parent, m_WorkbenchPartSite.Lock()); m_ShowDetailsAction->setIcon(QIcon(":/org.mitk.gui.qt.datamanager/ShowDataInfo_48.png")); m_UnknownDataNodeDescriptor->AddAction(m_ShowDetailsAction, true); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, m_ShowDetailsAction)); // default widget actions m_OpacityAction = new QmitkDataNodeOpacityAction(m_Parent, m_WorkbenchPartSite.Lock()); // not used for batch actions (no multi-selection action) m_UnknownDataNodeDescriptor->AddAction(m_OpacityAction, false); m_DescriptorActionList.push_back(std::make_pair(m_UnknownDataNodeDescriptor, m_OpacityAction)); m_ColorAction = new QmitkDataNodeColorAction(m_Parent, m_WorkbenchPartSite.Lock()); AddColorAction(m_ColorAction); m_ColormapAction = new QmitkDataNodeColorMapAction(m_Parent, m_WorkbenchPartSite.Lock()); // not used for batch actions (no multi-selection action) m_ImageDataNodeDescriptor->AddAction(m_ColormapAction, false); m_DescriptorActionList.push_back(std::make_pair(m_ImageDataNodeDescriptor, m_ColormapAction)); if (m_DiffusionImageDataNodeDescriptor != nullptr) { // not used for batch actions (no multi-selection action) m_DiffusionImageDataNodeDescriptor->AddAction(m_ColormapAction, false); m_DescriptorActionList.push_back(std::make_pair(m_DiffusionImageDataNodeDescriptor, m_ColormapAction)); } m_ComponentAction = new QmitkDataNodeComponentAction(m_Parent, m_WorkbenchPartSite.Lock()); // not used for batch actions (no multi-selection action) m_MultiComponentImageDataNodeDescriptor->AddAction(m_ComponentAction, false); m_DescriptorActionList.push_back(std::make_pair(m_MultiComponentImageDataNodeDescriptor, m_ComponentAction)); if (m_DiffusionImageDataNodeDescriptor != nullptr) { // not used for batch actions (no multi-selection action) m_DiffusionImageDataNodeDescriptor->AddAction(m_ComponentAction, false); m_DescriptorActionList.push_back(std::make_pair(m_DiffusionImageDataNodeDescriptor, m_ComponentAction)); } m_TextureInterpolationAction = new QmitkDataNodeTextureInterpolationAction(m_Parent, m_WorkbenchPartSite.Lock()); // not used for batch actions (no multi-selection action) m_ImageDataNodeDescriptor->AddAction(m_TextureInterpolationAction, false); m_DescriptorActionList.push_back(std::make_pair(m_ImageDataNodeDescriptor, m_TextureInterpolationAction)); if (m_DiffusionImageDataNodeDescriptor != nullptr) { // not used for batch actions (no multi-selection action) m_DiffusionImageDataNodeDescriptor->AddAction(m_TextureInterpolationAction, false); m_DescriptorActionList.push_back(std::make_pair(m_DiffusionImageDataNodeDescriptor, m_TextureInterpolationAction)); } if (m_SegmentDataNodeDescriptor != nullptr) { // not used for batch actions (no multi-selection action) m_SegmentDataNodeDescriptor->AddAction(m_TextureInterpolationAction, false); m_DescriptorActionList.push_back(std::make_pair(m_SegmentDataNodeDescriptor, m_TextureInterpolationAction)); } m_SurfaceRepresentationAction = new QmitkDataNodeSurfaceRepresentationAction(m_Parent, m_WorkbenchPartSite.Lock()); // not used for batch actions (no multi-selection action) m_SurfaceDataNodeDescriptor->AddAction(m_SurfaceRepresentationAction, false); m_DescriptorActionList.push_back(std::make_pair(m_SurfaceDataNodeDescriptor, m_SurfaceRepresentationAction)); } void QmitkDataNodeContextMenu::InitExtensionPointActions() { // find contextMenuAction extension points and add them to the node descriptor berry::IExtensionRegistry* extensionPointService = berry::Platform::GetExtensionRegistry(); QList customMenuConfigs = extensionPointService->GetConfigurationElementsFor("org.mitk.gui.qt.datamanager.contextMenuActions"); // prepare all custom QActions m_ConfigElements.clear(); DescriptorActionListType descriptorActionList; for (const auto& customMenuConfig : customMenuConfigs) { QString actionNodeDescriptorName = customMenuConfig->GetAttribute("nodeDescriptorName"); QString actionLabel = customMenuConfig->GetAttribute("label"); QString actionClass = customMenuConfig->GetAttribute("class"); if (actionNodeDescriptorName.isEmpty() || actionLabel.isEmpty() || actionClass.isEmpty()) { // no properties found for the current extension point continue; } // find matching descriptor auto nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(actionNodeDescriptorName); if (nullptr == nodeDescriptor) { MITK_WARN << "Cannot add action \"" << actionLabel << "\" because descriptor " << actionNodeDescriptorName << " does not exist."; continue; } // create action with or without icon QAction* contextMenuAction; QString actionIconName = customMenuConfig->GetAttribute("icon"); if (!actionIconName.isEmpty()) { QIcon actionIcon; if (QFile::exists(actionIconName)) { actionIcon = QIcon(actionIconName); } else { actionIcon = berry::AbstractUICTKPlugin::ImageDescriptorFromPlugin(customMenuConfig->GetContributor()->GetName(), actionIconName); } contextMenuAction = new QAction(actionIcon, actionLabel, m_Parent); } else { contextMenuAction = new QAction(actionLabel, m_Parent); } // connect action trigger connect(contextMenuAction, static_cast(&QAction::triggered), this, &QmitkDataNodeContextMenu::OnExtensionPointActionTriggered); // mark configuration element into lookup list for context menu handler m_ConfigElements[contextMenuAction] = customMenuConfig; // mark new action in sortable list for addition to descriptor descriptorActionList.emplace_back(nodeDescriptor, contextMenuAction); } AddDescriptorActionList(descriptorActionList); } void QmitkDataNodeContextMenu::InitServiceActions() { } void QmitkDataNodeContextMenu::OnContextMenuRequested(const QPoint& pos) { if (m_WorkbenchPartSite.Expired()) { return; } berry::ISelection::ConstPointer selection = m_WorkbenchPartSite.Lock()->GetWorkbenchWindow()->GetSelectionService()->GetSelection(); mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast(); if (currentSelection.IsNull() || currentSelection->IsEmpty()) { return; } m_SelectedNodes = QList::fromStdList(currentSelection->GetSelectedDataNodes()); if (!m_SelectedNodes.isEmpty()) { clear(); QList actions; if (m_SelectedNodes.size() == 1) { // no batch action; should only contain a single node actions = GetActions(m_SelectedNodes.front()); } else { // batch action actions = GetActions(m_SelectedNodes); } // initialize abstract data node actions for (auto& action : actions) { QmitkAbstractDataNodeAction* abstractDataNodeAction = dynamic_cast(action); if (nullptr != abstractDataNodeAction) { // use the first selected node to initialize the data node actions abstractDataNodeAction->InitializeWithDataNode(m_SelectedNodes.front()); } } /* if (!m_ShowInActions.isEmpty()) { QMenu* showInMenu = m_NodeMenu->addMenu(tr("Show In")); showInMenu->addActions(m_ShowInActions); } */ addActions(actions); popup(QCursor::pos()); } } void QmitkDataNodeContextMenu::OnExtensionPointActionTriggered(bool) { QAction* action = qobject_cast(sender()); ConfigurationElementsType::const_iterator it = m_ConfigElements.find(action); if (it == m_ConfigElements.end()) { MITK_WARN << "Associated configuration element for action " << action->text().toStdString() << " not found."; return; } berry::IConfigurationElement::Pointer confElem = it->second; mitk::IContextMenuAction* contextMenuAction = confElem->CreateExecutableExtension("class"); QString className = confElem->GetAttribute("class"); QString smoothed = confElem->GetAttribute("smoothed"); if (!m_DataStorage.IsExpired()) { auto dataStorage = m_DataStorage.Lock(); contextMenuAction->SetDataStorage(dataStorage); } if (className == "QmitkCreatePolygonModelAction") { if (smoothed == "false") { contextMenuAction->SetSmoothed(false); } else { contextMenuAction->SetSmoothed(true); } contextMenuAction->SetDecimated(m_SurfaceDecimation); } contextMenuAction->Run(m_SelectedNodes); } void QmitkDataNodeContextMenu::AddColorAction(QWidgetAction* colorAction) { bool colorActionCanBatch = true; if (nullptr != m_ImageDataNodeDescriptor) { m_ImageDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_ImageDataNodeDescriptor, colorAction)); } if (nullptr != m_MultiComponentImageDataNodeDescriptor) { m_MultiComponentImageDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_MultiComponentImageDataNodeDescriptor, colorAction)); } if (nullptr != m_DiffusionImageDataNodeDescriptor) { m_DiffusionImageDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_DiffusionImageDataNodeDescriptor, colorAction)); } if (nullptr != m_FiberBundleDataNodeDescriptor) { m_FiberBundleDataNodeDescriptor->AddAction(colorAction, false); m_DescriptorActionList.push_back(std::make_pair(m_FiberBundleDataNodeDescriptor, colorAction)); } if (nullptr != m_PeakImageDataNodeDescriptor) { m_PeakImageDataNodeDescriptor->AddAction(colorAction, false); m_DescriptorActionList.push_back(std::make_pair(m_PeakImageDataNodeDescriptor, colorAction)); } if (nullptr != m_SegmentDataNodeDescriptor) { m_SegmentDataNodeDescriptor->AddAction(colorAction, false); m_DescriptorActionList.push_back(std::make_pair(m_SegmentDataNodeDescriptor, colorAction)); } if (nullptr != m_SurfaceDataNodeDescriptor) { m_SurfaceDataNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_SurfaceDataNodeDescriptor, colorAction)); } if (nullptr != m_PointSetNodeDescriptor) { m_PointSetNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PointSetNodeDescriptor, colorAction)); } if (nullptr != m_PlanarLineNodeDescriptor) { m_PlanarLineNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarLineNodeDescriptor, colorAction)); } if (nullptr != m_PlanarCircleNodeDescriptor) { m_PlanarCircleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarCircleNodeDescriptor, colorAction)); } if (nullptr != m_PlanarEllipseNodeDescriptor) { m_PlanarEllipseNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarEllipseNodeDescriptor, colorAction)); } if (nullptr != m_PlanarAngleNodeDescriptor) { m_PlanarAngleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarAngleNodeDescriptor, colorAction)); } if (nullptr != m_PlanarFourPointAngleNodeDescriptor) { m_PlanarFourPointAngleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarFourPointAngleNodeDescriptor, colorAction)); } if (nullptr != m_PlanarRectangleNodeDescriptor) { m_PlanarRectangleNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarRectangleNodeDescriptor, colorAction)); } if (nullptr != m_PlanarPolygonNodeDescriptor) { m_PlanarPolygonNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarPolygonNodeDescriptor, colorAction)); } if (nullptr != m_PlanarPathNodeDescriptor) { m_PlanarPathNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarPathNodeDescriptor, colorAction)); } if (nullptr != m_PlanarDoubleEllipseNodeDescriptor) { m_PlanarDoubleEllipseNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarDoubleEllipseNodeDescriptor, colorAction)); } if (nullptr != m_PlanarBezierCurveNodeDescriptor) { m_PlanarBezierCurveNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarBezierCurveNodeDescriptor, colorAction)); } if (nullptr != m_PlanarSubdivisionPolygonNodeDescriptor) { m_PlanarSubdivisionPolygonNodeDescriptor->AddAction(colorAction, colorActionCanBatch); m_DescriptorActionList.push_back(std::make_pair(m_PlanarSubdivisionPolygonNodeDescriptor, colorAction)); } } void QmitkDataNodeContextMenu::AddDescriptorActionList(DescriptorActionListType& descriptorActionList) { // sort all custom QActions by their texts using ListEntryType = std::pair; std::sort(descriptorActionList.begin(), descriptorActionList.end(), [](const ListEntryType& left, const ListEntryType& right) -> bool { assert(left.second != nullptr && right.second != nullptr); // unless we messed up above return left.second->text() < right.second->text(); }); // add custom QActions in sorted order for (auto& descriptorActionPair : descriptorActionList) { auto& nodeDescriptor = descriptorActionPair.first; auto& contextMenuAction = descriptorActionPair.second; // add action to the descriptor nodeDescriptor->AddAction(contextMenuAction); // mark new action into list of descriptors to remove in destructor m_DescriptorActionList.push_back(descriptorActionPair); } } QList QmitkDataNodeContextMenu::GetActions(const mitk::DataNode* node) { QList actions; for (DescriptorActionListType::const_iterator it = m_DescriptorActionList.begin(); it != m_DescriptorActionList.end(); ++it) { if ((it->first)->CheckNode(node) || it->first->GetNameOfClass() == "Unknown") { actions.append(it->second); } } return actions; } QList QmitkDataNodeContextMenu::GetActions(const QList& nodes) { QList actions; for (DescriptorActionListType::const_iterator it = m_DescriptorActionList.begin(); it != m_DescriptorActionList.end(); ++it) { for (const auto& node : nodes) { if ((it->first)->CheckNode(node) || it->first->GetNameOfClass() == "Unknown") { const auto& batchActions = (it->first)->GetBatchActions(); if (std::find(batchActions.begin(), batchActions.end(), it->second) != batchActions.end()) { // current descriptor action is a batch action actions.append(it->second); } break; // only add action once; goto next descriptor action } } } return actions; } diff --git a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp index fb6ee04ad1..173a6e4f7b 100644 --- a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.cpp @@ -1,279 +1,269 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkCustomMultiWidgetEditor.h" #include #include #include #include #include // custom multi widget editor plugin #include "QmitkMultiWidgetDecorationManager.h" // mitk qt widgets module #include #include #include const QString QmitkCustomMultiWidgetEditor::EDITOR_ID = "org.mitk.editors.custommultiwidget"; class QmitkCustomMultiWidgetEditor::Impl final { public: Impl(); ~Impl(); void SetControlledRenderer(); QmitkCustomMultiWidget* m_CustomMultiWidget; QmitkInteractionSchemeToolBar* m_InteractionSchemeToolBar; QmitkMultiWidgetConfigurationToolBar* m_ConfigurationToolBar; std::unique_ptr m_MultiWidgetDecorationManager; std::unique_ptr m_RenderWindowViewDirectionController; }; QmitkCustomMultiWidgetEditor::Impl::Impl() : m_CustomMultiWidget(nullptr) , m_InteractionSchemeToolBar(nullptr) , m_ConfigurationToolBar(nullptr) { // nothing here } QmitkCustomMultiWidgetEditor::Impl::~Impl() { // nothing here } void QmitkCustomMultiWidgetEditor::Impl::SetControlledRenderer() { if (nullptr == m_RenderWindowViewDirectionController || nullptr == m_CustomMultiWidget) { return; } mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer; auto renderWindowWidgets = m_CustomMultiWidget->GetRenderWindowWidgets(); for (const auto& renderWindowWidget : renderWindowWidgets) { auto renderWindow = renderWindowWidget.second->GetRenderWindow(); auto vtkRenderWindow = renderWindow->GetRenderWindow(); mitk::BaseRenderer* baseRenderer = mitk::BaseRenderer::GetInstance(vtkRenderWindow); if (nullptr != baseRenderer) { controlledRenderer.push_back(baseRenderer); } } m_RenderWindowViewDirectionController->SetControlledRenderer(controlledRenderer); } ////////////////////////////////////////////////////////////////////////// // QmitkCustomMultiWidgetEditor ////////////////////////////////////////////////////////////////////////// QmitkCustomMultiWidgetEditor::QmitkCustomMultiWidgetEditor() : m_Impl(new Impl()) { // nothing here } QmitkCustomMultiWidgetEditor::~QmitkCustomMultiWidgetEditor() { // nothing here } QmitkRenderWindow* QmitkCustomMultiWidgetEditor::GetActiveQmitkRenderWindow() const { if (nullptr != m_Impl->m_CustomMultiWidget) { auto activeRenderWindowWidget = m_Impl->m_CustomMultiWidget->GetActiveRenderWindowWidget(); if (nullptr != activeRenderWindowWidget) { return activeRenderWindowWidget->GetRenderWindow(); } } return nullptr; } QHash QmitkCustomMultiWidgetEditor::GetQmitkRenderWindows() const { QHash result; if (nullptr == m_Impl->m_CustomMultiWidget) { return result; } result = m_Impl->m_CustomMultiWidget->GetRenderWindows(); return result; } QmitkRenderWindow* QmitkCustomMultiWidgetEditor::GetQmitkRenderWindow(const QString& id) const { if (nullptr == m_Impl->m_CustomMultiWidget) { return nullptr; } return m_Impl->m_CustomMultiWidget->GetRenderWindow(id); } mitk::Point3D QmitkCustomMultiWidgetEditor::GetSelectedPosition(const QString& id) const { if (nullptr == m_Impl->m_CustomMultiWidget) { return mitk::Point3D(); } return m_Impl->m_CustomMultiWidget->GetSelectedPosition(id); } void QmitkCustomMultiWidgetEditor::SetSelectedPosition(const mitk::Point3D& pos, const QString& id) { if (nullptr != m_Impl->m_CustomMultiWidget) { m_Impl->m_CustomMultiWidget->SetSelectedPosition(id, pos); } } void QmitkCustomMultiWidgetEditor::EnableDecorations(bool enable, const QStringList& decorations) { m_Impl->m_MultiWidgetDecorationManager->ShowDecorations(enable, decorations); } bool QmitkCustomMultiWidgetEditor::IsDecorationEnabled(const QString& decoration) const { return m_Impl->m_MultiWidgetDecorationManager->IsDecorationVisible(decoration); } QStringList QmitkCustomMultiWidgetEditor::GetDecorations() const { return m_Impl->m_MultiWidgetDecorationManager->GetDecorations(); } -void QmitkCustomMultiWidgetEditor::EnableSlicingPlanes(bool /*enable*/) -{ - // nothing here -} - -bool QmitkCustomMultiWidgetEditor::IsSlicingPlanesEnabled() const -{ - // nothing here - return false; -} - QmitkCustomMultiWidget* QmitkCustomMultiWidgetEditor::GetCustomMultiWidget() { return m_Impl->m_CustomMultiWidget; } void QmitkCustomMultiWidgetEditor::OnLayoutSet(int row, int column) { m_Impl->m_CustomMultiWidget->ResetLayout(row, column); m_Impl->SetControlledRenderer(); FirePropertyChange(berry::IWorkbenchPartConstants::PROP_INPUT); } void QmitkCustomMultiWidgetEditor::OnSynchronize(bool synchronized) { m_Impl->m_CustomMultiWidget->Synchronize(synchronized); } void QmitkCustomMultiWidgetEditor::OnViewDirectionChanged(ViewDirection viewDirection) { m_Impl->m_RenderWindowViewDirectionController->SetViewDirectionOfRenderer(viewDirection); } ////////////////////////////////////////////////////////////////////////// // PRIVATE ////////////////////////////////////////////////////////////////////////// void QmitkCustomMultiWidgetEditor::SetFocus() { if (nullptr != m_Impl->m_CustomMultiWidget) { m_Impl->m_CustomMultiWidget->setFocus(); } } void QmitkCustomMultiWidgetEditor::CreateQtPartControl(QWidget* parent) { if (nullptr == m_Impl->m_CustomMultiWidget) { QHBoxLayout* layout = new QHBoxLayout(parent); layout->setContentsMargins(0, 0, 0, 0); berry::IBerryPreferences* preferences = dynamic_cast(GetPreferences().GetPointer()); mitk::BaseRenderer::RenderingMode::Type renderingMode = static_cast(preferences->GetInt("Rendering Mode", 0)); m_Impl->m_CustomMultiWidget = new QmitkCustomMultiWidget(parent, 0, 0, renderingMode); // create left toolbar: interaction scheme toolbar to switch how the render window navigation behaves if (nullptr == m_Impl->m_InteractionSchemeToolBar) { m_Impl->m_InteractionSchemeToolBar = new QmitkInteractionSchemeToolBar(parent); layout->addWidget(m_Impl->m_InteractionSchemeToolBar); } m_Impl->m_InteractionSchemeToolBar->SetInteractionEventHandler(m_Impl->m_CustomMultiWidget->GetInteractionEventHandler()); // add center widget: the custom multi widget layout->addWidget(m_Impl->m_CustomMultiWidget); m_Impl->m_CustomMultiWidget->SetDataStorage(GetDataStorage()); m_Impl->m_CustomMultiWidget->InitializeRenderWindowWidgets(); // 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_CustomMultiWidget); layout->addWidget(m_Impl->m_ConfigurationToolBar); } connect(m_Impl->m_ConfigurationToolBar, &QmitkMultiWidgetConfigurationToolBar::LayoutSet, this, &QmitkCustomMultiWidgetEditor::OnLayoutSet); connect(m_Impl->m_ConfigurationToolBar, &QmitkMultiWidgetConfigurationToolBar::Synchronized, this, &QmitkCustomMultiWidgetEditor::OnSynchronize); connect(m_Impl->m_ConfigurationToolBar, &QmitkMultiWidgetConfigurationToolBar::ViewDirectionChanged, this, &QmitkCustomMultiWidgetEditor::OnViewDirectionChanged); m_Impl->m_MultiWidgetDecorationManager = std::make_unique(m_Impl->m_CustomMultiWidget); m_Impl->m_RenderWindowViewDirectionController = std::make_unique(); m_Impl->m_RenderWindowViewDirectionController->SetDataStorage(GetDataStorage()); m_Impl->SetControlledRenderer(); OnPreferencesChanged(preferences); } } void QmitkCustomMultiWidgetEditor::OnPreferencesChanged(const berry::IBerryPreferences* preferences) { if (m_Impl->m_CustomMultiWidget->GetRenderWindowWidgets().empty()) { return; } + // update decoration 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.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.h b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.h index 571a7a9571..a1c70a2431 100644 --- a/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.h +++ b/Plugins/org.mitk.gui.qt.custommultiwidgeteditor/src/QmitkCustomMultiWidgetEditor.h @@ -1,117 +1,109 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical Image Computing. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKCUSTOMMULTIWIDGETEDITOR_H #define QMITKCUSTOMMULTIWIDGETEDITOR_H #include #include // custom multi widget editor #include // mitk render window manager #include #include class QmitkCustomMultiWidget; -class CUSTOMMULTIWIDGETEDITOR_EXPORT QmitkCustomMultiWidgetEditor final : public QmitkAbstractRenderEditor, public mitk::ILinkedRenderWindowPart +class CUSTOMMULTIWIDGETEDITOR_EXPORT QmitkCustomMultiWidgetEditor final : public QmitkAbstractRenderEditor { Q_OBJECT public: using ViewDirection = mitk::SliceNavigationController::ViewDirection; berryObjectMacro(QmitkCustomMultiWidgetEditor) static const QString EDITOR_ID; QmitkCustomMultiWidgetEditor(); ~QmitkCustomMultiWidgetEditor(); /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual QmitkRenderWindow* GetActiveQmitkRenderWindow() const override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual QHash GetQmitkRenderWindows() const override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual QmitkRenderWindow* GetQmitkRenderWindow(const QString& id) const override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual mitk::Point3D GetSelectedPosition(const QString& id = QString()) const override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual void SetSelectedPosition(const mitk::Point3D& pos, const QString& id = QString()) override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual void EnableDecorations(bool enable, const QStringList& decorations = QStringList()) override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual bool IsDecorationEnabled(const QString& decoration) const override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart : IRenderWindowPart + * @brief Overridden from QmitkAbstractRenderEditor : IRenderWindowPart */ virtual QStringList GetDecorations() const override; /** - * @brief Overridden from mitk::ILinkedRenderWindowPart - */ - virtual void EnableSlicingPlanes(bool enable) override; - /** - * @brief Overridden from mitk::ILinkedRenderWindowPart - */ - virtual bool IsSlicingPlanesEnabled() const override; - /** * @brief Return the current custom multi widget of this editor. */ QmitkCustomMultiWidget* GetCustomMultiWidget(); private Q_SLOTS: void OnLayoutSet(int row, int column); void OnSynchronize(bool synchronized); void OnViewDirectionChanged(ViewDirection viewDirection); 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; }; #endif // QMITKCUSTOMMULTIWIDGETEDITOR_H diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp index 4671215f00..8788ee34cf 100644 --- a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.cpp @@ -1,115 +1,123 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // render window manager plugin #include "QmitkRenderWindowManagerView.h" // mitk core #include #include +// qt +#include + const std::string QmitkRenderWindowManagerView::VIEW_ID = "org.mitk.views.renderwindowmanager"; void QmitkRenderWindowManagerView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) { if (m_RenderWindowPart != renderWindowPart) { m_RenderWindowPart = renderWindowPart; } SetControlledRenderer(); } void QmitkRenderWindowManagerView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) { if (m_RenderWindowPart == renderWindowPart) { m_RenderWindowPart = nullptr; } SetControlledRenderer(); } void QmitkRenderWindowManagerView::RenderWindowPartInputChanged(mitk::IRenderWindowPart* renderWindowPart) { if (m_RenderWindowPart == renderWindowPart) { SetControlledRenderer(); } } void QmitkRenderWindowManagerView::SetFocus() { // nothing here } void QmitkRenderWindowManagerView::CreateQtPartControl(QWidget* parent) { // create GUI widgets m_Controls.setupUi(parent); // add custom render window manager UI widget to the 'renderWindowManagerTab' m_RenderWindowInspector = new QmitkDataStorageRenderWindowInspector(parent); m_RenderWindowInspector->SetDataStorage(GetDataStorage()); m_RenderWindowInspector->setObjectName(QStringLiteral("m_RenderWindowManipulatorWidget")); m_Controls.verticalLayout->addWidget(m_RenderWindowInspector); - SetControlledRenderer(); - - connect(m_Controls.comboBoxRenderWindowSelection, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnRenderWindowSelectionChanged(const QString&))); - // data node context menu and menu actions m_InspectorView = m_RenderWindowInspector->GetView(); m_DataNodeContextMenu = new QmitkDataNodeContextMenu(GetSite(), m_InspectorView); m_DataNodeContextMenu->SetDataStorage(GetDataStorage()); //m_DataNodeContextMenu->SetSurfaceDecimation(m_SurfaceDecimation); - connect(m_InspectorView, SIGNAL(customContextMenuRequested(const QPoint&)), m_DataNodeContextMenu, SLOT(OnContextMenuRequested(const QPoint&))); + + // connect objects + connect(m_Controls.comboBoxRenderWindowSelection, QOverload::of(&QComboBox::currentIndexChanged), this, &QmitkRenderWindowManagerView::OnRenderWindowSelectionChanged); + connect(m_InspectorView, &QAbstractItemView::customContextMenuRequested, m_DataNodeContextMenu, &QmitkDataNodeContextMenu::OnContextMenuRequested); + + m_RenderWindowPart = GetRenderWindowPart(); + if (nullptr == m_RenderWindowPart) + { + // also sets the controlled renderer + RenderWindowPartActivated(m_RenderWindowPart); + } } void QmitkRenderWindowManagerView::SetControlledRenderer() { m_Controls.comboBoxRenderWindowSelection->clear(); const mitk::RenderingManager::RenderWindowVector allRegisteredRenderWindows = mitk::RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); mitk::BaseRenderer* baseRenderer = nullptr; + mitk::RenderWindowLayerUtilities::RendererVector controlledRenderer; for (const auto &renderWindow : allRegisteredRenderWindows) { baseRenderer = mitk::BaseRenderer::GetInstance(renderWindow); if (nullptr != baseRenderer) { - m_ControlledRenderer.push_back(baseRenderer); + controlledRenderer.push_back(baseRenderer); m_Controls.comboBoxRenderWindowSelection->addItem(baseRenderer->GetName()); } } - m_RenderWindowInspector->SetControlledRenderer(m_ControlledRenderer); - - OnRenderWindowSelectionChanged(m_Controls.comboBoxRenderWindowSelection->itemText(0)); + m_RenderWindowInspector->SetControlledRenderer(controlledRenderer); } void QmitkRenderWindowManagerView::OnRenderWindowSelectionChanged(const QString& renderWindowId) { m_RenderWindowInspector->SetActiveRenderWindow(renderWindowId); mitk::BaseRenderer* selectedRenderer = mitk::BaseRenderer::GetByName(renderWindowId.toStdString()); if (nullptr != selectedRenderer) { m_DataNodeContextMenu->SetBaseRenderer(selectedRenderer); } } QItemSelectionModel* QmitkRenderWindowManagerView::GetDataNodeSelectionModel() const { return m_InspectorView->selectionModel(); } diff --git a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.h b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.h index 281b677441..29bbc1582d 100644 --- a/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.h +++ b/Plugins/org.mitk.gui.qt.renderwindowmanager/src/internal/QmitkRenderWindowManagerView.h @@ -1,83 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERWINDOWMANAGERVIEW_H #define QMITKRENDERWINDOWMANAGERVIEW_H // render window manager plugin #include "ui_QmitkRenderWindowManagerControls.h" // render window manager UI module #include // mitk gui qt application #include // mitk gui common plugin #include // mitk gui qt common plugin #include /** * @brief RenderWindowManager */ class QmitkRenderWindowManagerView : public QmitkAbstractView, public mitk::IRenderWindowPartListener { Q_OBJECT public: static const std::string VIEW_ID; virtual void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) override; virtual void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) override; virtual void RenderWindowPartInputChanged(mitk::IRenderWindowPart* renderWindowPart) override; protected: virtual void SetFocus() override; virtual void CreateQtPartControl(QWidget* parent) override; private Q_SLOTS: /** * @brief Called when the user changes the render window selection in the combo box. * * @param renderWindowId The text inside the combo box. */ void OnRenderWindowSelectionChanged(const QString& renderWindowId); private: void SetControlledRenderer(); QWidget* m_Parent; Ui::QmitkRenderWindowManagerControls m_Controls; mitk::IRenderWindowPart* m_RenderWindowPart; - + QmitkDataStorageRenderWindowInspector* m_RenderWindowInspector; - QmitkDataNodeContextMenu* m_DataNodeContextMenu; QAbstractItemView* m_InspectorView; - - mitk::RenderWindowLayerUtilities::RendererVector m_ControlledRenderer; + QmitkDataNodeContextMenu* m_DataNodeContextMenu; virtual QItemSelectionModel* GetDataNodeSelectionModel() const override; }; #endif // QMITKRENDERWINDOWMANAGERVIEW_H