forked from qt-creator/qt-creator
Qbs: Fix display of project tree
Do not display a folder below the Groups if the files are in the same directory as the product definition. The product directory is chosen since the groups can be implemented elsewhere as done in creator for the pluginspec groups. Task-number: QBS-257 (partial) Change-Id: I0e39bbc62f991f2485adb3c4b47dd62dfa72763c Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
@@ -38,10 +38,6 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
// <debug>
|
|
||||||
#include <QDebug>
|
|
||||||
// </debug>
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// Helpers:
|
// Helpers:
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -54,9 +50,6 @@ public:
|
|||||||
FileTreeNode(const QString &n, FileTreeNode *p = 0) :
|
FileTreeNode(const QString &n, FileTreeNode *p = 0) :
|
||||||
parent(p), name(n)
|
parent(p), name(n)
|
||||||
{
|
{
|
||||||
// <debug>
|
|
||||||
Q_ASSERT((!name.isEmpty() && p) || (name.isEmpty() && !p));
|
|
||||||
// </debug>
|
|
||||||
if (p)
|
if (p)
|
||||||
p->children.append(this);
|
p->children.append(this);
|
||||||
}
|
}
|
||||||
@@ -77,11 +70,47 @@ public:
|
|||||||
|
|
||||||
bool isFile() { return children.isEmpty(); }
|
bool isFile() { return children.isEmpty(); }
|
||||||
|
|
||||||
|
// Moves the node pointing to basedir to the root of the tree and deletes any now empty nodes.
|
||||||
|
static void reorder(FileTreeNode *node, const QString &basedir, FileTreeNode *root)
|
||||||
|
{
|
||||||
|
if (node != root && node->path() == basedir) {
|
||||||
|
// move node to root:
|
||||||
|
FileTreeNode *parent = node->parent;
|
||||||
|
if (parent)
|
||||||
|
parent->children.removeOne(node);
|
||||||
|
root->children.append(node);
|
||||||
|
node->parent = root;
|
||||||
|
if (basedir.startsWith(QLatin1Char('/')))
|
||||||
|
node->name = basedir.mid(1);
|
||||||
|
else
|
||||||
|
node->name = basedir;
|
||||||
|
|
||||||
|
// clean up now-empty nodes:
|
||||||
|
while (parent) {
|
||||||
|
if (parent->children.count() == 0) {
|
||||||
|
FileTreeNode *current = parent;
|
||||||
|
parent = current->parent;
|
||||||
|
parent->children.removeOne(current);
|
||||||
|
current->parent = 0;
|
||||||
|
delete current;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (FileTreeNode *n, node->children)
|
||||||
|
reorder(n, basedir, root);
|
||||||
|
}
|
||||||
|
|
||||||
static void simplify(FileTreeNode *node)
|
static void simplify(FileTreeNode *node)
|
||||||
{
|
{
|
||||||
foreach (FileTreeNode *c, node->children)
|
foreach (FileTreeNode *c, node->children)
|
||||||
simplify(c);
|
simplify(c);
|
||||||
|
|
||||||
|
if (!node->parent)
|
||||||
|
return;
|
||||||
|
|
||||||
if (node->children.count() == 1) {
|
if (node->children.count() == 1) {
|
||||||
FileTreeNode *child = node->children.at(0);
|
FileTreeNode *child = node->children.at(0);
|
||||||
if (child->isFile())
|
if (child->isFile())
|
||||||
@@ -99,11 +128,6 @@ public:
|
|||||||
child->children.clear();
|
child->children.clear();
|
||||||
child->parent = 0;
|
child->parent = 0;
|
||||||
delete child;
|
delete child;
|
||||||
|
|
||||||
// <debug>
|
|
||||||
Q_ASSERT(!node->name.isEmpty());
|
|
||||||
// </debug>
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,11 +244,11 @@ QList<ProjectExplorer::RunConfiguration *> QbsBaseProjectNode::runConfigurations
|
|||||||
// QbsGroupNode:
|
// QbsGroupNode:
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp) :
|
QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp, const QString &productPath) :
|
||||||
QbsBaseProjectNode(QString()),
|
QbsBaseProjectNode(QString()),
|
||||||
m_group(0)
|
m_group(0)
|
||||||
{
|
{
|
||||||
setGroup(grp);
|
setGroup(grp, productPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QbsGroupNode::isEnabled() const
|
bool QbsGroupNode::isEnabled() const
|
||||||
@@ -232,15 +256,18 @@ bool QbsGroupNode::isEnabled() const
|
|||||||
return static_cast<QbsProductNode *>(parentFolderNode())->isEnabled() && group()->isEnabled();
|
return static_cast<QbsProductNode *>(parentFolderNode())->isEnabled() && group()->isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QbsGroupNode::setGroup(const qbs::GroupData *group)
|
void QbsGroupNode::setGroup(const qbs::GroupData *group, const QString &productPath)
|
||||||
{
|
{
|
||||||
if (group == m_group)
|
if (group == m_group && productPath == m_productPath)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_productPath = productPath;
|
||||||
|
|
||||||
|
// Set Product file node used to jump to the product
|
||||||
setPath(group->location().fileName);
|
setPath(group->location().fileName);
|
||||||
setDisplayName(group->name());
|
setDisplayName(group->name());
|
||||||
|
|
||||||
// Set Product file node used to jump to the product
|
// set up file node...
|
||||||
QbsFileNode *indexFile = 0;
|
QbsFileNode *indexFile = 0;
|
||||||
if (!m_group) {
|
if (!m_group) {
|
||||||
indexFile = new QbsFileNode(group->location().fileName,
|
indexFile = new QbsFileNode(group->location().fileName,
|
||||||
@@ -254,6 +281,15 @@ void QbsGroupNode::setGroup(const qbs::GroupData *group)
|
|||||||
indexFile->emitNodeUpdated();
|
indexFile->emitNodeUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_group = group;
|
||||||
|
|
||||||
|
setGroup(this, group, productPath, QList<ProjectExplorer::Node *>() << indexFile);
|
||||||
|
emitNodeUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QbsGroupNode::setGroup(QbsBaseProjectNode *root, const qbs::GroupData *group,
|
||||||
|
const QString &productPath, QList<ProjectExplorer::Node *> keepers)
|
||||||
|
{
|
||||||
// Build up a tree of nodes:
|
// Build up a tree of nodes:
|
||||||
FileTreeNode *tree = new FileTreeNode(QString());
|
FileTreeNode *tree = new FileTreeNode(QString());
|
||||||
|
|
||||||
@@ -265,33 +301,32 @@ void QbsGroupNode::setGroup(const qbs::GroupData *group)
|
|||||||
root = root->addPart(pathSegments.takeFirst());
|
root = root->addPart(pathSegments.takeFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileTreeNode::reorder(tree, productPath, tree);
|
||||||
FileTreeNode::simplify(tree);
|
FileTreeNode::simplify(tree);
|
||||||
setupFolders(this, tree, indexFile);
|
setupFolders(root, root, tree, productPath, keepers);
|
||||||
|
|
||||||
delete tree;
|
delete tree;
|
||||||
|
|
||||||
m_group = group;
|
|
||||||
emitNodeUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QbsGroupNode::setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode *node,
|
void QbsGroupNode::setupFolders(QbsBaseProjectNode *topLevel, ProjectExplorer::FolderNode *root,
|
||||||
ProjectExplorer::FileNode *keep)
|
FileTreeNode *node, const QString &baseDirPath,
|
||||||
|
QList<ProjectExplorer::Node *> keepers)
|
||||||
{
|
{
|
||||||
// insert initial folder:
|
QList<ProjectExplorer::FileNode *> filesToRemove;
|
||||||
if (!node->parent && !node->name.isEmpty()) {
|
foreach (ProjectExplorer::FileNode *fn, root->fileNodes()) {
|
||||||
ProjectExplorer::FolderNode *fn = root->findSubFolder(node->name);
|
ProjectExplorer::Node *n = static_cast<ProjectExplorer::Node *>(fn);
|
||||||
if (!fn) {
|
if (!keepers.contains(n))
|
||||||
fn = new ProjectExplorer::FolderNode(node->name);
|
filesToRemove.append(fn);
|
||||||
addFolderNodes(QList<ProjectExplorer::FolderNode *>() << fn, root);
|
|
||||||
}
|
|
||||||
root = fn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ProjectExplorer::FileNode *> filesToRemove = root->fileNodes();
|
|
||||||
filesToRemove.removeAll(keep);
|
|
||||||
QList<ProjectExplorer::FileNode *> filesToAdd;
|
QList<ProjectExplorer::FileNode *> filesToAdd;
|
||||||
|
|
||||||
QList<ProjectExplorer::FolderNode *> foldersToRemove = root->subFolderNodes();
|
QList<ProjectExplorer::Node *> foldersToKeep = keepers;
|
||||||
|
QList<ProjectExplorer::FolderNode *> foldersToRemove;
|
||||||
|
foreach (ProjectExplorer::FolderNode *fn, root->subFolderNodes()) {
|
||||||
|
ProjectExplorer::Node *n = static_cast<ProjectExplorer::Node *>(fn);
|
||||||
|
if (!keepers.contains(n))
|
||||||
|
foldersToRemove.append(fn);
|
||||||
|
}
|
||||||
|
|
||||||
// insert subfolders
|
// insert subfolders
|
||||||
foreach (FileTreeNode *c, node->children) {
|
foreach (FileTreeNode *c, node->children) {
|
||||||
@@ -305,22 +340,31 @@ void QbsGroupNode::setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode
|
|||||||
fn = new ProjectExplorer::FileNode(path, ProjectExplorer::UnknownFileType, false);
|
fn = new ProjectExplorer::FileNode(path, ProjectExplorer::UnknownFileType, false);
|
||||||
filesToAdd.append(fn);
|
filesToAdd.append(fn);
|
||||||
}
|
}
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ProjectExplorer::FolderNode *fn = root->findSubFolder(path);
|
ProjectExplorer::FolderNode *fn = root->findSubFolder(path);
|
||||||
path = path.mid(root->path().length() + 1); // remove common prefix
|
if (path == baseDirPath) {
|
||||||
|
setupFolders(topLevel, root, c, c->path(), foldersToKeep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.startsWith(baseDirPath + QLatin1Char('/')))
|
||||||
|
path = path.mid(baseDirPath.length() + 1); // remove common prefix
|
||||||
|
|
||||||
if (fn) {
|
if (fn) {
|
||||||
fn->emitNodeUpdated(); // enabled might have changed
|
fn->emitNodeUpdated(); // enabled might have changed
|
||||||
foldersToRemove.removeOne(fn);
|
foldersToRemove.removeOne(fn);
|
||||||
} else {
|
} else {
|
||||||
fn = new ProjectExplorer::FolderNode(path);
|
fn = new ProjectExplorer::FolderNode(path);
|
||||||
addFolderNodes(QList<ProjectExplorer::FolderNode *>() << fn, root);
|
topLevel->addFolderNodes(QList<ProjectExplorer::FolderNode *>() << fn, root);
|
||||||
}
|
}
|
||||||
setupFolders(fn, c);
|
foldersToKeep.append(fn);
|
||||||
|
setupFolders(topLevel, fn, c, c->path());
|
||||||
}
|
}
|
||||||
}
|
topLevel->removeFileNodes(filesToRemove, root);
|
||||||
addFileNodes(filesToAdd, root);
|
topLevel->removeFolderNodes(foldersToRemove, root);
|
||||||
removeFileNodes(filesToRemove, root);
|
topLevel->addFileNodes(filesToAdd, root);
|
||||||
removeFolderNodes(foldersToRemove, root);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
@@ -346,31 +390,42 @@ void QbsProductNode::setProduct(const qbs::ProductData *prd)
|
|||||||
|
|
||||||
setDisplayName(prd->name());
|
setDisplayName(prd->name());
|
||||||
setPath(prd->location().fileName);
|
setPath(prd->location().fileName);
|
||||||
|
const QString &productPath = QFileInfo(prd->location().fileName).absolutePath();
|
||||||
|
|
||||||
// Set Product file node used to jump to the product
|
// Set Product file node used to jump to the product
|
||||||
QList<ProjectExplorer::FileNode *> files = fileNodes();
|
QList<ProjectExplorer::FileNode *> files = fileNodes();
|
||||||
|
QList<ProjectExplorer::Node *> toKeep;
|
||||||
if (files.isEmpty()) {
|
if (files.isEmpty()) {
|
||||||
addFileNodes(QList<ProjectExplorer::FileNode *>()
|
QbsFileNode *idx = new QbsFileNode(prd->location().fileName,
|
||||||
<< new QbsFileNode(prd->location().fileName,
|
|
||||||
ProjectExplorer::ProjectFileType, false,
|
ProjectExplorer::ProjectFileType, false,
|
||||||
prd->location().line),
|
prd->location().line);
|
||||||
this);
|
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this);
|
||||||
|
toKeep.append(idx);
|
||||||
} else {
|
} else {
|
||||||
QbsFileNode *qbsFile = static_cast<QbsFileNode *>(files.at(0));
|
QbsFileNode *idx = static_cast<QbsFileNode *>(files.at(0));
|
||||||
qbsFile->setPath(prd->location().fileName);
|
idx->setPath(prd->location().fileName);
|
||||||
qbsFile->setLine(prd->location().line);
|
idx->setLine(prd->location().line);
|
||||||
|
toKeep.append(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ProjectExplorer::ProjectNode *> toAdd;
|
QList<ProjectExplorer::ProjectNode *> toAdd;
|
||||||
QList<ProjectExplorer::ProjectNode *> toRemove = subProjectNodes();
|
QList<ProjectExplorer::ProjectNode *> toRemove = subProjectNodes();
|
||||||
|
|
||||||
foreach (const qbs::GroupData &grp, prd->groups()) {
|
foreach (const qbs::GroupData &grp, prd->groups()) {
|
||||||
|
if (grp.name() == prd->name() && grp.location() == prd->location()) {
|
||||||
|
// Set implicit product group right onto this node:
|
||||||
|
QbsGroupNode::setGroup(this, &grp, productPath, toKeep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
QbsGroupNode *qn = findGroupNode(grp.name());
|
QbsGroupNode *qn = findGroupNode(grp.name());
|
||||||
if (qn) {
|
if (qn) {
|
||||||
toRemove.removeAll(qn);
|
toRemove.removeAll(qn);
|
||||||
qn->setGroup(&grp);
|
toKeep.append(qn);
|
||||||
|
qn->setGroup(&grp, productPath);
|
||||||
} else {
|
} else {
|
||||||
toAdd << new QbsGroupNode(&grp);
|
qn = new QbsGroupNode(&grp, productPath);
|
||||||
|
toAdd.append(qn);
|
||||||
|
toKeep.append(qn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -64,6 +64,8 @@ private:
|
|||||||
// QbsBaseProjectNode:
|
// QbsBaseProjectNode:
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class QbsGroupNode;
|
||||||
|
|
||||||
class QbsBaseProjectNode : public ProjectExplorer::ProjectNode
|
class QbsBaseProjectNode : public ProjectExplorer::ProjectNode
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -94,6 +96,9 @@ public:
|
|||||||
const QString &newFilePath);
|
const QString &newFilePath);
|
||||||
|
|
||||||
QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
|
QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class QbsGroupNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
@@ -105,17 +110,24 @@ class QbsGroupNode : public QbsBaseProjectNode
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QbsGroupNode(const qbs::GroupData *grp);
|
QbsGroupNode(const qbs::GroupData *grp, const QString &productPath);
|
||||||
|
|
||||||
bool isEnabled() const;
|
bool isEnabled() const;
|
||||||
void setGroup(const qbs::GroupData *group);
|
void setGroup(const qbs::GroupData *group, const QString &productPath);
|
||||||
const qbs::GroupData *group() const { return m_group; }
|
const qbs::GroupData *group() const { return m_group; }
|
||||||
|
|
||||||
|
QString productPath() const;
|
||||||
|
|
||||||
|
static void setGroup(QbsBaseProjectNode *root, const qbs::GroupData *group,
|
||||||
|
const QString &productPath, QList<Node *> keepers);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode *node,
|
static void setupFolders(QbsBaseProjectNode *topLevel, FolderNode *root, FileTreeNode *node,
|
||||||
ProjectExplorer::FileNode *keep = 0);
|
const QString &baseDirPath,
|
||||||
|
QList<ProjectExplorer::Node *> keepers = QList<ProjectExplorer::Node *>());
|
||||||
|
|
||||||
const qbs::GroupData *m_group;
|
const qbs::GroupData *m_group;
|
||||||
|
QString m_productPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user