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