ProjectExplorer: Introduce some FolderNode convenience functions

... and use them.

Change-Id: I9f5237e5eac30715c2effbd3301dd2a70516d2a9
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
hjk
2017-01-26 17:02:16 +01:00
parent 8427932a0e
commit 87304b3ce0
8 changed files with 117 additions and 139 deletions

View File

@@ -281,13 +281,12 @@ void BuildDirManager::generateProjectTree(CMakeListsNode *root, const QList<cons
const Utils::FileName projectFile = m_buildConfiguration->target()->project()->projectFilePath(); const Utils::FileName projectFile = m_buildConfiguration->target()->project()->projectFilePath();
root->makeEmpty();
m_reader->generateProjectTree(root, allFiles); m_reader->generateProjectTree(root, allFiles);
// Make sure the top level CMakeLists.txt is always visible: // Make sure the top level CMakeLists.txt is always visible:
if (root->fileNodes().isEmpty() if (root->isEmpty())
&& root->folderNodes().isEmpty() root->addFileNode(new FileNode(projectFile, FileType::Project, false));
&& root->projectNodes().isEmpty())
root->addFileNodes({ new FileNode(projectFile, FileType::Project, false) });
} }
QSet<Core::Id> BuildDirManager::updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) QSet<Core::Id> BuildDirManager::updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder)

View File

@@ -217,9 +217,6 @@ void CMakeBuildConfiguration::generateProjectTree(CMakeListsNode *root,
if (!m_buildDirManager || m_buildDirManager->isParsing()) if (!m_buildDirManager || m_buildDirManager->isParsing())
return; return;
root->removeProjectNodes();
root->setFolderNodes({});
root->setFileNodes({});
m_buildDirManager->generateProjectTree(root, allFiles); m_buildDirManager->generateProjectTree(root, allFiles);
} }

View File

