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);
|
setProjectManager(manager);
|
||||||
setDocument(new Internal::CMakeFile(this, fileName));
|
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));
|
setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
|
||||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
|
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
|
||||||
|
|
||||||
@@ -244,7 +244,8 @@ void CMakeProject::updateProjectData()
|
|||||||
m_watchedFiles.insert(cm);
|
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!
|
bdm->clearFiles(); // Some of the FileNodes in files() were deleted!
|
||||||
|
|
||||||
updateApplicationAndDeploymentTargets();
|
updateApplicationAndDeploymentTargets();
|
||||||
@@ -416,98 +417,6 @@ bool CMakeProject::hasBuildTarget(const QString &title) const
|
|||||||
return Utils::anyOf(buildTargets(), [title](const CMakeBuildTarget &ct) { return ct.title == title; });
|
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
|
QString CMakeProject::displayName() const
|
||||||
{
|
{
|
||||||
return rootProjectNode()->displayName();
|
return rootProjectNode()->displayName();
|
||||||
@@ -515,9 +424,8 @@ QString CMakeProject::displayName() const
|
|||||||
|
|
||||||
QStringList CMakeProject::files(FilesMode fileMode) const
|
QStringList CMakeProject::files(FilesMode fileMode) const
|
||||||
{
|
{
|
||||||
QList<FileNode *> nodes;
|
const QList<FileNode *> nodes = Utils::filtered(rootProjectNode()->recursiveFileNodes(),
|
||||||
gatherFileNodes(rootProjectNode(), nodes);
|
[fileMode](const FileNode *fn) {
|
||||||
nodes = Utils::filtered(nodes, [fileMode](const FileNode *fn) {
|
|
||||||
const bool isGenerated = fn->isGenerated();
|
const bool isGenerated = fn->isGenerated();
|
||||||
switch (fileMode)
|
switch (fileMode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -118,9 +118,6 @@ private:
|
|||||||
void updateProjectData();
|
void updateProjectData();
|
||||||
void updateQmlJSCodeModel();
|
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();
|
void createGeneratedCodeModelSupport();
|
||||||
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
|
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
|
||||||
void updateTargetRunConfigurations(ProjectExplorer::Target *t);
|
void updateTargetRunConfigurations(ProjectExplorer::Target *t);
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
using namespace CMakeProjectManager;
|
using namespace CMakeProjectManager;
|
||||||
using namespace CMakeProjectManager::Internal;
|
using namespace CMakeProjectManager::Internal;
|
||||||
|
|
||||||
CMakeProjectNode::CMakeProjectNode(const Utils::FileName &fileName)
|
CMakeProjectNode::CMakeProjectNode(const Utils::FileName &dirName)
|
||||||
: ProjectExplorer::ProjectNode(fileName)
|
: ProjectExplorer::ProjectNode(dirName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Internal {
|
|||||||
class CMakeProjectNode : public ProjectExplorer::ProjectNode
|
class CMakeProjectNode : public ProjectExplorer::ProjectNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CMakeProjectNode(const Utils::FileName &fileName);
|
CMakeProjectNode(const Utils::FileName &dirName);
|
||||||
bool showInSimpleTree() const override;
|
bool showInSimpleTree() const override;
|
||||||
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const override;
|
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -269,11 +269,102 @@ QList<FileNode*> FolderNode::fileNodes() const
|
|||||||
return m_fileNodes;
|
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
|
QList<FolderNode*> FolderNode::subFolderNodes() const
|
||||||
{
|
{
|
||||||
return m_subFolderNodes;
|
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)
|
void FolderNode::accept(NodesVisitor *visitor)
|
||||||
{
|
{
|
||||||
visitor->visitFolderNode(this);
|
visitor->visitFolderNode(this);
|
||||||
@@ -707,7 +798,7 @@ ProjectNode *ProjectNode::asProjectNode()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
SessionNode::SessionNode() :
|
SessionNode::SessionNode() :
|
||||||
FolderNode(Utils::FileName::fromString(QLatin1String("session")), SessionNodeType)
|
FolderNode(Utils::FileName::fromString("session"), SessionNodeType)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
QList<ProjectAction> SessionNode::supportedActions(Node *node) const
|
QList<ProjectAction> SessionNode::supportedActions(Node *node) const
|
||||||
@@ -747,7 +838,7 @@ QList<ProjectNode*> SessionNode::projectNodes() const
|
|||||||
|
|
||||||
QString SessionNode::addFileFilter() 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)
|
void SessionNode::addProjectNodes(const QList<ProjectNode*> &projectNodes)
|
||||||
|
|||||||
@@ -172,8 +172,11 @@ public:
|
|||||||
QString displayName() const override;
|
QString displayName() const override;
|
||||||
QIcon icon() const;
|
QIcon icon() const;
|
||||||
|
|
||||||
QList<FileNode*> fileNodes() const;
|
QList<FileNode *> fileNodes() const;
|
||||||
QList<FolderNode*> subFolderNodes() const;
|
QList<FileNode *> recursiveFileNodes() const;
|
||||||
|
QList<FolderNode *> subFolderNodes() const;
|
||||||
|
FolderNode *findOrCreateSubFolderNode(const QString &directory);
|
||||||
|
void buildTree(QList<FileNode *> &files);
|
||||||
|
|
||||||
virtual void accept(NodesVisitor *visitor);
|
virtual void accept(NodesVisitor *visitor);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user