ProjectTree: Fix crash working with resources

Fix the notification of subtree changes to keep the project in
the loop, so that it can adjust its list of known files.

Ignoring that will cause crashes, e.g. when the ResourceEditor
updates its subtree of the project.

Task-number: QTCREATORBUG-19613
Change-Id: Ib7bb9afe48eb248cdf675ba2093b266fd728d7b2
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Tobias Hunger
2018-01-19 11:55:28 +01:00
parent cf94a15379
commit 034f0209b0
4 changed files with 38 additions and 16 deletions

View File

@@ -527,29 +527,33 @@ void Project::setRootProjectNode(ProjectNode *root)
root = nullptr;
}
ProjectTree::applyTreeManager(root);
if (root) {
ProjectTree::applyTreeManager(root);
root->setParentFolderNode(d->m_containerNode.get());
}
ProjectNode *oldNode = d->m_rootProjectNode;
d->m_rootProjectNode = root;
if (root) {
QVector<const Node *> nodeList;
root->forEachGenericNode([&nodeList](const Node *n) {
if (oldNode || root)
handleSubTreeChanged(d->m_containerNode.get());
delete oldNode;
}
void Project::handleSubTreeChanged(FolderNode *node)
{
QVector<const Node *> nodeList;
if (d->m_rootProjectNode) {
d->m_rootProjectNode->forEachGenericNode([&nodeList](const Node *n) {
nodeList.append(n);
});
Utils::sort(nodeList, &nodeLessThan);
d->m_sortedNodeList = nodeList;
root->setParentFolderNode(d->m_containerNode.get());
// Only announce non-null root, null is only used when project is destroyed.
// In that case SessionManager::projectRemoved() triggers the update.
ProjectTree::emitSubtreeChanged(root);
emit fileListChanged();
} else {
d->m_sortedNodeList.clear();
if (oldNode != nullptr)
emit fileListChanged();
}
d->m_sortedNodeList = nodeList;
delete oldNode;
ProjectTree::emitSubtreeChanged(node);
emit fileListChanged();
}
Target *Project::restoreTarget(const QVariantMap &data)

View File

@@ -48,6 +48,7 @@ namespace ProjectExplorer {
class BuildInfo;
class ContainerNode;
class EditorConfiguration;
class FolderNode;
class NamedWidget;
class Node;
class ProjectConfiguration;
@@ -241,10 +242,12 @@ protected:
virtual void projectLoaded(); // Called when the project is fully loaded.
private:
void handleSubTreeChanged(FolderNode *node);
void setActiveTarget(Target *target);
ProjectPrivate *d;
friend class Session;
friend class ContainerNode;
};
} // namespace ProjectExplorer

View File

@@ -628,7 +628,7 @@ bool FolderNode::replaceSubtree(Node *oldNode, Node *newNode)
}
QTimer::singleShot(0, [oldNode]() { delete oldNode; });
}
ProjectTree::emitSubtreeChanged(this);
handleSubTreeChanged(this);
return true;
}
@@ -879,6 +879,12 @@ bool FolderNode::isEmpty() const
return m_nodes.isEmpty();
}
void FolderNode::handleSubTreeChanged(FolderNode *node)
{
if (FolderNode *parent = parentFolderNode())
parent->handleSubTreeChanged(node);
}
ContainerNode::ContainerNode(Project *project)
: FolderNode(project->projectDirectory(), NodeType::Project), m_project(project)
{}
@@ -915,4 +921,9 @@ void ContainerNode::removeAllChildren()
m_nodes.clear();
}
void ContainerNode::handleSubTreeChanged(FolderNode *node)
{
m_project->handleSubTreeChanged(node);
}
} // namespace ProjectExplorer

View File

@@ -294,6 +294,8 @@ public:
const FolderNode *asFolderNode() const override { return this; }
protected:
virtual void handleSubTreeChanged(FolderNode *node);
QList<Node *> m_nodes;
QList<LocationInfo> m_locations;
@@ -361,6 +363,8 @@ public:
void removeAllChildren();
private:
void handleSubTreeChanged(FolderNode *node) final;
Project *m_project;
};