1/*
2 Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
3 Copyright (c) 2000 Matthias Elter <elter@kde.org>
4 Copyright (c) 2003,2004,2006 Matthias Kretz <kretz@kde.org>
5 Copyright (c) 2004 Frans Englich <frans.englich@telia.com>
6
7 This file is part of the KDE project
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License version 2, as published by the Free Software Foundation.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22*/
23
24#include "kcmoduleloader.h"
25
26#include <QtCore/QFile>
27#include <QtGui/QLabel>
28#include <QtGui/QLayout>
29
30#include <klibrary.h>
31#include <kpluginloader.h>
32#include <kdebug.h>
33#include <klocale.h>
34#include <kmessagebox.h>
35
36using namespace KCModuleLoader;
37
38/***************************************************************/
39/**
40 * When something goes wrong in loading the module, this one
41 * jumps in as a "dummy" module.
42 */
43class KCMError : public KCModule
44{
45 public:
46 KCMError( const QString& msg, const QString& details, QWidget* parent )
47 : KCModule( KGlobal::mainComponent(), parent )
48 {
49 QVBoxLayout* topLayout = new QVBoxLayout( this );
50 QLabel *lab = new QLabel( msg, this );
51 lab->setWordWrap(true);
52 topLayout->addWidget( lab );
53 lab = new QLabel(details, this );
54 lab->setWordWrap(true);
55 topLayout->addWidget( lab );
56 }
57};
58/***************************************************************/
59
60KCModule *KCModuleLoader::loadModule(const QString &module, ErrorReporting report, QWidget *parent, const QStringList &args)
61{
62 return loadModule( KCModuleInfo( module ), report, parent, args );
63}
64
65KCModule* KCModuleLoader::loadModule(const KCModuleInfo& mod, ErrorReporting report, QWidget* parent, const QStringList& args )
66{
67 /*
68 * Simple libraries as modules are the easiest case:
69 * We just have to load the library and get the module
70 * from the factory.
71 */
72
73 if ( !mod.service() )
74 return reportError( report,
75 i18n("The module %1 could not be found.",
76 mod.moduleName() ), i18n("<qt><p>The diagnosis is:<br />The desktop file %1 could not be found.</p></qt>", mod.fileName()), parent );
77 if( mod.service()->noDisplay() )
78 return reportError( report, i18n( "The module %1 is disabled.", mod.moduleName() ),
79 i18n( "<qt><p>Either the hardware/software the module configures is not available or the module has been disabled by the administrator.</p></qt>" ),
80 parent );
81
82 if (!mod.library().isEmpty())
83 {
84 QString error;
85 QVariantList args2;
86 foreach (const QString &arg, args) {
87 args2 << arg;
88 }
89 KCModule *module = mod.service()->createInstance<KCModule>(parent, args2, &error);
90 if (module) {
91 return module;
92 }
93#ifndef KDE_NO_DEPRECATED
94 // might be using K_EXPORT_COMPONENT_FACTORY
95 int error2 = 0;
96 module = KService::createInstance<KCModule>(mod.service(), parent, args, &error2);
97 if (module) {
98 kWarning(1208) << "This module still uses K_EXPORT_COMPONENT_FACTORY. Please port it to use KPluginFactory and K_EXPORT_PLUGIN.";
99 return module;
100 }
101 error += KLibLoader::errorString(error2);
102#endif
103//#ifndef NDEBUG
104 {
105 // get the create_ function
106 KLibrary lib(mod.library());
107 if (lib.load()) {
108 KCModule *(*create)(QWidget *, const char *);
109 QByteArray factorymethod("create_");
110 factorymethod += mod.handle().toLatin1();
111 create = reinterpret_cast<KCModule *(*)(QWidget *, const char*)>(lib.resolveFunction(factorymethod));
112 if (create) {
113 return create(parent, mod.handle().toLatin1());
114 kFatal(1208) << "This module still uses a custom factory method (" << factorymethod << "). This is not supported anymore. Please fix the module.";
115 } else {
116 kWarning(1208) << "This module has no valid entry symbol at all. The reason could be that it's still using K_EXPORT_COMPONENT_FACTORY with a custom X-KDE-FactoryName which is not supported anymore";
117 }
118 lib.unload();
119 }
120 }
121//#endif // NDEBUG
122 return reportError(report, error, QString(), parent);
123 }
124
125 /*
126 * Ok, we could not load the library.
127 * Try to run it as an executable.
128 * This must not be done when calling from kcmshell, or you'll
129 * have infinite recursion
130 * (startService calls kcmshell which calls modloader which calls startService...)
131 *
132 */
133 return reportError( report,
134 i18n("The module %1 is not a valid configuration module.", mod.moduleName() ),
135 i18n("<qt>The diagnosis is:<br />The desktop file %1 does not specify a library.</qt>", mod.fileName()), parent );
136}
137
138
139void KCModuleLoader::unloadModule(const KCModuleInfo &mod)
140{
141 // get the library loader instance
142 KPluginLoader loader(mod.library());
143 loader.unload();
144}
145
146#ifndef KDE_NO_DEPRECATED
147void KCModuleLoader::showLastLoaderError(QWidget *parent)
148{
149 KMessageBox::detailedError(parent,
150 i18n("There was an error loading the module."),i18n("<qt>The diagnosis is:<br />%1"
151 "<p>Possible reasons:</p><ul><li>An error occurred during your last "
152 "KDE upgrade leaving an orphaned control module</li><li>You have old third party "
153 "modules lying around.</li></ul><p>Check these points carefully and try to remove "
154 "the module mentioned in the error message. If this fails, consider contacting "
155 "your distributor or packager.</p></qt>",
156 KLibLoader::self()->lastErrorMessage()));
157
158}
159#endif
160
161KCModule* KCModuleLoader::reportError( ErrorReporting report, const QString & text,
162 const QString &details, QWidget * parent )
163{
164 QString realDetails = details;
165 if (realDetails.isNull()) {
166 realDetails = i18n("<qt><p>Possible reasons:<ul><li>An error occurred during your last "
167 "KDE upgrade leaving an orphaned control module</li><li>You have old third party "
168 "modules lying around.</li></ul></p><p>Check these points carefully and try to remove "
169 "the module mentioned in the error message. If this fails, consider contacting "
170 "your distributor or packager.</p></qt>");
171 }
172 if (report & KCModuleLoader::Dialog) {
173 KMessageBox::detailedError(parent, text, realDetails);
174 }
175 if (report & KCModuleLoader::Inline) {
176 return new KCMError(text, realDetails, parent);
177 }
178 return 0;
179}
180
181// vim: ts=4
182