I experience infinite loops when resizing the font choser dialog, or
[kdelibs.git] / kutils / kcmultidialog.cpp
blob5e832e317f237e74df2653e79a2ff3765971f56a
1 /*
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>
32 #include <kguiitem.h>
33 #include <khbox.h>
34 #include <kicon.h>
35 #include <klocale.h>
36 #include <kpagewidgetmodel.h>
37 #include <kpushbutton.h>
38 #include <ktoolinvocation.h>
39 #include <kdebug.h>
41 #include "kcmoduleloader.h"
42 #include "kcmoduleproxy.h"
44 void KCMultiDialogPrivate::_k_slotCurrentPageChanged( KPageWidgetItem *item )
46 kDebug(710) ;
48 if ( !item )
49 return;
51 KCModuleProxy *module = 0;
52 for ( int i = 0; i < modules.count(); ++i ) {
53 if ( modules[ i ].item == item ) {
54 module = modules[ i ].kcm;
55 break;
59 if ( !module )
60 return;
61 kDebug(710) << "found module for page: " << module->moduleInfo().moduleName();
63 currentModule = module;
65 Q_Q(KCMultiDialog);
66 q->enableButton(KDialog::Help, currentModule->buttons() & KCModule::Help);
67 q->enableButton(KDialog::Default, currentModule->buttons() & KCModule::Default);
70 void KCMultiDialogPrivate::_k_clientChanged()
72 Q_Q(KCMultiDialog);
73 for ( int i = 0; i < modules.count(); ++i ) {
74 if ( modules[ i ].kcm->changed() ) {
75 q->enableButton(KDialog::Apply, true);
76 return;
80 q->enableButton(KDialog::Apply, false);
83 void KCMultiDialogPrivate::_k_dialogClosed()
85 kDebug(710) ;
87 /**
88 * If we don't delete them, the DBUS registration stays, and trying to load the KCMs
89 * in other situations will lead to "module already loaded in Foo," while to the user
90 * doesn't appear so(the dialog is hidden)
92 for ( int i = 0; i < modules.count(); ++i )
93 modules[ i ].kcm->deleteClient();
96 void KCMultiDialogPrivate::init()
98 Q_Q(KCMultiDialog);
99 q->setFaceType(KPageDialog::Auto);
100 q->setCaption(i18n("Configure"));
101 q->setButtons(KDialog::Help | KDialog::Default |KDialog::Cancel | KDialog::Apply | KDialog::Ok | KDialog::User1);
102 q->setButtonGuiItem(KDialog::User1, KStandardGuiItem::reset());
103 q->setDefaultButton(KDialog::Ok);
104 q->setModal(false);
105 q->showButtonSeparator(true);
107 q->connect(q, SIGNAL(finished()), SLOT(_k_dialogClosed()));
109 q->showButton(KDialog::User1, false);
110 q->enableButton(KDialog::Apply, false);
112 q->connect(q, SIGNAL(currentPageChanged(KPageWidgetItem*, KPageWidgetItem*)),
113 SLOT(_k_slotCurrentPageChanged(KPageWidgetItem*)));
115 q->connect(q, SIGNAL(applyClicked()), SLOT(slotApplyClicked()));
116 q->connect(q, SIGNAL(okClicked()), SLOT(slotOkClicked()));
117 q->connect(q, SIGNAL(defaultClicked()), SLOT(slotDefaultClicked()));
118 q->connect(q, SIGNAL(helpClicked()), SLOT(slotHelpClicked()));
119 q->connect(q, SIGNAL(user1Clicked()), SLOT(slotUser1Clicked()));
121 q->setInitialSize(QSize(640, 480));
124 KCMultiDialog::KCMultiDialog( QWidget *parent )
125 : KPageDialog(*new KCMultiDialogPrivate, NULL, parent)
127 d_func()->init();
130 KCMultiDialog::KCMultiDialog(KPageWidget *pageWidget, QWidget *parent, Qt::WFlags flags)
131 : KPageDialog(*new KCMultiDialogPrivate, pageWidget, parent, flags)
133 d_func()->init();
136 KCMultiDialog::KCMultiDialog(KCMultiDialogPrivate &dd, KPageWidget *pageWidget, QWidget *parent, Qt::WFlags flags)
137 : KPageDialog(dd, pageWidget, parent, flags)
139 d_func()->init();
142 KCMultiDialog::~KCMultiDialog()
146 void KCMultiDialog::slotDefaultClicked()
148 Q_D(KCMultiDialog);
149 const KPageWidgetItem *item = currentPage();
150 if ( !item )
151 return;
153 for ( int i = 0; i < d->modules.count(); ++i ) {
154 if ( d->modules[ i ].item == item ) {
155 d->modules[ i ].kcm->defaults();
156 d->_k_clientChanged();
157 return;
162 void KCMultiDialog::slotUser1Clicked()
164 const KPageWidgetItem *item = currentPage();
165 if ( !item )
166 return;
168 Q_D(KCMultiDialog);
169 for ( int i = 0; i < d->modules.count(); ++i ) {
170 if ( d->modules[ i ].item == item ) {
171 d->modules[ i ].kcm->load();
172 d->_k_clientChanged();
173 return;
178 void KCMultiDialogPrivate::apply()
180 Q_Q(KCMultiDialog);
181 QStringList updatedComponents;
183 foreach (const CreatedModule &module, modules) {
184 KCModuleProxy *proxy = module.kcm;
186 if (proxy->changed()) {
187 proxy->save();
190 * Add name of the components the kcm belongs to the list
191 * of updated components.
193 const QStringList componentNames = module.componentNames;
194 foreach (const QString &componentName, module.componentNames) {
195 if (!updatedComponents.contains(componentName)) {
196 updatedComponents.append(componentName);
202 // Send the configCommitted signal for every updated component.
203 foreach (const QString &name, updatedComponents) {
204 emit q->configCommitted(name.toLatin1());
207 emit q->configCommitted();
210 void KCMultiDialog::slotApplyClicked()
212 setButtonFocus( Apply );
214 d_func()->apply();
218 void KCMultiDialog::slotOkClicked()
220 setButtonFocus( Ok );
222 d_func()->apply();
223 accept();
226 void KCMultiDialog::slotHelpClicked()
228 const KPageWidgetItem *item = currentPage();
229 if ( !item )
230 return;
232 Q_D(KCMultiDialog);
233 QString docPath;
234 for ( int i = 0; i < d->modules.count(); ++i ) {
235 if ( d->modules[ i ].item == item ) {
236 docPath = d->modules[ i ].kcm->moduleInfo().docPath();
237 break;
241 KUrl docUrl( KUrl( "help:/" ), docPath );
242 if ( docUrl.protocol() == "help" || docUrl.protocol() == "man" || docUrl.protocol() == "info" ) {
243 QProcess::startDetached("khelpcenter", QStringList() << docUrl.url());
244 } else {
245 KToolInvocation::invokeBrowser( docUrl.url() );
250 KPageWidgetItem* KCMultiDialog::addModule( const QString& path, const QStringList& args )
252 QString complete = path;
254 if ( !path.endsWith( ".desktop" ) )
255 complete += ".desktop";
257 KService::Ptr service = KService::serviceByStorageId( complete );
259 return addModule( KCModuleInfo( service ), 0, args );
262 KPageWidgetItem* KCMultiDialog::addModule( const KCModuleInfo& moduleInfo,
263 KPageWidgetItem *parentItem, const QStringList& args )
265 if ( !moduleInfo.service() )
266 return 0;
268 //KAuthorized::authorizeControlModule( moduleInfo.service()->menuId() ) is
269 //checked in noDisplay already
270 if ( moduleInfo.service()->noDisplay() )
271 return 0;
273 KCModuleProxy *kcm = new KCModuleProxy(moduleInfo, 0, args);
275 kDebug(710) << moduleInfo.moduleName();
276 KPageWidgetItem *item = new KPageWidgetItem(kcm, moduleInfo.moduleName());
277 item->setHeader( moduleInfo.comment() );
278 item->setIcon( KIcon( moduleInfo.icon() ) );
279 item->setProperty("_k_weight", moduleInfo.weight());
281 bool updateCurrentPage = false;
282 const KPageWidgetModel *model = qobject_cast<const KPageWidgetModel *>(pageWidget()->model());
283 Q_ASSERT(model);
284 if (parentItem) {
285 const QModelIndex parentIndex = model->index(parentItem);
286 const int siblingCount = model->rowCount(parentIndex);
287 int row = 0;
288 for (; row < siblingCount; ++row) {
289 KPageWidgetItem *siblingItem = model->item(parentIndex.child(row, 0));
290 if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) {
291 // the item we found is heavier than the new module
292 kDebug(710) << "adding KCM " << item->name() << " before " << siblingItem->name();
293 insertPage(siblingItem, item);
294 break;
297 if (row >= siblingCount) {
298 // the new module is either the first or the heaviest item
299 kDebug(710) << "adding KCM " << item->name() << " with parent " << parentItem->name();
300 addSubPage(parentItem, item);
302 } else {
303 const int siblingCount = model->rowCount();
304 int row = 0;
305 for (; row < siblingCount; ++row) {
306 KPageWidgetItem *siblingItem = model->item(model->index(row, 0));
307 if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) {
308 // the item we found is heavier than the new module
309 kDebug(710) << "adding KCM " << item->name() << " before " << siblingItem->name();
310 insertPage(siblingItem, item);
311 if ( siblingItem == currentPage() )
312 updateCurrentPage = true;
314 break;
317 if (row == siblingCount) {
318 // the new module is either the first or the heaviest item
319 kDebug(710) << "adding KCM " << item->name() << " at the top level";
320 addPage(item);
324 connect(kcm, SIGNAL(changed(bool)), this, SLOT(_k_clientChanged()));
327 Q_D(KCMultiDialog);
328 KCMultiDialogPrivate::CreatedModule cm;
329 cm.kcm = kcm;
330 cm.item = item;
331 cm.componentNames = moduleInfo.service()->property( "X-KDE-ParentComponents" ).toStringList();
332 d->modules.append( cm );
334 if ( d->modules.count() == 1 || updateCurrentPage )
335 setCurrentPage( item );
337 return item;
340 void KCMultiDialog::clear()
342 Q_D(KCMultiDialog);
343 kDebug( 710 ) ;
345 for ( int i = 0; i < d->modules.count(); ++i ) {
346 removePage( d->modules[ i ].item );
347 delete d->modules[ i ].kcm;
350 d->modules.clear();
352 d->_k_clientChanged();
357 #include "kcmultidialog.moc"