diff options
author | Tobias Hunger <tobias.hunger@qt.io> | 2017-12-07 13:10:36 +0100 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@qt.io> | 2017-12-08 10:37:32 +0000 |
commit | 7df3bff07ad07913744f0dcf4bddf3905bb3d9ba (patch) | |
tree | cae6433dae15dd1a5d06272ce0e3ec1e72c3f797 | |
parent | 1ddee692009975d89b36c51cf5e30808776e38e3 (diff) | |
download | qt-creator-7df3bff07ad07913744f0dcf4bddf3905bb3d9ba.tar.gz |
ProjectExplorer: Make subscriptions more robust
Make sure not to continue to connect after the receiver was destructed
and make sure to disconnect from everything when that happens.
Task-number: QTCREATORBUG-19391
Change-Id: I4d09a7dca2a5260c3d4744607dccbde5964a0623
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
-rw-r--r-- | src/plugins/projectexplorer/subscription.cpp | 54 | ||||
-rw-r--r-- | src/plugins/projectexplorer/subscription.h | 4 |
2 files changed, 44 insertions, 14 deletions
diff --git a/src/plugins/projectexplorer/subscription.cpp b/src/plugins/projectexplorer/subscription.cpp index b878bdacdc..6049fea02a 100644 --- a/src/plugins/projectexplorer/subscription.cpp +++ b/src/plugins/projectexplorer/subscription.cpp @@ -30,6 +30,7 @@ #include "target.h" #include <utils/asconst.h> +#include <utils/qtcassert.h> namespace ProjectExplorer { namespace Internal { @@ -37,42 +38,42 @@ namespace Internal { Subscription::Subscription(const Subscription::Connector &s, const QObject *receiver, QObject *parent) : QObject(parent), m_subscriber(s) { - if (receiver != parent) - connect(receiver, &QObject::destroyed, this, &QObject::deleteLater); + if (receiver != parent) { + connect(receiver, &QObject::destroyed, this, [this]() { + unsubscribeAll(); + m_subscriber = Connector(); // Reset subscriber + deleteLater(); + }); + } } Subscription::~Subscription() { - for (const auto &c : Utils::asConst(m_connections)) - disconnect(c); + unsubscribeAll(); } void Subscription::subscribe(ProjectConfiguration *pc) { if (!m_subscriber) return; - QMetaObject::Connection conn = m_subscriber(pc); - if (conn) - m_connections.insert(pc, conn); + + connectTo(pc); if (auto p = qobject_cast<Project *>(pc)) { for (Target *t : p->targets()) { for (ProjectConfiguration *pc : t->projectConfigurations()) - m_subscriber(pc); + connectTo(pc); } } else if (auto t = qobject_cast<Target *>(pc)) { for (ProjectConfiguration *pc : t->projectConfigurations()) - m_subscriber(pc); + connectTo(pc); } } void Subscription::unsubscribe(ProjectConfiguration *pc) { - auto c = m_connections.value(pc); - if (c) { - disconnect(c); - m_connections.remove(pc); - } + disconnectFrom(pc); + if (auto p = qobject_cast<Project *>(pc)) { for (Target *t : p->targets()) { for (ProjectConfiguration *pc : t->projectConfigurations()) @@ -82,7 +83,32 @@ void Subscription::unsubscribe(ProjectConfiguration *pc) for (ProjectConfiguration *pc : t->projectConfigurations()) unsubscribe(pc); } +} + +void Subscription::unsubscribeAll() +{ + for (const auto &c : Utils::asConst(m_connections)) + disconnect(c); + m_connections.clear(); +} + +void Subscription::connectTo(ProjectConfiguration *pc) +{ + QTC_ASSERT(!m_connections.contains(pc), return); + + QMetaObject::Connection conn = m_subscriber(pc); + if (conn) + m_connections.insert(pc, conn); +} + +void Subscription::disconnectFrom(ProjectConfiguration *pc) +{ + auto c = m_connections.value(pc); + if (!c) + return; + disconnect(c); + m_connections.remove(pc); } ProjectSubscription::ProjectSubscription(const Subscription::Connector &s, const QObject *r, diff --git a/src/plugins/projectexplorer/subscription.h b/src/plugins/projectexplorer/subscription.h index 5c1e0ec1a4..819a11d1f1 100644 --- a/src/plugins/projectexplorer/subscription.h +++ b/src/plugins/projectexplorer/subscription.h @@ -53,6 +53,10 @@ protected: void subscribe(ProjectConfiguration *pc); void unsubscribe(ProjectConfiguration *pc); + void unsubscribeAll(); + void connectTo(ProjectConfiguration *pc); + void disconnectFrom(ProjectConfiguration *pc); + Connector m_subscriber; QHash<ProjectConfiguration *, QMetaObject::Connection> m_connections; }; |