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