2
Copyright (c) 2000 Matthias Elter <elter@kde.org>
3
Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>
4
Copyright (c) 2003,2006 Matthias Kretz <kretz@kde.org>
5
Copyright (c) 2004 Frans Englich <frans.englich@telia.com>
6
Copyright (c) 2006 Tobias Koenig <tokoe@kde.org>
8
This library is free software; you can redistribute it and/or
9
modify it under the terms of the GNU Library General Public
10
License as published by the Free Software Foundation; either
11
version 2 of the License, or (at your option) any later version.
13
This library is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
Library General Public License for more details.
18
You should have received a copy of the GNU Library General Public License
19
along with this library; see the file COPYING.LIB. If not, write to
20
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
Boston, MA 02110-1301, USA.
25
#include "kcmultidialog.h"
26
#include "kcmultidialog_p.h"
28
#include <QtCore/QStringList>
29
#include <QtCore/QProcess>
31
#include <kauthorized.h>
36
#include <kpagewidgetmodel.h>
37
#include <kpushbutton.h>
38
#include <ktoolinvocation.h>
40
#include <kmessagebox.h>
42
#include "auth/kauthaction.h"
44
#include "kcolorscheme.h"
46
#include "kcmoduleloader.h"
47
#include "kcmoduleproxy.h"
49
bool KCMultiDialogPrivate::resolveChanges(KCModuleProxy *currentProxy)
52
if( !currentProxy || !currentProxy->changed() ) {
56
// Let the user decide
57
const int queryUser = KMessageBox::warningYesNoCancel(
59
i18n("The settings of the current module have changed.\n"
60
"Do you want to apply the changes or discard them?"),
61
i18n("Apply Settings"),
62
KStandardGuiItem::apply(),
63
KStandardGuiItem::discard(),
64
KStandardGuiItem::cancel());
67
case KMessageBox::Yes:
68
return moduleSave(currentProxy);
74
case KMessageBox::Cancel:
83
void KCMultiDialogPrivate::_k_slotCurrentPageChanged( KPageWidgetItem *current, KPageWidgetItem *previous )
88
q->blockSignals(true);
89
q->setCurrentPage(previous);
91
KCModuleProxy *previousModule = 0;
92
for ( int i = 0; i < modules.count(); ++i ) {
93
if ( modules[ i ].item == previous ) {
94
previousModule = modules[ i ].kcm;
99
KCModuleProxy *currentModule = 0;
100
for ( int i = 0; i < modules.count(); ++i ) {
101
if ( modules[ i ].item == current ) {
102
currentModule = modules[ i ].kcm;
107
if ( !previousModule || !currentModule ) {
108
q->blockSignals(false);
112
if( resolveChanges(previousModule) ) {
113
q->setCurrentPage(current);
115
q->blockSignals(false);
117
// We need to get the state of the now active module
121
void KCMultiDialogPrivate::_k_clientChanged()
125
// Get the current module
126
KCModuleProxy *activeModule = 0;
127
for ( int i = 0; i < modules.count(); ++i ) {
128
if ( modules[ i ].item == q->currentPage() ) {
129
activeModule = modules[ i ].kcm;
136
change = activeModule->changed();
138
if (q->button(KDialog::Apply)) {
139
q->disconnect(q, SIGNAL(applyClicked()), q, SLOT(slotApplyClicked()));
140
q->disconnect(q->button(KDialog::Apply), SIGNAL(authorized(KAuth::Action*)), q, SLOT(slotApplyClicked()));
141
q->button(KDialog::Apply)->setEnabled(change);
144
if (q->button(KDialog::Ok)) {
145
q->disconnect(q, SIGNAL(okClicked()), q, SLOT(slotOkClicked()));
146
q->disconnect(q->button(KDialog::Ok), SIGNAL(authorized(KAuth::Action*)), q, SLOT(slotOkClicked()));
149
if (activeModule->realModule()->needsAuthorization()) {
150
if (q->button(KDialog::Apply)) {
151
q->button(KDialog::Apply)->setAuthAction(currentModule->realModule()->authAction());
152
q->connect(q->button(KDialog::Apply), SIGNAL(authorized(KAuth::Action*)), SLOT(slotApplyClicked()));
155
if (q->button(KDialog::Ok)) {
156
q->button(KDialog::Ok)->setAuthAction(currentModule->realModule()->authAction());
157
q->connect(q->button(KDialog::Ok), SIGNAL(authorized(KAuth::Action*)), SLOT(slotOkClicked()));
160
if (q->button(KDialog::Apply)) {
161
q->connect(q, SIGNAL(applyClicked()), SLOT(slotApplyClicked()));
162
q->button(KDialog::Apply)->setAuthAction(activeModule->realModule()->authAction());
165
if (q->button(KDialog::Ok)) {
166
q->connect(q, SIGNAL(okClicked()), SLOT(slotOkClicked()));
167
q->button(KDialog::Ok)->setAuthAction(activeModule->realModule()->authAction());
172
if (q->button(KDialog::Reset)) {
173
q->button(KDialog::Reset)->setEnabled(change);
176
if (q->button(KDialog::Apply)) {
177
q->button(KDialog::Apply)->setEnabled(change);
180
q->enableButton(KDialog::Help, activeModule->buttons() & KCModule::Help);
181
q->enableButton(KDialog::Default, activeModule->buttons() & KCModule::Default);
184
void KCMultiDialogPrivate::_k_updateHeader(bool use, const QString &message)
187
KPageWidgetItem *item = q->currentPage();
188
KCModuleProxy *kcm = qobject_cast<KCModuleProxy*>(item->widget());
191
item->setHeader( "<b>"+kcm->moduleInfo().comment() + "</b><br><i>" +
193
item->setIcon( KIcon( kcm->moduleInfo().icon(), 0, QStringList() << "dialog-warning" ) );
195
item->setHeader( kcm->moduleInfo().comment() );
196
item->setIcon( KIcon( kcm->moduleInfo().icon() ) );
200
void KCMultiDialogPrivate::_k_dialogClosed()
205
* If we don't delete them, the DBUS registration stays, and trying to load the KCMs
206
* in other situations will lead to "module already loaded in Foo," while to the user
207
* doesn't appear so(the dialog is hidden)
209
for ( int i = 0; i < modules.count(); ++i )
210
modules[ i ].kcm->deleteClient();
213
void KCMultiDialogPrivate::init()
216
q->setFaceType(KPageDialog::Auto);
217
q->setCaption(i18n("Configure"));
218
q->setButtons(KDialog::Help | KDialog::Default |KDialog::Cancel | KDialog::Apply | KDialog::Ok | KDialog::Reset);
222
q->connect(q, SIGNAL(finished()), SLOT(_k_dialogClosed()));
223
q->connect(q, SIGNAL(applyClicked()), SLOT(slotApplyClicked()));
224
q->connect(q, SIGNAL(okClicked()), SLOT(slotOkClicked()));
225
q->connect(q, SIGNAL(defaultClicked()), SLOT(slotDefaultClicked()));
226
q->connect(q, SIGNAL(helpClicked()), SLOT(slotHelpClicked()));
227
q->connect(q, SIGNAL(user1Clicked()), SLOT(slotUser1Clicked()));
228
q->connect(q, SIGNAL(resetClicked()), SLOT(slotUser1Clicked()));
230
q->connect(q, SIGNAL(currentPageChanged(KPageWidgetItem*, KPageWidgetItem*)),
231
SLOT(_k_slotCurrentPageChanged(KPageWidgetItem*, KPageWidgetItem*)));
233
q->setInitialSize(QSize(800, 550));
236
KCMultiDialog::KCMultiDialog( QWidget *parent )
237
: KPageDialog(*new KCMultiDialogPrivate, NULL, parent)
242
KCMultiDialog::KCMultiDialog(KPageWidget *pageWidget, QWidget *parent, Qt::WFlags flags)
243
: KPageDialog(*new KCMultiDialogPrivate, pageWidget, parent, flags)
248
KCMultiDialog::KCMultiDialog(KCMultiDialogPrivate &dd, KPageWidget *pageWidget, QWidget *parent, Qt::WFlags flags)
249
: KPageDialog(dd, pageWidget, parent, flags)
254
KCMultiDialog::~KCMultiDialog()
258
void KCMultiDialog::slotDefaultClicked()
261
const KPageWidgetItem *item = currentPage();
265
for ( int i = 0; i < d->modules.count(); ++i ) {
266
if ( d->modules[ i ].item == item ) {
267
d->modules[ i ].kcm->defaults();
268
d->_k_clientChanged();
274
void KCMultiDialog::slotUser1Clicked()
276
const KPageWidgetItem *item = currentPage();
281
for ( int i = 0; i < d->modules.count(); ++i ) {
282
if ( d->modules[ i ].item == item ) {
283
d->modules[ i ].kcm->load();
284
d->_k_clientChanged();
290
bool KCMultiDialogPrivate::moduleSave(KCModuleProxy *module)
300
void KCMultiDialogPrivate::apply()
303
QStringList updatedComponents;
305
foreach (const CreatedModule &module, modules) {
306
KCModuleProxy *proxy = module.kcm;
308
if (proxy->changed()) {
311
* Add name of the components the kcm belongs to the list
312
* of updated components.
314
const QStringList componentNames = module.componentNames;
315
foreach (const QString &componentName, module.componentNames) {
316
if (!updatedComponents.contains(componentName)) {
317
updatedComponents.append(componentName);
323
// Send the configCommitted signal for every updated component.
324
foreach (const QString &name, updatedComponents) {
325
emit q->configCommitted(name.toLatin1());
328
emit q->configCommitted();
331
void KCMultiDialog::slotApplyClicked()
333
setButtonFocus( Apply );
339
void KCMultiDialog::slotOkClicked()
341
setButtonFocus( Ok );
347
void KCMultiDialog::slotHelpClicked()
349
const KPageWidgetItem *item = currentPage();
355
for ( int i = 0; i < d->modules.count(); ++i ) {
356
if ( d->modules[ i ].item == item ) {
357
docPath = d->modules[ i ].kcm->moduleInfo().docPath();
362
KUrl docUrl( KUrl( "help:/" ), docPath );
363
if ( docUrl.protocol() == "help" || docUrl.protocol() == "man" || docUrl.protocol() == "info" ) {
364
QProcess::startDetached("khelpcenter", QStringList() << docUrl.url());
366
KToolInvocation::invokeBrowser( docUrl.url() );
371
KPageWidgetItem* KCMultiDialog::addModule( const QString& path, const QStringList& args )
373
QString complete = path;
375
if ( !path.endsWith( QLatin1String(".desktop") ) )
376
complete += ".desktop";
378
KService::Ptr service = KService::serviceByStorageId( complete );
380
return addModule( KCModuleInfo( service ), 0, args );
383
KPageWidgetItem* KCMultiDialog::addModule( const KCModuleInfo& moduleInfo,
384
KPageWidgetItem *parentItem, const QStringList& args )
386
if ( !moduleInfo.service() )
389
//KAuthorized::authorizeControlModule( moduleInfo.service()->menuId() ) is
390
//checked in noDisplay already
391
if ( moduleInfo.service()->noDisplay() )
394
KCModuleProxy *kcm = new KCModuleProxy(moduleInfo, 0, args);
396
kDebug(710) << moduleInfo.moduleName();
397
KPageWidgetItem *item = new KPageWidgetItem(kcm, moduleInfo.moduleName());
399
if (kcm->useRootOnlyMessage()) {
400
item->setHeader( "<b>"+moduleInfo.comment() + "</b><br><i>" + kcm->rootOnlyMessage() + "</i>" );
401
item->setIcon( KIcon( moduleInfo.icon(), 0, QStringList() << "dialog-warning" ) );
403
item->setHeader( moduleInfo.comment() );
404
item->setIcon( KIcon( moduleInfo.icon() ) );
406
item->setProperty("_k_weight", moduleInfo.weight());
408
bool updateCurrentPage = false;
409
const KPageWidgetModel *model = qobject_cast<const KPageWidgetModel *>(pageWidget()->model());
412
const QModelIndex parentIndex = model->index(parentItem);
413
const int siblingCount = model->rowCount(parentIndex);
415
for (; row < siblingCount; ++row) {
416
KPageWidgetItem *siblingItem = model->item(parentIndex.child(row, 0));
417
if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) {
418
// the item we found is heavier than the new module
419
kDebug(710) << "adding KCM " << item->name() << " before " << siblingItem->name();
420
insertPage(siblingItem, item);
424
if (row >= siblingCount) {
425
// the new module is either the first or the heaviest item
426
kDebug(710) << "adding KCM " << item->name() << " with parent " << parentItem->name();
427
addSubPage(parentItem, item);
430
const int siblingCount = model->rowCount();
432
for (; row < siblingCount; ++row) {
433
KPageWidgetItem *siblingItem = model->item(model->index(row, 0));
434
if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) {
435
// the item we found is heavier than the new module
436
kDebug(710) << "adding KCM " << item->name() << " before " << siblingItem->name();
437
insertPage(siblingItem, item);
438
if ( siblingItem == currentPage() )
439
updateCurrentPage = true;
444
if (row == siblingCount) {
445
// the new module is either the first or the heaviest item
446
kDebug(710) << "adding KCM " << item->name() << " at the top level";
451
connect(kcm, SIGNAL(changed(bool)), this, SLOT(_k_clientChanged()));
452
connect(kcm->realModule(), SIGNAL(rootOnlyMessageChanged(bool,QString)), this, SLOT(_k_updateHeader(bool,QString)));
455
KCMultiDialogPrivate::CreatedModule cm;
458
cm.componentNames = moduleInfo.service()->property( "X-KDE-ParentComponents" ).toStringList();
459
d->modules.append( cm );
461
if ( d->modules.count() == 1 || updateCurrentPage )
463
setCurrentPage( item );
464
d->_k_clientChanged();
469
void KCMultiDialog::clear()
474
for ( int i = 0; i < d->modules.count(); ++i ) {
475
removePage( d->modules[ i ].item );
476
delete d->modules[ i ].kcm;
481
d->_k_clientChanged();
484
void KCMultiDialog::setButtons(ButtonCodes buttonMask)
486
KPageDialog::setButtons(buttonMask);
488
// Set Auto-Default mode ( KDE Bug #211187 )
489
if (buttonMask & KDialog::Ok) {
490
button(KDialog::Ok)->setAutoDefault(true);
492
if (buttonMask & KDialog::Apply) {
493
button(KDialog::Apply)->setAutoDefault(true);
495
if (buttonMask & KDialog::Default) {
496
button(KDialog::Default)->setAutoDefault(true);
498
if (buttonMask & KDialog::Reset) {
499
button(KDialog::Reset)->setAutoDefault(true);
501
if (buttonMask & KDialog::Cancel) {
502
button(KDialog::Cancel)->setAutoDefault(true);
504
if (buttonMask & KDialog::Help) {
505
button(KDialog::Help)->setAutoDefault(true);
509
enableButton(KDialog::User1, false);
510
enableButton(KDialog::Reset, false);
511
enableButton(KDialog::Apply, false);
515
#include "kcmultidialog.moc"