summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/installationmanager.cpp32
-rw-r--r--src/installationmanager.h17
-rw-r--r--src/mainwindow.cpp8
-rw-r--r--src/organizercore.cpp3
-rw-r--r--src/organizerproxy.cpp10
-rw-r--r--src/organizerproxy.h8
-rw-r--r--src/plugincontainer.cpp118
-rw-r--r--src/plugincontainer.h125
-rw-r--r--src/previewgenerator.cpp11
-rw-r--r--src/previewgenerator.h6
-rw-r--r--src/problemsdialog.cpp15
-rw-r--r--src/problemsdialog.h5
-rw-r--r--src/proxyutils.h2
13 files changed, 296 insertions, 64 deletions
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index e9773a95..06909994 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -78,7 +78,8 @@ static T resolveFunction(QLibrary &lib, const char *name)
}
InstallationManager::InstallationManager()
- : m_ParentWidget(nullptr),
+ :
+ m_ParentWidget(nullptr),
m_SupportedExtensions({"zip", "rar", "7z", "fomod", "001"}),
m_IsRunning(false) {
m_ArchiveHandler = CreateArchive();
@@ -106,7 +107,7 @@ InstallationManager::InstallationManager()
// Connect the query password slot - This is the only way I found to be able to query user
// from a separate thread. We use a BlockingQueuedConnection so that calling passwordRequested()
// will block until the end of the slot.
- connect(this, &InstallationManager::passwordRequested,
+ connect(this, &InstallationManager::passwordRequested,
this, &InstallationManager::queryPassword, Qt::BlockingQueuedConnection);
}
@@ -122,6 +123,11 @@ void InstallationManager::setParentWidget(QWidget *widget)
}
}
+void InstallationManager::setPluginContainer(const PluginContainer* pluginContainer)
+{
+ m_PluginContainer = pluginContainer;
+}
+
void InstallationManager::queryPassword() {
m_Password = QInputDialog::getText(m_ParentWidget, tr("Password required"),
tr("Password"), QLineEdit::Password);
@@ -284,7 +290,7 @@ QStringList InstallationManager::extractFiles(std::vector<std::shared_ptr<const
}
-QString InstallationManager::createFile(std::shared_ptr<const MOBase::FileTreeEntry> entry)
+QString InstallationManager::createFile(std::shared_ptr<const MOBase::FileTreeEntry> entry)
{
// Use QTemporaryFile to create the temporary file with the given template:
QTemporaryFile tempFile(QDir::cleanPath(QDir::tempPath() + QDir::separator() + "mo2-install"));
@@ -308,11 +314,11 @@ QString InstallationManager::createFile(std::shared_ptr<const MOBase::FileTreeEn
return QDir::toNativeSeparators(absPath);
}
-void InstallationManager::cleanCreatedFiles(std::shared_ptr<const MOBase::IFileTree> fileTree)
+void InstallationManager::cleanCreatedFiles(std::shared_ptr<const MOBase::IFileTree> fileTree)
{
// We simply have to check if all the entries have fileTree as a parent:
for (auto it = std::begin(m_CreatedFiles); it != std::end(m_CreatedFiles); ) {
-
+
// Find the parent - Could this be in FileTreeEntry?
bool found = false;
{
@@ -495,12 +501,12 @@ IPluginInstaller::EInstallResult InstallationManager::doInstall(GuessedValue<QSt
if (QFile::exists(destPath)) {
QFile::remove(destPath);
}
-
+
QDir dir = QFileInfo(destPath).absoluteDir();
if (!dir.exists()) {
dir.mkpath(".");
}
-
+
QFile::copy(p.second, destPath);
}
@@ -691,7 +697,7 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
}
ON_BLOCK_EXIT(std::bind(&InstallationManager::postInstallCleanup, this));
- std::shared_ptr<IFileTree> filesTree =
+ std::shared_ptr<IFileTree> filesTree =
archiveOpen ? ArchiveFileTree::makeTree(*m_ArchiveHandler) : nullptr;
IPluginInstaller::EInstallResult installResult = IPluginInstaller::RESULT_NOTATTEMPTED;
@@ -701,7 +707,7 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
for (IPluginInstaller *installer : m_Installers) {
// don't use inactive installers (installer can't be null here but vc static code analysis thinks it could)
- if ((installer == nullptr) || !installer->isActive()) {
+ if ((installer == nullptr) || !m_PluginContainer->isEnabled(installer)) {
continue;
}
@@ -731,7 +737,7 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
if (p == nullptr) {
throw IncompatibilityException(tr("Invalid file tree returned by plugin."));
}
-
+
// Detach the file tree (this ensure the parent is null and call to path()
// stops at this root):
p->detach();
@@ -786,7 +792,7 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
case IPluginInstaller::RESULT_SUCCESSCANCEL: {
if (filesTree != nullptr) {
auto iniTweakEntry = filesTree->find("INI Tweaks", FileTreeEntry::DIRECTORY);
- hasIniTweaks = iniTweakEntry != nullptr
+ hasIniTweaks = iniTweakEntry != nullptr
&& !iniTweakEntry->astree()->empty();
}
return IPluginInstaller::RESULT_SUCCESS;
@@ -860,7 +866,7 @@ QStringList InstallationManager::getSupportedExtensions() const
void InstallationManager::notifyInstallationStart(QString const& archive, bool reinstallation, ModInfo::Ptr currentMod)
{
for (auto* installer : m_Installers) {
- if (installer->isActive()) {
+ if (m_PluginContainer->isEnabled(installer)) {
installer->onInstallationStart(archive, reinstallation, currentMod.get());
}
}
@@ -871,7 +877,7 @@ void InstallationManager::notifyInstallationEnd(
ModInfo::Ptr newMod)
{
for (auto* installer : m_Installers) {
- if (installer->isActive()) {
+ if (m_PluginContainer->isEnabled(installer)) {
installer->onInstallationEnd(result, newMod.get());
}
}
diff --git a/src/installationmanager.h b/src/installationmanager.h
index 66f11eae..e1db5e1f 100644
--- a/src/installationmanager.h
+++ b/src/installationmanager.h
@@ -35,6 +35,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <errorcodes.h>
#include "modinfo.h"
+#include "plugincontainer.h"
/**
@@ -88,6 +89,11 @@ public:
void setModsDirectory(const QString &modsDirectory) { m_ModsDirectory = modsDirectory; }
/**
+ *
+ */
+ void setPluginContainer(const PluginContainer* pluginContainer);
+
+ /**
* @brief update the directory where downloads are stored
* @param downloadDirectory the download directory
*/
@@ -126,8 +132,8 @@ public:
* @brief register an installer-plugin
* @param the installer to register
*/
- void registerInstaller(MOBase::IPluginInstaller *installer);
-
+ void registerInstaller(MOBase::IPluginInstaller *installer);
+
/**
* @return the extensions of archives supported by this installation manager.
*/
@@ -167,7 +173,7 @@ public:
*
* The flatten argument is not present here while it is present in the deprecated QStringList
* version for multiple reasons: 1) it was never used, 2) it is kind of fishy because there
- * is no way to know if a file is going to be overriden, 3) it is quite easy to flatten a
+ * is no way to know if a file is going to be overriden, 3) it is quite easy to flatten a
* IFileTree and thus to given a list of entries flattened (this was not possible with the
* QStringList version since these were based on the name of the file inside the archive).
*/
@@ -185,7 +191,7 @@ public:
* @return the path to the created file.
*/
virtual QString createFile(std::shared_ptr<const MOBase::FileTreeEntry> entry) override;
-
+
/**
* @brief Installs the given archive.
*
@@ -279,6 +285,9 @@ private:
private:
+ // The plugin container, mostly to check if installer are enabled or not:
+ const PluginContainer *m_PluginContainer;
+
bool m_IsRunning;
QWidget *m_ParentWidget;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 94bc5800..93ca415d 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1132,7 +1132,7 @@ void MainWindow::checkForProblemsImpl()
size_t numProblems = 0;
for (QObject *pluginObj : m_PluginContainer.plugins<QObject>()) {
IPlugin *plugin = qobject_cast<IPlugin*>(pluginObj);
- if (plugin == nullptr || plugin->isActive()) {
+ if (plugin == nullptr || m_PluginContainer.isEnabled(plugin)) {
IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(pluginObj);
if (diagnose != nullptr)
numProblems += diagnose->activeProblems().size();
@@ -1663,9 +1663,11 @@ void MainWindow::registerPluginTools(std::vector<IPluginTool *> toolPlugins)
}
);
+ // TODO: I don't know when this method is called? Maybe the check should be perform when
+ // the context menu is opened?
// Remove inactive plugins
toolPlugins.erase(
- std::remove_if(toolPlugins.begin(), toolPlugins.end(), [](IPluginTool *plugin) -> bool { return !plugin->isActive(); }),
+ std::remove_if(toolPlugins.begin(), toolPlugins.end(), [this](IPluginTool *plugin) { return !m_PluginContainer.isEnabled(plugin); }),
toolPlugins.end()
);
@@ -5972,7 +5974,7 @@ void MainWindow::on_actionNotifications_triggered()
future.waitForFinished();
- ProblemsDialog problems(m_PluginContainer.plugins<QObject>(), this);
+ ProblemsDialog problems(m_PluginContainer, this);
problems.exec();
scheduleCheckForProblems();
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index f57903e2..86afe59a 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -287,6 +287,7 @@ void OrganizerCore::connectPlugins(PluginContainer *container)
m_InstallationManager.getSupportedExtensions());
m_PluginContainer = container;
m_Updater.setPluginContainer(m_PluginContainer);
+ m_InstallationManager.setPluginContainer(m_PluginContainer);
m_DownloadManager.setPluginContainer(m_PluginContainer);
m_ModList.setPluginContainer(m_PluginContainer);
@@ -2040,7 +2041,7 @@ std::vector<Mapping> OrganizerCore::fileMapping(const QString &profileName,
for (MOBase::IPluginFileMapper *mapper :
m_PluginContainer->plugins<MOBase::IPluginFileMapper>()) {
IPlugin *plugin = dynamic_cast<IPlugin *>(mapper);
- if (plugin->isActive()) {
+ if (m_PluginContainer->isEnabled(plugin)) {
MappingType pluginMap = mapper->mappings();
result.reserve(result.size() + pluginMap.size());
result.insert(result.end(), pluginMap.begin(), pluginMap.end());
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp
index a988ba9f..77b7c2d6 100644
--- a/src/organizerproxy.cpp
+++ b/src/organizerproxy.cpp
@@ -83,6 +83,16 @@ void OrganizerProxy::modDataChanged(IModInterface *mod)
m_Proxied->modDataChanged(mod);
}
+bool OrganizerProxy::isPluginEnabled(QString const& pluginName) const
+{
+ return m_PluginContainer->isEnabled(pluginName);
+}
+
+bool OrganizerProxy::isPluginEnabled(IPlugin* plugin) const
+{
+ return m_PluginContainer->isEnabled(plugin);
+}
+
QVariant OrganizerProxy::pluginSetting(const QString &pluginName, const QString &key) const
{
return m_Proxied->pluginSetting(pluginName, key);
diff --git a/src/organizerproxy.h b/src/organizerproxy.h
index 6690d612..4329bdda 100644
--- a/src/organizerproxy.h
+++ b/src/organizerproxy.h
@@ -35,8 +35,6 @@ public:
virtual MOBase::IPluginGame *getGame(const QString &gameName) const;
virtual MOBase::IModInterface *createMod(MOBase::GuessedValue<QString> &name);
virtual void modDataChanged(MOBase::IModInterface *mod);
- virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const;
- virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def = QVariant()) const;
virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync = true);
virtual QString pluginDataPath() const;
@@ -64,6 +62,12 @@ public:
virtual bool onProfileRenamed(std::function<void(MOBase::IProfile*, QString const&, QString const&)> const& func) override;
virtual bool onProfileRemoved(std::function<void(QString const&)> const& func) override;
virtual bool onProfileChanged(std::function<void(MOBase::IProfile*, MOBase::IProfile*)> const& func) override;
+
+ // Plugin related:
+ virtual bool isPluginEnabled(QString const& pluginName) const override;
+ virtual bool isPluginEnabled(MOBase::IPlugin* plugin) const override;
+ virtual QVariant pluginSetting(const QString& pluginName, const QString& key) const override;
+ virtual void setPluginSetting(const QString& pluginName, const QString& key, const QVariant& value) override;
virtual bool onPluginSettingChanged(std::function<void(QString const&, const QString& key, const QVariant&, const QVariant&)> const& func) override;
virtual MOBase::IPluginGame const *managedGame() const;
diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp
index 5992f28d..aa38803f 100644
--- a/src/plugincontainer.cpp
+++ b/src/plugincontainer.cpp
@@ -51,9 +51,26 @@ QStringList PluginContainer::pluginInterfaces()
}
+// PluginRequirementProxy
+
+std::vector<unsigned int> PluginRequirementProxy::problems() const
+{
+ return m_Requirement->problems(m_Proxy);
+}
+QString PluginRequirementProxy::description(unsigned int id) const
+{
+ return m_Requirement->description(id);
+}
+PluginRequirementProxy::PluginRequirementProxy(const MOBase::PluginRequirement* requirement, OrganizerProxy* proxy) :
+ m_Requirement(requirement), m_Proxy(proxy) { }
+
+
+// PluginContainer
+
PluginContainer::PluginContainer(OrganizerCore *organizer)
: m_Organizer(organizer)
, m_UserInterface(nullptr)
+ , m_PreviewGenerator(this)
{
}
@@ -184,6 +201,7 @@ bool PluginContainer::initPlugin(IPlugin *plugin)
if (m_Organizer) {
auto* proxy = new OrganizerProxy(m_Organizer, this, plugin);
+ m_Proxies[plugin] = proxy;
if (!plugin->init(proxy)) {
log::warn("plugin failed to initialize");
@@ -191,6 +209,10 @@ bool PluginContainer::initPlugin(IPlugin *plugin)
}
}
+ for (auto* requirement : plugin->requirements()) {
+ m_Requirements[plugin].emplace_back(requirement);
+ }
+
return true;
}
@@ -202,9 +224,10 @@ bool PluginContainer::initProxyPlugin(IPlugin *plugin)
return false;
}
- IOrganizer* proxy = nullptr;
+ OrganizerProxy* proxy = nullptr;
if (m_Organizer) {
proxy = new OrganizerProxy(m_Organizer, this, plugin);
+ m_Proxies[plugin] = proxy;
}
if (!plugin->init(proxy)) {
@@ -212,6 +235,10 @@ bool PluginContainer::initProxyPlugin(IPlugin *plugin)
return false;
}
+ for (auto* requirement : plugin->requirements()) {
+ m_Requirements[plugin].emplace_back(requirement);
+ }
+
return true;
}
@@ -227,24 +254,25 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName)
// way to cast directly between IPlugin* and IPluginDiagnose*
bf::at_key<QObject>(m_Plugins).push_back(plugin);
- { // generic treatment for all plugins
- IPlugin *pluginObj = qobject_cast<IPlugin*>(plugin);
- if (pluginObj == nullptr) {
- log::debug("not an IPlugin");
- return false;
- }
+ // generic treatment for all plugins
+ IPlugin *pluginObj = qobject_cast<IPlugin*>(plugin);
+ if (pluginObj == nullptr) {
+ log::debug("not an IPlugin");
+ return false;
+ }
+ bf::at_key<QString>(m_AccessPlugins)[pluginObj->name()] = pluginObj;
- plugin->setProperty("filename", fileName);
+ plugin->setProperty("filename", fileName);
- if (m_Organizer) {
- m_Organizer->settings().plugins().registerPlugin(pluginObj);
- }
+ if (m_Organizer) {
+ m_Organizer->settings().plugins().registerPlugin(pluginObj);
}
{ // diagnosis plugin
IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(plugin);
if (diagnose != nullptr) {
bf::at_key<IPluginDiagnose>(m_Plugins).push_back(diagnose);
+ bf::at_key<IPluginDiagnose>(m_AccessPlugins)[diagnose] = pluginObj;
m_DiagnosisConnections.push_back(
diagnose->onInvalidated([&] () { emit diagnosisUpdate(); })
);
@@ -254,6 +282,7 @@ bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName)
IPluginFileMapper *mapper = qobject_cast<IPluginFileMapper*>(plugin);
if (mapper != nullptr) {
bf::at_key<IPluginFileMapper>(m_Plugins).push_back(mapper);
+ bf::at_key<IPluginFileMapper>(m_AccessPlugins)[mapper] = pluginObj;
}
}
{ // mod page plugin
@@ -383,6 +412,73 @@ void PluginContainer::unloadPlugins()
}
}
+bool PluginContainer::isEnabled(IPlugin* plugin) const
+{
+ // Check if it's a game plugin:
+ if (implementInterface<IPluginGame>(plugin)) {
+ return plugin == m_Organizer->managedGame();
+ }
+
+ // Check if the plugin is enabled:
+ if (!m_Organizer->pluginSetting(plugin->name(), "enabled").toBool()) {
+ return false;
+ }
+
+ // Check the requirements:
+ auto* proxy = m_Proxies.at(plugin);
+ for (auto& requirement : m_Requirements.at(plugin)) {
+ if (!requirement->problems(proxy).empty()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+MOBase::IPlugin* PluginContainer::plugin(QString const& pluginName) const
+{
+ auto& map = bf::at_key<QString>(m_AccessPlugins);
+ auto it = map.find(pluginName);
+ if (it == std::end(map)) {
+ return nullptr;
+ }
+ return it->second;
+}
+
+MOBase::IPlugin* PluginContainer::plugin(MOBase::IPluginDiagnose* diagnose) const
+{
+ auto& map = bf::at_key<IPluginDiagnose>(m_AccessPlugins);
+ auto it = map.find(diagnose);
+ if (it == std::end(map)) {
+ return nullptr;
+ }
+ return it->second;
+}
+
+MOBase::IPlugin* PluginContainer::plugin(MOBase::IPluginFileMapper* mapper) const
+{
+ auto& map = bf::at_key<IPluginFileMapper>(m_AccessPlugins);
+ auto it = map.find(mapper);
+ if (it == std::end(map)) {
+ return nullptr;
+ }
+ return it->second;
+}
+
+bool PluginContainer::isEnabled(QString const& pluginName) const { return isEnabled(plugin(pluginName)); }
+bool PluginContainer::isEnabled(MOBase::IPluginDiagnose* diagnose) const { return isEnabled(plugin(diagnose)); }
+bool PluginContainer::isEnabled(MOBase::IPluginFileMapper* mapper) const { return isEnabled(plugin(mapper)); }
+
+std::vector<PluginRequirementProxy> PluginContainer::requirements(IPlugin* plugin) const
+{
+ auto* proxy = m_Proxies.at(plugin);
+ std::vector<PluginRequirementProxy> proxies;
+ for (auto& requirement : m_Requirements.at(plugin)) {
+ proxies.push_back(PluginRequirementProxy(requirement.get(), proxy));
+ }
+ return proxies;
+}
+
IPluginGame *PluginContainer::managedGame(const QString &name) const
{
auto iter = m_SupportedGames.find(name);
diff --git a/src/plugincontainer.h b/src/plugincontainer.h
index 2b39726b..1a3173fb 100644
--- a/src/plugincontainer.h
+++ b/src/plugincontainer.h
@@ -22,6 +22,30 @@ class IUserInterface;
#include <boost/mp11.hpp>
#endif // Q_MOC_RUN
#include <vector>
+#include <memory>
+
+
+class OrganizerProxy;
+
+
+// Small class that allows calling check() for plugin requirements
+// without passing the IOrganizer.
+class PluginRequirementProxy {
+public:
+
+ std::vector<unsigned int> problems() const;
+ QString description(unsigned int id) const;
+
+private:
+
+ const MOBase::PluginRequirement* m_Requirement;
+ OrganizerProxy* m_Proxy;
+
+ PluginRequirementProxy(const MOBase::PluginRequirement* requirement, OrganizerProxy* proxy);
+
+ friend class PluginContainer;
+
+};
class PluginContainer : public QObject, public MOBase::IPluginDiagnose
@@ -32,18 +56,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;
@@ -113,6 +143,71 @@ 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;
+ }
+
+ // Find all the names:
+ bool implement = false;
+ boost::mp11::mp_for_each<PluginTypeOrder>([oPlugin, &implement](const auto* p) {
+ using plugin_type = std::decay_t<decltype(*p)>;
+ if (qobject_cast<plugin_type*>(oPlugin)) {
+ implement = true;
+ }
+ });
+
+ return implement;
+ }
+
+ /**
+ * @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.
+ */
+ MOBase::IPlugin* plugin(QString const& pluginName) const;
+ MOBase::IPlugin* plugin(MOBase::IPluginDiagnose* diagnose) const;
+ MOBase::IPlugin* plugin(MOBase::IPluginFileMapper* mapper) 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 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.
+ */
+ std::vector<PluginRequirementProxy> requirements(MOBase::IPlugin* plugin) const;
+
+ /**
* @brief Retrieved the (localized) names of interfaces implemented by the given
* plugin.
*
@@ -179,6 +274,12 @@ private:
PluginMap m_Plugins;
+ // This maps allow access to IPlugin* from name or diagnose/mapper object.
+ AccessPluginMap m_AccessPlugins;
+
+ std::map<MOBase::IPlugin*, OrganizerProxy*> m_Proxies;
+ std::map<MOBase::IPlugin*, std::vector<std::unique_ptr<const MOBase::PluginRequirement>>> m_Requirements;
+
std::map<QString, MOBase::IPluginGame*> m_SupportedGames;
std::vector<boost::signals2::connection> m_DiagnosisConnections;
QStringList m_FailedPlugins;
diff --git a/src/previewgenerator.cpp b/src/previewgenerator.cpp
index b406b7bc..c7df5a25 100644
--- a/src/previewgenerator.cpp
+++ b/src/previewgenerator.cpp
@@ -18,14 +18,17 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "previewgenerator.h"
+
#include <QFileInfo>
#include <QLabel>
#include <QImageReader>
#include <QTextEdit>
#include <utility.h>
-PreviewGenerator::PreviewGenerator()
-{
+#include "plugincontainer.h"
+
+PreviewGenerator::PreviewGenerator(const PluginContainer* pluginContainer) :
+ m_PluginContainer(pluginContainer) {
m_MaxSize = QGuiApplication::primaryScreen()->size() * 0.8;
}
@@ -42,13 +45,13 @@ bool PreviewGenerator::previewSupported(const QString &fileExtension) const
if (it == m_PreviewPlugins.end()) {
return false;
}
- return it->second->isActive();
+ return m_PluginContainer->isEnabled(it->second);
}
QWidget *PreviewGenerator::genPreview(const QString &fileName) const
{
auto iter = m_PreviewPlugins.find(QFileInfo(fileName).suffix().toLower());
- if (iter != m_PreviewPlugins.end() && iter->second->isActive()) {
+ if (iter != m_PreviewPlugins.end() && m_PluginContainer->isEnabled(iter->second)) {
return iter->second->genFilePreview(fileName, m_MaxSize);
} else {
return nullptr;
diff --git a/src/previewgenerator.h b/src/previewgenerator.h
index e872b06b..0d8f0781 100644
--- a/src/previewgenerator.h
+++ b/src/previewgenerator.h
@@ -26,10 +26,12 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <functional>
#include <ipluginpreview.h>
+class PluginContainer;
+
class PreviewGenerator
{
public:
- PreviewGenerator();
+ PreviewGenerator(const PluginContainer* pluginContainer);
void registerPlugin(MOBase::IPluginPreview *plugin);
@@ -44,8 +46,8 @@ private:
private:
+ const PluginContainer* m_PluginContainer;
std::map<QString, MOBase::IPluginPreview*> m_PreviewPlugins;
-
QSize m_MaxSize;
};
diff --git a/src/problemsdialog.cpp b/src/problemsdialog.cpp
index 4b944ed2..d72f8c20 100644
--- a/src/problemsdialog.cpp
+++ b/src/problemsdialog.cpp
@@ -7,12 +7,13 @@
#include <QPushButton>
#include <Shellapi.h>
+#include "plugincontainer.h"
using namespace MOBase;
-ProblemsDialog::ProblemsDialog(std::vector<QObject *> pluginObjects, QWidget *parent) :
- QDialog(parent), ui(new Ui::ProblemsDialog), m_PluginObjects(pluginObjects),
+ProblemsDialog::ProblemsDialog(const PluginContainer& pluginContainer, QWidget *parent) :
+ QDialog(parent), ui(new Ui::ProblemsDialog), m_PluginContainer(pluginContainer),
m_hasProblems(false)
{
ui->setupUi(this);
@@ -40,14 +41,10 @@ void ProblemsDialog::runDiagnosis()
m_hasProblems = false;
ui->problemsWidget->clear();
- for(QObject *pluginObj : m_PluginObjects) {
- IPlugin *plugin = qobject_cast<IPlugin*>(pluginObj);
- if (plugin != nullptr && !plugin->isActive())
- continue;
-
- IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(pluginObj);
- if (diagnose == nullptr)
+ for (IPluginDiagnose *diagnose : m_PluginContainer.plugins<IPluginDiagnose>()) {
+ if (!m_PluginContainer.isEnabled(diagnose)) {
continue;
+ }
std::vector<unsigned int> activeProblems = diagnose->activeProblems();
foreach (unsigned int key, activeProblems) {
diff --git a/src/problemsdialog.h b/src/problemsdialog.h
index a30c8d48..504a0a10 100644
--- a/src/problemsdialog.h
+++ b/src/problemsdialog.h
@@ -11,13 +11,14 @@ namespace Ui {
class ProblemsDialog;
}
+class PluginContainer;
class ProblemsDialog : public QDialog
{
Q_OBJECT
public:
- explicit ProblemsDialog(std::vector<QObject*> pluginObjects, QWidget *parent = 0);
+ explicit ProblemsDialog(PluginContainer const& pluginContainer, QWidget *parent = 0);
~ProblemsDialog();
// also saves and restores geometry
@@ -37,7 +38,7 @@ private slots:
private:
Ui::ProblemsDialog *ui;
- std::vector<QObject *> m_PluginObjects;
+ const PluginContainer& m_PluginContainer;
bool m_hasProblems;
};
diff --git a/src/proxyutils.h b/src/proxyutils.h
index 4c1717d8..4f26c070 100644
--- a/src/proxyutils.h
+++ b/src/proxyutils.h
@@ -10,7 +10,7 @@ namespace MOShared {
template <class Fn, class T = int>
auto callIfPluginActive(OrganizerProxy* proxy, Fn&& callback, T defaultReturn = T{}) {
return [fn = std::forward<Fn>(callback), proxy, defaultReturn](auto&& ...args) {
- if (proxy->plugin()->isActive()) {
+ if (proxy->isPluginEnabled(proxy->plugin())) {
return fn(std::forward<decltype(args)>(args)...);
}
else {