/*========================================================================= Program: Visualization Toolkit Module: QVTKInteractorAdapter.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /* * Copyright 2004 Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the * U.S. Government. Redistribution and use in source and binary forms, with * or without modification, are permitted provided that this Notice and any * statement of authorship are reproduced on all copies. */ /*======================================================================== For general information about using VTK and Qt, see: http://www.trolltech.com/products/3rdparty/vtksupport.html =========================================================================*/ #ifdef _MSC_VER // Disable warnings that Qt headers give. #pragma warning(disable:4127) #pragma warning(disable:4512) #endif #include "QVTKInteractorAdapter.h" #include "QVTKInteractor.h" #include #include #include #include #include "vtkCommand.h" // function to get VTK keysyms from ascii characters static const char* ascii_to_key_sym(int); // function to get VTK keysyms from Qt keys static const char* qt_key_to_key_sym(Qt::Key, Qt::KeyboardModifiers modifiers); QVTKInteractorAdapter::QVTKInteractorAdapter(QObject* parentObject) : QObject(parentObject), AccumulatedDelta(0), DevicePixelRatio(1) { } QVTKInteractorAdapter::~QVTKInteractorAdapter() { } void QVTKInteractorAdapter::SetDevicePixelRatio(int ratio, vtkRenderWindowInteractor* iren) { if (ratio != DevicePixelRatio) { if (iren) { int tmp[2]; iren->GetSize(tmp); if (ratio == 1) { iren->SetSize(tmp[0] / 2, tmp[1] / 2); } else if (ratio == 2) { iren->SetSize(tmp[0] * 2, tmp[1] * 2); } } this->DevicePixelRatio = ratio; } } bool QVTKInteractorAdapter::ProcessEvent(QEvent* e, vtkRenderWindowInteractor* iren) { if(iren == nullptr || e == nullptr) return false; const QEvent::Type t = e->type(); if(t == QEvent::Resize) { QResizeEvent* e2 = static_cast(e); QSize size = e2->size(); iren->SetSize(size.width() * this->DevicePixelRatio, size.height() * this->DevicePixelRatio); iren->InvokeEvent(vtkCommand::ConfigureEvent, e2); return true; } if(t == QEvent::FocusIn) { // For 3DConnexion devices: QVTKInteractor* qiren = QVTKInteractor::SafeDownCast(iren); if(qiren) { qiren->StartListening(); } return true; } if(t == QEvent::FocusOut) { // For 3DConnexion devices: QVTKInteractor* qiren = QVTKInteractor::SafeDownCast(iren); if(qiren) { qiren->StopListening(); } return true; } // the following events only happen if the interactor is enabled if(!iren->GetEnabled()) return false; if(t == QEvent::MouseButtonPress || t == QEvent::MouseButtonRelease || t == QEvent::MouseButtonDblClick || t == QEvent::MouseMove) { QMouseEvent* e2 = static_cast(e); // give interactor the event information iren->SetEventInformationFlipY(e2->x() * this->DevicePixelRatio, e2->y() * this->DevicePixelRatio, (e2->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0, (e2->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0, 0, e2->type() == QEvent::MouseButtonDblClick ? 1 : 0); iren->SetAltKey((e2->modifiers() & Qt::AltModifier) > 0 ? 1 : 0); if(t == QEvent::MouseMove) { iren->InvokeEvent(vtkCommand::MouseMoveEvent, e2); } else if(t == QEvent::MouseButtonPress || t == QEvent::MouseButtonDblClick) { switch(e2->button()) { case Qt::LeftButton: iren->InvokeEvent(vtkCommand::LeftButtonPressEvent, e2); break; case Qt::MidButton: iren->InvokeEvent(vtkCommand::MiddleButtonPressEvent, e2); break; case Qt::RightButton: iren->InvokeEvent(vtkCommand::RightButtonPressEvent, e2); break; default: break; } } else if(t == QEvent::MouseButtonRelease) { switch(e2->button()) { case Qt::LeftButton: iren->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, e2); break; case Qt::MidButton: iren->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, e2); break; case Qt::RightButton: iren->InvokeEvent(vtkCommand::RightButtonReleaseEvent, e2); break; default: break; } } return true; } if (t == QEvent::TouchBegin || t == QEvent::TouchUpdate || t == QEvent::TouchEnd) { QTouchEvent* e2 = dynamic_cast(e); foreach (const QTouchEvent::TouchPoint& point, e2->touchPoints()) { if (point.id() >= VTKI_MAX_POINTERS) { break; } // give interactor the event information iren->SetEventInformationFlipY(point.pos().x() * this->DevicePixelRatio, point.pos().y() * this->DevicePixelRatio, (e2->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0, (e2->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0, 0,0,0, point.id()); } foreach (const QTouchEvent::TouchPoint& point, e2->touchPoints()) { if (point.id() >= VTKI_MAX_POINTERS) { break; } iren->SetPointerIndex(point.id()); if (point.state() & Qt::TouchPointReleased) { iren->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,nullptr); } if (point.state() & Qt::TouchPointPressed) { iren->InvokeEvent(vtkCommand::LeftButtonPressEvent,nullptr); } if (point.state() & Qt::TouchPointMoved) { iren->InvokeEvent(vtkCommand::MouseMoveEvent, nullptr); } } e2->accept(); return true; } if(t == QEvent::Enter) { iren->InvokeEvent(vtkCommand::EnterEvent, e); return true; } if(t == QEvent::Leave) { iren->InvokeEvent(vtkCommand::LeaveEvent, e); return true; } if(t == QEvent::KeyPress || t == QEvent::KeyRelease) { QKeyEvent* e2 = static_cast(e); // get key and keysym information int ascii_key = e2->text().length() ? e2->text().unicode()->toLatin1() : 0; const char* keysym = ascii_to_key_sym(ascii_key); if(!keysym || e2->modifiers() == Qt::KeypadModifier) { // get virtual keys keysym = qt_key_to_key_sym(static_cast(e2->key()), e2->modifiers()); } if(!keysym) { keysym = "None"; } // give interactor event information iren->SetKeyEventInformation( (e2->modifiers() & Qt::ControlModifier), (e2->modifiers() & Qt::ShiftModifier), ascii_key, e2->count(), keysym); iren->SetAltKey((e2->modifiers() & Qt::AltModifier) > 0 ? 1 : 0); if(t == QEvent::KeyPress) { // invoke vtk event iren->InvokeEvent(vtkCommand::KeyPressEvent, e2); // invoke char event only for ascii characters if(ascii_key) { iren->InvokeEvent(vtkCommand::CharEvent, e2); } } else { iren->InvokeEvent(vtkCommand::KeyReleaseEvent, e2); } return true; } if(t == QEvent::Wheel) { QWheelEvent* e2 = static_cast(e); iren->SetEventInformationFlipY(e2->x() * this->DevicePixelRatio, e2->y() * this->DevicePixelRatio, (e2->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0, (e2->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0); iren->SetAltKey((e2->modifiers() & Qt::AltModifier) > 0 ? 1 : 0); #if QT_VERSION >= 0x050000 this->AccumulatedDelta += e2->angleDelta().y(); #else this->AccumulatedDelta += e2->delta(); #endif const int threshold = 120; // invoke vtk event when accumulated delta passes the threshold if(this->AccumulatedDelta >= threshold) { iren->InvokeEvent(vtkCommand::MouseWheelForwardEvent, e2); this->AccumulatedDelta = 0; } else if(this->AccumulatedDelta <= -threshold) { iren->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, e2); this->AccumulatedDelta = 0; } return true; } if(t == QEvent::ContextMenu) { QContextMenuEvent* e2 = static_cast(e); // give interactor the event information iren->SetEventInformationFlipY(e2->x() * this->DevicePixelRatio, e2->y() * this->DevicePixelRatio, (e2->modifiers() & Qt::ControlModifier) > 0 ? 1 : 0, (e2->modifiers() & Qt::ShiftModifier ) > 0 ? 1 : 0); iren->SetAltKey((e2->modifiers() & Qt::AltModifier) > 0 ? 1 : 0); // invoke event and pass qt event for additional data as well iren->InvokeEvent(QVTKInteractor::ContextMenuEvent, e2); return true; } if(t == QEvent::DragEnter) { QDragEnterEvent* e2 = static_cast(e); // invoke event and pass qt event for additional data as well iren->InvokeEvent(QVTKInteractor::DragEnterEvent, e2); return true; } if(t == QEvent::DragLeave) { QDragLeaveEvent* e2 = static_cast(e); // invoke event and pass qt event for additional data as well iren->InvokeEvent(QVTKInteractor::DragLeaveEvent, e2); return true; } if(t == QEvent::DragMove) { QDragMoveEvent* e2 = static_cast(e); // give interactor the event information iren->SetEventInformationFlipY(e2->pos().x() * this->DevicePixelRatio, e2->pos().y() * this->DevicePixelRatio); // invoke event and pass qt event for additional data as well iren->InvokeEvent(QVTKInteractor::DragMoveEvent, e2); return true; } if(t == QEvent::Drop) { QDropEvent* e2 = static_cast(e); // give interactor the event information iren->SetEventInformationFlipY(e2->pos().x() * this->DevicePixelRatio, e2->pos().y() * this->DevicePixelRatio); // invoke event and pass qt event for additional data as well iren->InvokeEvent(QVTKInteractor::DropEvent, e2); return true; } return false; } // ***** keysym stuff below ***** static const char *AsciiToKeySymTable[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, "Tab", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "minus", "period", "slash", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const char* ascii_to_key_sym(int i) { if(i >= 0) { return AsciiToKeySymTable[i]; } return 0; } #define QVTK_HANDLE(x,y) \ case x : \ ret = y; \ break; #define QVTK_HANDLE_KEYPAD(x, y, z) \ case x : \ ret = (modifiers & Qt::KeypadModifier) ? (y) : (z); \ break; const char* qt_key_to_key_sym(Qt::Key i, Qt::KeyboardModifiers modifiers) { const char* ret = 0; switch(i) { // Cancel QVTK_HANDLE(Qt::Key_Backspace, "BackSpace") QVTK_HANDLE(Qt::Key_Tab, "Tab") QVTK_HANDLE(Qt::Key_Backtab, "Tab") QVTK_HANDLE(Qt::Key_Clear, "Clear") QVTK_HANDLE(Qt::Key_Return, "Return") QVTK_HANDLE(Qt::Key_Enter, "Return") QVTK_HANDLE(Qt::Key_Shift, "Shift_L") QVTK_HANDLE(Qt::Key_Control, "Control_L") QVTK_HANDLE(Qt::Key_Alt, "Alt_L") QVTK_HANDLE(Qt::Key_Pause, "Pause") QVTK_HANDLE(Qt::Key_CapsLock, "Caps_Lock") QVTK_HANDLE(Qt::Key_Escape, "Escape") QVTK_HANDLE(Qt::Key_Space, "space") QVTK_HANDLE(Qt::Key_PageUp, "Prior") QVTK_HANDLE(Qt::Key_PageDown, "Next") QVTK_HANDLE(Qt::Key_End, "End") QVTK_HANDLE(Qt::Key_Home, "Home") QVTK_HANDLE(Qt::Key_Left, "Left") QVTK_HANDLE(Qt::Key_Up, "Up") QVTK_HANDLE(Qt::Key_Right, "Right") QVTK_HANDLE(Qt::Key_Down, "Down") QVTK_HANDLE(Qt::Key_Select, "Select") QVTK_HANDLE(Qt::Key_Execute, "Execute") QVTK_HANDLE(Qt::Key_SysReq, "Snapshot") QVTK_HANDLE(Qt::Key_Insert, "Insert") QVTK_HANDLE(Qt::Key_Delete, "Delete") QVTK_HANDLE(Qt::Key_Help, "Help") QVTK_HANDLE_KEYPAD(Qt::Key_0, "KP_0", "0") QVTK_HANDLE_KEYPAD(Qt::Key_1, "KP_1", "1") QVTK_HANDLE_KEYPAD(Qt::Key_2, "KP_2", "2") QVTK_HANDLE_KEYPAD(Qt::Key_3, "KP_3", "3") QVTK_HANDLE_KEYPAD(Qt::Key_4, "KP_4", "4") QVTK_HANDLE_KEYPAD(Qt::Key_5, "KP_5", "5") QVTK_HANDLE_KEYPAD(Qt::Key_6, "KP_6", "6") QVTK_HANDLE_KEYPAD(Qt::Key_7, "KP_7", "7") QVTK_HANDLE_KEYPAD(Qt::Key_8, "KP_8", "8") QVTK_HANDLE_KEYPAD(Qt::Key_9, "KP_9", "9") QVTK_HANDLE(Qt::Key_A, "a") QVTK_HANDLE(Qt::Key_B, "b") QVTK_HANDLE(Qt::Key_C, "c") QVTK_HANDLE(Qt::Key_D, "d") QVTK_HANDLE(Qt::Key_E, "e") QVTK_HANDLE(Qt::Key_F, "f") QVTK_HANDLE(Qt::Key_G, "g") QVTK_HANDLE(Qt::Key_H, "h") QVTK_HANDLE(Qt::Key_I, "i") QVTK_HANDLE(Qt::Key_J, "h") QVTK_HANDLE(Qt::Key_K, "k") QVTK_HANDLE(Qt::Key_L, "l") QVTK_HANDLE(Qt::Key_M, "m") QVTK_HANDLE(Qt::Key_N, "n") QVTK_HANDLE(Qt::Key_O, "o") QVTK_HANDLE(Qt::Key_P, "p") QVTK_HANDLE(Qt::Key_Q, "q") QVTK_HANDLE(Qt::Key_R, "r") QVTK_HANDLE(Qt::Key_S, "s") QVTK_HANDLE(Qt::Key_T, "t") QVTK_HANDLE(Qt::Key_U, "u") QVTK_HANDLE(Qt::Key_V, "v") QVTK_HANDLE(Qt::Key_W, "w") QVTK_HANDLE(Qt::Key_X, "x") QVTK_HANDLE(Qt::Key_Y, "y") QVTK_HANDLE(Qt::Key_Z, "z") QVTK_HANDLE(Qt::Key_Asterisk, "asterisk") QVTK_HANDLE(Qt::Key_Plus, "plus") QVTK_HANDLE(Qt::Key_Bar, "bar") QVTK_HANDLE(Qt::Key_Minus, "minus") QVTK_HANDLE(Qt::Key_Period, "period") QVTK_HANDLE(Qt::Key_Slash, "slash") QVTK_HANDLE(Qt::Key_F1, "F1") QVTK_HANDLE(Qt::Key_F2, "F2") QVTK_HANDLE(Qt::Key_F3, "F3") QVTK_HANDLE(Qt::Key_F4, "F4") QVTK_HANDLE(Qt::Key_F5, "F5") QVTK_HANDLE(Qt::Key_F6, "F6") QVTK_HANDLE(Qt::Key_F7, "F7") QVTK_HANDLE(Qt::Key_F8, "F8") QVTK_HANDLE(Qt::Key_F9, "F9") QVTK_HANDLE(Qt::Key_F10, "F10") QVTK_HANDLE(Qt::Key_F11, "F11") QVTK_HANDLE(Qt::Key_F12, "F12") QVTK_HANDLE(Qt::Key_F13, "F13") QVTK_HANDLE(Qt::Key_F14, "F14") QVTK_HANDLE(Qt::Key_F15, "F15") QVTK_HANDLE(Qt::Key_F16, "F16") QVTK_HANDLE(Qt::Key_F17, "F17") QVTK_HANDLE(Qt::Key_F18, "F18") QVTK_HANDLE(Qt::Key_F19, "F19") QVTK_HANDLE(Qt::Key_F20, "F20") QVTK_HANDLE(Qt::Key_F21, "F21") QVTK_HANDLE(Qt::Key_F22, "F22") QVTK_HANDLE(Qt::Key_F23, "F23") QVTK_HANDLE(Qt::Key_F24, "F24") QVTK_HANDLE(Qt::Key_NumLock, "Num_Lock") QVTK_HANDLE(Qt::Key_ScrollLock, "Scroll_Lock") default: break; } return ret; }