1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2018-07-30
7 * Description : manager to load external plugins at run-time
8 *
9 * Copyright (C) 2018-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 *
11 * This program is free software; you can redistribute it
12 * and/or modify it under the terms of the GNU General
13 * Public License as published by the Free Software Foundation;
14 * either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * ============================================================ */
23
24 #include "dpluginloader_p.h"
25
26 // Qt includes
27
28 #include <QStringList>
29
30 // Local includes
31
32 #include "digikam_config.h"
33 #include "digikam_debug.h"
34 #include "dplugingeneric.h"
35 #include "dplugineditor.h"
36 #include "dpluginrawimport.h"
37
38 namespace Digikam
39 {
40
41 class Q_DECL_HIDDEN DPluginLoaderCreator
42 {
43 public:
44
45 DPluginLoader object;
46 };
47
Q_GLOBAL_STATIC(DPluginLoaderCreator,creator)48 Q_GLOBAL_STATIC(DPluginLoaderCreator, creator)
49
50 // -----------------------------------------------------
51
52 DPluginLoader::DPluginLoader()
53 : QObject(),
54 d (new Private)
55 {
56 }
57
~DPluginLoader()58 DPluginLoader::~DPluginLoader()
59 {
60 delete d;
61 }
62
instance()63 DPluginLoader* DPluginLoader::instance()
64 {
65 return &creator->object;
66 }
67
init()68 void DPluginLoader::init()
69 {
70 d->loadPlugins();
71 }
72
cleanUp()73 void DPluginLoader::cleanUp()
74 {
75 foreach (DPlugin* const p, d->allPlugins)
76 {
77 p->cleanUp();
78 }
79
80 d->allPlugins.clear();
81 }
82
configGroupName() const83 QString DPluginLoader::configGroupName() const
84 {
85 return QLatin1String("EnabledDPlugins");
86 }
87
allPlugins() const88 QList<DPlugin*> DPluginLoader::allPlugins() const
89 {
90 return d->allPlugins;
91 }
92
pluginsActions(DPluginAction::ActionType type,QObject * const parent) const93 QList<DPluginAction*> DPluginLoader::pluginsActions(DPluginAction::ActionType type, QObject* const parent) const
94 {
95 QList<DPluginAction*> list;
96
97 foreach (DPlugin* const p, d->allPlugins)
98 {
99 DPluginGeneric* const gene = dynamic_cast<DPluginGeneric*>(p);
100
101 if (gene)
102 {
103 foreach (DPluginAction* const ac, gene->actions(parent))
104 {
105 if (ac && (ac->actionType() == type))
106 {
107 list << ac;
108 }
109 }
110 }
111 }
112
113 if (list.isEmpty())
114 {
115 foreach (DPlugin* const p, d->allPlugins)
116 {
117 DPluginEditor* const edit = dynamic_cast<DPluginEditor*>(p);
118
119 if (edit)
120 {
121 foreach (DPluginAction* const ac, edit->actions(parent))
122 {
123 if (ac && (ac->actionType() == type))
124 {
125 list << ac;
126 }
127 }
128 }
129 }
130 }
131
132 std::sort(list.begin(), list.end(), DPluginAction::pluginActionLessThan);
133
134 return list;
135 }
136
pluginsActions(DPluginAction::ActionCategory cat,QObject * const parent) const137 QList<DPluginAction*> DPluginLoader::pluginsActions(DPluginAction::ActionCategory cat, QObject* const parent) const
138 {
139 QList<DPluginAction*> list;
140
141 foreach (DPlugin* const p, d->allPlugins)
142 {
143 DPluginGeneric* const gene = dynamic_cast<DPluginGeneric*>(p);
144
145 if (gene)
146 {
147 foreach (DPluginAction* const ac, gene->actions(parent))
148 {
149 if (ac && (ac->actionCategory() == cat))
150 {
151 list << ac;
152 }
153 }
154 }
155 }
156
157 if (list.isEmpty())
158 {
159 foreach (DPlugin* const p, d->allPlugins)
160 {
161 DPluginEditor* const edit = dynamic_cast<DPluginEditor*>(p);
162
163 if (edit)
164 {
165 foreach (DPluginAction* const ac, edit->actions(parent))
166 {
167 if (ac && (ac->actionCategory() == cat))
168 {
169 list << ac;
170 }
171 }
172 }
173 }
174 }
175
176 std::sort(list.begin(), list.end(), DPluginAction::pluginActionLessThan);
177 return list;
178 }
179
pluginActions(const QString & pluginIID,QObject * const parent) const180 QList<DPluginAction*> DPluginLoader::pluginActions(const QString& pluginIID, QObject* const parent) const
181 {
182 QList<DPluginAction*> list;
183
184 foreach (DPlugin* const p, d->allPlugins)
185 {
186 DPluginGeneric* const gene = dynamic_cast<DPluginGeneric*>(p);
187
188 if (gene)
189 {
190 if (p->iid() == pluginIID)
191 {
192 foreach (DPluginAction* const ac, gene->actions(parent))
193 {
194 list << ac;
195 }
196
197 break;
198 }
199 }
200 }
201
202 if (list.isEmpty())
203 {
204 foreach (DPlugin* const p, d->allPlugins)
205 {
206 DPluginEditor* const edit = dynamic_cast<DPluginEditor*>(p);
207
208 if (edit)
209 {
210 if (p->iid() == pluginIID)
211 {
212 foreach (DPluginAction* const ac, edit->actions(parent))
213 {
214 list << ac;
215 }
216
217 break;
218 }
219 }
220 }
221 }
222
223 std::sort(list.begin(), list.end(), DPluginAction::pluginActionLessThan);
224 return list;
225 }
226
pluginAction(const QString & actionName,QObject * const parent) const227 DPluginAction* DPluginLoader::pluginAction(const QString& actionName, QObject* const parent) const
228 {
229 foreach (DPlugin* const p, d->allPlugins)
230 {
231 DPluginGeneric* const gene = dynamic_cast<DPluginGeneric*>(p);
232
233 if (gene)
234 {
235 foreach (DPluginAction* const ac, gene->actions(parent))
236 {
237 if (ac && (ac->objectName() == actionName))
238 {
239 return ac;
240 }
241 }
242 }
243
244 DPluginEditor* const edit = dynamic_cast<DPluginEditor*>(p);
245
246 if (edit)
247 {
248 foreach (DPluginAction* const ac, edit->actions(parent))
249 {
250 if (ac && (ac->objectName() == actionName))
251 {
252 return ac;
253 }
254 }
255 }
256 }
257
258 qCCritical(DIGIKAM_GENERAL_LOG) << "DPluginAction named" << actionName
259 << "not found in" << parent->objectName()
260 << "(" << parent << ")";
261
262 return nullptr;
263 }
264
pluginXmlSections(DPluginAction::ActionCategory cat,QObject * const parent) const265 QString DPluginLoader::pluginXmlSections(DPluginAction::ActionCategory cat, QObject* const parent) const
266 {
267 QString xml;
268
269 foreach (DPluginAction* const ac, pluginsActions(cat, parent))
270 {
271 xml.append(ac->xmlSection());
272 }
273
274 return xml;
275 }
276
appendPluginToBlackList(const QString & filename)277 void DPluginLoader::appendPluginToBlackList(const QString& filename)
278 {
279 d->blacklist << filename;
280 }
281
appendPluginToWhiteList(const QString & filename)282 void DPluginLoader::appendPluginToWhiteList(const QString& filename)
283 {
284 d->whitelist << filename;
285 }
286
registerGenericPlugins(QObject * const parent)287 void DPluginLoader::registerGenericPlugins(QObject* const parent)
288 {
289 foreach (DPlugin* const plugin, d->allPlugins)
290 {
291 DPluginGeneric* const gene = dynamic_cast<DPluginGeneric*>(plugin);
292
293 if (gene)
294 {
295 gene->setup(parent);
296 gene->setVisible(plugin->shouldLoaded());
297
298 qCDebug(DIGIKAM_GENERAL_LOG) << "Generic plugin named" << gene->name()
299 << "registered to" << parent;
300 }
301 }
302 }
303
registerEditorPlugins(QObject * const parent)304 void DPluginLoader::registerEditorPlugins(QObject* const parent)
305 {
306 foreach (DPlugin* const plugin, d->allPlugins)
307 {
308 DPluginEditor* const edit = dynamic_cast<DPluginEditor*>(plugin);
309
310 if (edit)
311 {
312 edit->setup(parent);
313 edit->setVisible(plugin->shouldLoaded());
314
315 qCDebug(DIGIKAM_GENERAL_LOG) << "Editor plugin named" << edit->name()
316 << "registered to" << parent;
317 }
318 }
319 }
320
registerRawImportPlugins(QObject * const parent)321 void DPluginLoader::registerRawImportPlugins(QObject* const parent)
322 {
323 foreach (DPlugin* const plugin, d->allPlugins)
324 {
325 DPluginRawImport* const raw = dynamic_cast<DPluginRawImport*>(plugin);
326
327 if (raw)
328 {
329 raw->setup(parent);
330 qCDebug(DIGIKAM_GENERAL_LOG) << "Raw Import plugin named" << raw->name()
331 << "registered to" << parent;
332 }
333 }
334 }
335
336 } // namepace Digikam
337