summaryrefslogtreecommitdiffstats
path: root/kcontrol/keys/shortcuts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/keys/shortcuts.cpp')
-rw-r--r--kcontrol/keys/shortcuts.cpp435
1 files changed, 435 insertions, 0 deletions
diff --git a/kcontrol/keys/shortcuts.cpp b/kcontrol/keys/shortcuts.cpp
new file mode 100644
index 000000000..e65364f4c
--- /dev/null
+++ b/kcontrol/keys/shortcuts.cpp
@@ -0,0 +1,435 @@
+/*
+ * shortcuts.cpp
+ *
+ * Copyright (c) 1999 Matthias Hoelzer-Kluepfel <[email protected]>
+ * Copyright (c) 2001 Ellis Whitehead <[email protected]>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "shortcuts.h"
+
+#include <qdir.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kipc.h>
+#include <kkeynative.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kshortcutlist.h>
+#include <ksimpleconfig.h>
+#include <kstandarddirs.h>
+
+ShortcutsModule::ShortcutsModule( QWidget *parent, const char *name )
+: QWidget( parent, name )
+{
+ initGUI();
+}
+
+ShortcutsModule::~ShortcutsModule()
+{
+ delete m_pListGeneral;
+ delete m_pListSequence;
+ delete m_pListApplication;
+}
+
+// Called when [Reset] is pressed
+void ShortcutsModule::load()
+{
+ kdDebug(125) << "ShortcutsModule::load()" << endl;
+ slotSchemeCur();
+}
+
+// When [Apply] or [OK] are clicked.
+void ShortcutsModule::save()
+{
+ kdDebug(125) << "ShortcutsModule::save()" << endl;
+
+ // FIXME: This isn't working. Why? -- ellis, 2002/01/27
+ // Check for old group,
+ if( KGlobal::config()->hasGroup( "Keys" ) ) {
+ KGlobal::config()->deleteGroup( "Keys", true, true );
+ }
+ KGlobal::config()->sync();
+
+ m_pkcGeneral->commitChanges();
+ m_pkcSequence->commitChanges();
+ m_pkcApplication->save();
+
+ m_actionsGeneral.writeActions( "Global Shortcuts", 0, true, true );
+ m_actionsSequence.writeActions( "Global Shortcuts", 0, true, true );
+
+ KIPC::sendMessageAll( KIPC::SettingsChanged, KApplication::SETTINGS_SHORTCUTS );
+}
+
+void ShortcutsModule::defaults()
+{
+ m_pkcGeneral->allDefault();
+ m_pkcSequence->allDefault();
+ m_pkcApplication->allDefault();
+}
+
+QString ShortcutsModule::quickHelp() const
+{
+ return i18n("<h1>Key Bindings</h1> Using key bindings you can configure certain actions to be"
+ " triggered when you press a key or a combination of keys, e.g. Ctrl+C is normally bound to"
+ " 'Copy'. KDE allows you to store more than one 'scheme' of key bindings, so you might want"
+ " to experiment a little setting up your own scheme while you can still change back to the"
+ " KDE defaults.<p> In the tab 'Global Shortcuts' you can configure non-application specific"
+ " bindings like how to switch desktops or maximize a window. In the tab 'Application Shortcuts'"
+ " you will find bindings typically used in applications, such as copy and paste.");
+}
+
+void ShortcutsModule::initGUI()
+{
+ kdDebug(125) << "A-----------" << endl;
+ KAccelActions* keys = &m_actionsGeneral;
+// see also KShortcutsModule::init() below !!!
+#define NOSLOTS
+#define KICKER_ALL_BINDINGS
+#include "../../kwin/kwinbindings.cpp"
+#include "../../kicker/kicker/core/kickerbindings.cpp"
+#include "../../kicker/taskbar/taskbarbindings.cpp"
+#include "../../kdesktop/kdesktopbindings.cpp"
+#include "../../klipper/klipperbindings.cpp"
+#include "../../kxkb/kxkbbindings.cpp"
+
+ kdDebug(125) << "B-----------" << endl;
+ m_actionsSequence.init( m_actionsGeneral );
+
+ kdDebug(125) << "C-----------" << endl;
+ createActionsGeneral();
+ kdDebug(125) << "D-----------" << endl;
+ createActionsSequence();
+ kdDebug(125) << "E-----------" << endl;
+
+ kdDebug(125) << "F-----------" << endl;
+ QVBoxLayout* pVLayout = new QVBoxLayout( this, KDialog::marginHint() );
+
+ pVLayout->addSpacing( KDialog::marginHint() );
+
+ // (o) [Current ] <Remove> ( ) New <Save>
+
+ QHBoxLayout *pHLayout = new QHBoxLayout( pVLayout, KDialog::spacingHint() );
+ QButtonGroup* pGroup = new QButtonGroup( this );
+ pGroup->hide();
+
+ m_prbPre = new QRadioButton( "", this );
+ connect( m_prbPre, SIGNAL(clicked()), SLOT(slotSchemeCur()) );
+ pGroup->insert( m_prbPre );
+ pHLayout->addWidget( m_prbPre );
+
+ m_pcbSchemes = new KComboBox( this );
+ m_pcbSchemes->setMinimumWidth( 100 );
+ m_pcbSchemes->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
+ connect( m_pcbSchemes, SIGNAL(activated(int)), SLOT(slotSelectScheme(int)) );
+ pHLayout->addWidget( m_pcbSchemes );
+
+ pHLayout->addSpacing( KDialog::marginHint() );
+
+ m_pbtnRemove = new QPushButton( i18n("&Remove"), this );
+ m_pbtnRemove->setEnabled( false );
+ connect( m_pbtnRemove, SIGNAL(clicked()), SLOT(slotRemoveScheme()) );
+ QWhatsThis::add( m_pbtnRemove, i18n("Click here to remove the selected key bindings scheme. You cannot"
+ " remove the standard system-wide schemes 'Current scheme' and 'KDE default'.") );
+ pHLayout->addWidget( m_pbtnRemove );
+
+ pHLayout->addSpacing( KDialog::marginHint() * 3 );
+
+ m_prbNew = new QRadioButton( i18n("New scheme"), this );
+ m_prbNew->setEnabled( false );
+ pGroup->insert( m_prbNew );
+ pHLayout->addWidget( m_prbNew );
+
+ m_pbtnSave = new QPushButton( i18n("&Save..."), this );
+ m_pbtnSave->setEnabled( false );
+ QWhatsThis::add( m_pbtnSave, i18n("Click here to add a new key bindings scheme. You will be prompted for a name.") );
+ connect( m_pbtnSave, SIGNAL(clicked()), SLOT(slotSaveSchemeAs()) );
+ pHLayout->addWidget( m_pbtnSave );
+
+ pHLayout->addStretch( 1 );
+
+ m_pTab = new QTabWidget( this );
+ m_pTab->setMargin( KDialog::marginHint() );
+ pVLayout->addWidget( m_pTab );
+
+ m_pListGeneral = new KAccelShortcutList( m_actionsGeneral, true );
+ m_pkcGeneral = new KKeyChooser( m_pListGeneral, this, KKeyChooser::Global, false );
+ m_pTab->addTab( m_pkcGeneral, i18n("&Global Shortcuts") );
+ connect( m_pkcGeneral, SIGNAL(keyChange()), SLOT(slotKeyChange()) );
+
+ m_pListSequence = new KAccelShortcutList( m_actionsSequence, true );
+ m_pkcSequence = new KKeyChooser( m_pListSequence, this, KKeyChooser::Global, false );
+ m_pTab->addTab( m_pkcSequence, i18n("Shortcut Se&quences") );
+ connect( m_pkcSequence, SIGNAL(keyChange()), SLOT(slotKeyChange()) );
+
+ m_pListApplication = new KStdAccel::ShortcutList;
+ m_pkcApplication = new KKeyChooser( m_pListApplication, this, KKeyChooser::Standard, false );
+ m_pTab->addTab( m_pkcApplication, i18n("App&lication Shortcuts") );
+ connect( m_pkcApplication, SIGNAL(keyChange()), SLOT(slotKeyChange()) );
+
+ kdDebug(125) << "G-----------" << endl;
+ readSchemeNames();
+
+ kdDebug(125) << "I-----------" << endl;
+ slotSchemeCur();
+
+ kdDebug(125) << "J-----------" << endl;
+}
+
+void ShortcutsModule::createActionsGeneral()
+{
+ KAccelActions& actions = m_actionsGeneral;
+
+ for( uint i = 0; i < actions.count(); i++ ) {
+ QString sConfigKey = actions[i].name();
+ //kdDebug(125) << "sConfigKey: " << sConfigKey << endl;
+ int iLastSpace = sConfigKey.findRev( ' ' );
+ bool bIsNum = false;
+ if( iLastSpace >= 0 )
+ sConfigKey.mid( iLastSpace+1 ).toInt( &bIsNum );
+
+ //kdDebug(125) << "sConfigKey: " << sConfigKey
+ // << " bIsNum: " << bIsNum << endl;
+ if( bIsNum && !sConfigKey.contains( ':' ) ) {
+ actions[i].setConfigurable( false );
+ actions[i].setName( QString::null );
+ }
+ }
+}
+
+void ShortcutsModule::createActionsSequence()
+{
+ KAccelActions& actions = m_actionsSequence;
+
+ for( uint i = 0; i < actions.count(); i++ ) {
+ QString sConfigKey = actions[i].name();
+ //kdDebug(125) << "sConfigKey: " << sConfigKey << endl;
+ int iLastSpace = sConfigKey.findRev( ' ' );
+ bool bIsNum = false;
+ if( iLastSpace >= 0 )
+ sConfigKey.mid( iLastSpace+1 ).toInt( &bIsNum );
+
+ //kdDebug(125) << "sConfigKey: " << sConfigKey
+ // << " bIsNum: " << bIsNum << endl;
+ if( !bIsNum && !sConfigKey.contains( ':' ) ) {
+ actions[i].setConfigurable( false );
+ actions[i].setName( QString::null );
+ }
+ }
+}
+
+void ShortcutsModule::readSchemeNames()
+{
+ QStringList schemes = KGlobal::dirs()->findAllResources("data", "kcmkeys/*.kksrc");
+
+ m_pcbSchemes->clear();
+ m_rgsSchemeFiles.clear();
+
+ i18n("User-Defined Scheme");
+ m_pcbSchemes->insertItem( i18n("Current Scheme") );
+ m_rgsSchemeFiles.append( "cur" );
+
+ // This for system files
+ for ( QStringList::ConstIterator it = schemes.begin(); it != schemes.end(); ++it) {
+ // KPersonalizer relies on .kksrc files containing all the keyboard shortcut
+ // schemes for various setups. It also requires the KDE defaults to be in
+ // a .kksrc file. The KDE defaults shouldn't be listed here.
+ //if( r.search( *it ) != -1 )
+ // continue;
+
+ KSimpleConfig config( *it, true );
+ config.setGroup( "Settings" );
+ QString str = config.readEntry( "Name" );
+
+ m_pcbSchemes->insertItem( str );
+ m_rgsSchemeFiles.append( *it );
+ }
+}
+
+void ShortcutsModule::resizeEvent( QResizeEvent * )
+{
+ //m_pTab->setGeometry(0,0,width(),height());
+}
+
+void ShortcutsModule::slotSchemeCur()
+{
+ kdDebug(125) << "ShortcutsModule::slotSchemeCur()" << endl;
+ //m_pcbSchemes->setCurrentItem( 0 );
+ slotSelectScheme();
+}
+
+void ShortcutsModule::slotKeyChange()
+{
+ kdDebug(125) << "ShortcutsModule::slotKeyChange()" << endl;
+ m_prbNew->setEnabled( true );
+ m_prbNew->setChecked( true );
+ m_pbtnSave->setEnabled( true );
+ emit changed( true );
+}
+
+void ShortcutsModule::slotSelectScheme( int )
+{
+ i18n("Your current changes will be lost if you load another scheme before saving this one.");
+ kdDebug(125) << "ShortcutsModule::slotSelectScheme( " << m_pcbSchemes->currentItem() << " )" << endl;
+ QString sFilename = m_rgsSchemeFiles[ m_pcbSchemes->currentItem() ];
+
+ if( sFilename == "cur" ) {
+ // TODO: remove nulls params
+ m_pkcGeneral->syncToConfig( "Global Shortcuts", 0, true );
+ m_pkcSequence->syncToConfig( "Global Shortcuts", 0, true );
+ m_pkcApplication->syncToConfig( "Shortcuts", 0, false );
+ } else {
+ KSimpleConfig config( sFilename );
+ config.setGroup( "Settings" );
+ //m_sBaseSchemeFile = config.readEntry( "Name" );
+
+ // If the user's keyboard layout doesn't support the Win key,
+ // but this layout scheme requires it,
+ if( !KKeyNative::keyboardHasWinKey()
+ && config.readBoolEntry( "Uses Win Modifier", false ) ) {
+ // TODO: change "Win" to Win's label.
+ int ret = KMessageBox::warningContinueCancel( this,
+ i18n("This scheme requires the \"%1\" modifier key, which is not "
+ "available on your keyboard layout. Do you wish to view it anyway?" )
+ .arg(i18n("Win")) );
+ if( ret == KMessageBox::Cancel )
+ return;
+ }
+
+ m_pkcGeneral->syncToConfig( "Global Shortcuts", &config, true );
+ m_pkcSequence->syncToConfig( "Global Shortcuts", &config, true );
+ m_pkcApplication->syncToConfig( "Shortcuts", &config, false );
+ }
+
+ m_prbPre->setChecked( true );
+ m_prbNew->setEnabled( false );
+ m_pbtnSave->setEnabled( false );
+ emit changed(true);
+}
+
+void ShortcutsModule::slotSaveSchemeAs()
+{
+ QString sName, sFile;
+ bool bNameValid, ok;
+ int iScheme = -1;
+
+ sName = m_pcbSchemes->currentText();
+
+ do {
+ bNameValid = true;
+
+ sName = KInputDialog::getText( i18n( "Save Key Scheme" ),
+ i18n( "Enter a name for the key scheme:" ), sName, &ok, this );
+
+ if( ok ) {
+ sName = sName.simplifyWhiteSpace();
+ sFile = sName;
+
+ int ind = 0;
+ while( ind < (int) sFile.length() ) {
+ // parse the string for first white space
+ ind = sFile.find(" ");
+ if( ind == -1 ) {
+ ind = sFile.length();
+ break;
+ }
+
+ // remove from string
+ sFile.remove( ind, 1 );
+
+ // Make the next letter upper case
+ QString s = sFile.mid( ind, 1 );
+ s = s.upper();
+ sFile.replace( ind, 1, s );
+ }
+
+ iScheme = -1;
+ for( int i = 0; i < (int) m_pcbSchemes->count(); i++ ) {
+ if( sName.lower() == (m_pcbSchemes->text(i)).lower() ) {
+ iScheme = i;
+
+ int result = KMessageBox::warningContinueCancel( 0,
+ i18n("A key scheme with the name '%1' already exists;\n"
+ "do you want to overwrite it?\n").arg(sName),
+ i18n("Save Key Scheme"),
+ i18n("Overwrite"));
+ bNameValid = (result == KMessageBox::Continue);
+ }
+ }
+ } else
+ return;
+ } while( !bNameValid );
+
+ disconnect( m_pcbSchemes, SIGNAL(activated(int)), this, SLOT(slotSelectScheme(int)) );
+
+ QString kksPath = KGlobal::dirs()->saveLocation( "data", "kcmkeys/" );
+
+ QDir dir( kksPath );
+ if( !dir.exists() && !dir.mkdir( kksPath ) ) {
+ qWarning("KShortcutsModule: Could not make directory to store user info.");
+ return;
+ }
+
+ sFile.prepend( kksPath );
+ sFile += ".kksrc";
+ if( iScheme == -1 ) {
+ m_pcbSchemes->insertItem( sName );
+ //m_pcbSchemes->setFocus();
+ m_pcbSchemes->setCurrentItem( m_pcbSchemes->count()-1 );
+ m_rgsSchemeFiles.append( sFile );
+ } else {
+ //m_pcbSchemes->setFocus();
+ m_pcbSchemes->setCurrentItem( iScheme );
+ }
+
+ KSimpleConfig *config = new KSimpleConfig( sFile );
+
+ config->setGroup( "Settings" );
+ config->writeEntry( "Name", sName );
+ delete config;
+
+ saveScheme();
+
+ connect( m_pcbSchemes, SIGNAL(activated(int)), SLOT(slotSelectScheme(int)) );
+ slotSelectScheme();
+}
+
+void ShortcutsModule::saveScheme()
+{
+ QString sFilename = m_rgsSchemeFiles[ m_pcbSchemes->currentItem() ];
+ KSimpleConfig config( sFilename );
+
+ m_pkcGeneral->commitChanges();
+ m_pkcSequence->commitChanges();
+ m_pkcApplication->commitChanges();
+
+ m_pListGeneral->writeSettings( "Global Shortcuts", &config, true );
+ m_pListSequence->writeSettings( "Global Shortcuts", &config, true );
+ m_pListApplication->writeSettings( "Shortcuts", &config, true );
+}
+
+void ShortcutsModule::slotRemoveScheme()
+{
+}
+
+#include "shortcuts.moc"