@@ -231,7 +231,7 @@ FolderNode *setupCMakeVFolder(FolderNode *base, const Utils::FileName &basePath,
if (!folder) { if (!folder) {
folder = new VirtualFolderNode(basePath, priority); folder = new VirtualFolderNode(basePath, priority);
folder->setDisplayName(displayName); folder->setDisplayName(displayName);
base->addFolderNodes({ folder }); base->addFolderNode(folder);
} }
folder->buildTree(files); folder->buildTree(files);
return folder; return folder;
@@ -583,7 +583,7 @@ void ServerModeReader::updateCMakeLists(CMakeListsNode *root, const QList<FileNo
FileNode *cmFn = cmln->fileNode(fn->filePath()); FileNode *cmFn = cmln->fileNode(fn->filePath());
if (!cmFn) { if (!cmFn) {
cmFn = fn; cmFn = fn;
cmln->addFileNodes({ cmFn }); cmln->addFileNode(cmFn);
} }
// Update displayName of CMakeListsNode: // Update displayName of CMakeListsNode:
const QString dn = prefix.isEmpty() ? k : k.mid(prefix.count() + 1); const QString dn = prefix.isEmpty() ? k : k.mid(prefix.count() + 1);

View File

@@ -412,7 +412,7 @@ FolderNode *FolderNode::recursiveFindOrCreateFolderNode(const QString &directory
// No FolderNode yet, so create it // No FolderNode yet, so create it
auto tmp = new ProjectExplorer::FolderNode(path); auto tmp = new ProjectExplorer::FolderNode(path);
tmp->setDisplayName(part); tmp->setDisplayName(part);
parent->addFolderNodes(QList<ProjectExplorer::FolderNode *>({ tmp })); parent->addFolderNode(tmp);
next = tmp; next = tmp;
} }
parent = next; parent = next;
@@ -431,7 +431,7 @@ void FolderNode::buildTree(QList<FileNode *> &files, const Utils::FileName &over
// Get relative path to rootNode // Get relative path to rootNode
QString parentDir = fn->filePath().toFileInfo().absolutePath(); QString parentDir = fn->filePath().toFileInfo().absolutePath();
ProjectExplorer::FolderNode *folder = recursiveFindOrCreateFolderNode(parentDir, overrideBaseDir); ProjectExplorer::FolderNode *folder = recursiveFindOrCreateFolderNode(parentDir, overrideBaseDir);
folder->addFileNodes({ fn }); folder->addFileNode(fn);
} }
} }
@@ -514,30 +514,29 @@ FolderNode::AddNewInformation FolderNode::addNewInformation(const QStringList &f
addFiles. addFiles.
*/ */
void FolderNode::addFileNodes(const QList<FileNode *> &files) void FolderNode::addFileNode(FileNode *file)
{ {
Q_ASSERT(managingProject()); Q_ASSERT(managingProject());
if (files.isEmpty()) QTC_ASSERT(!file->parentFolderNode(),
return; qDebug("File node has already a parent folder"));
foreach (FileNode *file, files) { file->setParentFolderNode(this);
QTC_ASSERT(!file->parentFolderNode(), // Now find the correct place to insert file
qDebug("File node has already a parent folder")); if (m_fileNodes.count() == 0
|| m_fileNodes.last() < file) {
file->setParentFolderNode(this); // empty list or greater then last node
// Now find the correct place to insert file m_fileNodes.append(file);
if (m_fileNodes.count() == 0 } else {
|| m_fileNodes.last() < file) { auto it = std::lower_bound(m_fileNodes.begin(), m_fileNodes.end(), file);
// empty list or greater then last node m_fileNodes.insert(it, file);
m_fileNodes.append(file);
} else {
auto it = std::lower_bound(m_fileNodes.begin(), m_fileNodes.end(), file);
m_fileNodes.insert(it, file);
}
} }
}
ProjectTree::emitDataChanged(); void FolderNode::addFileNodes(const QList<FileNode *> &files)
{
foreach (FileNode *file, files)
addFileNode(file);
} }
/*! /*!
@@ -548,29 +547,24 @@ void FolderNode::addFileNodes(const QList<FileNode *> &files)
removeFiles. removeFiles.
*/ */
void FolderNode::removeFileNodes()
{
qDeleteAll(m_fileNodes);
m_fileNodes.clear();
ProjectTree::emitDataChanged();
}
void FolderNode::removeFileNodes(const QList<FileNode *> &files) void FolderNode::removeFileNodes(const QList<FileNode *> &files)
{
for (FileNode *file : files)
removeFileNode(file);
}
void FolderNode::removeFileNode(FileNode *file)
{ {
Q_ASSERT(managingProject()); Q_ASSERT(managingProject());
m_fileNodes.removeAll(file);
if (files.isEmpty()) delete file;
return;
QList<FileNode*> toRemove = files;
Utils::sort(toRemove);
auto toRemoveIter = toRemove.constBegin();
auto filesIter = m_fileNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
while (*filesIter != *toRemoveIter) {
++filesIter;
QTC_ASSERT(filesIter != m_fileNodes.end(),
qDebug("File to remove is not part of specified folder!"));
}
delete *filesIter;
filesIter = m_fileNodes.erase(filesIter);
}
ProjectTree::emitDataChanged();
} }
void FolderNode::setFileNodes(const QList<FileNode *> &files) void FolderNode::setFileNodes(const QList<FileNode *> &files)
@@ -586,35 +580,30 @@ void FolderNode::setFileNodes(const QList<FileNode *> &files)
Adds folder nodes specified by \a subFolders to the node hierarchy below Adds folder nodes specified by \a subFolders to the node hierarchy below
\a parentFolder and emits the corresponding signals. \a parentFolder and emits the corresponding signals.
*/ */
void FolderNode::addFolderNodes(const QList<FolderNode*> &subFolders) void FolderNode::addFolderNode(FolderNode *folder)
{ {
Q_ASSERT(managingProject()); Q_ASSERT(managingProject());
if (subFolders.isEmpty()) QTC_ASSERT(!folder->parentFolderNode(),
return; qDebug("Project node has already a parent folder"));
folder->setParentFolderNode(this);
foreach (FolderNode *folder, subFolders) { // Find the correct place to insert
QTC_ASSERT(!folder->parentFolderNode(), if (m_folderNodes.count() == 0
qDebug("Project node has already a parent folder")); || m_folderNodes.last() < folder) {
folder->setParentFolderNode(this); // empty list or greater then last node
m_folderNodes.append(folder);
// Find the correct place to insert } else {
if (m_folderNodes.count() == 0 // Binary Search for insertion point
|| m_folderNodes.last() < folder) { auto it = std::lower_bound(m_folderNodes.begin(), m_folderNodes.end(), folder);
// empty list or greater then last node m_folderNodes.insert(it, folder);
m_folderNodes.append(folder);
} else {
// Binary Search for insertion point
auto it = std::lower_bound(m_folderNodes.begin(), m_folderNodes.end(), folder);
m_folderNodes.insert(it, folder);
}
// project nodes have to be added via addProjectNodes
QTC_ASSERT(folder->nodeType() != NodeType::Project,
qDebug("project nodes have to be added via addProjectNodes"));
} }
}
ProjectTree::emitDataChanged(); void FolderNode::addFolderNodes(const QList<FolderNode*> &subFolders)
{
for (FolderNode *folder : subFolders)
addFolderNode(folder);
} }
/*! /*!
@@ -623,30 +612,25 @@ void FolderNode::addFolderNodes(const QList<FolderNode*> &subFolders)
All objects in the \a subFolders list are deleted. All objects in the \a subFolders list are deleted.
*/ */
void FolderNode::removeFolderNodes()
{
qDeleteAll(m_folderNodes);
m_folderNodes.clear();
ProjectTree::emitDataChanged();
}
void FolderNode::removeFolderNodes(const QList<FolderNode*> &subFolders) void FolderNode::removeFolderNodes(const QList<FolderNode*> &subFolders)
{ {
Q_ASSERT(managingProject()); Q_ASSERT(managingProject());
for (FolderNode *folder : subFolders)
removeFolderNode(folder);
}
if (subFolders.isEmpty()) void FolderNode::removeFolderNode(FolderNode *folder)
return; {
Q_ASSERT(managingProject());
QList<FolderNode*> toRemove = subFolders; m_folderNodes.removeAll(folder);
Utils::sort(toRemove); delete folder;
auto toRemoveIter = toRemove.constBegin();
auto folderIter = m_folderNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
QTC_ASSERT((*toRemoveIter)->nodeType() != NodeType::Project,
qDebug("project nodes have to be removed via removeProjectNodes"));
while (*folderIter != *toRemoveIter) {
++folderIter;
QTC_ASSERT(folderIter != m_folderNodes.end(),
qDebug("Folder to remove is not part of specified folder!"));
}
delete *folderIter;
folderIter = m_folderNodes.erase(folderIter);
}
ProjectTree::emitDataChanged(); ProjectTree::emitDataChanged();
} }
@@ -841,6 +825,18 @@ void ProjectNode::removeProjectNode(ProjectNode *subProject)
delete subProject; delete subProject;
} }
void ProjectNode::makeEmpty()
{
removeProjectNodes();
setFolderNodes({});
setFileNodes({});
}
bool ProjectNode::isEmpty() const
{
return m_fileNodes.isEmpty() && m_folderNodes.isEmpty() && m_projectNodes.isEmpty();
}
/*! /*!
\class ProjectExplorer::SessionNode \class ProjectExplorer::SessionNode
*/ */

