forked from qt-creator/qt-creator
Add helper code to generate trees of project nodes
Add helper code to FolderNode that enables the creation of a tree of File- and FolderNodes from a FolderNode and a list of FileNodes. Change-Id: Iba4b6a768fc3d0501851f141372e7e34913ba518 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
committed by
Tobias Hunger
parent
0ca288f518
commit
69627e494b
@@ -91,7 +91,7 @@ CMakeProject::CMakeProject(CMakeManager *manager, const FileName &fileName)
|
||||
setProjectManager(manager);
|
||||
setDocument(new Internal::CMakeFile(this, fileName));
|
||||
|
||||
setRootProjectNode(new CMakeProjectNode(fileName));
|
||||
setRootProjectNode(new CMakeProjectNode(Utils::FileName::fromString(fileName.toFileInfo().absolutePath())));
|
||||
setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
|
||||
|
||||
@@ -244,7 +244,8 @@ void CMakeProject::updateProjectData()
|
||||
m_watchedFiles.insert(cm);
|
||||
}
|
||||
|
||||
buildTree(static_cast<CMakeProjectNode *>(rootProjectNode()), bdm->files());
|
||||
QList<FileNode *> fileNodes = bdm->files();
|
||||
rootProjectNode()->buildTree(fileNodes);
|
||||
bdm->clearFiles(); // Some of the FileNodes in files() were deleted!
|
||||
|
||||
updateApplicationAndDeploymentTargets();
|
||||
@@ -416,98 +417,6 @@ bool CMakeProject::hasBuildTarget(const QString &title) const
|
||||
return Utils::anyOf(buildTargets(), [title](const CMakeBuildTarget &ct) { return ct.title == title; });
|
||||
}
|
||||
|
||||
void CMakeProject::gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list) const
|
||||
{
|
||||
foreach (ProjectExplorer::FolderNode *folder, parent->subFolderNodes())
|
||||
gatherFileNodes(folder, list);
|
||||
foreach (ProjectExplorer::FileNode *file, parent->fileNodes())
|
||||
list.append(file);
|
||||
}
|
||||
|
||||
bool sortNodesByPath(Node *a, Node *b)
|
||||
{
|
||||
return a->filePath() < b->filePath();
|
||||
}
|
||||
|
||||
void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> newList)
|
||||
{
|
||||
// Gather old list
|
||||
QList<ProjectExplorer::FileNode *> oldList;
|
||||
gatherFileNodes(rootNode, oldList);
|
||||
Utils::sort(oldList, sortNodesByPath);
|
||||
Utils::sort(newList, sortNodesByPath);
|
||||
|
||||
QList<ProjectExplorer::FileNode *> added;
|
||||
QList<ProjectExplorer::FileNode *> deleted;
|
||||
|
||||
ProjectExplorer::compareSortedLists(oldList, newList, deleted, added, sortNodesByPath);
|
||||
|
||||
qDeleteAll(ProjectExplorer::subtractSortedList(newList, added, sortNodesByPath));
|
||||
|
||||
QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > addedFolderMapping;
|
||||
QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > deletedFolderMapping;
|
||||
|
||||
// add added nodes
|
||||
foreach (ProjectExplorer::FileNode *fn, added) {
|
||||
// Get relative path to rootNode
|
||||
QString parentDir = fn->filePath().toFileInfo().absolutePath();
|
||||
ProjectExplorer::FolderNode *folder = findOrCreateFolder(rootNode, parentDir);
|
||||
addedFolderMapping[folder] << fn;
|
||||
}
|
||||
|
||||
for (auto i = addedFolderMapping.constBegin(); i != addedFolderMapping.constEnd(); ++i)
|
||||
i.key()->addFileNodes(i.value());
|
||||
|
||||
// remove old file nodes and check whether folder nodes can be removed
|
||||
foreach (ProjectExplorer::FileNode *fn, deleted)
|
||||
deletedFolderMapping[fn->parentFolderNode()] << fn;
|
||||
|
||||
for (auto i = deletedFolderMapping.constBegin(); i != deletedFolderMapping.constEnd(); ++i) {
|
||||
ProjectExplorer::FolderNode *parent = i.key();
|
||||
parent->removeFileNodes(i.value());
|
||||
// Check for empty parent
|
||||
while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) {
|
||||
ProjectExplorer::FolderNode *grandparent = parent->parentFolderNode();
|
||||
grandparent->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent);
|
||||
parent = grandparent;
|
||||
if (parent == rootNode)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode *rootNode, QString directory)
|
||||
{
|
||||
FileName path = rootNode->filePath().parentDir();
|
||||
QDir rootParentDir(path.toString());
|
||||
QString relativePath = rootParentDir.relativeFilePath(directory);
|
||||
if (relativePath == QLatin1String("."))
|
||||
relativePath.clear();
|
||||
QStringList parts = relativePath.split(QLatin1Char('/'), QString::SkipEmptyParts);
|
||||
ProjectExplorer::FolderNode *parent = rootNode;
|
||||
foreach (const QString &part, parts) {
|
||||
path.appendPath(part);
|
||||
// Find folder in subFolders
|
||||
bool found = false;
|
||||
foreach (ProjectExplorer::FolderNode *folder, parent->subFolderNodes()) {
|
||||
if (folder->filePath() == path) {
|
||||
// yeah found something :)
|
||||
parent = folder;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// No FolderNode yet, so create it
|
||||
auto tmp = new ProjectExplorer::FolderNode(path);
|
||||
tmp->setDisplayName(part);
|
||||
parent->addFolderNodes(QList<ProjectExplorer::FolderNode *>() << tmp);
|
||||
parent = tmp;
|
||||
}
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
QString CMakeProject::displayName() const
|
||||
{
|
||||
return rootProjectNode()->displayName();
|
||||
@@ -515,9 +424,8 @@ QString CMakeProject::displayName() const
|
||||
|
||||
QStringList CMakeProject::files(FilesMode fileMode) const
|
||||
{
|
||||
QList<FileNode *> nodes;
|
||||
gatherFileNodes(rootProjectNode(), nodes);
|
||||
nodes = Utils::filtered(nodes, [fileMode](const FileNode *fn) {
|
||||
const QList<FileNode *> nodes = Utils::filtered(rootProjectNode()->recursiveFileNodes(),
|
||||
[fileMode](const FileNode *fn) {
|
||||
const bool isGenerated = fn->isGenerated();
|
||||
switch (fileMode)
|
||||
{
|
||||
|
||||
@@ -118,9 +118,6 @@ private:
|
||||
void updateProjectData();
|
||||
void updateQmlJSCodeModel();
|
||||
|
||||
void buildTree(Internal::CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list);
|
||||
void gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list) const;
|
||||
ProjectExplorer::FolderNode *findOrCreateFolder(Internal::CMakeProjectNode *rootNode, QString directory);
|
||||
void createGeneratedCodeModelSupport();
|
||||
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
|
||||
void updateTargetRunConfigurations(ProjectExplorer::Target *t);
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
using namespace CMakeProjectManager;
|
||||
using namespace CMakeProjectManager::Internal;
|
||||
|
||||
CMakeProjectNode::CMakeProjectNode(const Utils::FileName &fileName)
|
||||
: ProjectExplorer::ProjectNode(fileName)
|
||||
CMakeProjectNode::CMakeProjectNode(const Utils::FileName &dirName)
|
||||
: ProjectExplorer::ProjectNode(dirName)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Internal {
|
||||
class CMakeProjectNode : public ProjectExplorer::ProjectNode
|
||||
{
|
||||
public:
|
||||
CMakeProjectNode(const Utils::FileName &fileName);
|
||||
CMakeProjectNode(const Utils::FileName &dirName);
|
||||
bool showInSimpleTree() const override;
|
||||
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const override;
|
||||
};
|
||||
|
||||
@@ -269,11 +269,102 @@ QList<FileNode*> FolderNode::fileNodes() const
|
||||
return m_fileNodes;
|
||||
}
|
||||
|
||||
QList<FileNode *> FolderNode::recursiveFileNodes() const
|
||||
{
|
||||
QList<FileNode *> result = fileNodes();
|
||||
foreach (ProjectExplorer::FolderNode *folder, subFolderNodes())
|
||||
result.append(folder->recursiveFileNodes());
|
||||
return result;
|
||||
}
|
||||
|
||||
QList<FolderNode*> FolderNode::subFolderNodes() const
|
||||
{
|
||||
return m_subFolderNodes;
|
||||
}
|
||||
|
||||
FolderNode *FolderNode::findOrCreateSubFolderNode(const QString &directory)
|
||||
{
|
||||
Utils::FileName path = filePath();
|
||||
QDir parentDir(path.toString());
|
||||
QString relativePath = parentDir.relativeFilePath(directory);
|
||||
if (relativePath == ".")
|
||||
relativePath.clear();
|
||||
QStringList parts = relativePath.split('/', QString::SkipEmptyParts);
|
||||
ProjectExplorer::FolderNode *parent = this;
|
||||
foreach (const QString &part, parts) {
|
||||
path.appendPath(part);
|
||||
// Find folder in subFolders
|
||||
bool found = false;
|
||||
foreach (ProjectExplorer::FolderNode *folder, parent->subFolderNodes()) {
|
||||
if (folder->filePath() == path) {
|
||||
// yeah found something :)
|
||||
parent = folder;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// No FolderNode yet, so create it
|
||||
auto tmp = new ProjectExplorer::FolderNode(path);
|
||||
tmp->setDisplayName(part);
|
||||
parent->addFolderNodes(QList<ProjectExplorer::FolderNode *>({ tmp }));
|
||||
parent = tmp;
|
||||
}
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
static bool sortNodesByPath(Node *a, Node *b)
|
||||
{
|
||||
return a->filePath() < b->filePath();
|
||||
}
|
||||
|
||||
void FolderNode::buildTree(QList<FileNode *> &files)
|
||||
{
|
||||
// Gather old list
|
||||
QList<ProjectExplorer::FileNode *> oldFiles = recursiveFileNodes();
|
||||
Utils::sort(oldFiles, sortNodesByPath);
|
||||
Utils::sort(files, sortNodesByPath);
|
||||
|
||||
QList<ProjectExplorer::FileNode *> added;
|
||||
QList<ProjectExplorer::FileNode *> deleted;
|
||||
|
||||
ProjectExplorer::compareSortedLists(oldFiles, files, deleted, added, sortNodesByPath);
|
||||
|
||||
qDeleteAll(ProjectExplorer::subtractSortedList(files, added, sortNodesByPath));
|
||||
|
||||
QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > addedFolderMapping;
|
||||
QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > deletedFolderMapping;
|
||||
|
||||
// add added nodes
|
||||
foreach (ProjectExplorer::FileNode *fn, added) {
|
||||
// Get relative path to rootNode
|
||||
QString parentDir = fn->filePath().toFileInfo().absolutePath();
|
||||
ProjectExplorer::FolderNode *folder = findOrCreateSubFolderNode(parentDir);
|
||||
addedFolderMapping[folder] << fn;
|
||||
}
|
||||
|
||||
for (auto i = addedFolderMapping.constBegin(); i != addedFolderMapping.constEnd(); ++i)
|
||||
i.key()->addFileNodes(i.value());
|
||||
|
||||
// remove old file nodes and check whether folder nodes can be removed
|
||||
foreach (ProjectExplorer::FileNode *fn, deleted)
|
||||
deletedFolderMapping[fn->parentFolderNode()] << fn;
|
||||
|
||||
for (auto i = deletedFolderMapping.constBegin(); i != deletedFolderMapping.constEnd(); ++i) {
|
||||
ProjectExplorer::FolderNode *parent = i.key();
|
||||
parent->removeFileNodes(i.value());
|
||||
// Check for empty parent
|
||||
while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) {
|
||||
ProjectExplorer::FolderNode *grandparent = parent->parentFolderNode();
|
||||
grandparent->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent);
|
||||
parent = grandparent;
|
||||
if (parent == this)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FolderNode::accept(NodesVisitor *visitor)
|
||||
{
|
||||
visitor->visitFolderNode(this);
|
||||
@@ -707,7 +798,7 @@ ProjectNode *ProjectNode::asProjectNode()
|
||||
*/
|
||||
|
||||
SessionNode::SessionNode() :
|
||||
FolderNode(Utils::FileName::fromString(QLatin1String("session")), SessionNodeType)
|
||||
FolderNode(Utils::FileName::fromString("session"), SessionNodeType)
|
||||
{ }
|
||||
|
||||
QList<ProjectAction> SessionNode::supportedActions(Node *node) const
|
||||
@@ -747,7 +838,7 @@ QList<ProjectNode*> SessionNode::projectNodes() const
|
||||
|
||||
QString SessionNode::addFileFilter() const
|
||||
{
|
||||
return QLatin1String("*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;");
|
||||
return QString::fromLatin1("*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;");
|
||||
}
|
||||
|
||||
void SessionNode::addProjectNodes(const QList<ProjectNode*> &projectNodes)
|
||||
|
||||
@@ -173,7 +173,10 @@ public:
|
||||
QIcon icon() const;
|
||||
|
||||
QList<FileNode *> fileNodes() const;
|
||||
QList<FileNode *> recursiveFileNodes() const;
|
||||
QList<FolderNode *> subFolderNodes() const;
|
||||
FolderNode *findOrCreateSubFolderNode(const QString &directory);
|
||||
void buildTree(QList<FileNode *> &files);
|
||||
|
||||
virtual void accept(NodesVisitor *visitor);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user