not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / khotkeys / kcm_hotkeys / kcm_hotkeys.cpp
blobecac478d5b0214c6636774b1c486c010c93c9db9
1 /*
2 Copyright (C) 2008 Michael Jansen <kde@michael-jansen.biz>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 #include "kcm_hotkeys.h"
22 #include "kcm_module_factory.h"
24 #include <typeinfo>
27 // ACTION_DATAS
28 #include "action_data/action_data_group.h"
29 // OUR ACTION WIDGETS
30 #include "action_group_widget.h"
31 #include "simple_action_data_widget.h"
32 #include "global_settings_widget.h"
33 // REST
34 #include "daemon/daemon.h"
35 #include "khotkeys_interface.h"
36 #include "hotkeys_model.h"
37 #include "hotkeys_proxy_model.h"
38 #include "hotkeys_tree_view.h"
39 #include "khotkeysglobal.h"
41 #include <QtGui/QHBoxLayout>
42 #include <QtGui/QSplitter>
43 #include <QtGui/QStackedWidget>
44 #include <QtGui/QWidget>
46 #include <QtDBus/QtDBus>
48 #include <KDE/KAboutData>
49 #include <KDE/KDebug>
50 #include <KDE/KLocale>
51 #include <KDE/KMessageBox>
52 #include <KDE/KPluginLoader>
56 class KCMHotkeysPrivate
58 public:
60 KCMHotkeysPrivate( KCMHotkeys *host );
62 // Treeview displaying the shortcuts
63 QTreeView *treeView;
65 /** The model holding the shortcut settings. Beware! There a proxy
66 * between us and that model */
67 KHotkeysModel *model;
69 //! Our host
70 KCMHotkeys *q;
72 //! Container for all editing widgets
73 QStackedWidget *stack;
75 //! Widget to edit an action group
76 ActionGroupWidget *action_group;
78 //! The currently shown dialog
79 HotkeysWidgetIFace *current;
81 //! GlobalSettingsWidget
82 GlobalSettingsWidget *global_settings;
84 SimpleActionDataWidget *simple_action;
86 /**
87 * Show the widget. If the current widget has changes allow
88 * cancelation ! of this action
90 bool maybeShowWidget();
92 /**
93 * Applies the changes from the current item
95 void applyCurrentItem();
97 /**
98 * A Hotkey was changed. Update the treeview.
100 void slotHotkeyChanged(KHotKeys::ActionDataBase*);
102 void load();
103 void save();
107 KCMHotkeys::KCMHotkeys( QWidget *parent, const QVariantList & /* args */ )
108 : KCModule( KCMModuleFactory::componentData(), parent )
109 ,d( new KCMHotkeysPrivate(this) )
111 // Inform KCModule of the buttons we support
112 KCModule::setButtons(KCModule::Buttons(KCModule::Default | KCModule::Apply));
114 // Add the about data
115 KAboutData *about = new KAboutData(
116 "khotkeys",
118 ki18n("KDE Hotkeys Configuration Module"),
119 KDE_VERSION_STRING,
120 KLocalizedString(),
121 KAboutData::License_GPL,
122 ki18n("Copyright 2008 (c) Michael Jansen")
124 about->addAuthor(
125 ki18n("Michael Jansen"),
126 ki18n("Maintainer"),
127 "kde@michael-jansen.biz" );
128 setAboutData(about);
130 // Tell KCModule we were changed.
131 connect(
132 d->action_group, SIGNAL(changed(bool)),
133 this, SIGNAL(changed(bool)) );
134 connect(
135 d->simple_action, SIGNAL(changed(bool)),
136 this, SIGNAL(changed(bool)) );
137 connect(
138 d->global_settings, SIGNAL(changed(bool)),
139 this, SIGNAL(changed(bool)) );
140 // Update TreeView if hotkeys was changed
141 connect(
142 d->simple_action, SIGNAL(changed(KHotKeys::ActionDataBase*)),
143 this, SLOT(slotHotkeyChanged(KHotKeys::ActionDataBase*)));
144 connect(
145 d->action_group, SIGNAL(changed(KHotKeys::ActionDataBase*)),
146 this, SLOT(slotHotkeyChanged(KHotKeys::ActionDataBase*)));
150 void KCMHotkeys::currentChanged( const QModelIndex &pCurrent, const QModelIndex &pPrevious )
152 // We're not interested in changes of columns. Just compare the rows
153 QModelIndex current =
154 pCurrent.isValid()
155 ? pCurrent.sibling( pCurrent.row(), 0 )
156 : QModelIndex();
157 QModelIndex previous =
158 pPrevious.isValid()
159 ? pPrevious.sibling( pPrevious.row(), 0 )
160 : QModelIndex();
162 // Now it's possible for previous and current to be the same
163 if (current==previous)
165 return;
168 // Current and previous differ. Ask user if there are unsaved changes
169 if ( !d->maybeShowWidget() )
171 return;
174 if (!current.isValid())
176 d->current = d->global_settings;
177 d->global_settings->copyFromObject();
178 d->stack->setCurrentWidget( d->global_settings );
179 return;
182 // Now go on and activate the new item;
183 KHotKeys::ActionDataBase *item = d->model->indexToActionDataBase( current );
184 QModelIndex typeOfIndex = d->model->index( current.row(), KHotkeysModel::TypeColumn, current.parent() );
186 switch (d->model->data( typeOfIndex ).toInt())
189 case KHotkeysModel::SimpleActionData:
191 KHotKeys::SimpleActionData *data = dynamic_cast<KHotKeys::SimpleActionData*>(item);
192 if (data)
194 d->simple_action->setActionData( data );
195 d->current = d->simple_action;
198 break;
200 case KHotkeysModel::ActionDataGroup:
202 KHotKeys::ActionDataGroup *group = dynamic_cast<KHotKeys::ActionDataGroup*>(item);
203 if (group)
205 d->action_group->setActionData( group );
206 d->current = d->action_group;
209 break;
211 default:
213 const std::type_info &ti = typeid(*item);
214 kDebug() << "##### Unknown ActionDataType " << ti.name();
217 } // switch
219 d->stack->setCurrentWidget( d->current );
223 KCMHotkeys::~KCMHotkeys()
225 delete d; d=0;
229 void KCMHotkeys::defaults()
231 kWarning() << "not yet implemented!";
235 void KCMHotkeys::load()
237 d->load();
241 void KCMHotkeys::slotChanged()
243 emit changed(true);
247 void KCMHotkeys::save()
249 d->save();
253 // ==========================================================================
254 // KCMHotkeysPrivate
257 KCMHotkeysPrivate::KCMHotkeysPrivate( KCMHotkeys *host )
258 : treeView( new HotkeysTreeView )
259 ,model(new KHotkeysModel)
260 ,q(host)
261 ,stack(0)
262 ,action_group(0)
263 ,current(0)
264 ,simple_action(0)
266 // The widget for groups
267 action_group = new ActionGroupWidget(q);
269 // The widget for simple hotkeys (one trigger - one action)
270 simple_action = new SimpleActionDataWidget(q);
272 // The widget for the global settings
273 global_settings = new GlobalSettingsWidget(q);
275 // Setup the stack
276 stack = new QStackedWidget;
277 stack->addWidget( global_settings );
278 stack->addWidget( action_group );
279 stack->addWidget( simple_action );
281 // A splitter for the treeview and the stack
282 QSplitter *splitter = new QSplitter;
283 splitter->addWidget( treeView );
284 splitter->addWidget( stack );
286 // The global layout
287 QHBoxLayout *layout = new QHBoxLayout;
288 layout->addWidget( splitter );
289 q->setLayout( layout );
291 // Initialize the global part of the khotkeys lib ( handler ... )
292 KHotKeys::init_global_data(false, q);
294 treeView->setModel(model);
296 current=global_settings;
297 global_settings->copyFromObject();
301 void KCMHotkeysPrivate::load()
303 // disconnect the signals
304 if (treeView->selectionModel())
306 QObject::disconnect(
307 treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
308 q, SLOT(currentChanged(QModelIndex,QModelIndex)) );
311 model->load();
313 QObject::connect(
314 model, SIGNAL( rowsRemoved( QModelIndex, int, int )),
315 q, SLOT( slotChanged() ));
316 QObject::connect(
317 model, SIGNAL( rowsInserted( QModelIndex, int, int )),
318 q, SLOT( slotChanged() ));
319 QObject::connect(
320 model, SIGNAL( dataChanged( QModelIndex, QModelIndex )),
321 q, SLOT( slotChanged() ));
323 // reconnect the signals
324 QObject::connect(
325 treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
326 q, SLOT(currentChanged(QModelIndex,QModelIndex)) );
328 // Start khotkeys
329 KHotKeys::Daemon::start();
333 bool KCMHotkeysPrivate::maybeShowWidget()
335 // If the current widget is changed, ask user if switch is ok
336 if (current && current->isChanged())
338 int choice = KMessageBox::warningContinueCancel(
340 i18n("The current action has unsaved changes. If you continue those changes will be lost!"),
341 i18n("Save changes") );
342 if (choice != KMessageBox::Continue)
344 return false;
346 // Apply the changes from the current item
347 applyCurrentItem();
348 save();
350 return true;
354 void KCMHotkeysPrivate::save()
356 if (current)
357 applyCurrentItem();
359 // Write the settings
360 model->save();
362 if (!(KHotKeys::Daemon::isRunning() or KHotKeys::Daemon::start()))
364 KMessageBox::error(
366 "<qt>" + i18n("Unable to contact khotkeys. Your changes are saved but i failed to activate them") + "</qt>" );
367 return;
370 // Inform kdedkhotkeys demon to reload settings
371 QDBusConnection bus = QDBusConnection::sessionBus();
372 QPointer<OrgKdeKhotkeysInterface> iface = new OrgKdeKhotkeysInterface(
373 "org.kde.kded",
374 "/modules/khotkeys",
375 bus,
378 QDBusError err;
379 if(!iface->isValid())
381 err = iface->lastError();
382 if (err.isValid())
384 kError() << err.name() << ":" << err.message();
386 KMessageBox::error(
388 "<qt>" + i18n("Unable to contact khotkeys. Your changes are saved but i failed to activate them") + "</qt>" );
389 return;
392 // Reread the configuration. We have no possibility to check if it worked.
393 iface->reread_configuration();
398 void KCMHotkeysPrivate::applyCurrentItem()
400 Q_ASSERT( current );
401 // Only save when really changed
402 if (current->isChanged())
404 current->apply();
409 void KCMHotkeysPrivate::slotHotkeyChanged(KHotKeys::ActionDataBase* hotkey)
411 model->emitChanged(hotkey);
415 #include "moc_kcm_hotkeys.cpp"