Loading...
Searching...
No Matches
PluginManager.hpp
1#pragma once
2#include <score/application/ApplicationContext.hpp>
3#include <score/application/GUIApplicationContext.hpp>
4#include <score/plugins/InterfaceList.hpp>
5#include <score/plugins/PluginInstances.hpp>
6#include <score/plugins/qt_interfaces/CommandFactory_QtInterface.hpp>
7#include <score/plugins/qt_interfaces/FactoryFamily_QtInterface.hpp>
8#include <score/plugins/qt_interfaces/FactoryInterface_QtInterface.hpp>
9#include <score/plugins/qt_interfaces/GUIApplicationPlugin_QtInterface.hpp>
10#include <score/plugins/qt_interfaces/PluginRequirements_QtInterface.hpp>
11#include <score/tools/std/Optional.hpp>
12
13#include <core/plugin/PluginDependencyGraph.hpp>
14
15#include <QString>
16#include <QStringList>
17
18#include <score_lib_base_export.h>
19
20#include <vector>
21namespace score
22{
23struct ApplicationContext;
24class GUIApplicationRegistrar;
25class Plugin_QtInterface;
26struct Addon;
27
32namespace PluginLoader
33{
34
35enum class PluginLoadingError
36{
37 NoError,
38 Blacklisted,
39 NotAPlugin,
40 AlreadyLoaded,
41 UnknownError
42};
43
44QStringList addonsDir();
45QStringList pluginsDir();
46
47SCORE_LIB_BASE_EXPORT void loadPluginsInAllFolders(
48 std::vector<score::Addon>& availablePlugins, QStringList additional = {});
49
50SCORE_LIB_BASE_EXPORT void
51loadAddonsInAllFolders(std::vector<score::Addon>& availablePlugins);
52
53std::pair<score::Plugin_QtInterface*, PluginLoadingError>
54loadPlugin(const QString& fileName, const std::vector<score::Addon>& availablePlugins);
55
56std::optional<score::Addon> makeAddon(
57 const QString& addon_path, const QJsonObject& json_addon,
58 const std::vector<score::Addon>& availablePlugins);
59
60template <typename Registrar_T>
61void registerPluginsImpl(
62 const std::vector<score::Addon>& availablePlugins, Registrar_T& registrar,
63 const score::GUIApplicationContext& context)
64{
65 // Load what the plug-ins have to offer.
66 for(const score::Addon& addon : availablePlugins)
67 {
68 auto commands_plugin = dynamic_cast<CommandFactory_QtInterface*>(addon.plugin);
69 if(commands_plugin)
70 {
71 auto [key, cmds] = commands_plugin->make_commands();
72 registrar.registerCommands(key, std::move(cmds));
73 }
74
75 auto factories_plugin = dynamic_cast<FactoryInterface_QtInterface*>(addon.plugin);
76 if(factories_plugin)
77 {
78 for(auto& factory_family : registrar.components().factories)
79 {
80 const score::ApplicationContext& base_ctx = context;
81 // Register core factories
82 for(auto&& new_factory :
83 factories_plugin->factories(base_ctx, factory_family.first))
84 {
85 factory_family.second->insert(std::unique_ptr<InterfaceBase>(new_factory));
86 }
87
88 // Register GUI factories
89 for(auto&& new_factory :
90 factories_plugin->guiFactories(context, factory_family.first))
91 {
92 factory_family.second->insert(std::unique_ptr<InterfaceBase>(new_factory));
93 }
94 }
95 }
96 }
97}
98
99template <typename Registrar_T>
100void registerPlugins(
101 const std::vector<score::Addon>& availablePlugins, Registrar_T& registrar,
102 const score::GUIApplicationContext& context)
103{
104 for(const score::Addon& addon : availablePlugins)
105 {
106 auto ctrl_plugin = dynamic_cast<ApplicationPlugin_QtInterface*>(addon.plugin);
107 if(ctrl_plugin)
108 {
109 if(auto plug = ctrl_plugin->make_applicationPlugin(context))
110 registrar.registerApplicationPlugin(plug);
111 if(auto plug = ctrl_plugin->make_guiApplicationPlugin(context))
112 registrar.registerGUIApplicationPlugin(plug);
113 }
114 }
115 registerPluginsImpl(availablePlugins, registrar, context);
116}
117
125template <typename Registrar_T, typename Context_T>
126void loadPlugins(Registrar_T& registrar, const Context_T& context)
127{
128 // Here, the plug-ins that are effectively loaded.
129 std::vector<score::Addon> availablePlugins;
130
131 // Load static plug-ins
132 for(auto score_plug : score::staticPlugins())
133 {
134 score::Addon addon;
135 addon.plugin = score_plug;
136 addon.key = score_plug->key();
137 addon.corePlugin = true;
138 availablePlugins.push_back(std::move(addon));
139 }
140
141 loadPluginsInAllFolders(availablePlugins);
142 loadAddonsInAllFolders(availablePlugins);
143
144 // First bring in the plugin objects
145 registrar.registerAddons(availablePlugins);
146
147 // Here, it is important not to collapse all the for-loops
148 // because for instance a ApplicationPlugin from plugin B might require the
149 // factory
150 // from plugin A to be loaded prior.
151 // Load all the factories.
152 for(const score::Addon& addon : availablePlugins)
153 {
154 auto facfam_interface = dynamic_cast<FactoryList_QtInterface*>(addon.plugin);
155
156 if(facfam_interface)
157 {
158 for(auto&& elt : facfam_interface->factoryFamilies())
159 {
160 registrar.registerFactory(std::move(elt));
161 }
162 }
163 }
164
165 // Load all the application context plugins.
166 // We have to order them according to their dependencies
167 PluginDependencyGraph graph{availablePlugins};
168 const auto& add = graph.sortedAddons();
169 if(!add.empty())
170 {
171 registerPlugins(add, registrar, context);
172 }
173}
174}
175}
Classes and functions used at the plug-in loading step.
Base toolkit upon which the software is built.
Definition Application.cpp:90
The Addon struct.
Definition Addon.hpp:16
Used to access all the application-wide state and structures.
Definition ApplicationContext.hpp:24
Specializes ApplicationContext with the QMainWindow.
Definition GUIApplicationContext.hpp:15