diff options
| author | Seth Riley <17361645+Qudix@users.noreply.github.com> | 2020-12-01 15:55:50 -0600 |
|---|---|---|
| committer | Seth Riley <17361645+Qudix@users.noreply.github.com> | 2020-12-01 15:55:50 -0600 |
| commit | 852d8745a1ac3ef2aaa83ae21d473d20428d7d30 (patch) | |
| tree | 7ff242377cd3ec72571cd96cd631c28bbaac6470 /src/plugincontainer.h | |
| parent | 60688ecf5bc6e44795472cb22888ec5994a904a8 (diff) | |
| parent | 1ec3ab2b8a845f75495b4cacbeb17c86ea137a01 (diff) | |
Merge https://github.com/ModOrganizer2/modorganizer into ignore_alt
Diffstat (limited to 'src/plugincontainer.h')
| -rw-r--r-- | src/plugincontainer.h | 260 |
1 files changed, 244 insertions, 16 deletions
diff --git a/src/plugincontainer.h b/src/plugincontainer.h index 2b39726b..26e12659 100644 --- a/src/plugincontainer.h +++ b/src/plugincontainer.h @@ -22,8 +22,107 @@ class IUserInterface; #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 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;
+ MOBase::IOrganizer* m_Organizer;
+ std::vector<MOBase::IPlugin*> m_RequiredFor;
+
+ PluginRequirements(
+ PluginContainer* pluginContainer, MOBase::IPlugin* plugin,
+ MOBase::IOrganizer* proxy, MOBase::IPluginProxy* pluginProxy);
+
+};
+
+
+/**
+ *
+ */
class PluginContainer : public QObject, public MOBase::IPluginDiagnose
{
@@ -32,18 +131,24 @@ class PluginContainer : public QObject, public MOBase::IPluginDiagnose private:
- typedef 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*>>
- > PluginMap;
+ 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;
@@ -83,7 +188,7 @@ public: PluginContainer(OrganizerCore *organizer);
virtual ~PluginContainer();
- void setUserInterface(IUserInterface *userInterface, QWidget *widget);
+ void setUserInterface(IUserInterface *userInterface);
void loadPlugins();
void unloadPlugins();
@@ -113,6 +218,81 @@ public: }
/**
+ * @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;
+
+ /**
+ * @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.
*
@@ -154,10 +334,43 @@ public: // IPluginDiagnose interface signals:
+ /**
+ * @brief Emitted plugins are enabled or disabled.
+ */
+ void pluginEnabled(MOBase::IPlugin*);
+ void pluginDisabled(MOBase::IPlugin*);
+
void diagnosisUpdate();
private:
+ friend class PluginRequirements;
+
+
+ /**
+ * @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.
*
@@ -167,11 +380,21 @@ private: */
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);
- bool initPlugin(MOBase::IPlugin *plugin);
- bool initProxyPlugin(MOBase::IPlugin *plugin);
void registerGame(MOBase::IPluginGame *game);
- bool registerPlugin(QObject *pluginObj, const QString &fileName);
+
+ MOBase::IPlugin* registerPlugin(QObject *pluginObj, const QString &fileName, MOBase::IPluginProxy *proxy);
OrganizerCore *m_Organizer;
@@ -179,6 +402,11 @@ private: 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;
std::vector<boost::signals2::connection> m_DiagnosisConnections;
QStringList m_FailedPlugins;
|
