Refactor ProjectExplorer::Node and remove NodesWatcher

The idea behind NodesWatcher was that it was the central place
to catch node related signals, so that users didn't need to
connect to each individual node and the nodes didn't need to
be QObjects. Somehow Nodes ended up being QObjects anyway.

Both the recently added ProjectTree and the FlatModels consume
the signals the NodesWatcher sends. Unfortunately there's a
ordering dependency between the ProjectTree and the FlatModels.

This patch removes all NodesWatcher and instead makes the
ProjectTree singleton the emitter of various project tree
related signals. The ProjectTree also ensures that the ordering
between the FlatModel and itself is taken into account.

And it makes Node not derive from QObject, saving some memory
in that process.

Task-number: QTCREATORBUG-13756
Change-Id: I8b0d357863f1dc1d2d440ce8172502594138b9fb
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
Daniel Teske
2015-01-09 15:50:06 +01:00
parent 44a7db5091
commit 70c9c51e5e
28 changed files with 350 additions and 619 deletions

View File

@@ -67,52 +67,12 @@ ProjectTree::ProjectTree(QObject *parent)
connect(Core::DocumentManager::instance(), &Core::DocumentManager::currentFileChanged,
this, &ProjectTree::documentManagerCurrentFileChanged);
SessionManager *session = SessionManager::instance();
connect(session, &SessionManager::aboutToRemoveProject,
this, &ProjectTree::aboutToRemoveProject);
connect(session, &SessionManager::projectRemoved,
this, &ProjectTree::projectRemoved);
m_watcher = new NodesWatcher(this);
SessionManager::sessionNode()->registerWatcher(m_watcher);
connect(m_watcher, &NodesWatcher::foldersAboutToBeRemoved,
this, &ProjectTree::foldersAboutToBeRemoved);
connect(m_watcher, &NodesWatcher::foldersRemoved,
this, &ProjectTree::foldersRemoved);
connect(m_watcher, &NodesWatcher::filesAboutToBeRemoved,
this, &ProjectTree::filesAboutToBeRemoved);
connect(m_watcher, &NodesWatcher::filesRemoved,
this, &ProjectTree::filesRemoved);
connect(m_watcher, &NodesWatcher::foldersAdded,
this, &ProjectTree::nodesAdded);
connect(m_watcher, &NodesWatcher::filesAdded,
this, &ProjectTree::nodesAdded);
connect(qApp, &QApplication::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);
@@ -187,7 +147,7 @@ Project *ProjectTree::projectForNode(Node *node)
if (!node)
return 0;
FolderNode *rootProjectNode = qobject_cast<FolderNode*>(node);
FolderNode *rootProjectNode = dynamic_cast<FolderNode*>(node);
if (!rootProjectNode)
rootProjectNode = node->parentFolderNode();
@@ -220,19 +180,18 @@ void ProjectTree::update(Node *node, Project *project)
{
if (project != m_currentProject) {
if (m_currentProject) {
disconnect(m_currentProject.data(), &Project::projectContextUpdated,
disconnect(m_currentProject, &Project::projectContextUpdated,
this, &ProjectTree::updateContext);
disconnect(m_currentProject.data(), &Project::projectLanguagesUpdated,
disconnect(m_currentProject, &Project::projectLanguagesUpdated,
this, &ProjectTree::updateContext);
}
m_currentProject = project;
emit currentProjectChanged(m_currentProject);
if (m_currentProject) {
connect(m_currentProject.data(), &Project::projectContextUpdated,
connect(m_currentProject, &Project::projectContextUpdated,
this, &ProjectTree::updateContext);
connect(m_currentProject.data(), &Project::projectLanguagesUpdated,
connect(m_currentProject, &Project::projectLanguagesUpdated,
this, &ProjectTree::updateContext);
}
}
@@ -248,6 +207,8 @@ void ProjectTree::update(Node *node, Project *project)
emit currentNodeChanged(m_currentNode, project);
}
emit currentProjectChanged(m_currentProject);
updateContext();
}
@@ -269,55 +230,107 @@ void ProjectTree::updateContext()
Core::ICore::updateAdditionalContexts(oldContext, newContext);
}
void ProjectTree::foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode*> &list)
void ProjectTree::emitNodeUpdated(Node *node)
{
emit nodeUpdated(node);
}
void ProjectTree::emitAboutToChangeShowInSimpleTree(FolderNode *node)
{
emit aboutToChangeShowInSimpleTree(node);
}
void ProjectTree::emitShowInSimpleTreeChanged(FolderNode *node)
{
emit showInSimpleTreeChanged(node);
}
void ProjectTree::emitFoldersAboutToBeAdded(FolderNode *parentFolder, const QList<FolderNode *> &newFolders)
{
emit foldersAboutToBeAdded(parentFolder, newFolders);
}
void ProjectTree::emitFoldersAdded()
{
emit foldersAdded();
if (Utils::anyOf(m_projectTreeWidgets, &ProjectTreeWidget::hasFocus))
return;
updateFromDocumentManager();
}
void ProjectTree::emitFoldersAboutToBeRemoved(FolderNode *parentFolder, const QList<FolderNode *> &staleFolders)
{
Node *n = ProjectTree::currentNode();
while (n) {
if (FolderNode *fn = qobject_cast<FolderNode *>(n)) {
if (list.contains(fn)) {
if (FolderNode *fn = dynamic_cast<FolderNode *>(n)) {
if (staleFolders.contains(fn)) {
ProjectNode *pn = n->projectNode();
// Make sure the node we are switching too isn't going to be removed also
while (list.contains(pn))
while (staleFolders.contains(pn))
pn = pn->parentFolderNode()->projectNode();
m_resetCurrentNodeFolder = true;
return;
break;
}
}
n = n->parentFolderNode();
}
emit foldersAboutToBeRemoved(parentFolder, staleFolders);
}
void ProjectTree::foldersRemoved()
void ProjectTree::emitFoldersRemoved()
{
QTimer::singleShot(0, this, SLOT(updateFromFocusResetFolderSingleShot()));
emit foldersRemoved();
if (m_resetCurrentNodeFolder) {
updateFromFocus(true);
m_resetCurrentNodeFolder = false;
}
}
void ProjectTree::filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &list)
void ProjectTree::emitFilesAboutToBeAdded(FolderNode *folder, const QList<FileNode *> &newFiles)
{
if (FileNode *fileNode = qobject_cast<FileNode *>(m_currentNode))
if (list.contains(fileNode))
emit filesAboutToBeAdded(folder, newFiles);
}
void ProjectTree::emitFilesAdded()
{
emit filesAdded();
if (Utils::anyOf(m_projectTreeWidgets, &ProjectTreeWidget::hasFocus))
return;
updateFromDocumentManager();
}
void ProjectTree::emitFilesAboutToBeRemoved(FolderNode *folder, const QList<FileNode *> &staleFiles)
{
if (FileNode *fileNode = dynamic_cast<FileNode *>(m_currentNode))
if (staleFiles.contains(fileNode))
m_resetCurrentNodeFile = false;
emit filesAboutToBeRemoved(folder, staleFiles);
}
void ProjectTree::filesRemoved()
void ProjectTree::emitFilesRemoved()
{
QTimer::singleShot(0, this, SLOT(updateFromFocusResetFileSingleShot()));
emit filesRemoved();
if (m_resetCurrentNodeFile) {
updateFromFocus(true);
m_resetCurrentNodeFile = false;
}
}
void ProjectTree::aboutToRemoveProject(Project *project)
void ProjectTree::emitNodeSortKeyAboutToChange(Node *node)
{
if (m_currentProject == project)
m_resetCurrentNodeProject = true;
emit nodeSortKeyAboutToChange(node);
}
void ProjectTree::projectRemoved()
void ProjectTree::emitNodeSortKeyChanged()
{
QTimer::singleShot(0, this, SLOT(updateFromFocusResetProjectSingleShot()));
}
void ProjectTree::nodesAdded()
{
QTimer::singleShot(0, this, SLOT(updateFromDocumentManagerSingleShot()));
emit nodeSortKeyChanged();
}
void ProjectTree::updateExternalFileWarning()
@@ -359,32 +372,3 @@ bool ProjectTree::hasFocus(ProjectTreeWidget *widget)
{
return widget && widget->focusWidget() && widget->focusWidget()->hasFocus();
}
void ProjectTree::updateFromFocusResetFileSingleShot()
{
if (m_resetCurrentNodeFile) {
updateFromFocus(true);
m_resetCurrentNodeFile = false;
}
}
void ProjectTree::updateFromFocusResetFolderSingleShot()
{
if (m_resetCurrentNodeFolder) {
updateFromFocus(true);
m_resetCurrentNodeFolder = false;
}
}
void ProjectTree::updateFromFocusResetProjectSingleShot()
{
updateFromFocus(true);
m_resetCurrentNodeProject = false;
}
void ProjectTree::updateFromDocumentManagerSingleShot()
{
if (Utils::anyOf(m_projectTreeWidgets, &ProjectTreeWidget::hasFocus))
return;
updateFromDocumentManager();
}