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
#endif
00041
00042
#include <kshortcutdialog_simple.h>
00043
#include <kshortcutdialog_advanced.h>
00044
00045
#include <qbuttongroup.h>
00046
#include <qcheckbox.h>
00047
#include <qframe.h>
00048
#include <qlayout.h>
00049
#include <qradiobutton.h>
00050
#include <qtimer.h>
00051
#include <qvbox.h>
00052
00053
#include <kapplication.h>
00054
#include <kconfig.h>
00055
#include <kdebug.h>
00056
#include <kglobal.h>
00057
#include <kiconloader.h>
00058
#include <kkeynative.h>
00059
#include <klocale.h>
00060
#include <kstdguiitem.h>
00061
#include <kpushbutton.h>
00062
00063
bool KShortcutDialog::s_showMore =
false;
00064
00065 KShortcutDialog::KShortcutDialog(
const KShortcut& shortcut,
bool bQtShortcut,
QWidget* parent,
const char* name )
00066 :
KDialogBase( parent,
name, true, i18n(
"Configure Shortcut"),
00067
KDialogBase::Details|
KDialogBase::Ok|
KDialogBase::Cancel,
KDialogBase::Cancel, true )
00068 {
00069 setButtonText(Details, i18n(
"Advanced"));
00070 m_stack =
new QVBox(
this);
00071 m_stack->setMinimumWidth(360);
00072 m_stack->setSpacing(0);
00073 m_stack->setMargin(0);
00074 setMainWidget(m_stack);
00075
00076 m_simple =
new KShortcutDialogSimple(m_stack);
00077
00078 m_adv =
new KShortcutDialogAdvanced(m_stack);
00079 m_adv->hide();
00080
00081 m_bQtShortcut = bQtShortcut;
00082
00083 m_bGrab =
false;
00084 m_iSeq = 0;
00085 m_iKey = 0;
00086 m_ptxtCurrent = 0;
00087 m_bRecording =
false;
00088 m_mod = 0;
00089
00090 m_simple->m_btnClearShortcut->setPixmap( SmallIcon(
"locationbar_erase" ) );
00091 m_adv->m_btnClearPrimary->setPixmap( SmallIcon(
"locationbar_erase" ) );
00092 m_adv->m_btnClearAlternate->setPixmap( SmallIcon(
"locationbar_erase" ) );
00093 connect(m_simple->m_btnClearShortcut, SIGNAL(clicked()),
00094
this, SLOT(slotClearShortcut()));
00095 connect(m_adv->m_btnClearPrimary, SIGNAL(clicked()),
00096
this, SLOT(slotClearPrimary()));
00097 connect(m_adv->m_btnClearAlternate, SIGNAL(clicked()),
00098
this, SLOT(slotClearAlternate()));
00099
00100 connect(m_adv->m_txtPrimary, SIGNAL(clicked()),
00101 m_adv->m_btnPrimary, SLOT(animateClick()));
00102 connect(m_adv->m_txtAlternate, SIGNAL(clicked()),
00103 m_adv->m_btnAlternate, SLOT(animateClick()));
00104 connect(m_adv->m_btnPrimary, SIGNAL(clicked()),
00105
this, SLOT(slotSelectPrimary()));
00106 connect(m_adv->m_btnAlternate, SIGNAL(clicked()),
00107
this, SLOT(slotSelectAlternate()));
00108
00109 KGuiItem ok = KStdGuiItem::ok();
00110 ok.setText( i18n(
"OK" ) );
00111 setButtonOK( ok );
00112
00113 KGuiItem cancel = KStdGuiItem::cancel();
00114 cancel.setText( i18n(
"Cancel" ) );
00115 setButtonCancel( cancel );
00116
00117 setShortcut( shortcut );
00118 resize( 0, 0 );
00119
00120 s_showMore =
KConfigGroup(KGlobal::config(),
"General").readBoolEntry(
"ShowAlternativeShortcutConfig", s_showMore);
00121 updateDetails();
00122
00123
#ifdef Q_WS_X11
00124
kapp->installX11EventFilter(
this );
00125
#endif
00126
}
00127
00128 KShortcutDialog::~KShortcutDialog()
00129 {
00130
KConfigGroup group(KGlobal::config(),
"General");
00131 group.writeEntry(
"ShowAlternativeShortcutConfig", s_showMore);
00132 }
00133
00134
void KShortcutDialog::setShortcut(
const KShortcut & shortcut )
00135 {
00136 m_shortcut =
shortcut;
00137 updateShortcutDisplay();
00138 }
00139
00140
void KShortcutDialog::updateShortcutDisplay()
00141 {
00142
QString s[2] = { m_shortcut.seq(0).toString(), m_shortcut.seq(1).toString() };
00143
00144
if( m_bRecording ) {
00145 m_ptxtCurrent->setDefault(
true );
00146 m_ptxtCurrent->setFocus();
00147
00148
00149
if( m_iKey == 0 ) {
00150
if( m_mod ) {
00151
QString keyModStr;
00152
if( m_mod & KKey::WIN ) keyModStr +=
KKey::modFlagLabel(KKey::WIN) +
"+";
00153
if( m_mod & KKey::ALT ) keyModStr +=
KKey::modFlagLabel(KKey::ALT) +
"+";
00154
if( m_mod & KKey::CTRL ) keyModStr +=
KKey::modFlagLabel(KKey::CTRL) +
"+";
00155
if( m_mod & KKey::SHIFT ) keyModStr +=
KKey::modFlagLabel(KKey::SHIFT) +
"+";
00156 s[m_iSeq] = keyModStr;
00157 }
00158 }
00159
00160
00161
else
00162 s[m_iSeq] +=
",";
00163 }
00164
else {
00165 m_adv->m_txtPrimary->setDefault(
false );
00166 m_adv->m_txtAlternate->setDefault(
false );
00167 this->setFocus();
00168 }
00169
00170 m_simple->m_txtShortcut->setText( s[0] );
00171 m_adv->m_txtPrimary->setText( s[0] );
00172 m_adv->m_txtAlternate->setText( s[1] );
00173
00174
00175
bool bLessOk;
00176
00177
if( m_shortcut.count() == 0 )
00178 bLessOk =
true;
00179
00180
else if( m_shortcut.count() == 1 && m_shortcut.seq(0).count() <= 1 )
00181 bLessOk =
true;
00182
00183
else
00184 bLessOk =
false;
00185 enableButton(Details, bLessOk);
00186 }
00187
00188
void KShortcutDialog::slotDetails()
00189 {
00190 s_showMore = (m_adv->isHidden());
00191 updateDetails();
00192 }
00193
00194
void KShortcutDialog::updateDetails()
00195 {
00196
bool showAdvanced = s_showMore || (m_shortcut.count() > 1);
00197 setDetails(showAdvanced);
00198 m_bRecording =
false;
00199 m_iSeq = 0;
00200 m_iKey = 0;
00201
00202
if (showAdvanced)
00203 {
00204 m_simple->hide();
00205 m_adv->show();
00206 m_adv->m_btnPrimary->setChecked(
true );
00207 slotSelectPrimary();
00208 }
00209
else
00210 {
00211 m_ptxtCurrent = m_simple->m_txtShortcut;
00212 m_adv->hide();
00213 m_simple->show();
00214 m_simple->m_txtShortcut->setDefault(
true );
00215 m_simple->m_txtShortcut->setFocus();
00216 m_adv->m_btnMultiKey->setChecked(
false );
00217 }
00218 kapp->processEvents();
00219 adjustSize();
00220 }
00221
00222
void KShortcutDialog::slotSelectPrimary()
00223 {
00224 m_bRecording =
false;
00225 m_iSeq = 0;
00226 m_iKey = 0;
00227 m_ptxtCurrent = m_adv->m_txtPrimary;
00228 m_ptxtCurrent->setDefault(
true);
00229 m_ptxtCurrent->setFocus();
00230 updateShortcutDisplay();
00231 }
00232
00233
void KShortcutDialog::slotSelectAlternate()
00234 {
00235 m_bRecording =
false;
00236 m_iSeq = 1;
00237 m_iKey = 0;
00238 m_ptxtCurrent = m_adv->m_txtAlternate;
00239 m_ptxtCurrent->setDefault(
true);
00240 m_ptxtCurrent->setFocus();
00241 updateShortcutDisplay();
00242 }
00243
00244
void KShortcutDialog::slotClearShortcut()
00245 {
00246 m_shortcut.setSeq( 0,
KKeySequence() );
00247 updateShortcutDisplay();
00248 }
00249
00250
void KShortcutDialog::slotClearPrimary()
00251 {
00252 m_shortcut.setSeq( 0,
KKeySequence() );
00253 m_adv->m_btnPrimary->setChecked(
true );
00254 slotSelectPrimary();
00255 }
00256
00257
void KShortcutDialog::slotClearAlternate()
00258 {
00259
if( m_shortcut.count() == 2 )
00260 m_shortcut.init( m_shortcut.seq(0) );
00261 m_adv->m_btnAlternate->setChecked(
true );
00262 slotSelectAlternate();
00263 }
00264
00265
void KShortcutDialog::slotMultiKeyMode(
bool bOn )
00266 {
00267
00268
if( !bOn && m_bRecording ) {
00269 m_bRecording =
false;
00270 m_iKey = 0;
00271 updateShortcutDisplay();
00272 }
00273 }
00274
00275
#ifdef Q_WS_X11
00276
bool KShortcutDialog::x11Event( XEvent *pEvent )
00277 {
00278
switch( pEvent->type ) {
00279
case XKeyPress:
00280 x11KeyPressEvent( pEvent );
00281
return true;
00282
case XKeyRelease:
00283 x11KeyReleaseEvent( pEvent );
00284
return true;
00285
case XFocusIn:
00286
if (!m_bGrab) {
00287
00288 grabKeyboard();
00289 m_bGrab =
true;
00290 }
00291
00292
00293
break;
00294
case XFocusOut:
00295
if (m_bGrab) {
00296
00297 releaseKeyboard();
00298 m_bGrab =
false;
00299 }
00300
00301
00302
break;
00303
default:
00304
00305
break;
00306 }
00307
return KDialogBase::x11Event( pEvent );
00308 }
00309
00310
static uint getModsFromModX( uint keyModX )
00311 {
00312 uint mod = 0;
00313
if( keyModX &
KKeyNative::modX(KKey::SHIFT) ) mod += KKey::SHIFT;
00314
if( keyModX &
KKeyNative::modX(KKey::CTRL) ) mod += KKey::CTRL;
00315
if( keyModX &
KKeyNative::modX(KKey::ALT) ) mod += KKey::ALT;
00316
if( keyModX &
KKeyNative::modX(KKey::WIN) ) mod += KKey::WIN;
00317
return mod;
00318 }
00319
00320
static bool convertSymXToMod( uint keySymX, uint* pmod )
00321 {
00322
switch( keySymX ) {
00323
00324
00325
00326
case XK_Shift_L:
case XK_Shift_R: *pmod = KKey::SHIFT;
break;
00327
case XK_Control_L:
case XK_Control_R: *pmod = KKey::CTRL;
break;
00328
case XK_Alt_L:
case XK_Alt_R: *pmod = KKey::ALT;
break;
00329
00330
case XK_Meta_L:
case XK_Meta_R:
00331
case XK_Super_L:
case XK_Super_R: *pmod = KKey::WIN;
break;
00332
case XK_Hyper_L:
case XK_Hyper_R:
00333
case XK_Mode_switch:
00334
case XK_Num_Lock:
00335
case XK_Caps_Lock:
00336
break;
00337
default:
00338
return false;
00339 }
00340
return true;
00341 }
00342
00343
void KShortcutDialog::x11KeyPressEvent( XEvent* pEvent )
00344 {
00345
KKeyNative keyNative( pEvent );
00346 uint keyModX = keyNative.mod();
00347 uint keySymX = keyNative.sym();
00348
00349 m_mod = getModsFromModX( keyModX );
00350
00351
if( keySymX ) {
00352 m_bRecording =
true;
00353
00354 uint mod = 0;
00355
if( convertSymXToMod( keySymX, &mod ) ) {
00356
if( mod )
00357 m_mod |= mod;
00358 }
00359
else
00360 keyPressed(
KKey(keyNative) );
00361 }
00362 updateShortcutDisplay();
00363 }
00364
00365
void KShortcutDialog::x11KeyReleaseEvent( XEvent* pEvent )
00366 {
00367
00368
00369
if( m_bRecording && m_iKey == 0 ) {
00370
KKeyNative keyNative( pEvent );
00371 uint keyModX = keyNative.mod();
00372 uint keySymX = keyNative.sym();
00373
00374 m_mod = getModsFromModX( keyModX );
00375
00376 uint mod = 0;
00377
if( convertSymXToMod( keySymX, &mod ) && mod ) {
00378 m_mod &= ~mod;
00379
if( !m_mod )
00380 m_bRecording =
false;
00381 }
00382 updateShortcutDisplay();
00383 }
00384 }
00385
00386
#endif // QT_WS_X11
00387
00388
void KShortcutDialog::keyPressed(
KKey key )
00389 {
00390
kdDebug(125) <<
"keyPressed: " <<
key.toString() <<
endl;
00391
00392
key.simplify();
00393
if( m_bQtShortcut ) {
00394
key =
key.keyCodeQt();
00395
if(
key.isNull() ) {
00396
00397 }
00398 }
00399
00400
KKeySequence seq;
00401
if( m_iKey == 0 )
00402 seq =
key;
00403
else {
00404
00405
key.init(
key.sym(), 0 );
00406 seq = m_shortcut.seq( m_iSeq );
00407 seq.
setKey( m_iKey, key );
00408 }
00409
00410 m_shortcut.setSeq( m_iSeq, seq );
00411
00412 m_mod = 0;
00413
if( m_adv->m_btnMultiKey->isChecked() && m_iKey < KKeySequence::MAX_KEYS - 1 )
00414 m_iKey++;
00415
else {
00416 m_iKey = 0;
00417 m_bRecording =
false;
00418 }
00419
00420 updateShortcutDisplay();
00421
00422
if( !m_adv->m_btnMultiKey->isChecked() )
00423
QTimer::singleShot(500,
this, SLOT(accept()));
00424 }
00425
00426
#include "kshortcutdialog.moc"