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