kkeydialog.cpp Source File (kdeui Library)

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

# kkeydialog.cpp

    00001 /* This file is part of the KDE libraries
    00002     Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>
    00003     Copyright (C) 1997 Nicolas Hadacek <hadacek@kde.org>
    00004     Copyright (C) 1998 Matthias Ettrich <ettrich@kde.org>
    00005     Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
    00006
    00007     This library is free software; you can redistribute it and/or
    00008     modify it under the terms of the GNU Library General Public
    00009     License as published by the Free Software Foundation; either
    00010     version 2 of the License, or (at your option) any later version.
    00011
    00012     This library is distributed in the hope that it will be useful,
    00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015     Library General Public License for more details.
    00016
    00017     You should have received a copy of the GNU Library General Public License
    00018     along with this library; see the file COPYING.LIB.  If not, write to
    00019     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00020     Boston, MA 02111-1307, USA.
    00021 */
    00022
    00023 #include "kkeydialog.h"
    00024 #include "kkeybutton.h"
    00025
    00026 #include <string.h>
    00027
    00028 #include <qbuttongroup.h>
    00029 #include <qlabel.h>
    00030 #include <qlayout.h>
    00031 #include <qdrawutil.h>
    00032 #include <qpainter.h>
    00033 #include <qradiobutton.h>
    00034 #include <qregexp.h>
    00035 #include <qwhatsthis.h>
    00036
    00037 #include <kaccel.h>
    00038 #include <kaction.h>
    00039 #include <kactionshortcutlist.h>
    00040 #include <kapplication.h>
    00041 #include <kconfig.h>
    00042 #include <kdebug.h>
    00043 #include <kglobal.h>
    00044 #include <kglobalaccel.h>
    00045 #include <klocale.h>
    00046 #include <kmessagebox.h>
    00047 #include <kshortcut.h>
    00048 #include <kshortcutlist.h>
    00049 #include <kxmlguifactory.h>
    00050 #include <kaboutdata.h>
    00051 #include <kstaticdeleter.h>
    00052
    00053 #ifdef Q_WS_X11
    00054 #define XK_XKB_KEYS
    00055 #define XK_MISCELLANY
    00056 #include <X11/Xlib.h>   // For x11Event()
    00057 #include <X11/keysymdef.h> // For XK_...
    00058
    00059 #ifdef KeyPress
    00060 const int XFocusOut = FocusOut;
    00061 const int XFocusIn = FocusIn;
    00062 const int XKeyPress = KeyPress;
    00063 const int XKeyRelease = KeyRelease;
    00064 #undef KeyRelease
    00065 #undef KeyPress
    00066 #undef FocusOut
    00067 #undef FocusIn
    00068 #endif
    00069 #endif
    00070
    00071 //---------------------------------------------------------------------
    00072 // KKeyChooserItem
    00073 //---------------------------------------------------------------------
    00074
    00075 class KKeyChooserItem : public KListViewItem
    00076 {
    00077  public:
    00078         KKeyChooserItem( KListView* parent, QListViewItem* after, KShortcutList* pList, uint iAction );
    00079         KKeyChooserItem( QListViewItem* parent, QListViewItem* after, KShortcutList* pList, uint iAction );
    00080
    00081         QString actionName() const;
    00082         const KShortcut& shortcut() const;
    00083         bool isConfigurable() const
    00084                 { return m_pList->isConfigurable( m_iAction ); }
    00085         const KShortcut& shortcutDefault() const
    00086                 { return m_pList->shortcutDefault( m_iAction ); }
    00087
    00088         void setShortcut( const KShortcut& cut );
    00089         void commitChanges();
    00090
    00091         virtual QString text( int iCol ) const;
    00092         virtual int compare( QListViewItem*, int iCol, bool bAscending ) const;
    00093
    00094  protected:
    00095         KShortcutList* m_pList;
    00096         uint m_iAction;
    00097         bool m_bModified;
    00098         KShortcut m_cut;
    00099 };
    00100
    00101 //---------------------------------------------------------------------
    00102 // KKeyChooserPrivate
    00103 //---------------------------------------------------------------------
    00104
    00105 class KKeyChooserPrivate
    00106 {
    00107  public:
    00108         QValueList<KShortcutList*> rgpLists;
    00109         QValueList<KShortcutList*> rgpListsAllocated;
    00110
    00111         KListView *pList;
    00112         QLabel *lInfo;
    00113         KKeyButton *pbtnShortcut;
    00114         QGroupBox *fCArea;
    00115         QButtonGroup *kbGroup;
    00116
    00117         QMap<QString, KShortcut> mapGlobals;
    00118
    00119         bool bAllowWinKey;
    00120         // If this is set, then shortcuts require a modifier:
    00121         //  so 'A' would not be valid, whereas 'Ctrl+A' would be.
    00122         // Note, however, that this only applies to printable characters.
    00123         //  'F1', 'Insert', etc., could still be used.
    00124         bool bAllowLetterShortcuts;
    00125         // When set, pressing the 'Default' button will select the aDefaultKeycode4,
    00126         //  otherwise aDefaultKeycode.
    00127         bool bPreferFourModifierKeys;
    00128 };
    00129
    00130 //---------------------------------------------------------------------
    00131 // KKeyChooser
    00132 //---------------------------------------------------------------------
    00133
    00134 KKeyChooser::KKeyChooser( QWidget* parent, ActionType type, bool bAllowLetterShortcuts )
    00135 : QWidget( parent )
    00136 {
    00137         initGUI( type, bAllowLetterShortcuts );
    00138 }
    00139
    00140 KKeyChooser::KKeyChooser( KActionCollection* coll, QWidget* parent, bool bAllowLetterShortcuts )
    00141 : QWidget( parent )
    00142 {
    00143         initGUI( Application, bAllowLetterShortcuts );
    00144         insert( coll );
    00145 }
    00146
    00147 KKeyChooser::KKeyChooser( KAccel* pAccel, QWidget* parent, bool bAllowLetterShortcuts )
    00148 : QWidget( parent )
    00149 {
    00150         initGUI( Application, bAllowLetterShortcuts );
    00151         insert( pAccel );
    00152 }
    00153
    00154 KKeyChooser::KKeyChooser( KGlobalAccel* pAccel, QWidget* parent )
    00155 : QWidget( parent )
    00156 {
    00157         initGUI( ApplicationGlobal, false );
    00158         insert( pAccel );
    00159 }
    00160
    00161 KKeyChooser::KKeyChooser( KShortcutList* pList, QWidget* parent, ActionType type, bool bAllowLetterShortcuts )
    00162 : QWidget( parent )
    00163 {
    00164         initGUI( type, bAllowLetterShortcuts );
    00165         insert( pList );
    00166 }
    00167
    00168 KKeyChooser::KKeyChooser( KAccel* actions, QWidget* parent,
    00169                         bool bCheckAgainstStdKeys,
    00170                         bool bAllowLetterShortcuts,
    00171                         bool bAllowWinKey )
    00172 : QWidget( parent )
    00173 {
    00174         ActionType type;
    00175         if( bAllowWinKey )
    00176                 type = (bCheckAgainstStdKeys) ? ApplicationGlobal : Global;
    00177         else
    00178                 type = Application;
    00179
    00180         initGUI( type, bAllowLetterShortcuts );
    00181         insert( actions );
    00182 }
    00183
    00184 KKeyChooser::KKeyChooser( KGlobalAccel* actions, QWidget* parent,
    00185                         bool bCheckAgainstStdKeys,
    00186                         bool bAllowLetterShortcuts,
    00187                         bool /*bAllowWinKey*/ )
    00188 : QWidget( parent )
    00189 {
    00190         ActionType type = (bCheckAgainstStdKeys) ? ApplicationGlobal : Global;
    00191
    00192         initGUI( type, bAllowLetterShortcuts );
    00193         insert( actions );
    00194 }
    00195
    00196 // list of all existing KKeyChooser's of type Global
    00197 // used when checking global shortcut for a possible conflict
    00198 // (just checking against kdeglobals isn't enough, the shortcuts
    00199 // might have changed in KKeyChooser and not being saved yet)
    00200 static QValueList< KKeyChooser* >* globalChoosers = NULL;
    00201 static KStaticDeleter< QValueList< KKeyChooser* > > globalChoosersDeleter;
    00202
    00203 KKeyChooser::~KKeyChooser()
    00204 {
    00205         if( m_type == Global && globalChoosers != NULL )
    00206             globalChoosers->remove( this );
    00207         // Delete allocated KShortcutLists
    00208         for( uint i = 0; i < d->rgpListsAllocated.count(); i++ )
    00209                 delete d->rgpListsAllocated[i];
    00210         delete d;
    00211 }
    00212
    00213 bool KKeyChooser::insert( KActionCollection *pColl)
    00214 {
    00215     return insert(pColl, QString::null);
    00216 }
    00217
    00218 bool KKeyChooser::insert( KActionCollection* pColl, const QString &title )
    00219 {
    00220     QString str = title;
    00221     if ( title.isEmpty() && pColl->instance()
    00222          && pColl->instance()->aboutData() )
    00223         str = pColl->instance()->aboutData()->programName();
    00224
    00225         KShortcutList* pList = new KActionShortcutList( pColl );
    00226         d->rgpListsAllocated.append( pList );
    00227         d->rgpLists.append( pList );
    00228         buildListView(d->rgpLists.count() - 1, str);
    00229         return true;
    00230 }
    00231
    00232 bool KKeyChooser::insert( KAccel* pAccel )
    00233 {
    00234         KShortcutList* pList = new KAccelShortcutList( pAccel );
    00235         d->rgpListsAllocated.append( pList );
    00236         return insert( pList );
    00237 }
    00238
    00239 bool KKeyChooser::insert( KGlobalAccel* pAccel )
    00240 {
    00241         KShortcutList* pList = new KAccelShortcutList( pAccel );
    00242         d->rgpListsAllocated.append( pList );
    00243         return insert( pList );
    00244 }
    00245
    00246 bool KKeyChooser::insert( KShortcutList* pList )
    00247 {
    00248         d->rgpLists.append( pList );
    00249         buildListView( d->rgpLists.count() - 1, QString::null );
    00250         return true;
    00251 }
    00252
    00253 void KKeyChooser::commitChanges()
    00254 {
    00255         kdDebug(125) << "KKeyChooser::commitChanges()" << endl;
    00256
    00257         QListViewItemIterator it( d->pList );
    00258         for( ; it.current(); ++it ) {
    00259                 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
    00260                 if( pItem )
    00261                         pItem->commitChanges();
    00262         }
    00263 }
    00264
    00265 void KKeyChooser::save()
    00266 {
    00267         commitChanges();
    00268         for( uint i = 0; i < d->rgpLists.count(); i++ )
    00269                 d->rgpLists[i]->save();
    00270 }
    00271
    00272 void KKeyChooser::initGUI( ActionType type, bool bAllowLetterShortcuts )
    00273 {
    00274   d = new KKeyChooserPrivate();
    00275
    00276   m_type = type;
    00277   d->bAllowLetterShortcuts = bAllowLetterShortcuts;
    00278
    00279   d->bAllowWinKey = (m_type == Global || m_type == ApplicationGlobal);
    00280   d->bPreferFourModifierKeys = KGlobalAccel::useFourModifierKeys();
    00281
    00282   //
    00283   // TOP LAYOUT MANAGER
    00284   //
    00285   // The following layout is used for the dialog
    00286   //            LIST LABELS LAYOUT
    00287   //            SPLIT LIST BOX WIDGET
    00288   //            CHOOSE KEY GROUP BOX WIDGET
    00289   //            BUTTONS LAYOUT
    00290   // Items are added to topLayout as they are created.
    00291   //
    00292
    00293   QBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
    00294
    00295   QGridLayout *stackLayout = new QGridLayout(2, 2, 2);
    00296   topLayout->addLayout( stackLayout, 10 );
    00297   stackLayout->setRowStretch( 1, 10 ); // Only list will stretch
    00298
    00299   //
    00300   // CREATE SPLIT LIST BOX
    00301   //
    00302   // fill up the split list box with the action/key pairs.
    00303   //
    00304   d->pList = new KListView( this );
    00305   d->pList->setFocus();
    00306
    00307   stackLayout->addMultiCellWidget( d->pList, 1, 1, 0, 1 );
    00308   QString wtstr = i18n("Here you can see a list of key bindings, "
    00309                        "i.e. associations between actions (e.g. 'Copy') "
    00310                        "shown in the left column and keys or combination "
    00311                        "of keys (e.g. Ctrl+V) shown in the right column.");
    00312
    00313   QWhatsThis::add( d->pList, wtstr );
    00314
    00315   d->pList->setAllColumnsShowFocus( true );
    00316   d->pList->addColumn(i18n("Action"));
    00317   d->pList->addColumn(i18n("Shortcut"));
    00318   d->pList->addColumn(i18n("Alternate"));
    00319
    00320   connect( d->pList, SIGNAL(currentChanged(QListViewItem*)),
    00321            SLOT(slotListItemSelected(QListViewItem*)) );
    00322   // handle double clicking an item
    00323   connect ( d->pList, SIGNAL ( doubleClicked ( QListViewItem *, const QPoint &, int ) ),
    00324                        SLOT ( slotListItemDoubleClicked ( QListViewItem *, const QPoint &, int ) ) );
    00325
    00326   //
    00327   // CREATE CHOOSE KEY GROUP
    00328   //
    00329   d->fCArea = new QGroupBox( this );
    00330   topLayout->addWidget( d->fCArea, 1 );
    00331
    00332   d->fCArea->setTitle( i18n("Shortcut for Selected Action") );
    00333   d->fCArea->setFrameStyle( QFrame::Box | QFrame::Sunken );
    00334
    00335   //
    00336   // CHOOSE KEY GROUP LAYOUT MANAGER
    00337   //
    00338   QGridLayout *grid = new QGridLayout( d->fCArea, 3, 4, KDialog::spacingHint() );
    00339   grid->addRowSpacing( 0, fontMetrics().lineSpacing() );
    00340
    00341   d->kbGroup = new QButtonGroup( d->fCArea );
    00342   d->kbGroup->hide();
    00343   d->kbGroup->setExclusive( true );
    00344
    00345   m_prbNone = new QRadioButton( i18n("no key", "&None"), d->fCArea );
    00346   d->kbGroup->insert( m_prbNone, NoKey );
    00347   m_prbNone->setEnabled( false );
    00348   //grid->addMultiCellWidget( rb, 1, 1, 1, 2 );
    00349   grid->addWidget( m_prbNone, 1, 0 );
    00350   QWhatsThis::add( m_prbNone, i18n("The selected action will not be associated with any key.") );
    00351   connect( m_prbNone, SIGNAL(clicked()), SLOT(slotNoKey()) );
    00352
    00353   m_prbDef = new QRadioButton( i18n("default key", "De&fault"), d->fCArea );
    00354   d->kbGroup->insert( m_prbDef, DefaultKey );
    00355   m_prbDef->setEnabled( false );
    00356   //grid->addMultiCellWidget( rb, 2, 2, 1, 2 );
    00357   grid->addWidget( m_prbDef, 1, 1 );
    00358   QWhatsThis::add( m_prbDef, i18n("This will bind the default key to the selected action. Usually a reasonable choice.") );
    00359   connect( m_prbDef, SIGNAL(clicked()), SLOT(slotDefaultKey()) );
    00360
    00361   m_prbCustom = new QRadioButton( i18n("C&ustom"), d->fCArea );
    00362   d->kbGroup->insert( m_prbCustom, CustomKey );
    00363   m_prbCustom->setEnabled( false );
    00364   //grid->addMultiCellWidget( rb, 3, 3, 1, 2 );
    00365   grid->addWidget( m_prbCustom, 1, 2 );
    00366   QWhatsThis::add( m_prbCustom, i18n("If this option is selected you can create a customized key binding for the"
    00367     " selected action using the buttons below.") );
    00368   connect( m_prbCustom, SIGNAL(clicked()), SLOT(slotCustomKey()) );
    00369
    00370   //connect( d->kbGroup, SIGNAL( clicked( int ) ), SLOT( keyMode( int ) ) );
    00371
    00372   QBoxLayout *pushLayout = new QHBoxLayout( KDialog::spacingHint() );
    00373   grid->addLayout( pushLayout, 1, 3 );
    00374
    00375   d->pbtnShortcut = new KKeyButton(d->fCArea, "key");
    00376   d->pbtnShortcut->setEnabled( false );
    00377   connect( d->pbtnShortcut, SIGNAL(capturedShortcut(const KShortcut&)), SLOT(capturedShortcut(const KShortcut&)) );
    00378   grid->addRowSpacing( 1, d->pbtnShortcut->sizeHint().height() + 5 );
    00379
    00380   wtstr = i18n("Use this button to choose a new shortcut key. Once you click it, "
    00381                 "you can press the key-combination which you would like to be assigned "
    00382                 "to the currently selected action.");
    00383   QWhatsThis::add( d->pbtnShortcut, wtstr );
    00384
    00385   //
    00386   // Add widgets to the geometry manager
    00387   //
    00388   pushLayout->addSpacing( KDialog::spacingHint()*2 );
    00389   pushLayout->addWidget( d->pbtnShortcut );
    00390   pushLayout->addStretch( 10 );
    00391
    00392   d->lInfo = new QLabel(d->fCArea);
    00393   //resize(0,0);
    00394   //d->lInfo->setAlignment( AlignCenter );
    00395   //d->lInfo->setEnabled( false );
    00396   //d->lInfo->hide();
    00397   grid->addMultiCellWidget( d->lInfo, 2, 2, 0, 3 );
    00398
    00399   //d->globalDict = new QDict<int> ( 100, false );
    00400   //d->globalDict->setAutoDelete( true );
    00401   readGlobalKeys();
    00402   //d->stdDict = new QDict<int> ( 100, false );
    00403   //d->stdDict->setAutoDelete( true );
    00404   //if (type == Application || type == ApplicationGlobal)
    00405   //  readStdKeys();
    00406   connect( kapp, SIGNAL( settingsChanged( int )), SLOT( slotSettingsChanged( int )));
    00407   if( m_type == Global ) {
    00408       if( globalChoosers == NULL )
    00409           globalChoosers = globalChoosersDeleter.setObject( new QValueList< KKeyChooser* > );
    00410       globalChoosers->append( this );
    00411   }
    00412 }
    00413
    00414 // Add all shortcuts to the list
    00415 void KKeyChooser::buildListView( uint iList, const QString &title )
    00416 {
    00417         KShortcutList* pList = d->rgpLists[iList];
    00418
    00419         //d->pList->setSorting( -1 );
    00420         KListViewItem *pProgramItem, *pGroupItem = 0, *pParentItem, *pItem;
    00421
    00422         QString str = (title.isEmpty() ? i18n("Shortcuts") : title);
    00423         pParentItem = pProgramItem = pItem = new KListViewItem( d->pList, str );
    00424         pParentItem->setExpandable( true );
    00425         pParentItem->setOpen( true );
    00426         pParentItem->setSelectable( false );
    00427         uint nSize = pList->count();
    00428         for( uint iAction = 0; iAction < nSize; iAction++ ) {
    00429                 QString sName = pList->name(iAction);
    00430                 kdDebug(125) << "Key: " << sName << endl;
    00431                 if( sName.startsWith( "Program:" ) ) {
    00432                         pItem = new KListViewItem( d->pList, pProgramItem, pList->label(iAction) );
    00433                         pItem->setSelectable( false );
    00434                         pItem->setExpandable( true );
    00435                         pItem->setOpen( true );
    00436                         if( !pProgramItem->firstChild() )
    00437                                 delete pProgramItem;
    00438                         pProgramItem = pParentItem = pItem;
    00439                 } else if( sName.startsWith( "Group:" ) ) {
    00440                         pItem = new KListViewItem( pProgramItem, pParentItem, pList->label(iAction) );
    00441                         pItem->setSelectable( false );
    00442                         pItem->setExpandable( true );
    00443                         pItem->setOpen( true );
    00444                         if( pGroupItem && !pGroupItem->firstChild() )
    00445                                 delete pGroupItem;
    00446                         pGroupItem = pParentItem = pItem;
    00447                 } else if( !sName.isEmpty() && pList->isConfigurable(iAction) )
    00448                         pItem = new KKeyChooserItem( pParentItem, pItem, pList, iAction );
    00449         }
    00450         if( !pProgramItem->firstChild() )
    00451                 delete pProgramItem;
    00452         if( pGroupItem && !pGroupItem->firstChild() )
    00453                 delete pGroupItem;
    00454 }
    00455
    00456 void KKeyChooser::updateButtons()
    00457 {
    00458         // Hack: Do this incase we still have changeKey() running.
    00459         //  Better would be to capture the mouse pointer so that we can't click
    00460         //   around while we're supposed to be entering a key.
    00461         //  Better yet would be a modal dialog for changeKey()!
    00462         releaseKeyboard();
    00463         KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
    00464
    00465         if ( !pItem ) {
    00466                 // if nothing is selected -> disable radio boxes
    00467                 m_prbNone->setEnabled( false );
    00468                 m_prbDef->setEnabled( false );
    00469                 m_prbCustom->setEnabled( false );
    00470                 d->pbtnShortcut->setEnabled( false );
    00471                 d->pbtnShortcut->setShortcut( KShortcut() );
    00472         } else {
    00473                 bool bConfigurable = pItem->isConfigurable();
    00474                 bool bQtShortcut = (m_type == Application || m_type == Standard);
    00475                 const KShortcut& cutDef = pItem->shortcutDefault();
    00476
    00477                 // Set key strings
    00478                 QString keyStrCfg = pItem->shortcut().toString();
    00479                 QString keyStrDef = cutDef.toString();
    00480
    00481                 d->pbtnShortcut->setShortcut( pItem->shortcut(), bQtShortcut );
    00482                 //item->setText( 1, keyStrCfg );
    00483                 pItem->repaint();
    00484                 d->lInfo->setText( i18n("Default key:") + QString(" %1").arg(keyStrDef.isEmpty() ? i18n("None") : keyStrDef) );
    00485
    00486                 // Select the appropriate radio button.
    00487                 int index = (pItem->shortcut().isNull()) ? NoKey
    00488                                 : (pItem->shortcut() == cutDef) ? DefaultKey
    00489                                 : CustomKey;
    00490                 m_prbNone->setChecked( index == NoKey );
    00491                 m_prbDef->setChecked( index == DefaultKey );
    00492                 m_prbCustom->setChecked( index == CustomKey );
    00493
    00494                 // Enable buttons if this key is configurable.
    00495                 // The 'Default Key' button must also have a default key.
    00496                 m_prbNone->setEnabled( bConfigurable );
    00497                 m_prbDef->setEnabled( bConfigurable && cutDef.count() != 0 );
    00498                 m_prbCustom->setEnabled( bConfigurable );
    00499                 d->pbtnShortcut->setEnabled( bConfigurable );
    00500         }
    00501 }
    00502
    00503 void KKeyChooser::slotNoKey()
    00504 {
    00505         // return if no key is selected
    00506         KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
    00507         if( pItem ) {
    00508                 //kdDebug(125) << "no Key" << d->pList->currentItem()->text(0) << endl;
    00509                 pItem->setShortcut( KShortcut() );
    00510                 updateButtons();
    00511                 emit keyChange();
    00512         }
    00513 }
    00514
    00515 void KKeyChooser::slotDefaultKey()
    00516 {
    00517         // return if no key is selected
    00518         KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
    00519         if( pItem ) {
    00520                 pItem->setShortcut( pItem->shortcutDefault() );
    00521                 updateButtons();
    00522                 emit keyChange();
    00523         }
    00524 }
    00525
    00526 void KKeyChooser::slotCustomKey()
    00527 {
    00528         d->pbtnShortcut->captureShortcut();
    00529 }
    00530
    00531 void KKeyChooser::readGlobalKeys()
    00532 {
    00533         d->mapGlobals.clear();
    00534         if( m_type == Global )
    00535             return; // they will be checked normally, because we're configuring them
    00536         QMap<QString, QString> mapEntry = KGlobal::config()->entryMap( "Global Shortcuts" );
    00537         QMap<QString, QString>::Iterator it( mapEntry.begin() );
    00538         for( uint i = 0; it != mapEntry.end(); ++it, i++ )
    00539                 d->mapGlobals[it.key()] = KShortcut(*it);
    00540 }
    00541
    00542 void KKeyChooser::slotSettingsChanged( int category )
    00543 {
    00544     if( category == KApplication::SETTINGS_SHORTCUTS )
    00545         readGlobalKeys(); // reread
    00546 }
    00547
    00548 void KKeyChooser::fontChange( const QFont & )
    00549 {
    00550         d->fCArea->setMinimumHeight( 4*d->pbtnShortcut->sizeHint().height() );
    00551
    00552         int widget_width = 0;
    00553
    00554         setMinimumWidth( 20+5*(widget_width+10) );
    00555 }
    00556
    00557 void KKeyChooser::allDefault()
    00558 {
    00559         kdDebug(125) << "KKeyChooser::allDefault()" << endl;
    00560
    00561         QListViewItemIterator it( d->pList );
    00562         for( ; it.current(); ++it ) {
    00563                 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
    00564                 if( pItem )
    00565                         pItem->setShortcut( pItem->shortcutDefault() );
    00566         }
    00567
    00568         updateButtons();
    00569         emit keyChange();
    00570 }
    00571
    00572 void KKeyChooser::slotListItemSelected( QListViewItem* )
    00573 {
    00574         updateButtons();
    00575 }
    00576
    00577
    00578 void KKeyChooser::slotListItemDoubleClicked ( QListViewItem *, const QPoint & , int )
    00579 {
    00580
    00581   KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
    00582   if( pItem != NULL && pItem->isConfigurable())
    00583       d->pbtnShortcut->captureShortcut ( );
    00584
    00585 }
    00586
    00587 void KKeyChooser::setPreferFourModifierKeys( bool bPreferFourModifierKeys )
    00588 {
    00589         d->bPreferFourModifierKeys = bPreferFourModifierKeys;
    00590 }
    00591
    00592 void KKeyChooser::capturedShortcut( const KShortcut& cut )
    00593 {
    00594         if( cut.isNull() )
    00595                 slotNoKey();
    00596         else
    00597                 setShortcut( cut );
    00598 }
    00599
    00600 // FIXME: give this functionality again -- I don't think it's ever used, though. -- ellis
    00601 // TODO: Check lxr.kde.org to see if it's used anywhere
    00602 void KKeyChooser::listSync()
    00603 {
    00604 /*      kdDebug(125) << "KKeyChooser::listSync()" << endl;
    00605
    00606         if( d->pColl ) {
    00607                 // TODO: This is very inefficient.  Come up with something better.
    00608                 KAccelActions aa;
    00609                 d->pColl->createKeyMap( aa );
    00610                 d->actionsNew.updateShortcuts( aa );
    00611         } else if( d->pActionsOrig ) {
    00612                 d->actionsNew.updateShortcuts( *d->pActionsOrig );
    00613                 update();
    00614                 updateButtons();
    00615         }*/
    00616 }
    00617
    00618 void KKeyChooser::syncToConfig( const QString& sConfigGroup, KConfigBase* pConfig, bool bClearUnset )
    00619 {
    00620         kdDebug(125) << "KKeyChooser::syncToConfig( \"" << sConfigGroup << "\", " << pConfig << " ) start" << endl;
    00621         if( !pConfig )
    00622                 pConfig = KGlobal::config();
    00623         KConfigGroupSaver cgs( pConfig, sConfigGroup );
    00624
    00625         QListViewItemIterator it( d->pList );
    00626         for( ; it.current(); ++it ) {
    00627                 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
    00628                 if( pItem ) {
    00629                         QString sEntry = pConfig->readEntry( pItem->actionName() );
    00630                         if( !sEntry.isNull() || bClearUnset ) {
    00631                                 if( sEntry == "none" )
    00632                                         sEntry = QString::null;
    00633                                 pItem->setShortcut( sEntry );
    00634                         }
    00635                         kdDebug(125) << pItem->actionName() << " = " << pItem->shortcut().toStringInternal() << endl;
    00636                 }
    00637         }
    00638         updateButtons();
    00639         kdDebug(125) << "KKeyChooser::syncToConfig() done" << endl;
    00640 }
    00641
    00642 void KKeyChooser::setShortcut( const KShortcut& cut )
    00643 {
    00644         kdDebug(125) << "KKeyChooser::setShortcut( " << cut.toString() << " )" << endl;
    00645         KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
    00646         if( !pItem )
    00647                 return;
    00648
    00649         for( uint i = 0; i < cut.count(); i++ ) {
    00650                 const KKeySequence& seq = cut.seq(i);
    00651                 const KKey& key = seq.key(0);
    00652
    00653                 if( !d->bAllowWinKey && (key.modFlags() & KKey::WIN) ) {
    00654                         QString s = i18n("The Win key is not allowed in this context.");
    00655                         KMessageBox::sorry( this, s, i18n("Invalid Shortcut Key") );
    00656                         return;
    00657                 }
    00658                 if( !d->bAllowLetterShortcuts && key.modFlags() == 0
    00659                     && key.sym() < 0x3000 && QChar(key.sym()).isLetterOrNumber() ) {
    00660                         QString s = i18n(       "In order to use the '%1' key as a shortcut, "
    00661                                                 "it must be combined with the "
    00662                                                 "Win, Alt, Ctrl, and/or Shift keys." ).arg(QChar(key.sym()));
    00663                         KMessageBox::sorry( this, s, i18n("Invalid Shortcut Key") );
    00664                         return;
    00665                 }
    00666         }
    00667
    00668         // If key isn't already in use,
    00669         if( !isKeyPresent( cut ) ) {
    00670                 // Set new key code
    00671                 pItem->setShortcut( cut );
    00672                 // Update display
    00673                 updateButtons();
    00674                 emit keyChange();
    00675         }
    00676 }
    00677
    00678 // Returns iSeq index if cut2 has a sequence of equal or higher priority to a sequence in cut.
    00679 // else -1
    00680 static int keyConflict( const KShortcut& cut, const KShortcut& cut2 )
    00681 {
    00682         for( uint iSeq = 0; iSeq < cut.count(); iSeq++ ) {
    00683                 for( uint iSeq2 = 0; iSeq2 <= iSeq && iSeq2 < cut2.count(); iSeq2++ ) {
    00684                         if( cut.seq(iSeq) == cut2.seq(iSeq2) )
    00685                                 return iSeq;
    00686                 }
    00687         }
    00688         return -1;
    00689 }
    00690
    00691 bool KKeyChooser::isKeyPresent( const KShortcut& cut, bool bWarnUser )
    00692 {
    00693         KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
    00694
    00695         // If editing global shortcuts, check them for conflicts with the stdaccels.
    00696         if( m_type == ApplicationGlobal || m_type == Global ) {
    00697                 // For each key sequence in the shortcut,
    00698                 for( uint i = 0; i < cut.count(); i++ ) {
    00699                         const KKeySequence& seq = cut.seq(i);
    00700
    00701                         KStdAccel::StdAccel id = KStdAccel::findStdAccel( seq );
    00702                         if( id != KStdAccel::AccelNone
    00703                             && keyConflict( cut, KStdAccel::shortcut( id ) ) > -1 ) {
    00704                                 if( bWarnUser )
    00705                                         _warning( seq, KStdAccel::label(id), i18n("Conflict with Standard Application Shortcut") );
    00706                                 return true;
    00707                         }
    00708                 }
    00709         }
    00710
    00711         QMap<QString, KShortcut>::ConstIterator it;
    00712         for( it = d->mapGlobals.begin(); it != d->mapGlobals.end(); ++it ) {
    00713                 int iSeq = keyConflict( cut, (*it) );
    00714                 if( iSeq > -1 ) {
    00715                         if( m_type != Global || it.key() != pItem->actionName() ) {
    00716                                 if( bWarnUser )
    00717                                         _warning( cut.seq(iSeq), it.key(), i18n("Conflict with Global Shortcuts") );
    00718                                 return true;
    00719                         }
    00720                 }
    00721         }
    00722
    00723         if( isKeyPresentLocally( cut, pItem, bWarnUser ? i18n("Key Conflict") : QString::null ))
    00724             return true;
    00725
    00726         // check also other Global KKeyChooser's
    00727         if( m_type == Global && globalChoosers != NULL ) {
    00728             for( QValueList< KKeyChooser* >::ConstIterator it = globalChoosers->begin();
    00729                  it != globalChoosers->end();
    00730                  ++it ) {
    00731                 if( (*it) != this && (*it)->isKeyPresentLocally( cut, NULL,
    00732                     bWarnUser ? i18n("Key Conflict") : QString::null))
    00733                     return true;
    00734             }
    00735         }
    00736         return false;
    00737 }
    00738
    00739 bool KKeyChooser::isKeyPresentLocally( const KShortcut& cut, KKeyChooserItem* ignoreItem, const QString& warnText )
    00740 {
    00741     if ( cut.toString().isEmpty())
    00742                return false;
    00743
    00744                 // Search for shortcut conflicts with other actions in the
    00745         //  lists we're configuring.
    00746         for( QListViewItemIterator it( d->pList ); it.current(); ++it ) {
    00747                 KKeyChooserItem* pItem2 = dynamic_cast<KKeyChooserItem*>(it.current());
    00748                 if( pItem2 && pItem2 != ignoreItem ) {
    00749                         int iSeq = keyConflict( cut, pItem2->shortcut() );
    00750                         if( iSeq > -1 ) {
    00751                                 if( !warnText.isNull() )
    00752                                         _warning( cut.seq(iSeq), pItem2->text(0), warnText );
    00753                                 return true;
    00754                         }
    00755                 }
    00756         }
    00757         return false;
    00758 }
    00759
    00760 void KKeyChooser::_warning( const KKeySequence& cut, QString sAction, QString sTitle )
    00761 {
    00762         sAction = sAction.stripWhiteSpace();
    00763
    00764         QString s =
    00765                 i18n("The '%1' key combination has already been allocated "
    00766                 "to the \"%2\" action.\n"
    00767                 "Please choose a unique key combination.").
    00768                 arg(cut.toString()).arg(sAction);
    00769
    00770         KMessageBox::sorry( this, s, sTitle );
    00771 }
    00772
    00773 //---------------------------------------------------
    00774 KKeyChooserItem::KKeyChooserItem( KListView* parent, QListViewItem* after, KShortcutList* pList, uint iAction )
    00775 :       KListViewItem( parent, after )
    00776 {
    00777         m_pList = pList;
    00778         m_iAction = iAction;
    00779         m_bModified = false;
    00780         m_cut = m_pList->shortcut(m_iAction);
    00781 }
    00782
    00783 KKeyChooserItem::KKeyChooserItem( QListViewItem* parent, QListViewItem* after, KShortcutList* pList, uint iAction )
    00784 :       KListViewItem( parent, after )
    00785 {
    00786         m_pList = pList;
    00787         m_iAction = iAction;
    00788         m_bModified = false;
    00789         m_cut = m_pList->shortcut(m_iAction);
    00790 }
    00791
    00792 QString KKeyChooserItem::actionName() const
    00793 {
    00794         return m_pList->name(m_iAction);
    00795 }
    00796
    00797 const KShortcut& KKeyChooserItem::shortcut() const
    00798 {
    00799         return m_cut;
    00800 }
    00801
    00802 void KKeyChooserItem::setShortcut( const KShortcut& cut )
    00803 {
    00804         m_cut = cut;
    00805         m_bModified = (m_cut != m_pList->shortcut(m_iAction));
    00806         listView()->repaintItem( this );
    00807 }
    00808
    00809 void KKeyChooserItem::commitChanges()
    00810 {
    00811         if( m_bModified )
    00812                 m_pList->setShortcut( m_iAction, m_cut );
    00813 }
    00814
    00815 QString KKeyChooserItem::text( int iCol ) const
    00816 {
    00817         if( iCol == 0 ) {
    00818                 // Quick HACK to get rid of '&'s.
    00819                 QString s = m_pList->label(m_iAction);
    00820                 QString s2;
    00821                 for( uint i = 0; i < s.length(); i++ )
    00822                         if( s[i] != '&' || ( i+1<s.length() && s[i+1] == '&' ) )
    00823                                 s2 += s[i];
    00824                 return s2;
    00825         }
    00826         else if( iCol <= (int) m_cut.count() )
    00827                 return m_cut.seq(iCol-1).toString();
    00828         else
    00829                 return QString::null;
    00830 }
    00831
    00832 int KKeyChooserItem::compare( QListViewItem* item, int iCol, bool bAscending ) const
    00833 {
    00834         KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( item );
    00835         if( iCol == 0 && pItem ) {
    00836                 QString psName1 = m_pList->name(m_iAction);
    00837                 QString psName2 = pItem->m_pList->name(pItem->m_iAction);
    00838                 QRegExp rxNumber1( " (\\d+)$" );
    00839                 QRegExp rxNumber2( " (\\d+)$" );
    00840                 int iNumber1 = rxNumber1.search( psName1 );
    00841                 int iNumber2 = rxNumber2.search( psName2 );
    00842
    00843                 // Check if the last word is one or more digits
    00844                 if( iNumber1 >= 0 && iNumber1 == iNumber2 && psName1.startsWith( psName2.left( iNumber1+1 ) ) ) {
    00845                         int n1 = rxNumber1.cap(1).toInt();
    00846                         int n2 = rxNumber2.cap(1).toInt();
    00847                         return (n1 < n2) ? -1 : (n1 > n2) ? 1 : 0;
    00848                 }
    00849         }
    00850
    00851         return QListViewItem::compare( item, iCol, bAscending );
    00852 }
    00853
    00854 /************************************************************************/
    00855 /* KKeyDialog                                                           */
    00856 /*                                                                      */
    00857 /* Originally by Nicolas Hadacek <hadacek@via.ecp.fr>                   */
    00858 /*                                                                      */
    00859 /* Substantially revised by Mark Donohoe <donohoe@kde.org>              */
    00860 /*                                                                      */
    00861 /* And by Espen Sand <espen@kde.org> 1999-10-19                         */
    00862 /* (by using KDialogBase there is almost no code left ;)                */
    00863 /*                                                                      */
    00864 /************************************************************************/
    00865 KKeyDialog::KKeyDialog( KKeyChooser::ActionType type, bool bAllowLetterShortcuts, QWidget *parent, const char* name )
    00866 : KDialogBase( parent, name, true, i18n("Configure Shortcuts"), Help|Default|Ok|Cancel, Ok )
    00867 {
    00868         m_pKeyChooser = new KKeyChooser( this, type, bAllowLetterShortcuts );
    00869         setMainWidget( m_pKeyChooser );
    00870         connect( this, SIGNAL(defaultClicked()), m_pKeyChooser, SLOT(allDefault()) );
    00871         enableButton( Help, false );
    00872
    00873         KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
    00874         QSize sz = size();
    00875         resize( group.readSizeEntry( "Dialog Size", &sz ) );
    00876 }
    00877
    00878 KKeyDialog::KKeyDialog( bool bAllowLetterShortcuts, QWidget *parent, const char* name )
    00879 : KDialogBase( parent, name, true, i18n("Configure Shortcuts"), Help|Default|Ok|Cancel, Ok )
    00880 {
    00881         m_pKeyChooser = new KKeyChooser( this, KKeyChooser::Application, bAllowLetterShortcuts );
    00882         setMainWidget( m_pKeyChooser );
    00883         connect( this, SIGNAL(defaultClicked()), m_pKeyChooser, SLOT(allDefault()) );
    00884         enableButton( Help, false );
    00885
    00886         KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
    00887         QSize sz = size();
    00888         resize( group.readSizeEntry( "Dialog Size", &sz ) );
    00889 }
    00890
    00891 KKeyDialog::~KKeyDialog()
    00892 {
    00893         KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
    00894         group.writeEntry( "Dialog Size", size(), true, true );
    00895 }
    00896
    00897 bool KKeyDialog::insert( KActionCollection* pColl )
    00898 {
    00899         return m_pKeyChooser->insert( pColl );
    00900 }
    00901
    00902 bool KKeyDialog::insert(KActionCollection *pColl, const QString &title)
    00903 {
    00904     return m_pKeyChooser->insert(pColl, title);
    00905 }
    00906
    00907 bool KKeyDialog::configure( bool bSaveSettings )
    00908 {
    00909         int retcode = exec();
    00910         if( retcode == Accepted ) {
    00911                 if( bSaveSettings )
    00912                         m_pKeyChooser->save();
    00913                 else
    00914                         commitChanges();
    00915         }
    00916         return retcode;
    00917 }
    00918
    00919 void KKeyDialog::commitChanges()
    00920 {
    00921         m_pKeyChooser->commitChanges();
    00922 }
    00923
    00924 int KKeyDialog::configure( KActionCollection* coll, QWidget* parent, bool bSaveSettings )
    00925 {
    00926         return configure( coll, true, parent, bSaveSettings);
    00927 }
    00928
    00929 int KKeyDialog::configure( KAccel* keys, QWidget* parent, bool bSaveSettings )
    00930 {
    00931         return configure( keys, true, parent, bSaveSettings);
    00932 }
    00933
    00934 int KKeyDialog::configure( KGlobalAccel* keys, QWidget* parent, bool bSaveSettings )
    00935 {
    00936         return configure( keys, true, parent, bSaveSettings);
    00937 }
    00938
    00939 int KKeyDialog::configure( KAccel* keys, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
    00940 {
    00941         KKeyDialog dlg( bAllowLetterShortcuts, parent );
    00942         dlg.m_pKeyChooser->insert( keys );
    00943         bool b = dlg.configure( bSaveSettings );
    00944         if( b && bSaveSettings )
    00945                 keys->updateConnections();
    00946         return b;
    00947 }
    00948
    00949 int KKeyDialog::configure( KGlobalAccel* keys, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
    00950 {
    00951         KKeyDialog dlg( KKeyChooser::ApplicationGlobal, bAllowLetterShortcuts, parent );
    00952         dlg.m_pKeyChooser->insert( keys );
    00953         bool b = dlg.configure( bSaveSettings );
    00954         if( b && bSaveSettings )
    00955                 keys->updateConnections();
    00956         return b;
    00957 }
    00958
    00959 int KKeyDialog::configure( KActionCollection* coll, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
    00960 {
    00961         kdDebug(125) << "KKeyDialog::configureKeys( KActionCollection*, " << bSaveSettings << " )" << endl;
    00962         KKeyDialog dlg( bAllowLetterShortcuts, parent );
    00963         dlg.m_pKeyChooser->insert( coll );
    00964         return dlg.configure( bSaveSettings );
    00965 }
    00966
    00967 /*int KKeyDialog::configure( KActionPtrList* coll, const QString& file, QWidget *parent, bool bSaveSettings )
    00968 {
    00969         kdDebug(125) << "KKeyDialog::configureKeys( KActionCollection*, " << file << ", " << bSaveSettings << " )" << endl;
    00970         KAccelActions actions;
    00971         coll->createKeyMap( actions );
    00972
    00973         int retcode = configure( actions, file, parent, bSaveSettings );
    00974         if( retcode == Accepted )
    00975                 coll->setKeyMap( actions );
    00976
    00977         return retcode;
    00978 }*/
    00979
    00980 void KKeyChooser::virtual_hook( int, void* )
    00981 { /*BASE::virtual_hook( id, data );*/ }
    00982
    00983 void KKeyDialog::virtual_hook( int id, void* data )
    00984 { KDialogBase::virtual_hook( id, data ); }
    00985
    00986 #include "kkeydialog.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:00 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001