diff options
| author | Mikaël Capelle <capelle.mikael@gmail.com> | 2022-05-17 11:37:19 +0200 |
|---|---|---|
| committer | Mikaël Capelle <capelle.mikael@gmail.com> | 2023-07-09 17:17:53 +0200 |
| commit | 86bb01ba9eac879d3685c439ac9da0028bc4bc80 (patch) | |
| tree | 90cc575c2d02113af459b7772418285f2e5caa1f /src/plugincontainer.h | |
| parent | 7d6cb8528d20e36a4cee822263865ee2f7f32481 (diff) | |
Convert everything to CRLF.
Diffstat (limited to 'src/plugincontainer.h')
| -rw-r--r-- | src/plugincontainer.h | 996 |
1 files changed, 498 insertions, 498 deletions
diff --git a/src/plugincontainer.h b/src/plugincontainer.h index 2ab9a4b7..688c9f10 100644 --- a/src/plugincontainer.h +++ b/src/plugincontainer.h @@ -1,498 +1,498 @@ -#ifndef PLUGINCONTAINER_H
-#define PLUGINCONTAINER_H
-
-#include "previewgenerator.h"
-
-class OrganizerCore;
-class IUserInterface;
-
-#include <iplugindiagnose.h>
-#include <ipluginmodpage.h>
-#include <iplugingame.h>
-#include <iplugintool.h>
-#include <ipluginproxy.h>
-#include <iplugininstaller.h>
-#include <ipluginfilemapper.h>
-#include <QtPlugin>
-#include <QPluginLoader>
-#include <QFile>
-#ifndef Q_MOC_RUN
-#include <boost/fusion/container.hpp>
-#include <boost/fusion/include/at_key.hpp>
-#include <boost/mp11.hpp>
-#endif // Q_MOC_RUN
-#include <vector>
-#include <memory>
-
-
-class OrganizerProxy;
-
-/**
- * @brief Class that wrap multiple requirements for a plugin together. THis
- * class owns the requirements.
- */
-class PluginRequirements {
-public:
-
- /**
- * @return true if the plugin can be enabled (all requirements are met).
- */
- bool canEnable() const;
-
- /**
- * @return true if this is a core plugin, i.e. a plugin that should not be
- * manually enabled or disabled by the user.
- */
- bool isCorePlugin() const;
-
- /**
- * @return true if this plugin has requirements (satisfied or not).
- */
- bool hasRequirements() const;
-
- /**
- * @return the proxy that created this plugin, if any.
- */
- MOBase::IPluginProxy* proxy() const;
-
- /**
- * @return the list of plugins this plugin proxies (if it's a proxy plugin).
- */
- std::vector<MOBase::IPlugin*> proxied() const;
-
- /**
- * @return the master of this plugin, if any.
- */
- MOBase::IPlugin* master() const;
-
- /**
- * @return the plugins this plugin is master of.
- */
- std::vector<MOBase::IPlugin*> children() const;
-
- /**
- * @return the list of problems to be resolved before enabling the plugin.
- */
- std::vector<MOBase::IPluginRequirement::Problem> problems() const;
-
- /**
- * @return the name of the games (gameName()) this plugin can be used with, or an empty
- * list if this plugin does not require particular games.
- */
- QStringList requiredGames() const;
-
- /**
- * @return the list of plugins currently enabled that would have to be disabled
- * if this plugin was disabled.
- */
- std::vector<MOBase::IPlugin*> requiredFor() const;
-
-private:
-
- // The list of "Core" plugins.
- static const std::set<QString> s_CorePlugins;
-
- // Accumulator version for requiredFor() to avoid infinite recursion.
- void requiredFor(std::vector<MOBase::IPlugin*>& required, std::set<MOBase::IPlugin*>& visited) const;
-
- // Retrieve the requirements from the underlying plugin, take ownership on them
- // and store them. We cannot do this in the constructor because we want to have a
- // constructed object before calling init().
- void fetchRequirements();
-
- // Set the master for this plugin. This is required to "fake" masters for proxied plugins.
- void setMaster(MOBase::IPlugin* master);
-
- friend class OrganizerCore;
- friend class PluginContainer;
-
- PluginContainer* m_PluginContainer;
- MOBase::IPlugin* m_Plugin;
- MOBase::IPluginProxy* m_PluginProxy;
- MOBase::IPlugin* m_Master;
- std::vector<std::shared_ptr<const MOBase::IPluginRequirement>> m_Requirements;
- OrganizerProxy* m_Organizer;
- std::vector<MOBase::IPlugin*> m_RequiredFor;
-
- PluginRequirements(
- PluginContainer* pluginContainer, MOBase::IPlugin* plugin,
- OrganizerProxy* proxy, MOBase::IPluginProxy* pluginProxy);
-
-};
-
-
-/**
- *
- */
-class PluginContainer : public QObject, public MOBase::IPluginDiagnose
-{
-
- Q_OBJECT
- Q_INTERFACES(MOBase::IPluginDiagnose)
-
-private:
-
- using PluginMap = boost::fusion::map<
- boost::fusion::pair<QObject, std::vector<QObject*>>,
- boost::fusion::pair<MOBase::IPlugin, std::vector<MOBase::IPlugin*>>,
- boost::fusion::pair<MOBase::IPluginDiagnose, std::vector<MOBase::IPluginDiagnose*>>,
- boost::fusion::pair<MOBase::IPluginGame, std::vector<MOBase::IPluginGame*>>,
- boost::fusion::pair<MOBase::IPluginInstaller, std::vector<MOBase::IPluginInstaller*>>,
- boost::fusion::pair<MOBase::IPluginModPage, std::vector<MOBase::IPluginModPage*>>,
- boost::fusion::pair<MOBase::IPluginPreview, std::vector<MOBase::IPluginPreview*>>,
- boost::fusion::pair<MOBase::IPluginTool, std::vector<MOBase::IPluginTool*>>,
- boost::fusion::pair<MOBase::IPluginProxy, std::vector<MOBase::IPluginProxy*>>,
- boost::fusion::pair<MOBase::IPluginFileMapper, std::vector<MOBase::IPluginFileMapper*>>
- >;
-
- using AccessPluginMap = boost::fusion::map<
- boost::fusion::pair<MOBase::IPluginDiagnose, std::map<MOBase::IPluginDiagnose*, MOBase::IPlugin*>>,
- boost::fusion::pair<MOBase::IPluginFileMapper, std::map<MOBase::IPluginFileMapper*, MOBase::IPlugin*>>,
- boost::fusion::pair<QString, std::map<QString, MOBase::IPlugin*>>
- >;
-
- static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1;
-
- /**
- * This typedefs defines the order of plugin interface. This is increasing order of
- * importance".
- *
- * @note IPlugin is the less important interface, followed by IPluginDiagnose and
- * IPluginFileMapper as those are usually implemented together with another interface.
- * Other interfaces are in a alphabetical order since it is unlikely a plugin will
- * implement multiple ones.
- */
- using PluginTypeOrder =
- boost::mp11::mp_transform<
- std::add_pointer_t,
- boost::mp11::mp_list<
- MOBase::IPluginGame, MOBase::IPluginInstaller, MOBase::IPluginModPage, MOBase::IPluginPreview,
- MOBase::IPluginProxy, MOBase::IPluginTool, MOBase::IPluginDiagnose, MOBase::IPluginFileMapper,
- MOBase::IPlugin
- >
- >;
-
- static_assert(
- boost::mp11::mp_size<PluginTypeOrder>::value == boost::mp11::mp_size<PluginContainer::PluginMap>::value - 1);
-
-public:
-
- /**
- * @brief Retrieved the (localized) names of the various plugin interfaces.
- *
- * @return the (localized) names of the various plugin interfaces.
- */
- static QStringList pluginInterfaces();
-
-public:
-
- PluginContainer(OrganizerCore* organizer);
- virtual ~PluginContainer();
-
- /**
- * @brief Start the plugins.
- *
- * This function should not be called before MO2 is ready and plugins can be
- * started, and will do the following:
- * - connect the callbacks of the plugins,
- * - set the parent widget for plugins that can have one,
- * - notify plugins that MO2 has been started, including:
- * - triggering a call to the "profile changed" callback for the initial profile,
- * - triggering a call to the "user interface initialized" callback.
- *
- * @param userInterface The main user interface to use for the plugins.
- */
- void startPlugins(IUserInterface* userInterface);
-
- /**
- * @brief Load, unload or reload the plugin at the given path.
- *
- */
- void loadPlugin(QString const& filepath);
- void unloadPlugin(QString const& filepath);
- void reloadPlugin(QString const& filepath);
-
- /**
- * @brief Load all plugins.
- *
- */
- void loadPlugins();
-
- /**
- * @brief Retrieve the list of plugins of the given type.
- *
- * @return the list of plugins of the specified type.
- *
- * @tparam T The type of plugin to retrieve.
- */
- template <typename T>
- const std::vector<T*> &plugins() const {
- typename boost::fusion::result_of::at_key<const PluginMap, T>::type temp = boost::fusion::at_key<T>(m_Plugins);
- return temp;
- }
-
- /**
- * @brief Check if a plugin implement a given interface.
- *
- * @param plugin The plugin to check.
- *
- * @return true if the plugin implements the interface, false otherwise.
- *
- * @tparam The interface type.
- */
- template <typename T>
- bool implementInterface(MOBase::IPlugin* plugin) const {
- // We need a QObject to be able to qobject_cast<> to the plugin types:
- QObject* oPlugin = as_qobject(plugin);
-
- if (!oPlugin) {
- return false;
- }
-
- return qobject_cast<T*>(oPlugin);
- }
-
- /**
- * @brief Retrieve a plugin from its name or a corresponding non-IPlugin
- * interface.
- *
- * @param t Name of the plugin to retrieve, or non-IPlugin interface.
- *
- * @return the corresponding plugin, or a null pointer.
- *
- * @note It is possible to have multiple plugins for the same name when
- * dealing with proxied plugins (e.g. Python), in which case the
- * most important one will be returned, as specified in PluginTypeOrder.
- */
- MOBase::IPlugin* plugin(QString const& pluginName) const;
- MOBase::IPlugin* plugin(MOBase::IPluginDiagnose* diagnose) const;
- MOBase::IPlugin* plugin(MOBase::IPluginFileMapper* mapper) const;
-
- /**
- * @brief Find the game plugin corresponding to the given name.
- *
- * @param name The name of the game to find a plugin for (as returned by
- * IPluginGame::gameName()).
- *
- * @return the game plugin for the given name, or a null pointer if no
- * plugin exists for this game.
- */
- MOBase::IPluginGame* game(const QString& name) const;
-
- /**
- * @return the IPlugin interface to the currently managed game.
- */
- MOBase::IPlugin* managedGame() const;
-
- /**
- * @brief Check if the given plugin is enabled.
- *
- * @param plugin The plugin to check.
- *
- * @return true if the plugin is enabled, false otherwise.
- */
- bool isEnabled(MOBase::IPlugin* plugin) const;
-
- // These are friendly methods that called isEnabled(plugin(arg)).
- bool isEnabled(QString const& pluginName) const;
- bool isEnabled(MOBase::IPluginDiagnose* diagnose) const;
- bool isEnabled(MOBase::IPluginFileMapper* mapper) const;
-
- /**
- * @brief Enable or disable a plugin.
- *
- * @param plugin The plugin to enable or disable.
- * @param enable true to enable, false to disable.
- * @param dependencies If true and enable is false, dependencies will also
- * be disabled (see PluginRequirements::requiredFor).
- */
- void setEnabled(MOBase::IPlugin* plugin, bool enable, bool dependencies = true);
-
- /**
- * @brief Retrieve the requirements for the given plugin.
- *
- * @param plugin The plugin to retrieve the requirements for.
- *
- * @return the requirements (as proxy) for the given plugin.
- */
- const PluginRequirements& requirements(MOBase::IPlugin* plugin) const;
-
- /**
- * @brief Retrieved the (localized) names of interfaces implemented by the given
- * plugin.
- *
- * @param plugin The plugin to retrieve interface for.
- *
- * @return the (localized) names of interfaces implemented by this plugin.
- */
- QStringList implementedInterfaces(MOBase::IPlugin* plugin) const;
-
- /**
- * @brief Return the (localized) name of the most important interface implemented by
- * the given plugin.
- *
- * The order of interfaces is defined in X.
- *
- * @param plugin The plugin to retrieve the interface for.
- *
- * @return the (localized) name of the most important interface implemented by this plugin.
- */
- QString topImplementedInterface(MOBase::IPlugin* plugin) const;
-
- /**
- * @return the preview generator.
- */
- const PreviewGenerator &previewGenerator() const;
-
- /**
- * @return the list of plugin file names, including proxied plugins.
- */
- QStringList pluginFileNames() const;
-
-public: // IPluginDiagnose interface
-
- virtual std::vector<unsigned int> activeProblems() const;
- virtual QString shortDescription(unsigned int key) const;
- virtual QString fullDescription(unsigned int key) const;
- virtual bool hasGuidedFix(unsigned int key) const;
- virtual void startGuidedFix(unsigned int key) const;
-
-signals:
-
- /**
- * @brief Emitted when plugins are enabled or disabled.
- */
- void pluginEnabled(MOBase::IPlugin*);
- void pluginDisabled(MOBase::IPlugin*);
-
- /**
- * @brief Emitted when plugins are registered or unregistered.
- */
- void pluginRegistered(MOBase::IPlugin*);
- void pluginUnregistered(MOBase::IPlugin*);
-
- void diagnosisUpdate();
-
-private:
-
- friend class PluginRequirements;
-
- // Unload all the plugins.
- void unloadPlugins();
-
- // Retrieve the organizer proxy for the given plugin.
- OrganizerProxy* organizerProxy(MOBase::IPlugin* plugin) const;
-
- // Retrieve the proxy plugin that instantiated the given plugin, or a null pointer
- // if the plugin was not instantiated by a proxy.
- MOBase::IPluginProxy* pluginProxy(MOBase::IPlugin* plugin) const;
-
- // Retrieve the path to the file or folder corresponding to the plugin.
- QString filepath(MOBase::IPlugin* plugin) const;
-
- // Load plugins from the given filepath using the given proxy.
- std::vector<QObject*> loadProxied(const QString& filepath, MOBase::IPluginProxy* proxy);
-
- // Load the Qt plugin from the given file.
- QObject* loadQtPlugin(const QString& filepath);
-
- // check if a plugin is folder containing a Qt plugin, it is, return the path to the
- // DLL containing the plugin in the folder, otherwise return an empty optional
- //
- // a Qt plugin folder is a folder with a DLL containing a library (not in a subdirectory),
- // if multiple plugins are present, only the first one is returned
- //
- // extra DLLs are ignored by Qt so can be present in the folder
- //
- std::optional<QString> isQtPluginFolder(const QString& filepath) const;
-
- // See startPlugins for more details. This is simply an intermediate function
- // that can be used when loading plugins after initialization. This uses the
- // user interface in m_UserInterface.
- void startPluginsImpl(const std::vector<QObject*>& plugins) const;
-
- /**
- * @brief Unload the given plugin.
- *
- * This function is not public because it's kind of dangerous trying to unload
- * plugin directly since some plugins are linked together.
- *
- * @param plugin The plugin to unload/unregister.
- * @param object The QObject corresponding to the plugin.
- */
- void unloadPlugin(MOBase::IPlugin* plugin, QObject* object);
-
- /**
- * @brief Retrieved the (localized) names of interfaces implemented by the given
- * plugin.
- *
- * @param plugin The plugin to retrieve interface for.
- *
- * @return the (localized) names of interfaces implemented by this plugin.
- *
- * @note This function can be used to get implemented interfaces before registering
- * a plugin.
- */
- QStringList implementedInterfaces(QObject* plugin) const;
-
- /**
- * @brief Check if a plugin implements a "better" interface than another
- * one, as specified by PluginTypeOrder.
- *
- * @param lhs, rhs The plugin to compare.
- *
- * @return true if the left plugin implements a better interface than the right
- * one, false otherwise (or if both implements the same interface).
- */
- bool isBetterInterface(QObject* lhs, QObject* rhs) const;
-
- /**
- * @brief Find the QObject* corresponding to the given plugin.
- *
- * @param plugin The plugin to find the QObject* for.
- *
- * @return a QObject* for the given plugin.
- */
- QObject* as_qobject(MOBase::IPlugin* plugin) const;
-
- /**
- * @brief Initialize a plugin.
- *
- * @param plugin The plugin to initialize.
- * @param proxy The proxy that created this plugin (can be null).
- * @param skipInit If true, IPlugin::init() will not be called, regardless
- * of the state of the container.
- *
- * @return true if the plugin was initialized correctly, false otherwise.
- */
- bool initPlugin(MOBase::IPlugin *plugin, MOBase::IPluginProxy* proxy, bool skipInit);
-
- void registerGame(MOBase::IPluginGame *game);
- void unregisterGame(MOBase::IPluginGame* game);
-
- MOBase::IPlugin* registerPlugin(QObject *pluginObj, const QString &fileName, MOBase::IPluginProxy *proxy);
-
- // Core organizer, can be null (e.g. on first MO2 startup).
- OrganizerCore *m_Organizer;
-
- // Main user interface, can be null until MW has been initialized.
- IUserInterface *m_UserInterface;
-
- PluginMap m_Plugins;
-
- // This maps allow access to IPlugin* from name or diagnose/mapper object.
- AccessPluginMap m_AccessPlugins;
-
- std::map<MOBase::IPlugin*, PluginRequirements> m_Requirements;
-
- std::map<QString, MOBase::IPluginGame*> m_SupportedGames;
- QStringList m_FailedPlugins;
- std::vector<QPluginLoader*> m_PluginLoaders;
-
- PreviewGenerator m_PreviewGenerator;
-
- QFile m_PluginsCheck;
-};
-
-
-#endif // PLUGINCONTAINER_H
+#ifndef PLUGINCONTAINER_H +#define PLUGINCONTAINER_H + +#include "previewgenerator.h" + +class OrganizerCore; +class IUserInterface; + +#include <iplugindiagnose.h> +#include <ipluginmodpage.h> +#include <iplugingame.h> +#include <iplugintool.h> +#include <ipluginproxy.h> +#include <iplugininstaller.h> +#include <ipluginfilemapper.h> +#include <QtPlugin> +#include <QPluginLoader> +#include <QFile> +#ifndef Q_MOC_RUN +#include <boost/fusion/container.hpp> +#include <boost/fusion/include/at_key.hpp> +#include <boost/mp11.hpp> +#endif // Q_MOC_RUN +#include <vector> +#include <memory> + + +class OrganizerProxy; + +/** + * @brief Class that wrap multiple requirements for a plugin together. THis + * class owns the requirements. + */ +class PluginRequirements { +public: + + /** + * @return true if the plugin can be enabled (all requirements are met). + */ + bool canEnable() const; + + /** + * @return true if this is a core plugin, i.e. a plugin that should not be + * manually enabled or disabled by the user. + */ + bool isCorePlugin() const; + + /** + * @return true if this plugin has requirements (satisfied or not). + */ + bool hasRequirements() const; + + /** + * @return the proxy that created this plugin, if any. + */ + MOBase::IPluginProxy* proxy() const; + + /** + * @return the list of plugins this plugin proxies (if it's a proxy plugin). + */ + std::vector<MOBase::IPlugin*> proxied() const; + + /** + * @return the master of this plugin, if any. + */ + MOBase::IPlugin* master() const; + + /** + * @return the plugins this plugin is master of. + */ + std::vector<MOBase::IPlugin*> children() const; + + /** + * @return the list of problems to be resolved before enabling the plugin. + */ + std::vector<MOBase::IPluginRequirement::Problem> problems() const; + + /** + * @return the name of the games (gameName()) this plugin can be used with, or an empty + * list if this plugin does not require particular games. + */ + QStringList requiredGames() const; + + /** + * @return the list of plugins currently enabled that would have to be disabled + * if this plugin was disabled. + */ + std::vector<MOBase::IPlugin*> requiredFor() const; + +private: + + // The list of "Core" plugins. + static const std::set<QString> s_CorePlugins; + + // Accumulator version for requiredFor() to avoid infinite recursion. + void requiredFor(std::vector<MOBase::IPlugin*>& required, std::set<MOBase::IPlugin*>& visited) const; + + // Retrieve the requirements from the underlying plugin, take ownership on them + // and store them. We cannot do this in the constructor because we want to have a + // constructed object before calling init(). + void fetchRequirements(); + + // Set the master for this plugin. This is required to "fake" masters for proxied plugins. + void setMaster(MOBase::IPlugin* master); + + friend class OrganizerCore; + friend class PluginContainer; + + PluginContainer* m_PluginContainer; + MOBase::IPlugin* m_Plugin; + MOBase::IPluginProxy* m_PluginProxy; + MOBase::IPlugin* m_Master; + std::vector<std::shared_ptr<const MOBase::IPluginRequirement>> m_Requirements; + OrganizerProxy* m_Organizer; + std::vector<MOBase::IPlugin*> m_RequiredFor; + + PluginRequirements( + PluginContainer* pluginContainer, MOBase::IPlugin* plugin, + OrganizerProxy* proxy, MOBase::IPluginProxy* pluginProxy); + +}; + + +/** + * + */ +class PluginContainer : public QObject, public MOBase::IPluginDiagnose +{ + + Q_OBJECT + Q_INTERFACES(MOBase::IPluginDiagnose) + +private: + + using PluginMap = boost::fusion::map< + boost::fusion::pair<QObject, std::vector<QObject*>>, + boost::fusion::pair<MOBase::IPlugin, std::vector<MOBase::IPlugin*>>, + boost::fusion::pair<MOBase::IPluginDiagnose, std::vector<MOBase::IPluginDiagnose*>>, + boost::fusion::pair<MOBase::IPluginGame, std::vector<MOBase::IPluginGame*>>, + boost::fusion::pair<MOBase::IPluginInstaller, std::vector<MOBase::IPluginInstaller*>>, + boost::fusion::pair<MOBase::IPluginModPage, std::vector<MOBase::IPluginModPage*>>, + boost::fusion::pair<MOBase::IPluginPreview, std::vector<MOBase::IPluginPreview*>>, + boost::fusion::pair<MOBase::IPluginTool, std::vector<MOBase::IPluginTool*>>, + boost::fusion::pair<MOBase::IPluginProxy, std::vector<MOBase::IPluginProxy*>>, + boost::fusion::pair<MOBase::IPluginFileMapper, std::vector<MOBase::IPluginFileMapper*>> + >; + + using AccessPluginMap = boost::fusion::map< + boost::fusion::pair<MOBase::IPluginDiagnose, std::map<MOBase::IPluginDiagnose*, MOBase::IPlugin*>>, + boost::fusion::pair<MOBase::IPluginFileMapper, std::map<MOBase::IPluginFileMapper*, MOBase::IPlugin*>>, + boost::fusion::pair<QString, std::map<QString, MOBase::IPlugin*>> + >; + + static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1; + + /** + * This typedefs defines the order of plugin interface. This is increasing order of + * importance". + * + * @note IPlugin is the less important interface, followed by IPluginDiagnose and + * IPluginFileMapper as those are usually implemented together with another interface. + * Other interfaces are in a alphabetical order since it is unlikely a plugin will + * implement multiple ones. + */ + using PluginTypeOrder = + boost::mp11::mp_transform< + std::add_pointer_t, + boost::mp11::mp_list< + MOBase::IPluginGame, MOBase::IPluginInstaller, MOBase::IPluginModPage, MOBase::IPluginPreview, + MOBase::IPluginProxy, MOBase::IPluginTool, MOBase::IPluginDiagnose, MOBase::IPluginFileMapper, + MOBase::IPlugin + > + >; + + static_assert( + boost::mp11::mp_size<PluginTypeOrder>::value == boost::mp11::mp_size<PluginContainer::PluginMap>::value - 1); + +public: + + /** + * @brief Retrieved the (localized) names of the various plugin interfaces. + * + * @return the (localized) names of the various plugin interfaces. + */ + static QStringList pluginInterfaces(); + +public: + + PluginContainer(OrganizerCore* organizer); + virtual ~PluginContainer(); + + /** + * @brief Start the plugins. + * + * This function should not be called before MO2 is ready and plugins can be + * started, and will do the following: + * - connect the callbacks of the plugins, + * - set the parent widget for plugins that can have one, + * - notify plugins that MO2 has been started, including: + * - triggering a call to the "profile changed" callback for the initial profile, + * - triggering a call to the "user interface initialized" callback. + * + * @param userInterface The main user interface to use for the plugins. + */ + void startPlugins(IUserInterface* userInterface); + + /** + * @brief Load, unload or reload the plugin at the given path. + * + */ + void loadPlugin(QString const& filepath); + void unloadPlugin(QString const& filepath); + void reloadPlugin(QString const& filepath); + + /** + * @brief Load all plugins. + * + */ + void loadPlugins(); + + /** + * @brief Retrieve the list of plugins of the given type. + * + * @return the list of plugins of the specified type. + * + * @tparam T The type of plugin to retrieve. + */ + template <typename T> + const std::vector<T*> &plugins() const { + typename boost::fusion::result_of::at_key<const PluginMap, T>::type temp = boost::fusion::at_key<T>(m_Plugins); + return temp; + } + + /** + * @brief Check if a plugin implement a given interface. + * + * @param plugin The plugin to check. + * + * @return true if the plugin implements the interface, false otherwise. + * + * @tparam The interface type. + */ + template <typename T> + bool implementInterface(MOBase::IPlugin* plugin) const { + // We need a QObject to be able to qobject_cast<> to the plugin types: + QObject* oPlugin = as_qobject(plugin); + + if (!oPlugin) { + return false; + } + + return qobject_cast<T*>(oPlugin); + } + + /** + * @brief Retrieve a plugin from its name or a corresponding non-IPlugin + * interface. + * + * @param t Name of the plugin to retrieve, or non-IPlugin interface. + * + * @return the corresponding plugin, or a null pointer. + * + * @note It is possible to have multiple plugins for the same name when + * dealing with proxied plugins (e.g. Python), in which case the + * most important one will be returned, as specified in PluginTypeOrder. + */ + MOBase::IPlugin* plugin(QString const& pluginName) const; + MOBase::IPlugin* plugin(MOBase::IPluginDiagnose* diagnose) const; + MOBase::IPlugin* plugin(MOBase::IPluginFileMapper* mapper) const; + + /** + * @brief Find the game plugin corresponding to the given name. + * + * @param name The name of the game to find a plugin for (as returned by + * IPluginGame::gameName()). + * + * @return the game plugin for the given name, or a null pointer if no + * plugin exists for this game. + */ + MOBase::IPluginGame* game(const QString& name) const; + + /** + * @return the IPlugin interface to the currently managed game. + */ + MOBase::IPlugin* managedGame() const; + + /** + * @brief Check if the given plugin is enabled. + * + * @param plugin The plugin to check. + * + * @return true if the plugin is enabled, false otherwise. + */ + bool isEnabled(MOBase::IPlugin* plugin) const; + + // These are friendly methods that called isEnabled(plugin(arg)). + bool isEnabled(QString const& pluginName) const; + bool isEnabled(MOBase::IPluginDiagnose* diagnose) const; + bool isEnabled(MOBase::IPluginFileMapper* mapper) const; + + /** + * @brief Enable or disable a plugin. + * + * @param plugin The plugin to enable or disable. + * @param enable true to enable, false to disable. + * @param dependencies If true and enable is false, dependencies will also + * be disabled (see PluginRequirements::requiredFor). + */ + void setEnabled(MOBase::IPlugin* plugin, bool enable, bool dependencies = true); + + /** + * @brief Retrieve the requirements for the given plugin. + * + * @param plugin The plugin to retrieve the requirements for. + * + * @return the requirements (as proxy) for the given plugin. + */ + const PluginRequirements& requirements(MOBase::IPlugin* plugin) const; + + /** + * @brief Retrieved the (localized) names of interfaces implemented by the given + * plugin. + * + * @param plugin The plugin to retrieve interface for. + * + * @return the (localized) names of interfaces implemented by this plugin. + */ + QStringList implementedInterfaces(MOBase::IPlugin* plugin) const; + + /** + * @brief Return the (localized) name of the most important interface implemented by + * the given plugin. + * + * The order of interfaces is defined in X. + * + * @param plugin The plugin to retrieve the interface for. + * + * @return the (localized) name of the most important interface implemented by this plugin. + */ + QString topImplementedInterface(MOBase::IPlugin* plugin) const; + + /** + * @return the preview generator. + */ + const PreviewGenerator &previewGenerator() const; + + /** + * @return the list of plugin file names, including proxied plugins. + */ + QStringList pluginFileNames() const; + +public: // IPluginDiagnose interface + + virtual std::vector<unsigned int> activeProblems() const; + virtual QString shortDescription(unsigned int key) const; + virtual QString fullDescription(unsigned int key) const; + virtual bool hasGuidedFix(unsigned int key) const; + virtual void startGuidedFix(unsigned int key) const; + +signals: + + /** + * @brief Emitted when plugins are enabled or disabled. + */ + void pluginEnabled(MOBase::IPlugin*); + void pluginDisabled(MOBase::IPlugin*); + + /** + * @brief Emitted when plugins are registered or unregistered. + */ + void pluginRegistered(MOBase::IPlugin*); + void pluginUnregistered(MOBase::IPlugin*); + + void diagnosisUpdate(); + +private: + + friend class PluginRequirements; + + // Unload all the plugins. + void unloadPlugins(); + + // Retrieve the organizer proxy for the given plugin. + OrganizerProxy* organizerProxy(MOBase::IPlugin* plugin) const; + + // Retrieve the proxy plugin that instantiated the given plugin, or a null pointer + // if the plugin was not instantiated by a proxy. + MOBase::IPluginProxy* pluginProxy(MOBase::IPlugin* plugin) const; + + // Retrieve the path to the file or folder corresponding to the plugin. + QString filepath(MOBase::IPlugin* plugin) const; + + // Load plugins from the given filepath using the given proxy. + std::vector<QObject*> loadProxied(const QString& filepath, MOBase::IPluginProxy* proxy); + + // Load the Qt plugin from the given file. + QObject* loadQtPlugin(const QString& filepath); + + // check if a plugin is folder containing a Qt plugin, it is, return the path to the + // DLL containing the plugin in the folder, otherwise return an empty optional + // + // a Qt plugin folder is a folder with a DLL containing a library (not in a subdirectory), + // if multiple plugins are present, only the first one is returned + // + // extra DLLs are ignored by Qt so can be present in the folder + // + std::optional<QString> isQtPluginFolder(const QString& filepath) const; + + // See startPlugins for more details. This is simply an intermediate function + // that can be used when loading plugins after initialization. This uses the + // user interface in m_UserInterface. + void startPluginsImpl(const std::vector<QObject*>& plugins) const; + + /** + * @brief Unload the given plugin. + * + * This function is not public because it's kind of dangerous trying to unload + * plugin directly since some plugins are linked together. + * + * @param plugin The plugin to unload/unregister. + * @param object The QObject corresponding to the plugin. + */ + void unloadPlugin(MOBase::IPlugin* plugin, QObject* object); + + /** + * @brief Retrieved the (localized) names of interfaces implemented by the given + * plugin. + * + * @param plugin The plugin to retrieve interface for. + * + * @return the (localized) names of interfaces implemented by this plugin. + * + * @note This function can be used to get implemented interfaces before registering + * a plugin. + */ + QStringList implementedInterfaces(QObject* plugin) const; + + /** + * @brief Check if a plugin implements a "better" interface than another + * one, as specified by PluginTypeOrder. + * + * @param lhs, rhs The plugin to compare. + * + * @return true if the left plugin implements a better interface than the right + * one, false otherwise (or if both implements the same interface). + */ + bool isBetterInterface(QObject* lhs, QObject* rhs) const; + + /** + * @brief Find the QObject* corresponding to the given plugin. + * + * @param plugin The plugin to find the QObject* for. + * + * @return a QObject* for the given plugin. + */ + QObject* as_qobject(MOBase::IPlugin* plugin) const; + + /** + * @brief Initialize a plugin. + * + * @param plugin The plugin to initialize. + * @param proxy The proxy that created this plugin (can be null). + * @param skipInit If true, IPlugin::init() will not be called, regardless + * of the state of the container. + * + * @return true if the plugin was initialized correctly, false otherwise. + */ + bool initPlugin(MOBase::IPlugin *plugin, MOBase::IPluginProxy* proxy, bool skipInit); + + void registerGame(MOBase::IPluginGame *game); + void unregisterGame(MOBase::IPluginGame* game); + + MOBase::IPlugin* registerPlugin(QObject *pluginObj, const QString &fileName, MOBase::IPluginProxy *proxy); + + // Core organizer, can be null (e.g. on first MO2 startup). + OrganizerCore *m_Organizer; + + // Main user interface, can be null until MW has been initialized. + IUserInterface *m_UserInterface; + + PluginMap m_Plugins; + + // This maps allow access to IPlugin* from name or diagnose/mapper object. + AccessPluginMap m_AccessPlugins; + + std::map<MOBase::IPlugin*, PluginRequirements> m_Requirements; + + std::map<QString, MOBase::IPluginGame*> m_SupportedGames; + QStringList m_FailedPlugins; + std::vector<QPluginLoader*> m_PluginLoaders; + + PreviewGenerator m_PreviewGenerator; + + QFile m_PluginsCheck; +}; + + +#endif // PLUGINCONTAINER_H |
