summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMikaël Capelle <capelle.mikael@gmail.com>2020-12-04 08:50:31 +0100
committerMikaël Capelle <capelle.mikael@gmail.com>2020-12-04 08:50:31 +0100
commita30d49f4fc845164ef6bba4d2a834efce1dc01d7 (patch)
tree5aa8becd18a2eae3795e602db0f499a864dab40f /src
parentf229dbaaa7f516dc1958d0a0555b47cb17136377 (diff)
Avoid duplicating code to simulate startup.
Diffstat (limited to 'src')
-rw-r--r--src/downloadmanagerproxy.cpp12
-rw-r--r--src/downloadmanagerproxy.h6
-rw-r--r--src/iuserinterface.h2
-rw-r--r--src/mainwindow.cpp15
-rw-r--r--src/mainwindow.h8
-rw-r--r--src/modlistproxy.cpp12
-rw-r--r--src/modlistproxy.h6
-rw-r--r--src/organizerproxy.cpp24
-rw-r--r--src/organizerproxy.h17
-rw-r--r--src/plugincontainer.cpp207
-rw-r--r--src/plugincontainer.h37
-rw-r--r--src/pluginlistproxy.cpp12
-rw-r--r--src/pluginlistproxy.h6
13 files changed, 208 insertions, 156 deletions
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<DownloadManagerProxy>(this, organizer->downloadManager()))
, m_ModListProxy(std::make_unique<ModListProxy>(this, organizer->modList()))
- , m_PluginListProxy(std::make_unique<PluginListProxy>(this, organizer->pluginList()))
+ , m_PluginListProxy(std::make_unique<PluginListProxy>(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<IPluginProxy>(m_Plugins)) {
- proxy->setParentWidget(userInterface->mainWindow());
- }
- for (IPluginModPage* modPage : bf::at_key<IPluginModPage>(m_Plugins)) {
- modPage->setParentWidget(userInterface->mainWindow());
- }
- for (IPluginTool* tool : bf::at_key<IPluginTool>(m_Plugins)) {
- tool->setParentWidget(userInterface->mainWindow());
- }
- for (IPluginInstaller* installer : bf::at_key<IPluginInstaller>(m_Plugins)) {
- installer->setParentWidget(userInterface->mainWindow());
- }
- }
-
m_UserInterface = userInterface;
+ startPluginsImpl(plugins<QObject>());
}
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<QPluginLoader> 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<IPlugin*> PluginContainer::loadProxied(const QString& filepath, IPluginProxy* proxy)
-{
- std::vector<IPlugin*> 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<QObject*> matchingPlugins = proxy->load(filepath);
-
- // We are going to group plugin by names and "fix" them later:
- std::map<QString, std::vector<IPlugin*>> 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<IPlugin*>& plugins) const
+void PluginContainer::startPluginsImpl(const std::vector<QObject*>& plugins) const
{
// setUserInterface()
if (m_UserInterface) {
for (auto* plugin : plugins) {
- if (auto* proxy = dynamic_cast<IPluginProxy*>(plugin)) {
+ if (auto* proxy = qobject_cast<IPluginProxy*>(plugin)) {
proxy->setParentWidget(m_UserInterface->mainWindow());
}
- if (auto* modPage = dynamic_cast<IPluginModPage*>(plugin)) {
+ if (auto* modPage = qobject_cast<IPluginModPage*>(plugin)) {
modPage->setParentWidget(m_UserInterface->mainWindow());
}
- if (auto* tool = dynamic_cast<IPluginTool*>(plugin)) {
+ if (auto* tool = qobject_cast<IPluginTool*>(plugin)) {
tool->setParentWidget(m_UserInterface->mainWindow());
}
- if (auto* installer = dynamic_cast<IPluginInstaller*>(plugin)) {
+ if (auto* installer = qobject_cast<IPluginInstaller*>(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<IPlugin*>(object);
auto* oproxy = organizerProxy(plugin);
+ oproxy->connectSignals();
oproxy->m_UserInterfaceInitialized(m_UserInterface->mainWindow());
oproxy->m_ProfileChanged(nullptr, m_Organizer->currentProfile());
}
}
+std::vector<QObject*> PluginContainer::loadProxied(const QString& filepath, IPluginProxy* proxy)
+{
+ std::vector<QObject*> 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<QObject*> matchingPlugins = proxy->load(filepath);
+
+ // We are going to group plugin by names and "fix" them later:
+ std::map<QString, std::vector<IPlugin*>> 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<QPluginLoader> 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<IPlugin*> plugins;
+ std::vector<QObject*> 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<IPlugin*>(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<unsigned int> PluginContainer::activeProblems() const
{
std::vector<unsigned int> 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<MOBase::IPlugin*> loadProxied(const QString& filepath, MOBase::IPluginProxy* proxy);
+ std::vector<QObject*> 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<MOBase::IPlugin*>& 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<QObject*>& 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;