/** ** ** @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 ** ** ----------------------------------------------------------------------------------------------- */ #pragma once #include #include #include #include #include class QEvent; class QWidget; class QGestureRecognizer; namespace SituationMap { namespace RB { /** @class AbstractEventDispatcher abstract_event_dispatcher.h @brief Base class of Qt event filter implementations to handle user interactions of map window An EventDispatcher installs an event filter on a QWidget to receive all events that are send to the widget. Depending on the type of event and the state of the event dispatcher the event will be processed by the dispatcher and stopped or forwarded to the QWidget. In case of processing the event methodes of the EventActionInterface are called to controll a rubberband. @see EventDelegater, EventDispatcher, EventMouseNavigator */ class AbstractEventDispatcher : public QObject { friend class EventDelegater; Q_OBJECT public: /** @brief Logical interface between EventDispatcher and Rubberband Defines interface functions the EventDispatcher will call to control a rubberband. The rubberband class is derived from EventActionInterface and overrides the interface functions to implement them. The mapping user interaction to interface action is defined the derived classes of AbstractEventDispatcher. */ class EventActionInterface { public: EventActionInterface() = default; virtual ~EventActionInterface() = default; virtual void unlinkEventDispatcher ( AbstractEventDispatcher * causer ) = 0; virtual void resetAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); } virtual bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool multiSelectActionPress ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool applyAndEndAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool abortAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual bool buttonPositionAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; } virtual void userActionFinished() = 0; }; /* EventActionInterface */ /** @name Construction & Destruction @{ */ explicit AbstractEventDispatcher( QWidget * getEventsFrom ); explicit AbstractEventDispatcher( QWidget * getEventsFrom, EventActionInterface* ); virtual ~AbstractEventDispatcher(); AbstractEventDispatcher(const AbstractEventDispatcher &) = delete; AbstractEventDispatcher & operator = (const AbstractEventDispatcher &) = delete; /** @} */ /** Conceal deleteLater slot. Use onDo_delete() instead to avoid "QCoreApplication::postEvent: Unexpected null receiver" warning. */ void deleteLater() = delete; /** Provides the number of EventDispatcher installed to the QWidget of this EventDispatcher */ unsigned int numberOfEventDispatcher() const; inline void setEventActions(EventActionInterface * eventActions) { _eventActions = eventActions; } inline bool hasGrab() const { return _hasGrab; } inline void setCursor(const QCursor & cursor) { _dispatcherCursor = cursor; } void setWhatsThis(const QString & whatsThis); void grab(); void ungrab(); public slots: /** @brief Slot calling internal \c KickTheBucket methode Calls internal methode \c KickTheBucket. Be careful using this function. Should only be used from implementations of \c EventActionInterface methodes or \c EventDelegater class. */ void onDo_kickTheBucket(); /** @brief Slot calling \c deleteLater function of QObject Never use \c delete directly for EventDispatcher class. Instead of use \c onDo_delete() function. */ void onDo_delete(); protected: QWidget * _getEventsFrom; LOGGER_T _logger; bool _cursorIsInWidget; inline bool hasFinished() { return _finishFlag; } inline bool hasActiveEvent() { return _activeEvent; } inline void setActiveEvent(bool val) { _activeEvent = val; } /** @brief Destroying EventDispatcher as result of an incoming event. As result of an incomming event (e.g. Keypress ESC) the EventDispatcher will stop, emiting signal \c signalKickTheBucket() and calls methode \c EventActionInterface::unlinkEventDispatcher() before setup \c deleteLater() call to destroy it self. */ virtual void KickTheBucket(); inline void unlinkEventDispatcher() { if (_eventActions) { _eventActions -> unlinkEventDispatcher( this ); _eventActions = nullptr; } } /* unlinkEventDispatcher */ inline bool callEventAction( bool( EventActionInterface::*actionMethodePtr)( AbstractEventDispatcher*,int,int), int x, int y ) { if (_eventActions == nullptr) return false; return (_eventActions->*actionMethodePtr)( this, x, y ); } /* callEventAction */ /** Event filter function to override to implement event handling. To workaround a cursor handling bug in QGraphicsView it is necessary to call the eventFilter function of this base class, which will monitor enter and leave events. */ virtual bool eventFilter( QObject * widget, QEvent * e ); inline EventActionInterface * getEventActions() { return _eventActions; } void setCursorToWidget( const QCursor & cursor ); QCursor getCursorFromWidget() const; bool _synthesisTouchFromMouseEvents; static unsigned int _applyGestureID; private: void initDispatcher(); bool _deleteRequested; bool _hasGrab; bool _finishFlag; bool _restoreCursor; bool _restoreMouseTracking; QCursor _cursorToRestore; bool _activeEvent; QCursor _dispatcherCursor; QString _whatsThisBackup; EventActionInterface * _eventActions; static QGestureRecognizer * _applyGestureDetection; signals: void signalKickTheBucket(); }; /* EventDispatcher */ } } /* namespace SituationMap::RB */