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