KUtils
kcmultidialog.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (c) 2000 Matthias Elter <elter@kde.org> 00003 Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org> 00004 Copyright (c) 2003,2006 Matthias Kretz <kretz@kde.org> 00005 Copyright (c) 2004 Frans Englich <frans.englich@telia.com> 00006 Copyright (c) 2006 Tobias Koenig <tokoe@kde.org> 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00021 Boston, MA 02110-1301, USA. 00022 00023 */ 00024 00025 #include "kcmultidialog.h" 00026 #include "kcmultidialog_p.h" 00027 00028 #include <QtCore/QStringList> 00029 #include <QtCore/QProcess> 00030 00031 #include <kauthorized.h> 00032 #include <kguiitem.h> 00033 #include <khbox.h> 00034 #include <kicon.h> 00035 #include <klocale.h> 00036 #include <kpagewidgetmodel.h> 00037 #include <kpushbutton.h> 00038 #include <ktoolinvocation.h> 00039 #include <kdebug.h> 00040 #include <kmessagebox.h> 00041 00042 #include "auth/kauthaction.h" 00043 00044 #include "kcolorscheme.h" 00045 00046 #include "kcmoduleloader.h" 00047 #include "kcmoduleproxy.h" 00048 00049 bool KCMultiDialogPrivate::resolveChanges(KCModuleProxy *currentProxy) 00050 { 00051 Q_Q(KCMultiDialog); 00052 if( !currentProxy || !currentProxy->changed() ) { 00053 return true; 00054 } 00055 00056 // Let the user decide 00057 const int queryUser = KMessageBox::warningYesNoCancel( 00058 q, 00059 i18n("The settings of the current module have changed.\n" 00060 "Do you want to apply the changes or discard them?"), 00061 i18n("Apply Settings"), 00062 KStandardGuiItem::apply(), 00063 KStandardGuiItem::discard(), 00064 KStandardGuiItem::cancel()); 00065 00066 switch (queryUser) { 00067 case KMessageBox::Yes: 00068 return moduleSave(currentProxy); 00069 00070 case KMessageBox::No: 00071 currentProxy->load(); 00072 return true; 00073 00074 case KMessageBox::Cancel: 00075 return false; 00076 00077 default: 00078 Q_ASSERT(false); 00079 return false; 00080 } 00081 } 00082 00083 void KCMultiDialogPrivate::_k_slotCurrentPageChanged( KPageWidgetItem *current, KPageWidgetItem *previous ) 00084 { 00085 Q_Q(KCMultiDialog); 00086 kDebug(710); 00087 00088 q->blockSignals(true); 00089 q->setCurrentPage(previous); 00090 00091 KCModuleProxy *previousModule = 0; 00092 for ( int i = 0; i < modules.count(); ++i ) { 00093 if ( modules[ i ].item == previous ) { 00094 previousModule = modules[ i ].kcm; 00095 break; 00096 } 00097 } 00098 00099 if( resolveChanges(previousModule) ) { 00100 q->setCurrentPage(current); 00101 } 00102 q->blockSignals(false); 00103 00104 // We need to get the state of the now active module 00105 _k_clientChanged(); 00106 } 00107 00108 void KCMultiDialogPrivate::_k_clientChanged() 00109 { 00110 Q_Q(KCMultiDialog); 00111 kDebug(710); 00112 // Get the current module 00113 KCModuleProxy *activeModule = 0; 00114 for ( int i = 0; i < modules.count(); ++i ) { 00115 if ( modules[ i ].item == q->currentPage() ) { 00116 activeModule = modules[ i ].kcm; 00117 break; 00118 } 00119 } 00120 00121 bool change = false; 00122 if (activeModule) { 00123 change = activeModule->changed(); 00124 00125 if (q->button(KDialog::Apply)) { 00126 q->disconnect(q, SIGNAL(applyClicked()), q, SLOT(slotApplyClicked())); 00127 q->disconnect(q->button(KDialog::Apply), SIGNAL(authorized(KAuth::Action*)), q, SLOT(slotApplyClicked())); 00128 q->button(KDialog::Apply)->setEnabled(change); 00129 } 00130 00131 if (q->button(KDialog::Ok)) { 00132 q->disconnect(q, SIGNAL(okClicked()), q, SLOT(slotOkClicked())); 00133 q->disconnect(q->button(KDialog::Ok), SIGNAL(authorized(KAuth::Action*)), q, SLOT(slotOkClicked())); 00134 } 00135 00136 if (activeModule->realModule()->needsAuthorization()) { 00137 if (q->button(KDialog::Apply)) { 00138 q->button(KDialog::Apply)->setAuthAction(activeModule->realModule()->authAction()); 00139 activeModule->realModule()->authAction()->setParentWidget(activeModule->realModule()); 00140 q->connect(q->button(KDialog::Apply), SIGNAL(authorized(KAuth::Action*)), SLOT(slotApplyClicked())); 00141 } 00142 00143 if (q->button(KDialog::Ok)) { 00144 q->button(KDialog::Ok)->setAuthAction(activeModule->realModule()->authAction()); 00145 activeModule->realModule()->authAction()->setParentWidget(activeModule->realModule()); 00146 q->connect(q->button(KDialog::Ok), SIGNAL(authorized(KAuth::Action*)), SLOT(slotOkClicked())); 00147 } 00148 } else { 00149 if (q->button(KDialog::Apply)) { 00150 q->connect(q, SIGNAL(applyClicked()), SLOT(slotApplyClicked())); 00151 q->button(KDialog::Apply)->setAuthAction(0); 00152 } 00153 00154 if (q->button(KDialog::Ok)) { 00155 q->connect(q, SIGNAL(okClicked()), SLOT(slotOkClicked())); 00156 q->button(KDialog::Ok)->setAuthAction(0); 00157 } 00158 } 00159 } 00160 00161 if (q->button(KDialog::Reset)) { 00162 q->button(KDialog::Reset)->setEnabled(change); 00163 } 00164 00165 if (q->button(KDialog::Apply)) { 00166 q->button(KDialog::Apply)->setEnabled(change); 00167 } 00168 00169 if (activeModule) { 00170 q->enableButton(KDialog::Help, activeModule->buttons() & KCModule::Help); 00171 q->enableButton(KDialog::Default, activeModule->buttons() & KCModule::Default); 00172 } 00173 } 00174 00175 void KCMultiDialogPrivate::_k_updateHeader(bool use, const QString &message) 00176 { 00177 Q_Q(KCMultiDialog); 00178 KPageWidgetItem *item = q->currentPage(); 00179 KCModuleProxy *kcm = qobject_cast<KCModuleProxy*>(item->widget()); 00180 00181 if (use) { 00182 item->setHeader( "<b>"+kcm->moduleInfo().comment() + "</b><br><i>" + 00183 message + "</i>" ); 00184 item->setIcon( KIcon( kcm->moduleInfo().icon(), 0, QStringList() << "dialog-warning" ) ); 00185 } else { 00186 item->setHeader( kcm->moduleInfo().comment() ); 00187 item->setIcon( KIcon( kcm->moduleInfo().icon() ) ); 00188 } 00189 } 00190 00191 void KCMultiDialogPrivate::_k_dialogClosed() 00192 { 00193 kDebug(710) ; 00194 00200 for ( int i = 0; i < modules.count(); ++i ) 00201 modules[ i ].kcm->deleteClient(); 00202 } 00203 00204 void KCMultiDialogPrivate::init() 00205 { 00206 Q_Q(KCMultiDialog); 00207 q->setFaceType(KPageDialog::Auto); 00208 q->setCaption(i18n("Configure")); 00209 q->setButtons(KDialog::Help | KDialog::Default |KDialog::Cancel | KDialog::Apply | KDialog::Ok | KDialog::Reset); 00210 00211 q->setModal(false); 00212 00213 q->connect(q, SIGNAL(finished()), SLOT(_k_dialogClosed())); 00214 q->connect(q, SIGNAL(applyClicked()), SLOT(slotApplyClicked())); 00215 q->connect(q, SIGNAL(okClicked()), SLOT(slotOkClicked())); 00216 q->connect(q, SIGNAL(defaultClicked()), SLOT(slotDefaultClicked())); 00217 q->connect(q, SIGNAL(helpClicked()), SLOT(slotHelpClicked())); 00218 q->connect(q, SIGNAL(user1Clicked()), SLOT(slotUser1Clicked())); 00219 q->connect(q, SIGNAL(resetClicked()), SLOT(slotUser1Clicked())); 00220 00221 q->connect(q, SIGNAL(currentPageChanged(KPageWidgetItem*, KPageWidgetItem*)), 00222 SLOT(_k_slotCurrentPageChanged(KPageWidgetItem*, KPageWidgetItem*))); 00223 00224 q->setInitialSize(QSize(800, 550)); 00225 } 00226 00227 KCMultiDialog::KCMultiDialog( QWidget *parent ) 00228 : KPageDialog(*new KCMultiDialogPrivate, NULL, parent) 00229 { 00230 d_func()->init(); 00231 } 00232 00233 KCMultiDialog::KCMultiDialog(KPageWidget *pageWidget, QWidget *parent, Qt::WFlags flags) 00234 : KPageDialog(*new KCMultiDialogPrivate, pageWidget, parent, flags) 00235 { 00236 d_func()->init(); 00237 } 00238 00239 KCMultiDialog::KCMultiDialog(KCMultiDialogPrivate &dd, KPageWidget *pageWidget, QWidget *parent, Qt::WFlags flags) 00240 : KPageDialog(dd, pageWidget, parent, flags) 00241 { 00242 d_func()->init(); 00243 } 00244 00245 KCMultiDialog::~KCMultiDialog() 00246 { 00247 } 00248 00249 void KCMultiDialog::slotDefaultClicked() 00250 { 00251 Q_D(KCMultiDialog); 00252 const KPageWidgetItem *item = currentPage(); 00253 if ( !item ) 00254 return; 00255 00256 for ( int i = 0; i < d->modules.count(); ++i ) { 00257 if ( d->modules[ i ].item == item ) { 00258 d->modules[ i ].kcm->defaults(); 00259 d->_k_clientChanged(); 00260 return; 00261 } 00262 } 00263 } 00264 00265 void KCMultiDialog::slotUser1Clicked() 00266 { 00267 const KPageWidgetItem *item = currentPage(); 00268 if ( !item ) 00269 return; 00270 00271 Q_D(KCMultiDialog); 00272 for ( int i = 0; i < d->modules.count(); ++i ) { 00273 if ( d->modules[ i ].item == item ) { 00274 d->modules[ i ].kcm->load(); 00275 d->_k_clientChanged(); 00276 return; 00277 } 00278 } 00279 } 00280 00281 bool KCMultiDialogPrivate::moduleSave(KCModuleProxy *module) 00282 { 00283 if( !module ) { 00284 return false; 00285 } 00286 00287 module->save(); 00288 return true; 00289 } 00290 00291 void KCMultiDialogPrivate::apply() 00292 { 00293 Q_Q(KCMultiDialog); 00294 QStringList updatedComponents; 00295 00296 foreach (const CreatedModule &module, modules) { 00297 KCModuleProxy *proxy = module.kcm; 00298 00299 if (proxy->changed()) { 00300 proxy->save(); 00305 const QStringList componentNames = module.componentNames; 00306 foreach (const QString &componentName, module.componentNames) { 00307 if (!updatedComponents.contains(componentName)) { 00308 updatedComponents.append(componentName); 00309 } 00310 } 00311 } 00312 } 00313 00314 // Send the configCommitted signal for every updated component. 00315 foreach (const QString &name, updatedComponents) { 00316 emit q->configCommitted(name.toLatin1()); 00317 } 00318 00319 emit q->configCommitted(); 00320 } 00321 00322 void KCMultiDialog::slotApplyClicked() 00323 { 00324 setButtonFocus( Apply ); 00325 00326 d_func()->apply(); 00327 } 00328 00329 00330 void KCMultiDialog::slotOkClicked() 00331 { 00332 setButtonFocus( Ok ); 00333 00334 d_func()->apply(); 00335 accept(); 00336 } 00337 00338 void KCMultiDialog::slotHelpClicked() 00339 { 00340 const KPageWidgetItem *item = currentPage(); 00341 if ( !item ) 00342 return; 00343 00344 Q_D(KCMultiDialog); 00345 QString docPath; 00346 for ( int i = 0; i < d->modules.count(); ++i ) { 00347 if ( d->modules[ i ].item == item ) { 00348 docPath = d->modules[ i ].kcm->moduleInfo().docPath(); 00349 break; 00350 } 00351 } 00352 00353 KUrl docUrl( KUrl( "help:/" ), docPath ); 00354 if ( docUrl.protocol() == "help" || docUrl.protocol() == "man" || docUrl.protocol() == "info" ) { 00355 QProcess::startDetached("khelpcenter", QStringList() << docUrl.url()); 00356 } else { 00357 KToolInvocation::invokeBrowser( docUrl.url() ); 00358 } 00359 } 00360 00361 00362 KPageWidgetItem* KCMultiDialog::addModule( const QString& path, const QStringList& args ) 00363 { 00364 QString complete = path; 00365 00366 if ( !path.endsWith( QLatin1String(".desktop") ) ) 00367 complete += ".desktop"; 00368 00369 KService::Ptr service = KService::serviceByStorageId( complete ); 00370 00371 return addModule( KCModuleInfo( service ), 0, args ); 00372 } 00373 00374 KPageWidgetItem* KCMultiDialog::addModule( const KCModuleInfo& moduleInfo, 00375 KPageWidgetItem *parentItem, const QStringList& args ) 00376 { 00377 if ( !moduleInfo.service() ) 00378 return 0; 00379 00380 //KAuthorized::authorizeControlModule( moduleInfo.service()->menuId() ) is 00381 //checked in noDisplay already 00382 if ( moduleInfo.service()->noDisplay() ) 00383 return 0; 00384 00385 KCModuleProxy *kcm = new KCModuleProxy(moduleInfo, 0, args); 00386 00387 kDebug(710) << moduleInfo.moduleName(); 00388 KPageWidgetItem *item = new KPageWidgetItem(kcm, moduleInfo.moduleName()); 00389 00390 if (kcm->useRootOnlyMessage()) { 00391 item->setHeader( "<b>"+moduleInfo.comment() + "</b><br><i>" + kcm->rootOnlyMessage() + "</i>" ); 00392 item->setIcon( KIcon( moduleInfo.icon(), 0, QStringList() << "dialog-warning" ) ); 00393 } else { 00394 item->setHeader( moduleInfo.comment() ); 00395 item->setIcon( KIcon( moduleInfo.icon() ) ); 00396 } 00397 item->setProperty("_k_weight", moduleInfo.weight()); 00398 00399 bool updateCurrentPage = false; 00400 const KPageWidgetModel *model = qobject_cast<const KPageWidgetModel *>(pageWidget()->model()); 00401 Q_ASSERT(model); 00402 if (parentItem) { 00403 const QModelIndex parentIndex = model->index(parentItem); 00404 const int siblingCount = model->rowCount(parentIndex); 00405 int row = 0; 00406 for (; row < siblingCount; ++row) { 00407 KPageWidgetItem *siblingItem = model->item(parentIndex.child(row, 0)); 00408 if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) { 00409 // the item we found is heavier than the new module 00410 kDebug(710) << "adding KCM " << item->name() << " before " << siblingItem->name(); 00411 insertPage(siblingItem, item); 00412 break; 00413 } 00414 } 00415 if (row >= siblingCount) { 00416 // the new module is either the first or the heaviest item 00417 kDebug(710) << "adding KCM " << item->name() << " with parent " << parentItem->name(); 00418 addSubPage(parentItem, item); 00419 } 00420 } else { 00421 const int siblingCount = model->rowCount(); 00422 int row = 0; 00423 for (; row < siblingCount; ++row) { 00424 KPageWidgetItem *siblingItem = model->item(model->index(row, 0)); 00425 if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) { 00426 // the item we found is heavier than the new module 00427 kDebug(710) << "adding KCM " << item->name() << " before " << siblingItem->name(); 00428 insertPage(siblingItem, item); 00429 if ( siblingItem == currentPage() ) 00430 updateCurrentPage = true; 00431 00432 break; 00433 } 00434 } 00435 if (row == siblingCount) { 00436 // the new module is either the first or the heaviest item 00437 kDebug(710) << "adding KCM " << item->name() << " at the top level"; 00438 addPage(item); 00439 } 00440 } 00441 00442 connect(kcm, SIGNAL(changed(bool)), this, SLOT(_k_clientChanged())); 00443 connect(kcm->realModule(), SIGNAL(rootOnlyMessageChanged(bool,QString)), this, SLOT(_k_updateHeader(bool,QString))); 00444 00445 Q_D(KCMultiDialog); 00446 KCMultiDialogPrivate::CreatedModule cm; 00447 cm.kcm = kcm; 00448 cm.item = item; 00449 cm.componentNames = moduleInfo.service()->property( "X-KDE-ParentComponents" ).toStringList(); 00450 d->modules.append( cm ); 00451 00452 if ( d->modules.count() == 1 || updateCurrentPage ) 00453 { 00454 setCurrentPage( item ); 00455 d->_k_clientChanged(); 00456 } 00457 return item; 00458 } 00459 00460 void KCMultiDialog::clear() 00461 { 00462 Q_D(KCMultiDialog); 00463 kDebug( 710 ) ; 00464 00465 for ( int i = 0; i < d->modules.count(); ++i ) { 00466 removePage( d->modules[ i ].item ); 00467 delete d->modules[ i ].kcm; 00468 } 00469 00470 d->modules.clear(); 00471 00472 d->_k_clientChanged(); 00473 } 00474 00475 void KCMultiDialog::setButtons(ButtonCodes buttonMask) 00476 { 00477 KPageDialog::setButtons(buttonMask); 00478 00479 // Set Auto-Default mode ( KDE Bug #211187 ) 00480 if (buttonMask & KDialog::Ok) { 00481 button(KDialog::Ok)->setAutoDefault(true); 00482 } 00483 if (buttonMask & KDialog::Apply) { 00484 button(KDialog::Apply)->setAutoDefault(true); 00485 } 00486 if (buttonMask & KDialog::Default) { 00487 button(KDialog::Default)->setAutoDefault(true); 00488 } 00489 if (buttonMask & KDialog::Reset) { 00490 button(KDialog::Reset)->setAutoDefault(true); 00491 } 00492 if (buttonMask & KDialog::Cancel) { 00493 button(KDialog::Cancel)->setAutoDefault(true); 00494 } 00495 if (buttonMask & KDialog::Help) { 00496 button(KDialog::Help)->setAutoDefault(true); 00497 } 00498 00499 // Old Reset Button 00500 enableButton(KDialog::User1, false); 00501 enableButton(KDialog::Reset, false); 00502 enableButton(KDialog::Apply, false); 00503 } 00504 00505 00506 #include "kcmultidialog.moc"
KDE 4.6 API Reference