KUtils
kcmoduleproxy.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2004 Frans Englich <frans.englich@telia.com> 00003 Copyright (C) 2003 Matthias Kretz <kretz@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "kcmoduleproxy.h" 00021 #include "kcmoduleproxy_p.h" 00022 00023 #include <QtGui/QApplication> 00024 #include <QtGui/QCursor> 00025 #include <QtCore/QDataStream> 00026 #include <QtGui/QKeyEvent> 00027 #include <QtCore/QFileInfo> 00028 #include <QtGui/QFrame> 00029 #include <QtGui/QLabel> 00030 #include <QtGui/QLayout> 00031 #include <QtCore/QPoint> 00032 00033 #include <QtGui/QImage> 00034 00035 #include <QtDBus/QtDBus> 00036 00037 #include <kaboutdata.h> 00038 #include <kcmodule.h> 00039 #include <kcmoduleinfo.h> 00040 00041 #include <kdebug.h> 00042 #include <kdialog.h> 00043 #include <klocale.h> 00044 #include <kservice.h> 00045 #include <kstandarddirs.h> 00046 #include <kuser.h> 00047 00048 #include <kvbox.h> 00049 00050 #include <kcmoduleloader.h> 00051 00052 #include "kcolorscheme.h" 00053 00054 #include "ksettingswidgetadaptor.h" 00055 00056 /* 00057 TODO: 00058 00059 - Two Layout problems in runAsRoot: 00060 * lblBusy doesn't show 00061 * d->kcm/d->rootInfo doesn't get it right when the user 00062 presses cancel in the kdesu dialog 00063 00064 - Resizing horizontally is contrained; minimum size is set somewhere. 00065 It appears to be somehow derived from the module's size. 00066 00067 - Prettify: set icon in KCMultiDialog. 00068 00069 */ 00070 /***************************************************************/ 00071 KCModule* KCModuleProxy::realModule() const 00072 { 00073 Q_D(const KCModuleProxy); 00074 /* 00075 * Note, don't call any function that calls realModule() since 00076 * that leads to an infinite loop. 00077 */ 00078 00079 /* Already loaded */ 00080 if( !d->kcm ) 00081 { 00082 QApplication::setOverrideCursor( Qt::WaitCursor ); 00083 const_cast<KCModuleProxyPrivate *>(d)->loadModule(); 00084 QApplication::restoreOverrideCursor(); 00085 } 00086 return d->kcm; 00087 } 00088 00089 void KCModuleProxyPrivate::loadModule() 00090 { 00091 if( !topLayout ) 00092 { 00093 topLayout = new QVBoxLayout( parent ); 00094 topLayout->setMargin( 0 ); 00095 00096 QString name = modInfo.handle(); 00097 dbusPath = QLatin1String("/internal/KSettingsWidget/") + name; 00098 dbusService = QLatin1String("org.kde.internal.KSettingsWidget-") + name; 00099 } 00100 00101 if( QDBusConnection::sessionBus().registerService( dbusService ) || bogusOccupier ) 00102 { /* We got the name we requested, because no one was before us, 00103 * or, it was an random application which had picked that name */ 00104 kDebug(711) << "Module not already loaded, loading module " << modInfo.moduleName() << " from library " << modInfo.library() << " using symbol " << modInfo.handle(); 00105 00106 kcm = KCModuleLoader::loadModule( modInfo, KCModuleLoader::Inline, parent, args ); 00107 00108 QObject::connect(kcm, SIGNAL(changed(bool)), parent, SLOT(_k_moduleChanged(bool))); 00109 QObject::connect(kcm, SIGNAL(destroyed()), parent, SLOT(_k_moduleDestroyed())); 00110 QObject::connect( kcm, SIGNAL(quickHelpChanged()), parent, SIGNAL(quickHelpChanged()) ); 00111 parent->setWhatsThis( kcm->quickHelp() ); 00112 00113 if ( kcm->layout() ) { 00114 kcm->layout()->setMargin( 0 ); 00115 } 00116 topLayout->addWidget( kcm ); 00117 if( !modInfo.handle().isEmpty() ) 00118 QDBusConnection::sessionBus().registerObject(dbusPath, new KSettingsWidgetAdaptor(parent), QDBusConnection::ExportAllSlots); 00119 00120 if ( !rootInfo && /* If it's not already done */ 00121 kcm->useRootOnlyMessage() && /* kcm wants root message */ 00122 !KUser().isSuperUser() ) /* Not necessary if we're root */ 00123 { 00124 /*rootInfo = new QLabel( parent ); 00125 topLayout->insertWidget( 0, rootInfo ); 00126 00127 QPalette palette = rootInfo->palette(); 00128 KStatefulBrush stbrush(KColorScheme::Window, KColorScheme::NeutralBackground); 00129 qDebug() << stbrush.brush(rootInfo); 00130 palette.setBrush(QPalette::Window, stbrush.brush(rootInfo)); 00131 rootInfo->setPalette(palette); 00132 rootInfo->setAutoFillBackground(true); 00133 00134 const QString message = kcm->rootOnlyMessage(); 00135 if( message.isEmpty() ) 00136 rootInfo->setText( i18n( 00137 "<b>Changes in this section require root access.</b><br />" 00138 "On applying your changes you will have to supply your root " 00139 "password." ) ); 00140 else 00141 rootInfo->setText(message); 00142 00143 rootInfo->setWhatsThis( i18n( 00144 "This section requires special permissions, probably " 00145 "for system-wide changes; therefore, it is " 00146 "required that you provide the root password to be " 00147 "able to change the module's properties. If " 00148 "you cannot provide the password, the changes of the " 00149 "module cannot be saved " ) );*/ 00150 } 00151 } 00152 else 00153 { 00154 kDebug(711) << "Module already loaded, loading KCMError"; 00155 00156 /* Figure out the name of where the module is already loaded */ 00157 QDBusInterface proxy( dbusService, dbusPath, "org.kde.internal.KSettingsWidget" ); 00158 QDBusReply<QString> reply = proxy.call("applicationName"); 00159 00160 if( reply.isValid() ) 00161 { 00162 QObject::connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), 00163 parent, SLOT(_k_ownerChanged(QString,QString,QString))); 00164 kcm = KCModuleLoader::reportError( KCModuleLoader::Inline, 00165 i18nc( "Argument is application name", "This configuration section is " 00166 "already opened in %1" , reply.value() ), " ", parent ); 00167 topLayout->addWidget( kcm ); 00168 } 00169 else 00170 { 00171 kDebug(711) << "Calling KCModuleProxy's DBus interface for fetching the name failed."; 00172 bogusOccupier = true; 00173 loadModule(); 00174 } 00175 } 00176 } 00177 00178 void KCModuleProxyPrivate::_k_ownerChanged(const QString &service, const QString &oldOwner, const QString &) 00179 { 00180 if (service == dbusService && !oldOwner.isEmpty()) { 00181 // Violence: Get rid of KCMError & CO, so that 00182 // realModule() attempts to reload the module 00183 delete kcm; 00184 kcm = 0; 00185 Q_Q(KCModuleProxy); 00186 q->realModule(); 00187 00188 Q_ASSERT(kcm); 00189 kcm->show(); 00190 } 00191 } 00192 00193 void KCModuleProxy::showEvent( QShowEvent * ev ) 00194 { 00195 Q_D(KCModuleProxy); 00196 00197 ( void )realModule(); 00198 00199 /* We have no kcm, if we're in root mode */ 00200 if( d->kcm ) { 00201 d->kcm->showEvent(ev); 00202 } 00203 00204 QWidget::showEvent( ev ); 00205 00206 } 00207 00208 KCModuleProxy::~KCModuleProxy() 00209 { 00210 deleteClient(); 00211 KCModuleLoader::unloadModule(moduleInfo()); 00212 00213 delete d_ptr; 00214 } 00215 00216 void KCModuleProxy::deleteClient() 00217 { 00218 Q_D(KCModuleProxy); 00219 delete d->kcm; 00220 d->kcm = 0; 00221 00222 qApp->syncX(); 00223 } 00224 00225 void KCModuleProxyPrivate::_k_moduleChanged(bool c) 00226 { 00227 if(changed == c) { 00228 return; 00229 } 00230 00231 Q_Q(KCModuleProxy); 00232 changed = c; 00233 emit q->changed(c); 00234 emit q->changed(q); 00235 } 00236 00237 void KCModuleProxyPrivate::_k_moduleDestroyed() 00238 { 00239 kcm = 0; 00240 } 00241 00242 KCModuleProxy::KCModuleProxy( const KService::Ptr& service, QWidget * parent, 00243 const QStringList& args ) 00244 : QWidget(parent), d_ptr(new KCModuleProxyPrivate(this, KCModuleInfo(service), args)) 00245 { 00246 d_ptr->q_ptr = this; 00247 } 00248 00249 KCModuleProxy::KCModuleProxy( const KCModuleInfo& info, QWidget * parent, 00250 const QStringList& args ) 00251 : QWidget(parent), d_ptr(new KCModuleProxyPrivate(this, info, args)) 00252 { 00253 d_ptr->q_ptr = this; 00254 } 00255 00256 KCModuleProxy::KCModuleProxy( const QString& serviceName, QWidget * parent, 00257 const QStringList& args ) 00258 : QWidget(parent), d_ptr(new KCModuleProxyPrivate(this, KCModuleInfo(serviceName), args)) 00259 { 00260 d_ptr->q_ptr = this; 00261 } 00262 00263 00264 void KCModuleProxy::load() 00265 { 00266 Q_D(KCModuleProxy); 00267 if( realModule() ) 00268 { 00269 d->kcm->load(); 00270 d->_k_moduleChanged(false); 00271 } 00272 } 00273 00274 void KCModuleProxy::save() 00275 { 00276 Q_D(KCModuleProxy); 00277 if( d->changed && realModule() ) 00278 { 00279 d->kcm->save(); 00280 d->_k_moduleChanged(false); 00281 } 00282 } 00283 00284 void KCModuleProxy::defaults() 00285 { 00286 Q_D(KCModuleProxy); 00287 if( realModule() ) 00288 d->kcm->defaults(); 00289 } 00290 00291 QString KCModuleProxy::quickHelp() const 00292 { 00293 return realModule() ? realModule()->quickHelp() : QString(); 00294 } 00295 00296 const KAboutData * KCModuleProxy::aboutData() const 00297 { 00298 return realModule() ? realModule()->aboutData() : 0; 00299 } 00300 00301 KCModule::Buttons KCModuleProxy::buttons() const 00302 { 00303 if( realModule() ) 00304 return realModule()->buttons(); 00305 return KCModule::Buttons( KCModule::Help | KCModule::Default | KCModule::Apply ); 00306 } 00307 00308 QString KCModuleProxy::rootOnlyMessage() const 00309 { 00310 return realModule() ? realModule()->rootOnlyMessage() : QString(); 00311 } 00312 00313 bool KCModuleProxy::useRootOnlyMessage() const 00314 { 00315 return realModule() ? realModule()->useRootOnlyMessage() : true; 00316 } 00317 00318 KComponentData KCModuleProxy::componentData() const 00319 { 00320 return realModule() ? realModule()->componentData() : KComponentData(); 00321 } 00322 00323 bool KCModuleProxy::changed() const 00324 { 00325 Q_D(const KCModuleProxy); 00326 return d->changed; 00327 } 00328 00329 KCModuleInfo KCModuleProxy::moduleInfo() const 00330 { 00331 Q_D(const KCModuleProxy); 00332 return d->modInfo; 00333 } 00334 00335 QString KCModuleProxy::dbusService() const 00336 { 00337 Q_D(const KCModuleProxy); 00338 return d->dbusService; 00339 } 00340 00341 QString KCModuleProxy::dbusPath() const 00342 { 00343 Q_D(const KCModuleProxy); 00344 return d->dbusPath; 00345 } 00346 00347 QSize KCModuleProxy::minimumSizeHint() const 00348 { 00349 return QWidget::minimumSizeHint(); 00350 } 00351 00352 //X void KCModuleProxy::emitQuickHelpChanged() 00353 //X { 00354 //X emit quickHelpChanged(); 00355 //X } 00356 00357 /***************************************************************/ 00358 #include "kcmoduleproxy.moc" 00359 00360 // vim: ts=4
KDE 4.6 API Reference