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"