forked from qt-creator/qt-creator
ProjectExplorer: Fix some corner cases in signal subscriptions
Handle cases where targets/projects are removed and then added again. This is currently not done anywhere, but there should not be nasty surprises when somebody decides to do that later. Change-Id: I47f9b4a1577f2021bcee87ccdd5435e3628b2a95 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "project.h"
|
||||
#include "projectconfiguration.h"
|
||||
#include "session.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -37,13 +38,8 @@ 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, [this]() {
|
||||
unsubscribeAll();
|
||||
m_subscriber = Connector(); // Reset subscriber
|
||||
deleteLater();
|
||||
});
|
||||
}
|
||||
if (receiver != parent)
|
||||
connect(receiver, &QObject::destroyed, this, &Subscription::destroy);
|
||||
}
|
||||
|
||||
Subscription::~Subscription()
|
||||
@@ -58,12 +54,7 @@ void Subscription::subscribe(ProjectConfiguration *pc)
|
||||
|
||||
connectTo(pc);
|
||||
|
||||
if (auto p = qobject_cast<Project *>(pc)) {
|
||||
for (Target *t : p->targets()) {
|
||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||
connectTo(pc);
|
||||
}
|
||||
} else if (auto t = qobject_cast<Target *>(pc)) {
|
||||
if (auto t = qobject_cast<Target *>(pc)) {
|
||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||
connectTo(pc);
|
||||
}
|
||||
@@ -73,14 +64,9 @@ void Subscription::unsubscribe(ProjectConfiguration *pc)
|
||||
{
|
||||
disconnectFrom(pc);
|
||||
|
||||
if (auto p = qobject_cast<Project *>(pc)) {
|
||||
for (Target *t : p->targets()) {
|
||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||
unsubscribe(pc);
|
||||
}
|
||||
} else if (auto t = qobject_cast<Target *>(pc)) {
|
||||
if (auto t = qobject_cast<Target *>(pc)) {
|
||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||
unsubscribe(pc);
|
||||
disconnectFrom(pc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +79,9 @@ void Subscription::unsubscribeAll()
|
||||
|
||||
void Subscription::connectTo(ProjectConfiguration *pc)
|
||||
{
|
||||
if (!m_subscriber)
|
||||
return; // May happen during shutdown of a subscription
|
||||
|
||||
QTC_ASSERT(!m_connections.contains(pc), return);
|
||||
|
||||
QMetaObject::Connection conn = m_subscriber(pc);
|
||||
@@ -110,18 +99,27 @@ void Subscription::disconnectFrom(ProjectConfiguration *pc)
|
||||
m_connections.remove(pc);
|
||||
}
|
||||
|
||||
void Subscription::destroy()
|
||||
{
|
||||
unsubscribeAll();
|
||||
m_subscriber = Connector(); // Reset subscriber
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
ProjectSubscription::ProjectSubscription(const Subscription::Connector &s, const QObject *r,
|
||||
Project *p) :
|
||||
Subscription(s, r, p)
|
||||
{
|
||||
if (m_subscriber) {
|
||||
for (const Target *t : p->targets()) {
|
||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||
m_subscriber(pc);
|
||||
}
|
||||
connect(p, &Project::addedProjectConfiguration, this, &ProjectSubscription::subscribe);
|
||||
connect(p, &Project::removedProjectConfiguration, this, &ProjectSubscription::unsubscribe);
|
||||
}
|
||||
QTC_ASSERT(m_subscriber, return);
|
||||
|
||||
for (Target *t : p->targets())
|
||||
subscribe(t);
|
||||
|
||||
// Disconnect on removal of a project, to make it save to remove/add a project:
|
||||
connect(SessionManager::instance(), &SessionManager::projectRemoved,
|
||||
this, [this, p](Project *reported) { if (p == reported) { destroy(); } });
|
||||
connect(p, &Project::addedProjectConfiguration, this, &ProjectSubscription::subscribe);
|
||||
connect(p, &Project::removedProjectConfiguration, this, &ProjectSubscription::unsubscribe);
|
||||
}
|
||||
|
||||
ProjectSubscription::~ProjectSubscription() = default;
|
||||
@@ -130,8 +128,13 @@ TargetSubscription::TargetSubscription(const Subscription::Connector &s, const Q
|
||||
Target *t) :
|
||||
Subscription(s, r, t)
|
||||
{
|
||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||
m_subscriber(pc);
|
||||
QTC_ASSERT(m_subscriber, return);
|
||||
|
||||
subscribe(t);
|
||||
|
||||
// Disconnect on removal of a target, to make it save to remove/add a target:
|
||||
connect(t->project(), &Project::removedTarget, this,
|
||||
[t, this](const Target *reportedTarget) { if (t == reportedTarget) { destroy(); } });
|
||||
connect(t, &Target::addedProjectConfiguration, this, &TargetSubscription::subscribe);
|
||||
connect(t, &Target::removedProjectConfiguration, this, &TargetSubscription::unsubscribe);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@ protected:
|
||||
void connectTo(ProjectConfiguration *pc);
|
||||
void disconnectFrom(ProjectConfiguration *pc);
|
||||
|
||||
void destroy();
|
||||
|
||||
Connector m_subscriber;
|
||||
QHash<ProjectConfiguration *, QMetaObject::Connection> m_connections;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user