summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Hunger <tobias.hunger@digia.com>2013-01-22 15:41:28 +0100
committerTobias Hunger <tobias.hunger@digia.com>2013-01-24 15:11:22 +0100
commitf264a4062f3d22f9ec7772c7d4f17630ae5449cf (patch)
treec936a50b4f63752b50cb7399f6e533961a2de3c0
parent0e9231c75621a52624499a6c02bdc2ab1de893b5 (diff)
downloadqt-creator-f264a4062f3d22f9ec7772c7d4f17630ae5449cf.tar.gz
Qbs: Reuse ProjectNodes
This preserves state of the Projects view Change-Id: I335ed3abf58c811cd44531f91f74a911b139decb
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp28
-rw-r--r--src/plugins/projectexplorer/projectnodes.h8
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.cpp306
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodes.h25
4 files changed, 278 insertions, 89 deletions
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index f493856ce9..20864ec47e 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -73,6 +73,16 @@ Node::Node(NodeType nodeType,
}
+/*!
+ * \brief The path of the file representing this node.
+ *
+ * This method does not emit any signals, that has to be done by the calling class!
+ */
+void Node::setPath(const QString &path)
+{
+ m_path = path;
+}
+
NodeType Node::nodeType() const
{
return m_nodeType;
@@ -246,6 +256,24 @@ void FolderNode::setIcon(const QIcon &icon)
m_icon = icon;
}
+FileNode *FolderNode::findFile(const QString &path)
+{
+ foreach (FileNode *n, fileNodes()) {
+ if (n->path() == path)
+ return n;
+ }
+ return 0;
+}
+
+FolderNode *FolderNode::findSubFolder(const QString &path)
+{
+ foreach (FolderNode *n, subFolderNodes()) {
+ if (n->path() == path)
+ return n;
+ }
+ return 0;
+}
+
/*!
\class ProjectExplorer::VirtualFolderNode
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index bc1e13774c..8d820927ed 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -91,6 +91,9 @@ public:
virtual QString tooltip() const;
virtual bool isEnabled() const;
+ void setPath(const QString &path); // this does not call emitNodeUpdated!
+ void emitNodeUpdated();
+
protected:
Node(NodeType nodeType, const QString &path);
@@ -98,8 +101,6 @@ protected:
void setProjectNode(ProjectNode *project);
void setParentFolderNode(FolderNode *parentFolder);
- void emitNodeUpdated();
-
private:
NodeType m_nodeType;
ProjectNode *m_projectNode;
@@ -141,6 +142,9 @@ public:
void setDisplayName(const QString &name);
void setIcon(const QIcon &icon);
+ FileNode *findFile(const QString &path);
+ FolderNode *findSubFolder(const QString &path);
+
protected:
QList<FolderNode*> m_subFolderNodes;
QList<FileNode*> m_fileNodes;
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp
index f26df774f1..d9f1c3bc7b 100644
--- a/src/plugins/qbsprojectmanager/qbsnodes.cpp
+++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp
@@ -35,27 +35,89 @@
#include <api/project.h> // qbs
-#include <QFileInfo>
+#include <QDir>
-// --------------------------------------------------------------------
+// <debug>
+#include <QDebug>
+// </debug>
+
+// ----------------------------------------------------------------------
// Helpers:
-// --------------------------------------------------------------------
+// ----------------------------------------------------------------------
-namespace {
+namespace QbsProjectManager {
+namespace Internal {
-ProjectExplorer::FolderNode *findFolder(ProjectExplorer::FolderNode *root, const QString &name)
-{
- foreach (ProjectExplorer::FolderNode *n, root->subFolderNodes()) {
- if (n->displayName() == name)
- return n;
+class FileTreeNode {
+public:
+ FileTreeNode(const QString &n, FileTreeNode *p = 0) :
+ parent(p), name(n)
+ {
+ // <debug>
+ Q_ASSERT((!name.isEmpty() && p) || (name.isEmpty() && !p));
+ // </debug>
+ if (p)
+ p->children.append(this);
}
- return 0;
-}
-} // namespace
+ ~FileTreeNode()
+ {
+ qDeleteAll(children);
+ }
-namespace QbsProjectManager {
-namespace Internal {
+ FileTreeNode *addPart(const QString &n)
+ {
+ foreach (FileTreeNode *c, children) {
+ if (c->name == n)
+ return c;
+ }
+ return new FileTreeNode(n, this);
+ }
+
+ bool isFile() { return children.isEmpty(); }
+
+ static void simplify(FileTreeNode *node)
+ {
+ foreach (FileTreeNode *c, node->children)
+ simplify(c);
+
+ if (node->children.count() == 1) {
+ FileTreeNode *child = node->children.at(0);
+ if (child->isFile())
+ return;
+
+ node->name = node->name + QLatin1Char('/') + child->name;
+ node->children = child->children;
+
+ foreach (FileTreeNode *tmpChild, node->children)
+ tmpChild->parent = node;
+
+ child->children.clear();
+ child->parent = 0;
+ delete child;
+
+ // <debug>
+ Q_ASSERT(!node->name.isEmpty());
+ // </debug>
+ return;
+ }
+ }
+
+ QString path()
+ {
+ QString p = name;
+ FileTreeNode *node = parent;
+ while (node) {
+ p = node->name + QLatin1Char('/') + p;
+ node = node->parent;
+ }
+ return p;
+ }
+
+ QList<FileTreeNode *> children;
+ FileTreeNode *parent;
+ QString name;
+};
// ----------------------------------------------------------------------
// QbsFileNode:
@@ -67,9 +129,9 @@ QbsFileNode::QbsFileNode(const QString &filePath, const ProjectExplorer::FileTyp
m_line(line)
{ }
-int QbsFileNode::line() const
+void QbsFileNode::setLine(int l)
{
- return m_line;
+ m_line = l;
}
// ---------------------------------------------------------------------------
@@ -153,48 +215,107 @@ QList<ProjectExplorer::RunConfiguration *> QbsBaseProjectNode::runConfigurations
// QbsGroupNode:
// --------------------------------------------------------------------
-QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp, const qbs::ProductData *prd) :
- QbsBaseProjectNode(prd->location().fileName)
+QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp) :
+ QbsBaseProjectNode(QString()),
+ m_group(0)
{
- setDisplayName(grp->name());
- group = grp;
+ setGroup(grp);
+}
- addFileNodes(QList<ProjectExplorer::FileNode *>()
- << new QbsFileNode(grp->location().fileName,
- ProjectExplorer::ProjectFileType, false, grp->location().line), this);
+bool QbsGroupNode::isEnabled() const
+{
+ return static_cast<QbsProductNode *>(parentFolderNode())->isEnabled() && group()->isEnabled();
+}
- QString basePath = QFileInfo(prd->location().fileName).absolutePath();
- if (!basePath.endsWith(QLatin1Char('/')))
- basePath.append(QLatin1Char('/'));
- foreach (const QString &p, grp->allFilePaths()) {
- QString path = p;
- if (path.startsWith(basePath))
- path = path.mid(basePath.count());
+void QbsGroupNode::setGroup(const qbs::GroupData *group)
+{
+ if (group == m_group)
+ return;
+
+ setPath(group->location().fileName);
+ setDisplayName(group->name());
+
+ // Set Product file node used to jump to the product
+ QbsFileNode *indexFile = 0;
+ if (!m_group) {
+ indexFile = new QbsFileNode(group->location().fileName,
+ ProjectExplorer::ProjectFileType, false,
+ group->location().line);
+ addFileNodes(QList<ProjectExplorer::FileNode *>() << indexFile, this);
+ } else {
+ indexFile = static_cast<QbsFileNode *>(fileNodes().first());
+ indexFile->setPath(group->location().fileName);
+ indexFile->setLine(group->location().line);
+ indexFile->emitNodeUpdated();
+ }
+
+ // Build up a tree of nodes:
+ FileTreeNode *tree = new FileTreeNode(QString());
+ foreach (const QString &path, group->allFilePaths()) {
QStringList pathSegments = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
- FolderNode *root = this;
- while (pathSegments.count()) {
- if (pathSegments.count() == 1) {
- addFileNodes(QList<ProjectExplorer::FileNode *>()
- << new ProjectExplorer::FileNode(p, ProjectExplorer::UnknownFileType, false),
- root);
- } else {
- const QString folder = pathSegments.at(0);
- FolderNode *n = findFolder(root, folder);
- if (!n) {
- n = new ProjectExplorer::FolderNode(folder);
- addFolderNodes(QList<ProjectExplorer::FolderNode *>() << n, root);
- }
- root = n;
- }
- pathSegments.removeFirst();
- };
+
+ FileTreeNode *root = tree;
+ while (!pathSegments.isEmpty())
+ root = root->addPart(pathSegments.takeFirst());
}
+
+ FileTreeNode::simplify(tree);
+ setupFolders(this, tree, indexFile);
+
+ delete tree;
+
+ m_group = group;
+ emitNodeUpdated();
}
-bool QbsGroupNode::isEnabled() const
+void QbsGroupNode::setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode *node,
+ ProjectExplorer::FileNode *keep)
{
- return group->isEnabled();
+ // 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<ProjectExplorer::FolderNode *>() << fn, root);
+ }
+ root = fn;
+ }
+
+ QList<ProjectExplorer::FileNode *> filesToRemove = root->fileNodes();
+ filesToRemove.removeAll(keep);
+ QList<ProjectExplorer::FileNode *> filesToAdd;
+
+ QList<ProjectExplorer::FolderNode *> foldersToRemove = root->subFolderNodes();
+
+ // insert subfolders
+ foreach (FileTreeNode *c, node->children) {
+ QString path = c->path();
+ if (c->isFile()) {
+ ProjectExplorer::FileNode *fn = root->findFile(path);
+ if (fn) {
+ fn->emitNodeUpdated(); // enabled might have changed
+ filesToRemove.removeOne(fn);
+ } else {
+ 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<ProjectExplorer::FolderNode *>() << fn, root);
+ }
+ setupFolders(fn, c);
+ }
+ }
+ addFileNodes(filesToAdd, root);
+ removeFileNodes(filesToRemove, root);
+ removeFolderNodes(foldersToRemove, root);
}
// --------------------------------------------------------------------
@@ -202,35 +323,67 @@ bool QbsGroupNode::isEnabled() const
// --------------------------------------------------------------------
QbsProductNode::QbsProductNode(const qbs::ProductData *prd) :
- QbsBaseProjectNode(prd->location().fileName)
+ QbsBaseProjectNode(prd->location().fileName),
+ m_product(0)
{
- setDisplayName(prd->name());
- product = prd;
+ setProduct(prd);
+}
- addFileNodes(QList<ProjectExplorer::FileNode *>()
- << new QbsFileNode(prd->location().fileName,
- ProjectExplorer::ProjectFileType, false, prd->location().line), this);
+bool QbsProductNode::isEnabled() const
+{
+ return product()->isEnabled();
+}
+
+void QbsProductNode::setProduct(const qbs::ProductData *prd)
+{
+ if (m_product == prd)
+ return;
+
+ setDisplayName(prd->name());
+ setPath(prd->location().fileName);
+
+ // Set Product file node used to jump to the product
+ QList<ProjectExplorer::FileNode *> files = fileNodes();
+ if (files.isEmpty()) {
+ addFileNodes(QList<ProjectExplorer::FileNode *>()
+ << new QbsFileNode(prd->location().fileName,
+ ProjectExplorer::ProjectFileType, false,
+ prd->location().line),
+ this);
+ } else {
+ QbsFileNode *qbsFile = static_cast<QbsFileNode *>(files.at(0));
+ qbsFile->setPath(prd->location().fileName);
+ qbsFile->setLine(prd->location().line);
+ }
QList<ProjectExplorer::ProjectNode *> toAdd;
- foreach (const qbs::GroupData &grp, prd->groups())
- toAdd << new QbsGroupNode(&grp, prd);
+ QList<ProjectExplorer::ProjectNode *> toRemove = subProjectNodes();
+
+ foreach (const qbs::GroupData &grp, prd->groups()) {
+ QbsGroupNode *qn = findGroupNode(grp.name());
+ if (qn) {
+ toRemove.removeAll(qn);
+ qn->setGroup(&grp);
+ } else {
+ toAdd << new QbsGroupNode(&grp);
+ }
+ }
addProjectNodes(toAdd);
-}
+ removeProjectNodes(toRemove);
-bool QbsProductNode::isEnabled() const
-{
- return product->isEnabled();
+ m_product = prd;
+ emitNodeUpdated();
}
-void QbsProductNode::updateProductData(const qbs::ProductData *prd)
+QbsGroupNode *QbsProductNode::findGroupNode(const QString &name)
{
- product = prd;
-
- for (int i = 0; i < subProjectNodes().count(); ++i) {
- QbsGroupNode *gn = static_cast<QbsGroupNode *>(subProjectNodes().at(i));
- gn->group = &(prd->groups().at(i));
+ foreach(ProjectExplorer::ProjectNode *n, subProjectNodes()) {
+ QbsGroupNode *qn = static_cast<QbsGroupNode *>(n);
+ if (qn->group()->name() == name)
+ return qn;
}
+ return 0;
}
// --------------------------------------------------------------------
@@ -254,9 +407,7 @@ QbsProjectNode::~QbsProjectNode()
void QbsProjectNode::update(const qbs::Project *prj)
{
QList<ProjectExplorer::ProjectNode *> toAdd;
- QList<ProjectExplorer::ProjectNode *> toRemove;
-
- QList<ProjectExplorer::ProjectNode *> oldNodeList = subProjectNodes();
+ QList<ProjectExplorer::ProjectNode *> toRemove = subProjectNodes();
qbs::ProjectData *newData = 0;
@@ -267,18 +418,11 @@ void QbsProjectNode::update(const qbs::Project *prj)
if (!qn) {
toAdd << new QbsProductNode(&prd);
} else {
- oldNodeList.removeOne(qn);
-
- if (*qn->product != prd) {
- toRemove << qn;
- toAdd << new QbsProductNode(&prd);
- } else {
- qn->updateProductData(&prd);
- }
+ qn->setProduct(&prd);
+ toRemove.removeOne(qn);
}
}
}
- toRemove.append(oldNodeList);
delete m_projectData;
m_projectData = newData;
@@ -307,8 +451,8 @@ const qbs::ProjectData *QbsProjectNode::projectData() const
QbsProductNode *QbsProjectNode::findProductNode(const QString &name)
{
foreach(ProjectExplorer::ProjectNode *n, subProjectNodes()) {
- QbsProductNode *qn = qobject_cast<QbsProductNode *>(n);
- if (qn && (qn->product->name() == name))
+ QbsProductNode *qn = static_cast<QbsProductNode *>(n);
+ if (qn->product()->name() == name)
return qn;
}
return 0;
diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h
index acde5a31ad..914fff9057 100644
--- a/src/plugins/qbsprojectmanager/qbsnodes.h
+++ b/src/plugins/qbsprojectmanager/qbsnodes.h
@@ -39,6 +39,7 @@ namespace qbs { class Project; }
namespace QbsProjectManager {
namespace Internal {
+class FileTreeNode;
class QbsProjectFile;
// ----------------------------------------------------------------------
@@ -51,7 +52,9 @@ class QbsFileNode : public ProjectExplorer::FileNode
public:
QbsFileNode(const QString &filePath, const ProjectExplorer::FileType fileType, bool generated,
int line);
- int line() const;
+ int line() const { return m_line; }
+
+ void setLine(int l);
private:
int m_line;
@@ -102,11 +105,17 @@ class QbsGroupNode : public QbsBaseProjectNode
Q_OBJECT
public:
- QbsGroupNode(const qbs::GroupData *grp, const qbs::ProductData *prd);
+ QbsGroupNode(const qbs::GroupData *grp);
bool isEnabled() const;
+ void setGroup(const qbs::GroupData *group);
+ const qbs::GroupData *group() const { return m_group; }
+
+private:
+ void setupFolders(ProjectExplorer::FolderNode *root, FileTreeNode *node,
+ ProjectExplorer::FileNode *keep = 0);
- const qbs::GroupData *group;
+ const qbs::GroupData *m_group;
};
// --------------------------------------------------------------------
@@ -122,9 +131,13 @@ public:
bool isEnabled() const;
- void updateProductData(const qbs::ProductData *prd);
+ void setProduct(const qbs::ProductData *prd);
+ const qbs::ProductData *product() const { return m_product; }
- const qbs::ProductData *product;
+private:
+ QbsGroupNode *findGroupNode(const QString &name);
+
+ const qbs::ProductData *m_product;
};
// ---------------------------------------------------------------------------
@@ -144,9 +157,9 @@ public:
const qbs::Project *project() const;
const qbs::ProjectData *projectData() const;
+private:
QbsProductNode *findProductNode(const QString &name);
-private:
const qbs::Project *m_project;
const qbs::ProjectData *m_projectData;
};