View File

@@ -245,14 +245,23 @@ public:
// determines if node will be shown in the flat view, by default folder and projects aren't shown // determines if node will be shown in the flat view, by default folder and projects aren't shown
virtual bool showInSimpleTree() const; virtual bool showInSimpleTree() const;
void addFileNode(FileNode *file);
void removeFileNodes();
void removeFileNode(FileNode *file);
void addFileNodes(const QList<FileNode*> &files); void addFileNodes(const QList<FileNode*> &files);
void removeFileNodes(const QList<FileNode*> &files); void removeFileNodes(const QList<FileNode*> &files);
void setFileNodes(const QList<FileNode*> &files); void setFileNodes(const QList<FileNode*> &files);
void addFolderNode(FolderNode *subFolder);
void removeFolderNodes();
void removeFolderNode(FolderNode *subFolder);
void addFolderNodes(const QList<FolderNode*> &subFolders); void addFolderNodes(const QList<FolderNode*> &subFolders);
void removeFolderNodes(const QList<FolderNode*> &subFolders); void removeFolderNodes(const QList<FolderNode*> &subFolders);
void setFolderNodes(const QList<FolderNode*> &folders); void setFolderNodes(const QList<FolderNode*> &folders);
void makeEmpty();
bool isEmpty() const;
FolderNode *asFolderNode() override { return this; } FolderNode *asFolderNode() override { return this; }
const FolderNode *asFolderNode() const override { return this; } const FolderNode *asFolderNode() const override { return this; }
@@ -304,6 +313,9 @@ public:
void removeProjectNodes(); void removeProjectNodes();
void removeProjectNode(ProjectNode *subProject); void removeProjectNode(ProjectNode *subProject);
void makeEmpty();
bool isEmpty() const;
ProjectNode *asProjectNode() final { return this; } ProjectNode *asProjectNode() final { return this; }
const ProjectNode *asProjectNode() const final { return this; } const ProjectNode *asProjectNode() const final { return this; }

