1 | /* -*- c++ -*- |
2 | Copyright (c) 2008 Tobias Koenig <tokoe@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "pluginloader_p.h" |
21 | |
22 | #include <kconfiggroup.h> |
23 | #include <kdebug.h> |
24 | #include <kglobal.h> |
25 | #include <klocale.h> |
26 | #include <klocalizedstring.h> |
27 | #include <kstandarddirs.h> |
28 | #include <KPluginLoader> |
29 | |
30 | #include <QtCore/QDebug> |
31 | |
32 | using namespace Akonadi; |
33 | |
34 | PluginMetaData::PluginMetaData() |
35 | { |
36 | } |
37 | |
38 | PluginMetaData::PluginMetaData(const QString &lib, const QString &name, const QString &, const QString &cname) |
39 | : library(lib) |
40 | , nameLabel(name) |
41 | , descriptionLabel(comment) |
42 | , className(cname) |
43 | , loaded(false) |
44 | { |
45 | } |
46 | |
47 | PluginLoader *PluginLoader::mSelf = 0; |
48 | |
49 | PluginLoader::PluginLoader() |
50 | { |
51 | scan(); |
52 | } |
53 | |
54 | PluginLoader::~PluginLoader() |
55 | { |
56 | qDeleteAll(mPluginLoaders); |
57 | mPluginLoaders.clear(); |
58 | } |
59 | |
60 | PluginLoader *PluginLoader::self() |
61 | { |
62 | if (!mSelf) { |
63 | mSelf = new PluginLoader(); |
64 | } |
65 | |
66 | return mSelf; |
67 | } |
68 | |
69 | QStringList PluginLoader::names() const |
70 | { |
71 | return mPluginInfos.keys(); |
72 | } |
73 | |
74 | QObject *PluginLoader::createForName(const QString &name) |
75 | { |
76 | if (!mPluginInfos.contains(name)) { |
77 | kWarning(5300) << "plugin name \"" << name << "\" is unknown to the plugin loader." << endl; |
78 | return 0; |
79 | } |
80 | |
81 | PluginMetaData &info = mPluginInfos[name]; |
82 | |
83 | //First try to load it staticly |
84 | foreach (QObject *plugin, QPluginLoader::staticInstances()) { |
85 | if (QLatin1String(plugin->metaObject()->className()) == info.className) { |
86 | info.loaded = true; |
87 | return plugin; |
88 | break; |
89 | } |
90 | } |
91 | |
92 | if (!info.loaded) { |
93 | KPluginLoader *loader = new KPluginLoader(info.library); |
94 | if (loader->fileName().isEmpty()) { |
95 | kWarning(5300) << loader->errorString(); |
96 | delete loader; |
97 | return 0; |
98 | } |
99 | |
100 | mPluginLoaders.insert(name, loader); |
101 | info.loaded = true; |
102 | } |
103 | |
104 | QPluginLoader *loader = mPluginLoaders.value(name); |
105 | Q_ASSERT(loader); |
106 | |
107 | QObject *object = loader->instance(); |
108 | if (!object) { |
109 | kWarning(5300) << "unable to load plugin for plugin name \"" << name << "\"." << endl; |
110 | kWarning(5300) << "Error was:\"" << loader->errorString() << "\"." << endl; |
111 | return 0; |
112 | } |
113 | |
114 | return object; |
115 | } |
116 | |
117 | PluginMetaData PluginLoader::infoForName(const QString &name) const |
118 | { |
119 | if (!mPluginInfos.contains(name)) { |
120 | return PluginMetaData(); |
121 | } |
122 | |
123 | return mPluginInfos.value(name); |
124 | } |
125 | |
126 | void PluginLoader::scan() |
127 | { |
128 | const QStringList list = KGlobal::dirs()->findAllResources("data" , QLatin1String("akonadi/plugins/serializer/*.desktop" ), |
129 | KStandardDirs::Recursive | KStandardDirs::NoDuplicates); |
130 | for (int i = 0; i < list.count(); ++i) { |
131 | const QString entry = list.at(i); |
132 | |
133 | KConfig config(entry, KConfig::SimpleConfig); |
134 | if (config.hasGroup("Misc" ) && config.hasGroup("Plugin" )) { |
135 | KConfigGroup group(&config, "Plugin" ); |
136 | |
137 | const QString type = group.readEntry("Type" ).toLower(); |
138 | if (type.isEmpty()) { |
139 | kWarning(5300) << "missing or empty [Plugin]Type value in \"" << entry << "\" - skipping" << endl; |
140 | continue; |
141 | } |
142 | |
143 | // read Class entry as a list so that types like QPair<A,B> are |
144 | // properly escaped and don't end up being split into QPair<A |
145 | // and B>. |
146 | const QStringList classes = group.readXdgListEntry("X-Akonadi-Class" ); |
147 | if (classes.isEmpty()) { |
148 | kWarning(5300) << "missing or empty [Plugin]X-Akonadi-Class value in \"" << entry << "\" - skipping" << endl; |
149 | continue; |
150 | } |
151 | |
152 | const QString library = group.readEntry("X-KDE-Library" ); |
153 | if (library.isEmpty()) { |
154 | kWarning(5300) << "missing or empty [Plugin]X-KDE-Library value in \"" << entry << "\" - skipping" << endl; |
155 | continue; |
156 | } |
157 | |
158 | KConfigGroup group2(&config, "Misc" ); |
159 | |
160 | QString name = group2.readEntry("Name" ); |
161 | if (name.isEmpty()) { |
162 | kWarning(5300) << "missing or empty [Misc]Name value in \"" << entry << "\" - inserting default name" << endl; |
163 | name = i18n("Unnamed plugin" ); |
164 | } |
165 | |
166 | QString = group2.readEntry("Comment" ); |
167 | if (comment.isEmpty()) { |
168 | kWarning(5300) << "missing or empty [Misc]Comment value in \"" << entry << "\" - inserting default name" << endl; |
169 | comment = i18n("No description available" ); |
170 | } |
171 | |
172 | QString cname = group.readEntry("X-KDE-ClassName" ); |
173 | if (cname.isEmpty()) { |
174 | kWarning(5300) << "missing or empty X-KDE-ClassName value in \"" << entry << "\"" << endl; |
175 | } |
176 | |
177 | const QStringList mimeTypes = type.split(QLatin1Char(','), QString::SkipEmptyParts); |
178 | |
179 | kDebug(5300) << "registering Desktop file" << entry << "for" << mimeTypes << '@' << classes; |
180 | Q_FOREACH (const QString &mimeType, mimeTypes) { |
181 | Q_FOREACH (const QString &classType, classes) { |
182 | mPluginInfos.insert(mimeType + QLatin1Char('@') + classType, PluginMetaData(library, name, comment, cname)); |
183 | } |
184 | } |
185 | |
186 | } else { |
187 | kWarning(5300) << "Desktop file \"" << entry << "\" doesn't seem to describe a plugin " << "(misses Misc and/or Plugin group)" << endl; |
188 | } |
189 | } |
190 | } |
191 | |