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