diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index bffda992ce6..c0753eacbef 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -38,10 +38,6 @@ #include -// -#include -// - // ---------------------------------------------------------------------- // Helpers: // ---------------------------------------------------------------------- @@ -54,9 +50,6 @@ public: FileTreeNode(const QString &n, FileTreeNode *p = 0) : parent(p), name(n) { - // - Q_ASSERT((!name.isEmpty() && p) || (name.isEmpty() && !p)); - // if (p) p->children.append(this); } @@ -77,11 +70,47 @@ public: 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) { foreach (FileTreeNode *c, node->children) simplify(c); + if (!node->parent) + return; + if (node->children.count() == 1) { FileTreeNode *child = node->children.at(0); if (child->isFile()) @@ -99,11 +128,6 @@ public: child->children.clear(); child->parent = 0; delete child; - - // - Q_ASSERT(!node->name.isEmpty()); - // - return; } } @@ -220,11 +244,11 @@ QList QbsBaseProjectNode::runConfigurations // QbsGroupNode: // -------------------------------------------------------------------- -QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp) : +QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp, const QString &productPath) : QbsBaseProjectNode(QString()), m_group(0) { - setGroup(grp); + setGroup(grp, productPath); } bool QbsGroupNode::isEnabled() const @@ -232,15 +256,18 @@ bool QbsGroupNode::isEnabled() const return static_cast(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; + m_productPath = productPath; + + // Set Product file node used to jump to the product setPath(group->location().fileName); setDisplayName(group->name()); - // Set Product file node used to jump to the product + // set up file node... QbsFileNode *indexFile = 0; if (!m_group) { indexFile = new QbsFileNode(group->location().fileName, @@ -254,6 +281,15 @@ void QbsGroupNode::setGroup(const qbs::GroupData *group) indexFile->emitNodeUpdated(); } + m_group = group; + + setGroup(this, group, productPath, QList() << indexFile); + emitNodeUpdated(); +} + +void QbsGroupNode::setGroup(QbsBaseProjectNode *root, const qbs::GroupData *group, + const QString &productPath, QList keepers) +{ // Build up a tree of nodes: FileTreeNode *tree = new FileTreeNode(QString()); @@ -265,33 +301,32 @@ void QbsGroupNode::setGroup(const qbs::GroupData *group) root = root->addPart(pathSegments.takeFirst()); } + FileTreeNode::reorder(tree, productPath, tree); FileTreeNode::simplify(tree); - setupFolders(this, tree, indexFile); - + setupFolders(root, root, tree, productPath, keepers); delete tree; - - m_group = group; - emitNodeUpdated(); } -void QbsGroupNode::setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode *node, - ProjectExplorer::FileNode *keep) +void QbsGroupNode::setupFolders(QbsBaseProjectNode *topLevel, ProjectExplorer::FolderNode *root, + FileTreeNode *node, const QString &baseDirPath, + QList keepers) { - // insert initial folder: - if (!node->parent && !node->name.isEmpty()) { - ProjectExplorer::FolderNode *fn = root->findSubFolder(node->name); - if (!fn) { - fn = new ProjectExplorer::FolderNode(node->name); - addFolderNodes(QList() << fn, root); - } - root = fn; + QList filesToRemove; + foreach (ProjectExplorer::FileNode *fn, root->fileNodes()) { + ProjectExplorer::Node *n = static_cast(fn); + if (!keepers.contains(n)) + filesToRemove.append(fn); } - QList filesToRemove = root->fileNodes(); - filesToRemove.removeAll(keep); QList filesToAdd; - QList foldersToRemove = root->subFolderNodes(); + QList foldersToKeep = keepers; + QList foldersToRemove; + foreach (ProjectExplorer::FolderNode *fn, root->subFolderNodes()) { + ProjectExplorer::Node *n = static_cast(fn); + if (!keepers.contains(n)) + foldersToRemove.append(fn); + } // insert subfolders foreach (FileTreeNode *c, node->children) { @@ -305,22 +340,31 @@ void QbsGroupNode::setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode fn = new ProjectExplorer::FileNode(path, ProjectExplorer::UnknownFileType, false); filesToAdd.append(fn); } - } else { - ProjectExplorer::FolderNode *fn = root->findSubFolder(path); - path = path.mid(root->path().length() + 1); // remove common prefix - if (fn) { - fn->emitNodeUpdated(); // enabled might have changed - foldersToRemove.removeOne(fn); - } else { - fn = new ProjectExplorer::FolderNode(path); - addFolderNodes(QList() << fn, root); - } - setupFolders(fn, c); + continue; } + + ProjectExplorer::FolderNode *fn = root->findSubFolder(path); + 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) { + fn->emitNodeUpdated(); // enabled might have changed + foldersToRemove.removeOne(fn); + } else { + fn = new ProjectExplorer::FolderNode(path); + topLevel->addFolderNodes(QList() << fn, root); + } + foldersToKeep.append(fn); + setupFolders(topLevel, fn, c, c->path()); } - addFileNodes(filesToAdd, root); - removeFileNodes(filesToRemove, root); - removeFolderNodes(foldersToRemove, root); + topLevel->removeFileNodes(filesToRemove, root); + topLevel->removeFolderNodes(foldersToRemove, root); + topLevel->addFileNodes(filesToAdd, root); } // -------------------------------------------------------------------- @@ -346,31 +390,42 @@ void QbsProductNode::setProduct(const qbs::ProductData *prd) setDisplayName(prd->name()); setPath(prd->location().fileName); + const QString &productPath = QFileInfo(prd->location().fileName).absolutePath(); // Set Product file node used to jump to the product QList files = fileNodes(); + QList toKeep; if (files.isEmpty()) { - addFileNodes(QList() - << new QbsFileNode(prd->location().fileName, - ProjectExplorer::ProjectFileType, false, - prd->location().line), - this); + QbsFileNode *idx = new QbsFileNode(prd->location().fileName, + ProjectExplorer::ProjectFileType, false, + prd->location().line); + addFileNodes(QList() << idx, this); + toKeep.append(idx); } else { - QbsFileNode *qbsFile = static_cast(files.at(0)); - qbsFile->setPath(prd->location().fileName); - qbsFile->setLine(prd->location().line); + QbsFileNode *idx = static_cast(files.at(0)); + idx->setPath(prd->location().fileName); + idx->setLine(prd->location().line); + toKeep.append(idx); } QList toAdd; QList toRemove = subProjectNodes(); 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()); if (qn) { toRemove.removeAll(qn); - qn->setGroup(&grp); + toKeep.append(qn); + qn->setGroup(&grp, productPath); } else { - toAdd << new QbsGroupNode(&grp); + qn = new QbsGroupNode(&grp, productPath); + toAdd.append(qn); + toKeep.append(qn); } } diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h index c398d4b7220..6f703cfda56 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.h +++ b/src/plugins/qbsprojectmanager/qbsnodes.h @@ -64,6 +64,8 @@ private: // QbsBaseProjectNode: // --------------------------------------------------------------------------- +class QbsGroupNode; + class QbsBaseProjectNode : public ProjectExplorer::ProjectNode { Q_OBJECT @@ -94,6 +96,9 @@ public: const QString &newFilePath); QList runConfigurationsFor(Node *node); + +private: + friend class QbsGroupNode; }; // -------------------------------------------------------------------- @@ -105,17 +110,24 @@ class QbsGroupNode : public QbsBaseProjectNode Q_OBJECT public: - QbsGroupNode(const qbs::GroupData *grp); + QbsGroupNode(const qbs::GroupData *grp, const QString &productPath); 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; } + QString productPath() const; + + static void setGroup(QbsBaseProjectNode *root, const qbs::GroupData *group, + const QString &productPath, QList keepers); + private: - void setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode *node, - ProjectExplorer::FileNode *keep = 0); + static void setupFolders(QbsBaseProjectNode *topLevel, FolderNode *root, FileTreeNode *node, + const QString &baseDirPath, + QList keepers = QList()); const qbs::GroupData *m_group; + QString m_productPath; }; // --------------------------------------------------------------------