kutils Library API Documentation

kcmoduleloader.cpp

00001 /* 00002 Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> 00003 Copyright (c) 2000 Matthias Elter <elter@kde.org> 00004 Copyright (c) 2003,2004 Matthias Kretz <kretz@kde.org> 00005 Copyright (c) 2004 Frans Englich <frans.englich@telia.com> 00006 00007 This file is part of the KDE project 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Library General Public 00011 License version 2, as published by the Free Software Foundation. 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., 59 Temple Place - Suite 330, 00021 Boston, MA 02111-1307, USA. 00022 */ 00023 00024 #include <qfile.h> 00025 #include <qlabel.h> 00026 #include <qlayout.h> 00027 00028 #include <kapplication.h> 00029 #include <kdebug.h> 00030 #include <klocale.h> 00031 #include <kmessagebox.h> 00032 #include <kparts/componentfactory.h> 00033 00034 #include "kcmoduleloader.h" 00035 00036 00037 /***************************************************************/ 00042 class KCMError : public KCModule 00043 { 00044 public: 00045 KCMError( const QString& msg, const QString& details, QWidget* parent ) 00046 : KCModule( parent, "KCMError" ) 00047 { 00048 QVBoxLayout* topLayout = new QVBoxLayout( this ); 00049 topLayout->addWidget( new QLabel( msg, this ) ); 00050 topLayout->addWidget( new QLabel( details, this ) ); 00051 } 00052 }; 00053 /***************************************************************/ 00054 00055 00056 00057 00058 KCModule* KCModuleLoader::load(const KCModuleInfo &mod, const QString &libname, 00059 KLibLoader *loader, ErrorReporting report, QWidget * parent, 00060 const char * name, const QStringList & args ) 00061 { 00062 // attempt to load modules with ComponentFactory, only if the symbol init_<lib> exists 00063 // (this is because some modules, e.g. kcmkio with multiple modules in the library, 00064 // cannot be ported to KGenericFactory) 00065 KLibrary *lib = loader->library(QFile::encodeName(libname.arg(mod.library()))); 00066 if (lib) { 00067 QString initSym("init_"); 00068 initSym += libname.arg(mod.library()); 00069 00070 if ( lib->hasSymbol(QFile::encodeName(initSym)) ) 00071 { 00072 KLibFactory *factory = lib->factory(); 00073 if ( factory ) 00074 { 00075 KCModule *module = KParts::ComponentFactory::createInstanceFromFactory<KCModule>( factory, parent, name ? name : mod.handle().latin1(), args ); 00076 if (module) 00077 return module; 00078 } 00079 // else do a fallback 00080 kdDebug(1208) << "Unable to load module using ComponentFactory. Falling back to old loader." << endl; 00081 } 00082 00083 // get the create_ function 00084 QString factory("create_%1"); 00085 void *create = lib->symbol(QFile::encodeName(factory.arg(mod.handle()))); 00086 00087 if (create) 00088 { 00089 // create the module 00090 KCModule* (*func)(QWidget *, const char *); 00091 func = (KCModule* (*)(QWidget *, const char *)) create; 00092 return func( parent, name ? name : mod.handle().latin1() ); 00093 } 00094 else 00095 { 00096 lib->unload(); 00097 return reportError( report, i18n("<qt>There was an error when loading the module '%1'.<br><br>" 00098 "The desktop file (%2) as well as the library (%3) was found but " 00099 "yet the module could not be loaded properly. Most likely " 00100 "the factory declaration was wrong, or the " 00101 "create_* function was missing.</qt>") 00102 .arg( mod.moduleName() ) 00103 .arg( mod.fileName() ) 00104 .arg( lib->fileName() ), 00105 QString::null, parent ); 00106 } 00107 00108 lib->unload(); 00109 } 00110 return reportError( report, i18n("The specified library %1 could not be found.") 00111 .arg( mod.library() ), QString::null, parent ); 00112 return 0; 00113 } 00114 00115 KCModule* KCModuleLoader::loadModule(const KCModuleInfo &mod, bool withfallback, QWidget * parent, const char * name, const QStringList & args ) 00116 { 00117 return loadModule( mod, None, withfallback, parent, name, args ); 00118 } 00119 00120 KCModule* KCModuleLoader::loadModule(const KCModuleInfo &mod, ErrorReporting report, bool withfallback, QWidget * parent, const char * name, const QStringList & args ) 00121 { 00122 /* 00123 * Simple libraries as modules are the easiest case: 00124 * We just have to load the library and get the module 00125 * from the factory. 00126 */ 00127 00128 if ( !mod.service() ) 00129 { 00130 return reportError( report, 00131 i18n("The module %1 could not be found.") 00132 .arg( mod.moduleName() ), i18n("<qt><p>The diagnostics is:<br>The desktop file %1 could not be found.</qt>").arg(mod.fileName()), parent ); 00133 } 00134 00135 if (!mod.library().isEmpty()) 00136 { 00137 // get the library loader instance 00138 00139 KLibLoader *loader = KLibLoader::self(); 00140 00141 KCModule *module = load(mod, "kcm_%1", loader, report, parent, name, args ); 00142 /* 00143 * Only try to load libkcm_* if it exists, otherwise KLibLoader::lastErrorMessage would say 00144 * "libkcm_foo not found" instead of the real problem with loading kcm_foo. 00145 */ 00146 if (!KLibLoader::findLibrary( QCString( "libkcm_" ) + QFile::encodeName( mod.library() ) ).isEmpty() ) 00147 module = load(mod, "libkcm_%1", loader, report, parent, name, args ); 00148 if (module) 00149 return module; 00150 return reportError( report, 00151 i18n("The module %1 could not be loaded.") 00152 .arg( mod.moduleName() ), QString::null, parent ); 00153 } 00154 00155 /* 00156 * Ok, we could not load the library. 00157 * Try to run it as an executable. 00158 * This must not be done when calling from kcmshell, or you'll 00159 * have infinite recursion 00160 * (startService calls kcmshell which calls modloader which calls startService...) 00161 * 00162 */ 00163 if(withfallback) 00164 { 00165 KApplication::startServiceByDesktopPath(mod.fileName(), QString::null); 00166 } 00167 else 00168 { 00169 return reportError( report, 00170 i18n("The module %1 is not a valid configuration module.") 00171 .arg( mod.moduleName() ), i18n("<qt><p>The diagnostics is:<br>The desktop file %1 does not specify a library.</qt>").arg(mod.fileName()), parent ); 00172 } 00173 00174 return 0; 00175 } 00176 00177 KCModule* KCModuleLoader::loadModule(const QString &module, QWidget *parent, 00178 const char *name, const QStringList & args) 00179 { 00180 return loadModule(KCModuleInfo(module), None, false, parent, name, args); 00181 } 00182 00183 KCModule* KCModuleLoader::loadModule(const QString &module, ErrorReporting 00184 report, QWidget *parent, const char *name, const QStringList & args) 00185 { 00186 return loadModule(KCModuleInfo(module), report, false, parent, name, args); 00187 } 00188 00189 void KCModuleLoader::unloadModule(const KCModuleInfo &mod) 00190 { 00191 // get the library loader instance 00192 KLibLoader *loader = KLibLoader::self(); 00193 00194 // try to unload the library 00195 QString libname("libkcm_%1"); 00196 loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library()))); 00197 00198 libname = "kcm_%1"; 00199 loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library()))); 00200 } 00201 00202 void KCModuleLoader::showLastLoaderError(QWidget *parent) 00203 { 00204 KMessageBox::detailedError(parent, 00205 i18n("There was an error loading the module."),i18n("<qt><p>The diagnostics is:<br>%1" 00206 "<p>Possible reasons:</p><ul><li>An error occurred during your last " 00207 "KDE upgrade leaving an orphaned control module<li>You have old third party " 00208 "modules lying around.</ul><p>Check these points carefully and try to remove " 00209 "the module mentioned in the error message. If this fails, consider contacting " 00210 "your distributor or packager.</p></qt>") 00211 .arg(KLibLoader::self()->lastErrorMessage())); 00212 00213 } 00214 00215 bool KCModuleLoader::testModule( const QString& module ) 00216 { 00217 return testModule( KCModuleInfo( module ) ); 00218 } 00219 00220 bool KCModuleLoader::testModule( const KCModuleInfo& module ) 00221 { 00222 if (!module.service()) 00223 { 00224 kdDebug(1208) << "Module '" << module.fileName() << "' not found." << endl; 00225 return true; 00226 } 00227 00228 bool doLoad = module.service()->property( "X-KDE-Test-Module", QVariant::Bool ).toBool(); 00229 if( !doLoad ) 00230 { 00231 return true; 00232 } 00233 else 00234 { 00241 KLibLoader* loader = KLibLoader::self(); 00242 KLibrary* library = loader->library( QFile::encodeName((QString("kcm_%1").arg(module.library()))) ); 00243 if( library ) 00244 { 00245 void *test_func = library->symbol( QString("test_%1").arg(module.factoryName()).utf8() ); 00246 if( test_func ) 00247 { 00248 bool (*func)() = (bool(*)())test_func; 00249 if( func() ) 00250 { 00251 return true; 00252 } 00253 else 00254 { 00255 return false; 00256 } 00257 } 00258 else 00259 { 00260 kdDebug(1208) << "The test function for module '" << module.fileName() << "' could not be found." << endl; 00261 return true; 00262 } 00263 } 00264 kdDebug(1208) << "The library '" << module.library() << "' could not be found." << endl; 00265 return true; 00266 } 00267 } 00268 00269 KCModule* KCModuleLoader::reportError( ErrorReporting report, const QString & text, 00270 QString details, QWidget * parent ) 00271 { 00272 if( details.isNull() ) 00273 details = i18n("<qt><p>The diagnostics is:<br>%1" 00274 "<p>Possible reasons:</p><ul><li>An error occurred during your last " 00275 "KDE upgrade leaving an orphaned control module<li>You have old third party " 00276 "modules lying around.</ul><p>Check these points carefully and try to remove " 00277 "the module mentioned in the error message. If this fails, consider contacting " 00278 "your distributor or packager.</p></qt>").arg(KLibLoader::self()->lastErrorMessage()); 00279 if( report & Dialog ) 00280 KMessageBox::detailedError( parent, text, details ); 00281 if( report & Inline ) 00282 return new KCMError( text, details, parent ); 00283 return 0; 00284 } 00285 00286 // vim: ts=2 sw=2 et 00287
KDE Logo
This file is part of the documentation for kutils Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:32:59 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003