/** ** ** @RDE_HEADER@ ** Abstract Event Dispatcher for Qt5 ** $Id$ ** $HeadURL$ ** $Author$ ** ** ----------------------------------------------------------------------------------------------- ** ** Hardware-Environment: Intel-PC ** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5 ** ** Language ........: C++ 11 ** ** ----------------------------------------------------------------------------------------------- ** ** Author ...........: Jörg Turla, SPD G, Tel. 3132 ** ** ----------------------------------------------------------------------------------------------- ** ** Notes .........: ** ** 28.04.2003, JT : First edition for use with Qt4 in START Feature Editor fee ** 25.03.2015, JT : Refactoring for use with Qt5 ** ** ----------------------------------------------------------------------------------------------- */ #include "abstract_event_dispatcher.h" #include "gestures.h" #include #include #include #include #include #include #include #include #include // for debugging only namespace SituationMap { namespace RB { QGestureRecognizer * AbstractEventDispatcher::_applyGestureDetection = nullptr; unsigned int AbstractEventDispatcher::_applyGestureID = 0; AbstractEventDispatcher::AbstractEventDispatcher( QWidget * getEventsFrom ) : QObject(getEventsFrom) , _getEventsFrom(getEventsFrom) , _cursorIsInWidget(false) , _ignoreMouseMoveTimestamp() , _synthesisTouchFromMouseEvents(false) , _deleteRequested(false) , _hasGrab(false) , _finishFlag(false) , _activeEvent(false) , _dispatcherCursor() , _whatsThisBackup() , _eventActions(nullptr) { initDispatcher(); } /* AbstractEventDispatcher::AbstractEventDispatcher */ AbstractEventDispatcher::AbstractEventDispatcher( QWidget * getEventsFrom, EventActionInterface * eventActions ) : QObject(getEventsFrom) , _getEventsFrom(getEventsFrom) , _cursorIsInWidget(false) , _ignoreMouseMoveTimestamp() , _synthesisTouchFromMouseEvents(false) , _deleteRequested(false) , _hasGrab(false) , _finishFlag(false) , _activeEvent(false) , _dispatcherCursor() , _whatsThisBackup() , _eventActions(eventActions) { initDispatcher(); } /* AbstractEventDispatcher::AbstractEventDispatcher */ void AbstractEventDispatcher::initDispatcher() { _restoreCursor = true; /* The methode QWidget::ownCursor doesn't exist any more. * Try to find out if the inherited from parent */ // _restoreCursor = getEventsFrom->ownCursor(); if (_restoreCursor) { _cursorToRestore = getCursorFromWidget(); } _restoreMouseTracking = _getEventsFrom->hasMouseTracking(); // just a test exe, but remove process Events // QCoreApplication::process Events ( ); /// removePostedEvents( _getEventsFrom ); _getEventsFrom->setMouseTracking(true); _getEventsFrom->raise(); _getEventsFrom->installEventFilter(this); _synthesisTouchFromMouseEvents = QCoreApplication::testAttribute( Qt::AA_SynthesizeTouchForUnhandledMouseEvents ); QCoreApplication::setAttribute( Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false ); QCoreApplication::setAttribute( Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true ); #ifdef NEVER static const Qt::GestureType gestures[] = { Qt::GestureType::TapGesture , Qt::GestureType::TapAndHoldGesture , Qt::GestureType::PanGesture , Qt::GestureType::PinchGesture , Qt::GestureType::SwipeGesture }; for (auto gestureType : gestures) _getEventsFrom->grabGesture(gestureType); if (_applyGestureDetection == nullptr) { _applyGestureDetection = new ApplyGestureRecognizer(); _applyGestureID = QGestureRecognizer::registerRecognizer( _applyGestureDetection ); } _getEventsFrom->grabGesture( (Qt::GestureType)_applyGestureID ); _getEventsFrom->setAttribute( Qt::WA_AcceptTouchEvents, true ); #endif } /* AbstractEventDispatcher::initDispatcher */ AbstractEventDispatcher::~AbstractEventDispatcher() { _finishFlag = true; if (_getEventsFrom) { _getEventsFrom->removeEventFilter(this); _getEventsFrom->setMouseTracking( _restoreMouseTracking ); ungrab(); if (!_whatsThisBackup.isNull()) { _getEventsFrom->setWhatsThis(_whatsThisBackup); } } QCoreApplication::setAttribute( Qt::AA_SynthesizeTouchForUnhandledMouseEvents, _synthesisTouchFromMouseEvents ); } /* AbstractEventDispatcher::~AbstractEventDispatcher */ void AbstractEventDispatcher::onDo_delete() { if (_deleteRequested) return; _deleteRequested = true; QObject::deleteLater(); } /* AbstractEventDispatcher::onDo_delete */ void AbstractEventDispatcher::KickTheBucket() { if (_getEventsFrom == nullptr) return; _finishFlag = true; unlinkEventDispatcher(); _getEventsFrom->removeEventFilter(this); _getEventsFrom->setMouseTracking( _restoreMouseTracking ); ungrab(); if (!_whatsThisBackup.isNull()) { _getEventsFrom->setWhatsThis(_whatsThisBackup); } _getEventsFrom = nullptr; emit signalKickTheBucket(); QCoreApplication::flush(); // just a test exe, but remove process Events // QCoreApplication::process Events(); // dispatch window system events onDo_delete(); } /* AbstractEventDispatcher::KickTheBucket */ void AbstractEventDispatcher::onDo_kickTheBucket() { KickTheBucket(); } void AbstractEventDispatcher::setWhatsThis(const QString & whatsThis) { if (_whatsThisBackup.isNull()) { _whatsThisBackup = _getEventsFrom->whatsThis(); } _getEventsFrom->setWhatsThis(whatsThis); } /* AbstractEventDispatcher::setWhatsThis */ void AbstractEventDispatcher::grab() { if (_hasGrab) return; _hasGrab = true; setCursorToWidget( _dispatcherCursor ); _getEventsFrom -> setFocus(); } /* AbstractEventDispatcher::Grab */ void AbstractEventDispatcher::ungrab() { if (!_hasGrab) return; _hasGrab = false; if (_restoreCursor) { setCursorToWidget( _cursorToRestore ); } // else _getEventsFrom -> unsetCursor(); _getEventsFrom -> clearFocus(); } /* AbstractEventDispatcher::Ungrab */ bool AbstractEventDispatcher::eventFilter( QObject * widget, QEvent * e ) { if (widget != ((QObject*)_getEventsFrom)) return false; return false; } /* AbstractEventDispatcher::eventFilter */ void AbstractEventDispatcher::setCursorToWidget( const QCursor & cursor ) { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The cursor handling of QGraphicView are not free of bugs. If it tries to restore the default cursor after setting a special cursor for one item * it can happend that the restored cursor is not the last cursor that was set with setCursor function because the internal stored restore cursor is * not updated with setCursor function. As work around a mouse move event is send to the widget to reset cursor handling. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ const QPoint & currentCursorPosition = _getEventsFrom->mapFromGlobal( QCursor::pos() ); #ifdef ShowBug QMouseEvent && mouseEvent = QMouseEvent( QEvent::Type::MouseMove, QPointF(-1,-1), Qt::MouseButton::NoButton, Qt::MouseButtons(), Qt::KeyboardModifier::NoModifier ); _ignoreMouseMoveTimestamp = mouseEvent.timestamp(); QCoreApplication::sendEvent(_getEventsFrom, &mouseEvent ); QCoreApplication::process Events(); _getEventsFrom -> setCursor( cursor ); if (_cursorIsInWidget) { mouseEvent = QMouseEvent( QEvent::Type::MouseMove, currentCursorPosition, Qt::MouseButton::NoButton, Qt::MouseButtons(), Qt::KeyboardModifier::NoModifier ); QCoreApplication::sendEvent(_getEventsFrom, &mouseEvent ); } QCoreApplication::process Events(); _getEventsFrom -> update(); #else _getEventsFrom -> setCursor( cursor ); #endif } /* AbstractEventDispatcher::setCursorToWidget */ QCursor AbstractEventDispatcher::getCursorFromWidget() { const QPoint & currentCursorPosition = _getEventsFrom->mapFromGlobal( QCursor::pos() ); #ifdef ShowBug QMouseEvent && mouseEvent = QMouseEvent( QEvent::Type::MouseMove, QPointF(-1,-1), Qt::MouseButton::NoButton, Qt::MouseButtons(), Qt::KeyboardModifier::NoModifier ); _ignoreMouseMoveTimestamp = mouseEvent.timestamp(); QCoreApplication::sendEvent(_getEventsFrom, &mouseEvent ); QCoreApplication::process Events(); const QCursor & currentCursor = _getEventsFrom->cursor(); if (_cursorIsInWidget) { mouseEvent = QMouseEvent( QEvent::Type::MouseMove, currentCursorPosition, Qt::MouseButton::NoButton, Qt::MouseButtons(), Qt::KeyboardModifier::NoModifier ); QCoreApplication::sendEvent(_getEventsFrom, &mouseEvent ); } QCoreApplication::process Events(); _getEventsFrom -> update(); #else const QCursor & currentCursor = _getEventsFrom->cursor(); #endif return currentCursor; } /* AbstractEventDispatcher::getCursorFromWidget */ } } /* namespace SituationMap::RB */