From cb453a9ba70106832eec2cb0feecbd91d2e8b7d7 Mon Sep 17 00:00:00 2001 From: Mikaƫl Capelle Date: Wed, 2 Dec 2020 21:08:22 +0100 Subject: Fix callbacks for IOrganizer when plugin are unloaded/loaded. --- src/organizercore.cpp | 42 ++++++++++++++++++------------------- src/organizercore.h | 24 +++++++++++---------- src/organizerproxy.cpp | 57 ++++++++++++++++++++++++++++++++++---------------- src/organizerproxy.h | 23 +++++++++++++++++++- src/proxyutils.h | 15 +++++++++++++ 5 files changed, 109 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/organizercore.cpp b/src/organizercore.cpp index f14d3234..7016f9a1 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1184,58 +1184,56 @@ bool OrganizerCore::previewFile( return true; } -bool OrganizerCore::onAboutToRun( +boost::signals2::connection OrganizerCore::onAboutToRun( const std::function &func) { - auto conn = m_AboutToRun.connect(func); - return conn.connected(); + return m_AboutToRun.connect(func); } -bool OrganizerCore::onFinishedRun( +boost::signals2::connection OrganizerCore::onFinishedRun( const std::function &func) { - auto conn = m_FinishedRun.connect(func); - return conn.connected(); + return m_FinishedRun.connect(func); } -bool OrganizerCore::onUserInterfaceInitialized(std::function const& func) +boost::signals2::connection OrganizerCore::onUserInterfaceInitialized(std::function const& func) { - return m_UserInterfaceInitialized.connect(func).connected(); + return m_UserInterfaceInitialized.connect(func); } -bool OrganizerCore::onProfileCreated(std::function const& func) +boost::signals2::connection OrganizerCore::onProfileCreated(std::function const& func) { - return m_ProfileCreated.connect(func).connected(); + return m_ProfileCreated.connect(func); } -bool OrganizerCore::onProfileRenamed(std::function const& func) +boost::signals2::connection OrganizerCore::onProfileRenamed(std::function const& func) { - return m_ProfileRenamed.connect(func).connected(); + return m_ProfileRenamed.connect(func); } -bool OrganizerCore::onProfileRemoved(std::function const& func) +boost::signals2::connection OrganizerCore::onProfileRemoved(std::function const& func) { - return m_ProfileRemoved.connect(func).connected(); + return m_ProfileRemoved.connect(func); } -bool OrganizerCore::onProfileChanged(std::function const& func) +boost::signals2::connection OrganizerCore::onProfileChanged(std::function const& func) { - return m_ProfileChanged.connect(func).connected(); + return m_ProfileChanged.connect(func); } -bool OrganizerCore::onPluginSettingChanged(std::function const& func) +boost::signals2::connection OrganizerCore::onPluginSettingChanged(std::function const& func) { - return m_PluginSettingChanged.connect(func).connected(); + return m_PluginSettingChanged.connect(func); } -bool OrganizerCore::onPluginEnabled(std::function const& func) +boost::signals2::connection OrganizerCore::onPluginEnabled(std::function const& func) { - return m_PluginEnabled.connect(func).connected(); + return m_PluginEnabled.connect(func); } -bool OrganizerCore::onPluginDisabled(std::function const& func) +boost::signals2::connection OrganizerCore::onPluginDisabled(std::function const& func) { - return m_PluginDisabled.connect(func).connected(); + return m_PluginDisabled.connect(func); } void OrganizerCore::refresh(bool saveChanges) diff --git a/src/organizercore.h b/src/organizercore.h index 23b624e8..1b77b7f5 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -61,6 +61,8 @@ class OrganizerCore : public QObject, public MOBase::IPluginDiagnose private: + friend class OrganizerProxy; + struct SignalCombinerAnd { typedef bool result_type; @@ -87,7 +89,7 @@ private: using SignalProfileRemoved = boost::signals2::signal; using SignalProfileChanged = boost::signals2::signal; using SignalPluginSettingChanged = boost::signals2::signal; - using SignalPluginEnabled = boost::signals2::signal; + using SignalPluginEnabled = boost::signals2::signal; public: @@ -328,16 +330,16 @@ public: ModList *modList(); void refresh(bool saveChanges = true); - bool onAboutToRun(const std::function& func); - bool onFinishedRun(const std::function& func); - bool onUserInterfaceInitialized(std::function const& func); - bool onProfileCreated(std::function const& func); - bool onProfileRenamed(std::function const& func); - bool onProfileRemoved(std::function const& func); - bool onProfileChanged(std::function const& func); - bool onPluginSettingChanged(std::function const& func); - bool onPluginEnabled(std::function const& func); - bool onPluginDisabled(std::function const& func); + boost::signals2::connection onAboutToRun(const std::function& func); + boost::signals2::connection onFinishedRun(const std::function& func); + boost::signals2::connection onUserInterfaceInitialized(std::function const& func); + boost::signals2::connection onProfileCreated(std::function const& func); + boost::signals2::connection onProfileRenamed(std::function const& func); + boost::signals2::connection onProfileRemoved(std::function const& func); + boost::signals2::connection onProfileChanged(std::function const& func); + boost::signals2::connection onPluginSettingChanged(std::function const& func); + boost::signals2::connection onPluginEnabled(std::function const& func); + boost::signals2::connection onPluginDisabled(std::function const& func); bool getArchiveParsing() const { diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp index 92f250ea..13b91ff4 100644 --- a/src/organizerproxy.cpp +++ b/src/organizerproxy.cpp @@ -22,10 +22,31 @@ OrganizerProxy::OrganizerProxy(OrganizerCore* organizer, PluginContainer* plugin : m_Proxied(organizer) , m_PluginContainer(pluginContainer) , m_Plugin(plugin) + , m_PluginName(plugin->name()) , m_DownloadManagerProxy(std::make_unique(this, organizer->downloadManager())) , m_ModListProxy(std::make_unique(this, organizer->modList())) , m_PluginListProxy(std::make_unique(this, organizer->pluginList())) { + m_Connections.push_back(m_Proxied->onAboutToRun(callSignalIfPluginActive(this, m_AboutToRun, true))); + m_Connections.push_back(m_Proxied->onFinishedRun(callSignalIfPluginActive(this, m_FinishedRun))); + m_Connections.push_back(m_Proxied->onProfileCreated(callSignalIfPluginActive(this, m_ProfileCreated))); + m_Connections.push_back(m_Proxied->onProfileRenamed(callSignalIfPluginActive(this, m_ProfileRenamed))); + m_Connections.push_back(m_Proxied->onProfileRemoved(callSignalIfPluginActive(this, m_ProfileRemoved))); + m_Connections.push_back(m_Proxied->onProfileChanged(callSignalIfPluginActive(this, m_ProfileChanged))); + + m_Connections.push_back(m_Proxied->onUserInterfaceInitialized(callSignalAlways(m_UserInterfaceInitialized))); + m_Connections.push_back(m_Proxied->onPluginSettingChanged(callSignalAlways(m_PluginSettingChanged))); + m_Connections.push_back(m_Proxied->onPluginEnabled(callSignalAlways(m_PluginEnabled))); + m_Connections.push_back(m_Proxied->onPluginDisabled(callSignalAlways(m_PluginDisabled))); + +} + +OrganizerProxy::~OrganizerProxy() +{ + log::debug("~OrganizerProxy() for {}.", m_PluginName); + for (auto& conn : m_Connections) { + conn.disconnect(); + } } IModRepositoryBridge *OrganizerProxy::createNexusBridge() const @@ -265,68 +286,68 @@ MOBase::IPluginGame const *OrganizerProxy::managedGame() const bool OrganizerProxy::onAboutToRun(const std::function& func) { - return m_Proxied->onAboutToRun(MOShared::callIfPluginActive(this, func, true)); + return m_Proxied->onAboutToRun(MOShared::callIfPluginActive(this, func, true)).connected(); } bool OrganizerProxy::onFinishedRun(const std::function& func) { - return m_Proxied->onFinishedRun(MOShared::callIfPluginActive(this, func)); -} - -bool OrganizerProxy::onUserInterfaceInitialized(std::function const& func) -{ - // Always call this one to allow plugin to initialize themselves even when not active: - return m_Proxied->onUserInterfaceInitialized(func); + return m_Proxied->onFinishedRun(MOShared::callIfPluginActive(this, func)).connected(); } bool OrganizerProxy::onProfileCreated(std::function const& func) { - return m_Proxied->onProfileCreated(MOShared::callIfPluginActive(this, func)); + return m_ProfileCreated.connect(func).connected(); } bool OrganizerProxy::onProfileRenamed(std::function const& func) { - return m_Proxied->onProfileRenamed(MOShared::callIfPluginActive(this, func)); + return m_ProfileRenamed.connect(func).connected(); } bool OrganizerProxy::onProfileRemoved(std::function const& func) { - return m_Proxied->onProfileRemoved(MOShared::callIfPluginActive(this, func)); + return m_ProfileRemoved.connect(func).connected(); } bool OrganizerProxy::onProfileChanged(std::function const& func) { - return m_Proxied->onProfileChanged(MOShared::callIfPluginActive(this, func)); + return m_ProfileChanged.connect(func).connected(); +} + +bool OrganizerProxy::onUserInterfaceInitialized(std::function const& func) +{ + // Always call this one to allow plugin to initialize themselves even when not active: + return m_UserInterfaceInitialized.connect(func).connected(); } // Always call these one, otherwise plugin cannot detect they are being enabled / disabled: bool OrganizerProxy::onPluginSettingChanged(std::function const& func) { - return m_Proxied->onPluginSettingChanged(func); + return m_PluginSettingChanged.connect(func).connected(); } bool OrganizerProxy::onPluginEnabled(std::function const& func) { - return m_Proxied->onPluginEnabled(func); + return m_PluginEnabled.connect(func).connected(); } bool OrganizerProxy::onPluginEnabled(const QString& pluginName, std::function const& func) { - return m_Proxied->onPluginEnabled([=](const IPlugin* plugin) { + return onPluginEnabled([=](const IPlugin* plugin) { if (plugin->name().compare(pluginName, Qt::CaseInsensitive) == 0) { func(); } - }); + }); } bool OrganizerProxy::onPluginDisabled(std::function const& func) { - return m_Proxied->onPluginDisabled(func); + return m_PluginDisabled.connect(func).connected(); } bool OrganizerProxy::onPluginDisabled(const QString& pluginName, std::function const& func) { - return m_Proxied->onPluginDisabled([=](const IPlugin* plugin) { + return onPluginDisabled([=](const IPlugin* plugin) { if (plugin->name().compare(pluginName, Qt::CaseInsensitive) == 0) { func(); } diff --git a/src/organizerproxy.h b/src/organizerproxy.h index 3097adf0..fb463822 100644 --- a/src/organizerproxy.h +++ b/src/organizerproxy.h @@ -6,7 +6,8 @@ #include #include -class OrganizerCore; +#include "organizercore.h" + class PluginContainer; class DownloadManagerProxy; class ModListProxy; @@ -18,6 +19,7 @@ class OrganizerProxy : public MOBase::IOrganizer public: OrganizerProxy(OrganizerCore *organizer, PluginContainer *pluginContainer, MOBase::IPlugin *plugin); + ~OrganizerProxy(); /** * @return the plugin corresponding to this proxy. @@ -76,12 +78,31 @@ public: virtual MOBase::IPluginGame const *managedGame() const; +protected: + + // The container needs access to some callbacks to simulate startup. + friend class PluginContainer; + private: OrganizerCore *m_Proxied; PluginContainer *m_PluginContainer; MOBase::IPlugin *m_Plugin; + QString m_PluginName; + + OrganizerCore::SignalAboutToRunApplication m_AboutToRun; + OrganizerCore::SignalFinishedRunApplication m_FinishedRun; + OrganizerCore::SignalUserInterfaceInitialized m_UserInterfaceInitialized; + OrganizerCore::SignalProfileCreated m_ProfileCreated; + OrganizerCore::SignalProfileRenamed m_ProfileRenamed; + OrganizerCore::SignalProfileRemoved m_ProfileRemoved; + OrganizerCore::SignalProfileChanged m_ProfileChanged; + OrganizerCore::SignalPluginSettingChanged m_PluginSettingChanged; + OrganizerCore::SignalPluginEnabled m_PluginEnabled; + OrganizerCore::SignalPluginEnabled m_PluginDisabled; + + std::vector m_Connections; std::unique_ptr m_DownloadManagerProxy; std::unique_ptr m_ModListProxy; diff --git a/src/proxyutils.h b/src/proxyutils.h index 4f26c070..6c85ba14 100644 --- a/src/proxyutils.h +++ b/src/proxyutils.h @@ -21,6 +21,21 @@ namespace MOShared { }; } + // We need to connect to the organizer. + template + auto callSignalIfPluginActive(OrganizerProxy* proxy, const Signal& signal, T defaultReturn = T{}) { + return callIfPluginActive(proxy, [&signal](auto&&... args) { + return signal(std::forward(args)...); + }, defaultReturn); + } + + template + auto callSignalAlways(const Signal& signal) { + return [&signal](auto&&... args) { + return signal(std::forward(args)...); + }; + } + } #endif -- cgit v1.3.1