forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
Reference in New Issue
Block a user