not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / keys / globalshortcuts.cpp
blobe55c209772044183aba81b43a395c5fa07cdc2bc
1 /*
2 * Copyright 2007 Andreas Pakulat <apaku@gmx.de>
3 * Copyright 2008 Michael Jansen <kde@michael-jansen.biz>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "globalshortcuts.h"
20 #include "kglobalshortcutseditor.h"
21 #include "select_scheme_dialog.h"
22 #include "kdedglobalaccel_interface.h"
23 #include "kdedglobalaccel_component_interface.h"
24 #include <kdebug.h>
26 #include <QCoreApplication>
27 #include <QDBusConnection>
28 #include <QDBusError>
29 #include <QDBusInterface>
30 #include <QDBusReply>
31 #include <QDBusMetaType>
32 #include <QLayout>
33 #include <QPointer>
35 #include <KAction>
36 #include <KActionCollection>
37 #include <KConfig>
38 #include <KConfigGroup>
39 #include <KFileDialog>
40 #include <KLocale>
41 #include <KMessageBox>
42 #include <KPluginFactory>
43 #include <KPushButton>
45 K_PLUGIN_FACTORY(GlobalShortcutsModuleFactory, registerPlugin<GlobalShortcutsModule>();)
46 K_EXPORT_PLUGIN(GlobalShortcutsModuleFactory("kcmkeys"))
48 GlobalShortcutsModule::GlobalShortcutsModule(QWidget *parent, const QVariantList &args)
49 : KCModule(GlobalShortcutsModuleFactory::componentData(), parent, args),
50 editor(0)
52 KCModule::setButtons(KCModule::Buttons(KCModule::Default | KCModule::Apply));
54 // Add import scheme button
55 KPushButton *importButton = new KPushButton(this);
56 importButton->setText(i18n("Import Scheme..."));
57 connect(importButton, SIGNAL(clicked()), this, SLOT(importScheme()));
59 // Add export scheme button
60 KPushButton *exportButton = new KPushButton(this);
61 exportButton->setText(i18n("Export Scheme..."));
62 connect(exportButton, SIGNAL(clicked()), this, SLOT(exportScheme()));
64 // Layout for the buttons
65 QHBoxLayout *hbox = new QHBoxLayout;
66 hbox->addWidget(exportButton);
67 hbox->addWidget(importButton);
69 // Create the kglobaleditor
70 editor = new KGlobalShortcutsEditor(this, KShortcutsEditor::GlobalAction);
71 connect(editor, SIGNAL(changed(bool)), this, SIGNAL(changed(bool)));
73 // Layout the hole bunch
74 QVBoxLayout *global = new QVBoxLayout;
75 global->addLayout(hbox);
76 global->addWidget(editor);
77 setLayout(global);
80 GlobalShortcutsModule::~GlobalShortcutsModule()
84 void GlobalShortcutsModule::load()
86 // Connect to kdedglobalaccel. If that fails there is no need to continue.
87 qRegisterMetaType<QList<int> >();
88 qDBusRegisterMetaType<QList<int> >();
89 qDBusRegisterMetaType<QList<KGlobalShortcutInfo> >();
90 qDBusRegisterMetaType<KGlobalShortcutInfo>();
91 QDBusConnection bus = QDBusConnection::sessionBus();
92 org::kde::KdedGlobalAccel kdedglobalaccel(
93 "org.kde.kded",
94 "/modules/kdedglobalaccel",
95 bus);
97 if (!kdedglobalaccel.isValid()) {
98 QString errorString;
99 QDBusError error = kdedglobalaccel.lastError();
100 // The global shortcuts DBus service manages all global shortcuts and we
101 // can't do anything useful without it.
102 if (error.isValid()) {
103 errorString = i18n("Message: %1\nError: %2", error.message(), error.name());
106 KMessageBox::sorry(
107 this,
108 i18n("Failed to contact the KDE global shortcuts daemon\n")
109 + errorString );
110 return;
113 // Undo all changes not yet applied
114 editor->clear();
116 QDBusReply< QList<QDBusObjectPath> > componentsRc = kdedglobalaccel.allComponents();
117 if (!componentsRc.isValid())
119 kDebug() << "allComponents() failed!";
120 return;
122 QList<QDBusObjectPath> components = componentsRc;
124 Q_FOREACH(QDBusObjectPath componentPath, components) {
126 // Get the component
127 org::kde::kdedglobalaccel::Component component(
128 "org.kde.kded",
129 componentPath.path(),
130 bus);
131 if (!component.isValid()) {
132 kDebug() << "Component " << componentPath.path() << "not valid! Skipping!";
133 continue;
136 // Get the shortcut contexts.
137 QDBusReply<QStringList> shortcutContextsRc = component.getShortcutContexts();
138 if (!shortcutContextsRc.isValid()) {
139 kDebug() << "Failed to get contexts for component "
140 << componentPath.path() <<"! Skipping!";
141 continue;
143 QStringList shortcutContexts = shortcutContextsRc;
145 // We add shortcut all shortcut context to the editor. Thias way the
146 // user keep full control of it's shortcuts.
147 Q_FOREACH (QString shortcutContext, shortcutContexts) {
149 QDBusReply< QList<KGlobalShortcutInfo> > shortcutsRc =
150 component.allShortcutInfos(shortcutContext);
151 if (!shortcutsRc.isValid())
153 kDebug() << "allShortcutInfos() failed for " << componentPath.path() << shortcutContext;
154 continue;
156 QList<KGlobalShortcutInfo> shortcuts = shortcutsRc;
157 // Shouldn't happen. But you never know
158 if (shortcuts.isEmpty()) {
159 kDebug() << "Got shortcut context" << shortcutContext << "without shortcuts for"
160 << componentPath.path();
161 continue;
164 // It's safe now
165 const QString componentUnique = shortcuts[0].componentUniqueName();
166 QString componentContextId = componentUnique;
167 // kdedglobalaccel knows that '|' is our separator between
168 // component and context
169 if (shortcutContext != "default") {
170 componentContextId += QString("|") + shortcutContext;
173 // Create a action collection for our current component:context
174 KActionCollection* col = new KActionCollection(
175 this,
176 KComponentData(componentContextId.toAscii()));
178 // Now add the shortcuts.
179 foreach (const KGlobalShortcutInfo &shortcut, shortcuts) {
181 const QString &objectName = shortcut.uniqueName();
182 KAction *action = col->addAction(objectName);
183 action->setProperty("isConfigurationAction", QVariant(true)); // see KAction::~KAction
184 action->setText(shortcut.friendlyName());
186 // Always call this to enable global shortcuts for the action. The editor widget
187 // checks it.
188 // Also actually loads the shortcut using the KAction::Autoloading mechanism.
189 // Avoid setting the default shortcut; it would just be written to the global
190 // configuration so we would not get the real one below.
191 action->setGlobalShortcut(KShortcut(), KAction::ActiveShortcut);
193 // The default shortcut will never be loaded because it's pointless in a real
194 // application. There are no scarce resources [i.e. physical keys] to manage
195 // so applications can set them at will and there's no autoloading.
196 QList<QKeySequence> sc = shortcut.defaultKeys();
197 if (sc.count()>0) {
198 action->setGlobalShortcut(KShortcut(sc[0]), KAction::DefaultShortcut);
200 } // Q_FOREACH(shortcut)
202 QString componentFriendlyName = shortcuts[0].componentFriendlyName();
204 if (shortcuts[0].contextUniqueName() != "default")
206 componentFriendlyName +=
207 QString('[') + shortcuts[0].contextFriendlyName() + QString(']');
210 editor->addCollection(col, componentContextId, componentFriendlyName);
212 } // Q_FOREACH(context)
213 } // Q_FOREACH(component)
216 void GlobalShortcutsModule::defaults()
218 editor->allDefault();
222 void GlobalShortcutsModule::save()
224 editor->save();
228 void GlobalShortcutsModule::importScheme()
230 // Check for unsaved modifications
231 if (editor->isModified()) {
232 int choice = KMessageBox::warningContinueCancel(
233 parentWidget(),
234 i18n("Your current changes will be lost if you load another scheme before saving this one"),
235 i18n("Load Shortcurt Scheme"),
236 KGuiItem(i18n("Load")));
237 if (choice != KMessageBox::Continue) {
238 return;
242 SelectSchemeDialog dialog(this);
243 if (dialog.exec() != KDialog::Accepted) {
244 return;
247 KUrl url = dialog.selectedScheme();
248 if (!url.isLocalFile()) {
249 KMessageBox::sorry(this, i18n("This file (%1) does not exist. You can only select local files.",
250 url.url()));
251 return;
253 kDebug() << url.path();
254 KConfig config(url.path());
255 editor->importConfiguration(&config);
259 void GlobalShortcutsModule::exportScheme()
261 KUrl url = KFileDialog::getSaveFileName(KUrl(), "*.kksrc", parentWidget());
262 if (!url.isEmpty()) {
263 KConfig config(url.path());
264 config.deleteGroup("Shortcuts");
265 config.deleteGroup("Global Shortcuts");
266 editor->exportConfiguration(&config);
270 #include "globalshortcuts.moc"