2
// KDE Shortcut config module
4
// Copyright (c) Mark Donohoe 1998
5
// Copyright (c) Matthias Ettrich 1998
6
// Converted to generic key configuration module, Duncan Haldane 1998.
7
// Layout fixes copyright (c) 2000 Preston Brown <pbrown@kde.org>
17
#include <qwhatsthis.h>
18
#include <qcheckbox.h>
23
#include <kstandarddirs.h>
24
#include <ksimpleconfig.h>
25
#include <kmessagebox.h>
26
#include <kseparator.h>
27
#include <dcopclient.h>
28
#include <kapplication.h>
29
#include <kkey_x11.h> // Used in KKeyModule::init()
31
#include "keyconfig.h"
32
#include "keyconfig.moc"
34
#define KICKER_ALL_BINDINGS
36
//----------------------------------------------------------------------------
38
KKeyModule::KKeyModule( QWidget *parent, bool isGlobal, bool bSeriesOnly, bool bSeriesNone, const char *name )
39
: QWidget( parent, name )
41
init( isGlobal, bSeriesOnly, bSeriesNone );
44
KKeyModule::KKeyModule( QWidget *parent, bool isGlobal, const char *name )
45
: QWidget( parent, name )
47
init( isGlobal, false, false );
50
void KKeyModule::init( bool isGlobal, bool _bSeriesOnly, bool bSeriesNone )
54
KeyType = isGlobal ? "global" : "standard";
56
bSeriesOnly = _bSeriesOnly;
58
kdDebug(125) << "KKeyModule::init() - Get default key bindings." << endl;
59
if ( KeyType == "global" ) {
60
KAccelActions* keys = &actions;
61
// see also KKeyModule::init() below !!!
63
#define KShortcuts KAccelShortcuts
64
#include "../../kwin/kwinbindings.cpp"
65
#include "../../kicker/core/kickerbindings.cpp"
66
#include "../../kdesktop/kdesktopbindings.cpp"
67
#include "../../klipper/klipperbindings.cpp"
68
#include "../../kxkb/kxkbbindings.cpp"
70
KeyScheme = "Global Key Scheme";
71
KeySet = "Global Keys";
72
// Sorting Hack: I'll re-write the module once feature-adding begins again.
73
if( bSeriesOnly || bSeriesNone ) {
74
for( uint i = 0; i < actions.size(); i++ ) {
75
QString sConfigKey = actions[i].m_sName;
76
//kdDebug(125) << "sConfigKey: " << sConfigKey << endl;
77
int iLastSpace = sConfigKey.findRev( ' ' );
80
sConfigKey.mid( iLastSpace+1 ).toInt( &bIsNum );
82
kdDebug(125) << "sConfigKey: " << sConfigKey
83
<< " bIsNum: " << bIsNum
84
<< " bSeriesOnly: " << bSeriesOnly << endl;
85
if( ((bSeriesOnly && !bIsNum) || (bSeriesNone && bIsNum)) && !sConfigKey.contains( ':' ) ) {
86
actions.removeAction( sConfigKey );
93
if ( KeyType == "standard" ) {
94
for(uint i=0; i<KStdAccel::NB_STD_ACCELS; i++) {
95
KStdAccel::StdAccel id = (KStdAccel::StdAccel)i;
96
actions.insertAction( KStdAccel::action(id),
97
KStdAccel::description(id),
98
KStdAccel::defaultKey3(id),
99
KStdAccel::defaultKey4(id) );
102
KeyScheme = "Standard Key Scheme";
106
//kdDebug(125) << "KKeyModule::init() - Read current key bindings from config." << endl;
107
//actions.readActions( KeySet );
109
sFileList = new QStringList();
110
sList = new QListBox( this );
113
sList->setCurrentItem( 0 );
114
connect( sList, SIGNAL( highlighted( int ) ),
115
SLOT( slotPreviewScheme( int ) ) );
117
QLabel *label = new QLabel( sList, i18n("&Key Scheme"), this );
119
wtstr = i18n("Here you can see a list of the existing key binding schemes with 'Current scheme'"
120
" referring to the settings you are using right now. Select a scheme to use, remove or"
122
QWhatsThis::add( label, wtstr );
123
QWhatsThis::add( sList, wtstr );
125
addBt = new QPushButton( i18n("&Save Scheme..."), this );
126
connect( addBt, SIGNAL( clicked() ), SLOT( slotAdd() ) );
127
QWhatsThis::add(addBt, i18n("Click here to add a new key bindings scheme. You will be prompted for a name."));
129
removeBt = new QPushButton( i18n("&Remove Scheme"), this );
130
removeBt->setEnabled(FALSE);
131
connect( removeBt, SIGNAL( clicked() ), SLOT( slotRemove() ) );
132
QWhatsThis::add( removeBt, i18n("Click here to remove the selected key bindings scheme. You can not"
133
" remove the standard system wide schemes, 'Current scheme' and 'KDE default'.") );
135
// Hack to get this setting only displayed once. It belongs in main.cpp instead.
136
// That move will take a lot of UI redesigning, though, so i'll do it once CVS
137
// opens up for feature commits again. -- ellis
138
/* Needed to remove because this depended upon non-BC changes in KeyEntry.*/
139
// If this is the "Global Keys" section of the KDE Control Center:
140
if( isGlobal && !bSeriesOnly ) {
141
preferMetaBt = new QCheckBox( i18n("Prefer 4-modifier defaults"), this );
142
if( !KKeySequence::keyboardHasMetaKey() )
143
preferMetaBt->setEnabled( false );
144
preferMetaBt->setChecked( KKeySequence::useFourModifierKeys() );
145
connect( preferMetaBt, SIGNAL(clicked()), SLOT(slotPreferMeta()) );
146
QWhatsThis::add( preferMetaBt, i18n("If your keyboard has a Meta key, but you would "
147
"like KDE to prefer the 3-modifier configuration defaults, then this option "
148
"should be unchecked.") );
152
KSeparator* line = new KSeparator( KSeparator::HLine, this );
154
kc = new KeyChooserSpec( actions, this, isGlobal );
155
connect( kc, SIGNAL(keyChange()), this, SLOT(slotKeyChange()) );
159
QGridLayout *topLayout = new QGridLayout( this, 6, 2,
160
KDialog::marginHint(),
161
KDialog::spacingHint());
162
topLayout->addWidget(label, 0, 0);
163
topLayout->addMultiCellWidget(sList, 1, 2, 0, 0);
164
topLayout->addWidget(addBt, 1, 1);
165
topLayout->addWidget(removeBt, 2, 1);
167
topLayout->addWidget(preferMetaBt, 3, 0);
168
topLayout->addMultiCellWidget(line, 4, 4, 0, 1);
169
topLayout->addRowSpacing(3, 15);
170
topLayout->addMultiCellWidget(kc, 5, 5, 0, 1);
172
setMinimumSize(topLayout->sizeHint());
175
KKeyModule::~KKeyModule (){
176
//kdDebug() << "KKeyModule destructor" << endl;
181
bool KKeyModule::writeSettings( const QString& sGroup, KConfig* pConfig )
184
actions.writeActions( sGroup, pConfig, true, false );
188
bool KKeyModule::writeSettingsGlobal( const QString& sGroup )
191
actions.writeActions( sGroup, 0, true, true );
195
void KKeyModule::load()
200
/*void KKeyModule::save()
203
KKeySequence::useFourModifierKeys( preferMetaBt->isChecked() );
206
actions.writeActions( KeySet, 0, true, true );
207
if ( KeyType == "global" ) {
208
if ( !kapp->dcopClient()->isAttached() )
209
kapp->dcopClient()->attach();
210
// TODO: create a reconfigureKeys() method.
211
kapp->dcopClient()->send("kwin", "", "reconfigure()", "");
212
kapp->dcopClient()->send("kdesktop", "", "configure()", "");
213
kapp->dcopClient()->send("kicker", "Panel", "configure()", "");
217
void KKeyModule::defaults()
220
preferMetaBt->setChecked( false );
221
KKeySequence::useFourModifierKeys( false );
225
/*void KKeyModule::slotRemove()
228
KGlobal::dirs()->saveLocation("data", "kcmkeys/" + KeyType);
231
if (!d.exists()) // what can we do?
234
d.setFilter( QDir::Files );
235
d.setSorting( QDir::Name );
236
d.setNameFilter("*.kksrc");
238
uint ind = sList->currentItem();
240
if ( !d.remove( *sFileList->at( ind ) ) ) {
241
KMessageBox::sorry( 0,
242
i18n("This key scheme could not be removed.\n"
243
"Perhaps you do not have permission to alter the file "
244
"system where the key scheme is stored." ));
248
sList->removeItem( ind );
249
sFileList->remove( sFileList->at(ind) );
252
void KKeyModule::slotKeyChange()
255
//emit keysChanged( &dict );
258
/*void KKeyModule::slotSave( )
260
KSimpleConfig config(*sFileList->at( sList->currentItem() ) );
261
// global=true is necessary in order to
262
// let both 'Global Shortcuts' and 'Shortcut Sequences' be
263
// written to the same scheme file.
265
actions.writeActions( KeyScheme, &config, KeyType == "global", KeyType == "global" );
268
void KKeyModule::slotPreferMeta()
270
kc->setPreferFourModifierKeys( preferMetaBt->isChecked() );
273
void KKeyModule::readScheme( int index )
275
kdDebug(125) << "readScheme( " << index << " )\n";
277
kc->allDefault( false );
278
//else if( index == 2 )
279
// kc->allDefault( true );
281
KConfigBase* config = 0;
282
if( index == 0 ) config = new KConfig( "kdeglobals" );
283
//else config = new KSimpleConfig( *sFileList->at( index ), true );
285
actions.readActions( (index == 0) ? KeySet : KeyScheme, config );
291
/*void KKeyModule::slotAdd()
295
if ( sList->currentItem() >= nSysSchemes )
296
sName = sList->currentText();
297
SaveScm ss( 0, "save scheme", sName );
308
sName = ss.nameLine->text();
309
if ( sName.stripWhiteSpace().isEmpty() )
312
sName = sName.simplifyWhiteSpace();
316
while ( ind < (int) sFile.length() ) {
318
// parse the string for first white space
320
ind = sFile.find(" ");
322
ind = sFile.length();
326
// remove from string
328
sFile.remove( ind, 1);
330
// Make the next letter upper case
332
QString s = sFile.mid( ind, 1 );
334
sFile.replace( ind, 1, s );
339
for ( int i = 0; i < (int) sList->count(); i++ ) {
340
if ( sName.lower() == (sList->text(i)).lower() ) {
343
int result = KMessageBox::warningContinueCancel( 0,
344
i18n("A key scheme with the name '%1' already exists.\n"
345
"Do you want to overwrite it?\n").arg(sName),
346
i18n("Save Key Scheme"),
348
if (result == KMessageBox::Continue)
356
} while ( nameValid == FALSE );
358
disconnect( sList, SIGNAL( highlighted( int ) ), this,
359
SLOT( slotPreviewScheme( int ) ) );
362
QString kksPath = KGlobal::dirs()->saveLocation("data", "kcmkeys/");
366
if ( !d.mkdir( kksPath ) ) {
367
qWarning("KKeyModule: Could not make directory to store user info.");
374
d.setPath( kksPath );
376
if ( !d.mkdir( kksPath ) ) {
377
qWarning("KKeyModule: Could not make directory to store user info.");
381
sFile.prepend( kksPath );
385
sList->insertItem( sName );
387
sList->setCurrentItem( sList->count()-1 );
388
sFileList->append( sFile );
393
sList->setCurrentItem( exists );
396
KSimpleConfig *config =
397
new KSimpleConfig( sFile );
399
config->setGroup( KeyScheme );
400
config->writeEntry( "Name", sName );
405
connect( sList, SIGNAL( highlighted( int ) ), this,
406
SLOT( slotPreviewScheme( int ) ) );
408
slotPreviewScheme( sList->currentItem() );
411
/*void KKeyModule::slotPreviewScheme( int indx )
415
// Set various appropriate for the scheme
417
if ( indx < nSysSchemes ||
418
(*sFileList->at(indx)).contains( "/global-" ) ||
419
(*sFileList->at(indx)).contains( "/app-" ) ) {
420
removeBt->setEnabled( FALSE );
422
removeBt->setEnabled( TRUE );
426
/*void KKeyModule::readSchemeNames( )
428
QStringList schemes = KGlobal::dirs()->findAllResources("data", "kcmkeys/" + KeyType + "/*.kksrc");
429
//QRegExp r( "-kde[34].kksrc$" );
430
QRegExp r( "-kde3.kksrc$" );
434
sList->insertItem( i18n("Current Scheme"), 0 );
435
sFileList->append( "Not a kcsrc file" );
436
sList->insertItem( i18n("KDE Traditional"), 1 );
437
sFileList->append( "Not a kcsrc file" );
438
//sList->insertItem( i18n("KDE Extended (With 'Win' Key)"), 2 );
439
//sList->insertItem( i18n("KDE Default for 4 Modifiers (Meta/Alt/Ctrl/Shift)"), 2 );
440
//sFileList->append( "Not a kcsrc file" );
443
// This for system files
444
for ( QStringList::ConstIterator it = schemes.begin(); it != schemes.end(); it++) {
445
// KPersonalizer relies on .kksrc files containing all the keyboard shortcut
446
// schemes for various setups. It also requires the KDE defaults to be in
447
// a .kksrc file. The KDE defaults shouldn't be listed here.
448
//if( r.search( *it ) != -1 )
451
KSimpleConfig config( *it, true );
452
// TODO: Put 'Name' in "Settings" group
453
config.setGroup( KeyScheme );
454
QString str = config.readEntry( "Name" );
456
sList->insertItem( str );
457
sFileList->append( *it );
461
/*void KKeyModule::updateKeys( const KAccelActions* map_P )
463
kc->updateKeys( map_P );
466
// write all the global keys to kdeglobals
467
// this is needed to be able to check for conflicts with global keys in app's keyconfig
468
// dialogs, kdeglobals is empty as long as you don't apply any change in controlcenter/keys
469
void KKeyModule::init()
471
kdDebug(125) << "KKeyModule::init()\n";
473
/*kdDebug(125) << "KKeyModule::init() - Initialize # Modifier Keys Settings\n";
474
KConfigGroupSaver cgs( KGlobal::config(), "Keyboard" );
475
QString fourMods = KGlobal::config()->readEntry( "Use Four Modifier Keys", KAccel::keyboardHasMetaKey() ? "true" : "false" );
476
KAccel::useFourModifierKeys( fourMods == "true" );
477
bool bUseFourModifierKeys = KAccel::useFourModifierKeys();
478
KGlobal::config()->writeEntry( "User Four Modifier Keys", bUseFourModifierKeys ? "true" : "false", true, true );
480
KAccelActions* keys = new KAccelActions();
482
kdDebug(125) << "KKeyModule::init() - Load Included Bindings\n";
483
// this should match the included files above
485
#define KShortcuts KAccelShortcuts
486
#include "../../klipper/klipperbindings.cpp"
487
#include "../../kwin/kwinbindings.cpp"
488
#include "../../kicker/core/kickerbindings.cpp"
489
#include "../../kdesktop/kdesktopbindings.cpp"
490
#include "../../kxkb/kxkbbindings.cpp"
493
kdDebug(125) << "KKeyModule::init() - Read Config Bindings\n";
494
keys->readActions( "Global Keys" );
497
KSimpleConfig cfg( "kdeglobals" );
498
cfg.deleteGroup( "Global Keys" );
501
kdDebug(125) << "KKeyModule::init() - Write Config Bindings\n";
502
keys->writeActions( "Global Keys", 0, true, true );
505
//-----------------------------------------------------------------
507
//-----------------------------------------------------------------
509
KeyChooserSpec::KeyChooserSpec( KAccelActions& actions, QWidget* parent, bool bGlobal )
510
: KKeyChooser( actions, parent, bGlobal, false, true ), m_bGlobal( bGlobal )
513
// globalDict()->clear(); // don't check against global keys twice
516
/*void KeyChooserSpec::updateKeys( const KAccelActions* map_P )
521
for( KAccelActions::ConstIterator gIt( map_P->begin());
525
int* keyCode = new int;
526
*keyCode = ( *gIt ).aConfigKeyCode;
527
stdDict()->insert( gIt.key(), keyCode);
532
globalDict()->clear();
533
for( KAccelActions::ConstIterator gIt( map_P->begin());
537
int* keyCode = new int;
538
*keyCode = ( *gIt ).aConfigKeyCode;
539
globalDict()->insert( gIt.key(), keyCode);