From 119caa786e042bfcad6621c4d24c04bcd9c1596a Mon Sep 17 00:00:00 2001 From: asv Date: Thu, 9 Mar 2006 14:20:08 +0000 Subject: [PATCH] a bug with accelerator shadowing key presses in OTHER windows (not viewers) is fixed. --- src/SUIT/SUIT_Accel.cxx | 110 ++++++++++++++++++++++++++++++---------- src/SUIT/SUIT_Accel.h | 24 +++++---- 2 files changed, 97 insertions(+), 37 deletions(-) diff --git a/src/SUIT/SUIT_Accel.cxx b/src/SUIT/SUIT_Accel.cxx index a72a317e1..887b98bca 100644 --- a/src/SUIT/SUIT_Accel.cxx +++ b/src/SUIT/SUIT_Accel.cxx @@ -21,60 +21,116 @@ ////////////////////////////////////////////////////////////////////// #include "SUIT_Accel.h" -#include "SUIT_Desktop.h" -#include "SUIT_ViewManager.h" #include "SUIT_ViewWindow.h" +#include "SUIT_ViewManager.h" #include "SUIT_ViewModel.h" -#include +#include +#include +#include + /*!\class SUIT_Accel * Class handles keyboard accelerator bindings. */ +SUIT_Accel* SUIT_Accel::myself = 0; -/*! Constructor.*/ -SUIT_Accel::SUIT_Accel(SUIT_Desktop* theDesktop) - : QObject( theDesktop, "SUIT_Accel" ), - myDesktop( theDesktop ) +/*! Constructor [private].*/ +SUIT_Accel::SUIT_Accel() + : QObject( qApp, "SUIT_Accel" ) { - myAccel = new QAccel( theDesktop, "SUIT_Accel_interal_qaccel" ); - connect( myAccel, SIGNAL( activated( int ) ), this, SLOT( onActivated( int ) ) ); + qApp->installEventFilter( this ); } -/*! Destructor.*/ -SUIT_Accel::~SUIT_Accel() +/*! getAccel() : public interface for SUIT_Accel object. Only one instance is created and returned. */ +SUIT_Accel* SUIT_Accel::getAccel() { + if ( !myself ) + myself = new SUIT_Accel(); + return myself; } -/*! setActionKey assign a ceratain action for a key accelerator */ +/*! setActionKey() : assign a ceratain action for a key accelerator */ void SUIT_Accel::setActionKey( const int action, const int key, const QString& type ) -{ - // 1. get or generate interal "id" of action - int id = myAccel->findKey( key ); - if ( id == -1 ) - id = myAccel->insertItem( key ); - +{ IdActionMap idActionMap; if ( myMap.contains( type ) ) idActionMap = myMap[type]; - idActionMap[id] = action; + idActionMap[key] = action; myMap[type] = idActionMap; + + myOptMap[key] = true; } -/*! onActivated slot called when a registered key accelerator was activated */ -void SUIT_Accel::onActivated( int id ) +/*! unsetActionKey() : unregister a certain key accelerator */ +void SUIT_Accel::unsetActionKey( const int key, const QString& type ) { - if ( myDesktop ) { - if ( SUIT_ViewWindow* vw = myDesktop->activeWindow() ) { + if ( myMap.contains( type ) ) { + IdActionMap idActionMap = myMap[type]; + if ( idActionMap.contains( key ) ) { + idActionMap.erase( key ); + myMap[type] = idActionMap; + } + } +} + +/*! getParentViewWindow() : returns given object or any of its parents-grandparents-.. if it is a SUIT_ViewWindow */ +SUIT_ViewWindow* getParentViewWindow( const QObject* obj ) +{ + if ( obj ) { + if ( obj->inherits( "SUIT_ViewWindow" ) ) + return (SUIT_ViewWindow*)obj; + else + return getParentViewWindow( obj->parent() ); + } + return 0; +} + +/*! getKey() : returns integer key code (with modifiers) made of key pressed 'inside' given event */ +int getKey( QKeyEvent *keyEvent ) +{ + int key = keyEvent->key(), + state = keyEvent->state(); + if ( state & Qt::ShiftButton ) + key += Qt::SHIFT; + if ( state & Qt::ControlButton ) + key += Qt::CTRL; + if ( state & Qt::AltButton ) + key += Qt::ALT; + if ( state & Qt::MetaButton ) + key += Qt::META; + return key; +} + +/*! getAccelKey() : returns key pressed if 1) event was KeyPress 2) pressed key is a registered accelerator */ +int SUIT_Accel::getAccelKey( QEvent *event ) +{ + if ( event && event->type() == QEvent::KeyPress ) { + int key = ::getKey( (QKeyEvent*)event ); + if ( myOptMap.contains( key ) ) + return key; + } + return 0; +} + +/*! eventFilter() : filtering ALL events of QApplication. */ +bool SUIT_Accel::eventFilter( QObject *obj, QEvent *event ) +{ + const int key = getAccelKey( event ); + if ( key ) { + SUIT_ViewWindow* vw = ::getParentViewWindow( obj ); + if ( vw ) { QString type = vw->getViewManager()->getViewModel()->getType(); - if ( myMap.contains( type ) ) { + if ( myMap.contains( type ) ) { IdActionMap idActionMap = myMap[type]; - if ( idActionMap.contains( id ) ) { - vw->onAccelAction( idActionMap[id] ); + if ( idActionMap.contains( key ) ) { + vw->onAccelAction( idActionMap[key] ); + return true; } } } } + return false; } - + diff --git a/src/SUIT/SUIT_Accel.h b/src/SUIT/SUIT_Accel.h index 78c9bff30..ee3e96cf6 100644 --- a/src/SUIT/SUIT_Accel.h +++ b/src/SUIT/SUIT_Accel.h @@ -29,9 +29,6 @@ #include #include -class QAccel; -class SUIT_Desktop; - class SUIT_EXPORT SUIT_Accel: public QObject { Q_OBJECT @@ -53,21 +50,28 @@ public: }; public: - SUIT_Accel( SUIT_Desktop* theDesktop ); - virtual ~SUIT_Accel(); + static SUIT_Accel* getAccel(); void setActionKey( const int action, const int key, const QString& type ); + void unsetActionKey( const int key, const QString& type ); -protected slots: - void onActivated( int ); +protected: + bool eventFilter( QObject *, QEvent * ); private: - QAccel* myAccel; - SUIT_Desktop* myDesktop; + SUIT_Accel(); + + int getAccelKey( QEvent* ); // returns key pressed if 1) event was KeyPress + // 2) pressed key is a registered accelerator - typedef QMap IdActionMap; // internal_id - to - action map + typedef QMap IdActionMap; // key - to - action_id map typedef QMap ViewerTypeIdActionMap; // viewer_type - to - IdActionMap ViewerTypeIdActionMap myMap; + + QMap myOptMap; // key - to - map, used for optimazation. all registered keys (accelerators) + // are stored in this map. + + static SUIT_Accel* myself; }; #endif -- 2.39.2