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 <qtoolbutton.h>
00036
#include <qwhatsthis.h>
00037
00038
#include <kaccel.h>
00039
#include <kaction.h>
00040
#include <kaccelaction.h>
00041
#include <kactionshortcutlist.h>
00042
#include <kapplication.h>
00043
#include <kconfig.h>
00044
#include <kdebug.h>
00045
#include <kglobal.h>
00046
#include <kglobalaccel.h>
00047
#include <kiconloader.h>
00048
#include <klistviewsearchline.h>
00049
#include <klocale.h>
00050
#include <kmessagebox.h>
00051
#include <kshortcut.h>
00052
#include <kshortcutlist.h>
00053
#include <kxmlguifactory.h>
00054
#include <kaboutdata.h>
00055
#include <kstaticdeleter.h>
00056
00057
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00058
#define XK_XKB_KEYS
00059
#define XK_MISCELLANY
00060
#include <X11/Xlib.h>
00061
#include <X11/keysymdef.h>
00062
00063
#ifdef KeyPress
00064
const int XFocusOut = FocusOut;
00065
const int XFocusIn = FocusIn;
00066
const int XKeyPress = KeyPress;
00067
const int XKeyRelease = KeyRelease;
00068
#undef KeyRelease
00069
#undef KeyPress
00070
#undef FocusOut
00071
#undef FocusIn
00072
#endif // KEYPRESS
00073
#endif // Q_WX_X11 && ! K_WS_QTONLY
00074
00075
00076
00077
00078
00079
class KKeyChooserItem :
public KListViewItem
00080 {
00081
public:
00082 KKeyChooserItem(
KListView* parent,
QListViewItem* after,
KShortcutList* pList, uint iAction );
00083 KKeyChooserItem(
QListViewItem* parent,
QListViewItem* after,
KShortcutList* pList, uint iAction );
00084
00085
QString actionName() const;
00086 const
KShortcut& shortcut() const;
00087
bool isConfigurable()
const
00088
{
return m_pList->isConfigurable( m_iAction ); }
00089
const KShortcut&
shortcutDefault()
const
00090
{
return m_pList->shortcutDefault( m_iAction ); }
00091
00092
void setShortcut(
const KShortcut& cut );
00093
void commitChanges();
00094
00095
virtual QString text(
int iCol )
const;
00096
virtual int compare(
QListViewItem*,
int iCol,
bool bAscending )
const;
00097
00098
protected:
00099
KShortcutList* m_pList;
00100 uint m_iAction;
00101
bool m_bModified;
00102
KShortcut m_cut;
00103 };
00104
00105
00106
00107
00108
00109
class KKeyChooserPrivate
00110 {
00111
public:
00112
QValueList<KShortcutList*> rgpLists;
00113
QValueList<KShortcutList*> rgpListsAllocated;
00114
00115
KListView *pList;
00116
QLabel *lInfo;
00117
KKeyButton *pbtnShortcut;
00118
QGroupBox *fCArea;
00119
QButtonGroup *kbGroup;
00120
00121
QMap<QString, KShortcut> mapGlobals;
00122
00123
00124
00125
00126
00127
bool bAllowLetterShortcuts;
00128
00129
00130
bool bPreferFourModifierKeys;
00131 };
00132
00133
00134
00135
00136
00137 KKeyChooser::KKeyChooser(
QWidget* parent, ActionType type,
bool bAllowLetterShortcuts )
00138 :
QWidget( parent )
00139 {
00140 initGUI( type, bAllowLetterShortcuts );
00141 }
00142
00143 KKeyChooser::KKeyChooser(
KActionCollection* coll,
QWidget* parent,
bool bAllowLetterShortcuts )
00144 :
QWidget( parent )
00145 {
00146 initGUI( Application, bAllowLetterShortcuts );
00147
insert( coll );
00148 }
00149
00150
KKeyChooser::KKeyChooser(
KAccel* pAccel,
QWidget* parent,
bool bAllowLetterShortcuts )
00151 :
QWidget( parent )
00152 {
00153 initGUI( Application, bAllowLetterShortcuts );
00154
insert( pAccel );
00155 }
00156
00157
KKeyChooser::KKeyChooser(
KGlobalAccel* pAccel,
QWidget* parent )
00158 :
QWidget( parent )
00159 {
00160 initGUI( ApplicationGlobal,
false );
00161
insert( pAccel );
00162 }
00163
00164
KKeyChooser::KKeyChooser(
KShortcutList* pList,
QWidget* parent, ActionType type,
bool bAllowLetterShortcuts )
00165 :
QWidget( parent )
00166 {
00167 initGUI( type, bAllowLetterShortcuts );
00168
insert( pList );
00169 }
00170
00171 KKeyChooser::KKeyChooser(
KAccel* actions,
QWidget* parent,
00172
bool bCheckAgainstStdKeys,
00173
bool bAllowLetterShortcuts,
00174
bool bAllowWinKey )
00175 :
QWidget( parent )
00176 {
00177 ActionType type;
00178
if( bAllowWinKey )
00179 type = (bCheckAgainstStdKeys) ? ApplicationGlobal : Global;
00180
else
00181 type = Application;
00182
00183 initGUI( type, bAllowLetterShortcuts );
00184
insert( actions );
00185 }
00186
00187 KKeyChooser::KKeyChooser(
KGlobalAccel* actions,
QWidget* parent,
00188
bool bCheckAgainstStdKeys,
00189
bool bAllowLetterShortcuts,
00190
bool )
00191 :
QWidget( parent )
00192 {
00193 ActionType type = (bCheckAgainstStdKeys) ? ApplicationGlobal : Global;
00194
00195 initGUI( type, bAllowLetterShortcuts );
00196
insert( actions );
00197 }
00198
00199
00200
00201
00202
00203
00204
static QValueList< KKeyChooser* >* allChoosers = NULL;
00205
static KStaticDeleter< QValueList< KKeyChooser* > > allChoosersDeleter;
00206
00207 KKeyChooser::~KKeyChooser()
00208 {
00209 allChoosers->remove(
this );
00210
00211
for( uint i = 0; i < d->rgpListsAllocated.count(); i++ )
00212
delete d->rgpListsAllocated[i];
00213
delete d;
00214 }
00215
00216 bool KKeyChooser::insert(
KActionCollection *pColl)
00217 {
00218
return insert(pColl, QString::null);
00219 }
00220
00221 bool KKeyChooser::insert(
KActionCollection* pColl,
const QString &title )
00222 {
00223
QString str = title;
00224
if ( title.isEmpty() && pColl->
instance()
00225 && pColl->
instance()->
aboutData() )
00226 str = pColl->
instance()->
aboutData()->
programName();
00227
00228
KShortcutList* pList =
new KActionShortcutList( pColl );
00229 d->rgpListsAllocated.append( pList );
00230 d->rgpLists.append( pList );
00231
buildListView(d->rgpLists.count() - 1, str);
00232
return true;
00233 }
00234
00235
bool KKeyChooser::insert(
KAccel* pAccel )
00236 {
00237
KShortcutList* pList =
new KAccelShortcutList( pAccel );
00238 d->rgpListsAllocated.append( pList );
00239
return insert( pList );
00240 }
00241
00242
bool KKeyChooser::insert(
KGlobalAccel* pAccel )
00243 {
00244
KShortcutList* pList =
new KAccelShortcutList( pAccel );
00245 d->rgpListsAllocated.append( pList );
00246
return insert( pList );
00247 }
00248
00249
bool KKeyChooser::insert(
KShortcutList* pList )
00250 {
00251 d->rgpLists.append( pList );
00252
buildListView( d->rgpLists.count() - 1, QString::null );
00253
return true;
00254 }
00255
00256 void KKeyChooser::commitChanges()
00257 {
00258
kdDebug(125) <<
"KKeyChooser::commitChanges()" <<
endl;
00259
00260
QListViewItemIterator it( d->pList );
00261
for( ; it.current(); ++it ) {
00262 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
00263
if( pItem )
00264 pItem->commitChanges();
00265 }
00266 }
00267
00268 void KKeyChooser::save()
00269 {
00270
commitChanges();
00271
for( uint i = 0; i < d->rgpLists.count(); i++ )
00272 d->rgpLists[i]->save();
00273 }
00274
00275
void KKeyChooser::initGUI( ActionType type,
bool bAllowLetterShortcuts )
00276 {
00277 d =
new KKeyChooserPrivate();
00278
00279 m_type = type;
00280 d->bAllowLetterShortcuts = bAllowLetterShortcuts;
00281
00282 d->bPreferFourModifierKeys =
KGlobalAccel::useFourModifierKeys();
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
QBoxLayout *topLayout =
new QVBoxLayout(
this, 0, KDialog::spacingHint() );
00296
00297
00298
00299
00300
QHBoxLayout* searchLayout =
new QHBoxLayout(0, 0, KDialog::spacingHint());
00301 topLayout->addLayout(searchLayout, 10);
00302
00303
QToolButton *clearSearch =
new QToolButton(
this);
00304 clearSearch->setTextLabel(i18n(
"Clear Search"),
true);
00305 clearSearch->setIconSet(SmallIconSet(
"locationbar_erase"));
00306 searchLayout->addWidget(clearSearch);
00307
QLabel* slbl =
new QLabel(i18n(
"&Search:"),
this);
00308 searchLayout->addWidget(slbl);
00309
KListViewSearchLine* listViewSearch =
new KListViewSearchLine(
this);
00310 searchLayout->addWidget(listViewSearch);
00311 slbl->setBuddy(listViewSearch);
00312 connect(clearSearch, SIGNAL(pressed()), listViewSearch, SLOT(clear()));
00313
00314
QString wtstr = i18n(
"Search interactively for shortcut names (e.g. Copy) "
00315
"or combination of keys (e.g. Ctrl+C) by typing them here.");
00316
00317 QWhatsThis::add(slbl, wtstr);
00318 QWhatsThis::add(listViewSearch, wtstr);
00319
00320
00321
00322
00323
00324
00325
QGridLayout *stackLayout =
new QGridLayout(2, 2, 2);
00326 topLayout->addLayout( stackLayout, 10 );
00327 stackLayout->setRowStretch( 1, 10 );
00328
00329 d->pList =
new KListView(
this );
00330 d->pList->setFocus();
00331 listViewSearch->
setListView(d->pList);
00332
QValueList<int> columns;
00333 columns.append(0);
00334 listViewSearch->
setSearchColumns(columns);
00335
00336 stackLayout->addMultiCellWidget( d->pList, 1, 1, 0, 1 );
00337
00338 wtstr = i18n(
"Here you can see a list of key bindings, "
00339
"i.e. associations between actions (e.g. 'Copy') "
00340
"shown in the left column and keys or combination "
00341
"of keys (e.g. Ctrl+V) shown in the right column.");
00342
00343 QWhatsThis::add( d->pList, wtstr );
00344
00345 d->pList->setAllColumnsShowFocus(
true );
00346 d->pList->addColumn(i18n(
"Action"));
00347 d->pList->addColumn(i18n(
"Shortcut"));
00348 d->pList->addColumn(i18n(
"Alternate"));
00349
00350 connect( d->pList, SIGNAL(currentChanged(
QListViewItem*)),
00351 SLOT(slotListItemSelected(
QListViewItem*)) );
00352
00353
00354 connect ( d->pList, SIGNAL ( doubleClicked (
QListViewItem *,
const QPoint &,
int ) ),
00355 SLOT ( captureCurrentItem()) );
00356 connect ( d->pList, SIGNAL ( spacePressed( QListViewItem* )), SLOT( captureCurrentItem()));
00357
00358
00359
00360 d->fCArea =
new QGroupBox(
this );
00361 topLayout->
addWidget( d->fCArea, 1 );
00362
00363 d->fCArea->setTitle( i18n(
"Shortcut for Selected Action") );
00364 d->fCArea->setFrameStyle( QFrame::Box | QFrame::Sunken );
00365
00366
00367
00368
00369
QGridLayout *grid =
new QGridLayout( d->fCArea, 3, 4, KDialog::spacingHint() );
00370 grid->addRowSpacing( 0, fontMetrics().lineSpacing() );
00371
00372 d->kbGroup =
new QButtonGroup( d->fCArea );
00373 d->kbGroup->hide();
00374 d->kbGroup->setExclusive(
true );
00375
00376 m_prbNone =
new QRadioButton( i18n(
"no key",
"&None"), d->fCArea );
00377 d->kbGroup->insert( m_prbNone, NoKey );
00378 m_prbNone->setEnabled(
false );
00379
00380 grid->addWidget( m_prbNone, 1, 0 );
00381 QWhatsThis::add( m_prbNone, i18n(
"The selected action will not be associated with any key.") );
00382 connect( m_prbNone, SIGNAL(clicked()), SLOT(slotNoKey()) );
00383
00384 m_prbDef =
new QRadioButton( i18n(
"default key",
"De&fault"), d->fCArea );
00385 d->kbGroup->insert( m_prbDef, DefaultKey );
00386 m_prbDef->setEnabled(
false );
00387
00388 grid->addWidget( m_prbDef, 1, 1 );
00389 QWhatsThis::add( m_prbDef, i18n(
"This will bind the default key to the selected action. Usually a reasonable choice.") );
00390 connect( m_prbDef, SIGNAL(clicked()), SLOT(slotDefaultKey()) );
00391
00392 m_prbCustom =
new QRadioButton( i18n(
"C&ustom"), d->fCArea );
00393 d->kbGroup->insert( m_prbCustom, CustomKey );
00394 m_prbCustom->setEnabled(
false );
00395
00396 grid->addWidget( m_prbCustom, 1, 2 );
00397 QWhatsThis::add( m_prbCustom, i18n(
"If this option is selected you can create a customized key binding for the"
00398
" selected action using the buttons below.") );
00399 connect( m_prbCustom, SIGNAL(clicked()), SLOT(slotCustomKey()) );
00400
00401
00402
00403
QBoxLayout *pushLayout =
new QHBoxLayout( KDialog::spacingHint() );
00404 grid->addLayout( pushLayout, 1, 3 );
00405
00406 d->pbtnShortcut =
new KKeyButton(d->fCArea,
"key");
00407 d->pbtnShortcut->setEnabled(
false );
00408 connect( d->pbtnShortcut, SIGNAL(capturedShortcut(
const KShortcut&)), SLOT(capturedShortcut(
const KShortcut&)) );
00409 grid->addRowSpacing( 1, d->pbtnShortcut->sizeHint().height() + 5 );
00410
00411 wtstr = i18n(
"Use this button to choose a new shortcut key. Once you click it, "
00412
"you can press the key-combination which you would like to be assigned "
00413
"to the currently selected action.");
00414 QWhatsThis::add( d->pbtnShortcut, wtstr );
00415
00416
00417
00418
00419 pushLayout->addSpacing( KDialog::spacingHint()*2 );
00420 pushLayout->
addWidget( d->pbtnShortcut );
00421 pushLayout->addStretch( 10 );
00422
00423 d->lInfo =
new QLabel(d->fCArea);
00424
00425
00426
00427
00428 grid->addMultiCellWidget( d->lInfo, 2, 2, 0, 3 );
00429
00430
00431
00432 readGlobalKeys();
00433
00434
00435
00436
00437 connect( kapp, SIGNAL( settingsChanged(
int )), SLOT( slotSettingsChanged(
int )));
00438
if( allChoosers == NULL )
00439 allChoosers = allChoosersDeleter.setObject( allChoosers,
new QValueList< KKeyChooser* > );
00440 allChoosers->append(
this );
00441 }
00442
00443
00444 void KKeyChooser::buildListView( uint iList,
const QString &title )
00445 {
00446
KShortcutList* pList = d->rgpLists[iList];
00447 KActionShortcutList *pAList = dynamic_cast<KActionShortcutList*>(pList);
00448
00449
if( m_type == Global || m_type == ApplicationGlobal )
00450 d->pList->setSorting( -1 );
00451
KListViewItem *pProgramItem, *pGroupItem = 0, *pParentItem, *pItem;
00452
00453
QString str = (title.isEmpty() ? i18n(
"Shortcuts") : title);
00454 pParentItem = pProgramItem = pItem =
new KListViewItem( d->pList, str );
00455 pParentItem->setExpandable(
true );
00456 pParentItem->setOpen(
true );
00457 pParentItem->setSelectable(
false );
00458 uint nSize = pList->
count();
00459
for( uint iAction = 0; iAction < nSize; iAction++ ) {
00460
QString sName = pList->
name(iAction);
00461
kdDebug(125) <<
"Key: " << sName <<
endl;
00462
if( sName.startsWith(
"Program:" ) ) {
00463 pItem =
new KListViewItem( d->pList, pProgramItem, pList->
label(iAction) );
00464 pItem->setSelectable(
false );
00465 pItem->setExpandable(
true );
00466 pItem->setOpen(
true );
00467
if( !pProgramItem->firstChild() )
00468
delete pProgramItem;
00469 pProgramItem = pParentItem = pItem;
00470 }
else if( sName.startsWith(
"Group:" ) ) {
00471 pItem =
new KListViewItem( pProgramItem, pParentItem, pList->
label(iAction) );
00472 pItem->setSelectable(
false );
00473 pItem->setExpandable(
true );
00474 pItem->setOpen(
true );
00475
if( pGroupItem && !pGroupItem->firstChild() )
00476
delete pGroupItem;
00477 pGroupItem = pParentItem = pItem;
00478 }
else if( !sName.isEmpty() && pList->
isConfigurable(iAction) ) {
00479 pItem =
new KKeyChooserItem( pParentItem, pItem, pList, iAction );
00480
if(pAList)
00481 pItem->setPixmap(0,pAList->action(iAction)->iconSet().pixmap(QIconSet::Small,QIconSet::Normal));
00482 }
00483 }
00484
if( !pProgramItem->firstChild() )
00485
delete pProgramItem;
00486
if( pGroupItem && !pGroupItem->firstChild() )
00487
delete pGroupItem;
00488 }
00489
00490
00491
void KKeyChooser::updateButtons()
00492 {
00493
00494
00495
00496
00497 releaseKeyboard();
00498 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
00499
00500
if ( !pItem ) {
00501
00502 m_prbNone->setEnabled(
false );
00503 m_prbDef->setEnabled(
false );
00504 m_prbCustom->setEnabled(
false );
00505 d->pbtnShortcut->setEnabled(
false );
00506 d->pbtnShortcut->setShortcut(
KShortcut(),
false );
00507 }
else {
00508
bool bConfigurable = pItem->isConfigurable();
00509
bool bQtShortcut = (m_type == Application || m_type == Standard);
00510
const KShortcut& cutDef = pItem->shortcutDefault();
00511
00512
00513
QString keyStrCfg = pItem->shortcut().toString();
00514
QString keyStrDef = cutDef.
toString();
00515
00516 d->pbtnShortcut->setShortcut( pItem->shortcut(), bQtShortcut );
00517
00518 pItem->repaint();
00519 d->lInfo->setText( i18n(
"Default key:") +
QString(
" %1").arg(keyStrDef.isEmpty() ? i18n(
"None") : keyStrDef) );
00520
00521
00522
int index = (pItem->shortcut().isNull()) ? NoKey
00523 : (pItem->shortcut() == cutDef) ? DefaultKey
00524 : CustomKey;
00525 m_prbNone->setChecked( index == NoKey );
00526 m_prbDef->setChecked( index == DefaultKey );
00527 m_prbCustom->setChecked( index == CustomKey );
00528
00529
00530
00531 m_prbNone->setEnabled( bConfigurable );
00532 m_prbDef->setEnabled( bConfigurable && cutDef.
count() != 0 );
00533 m_prbCustom->setEnabled( bConfigurable );
00534 d->pbtnShortcut->setEnabled( bConfigurable );
00535 }
00536 }
00537
00538
void KKeyChooser::slotNoKey()
00539 {
00540
00541 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
00542
if( pItem ) {
00543
00544 pItem->setShortcut(
KShortcut() );
00545 updateButtons();
00546 emit
keyChange();
00547 }
00548 }
00549
00550
void KKeyChooser::slotDefaultKey()
00551 {
00552
00553 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
00554
if( pItem )
00555 setShortcut( pItem->shortcutDefault() );
00556 }
00557
00558
void KKeyChooser::slotCustomKey()
00559 {
00560 d->pbtnShortcut->captureShortcut();
00561 }
00562
00563
void KKeyChooser::readGlobalKeys()
00564 {
00565 d->mapGlobals.clear();
00566
if( m_type == Global )
00567
return;
00568 readGlobalKeys( d->mapGlobals );
00569 }
00570
00571
void KKeyChooser::readGlobalKeys(
QMap< QString, KShortcut >& map )
00572 {
00573
QMap<QString, QString> mapEntry =
KGlobal::config()->
entryMap(
"Global Shortcuts" );
00574
QMap<QString, QString>::Iterator it( mapEntry.begin() );
00575
for( uint i = 0; it != mapEntry.end(); ++it, i++ )
00576 map[it.key()] =
KShortcut(*it);
00577 }
00578
00579
void KKeyChooser::slotSettingsChanged(
int category )
00580 {
00581
if( category == KApplication::SETTINGS_SHORTCUTS )
00582 readGlobalKeys();
00583 }
00584
00585
void KKeyChooser::fontChange(
const QFont & )
00586 {
00587 d->fCArea->setMinimumHeight( 4*d->pbtnShortcut->sizeHint().height() );
00588
00589
int widget_width = 0;
00590
00591 setMinimumWidth( 20+5*(widget_width+10) );
00592 }
00593
00594
00595
00596
00597
00598 void KKeyChooser::allDefault()
00599 {
00600
kdDebug(125) <<
"KKeyChooser::allDefault()" <<
endl;
00601
00602
QListViewItemIterator it( d->pList );
00603
for( ; it.current(); ++it ) {
00604 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
00605
if( pItem )
00606 pItem->setShortcut( pItem->shortcutDefault() );
00607 }
00608
00609 updateButtons();
00610 emit
keyChange();
00611 }
00612
00613
void KKeyChooser::slotListItemSelected( QListViewItem* )
00614 {
00615 updateButtons();
00616 }
00617
00618
void KKeyChooser::slotListItemDoubleClicked ( QListViewItem *,
const QPoint & ,
int )
00619 {
00620 captureCurrentItem();
00621 }
00622
00623
void KKeyChooser::captureCurrentItem()
00624 {
00625 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
00626
if( pItem != NULL && pItem->isConfigurable())
00627 d->pbtnShortcut->captureShortcut ( );
00628 }
00629
00630 void KKeyChooser::setPreferFourModifierKeys(
bool bPreferFourModifierKeys )
00631 {
00632 d->bPreferFourModifierKeys = bPreferFourModifierKeys;
00633 }
00634
00635
void KKeyChooser::capturedShortcut(
const KShortcut& cut )
00636 {
00637
if( cut.
isNull() )
00638 slotNoKey();
00639
else
00640 setShortcut( cut );
00641 }
00642
00643
00644
00645 void KKeyChooser::listSync()
00646 {
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 }
00660
00661
void KKeyChooser::syncToConfig(
const QString& sConfigGroup,
KConfigBase* pConfig,
bool bClearUnset )
00662 {
00663
kdDebug(125) <<
"KKeyChooser::syncToConfig( \"" << sConfigGroup <<
"\", " << pConfig <<
" ) start" <<
endl;
00664
if( !pConfig )
00665 pConfig =
KGlobal::config();
00666
KConfigGroupSaver cgs( pConfig, sConfigGroup );
00667
00668
QListViewItemIterator it( d->pList );
00669
for( ; it.current(); ++it ) {
00670 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
00671
if( pItem ) {
00672
QString sEntry = pConfig->
readEntry( pItem->actionName() );
00673
if( !sEntry.isNull() || bClearUnset ) {
00674
if( sEntry ==
"none" )
00675 sEntry = QString::null;
00676 pItem->setShortcut( sEntry );
00677 }
00678
kdDebug(125) << pItem->actionName() <<
" = " << pItem->shortcut().toStringInternal() <<
endl;
00679 }
00680 }
00681 updateButtons();
00682
kdDebug(125) <<
"KKeyChooser::syncToConfig() done" <<
endl;
00683 }
00684
00685
void KKeyChooser::setShortcut(
const KShortcut& cut )
00686 {
00687
kdDebug(125) <<
"KKeyChooser::setShortcut( " <<
cut.
toString() <<
" )" <<
endl;
00688 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
00689
if( !pItem )
00690
return;
00691
00692
for( uint i = 0; i <
cut.
count(); i++ ) {
00693
const KKeySequence& seq =
cut.
seq(i);
00694
const KKey&
key = seq.
key(0);
00695
00696
if( !d->bAllowLetterShortcuts &&
key.modFlags() == 0
00697 &&
key.sym() < 0x3000 &&
QChar(
key.sym()).isLetterOrNumber() ) {
00698
QString s = i18n(
"In order to use the '%1' key as a shortcut, "
00699
"it must be combined with the "
00700
"Win, Alt, Ctrl, and/or Shift keys." ).arg(
QChar(
key.sym()));
00701
KMessageBox::sorry(
this, s, i18n(
"Invalid Shortcut Key") );
00702
return;
00703 }
00704 }
00705
00706
00707
if( !isKeyPresent( cut ) ) {
00708
00709 pItem->setShortcut( cut );
00710
00711 updateButtons();
00712 emit
keyChange();
00713 }
00714 }
00715
00716
00717
00718
static int keyConflict(
const KShortcut& cut,
const KShortcut& cut2 )
00719 {
00720
for( uint iSeq = 0; iSeq <
cut.
count(); iSeq++ ) {
00721
for( uint iSeq2 = 0; iSeq2 < cut2.
count(); iSeq2++ ) {
00722
if(
cut.
seq(iSeq) == cut2.
seq(iSeq2) )
00723
return iSeq;
00724 }
00725 }
00726
return -1;
00727 }
00728
00729
00730
static void removeFromShortcut(
KShortcut & cut1,
const KShortcut &cut2)
00731 {
00732
for( uint iSeq2 = 0; iSeq2 < cut2.
count(); iSeq2++ )
00733 cut1.
remove(cut2.
seq(iSeq2));
00734 }
00735
00736
bool KKeyChooser::isKeyPresent(
const KShortcut& cut,
bool bWarnUser )
00737 {
00738 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
00739
00740
if (!pItem) {
00741
return false;
00742 }
00743
00744
bool has_global_chooser =
false;
00745
bool has_standard_chooser =
false;
00746
for(
QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
00747 it != allChoosers->end();
00748 ++it ) {
00749 has_global_chooser |= ((*it)->m_type == Global);
00750 has_standard_chooser |= ((*it)->m_type == Standard);
00751 }
00752
00753
00754
if( m_type == ApplicationGlobal || m_type == Global ) {
00755
if( !has_standard_chooser ) {
00756
if(
checkStandardShortcutsConflict( cut, bWarnUser,
this ))
00757
return true;
00758 }
00759 }
00760
00761
00762
if( !has_global_chooser ) {
00763
if(
checkGlobalShortcutsConflict( cut, bWarnUser,
this, d->mapGlobals,
00764 m_type == Global ? pItem->actionName() :
QString::null ))
00765 return true;
00766 }
00767
00768
if( isKeyPresentLocally( cut, pItem, bWarnUser ))
00769
return true;
00770
00771
00772
for(
QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
00773 it != allChoosers->end();
00774 ++it ) {
00775
if( (*it) !=
this && (*it)->isKeyPresentLocally( cut, NULL, bWarnUser ))
00776
return true;
00777 }
00778
return false;
00779 }
00780
00781
00782
bool KKeyChooser::isKeyPresentLocally(
const KShortcut& cut, KKeyChooserItem* ignoreItem,
const QString& warnText )
00783 {
00784
return isKeyPresentLocally( cut, ignoreItem, !warnText.isNull());
00785 }
00786
00787
bool KKeyChooser::isKeyPresentLocally(
const KShortcut& cut, KKeyChooserItem* ignoreItem,
bool bWarnUser )
00788 {
00789
if (
cut.
toString().isEmpty())
00790
return false;
00791
00792
00793
for(
QListViewItemIterator it( d->pList ); it.current(); ++it ) {
00794 KKeyChooserItem* pItem2 = dynamic_cast<KKeyChooserItem*>(it.current());
00795
if( pItem2 && pItem2 != ignoreItem ) {
00796
int iSeq = keyConflict( cut, pItem2->shortcut() );
00797
if( iSeq > -1 ) {
00798
if( bWarnUser ) {
00799
if( !promptForReassign(
cut.
seq(iSeq), pItem2->text(0), Application,
this ))
00800
return true;
00801
00802
KShortcut cut2 = pItem2->shortcut();
00803 removeFromShortcut(cut2, cut);
00804 pItem2->setShortcut(cut2);
00805 updateButtons();
00806 emit
keyChange();
00807 }
00808 }
00809 }
00810 }
00811
return false;
00812 }
00813
00814 bool KKeyChooser::checkStandardShortcutsConflict(
const KShortcut& cut,
bool bWarnUser,
QWidget* parent )
00815 {
00816
00817
for( uint i = 0; i < cut.
count(); i++ ) {
00818
const KKeySequence& seq = cut.
seq(i);
00819 KStdAccel::StdAccel
id =
KStdAccel::findStdAccel( seq );
00820
if(
id != KStdAccel::AccelNone
00821 && keyConflict( cut, KStdAccel::shortcut(
id ) ) > -1 ) {
00822
if( bWarnUser ) {
00823
if( !promptForReassign( seq, KStdAccel::label(
id), Standard, parent ))
00824
return true;
00825 removeStandardShortcut( KStdAccel::label(
id), dynamic_cast< KKeyChooser* > ( parent ), KStdAccel::shortcut(
id ), cut);
00826 }
00827 }
00828 }
00829
return false;
00830 }
00831
00832 bool KKeyChooser::checkGlobalShortcutsConflict(
const KShortcut& cut,
bool bWarnUser,
QWidget* parent )
00833 {
00834
QMap< QString, KShortcut > map;
00835 readGlobalKeys( map );
00836
return checkGlobalShortcutsConflict( cut, bWarnUser, parent, map, QString::null );
00837 }
00838
00839
bool KKeyChooser::checkGlobalShortcutsConflict(
const KShortcut& cut,
bool bWarnUser,
QWidget* parent,
00840
const QMap< QString, KShortcut >& map,
const QString& ignoreAction )
00841 {
00842
QMap<QString, KShortcut>::ConstIterator it;
00843
for( it = map.begin(); it != map.end(); ++it ) {
00844
int iSeq = keyConflict( cut, (*it) );
00845
if( iSeq > -1 ) {
00846
if( ignoreAction.isEmpty() || it.key() != ignoreAction ) {
00847
if( bWarnUser ) {
00848
if( !promptForReassign( cut.
seq(iSeq), it.key(), Global, parent ))
00849
return true;
00850 removeGlobalShortcut( it.key(), dynamic_cast< KKeyChooser* >( parent ), (*it), cut);
00851 }
00852 }
00853 }
00854 }
00855
return false;
00856 }
00857
00858
void KKeyChooser::removeStandardShortcut(
const QString& name,
KKeyChooser* chooser,
const KShortcut &origCut,
const KShortcut &cut )
00859 {
00860
bool was_in_choosers =
false;
00861
if( allChoosers != NULL ) {
00862
for(
QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
00863 it != allChoosers->end();
00864 ++it ) {
00865
if( (*it) != chooser && (*it)->
m_type == Standard ) {
00866 was_in_choosers |= ( (*it)->removeShortcut( name, cut ));
00867 }
00868 }
00869 }
00870
if( !was_in_choosers ) {
00871
KStdAccel::ShortcutList std_list;
00872
KShortcut newCut = origCut;
00873 removeFromShortcut(newCut, cut);
00874 std_list.
setShortcut( std_list.
index( name ), newCut);
00875 std_list.
save();
00876 }
00877 }
00878
00879
void KKeyChooser::removeGlobalShortcut(
const QString& name,
KKeyChooser* chooser,
const KShortcut &origCut,
const KShortcut &cut )
00880 {
00881
bool was_in_choosers =
false;
00882
if( allChoosers != NULL ) {
00883
for(
QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
00884 it != allChoosers->end();
00885 ++it ) {
00886
if( (*it) != chooser && (*it)->
m_type == Global ) {
00887 was_in_choosers |= ( (*it)->removeShortcut( name, cut ));
00888 }
00889 }
00890 }
00891
if( !was_in_choosers ) {
00892 KAccelActions actions;
00893
KShortcut newCut = origCut;
00894 removeFromShortcut(newCut, cut);
00895 actions.insert( name,
"",
"", newCut, newCut);
00896 actions.writeActions(
"Global Shortcuts", 0,
true,
true );
00897 }
00898 }
00899
00900
bool KKeyChooser::removeShortcut(
const QString& name,
const KShortcut &cut )
00901 {
00902
for(
QListViewItemIterator it( d->pList ); it.current(); ++it ) {
00903 KKeyChooserItem* pItem2 = dynamic_cast<KKeyChooserItem*>(it.current());
00904
if( pItem2 && pItem2->actionName() ==
name ) {
00905
00906
KShortcut cut2 = pItem2->shortcut();
00907 removeFromShortcut(cut2, cut);
00908 pItem2->setShortcut(cut2);
00909 updateButtons();
00910 emit
keyChange();
00911
return true;
00912 }
00913 }
00914
return false;
00915 }
00916
00917
00918
void KKeyChooser::_warning(
const KKeySequence& cut,
QString sAction,
QString sTitle )
00919 {
00920 sAction = sAction.stripWhiteSpace();
00921
00922
QString s =
00923 i18n(
"The '%1' key combination has already been allocated "
00924
"to the \"%2\" action.\n"
00925
"Please choose a unique key combination.").
00926 arg(
cut.
toString()).arg(sAction);
00927
00928
KMessageBox::sorry(
this, s, sTitle );
00929 }
00930
00931
bool KKeyChooser::promptForReassign(
const KKeySequence& cut,
const QString& sAction, ActionType type,
QWidget* parent )
00932 {
00933
QString sTitle;
00934
QString s;
00935
if( type == Standard ) {
00936 sTitle = i18n(
"Conflict with Standard Application Shortcut");
00937 s = i18n(
"The '%1' key combination has already been allocated "
00938
"to the standard action \"%2\".\n"
00939
"Do you want to reassign it from that action to the current one?");
00940 }
00941
else if( type == Global ) {
00942 sTitle = i18n(
"Conflict with Global Shortcut");
00943 s = i18n(
"The '%1' key combination has already been allocated "
00944
"to the global action \"%2\".\n"
00945
"Do you want to reassign it from that action to the current one?");
00946 }
00947
else {
00948 sTitle = i18n(
"Key Conflict");
00949 s = i18n(
"The '%1' key combination has already been allocated "
00950
"to the \"%2\" action.\n"
00951
"Do you want to reassign it from that action to the current one?");
00952 }
00953 s = s.arg(
cut.
toString()).arg(sAction.stripWhiteSpace());
00954
00955
return KMessageBox::warningYesNo( parent, s, sTitle ) == KMessageBox::Yes;
00956 }
00957
00958
00959 KKeyChooserItem::KKeyChooserItem(
KListView* parent, QListViewItem* after,
KShortcutList* pList, uint iAction )
00960 :
KListViewItem( parent, after )
00961 {
00962 m_pList = pList;
00963 m_iAction = iAction;
00964 m_bModified =
false;
00965 m_cut = m_pList->
shortcut(m_iAction);
00966 }
00967
00968 KKeyChooserItem::KKeyChooserItem( QListViewItem* parent, QListViewItem* after,
KShortcutList* pList, uint iAction )
00969 :
KListViewItem( parent, after )
00970 {
00971 m_pList = pList;
00972 m_iAction = iAction;
00973 m_bModified =
false;
00974 m_cut = m_pList->
shortcut(m_iAction);
00975 }
00976
00977
QString KKeyChooserItem::actionName()
const
00978
{
00979
return m_pList->name(m_iAction);
00980 }
00981
00982
const KShortcut& KKeyChooserItem::shortcut()
const
00983
{
00984
return m_cut;
00985 }
00986
00987
void KKeyChooserItem::setShortcut(
const KShortcut& cut )
00988 {
00989 m_cut =
cut;
00990 m_bModified = (m_cut != m_pList->shortcut(m_iAction));
00991 listView()->repaintItem(
this );
00992 }
00993
00994
void KKeyChooserItem::commitChanges()
00995 {
00996
if( m_bModified )
00997 m_pList->setShortcut( m_iAction, m_cut );
00998 }
00999
01000
QString KKeyChooserItem::text(
int iCol )
const
01001
{
01002
if( iCol == 0 ) {
01003
01004
QString s = m_pList->label(m_iAction);
01005
QString s2;
01006
for( uint i = 0; i < s.length(); i++ )
01007
if( s[i] !=
'&' || ( i+1<s.length() && s[i+1] ==
'&' ) )
01008 s2 += s[i];
01009
return s2;
01010 }
01011
else if( iCol <= (
int) m_cut.count() )
01012
return m_cut.seq(iCol-1).toString();
01013
else
01014
return QString::null;
01015 }
01016
01017
int KKeyChooserItem::compare( QListViewItem* item,
int iCol,
bool bAscending )
const
01018
{
01019 KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( item );
01020
if( iCol == 0 && pItem ) {
01021
QString psName1 = m_pList->name(m_iAction);
01022
QString psName2 = pItem->m_pList->name(pItem->m_iAction);
01023
QRegExp rxNumber1(
" (\\d+)$" );
01024
QRegExp rxNumber2(
" (\\d+)$" );
01025
int iNumber1 = rxNumber1.search( psName1 );
01026
int iNumber2 = rxNumber2.search( psName2 );
01027
01028
01029
if( iNumber1 >= 0 && iNumber1 == iNumber2 && psName1.startsWith( psName2.left( iNumber1+1 ) ) ) {
01030
int n1 = rxNumber1.cap(1).toInt();
01031
int n2 = rxNumber2.cap(1).toInt();
01032
return (n1 < n2) ? -1 : (n1 > n2) ? 1 : 0;
01033 }
01034 }
01035
01036
return QListViewItem::compare( item, iCol, bAscending );
01037 }
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
KKeyDialog::KKeyDialog( KKeyChooser::ActionType type,
bool bAllowLetterShortcuts,
QWidget *parent,
const char* name )
01051 :
KDialogBase( parent,
name, true, i18n(
"Configure Shortcuts"), Help|Default|Ok|Cancel, Ok )
01052 {
01053 m_pKeyChooser =
new KKeyChooser(
this, type, bAllowLetterShortcuts );
01054 setMainWidget( m_pKeyChooser );
01055 connect(
this, SIGNAL(defaultClicked()), m_pKeyChooser, SLOT(
allDefault()) );
01056 enableButton( Help,
false );
01057
01058
KConfigGroup group( KGlobal::config(),
"KKeyDialog Settings" );
01059
QSize sz = size();
01060 resize( group.readSizeEntry(
"Dialog Size", &sz ) );
01061 }
01062
01063 KKeyDialog::KKeyDialog(
bool bAllowLetterShortcuts,
QWidget *parent,
const char* name )
01064 :
KDialogBase( parent, name, true, i18n(
"Configure Shortcuts"), Help|Default|Ok|Cancel, Ok )
01065 {
01066 m_pKeyChooser =
new KKeyChooser(
this, KKeyChooser::Application, bAllowLetterShortcuts );
01067
setMainWidget( m_pKeyChooser );
01068 connect(
this, SIGNAL(
defaultClicked()), m_pKeyChooser, SLOT(allDefault()) );
01069
enableButton( Help,
false );
01070
01071
KConfigGroup group( KGlobal::config(),
"KKeyDialog Settings" );
01072
QSize sz = size();
01073 resize( group.
readSizeEntry(
"Dialog Size", &sz ) );
01074 }
01075
01076 KKeyDialog::~KKeyDialog()
01077 {
01078
KConfigGroup group( KGlobal::config(),
"KKeyDialog Settings" );
01079 group.
writeEntry(
"Dialog Size", size(),
true,
true );
01080 }
01081
01082 bool KKeyDialog::insert(
KActionCollection* pColl )
01083 {
01084
return m_pKeyChooser->
insert( pColl );
01085 }
01086
01087 bool KKeyDialog::insert(
KActionCollection *pColl,
const QString &title)
01088 {
01089
return m_pKeyChooser->
insert(pColl, title);
01090 }
01091
01092
bool KKeyDialog::configure(
bool bSaveSettings )
01093 {
01094
int retcode = exec();
01095
if( retcode == Accepted ) {
01096
if( bSaveSettings )
01097 m_pKeyChooser->
save();
01098
else
01099
commitChanges();
01100 }
01101
return retcode;
01102 }
01103
01104 void KKeyDialog::commitChanges()
01105 {
01106 m_pKeyChooser->
commitChanges();
01107 }
01108
01109 int KKeyDialog::configure(
KActionCollection* coll,
QWidget* parent,
bool bSaveSettings )
01110 {
01111
return configure( coll,
true, parent, bSaveSettings);
01112 }
01113
01114 int KKeyDialog::configure(
KAccel* keys,
QWidget* parent,
bool bSaveSettings )
01115 {
01116
return configure( keys,
true, parent, bSaveSettings);
01117 }
01118
01119 int KKeyDialog::configure(
KGlobalAccel* keys,
QWidget* parent,
bool bSaveSettings )
01120 {
01121
return configure( keys,
true, parent, bSaveSettings);
01122 }
01123
01124 int KKeyDialog::configure(
KAccel* keys,
bool bAllowLetterShortcuts,
QWidget *parent,
bool bSaveSettings )
01125 {
01126
KKeyDialog dlg( bAllowLetterShortcuts, parent );
01127 dlg.
m_pKeyChooser->
insert( keys );
01128
bool b = dlg.
configure( bSaveSettings );
01129
if( b && bSaveSettings )
01130 keys->
updateConnections();
01131
return b;
01132 }
01133
01134 int KKeyDialog::configure(
KGlobalAccel* keys,
bool bAllowLetterShortcuts,
QWidget *parent,
bool bSaveSettings )
01135 {
01136
KKeyDialog dlg( KKeyChooser::ApplicationGlobal, bAllowLetterShortcuts, parent );
01137 dlg.
m_pKeyChooser->
insert( keys );
01138
bool b = dlg.
configure( bSaveSettings );
01139
if( b && bSaveSettings )
01140 keys->
updateConnections();
01141
return b;
01142 }
01143
01144 int KKeyDialog::configure(
KActionCollection* coll,
bool bAllowLetterShortcuts,
QWidget *parent,
bool bSaveSettings )
01145 {
01146
kdDebug(125) <<
"KKeyDialog::configureKeys( KActionCollection*, " << bSaveSettings <<
" )" <<
endl;
01147
KKeyDialog dlg( bAllowLetterShortcuts, parent );
01148 dlg.
m_pKeyChooser->
insert( coll );
01149
return dlg.
configure( bSaveSettings );
01150 }
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
void KKeyChooser::virtual_hook(
int,
void* )
01166 { }
01167
01168
void KKeyDialog::virtual_hook(
int id,
void* data )
01169 { KDialogBase::virtual_hook(
id, data ); }
01170
01171
#include "kkeydialog.moc"