Dekko
Loading...
Searching...
No Matches
PluginLoader.cpp
1/* Copyright (C) 2017 Dan Chapman <dpniel@ubuntu.com>
2
3 This file is part of Dekko email client for Ubuntu devices
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License or (at your option) version 3
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "PluginLoader.h"
19#include <QCoreApplication>
20#include <QGuiApplication>
21#include <QPluginLoader>
22#include <QDebug>
23#include <QDir>
24#include <QDirIterator>
25#include <QFileInfo>
26#include <QLibrary>
27#include <QStringBuilder>
28
29Q_LOGGING_CATEGORY(PLUGIN_LOADER, "dekko.plugman.loader")
30
32{
33 // by default only look next to the app binary for a plugins folder
34 m_pluginPaths << qApp->applicationDirPath() % "/plugins";
35}
36
37PluginLoader::~PluginLoader()
38{
39 qDeleteAll(m_translators);
40 m_translators.clear();
41}
42
43void PluginLoader::loadPlugins(QMultiMap<QString, PluginInfo *> &registry, const QString &pluginType)
44{
45 Q_UNUSED(pluginType);
46 qCDebug(PLUGIN_LOADER) << "Loading plugins....";
47 QStringList dirs;
48 dirs << qApp->applicationDirPath() % "/plugins";
49 dirs << m_pluginPaths;
50 QString pluginEnv = QString(qgetenv("DEKKO_PLUGINS"));
51 if (!pluginEnv.isEmpty()) {
52 dirs << pluginEnv;
53 }
54
55 // First iterate over library plugins
56 QStringList pluginPaths;
57
58 qCDebug(PLUGIN_LOADER) << "Looking for library plugins";
59 Q_FOREACH(const QString &directory, dirs) {
60 QDir dir(directory);
61 Q_FOREACH(const QString &file, dir.entryList()) {
62 const QString abs = QFileInfo(dir.absoluteFilePath(file)).canonicalFilePath();
63 if (pluginPaths.contains(abs)) {
64 continue;
65 }
66 pluginPaths << abs;
67 if (!QLibrary::isLibrary(abs)) {
68 continue;
69 }
70 QPluginLoader *l = new QPluginLoader(abs);
71 if (l->load()) {
72 if (auto plugin = qobject_cast<PluginInterface *>(l->instance())) {
73 if (PluginInfo *p = plugin->create(Q_NULLPTR)) {
74 qCDebug(PLUGIN_LOADER) << "+---------------------------------+";
75 qCDebug(PLUGIN_LOADER) << "Library plugin found >> " << plugin->name();
76 qCDebug(PLUGIN_LOADER) << "Registered >> " << p->location();
77 qCDebug(PLUGIN_LOADER) << "I18n >> " << p->i18n();
78 qCDebug(PLUGIN_LOADER) << "+---------------------------------+";
79 registry.insert(p->location(), p);
80 if (!p->i18n().isEmpty()) {
81 // we also load the translations for this plugin now
82 loadTranslations(directory % "/" % p->i18n());
83 }
84 }
85 }
86 }
87 l->deleteLater();
88 }
89 }
90
91 qCDebug(PLUGIN_LOADER) << "Looking for dekko spec plugins";
92 // Now scan for any *.dekko-plugin specs and generate a DekkoPlugin
93 pluginPaths.clear();
94
95 Q_FOREACH(const QString &directory, dirs) {
96 QDirIterator it(directory, QStringList() << "*.dekko-plugin", QDir::Files, QDirIterator::Subdirectories);
97 while (it.hasNext()) {
98 QString path = it.next();
99 const QString abs = QFileInfo(path).canonicalFilePath();
100 if (pluginPaths.contains(abs)) {
101 continue;
102 }
103 pluginPaths << abs;
104
105 if (auto pluginInfo = DekkoPlugin::fromSpec(abs)) {
106 qCDebug(PLUGIN_LOADER) << "+-------------------------------------+";
107 qCDebug(PLUGIN_LOADER) << "PluginReady: " << abs;
108 qCDebug(PLUGIN_LOADER) << "Registered: " << pluginInfo->location();
109 qCDebug(PLUGIN_LOADER) << "Path: " << it.fileInfo().absolutePath();
110 qCDebug(PLUGIN_LOADER) << "I18n >> " << pluginInfo->i18n();
111 qobject_cast<DekkoPlugin *>(pluginInfo)->setPluginDirectory(it.fileInfo().absolutePath());
112 registry.insert(pluginInfo->location(), pluginInfo);
113 if (!pluginInfo->i18n().isEmpty()) {
114 // we also load the translations for this plugin now
115 loadTranslations(it.fileInfo().absolutePath() % "/" % pluginInfo->i18n());
116 }
117 qCDebug(PLUGIN_LOADER) << "+-------------------------------------+";
118 }
119 }
120 }
121}
122
123void PluginLoader::setPluginPaths(const QStringList &paths)
124{
125 if (!paths.isEmpty()) {
126 m_pluginPaths = paths;
127 }
128}
129
130void PluginLoader::loadTranslations(const QString &i18nDir)
131{
132 qCDebug(PLUGIN_LOADER) << "Plugin declared i18n directory: " << i18nDir;
133 QDir dir(i18nDir);
134 if (dir.exists()) {
135 qCDebug(PLUGIN_LOADER) << "Plugin has i18n directory, creating a translator";
136 QTranslator *tr = new QTranslator(Q_NULLPTR);
137 if (tr->load(QLocale::system().name(), i18nDir)) {
138 qApp->installTranslator(tr);
139 m_translators.append(tr);
140 qCDebug(PLUGIN_LOADER) << "Translator created for directory: " << i18nDir;
141 } else {
142 qCDebug(PLUGIN_LOADER) << "Failed creating translator for: " << i18nDir;
143 qCDebug(PLUGIN_LOADER) << "Locale: " << QLocale::system().name();
144 }
145 } else {
146 qCDebug(PLUGIN_LOADER) << "i18n directory doesn't exist";
147 }
148}
149
150