From 4240f10260cbffbff52bf2d549100f4690a642b5 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Wed, 2 Dec 2020 21:09:42 +0100 Subject: Fix callbacks for pluginlist, modlist and download manager. --- src/modlistproxy.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'src/modlistproxy.cpp') diff --git a/src/modlistproxy.cpp b/src/modlistproxy.cpp index 8fcbdbdf..991476da 100644 --- a/src/modlistproxy.cpp +++ b/src/modlistproxy.cpp @@ -1,11 +1,26 @@ #include "modlistproxy.h" #include "organizerproxy.h" #include "proxyutils.h" +#include "modlist.h" using namespace MOBase; +using namespace MOShared; -ModListProxy::ModListProxy(OrganizerProxy* oproxy, IModList* modlist) : - m_OrganizerProxy(oproxy), m_Proxied(modlist) { } +ModListProxy::ModListProxy(OrganizerProxy* oproxy, ModList* modlist) : + m_OrganizerProxy(oproxy), m_Proxied(modlist) +{ + m_Connections.push_back(m_Proxied->onModInstalled(callSignalIfPluginActive(m_OrganizerProxy, m_ModInstalled))); + m_Connections.push_back(m_Proxied->onModMoved(callSignalIfPluginActive(m_OrganizerProxy, m_ModMoved))); + m_Connections.push_back(m_Proxied->onModRemoved(callSignalIfPluginActive(m_OrganizerProxy, m_ModRemoved))); + m_Connections.push_back(m_Proxied->onModStateChanged(callSignalIfPluginActive(m_OrganizerProxy, m_ModStateChanged))); +} + +ModListProxy::~ModListProxy() +{ + for (auto& conn : m_Connections) { + conn.disconnect(); + } +} QString ModListProxy::displayName(const QString& internalName) const { @@ -59,20 +74,20 @@ bool ModListProxy::setPriority(const QString& name, int newPriority) bool ModListProxy::onModInstalled(const std::function& func) { - return m_Proxied->onModInstalled(MOShared::callIfPluginActive(m_OrganizerProxy, func)); + return m_ModInstalled.connect(func).connected(); } bool ModListProxy::onModRemoved(const std::function& func) { - return m_Proxied->onModRemoved(MOShared::callIfPluginActive(m_OrganizerProxy, func)); + return m_ModRemoved.connect(func).connected(); } bool ModListProxy::onModStateChanged(const std::function&)>& func) { - return m_Proxied->onModStateChanged(MOShared::callIfPluginActive(m_OrganizerProxy, func)); + return m_ModStateChanged.connect(func).connected(); } bool ModListProxy::onModMoved(const std::function& func) { - return m_Proxied->onModMoved(MOShared::callIfPluginActive(m_OrganizerProxy, func)); + return m_ModMoved.connect(func).connected(); } -- cgit v1.3.1 From a30d49f4fc845164ef6bba4d2a834efce1dc01d7 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Fri, 4 Dec 2020 08:50:31 +0100 Subject: Avoid duplicating code to simulate startup. --- src/downloadmanagerproxy.cpp | 12 ++- src/downloadmanagerproxy.h | 6 ++ src/iuserinterface.h | 2 - src/mainwindow.cpp | 15 +--- src/mainwindow.h | 8 -- src/modlistproxy.cpp | 12 ++- src/modlistproxy.h | 6 ++ src/organizerproxy.cpp | 24 ++++- src/organizerproxy.h | 17 ++++ src/plugincontainer.cpp | 207 ++++++++++++++++++++----------------------- src/plugincontainer.h | 37 ++++---- src/pluginlistproxy.cpp | 12 ++- src/pluginlistproxy.h | 6 ++ 13 files changed, 208 insertions(+), 156 deletions(-) (limited to 'src/modlistproxy.cpp') diff --git a/src/downloadmanagerproxy.cpp b/src/downloadmanagerproxy.cpp index 06dad21f..95099044 100644 --- a/src/downloadmanagerproxy.cpp +++ b/src/downloadmanagerproxy.cpp @@ -7,7 +7,14 @@ using namespace MOBase; using namespace MOShared; DownloadManagerProxy::DownloadManagerProxy(OrganizerProxy* oproxy, DownloadManager* downloadManager) : - m_OrganizerProxy(oproxy), m_Proxied(downloadManager) + m_OrganizerProxy(oproxy), m_Proxied(downloadManager) { } + +DownloadManagerProxy::~DownloadManagerProxy() +{ + disconnectSignals(); +} + +void DownloadManagerProxy::connectSignals() { m_Connections.push_back(m_Proxied->onDownloadComplete(callSignalIfPluginActive(m_OrganizerProxy, m_DownloadComplete))); m_Connections.push_back(m_Proxied->onDownloadFailed(callSignalIfPluginActive(m_OrganizerProxy, m_DownloadFailed))); @@ -15,11 +22,12 @@ DownloadManagerProxy::DownloadManagerProxy(OrganizerProxy* oproxy, DownloadManag m_Connections.push_back(m_Proxied->onDownloadPaused(callSignalIfPluginActive(m_OrganizerProxy, m_DownloadPaused))); } -DownloadManagerProxy::~DownloadManagerProxy() +void DownloadManagerProxy::disconnectSignals() { for (auto& conn : m_Connections) { conn.disconnect(); } + m_Connections.clear(); } int DownloadManagerProxy::startDownloadURLs(const QStringList& urls) diff --git a/src/downloadmanagerproxy.h b/src/downloadmanagerproxy.h index 23692179..729fde91 100644 --- a/src/downloadmanagerproxy.h +++ b/src/downloadmanagerproxy.h @@ -25,6 +25,12 @@ public: private: + friend class OrganizerProxy; + + // See OrganizerProxy::connectSignals(). + void connectSignals(); + void disconnectSignals(); + OrganizerProxy* m_OrganizerProxy; DownloadManager* m_Proxied; diff --git a/src/iuserinterface.h b/src/iuserinterface.h index a2a91e62..277d5cf5 100644 --- a/src/iuserinterface.h +++ b/src/iuserinterface.h @@ -17,8 +17,6 @@ public: virtual void installTranslator(const QString &name) = 0; - virtual void disconnectPlugins() = 0; - virtual bool closeWindow() = 0; virtual void setWindowEnabled(bool enabled) = 0; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8e08103f..a270fd10 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -512,8 +512,6 @@ MainWindow::MainWindow(Settings &settings m_Tutorial.expose("espList", m_OrganizerCore.pluginList()); m_OrganizerCore.setUserInterface(this); - m_PluginContainer.setUserInterface(this); - connect(this, &MainWindow::userInterfaceInitialized, &m_OrganizerCore, &OrganizerCore::userInterfaceInitialized); for (const QString &fileName : m_PluginContainer.pluginFileNames()) { installTranslator(QFileInfo(fileName).baseName()); } @@ -705,7 +703,6 @@ MainWindow::~MainWindow() try { cleanup(); - m_PluginContainer.setUserInterface(nullptr); m_OrganizerCore.setUserInterface(nullptr); if (m_IntegratedBrowser) { @@ -744,14 +741,6 @@ void MainWindow::onRequestsChanged(const APIStats& stats, const APIUserAccount& } -void MainWindow::disconnectPlugins() -{ - if (ui->actionTool->menu() != nullptr) { - ui->actionTool->menu()->clear(); - } -} - - void MainWindow::resizeLists(bool pluginListCustom) { // ensure the columns aren't so small you can't see them any more @@ -1413,8 +1402,8 @@ void MainWindow::showEvent(QShowEvent *event) m_WasVisible = true; updateProblemsButton(); - // Notify plugin that the UI is initialized: - emit userInterfaceInitialized(); + // Notify plugin that the MO2 is ready: + m_PluginContainer.startPlugins(this); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 17c27b29..7a1c683d 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -133,8 +133,6 @@ public: void installTranslator(const QString &name); - virtual void disconnectPlugins(); - void displayModInformation( ModInfo::Ptr modInfo, unsigned int modIndex, ModInfoTabIDs tabID) override; @@ -168,12 +166,6 @@ signals: */ void styleChanged(const QString &styleFile); - /** - * @brief emitted when the user interface has been completely initialized - */ - void userInterfaceInitialized(); - - void modListDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void checkForProblemsDone(); diff --git a/src/modlistproxy.cpp b/src/modlistproxy.cpp index 991476da..6165fc3f 100644 --- a/src/modlistproxy.cpp +++ b/src/modlistproxy.cpp @@ -7,7 +7,14 @@ using namespace MOBase; using namespace MOShared; ModListProxy::ModListProxy(OrganizerProxy* oproxy, ModList* modlist) : - m_OrganizerProxy(oproxy), m_Proxied(modlist) + m_OrganizerProxy(oproxy), m_Proxied(modlist) { } + +ModListProxy::~ModListProxy() +{ + disconnectSignals(); +} + +void ModListProxy::connectSignals() { m_Connections.push_back(m_Proxied->onModInstalled(callSignalIfPluginActive(m_OrganizerProxy, m_ModInstalled))); m_Connections.push_back(m_Proxied->onModMoved(callSignalIfPluginActive(m_OrganizerProxy, m_ModMoved))); @@ -15,11 +22,12 @@ ModListProxy::ModListProxy(OrganizerProxy* oproxy, ModList* modlist) : m_Connections.push_back(m_Proxied->onModStateChanged(callSignalIfPluginActive(m_OrganizerProxy, m_ModStateChanged))); } -ModListProxy::~ModListProxy() +void ModListProxy::disconnectSignals() { for (auto& conn : m_Connections) { conn.disconnect(); } + m_Connections.clear(); } QString ModListProxy::displayName(const QString& internalName) const diff --git a/src/modlistproxy.h b/src/modlistproxy.h index 12d74e4a..162b0b43 100644 --- a/src/modlistproxy.h +++ b/src/modlistproxy.h @@ -31,6 +31,12 @@ public: private: + friend class OrganizerProxy; + + // See OrganizerProxy::connectSignals(). + void connectSignals(); + void disconnectSignals(); + OrganizerProxy* m_OrganizerProxy; ModList* m_Proxied; diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp index 1f73ee13..c41045e1 100644 --- a/src/organizerproxy.cpp +++ b/src/organizerproxy.cpp @@ -25,7 +25,14 @@ OrganizerProxy::OrganizerProxy(OrganizerCore* organizer, PluginContainer* 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_PluginListProxy(std::make_unique(this, organizer->pluginList())) { } + +OrganizerProxy::~OrganizerProxy() +{ + disconnectSignals(); +} + +void OrganizerProxy::connectSignals() { m_Connections.push_back(m_Proxied->onAboutToRun(callSignalIfPluginActive(this, m_AboutToRun, true))); m_Connections.push_back(m_Proxied->onFinishedRun(callSignalIfPluginActive(this, m_FinishedRun))); @@ -39,14 +46,25 @@ OrganizerProxy::OrganizerProxy(OrganizerCore* organizer, PluginContainer* plugin m_Connections.push_back(m_Proxied->onPluginEnabled(callSignalAlways(m_PluginEnabled))); m_Connections.push_back(m_Proxied->onPluginDisabled(callSignalAlways(m_PluginDisabled))); + // Connect the child proxies. + m_DownloadManagerProxy->connectSignals(); + m_ModListProxy->connectSignals(); + m_PluginListProxy->connectSignals(); } -OrganizerProxy::~OrganizerProxy() +void OrganizerProxy::disconnectSignals() { - log::debug("Deleting organizer proxy for plugin '{}'.", m_PluginName); + log::debug("Disconnecting organizer proxy for plugin '{}'.", m_PluginName); + + // Disconnect the child proxies. + m_DownloadManagerProxy->disconnectSignals(); + m_ModListProxy->disconnectSignals(); + m_PluginListProxy->disconnectSignals(); + for (auto& conn : m_Connections) { conn.disconnect(); } + m_Connections.clear(); } IModRepositoryBridge *OrganizerProxy::createNexusBridge() const diff --git a/src/organizerproxy.h b/src/organizerproxy.h index fb463822..c52f2730 100644 --- a/src/organizerproxy.h +++ b/src/organizerproxy.h @@ -21,11 +21,15 @@ public: OrganizerProxy(OrganizerCore *organizer, PluginContainer *pluginContainer, MOBase::IPlugin *plugin); ~OrganizerProxy(); +public: + /** * @return the plugin corresponding to this proxy. */ MOBase::IPlugin* plugin() const { return m_Plugin; } +public: // IOrganizer interface + virtual MOBase::IModRepositoryBridge *createNexusBridge() const; virtual QString profileName() const; virtual QString profilePath() const; @@ -83,6 +87,19 @@ protected: // The container needs access to some callbacks to simulate startup. friend class PluginContainer; + /** + * @brief Connect the signals from this proxy and all the child proxies (plugin list, mod + * list, etc.) to the actual implementation. Before this call, plugins can register signals + * but they won't be triggered. + */ + void connectSignals(); + + /** + * @brief Disconnect the signals from this proxy and all the child proxies (plugin list, mod + * list, etc.) from the actual implementation. + */ + void disconnectSignals(); + private: OrganizerCore *m_Proxied; diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp index 9b73a964..3c8050cf 100644 --- a/src/plugincontainer.cpp +++ b/src/plugincontainer.cpp @@ -289,24 +289,10 @@ PluginContainer::~PluginContainer() { unloadPlugins(); } -void PluginContainer::setUserInterface(IUserInterface *userInterface) +void PluginContainer::startPlugins(IUserInterface *userInterface) { - if (userInterface) { - for (IPluginProxy* proxy : bf::at_key(m_Plugins)) { - proxy->setParentWidget(userInterface->mainWindow()); - } - for (IPluginModPage* modPage : bf::at_key(m_Plugins)) { - modPage->setParentWidget(userInterface->mainWindow()); - } - for (IPluginTool* tool : bf::at_key(m_Plugins)) { - tool->setParentWidget(userInterface->mainWindow()); - } - for (IPluginInstaller* installer : bf::at_key(m_Plugins)) { - installer->setParentWidget(userInterface->mainWindow()); - } - } - m_UserInterface = userInterface; + startPluginsImpl(plugins()); } QStringList PluginContainer::implementedInterfaces(IPlugin* plugin) const @@ -591,83 +577,6 @@ IPlugin* PluginContainer::registerPlugin(QObject *plugin, const QString& filepat return nullptr; } -MOBase::IPlugin* PluginContainer::loadQtPlugin(const QString& filepath) -{ - std::unique_ptr pluginLoader(new QPluginLoader(filepath, this)); - if (pluginLoader->instance() == nullptr) { - m_FailedPlugins.push_back(filepath); - log::error("failed to load plugin {}: {}",filepath, pluginLoader->errorString()); - } - else { - if (IPlugin* plugin = registerPlugin(pluginLoader->instance(), filepath, nullptr); plugin) { - log::debug("loaded plugin '{}' from '{}' - [{}]", - plugin->name(), QFileInfo(filepath).fileName(), implementedInterfaces(plugin).join(", ")); - m_PluginLoaders.push_back(pluginLoader.release()); - return plugin; - } - else { - m_FailedPlugins.push_back(filepath); - log::warn("plugin '{}' failed to load (may be outdated)", filepath); - } - } - return nullptr; -} - -std::vector PluginContainer::loadProxied(const QString& filepath, IPluginProxy* proxy) -{ - std::vector proxiedPlugins; - - try { - // We get a list of matching plugins as proxies can return multiple plugins - // per file and do not have a good way of supporting multiple inheritance. - QList matchingPlugins = proxy->load(filepath); - - // We are going to group plugin by names and "fix" them later: - std::map> proxiedByNames; - - for (QObject* proxiedPlugin : matchingPlugins) { - if (proxiedPlugin != nullptr) { - - if (IPlugin* proxied = registerPlugin(proxiedPlugin, filepath, proxy); proxied) { - log::debug("loaded plugin '{}' from '{}' - [{}]", - proxied->name(), QFileInfo(filepath).fileName(), implementedInterfaces(proxied).join(", ")); - - // Store the plugin for later: - proxiedPlugins.push_back(proxied); - proxiedByNames[proxied->name()].push_back(proxied); - } - else { - log::warn( - "plugin \"{}\" failed to load. If this plugin is for an older version of MO " - "you have to update it or delete it if no update exists.", - filepath); - } - } - } - - // Fake masters: - for (auto& [name, proxiedPlugins] : proxiedByNames) { - if (proxiedPlugins.size() > 1) { - auto it = std::min_element(std::begin(proxiedPlugins), std::end(proxiedPlugins), - [&](auto const& lhs, auto const& rhs) { - return isBetterInterface(as_qobject(lhs), as_qobject(rhs)); - }); - - for (auto& proxiedPlugin : proxiedPlugins) { - if (proxiedPlugin != *it) { - m_Requirements.at(proxiedPlugin).setMaster(*it); - } - } - } - } - } - catch (const std::exception& e) { - reportError(QObject::tr("failed to initialize plugin %1: %2").arg(filepath).arg(e.what())); - } - - return proxiedPlugins; -} - IPlugin* PluginContainer::managedGame() const { // TODO: This const_cast is safe but ugly. Most methods require a IPlugin*, so @@ -802,39 +711,119 @@ const PreviewGenerator &PluginContainer::previewGenerator() const return m_PreviewGenerator; } -void PluginContainer::simulateStartup(const std::vector& plugins) const +void PluginContainer::startPluginsImpl(const std::vector& plugins) const { // setUserInterface() if (m_UserInterface) { for (auto* plugin : plugins) { - if (auto* proxy = dynamic_cast(plugin)) { + if (auto* proxy = qobject_cast(plugin)) { proxy->setParentWidget(m_UserInterface->mainWindow()); } - if (auto* modPage = dynamic_cast(plugin)) { + if (auto* modPage = qobject_cast(plugin)) { modPage->setParentWidget(m_UserInterface->mainWindow()); } - if (auto* tool = dynamic_cast(plugin)) { + if (auto* tool = qobject_cast(plugin)) { tool->setParentWidget(m_UserInterface->mainWindow()); } - if (auto* installer = dynamic_cast(plugin)) { + if (auto* installer = qobject_cast(plugin)) { installer->setParentWidget(m_UserInterface->mainWindow()); } } } - // Simulate callbacks, e.g. onUserInterfaceInitialized and onProfileChanged. - for (auto* plugin : plugins) { + // Trigger initial callbacks, e.g. onUserInterfaceInitialized and onProfileChanged. + for (auto* object : plugins) { + auto* plugin = qobject_cast(object); auto* oproxy = organizerProxy(plugin); + oproxy->connectSignals(); oproxy->m_UserInterfaceInitialized(m_UserInterface->mainWindow()); oproxy->m_ProfileChanged(nullptr, m_Organizer->currentProfile()); } } +std::vector PluginContainer::loadProxied(const QString& filepath, IPluginProxy* proxy) +{ + std::vector proxiedPlugins; + + try { + // We get a list of matching plugins as proxies can return multiple plugins + // per file and do not have a good way of supporting multiple inheritance. + QList matchingPlugins = proxy->load(filepath); + + // We are going to group plugin by names and "fix" them later: + std::map> proxiedByNames; + + for (QObject* proxiedPlugin : matchingPlugins) { + if (proxiedPlugin != nullptr) { + + if (IPlugin* proxied = registerPlugin(proxiedPlugin, filepath, proxy); proxied) { + log::debug("loaded plugin '{}' from '{}' - [{}]", + proxied->name(), QFileInfo(filepath).fileName(), implementedInterfaces(proxied).join(", ")); + + // Store the plugin for later: + proxiedPlugins.push_back(proxiedPlugin); + proxiedByNames[proxied->name()].push_back(proxied); + } + else { + log::warn( + "plugin \"{}\" failed to load. If this plugin is for an older version of MO " + "you have to update it or delete it if no update exists.", + filepath); + } + } + } + + // Fake masters: + for (auto& [name, proxiedPlugins] : proxiedByNames) { + if (proxiedPlugins.size() > 1) { + auto it = std::min_element(std::begin(proxiedPlugins), std::end(proxiedPlugins), + [&](auto const& lhs, auto const& rhs) { + return isBetterInterface(as_qobject(lhs), as_qobject(rhs)); + }); + + for (auto& proxiedPlugin : proxiedPlugins) { + if (proxiedPlugin != *it) { + m_Requirements.at(proxiedPlugin).setMaster(*it); + } + } + } + } + } + catch (const std::exception& e) { + reportError(QObject::tr("failed to initialize plugin %1: %2").arg(filepath).arg(e.what())); + } + + return proxiedPlugins; +} + +QObject* PluginContainer::loadQtPlugin(const QString& filepath) +{ + std::unique_ptr pluginLoader(new QPluginLoader(filepath, this)); + if (pluginLoader->instance() == nullptr) { + m_FailedPlugins.push_back(filepath); + log::error("failed to load plugin {}: {}", filepath, pluginLoader->errorString()); + } + else { + QObject* object = pluginLoader->instance(); + if (IPlugin* plugin = registerPlugin(object, filepath, nullptr); plugin) { + log::debug("loaded plugin '{}' from '{}' - [{}]", + plugin->name(), QFileInfo(filepath).fileName(), implementedInterfaces(plugin).join(", ")); + m_PluginLoaders.push_back(pluginLoader.release()); + return object; + } + else { + m_FailedPlugins.push_back(filepath); + log::warn("plugin '{}' failed to load (may be outdated)", filepath); + } + } + return nullptr; +} + void PluginContainer::loadPlugin(QString const& filepath) { - std::vector plugins; + std::vector plugins; if (QFileInfo(filepath).isFile() && QLibrary::isLibrary(filepath)) { - IPlugin* plugin = loadQtPlugin(filepath); + QObject* plugin = loadQtPlugin(filepath); if (plugin) { plugins.push_back(plugin); } @@ -852,10 +841,10 @@ void PluginContainer::loadPlugin(QString const& filepath) } for (auto* plugin : plugins) { - emit pluginRegistered(plugin); + emit pluginRegistered(qobject_cast(plugin)); } - simulateStartup(plugins); + startPluginsImpl(plugins); } void PluginContainer::unloadPlugin(MOBase::IPlugin* plugin, QObject* object) @@ -895,6 +884,11 @@ void PluginContainer::unloadPlugin(MOBase::IPlugin* plugin, QObject* object) m_Organizer->settings().plugins().unregisterPlugin(plugin); + // Force disconnection of the signals from the proxies. This is a safety + // operations since those signals should be disconnected when the proxies + // are destroyed anyway. + organizerProxy(plugin)->disconnectSignals(); + // Is this a proxied plugin? auto* proxy = pluginProxy(plugin); @@ -949,10 +943,6 @@ void PluginContainer::reloadPlugin(QString const& filepath) void PluginContainer::unloadPlugins() { - if (m_UserInterface != nullptr) { - m_UserInterface->disconnectPlugins(); - } - // disconnect all slots before unloading plugins so plugins don't have to take care of that if (m_Organizer) { m_Organizer->disconnectPlugins(); @@ -1104,7 +1094,6 @@ void PluginContainer::loadPlugins() } } - std::vector PluginContainer::activeProblems() const { std::vector problems; diff --git a/src/plugincontainer.h b/src/plugincontainer.h index 43c7973f..d6503a43 100644 --- a/src/plugincontainer.h +++ b/src/plugincontainer.h @@ -186,10 +186,23 @@ public: public: - PluginContainer(OrganizerCore *organizer); + PluginContainer(OrganizerCore* organizer); virtual ~PluginContainer(); - void setUserInterface(IUserInterface *userInterface); + /** + * @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); void loadPlugin(QString const& filepath); void unloadPlugin(QString const& filepath); @@ -392,21 +405,15 @@ private: * * @return the list of created plugins. */ - std::vector loadProxied(const QString& filepath, MOBase::IPluginProxy* proxy); + std::vector loadProxied(const QString& filepath, MOBase::IPluginProxy* proxy); - /** - * @brief Load the Qt plugin from the given file. - * - * @param filepath Path to the DLL containing the Qt plugin. - */ - MOBase::IPlugin* loadQtPlugin(const QString& filepath); + // Load the Qt plugin from the given file. + QObject* loadQtPlugin(const QString& filepath); - /** - * @brief Simulate MO2 startup for the given plugins. - * - * @param plugins Plugins to simulate startup for. - */ - void simulateStartup(const std::vector& plugins) 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& plugins) const; /** * @brief Retrieved the (localized) names of interfaces implemented by the given diff --git a/src/pluginlistproxy.cpp b/src/pluginlistproxy.cpp index b51d108b..b9ea9e36 100644 --- a/src/pluginlistproxy.cpp +++ b/src/pluginlistproxy.cpp @@ -6,18 +6,26 @@ using namespace MOBase; using namespace MOShared; PluginListProxy::PluginListProxy(OrganizerProxy* oproxy, PluginList* pluginlist) : - m_OrganizerProxy(oproxy), m_Proxied(pluginlist) + m_OrganizerProxy(oproxy), m_Proxied(pluginlist) { } + +PluginListProxy::~PluginListProxy() +{ + disconnectSignals(); +} + +void PluginListProxy::connectSignals() { m_Connections.push_back(m_Proxied->onRefreshed(callSignalIfPluginActive(m_OrganizerProxy, m_Refreshed))); m_Connections.push_back(m_Proxied->onPluginMoved(callSignalIfPluginActive(m_OrganizerProxy, m_PluginMoved))); m_Connections.push_back(m_Proxied->onPluginStateChanged(callSignalIfPluginActive(m_OrganizerProxy, m_PluginStateChanged))); } -PluginListProxy::~PluginListProxy() +void PluginListProxy::disconnectSignals() { for (auto& conn : m_Connections) { conn.disconnect(); } + m_Connections.clear(); } QStringList PluginListProxy::pluginNames() const diff --git a/src/pluginlistproxy.h b/src/pluginlistproxy.h index 04a6ad55..e421b6ee 100644 --- a/src/pluginlistproxy.h +++ b/src/pluginlistproxy.h @@ -30,6 +30,12 @@ public: private: + friend class OrganizerProxy; + + // See OrganizerProxy::connectSignals(). + void connectSignals(); + void disconnectSignals(); + OrganizerProxy* m_OrganizerProxy; PluginList* m_Proxied; -- cgit v1.3.1