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:
Tobias Hunger
2013-04-16 16:19:11 +02:00
parent 13913ed391
commit 892066cfa6
2 changed files with 130 additions and 63 deletions

View File

@@ -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);
} }
} }

View File

@@ -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;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------