00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include "kshortcutdialog.h"
00021
00022
#include <qvariant.h>
00023
00024
#ifdef Q_WS_X11
00025
#define XK_XKB_KEYS
00026
#define XK_MISCELLANY
00027
#include <X11/Xlib.h>
00028
#include <X11/keysymdef.h>
00029
00030
#ifdef KeyPress
00031
const int XKeyPress = KeyPress;
00032
const int XKeyRelease = KeyRelease;
00033
const int XFocusOut = FocusOut;
00034
const int XFocusIn = FocusIn;
00035
#undef KeyRelease
00036
#undef KeyPress
00037
#undef FocusOut
00038
#undef FocusIn
00039
#endif
00040
#elif defined(Q_WS_WIN)
00041
# include <kkeyserver.h>
00042
#endif
00043
00044
#include <kshortcutdialog_simple.h>
00045
#include <kshortcutdialog_advanced.h>
00046
00047
#include <qbuttongroup.h>
00048
#include <qcheckbox.h>
00049
#include <qframe.h>
00050
#include <qlayout.h>
00051
#include <qradiobutton.h>
00052
#include <qtimer.h>
00053
#include <qvbox.h>
00054
00055
#include <kapplication.h>
00056
#include <kconfig.h>
00057
#include <kdebug.h>
00058
#include <kglobal.h>
00059
#include <kiconloader.h>
00060
#include <kkeynative.h>
00061
#include <klocale.h>
00062
#include <kstdguiitem.h>
00063
#include <kpushbutton.h>
00064
00065
bool KShortcutDialog::s_showMore =
false;
00066
00067 KShortcutDialog::KShortcutDialog(
const KShortcut& shortcut,
bool bQtShortcut,
QWidget* parent,
const char* name )
00068 :
KDialogBase( parent,
name, true, i18n("Configure Shortcut"),
00069
KDialogBase::Details|
KDialogBase::Ok|
KDialogBase::Cancel,
KDialogBase::Cancel, true )
00070 {
00071 setButtonText(Details, i18n(
"Advanced"));
00072 m_stack =
new QVBox(
this);
00073 m_stack->setMinimumWidth(360);
00074 m_stack->setSpacing(0);
00075 m_stack->setMargin(0);
00076 setMainWidget(m_stack);
00077
00078 m_simple =
new KShortcutDialogSimple(m_stack);
00079
00080 m_adv =
new KShortcutDialogAdvanced(m_stack);
00081 m_adv->hide();
00082
00083 m_bQtShortcut = bQtShortcut;
00084
00085 m_bGrab =
false;
00086 m_iSeq = 0;
00087 m_iKey = 0;
00088 m_ptxtCurrent = 0;
00089 m_bRecording =
false;
00090 m_mod = 0;
00091
00092 m_simple->m_btnClearShortcut->setPixmap( SmallIcon(
"locationbar_erase" ) );
00093 m_adv->m_btnClearPrimary->setPixmap( SmallIcon(
"locationbar_erase" ) );
00094 m_adv->m_btnClearAlternate->setPixmap( SmallIcon(
"locationbar_erase" ) );
00095 connect(m_simple->m_btnClearShortcut, SIGNAL(clicked()),
00096
this, SLOT(slotClearShortcut()));
00097 connect(m_adv->m_btnClearPrimary, SIGNAL(clicked()),
00098
this, SLOT(slotClearPrimary()));
00099 connect(m_adv->m_btnClearAlternate, SIGNAL(clicked()),
00100
this, SLOT(slotClearAlternate()));
00101
00102 connect(m_adv->m_txtPrimary, SIGNAL(clicked()),
00103 m_adv->m_btnPrimary, SLOT(animateClick()));
00104 connect(m_adv->m_txtAlternate, SIGNAL(clicked()),
00105 m_adv->m_btnAlternate, SLOT(animateClick()));
00106 connect(m_adv->m_btnPrimary, SIGNAL(clicked()),
00107
this, SLOT(slotSelectPrimary()));
00108 connect(m_adv->m_btnAlternate, SIGNAL(clicked()),
00109
this, SLOT(slotSelectAlternate()));
00110
00111
KGuiItem ok = KStdGuiItem::ok();
00112 ok.
setText( i18n(
"OK" ) );
00113 setButtonOK( ok );
00114
00115
KGuiItem cancel = KStdGuiItem::cancel();
00116 cancel.
setText( i18n(
"Cancel" ) );
00117 setButtonCancel( cancel );
00118
00119 setShortcut( shortcut );
00120 resize( 0, 0 );
00121
00122 s_showMore =
KConfigGroup(KGlobal::config(),
"General").readBoolEntry(
"ShowAlternativeShortcutConfig", s_showMore);
00123 updateDetails();
00124
00125
#ifdef Q_WS_X11
00126
kapp->installX11EventFilter(
this );
00127
#endif
00128
}
00129
00130 KShortcutDialog::~KShortcutDialog()
00131 {
00132 KConfigGroup group(KGlobal::config(),
"General");
00133 group.
writeEntry(
"ShowAlternativeShortcutConfig", s_showMore);
00134 }
00135
00136
void KShortcutDialog::setShortcut(
const KShortcut & shortcut )
00137 {
00138 m_shortcut =
shortcut;
00139 updateShortcutDisplay();
00140 }
00141
00142
void KShortcutDialog::updateShortcutDisplay()
00143 {
00144
QString s[2] = { m_shortcut.
seq(0).
toString(), m_shortcut.
seq(1).
toString() };
00145
00146
if( m_bRecording ) {
00147 m_ptxtCurrent->setDefault(
true );
00148 m_ptxtCurrent->setFocus();
00149
00150
00151
if( m_iKey == 0 ) {
00152
if( m_mod ) {
00153
QString keyModStr;
00154
if( m_mod & KKey::WIN ) keyModStr +=
KKey::modFlagLabel(KKey::WIN) +
"+";
00155
if( m_mod & KKey::ALT ) keyModStr +=
KKey::modFlagLabel(KKey::ALT) +
"+";
00156
if( m_mod & KKey::CTRL ) keyModStr +=
KKey::modFlagLabel(KKey::CTRL) +
"+";
00157
if( m_mod & KKey::SHIFT ) keyModStr +=
KKey::modFlagLabel(KKey::SHIFT) +
"+";
00158 s[m_iSeq] = keyModStr;
00159 }
00160 }
00161
00162
00163
else
00164 s[m_iSeq] +=
",";
00165 }
00166
else {
00167 m_adv->m_txtPrimary->setDefault(
false );
00168 m_adv->m_txtAlternate->setDefault(
false );
00169 this->setFocus();
00170 }
00171
00172 s[0].replace(
'&', QString::fromLatin1(
"&&"));
00173 s[1].replace(
'&', QString::fromLatin1(
"&&"));
00174
00175 m_simple->m_txtShortcut->setText( s[0] );
00176 m_adv->m_txtPrimary->setText( s[0] );
00177 m_adv->m_txtAlternate->setText( s[1] );
00178
00179
00180
bool bLessOk;
00181
00182
if( m_shortcut.
count() == 0 )
00183 bLessOk =
true;
00184
00185
else if( m_shortcut.
count() == 1 && m_shortcut.
seq(0).
count() <= 1 )
00186 bLessOk =
true;
00187
00188
else
00189 bLessOk =
false;
00190
enableButton(Details, bLessOk);
00191 }
00192
00193 void KShortcutDialog::slotDetails()
00194 {
00195 s_showMore = (m_adv->isHidden());
00196 updateDetails();
00197 }
00198
00199
void KShortcutDialog::updateDetails()
00200 {
00201
bool showAdvanced = s_showMore || (m_shortcut.
count() > 1);
00202 setDetails(showAdvanced);
00203 m_bRecording =
false;
00204 m_iSeq = 0;
00205 m_iKey = 0;
00206
00207
if (showAdvanced)
00208 {
00209 m_simple->hide();
00210 m_adv->show();
00211 m_adv->m_btnPrimary->setChecked(
true );
00212 slotSelectPrimary();
00213 }
00214
else
00215 {
00216 m_ptxtCurrent = m_simple->m_txtShortcut;
00217 m_adv->hide();
00218 m_simple->show();
00219 m_simple->m_txtShortcut->setDefault(
true );
00220 m_simple->m_txtShortcut->setFocus();
00221 m_adv->m_btnMultiKey->setChecked(
false );
00222 }
00223 kapp->processEvents();
00224
adjustSize();
00225 }
00226
00227
void KShortcutDialog::slotSelectPrimary()
00228 {
00229 m_bRecording =
false;
00230 m_iSeq = 0;
00231 m_iKey = 0;
00232 m_ptxtCurrent = m_adv->m_txtPrimary;
00233 m_ptxtCurrent->setDefault(
true);
00234 m_ptxtCurrent->setFocus();
00235 updateShortcutDisplay();
00236 }
00237
00238
void KShortcutDialog::slotSelectAlternate()
00239 {
00240 m_bRecording =
false;
00241 m_iSeq = 1;
00242 m_iKey = 0;
00243 m_ptxtCurrent = m_adv->m_txtAlternate;
00244 m_ptxtCurrent->setDefault(
true);
00245 m_ptxtCurrent->setFocus();
00246 updateShortcutDisplay();
00247 }
00248
00249
void KShortcutDialog::slotClearShortcut()
00250 {
00251 m_shortcut.
setSeq( 0,
KKeySequence() );
00252 updateShortcutDisplay();
00253 }
00254
00255
void KShortcutDialog::slotClearPrimary()
00256 {
00257 m_shortcut.
setSeq( 0,
KKeySequence() );
00258 m_adv->m_btnPrimary->setChecked(
true );
00259 slotSelectPrimary();
00260 }
00261
00262
void KShortcutDialog::slotClearAlternate()
00263 {
00264
if( m_shortcut.
count() == 2 )
00265 m_shortcut.
init( m_shortcut.
seq(0) );
00266 m_adv->m_btnAlternate->setChecked(
true );
00267 slotSelectAlternate();
00268 }
00269
00270
void KShortcutDialog::slotMultiKeyMode(
bool bOn )
00271 {
00272
00273
if( !bOn && m_bRecording ) {
00274 m_bRecording =
false;
00275 m_iKey = 0;
00276 updateShortcutDisplay();
00277 }
00278 }
00279
00280
#ifdef Q_WS_X11
00281
00282
00283
00284
bool KShortcutDialog::x11Event( XEvent *pEvent )
00285 {
00286
switch( pEvent->type ) {
00287
case XKeyPress:
00288 x11KeyPressEvent( pEvent );
00289
return true;
00290
case XKeyRelease:
00291 x11KeyReleaseEvent( pEvent );
00292
return true;
00293
case XFocusIn:
00294
if (!m_bGrab) {
00295
00296 grabKeyboard();
00297 m_bGrab =
true;
00298 }
00299
00300
00301
break;
00302
case XFocusOut:
00303
if (m_bGrab) {
00304
00305 releaseKeyboard();
00306 m_bGrab =
false;
00307 }
00308
00309
00310
break;
00311
default:
00312
00313
break;
00314 }
00315
return KDialogBase::x11Event( pEvent );
00316 }
00317
00318
static uint getModsFromModX( uint keyModX )
00319 {
00320 uint mod = 0;
00321
if( keyModX &
KKeyNative::modX(KKey::SHIFT) ) mod += KKey::SHIFT;
00322
if( keyModX &
KKeyNative::modX(KKey::CTRL) ) mod += KKey::CTRL;
00323
if( keyModX &
KKeyNative::modX(KKey::ALT) ) mod += KKey::ALT;
00324
if( keyModX &
KKeyNative::modX(KKey::WIN) ) mod += KKey::WIN;
00325
return mod;
00326 }
00327
00328
static bool convertSymXToMod( uint keySymX, uint* pmod )
00329 {
00330
switch( keySymX ) {
00331
00332
00333
00334
case XK_Shift_L:
case XK_Shift_R: *pmod = KKey::SHIFT;
break;
00335
case XK_Control_L:
case XK_Control_R: *pmod = KKey::CTRL;
break;
00336
case XK_Alt_L:
case XK_Alt_R: *pmod = KKey::ALT;
break;
00337
00338
case XK_Meta_L:
case XK_Meta_R:
00339
case XK_Super_L:
case XK_Super_R: *pmod = KKey::WIN;
break;
00340
case XK_Hyper_L:
case XK_Hyper_R:
00341
case XK_Mode_switch:
00342
case XK_Num_Lock:
00343
case XK_Caps_Lock:
00344
break;
00345
default:
00346
return false;
00347 }
00348
return true;
00349 }
00350
00351
void KShortcutDialog::x11KeyPressEvent( XEvent* pEvent )
00352 {
00353
KKeyNative keyNative( pEvent );
00354 uint keyModX = keyNative.
mod();
00355 uint keySymX = keyNative.
sym();
00356
00357 m_mod = getModsFromModX( keyModX );
00358
00359
if( keySymX ) {
00360 m_bRecording =
true;
00361
00362 uint mod = 0;
00363
if( convertSymXToMod( keySymX, &mod ) ) {
00364
if( mod )
00365 m_mod |= mod;
00366 }
00367
else
00368 keyPressed(
KKey(keyNative) );
00369 }
00370 updateShortcutDisplay();
00371 }
00372
00373
void KShortcutDialog::x11KeyReleaseEvent( XEvent* pEvent )
00374 {
00375
00376
00377
if( m_bRecording && m_iKey == 0 ) {
00378
KKeyNative keyNative( pEvent );
00379 uint keyModX = keyNative.
mod();
00380 uint keySymX = keyNative.
sym();
00381
00382 m_mod = getModsFromModX( keyModX );
00383
00384 uint mod = 0;
00385
if( convertSymXToMod( keySymX, &mod ) && mod ) {
00386 m_mod &= ~mod;
00387
if( !m_mod )
00388 m_bRecording =
false;
00389 }
00390 updateShortcutDisplay();
00391 }
00392 }
00393
#elif defined(Q_WS_WIN)
00394
void KShortcutDialog::keyPressEvent(
QKeyEvent * e )
00395 {
00396
kdDebug() << e->text() <<
" " << (
int)e->text()[0].latin1()<<
" " << (
int)e->ascii() <<
endl;
00397
00398
int keyQt =
QChar( e->key() & 0xff ).isLetter() ?
00399 (QChar( e->key() & 0xff ).lower().latin1() | (e->key() & 0xffff00) )
00400 : e->key();
00401
int modQt =
KKeyServer::qtButtonStateToMod( e->state() );
00402
KKeyNative keyNative(
KKey(keyQt, modQt) );
00403 m_mod = keyNative.
mod();
00404 uint keySym = keyNative.
sym();
00405
00406
switch( keySym ) {
00407
case Key_Shift:
00408 m_mod |= KKey::SHIFT;
00409 m_bRecording =
true;
00410
break;
00411
case Key_Control:
00412 m_mod |= KKey::CTRL;
00413 m_bRecording =
true;
00414
break;
00415
case Key_Alt:
00416 m_mod |= KKey::ALT;
00417 m_bRecording =
true;
00418
break;
00419
case Key_Menu:
00420
case Key_Meta:
00421
break;
00422
default:
00423
if( keyNative.
sym() == Key_Return && m_iKey > 0 ) {
00424 accept();
00425
return;
00426 }
00427
00428
if (keyNative.
sym()) {
00429
KKey key = keyNative;
00430
key.simplify();
00431
KKeySequence seq;
00432
if( m_iKey == 0 )
00433 seq =
key;
00434
else {
00435 seq = m_shortcut.
seq( m_iSeq );
00436 seq.
setKey( m_iKey, key );
00437 }
00438 m_shortcut.
setSeq( m_iSeq, seq );
00439
00440
if(m_adv->m_btnMultiKey->isChecked())
00441 m_iKey++;
00442
00443 m_bRecording =
true;
00444
00445 updateShortcutDisplay();
00446
00447
if( !m_adv->m_btnMultiKey->isChecked() )
00448 QTimer::singleShot(500,
this, SLOT(accept()));
00449 }
00450
return;
00451 }
00452
00453
00454
00455
if( m_iKey == 0 ) {
00456 updateShortcutDisplay();
00457 }
00458 }
00459
00460
bool KShortcutDialog::event (
QEvent * e )
00461 {
00462
if (e->type()==QEvent::KeyRelease) {
00463
int modQt =
KKeyServer::qtButtonStateToMod( static_cast<QKeyEvent*>(e)->state() );
00464
KKeyNative keyNative(
KKey(static_cast<QKeyEvent*>(e)->
key(), modQt) );
00465 uint keySym = keyNative.
sym();
00466
00467
bool change =
true;
00468
switch( keySym ) {
00469
case Key_Shift:
00470
if (m_mod & KKey::SHIFT)
00471 m_mod ^= KKey::SHIFT;
00472
break;
00473
case Key_Control:
00474
if (m_mod & KKey::CTRL)
00475 m_mod ^= KKey::CTRL;
00476
break;
00477
case Key_Alt:
00478
if (m_mod & KKey::ALT)
00479 m_mod ^= KKey::ALT;
00480
break;
00481
default:
00482 change =
false;
00483 }
00484
if (change)
00485 updateShortcutDisplay();
00486 }
00487
return KDialogBase::event(e);
00488 }
00489
#endif
00490
00491
void KShortcutDialog::keyPressed(
KKey key )
00492 {
00493
kdDebug(125) <<
"keyPressed: " <<
key.toString() <<
endl;
00494
00495
key.simplify();
00496
if( m_bQtShortcut ) {
00497
key =
key.keyCodeQt();
00498
if(
key.isNull() ) {
00499
00500 }
00501 }
00502
00503
KKeySequence seq;
00504
if( m_iKey == 0 )
00505 seq =
key;
00506
else {
00507
00508
key.init(
key.sym(), 0 );
00509 seq = m_shortcut.
seq( m_iSeq );
00510 seq.
setKey( m_iKey, key );
00511 }
00512
00513 m_shortcut.
setSeq( m_iSeq, seq );
00514
00515 m_mod = 0;
00516
if( m_adv->m_btnMultiKey->isChecked() && m_iKey < KKeySequence::MAX_KEYS - 1 )
00517 m_iKey++;
00518
else {
00519 m_iKey = 0;
00520 m_bRecording =
false;
00521 }
00522
00523 updateShortcutDisplay();
00524
00525
if( !m_adv->m_btnMultiKey->isChecked() )
00526 QTimer::singleShot(500,
this, SLOT(accept()));
00527 }
00528
00529
#include "kshortcutdialog.moc"