00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00063
00064
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
00080 kdDebug(1208) << "Unable to load module using ComponentFactory. Falling back to old loader." << endl;
00081 }
00082
00083
00084 QString factory("create_%1");
00085 void *create = lib->symbol(QFile::encodeName(factory.arg(mod.handle())));
00086
00087 if (create)
00088 {
00089
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
00124
00125
00126
00127
00128 if ( !mod.service() )
00129 {
00130 if ( mod.moduleName() == "kcmlisa" || mod.moduleName() == "kcmkiolan" )
00131 {
00132 return reportError( report,
00133 i18n("The module %1 could not be found.")
00134 .arg( mod.moduleName() ),
00135 i18n("<qt><p>The Lisa and lan:/ ioslave modules "
00136 "are not installed by default in Kubuntu, because they are obsolete "
00137 "and replaced by zeroconf.<br> If you still wish to use them, you "
00138 "should install the lisa package from the Universe repository.</p></qt>"),
00139 parent );
00140 } else {
00141 return reportError( report,
00142 i18n("The module %1 could not be found.")
00143 .arg( mod.moduleName() ),
00144 i18n("<qt><p>The diagnostics is:<br>The desktop file %1 could not be found.</p></qt>").arg(mod.fileName()),
00145 parent );
00146 }
00147 }
00148
00149 if (!mod.library().isEmpty())
00150 {
00151
00152
00153 KLibLoader *loader = KLibLoader::self();
00154
00155 KCModule *module = load(mod, "kcm_%1", loader, report, parent, name, args );
00156
00157
00158
00159
00160 if (!KLibLoader::findLibrary( QCString( "libkcm_" ) + QFile::encodeName( mod.library() ) ).isEmpty() )
00161 module = load(mod, "libkcm_%1", loader, report, parent, name, args );
00162 if (module)
00163 return module;
00164 return reportError( report,
00165 i18n("The module %1 could not be loaded.")
00166 .arg( mod.moduleName() ), QString::null, parent );
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 if(withfallback)
00178 {
00179 KApplication::startServiceByDesktopPath(mod.fileName(), QString::null);
00180 }
00181 else
00182 {
00183 return reportError( report,
00184 i18n("The module %1 is not a valid configuration module.")
00185 .arg( mod.moduleName() ), i18n("<qt><p>The diagnostics is:<br>The desktop file %1 does not specify a library.</qt>").arg(mod.fileName()), parent );
00186 }
00187
00188 return 0;
00189 }
00190
00191 KCModule* KCModuleLoader::loadModule(const QString &module, QWidget *parent,
00192 const char *name, const QStringList & args)
00193 {
00194 return loadModule(KCModuleInfo(module), None, false, parent, name, args);
00195 }
00196
00197 KCModule* KCModuleLoader::loadModule(const QString &module, ErrorReporting
00198 report, QWidget *parent, const char *name, const QStringList & args)
00199 {
00200 return loadModule(KCModuleInfo(module), report, false, parent, name, args);
00201 }
00202
00203 void KCModuleLoader::unloadModule(const KCModuleInfo &mod)
00204 {
00205
00206 KLibLoader *loader = KLibLoader::self();
00207
00208
00209 QString libname("libkcm_%1");
00210 loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library())));
00211
00212 libname = "kcm_%1";
00213 loader->unloadLibrary(QFile::encodeName(libname.arg(mod.library())));
00214 }
00215
00216 void KCModuleLoader::showLastLoaderError(QWidget *parent)
00217 {
00218 KMessageBox::detailedError(parent,
00219 i18n("There was an error loading the module."),i18n("<qt><p>The diagnostics is:<br>%1"
00220 "<p>Possible reasons:</p><ul><li>An error occurred during your last "
00221 "KDE upgrade leaving an orphaned control module<li>You have old third party "
00222 "modules lying around.</ul><p>Check these points carefully and try to remove "
00223 "the module mentioned in the error message. If this fails, consider contacting "
00224 "your distributor or packager.</p></qt>")
00225 .arg(KLibLoader::self()->lastErrorMessage()));
00226
00227 }
00228
00229 bool KCModuleLoader::testModule( const QString& module )
00230 {
00231 return testModule( KCModuleInfo( module ) );
00232 }
00233
00234 bool KCModuleLoader::testModule( const KCModuleInfo& module )
00235 {
00236 if (!module.service())
00237 {
00238 kdDebug(1208) << "Module '" << module.fileName() << "' not found." << endl;
00239 return true;
00240 }
00241
00242 bool doLoad = module.service()->property( "X-KDE-Test-Module", QVariant::Bool ).toBool();
00243 if( !doLoad )
00244 {
00245 return true;
00246 }
00247 else
00248 {
00255 KLibLoader* loader = KLibLoader::self();
00256 KLibrary* library = loader->library( QFile::encodeName((QString("kcm_%1").arg(module.library()))) );
00257 if( library )
00258 {
00259 void *test_func = library->symbol( QString("test_%1").arg(module.factoryName()).utf8() );
00260 if( test_func )
00261 {
00262 bool (*func)() = (bool(*)())test_func;
00263 if( func() )
00264 {
00265 return true;
00266 }
00267 else
00268 {
00269 return false;
00270 }
00271 }
00272 else
00273 {
00274 kdDebug(1208) << "The test function for module '" << module.fileName() << "' could not be found." << endl;
00275 return true;
00276 }
00277 }
00278 kdDebug(1208) << "The library '" << module.library() << "' could not be found." << endl;
00279 return true;
00280 }
00281 }
00282
00283 KCModule* KCModuleLoader::reportError( ErrorReporting report, const QString & text,
00284 QString details, QWidget * parent )
00285 {
00286 if( details.isNull() )
00287 details = i18n("<qt><p>The diagnostics is:<br>%1"
00288 "<p>Possible reasons:</p><ul><li>An error occurred during your last "
00289 "KDE upgrade leaving an orphaned control module<li>You have old third party "
00290 "modules lying around.</ul><p>Check these points carefully and try to remove "
00291 "the module mentioned in the error message. If this fails, consider contacting "
00292 "your distributor or packager.</p></qt>").arg(KLibLoader::self()->lastErrorMessage());
00293 if( report & Dialog )
00294 KMessageBox::detailedError( parent, text, details );
00295 if( report & Inline )
00296 return new KCMError( text, details, parent );
00297 return 0;
00298 }
00299
00300
00301