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