Commit 4943510b authored by Daniel Teske's avatar Daniel Teske
Browse files

Completely rework currentNode/currentProject handling



Centralize the handling inside a new class ProjectTree.
React to moving focus and remove most special handling.

This properly fixes the linked task.

Task-number: QTCREATORBUG-13357
Change-Id: I6b06aa32b1e4305ec8a6d432857b302585d8734b
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent 042ef1ae
......@@ -43,7 +43,7 @@
#include <projectexplorer/target.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <proparser/profileevaluator.h>
......@@ -107,7 +107,7 @@ void AndroidQtVersion::addToEnvironment(const ProjectExplorer::Kit *k, Utils::En
env.set(QLatin1String("ANDROID_NDK_HOST"), AndroidConfigurations::currentConfig().toolchainHost());
env.set(QLatin1String("ANDROID_NDK_ROOT"), AndroidConfigurations::currentConfig().ndkLocation().toUserOutput());
Project *project = ProjectExplorerPlugin::instance()->currentProject();
Project *project = ProjectTree::currentProject();
if (!project || !project->activeTarget()
|| QtSupport::QtKitInformation::qtVersion(k)->type() != QLatin1String(Constants::ANDROIDQT))
return;
......
......@@ -49,7 +49,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <cppeditor/cppeditorconstants.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/project.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
......@@ -108,7 +108,7 @@ void ArtisticStyle::formatFile()
if (m_settings->useOtherFiles()) {
if (const ProjectExplorer::Project *project
= ProjectExplorer::ProjectExplorerPlugin::currentProject()) {
= ProjectExplorer::ProjectTree::currentProject()) {
const QStringList files = project->files(ProjectExplorer::Project::AllFiles);
for (int i = 0, total = files.size(); i < total; ++i) {
const QString &file = files.at(i);
......
......@@ -49,7 +49,7 @@
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <cppeditor/cppeditorconstants.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/project.h>
#include <utils/fileutils.h>
......@@ -107,7 +107,7 @@ void Uncrustify::formatFile()
if (m_settings->useOtherFiles()) {
if (const ProjectExplorer::Project *project
= ProjectExplorer::ProjectExplorerPlugin::currentProject()) {
= ProjectExplorer::ProjectTree::currentProject()) {
const QStringList files = project->files(ProjectExplorer::Project::AllFiles);
for (int i = 0, total = files.size(); i < total; ++i) {
const QString &file = files.at(i);
......
......@@ -54,7 +54,7 @@
#include <coreplugin/mimedatabase.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/locator/commandlocator.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/project.h>
#include <projectexplorer/iprojectmanager.h>
#include <utils/algorithm.h>
......@@ -453,8 +453,8 @@ bool ClearCasePlugin::initialize(const QStringList & /*arguments */, QString *er
m_settings.fromSettings(ICore::settings());
// update view name when changing active project
connect(ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
this, SLOT(projectChanged(ProjectExplorer::Project*)));
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &ClearCasePlugin::projectChanged);
addAutoReleasedObject(new SettingsPage);
......@@ -2055,7 +2055,7 @@ void ClearCasePlugin::updateIndex()
{
QTC_ASSERT(currentState().hasTopLevel(), return);
ProgressManager::cancelTasks(ClearCase::Constants::TASK_INDEX);
Project *project = ProjectExplorerPlugin::currentProject();
Project *project = ProjectTree::currentProject();
if (!project)
return;
m_checkInAllAction->setEnabled(false);
......
......@@ -41,6 +41,7 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <QDateTime>
using namespace CMakeProjectManager::Internal;
......@@ -67,7 +68,7 @@ CMakeManager::CMakeManager(CMakeSettingsPage *cmakeSettingsPage)
command->setAttribute(Core::Command::CA_Hide);
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_DEPLOY);
connect(m_runCMakeAction, &QAction::triggered, [this]() {
runCMake(ProjectExplorer::ProjectExplorerPlugin::currentProject());
runCMake(ProjectExplorer::ProjectTree::currentProject());
});
m_runCMakeActionContextMenu = new QAction(QIcon(), tr("Run CMake"), this);
......
......@@ -36,7 +36,7 @@
#include <projectexplorer/editorconfiguration.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <utils/qtcassert.h>
#include <utils/settingsutils.h>
......@@ -210,7 +210,7 @@ static void configureOverviewWithCodeStyleSettings(CPlusPlus::Overview &overview
CPlusPlus::Overview CppCodeStyleSettings::currentProjectCodeStyleOverview()
{
ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::currentProject();
ProjectExplorer::Project *project = ProjectExplorer::ProjectTree::currentProject();
if (!project)
return currentGlobalCodeStyleOverview();
......
......@@ -53,6 +53,7 @@
#include <coreplugin/jsexpander.h>
#include <coreplugin/vcsmanager.h>
#include <cppeditor/cppeditorconstants.h>
#include <projectexplorer/projecttree.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
......@@ -431,7 +432,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
}
// Find files in the current project
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectExplorerPlugin::currentProject();
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject();
if (currentProject) {
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
currentProject);
......
......@@ -93,6 +93,7 @@
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/projectexplorersettings.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
......@@ -481,7 +482,7 @@ public:
bool DummyEngine::hasCapability(unsigned cap) const
{
// This can only be a first approximation of what to expect when running.
Project *project = ProjectExplorerPlugin::currentProject();
Project *project = ProjectTree::currentProject();
if (!project)
return 0;
Target *target = project->activeTarget();
......@@ -3437,7 +3438,7 @@ void DebuggerPlugin::extensionsInitialized()
void DebuggerPluginPrivate::testLoadProject(const QString &proFile, const TestCallBack &cb)
{
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::currentProjectChanged,
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &DebuggerPluginPrivate::testProjectLoaded);
m_testCallbacks.append(cb);
......
......@@ -39,7 +39,7 @@
#include <projectexplorer/target.h>
#include <projectexplorer/project.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/localapplicationrunconfiguration.h>
......@@ -88,7 +88,7 @@ UnstartedAppWatcherDialog::UnstartedAppWatcherDialog(QWidget *parent)
m_kitChooser->populate();
m_kitChooser->setVisible(true);
Project *project = ProjectExplorerPlugin::currentProject();
Project *project = ProjectTree::currentProject();
if (project && project->activeTarget() && project->activeTarget()->kit())
m_kitChooser->setCurrentKitId(project->activeTarget()->kit()->id());
else if (KitManager::defaultKit())
......@@ -163,7 +163,7 @@ void UnstartedAppWatcherDialog::selectExecutable()
{
QString path;
Project *project = ProjectExplorerPlugin::currentProject();
Project *project = ProjectTree::currentProject();
if (project && project->activeTarget() && project->activeTarget()->activeRunConfiguration()) {
......
......@@ -29,7 +29,7 @@
****************************************************************************/
#include "currentprojectfilter.h"
#include "projectexplorer.h"
#include "projecttree.h"
#include "project.h"
#include <utils/algorithm.h>
......@@ -49,8 +49,8 @@ CurrentProjectFilter::CurrentProjectFilter()
setShortcutString(QString(QLatin1Char('p')));
setIncludedByDefault(false);
connect(ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
this, SLOT(currentProjectChanged(ProjectExplorer::Project*)));
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &CurrentProjectFilter::currentProjectChanged);
}
void CurrentProjectFilter::markFilesAsOutOfDate()
......
......@@ -30,8 +30,8 @@
#include "currentprojectfind.h"
#include "projectexplorer.h"
#include "project.h"
#include "projecttree.h"
#include "session.h"
#include <utils/qtcassert.h>
......@@ -46,8 +46,8 @@ using namespace TextEditor;
CurrentProjectFind::CurrentProjectFind()
{
connect(ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project*)),
this, SLOT(handleProjectChanged()));
connect(ProjectTree::instance(), &ProjectTree::currentProjectChanged,
this, &CurrentProjectFind::handleProjectChanged);
connect(SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)),
this, SLOT(handleProjectChanged()));
connect(SessionManager::instance(), SIGNAL(projectAdded(ProjectExplorer::Project*)),
......@@ -66,12 +66,12 @@ QString CurrentProjectFind::displayName() const
bool CurrentProjectFind::isEnabled() const
{
return ProjectExplorerPlugin::currentProject() != 0 && BaseFileFind::isEnabled();
return ProjectTree::currentProject() != 0 && BaseFileFind::isEnabled();
}
QVariant CurrentProjectFind::additionalParameters() const
{
Project *project = ProjectExplorerPlugin::currentProject();
Project *project = ProjectTree::currentProject();
if (project && project->document())
return qVariantFromValue(project->projectFilePath().toString());
return QVariant();
......@@ -92,8 +92,8 @@ Utils::FileIterator *CurrentProjectFind::files(const QStringList &nameFilters,
QString CurrentProjectFind::label() const
{
QTC_ASSERT(ProjectExplorerPlugin::currentProject(), return QString());
return tr("Project \"%1\":").arg(ProjectExplorerPlugin::currentProject()->displayName());
QTC_ASSERT(ProjectTree::currentProject(), return QString());
return tr("Project \"%1\":").arg(ProjectTree::currentProject()->displayName());
}
void CurrentProjectFind::handleProjectChanged()
......
......@@ -101,6 +101,11 @@ void FindNodesForFileVisitor::visitFolderNode(FolderNode *node)
}
}
void FindNodesForFileVisitor::visitSessionNode(SessionNode *node)
{
visitFolderNode(node);
}
/*!
\class FindAllFilesVisitor
......
......@@ -64,6 +64,7 @@ public:
void visitProjectNode(ProjectNode *node);
void visitFolderNode(FolderNode *node);
void visitSessionNode(SessionNode *node);
private:
QString m_path;
QList<Node*> m_nodes;
......
......@@ -76,12 +76,6 @@ public:
Q_SLOT void openProjectWelcomePage(const QString &fileName);
static void unloadProject(Project *project);
static Project *currentProject();
static Node *currentNode();
static void setCurrentFile(Project *project, const QString &file);
static void setCurrentNode(Node *node);
static bool saveModifiedFiles();
static void showContextMenu(QWidget *view, const QPoint &globalPos, Node *node);
......@@ -98,7 +92,7 @@ public:
static void showRunErrorMessage(const QString &errorMessage);
// internal public for FlatModel
static void renameFile(Node *node, const QString &to);
static void renameFile(Node *node, const QString &newFilePath);
static QStringList projectFilePatterns();
static bool coreAboutToClose();
static QList<QPair<QString, QString> > recentProjects();
......@@ -133,8 +127,6 @@ signals:
// or the file list of a specific project has changed.
void fileListChanged();
void currentProjectChanged(ProjectExplorer::Project *project);
void currentNodeChanged(ProjectExplorer::Node *node, ProjectExplorer::Project *project);
void aboutToExecuteProject(ProjectExplorer::Project *project, RunMode runMode);
void recentProjectsChanged();
......@@ -203,12 +195,7 @@ private slots:
void updateUnloadProjectMenu();
void openTerminalHere();
// for keeping current node / current project up to date
void invalidateProject(ProjectExplorer::Project *project);
void foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode*> &);
void filesAboutToBeRemoved(FolderNode *, const QList<FileNode*> &);
void setCurrentFile(const QString &filePath);
void runControlFinished();
......@@ -225,10 +212,8 @@ private slots:
void loadCustomWizards();
void updateWelcomePage();
void updateExternalFileWarning();
void updateActions();
void updateContext();
void runConfigurationConfigurationFinished();
void showRenameFileError();
......
......@@ -152,7 +152,8 @@ HEADERS += projectexplorer.h \
propertiespanel.h \
panelswidget.h \
projectwelcomepage.h \
projectpanelfactory.h
projectpanelfactory.h \
projecttree.h
SOURCES += projectexplorer.cpp \
abi.cpp \
......@@ -290,7 +291,8 @@ SOURCES += projectexplorer.cpp \
propertiespanel.cpp \
panelswidget.cpp \
projectwelcomepage.cpp \
projectpanelfactory.cpp
projectpanelfactory.cpp \
projecttree.cpp
FORMS += processstep.ui \
editorsettingspropertiespage.ui \
......
......@@ -352,7 +352,14 @@ bool FlatModel::setData(const QModelIndex &index, const QVariant &value, int rol
if (role != Qt::EditRole)
return false;
ProjectExplorerPlugin::renameFile(nodeForIndex(index), value.toString());
Node *node = nodeForIndex(index);
QString orgFilePath = QFileInfo(node->path()).absoluteFilePath();
QString dir = QFileInfo(orgFilePath).absolutePath();
QString newFilePath = dir + QLatin1Char('/') + value.toString();
ProjectExplorerPlugin::renameFile(node, newFilePath);
emit renamed(orgFilePath, newFilePath);
return true;
}
......
......@@ -78,6 +78,9 @@ public:
bool projectFilterEnabled();
bool generatedFilesFilterEnabled();
signals:
void renamed(const QString &oldName, const QString &newName);
public slots:
void setProjectFilterEnabled(bool filter);
void setGeneratedFilesFilterEnabled(bool filter);
......
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "projecttree.h"
#include "projecttreewidget.h"
#include "session.h"
#include "project.h"
#include "projectnodes.h"
#include <utils/algorithm.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/infobar.h>
#include <coreplugin/vcsmanager.h>
#include <QApplication>
namespace {
const char EXTERNAL_FILE_WARNING[] = "ExternalFile";
}
using namespace ProjectExplorer;
using namespace Internal;
ProjectTree *ProjectTree::s_instance = 0;
ProjectTree::ProjectTree(QObject *parent)
: QObject(parent),
m_currentNode(0),
m_currentProject(0),
m_resetCurrentNodeFolder(0),
m_resetCurrentNodeFile(0),
m_resetCurrentNodeProject(0)
{
s_instance = this;
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);
NodesWatcher *watcher = new NodesWatcher(this);
SessionManager::sessionNode()->registerWatcher(watcher);
connect(watcher, &NodesWatcher::foldersAboutToBeRemoved,
this, &ProjectTree::foldersAboutToBeRemoved);
connect(watcher, &NodesWatcher::foldersRemoved,
this, &ProjectTree::foldersRemoved);
connect(watcher, &NodesWatcher::filesAboutToBeRemoved,
this, &ProjectTree::filesAboutToBeRemoved);
connect(watcher, &NodesWatcher::filesRemoved,
this, &ProjectTree::filesRemoved);
connect(watcher, &NodesWatcher::foldersAdded,
this, &ProjectTree::nodesAdded);
connect(watcher, &NodesWatcher::filesAdded,
this, &ProjectTree::nodesAdded);
connect(qApp, &QApplication::focusChanged,
this, &ProjectTree::focusChanged);
}
ProjectTree *ProjectTree::instance()
{
return s_instance;
}
Project *ProjectTree::currentProject()
{
return s_instance->m_currentProject;
}
Node *ProjectTree::currentNode()
{
return s_instance->m_currentNode;
}
void ProjectTree::registerWidget(ProjectTreeWidget *widget)
{
s_instance->m_projectTreeWidgets.append(widget);
if (hasFocus(widget))
s_instance->updateFromProjectTreeWidget(widget);
}
void ProjectTree::unregisterWidget(ProjectTreeWidget *widget)
{
s_instance->m_projectTreeWidgets.removeOne(widget);
if (hasFocus(widget))
s_instance->updateFromDocumentManager();
}
void ProjectTree::nodeChanged(ProjectTreeWidget *widget)
{
if (hasFocus(widget))
s_instance->updateFromProjectTreeWidget(widget);
}
void ProjectTree::focusChanged()
{
s_instance->updateFromFocus();
}
bool ProjectTree::editorHasFocus()
{
Core::IEditor *editor = Core::EditorManager::currentEditor();
if (!editor)
return false;
QWidget *widget = editor->widget();
if (!widget)
return false;
widget = widget->focusWidget();
if (!widget)
return false;
return widget->hasFocus();
}
void ProjectTree::updateFromFocus(bool invalidCurrentNode)
{
ProjectTreeWidget *focus = Utils::findOrDefault(s_instance->m_projectTreeWidgets,
&ProjectTree::hasFocus);
if (focus)
updateFromProjectTreeWidget(focus);
else if (editorHasFocus())
updateFromDocumentManager(invalidCurrentNode);
}
void ProjectTree::updateFromProjectTreeWidget(ProjectTreeWidget *widget)
{
ProjectExplorer::Node *currentNode = widget->currentNode();
ProjectExplorer::Project *project = projectForNode(currentNode);
update(currentNode, project);
}
void ProjectTree::documentManagerCurrentFileChanged()
{
if (editorHasFocus())
updateFromDocumentManager();
}
Project *ProjectTree::projectForNode(Node *node)
{
if (!node)
return 0;
FolderNode *rootProjectNode = qobject_cast<FolderNode*>(node);
if (!rootProjectNode)
rootProjectNode = node->parentFolderNode();
while (rootProjectNode && rootProjectNode->parentFolderNode() != SessionManager::sessionNode())
rootProjectNode = rootProjectNode->parentFolderNode();
Q_ASSERT(rootProjectNode);
return Utils::findOrDefault(SessionManager::projects(), Utils::equal(&Project::rootProjectNode, rootProjectNode));
}
void ProjectTree::updateFromDocumentManager(bool invalidCurrentNode)
{
const QString &fileName = Core::DocumentManager::currentFile();
ProjectExplorer::Node *currentNode = 0;
if (!invalidCurrentNode && m_currentNode && m_currentNode->path() == fileName)
currentNode = m_currentNode;
else
currentNode = ProjectTreeWidget::nodeForFile(fileName);
ProjectExplorer::Project *project = projectForNode(currentNode);
update(currentNode, project);
foreach (ProjectTreeWidget *widget, m_projectTreeWidgets)
widget->sync(currentNode);
}
void ProjectTree::update(Node *node, Project *project)
{
if (project != m_currentProject) {