forked from qt-creator/qt-creator
ProjectExplorer: Make the FlatModel a Utils::TreeModel
The FlatModel is essentially a proxy model keeping expansion and
filter state per ProjectTree(View). Using a Utils::TreeModel makes
it fast enough to allow recreation of the proxy structure on
structural changes simplifying the parent/child logic significantly.
The {Session,Project,Folder,File}Node hierarchy still is still primary
information and shared by all views.
Change-Id: Ic08180a19bda37908280ff30e0737d188ed93e92
Reviewed-by: Robert Loehning <robert.loehning@qt.io>
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -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 ¤t)
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user