From 14c6ee4d27b443d271b59d894ac6c06028aa45ff Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 28 Apr 2022 13:24:27 +0200 Subject: Ties plugin to the PluginContainer. --- src/plugincontainer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/plugincontainer.cpp') diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp index c4640cc3..61169196 100644 --- a/src/plugincontainer.cpp +++ b/src/plugincontainer.cpp @@ -467,8 +467,8 @@ IPlugin* PluginContainer::registerPlugin(QObject *plugin, const QString& filepat } } else { - log::warn("Trying to register two plugins with the name '{}', the second one will not be registered.", - pluginObj->name()); + log::warn("Trying to register two plugins with the name '{}' (from {} and {}), the second one will not be registered.", + pluginObj->name(), this->filepath(other), QDir::cleanPath(filepath)); return nullptr; } } @@ -481,6 +481,7 @@ IPlugin* PluginContainer::registerPlugin(QObject *plugin, const QString& filepat bf::at_key(m_Plugins).push_back(plugin); plugin->setProperty("filepath", QDir::cleanPath(filepath)); + plugin->setParent(this); if (m_Organizer) { m_Organizer->settings().plugins().registerPlugin(pluginObj); @@ -921,6 +922,8 @@ void PluginContainer::unloadPlugin(MOBase::IPlugin* plugin, QObject* object) } + object->deleteLater(); + // Do this at the end. m_Requirements.erase(plugin); } -- cgit v1.3.1 From abe926dc1519e7a29769a1a050e80cc5512146a3 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Thu, 28 Apr 2022 19:36:39 +0200 Subject: Allow Qt plugins in subfolder. --- src/organizer_en.ts | 20 ++++++++++---------- src/plugincontainer.cpp | 38 +++++++++++++++++++++++++++++++++++++- src/plugincontainer.h | 10 ++++++++++ 3 files changed, 57 insertions(+), 11 deletions(-) (limited to 'src/plugincontainer.cpp') diff --git a/src/organizer_en.ts b/src/organizer_en.ts index d5b32741..0d7854ff 100644 --- a/src/organizer_en.ts +++ b/src/organizer_en.ts @@ -5909,48 +5909,48 @@ Continue? PluginContainer - + Plugin error - + Mod Organizer failed to load the plugin '%1' last time it was started. - + The plugin can be skipped for this session, blacklisted, or loaded normally, in which case it might fail again. Blacklisted plugins can be re-enabled later in the settings. - + Skip this plugin - + Blacklist this plugin - + Load this plugin - + Some plugins could not be loaded - - + + Description missing - + The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version: diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp index 61169196..f71d89e4 100644 --- a/src/plugincontainer.cpp +++ b/src/plugincontainer.cpp @@ -823,6 +823,33 @@ QObject* PluginContainer::loadQtPlugin(const QString& filepath) return nullptr; } +std::optional PluginContainer::isQtPluginFolder(const QString& filepath) const { + + if (!QFileInfo(filepath).isDir()) { + return {}; + } + + QDirIterator iter(filepath, QDir::Files | QDir::NoDotAndDotDot); + while (iter.hasNext()) { + iter.next(); + const auto filePath = iter.filePath(); + + // not a library, skip + if (!QLibrary::isLibrary(filePath)) { + continue; + } + + // check if we have proper metadata - this does not load the plugin (metaData() should + // be very lightweight) + const QPluginLoader loader(filePath); + if (!loader.metaData().isEmpty()) { + return filePath; + } + } + + return {}; +} + void PluginContainer::loadPlugin(QString const& filepath) { std::vector plugins; @@ -832,6 +859,12 @@ void PluginContainer::loadPlugin(QString const& filepath) plugins.push_back(plugin); } } + else if (auto p = isQtPluginFolder(filepath)) { + QObject* plugin = loadQtPlugin(*p); + if (plugin) { + plugins.push_back(plugin); + } + } else { // We need to check if this can be handled by a proxy. for (auto* proxy : this->plugins()) { @@ -1049,7 +1082,7 @@ void PluginContainer::loadPlugins() QString pluginPath = qApp->applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()); log::debug("looking for plugins in {}", QDir::toNativeSeparators(pluginPath)); - QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot); + QDirIterator iter(pluginPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); while (iter.hasNext()) { iter.next(); @@ -1076,6 +1109,9 @@ void PluginContainer::loadPlugins() if (QLibrary::isLibrary(filepath)) { loadQtPlugin(filepath); } + else if (auto p = isQtPluginFolder(filepath)) { + loadQtPlugin(*p); + } } if (skipPlugin.isEmpty()) { diff --git a/src/plugincontainer.h b/src/plugincontainer.h index b250573a..2ab9a4b7 100644 --- a/src/plugincontainer.h +++ b/src/plugincontainer.h @@ -396,6 +396,16 @@ private: // 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 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. -- cgit v1.3.1