View File

@@ -322,10 +322,9 @@ QbsGroupNode::QbsGroupNode(const qbs::GroupData &grp, const QString &productPath
setIcon(m_groupIcon); setIcon(m_groupIcon);
QbsFileNode *idx = new QbsFileNode(Utils::FileName::fromString(grp.location().filePath()), addFileNode(new QbsFileNode(Utils::FileName::fromString(grp.location().filePath()),
ProjectExplorer::FileType::Project, false, ProjectExplorer::FileType::Project, false,
grp.location().line()); grp.location().line()));
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx);
updateQbsGroupData(grp, productPath, true, true); updateQbsGroupData(grp, productPath, true, true);
} }
@@ -583,11 +582,10 @@ QbsProductNode::QbsProductNode(const qbs::Project &project, const qbs::ProductDa
setIcon(m_productIcon); setIcon(m_productIcon);
addFolderNodes(QList<ProjectExplorer::FolderNode *>() << m_generatedFilesNode); addFolderNode(m_generatedFilesNode);
auto idx = new QbsFileNode(Utils::FileName::fromString(prd.location().filePath()), addFileNode(new QbsFileNode(Utils::FileName::fromString(prd.location().filePath()),
ProjectExplorer::FileType::Project, false, ProjectExplorer::FileType::Project, false,
prd.location().line()); prd.location().line()));
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx);
setQbsProductData(project, prd); setQbsProductData(project, prd);
} }
@@ -760,38 +758,23 @@ QbsProjectNode::~QbsProjectNode()
void QbsProjectNode::update(const qbs::Project &qbsProject, const qbs::ProjectData &prjData) void QbsProjectNode::update(const qbs::Project &qbsProject, const qbs::ProjectData &prjData)
{ {
QList<ProjectExplorer::ProjectNode *> toRemove = projectNodes(); QTC_ASSERT(isEmpty(), makeEmpty());
foreach (const qbs::ProjectData &subData, prjData.subProjects()) { foreach (const qbs::ProjectData &subData, prjData.subProjects()) {
QbsProjectNode *qn = findProjectNode(subData.name()); auto subProject =
if (!qn) { new QbsProjectNode(Utils::FileName::fromString(subData.location().filePath()));
auto subProject = subProject->update(qbsProject, subData);
new QbsProjectNode(Utils::FileName::fromString(subData.location().filePath())); addProjectNode(subProject);
subProject->update(qbsProject, subData);
addProjectNode(subProject);
} else {
qn->update(qbsProject, subData);
toRemove.removeOne(qn);
}
} }
foreach (const qbs::ProductData &prd, prjData.products()) { foreach (const qbs::ProductData &prd, prjData.products())
QbsProductNode *qn = findProductNode(QbsProject::uniqueProductName(prd)); addProjectNode(new QbsProductNode(qbsProject, prd));
if (!qn) {
addProjectNode(new QbsProductNode(qbsProject, prd));
} else {
qn->setQbsProductData(qbsProject, prd);
toRemove.removeOne(qn);
}
}
if (!prjData.name().isEmpty()) if (!prjData.name().isEmpty())
setDisplayName(prjData.name()); setDisplayName(prjData.name());
else else
setDisplayName(project()->displayName()); setDisplayName(project()->displayName());
foreach (ProjectNode *node, toRemove)
removeProjectNode(node);
m_projectData = prjData; m_projectData = prjData;
} }
@@ -816,8 +799,7 @@ void QbsProjectNode::ctor()
m_projectIcon = generateIcon(QString::fromLatin1(ProjectExplorer::Constants::FILEOVERLAY_QT)); m_projectIcon = generateIcon(QString::fromLatin1(ProjectExplorer::Constants::FILEOVERLAY_QT));
setIcon(m_projectIcon); setIcon(m_projectIcon);
addFileNodes(QList<ProjectExplorer::FileNode *>() addFileNode(new ProjectExplorer::FileNode(filePath(), ProjectExplorer::FileType::Project, false));
<< new ProjectExplorer::FileNode(filePath(), ProjectExplorer::FileType::Project, false));
} }
QbsProductNode *QbsProjectNode::findProductNode(const QString &uniqueName) QbsProductNode *QbsProjectNode::findProductNode(const QString &uniqueName)
@@ -851,7 +833,7 @@ QbsRootProjectNode::QbsRootProjectNode(QbsProject *project) :
ProjectExplorer::NodeType::Folder, ProjectExplorer::NodeType::Folder,
QCoreApplication::translate("QbsRootProjectNode", "Qbs files"))) QCoreApplication::translate("QbsRootProjectNode", "Qbs files")))
{ {
addFolderNodes(QList<FolderNode *>() << m_buildSystemFiles); addFolderNode(m_buildSystemFiles);
} }
void QbsRootProjectNode::update() void QbsRootProjectNode::update()

