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 "project.h"
|
||||||
#include "projectconfiguration.h"
|
#include "projectconfiguration.h"
|
||||||
|
#include "session.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -37,13 +38,8 @@ namespace Internal {
|
|||||||
Subscription::Subscription(const Subscription::Connector &s, const QObject *receiver, QObject *parent) :
|
Subscription::Subscription(const Subscription::Connector &s, const QObject *receiver, QObject *parent) :
|
||||||
QObject(parent), m_subscriber(s)
|
QObject(parent), m_subscriber(s)
|
||||||
{
|
{
|
||||||
if (receiver != parent) {
|
if (receiver != parent)
|
||||||
connect(receiver, &QObject::destroyed, this, [this]() {
|
connect(receiver, &QObject::destroyed, this, &Subscription::destroy);
|
||||||
unsubscribeAll();
|
|
||||||
m_subscriber = Connector(); // Reset subscriber
|
|
||||||
deleteLater();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Subscription::~Subscription()
|
Subscription::~Subscription()
|
||||||
@@ -58,12 +54,7 @@ void Subscription::subscribe(ProjectConfiguration *pc)
|
|||||||
|
|
||||||
connectTo(pc);
|
connectTo(pc);
|
||||||
|
|
||||||
if (auto p = qobject_cast<Project *>(pc)) {
|
if (auto t = qobject_cast<Target *>(pc)) {
|
||||||
for (Target *t : p->targets()) {
|
|
||||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
|
||||||
connectTo(pc);
|
|
||||||
}
|
|
||||||
} else if (auto t = qobject_cast<Target *>(pc)) {
|
|
||||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||||
connectTo(pc);
|
connectTo(pc);
|
||||||
}
|
}
|
||||||
@@ -73,14 +64,9 @@ void Subscription::unsubscribe(ProjectConfiguration *pc)
|
|||||||
{
|
{
|
||||||
disconnectFrom(pc);
|
disconnectFrom(pc);
|
||||||
|
|
||||||
if (auto p = qobject_cast<Project *>(pc)) {
|
if (auto t = qobject_cast<Target *>(pc)) {
|
||||||
for (Target *t : p->targets()) {
|
|
||||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
|
||||||
unsubscribe(pc);
|
|
||||||
}
|
|
||||||
} else if (auto t = qobject_cast<Target *>(pc)) {
|
|
||||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
for (ProjectConfiguration *pc : t->projectConfigurations())
|
||||||
unsubscribe(pc);
|
disconnectFrom(pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +79,9 @@ void Subscription::unsubscribeAll()
|
|||||||
|
|
||||||
void Subscription::connectTo(ProjectConfiguration *pc)
|
void Subscription::connectTo(ProjectConfiguration *pc)
|
||||||
{
|
{
|
||||||
|
if (!m_subscriber)
|
||||||
|
return; // May happen during shutdown of a subscription
|
||||||
|
|
||||||
QTC_ASSERT(!m_connections.contains(pc), return);
|
QTC_ASSERT(!m_connections.contains(pc), return);
|
||||||
|
|
||||||
QMetaObject::Connection conn = m_subscriber(pc);
|
QMetaObject::Connection conn = m_subscriber(pc);
|
||||||
@@ -110,18 +99,27 @@ void Subscription::disconnectFrom(ProjectConfiguration *pc)
|
|||||||
m_connections.remove(pc);
|
m_connections.remove(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Subscription::destroy()
|
||||||
|
{
|
||||||
|
unsubscribeAll();
|
||||||
|
m_subscriber = Connector(); // Reset subscriber
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
ProjectSubscription::ProjectSubscription(const Subscription::Connector &s, const QObject *r,
|
ProjectSubscription::ProjectSubscription(const Subscription::Connector &s, const QObject *r,
|
||||||
Project *p) :
|
Project *p) :
|
||||||
Subscription(s, r, p)
|
Subscription(s, r, p)
|
||||||
{
|
{
|
||||||
if (m_subscriber) {
|
QTC_ASSERT(m_subscriber, return);
|
||||||
for (const Target *t : p->targets()) {
|
|
||||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
for (Target *t : p->targets())
|
||||||
m_subscriber(pc);
|
subscribe(t);
|
||||||
}
|
|
||||||
connect(p, &Project::addedProjectConfiguration, this, &ProjectSubscription::subscribe);
|
// Disconnect on removal of a project, to make it save to remove/add a project:
|
||||||
connect(p, &Project::removedProjectConfiguration, this, &ProjectSubscription::unsubscribe);
|
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;
|
ProjectSubscription::~ProjectSubscription() = default;
|
||||||
@@ -130,8 +128,13 @@ TargetSubscription::TargetSubscription(const Subscription::Connector &s, const Q
|
|||||||
Target *t) :
|
Target *t) :
|
||||||
Subscription(s, r, t)
|
Subscription(s, r, t)
|
||||||
{
|
{
|
||||||
for (ProjectConfiguration *pc : t->projectConfigurations())
|
QTC_ASSERT(m_subscriber, return);
|
||||||
m_subscriber(pc);
|
|
||||||
|
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::addedProjectConfiguration, this, &TargetSubscription::subscribe);
|
||||||
connect(t, &Target::removedProjectConfiguration, this, &TargetSubscription::unsubscribe);
|
connect(t, &Target::removedProjectConfiguration, this, &TargetSubscription::unsubscribe);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ protected:
|
|||||||
void connectTo(ProjectConfiguration *pc);
|
void connectTo(ProjectConfiguration *pc);
|
||||||
void disconnectFrom(ProjectConfiguration *pc);
|
void disconnectFrom(ProjectConfiguration *pc);
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
|
||||||
Connector m_subscriber;
|
Connector m_subscriber;
|
||||||
QHash<ProjectConfiguration *, QMetaObject::Connection> m_connections;
|
QHash<ProjectConfiguration *, QMetaObject::Connection> m_connections;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user