diff --git a/Documentation/Doxygen/Tutorial/Step10.dox b/Documentation/Doxygen/Tutorial/Step10.dox index be027c43be..82ee944421 100644 --- a/Documentation/Doxygen/Tutorial/Step10.dox +++ b/Documentation/Doxygen/Tutorial/Step10.dox @@ -1,432 +1,432 @@ /** \page Step10Page MITK Tutorial - Step 10: Adding new Interaction \tableofcontents \section HowToUseDataInteractor How to use an existing DataInteractor MITK provides finished DataInteractors for a variety of tasks, they can be found in Code/Core/Interactors. They can be used with state machine patterns and config files located under Resources/Interaction. A DataInteractor consists of four parts. The class describing the functionality and two XML files; one describes the state machine pattern, that is the workflow of an interaction and the second describes the user events which trigger an action. Lastly every DataInteractor works on a DataNode in which it stores and manipulates data. To use a DataInteractor these parts have to be brought together. This code demonstrates the use of an existing DataInteractor exemplary for the PointSetDataInteractor: First we need a DataNode that is added to the DataStorage. \code mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); GetDataStorage()->Add(dataNode.GetPointer()); \endcode Then we create an instance of to PointSetDataInteractor and load a statemachine pattern as well as a configuration for it: \code m_CurrentInteractor = mitk::PointSetDataInteractor::New(); m_CurrentInteractor->LoadStateMachine("PointSet.xml"); - m_CurrentInteractor->AddEventConfig("PointSetConfig.xml"); + m_CurrentInteractor->LoadEventConfig("PointSetConfig.xml"); \endcode Lastly the DataNode is added to the DataInteractor \code m_CurrentInteractor->SetDataNode(dataNode); \endcode now the DataInteractor is ready for usage. \section SectionImplementationDataInteractor How to implement a new DataInteractor This second part of the tutorial step goes beyond the activation of an interactor, that modifies data by user interaction) as shown above. It shows what needs to be implemented to add a new way of interaction within your MITK application. Please see \ref DataInteractionPage as an introduction to the MITK interaction mechanism, you may also want to read \ref DataInteractionTechnicalPage. This tutorial is structured as follows: The first section deals with config files, describing all the parameters of events and how to use them in a configuration file. In the second section the basics are described that are needed to write a state machine pattern. The last section deals with brining configuration, state machine pattern and code together and gives an examplary implementation of a DataInteractor. \section ConfigFileDescriptionSection How to create a Config-File \subsection EventDescriptionSection Event Description Events are described by their parameters. Each event type has its own set of parameters that can be set in the configuration file. If a parameter is ommitted it is set to its default value. Following all possible parameters are listed and described, to which parameters events have is decribed in their respective documentation. Mandatory for each event description is the event class and the event variant. The parameters of an event are set by attribute tags. \note Refer to \ref EventClassSection for the meaning of event class. \b Mouse \b Buttons \n mitk::MouseButtons represent the buttons. They can be used for two attributes. First the EventButton which describes the button that triggered the event, this allways is a single button. Secondly the ButtonState attribute that describes which buttons were pressed at the moment the event has been generated. For example assume the right mouse button and the middle mouse button are already pressed, now also the left mouse button is pressed too and generates a second event, this would be described as follows: \code \endcode Note: Technically the LeftMouseButton is also pressed and should be listed in the ButtonState, but this is taken care of by the mitk:EventFactory . Key Events \n mitk::InteractionKeyEvent represents a pressed key, which key is pressed is provided with the Key attribute like this \code \endcode or \code \endcode \note Key Events do not require an explicit configuration all, for all key events there exists a predefined event variant with the name 'Std' + value, that is key a is named 'StdA'. The names for special keys are listed here: \dontinclude mitkInteractionEventConst.h \skipline // Special Keys \until // End special keys Modifier Keys \n mitk::ModifierKeys represent the combination of pressed modifier keys, several modifier keys pressed at the same time are denoted by listing them all separated by commas. \code \endcode \b ScrollDirection \n This attribute is unique to the mitk::MouseWheelEvent and describes the direction in which the mouse wheel is rotated. In the event description actual only the direction is provided, but the event is generated with the actual value, and this value can be retrieved from the object. \code \endcode \subsection ExamplesSection Examples Examples for key events: \code \endcode Examples for MousePress events: \code \endcode There exists a standard configuration file for the most common events called GlobalConfig.xml that can be used to as a default and can be extended by a specific definition. \subsection ParameterDescriptionSection Parameter Description It is also possible to store parameters in the config file. Those are stored using the param-tag, like this: \code \endcode Within the application these properties can then be access via a mitk::PropertyList like this: \code // sm - state machine loaded with config file example2 mitk::PropertyList::Pointer properties = GetAttributes(); std::string prop1; properties->GetStringProperty("property1",prop1); \endcode \section HowToStateMachine HowTo Write a State Machine A state machine pattern is described in a XML file. \subsection StateSection States States are described using the state-tag. Each state has to have a name. Exactly one state has to be as start state in each state machine to indicate the state in which the state machine is set when it is constructed. So a valid, but rather useless state machine would like like this: \code \endcode Optionally a state can be assigned a special mode that influences the event distribution. These modes are GRAB_INPUT , PREFER_INPUT and REGULAR (where REGULAR is default and does not need to be indicated). See \ref DispatcherEventDistSection for a description of these modes. Use the special modes only when necessary as they prevent other DataInteractors to receive events. \code \endcode \subsection TransitionSection Transitions Transitions are part of a state and describe all possible state switches, and are therefore important for modelling an interaction scheme. Transitions consist a part that describes the event which triggers the transition (event class and event variant) and a target which is state to which the state machine switches after executing a transition. An event class describes the event type (see mitk::InteractionEvent for the different classes) and the event variant is a specification thereof and the exact description is taken from a config file. Together they determine which event can trigger this transition. For example this state machine will switch from state A to state B when the StdMousePressPrimaryButton event (left mouse button is pressed) occurs. \subsubsection EventClassSection Event Class The event class description supports the polymorphism of the event classes. Therefore state machine patters should be written in the most general ways possible. So for a given class hierarchy like this: \dot digraph { node [shape=record, fontname=Helvetica, fontsize=10]; a [ label="{PositionEvent}"]; b [ label="{MousePressEvent}" ]; c [ label="MouseReleaseEvent" ]; d [ label="TouchEvent", style=dotted ]; a -> b; a -> c; a -> d; } \enddot in the state machine pattern the PositionEvent can be declared as event class to restrict to the events which hold a position information. The actual implementation is then given in the configuration file. In this case it allows to define event of the classes PositionEvent itself, or MousePressEvent,MouseReleaseEvent,TouchEvent. This has the advantage that the patterns remain the same no matter what input devices are used, and the state machine patterns can be configured for newly added event classes as long as they match the class hierachy (this ensures they hold the neccessary properties). \code \endcode \subsection ActionSection Actions Actions can be added to transitions and represent functions in the DataInteractor that are executed on taking a transition. The following simple state machine will listen for left mouse clicks and execute two actions (and actually never stop). \code \endcode In order to tell the DataInteractor which function to execute these actions are made known to the DataInteractor using the CONNECT_FUNCTION macro. This example assumes that there exists an ExampleInteractor which inherits from DataInteractor. This class implements the functions AddPoint and CountClicks. The actions are introduced by implementing the virtual method ConnectActionsAndFunctions(): \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("countClicks", CountClicks); } \endcode \section HowToDataInteractor Implementation a new DataInteractor DataInteractors are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: \code bool SomeFunctionality(StateMachineAction* , InteractionEvent*); \endcode Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } \endcode Now all that is left it to write a state machine pattern and a config file as is described in the tutorials. \subsection ExampleInternalEvent PointSetDataInteractor To provide a useful example the mitk::PointSetDataInteractor is annotated with comments that describe the important parts for an implementation of a DataInteractor. This step assumes knowlege of the Interaction concept described in \ref DataInteractionPage and some background of the implementation which is described in \ref DataInteractionPageTechnical. Please refer to these pages before proceeding. DataInteractor are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: \code bool SomeFunctionality(StateMachineAction* , InteractionEvent*); \endcode Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } \endcode Now all that is left it to write a state machine pattern and a config file as is described in the tutorials. \subsection ExampleInternalEvent Example Interactor using InternalEvent A useful tool in creating DataInteractors are mitk::InternalEvents which allow to the DataInteractor send signals on its own. The following will describe how to build a DataInteractor that allows to add points until a certain number of points is reached. The number of accepted points is provided in the config file as a parameter. So we start by writing a state machine pattern that add points until it receives an InternalEvent telling it, that enough points have been added. \code <--! dead state, nothing happens any more, once we reached this --> \endcode In our config file we set the number of maximal points to 10, and define AddPointClick as a right mouse click with the ctrl button pressed. \code \endcode The implementation is desribed in the following. \see Step10.h \see Step10.cpp \dontinclude Step10.h Implementation of protected functions: \skipline protected: \until virtual void ConfigurationChanged(); ConnectActionsAndFunctions - Is inherited from mitk::InteractionStateMachine, here action strings from the xml are connected with functions in the Interactor (as seen above). In our example this looks like this: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConnectActionsAndFunctions() \until } ConfigurationChanged - Is called whenever a new configuration file is loaded (by the mitk::EventHandler super class), this function allows to implement initialization code that depends on configuration values. In our example we want to set the limit of allowed points: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConfigurationChang \until } Next the actual functionality of the DataInteractor is implemented, by providing one function per action, following this prototype: \code bool FUNCTION_NAME (StateMachineAction* , InteractionEvent*); \endcode \dontinclude Step10.h \skipline private: \until bool EnoughPoints(StateMac Each function has to return a boolean value. True if the action has been executed, and false if the action has not been executed. \dontinclude Step10.cpp \skipline bool mitk::ExampleInteractor::AddPoint(StateM \until //- Here we see an internal event used to signal that the point set reached the maximal number of allowed points. The event is created and added to the Dispatchers event queue. \dontinclude Step10.cpp \skipline // create internal \until positionEvent->GetSender( \note That internal events do not need any mapping to event variants. Their signal same is equivalent with the event variant. There are also two documented classes implementing a DataInteractor and an EventObserver which can be looked at for further understanding: \see mitk::PointSetDataInteractor \see mitk::DisplayInteractor Have fun with creating your own interaction and please think about contributing it to MITK! If you meet any difficulties during this step, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! People there are kind and will try to help you. \ref Step09Page "[Previous step]" \ref TutorialPage "[Main tutorial page]" */ \ No newline at end of file diff --git a/Modules/Qmitk/QmitkRenderWindow.cpp b/Modules/Qmitk/QmitkRenderWindow.cpp index e69336e0f1..91b8244b6a 100644 --- a/Modules/Qmitk/QmitkRenderWindow.cpp +++ b/Modules/Qmitk/QmitkRenderWindow.cpp @@ -1,544 +1,544 @@ /*=================================================================== 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 "QmitkRenderWindow.h" #include #include #include #include #include #include #include #include #include "QmitkEventAdapter.h" // TODO: INTERACTION_LEGACY #include "mitkMousePressEvent.h" #include "mitkMouseMoveEvent.h" #include "mitkMouseReleaseEvent.h" #include "mitkInteractionKeyEvent.h" #include "mitkMouseWheelEvent.h" #include "mitkInternalEvent.h" #include "QmitkRenderWindowMenu.h" QmitkRenderWindow::QmitkRenderWindow(QWidget *parent, QString name, mitk::VtkPropRenderer* /*renderer*/, mitk::RenderingManager* renderingManager) : QVTKWidget(parent), m_ResendQtEvents(true), m_MenuWidget(NULL), m_MenuWidgetActivated(false), m_LayoutIndex(0) { Initialize(renderingManager, name.toStdString().c_str()); // Initialize mitkRenderWindowBase setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); } QmitkRenderWindow::~QmitkRenderWindow() { Destroy(); // Destroy mitkRenderWindowBase } void QmitkRenderWindow::SetResendQtEvents(bool resend) { m_ResendQtEvents = resend; } void QmitkRenderWindow::SetLayoutIndex(unsigned int layoutIndex) { m_LayoutIndex = layoutIndex; if (m_MenuWidget) m_MenuWidget->SetLayoutIndex(layoutIndex); } unsigned int QmitkRenderWindow::GetLayoutIndex() { if (m_MenuWidget) return m_MenuWidget->GetLayoutIndex(); else return 0; } void QmitkRenderWindow::LayoutDesignListChanged(int layoutDesignIndex) { if (m_MenuWidget) m_MenuWidget->UpdateLayoutDesignList(layoutDesignIndex); } void QmitkRenderWindow::mousePressEvent(QMouseEvent *me) { mitk::MousePressEvent::Pointer mPressEvent = mitk::MousePressEvent::New(m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me)); if (!this->HandleEvent(mPressEvent.GetPointer())) { // TODO: INTERACTION_LEGACY mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(m_Renderer, me)); this->mousePressMitkEvent(&myevent); } QVTKWidget::mousePressEvent(me); if (m_ResendQtEvents) me->ignore(); } void QmitkRenderWindow::mouseReleaseEvent(QMouseEvent *me) { mitk::MouseReleaseEvent::Pointer mReleaseEvent = mitk::MouseReleaseEvent::New(m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me)); if (!this->HandleEvent(mReleaseEvent.GetPointer())) { // TODO: INTERACTION_LEGACY mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(m_Renderer, me)); this->mouseReleaseMitkEvent(&myevent); } QVTKWidget::mouseReleaseEvent(me); if (m_ResendQtEvents) me->ignore(); } void QmitkRenderWindow::mouseMoveEvent(QMouseEvent *me) { this->AdjustRenderWindowMenuVisibility(me->pos()); mitk::MouseMoveEvent::Pointer mMoveEvent = mitk::MouseMoveEvent::New(m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me)); if (!this->HandleEvent(mMoveEvent.GetPointer())) { // TODO: INTERACTION_LEGACY mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(m_Renderer, me)); this->mouseReleaseMitkEvent(&myevent); } mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(m_Renderer, me)); this->mouseMoveMitkEvent(&myevent); QVTKWidget::mouseMoveEvent(me); } void QmitkRenderWindow::wheelEvent(QWheelEvent *we) { mitk::MouseWheelEvent::Pointer mWheelEvent = mitk::MouseWheelEvent::New(m_Renderer, GetMousePosition(we), GetButtonState(we), GetModifiers(we), GetDelta(we)); if (!this->HandleEvent(mWheelEvent.GetPointer())) { // TODO: INTERACTION_LEGACY mitk::WheelEvent myevent(QmitkEventAdapter::AdaptWheelEvent(m_Renderer, we)); this->wheelMitkEvent(&myevent); } QVTKWidget::wheelEvent(we); if (m_ResendQtEvents) we->ignore(); } void QmitkRenderWindow::keyPressEvent(QKeyEvent *ke) { mitk::ModifierKeys modifiers = GetModifiers(ke); std::string key = GetKeyLetter(ke); mitk::InteractionKeyEvent::Pointer keyEvent = mitk::InteractionKeyEvent::New(m_Renderer, key, modifiers); if (!this->HandleEvent(keyEvent.GetPointer())) { // TODO: INTERACTION_LEGACY QPoint cp = mapFromGlobal(QCursor::pos()); mitk::KeyEvent mke(QmitkEventAdapter::AdaptKeyEvent(m_Renderer, ke, cp)); this->keyPressMitkEvent(&mke); ke->accept(); } QVTKWidget::keyPressEvent(ke); if (m_ResendQtEvents) ke->ignore(); } void QmitkRenderWindow::enterEvent(QEvent *e) { // TODO implement new event QVTKWidget::enterEvent(e); } void QmitkRenderWindow::DeferredHideMenu() { MITK_DEBUG << "QmitkRenderWindow::DeferredHideMenu"; if (m_MenuWidget) m_MenuWidget->HideMenu(); } void QmitkRenderWindow::leaveEvent(QEvent *e) { mitk::InternalEvent::Pointer internalEvent = mitk::InternalEvent::New(this->m_Renderer, NULL, "LeaveRenderWindow"); if (!this->HandleEvent(internalEvent.GetPointer())) // TODO implement new event MITK_DEBUG << "QmitkRenderWindow::leaveEvent"; if (m_MenuWidget) m_MenuWidget->smoothHide(); QVTKWidget::leaveEvent(e); } void QmitkRenderWindow::paintEvent(QPaintEvent* /*event*/) { //We are using our own interaction and thus have to call the rendering manually. this->GetRenderer()->GetRenderingManager()->RequestUpdate(GetRenderWindow()); } void QmitkRenderWindow::resizeEvent(QResizeEvent* event) { this->resizeMitkEvent(event->size().width(), event->size().height()); QVTKWidget::resizeEvent(event); emit resized(); } void QmitkRenderWindow::moveEvent(QMoveEvent* event) { QVTKWidget::moveEvent(event); // after a move the overlays need to be positioned emit moved(); } void QmitkRenderWindow::showEvent(QShowEvent* event) { QVTKWidget::showEvent(event); // this singleshot is necessary to have the overlays positioned correctly after initial show // simple call of moved() is no use here!! QTimer::singleShot(0, this, SIGNAL( moved() )); } void QmitkRenderWindow::ActivateMenuWidget(bool state, QmitkStdMultiWidget* stdMultiWidget) { m_MenuWidgetActivated = state; if (!m_MenuWidgetActivated && m_MenuWidget) { //disconnect Signal/Slot Connection disconnect(m_MenuWidget, SIGNAL( SignalChangeLayoutDesign(int) ), this, SLOT(OnChangeLayoutDesign(int))); disconnect(m_MenuWidget, SIGNAL( ResetView() ), this, SIGNAL( ResetView())); disconnect(m_MenuWidget, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SIGNAL( ChangeCrosshairRotationMode(int))); delete m_MenuWidget; m_MenuWidget = 0; } else if (m_MenuWidgetActivated && !m_MenuWidget) { //create render window MenuBar for split, close Window or set new setting. m_MenuWidget = new QmitkRenderWindowMenu(this, 0, m_Renderer, stdMultiWidget); m_MenuWidget->SetLayoutIndex(m_LayoutIndex); //create Signal/Slot Connection connect(m_MenuWidget, SIGNAL( SignalChangeLayoutDesign(int) ), this, SLOT(OnChangeLayoutDesign(int))); connect(m_MenuWidget, SIGNAL( ResetView() ), this, SIGNAL( ResetView())); connect(m_MenuWidget, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SIGNAL( ChangeCrosshairRotationMode(int))); } } void QmitkRenderWindow::AdjustRenderWindowMenuVisibility(const QPoint& /*pos*/) { if (m_MenuWidget) { m_MenuWidget->ShowMenu(); m_MenuWidget->MoveWidgetToCorrectPos(1.0f); } } void QmitkRenderWindow::HideRenderWindowMenu() { // DEPRECATED METHOD } void QmitkRenderWindow::OnChangeLayoutDesign(int layoutDesignIndex) { emit SignalLayoutDesignChanged(layoutDesignIndex); } void QmitkRenderWindow::OnWidgetPlaneModeChanged(int mode) { if (m_MenuWidget) m_MenuWidget->NotifyNewWidgetPlanesMode(mode); } void QmitkRenderWindow::FullScreenMode(bool state) { if (m_MenuWidget) m_MenuWidget->ChangeFullScreenMode(state); } void QmitkRenderWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("application/x-mitk-datanodes")) { event->accept(); } } void QmitkRenderWindow::dropEvent(QDropEvent * event) { if (event->mimeData()->hasFormat("application/x-mitk-datanodes")) { QString arg = QString(event->mimeData()->data("application/x-mitk-datanodes").data()); QStringList listOfDataNodes = arg.split(","); std::vector vectorOfDataNodePointers; for (int i = 0; i < listOfDataNodes.size(); i++) { long val = listOfDataNodes[i].toLong(); mitk::DataNode* node = static_cast((void*) val); vectorOfDataNodePointers.push_back(node); } emit NodesDropped(this, vectorOfDataNodePointers); } } mitk::Point2D QmitkRenderWindow::GetMousePosition(QMouseEvent* me) { mitk::Point2D point; point[0] = me->x(); point[1] = me->y(); return point; } mitk::Point2D QmitkRenderWindow::GetMousePosition(QWheelEvent* we) { mitk::Point2D point; point[0] = we->x(); point[1] = we->y(); return point; } mitk::MouseButtons QmitkRenderWindow::GetEventButton(QMouseEvent* me) { mitk::MouseButtons eventButton; switch (me->button()) { case Qt::LeftButton: eventButton = mitk::LeftMouseButton; break; case Qt::RightButton: eventButton = mitk::RightMouseButton; break; - case Qt::MiddleButton: + case Qt::MidButton: eventButton = mitk::MiddleMouseButton; break; default: eventButton = mitk::NoButton; break; } return eventButton; } mitk::MouseButtons QmitkRenderWindow::GetButtonState(QMouseEvent* me) { mitk::MouseButtons buttonState = mitk::NoButton; if (me->buttons() & Qt::LeftButton) { buttonState = buttonState | mitk::LeftMouseButton; } if (me->buttons() & Qt::RightButton) { buttonState = buttonState | mitk::RightMouseButton; } - if (me->buttons() & Qt::MiddleButton) + if (me->buttons() & Qt::MidButton) { buttonState = buttonState | mitk::MiddleMouseButton; } return buttonState; } mitk::ModifierKeys QmitkRenderWindow::GetModifiers(QMouseEvent* me) { mitk::ModifierKeys modifiers = mitk::NoKey; if (me->modifiers() & Qt::ALT) { modifiers = modifiers | mitk::AltKey; } if (me->modifiers() & Qt::CTRL) { modifiers = modifiers | mitk::ControlKey; } if (me->modifiers() & Qt::SHIFT) { modifiers = modifiers | mitk::ShiftKey; } return modifiers; } mitk::MouseButtons QmitkRenderWindow::GetButtonState(QWheelEvent* we) { mitk::MouseButtons buttonState = mitk::NoButton; if (we->buttons() & Qt::LeftButton) { buttonState = buttonState | mitk::RightMouseButton; } if (we->buttons() & Qt::RightButton) { buttonState = buttonState | mitk::LeftMouseButton; } - if (we->buttons() & Qt::MiddleButton) + if (we->buttons() & Qt::MidButton) { buttonState = buttonState | mitk::MiddleMouseButton; } return buttonState; } mitk::ModifierKeys QmitkRenderWindow::GetModifiers(QWheelEvent* we) { mitk::ModifierKeys modifiers = mitk::NoKey; if (we->modifiers() & Qt::ALT) { modifiers = modifiers | mitk::AltKey; } if (we->modifiers() & Qt::CTRL) { modifiers = modifiers | mitk::ControlKey; } if (we->modifiers() & Qt::SHIFT) { modifiers = modifiers | mitk::ShiftKey; } return modifiers; } mitk::ModifierKeys QmitkRenderWindow::GetModifiers(QKeyEvent* ke) { mitk::ModifierKeys modifiers = mitk::NoKey; if (ke->modifiers() & Qt::ShiftModifier) modifiers = modifiers | mitk::ShiftKey; if (ke->modifiers() & Qt::CTRL) modifiers = modifiers | mitk::ControlKey; if (ke->modifiers() & Qt::ALT) modifiers = modifiers | mitk::AltKey; return modifiers; } std::string QmitkRenderWindow::GetKeyLetter(QKeyEvent *ke) { // Converting Qt Key Event to string element. std::string key = ""; int tkey = ke->key(); if (tkey < 128) { //standard ascii letter key = (char) toupper(tkey); } else { // special keys switch (tkey) { case Qt::Key_Return: key = mitk::KeyReturn; break; case Qt::Key_Enter: key = mitk::KeyEnter; break; case Qt::Key_Escape: key = mitk::KeyEnter; break; case Qt::Key_Delete: key = mitk::KeyDelete; break; case Qt::Key_Up: key = mitk::KeyArrowUp; break; case Qt::Key_Down: key = mitk::KeyArrowDown; break; case Qt::Key_Left: key = mitk::KeyArrowLeft; break; case Qt::Key_Right: key = mitk::KeyArrowRight; break; case Qt::Key_F1: key = mitk::KeyF1; break; case Qt::Key_F2: key = mitk::KeyF2; break; case Qt::Key_F3: key = mitk::KeyF3; break; case Qt::Key_F4: key = mitk::KeyF4; break; case Qt::Key_F5: key = mitk::KeyF5; break; case Qt::Key_F6: key = mitk::KeyF6; break; case Qt::Key_F7: key = mitk::KeyF7; break; case Qt::Key_F8: key = mitk::KeyF8; break; case Qt::Key_F9: key = mitk::KeyF9; break; case Qt::Key_F10: key = mitk::KeyF10; break; case Qt::Key_F11: key = mitk::KeyF11; break; case Qt::Key_F12: key = mitk::KeyF12; break; case Qt::Key_End: key = mitk::KeyEend; break; case Qt::Key_Home: key = mitk::KeyPos1; break; case Qt::Key_Insert: key = mitk::KeyInsert; break; case Qt::Key_PageDown: key = mitk::KeyPageDown; break; case Qt::Key_PageUp: key = mitk::KeyPageUp; break; } } return key; } int QmitkRenderWindow::GetDelta(QWheelEvent* we) { return we->delta(); }