##// END OF EJS Templates
Merge pull request 385 from SciQLop-IPSIS-fork StaticPlugins...
perrinel -
r1189:bdd9ca279197 merge
parent child
Show More
@@ -1,80 +1,89
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the QLop Software
3 3 -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include <QProcessEnvironment>
24 24 #include <QThread>
25 25 #include <SqpApplication.h>
26 26 #include <qglobal.h>
27 27
28 #include <QtPlugin>
28 29 #include <Plugin/PluginManager.h>
29 30 #include <QDir>
30 31
31 32 #include <QLoggingCategory>
32 33
33 34 Q_LOGGING_CATEGORY(LOG_Main, "Main")
34 35
35 36 namespace {
36 37
37 38 const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins");
38 39
39 40
40 41 } // namespace
41 42
42 43 int main(int argc, char *argv[])
43 44 {
45 #ifdef QT_STATICPLUGIN
46 Q_IMPORT_PLUGIN(MockPlugin)
47 Q_IMPORT_PLUGIN(AmdaPlugin)
48 Q_INIT_RESOURCE(amdaresources);
49 #endif
50 Q_INIT_RESOURCE(sqpguiresources);
51
44 52 SqpApplication a{argc, argv};
45 53 SqpApplication::setOrganizationName("LPP");
46 54 SqpApplication::setOrganizationDomain("lpp.fr");
47 55 SqpApplication::setApplicationName("SciQLop");
48 56 MainWindow w;
49 57 w.show();
50 58
51 59 // Loads plugins
52 60 auto pluginDir = QDir{a.applicationDirPath()};
53 61 auto pluginLookupPath = {
54 62 a.applicationDirPath(),
55 63 a.applicationDirPath() + "/" + PLUGIN_DIRECTORY_NAME,
56 64 a.applicationDirPath() + "/../lib64/SciQlop",
57 65 a.applicationDirPath() + "/../lib64/sciqlop",
58 66 a.applicationDirPath() + "/../lib/SciQlop",
59 67 a.applicationDirPath() + "/../lib/sciqlop",
60 68 a.applicationDirPath() + "/../plugins",
61 69 };
62 70
63 71 #if _WIN32 || _WIN64
64 72 pluginDir.mkdir(PLUGIN_DIRECTORY_NAME);
65 73 pluginDir.cd(PLUGIN_DIRECTORY_NAME);
66 74 #endif
67 75
68 76 PluginManager pluginManager{};
69 77
70 78 for (auto &&path : pluginLookupPath) {
71 79 QDir directory{path};
72 80 if (directory.exists()) {
73 81 qCDebug(LOG_Main())
74 82 << QObject::tr("Plugin directory: %1").arg(directory.absolutePath());
75 83 pluginManager.loadPlugins(directory);
76 84 }
77 85 }
86 pluginManager.loadStaticPlugins();
78 87
79 88 return a.exec();
80 89 }
@@ -1,36 +1,41
1 1 #ifndef SCIQLOP_PLUGINMANAGER_H
2 2 #define SCIQLOP_PLUGINMANAGER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10 class QDir;
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_PluginManager)
13 13
14 14 /**
15 15 * @brief The PluginManager class aims to handle the plugins loaded dynamically into SciQLop.
16 16 */
17 17 class SCIQLOP_CORE_EXPORT PluginManager {
18 18 public:
19 19 explicit PluginManager();
20 20
21 21 /**
22 22 * Loads plugins into SciQlop. The loaded plugins are those located in the directory passed in
23 23 * parameter
24 24 * @param pluginDir the directory containing the plugins
25 25 */
26 26 void loadPlugins(const QDir &pluginDir);
27 27
28 /**
29 * Loads static plugins into SciQlop. SciQLOP supports statically linked plugins.
30 */
31 void loadStaticPlugins();
32
28 33 /// @returns the number of plugins loaded
29 34 int nbPluginsLoaded() const noexcept;
30 35
31 36 private:
32 class PluginManagerPrivate;
37 struct PluginManagerPrivate;
33 38 spimpl::unique_impl_ptr<PluginManagerPrivate> impl;
34 39 };
35 40
36 41 #endif // SCIQLOP_PLUGINMANAGER_H
@@ -1,124 +1,138
1 1 #include <Plugin/PluginManager.h>
2 2
3 3 #include <Plugin/IPlugin.h>
4 4
5 5 #include <QDir>
6 6 #include <QLibrary>
7 7 #include <QPluginLoader>
8 8
9 9 Q_LOGGING_CATEGORY(LOG_PluginManager, "PluginManager")
10 10
11 11 namespace {
12 12
13 13 /// Key for retrieving metadata of the plugin
14 14 const auto PLUGIN_METADATA_KEY = QStringLiteral("MetaData");
15 15
16 16 /// Key for retrieving the name of the plugin in its metadata
17 17 const auto PLUGIN_NAME_KEY = QStringLiteral("name");
18 18
19 19 /// Helper to state the plugin loading operation
20 20 struct LoadPluginState {
21 21 explicit LoadPluginState(const QString &pluginPath)
22 22 : m_PluginPath{pluginPath}, m_Valid{true}, m_ErrorMessage{}
23 23 {
24 24 }
25 25
26 26 void log() const
27 27 {
28 28 if (m_Valid) {
29 29 qCDebug(LOG_PluginManager())
30 30 << QObject::tr("File '%1' has been loaded as a plugin").arg(m_PluginPath);
31 31 }
32 32 else {
33 33 qCWarning(LOG_PluginManager())
34 34 << QObject::tr("File '%1' can't be loaded as a plugin: %2")
35 35 .arg(m_PluginPath)
36 36 .arg(m_ErrorMessage);
37 37 }
38 38 }
39 39
40 40 void setError(const QString &errorMessage)
41 41 {
42 42 m_Valid = false;
43 43 m_ErrorMessage = errorMessage;
44 44 }
45 45
46 46 QString m_PluginPath;
47 47 bool m_Valid;
48 48 QString m_ErrorMessage;
49 49 };
50 50
51 51 } // namespace
52 52
53 53 struct PluginManager::PluginManagerPrivate {
54 54 /**
55 55 * Loads a single plugin into SciQlop. The method has no effect if the plugin is malformed (e.g.
56 56 * wrong library type, missing metadata, etc.)
57 57 * @param pluginPath the path to the plugin library.
58 58 */
59 59 void loadPlugin(const QString &pluginPath)
60 60 {
61 61 qCDebug(LOG_PluginManager())
62 62 << QObject::tr("Attempting to load file '%1' as a plugin").arg(pluginPath);
63 63
64 64 LoadPluginState loadState{pluginPath};
65 65
66 66 if (QLibrary::isLibrary(pluginPath)) {
67 67 QPluginLoader pluginLoader{pluginPath};
68 68
69 69 // Retrieving the plugin name to check if it can be loaded (i.e. no plugin with the same
70 70 // name has been registered yet)
71 71 auto metadata = pluginLoader.metaData().value(PLUGIN_METADATA_KEY).toObject();
72 72 auto pluginName = metadata.value(PLUGIN_NAME_KEY).toString();
73 73
74 74 if (pluginName.isEmpty()) {
75 75 loadState.setError(QObject::tr("empty file name"));
76 76 }
77 77 else if (m_RegisteredPlugins.contains(pluginName)) {
78 78 loadState.setError(QObject::tr("name '%1' already registered").arg(pluginName));
79 79 }
80 80 else {
81 81 if (auto pluginInstance = qobject_cast<IPlugin *>(pluginLoader.instance())) {
82 82 pluginInstance->initialize();
83 83 m_RegisteredPlugins.insert(pluginName, pluginPath);
84 84 }
85 85 else {
86 86 loadState.setError(QObject::tr("the file is not a Sciqlop plugin"));
87 87 }
88 88 }
89 89 }
90 90 else {
91 91 loadState.setError(QObject::tr("the file is not a library"));
92 92 }
93 93
94 94 // Log loading result
95 95 loadState.log();
96 96 }
97 97
98 void loadStaticPlugins()
99 {
100 for (QObject *plugin : QPluginLoader::staticInstances())
101 {
102 qobject_cast<IPlugin *>(plugin)->initialize();
103 m_RegisteredPlugins.insert(plugin->metaObject()->className(), "StaticPlugin");
104 }
105 }
106
98 107 /// Registered plugins (key: plugin name, value: plugin path)
99 108 QHash<QString, QString> m_RegisteredPlugins;
100 109 };
101 110
102 111 PluginManager::PluginManager() : impl{spimpl::make_unique_impl<PluginManagerPrivate>()}
103 112 {
104 113 }
105 114
106 115 void PluginManager::loadPlugins(const QDir &pluginDir)
107 116 {
108 117 // Load plugins
109 118 auto pluginInfoList
110 119 = pluginDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
111 120 for (auto entryInfo : qAsConst(pluginInfoList)) {
112 121 if (entryInfo.isDir()) {
113 122 this->loadPlugins(QDir{entryInfo.absoluteFilePath()});
114 123 }
115 124 else if (QLibrary::isLibrary(entryInfo.absoluteFilePath())) {
116 125 impl->loadPlugin(entryInfo.absoluteFilePath());
117 126 }
118 127 }
119 128 }
120 129
130 void PluginManager::loadStaticPlugins()
131 {
132 impl->loadStaticPlugins();
133 }
134
121 135 int PluginManager::nbPluginsLoaded() const noexcept
122 136 {
123 137 return impl->m_RegisteredPlugins.size();
124 138 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved

Status change > Approved

You need to be logged in to leave comments. Login now