Fix crash in ProjectTree on restoring a session

On adding nodes to the node structure, both the FlatModel::nodesAdded
and ProjectTree::nodesAdded code is run. We need to ensure that
FlatModel::nodesAdded is run first though, as we need that information
in the ProjectTree.

Task-number: QTCREATORBUG-13667
Change-Id: I0b4b41ed6036cfdef668c16689d25611633ab0c9
Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
This commit is contained in:
Daniel Teske
2014-12-15 18:24:25 +01:00
committed by Eike Ziller
parent beb0797008
commit 5d2d37b794
4 changed files with 61 additions and 26 deletions

View File

@@ -1392,6 +1392,7 @@ ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
{ {
disconnect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*,Core::IMode*)), disconnect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*,Core::IMode*)),
this, SLOT(currentModeChanged(Core::IMode*,Core::IMode*))); this, SLOT(currentModeChanged(Core::IMode*,Core::IMode*)));
ProjectTree::aboutToShutDown();
dd->m_proWindow->aboutToShutdown(); // disconnect from session dd->m_proWindow->aboutToShutdown(); // disconnect from session
SessionManager::closeAllProjects(); SessionManager::closeAllProjects();
dd->m_projectsMode = 0; dd->m_projectsMode = 0;

View File

@@ -43,6 +43,7 @@
#include <coreplugin/vcsmanager.h> #include <coreplugin/vcsmanager.h>
#include <QApplication> #include <QApplication>
#include <QTimer>
namespace { namespace {
const char EXTERNAL_FILE_WARNING[] = "ExternalFile"; const char EXTERNAL_FILE_WARNING[] = "ExternalFile";
@@ -73,28 +74,50 @@ ProjectTree::ProjectTree(QObject *parent)
this, &ProjectTree::projectRemoved); this, &ProjectTree::projectRemoved);
NodesWatcher *watcher = new NodesWatcher(this); m_watcher = new NodesWatcher(this);
SessionManager::sessionNode()->registerWatcher(watcher); SessionManager::sessionNode()->registerWatcher(m_watcher);
connect(watcher, &NodesWatcher::foldersAboutToBeRemoved, connect(m_watcher, &NodesWatcher::foldersAboutToBeRemoved,
this, &ProjectTree::foldersAboutToBeRemoved); this, &ProjectTree::foldersAboutToBeRemoved);
connect(watcher, &NodesWatcher::foldersRemoved, connect(m_watcher, &NodesWatcher::foldersRemoved,
this, &ProjectTree::foldersRemoved); this, &ProjectTree::foldersRemoved);
connect(watcher, &NodesWatcher::filesAboutToBeRemoved, connect(m_watcher, &NodesWatcher::filesAboutToBeRemoved,
this, &ProjectTree::filesAboutToBeRemoved); this, &ProjectTree::filesAboutToBeRemoved);
connect(watcher, &NodesWatcher::filesRemoved, connect(m_watcher, &NodesWatcher::filesRemoved,
this, &ProjectTree::filesRemoved); this, &ProjectTree::filesRemoved);
connect(watcher, &NodesWatcher::foldersAdded, connect(m_watcher, &NodesWatcher::foldersAdded,
this, &ProjectTree::nodesAdded); this, &ProjectTree::nodesAdded);
connect(watcher, &NodesWatcher::filesAdded, connect(m_watcher, &NodesWatcher::filesAdded,
this, &ProjectTree::nodesAdded); this, &ProjectTree::nodesAdded);
connect(qApp, &QApplication::focusChanged, connect(qApp, &QApplication::focusChanged,
this, &ProjectTree::focusChanged); this, &ProjectTree::focusChanged);
} }
void ProjectTree::aboutToShutDown()
{
disconnect(s_instance->m_watcher, &NodesWatcher::foldersAboutToBeRemoved,
s_instance, &ProjectTree::foldersAboutToBeRemoved);
disconnect(s_instance->m_watcher, &NodesWatcher::foldersRemoved,
s_instance, &ProjectTree::foldersRemoved);
disconnect(s_instance->m_watcher, &NodesWatcher::filesAboutToBeRemoved,
s_instance, &ProjectTree::filesAboutToBeRemoved);
disconnect(s_instance->m_watcher, &NodesWatcher::filesRemoved,
s_instance, &ProjectTree::filesRemoved);
disconnect(s_instance->m_watcher, &NodesWatcher::foldersAdded,
s_instance, &ProjectTree::nodesAdded);
disconnect(s_instance->m_watcher, &NodesWatcher::filesAdded,
s_instance, &ProjectTree::nodesAdded);
disconnect(qApp, &QApplication::focusChanged,
s_instance, &ProjectTree::focusChanged);
s_instance->update(0, 0);
}
ProjectTree *ProjectTree::instance() ProjectTree *ProjectTree::instance()
{ {
return s_instance; return s_instance;
@@ -266,10 +289,12 @@ void ProjectTree::foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode*>
void ProjectTree::foldersRemoved() void ProjectTree::foldersRemoved()
{ {
QTimer::singleShot(0, [this]() {
if (m_resetCurrentNodeFolder) { if (m_resetCurrentNodeFolder) {
updateFromFocus(true); updateFromFocus(true);
m_resetCurrentNodeFolder = false; m_resetCurrentNodeFolder = false;
} }
});
} }
void ProjectTree::filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &list) void ProjectTree::filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &list)
@@ -281,10 +306,12 @@ void ProjectTree::filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &li
void ProjectTree::filesRemoved() void ProjectTree::filesRemoved()
{ {
QTimer::singleShot(0, [this]() {
if (m_resetCurrentNodeFile) { if (m_resetCurrentNodeFile) {
updateFromFocus(true); updateFromFocus(true);
m_resetCurrentNodeFile = false; m_resetCurrentNodeFile = false;
} }
});
} }
void ProjectTree::aboutToRemoveProject(Project *project) void ProjectTree::aboutToRemoveProject(Project *project)
@@ -295,16 +322,20 @@ void ProjectTree::aboutToRemoveProject(Project *project)
void ProjectTree::projectRemoved() void ProjectTree::projectRemoved()
{ {
QTimer::singleShot(0, [this]() {
updateFromFocus(true); updateFromFocus(true);
m_resetCurrentNodeProject = false; m_resetCurrentNodeProject = false;
});
} }
void ProjectTree::nodesAdded() void ProjectTree::nodesAdded()
{ {
QTimer::singleShot(0, [this]() {
if (Utils::anyOf(m_projectTreeWidgets, &ProjectTreeWidget::hasFocus)) if (Utils::anyOf(m_projectTreeWidgets, &ProjectTreeWidget::hasFocus))
return; return;
updateFromDocumentManager(); updateFromDocumentManager();
});
} }
void ProjectTree::updateExternalFileWarning() void ProjectTree::updateExternalFileWarning()

