• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kdeui
 

kdeui

kshortcutdialog.cpp
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2002,2003 Ellis Whitehead <ellis@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kshortcutdialog.h"
00021 
00022 #include <tqvariant.h>
00023 
00024 #ifdef Q_WS_X11
00025     #define XK_XKB_KEYS
00026     #define XK_MISCELLANY
00027     #include <X11/Xlib.h>   // For x11Event()
00028     #include <X11/keysymdef.h> // For XK_...
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 <tqbuttongroup.h>
00048 #include <tqcheckbox.h>
00049 #include <tqframe.h>
00050 #include <tqlayout.h>
00051 #include <tqradiobutton.h>
00052 #include <tqtimer.h>
00053 #include <tqvbox.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, TQWidget* 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 TQVBox(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_iSeq = 0;
00086     m_iKey = 0;
00087     m_ptxtCurrent = 0;
00088     m_bRecording = false;
00089     m_mod = 0;
00090 
00091     m_simple->m_btnClearShortcut->setPixmap( SmallIcon( "locationbar_erase" ) );
00092     m_adv->m_btnClearPrimary->setPixmap( SmallIcon( "locationbar_erase" ) );
00093     m_adv->m_btnClearAlternate->setPixmap( SmallIcon( "locationbar_erase" ) );
00094     connect(m_simple->m_btnClearShortcut, TQT_SIGNAL(clicked()),
00095             this, TQT_SLOT(slotClearShortcut()));
00096     connect(m_adv->m_btnClearPrimary, TQT_SIGNAL(clicked()),
00097             this, TQT_SLOT(slotClearPrimary()));
00098     connect(m_adv->m_btnClearAlternate, TQT_SIGNAL(clicked()),
00099             this, TQT_SLOT(slotClearAlternate()));
00100 
00101     connect(m_adv->m_txtPrimary, TQT_SIGNAL(clicked()),
00102         m_adv->m_btnPrimary, TQT_SLOT(animateClick()));
00103     connect(m_adv->m_txtAlternate, TQT_SIGNAL(clicked()),
00104         m_adv->m_btnAlternate, TQT_SLOT(animateClick()));
00105     connect(m_adv->m_btnPrimary, TQT_SIGNAL(clicked()),
00106         this, TQT_SLOT(slotSelectPrimary()));
00107     connect(m_adv->m_btnAlternate, TQT_SIGNAL(clicked()),
00108         this, TQT_SLOT(slotSelectAlternate()));
00109 
00110     KGuiItem ok = KStdGuiItem::ok();
00111     ok.setText( i18n( "OK" ) );
00112     setButtonOK( ok );
00113 
00114     KGuiItem cancel = KStdGuiItem::cancel();
00115     cancel.setText( i18n( "Cancel" ) );
00116     setButtonCancel( cancel );
00117 
00118     setShortcut( shortcut );
00119     resize( 0, 0 );
00120 
00121     s_showMore = KConfigGroup(KGlobal::config(), "General").readBoolEntry("ShowAlternativeShortcutConfig", s_showMore);
00122     updateDetails();
00123 
00124     #ifdef Q_WS_X11
00125     kapp->installX11EventFilter( this );    // Allow button to capture X Key Events.
00126     #endif
00127 }
00128 
00129 KShortcutDialog::~KShortcutDialog()
00130 {
00131     KConfigGroup group(KGlobal::config(), "General");
00132     group.writeEntry("ShowAlternativeShortcutConfig", s_showMore);
00133 }
00134 
00135 void KShortcutDialog::setShortcut( const KShortcut & shortcut )
00136 {
00137     m_shortcut = shortcut;
00138     updateShortcutDisplay();
00139 }
00140 
00141 void KShortcutDialog::updateShortcutDisplay()
00142 {
00143     TQString s[2] = { m_shortcut.seq(0).toString(), m_shortcut.seq(1).toString() };
00144 
00145     if( m_bRecording ) {
00146         m_ptxtCurrent->setDefault( true );
00147         m_ptxtCurrent->setFocus();
00148 
00149         // Display modifiers for the first key in the KKeySequence
00150         if( m_iKey == 0 ) {
00151             if( m_mod ) {
00152                 TQString keyModStr;
00153                 if( m_mod & KKey::WIN )   keyModStr += KKey::modFlagLabel(KKey::WIN) + "+";
00154                 if( m_mod & KKey::ALT )   keyModStr += KKey::modFlagLabel(KKey::ALT) + "+";
00155                 if( m_mod & KKey::CTRL )  keyModStr += KKey::modFlagLabel(KKey::CTRL) + "+";
00156                 if( m_mod & KKey::SHIFT ) keyModStr += KKey::modFlagLabel(KKey::SHIFT) + "+";
00157                 s[m_iSeq] = keyModStr;
00158     }
00159         }
00160         // When in the middle of entering multi-key shortcuts,
00161         //  add a "," to the end of the displayed shortcut.
00162         else
00163             s[m_iSeq] += ",";
00164     }
00165     else {
00166         m_adv->m_txtPrimary->setDefault( false );
00167         m_adv->m_txtAlternate->setDefault( false );
00168         this->setFocus();
00169     }
00170     
00171     s[0].replace('&', TQString::fromLatin1("&&"));
00172     s[1].replace('&', TQString::fromLatin1("&&"));
00173 
00174     m_simple->m_txtShortcut->setText( s[0] );
00175     m_adv->m_txtPrimary->setText( s[0] );
00176     m_adv->m_txtAlternate->setText( s[1] );
00177 
00178     // Determine the enable state of the 'Less' button
00179     bool bLessOk;
00180     // If there is no shortcut defined,
00181     if( m_shortcut.count() == 0 )
00182         bLessOk = true;
00183     // If there is a single shortcut defined, and it is not a multi-key shortcut,
00184     else if( m_shortcut.count() == 1 && m_shortcut.seq(0).count() <= 1 )
00185         bLessOk = true;
00186     // Otherwise, we have an alternate shortcut or multi-key shortcut(s).
00187     else
00188         bLessOk = false;
00189     enableButton(Details, bLessOk);
00190 }
00191 
00192 void KShortcutDialog::slotDetails()
00193 {
00194     s_showMore = (m_adv->isHidden());
00195     updateDetails();
00196 }
00197 
00198 void KShortcutDialog::updateDetails()
00199 {
00200     bool showAdvanced = s_showMore || (m_shortcut.count() > 1);
00201     setDetails(showAdvanced);
00202     m_bRecording = false;
00203     m_iSeq = 0;
00204     m_iKey = 0;
00205 
00206     if (showAdvanced)
00207     {
00208         m_simple->hide();
00209         m_adv->show();
00210         m_adv->m_btnPrimary->setChecked( true );
00211         slotSelectPrimary();
00212     }
00213     else
00214     {
00215         m_ptxtCurrent = m_simple->m_txtShortcut;
00216         m_adv->hide();
00217         m_simple->show();
00218         m_simple->m_txtShortcut->setDefault( true );
00219         m_simple->m_txtShortcut->setFocus();
00220         m_adv->m_btnMultiKey->setChecked( false );
00221     }
00222     kapp->processEvents();
00223     adjustSize();
00224 }
00225 
00226 void KShortcutDialog::slotSelectPrimary()
00227 {
00228     m_bRecording = false;
00229     m_iSeq = 0;
00230     m_iKey = 0;
00231     m_ptxtCurrent = m_adv->m_txtPrimary;
00232     m_ptxtCurrent->setDefault(true);
00233     m_ptxtCurrent->setFocus();
00234     updateShortcutDisplay();
00235 }
00236 
00237 void KShortcutDialog::slotSelectAlternate()
00238 {
00239     m_bRecording = false;
00240     m_iSeq = 1;
00241     m_iKey = 0;
00242     m_ptxtCurrent = m_adv->m_txtAlternate;
00243     m_ptxtCurrent->setDefault(true);
00244     m_ptxtCurrent->setFocus();
00245     updateShortcutDisplay();
00246 }
00247 
00248 void KShortcutDialog::slotClearShortcut()
00249 {
00250     m_shortcut.setSeq( 0, KKeySequence() );
00251     updateShortcutDisplay();
00252 }
00253 
00254 void KShortcutDialog::slotClearPrimary()
00255 {
00256     m_shortcut.setSeq( 0, KKeySequence() );
00257     m_adv->m_btnPrimary->setChecked( true );
00258     slotSelectPrimary();
00259 }
00260 
00261 void KShortcutDialog::slotClearAlternate()
00262 {
00263     if( m_shortcut.count() == 2 )
00264         m_shortcut.init( m_shortcut.seq(0) );
00265     m_adv->m_btnAlternate->setChecked( true );
00266     slotSelectAlternate();
00267 }
00268 
00269 void KShortcutDialog::slotMultiKeyMode( bool bOn )
00270 {
00271     // If turning off multi-key mode during a recording,
00272     if( !bOn && m_bRecording ) {
00273         m_bRecording = false;
00274     m_iKey = 0;
00275         updateShortcutDisplay();
00276     }
00277 }
00278 
00279 #ifdef Q_WS_X11
00280 /* we don't use the generic Qt code on X11 because it allows us 
00281  to grab the keyboard so that all keypresses are seen
00282  */
00283 bool KShortcutDialog::x11Event( XEvent *pEvent )
00284 {
00285     switch( pEvent->type ) {
00286         case XKeyPress:
00287             x11KeyPressEvent( pEvent );
00288             return true;
00289         case XKeyRelease:
00290             x11KeyReleaseEvent( pEvent );
00291                 return true;
00292         case XFocusIn:
00293             {
00294                 XFocusInEvent *fie = (XFocusInEvent*)pEvent;
00295                 if (fie->mode != NotifyGrab && fie->mode != NotifyUngrab) {
00296                     grabKeyboard();
00297                 }
00298             }
00299             break;
00300         case XFocusOut:
00301             {
00302                 XFocusOutEvent *foe = (XFocusOutEvent*)pEvent;
00303                 if (foe->mode != NotifyGrab && foe->mode != NotifyUngrab) {
00304                     releaseKeyboard();
00305                 }
00306             }
00307             break;
00308         default:
00309             //kdDebug(125) << "x11Event->type = " << pEvent->type << endl;
00310             break;
00311     }
00312     return KDialogBase::x11Event( pEvent );
00313 }
00314 
00315 static uint getModsFromModX( uint keyModX )
00316 {
00317     uint mod = 0;
00318     if( keyModX & KKeyNative::modX(KKey::SHIFT) ) mod += KKey::SHIFT;
00319     if( keyModX & KKeyNative::modX(KKey::CTRL) )  mod += KKey::CTRL;
00320     if( keyModX & KKeyNative::modX(KKey::ALT) )   mod += KKey::ALT;
00321     if( keyModX & KKeyNative::modX(KKey::WIN) )   mod += KKey::WIN;
00322     return mod;
00323 }
00324 
00325 static bool convertSymXToMod( uint keySymX, uint* pmod )
00326 {
00327     switch( keySymX ) {
00328         // Don't allow setting a modifier key as an accelerator.
00329         // Also, don't release the focus yet.  We'll wait until
00330         //  we get a 'normal' key.
00331         case XK_Shift_L:   case XK_Shift_R:   *pmod = KKey::SHIFT; break;
00332         case XK_Control_L: case XK_Control_R: *pmod = KKey::CTRL; break;
00333         case XK_Alt_L:     case XK_Alt_R:     *pmod = KKey::ALT; break;
00334         // FIXME: check whether the Meta or Super key are for the Win modifier
00335         case XK_Meta_L:    case XK_Meta_R:
00336         case XK_Super_L:   case XK_Super_R:   *pmod = KKey::WIN; break;
00337         case XK_Hyper_L:   case XK_Hyper_R:
00338         case XK_Mode_switch:
00339         case XK_Num_Lock:
00340         case XK_Caps_Lock:
00341             break;
00342         default:
00343             return false;
00344                 }
00345     return true;
00346 }
00347 
00348 void KShortcutDialog::x11KeyPressEvent( XEvent* pEvent )
00349 {
00350     KKeyNative keyNative( pEvent );
00351     uint keyModX = keyNative.mod();
00352     uint keySymX = keyNative.sym();
00353 
00354     m_mod = getModsFromModX( keyModX );
00355 
00356     if( keySymX ) {
00357         m_bRecording = true;
00358 
00359         uint mod = 0;
00360         if( convertSymXToMod( keySymX, &mod ) ) {
00361             if( mod )
00362                 m_mod |= mod;
00363         }
00364         else
00365             keyPressed( KKey(keyNative) );
00366     }
00367     updateShortcutDisplay();
00368 }
00369 
00370 void KShortcutDialog::x11KeyReleaseEvent( XEvent* pEvent )
00371 {
00372     // We're only interested in the release of modifier keys,
00373     //  and then only when it's for the first key in a sequence.
00374     if( m_bRecording && m_iKey == 0 ) {
00375         KKeyNative keyNative( pEvent );
00376         uint keyModX = keyNative.mod();
00377         uint keySymX = keyNative.sym();
00378 
00379         m_mod = getModsFromModX( keyModX );
00380 
00381         uint mod = 0;
00382         if( convertSymXToMod( keySymX, &mod ) && mod ) {
00383             m_mod &= ~mod;
00384             if( !m_mod )
00385                 m_bRecording = false;
00386         }
00387         updateShortcutDisplay();
00388     }
00389 }
00390 #elif defined(Q_WS_WIN)
00391 void KShortcutDialog::keyPressEvent( TQKeyEvent * e )
00392 {
00393     kdDebug() << e->text() << " " << (int)e->text()[0].latin1()<<  " " << (int)e->ascii() << endl;
00394     //if key is a letter, it must be stored as lowercase
00395     int keyQt = TQChar( e->key() & 0xff ).isLetter() ? 
00396         (TQChar( e->key() & 0xff ).lower().latin1() | (e->key() & 0xffff00) )
00397         : e->key();
00398     int modQt = KKeyServer::qtButtonStateToMod( e->state() );
00399     KKeyNative keyNative( KKey(keyQt, modQt) );
00400     m_mod = keyNative.mod();
00401     uint keySym = keyNative.sym();
00402 
00403     switch( keySym ) {
00404         case Key_Shift: 
00405             m_mod |= KKey::SHIFT;
00406             m_bRecording = true;
00407             break;
00408         case Key_Control:
00409             m_mod |= KKey::CTRL;
00410             m_bRecording = true;
00411             break;
00412         case Key_Alt:
00413             m_mod |= KKey::ALT;
00414             m_bRecording = true;
00415             break;
00416         case Key_Menu:
00417         case Key_Meta: //unused
00418             break;
00419         default:
00420             if( keyNative.sym() == Key_Return && m_iKey > 0 ) {
00421                 accept();
00422                 return;
00423             }
00424             //accept
00425             if (keyNative.sym()) {
00426                 KKey key = keyNative;
00427                 key.simplify();
00428                 KKeySequence seq;
00429                 if( m_iKey == 0 )
00430                     seq = key;
00431                 else {
00432                     seq = m_shortcut.seq( m_iSeq );
00433                     seq.setKey( m_iKey, key );
00434                 }
00435                 m_shortcut.setSeq( m_iSeq, seq );
00436 
00437                 if(m_adv->m_btnMultiKey->isChecked())
00438                     m_iKey++;
00439 
00440                 m_bRecording = true;
00441 
00442                 updateShortcutDisplay();
00443 
00444                 if( !m_adv->m_btnMultiKey->isChecked() )
00445                     TQTimer::singleShot(500, this, TQT_SLOT(accept()));
00446             }
00447             return;
00448     }
00449 
00450     // If we are editing the first key in the sequence,
00451     //  display modifier keys which are held down
00452     if( m_iKey == 0 ) {
00453         updateShortcutDisplay();
00454     }
00455 }
00456 
00457 bool KShortcutDialog::event ( TQEvent * e )
00458 {
00459     if (e->type()==TQEvent::KeyRelease) {
00460         int modQt = KKeyServer::qtButtonStateToMod( static_cast<TQKeyEvent*>(e)->state() );
00461         KKeyNative keyNative( KKey(static_cast<TQKeyEvent*>(e)->key(), modQt) );
00462         uint keySym = keyNative.sym();
00463 
00464         bool change = true;
00465         switch( keySym ) {
00466         case Key_Shift: 
00467             if (m_mod & KKey::SHIFT)
00468                 m_mod ^= KKey::SHIFT;
00469             break;
00470         case Key_Control:
00471             if (m_mod & KKey::CTRL)
00472                 m_mod ^= KKey::CTRL;
00473             break;
00474         case Key_Alt:
00475             if (m_mod & KKey::ALT)
00476                 m_mod ^= KKey::ALT;
00477             break;
00478         default:
00479             change = false;
00480         }
00481         if (change)
00482             updateShortcutDisplay();
00483     }
00484     return KDialogBase::event(e);
00485 }
00486 #endif
00487 
00488 void KShortcutDialog::keyPressed( KKey key )
00489 {
00490     kdDebug(125) << "keyPressed: " << key.toString() << endl;
00491 
00492     key.simplify();
00493     if( m_bQtShortcut ) {
00494         key = key.keyCodeQt();
00495         if( key.isNull() ) {
00496             // TODO: message box about key not able to be used as application shortcut
00497         }
00498     }
00499 
00500     KKeySequence seq;
00501     if( m_iKey == 0 )
00502         seq = key;
00503     else {
00504         // Remove modifiers
00505         key.init( key.sym(), 0 );
00506         seq = m_shortcut.seq( m_iSeq );
00507         seq.setKey( m_iKey, key );
00508     }
00509 
00510     m_shortcut.setSeq( m_iSeq, seq );
00511 
00512     m_mod = 0;
00513     if( m_adv->m_btnMultiKey->isChecked() && m_iKey < KKeySequence::MAX_KEYS - 1 )
00514         m_iKey++;
00515     else {
00516         m_iKey = 0;
00517         m_bRecording = false;
00518     }
00519 
00520     updateShortcutDisplay();
00521 
00522     if( !m_adv->m_btnMultiKey->isChecked() )
00523         TQTimer::singleShot(500, this, TQT_SLOT(accept()));
00524 }
00525 
00526 #include "kshortcutdialog.moc"

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdeui

Skip menu "kdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdeui by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |