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 | |
36 | using namespace KCModuleLoader; |
37 | |
38 | /***************************************************************/ |
39 | /** |
40 | * When something goes wrong in loading the module, this one |
41 | * jumps in as a "dummy" module. |
42 | */ |
43 | class 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 | |
60 | KCModule *KCModuleLoader::loadModule(const QString &module, ErrorReporting report, QWidget *parent, const QStringList &args) |
61 | { |
62 | return loadModule( KCModuleInfo( module ), report, parent, args ); |
63 | } |
64 | |
65 | KCModule* 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 | |
139 | void 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 |
147 | void 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 | |
161 | KCModule* 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 | |