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 qt_try_modal(
QWidget *, XEvent * );
00089
00090
bool KAccelEventHandler::x11Event( XEvent* pEvent )
00091 {
00092
if( QWidget::keyboardGrabber() || !kapp->focusWidget() )
00093
return false;
00094
00095
if ( !qt_try_modal(kapp->focusWidget(), pEvent) )
00096
return false;
00097
00098
if( pEvent->type == XKeyPress ) {
00099
KKeyNative keyNative( pEvent );
00100
KKey key( keyNative );
00101
key.simplify();
00102
int keyCodeQt =
key.keyCodeQt();
00103
int state = 0;
00104
if(
key.modFlags() & KKey::SHIFT ) state |= Qt::ShiftButton;
00105
if(
key.modFlags() & KKey::CTRL ) state |= Qt::ControlButton;
00106
if(
key.modFlags() & KKey::ALT ) state |= Qt::AltButton;
00107
if(
key.modFlags() & KKey::WIN ) state |= Qt::MetaButton;
00108
00109
QKeyEvent ke( QEvent::AccelOverride, keyCodeQt, 0, state );
00110 ke.ignore();
00111
00112 g_bActive =
true;
00113 g_bAccelActivated =
false;
00114 kapp->sendEvent( kapp->focusWidget(), &ke );
00115 g_bActive =
false;
00116
00117
00118
00119
if( ke.isAccepted() && !g_bAccelActivated )
00120 kde_g_bKillAccelOverride =
true;
00121
00122
00123
return g_bAccelActivated;
00124 }
00125
00126
return false;
00127 }
00128
#endif // Q_WS_X11
00129
00130
00131
00132
00133
00134 KAccelPrivate::KAccelPrivate(
KAccel* pParent,
QWidget* pWatch )
00135 : KAccelBase( KAccelBase::QT_KEYS )
00136 {
00137
00138 m_pAccel = pParent;
00139 m_pWatch = pWatch;
00140 m_bAutoUpdate =
true;
00141 connect( (
QAccel*)m_pAccel, SIGNAL(activated(
int)),
this, SLOT(slotKeyPressed(
int)) );
00142
00143
if( m_pWatch )
00144 m_pWatch->installEventFilter(
this );
00145 KAccelEventHandler::self();
00146 }
00147
00148
void KAccelPrivate::setEnabled(
bool bEnabled )
00149 {
00150 m_bEnabled = bEnabled;
00151 ((
QAccel*)m_pAccel)->setEnabled( bEnabled );
00152 }
00153
00154
bool KAccelPrivate::setEnabled(
const QString& sAction,
bool bEnable )
00155 {
00156 kdDebug(125) <<
"KAccelPrivate::setEnabled( \"" << sAction <<
"\", " << bEnable <<
" ): this = " <<
this <<
endl;
00157 KAccelAction* pAction = actionPtr( sAction );
00158
if( !pAction )
00159
return false;
00160
if( pAction->isEnabled() == bEnable )
00161
return true;
00162
00163 pAction->setEnabled( bEnable );
00164
00165
QMap<int, KAccelAction*>::iterator it = m_mapIDToAction.begin();
00166
for( ; it != m_mapIDToAction.end(); ++it ) {
00167
if( *it == pAction )
00168 ((
QAccel*)m_pAccel)->setItemEnabled( it.key(), bEnable );
00169 }
00170
return true;
00171 }
00172
00173
bool KAccelPrivate::removeAction(
const QString& sAction )
00174 {
00175
00176
00177
00178 KAccelAction* pAction = actions().actionPtr( sAction );
00179
if( pAction ) {
00180
int nID = pAction->getID();
00181
00182
bool b = KAccelBase::remove( sAction );
00183 ((
QAccel*)m_pAccel)->removeItem( nID );
00184
return b;
00185 }
else
00186
return false;
00187 }
00188
00189
bool KAccelPrivate::emitSignal( KAccelBase::Signal signal )
00190 {
00191
if( signal == KAccelBase::KEYCODE_CHANGED ) {
00192 m_pAccel->emitKeycodeChanged();
00193
return true;
00194 }
00195
return false;
00196 }
00197
00198
bool KAccelPrivate::connectKey( KAccelAction& action,
const KKeyServer::Key& key )
00199 {
00200 uint keyQt =
key.keyCodeQt();
00201
int nID = ((
QAccel*)m_pAccel)->insertItem( keyQt );
00202 m_mapIDToAction[nID] = &
action;
00203 m_mapIDToKey[nID] = keyQt;
00204
00205
if(
action.objSlotPtr() &&
action.methodSlotPtr() ) {
00206 ((
QAccel*)m_pAccel)->connectItem( nID,
action.objSlotPtr(),
action.methodSlotPtr() );
00207
if( !
action.
isEnabled() )
00208 ((
QAccel*)m_pAccel)->setItemEnabled( nID,
false );
00209 }
00210
00211 kdDebug(125) <<
"KAccelPrivate::connectKey( \"" <<
action.name() <<
"\", " <<
key.key().toStringInternal() <<
" = 0x" << QString::number(keyQt,16) <<
" ): id = " << nID <<
" m_pObjSlot = " <<
action.objSlotPtr() <<
endl;
00212
00213
return nID != 0;
00214 }
00215
00216
bool KAccelPrivate::connectKey(
const KKeyServer::Key& key )
00217 {
00218 uint keyQt =
key.keyCodeQt();
00219
int nID = ((
QAccel*)m_pAccel)->insertItem( keyQt );
00220
00221 m_mapIDToKey[nID] = keyQt;
00222
00223 kdDebug(125) <<
"KAccelPrivate::connectKey( " <<
key.key().toStringInternal() <<
" = 0x" << QString::number(keyQt,16) <<
" ): id = " << nID <<
endl;
00224
return nID != 0;
00225 }
00226
00227
bool KAccelPrivate::disconnectKey( KAccelAction& action,
const KKeyServer::Key& key )
00228 {
00229
int keyQt =
key.keyCodeQt();
00230
QMap<int, int>::iterator it = m_mapIDToKey.begin();
00231
for( ; it != m_mapIDToKey.end(); ++it ) {
00232
00233
if( *it == keyQt ) {
00234
int nID = it.key();
00235 kdDebug(125) <<
"KAccelPrivate::disconnectKey( \"" <<
action.name() <<
"\", 0x" << QString::number(keyQt,16) <<
" ) : id = " << nID <<
" m_pObjSlot = " <<
action.objSlotPtr() <<
endl;
00236 ((
QAccel*)m_pAccel)->removeItem( nID );
00237 m_mapIDToAction.remove( nID );
00238 m_mapIDToKey.remove( it );
00239
return true;
00240 }
00241 }
00242
00243 kdWarning(125) <<
"Didn't find key in m_mapIDToKey." <<
endl;
00244
return false;
00245 }
00246
00247
bool KAccelPrivate::disconnectKey(
const KKeyServer::Key& key )
00248 {
00249
int keyQt =
key.keyCodeQt();
00250 kdDebug(125) <<
"KAccelPrivate::disconnectKey( 0x" << QString::number(keyQt,16) <<
" )" <<
endl;
00251
QMap<int, int>::iterator it = m_mapIDToKey.begin();
00252
for( ; it != m_mapIDToKey.end(); ++it ) {
00253
if( *it == keyQt ) {
00254 ((
QAccel*)m_pAccel)->removeItem( it.key() );
00255 m_mapIDToKey.remove( it );
00256
return true;
00257 }
00258 }
00259
00260 kdWarning(125) <<
"Didn't find key in m_mapIDTokey." <<
endl;
00261
return false;
00262 }
00263
00264
void KAccelPrivate::slotKeyPressed(
int id )
00265 {
00266 kdDebug(125) <<
"KAccelPrivate::slotKeyPressed( " <<
id <<
" )" <<
endl;
00267
00268
if( m_mapIDToKey.contains(
id ) ) {
00269
KKey key = m_mapIDToKey[
id];
00270
KKeySequence seq( key );
00271
QPopupMenu* pMenu = createPopupMenu( m_pWatch, seq );
00272
00273
00274
00275
00276
00277
00278
00279
if( pMenu->count() == 2 && static_cast<int>( pMenu->accel(1) ) == 0 ) {
00280
int iAction = pMenu->idAt(1);
00281 slotMenuActivated( iAction );
00282 }
else {
00283 connect( pMenu, SIGNAL(activated(
int)),
this, SLOT(slotMenuActivated(
int)) );
00284 pMenu->exec( m_pWatch->mapToGlobal(
QPoint( 0, 0 ) ) );
00285 disconnect( pMenu, SIGNAL(activated(
int)),
this, SLOT(slotMenuActivated(
int)) );
00286 }
00287
delete pMenu;
00288 }
00289 }
00290
00291
void KAccelPrivate::slotShowMenu()
00292 {
00293 }
00294
00295
void KAccelPrivate::slotMenuActivated(
int iAction )
00296 {
00297 kdDebug(125) <<
"KAccelPrivate::slotMenuActivated( " << iAction <<
" )" <<
endl;
00298 KAccelAction* pAction = actions().actionPtr( iAction );
00299
if( pAction ) {
00300 connect(
this, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
00301 emit menuItemActivated();
00302 disconnect(
this, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
00303 }
00304 }
00305
00306
bool KAccelPrivate::eventFilter(
QObject* ,
QEvent* pEvent )
00307 {
00308
if( KAccelEventHandler::active() && pEvent->type() == QEvent::AccelOverride && m_bEnabled ) {
00309
QKeyEvent* pKeyEvent = (
QKeyEvent*) pEvent;
00310
KKey key( pKeyEvent );
00311 kdDebug(125) <<
"KAccelPrivate::eventFilter( AccelOverride ): this = " <<
this <<
", key = " <<
key.toStringInternal() <<
endl;
00312
int keyCodeQt =
key.keyCodeQt();
00313
QMap<int, int>::iterator it = m_mapIDToKey.begin();
00314
for( ; it != m_mapIDToKey.end(); ++it ) {
00315
if( (*it) == keyCodeQt ) {
00316
int nID = it.key();
00317 kdDebug(125) <<
"shortcut found!" <<
endl;
00318
if( m_mapIDToAction.contains( nID ) ) {
00319
00320 KAccelAction* pAction = m_mapIDToAction[nID];
00321
if( !pAction->isEnabled() )
00322
continue;
00323 connect(
this, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
00324 emit menuItemActivated();
00325 disconnect(
this, SIGNAL(menuItemActivated()), pAction->objSlotPtr(), pAction->methodSlotPtr() );
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::action(
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"