4
* Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
5
* Copyright (c) 2001 Ellis Whitehead <ellis@kde.org>
7
* Requires the Qt widget libraries, available at no cost at
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
#include "shortcuts.h"
29
#include <qwhatsthis.h>
31
#include <kapplication.h>
34
#include <kkeynative.h>
35
#include <kinputdialog.h>
37
#include <kmessagebox.h>
38
#include <kshortcutlist.h>
39
#include <ksimpleconfig.h>
40
#include <kstandarddirs.h>
42
ShortcutsModule::ShortcutsModule( QWidget *parent, const char *name )
43
: QWidget( parent, name )
48
ShortcutsModule::~ShortcutsModule()
50
delete m_pListGeneral;
51
delete m_pListSequence;
52
delete m_pListApplication;
55
// Called when [Reset] is pressed
56
void ShortcutsModule::load()
58
kdDebug(125) << "ShortcutsModule::load()" << endl;
62
// When [Apply] or [OK] are clicked.
63
void ShortcutsModule::save()
65
kdDebug(125) << "ShortcutsModule::save()" << endl;
67
// FIXME: This isn't working. Why? -- ellis, 2002/01/27
68
// Check for old group,
69
if( KGlobal::config()->hasGroup( "Keys" ) ) {
70
KGlobal::config()->deleteGroup( "Keys", true, true );
72
KGlobal::config()->sync();
74
m_pkcGeneral->commitChanges();
75
m_pkcSequence->commitChanges();
76
m_pkcApplication->save();
78
m_actionsGeneral.writeActions( "Global Shortcuts", 0, true, true );
79
m_actionsSequence.writeActions( "Global Shortcuts", 0, true, true );
81
KIPC::sendMessageAll( KIPC::SettingsChanged, KApplication::SETTINGS_SHORTCUTS );
84
void ShortcutsModule::defaults()
86
m_pkcGeneral->allDefault();
87
m_pkcSequence->allDefault();
88
m_pkcApplication->allDefault();
91
QString ShortcutsModule::quickHelp() const
93
return i18n("<h1>Key Bindings</h1> Using key bindings you can configure certain actions to be"
94
" triggered when you press a key or a combination of keys, e.g. Ctrl+C is normally bound to"
95
" 'Copy'. KDE allows you to store more than one 'scheme' of key bindings, so you might want"
96
" to experiment a little setting up your own scheme while you can still change back to the"
97
" KDE defaults.<p> In the tab 'Global Shortcuts' you can configure non-application specific"
98
" bindings like how to switch desktops or maximize a window. In the tab 'Application Shortcuts'"
99
" you will find bindings typically used in applications, such as copy and paste.");
102
void ShortcutsModule::initGUI()
104
kdDebug(125) << "A-----------" << endl;
105
KAccelActions* keys = &m_actionsGeneral;
106
// see also KShortcutsModule::init() below !!!
108
#define KICKER_ALL_BINDINGS
109
#include "../../kwin/kwinbindings.cpp"
110
#include "../../kicker/core/kickerbindings.cpp"
111
#include "../../kdesktop/kdesktopbindings.cpp"
112
#include "../../klipper/klipperbindings.cpp"
113
#include "../../kxkb/kxkbbindings.cpp"
115
kdDebug(125) << "B-----------" << endl;
116
m_actionsSequence.init( m_actionsGeneral );
118
kdDebug(125) << "C-----------" << endl;
119
createActionsGeneral();
120
kdDebug(125) << "D-----------" << endl;
121
createActionsSequence();
122
kdDebug(125) << "E-----------" << endl;
124
kdDebug(125) << "F-----------" << endl;
125
QVBoxLayout* pVLayout = new QVBoxLayout( this, KDialog::marginHint() );
127
pVLayout->addSpacing( KDialog::marginHint() );
129
// (o) [Current ] <Remove> ( ) New <Save>
131
QHBoxLayout *pHLayout = new QHBoxLayout( pVLayout, KDialog::spacingHint() );
132
QButtonGroup* pGroup = new QButtonGroup( this );
135
m_prbPre = new QRadioButton( "", this );
136
connect( m_prbPre, SIGNAL(clicked()), SLOT(slotSchemeCur()) );
137
pGroup->insert( m_prbPre );
138
pHLayout->addWidget( m_prbPre );
140
m_pcbSchemes = new KComboBox( this );
141
connect( m_pcbSchemes, SIGNAL(activated(int)), SLOT(slotSelectScheme(int)) );
142
pHLayout->addWidget( m_pcbSchemes );
144
pHLayout->addSpacing( KDialog::marginHint() );
146
m_pbtnRemove = new QPushButton( i18n("&Remove"), this );
147
m_pbtnRemove->setEnabled( false );
148
connect( m_pbtnRemove, SIGNAL(clicked()), SLOT(slotRemoveScheme()) );
149
QWhatsThis::add( m_pbtnRemove, i18n("Click here to remove the selected key bindings scheme. You can not"
150
" remove the standard system wide schemes, 'Current scheme' and 'KDE default'.") );
151
pHLayout->addWidget( m_pbtnRemove );
153
pHLayout->addSpacing( KDialog::marginHint() * 3 );
155
m_prbNew = new QRadioButton( i18n("New scheme"), this );
156
m_prbNew->setEnabled( false );
157
pGroup->insert( m_prbNew );
158
pHLayout->addWidget( m_prbNew );
160
m_pbtnSave = new QPushButton( i18n("&Save..."), this );
161
m_pbtnSave->setEnabled( false );
162
QWhatsThis::add( m_pbtnSave, i18n("Click here to add a new key bindings scheme. You will be prompted for a name.") );
163
connect( m_pbtnSave, SIGNAL(clicked()), SLOT(slotSaveSchemeAs()) );
164
pHLayout->addWidget( m_pbtnSave );
166
pHLayout->addStretch( 1 );
168
m_pTab = new QTabWidget( this );
169
m_pTab->setMargin( KDialog::marginHint() );
170
pVLayout->addWidget( m_pTab );
172
m_pListGeneral = new KAccelShortcutList( m_actionsGeneral, true );
173
m_pkcGeneral = new KKeyChooser( m_pListGeneral, this, KKeyChooser::Global, false );
174
m_pTab->addTab( m_pkcGeneral, i18n("&Global Shortcuts") );
175
connect( m_pkcGeneral, SIGNAL(keyChange()), SLOT(slotKeyChange()) );
177
m_pListSequence = new KAccelShortcutList( m_actionsSequence, true );
178
m_pkcSequence = new KKeyChooser( m_pListSequence, this, KKeyChooser::Global, false );
179
m_pTab->addTab( m_pkcSequence, i18n("Shortcut Se&quences") );
180
connect( m_pkcSequence, SIGNAL(keyChange()), SLOT(slotKeyChange()) );
182
m_pListApplication = new KStdAccel::ShortcutList;
183
m_pkcApplication = new KKeyChooser( m_pListApplication, this, KKeyChooser::Standard, false );
184
m_pTab->addTab( m_pkcApplication, i18n("App&lication Shortcuts") );
185
connect( m_pkcApplication, SIGNAL(keyChange()), SLOT(slotKeyChange()) );
187
kdDebug(125) << "G-----------" << endl;
190
kdDebug(125) << "I-----------" << endl;
193
kdDebug(125) << "J-----------" << endl;
196
void ShortcutsModule::createActionsGeneral()
198
KAccelActions& actions = m_actionsGeneral;
200
for( uint i = 0; i < actions.count(); i++ ) {
201
QString sConfigKey = actions[i].name();
202
//kdDebug(125) << "sConfigKey: " << sConfigKey << endl;
203
int iLastSpace = sConfigKey.findRev( ' ' );
205
if( iLastSpace >= 0 )
206
sConfigKey.mid( iLastSpace+1 ).toInt( &bIsNum );
208
//kdDebug(125) << "sConfigKey: " << sConfigKey
209
// << " bIsNum: " << bIsNum << endl;
210
if( bIsNum && !sConfigKey.contains( ':' ) ) {
211
actions[i].setConfigurable( false );
212
actions[i].setName( QString::null );
217
void ShortcutsModule::createActionsSequence()
219
KAccelActions& actions = m_actionsSequence;
221
for( uint i = 0; i < actions.count(); i++ ) {
222
QString sConfigKey = actions[i].name();
223
//kdDebug(125) << "sConfigKey: " << sConfigKey << endl;
224
int iLastSpace = sConfigKey.findRev( ' ' );
226
if( iLastSpace >= 0 )
227
sConfigKey.mid( iLastSpace+1 ).toInt( &bIsNum );
229
//kdDebug(125) << "sConfigKey: " << sConfigKey
230
// << " bIsNum: " << bIsNum << endl;
231
if( !bIsNum && !sConfigKey.contains( ':' ) ) {
232
actions[i].setConfigurable( false );
233
actions[i].setName( QString::null );
238
void ShortcutsModule::readSchemeNames()
240
QStringList schemes = KGlobal::dirs()->findAllResources("data", "kcmkeys/*.kksrc");
242
m_pcbSchemes->clear();
243
m_rgsSchemeFiles.clear();
245
i18n("User-Defined Scheme");
246
m_pcbSchemes->insertItem( i18n("Current Scheme") );
247
m_rgsSchemeFiles.append( "cur" );
249
// This for system files
250
for ( QStringList::ConstIterator it = schemes.begin(); it != schemes.end(); it++) {
251
// KPersonalizer relies on .kksrc files containing all the keyboard shortcut
252
// schemes for various setups. It also requires the KDE defaults to be in
253
// a .kksrc file. The KDE defaults shouldn't be listed here.
254
//if( r.search( *it ) != -1 )
257
KSimpleConfig config( *it, true );
258
config.setGroup( "Settings" );
259
QString str = config.readEntry( "Name" );
261
m_pcbSchemes->insertItem( str );
262
m_rgsSchemeFiles.append( *it );
266
void ShortcutsModule::resizeEvent( QResizeEvent * )
268
//m_pTab->setGeometry(0,0,width(),height());
271
void ShortcutsModule::slotSchemeCur()
273
kdDebug(125) << "ShortcutsModule::slotSchemeCur()" << endl;
274
//m_pcbSchemes->setCurrentItem( 0 );
278
void ShortcutsModule::slotKeyChange()
280
kdDebug(125) << "ShortcutsModule::slotKeyChange()" << endl;
281
m_prbNew->setEnabled( true );
282
m_prbNew->setChecked( true );
283
m_pbtnSave->setEnabled( true );
284
emit changed( true );
287
void ShortcutsModule::slotSelectScheme( int )
289
i18n("Your current changes will be lost if you load another scheme before saving this one.");
290
kdDebug(125) << "ShortcutsModule::slotSelectScheme( " << m_pcbSchemes->currentItem() << " )" << endl;
291
QString sFilename = m_rgsSchemeFiles[ m_pcbSchemes->currentItem() ];
293
if( sFilename == "cur" ) {
294
// TODO: remove nulls params
295
m_pkcGeneral->syncToConfig( "Global Shortcuts", 0, true );
296
m_pkcSequence->syncToConfig( "Global Shortcuts", 0, true );
297
m_pkcApplication->syncToConfig( "Shortcuts", 0, false );
299
KSimpleConfig config( sFilename );
300
config.setGroup( "Settings" );
301
//m_sBaseSchemeFile = config.readEntry( "Name" );
303
// If the user's keyboard layout doesn't support the Win key,
304
// but this layout scheme requires it,
305
if( !KKeyNative::keyboardHasWinKey()
306
&& config.readBoolEntry( "Uses Win Modifier", false ) ) {
307
// TODO: change "Win" to Win's label.
308
int ret = KMessageBox::warningContinueCancel( this,
309
i18n("This scheme requires the \"%1\" modifier key, which is not "
310
"available on your keyboard layout. Do you wish to view it anyway?" )
312
if( ret == KMessageBox::Cancel )
316
m_pkcGeneral->syncToConfig( "Global Shortcuts", &config, true );
317
m_pkcSequence->syncToConfig( "Global Shortcuts", &config, true );
318
m_pkcApplication->syncToConfig( "Shortcuts", &config, false );
321
m_prbPre->setChecked( true );
322
m_prbNew->setEnabled( false );
323
m_pbtnSave->setEnabled( false );
327
void ShortcutsModule::slotSaveSchemeAs()
329
QString sName, sFile;
333
sName = m_pcbSchemes->currentText();
338
sName = KInputDialog::getText( i18n( "Save Key Scheme" ),
339
i18n( "Enter a name for the key scheme:" ), sName, &ok, this );
342
sName = sName.simplifyWhiteSpace();
346
while( ind < (int) sFile.length() ) {
347
// parse the string for first white space
348
ind = sFile.find(" ");
350
ind = sFile.length();
354
// remove from string
355
sFile.remove( ind, 1 );
357
// Make the next letter upper case
358
QString s = sFile.mid( ind, 1 );
360
sFile.replace( ind, 1, s );
364
for( int i = 0; i < (int) m_pcbSchemes->count(); i++ ) {
365
if( sName.lower() == (m_pcbSchemes->text(i)).lower() ) {
368
int result = KMessageBox::warningContinueCancel( 0,
369
i18n("A key scheme with the name '%1' already exists.\n"
370
"Do you want to overwrite it?\n").arg(sName),
371
i18n("Save key scheme"),
373
bNameValid = (result == KMessageBox::Continue);
378
} while( !bNameValid );
380
disconnect( m_pcbSchemes, SIGNAL(activated(int)), this, SLOT(slotSelectScheme(int)) );
382
QString kksPath = KGlobal::dirs()->saveLocation( "data", "kcmkeys/" );
385
if( !dir.exists() && !dir.mkdir( kksPath ) ) {
386
qWarning("KShortcutsModule: Could not make directory to store user info.");
390
sFile.prepend( kksPath );
392
if( iScheme == -1 ) {
393
m_pcbSchemes->insertItem( sName );
394
//m_pcbSchemes->setFocus();
395
m_pcbSchemes->setCurrentItem( m_pcbSchemes->count()-1 );
396
m_rgsSchemeFiles.append( sFile );
398
//m_pcbSchemes->setFocus();
399
m_pcbSchemes->setCurrentItem( iScheme );
402
KSimpleConfig *config = new KSimpleConfig( sFile );
404
config->setGroup( "Settings" );
405
config->writeEntry( "Name", sName );
410
connect( m_pcbSchemes, SIGNAL(activated(int)), SLOT(slotSelectScheme(int)) );
414
void ShortcutsModule::saveScheme()
416
QString sFilename = m_rgsSchemeFiles[ m_pcbSchemes->currentItem() ];
417
KSimpleConfig config( sFilename );
419
m_pkcGeneral->commitChanges();
420
m_pkcSequence->commitChanges();
421
m_pkcApplication->commitChanges();
423
m_pListGeneral->writeSettings( "Global Shortcuts", &config, true );
424
m_pListSequence->writeSettings( "Global Shortcuts", &config, true );
425
m_pListApplication->writeSettings( "Shortcuts", &config, true );
428
void ShortcutsModule::slotRemoveScheme()
432
#include "shortcuts.moc"