View File

@@ -39,6 +39,7 @@ namespace ProjectExplorer {
class FileNode; class FileNode;
class FolderNode; class FolderNode;
class Node; class Node;
class NodesWatcher;
class Project; class Project;
namespace Internal { class ProjectTreeWidget; } namespace Internal { class ProjectTreeWidget; }
@@ -58,14 +59,15 @@ public:
static void registerWidget(Internal::ProjectTreeWidget *widget); static void registerWidget(Internal::ProjectTreeWidget *widget);
static void unregisterWidget(Internal::ProjectTreeWidget *widget); static void unregisterWidget(Internal::ProjectTreeWidget *widget);
static void nodeChanged(Internal::ProjectTreeWidget *widget); static void nodeChanged(Internal::ProjectTreeWidget *widget);
static void focusChanged();
static Project *projectForNode(Node *node); static Project *projectForNode(Node *node);
static void aboutToShutDown();
signals: signals:
void currentProjectChanged(ProjectExplorer::Project *project); void currentProjectChanged(ProjectExplorer::Project *project);
void currentNodeChanged(ProjectExplorer::Node *node, ProjectExplorer::Project *project); void currentNodeChanged(ProjectExplorer::Node *node, ProjectExplorer::Project *project);
private: private:
void focusChanged();
void updateFromProjectTreeWidget(Internal::ProjectTreeWidget *widget); void updateFromProjectTreeWidget(Internal::ProjectTreeWidget *widget);
void documentManagerCurrentFileChanged(); void documentManagerCurrentFileChanged();
void updateFromDocumentManager(bool invalidCurrentNode = false); void updateFromDocumentManager(bool invalidCurrentNode = false);
@@ -95,6 +97,7 @@ private:
bool m_resetCurrentNodeFile; bool m_resetCurrentNodeFile;
bool m_resetCurrentNodeProject; bool m_resetCurrentNodeProject;
Core::Context m_lastProjectContext; Core::Context m_lastProjectContext;
NodesWatcher *m_watcher;
}; };
} }

View File

@@ -243,15 +243,15 @@ Node *ProjectTreeWidget::nodeForFile(const QString &fileName)
foreach (Node *node, SessionManager::nodesForFile(fileName)) { foreach (Node *node, SessionManager::nodesForFile(fileName)) {
if (!bestNode) { if (!bestNode) {
bestNode = node; bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node->parentFolderNode()); bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
} else if (node->nodeType() < bestNode->nodeType()) { } else if (node->nodeType() < bestNode->nodeType()) {
bestNode = node; bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node->parentFolderNode()); bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
} else if (node->nodeType() == bestNode->nodeType()) { } else if (node->nodeType() == bestNode->nodeType()) {
int nodeExpandCount = ProjectTreeWidget::expandedCount(node->parentFolderNode()); int nodeExpandCount = ProjectTreeWidget::expandedCount(node);
if (nodeExpandCount < bestNodeExpandCount) { if (nodeExpandCount < bestNodeExpandCount) {
bestNode = node; bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node->parentFolderNode()); bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
} }
} }
} }