00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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>
00057 #include <X11/keysymdef.h>
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
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
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
00121
00122
00123
00124 bool bAllowLetterShortcuts;
00125
00126
00127 bool bPreferFourModifierKeys;
00128 };
00129
00130
00131
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 )
00188 : QWidget( parent )
00189 {
00190 ActionType type = (bCheckAgainstStdKeys) ? ApplicationGlobal : Global;
00191
00192 initGUI( type, bAllowLetterShortcuts );
00193 insert( actions );
00194 }
00195
00196
00197
00198
00199
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
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
00284
00285
00286
00287
00288
00289
00290
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 );
00298
00299
00300
00301
00302
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
00323
00324
00325
00326 d->fCArea = new QGroupBox( this );
00327 topLayout->addWidget( d->fCArea, 1 );
00328
00329 d->fCArea->setTitle( i18n("Shortcut for Selected Action") );
00330 d->fCArea->setFrameStyle( QFrame::Box | QFrame::Sunken );
00331
00332
00333
00334
00335 QGridLayout *grid = new QGridLayout( d->fCArea, 3, 4, KDialog::spacingHint() );
00336 grid->addRowSpacing( 0, fontMetrics().lineSpacing() );
00337
00338 d->kbGroup = new QButtonGroup( d->fCArea );
00339 d->kbGroup->hide();
00340 d->kbGroup->setExclusive( true );
00341
00342 m_prbNone = new QRadioButton( i18n("no key", "&None"), d->fCArea );
00343 d->kbGroup->insert( m_prbNone, NoKey );
00344 m_prbNone->setEnabled( false );
00345
00346 grid->addWidget( m_prbNone, 1, 0 );
00347 QWhatsThis::add( m_prbNone, i18n("The selected action will not be associated with any key.") );
00348 connect( m_prbNone, SIGNAL(clicked()), SLOT(slotNoKey()) );
00349
00350 m_prbDef = new QRadioButton( i18n("default key", "De&fault"), d->fCArea );
00351 d->kbGroup->insert( m_prbDef, DefaultKey );
00352 m_prbDef->setEnabled( false );
00353
00354 grid->addWidget( m_prbDef, 1, 1 );
00355 QWhatsThis::add( m_prbDef, i18n("This will bind the default key to the selected action. Usually a reasonable choice.") );
00356 connect( m_prbDef, SIGNAL(clicked()), SLOT(slotDefaultKey()) );
00357
00358 m_prbCustom = new QRadioButton( i18n("C&ustom"), d->fCArea );
00359 d->kbGroup->insert( m_prbCustom, CustomKey );
00360 m_prbCustom->setEnabled( false );
00361
00362 grid->addWidget( m_prbCustom, 1, 2 );
00363 QWhatsThis::add( m_prbCustom, i18n("If this option is selected you can create a customized key binding for the"
00364 " selected action using the buttons below.") );
00365 connect( m_prbCustom, SIGNAL(clicked()), SLOT(slotCustomKey()) );
00366
00367
00368
00369 QBoxLayout *pushLayout = new QHBoxLayout( KDialog::spacingHint() );
00370 grid->addLayout( pushLayout, 1, 3 );
00371
00372 d->pbtnShortcut = new KKeyButton(d->fCArea, "key");
00373 d->pbtnShortcut->setEnabled( false );
00374 connect( d->pbtnShortcut, SIGNAL(capturedShortcut(const KShortcut&)), SLOT(capturedShortcut(const KShortcut&)) );
00375 grid->addRowSpacing( 1, d->pbtnShortcut->sizeHint().height() + 5 );
00376
00377 wtstr = i18n("Use this button to choose a new shortcut key. Once you click it, "
00378 "you can press the key-combination which you would like to be assigned "
00379 "to the currently selected action.");
00380 QWhatsThis::add( d->pbtnShortcut, wtstr );
00381
00382
00383
00384
00385 pushLayout->addSpacing( KDialog::spacingHint()*2 );
00386 pushLayout->addWidget( d->pbtnShortcut );
00387 pushLayout->addStretch( 10 );
00388
00389 d->lInfo = new QLabel(d->fCArea);
00390
00391
00392
00393
00394 grid->addMultiCellWidget( d->lInfo, 2, 2, 0, 3 );
00395
00396
00397
00398 readGlobalKeys();
00399
00400
00401
00402
00403 connect( kapp, SIGNAL( settingsChanged( int )), SLOT( slotSettingsChanged( int )));
00404 if( m_type == Global ) {
00405 if( globalChoosers == NULL )
00406 globalChoosers = globalChoosersDeleter.setObject( new QValueList< KKeyChooser* > );
00407 globalChoosers->append( this );
00408 }
00409 }
00410
00411
00412 void KKeyChooser::buildListView( uint iList, const QString &title )
00413 {
00414 KShortcutList* pList = d->rgpLists[iList];
00415
00416
00417 KListViewItem *pProgramItem, *pGroupItem = 0, *pParentItem, *pItem;
00418
00419 QString str = (title.isEmpty() ? i18n("Shortcuts") : title);
00420 pParentItem = pProgramItem = pItem = new KListViewItem( d->pList, str );
00421 pParentItem->setExpandable( true );
00422 pParentItem->setOpen( true );
00423 pParentItem->setSelectable( false );
00424 uint nSize = pList->count();
00425 for( uint iAction = 0; iAction < nSize; iAction++ ) {
00426 QString sName = pList->name(iAction);
00427 kdDebug(125) << "Key: " << sName << endl;
00428 if( sName.startsWith( "Program:" ) ) {
00429 pItem = new KListViewItem( d->pList, pProgramItem, pList->label(iAction) );
00430 pItem->setSelectable( false );
00431 pItem->setExpandable( true );
00432 pItem->setOpen( true );
00433 if( !pProgramItem->firstChild() )
00434 delete pProgramItem;
00435 pProgramItem = pParentItem = pItem;
00436 } else if( sName.startsWith( "Group:" ) ) {
00437 pItem = new KListViewItem( pProgramItem, pParentItem, pList->label(iAction) );
00438 pItem->setSelectable( false );
00439 pItem->setExpandable( true );
00440 pItem->setOpen( true );
00441 if( pGroupItem && !pGroupItem->firstChild() )
00442 delete pGroupItem;
00443 pGroupItem = pParentItem = pItem;
00444 } else if( !sName.isEmpty() && pList->isConfigurable(iAction) )
00445 pItem = new KKeyChooserItem( pParentItem, pItem, pList, iAction );
00446 }
00447 if( !pProgramItem->firstChild() )
00448 delete pProgramItem;
00449 if( pGroupItem && !pGroupItem->firstChild() )
00450 delete pGroupItem;
00451 }
00452
00453 void KKeyChooser::updateButtons()
00454 {
00455
00456
00457
00458
00459 releaseKeyboard();
00460 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
00461
00462 if ( !pItem ) {
00463
00464 m_prbNone->setEnabled( false );
00465 m_prbDef->setEnabled( false );
00466 m_prbCustom->setEnabled( false );
00467 d->pbtnShortcut->setEnabled( false );
00468 d->pbtnShortcut->setShortcut( KShortcut() );
00469 } else {
00470 bool bConfigurable = pItem->isConfigurable();
00471 bool bQtShortcut = (m_type == Application || m_type == Standard);
00472 const KShortcut& cutDef = pItem->shortcutDefault();
00473
00474
00475 QString keyStrCfg = pItem->shortcut().toString();
00476 QString keyStrDef = cutDef.toString();
00477
00478 d->pbtnShortcut->setShortcut( pItem->shortcut(), bQtShortcut );
00479
00480 pItem->repaint();
00481 d->lInfo->setText( i18n("Default key:") + QString(" %1").arg(keyStrDef.isEmpty() ? i18n("None") : keyStrDef) );
00482
00483
00484 int index = (pItem->shortcut().isNull()) ? NoKey
00485 : (pItem->shortcut() == cutDef) ? DefaultKey
00486 : CustomKey;
00487 m_prbNone->setChecked( index == NoKey );
00488 m_prbDef->setChecked( index == DefaultKey );
00489 m_prbCustom->setChecked( index == CustomKey );
00490
00491
00492
00493 m_prbNone->setEnabled( bConfigurable );
00494 m_prbDef->setEnabled( bConfigurable && cutDef.count() != 0 );
00495 m_prbCustom->setEnabled( bConfigurable );
00496 d->pbtnShortcut->setEnabled( bConfigurable );
00497 }
00498 }
00499
00500 void KKeyChooser::slotNoKey()
00501 {
00502
00503 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
00504 if( pItem ) {
00505
00506 pItem->setShortcut( KShortcut() );
00507 updateButtons();
00508 emit keyChange();
00509 }
00510 }
00511
00512 void KKeyChooser::slotDefaultKey()
00513 {
00514
00515 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
00516 if( pItem ) {
00517 pItem->setShortcut( pItem->shortcutDefault() );
00518 updateButtons();
00519 emit keyChange();
00520 }
00521 }
00522
00523 void KKeyChooser::slotCustomKey()
00524 {
00525 d->pbtnShortcut->captureShortcut();
00526 }
00527
00528 void KKeyChooser::readGlobalKeys()
00529 {
00530 d->mapGlobals.clear();
00531 if( m_type == Global )
00532 return;
00533 QMap<QString, QString> mapEntry = KGlobal::config()->entryMap( "Global Shortcuts" );
00534 QMap<QString, QString>::Iterator it( mapEntry.begin() );
00535 for( uint i = 0; it != mapEntry.end(); ++it, i++ )
00536 d->mapGlobals[it.key()] = KShortcut(*it);
00537 }
00538
00539 void KKeyChooser::slotSettingsChanged( int category )
00540 {
00541 if( category == KApplication::SETTINGS_SHORTCUTS )
00542 readGlobalKeys();
00543 }
00544
00545 void KKeyChooser::fontChange( const QFont & )
00546 {
00547 d->fCArea->setMinimumHeight( 4*d->pbtnShortcut->sizeHint().height() );
00548
00549 int widget_width = 0;
00550
00551 setMinimumWidth( 20+5*(widget_width+10) );
00552 }
00553
00554 void KKeyChooser::allDefault()
00555 {
00556 kdDebug(125) << "KKeyChooser::allDefault()" << endl;
00557
00558 QListViewItemIterator it( d->pList );
00559 for( ; it.current(); ++it ) {
00560 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
00561 if( pItem )
00562 pItem->setShortcut( pItem->shortcutDefault() );
00563 }
00564
00565 updateButtons();
00566 emit keyChange();
00567 }
00568
00569 void KKeyChooser::slotListItemSelected( QListViewItem* )
00570 {
00571 updateButtons();
00572 }
00573
00574 void KKeyChooser::setPreferFourModifierKeys( bool bPreferFourModifierKeys )
00575 {
00576 d->bPreferFourModifierKeys = bPreferFourModifierKeys;
00577 }
00578
00579 void KKeyChooser::capturedShortcut( const KShortcut& cut )
00580 {
00581 if( cut.isNull() )
00582 slotNoKey();
00583 else
00584 setShortcut( cut );
00585 }
00586
00587
00588
00589 void KKeyChooser::listSync()
00590 {
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 }
00604
00605 void KKeyChooser::syncToConfig( const QString& sConfigGroup, KConfigBase* pConfig, bool bClearUnset )
00606 {
00607 kdDebug(125) << "KKeyChooser::syncToConfig( \"" << sConfigGroup << "\", " << pConfig << " ) start" << endl;
00608 if( !pConfig )
00609 pConfig = KGlobal::config();
00610 KConfigGroupSaver cgs( pConfig, sConfigGroup );
00611
00612 QListViewItemIterator it( d->pList );
00613 for( ; it.current(); ++it ) {
00614 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
00615 if( pItem ) {
00616 QString sEntry = pConfig->readEntry( pItem->actionName() );
00617 if( !sEntry.isNull() || bClearUnset ) {
00618 if( sEntry == "none" )
00619 sEntry = QString::null;
00620 pItem->setShortcut( sEntry );
00621 }
00622 kdDebug(125) << pItem->actionName() << " = " << pItem->shortcut().toStringInternal() << endl;
00623 }
00624 }
00625 updateButtons();
00626 kdDebug(125) << "KKeyChooser::syncToConfig() done" << endl;
00627 }
00628
00629 void KKeyChooser::setShortcut( const KShortcut& cut )
00630 {
00631 kdDebug(125) << "KKeyChooser::setShortcut( " << cut.toString() << " )" << endl;
00632 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
00633 if( !pItem )
00634 return;
00635
00636 for( uint i = 0; i < cut.count(); i++ ) {
00637 const KKeySequence& seq = cut.seq(i);
00638 const KKey& key = seq.key(0);
00639
00640 if( !d->bAllowWinKey && (key.modFlags() & KKey::WIN) ) {
00641 QString s = i18n("The Win key is not allowed in this context.");
00642 KMessageBox::sorry( this, s, i18n("Invalid Shortcut Key") );
00643 return;
00644 }
00645 if( !d->bAllowLetterShortcuts && key.modFlags() == 0
00646 && key.sym() < 0x3000 && QChar(key.sym()).isLetterOrNumber() ) {
00647 QString s = i18n( "In order to use the '%1' key as a shortcut, "
00648 "it must be combined with the "
00649 "Win, Alt, Ctrl, and/or Shift keys." ).arg(QChar(key.sym()));
00650 KMessageBox::sorry( this, s, i18n("Invalid Shortcut Key") );
00651 return;
00652 }
00653 }
00654
00655
00656 if( !isKeyPresent( cut ) ) {
00657
00658 pItem->setShortcut( cut );
00659
00660 updateButtons();
00661 emit keyChange();
00662 }
00663 }
00664
00665
00666
00667 static int keyConflict( const KShortcut& cut, const KShortcut& cut2 )
00668 {
00669 for( uint iSeq = 0; iSeq < cut.count(); iSeq++ ) {
00670 for( uint iSeq2 = 0; iSeq2 <= iSeq && iSeq2 < cut2.count(); iSeq2++ ) {
00671 if( cut.seq(iSeq) == cut2.seq(iSeq2) )
00672 return iSeq;
00673 }
00674 }
00675 return -1;
00676 }
00677
00678 bool KKeyChooser::isKeyPresent( const KShortcut& cut, bool bWarnUser )
00679 {
00680 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
00681
00682
00683 if( m_type == ApplicationGlobal || m_type == Global ) {
00684
00685 for( uint i = 0; i < cut.count(); i++ ) {
00686 const KKeySequence& seq = cut.seq(i);
00687
00688 KStdAccel::StdAccel id = KStdAccel::findStdAccel( seq );
00689 if( id != KStdAccel::AccelNone
00690 && keyConflict( cut, KStdAccel::shortcut( id ) ) > -1 ) {
00691 if( bWarnUser )
00692 _warning( seq, KStdAccel::label(id), i18n("Conflict with Standard Application Shortcut") );
00693 return true;
00694 }
00695 }
00696 }
00697
00698 QMap<QString, KShortcut>::ConstIterator it;
00699 for( it = d->mapGlobals.begin(); it != d->mapGlobals.end(); ++it ) {
00700 int iSeq = keyConflict( cut, (*it) );
00701 if( iSeq > -1 ) {
00702 if( m_type != Global || it.key() != pItem->actionName() ) {
00703 if( bWarnUser )
00704 _warning( cut.seq(iSeq), it.key(), i18n("Conflict with Global Shortcuts") );
00705 return true;
00706 }
00707 }
00708 }
00709
00710 if( isKeyPresentLocally( cut, pItem, bWarnUser ? i18n("Key Conflict") : QString::null ))
00711 return true;
00712
00713
00714 if( m_type == Global && globalChoosers != NULL ) {
00715 for( QValueList< KKeyChooser* >::ConstIterator it = globalChoosers->begin();
00716 it != globalChoosers->end();
00717 ++it ) {
00718 if( (*it) != this && (*it)->isKeyPresentLocally( cut, NULL,
00719 bWarnUser ? i18n("Key Conflict") : QString::null))
00720 return true;
00721 }
00722 }
00723 return false;
00724 }
00725
00726 bool KKeyChooser::isKeyPresentLocally( const KShortcut& cut, KKeyChooserItem* ignoreItem, const QString& warnText )
00727 {
00728
00729
00730 for( QListViewItemIterator it( d->pList ); it.current(); ++it ) {
00731 KKeyChooserItem* pItem2 = dynamic_cast<KKeyChooserItem*>(it.current());
00732 if( pItem2 && pItem2 != ignoreItem ) {
00733 int iSeq = keyConflict( cut, pItem2->shortcut() );
00734 if( iSeq > -1 ) {
00735 if( !warnText.isNull() )
00736 _warning( cut.seq(iSeq), pItem2->text(0), warnText );
00737 return true;
00738 }
00739 }
00740 }
00741 return false;
00742 }
00743
00744 void KKeyChooser::_warning( const KKeySequence& cut, QString sAction, QString sTitle )
00745 {
00746 sAction = sAction.stripWhiteSpace();
00747
00748 QString s =
00749 i18n("The '%1' key combination has already been allocated "
00750 "to the \"%2\" action.\n"
00751 "Please choose a unique key combination.").
00752 arg(cut.toString()).arg(sAction);
00753
00754 KMessageBox::sorry( this, s, sTitle );
00755 }
00756
00757
00758 KKeyChooserItem::KKeyChooserItem( KListView* parent, QListViewItem* after, KShortcutList* pList, uint iAction )
00759 : KListViewItem( parent, after )
00760 {
00761 m_pList = pList;
00762 m_iAction = iAction;
00763 m_bModified = false;
00764 m_cut = m_pList->shortcut(m_iAction);
00765 }
00766
00767 KKeyChooserItem::KKeyChooserItem( QListViewItem* parent, QListViewItem* after, KShortcutList* pList, uint iAction )
00768 : KListViewItem( parent, after )
00769 {
00770 m_pList = pList;
00771 m_iAction = iAction;
00772 m_bModified = false;
00773 m_cut = m_pList->shortcut(m_iAction);
00774 }
00775
00776 QString KKeyChooserItem::actionName() const
00777 {
00778 return m_pList->name(m_iAction);
00779 }
00780
00781 const KShortcut& KKeyChooserItem::shortcut() const
00782 {
00783 return m_cut;
00784 }
00785
00786 void KKeyChooserItem::setShortcut( const KShortcut& cut )
00787 {
00788 m_cut = cut;
00789 m_bModified = (m_cut != m_pList->shortcut(m_iAction));
00790 listView()->repaintItem( this );
00791 }
00792
00793 void KKeyChooserItem::commitChanges()
00794 {
00795 if( m_bModified )
00796 m_pList->setShortcut( m_iAction, m_cut );
00797 }
00798
00799 QString KKeyChooserItem::text( int iCol ) const
00800 {
00801 if( iCol == 0 ) {
00802
00803 QString s = m_pList->label(m_iAction);
00804 QString s2;
00805 for( uint i = 0; i < s.length(); i++ )
00806 if( s[i] != '&' || ( i+1<s.length() && s[i+1] == '&' ) )
00807 s2 += s[i];
00808 return s2;
00809 }
00810 else if( iCol <= (int) m_cut.count() )
00811 return m_cut.seq(iCol-1).toString();
00812 else
00813 return QString::null;
00814 }
00815
00816 int KKeyChooserItem::compare( QListViewItem* item, int iCol, bool bAscending ) const
00817 {
00818 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( item );
00819 if( iCol == 0 && pItem ) {
00820 QString psName1 = m_pList->name(m_iAction);
00821 QString psName2 = pItem->m_pList->name(pItem->m_iAction);
00822 QRegExp rxNumber1( " (\\d+)$" );
00823 QRegExp rxNumber2( " (\\d+)$" );
00824 int iNumber1 = rxNumber1.search( psName1 );
00825 int iNumber2 = rxNumber2.search( psName2 );
00826
00827
00828 if( iNumber1 >= 0 && iNumber1 == iNumber2 && psName1.startsWith( psName2.left( iNumber1+1 ) ) ) {
00829 int n1 = rxNumber1.cap(1).toInt();
00830 int n2 = rxNumber2.cap(1).toInt();
00831 return (n1 < n2) ? -1 : (n1 > n2) ? 1 : 0;
00832 }
00833 }
00834
00835 return QListViewItem::compare( item, iCol, bAscending );
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 KKeyDialog::KKeyDialog( KKeyChooser::ActionType type, bool bAllowLetterShortcuts, QWidget *parent, const char* name )
00850 : KDialogBase( parent, name, true, i18n("Configure Shortcuts"), Help|Default|Ok|Cancel, Ok )
00851 {
00852 m_pKeyChooser = new KKeyChooser( this, type, bAllowLetterShortcuts );
00853 setMainWidget( m_pKeyChooser );
00854 connect( this, SIGNAL(defaultClicked()), m_pKeyChooser, SLOT(allDefault()) );
00855 enableButton( Help, false );
00856
00857 KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
00858 QSize sz = size();
00859 resize( group.readSizeEntry( "Dialog Size", &sz ) );
00860 }
00861
00862 KKeyDialog::KKeyDialog( bool bAllowLetterShortcuts, QWidget *parent, const char* name )
00863 : KDialogBase( parent, name, true, i18n("Configure Shortcuts"), Help|Default|Ok|Cancel, Ok )
00864 {
00865 m_pKeyChooser = new KKeyChooser( this, KKeyChooser::Application, bAllowLetterShortcuts );
00866 setMainWidget( m_pKeyChooser );
00867 connect( this, SIGNAL(defaultClicked()), m_pKeyChooser, SLOT(allDefault()) );
00868 enableButton( Help, false );
00869
00870 KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
00871 QSize sz = size();
00872 resize( group.readSizeEntry( "Dialog Size", &sz ) );
00873 }
00874
00875 KKeyDialog::~KKeyDialog()
00876 {
00877 KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
00878 group.writeEntry( "Dialog Size", size(), true, true );
00879 }
00880
00881 bool KKeyDialog::insert( KActionCollection* pColl )
00882 {
00883 return m_pKeyChooser->insert( pColl );
00884 }
00885
00886 bool KKeyDialog::insert(KActionCollection *pColl, const QString &title)
00887 {
00888 return m_pKeyChooser->insert(pColl, title);
00889 }
00890
00891 bool KKeyDialog::configure( bool bSaveSettings )
00892 {
00893 int retcode = exec();
00894 if( retcode == Accepted ) {
00895 if( bSaveSettings )
00896 m_pKeyChooser->save();
00897 else
00898 commitChanges();
00899 }
00900 return retcode;
00901 }
00902
00903 void KKeyDialog::commitChanges()
00904 {
00905 m_pKeyChooser->commitChanges();
00906 }
00907
00908 int KKeyDialog::configure( KActionCollection* coll, QWidget* parent, bool bSaveSettings )
00909 {
00910 return configure( coll, true, parent, bSaveSettings);
00911 }
00912
00913 int KKeyDialog::configure( KAccel* keys, QWidget* parent, bool bSaveSettings )
00914 {
00915 return configure( keys, true, parent, bSaveSettings);
00916 }
00917
00918 int KKeyDialog::configure( KGlobalAccel* keys, QWidget* parent, bool bSaveSettings )
00919 {
00920 return configure( keys, true, parent, bSaveSettings);
00921 }
00922
00923 int KKeyDialog::configure( KAccel* keys, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
00924 {
00925 KKeyDialog dlg( bAllowLetterShortcuts, parent );
00926 dlg.m_pKeyChooser->insert( keys );
00927 bool b = dlg.configure( bSaveSettings );
00928 if( b && bSaveSettings )
00929 keys->updateConnections();
00930 return b;
00931 }
00932
00933 int KKeyDialog::configure( KGlobalAccel* keys, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
00934 {
00935 KKeyDialog dlg( KKeyChooser::ApplicationGlobal, bAllowLetterShortcuts, parent );
00936 dlg.m_pKeyChooser->insert( keys );
00937 bool b = dlg.configure( bSaveSettings );
00938 if( b && bSaveSettings )
00939 keys->updateConnections();
00940 return b;
00941 }
00942
00943 int KKeyDialog::configure( KActionCollection* coll, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
00944 {
00945 kdDebug(125) << "KKeyDialog::configureKeys( KActionCollection*, " << bSaveSettings << " )" << endl;
00946 KKeyDialog dlg( bAllowLetterShortcuts, parent );
00947 dlg.m_pKeyChooser->insert( coll );
00948 return dlg.configure( bSaveSettings );
00949 }
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 void KKeyChooser::virtual_hook( int, void* )
00965 { }
00966
00967 void KKeyDialog::virtual_hook( int id, void* data )
00968 { KDialogBase::virtual_hook( id, data ); }
00969
00970 #include "kkeydialog.moc"