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

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);
......
This diff is collapsed.
/****************************************************************************
**
** 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.
**
****************************************************************************/
#ifndef PROJECTTREE_H
#define PROJECTTREE_H
#include "projectexplorer_export.h"
#include <coreplugin/icontext.h>
#include <QObject>
namespace ProjectExplorer {
class FileNode;
class FolderNode;
class Node;
class Project;
class ProjectNode;
namespace Internal {
class ProjectTreeWidget;
}
class PROJECTEXPLORER_EXPORT ProjectTree : public QObject
{
Q_OBJECT
public:
explicit ProjectTree(QObject *parent = 0);
static ProjectTree *instance();
static Project *currentProject();
static Node *currentNode();
// Integration with ProjectTreeWidget
static void registerWidget(ProjectExplorer::Internal::ProjectTreeWidget *widget);
static void unregisterWidget(ProjectExplorer::Internal::ProjectTreeWidget *widget);
static void nodeChanged(ProjectExplorer::Internal::ProjectTreeWidget *widget);
static void focusChanged();
static Project *projectForNode(Node *node);
signals:
void currentProjectChanged(ProjectExplorer::Project *project);
void currentNodeChanged(ProjectExplorer::Node *node, ProjectExplorer::Project *project);
private:
void updateFromProjectTreeWidget(ProjectExplorer::Internal::ProjectTreeWidget *widget);
void documentManagerCurrentFileChanged();
void updateFromDocumentManager(bool invalidCurrentNode = false);
void update(Node *node, Project *project);
void updateContext();
// slots to kepp the current node/current project from deletion
void foldersAboutToBeRemoved(FolderNode *, const QList<FolderNode *> &list);
void foldersRemoved();
void filesAboutToBeRemoved(FolderNode *, const QList<FileNode *> &list);
void filesRemoved();
void aboutToRemoveProject(ProjectExplorer::Project *project);
void projectRemoved();
void nodesAdded();
void updateFromFocus(bool invalidCurrentNode = false);
void updateExternalFileWarning();
bool editorHasFocus();
static bool hasFocus(Internal::ProjectTreeWidget *widget);
static ProjectTree *s_instance;
QList<ProjectExplorer::Internal::ProjectTreeWidget *> m_projectTreeWidgets;
Node *m_currentNode;
Project *m_currentProject;
bool m_resetCurrentNodeFolder;
bool m_resetCurrentNodeFile;
bool m_resetCurrentNodeProject;
Core::Context m_lastProjectContext;
};
}
#endif // PROJECTTREE_H
......@@ -35,9 +35,11 @@
#include "project.h"
#include "session.h"
#include "projectmodels.h"
#include "projecttree.h"
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
......@@ -127,6 +129,7 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
m_view->setModel(m_model);
m_view->setItemDelegate(new ProjectTreeItemDelegate(this));
setFocusProxy(m_view);
m_view->installEventFilter(this);
initView();
QVBoxLayout *layout = new QVBoxLayout();
......@@ -149,6 +152,8 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
// connections
connect(m_model, SIGNAL(modelReset()),
this, SLOT(initView()));
connect(m_model, &FlatModel::renamed,
this, &ProjectTreeWidget::renamed);
connect(m_view, SIGNAL(activated(QModelIndex)),
this, SLOT(openItem(QModelIndex)));
connect(m_view->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
......@@ -179,11 +184,13 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent)
setAutoSynchronization(true);
m_projectTreeWidgets << this;
ProjectTree::registerWidget(this);
}
ProjectTreeWidget::~ProjectTreeWidget()
{
m_projectTreeWidgets.removeOne(this);
ProjectTree::unregisterWidget(this);
}
// returns how many nodes need to be expanded to make node visible
......@@ -208,21 +215,32 @@ int ProjectTreeWidget::expandedCount(Node *node)
return count;
}
void ProjectTreeWidget::rowsInserted(const QModelIndex &parent, int, int)
void ProjectTreeWidget::rowsInserted(const QModelIndex &parent, int start, int end)
{
const QString &path = m_model->nodeForIndex(parent)->path();
if (m_toExpand.contains(path)) {
m_view->expand(parent);
m_toExpand.remove(path);
}
int i = start;
while (i <= end) {
QModelIndex idx = m_model->index(i, 0, parent);
Node *n = m_model->nodeForIndex(idx);
if (n && n->path() == m_delayedRename) {
m_view->setCurrentIndex(idx);
m_delayedRename.clear();
break;
}
++i;
}
}
Node *ProjectTreeWidget::nodeForFile(const QString &fileName, Project *project)
Node *ProjectTreeWidget::nodeForFile(const QString &fileName)
{
Node *bestNode = 0;
int bestNodeExpandCount = INT_MAX;
foreach (Node *node, SessionManager::nodesForFile(fileName, project)) {
foreach (Node *node, SessionManager::nodesForFile(fileName)) {
if (!bestNode) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node->parentFolderNode());
......@@ -304,7 +322,7 @@ bool ProjectTreeWidget::autoSynchronization() const
return m_autoSync;
}
void ProjectTreeWidget::setAutoSynchronization(bool sync, bool syncNow)
void ProjectTreeWidget::setAutoSynchronization(bool sync)
{
m_toggleSync->setChecked(sync);
if (sync == m_autoSync)
......@@ -314,14 +332,12 @@ void ProjectTreeWidget::setAutoSynchronization(bool sync, bool syncNow)
if (debug)
qDebug() << (m_autoSync ? "Enabling auto synchronization" : "Disabling auto synchronization");
if (m_autoSync) {
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::currentNodeChanged,
this, &ProjectTreeWidget::setCurrentItem);
if (syncNow)
setCurrentItem(ProjectExplorerPlugin::currentNode(), ProjectExplorerPlugin::currentProject());
} else {
disconnect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::currentNodeChanged,
this, &ProjectTreeWidget::setCurrentItem);
// sync from document manager
const QString &fileName = Core::DocumentManager::currentFile();
if (!currentNode() || currentNode()->path() != fileName)
setCurrentItem(ProjectTreeWidget::nodeForFile(fileName));
}
}
......@@ -332,19 +348,27 @@ void ProjectTreeWidget::collapseAll()
void ProjectTreeWidget::editCurrentItem()
{
m_delayedRename.clear();
if (m_view->selectionModel()->currentIndex().isValid())
m_view->edit(m_view->selectionModel()->currentIndex());
}
void ProjectTreeWidget::setCurrentItem(Node *node, Project *project)
{
if (debug)
qDebug() << "ProjectTreeWidget::setCurrentItem(" << (project ? project->displayName() : QLatin1String("0"))
<< ", " << (node ? node->path() : QLatin1String("0")) << ")";
if (!project)
return;
void ProjectTreeWidget::renamed(const QString &oldPath, const QString &newPath)
{
Q_UNUSED(oldPath);
if (!currentNode() || currentNode()->path() != newPath) {