/** ** ** @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 namespace SituationMap { namespace RB { static QHash> &runningDispatcher() { static QHash> hashTable; return hashTable; } // runningDispatcher() QGestureRecognizer * AbstractEventDispatcher::_applyGestureDetection = nullptr; unsigned int AbstractEventDispatcher::_applyGestureID = 0; AbstractEventDispatcher::AbstractEventDispatcher( QWidget * getEventsFrom ) : QObject(getEventsFrom) , _getEventsFrom(getEventsFrom) , _logger(getLogger("EventDispatcher")) , _cursorIsInWidget(false) , _synthesisTouchFromMouseEvents(false) , _deleteRequested(false) , _hasGrab(false) , _finishFlag(false) , _activeEvent(false) , _dispatcherCursor() , _whatsThisBackup() , _eventActions(nullptr) { DEBUG_LOG(_logger) << LOGFUNCTION << " " << this; initDispatcher(); } /* AbstractEventDispatcher::AbstractEventDispatcher */ AbstractEventDispatcher::AbstractEventDispatcher( QWidget * getEventsFrom, EventActionInterface * eventActions ) : QObject(getEventsFrom) , _getEventsFrom(getEventsFrom) , _logger(getLogger("EventDispatcher")) , _cursorIsInWidget(false) , _synthesisTouchFromMouseEvents(false) , _deleteRequested(false) , _hasGrab(false) , _finishFlag(false) , _activeEvent(false) , _dispatcherCursor() , _whatsThisBackup() , _eventActions(eventActions) { DEBUG_LOG(_logger) << LOGFUNCTION << " " << this; initDispatcher(); } /* AbstractEventDispatcher::AbstractEventDispatcher */ void AbstractEventDispatcher::initDispatcher() { _restoreCursor = _getEventsFrom->testAttribute(Qt::WA_SetCursor); if (_restoreCursor) { _cursorToRestore = getCursorFromWidget(); DEBUG_LOG(_logger) << LOGFUNCTION << " this=" << this << " get cursorToRestore"; } _restoreMouseTracking = _getEventsFrom->hasMouseTracking(); // { // bool activeEvent = _activeEvent; // _activeEvent = true; // don't process events while init has not been finished // QCoreApplication::process Events(); // remove events from event queue; in which circumstances this is necessary? // _activeEvent = activeEvent; // } _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 ); 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 ); runningDispatcher()[_getEventsFrom].append(this); } /* AbstractEventDispatcher::initDispatcher */ AbstractEventDispatcher::~AbstractEventDispatcher() { DEBUG_LOG(_logger) << LOGFUNCTION << " " << this; _finishFlag = true; if (_getEventsFrom) { _getEventsFrom->removeEventFilter(this); _getEventsFrom->setMouseTracking( _restoreMouseTracking ); ungrab(); if (!_whatsThisBackup.isNull()) { _getEventsFrom->setWhatsThis(_whatsThisBackup); } runningDispatcher()[_getEventsFrom].removeAll(this); } QCoreApplication::setAttribute( Qt::AA_SynthesizeTouchForUnhandledMouseEvents, _synthesisTouchFromMouseEvents ); } /* AbstractEventDispatcher::~AbstractEventDispatcher */ unsigned int AbstractEventDispatcher::numberOfEventDispatcher() const { return static_cast( runningDispatcher()[_getEventsFrom].size() ); } /* AbstractEventDispatcher::numberOfEventDispatcher */ 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); } runningDispatcher()[_getEventsFrom].removeAll(this); _getEventsFrom = nullptr; emit signalKickTheBucket(); // QCoreApplication::sendPostedEvents(); // 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; DEBUG_LOG(_logger) << LOGFUNCTION << " this=" << this << " set dispatcherCursor = " << (int)_dispatcherCursor.shape(); setCursorToWidget( _dispatcherCursor ); _getEventsFrom -> setFocus(); } /* AbstractEventDispatcher::Grab */ void AbstractEventDispatcher::ungrab() { if (!_hasGrab) return; _hasGrab = false; if (_restoreCursor) { DEBUG_LOG(_logger) << LOGFUNCTION << " this=" << this << " set cursorToRestore = " << (int)_cursorToRestore.shape(); setCursorToWidget( _cursorToRestore ); } else _getEventsFrom -> unsetCursor(); _getEventsFrom -> clearFocus(); } /* AbstractEventDispatcher::Ungrab */ bool AbstractEventDispatcher::eventFilter( QObject * widget, QEvent * e ) { if (widget != ((QObject*)_getEventsFrom)) return false; if (_logger.isDebugEnabled()) { switch (e->type()) { case QEvent::CursorChange: { QCursor cursor = _getEventsFrom->cursor(); DEBUG_LOG(_logger) << LOGFUNCTION << " Cursor has changed, this = " << this << " cursor = " << cursor.shape(); } break; case QEvent::Enter : { _cursorIsInWidget = true; QCursor cursor = _getEventsFrom->cursor(); DEBUG_LOG(_logger) << LOGFUNCTION << " Enter event, this = " << this << " cursor = " << cursor.shape(); } break; case QEvent::Leave : { _cursorIsInWidget = false; QCursor cursor = _getEventsFrom->cursor(); DEBUG_LOG(_logger) << LOGFUNCTION << " Leave event, this = " << " cursor = " << cursor.shape(); } break; default: break; } } return false; } /* AbstractEventDispatcher::eventFilter */ void AbstractEventDispatcher::setCursorToWidget( const QCursor & cursor ) { _getEventsFrom -> setCursor( cursor ); } QCursor AbstractEventDispatcher::getCursorFromWidget() const { return _getEventsFrom->cursor(); } } } /* namespace SituationMap::RB */