View File

@@ -453,7 +453,6 @@ struct InternalNode
existingFolderNodes.insert(node->filePath().toString(), node); existingFolderNodes.insert(node->filePath().toString(), node);
QList<FolderNode *> foldersToRemove; QList<FolderNode *> foldersToRemove;
QList<FolderNode *> foldersToAdd;
typedef QPair<InternalNode *, FolderNode *> NodePair; typedef QPair<InternalNode *, FolderNode *> NodePair;
QList<NodePair> nodesToUpdate; QList<NodePair> nodesToUpdate;
@@ -480,7 +479,7 @@ struct InternalNode
nodesToUpdate << NodePair(*it, *oldit); nodesToUpdate << NodePair(*it, *oldit);
} else { } else {
FolderNode *newNode = createFolderNode(*it); FolderNode *newNode = createFolderNode(*it);
foldersToAdd << newNode; folder->addFolderNode(newNode);
nodesToUpdate << NodePair(*it, newNode); nodesToUpdate << NodePair(*it, newNode);
} }
} }
@@ -506,7 +505,7 @@ struct InternalNode
nodesToUpdate << NodePair(it.value(), *oldit); nodesToUpdate << NodePair(it.value(), *oldit);
} else { } else {
FolderNode *newNode = createFolderNode(it.value()); FolderNode *newNode = createFolderNode(it.value());
foldersToAdd << newNode; folder->addFolderNode(newNode);
nodesToUpdate << NodePair(it.value(), newNode); nodesToUpdate << NodePair(it.value(), newNode);
} }
} }
@@ -524,8 +523,6 @@ struct InternalNode
if (!foldersToRemove.isEmpty()) if (!foldersToRemove.isEmpty())
folder->removeFolderNodes(foldersToRemove); folder->removeFolderNodes(foldersToRemove);
if (!foldersToAdd.isEmpty())
folder->addFolderNodes(foldersToAdd);
foreach (const NodePair &np, nodesToUpdate) foreach (const NodePair &np, nodesToUpdate)
np.first->updateSubFolders(np.second); np.first->updateSubFolders(np.second);
@@ -582,7 +579,7 @@ struct InternalNode
dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(fn)->update(); dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(fn)->update();
} }
}; };
} } // Internal
QStringList QmakePriFileNode::baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir) QStringList QmakePriFileNode::baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir)
{ {
@@ -701,7 +698,7 @@ void QmakePriFileNode::update(const Internal::PriFileEvalResult &result)
{ {
// add project file node // add project file node
if (m_fileNodes.isEmpty()) if (m_fileNodes.isEmpty())
addFileNodes(QList<FileNode *>() << new FileNode(m_projectFilePath, FileType::Project, false)); addFileNode(new FileNode(m_projectFilePath, FileType::Project, false));
m_recursiveEnumerateFiles = result.recursiveEnumerateFiles; m_recursiveEnumerateFiles = result.recursiveEnumerateFiles;
watchFolders(result.folders.toSet()); watchFolders(result.folders.toSet());

View File

@@ -121,7 +121,6 @@ ResourceTopLevelNode::~ResourceTopLevelNode()
void ResourceTopLevelNode::update() void ResourceTopLevelNode::update()
{ {
QList<ProjectExplorer::FolderNode *> newPrefixList;
QMap<PrefixFolderLang, QList<ProjectExplorer::FileNode *>> filesToAdd; QMap<PrefixFolderLang, QList<ProjectExplorer::FileNode *>> filesToAdd;
QMap<PrefixFolderLang, QList<ProjectExplorer::FolderNode *>> foldersToAddToFolders; QMap<PrefixFolderLang, QList<ProjectExplorer::FolderNode *>> foldersToAddToFolders;
QMap<PrefixFolderLang, QList<ProjectExplorer::FolderNode *>> foldersToAddToPrefix; QMap<PrefixFolderLang, QList<ProjectExplorer::FolderNode *>> foldersToAddToPrefix;
@@ -139,8 +138,7 @@ void ResourceTopLevelNode::update()
PrefixFolderLang prefixId(prefix, QString(), lang); PrefixFolderLang prefixId(prefix, QString(), lang);
if (!prefixNodes.contains(prefixId)) { if (!prefixNodes.contains(prefixId)) {
ProjectExplorer::FolderNode *fn = new ResourceFolderNode(file.prefix(i), file.lang(i), this); ProjectExplorer::FolderNode *fn = new ResourceFolderNode(file.prefix(i), file.lang(i), this);
newPrefixList << fn; addFolderNode(fn);
prefixNodes.insert(prefixId, fn); prefixNodes.insert(prefixId, fn);
} }
ResourceFolderNode *currentPrefixNode = static_cast<ResourceFolderNode*>(prefixNodes[prefixId]); ResourceFolderNode *currentPrefixNode = static_cast<ResourceFolderNode*>(prefixNodes[prefixId]);
@@ -208,9 +206,6 @@ void ResourceTopLevelNode::update()
} }
} }
addFolderNodes(newPrefixList);
foreach (FolderNode *sfn, folderNodes()) { foreach (FolderNode *sfn, folderNodes()) {
ResourceFolderNode *srn = static_cast<ResourceFolderNode *>(sfn); ResourceFolderNode *srn = static_cast<ResourceFolderNode *>(sfn);
PrefixFolderLang folderId(srn->prefix(), QString(), srn->lang()); PrefixFolderLang folderId(srn->prefix(), QString(), srn->lang());