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 Wed May 4 06:55:46 2005 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003