Commit 7df3bff0 authored by Tobias Hunger's avatar Tobias Hunger

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's avatarEike Ziller <eike.ziller@qt.io>
parent 1ddee692
......@@ -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,
......
......@@ -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;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment