| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kshortcutdialog.cpp

    00001 #include "kshortcutdialog.h"
    00002
    00003 #include <qbuttongroup.h>
    00004 #include <qcheckbox.h>
    00005 #include <qlayout.h>
    00006 #include <qpushbutton.h>
    00007 #include <qradiobutton.h>
    00008 #include <qsizepolicy.h>
    00009 #include <qtooltip.h>
    00010 #include <qvbox.h>
    00011
    00012 #include <kapplication.h>
    00013 #include <kdebug.h>
    00014 #include <kglobalaccel.h>
    00015 #include <kiconloader.h>
    00016 #include <kkeynative.h>
    00017 #include <klocale.h>
    00018 #include <kpushbutton.h>
    00019 #include <kstdguiitem.h>
    00020
    00021 #ifdef Q_WS_X11
    00022 #define XK_XKB_KEYS
    00023 #define XK_MISCELLANY
    00024 #include <X11/Xlib.h>   // For x11Event()
    00025 #include <X11/keysymdef.h> // For XK_...
    00026
    00027 #ifdef KeyPress
    00028 const int XFocusOut = FocusOut;
    00029 const int XFocusIn = FocusIn;
    00030 const int XKeyPress = KeyPress;
    00031 const int XKeyRelease = KeyRelease;
    00032 #undef KeyRelease
    00033 #undef KeyPress
    00034 #undef FocusOut
    00035 #undef FocusIn
    00036 #endif
    00037 #endif
    00038
    00039 KShortcutBox::KShortcutBox( const KKeySequence& seq, QWidget* parent, const char* name )
    00040 :       QLabel( parent, name )
    00041 {
    00042         setSeq( seq );
    00043         setFrameStyle( QFrame::Panel | QFrame::Plain );
    00044 }
    00045
    00046 void KShortcutBox::setSeq( const KKeySequence& seq )
    00047 {
    00048         m_seq = seq;
    00049         if( !m_seq.isNull() )
    00050                 setText( seq.toString() );
    00051         else
    00052                 setText( i18n("None") );
    00053 }
    00054
    00055 KShortcutDialog::KShortcutDialog( const KShortcut& cut, bool bQtShortcut, QWidget* parent, const char* name )
    00056 :       KDialog( parent, name ),
    00057         m_cut( cut )
    00058 {
    00059         m_bQtShortcut = bQtShortcut;
    00060         m_bGrabKeyboardOnFocusIn = true;
    00061         m_bKeyboardGrabbed = false;
    00062         m_iSeq = 0;
    00063         m_iKey = 0;
    00064         initGUI();
    00065
    00066 #ifdef Q_WS_X11
    00067         kapp->installX11EventFilter( this );    // Allow button to capture X Key Events.
    00068 #endif
    00069 }
    00070
    00071 KShortcutDialog::~KShortcutDialog()
    00072 {
    00073         if( m_bKeyboardGrabbed ) {
    00074                 kdDebug(125) << "KShortcutDialog::~KShortcutDialog(): m_bKeyboardGrabbed still true." << endl;
    00075                 releaseKeyboard();
    00076         }
    00077 }
    00078
    00079 void KShortcutDialog::initGUI()
    00080 {
    00081         setCaption( i18n("Define Shortcut") );
    00082
    00083         QHBoxLayout* pHLayout = new QHBoxLayout( this, KDialog::marginHint() );
    00084         QButtonGroup* pGroup = new QButtonGroup( this );
    00085         pHLayout->addWidget( pGroup );
    00086
    00087         m_prbSeq[0] = new QRadioButton( i18n("Primary"), pGroup );
    00088         m_prbSeq[0]->setChecked( true );
    00089         connect( m_prbSeq[0], SIGNAL(clicked()), this, SLOT(slotSeq0Selected()) );
    00090         QPushButton* pb0 = new QPushButton( pGroup );
    00091         pb0->setFlat( true );
    00092         pb0->setPixmap( SmallIcon( "locationbar_erase" ) );
    00093         QToolTip::add( pb0, i18n("Clear shortcut") );
    00094         connect( pb0, SIGNAL(clicked()), this, SLOT(slotClearSeq0()) );
    00095         m_peditSeq[0] = new KShortcutBox( m_cut.seq(0), pGroup );
    00096         m_pcbMultiKey[0] = new QCheckBox( i18n("Multi-key"), pGroup );
    00097         m_pcbMultiKey[0]->setChecked( m_cut.seq(0).count() > 1 );
    00098         connect( m_pcbMultiKey[0], SIGNAL(clicked()), this, SLOT(slotSeq0Selected()) );
    00099
    00100         m_prbSeq[1] = new QRadioButton( i18n("Alternate"), pGroup );
    00101         connect( m_prbSeq[1], SIGNAL(clicked()), this, SLOT(slotSeq1Selected()) );
    00102         QPushButton* pb1 = new QPushButton( pGroup );
    00103         pb1->setFlat( true );
    00104         pb1->setPixmap( SmallIcon( "locationbar_erase" ) );
    00105         QToolTip::add( pb1, i18n("Clear shortcut") );
    00106         connect( pb1, SIGNAL(clicked()), this, SLOT(slotClearSeq1()) );
    00107         m_peditSeq[1] = new KShortcutBox( m_cut.seq(1), pGroup );
    00108         m_pcbMultiKey[1] = new QCheckBox( i18n("Multi-key"), pGroup );
    00109         m_pcbMultiKey[1]->setChecked( m_cut.seq(1).count() > 1 );
    00110         connect( m_pcbMultiKey[1], SIGNAL(clicked()), this, SLOT(slotSeq1Selected()) );
    00111
    00112         QGridLayout* pLayout = new QGridLayout( pGroup, 2, 3, KDialog::marginHint(), KDialog::spacingHint() );
    00113         pLayout->setColStretch( 2, 1 );
    00114         pLayout->addWidget( m_prbSeq[0], 0, 0 );
    00115         pLayout->addWidget( pb0, 0, 1 );
    00116         pLayout->addWidget( m_peditSeq[0], 0, 2 );
    00117         pLayout->addWidget( m_pcbMultiKey[0], 0, 3 );
    00118         pLayout->addWidget( m_prbSeq[1], 1, 0 );
    00119         pLayout->addWidget( pb1, 1, 1 );
    00120         pLayout->addWidget( m_peditSeq[1], 1, 2 );
    00121         pLayout->addWidget( m_pcbMultiKey[1], 1, 3 );
    00122
    00123         QVBox* pVBox = new QVBox( this );
    00124
    00125         // Don't use KStdGuiItem because shown accels would be assigned as shortcut when pressed
    00126         KGuiItem ok = KStdGuiItem::ok();
    00127         ok.setText( i18n( "OK" ) );
    00128         KGuiItem cancel = KStdGuiItem::cancel();
    00129         cancel.setText( i18n( "Cancel" ) );
    00130         m_pcmdOK = new KPushButton( ok, pVBox );
    00131         m_pcmdCancel = new KPushButton( cancel, pVBox );
    00132         m_pcbAutoClose = new QCheckBox( i18n("Auto-close"), pVBox );
    00133         m_pcbAutoClose->setChecked( true );
    00134         // Disable auto-close if the sequence we're editing is a multi-key shortcut.
    00135         m_pcbAutoClose->setEnabled( !m_pcbMultiKey[0]->isChecked() );
    00136
    00137         connect( m_pcmdOK, SIGNAL(clicked()), this, SLOT(accept()) );
    00138         connect( m_pcmdCancel, SIGNAL(clicked()), this, SLOT(reject()) );
    00139
    00140         pHLayout->addWidget( pVBox );
    00141         m_prbSeq[0]->clearFocus();
    00142 }
    00143
    00144 void KShortcutDialog::selectSeq( uint i )
    00145 {
    00146         kdDebug(125) << "KShortcutDialog::selectSeq( " << i << " )" << endl;
    00147         m_iSeq = i;
    00148         m_prbSeq[m_iSeq]->setChecked( true );
    00149         // Start editing at the first key in the sequence.
    00150         m_iKey = 0;
    00151         // Can't auto-close if editing a multi-key shortcut.
    00152         m_pcbAutoClose->setEnabled( !m_pcbMultiKey[m_iSeq]->isChecked() );
    00153         m_prbSeq[m_iSeq]->setFocus();
    00154 }
    00155
    00156 void KShortcutDialog::clearSeq( uint i )
    00157 {
    00158         kdDebug(125) << "KShortcutDialog::deleteSeq( " << i << " )" << endl;
    00159         m_peditSeq[i]->setSeq( KKeySequence::null() );
    00160         m_cut.setSeq( i, KKeySequence::null() );
    00161         selectSeq( i );
    00162
    00163         // If we're clearing the alternate, then we need to set m_cut.count()
    00164         //  back to 1 if there is a primary sequence.
    00165         if( i == 1 && m_cut.count() > 0 )
    00166                 m_cut = m_cut.seq(0);
    00167 }
    00168
    00169 void KShortcutDialog::slotSeq0Selected() { selectSeq( 0 ); }
    00170 void KShortcutDialog::slotSeq1Selected() { selectSeq( 1 ); }
    00171 void KShortcutDialog::slotClearSeq0()    { clearSeq( 0 ); }
    00172 void KShortcutDialog::slotClearSeq1()    { clearSeq( 1 ); }
    00173
    00174 void KShortcutDialog::accept()
    00175 {
    00176         kdDebug(125) << "KShortcutDialog::accept()" << endl;
    00177         m_bGrabKeyboardOnFocusIn = false;
    00178         m_bKeyboardGrabbed = false;
    00179         releaseKeyboard();
    00180         KDialog::accept();
    00181 }
    00182
    00183 #ifdef Q_WS_X11
    00184 bool KShortcutDialog::x11Event( XEvent *pEvent )
    00185 {
    00186         switch( pEvent->type ) {
    00187                 case XKeyPress:
    00188                 case XKeyRelease:
    00189                         if( m_bKeyboardGrabbed ) {
    00190                                 x11EventKeyPress( pEvent );
    00191                                 return true;
    00192                         }
    00193                         break;
    00194                 case ButtonPress:
    00195                         m_iKey = 0;
    00196                         break;
    00197                 case XFocusIn:
    00198                         kdDebug(125) << "FocusIn" << endl;
    00199                         if( m_bGrabKeyboardOnFocusIn && !m_bKeyboardGrabbed ) {
    00200                                 kdDebug(125) << "\tkeyboard grabbed." << endl;
    00201                                 m_bKeyboardGrabbed = true;
    00202                                 grabKeyboard();
    00203                         }
    00204                         break;
    00205                 case XFocusOut:
    00206                         kdDebug(125) << "FocusOut" << endl;
    00207                         if( m_bKeyboardGrabbed ) {
    00208                                 kdDebug(125) << "\tkeyboard released." << endl;
    00209                                 m_bKeyboardGrabbed = false;
    00210                                 releaseKeyboard();
    00211                         }
    00212                         break;
    00213                 default:
    00214                         //kdDebug(125) << "x11Event->type = " << pEvent->type << endl;
    00215                         break;
    00216         }
    00217         return QWidget::x11Event( pEvent );
    00218 }
    00219
    00220 void KShortcutDialog::x11EventKeyPress( XEvent *pEvent )
    00221 {
    00222         KKeyNative keyNative( pEvent );
    00223         uint keyModX = keyNative.mod(), keySymX = keyNative.sym();
    00224
    00225         //kdDebug(125) << QString( "keycode: 0x%1 state: 0x%2\n" )
    00226         //                      .arg( pEvent->xkey.keycode, 0, 16 ).arg( pEvent->xkey.state, 0, 16 );
    00227
    00228         switch( keySymX ) {
    00229                 // Don't allow setting a modifier key as an accelerator.
    00230                 // Also, don't release the focus yet.  We'll wait until
    00231                 //  we get a 'normal' key.
    00232                 case XK_Shift_L:   case XK_Shift_R:   keyModX = KKeyNative::modX(KKey::SHIFT); break;
    00233                 case XK_Control_L: case XK_Control_R: keyModX = KKeyNative::modX(KKey::CTRL); break;
    00234                 case XK_Alt_L:     case XK_Alt_R:     keyModX = KKeyNative::modX(KKey::ALT); break;
    00235                 // FIXME: check whether the Meta or Super key are for the Win modifier
    00236                 case XK_Meta_L:    case XK_Meta_R:
    00237                 case XK_Super_L:   case XK_Super_R:   keyModX = KKeyNative::modX(KKey::WIN); break;
    00238                 case XK_Hyper_L:   case XK_Hyper_R:
    00239                 case XK_Mode_switch:
    00240                 case XK_Num_Lock:
    00241                 case XK_Caps_Lock:
    00242                         break;
    00243                 default:
    00244                         if( pEvent->type == XKeyPress && keyNative.sym() ) {
    00245                                 // If RETURN was pressed and we are recording a
    00246                                 //  multi-key shortcut, then we are done.
    00247                                 if( keyNative.sym() == XK_Return && m_iKey > 0 ) {
    00248                                         accept();
    00249                                         return;
    00250                                 }
    00251
    00252                                 KKey key = keyNative;
    00253 #ifndef NDEBUG
    00254                                 //KKey key2 = key;
    00255                                 //key2.simplify();
    00256                                 //if( key != key2 )
    00257                                 //      kdDebug(125) << key.toStringInternal() << " simplified to " << key2.toStringInternal();
    00258 #endif
    00259                                 key.simplify();
    00260                                 if( m_bQtShortcut )
    00261                                         key = key.keyCodeQt();
    00262                                 KKeySequence seq;
    00263                                 if( m_iKey == 0 )
    00264                                         seq = key;
    00265                                 else {
    00266                                         seq = m_cut.seq( m_iSeq );
    00267                                         seq.setKey( m_iKey, key );
    00268                                 }
    00269                                 m_cut.setSeq( m_iSeq, seq );
    00270
    00271                                 if( m_pcbMultiKey[m_iSeq]->isChecked() )
    00272                                         m_iKey++;
    00273
    00274                                 m_peditSeq[m_iSeq]->setSeq( m_cut.seq(m_iSeq) );
    00275                                 //captureShortcut( false );
    00276                                 // The parent must decide whether this is a valid
    00277                                 //  key, and if so, call setShortcut(uint) with the new value.
    00278                                 //emit capturedShortcut( KShortcut(KKey(keyNative)) );
    00279                                 kdDebug(125) << "m_cut = " << m_cut.toString() << " m_bQtShortcut = " << m_bQtShortcut << endl;
    00280                                 if( m_pcbAutoClose->isEnabled() && m_pcbAutoClose->isChecked() )
    00281                                         accept();
    00282                         }
    00283                         return;
    00284         }
    00285
    00286         // If we are editing the first key in the sequence,
    00287         //  display modifier keys which are held down
    00288         if( m_iKey == 0 ) {
    00289                 if( pEvent->type == XKeyPress )
    00290                         keyModX |= pEvent->xkey.state;
    00291                 else
    00292                         keyModX = pEvent->xkey.state & ~keyModX;
    00293
    00294                 QString keyModStr;
    00295                 if( keyModX & KKeyNative::modX(KKey::WIN) )     keyModStr += KKey::modFlagLabel(KKey::WIN) + "+";
    00296                 if( keyModX & KKeyNative::modX(KKey::ALT) )     keyModStr += KKey::modFlagLabel(KKey::ALT) + "+";
    00297                 if( keyModX & KKeyNative::modX(KKey::CTRL) )    keyModStr += KKey::modFlagLabel(KKey::CTRL) + "+";
    00298                 if( keyModX & KKeyNative::modX(KKey::SHIFT) )   keyModStr += KKey::modFlagLabel(KKey::SHIFT) + "+";
    00299
    00300                 // Display currently selected modifiers, or redisplay old key.
    00301                 if( !keyModStr.isEmpty() )
    00302                         m_peditSeq[m_iSeq]->setText( keyModStr );
    00303                 else
    00304                         m_peditSeq[m_iSeq]->setSeq( m_cut.seq(m_iSeq) );
    00305         }
    00306 }
    00307 #endif // QT_WS_X11
    00308
    00309 void KShortcutDialog::virtual_hook( int id, void* data )
    00310 { KDialog::virtual_hook( id, data ); }
    00311
    00312
    00313 #include "kshortcutdialog.moc"

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:57:40 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001