• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KUtils

kcmoduleloader.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00021   Boston, MA 02110-1301, 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       QString libFileName = lib->fileName();
00097       lib->unload();
00098       return reportError( report, i18n("<qt>There was an error when loading the module '%1'.<br><br>"
00099           "The desktop file (%2) as well as the library (%3) was found but "
00100           "yet the module could not be loaded properly. Most likely "
00101           "the factory declaration was wrong, or the "
00102           "create_* function was missing.</qt>")
00103           .arg( mod.moduleName() )
00104           .arg( mod.fileName() )
00105           .arg( libFileName ),
00106           QString::null, parent );
00107     }
00108 
00109     lib->unload();
00110   }
00111   return reportError( report, i18n("The specified library %1 could not be found.")
00112       .arg( mod.library() ), QString::null, parent );
00113   return 0;
00114 }
00115 
00116 KCModule* KCModuleLoader::loadModule(const KCModuleInfo &mod, bool withfallback, QWidget * parent, const char * name, const QStringList & args )
00117 {
00118   return loadModule( mod, None, withfallback, parent, name, args );
00119 }
00120 
00121 KCModule* KCModuleLoader::loadModule(const KCModuleInfo &mod, ErrorReporting report, bool withfallback, QWidget * parent, const char * name, const QStringList & args )
00122 {
00123   /*
00124    * Simple libraries as modules are the easiest case:
00125    *  We just have to load the library and get the module
00126    *  from the factory.
00127    */
00128 
00129   if ( !mod.service() )
00130   {
00131     return reportError( report,
00132         i18n("The module %1 could not be found.")
00133         .arg( mod.moduleName() ), i18n("<qt><p>The diagnostics is:<br>The desktop file %1 could not be found.</qt>").arg(mod.fileName()), parent );
00134   }
00135 
00136   if (!mod.library().isEmpty())
00137   {
00138     // get the library loader instance
00139 
00140     KLibLoader *loader = KLibLoader::self();
00141 
00142     KCModule *module = load(mod, "kcm_%1", loader, report, parent, name, args );
00143     /*
00144      * Only try to load libkcm_* if it exists, otherwise KLibLoader::lastErrorMessage would say
00145      * "libkcm_foo not found" instead of the real problem with loading kcm_foo.
00146      */
00147     if (!KLibLoader::findLibrary( QCString( "libkcm_" ) + QFile::encodeName( mod.library() ) ).isEmpty() )
00148       module = load(mod, "libkcm_%1", loader, report, parent, name, args );
00149     if (module)
00150       return module;
00151     return reportError( report,
00152         i18n("The module %1 could not be loaded.")
00153         .arg( mod.moduleName() ), QString::null, parent );
00154   }
00155 
00156   /*
00157    * Ok, we could not load the library.
00158    * Try to run it as an executable.
00159    * This must not be done when calling from kcmshell, or you'll
00160    * have infinite recursion
00161    * (startService calls kcmshell which calls modloader which calls startService...)
00162    *
00163    */
00164   if(withfallback)
00165   {
00166     KApplication::startServiceByDesktopPath(mod.fileName(), QString::null);
00167   }
00168   else
00169   {
00170     return reportError( report,
00171         i18n("The module %1 is not a valid configuration module.")
00172         .arg( mod.moduleName() ), i18n("<qt><p>The diagnostics is:<br>The desktop file %1 does not specify a library.</qt>").arg(mod.fileName()), parent );
00173   }
00174 
00175   return 0;
00176 }
00177 
00178 KCModule* KCModuleLoader::loadModule(const QString &module, QWidget *parent,
00179       const char *name, const QStringList & args)
00180 {
00181   return loadModule(KCModuleInfo(module), None, false, parent, name, args);
00182 }
00183 
00184 KCModule* KCModuleLoader::loadModule(const QString &module, ErrorReporting
00185     report, QWidget *parent, const char *name, const QStringList & args)
00186 {
00187   return loadModule(KCModuleInfo(module), report, false, parent, name, args);
00188 }
00189 
00190 void KCModuleLoader::unloadModule(const KCModuleInfo &mod)
00191 {
00192   // get the library loader instance
00193   KLibLoader *loader = KLibLoader::self();
00194 
00195   // try to unload the library
00196   QString libname("libkcm_%1");
00197   loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library())));
00198 
00199   libname = "kcm_%1";
00200   loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library())));
00201 }
00202 
00203 void KCModuleLoader::showLastLoaderError(QWidget *parent)
00204 {
00205   KMessageBox::detailedError(parent,
00206       i18n("There was an error loading the module."),i18n("<qt><p>The diagnostics is:<br>%1"
00207         "<p>Possible reasons:</p><ul><li>An error occurred during your last "
00208         "KDE upgrade leaving an orphaned control module<li>You have old third party "
00209         "modules lying around.</ul><p>Check these points carefully and try to remove "
00210         "the module mentioned in the error message. If this fails, consider contacting "
00211         "your distributor or packager.</p></qt>")
00212       .arg(KLibLoader::self()->lastErrorMessage()));
00213 
00214 }
00215 
00216 bool KCModuleLoader::testModule( const QString& module )
00217 {
00218   return testModule( KCModuleInfo( module ) );
00219 }
00220 
00221 bool KCModuleLoader::testModule( const KCModuleInfo& module )
00222 {
00223   if (!module.service())
00224   {
00225     kdDebug(1208) << "Module '" << module.fileName() << "' not found." << endl;
00226     return true;
00227   }
00228 
00229   bool doLoad = module.service()->property( "X-KDE-Test-Module", QVariant::Bool ).toBool();
00230   if( !doLoad )
00231   {
00232     return true;
00233   }
00234   else
00235   {
00242     KLibLoader* loader = KLibLoader::self();
00243     KLibrary* library = loader->library( QFile::encodeName((QString("kcm_%1").arg(module.library()))) );
00244     if( library )
00245     {
00246       void *test_func = library->symbol( QString("test_%1").arg(module.factoryName()).utf8() );
00247       if( test_func )
00248       {
00249         bool (*func)() = (bool(*)())test_func;
00250         if( func() )
00251         {
00252           return true;
00253         }
00254         else
00255         {
00256           return false;
00257         }
00258       }
00259       else
00260       {
00261         kdDebug(1208) << "The test function for module '" << module.fileName() << "' could not be found." << endl;
00262         return true;
00263       }
00264     }
00265     kdDebug(1208) << "The library '" << module.library() << "' could not be found." << endl;
00266     return true;
00267   }
00268 }
00269 
00270 KCModule* KCModuleLoader::reportError( ErrorReporting report, const QString & text,
00271         QString details, QWidget * parent )
00272 {
00273   if( details.isNull() )
00274     details = i18n("<qt><p>The diagnostics is:<br>%1"
00275         "<p>Possible reasons:</p><ul><li>An error occurred during your last "
00276         "KDE upgrade leaving an orphaned control module<li>You have old third party "
00277         "modules lying around.</ul><p>Check these points carefully and try to remove "
00278         "the module mentioned in the error message. If this fails, consider contacting "
00279         "your distributor or packager.</p></qt>").arg(KLibLoader::self()->lastErrorMessage());
00280   if( report & Dialog )
00281     KMessageBox::detailedError( parent, text, details );
00282   if( report & Inline )
00283     return new KCMError( text, details, parent );
00284   return 0;
00285 }
00286 
00287 // vim: ts=2 sw=2 et
00288 

KUtils

Skip menu "KUtils"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal