00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kaccel.h"
00021
00022 #include <qaccel.h>
00023 #include <qguardedptr.h>
00024 #include <qpopupmenu.h>
00025 #include <qstring.h>
00026 #include <qtimer.h>
00027
00028 #include "kaccelbase.h"
00029 #include <kapplication.h>
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <kshortcut.h>
00033
00034 #include "kaccelprivate.h"
00035
00036 #ifdef Q_WS_X11
00037 # include <X11/Xlib.h>
00038 # ifdef KeyPress // needed for --enable-final
00039
00040 const int XKeyPress = KeyPress;
00041 # undef KeyPress
00042 # endif
00043 #endif
00044
00045
00046
00047
00048
00049
00050 bool kde_g_bKillAccelOverride = false;
00051
00052 class KAccelEventHandler : public QWidget
00053 {
00054 public:
00055 static KAccelEventHandler* self()
00056 {
00057 if( !g_pSelf )
00058 g_pSelf = new KAccelEventHandler;
00059 return g_pSelf;
00060 }
00061
00062 static void accelActivated( bool b ) { g_bAccelActivated = b; }
00063
00064 private:
00065 KAccelEventHandler();
00066
00067 # ifdef Q_WS_X11
00068 bool x11Event( XEvent* pEvent );
00069 # endif
00070
00071 static KAccelEventHandler* g_pSelf;
00072 static bool g_bAccelActivated;
00073 };
00074
00075 KAccelEventHandler* KAccelEventHandler::g_pSelf = 0;
00076 bool KAccelEventHandler::g_bAccelActivated = false;
00077
00078 KAccelEventHandler::KAccelEventHandler()
00079 {
00080 # ifdef Q_WS_X11
00081 if ( kapp )
00082 kapp->installX11EventFilter( this );
00083 # endif
00084 }
00085
00086 #ifdef Q_WS_X11
00087 bool qt_try_modal( QWidget *, XEvent * );
00088
00089 bool KAccelEventHandler::x11Event( XEvent* pEvent )
00090 {
00091 if( QWidget::keyboardGrabber() || !kapp->focusWidget() )
00092 return false;
00093
00094 if ( !qt_try_modal(kapp->focusWidget(), pEvent) )
00095 return false;
00096
00097 if( pEvent->type == XKeyPress ) {
00098 KKeyNative keyNative( pEvent );
00099 KKey key( keyNative );
00100 key.simplify();
00101 int keyCodeQt = key.keyCodeQt();
00102 int state = 0;
00103 if( key.modFlags() & KKey::SHIFT ) state |= Qt::ShiftButton;
00104 if( key.modFlags() & KKey::CTRL ) state |= Qt::ControlButton;
00105 if( key.modFlags() & KKey::ALT ) state |= Qt::AltButton;
00106 if( key.modFlags() & KKey::WIN ) state |= Qt::MetaButton;
00107
00108 QKeyEvent ke( QEvent::AccelOverride, keyCodeQt, 0, state );
00109 ke.ignore();
00110
00111 g_bAccelActivated = false;
00112 kapp->sendEvent( kapp->focusWidget(), &ke );
00113
00114
00115
00116 if( ke.isAccepted() && !g_bAccelActivated )
00117 kde_g_bKillAccelOverride = true;
00118
00119
00120 return g_bAccelActivated;
00121 }
00122
00123 return false;
00124 }
00125 #endif // Q_WS_X11
00126
00127
00128
00129
00130
00131 KAccelPrivate::KAccelPrivate( KAccel* pParent, QWidget* pWatch )
00132 : KAccelBase( KAccelBase::QT_KEYS )
00133 {
00134
00135 m_pAccel = pParent;
00136 m_pWatch = pWatch;
00137 m_bAutoUpdate = true;
00138 connect( (QAccel*)m_pAccel, SIGNAL(activated(int)), this, SLOT(slotKeyPressed(int)) );
00139
00140 if( m_pWatch )
00141 m_pWatch->installEventFilter( this );
00142 KAccelEventHandler::self();
00143 }
00144
00145 void KAccelPrivate::setEnabled( bool bEnabled )
00146 {
00147 m_bEnabled = bEnabled;
00148 ((QAccel*)m_pAccel)->setEnabled( bEnabled );
00149 }
00150
00151 bool KAccelPrivate::setEnabled( const QString& sAction, bool bEnable )
00152 {
00153 kdDebug(125) << "KAccelPrivate::setEnabled( \"" << sAction << "\", " << bEnable << " ): this = " << this << endl;
00154 KAccelAction* pAction = actionPtr( sAction );
00155 if( !pAction )
00156 return false;
00157 if( pAction->isEnabled() == bEnable )
00158 return true;
00159
00160 pAction->setEnabled( bEnable );
00161
00162 QMap<int, KAccelAction*>::iterator it = m_mapIDToAction.begin();
00163 for( ; it != m_mapIDToAction.end(); ++it ) {
00164 if( *it == pAction )
00165 ((QAccel*)m_pAccel)->setItemEnabled( it.key(), bEnable );
00166 }
00167 return true;
00168 }
00169
00170 bool KAccelPrivate::removeAction( const QString& sAction )
00171 {
00172
00173
00174
00175 KAccelAction* pAction = actions().actionPtr( sAction );
00176 if( pAction ) {
00177 int nID = pAction->getID();
00178
00179 bool b = KAccelBase::remove( sAction );
00180 ((QAccel*)m_pAccel)->removeItem( nID );
00181 return b;
00182 } else
00183 return false;
00184 }
00185
00186 bool KAccelPrivate::emitSignal( KAccelBase::Signal signal )
00187 {
00188 if( signal == KAccelBase::KEYCODE_CHANGED ) {
00189 m_pAccel->emitKeycodeChanged();
00190 return true;
00191 }
00192 return false;
00193 }
00194
00195 bool KAccelPrivate::connectKey( KAccelAction& action, const KKeyServer::Key& key )
00196 {
00197 uint keyQt = key.keyCodeQt();
00198 int nID = ((QAccel*)m_pAccel)->insertItem( keyQt );
00199 m_mapIDToAction[nID] = &action;
00200 m_mapIDToKey[nID] = keyQt;
00201
00202 if( action.objSlotPtr() && action.methodSlotPtr() ) {
00203 ((QAccel*)m_pAccel)->connectItem( nID, action.objSlotPtr(), action.methodSlotPtr() );
00204 if( !action.isEnabled() )
00205 ((QAccel*)m_pAccel)->setItemEnabled( nID, false );
00206 }
00207
00208 kdDebug(125) << "KAccelPrivate::connectKey( \"" << action.name() << "\", " << key.key().toStringInternal() << " = 0x" << QString::number(keyQt,16) << " ): id = " << nID << " m_pObjSlot = " << action.objSlotPtr() << endl;
00209
00210 return nID != 0;
00211 }
00212
00213 bool KAccelPrivate::connectKey( const KKeyServer::Key& key )
00214 {
00215 uint keyQt = key.keyCodeQt();
00216 int nID = ((QAccel*)m_pAccel)->insertItem( keyQt );
00217
00218 m_mapIDToKey[nID] = keyQt;
00219
00220 kdDebug(125) << "KAccelPrivate::connectKey( " << key.key().toStringInternal() << " = 0x" << QString::number(keyQt,16) << " ): id = " << nID << endl;
00221 return nID != 0;
00222 }
00223
00224 bool KAccelPrivate::disconnectKey( KAccelAction& action, const KKeyServer::Key& key )
00225 {
00226 int keyQt = key.keyCodeQt();
00227 QMap<int, int>::iterator it = m_mapIDToKey.begin();
00228 for( ; it != m_mapIDToKey.end(); ++it ) {
00229
00230 if( *it == keyQt ) {
00231 int nID = it.key();
00232 kdDebug(125) << "KAccelPrivate::disconnectKey( \"" << action.name() << "\", 0x" << QString::number(keyQt,16) << " ) : id = " << nID << " m_pObjSlot = " << action.objSlotPtr() << endl;
00233 ((QAccel*)m_pAccel)->removeItem( nID );
00234 m_mapIDToAction.remove( nID );
00235 m_mapIDToKey.remove( it );
00236 return true;
00237 }
00238 }
00239
00240 kdWarning(125) << "Didn't find key in m_mapIDToKey." << endl;
00241 return false;
00242 }
00243
00244 bool KAccelPrivate::disconnectKey( const KKeyServer::Key& key )
00245 {
00246 int keyQt = key.keyCodeQt();
00247 kdDebug(125) << "KAccelPrivate::disconnectKey( 0x" << QString::number(keyQt,16) << " )" << endl;
00248 QMap<int, int>::iterator it = m_mapIDToKey.begin();
00249 for( ; it != m_mapIDToKey.end(); ++it ) {
00250 if( *it == keyQt ) {
00251 ((QAccel*)m_pAccel)->removeItem( it.key() );
00252 m_mapIDToKey.remove( it );
00253 return true;
00254 }
00255 }
00256
00257 kdWarning(125) << "Didn't find key in m_mapIDTokey." << endl;
00258 return false;
00259 }
00260
00261 void KAccelPrivate::slotKeyPressed( int id )
00262 {
00263 kdDebug(125) << "KAccelPrivate::slotKeyPressed( " << id << " )" << endl;
00264
00265 if( m_mapIDToKey.contains( id ) ) {
00266 KKey key = m_mapIDToKey[id];
00267 KKeySequence seq( key );
00268 QPopupMenu* pMenu = createPopupMenu( m_pWatch, seq );
00269
00270
00271
00272
00273
00274
00275
00276 if( pMenu->count() == 2 && static_cast<int>( pMenu->accel(1) ) == 0 ) {
00277 int iAction = pMenu->idAt(1);
00278 slotMenuActivated( iAction );
00279 } else {
00280 connect( pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuActivated(int)) );
00281 pMenu->exec( m_pWatch->mapToGlobal( QPoint( 0, 0 ) ) );
00282 disconnect( pMenu, SIGNAL(activated(int)), this, SLOT(slotMenuActivated(int)) );
00283 }
00284 delete pMenu;
00285 }
00286 }
00287
00288 void KAccelPrivate::slotShowMenu()
00289 {
00290 }
00291
00292 void KAccelPrivate::slotMenuActivated( int iAction )
00293 {
00294 kdDebug(125) << "KAccelPrivate::slotMenuActivated( " << iAction << " )" << endl;
00295 KAccelAction* pAction = actions().actionPtr( iAction );
00296 if( pAction ) {
00297 connect( this, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
00298 emit menuItemActivated();
00299 disconnect( this, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
00300 }
00301 }
00302
00303 bool KAccelPrivate::eventFilter( QObject* , QEvent* pEvent )
00304 {
00305 if( pEvent->type() == QEvent::AccelOverride && m_bEnabled ) {
00306 QKeyEvent* pKeyEvent = (QKeyEvent*) pEvent;
00307 KKey key( pKeyEvent );
00308 kdDebug(125) << "KAccelPrivate::eventFilter( AccelOverride ): this = " << this << ", key = " << key.toStringInternal() << endl;
00309 int keyCodeQt = key.keyCodeQt();
00310 QMap<int, int>::iterator it = m_mapIDToKey.begin();
00311 for( ; it != m_mapIDToKey.end(); ++it ) {
00312 if( (*it) == keyCodeQt ) {
00313 int nID = it.key();
00314 kdDebug(125) << "shortcut found!" << endl;
00315 if( m_mapIDToAction.contains( nID ) ) {
00316
00317 KAccelAction* pAction = m_mapIDToAction[nID];
00318 if( !pAction->isEnabled() )
00319 continue;
00320 QGuardedPtr<KAccelPrivate> me = this;
00321 connect( this, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
00322 emit menuItemActivated();
00323 if (me) {
00324 disconnect( me, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
00325 }
00326 } else
00327 slotKeyPressed( nID );
00328
00329 pKeyEvent->accept();
00330 KAccelEventHandler::accelActivated( true );
00331 return true;
00332 }
00333 }
00334 }
00335 return false;
00336 }
00337
00338
00339
00340
00341
00342 KAccel::KAccel( QWidget* pParent, const char* psName )
00343 : QAccel( pParent, (psName) ? psName : "KAccel-QAccel" )
00344 {
00345 kdDebug(125) << "KAccel( pParent = " << pParent << ", psName = " << psName << " ): this = " << this << endl;
00346 d = new KAccelPrivate( this, pParent );
00347 }
00348
00349 KAccel::KAccel( QWidget* watch, QObject* pParent, const char* psName )
00350 : QAccel( watch, pParent, (psName) ? psName : "KAccel-QAccel" )
00351 {
00352 kdDebug(125) << "KAccel( watch = " << watch << ", pParent = " << pParent << ", psName = " << psName << " ): this = " << this << endl;
00353 if( !watch )
00354 kdDebug(125) << kdBacktrace() << endl;
00355 d = new KAccelPrivate( this, watch );
00356 }
00357
00358 KAccel::~KAccel()
00359 {
00360 kdDebug(125) << "~KAccel(): this = " << this << endl;
00361 delete d;
00362 }
00363
00364 KAccelActions& KAccel::actions() { return d->actions(); }
00365 const KAccelActions& KAccel::actions() const { return d->actions(); }
00366 bool KAccel::isEnabled() { return d->isEnabled(); }
00367 void KAccel::setEnabled( bool bEnabled ) { d->setEnabled( bEnabled ); }
00368 bool KAccel::setAutoUpdate( bool bAuto ) { return d->setAutoUpdate( bAuto ); }
00369
00370 KAccelAction* KAccel::insert( const QString& sAction, const QString& sLabel, const QString& sWhatsThis,
00371 const KShortcut& cutDef,
00372 const QObject* pObjSlot, const char* psMethodSlot,
00373 bool bConfigurable, bool bEnabled )
00374 {
00375 return d->insert( sAction, sLabel, sWhatsThis,
00376 cutDef, cutDef,
00377 pObjSlot, psMethodSlot,
00378 bConfigurable, bEnabled );
00379 }
00380
00381 KAccelAction* KAccel::insert( const QString& sAction, const QString& sLabel, const QString& sWhatsThis,
00382 const KShortcut& cutDef3, const KShortcut& cutDef4,
00383 const QObject* pObjSlot, const char* psMethodSlot,
00384 bool bConfigurable, bool bEnabled )
00385 {
00386 return d->insert( sAction, sLabel, sWhatsThis,
00387 cutDef3, cutDef4,
00388 pObjSlot, psMethodSlot,
00389 bConfigurable, bEnabled );
00390 }
00391
00392 KAccelAction* KAccel::insert( const char* psAction, const KShortcut& cutDef,
00393 const QObject* pObjSlot, const char* psMethodSlot,
00394 bool bConfigurable, bool bEnabled )
00395 {
00396 return d->insert( psAction, i18n(psAction), QString::null,
00397 cutDef, cutDef,
00398 pObjSlot, psMethodSlot,
00399 bConfigurable, bEnabled );
00400 }
00401
00402 KAccelAction* KAccel::insert( KStdAccel::StdAccel id,
00403 const QObject* pObjSlot, const char* psMethodSlot,
00404 bool bConfigurable, bool bEnabled )
00405 {
00406 QString sAction = KStdAccel::name( id );
00407 if( sAction.isEmpty() )
00408 return 0;
00409
00410 KAccelAction* pAction = d->insert( sAction, KStdAccel::label( id ), KStdAccel::whatsThis( id ),
00411 KStdAccel::shortcutDefault3( id ), KStdAccel::shortcutDefault4( id ),
00412 pObjSlot, psMethodSlot,
00413 bConfigurable, bEnabled );
00414 if( pAction )
00415 pAction->setShortcut( KStdAccel::shortcut( id ) );
00416
00417 return pAction;
00418 }
00419
00420 bool KAccel::remove( const QString& sAction )
00421 { return d->removeAction( sAction ); }
00422 bool KAccel::updateConnections()
00423 { return d->updateConnections(); }
00424
00425 const KShortcut& KAccel::shortcut( const QString& sAction ) const
00426 {
00427 const KAccelAction* pAction = actions().actionPtr( sAction );
00428 return (pAction) ? pAction->shortcut() : KShortcut::null();
00429 }
00430
00431 bool KAccel::setSlot( const QString& sAction, const QObject* pObjSlot, const char* psMethodSlot )
00432 { return d->setActionSlot( sAction, pObjSlot, psMethodSlot ); }
00433
00434 bool KAccel::setEnabled( const QString& sAction, bool bEnable )
00435 { return d->setEnabled( sAction, bEnable ); }
00436
00437 bool KAccel::setShortcut( const QString& sAction, const KShortcut& cut )
00438 {
00439 kdDebug(125) << "KAccel::setShortcut( \"" << sAction << "\", " << cut.toStringInternal() << " )" << endl;
00440 KAccelAction* pAction = actions().actionPtr( sAction );
00441 if( pAction ) {
00442 if( pAction->shortcut() != cut )
00443 return d->setShortcut( sAction, cut );
00444 return true;
00445 }
00446 return false;
00447 }
00448
00449 const QString& KAccel::configGroup() const
00450 { return d->configGroup(); }
00451
00452 void KAccel::setConfigGroup( const QString& s )
00453 { d->setConfigGroup( s ); }
00454
00455 bool KAccel::readSettings( KConfigBase* pConfig )
00456 {
00457 d->readSettings( pConfig );
00458 return true;
00459 }
00460
00461 bool KAccel::writeSettings( KConfigBase* pConfig ) const
00462 { d->writeSettings( pConfig ); return true; }
00463
00464 void KAccel::emitKeycodeChanged()
00465 {
00466 kdDebug(125) << "KAccel::emitKeycodeChanged()" << endl;
00467 emit keycodeChanged();
00468 }
00469
00470 #ifndef KDE_NO_COMPAT
00471
00472
00473
00474
00475 bool KAccel::insertItem( const QString& sLabel, const QString& sAction,
00476 const char* cutsDef,
00477 int , QPopupMenu *, bool bConfigurable )
00478 {
00479 KShortcut cut( cutsDef );
00480 bool b = d->insert( sAction, sLabel, QString::null,
00481 cut, cut,
00482 0, 0,
00483 bConfigurable ) != 0;
00484 return b;
00485 }
00486
00487 bool KAccel::insertItem( const QString& sLabel, const QString& sAction,
00488 int key,
00489 int , QPopupMenu*, bool bConfigurable )
00490 {
00491 KShortcut cut;
00492 cut.init( QKeySequence(key) );
00493 KAccelAction* pAction = d->insert( sAction, sLabel, QString::null,
00494 cut, cut,
00495 0, 0,
00496 bConfigurable );
00497 return pAction != 0;
00498 }
00499
00500
00501 bool KAccel::insertStdItem( KStdAccel::StdAccel id, const QString& sLabel )
00502 {
00503 KAccelAction* pAction = d->insert( KStdAccel::name( id ), sLabel, QString::null,
00504 KStdAccel::shortcutDefault3( id ), KStdAccel::shortcutDefault4( id ),
00505 0, 0 );
00506 if( pAction )
00507 pAction->setShortcut( KStdAccel::shortcut( id ) );
00508
00509 return true;
00510 }
00511
00512 bool KAccel::connectItem( const QString& sAction, const QObject* pObjSlot, const char* psMethodSlot, bool bActivate )
00513 {
00514 kdDebug(125) << "KAccel::connectItem( " << sAction << ", " << pObjSlot << ", " << psMethodSlot << " )" << endl;
00515 if( bActivate == false )
00516 d->setActionEnabled( sAction, false );
00517 bool b = setSlot( sAction, pObjSlot, psMethodSlot );
00518 if( bActivate == true )
00519 d->setActionEnabled( sAction, true );
00520 return b;
00521 }
00522
00523 bool KAccel::removeItem( const QString& sAction )
00524 { return d->removeAction( sAction ); }
00525
00526 bool KAccel::setItemEnabled( const QString& sAction, bool bEnable )
00527 { return setEnabled( sAction, bEnable ); }
00528
00529 void KAccel::changeMenuAccel( QPopupMenu *menu, int id, const QString& action )
00530 {
00531 KAccelAction* pAction = actions().actionPtr( action );
00532 QString s = menu->text( id );
00533 if( !pAction || s.isEmpty() )
00534 return;
00535
00536 int i = s.find( '\t' );
00537
00538 QString k = pAction->shortcut().seq(0).toString();
00539 if( k.isEmpty() )
00540 return;
00541
00542 if ( i >= 0 )
00543 s.replace( i+1, s.length()-i, k );
00544 else {
00545 s += '\t';
00546 s += k;
00547 }
00548
00549 QPixmap *pp = menu->pixmap(id);
00550 if( pp && !pp->isNull() )
00551 menu->changeItem( *pp, s, id );
00552 else
00553 menu->changeItem( s, id );
00554 }
00555
00556 void KAccel::changeMenuAccel( QPopupMenu *menu, int id, KStdAccel::StdAccel accel )
00557 {
00558 changeMenuAccel( menu, id, KStdAccel::name( accel ) );
00559 }
00560
00561 int KAccel::stringToKey( const QString& sKey )
00562 {
00563 return KKey( sKey ).keyCodeQt();
00564 }
00565
00566 int KAccel::currentKey( const QString& sAction ) const
00567 {
00568 KAccelAction* pAction = d->actionPtr( sAction );
00569 if( pAction )
00570 return pAction->shortcut().keyCodeQt();
00571 return 0;
00572 }
00573
00574 QString KAccel::findKey( int key ) const
00575 {
00576 KAccelAction* pAction = d->actionPtr( KKey(key) );
00577 if( pAction )
00578 return pAction->name();
00579 else
00580 return QString::null;
00581 }
00582 #endif // !KDE_NO_COMPAT
00583
00584 void KAccel::virtual_hook( int, void* )
00585 { }
00586
00587 #include "kaccel.moc"
00588 #include "kaccelprivate.moc"