kcmoduleloader.cpp
/*
Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
Copyright (c) 2000 Matthias Elter <elter@kde.org>
Copyright (c) 2003,2004 Matthias Kretz <kretz@kde.org>
Copyright (c) 2004 Frans Englich <frans.englich@telia.com>
This file is part of the KDE project
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <qfile.h>
#include <qlabel.h>
#include <qlayout.h>
#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kparts/componentfactory.h>
#include "kcmoduleloader.h"
/***************************************************************/
class KCMError : public KCModule
{
public:
KCMError( const QString& msg, const QString& details, QWidget* parent )
: KCModule( parent, "KCMError" )
{
QVBoxLayout* topLayout = new QVBoxLayout( this );
topLayout->addWidget( new QLabel( msg, this ) );
topLayout->addWidget( new QLabel( details, this ) );
}
};
/***************************************************************/
KCModule* KCModuleLoader::load(const KCModuleInfo &mod, const QString &libname,
KLibLoader *loader, ErrorReporting report, QWidget * parent,
const char * name, const QStringList & args )
{
// attempt to load modules with ComponentFactory, only if the symbol init_<lib> exists
// (this is because some modules, e.g. kcmkio with multiple modules in the library,
// cannot be ported to KGenericFactory)
KLibrary *lib = loader->library(QFile::encodeName(libname.arg(mod.library())));
if (lib) {
QString initSym("init_");
initSym += libname.arg(mod.library());
if ( lib->hasSymbol(QFile::encodeName(initSym)) )
{
KLibFactory *factory = lib->factory();
if ( factory )
{
KCModule *module = KParts::ComponentFactory::createInstanceFromFactory<KCModule>( factory, parent, name ? name : mod.handle().latin1(), args );
if (module)
return module;
}
// else do a fallback
kdDebug(1208) << "Unable to load module using ComponentFactory. Falling back to old loader." << endl;
}
// get the create_ function
QString factory("create_%1");
void *create = lib->symbol(QFile::encodeName(factory.arg(mod.handle())));
if (create)
{
// create the module
KCModule* (*func)(QWidget *, const char *);
func = (KCModule* (*)(QWidget *, const char *)) create;
return func( parent, name ? name : mod.handle().latin1() );
}
else
{
QString libFileName = lib->fileName();
lib->unload();
return reportError( report, i18n("<qt>There was an error when loading the module '%1'.<br><br>"
"The desktop file (%2) as well as the library (%3) was found but "
"yet the module could not be loaded properly. Most likely "
"the factory declaration was wrong, or the "
"create_* function was missing.</qt>")
.arg( mod.moduleName() )
.arg( mod.fileName() )
.arg( libFileName ),
QString::null, parent );
}
lib->unload();
}
return reportError( report, i18n("The specified library %1 could not be found.")
.arg( mod.library() ), QString::null, parent );
return 0;
}
KCModule* KCModuleLoader::loadModule(const KCModuleInfo &mod, bool withfallback, QWidget * parent, const char * name, const QStringList & args )
{
return loadModule( mod, None, withfallback, parent, name, args );
}
KCModule* KCModuleLoader::loadModule(const KCModuleInfo &mod, ErrorReporting report, bool withfallback, QWidget * parent, const char * name, const QStringList & args )
{
/*
* Simple libraries as modules are the easiest case:
* We just have to load the library and get the module
* from the factory.
*/
if ( !mod.service() )
{
return reportError( report,
i18n("The module %1 could not be found.")
.arg( mod.moduleName() ), i18n("<qt><p>The diagnostics is:<br>The desktop file %1 could not be found.</qt>").arg(mod.fileName()), parent );
}
if (!mod.library().isEmpty())
{
// get the library loader instance
KLibLoader *loader = KLibLoader::self();
KCModule *module = load(mod, "kcm_%1", loader, report, parent, name, args );
/*
* Only try to load libkcm_* if it exists, otherwise KLibLoader::lastErrorMessage would say
* "libkcm_foo not found" instead of the real problem with loading kcm_foo.
*/
if (!KLibLoader::findLibrary( QCString( "libkcm_" ) + QFile::encodeName( mod.library() ) ).isEmpty() )
module = load(mod, "libkcm_%1", loader, report, parent, name, args );
if (module)
return module;
return reportError( report,
i18n("The module %1 could not be loaded.")
.arg( mod.moduleName() ), QString::null, parent );
}
/*
* Ok, we could not load the library.
* Try to run it as an executable.
* This must not be done when calling from kcmshell, or you'll
* have infinite recursion
* (startService calls kcmshell which calls modloader which calls startService...)
*
*/
if(withfallback)
{
KApplication::startServiceByDesktopPath(mod.fileName(), QString::null);
}
else
{
return reportError( report,
i18n("The module %1 is not a valid configuration module.")
.arg( mod.moduleName() ), i18n("<qt><p>The diagnostics is:<br>The desktop file %1 does not specify a library.</qt>").arg(mod.fileName()), parent );
}
return 0;
}
KCModule* KCModuleLoader::loadModule(const QString &module, QWidget *parent,
const char *name, const QStringList & args)
{
return loadModule(KCModuleInfo(module), None, false, parent, name, args);
}
KCModule* KCModuleLoader::loadModule(const QString &module, ErrorReporting
report, QWidget *parent, const char *name, const QStringList & args)
{
return loadModule(KCModuleInfo(module), report, false, parent, name, args);
}
void KCModuleLoader::unloadModule(const KCModuleInfo &mod)
{
// get the library loader instance
KLibLoader *loader = KLibLoader::self();
// try to unload the library
QString libname("libkcm_%1");
loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library())));
libname = "kcm_%1";
loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library())));
}
void KCModuleLoader::showLastLoaderError(QWidget *parent)
{
KMessageBox::detailedError(parent,
i18n("There was an error loading the module."),i18n("<qt><p>The diagnostics is:<br>%1"
"<p>Possible reasons:</p><ul><li>An error occurred during your last "
"KDE upgrade leaving an orphaned control module<li>You have old third party "
"modules lying around.</ul><p>Check these points carefully and try to remove "
"the module mentioned in the error message. If this fails, consider contacting "
"your distributor or packager.</p></qt>")
.arg(KLibLoader::self()->lastErrorMessage()));
}
bool KCModuleLoader::testModule( const QString& module )
{
return testModule( KCModuleInfo( module ) );
}
bool KCModuleLoader::testModule( const KCModuleInfo& module )
{
if (!module.service())
{
kdDebug(1208) << "Module '" << module.fileName() << "' not found." << endl;
return true;
}
bool doLoad = module.service()->property( "X-KDE-Test-Module", QVariant::Bool ).toBool();
if( !doLoad )
{
return true;
}
else
{
KLibLoader* loader = KLibLoader::self();
KLibrary* library = loader->library( QFile::encodeName((QString("kcm_%1").arg(module.library()))) );
if( library )
{
void *test_func = library->symbol( QString("test_%1").arg(module.factoryName()).utf8() );
if( test_func )
{
bool (*func)() = (bool(*)())test_func;
if( func() )
{
return true;
}
else
{
return false;
}
}
else
{
kdDebug(1208) << "The test function for module '" << module.fileName() << "' could not be found." << endl;
return true;
}
}
kdDebug(1208) << "The library '" << module.library() << "' could not be found." << endl;
return true;
}
}
KCModule* KCModuleLoader::reportError( ErrorReporting report, const QString & text,
QString details, QWidget * parent )
{
if( details.isNull() )
details = i18n("<qt><p>The diagnostics is:<br>%1"
"<p>Possible reasons:</p><ul><li>An error occurred during your last "
"KDE upgrade leaving an orphaned control module<li>You have old third party "
"modules lying around.</ul><p>Check these points carefully and try to remove "
"the module mentioned in the error message. If this fails, consider contacting "
"your distributor or packager.</p></qt>").arg(KLibLoader::self()->lastErrorMessage());
if( report & Dialog )
KMessageBox::detailedError( parent, text, details );
if( report & Inline )
return new KCMError( text, details, parent );
return 0;
}
// vim: ts=2 sw=2 et
KLibFactory
KApplication::startServiceByDesktopPath
static int startServiceByDesktopPath(const QString &_name, const QString &URL, QString *error=0, QCString *dcopService=0, int *pid=0, const QCString &startup_id="", bool noWait=false)
KCModuleLoader::None
no error reporting is done
Definition: kcmoduleloader.h:88
KCModuleInfo::factoryName
QString factoryName() const
Returns the module's factory name, if it's set.
Definition: kcmoduleinfo.cpp:93
kdDebug
kdbgstream kdDebug(int area=0)
klocale.h
KCModuleLoader::Inline
the error report is shown instead of the KCModule that should have * been loaded
Definition: kcmoduleloader.h:93
KLibLoader::unloadLibrary
virtual void unloadLibrary(const char *libname)
KStdAction::create
KAction * create(StdAction id, const char *name, const QObject *recvr, const char *slot, KActionCollection *parent)
KLibrary::unload
void unload() const
KCModuleLoader::ErrorReporting
ErrorReporting
Determines the way errors are reported.
Definition: kcmoduleloader.h:84
KLibrary
KCModuleInfo::fileName
QString fileName() const
Definition: kcmoduleinfo.h:113
KLibrary::factory
KLibFactory * factory()
KCModuleLoader::Dialog
shows a dialog with the error report
Definition: kcmoduleloader.h:97
KLibrary::fileName
QString fileName() const
KLibrary::hasSymbol
bool hasSymbol(const char *name) const
KCModuleInfo::library
QString library() const
Definition: kcmoduleinfo.h:157
KCModuleInfo
A class that provides information about a KCModule.
Definition: kcmoduleinfo.h:49
KLibLoader::library
virtual KLibrary * library(const char *libname)
KCModuleLoader::reportError
static KCModule * reportError(ErrorReporting report, const QString &text, QString details, QWidget *parent)
Returns a KCModule containing the messages report and text.
Definition: kcmoduleloader.cpp:270
KLibLoader::findLibrary
static QString findLibrary(const char *name, const KInstance *instance=KGlobal::instance())
KCModuleLoader::testModule
static bool testModule(const QString &module)
Checks whether an KCModule should be shown by running its test function.
Definition: kcmoduleloader.cpp:216
KLibLoader::self
static KLibLoader * self()
KLibLoader
KCModuleInfo::service
KService::Ptr service() const
Definition: kcmoduleinfo.h:137
KCModuleLoader::showLastLoaderError
static void showLastLoaderError(QWidget *parent) KDE_DEPRECATED
Display a message box explaining an error occured and possible reasons to why.
Definition: kcmoduleloader.cpp:203
KLibrary::symbol
void * symbol(const char *name) const
endl
kndbgstream & endl(kndbgstream &s)
KMessageBox::detailedError
static void detailedError(QWidget *parent, const QString &text, const QString &details, const QString &caption=QString::null, int options=Notify)
KCModuleLoader::loadModule
static KCModule * loadModule(const KCModuleInfo &module, bool withFallback=true, QWidget *parent=0, const char *name=0, const QStringList &args=QStringList()) KDE_DEPRECATED
Loads a KCModule.
Definition: kcmoduleloader.cpp:116
KCModule
KCModuleInfo::moduleName
QString moduleName() const
Definition: kcmoduleinfo.h:131
KCModuleInfo::handle
QString handle() const
Definition: kcmoduleinfo.cpp:190
KCModuleLoader::unloadModule
static void unloadModule(const KCModuleInfo &mod)
Unloads the module's library.
Definition: kcmoduleloader.cpp:190

KDE Home | KDE Accessibility Home | Description of Access Keys