add more spacing
[personal-kdebase.git] / runtime / kcontrol / kded / kcmkded.cpp
bloba972781fb90cb874de82fbbe740e85c87e76963d
1 // vim: noexpandtab shiftwidth=4 tabstop=4
2 /* This file is part of the KDE project
3 Copyright (C) 2002 Daniel Molkentin <molkentin@kde.org>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (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 GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #include "kcmkded.h"
23 #include <QByteArray>
24 #include <QtDBus/QtDBus>
25 #include <QGroupBox>
26 #include <QHeaderView>
27 #include <QPushButton>
28 #include <QTimer>
29 #include <QTreeWidget>
30 #include <QVBoxLayout>
32 #include <kaboutdata.h>
33 #include <kdialogbuttonbox.h>
34 #include <kdebug.h>
35 #include <kdesktopfile.h>
36 #include <kdialog.h>
37 #include <kmessagebox.h>
38 #include <kservice.h>
39 #include <kstandarddirs.h>
41 #include <KPluginFactory>
42 #include <KPluginLoader>
43 #include "kcmkded.moc"
45 K_PLUGIN_FACTORY(KDEDFactory,
46 registerPlugin<KDEDConfig>();
48 K_EXPORT_PLUGIN(KDEDFactory("kcmkded"))
50 enum OnDemandColumns
52 OnDemandService = 0,
53 OnDemandStatus = 1,
54 OnDemandDescription = 2
57 enum StartupColumns
59 StartupUse = 0,
60 StartupService = 1,
61 StartupStatus = 2,
62 StartupDescription = 3
67 static const int LibraryRole = Qt::UserRole + 1;
69 KDEDConfig::KDEDConfig(QWidget* parent, const QVariantList &) :
70 KCModule( KDEDFactory::componentData(), parent )
72 KAboutData *about =
73 new KAboutData( I18N_NOOP( "kcmkded" ), 0, ki18n( "KDE Service Manager" ),
74 0, KLocalizedString(), KAboutData::License_GPL,
75 ki18n( "(c) 2002 Daniel Molkentin" ) );
76 about->addAuthor(ki18n("Daniel Molkentin"),KLocalizedString(),"molkentin@kde.org");
77 setAboutData( about );
78 setButtons(Apply|Default);
79 setQuickHelp( i18n("<h1>Service Manager</h1><p>This module allows you to have an overview of all plugins of the "
80 "KDE Daemon, also referred to as KDE Services. Generally, there are two types of service:</p>"
81 "<ul><li>Services invoked at startup</li><li>Services called on demand</li></ul>"
82 "<p>The latter are only listed for convenience. The startup services can be started and stopped. "
83 "In Administrator mode, you can also define whether services should be loaded at startup.</p>"
84 "<p><b> Use this with care: some services are vital for KDE; do not deactivate services if you"
85 " do not know what you are doing.</b></p>"));
87 RUNNING = i18n("Running")+' ';
88 NOT_RUNNING = i18n("Not running")+' ';
90 QVBoxLayout *lay = new QVBoxLayout( this );
91 lay->setMargin( 0 );
92 lay->setSpacing( KDialog::spacingHint() );
94 QGroupBox *gb = new QGroupBox( i18n("Load-on-Demand Services"), this );
95 gb->setWhatsThis( i18n("This is a list of available KDE services which will "
96 "be started on demand. They are only listed for convenience, as you "
97 "cannot manipulate these services."));
98 lay->addWidget( gb );
100 QVBoxLayout *gblay = new QVBoxLayout( gb );
102 _lvLoD = new QTreeWidget( gb );
103 QStringList cols;
104 cols.append( i18n("Service") );
105 cols.append( i18n("Status") );
106 cols.append( i18n("Description") );
107 _lvLoD->setHeaderLabels( cols );
108 _lvLoD->setAllColumnsShowFocus(true);
109 _lvLoD->setRootIsDecorated( false );
110 _lvLoD->header()->setStretchLastSection(true);
111 gblay->addWidget( _lvLoD );
113 gb = new QGroupBox( i18n("Startup Services"), this );
114 gb->setWhatsThis( i18n("This shows all KDE services that can be loaded "
115 "on KDE startup. Checked services will be invoked on next startup. "
116 "Be careful with deactivation of unknown services."));
117 lay->addWidget( gb );
119 gblay = new QVBoxLayout( gb );
121 _lvStartup = new QTreeWidget( gb );
122 cols.clear();
123 cols.append( i18n("Use") );
124 cols.append( i18n("Service") );
125 cols.append( i18n("Status") );
126 cols.append( i18n("Description") );
127 _lvStartup->setHeaderLabels( cols );
128 _lvStartup->setAllColumnsShowFocus(true);
129 _lvStartup->setRootIsDecorated( false );
130 _lvStartup->header()->setStretchLastSection(true);
131 gblay->addWidget( _lvStartup );
133 KDialogButtonBox *buttonBox = new KDialogButtonBox( gb, Qt::Horizontal);
134 _pbStart = buttonBox->addButton( i18n("Start") , QDialogButtonBox::ActionRole );
135 _pbStop = buttonBox->addButton( i18n("Stop") , QDialogButtonBox::ActionRole );
136 gblay->addWidget( buttonBox );
138 _pbStart->setEnabled( false );
139 _pbStop->setEnabled( false );
141 connect(_pbStart, SIGNAL(clicked()), SLOT(slotStartService()));
142 connect(_pbStop, SIGNAL(clicked()), SLOT(slotStopService()));
143 connect(_lvLoD, SIGNAL(itemClicked(QTreeWidgetItem*, int)), SLOT(slotLodItemSelected(QTreeWidgetItem*)) );
144 connect(_lvStartup, SIGNAL(itemClicked(QTreeWidgetItem*, int)), SLOT(slotEvalItem(QTreeWidgetItem*)) );
145 connect(_lvStartup, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(slotItemChecked(QTreeWidgetItem*, int)) );
149 QString setModuleGroup(const QString &filename)
151 QString module = filename;
152 int i = module.lastIndexOf('/');
153 if (i != -1)
154 module = module.mid(i+1);
155 i = module.lastIndexOf('.');
156 if (i != -1)
157 module = module.left(i);
159 return QString("Module-%1").arg(module);
162 bool KDEDConfig::autoloadEnabled(KConfig *config, const QString &filename)
164 KConfigGroup cg(config, setModuleGroup(filename));
165 return cg.readEntry("autoload", true);
168 void KDEDConfig::setAutoloadEnabled(KConfig *config, const QString &filename, bool b)
170 KConfigGroup cg(config, setModuleGroup(filename));
171 return cg.writeEntry("autoload", b);
174 void KDEDConfig::load() {
175 KConfig kdedrc( "kdedrc", KConfig::NoGlobals );
177 _lvStartup->clear();
178 _lvLoD->clear();
180 QStringList files;
181 KGlobal::dirs()->findAllResources( "services",
182 QLatin1String( "kded/*.desktop" ),
183 KStandardDirs::Recursive | KStandardDirs::NoDuplicates,
184 files );
186 QTreeWidgetItem* treeitem = 0L;
187 for ( QStringList::ConstIterator it = files.constBegin(); it != files.constEnd(); ++it ) {
188 kDebug() << *it;
190 if ( KDesktopFile::isDesktopFile( *it ) ) {
191 KDesktopFile file( "services", *it );
192 Q_ASSERT( file.desktopGroup().readEntry("X-KDE-ServiceTypes") == "KDEDModule" );
193 // The logic has to be identical to Kded::initModules.
194 // They interpret X-KDE-Kded-autoload as false if not specified
195 // X-KDE-Kded-load-on-demand as true if not specified
196 if ( file.desktopGroup().readEntry("X-KDE-Kded-autoload", false) ) {
197 treeitem = new QTreeWidgetItem();
198 treeitem->setCheckState( StartupUse, autoloadEnabled(&kdedrc, *it) ? Qt::Checked : Qt::Unchecked );
199 treeitem->setText( StartupService, file.readName() );
200 treeitem->setText( StartupDescription, file.readComment() );
201 treeitem->setText( StartupStatus, NOT_RUNNING );
202 if (file.desktopGroup().hasKey("X-KDE-DBus-ModuleName")) {
203 treeitem->setData( StartupService, LibraryRole, file.desktopGroup().readEntry("X-KDE-DBus-ModuleName") );
204 } else {
205 kWarning() << "X-KDE-DBUS-ModuleName not set for module " << file.readName();
206 treeitem->setData( StartupService, LibraryRole, file.desktopGroup().readEntry("X-KDE-Library") );
208 _lvStartup->addTopLevelItem( treeitem );
210 else if ( file.desktopGroup().readEntry("X-KDE-Kded-load-on-demand", true) ) {
211 treeitem = new QTreeWidgetItem();
212 treeitem->setText( OnDemandService, file.readName() );
213 treeitem->setText( OnDemandDescription, file.readComment() );
214 treeitem->setText( OnDemandStatus, NOT_RUNNING );
215 if (file.desktopGroup().hasKey("X-KDE-DBus-ModuleName")) {
216 treeitem->setData( OnDemandService, LibraryRole, file.desktopGroup().readEntry("X-KDE-DBus-ModuleName") );
217 } else {
218 kWarning() << "X-KDE-DBUS-ModuleName not set for module " << file.readName();
219 treeitem->setData( OnDemandService, LibraryRole, file.desktopGroup().readEntry("X-KDE-Library") );
221 _lvLoD->addTopLevelItem( treeitem );
223 else {
224 kWarning() << "kcmkded: Module " << file.readName() << " not loaded on demand or startup! Skipping.";
229 _lvStartup->resizeColumnToContents(StartupUse);
230 _lvStartup->resizeColumnToContents(StartupService);
231 _lvStartup->resizeColumnToContents(StartupStatus);
233 _lvLoD->resizeColumnToContents(OnDemandService);
234 _lvLoD->resizeColumnToContents(OnDemandStatus);
236 getServiceStatus();
238 emit changed(false);
241 void KDEDConfig::save() {
242 QStringList files;
243 KGlobal::dirs()->findAllResources( "services",
244 QLatin1String( "kded/*.desktop" ),
245 KStandardDirs::Recursive | KStandardDirs::NoDuplicates,
246 files );
248 KConfig kdedrc("kdedrc", KConfig::NoGlobals);
250 for ( QStringList::ConstIterator it = files.constBegin(); it != files.constEnd(); ++it ) {
252 if ( KDesktopFile::isDesktopFile( *it ) ) {
254 KConfig _file( *it, KConfig::NoGlobals, "services" );
255 KConfigGroup file(&_file, "Desktop Entry");
257 if (file.readEntry("X-KDE-Kded-autoload", false)){
259 QString libraryName = file.readEntry( "X-KDE-Library" );
260 int count = _lvStartup->topLevelItemCount();
261 for( int i = 0; i < count; ++i )
263 QTreeWidgetItem *treeitem = _lvStartup->topLevelItem( i );
264 if ( treeitem->data( StartupService, LibraryRole ).toString() == libraryName )
266 // we found a match, now compare and see what changed
267 setAutoloadEnabled( &kdedrc, *it, treeitem->checkState( StartupUse ) == Qt::Checked);
268 break;
274 kdedrc.sync();
276 emit changed(false);
278 QDBusInterface kdedInterface( "org.kde.kded", "/kded", "org.kde.kded" );
279 kdedInterface.call( "reconfigure" );
280 QTimer::singleShot(0, this, SLOT(slotServiceRunningToggled()));
284 void KDEDConfig::defaults()
286 int count = _lvStartup->topLevelItemCount();
287 for( int i = 0; i < count; ++i )
289 _lvStartup->topLevelItem( i )->setCheckState( StartupUse, Qt::Unchecked );
292 getServiceStatus();
294 emit changed(false);
298 void KDEDConfig::getServiceStatus()
300 QStringList modules;
301 QDBusInterface kdedInterface( "org.kde.kded", "/kded", "org.kde.kded" );
302 QDBusReply<QStringList> reply = kdedInterface.call( "loadedModules" );
304 if ( reply.isValid() ) {
305 modules = reply.value();
307 else {
308 _lvLoD->setEnabled( false );
309 _lvStartup->setEnabled( false );
310 KMessageBox::error(this, i18n("Unable to contact KDED."));
311 return;
314 // Initialize
315 int count = _lvLoD->topLevelItemCount();
316 for( int i = 0; i < count; ++i )
317 _lvLoD->topLevelItem( i )->setText( OnDemandStatus, NOT_RUNNING );
318 count = _lvStartup->topLevelItemCount();
319 for( int i = 0; i < count; ++i )
320 _lvStartup->topLevelItem( i )->setText( StartupStatus, NOT_RUNNING );
322 // Fill
323 foreach( const QString& module, modules )
325 bool found = false;
327 count = _lvLoD->topLevelItemCount();
328 for( int i = 0; i < count; ++i )
330 QTreeWidgetItem *treeitem = _lvLoD->topLevelItem( i );
331 if ( treeitem->data( OnDemandService, LibraryRole ).toString() == module )
333 treeitem->setText( OnDemandStatus, RUNNING );
334 found = true;
335 break;
339 count = _lvStartup->topLevelItemCount();
340 for( int i = 0; i < count; ++i )
342 QTreeWidgetItem *treeitem = _lvStartup->topLevelItem( i );
343 if ( treeitem->data( StartupService, LibraryRole ).toString() == module )
345 treeitem->setText( StartupStatus, RUNNING );
346 found = true;
347 break;
351 if (!found)
353 kDebug() << "Could not relate module " << module;
354 #ifndef NDEBUG
355 kDebug() << "Candidates were:";
356 count = _lvLoD->topLevelItemCount();
357 for( int i = 0; i < count; ++i )
359 QTreeWidgetItem *treeitem = _lvLoD->topLevelItem( i );
360 kDebug() << treeitem->data( OnDemandService, LibraryRole ).toString();
363 count = _lvStartup->topLevelItemCount();
364 for( int i = 0; i < count; ++i )
366 QTreeWidgetItem *treeitem = _lvStartup->topLevelItem( i );
367 kDebug() << treeitem->data( StartupService, LibraryRole ).toString();
369 #endif
376 void KDEDConfig::slotReload()
378 QString current;
379 if ( _lvStartup->currentItem() )
380 current = _lvStartup->currentItem()->data( StartupService, LibraryRole ).toString();
381 load();
382 if ( !current.isEmpty() )
384 int count = _lvStartup->topLevelItemCount();
385 for( int i = 0; !i < count; ++i )
387 QTreeWidgetItem *treeitem = _lvStartup->topLevelItem( i );
388 if ( treeitem->data( StartupService, LibraryRole ).toString() == current )
390 _lvStartup->setCurrentItem( treeitem );
391 break;
397 void KDEDConfig::slotEvalItem(QTreeWidgetItem * item)
399 if (!item) {
400 // Disable the buttons
401 _pbStart->setEnabled( false );
402 _pbStop->setEnabled( false );
403 return;
406 // Deselect a currently selected element in the "load on demand" treeview
407 _lvLoD->setCurrentItem(NULL);
409 if ( item->text(StartupStatus) == RUNNING ) {
410 _pbStart->setEnabled( false );
411 _pbStop->setEnabled( true );
413 else if ( item->text(StartupStatus) == NOT_RUNNING ) {
414 _pbStart->setEnabled( true );
415 _pbStop->setEnabled( false );
417 else // Error handling, better do nothing
419 _pbStart->setEnabled( false );
420 _pbStop->setEnabled( false );
423 getServiceStatus();
426 void KDEDConfig::slotLodItemSelected(QTreeWidgetItem * item)
428 if (!item)
429 return;
431 // Deselect a currently selected element in the "load on startup" treeview
432 _lvStartup->setCurrentItem(NULL);
433 // The above line doesn't trigger itemClicked. So call that handler
434 // ourselve
435 slotEvalItem(NULL);
438 void KDEDConfig::slotServiceRunningToggled()
440 getServiceStatus();
441 slotEvalItem(_lvStartup->currentItem());
444 void KDEDConfig::slotStartService()
446 QString service = _lvStartup->currentItem()->data( StartupService, LibraryRole ).toString();
448 QDBusInterface kdedInterface( "org.kde.kded", "/kded","org.kde.kded" );
449 QDBusReply<bool> reply = kdedInterface.call( "loadModule", service );
451 if ( reply.isValid() ) {
452 if ( reply.value() )
453 slotServiceRunningToggled();
454 else
455 KMessageBox::error(this, "<qt>" + i18n("Unable to start server <em>%1</em>.", service) + "</qt>");
457 else {
458 KMessageBox::error(this, "<qt>" + i18n("Unable to start service <em>%1</em>.<br /><br /><i>Error: %2</i>",
459 service, reply.error().message()) + "</qt>" );
463 void KDEDConfig::slotStopService()
465 QString service = _lvStartup->currentItem()->data( StartupService, LibraryRole ).toString();
466 kDebug() << "Stopping: " << service;
468 QDBusInterface kdedInterface( "org.kde.kded", "/kded", "org.kde.kded" );
469 QDBusReply<bool> reply = kdedInterface.call( "unloadModule", service );
471 if ( reply.isValid() ) {
472 if ( reply.value() )
473 slotServiceRunningToggled();
474 else
475 KMessageBox::error(this, "<qt>" + i18n("Unable to stop server <em>%1</em>.", service) + "</qt>");
477 else {
478 KMessageBox::error(this, "<qt>" + i18n("Unable to stop service <em>%1</em>.<br /><br /><i>Error: %2</i>",
479 service, reply.error().message()) + "</qt>" );
483 void KDEDConfig::slotItemChecked(QTreeWidgetItem*, int column)
485 // We only listen to changes the user did.
486 if (column==StartupUse) {
487 emit changed(true);