summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/utils/treemodel.h3
-rw-r--r--src/plugins/projectexplorer/expanddata.cpp10
-rw-r--r--src/plugins/projectexplorer/expanddata.h4
-rw-r--r--src/plugins/projectexplorer/projectmodels.cpp680
-rw-r--r--src/plugins/projectexplorer/projectmodels.h93
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp67
-rw-r--r--src/plugins/projectexplorer/projectnodes.h17
-rw-r--r--src/plugins/projectexplorer/projecttree.cpp161
-rw-r--r--src/plugins/projectexplorer/projecttree.h62
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.cpp138
-rw-r--r--src/plugins/projectexplorer/projecttreewidget.h13
-rw-r--r--src/plugins/projectexplorer/session.cpp16
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.cpp9
13 files changed, 223 insertions, 1050 deletions
diff --git a/src/libs/utils/treemodel.h b/src/libs/utils/treemodel.h
index 6532caaf1e..ba791c1cf8 100644
--- a/src/libs/utils/treemodel.h
+++ b/src/libs/utils/treemodel.h
@@ -249,13 +249,16 @@ public:
explicit TreeModel(QObject *parent = 0) : BaseTreeModel(new RootItem, parent) {}
explicit TreeModel(RootItem *root, QObject *parent = 0) : BaseTreeModel(root, parent) {}
+ using BaseTreeModel::canFetchMore;
using BaseTreeModel::clear;
using BaseTreeModel::columnCount;
using BaseTreeModel::data;
using BaseTreeModel::destroyItem;
+ using BaseTreeModel::fetchMore;
using BaseTreeModel::hasChildren;
using BaseTreeModel::index;
using BaseTreeModel::indexForItem;
+ using BaseTreeModel::parent;
using BaseTreeModel::rowCount;
using BaseTreeModel::setData;
using BaseTreeModel::setHeader;
diff --git a/src/plugins/projectexplorer/expanddata.cpp b/src/plugins/projectexplorer/expanddata.cpp
index 9e940aeb27..2322735a76 100644
--- a/src/plugins/projectexplorer/expanddata.cpp
+++ b/src/plugins/projectexplorer/expanddata.cpp
@@ -37,9 +37,15 @@ bool ExpandData::operator==(const ExpandData &other) const
return path == other.path && displayName == other.displayName;
}
-QStringList ExpandData::toStringList() const
+ExpandData ExpandData::fromSettings(const QVariant &v)
{
- return { path, displayName };
+ QStringList list = v.toStringList();
+ return list.size() == 2 ? ExpandData(list.at(0), list.at(1)) : ExpandData();
+}
+
+QVariant ExpandData::toSettings() const
+{
+ return QVariant::fromValue(QStringList({ path, displayName }));
}
int ProjectExplorer::Internal::qHash(const ExpandData &data)
diff --git a/src/plugins/projectexplorer/expanddata.h b/src/plugins/projectexplorer/expanddata.h
index 090007b619..9d6a656449 100644
--- a/src/plugins/projectexplorer/expanddata.h
+++ b/src/plugins/projectexplorer/expanddata.h
@@ -38,7 +38,9 @@ public:
ExpandData() = default;
ExpandData(const QString &path_, const QString &displayName_);
bool operator==(const ExpandData &other) const;
- QStringList toStringList() const;
+
+ static ExpandData fromSettings(const QVariant &v);
+ QVariant toSettings() const;
QString path;
QString displayName;
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index e597e23bf7..c4fb0e6e59 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -29,6 +29,7 @@
#include "projectnodes.h"
#include "projectexplorer.h"
#include "projecttree.h"
+#include "session.h"
#include <coreplugin/fileiconprovider.h>
#include <utils/algorithm.h>
@@ -40,15 +41,13 @@
#include <QMimeData>
#include <QLoggingCategory>
+using namespace Utils;
+
namespace ProjectExplorer {
using namespace Internal;
-namespace {
-
-// sorting helper function
-
-bool sortNodes(Node *n1, Node *n2)
+static bool sortNodes(const Node *n1, const Node *n2)
{
if (n1->priority() > n2->priority())
return true;
@@ -66,78 +65,45 @@ bool sortNodes(Node *n1, Node *n2)
return n1 < n2; // sort by pointer value
}
-} // namespace anon
+static bool sortWrapperNodes(const WrapperNode *w1, const WrapperNode *w2)
+{
+ return sortNodes(w1->m_node, w2->m_node);
+}
-FlatModel::FlatModel(SessionNode *rootNode, QObject *parent) : QAbstractItemModel(parent),
- m_rootNode(rootNode)
+FlatModel::FlatModel(QObject *parent)
+ : TreeModel<WrapperNode, WrapperNode>(new WrapperNode(SessionManager::sessionNode()), parent)
{
+ m_timer.setInterval(200);
+ connect(&m_timer, &QTimer::timeout, this, &FlatModel::doUpdate);
+
ProjectTree *tree = ProjectTree::instance();
+ connect(tree, &ProjectTree::dataChanged, this, &FlatModel::update);
+ connect(tree, &ProjectTree::nodeUpdated, this, &FlatModel::nodeUpdated);
- connect(tree, &ProjectTree::aboutToChangeShowInSimpleTree,
- this, &FlatModel::aboutToShowInSimpleTreeChanged);
-
- connect(tree, &ProjectTree::showInSimpleTreeChanged,
- this, &FlatModel::showInSimpleTreeChanged);
-
- connect(tree, &ProjectTree::foldersAboutToBeAdded,
- this, &FlatModel::foldersAboutToBeAdded);
- connect(tree, &ProjectTree::foldersAdded,
- this, &FlatModel::foldersAdded);
-
- connect(tree, &ProjectTree::foldersAboutToBeRemoved,
- this, &FlatModel::foldersAboutToBeRemoved);
- connect(tree, &ProjectTree::foldersRemoved,
- this, &FlatModel::foldersRemoved);
-
- connect(tree, &ProjectTree::filesAboutToBeAdded,
- this, &FlatModel::filesAboutToBeAdded);
- connect(tree, &ProjectTree::filesAdded,
- this, &FlatModel::filesAdded);
-
- connect(tree, &ProjectTree::filesAboutToBeRemoved,
- this, &FlatModel::filesAboutToBeRemoved);
- connect(tree, &ProjectTree::filesRemoved,
- this, &FlatModel::filesRemoved);
-
- connect(tree, &ProjectTree::nodeSortKeyAboutToChange,
- this, &FlatModel::nodeSortKeyAboutToChange);
- connect(tree, &ProjectTree::nodeSortKeyChanged,
- this, &FlatModel::nodeSortKeyChanged);
-
- connect(tree, &ProjectTree::nodeUpdated,
- this, &FlatModel::nodeUpdated);
-}
-
-QModelIndex FlatModel::index(int row, int column, const QModelIndex &parent) const
-{
- QModelIndex result;
- if (!parent.isValid() && row == 0 && column == 0) { // session
- result = createIndex(0, 0, m_rootNode);
- } else if (parent.isValid() && column == 0) {
- FolderNode *parentNode = nodeForIndex(parent)->asFolderNode();
- Q_ASSERT(parentNode);
- QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
- if (it == m_childNodes.constEnd()) {
- fetchMore(parentNode);
- it = m_childNodes.constFind(parentNode);
- }
+ SessionManager *sm = SessionManager::instance();
+ connect(sm, &SessionManager::projectRemoved, this, &FlatModel::update);
+ connect(sm, &SessionManager::startupProjectChanged, this, &FlatModel::startupProjectChanged);
- if (row < it.value().size())
- result = createIndex(row, 0, it.value().at(row));
- }
-// qDebug() << "index of " << row << column << parent.data(Project::FilePathRole) << " is " << result.data(Project::FilePathRole);
- return result;
+ connect(sm, &SessionManager::sessionLoaded, this, &FlatModel::loadExpandData);
+ connect(sm, &SessionManager::aboutToSaveSession, this, &FlatModel::saveExpandData);
+ connect(sm, &SessionManager::projectAdded, this, &FlatModel::handleProjectAdded);
}
-QModelIndex FlatModel::parent(const QModelIndex &idx) const
+void FlatModel::setView(QTreeView *view)
{
- QModelIndex parentIndex;
- if (Node *node = nodeForIndex(idx)) {
- FolderNode *parentNode = visibleFolderNode(node->parentFolderNode());
- if (parentNode)
- return indexForNode(parentNode);
- }
- return parentIndex;
+ QTC_CHECK(!m_view);
+ m_view = view;
+ connect(m_view, &QTreeView::expanded, this, &FlatModel::onExpanded);
+ connect(m_view, &QTreeView::collapsed, this, &FlatModel::onCollapsed);
+}
+
+void FlatModel::startupProjectChanged(Project *project)
+{
+ ProjectNode *projectNode = project ? project->rootProjectNode() : nullptr;
+ if (m_startupProject == projectNode)
+ return;
+ m_startupProject = projectNode;
+ layoutChanged();
}
QVariant FlatModel::data(const QModelIndex &index, int role) const
@@ -149,7 +115,6 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
switch (role) {
case Qt::DisplayRole: {
QString name = node->displayName();
-
if (node->nodeType() == NodeType::Project
&& node->parentFolderNode()
&& node->parentFolderNode()->nodeType() == NodeType::Session) {
@@ -207,7 +172,7 @@ Qt::ItemFlags FlatModel::flags(const QModelIndex &index) const
// We control the only view, and that one does the checks
Qt::ItemFlags f = Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsDragEnabled;
if (Node *node = nodeForIndex(index)) {
- if (node == m_rootNode)
+ if (node->asSessionNode())
return 0; // no flags for session node...
if (!node->asProjectNode()) {
// either folder or file node
@@ -235,142 +200,116 @@ bool FlatModel::setData(const QModelIndex &index, const QVariant &value, int rol
return true;
}
-int FlatModel::rowCount(const QModelIndex &parent) const
+void FlatModel::update()
{
- int rows = 0;
- if (!parent.isValid()) {
- rows = 1;
- } else {
- FolderNode *folderNode = nodeForIndex(parent)->asFolderNode();
- if (folderNode && m_childNodes.contains(folderNode))
- rows = m_childNodes.value(folderNode).size();
- }
- return rows;
+ m_timer.start(300);
}
-int FlatModel::columnCount(const QModelIndex &/*parent*/) const
+void FlatModel::doUpdate()
{
- return 1;
+ m_timer.stop();
+ rebuildModel();
}
-bool FlatModel::hasChildren(const QModelIndex &parent) const
+void FlatModel::rebuildModel()
{
- if (!parent.isValid())
- return true;
-
- FolderNode *folderNode = nodeForIndex(parent)->asFolderNode();
- if (!folderNode)
- return false;
+ QSet<Node *> seen;
- QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(folderNode);
- if (it == m_childNodes.constEnd()) {
- fetchMore(folderNode);
- it = m_childNodes.constFind(folderNode);
+ rootItem()->removeChildren();
+ const QList<ProjectNode *> projectNodes = SessionManager::sessionNode()->projectNodes();
+ for (ProjectNode *projectNode : projectNodes) {
+ if (!seen.contains(projectNode))
+ addProjectNode(rootItem(), projectNode, &seen);
}
- return !it.value().isEmpty();
-}
-bool FlatModel::canFetchMore(const QModelIndex & parent) const
-{
- if (!parent.isValid()) {
- return false;
- } else {
- if (FolderNode *folderNode = nodeForIndex(parent)->asFolderNode())
- return !m_childNodes.contains(folderNode);
- else
- return false;
- }
+ forAllItems([this](WrapperNode *node) {
+ const QString path = node->m_node->filePath().toString();
+ const QString displayName = node->m_node->displayName();
+ ExpandData ed(path, displayName);
+ if (m_toExpand.contains(ed))
+ m_view->expand(node->index());
+ });
}
-void FlatModel::recursiveAddFolderNodes(FolderNode *startNode, QList<Node *> *list, const QSet<Node *> &blackList) const
+void FlatModel::onCollapsed(const QModelIndex &idx)
{
- foreach (FolderNode *folderNode, startNode->folderNodes()) {
- if (folderNode && !blackList.contains(folderNode))
- recursiveAddFolderNodesImpl(folderNode, list, blackList);
- }
+ m_toExpand.remove(expandDataForNode(nodeForIndex(idx)));
}
-void FlatModel::recursiveAddFolderNodesImpl(FolderNode *startNode, QList<Node *> *list, const QSet<Node *> &blackList) const
+void FlatModel::onExpanded(const QModelIndex &idx)
{
- if (!filter(startNode)) {
- if (!blackList.contains(startNode))
- list->append(startNode);
- } else {
- foreach (FolderNode *folderNode, startNode->folderNodes()) {
- if (folderNode && !blackList.contains(folderNode))
- recursiveAddFolderNodesImpl(folderNode, list, blackList);
- }
- }
+ m_toExpand.insert(expandDataForNode(nodeForIndex(idx)));
}
-void FlatModel::recursiveAddFileNodes(FolderNode *startNode, QList<Node *> *list, const QSet<Node *> &blackList) const
+ExpandData FlatModel::expandDataForNode(const Node *node) const
{
- foreach (FolderNode *subFolderNode, startNode->folderNodes()) {
- if (!blackList.contains(subFolderNode))
- recursiveAddFileNodes(subFolderNode, list, blackList);
- }
- foreach (Node *node, startNode->fileNodes()) {
- if (!blackList.contains(node) && !filter(node))
- list->append(node);
- }
+ QTC_ASSERT(node, return ExpandData());
+ const QString path = node->filePath().toString();
+ const QString displayName = node->displayName();
+ return ExpandData(path, displayName);
}
-QList<Node*> FlatModel::childNodes(FolderNode *parentNode, const QSet<Node*> &blackList) const
+void FlatModel::handleProjectAdded(Project *project)
{
- qCDebug(logger()) << " FlatModel::childNodes for " << parentNode->filePath();
- QList<Node*> nodeList;
-
- if (parentNode->nodeType() == NodeType::Session) {
- auto sessionNode = static_cast<SessionNode*>(parentNode);
- QList<ProjectNode*> projectList = sessionNode->projectNodes();
- for (int i = 0; i < projectList.size(); ++i) {
- if (!blackList.contains(projectList.at(i)))
- nodeList << projectList.at(i);
- }
- } else {
- recursiveAddFolderNodes(parentNode, &nodeList, blackList);
- recursiveAddFileNodes(parentNode, &nodeList, blackList + nodeList.toSet());
+ Node *node = project->rootProjectNode();
+ m_toExpand.insert(expandDataForNode(node));
+ if (WrapperNode *wrapper = wrapperForNode(node)) {
+ wrapper->forFirstLevelChildren([this](WrapperNode *child) {
+ m_toExpand.insert(expandDataForNode(child->m_node));
+ });
}
- Utils::sort(nodeList, sortNodes);
- qCDebug(logger()) << " found" << nodeList.size() << "nodes";
- return nodeList;
+ doUpdate();
}
-void FlatModel::fetchMore(FolderNode *folderNode) const
+void FlatModel::loadExpandData()
{
- Q_ASSERT(folderNode);
- Q_ASSERT(!m_childNodes.contains(folderNode));
-
- QList<Node*> nodeList = childNodes(folderNode);
- m_childNodes.insert(folderNode, nodeList);
+ const QList<QVariant> data = SessionManager::value("ProjectTree.ExpandData").value<QList<QVariant>>();
+ m_toExpand = Utils::transform<QSet>(data, [](const QVariant &v) { return ExpandData::fromSettings(v); });
+ m_toExpand.remove(ExpandData());
}
-void FlatModel::fetchMore(const QModelIndex &parent)
+void FlatModel::saveExpandData()
{
- FolderNode *folderNode = nodeForIndex(parent)->asFolderNode();
- Q_ASSERT(folderNode);
-
- fetchMore(folderNode);
+ // TODO if there are multiple ProjectTreeWidgets, the last one saves the data
+ QList<QVariant> data = Utils::transform<QList>(m_toExpand, &ExpandData::toSettings);
+ SessionManager::setValue(QLatin1String("ProjectTree.ExpandData"), data);
}
-void FlatModel::setStartupProject(ProjectNode *projectNode)
+void FlatModel::addProjectNode(WrapperNode *parent, ProjectNode *projectNode, QSet<Node *> *seen)
{
- if (m_startupProject != projectNode) {
- QModelIndex oldIndex = (m_startupProject ? indexForNode(m_startupProject) : QModelIndex());
- QModelIndex newIndex = (projectNode ? indexForNode(projectNode) : QModelIndex());
- m_startupProject = projectNode;
- if (oldIndex.isValid())
- emit dataChanged(oldIndex, oldIndex);
- if (newIndex.isValid())
- emit dataChanged(newIndex, newIndex);
+ seen->insert(projectNode);
+ auto node = new WrapperNode(projectNode);
+ parent->appendChild(node);
+ addFolderNode(node, projectNode, seen);
+ const QList<ProjectNode *> subProjectNodes = projectNode->projectNodes();
+ for (ProjectNode *subProjectNode : subProjectNodes) {
+ if (!seen->contains(subProjectNode))
+ addProjectNode(node, subProjectNode, seen);
}
+ node->sortChildren(&sortWrapperNodes);
}
-void FlatModel::reset()
+void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<Node *> *seen)
{
- beginResetModel();
- m_childNodes.clear();
- endResetModel();
+ const QList<FolderNode *> subFolderNodes = folderNode->folderNodes();
+ for (FolderNode *subFolderNode : subFolderNodes) {
+ if (!filter(subFolderNode) && !seen->contains(subFolderNode)) {
+ seen->insert(subFolderNode);
+ auto node = new WrapperNode(subFolderNode);
+ parent->appendChild(node);
+ addFolderNode(node, subFolderNode, seen);
+ node->sortChildren(&sortWrapperNodes);
+ } else {
+ addFolderNode(parent, subFolderNode, seen);
+ }
+ }
+ const QList<FileNode *> fileNodes = folderNode->fileNodes();
+ for (FileNode *fileNode : fileNodes) {
+ if (!filter(fileNode) && !seen->contains(fileNode)) {
+ seen->insert(fileNode);
+ parent->appendChild(new WrapperNode(fileNode));
+ }
+ }
}
Qt::DropActions FlatModel::supportedDragActions() const
@@ -395,32 +334,17 @@ QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const
return data;
}
-QModelIndex FlatModel::indexForNode(const Node *node_) const
+WrapperNode *FlatModel::wrapperForNode(const Node *node) const
{
- // We assume that we are only called for nodes that are represented
-
- // we use non-const pointers internally
- auto node = const_cast<Node*>(node_);
- if (!node)
- return QModelIndex();
-
- if (node == m_rootNode)
- return createIndex(0, 0, m_rootNode);
-
- FolderNode *parentNode = visibleFolderNode(node->parentFolderNode());
+ return findNonRooItem([this, node](WrapperNode *item) {
+ return item->m_node == node;
+ });
+}
- // Do we have the parent mapped?
- QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
- if (it == m_childNodes.constEnd()) {
- fetchMore(parentNode);
- it = m_childNodes.constFind(parentNode);
- }
- if (it != m_childNodes.constEnd()) {
- const int row = it.value().indexOf(node);
- if (row != -1)
- return createIndex(row, 0, node);
- }
- return QModelIndex();
+QModelIndex FlatModel::indexForNode(const Node *node) const
+{
+ WrapperNode *wrapper = wrapperForNode(node);
+ return wrapper ? indexForItem(wrapper) : QModelIndex();
}
void FlatModel::setProjectFilterEnabled(bool filter)
@@ -428,13 +352,13 @@ void FlatModel::setProjectFilterEnabled(bool filter)
if (filter == m_filterProjects)
return;
m_filterProjects = filter;
- reset();
+ rebuildModel();
}
void FlatModel::setGeneratedFilesFilterEnabled(bool filter)
{
m_filterGeneratedFiles = filter;
- reset();
+ rebuildModel();
}
bool FlatModel::projectFilterEnabled()
@@ -449,28 +373,8 @@ bool FlatModel::generatedFilesFilterEnabled()
Node *FlatModel::nodeForIndex(const QModelIndex &index) const
{
- if (index.isValid())
- return (Node*)index.internalPointer();
- return nullptr;
-}
-
-/*
- Returns the first folder node in the ancestors
- for the given node that is not filtered
- out by the Flat Model.
-*/
-FolderNode *FlatModel::visibleFolderNode(FolderNode *node) const
-{
- if (!node)
- return nullptr;
-
- for (FolderNode *folderNode = node;
- folderNode;
- folderNode = folderNode->parentFolderNode()) {
- if (!filter(folderNode))
- return folderNode;
- }
- return nullptr;
+ WrapperNode *flatNode = itemForIndex(index);
+ return flatNode ? flatNode->m_node : nullptr;
}
bool FlatModel::filter(Node *node) const
@@ -502,343 +406,9 @@ bool isSorted(const QList<Node *> &nodes)
return true;
}
-/// slots and all the fun
-void FlatModel::added(FolderNode* parentNode, const QList<Node*> &newNodeList)
-{
- qCDebug(logger()) << "FlatModel::added" << parentNode->filePath() << newNodeList.size() << "nodes";
- QModelIndex parentIndex = indexForNode(parentNode);
- // Old list
-
- if (newNodeList.isEmpty()) {
- qCDebug(logger()) << " newNodeList empty";
- return;
- }
-
- QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
- if (it == m_childNodes.constEnd()) {
- if (!parentIndex.isValid()) {
- qCDebug(logger()) << " parent not mapped returning";
- return;
- }
- qCDebug(logger()) << " updated m_childNodes";
- beginInsertRows(parentIndex, 0, newNodeList.size() - 1);
- m_childNodes.insert(parentNode, newNodeList);
- endInsertRows();
- return;
- }
- QList<Node *> oldNodeList = it.value();
-
- // Compare lists and emit signals, and modify m_childNodes on the fly
- QList<Node *>::const_iterator oldIter = oldNodeList.constBegin();
- QList<Node *>::const_iterator newIter = newNodeList.constBegin();
-
- Q_ASSERT(isSorted(oldNodeList));
- Q_ASSERT(isSorted(newNodeList));
-
- QSet<Node *> emptyDifference;
- emptyDifference = oldNodeList.toSet();
- emptyDifference.subtract(newNodeList.toSet());
- if (!emptyDifference.isEmpty()) {
- // This should not happen...
- qDebug() << "FlatModel::added, old Node list should be subset of newNode list, found files in old list which were not part of new list";
- foreach (Node *n, emptyDifference)
- qDebug()<<n->filePath();
- Q_ASSERT(false);
- }
-
- // optimization, check for old list is empty
- if (oldIter == oldNodeList.constEnd()) {
- // New Node List is empty, nothing added which intrest us
- if (newIter == newNodeList.constEnd())
- return;
- // So all we need to do is easy
- beginInsertRows(parentIndex, 0, newNodeList.size() - 1);
- m_childNodes.insert(parentNode, newNodeList);
- endInsertRows();
- qCDebug(logger()) << " updated m_childNodes";
- return;
- }
-
- while (true) {
- // Skip all that are the same
- while (*oldIter == *newIter) {
- ++oldIter;
- ++newIter;
- if (oldIter == oldNodeList.constEnd()) {
- // At end of oldNodeList, sweep up rest of newNodeList
- QList<Node *>::const_iterator startOfBlock = newIter;
- newIter = newNodeList.constEnd();
- int pos = oldIter - oldNodeList.constBegin();
- int count = newIter - startOfBlock;
- if (count > 0) {
- beginInsertRows(parentIndex, pos, pos+count-1);
- while (startOfBlock != newIter) {
- oldNodeList.insert(pos, *startOfBlock);
- ++pos;
- ++startOfBlock;
- }
- m_childNodes.insert(parentNode, oldNodeList);
- endInsertRows();
- }
- return; // Done with the lists, leave the function
- }
- }
-
- QList<Node *>::const_iterator startOfBlock = newIter;
- while (*oldIter != *newIter)
- ++newIter;
- // startOfBlock is the first that was diffrent
- // newIter points to the new position of oldIter
- // newIter - startOfBlock is number of new items
- // oldIter is the position where those are...
- int pos = oldIter - oldNodeList.constBegin();
- int count = newIter - startOfBlock;
- beginInsertRows(parentIndex, pos, pos + count - 1);
- while (startOfBlock != newIter) {
- oldNodeList.insert(pos, *startOfBlock);
- ++pos;
- ++startOfBlock;
- }
- m_childNodes.insert(parentNode, oldNodeList);
- endInsertRows();
- oldIter = oldNodeList.constBegin() + pos;
- }
- qCDebug(logger()) << " updated m_childNodes";
-}
-
-void FlatModel::removed(FolderNode* parentNode, const QList<Node*> &newNodeList)
-{
- qCDebug(logger()) << "FlatModel::removed" << parentNode->filePath() << newNodeList.size() << "nodes";
- QModelIndex parentIndex = indexForNode(parentNode);
- // Old list
- QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
- if (it == m_childNodes.constEnd()) {
- qCDebug(logger()) << " unmapped node";
- return;
- }
-
- QList<Node *> oldNodeList = it.value();
- // Compare lists and emit signals, and modify m_childNodes on the fly
- QList<Node *>::const_iterator oldIter = oldNodeList.constBegin();
- QList<Node *>::const_iterator newIter = newNodeList.constBegin();
-
- Q_ASSERT(isSorted(newNodeList));
-
- QSet<Node *> emptyDifference;
- emptyDifference = newNodeList.toSet();
- emptyDifference.subtract(oldNodeList.toSet());
- if (!emptyDifference.isEmpty()) {
- // This should not happen...
- qDebug() << "FlatModel::removed, new Node list should be subset of oldNode list, found files in new list which were not part of old list";
- foreach (Node *n, emptyDifference)
- qDebug()<<n->filePath();
- Q_ASSERT(false);
- }
-
- // optimization, check for new list is empty
- if (newIter == newNodeList.constEnd()) {
- // New Node List is empty, everything removed
- if (oldIter == oldNodeList.constEnd())
- return;
- // So all we need to do is easy
- beginRemoveRows(parentIndex, 0, oldNodeList.size() - 1);
- m_childNodes.insert(parentNode, newNodeList);
- endRemoveRows();
- qCDebug(logger()) << " updated m_childNodes";
- return;
- }
-
- while (true) {
- // Skip all that are the same
- while (*oldIter == *newIter) {
- ++oldIter;
- ++newIter;
- if (newIter == newNodeList.constEnd()) {
- // At end of newNodeList, sweep up rest of oldNodeList
- QList<Node *>::const_iterator startOfBlock = oldIter;
- oldIter = oldNodeList.constEnd();
- int pos = startOfBlock - oldNodeList.constBegin();
- int count = oldIter - startOfBlock;
- if (count > 0) {
- beginRemoveRows(parentIndex, pos, pos+count-1);
- while (startOfBlock != oldIter) {
- ++startOfBlock;
- oldNodeList.removeAt(pos);
- }
-
- m_childNodes.insert(parentNode, oldNodeList);
- endRemoveRows();
- }
- return; // Done with the lists, leave the function
- }
- }
-
- QList<Node *>::const_iterator startOfBlock = oldIter;
- while (*oldIter != *newIter)
- ++oldIter;
- // startOfBlock is the first that was diffrent
- // oldIter points to the new position of newIter
- // oldIter - startOfBlock is number of new items
- // newIter is the position where those are...
- int pos = startOfBlock - oldNodeList.constBegin();
- int count = oldIter - startOfBlock;
- beginRemoveRows(parentIndex, pos, pos + count - 1);
- while (startOfBlock != oldIter) {
- ++startOfBlock;
- oldNodeList.removeAt(pos);
- }
- m_childNodes.insert(parentNode, oldNodeList);
- endRemoveRows();
- oldIter = oldNodeList.constBegin() + pos;
- }
- qCDebug(logger()) << " updated m_childNodes";
-}
-
-void FlatModel::aboutToShowInSimpleTreeChanged(FolderNode* node)
-{
- if (!m_filterProjects)
- return;
- FolderNode *folder = visibleFolderNode(node->parentFolderNode());
- QList<Node *> newNodeList = childNodes(folder, QSet<Node *>() << node);
- removed(folder, newNodeList);
-
- QList<Node *> staleFolders;
- recursiveAddFolderNodesImpl(node, &staleFolders);
- foreach (Node *n, staleFolders)
- if (FolderNode *fn = n->asFolderNode())
- m_childNodes.remove(fn);
-}
-
-void FlatModel::showInSimpleTreeChanged(FolderNode *node)
-{
- if (!m_filterProjects)
- return;
- // we are only interested if we filter
- FolderNode *folder = visibleFolderNode(node->parentFolderNode());
- QList<Node *> newNodeList = childNodes(folder);
- added(folder, newNodeList);
-}
-
-void FlatModel::foldersAboutToBeAdded(FolderNode *parentFolder, const QList<FolderNode*> &newFolders)
-{
- qCDebug(logger()) << "FlatModel::foldersAboutToBeAdded";
- Q_UNUSED(newFolders)
- m_parentFolderForChange = parentFolder;
-}
-
-void FlatModel::foldersAdded()
-{
- // First found out what the folder is that we are adding the files to
- FolderNode *folderNode = visibleFolderNode(m_parentFolderForChange);
-
- // Now get the new list for that folder
- QList<Node *> newNodeList = childNodes(folderNode);
-
- added(folderNode, newNodeList);
-}
-
-void FlatModel::foldersAboutToBeRemoved(FolderNode *parentFolder, const QList<FolderNode*> &staleFolders)
-{
- QSet<Node *> blackList;
- foreach (FolderNode *node, staleFolders)
- blackList.insert(node);
-
- FolderNode *folderNode = visibleFolderNode(parentFolder);
- QList<Node *> newNodeList = childNodes(folderNode, blackList);
-
- removed(folderNode, newNodeList);
- removeFromCache(staleFolders);
-}
-
-void FlatModel::removeFromCache(QList<FolderNode *> list)
-{
- foreach (FolderNode *fn, list) {
- removeFromCache(fn->folderNodes());
- m_childNodes.remove(fn);
- }
-}
-
-void FlatModel::changedSortKey(FolderNode *folderNode, Node *node)
-{
- if (!m_childNodes.contains(folderNode))
- return; // The directory was not yet mapped, so there is no need to sort it.
-
- QList<Node *> nodes = m_childNodes.value(folderNode);
- int oldIndex = nodes.indexOf(node);
-
- nodes.removeAt(oldIndex);
- QList<Node *>::iterator newPosIt = std::lower_bound(nodes.begin(), nodes.end(), node, sortNodes);
- int newIndex = newPosIt - nodes.begin();
-
- if (newIndex == oldIndex)
- return;
-
- nodes.insert(newPosIt, node);
-
- QModelIndex parentIndex = indexForNode(folderNode);
- if (newIndex > oldIndex)
- ++newIndex; // see QAbstractItemModel::beginMoveRows
- beginMoveRows(parentIndex, oldIndex, oldIndex, parentIndex, newIndex);
- m_childNodes[folderNode] = nodes;
- endMoveRows();
-}
-
-void FlatModel::foldersRemoved()
-{
- // Do nothing
-}
-
-void FlatModel::filesAboutToBeAdded(FolderNode *folder, const QList<FileNode*> &newFiles)
-{
- qCDebug(logger()) << "FlatModel::filesAboutToBeAdded";
- Q_UNUSED(newFiles)
- m_parentFolderForChange = folder;
-}
-
-void FlatModel::filesAdded()
-{
- // First find out what the folder is that we are adding the files to
- FolderNode *folderNode = visibleFolderNode(m_parentFolderForChange);
-
- // Now get the new List for that folder
- QList<Node *> newNodeList = childNodes(folderNode);
- added(folderNode, newNodeList);
-}
-
-void FlatModel::filesAboutToBeRemoved(FolderNode *folder, const QList<FileNode*> &staleFiles)
-{
- // First found out what the folder (that is the project) is that we are adding the files to
- FolderNode *folderNode = visibleFolderNode(folder);
-
- QSet<Node *> blackList;
- foreach (Node *node, staleFiles)
- blackList.insert(node);
-
- // Now get the new List for that folder
- QList<Node *> newNodeList = childNodes(folderNode, blackList);
- removed(folderNode, newNodeList);
-}
-
-void FlatModel::filesRemoved()
-{
- // Do nothing
-}
-
-void FlatModel::nodeSortKeyAboutToChange(Node *node)
-{
- m_nodeForSortKeyChange = node;
-}
-
-void FlatModel::nodeSortKeyChanged()
-{
- FolderNode *folderNode = visibleFolderNode(m_nodeForSortKeyChange->parentFolderNode());
- changedSortKey(folderNode, m_nodeForSortKeyChange);
-}
-
-void FlatModel::nodeUpdated(Node *node)
+void FlatModel::nodeUpdated(Node *)
{
- QModelIndex idx = indexForNode(node);
- emit dataChanged(idx, idx);
+ update();
}
namespace Internal {
diff --git a/src/plugins/projectexplorer/projectmodels.h b/src/plugins/projectexplorer/projectmodels.h
index cfd4e5c1b8..4b466fe27c 100644
--- a/src/plugins/projectexplorer/projectmodels.h
+++ b/src/plugins/projectexplorer/projectmodels.h
@@ -25,51 +25,53 @@
#pragma once
+#include "expanddata.h"
+#include "projectnodes.h"
+
#include <utils/fileutils.h>
+#include <utils/treemodel.h>
-#include <QAbstractItemModel>
+#include <QPointer>
#include <QSet>
+#include <QTimer>
+#include <QTreeView>
namespace ProjectExplorer {
class Node;
-class FileNode;
class FolderNode;
+class Project;
class ProjectNode;
-class SessionNode;
namespace Internal {
-class FlatModel : public QAbstractItemModel
+class WrapperNode : public Utils::TypedTreeItem<WrapperNode>
+{
+public:
+ explicit WrapperNode(Node *node) : m_node(node) {}
+ QPointer<Node> m_node;
+};
+
+class FlatModel : public Utils::TreeModel<WrapperNode, WrapperNode>
{
Q_OBJECT
public:
- FlatModel(SessionNode *rootNode, QObject *parent);
+ FlatModel(QObject *parent);
+
+ void setView(QTreeView *view);
// QAbstractItemModel
- QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override;
- QModelIndex parent(const QModelIndex &index) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
- int rowCount(const QModelIndex & parent = QModelIndex()) const override;
- int columnCount(const QModelIndex & parent = QModelIndex()) const override;
- bool hasChildren(const QModelIndex & parent = QModelIndex()) const override;
-
- bool canFetchMore(const QModelIndex & parent) const override;
- void fetchMore(const QModelIndex & parent) override;
-
- void reset();
-
Qt::DropActions supportedDragActions() const override;
QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
- void setStartupProject(ProjectNode *projectNode);
-
Node *nodeForIndex(const QModelIndex &index) const;
+ WrapperNode *wrapperForNode(const Node *node) const;
QModelIndex indexForNode(const Node *node) const;
bool projectFilterEnabled();
@@ -81,53 +83,34 @@ signals:
void renamed(const Utils::FileName &oldName, const Utils::FileName &newName);
private:
- void aboutToShowInSimpleTreeChanged(ProjectExplorer::FolderNode *node);
- void showInSimpleTreeChanged(ProjectExplorer::FolderNode *node);
- void foldersAboutToBeAdded(FolderNode *parentFolder, const QList<FolderNode*> &newFolders);
- void foldersAdded();
-
- void foldersAboutToBeRemoved(FolderNode *parentFolder, const QList<FolderNode*> &staleFolders);
- void foldersRemoved();
-
- // files
- void filesAboutToBeAdded(FolderNode *folder, const QList<FileNode*> &newFiles);
- void filesAdded();
-
- void filesAboutToBeRemoved(FolderNode *folder, const QList<FileNode*> &staleFiles);
- void filesRemoved();
-
- void nodeSortKeyAboutToChange(Node *node);
- void nodeSortKeyChanged();
-
+ void startupProjectChanged(Project *project);
void nodeUpdated(ProjectExplorer::Node *node);
- void added(FolderNode* folderNode, const QList<Node*> &newNodeList);
- void removed(FolderNode* parentNode, const QList<Node*> &newNodeList);
- void removeFromCache(QList<FolderNode *> list);
- void changedSortKey(FolderNode *folderNode, Node *node);
- void fetchMore(FolderNode *foldernode) const;
-
- void recursiveAddFolderNodes(FolderNode *startNode, QList<Node *> *list, const QSet<Node *> &blackList = QSet<Node*>()) const;
- void recursiveAddFolderNodesImpl(FolderNode *startNode, QList<Node *> *list, const QSet<Node *> &blackList = QSet<Node*>()) const;
- void recursiveAddFileNodes(FolderNode *startNode, QList<Node *> *list, const QSet<Node *> &blackList = QSet<Node*>()) const;
- QList<Node*> childNodes(FolderNode *parentNode, const QSet<Node*> &blackList = QSet<Node*>()) const;
-
- FolderNode *visibleFolderNode(FolderNode *node) const;
- bool filter(Node *node) const;
+ bool filter(Node *node) const; // Returns true if node is hidden.
bool m_filterProjects = false;
bool m_filterGeneratedFiles = true;
- SessionNode *m_rootNode;
- mutable QHash<FolderNode*, QList<Node*> > m_childNodes;
ProjectNode *m_startupProject = nullptr;
- FolderNode *m_parentFolderForChange = nullptr;
- Node *m_nodeForSortKeyChange = nullptr;
-
static const QLoggingCategory &logger();
- friend class FlatModelManager;
+ void update();
+ void doUpdate();
+ void rebuildModel();
+ void addProjectNode(WrapperNode *parent, ProjectNode *projectNode, QSet<Node *> *seen);
+ void addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<Node *> *seen);
+
+ ExpandData expandDataForNode(const Node *node) const;
+ void onExpanded(const QModelIndex &idx);
+ void onCollapsed(const QModelIndex &idx);
+ void loadExpandData();
+ void saveExpandData();
+ void handleProjectAdded(Project *project);
+
+ QTimer m_timer;
+ QTreeView *m_view = nullptr;
+ QSet<ExpandData> m_toExpand;
};
int caseFriendlyCompare(const QString &a, const QString &b);
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index a6e6e8c3af..d2f54d02be 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -68,30 +68,21 @@ void Node::setPriority(int p)
m_priority = p;
}
-void Node::emitNodeSortKeyAboutToChange()
-{
- if (parentFolderNode())
- ProjectTree::instance()->emitNodeSortKeyAboutToChange(this);
-}
-
-void Node::emitNodeSortKeyChanged()
-{
- if (parentFolderNode())
- ProjectTree::instance()->emitNodeSortKeyChanged(this);
-}
-
void Node::setAbsoluteFilePathAndLine(const Utils::FileName &path, int line)
{
if (m_filePath == path && m_line == line)
return;
- emitNodeSortKeyAboutToChange();
m_filePath = path;
m_line = line;
- emitNodeSortKeyChanged();
emitNodeUpdated();
}
+Node::~Node()
+{
+
+}
+
NodeType Node::nodeType() const
{
return m_nodeType;
@@ -186,7 +177,12 @@ void Node::setEnabled(bool enabled)
void Node::emitNodeUpdated()
{
if (parentFolderNode())
- ProjectTree::instance()->emitNodeUpdated(this);
+ ProjectTree::emitNodeUpdated(this);
+}
+
+void Node::emitTreeChanged()
+{
+ ProjectTree::emitDataChanged();
}
Node *Node::trim(const QSet<Node *> &keepers)
@@ -511,9 +507,7 @@ void FolderNode::setDisplayName(const QString &name)
{
if (m_displayName == name)
return;
- emitNodeSortKeyAboutToChange();
m_displayName = name;
- emitNodeSortKeyChanged();
emitNodeUpdated();
}
@@ -588,8 +582,6 @@ void FolderNode::addFileNodes(const QList<FileNode *> &files)
if (files.isEmpty())
return;
- ProjectTree::instance()->emitFilesAboutToBeAdded(this, files);
-
foreach (FileNode *file, files) {
QTC_ASSERT(!file->parentFolderNode(),
qDebug("File node has already a parent folder"));
@@ -606,7 +598,7 @@ void FolderNode::addFileNodes(const QList<FileNode *> &files)
}
}
- ProjectTree::instance()->emitFilesAdded(this);
+ ProjectTree::emitDataChanged();
}
/*!
@@ -627,8 +619,6 @@ void FolderNode::removeFileNodes(const QList<FileNode *> &files)
QList<FileNode*> toRemove = files;
Utils::sort(toRemove);
- ProjectTree::instance()->emitFilesAboutToBeRemoved(this, toRemove);
-
auto toRemoveIter = toRemove.constBegin();
auto filesIter = m_fileNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
@@ -641,7 +631,7 @@ void FolderNode::removeFileNodes(const QList<FileNode *> &files)
filesIter = m_fileNodes.erase(filesIter);
}
- ProjectTree::instance()->emitFilesRemoved(this);
+ ProjectTree::emitDataChanged();
}
/*!
@@ -655,7 +645,6 @@ void FolderNode::addFolderNodes(const QList<FolderNode*> &subFolders)
if (subFolders.isEmpty())
return;
- ProjectTree::instance()->emitFoldersAboutToBeAdded(this, subFolders);
foreach (FolderNode *folder, subFolders) {
QTC_ASSERT(!folder->parentFolderNode(),
qDebug("Project node has already a parent folder"));
@@ -677,7 +666,7 @@ void FolderNode::addFolderNodes(const QList<FolderNode*> &subFolders)
qDebug("project nodes have to be added via addProjectNodes"));
}
- ProjectTree::instance()->emitFoldersAdded(this);
+ ProjectTree::emitDataChanged();
}
/*!
@@ -696,8 +685,6 @@ void FolderNode::removeFolderNodes(const QList<FolderNode*> &subFolders)
QList<FolderNode*> toRemove = subFolders;
Utils::sort(toRemove);
- ProjectTree::instance()->emitFoldersAboutToBeRemoved(this, toRemove);
-
auto toRemoveIter = toRemove.constBegin();
auto folderIter = m_folderNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
@@ -712,7 +699,7 @@ void FolderNode::removeFolderNodes(const QList<FolderNode*> &subFolders)
folderIter = m_folderNodes.erase(folderIter);
}
- ProjectTree::instance()->emitFoldersRemoved(this);
+ ProjectTree::emitDataChanged();
}
bool FolderNode::showInSimpleTree() const
@@ -867,8 +854,6 @@ void ProjectNode::addProjectNodes(const QList<ProjectNode*> &subProjects)
foreach (ProjectNode *projectNode, subProjects)
folderNodes << projectNode;
- ProjectTree::instance()->emitFoldersAboutToBeAdded(this, folderNodes);
-
foreach (ProjectNode *project, subProjects) {
QTC_ASSERT(!project->parentFolderNode() || project->parentFolderNode() == this,
qDebug("Project node has already a parent"));
@@ -876,10 +861,9 @@ void ProjectNode::addProjectNodes(const QList<ProjectNode*> &subProjects)
m_folderNodes.append(project);
m_projectNodes.append(project);
}
+
Utils::sort(m_folderNodes);
Utils::sort(m_projectNodes);
-
- ProjectTree::instance()->emitFoldersAdded(this);
}
}
@@ -898,8 +882,6 @@ void ProjectNode::removeProjectNodes(const QList<ProjectNode*> &subProjects)
toRemove << projectNode;
Utils::sort(toRemove);
- ProjectTree::instance()->emitFoldersAboutToBeRemoved(this, toRemove);
-
auto toRemoveIter = toRemove.constBegin();
auto folderIter = m_folderNodes.begin();
auto projectIter = m_projectNodes.begin();
@@ -918,8 +900,6 @@ void ProjectNode::removeProjectNodes(const QList<ProjectNode*> &subProjects)
projectIter = m_projectNodes.erase(projectIter);
folderIter = m_folderNodes.erase(folderIter);
}
-
- ProjectTree::instance()->emitFoldersRemoved(this);
}
}
@@ -967,12 +947,6 @@ bool SessionNode::showInSimpleTree() const
return true;
}
-void SessionNode::projectDisplayNameChanged(Node *node)
-{
- ProjectTree::instance()->emitNodeSortKeyAboutToChange(node);
- ProjectTree::instance()->emitNodeSortKeyChanged(node);
-}
-
QList<ProjectNode*> SessionNode::projectNodes() const
{
return m_projectNodes;
@@ -990,8 +964,6 @@ void SessionNode::addProjectNodes(const QList<ProjectNode*> &projectNodes)
foreach (ProjectNode *projectNode, projectNodes)
folderNodes << projectNode;
- ProjectTree::instance()->emitFoldersAboutToBeAdded(this, folderNodes);
-
foreach (ProjectNode *project, projectNodes) {
QTC_ASSERT(!project->parentFolderNode(),
qDebug("Project node has already a parent folder"));
@@ -1002,8 +974,6 @@ void SessionNode::addProjectNodes(const QList<ProjectNode*> &projectNodes)
Utils::sort(m_folderNodes);
Utils::sort(m_projectNodes);
-
- ProjectTree::instance()->emitFoldersAdded(this);
}
}
@@ -1015,9 +985,6 @@ void SessionNode::removeProjectNodes(const QList<ProjectNode*> &projectNodes)
toRemove << projectNode;
Utils::sort(toRemove);
-
- ProjectTree::instance()->emitFoldersAboutToBeRemoved(this, toRemove);
-
auto toRemoveIter = toRemove.constBegin();
auto folderIter = m_folderNodes.begin();
auto projectIter = m_projectNodes.begin();
@@ -1035,8 +1002,6 @@ void SessionNode::removeProjectNodes(const QList<ProjectNode*> &projectNodes)
projectIter = m_projectNodes.erase(projectIter);
folderIter = m_folderNodes.erase(folderIter);
}
-
- ProjectTree::instance()->emitFoldersRemoved(this);
}
}
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index 1dd71df02f..99e4b2ac82 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -104,8 +104,9 @@ class NodesVisitor;
class SessionManager;
// Documentation inside.
-class PROJECTEXPLORER_EXPORT Node
+class PROJECTEXPLORER_EXPORT Node : public QObject
{
+ Q_OBJECT
public:
enum PriorityLevel {
DefaultPriority = 0,
@@ -116,7 +117,7 @@ public:
DefaultProjectFilePriority = 500000
};
- virtual ~Node() = default;
+ virtual ~Node();
NodeType nodeType() const;
int priority() const;
@@ -141,6 +142,7 @@ public:
void setAbsoluteFilePathAndLine(const Utils::FileName &filePath, int line);
void emitNodeUpdated();
+ void emitTreeChanged();
virtual Node *trim(const QSet<Node *> &keepers);
@@ -161,9 +163,6 @@ protected:
void setPriority(int priority);
void setParentFolderNode(FolderNode *parentFolder);
- void emitNodeSortKeyAboutToChange();
- void emitNodeSortKeyChanged();
-
private:
FolderNode *m_parentFolderNode = nullptr;
Utils::FileName m_filePath;
@@ -177,6 +176,7 @@ class PROJECTEXPLORER_EXPORT FileNode : public Node
{
public:
FileNode(const Utils::FileName &filePath, const FileType fileType, bool generated, int line = -1);
+ FileNode(const FileNode &other) : FileNode(other.filePath(), other.fileType(), true) {}
FileType fileType() const;
bool isGenerated() const;
@@ -255,8 +255,8 @@ public:
void addFolderNodes(const QList<FolderNode*> &subFolders);
void removeFolderNodes(const QList<FolderNode*> &subFolders);
- FolderNode *asFolderNode() final { return this; }
- const FolderNode *asFolderNode() const final { return this; }
+ FolderNode *asFolderNode() override { return this; }
+ const FolderNode *asFolderNode() const override { return this; }
protected:
QList<FolderNode*> m_folderNodes;
@@ -330,11 +330,8 @@ public:
SessionNode();
QList<ProjectAction> supportedActions(Node *node) const override;
-
QList<ProjectNode*> projectNodes() const;
-
QString addFileFilter() const override;
-
void accept(NodesVisitor *visitor) override;
bool showInSimpleTree() const override;
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index 376dc73d7f..1774d8ee0f 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -258,167 +258,14 @@ void ProjectTree::updateContext()
void ProjectTree::emitNodeUpdated(Node *node)
{
- if (!isInNodeHierarchy(node))
+ if (!s_instance->isInNodeHierarchy(node))
return;
- emit nodeUpdated(node);
+ emit s_instance->nodeUpdated(node);
}
-void ProjectTree::emitAboutToChangeShowInSimpleTree(FolderNode *node)
+void ProjectTree::emitDataChanged()
{
- if (!isInNodeHierarchy(node))
- return;
- emit aboutToChangeShowInSimpleTree(node);
-}
-
-void ProjectTree::emitShowInSimpleTreeChanged(FolderNode *node)
-{
- if (!isInNodeHierarchy(node))
- return;
- emit showInSimpleTreeChanged(node);
-}
-
-void ProjectTree::emitFoldersAboutToBeAdded(FolderNode *parentFolder, const QList<FolderNode *> &newFolders)
-{
- if (!isInNodeHierarchy(parentFolder))
- return;
-
- m_foldersAdded = newFolders;
-
- emit foldersAboutToBeAdded(parentFolder, newFolders);
-}
-
-void ProjectTree::emitFoldersAdded(FolderNode *folder)
-{
- if (!isInNodeHierarchy(folder))
- return;
-
- emit foldersAdded();
-
- if (Utils::anyOf(m_projectTreeWidgets, &ProjectTreeWidget::hasFocus))
- return;
-
- if (!m_currentNode) {
- Core::IDocument *document = Core::EditorManager::currentDocument();
- const FileName fileName = document ? document->filePath() : FileName();
-
-
- FindNodesForFileVisitor findNodes(fileName);
- foreach (FolderNode *fn, m_foldersAdded)
- fn->accept(&findNodes);
-
- Node *bestNode = ProjectTreeWidget::mostExpandedNode(findNodes.nodes());
- if (!bestNode)
- return;
-
- updateFromNode(bestNode);
- }
- m_foldersAdded.clear();
-}
-
-void ProjectTree::emitFoldersAboutToBeRemoved(FolderNode *parentFolder, const QList<FolderNode *> &staleFolders)
-{
- if (!isInNodeHierarchy(parentFolder))
- return;
-
- Node *n = ProjectTree::currentNode();
- while (n) {
- if (FolderNode *fn = n->asFolderNode()) {
- if (staleFolders.contains(fn)) {
- ProjectNode *pn = n->parentProjectNode();
- // Make sure the node we are switching too isn't going to be removed also
- while (staleFolders.contains(pn))
- pn = pn->parentFolderNode()->parentProjectNode();
- m_resetCurrentNodeFolder = true;
- break;
- }
- }
- n = n->parentFolderNode();
- }
- emit foldersAboutToBeRemoved(parentFolder, staleFolders);
-}
-
-void ProjectTree::emitFoldersRemoved(FolderNode *folder)
-{
- if (!isInNodeHierarchy(folder))
- return;
-
- emit foldersRemoved();
-
- if (m_resetCurrentNodeFolder) {
- updateFromFocus(true);
- m_resetCurrentNodeFolder = false;
- }
-}
-
-void ProjectTree::emitFilesAboutToBeAdded(FolderNode *folder, const QList<FileNode *> &newFiles)
-{
- if (!isInNodeHierarchy(folder))
- return;
- m_filesAdded = newFiles;
- emit filesAboutToBeAdded(folder, newFiles);
-}
-
-void ProjectTree::emitFilesAdded(FolderNode *folder)
-{
- if (!isInNodeHierarchy(folder))
- return;
-
- emit filesAdded();
-
- if (Utils::anyOf(m_projectTreeWidgets, &ProjectTreeWidget::hasFocus))
- return;
-
- if (!m_currentNode) {
- Core::IDocument *document = Core::EditorManager::currentDocument();
- const FileName fileName = document ? document->filePath() : FileName();
-
- int index = Utils::indexOf(m_filesAdded, Utils::equal(&FileNode::filePath, fileName));
-
- if (index == -1)
- return;
-
- updateFromNode(m_filesAdded.at(index));
- }
- m_filesAdded.clear();
-}
-
-void ProjectTree::emitFilesAboutToBeRemoved(FolderNode *folder, const QList<FileNode *> &staleFiles)
-{
- if (!isInNodeHierarchy(folder))
- return;
-
- if (m_currentNode)
- if (FileNode *fileNode = m_currentNode->asFileNode())
- if (staleFiles.contains(fileNode))
- m_resetCurrentNodeFile = true;
-
- emit filesAboutToBeRemoved(folder, staleFiles);
-}
-
-void ProjectTree::emitFilesRemoved(FolderNode *folder)
-{
- if (!isInNodeHierarchy(folder))
- return;
- emit filesRemoved();
-
- if (m_resetCurrentNodeFile) {
- updateFromFocus(true);
- m_resetCurrentNodeFile = false;
- }
-}
-
-void ProjectTree::emitNodeSortKeyAboutToChange(Node *node)
-{
- if (!isInNodeHierarchy(node))
- return;
- emit nodeSortKeyAboutToChange(node);
-}
-
-void ProjectTree::emitNodeSortKeyChanged(Node *node)
-{
- if (!isInNodeHierarchy(node))
- return;
- emit nodeSortKeyChanged();
+ instance()->dataChanged();
}
void ProjectTree::collapseAll()
diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h
index 196e280c14..e7822abc18 100644
--- a/src/plugins/projectexplorer/projecttree.h
+++ b/src/plugins/projectexplorer/projecttree.h
@@ -68,61 +68,14 @@ signals:
// Emitted whenever the model needs to send a update signal.
void nodeUpdated(ProjectExplorer::Node *node);
-
- // projects
- void aboutToChangeShowInSimpleTree(ProjectExplorer::FolderNode*);
- void showInSimpleTreeChanged(ProjectExplorer::FolderNode *node);
-
- // folders & projects
- void foldersAboutToBeAdded(FolderNode *parentFolder,
- const QList<FolderNode*> &newFolders);
- void foldersAdded();
-
- void foldersAboutToBeRemoved(FolderNode *parentFolder,
- const QList<FolderNode*> &staleFolders);
- void foldersRemoved();
-
- // files
- void filesAboutToBeAdded(FolderNode *folder,
- const QList<FileNode*> &newFiles);
- void filesAdded();
-
- void filesAboutToBeRemoved(FolderNode *folder,
- const QList<FileNode*> &staleFiles);
- void filesRemoved();
- void nodeSortKeyAboutToChange(Node *node);
- void nodeSortKeyChanged();
+ void dataChanged();
void aboutToShowContextMenu(ProjectExplorer::Project *project,
ProjectExplorer::Node *node);
public: // for nodes to emit signals, do not call unless you are a node
- void emitNodeUpdated(ProjectExplorer::Node *node);
-
- // projects
- void emitAboutToChangeShowInSimpleTree(ProjectExplorer::FolderNode *node);
- void emitShowInSimpleTreeChanged(ProjectExplorer::FolderNode *node);
-
- // folders & projects
- void emitFoldersAboutToBeAdded(FolderNode *parentFolder,
- const QList<FolderNode*> &newFolders);
- void emitFoldersAdded(FolderNode *folder);
-
- void emitFoldersAboutToBeRemoved(FolderNode *parentFolder,
- const QList<FolderNode*> &staleFolders);
- void emitFoldersRemoved(FolderNode *folder);
-
- // files
- void emitFilesAboutToBeAdded(FolderNode *folder,
- const QList<FileNode*> &newFiles);
- void emitFilesAdded(FolderNode *folder);
-
- void emitFilesAboutToBeRemoved(FolderNode *folder,
- const QList<FileNode*> &staleFiles);
- void emitFilesRemoved(FolderNode *folder);
- void emitNodeSortKeyAboutToChange(Node *node);
- void emitNodeSortKeyChanged(Node *node);
-
+ static void emitNodeUpdated(ProjectExplorer::Node *node);
+ static void emitDataChanged();
void collapseAll();
private:
@@ -144,14 +97,9 @@ private:
private:
static ProjectTree *s_instance;
- QList<Internal::ProjectTreeWidget *> m_projectTreeWidgets;
- Node *m_currentNode = nullptr;
+ QList<QPointer<Internal::ProjectTreeWidget>> m_projectTreeWidgets;
+ QPointer<Node> m_currentNode;
Project *m_currentProject = nullptr;
- QList<FileNode *> m_filesAdded;
- QList<FolderNode *> m_foldersAdded;
- bool m_resetCurrentNodeFolder = false;
- bool m_resetCurrentNodeFile = false;
- bool m_resetCurrentNodeProject = false;
Internal::ProjectTreeWidget *m_focusForContextMenu = nullptr;
Core::Context m_lastProjectContext;
};
diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp
index ba2f304c7a..387612e832 100644
--- a/src/plugins/projectexplorer/projecttreewidget.cpp
+++ b/src/plugins/projectexplorer/projecttreewidget.cpp
@@ -167,17 +167,15 @@ private:
*/
ProjectTreeWidget::ProjectTreeWidget(QWidget *parent) : QWidget(parent)
{
- m_model = new FlatModel(SessionManager::sessionNode(), this);
- Project *pro = SessionManager::startupProject();
- if (pro)
- m_model->setStartupProject(pro->rootProjectNode());
-
+ // We keep one instance per tree as this also manages the
+ // simple/non-simple etc state which is per tree.
+ m_model = new FlatModel(this);
m_view = new ProjectTreeView;
m_view->setModel(m_model);
m_view->setItemDelegate(new ProjectTreeItemDelegate(this));
setFocusProxy(m_view);
m_view->installEventFilter(this);
- initView();
+ m_model->setView(m_view);
auto layout = new QVBoxLayout();
layout->addWidget(ItemViewFind::createSearchableWrapper(
@@ -198,8 +196,6 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent) : QWidget(parent)
this, &ProjectTreeWidget::setGeneratedFilesFilter);
// connections
- connect(m_model, &QAbstractItemModel::modelReset,
- this, &ProjectTreeWidget::initView);
connect(m_model, &FlatModel::renamed,
this, &ProjectTreeWidget::renamed);
connect(m_view, &QAbstractItemView::activated,
@@ -209,19 +205,6 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent) : QWidget(parent)
connect(m_view, &QWidget::customContextMenuRequested,
this, &ProjectTreeWidget::showContextMenu);
- SessionManager *sessionManager = SessionManager::instance();
- connect(sessionManager, &SessionManager::projectAdded,
- this, &ProjectTreeWidget::handleProjectAdded);
- connect(sessionManager, &SessionManager::startupProjectChanged,
- this, &ProjectTreeWidget::startupProjectChanged);
-
- connect(sessionManager, &SessionManager::aboutToLoadSession,
- this, &ProjectTreeWidget::disableAutoExpand);
- connect(sessionManager, &SessionManager::sessionLoaded,
- this, &ProjectTreeWidget::loadExpandData);
- connect(sessionManager, &SessionManager::aboutToSaveSession,
- this, &ProjectTreeWidget::saveExpandData);
-
m_toggleSync = new QToolButton;
m_toggleSync->setIcon(Utils::Icons::LINK.icon());
m_toggleSync->setCheckable(true);
@@ -230,6 +213,7 @@ ProjectTreeWidget::ProjectTreeWidget(QWidget *parent) : QWidget(parent)
connect(m_toggleSync, &QAbstractButton::clicked,
this, &ProjectTreeWidget::toggleAutoSynchronization);
+ setCurrentItem(ProjectTree::currentNode());
setAutoSynchronization(true);
m_projectTreeWidgets << this;
@@ -268,14 +252,6 @@ void ProjectTreeWidget::rowsInserted(const QModelIndex &parent, int start, int e
{
Node *node = m_model->nodeForIndex(parent);
QTC_ASSERT(node, return);
- const QString path = node->filePath().toString();
- const QString displayName = node->displayName();
-
- auto it = m_toExpand.find(ExpandData(path, displayName));
- if (it != m_toExpand.end()) {
- m_view->expand(parent);
- m_toExpand.erase(it);
- }
int i = start;
while (i <= end) {
QModelIndex idx = m_model->index(i, 0, parent);
@@ -317,68 +293,6 @@ Node *ProjectTreeWidget::mostExpandedNode(const QList<Node *> &nodes)
return bestNode;
}
-void ProjectTreeWidget::disableAutoExpand()
-{
- m_autoExpand = false;
-}
-
-void ProjectTreeWidget::loadExpandData()
-{
- m_autoExpand = true;
- QList<QVariant> data = SessionManager::value(QLatin1String("ProjectTree.ExpandData")).value<QList<QVariant>>();
- QSet<ExpandData> set = Utils::transform<QSet>(data, [](const QVariant &v) {
- QStringList list = v.toStringList();
- if (list.size() != 2)
- return ExpandData();
- return ExpandData(list.at(0), list.at(1));
- });
-
- set.remove(ExpandData());
-
- recursiveLoadExpandData(m_view->rootIndex(), set);
-
- // store remaning nodes to expand
- m_toExpand = set;
-}
-
-void ProjectTreeWidget::recursiveLoadExpandData(const QModelIndex &index, QSet<ExpandData> &data)
-{
- Node *node = m_model->nodeForIndex(index);
- const QString path = node->filePath().toString();
- const QString displayName = node->displayName();
- auto it = data.find(ExpandData(path, displayName));
- if (it != data.end()) {
- m_view->expand(index);
- data.erase(it);
- int count = m_model->rowCount(index);
- for (int i = 0; i < count; ++i)
- recursiveLoadExpandData(index.child(i, 0), data);
- }
-}
-
-void ProjectTreeWidget::saveExpandData()
-{
- QList<QVariant> data;
- recursiveSaveExpandData(m_view->rootIndex(), &data);
- // TODO if there are multiple ProjectTreeWidgets, the last one saves the data
- SessionManager::setValue(QLatin1String("ProjectTree.ExpandData"), data);
-}
-
-void ProjectTreeWidget::recursiveSaveExpandData(const QModelIndex &index, QList<QVariant> *data)
-{
- Q_ASSERT(data);
- if (m_view->isExpanded(index) || index == m_view->rootIndex()) {
- // Note: We store the path+displayname of the node, which isn't unique for e.g. .pri files
- // but works for most nodes
- Node *node = m_model->nodeForIndex(index);
- const QStringList &list = ExpandData(node->filePath().toString(), node->displayName()).toStringList();
- data->append(QVariant::fromValue(list));
- int count = m_model->rowCount(index);
- for (int i = 0; i < count; ++i)
- recursiveSaveExpandData(index.child(i, 0), data);
- }
-}
-
QToolButton *ProjectTreeWidget::toggleSync()
{
return m_toggleSync;
@@ -427,9 +341,9 @@ void ProjectTreeWidget::editCurrentItem()
m_view->edit(m_view->selectionModel()->currentIndex());
}
-
void ProjectTreeWidget::renamed(const Utils::FileName &oldPath, const Utils::FileName &newPath)
{
+ update();
Q_UNUSED(oldPath);
if (!currentNode() || currentNode()->filePath() != newPath) {
// try to find the node
@@ -453,7 +367,6 @@ void ProjectTreeWidget::setCurrentItem(Node *node)
} else {
m_view->clearSelection();
}
-
}
void ProjectTreeWidget::handleCurrentItemChange(const QModelIndex &current)
@@ -491,45 +404,6 @@ void ProjectTreeWidget::showContextMenu(const QPoint &pos)
ProjectTree::showContextMenu(this, m_view->mapToGlobal(pos), node);
}
-void ProjectTreeWidget::handleProjectAdded(Project *project)
-{
- Node *node = project->rootProjectNode();
- QModelIndex idx = m_model->indexForNode(node);
- if (m_autoExpand) // disabled while session restoring
- m_view->setExpanded(idx, true);
- m_view->setCurrentIndex(idx);
-
- connect(m_model, &FlatModel::rowsInserted,
- this, &ProjectTreeWidget::rowsInserted);
-}
-
-void ProjectTreeWidget::startupProjectChanged(Project *project)
-{
- if (project) {
- ProjectNode *node = project->rootProjectNode();
- m_model->setStartupProject(node);
- } else {
- m_model->setStartupProject(0);
- }
-}
-
-void ProjectTreeWidget::initView()
-{
- QModelIndex sessionIndex = m_model->index(0, 0);
-
- // hide root folder
- m_view->setRootIndex(sessionIndex);
-
- while (m_model->canFetchMore(sessionIndex))
- m_model->fetchMore(sessionIndex);
-
- // expand top level projects
- for (int i = 0; i < m_model->rowCount(sessionIndex); ++i)
- m_view->expand(m_model->index(i, 0, sessionIndex));
-
- setCurrentItem(ProjectTree::currentNode());
-}
-
void ProjectTreeWidget::openItem(const QModelIndex &mainIndex)
{
Node *node = m_model->nodeForIndex(mainIndex);
diff --git a/src/plugins/projectexplorer/projecttreewidget.h b/src/plugins/projectexplorer/projecttreewidget.h
index dbda089187..2a94a29e0c 100644
--- a/src/plugins/projectexplorer/projecttreewidget.h
+++ b/src/plugins/projectexplorer/projecttreewidget.h
@@ -47,6 +47,7 @@ class FileNode;
namespace Internal {
class FlatModel;
+class WrapperNode;
class ProjectTreeWidget : public QWidget
{
@@ -78,32 +79,20 @@ private:
void handleCurrentItemChange(const QModelIndex &current);
void showContextMenu(const QPoint &pos);
void openItem(const QModelIndex &mainIndex);
- void handleProjectAdded(ProjectExplorer::Project *project);
- void startupProjectChanged(ProjectExplorer::Project *project);
- void initView();
-
- void loadExpandData();
- void saveExpandData();
- void disableAutoExpand();
void setCurrentItem(ProjectExplorer::Node *node);
- void recursiveLoadExpandData(const QModelIndex &index, QSet<ExpandData> &data);
- void recursiveSaveExpandData(const QModelIndex &index, QList<QVariant> *data);
static int expandedCount(Node *node);
void rowsInserted(const QModelIndex &parent, int start, int end);
void renamed(const Utils::FileName &oldPath, const Utils::FileName &newPath);
- QSet<ExpandData> m_toExpand;
QTreeView *m_view = nullptr;
FlatModel *m_model = nullptr;
QAction *m_filterProjectsAction = nullptr;
QAction *m_filterGeneratedFilesAction;
QToolButton *m_toggleSync;
- QModelIndex m_subIndex;
QString m_modelId;
bool m_autoSync = false;
- bool m_autoExpand = true;
Utils::FileName m_delayedRename;
static QList<ProjectTreeWidget *> m_projectTreeWidgets;
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index 2d789f6d83..42b36aca24 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -93,7 +93,7 @@ public:
static QString windowTitleAddition(const QString &filePath);
static QString sessionTitle(const QString &filePath);
- std::unique_ptr<SessionNode> m_sessionNode;
+ SessionNode m_sessionNode;
QString m_sessionName = QLatin1String("default");
bool m_virginSession = true;
bool m_loadingSession = false;
@@ -124,8 +124,6 @@ SessionManager::SessionManager(QObject *parent) : QObject(parent)
m_instance = this;
d = new SessionManagerPrivate;
- d->m_sessionNode.reset(new SessionNode);
-
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
this, &SessionManager::saveActiveMode);
@@ -383,13 +381,13 @@ void SessionManager::addProject(Project *pro)
QTC_ASSERT(!d->m_projects.contains(pro), return);
d->m_projects.append(pro);
- d->m_sessionNode->addProjectNodes(QList<ProjectNode *>() << pro->rootProjectNode());
+ d->m_sessionNode.addProjectNodes({ pro->rootProjectNode() });
connect(pro, &Project::fileListChanged,
m_instance, &SessionManager::clearProjectFileCache);
connect(pro, &Project::displayNameChanged, m_instance, [pro] {
- d->m_sessionNode->projectDisplayNameChanged(pro->rootProjectNode());
+ d->m_sessionNode.emitNodeUpdated();
emit m_instance->projectDisplayNameChanged(pro);
});
@@ -650,11 +648,9 @@ Project *SessionManager::projectForNode(Node *node)
if (!rootProjectNode)
rootProjectNode = node->parentFolderNode();
- while (rootProjectNode && rootProjectNode->parentFolderNode() != d->m_sessionNode.get())
+ while (rootProjectNode && rootProjectNode->parentFolderNode() != &d->m_sessionNode)
rootProjectNode = rootProjectNode->parentFolderNode();
- Q_ASSERT(rootProjectNode);
-
return Utils::findOrDefault(d->m_projects, Utils::equal(&Project::rootProjectNode, rootProjectNode));
}
@@ -742,7 +738,7 @@ void SessionManager::removeProjects(QList<Project *> remove)
m_instance, &SessionManager::clearProjectFileCache);
d->m_projectFileCache.remove(pro);
- d->m_sessionNode->removeProjectNodes(QList<ProjectNode *>() << pro->rootProjectNode());
+ d->m_sessionNode.removeProjectNodes({ pro->rootProjectNode() });
emit m_instance->projectRemoved(pro);
delete pro;
}
@@ -1095,7 +1091,7 @@ QString SessionManager::lastSession()
SessionNode *SessionManager::sessionNode()
{
- return d->m_sessionNode.get();
+ return &d->m_sessionNode;
}
void SessionManager::reportProjectLoadingProgress()
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
index f987c655b6..dd3b055db9 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
@@ -2083,15 +2083,7 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
removeProjectNodes(projectNodes());
removeFolderNodes(folderNodes());
- bool changesShowInSimpleTree = showInSimpleTree() ^ showInSimpleTree(result->projectType);
-
- if (changesShowInSimpleTree)
- ProjectTree::instance()->emitAboutToChangeShowInSimpleTree(this);
-
m_projectType = result->projectType;
-
- if (changesShowInSimpleTree)
- ProjectTree::instance()->emitShowInSimpleTreeChanged(this);
}
//
@@ -2232,6 +2224,7 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
updateGeneratedFiles(buildDirectory);
cleanupProFileReaders();
+ ProjectNode::emitTreeChanged();
}
void QmakeProFileNode::cleanupProFileReaders()