Commit d8090373 authored by Daniel Teske's avatar Daniel Teske

ProjectNodes: Move (add|remove)(File|Folder)Node to FolderNode

The reason they were on ProjectNode is that the signals are emitted
on the projectnode, but since I moved addFiles and others to FolderNode,
this makes more sense.

Change-Id: I918ca4d93dab78c8bb93dff03f53d1a6fbe21340
Reviewed-by: default avatarDaniel Teske <daniel.teske@digia.com>
parent a6b6a99d
......@@ -313,7 +313,7 @@ void AutotoolsProject::buildFileNodeTree(const QDir &directory,
// AutotoolsProjectNode::addFileNodes() is a very expensive operation. It is
// important to collect as much file nodes of the same parent folder as
// possible before invoking it.
m_rootNode->addFileNodes(fileNodes, oldParentFolder);
oldParentFolder->addFileNodes(fileNodes);
fileNodes.clear();
}
......@@ -330,7 +330,7 @@ void AutotoolsProject::buildFileNodeTree(const QDir &directory,
}
if (!fileNodes.isEmpty())
m_rootNode->addFileNodes(fileNodes, parentFolder);
parentFolder->addFileNodes(fileNodes);
// Remove unused file nodes and empty folder nodes
QHash<QString, Node *>::const_iterator it = nodeHash.constBegin();
......@@ -338,12 +338,12 @@ void AutotoolsProject::buildFileNodeTree(const QDir &directory,
if ((*it)->nodeType() == FileNodeType) {
FileNode *fileNode = static_cast<FileNode *>(*it);
FolderNode* parent = fileNode->parentFolderNode();
m_rootNode->removeFileNodes(QList<FileNode *>() << fileNode, parent);
parent->removeFileNodes(QList<FileNode *>() << fileNode);
// Remove all empty parent folders
while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) {
FolderNode *grandParent = parent->parentFolderNode();
m_rootNode->removeFolderNodes(QList<FolderNode *>() << parent, grandParent);
grandParent->removeFolderNodes(QList<FolderNode *>() << parent);
parent = grandParent;
if (parent == m_rootNode)
break;
......@@ -382,7 +382,7 @@ FolderNode *AutotoolsProject::insertFolderNode(const QDir &nodeDir, QHash<QStrin
}
}
m_rootNode->addFolderNodes(QList<FolderNode *>() << folder, parentFolder);
parentFolder->addFolderNodes(QList<FolderNode *>() << folder);
nodes.insert(nodePath, folder);
return folder;
......
......@@ -459,18 +459,18 @@ void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::
// Get relative path to rootNode
QString parentDir = QFileInfo(fn->path()).absolutePath();
ProjectExplorer::FolderNode *folder = findOrCreateFolder(rootNode, parentDir);
rootNode->addFileNodes(QList<ProjectExplorer::FileNode *>()<< fn, folder);
folder->addFileNodes(QList<ProjectExplorer::FileNode *>()<< fn);
}
// remove old file nodes and check whether folder nodes can be removed
foreach (ProjectExplorer::FileNode *fn, deleted) {
ProjectExplorer::FolderNode *parent = fn->parentFolderNode();
// qDebug()<<"removed"<<fn->path();
rootNode->removeFileNodes(QList<ProjectExplorer::FileNode *>() << fn, parent);
parent->removeFileNodes(QList<ProjectExplorer::FileNode *>() << fn);
// Check for empty parent
while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) {
ProjectExplorer::FolderNode *grandparent = parent->parentFolderNode();
rootNode->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent, grandparent);
grandparent->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent);
parent = grandparent;
if (parent == rootNode)
break;
......@@ -501,7 +501,7 @@ ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode *
// No FolderNode yet, so create it
ProjectExplorer::FolderNode *tmp = new ProjectExplorer::FolderNode(path);
tmp->setDisplayName(part);
rootNode->addFolderNodes(QList<ProjectExplorer::FolderNode *>() << tmp, parent);
parent->addFolderNodes(QList<ProjectExplorer::FolderNode *>() << tmp);
parent = tmp;
}
}
......
......@@ -103,8 +103,7 @@ void GenericProjectNode::refresh(QSet<QString> oldFileList)
addFileNodes(QList<FileNode *>()
<< projectFilesNode
<< projectIncludesNode
<< projectConfigNode,
this);
<< projectConfigNode);
}
// Do those separately
......@@ -142,7 +141,7 @@ void GenericProjectNode::refresh(QSet<QString> oldFileList)
fileNodes.append(fileNode);
}
addFileNodes(fileNodes, folder);
folder->addFileNodes(fileNodes);
}
filesInPaths = sortFilesIntoPaths(baseDir, removed);
......@@ -161,7 +160,7 @@ void GenericProjectNode::refresh(QSet<QString> oldFileList)
fileNodes.append(fn);
}
removeFileNodes(fileNodes, folder);
folder->removeFileNodes(fileNodes);
}
foreach (FolderNode *fn, subFolderNodes())
......@@ -175,7 +174,7 @@ void GenericProjectNode::removeEmptySubFolders(FolderNode *gparent, FolderNode *
removeEmptySubFolders(parent, fn);
if (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty())
removeFolderNodes(QList<FolderNode*>() << parent, gparent);
gparent->removeFolderNodes(QList<FolderNode*>() << parent);
}
FolderNode *GenericProjectNode::createFolderByName(const QStringList &components, int end)
......@@ -198,7 +197,7 @@ FolderNode *GenericProjectNode::createFolderByName(const QStringList &components
FolderNode *parent = findFolderByName(components, end - 1);
if (!parent)
parent = createFolderByName(components, end - 1);
addFolderNodes(QList<FolderNode*>() << folder, parent);
parent->addFolderNodes(QList<FolderNode*>() << folder);
return folder;
}
......
......@@ -357,6 +357,168 @@ bool FolderNode::renameFile(const QString &filePath, const QString &newFilePath)
return false;
}
/*!
Adds file nodes specified by \a files to the internal list of the folder
and emits the corresponding signals from the projectNode.
This function should be called within an implementation of the public function
addFiles.
*/
void FolderNode::addFileNodes(const QList<FileNode *> &files)
{
Q_ASSERT(projectNode());
ProjectNode *pn = projectNode();
if (files.isEmpty())
return;
foreach (NodesWatcher *watcher, pn->watchers())
emit watcher->filesAboutToBeAdded(this, files);
foreach (FileNode *file, files) {
QTC_ASSERT(!file->parentFolderNode(),
qDebug("File node has already a parent folder"));
file->setParentFolderNode(this);
file->setProjectNode(pn);
// Now find the correct place to insert file
if (m_fileNodes.count() == 0
|| m_fileNodes.last() < file) {
// empty list or greater then last node
m_fileNodes.append(file);
} else {
QList<FileNode *>::iterator it
= qLowerBound(m_fileNodes.begin(),
m_fileNodes.end(),
file);
m_fileNodes.insert(it, file);
}
}
foreach (NodesWatcher *watcher, pn->watchers())
emit watcher->filesAdded();
}
/*!
Removes \a files from the internal list and emits the corresponding signals.
All objects in the \a files list are deleted.
This function should be called within an implementation of the public function
removeFiles.
*/
void FolderNode::removeFileNodes(const QList<FileNode *> &files)
{
Q_ASSERT(projectNode());
ProjectNode *pn = projectNode();
if (files.isEmpty())
return;
QList<FileNode*> toRemove = files;
qSort(toRemove.begin(), toRemove.end());
foreach (NodesWatcher *watcher, pn->watchers())
emit watcher->filesAboutToBeRemoved(this, toRemove);
QList<FileNode*>::const_iterator toRemoveIter = toRemove.constBegin();
QList<FileNode*>::iterator filesIter = m_fileNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
while (*filesIter != *toRemoveIter) {
++filesIter;
QTC_ASSERT(filesIter != m_fileNodes.end(),
qDebug("File to remove is not part of specified folder!"));
}
delete *filesIter;
filesIter = m_fileNodes.erase(filesIter);
}
foreach (NodesWatcher *watcher, pn->watchers())
emit watcher->filesRemoved();
}
/*!
Adds folder nodes specified by \a subFolders to the node hierarchy below
\a parentFolder and emits the corresponding signals.
*/
void FolderNode::addFolderNodes(const QList<FolderNode*> &subFolders)
{
Q_ASSERT(projectNode());
ProjectNode *pn = projectNode();
if (subFolders.isEmpty())
return;
foreach (NodesWatcher *watcher, pn->watchers())
watcher->foldersAboutToBeAdded(this, subFolders);
foreach (FolderNode *folder, subFolders) {
QTC_ASSERT(!folder->parentFolderNode(),
qDebug("Project node has already a parent folder"));
folder->setParentFolderNode(this);
folder->setProjectNode(pn);
// Find the correct place to insert
if (m_subFolderNodes.count() == 0
|| m_subFolderNodes.last() < folder) {
// empty list or greater then last node
m_subFolderNodes.append(folder);
} else {
// Binary Search for insertion point
QList<FolderNode*>::iterator it
= qLowerBound(m_subFolderNodes.begin(),
m_subFolderNodes.end(),
folder);
m_subFolderNodes.insert(it, folder);
}
// project nodes have to be added via addProjectNodes
QTC_ASSERT(folder->nodeType() != ProjectNodeType,
qDebug("project nodes have to be added via addProjectNodes"));
}
foreach (NodesWatcher *watcher, pn->watchers())
emit watcher->foldersAdded();
}
/*!
Removes file nodes specified by \a subFolders from the node hierarchy and emits
the corresponding signals.
All objects in the \a subFolders list are deleted.
*/
void FolderNode::removeFolderNodes(const QList<FolderNode*> &subFolders)
{
Q_ASSERT(projectNode());
ProjectNode *pn = projectNode();
if (subFolders.isEmpty())
return;
QList<FolderNode*> toRemove = subFolders;
qSort(toRemove.begin(), toRemove.end());
foreach (NodesWatcher *watcher, pn->watchers())
emit watcher->foldersAboutToBeRemoved(this, toRemove);
QList<FolderNode*>::const_iterator toRemoveIter = toRemove.constBegin();
QList<FolderNode*>::iterator folderIter = m_subFolderNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
QTC_ASSERT((*toRemoveIter)->nodeType() != ProjectNodeType,
qDebug("project nodes have to be removed via removeProjectNodes"));
while (*folderIter != *toRemoveIter) {
++folderIter;
QTC_ASSERT(folderIter != m_subFolderNodes.end(),
qDebug("Folder to remove is not part of specified folder!"));
}
delete *folderIter;
folderIter = m_subFolderNodes.erase(folderIter);
}
foreach (NodesWatcher *watcher, pn->watchers())
emit watcher->foldersRemoved();
}
/*!
\class ProjectExplorer::VirtualFolderNode
......@@ -573,178 +735,6 @@ void ProjectNode::removeProjectNodes(const QList<ProjectNode*> &subProjects)
}
}
/*!
Adds folder nodes specified by \a subFolders to the node hierarchy below
\a parentFolder and emits the corresponding signals.
*/
void ProjectNode::addFolderNodes(const QList<FolderNode*> &subFolders, FolderNode *parentFolder)
{
Q_ASSERT(parentFolder);
if (!subFolders.isEmpty()) {
const bool emitSignals = (parentFolder->projectNode() == this);
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
watcher->foldersAboutToBeAdded(parentFolder, subFolders);
foreach (FolderNode *folder, subFolders) {
QTC_ASSERT(!folder->parentFolderNode(),
qDebug("Project node has already a parent folder"));
folder->setParentFolderNode(parentFolder);
folder->setProjectNode(this);
// Find the correct place to insert
if (parentFolder->m_subFolderNodes.count() == 0
|| parentFolder->m_subFolderNodes.last() < folder) {
// empty list or greater then last node
parentFolder->m_subFolderNodes.append(folder);
} else {
// Binary Search for insertion point
QList<FolderNode*>::iterator it
= qLowerBound(parentFolder->m_subFolderNodes.begin(),
parentFolder->m_subFolderNodes.end(),
folder);
parentFolder->m_subFolderNodes.insert(it, folder);
}
// project nodes have to be added via addProjectNodes
QTC_ASSERT(folder->nodeType() != ProjectNodeType,
qDebug("project nodes have to be added via addProjectNodes"));
}
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
emit watcher->foldersAdded();
}
}
/*!
Removes file nodes specified by \a subFolders from the node hierarchy and emits
the corresponding signals.
All objects in the \a subFolders list are deleted.
*/
void ProjectNode::removeFolderNodes(const QList<FolderNode*> &subFolders,
FolderNode *parentFolder)
{
Q_ASSERT(parentFolder);
if (!subFolders.isEmpty()) {
const bool emitSignals = (parentFolder->projectNode() == this);
QList<FolderNode*> toRemove = subFolders;
qSort(toRemove.begin(), toRemove.end());
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
emit watcher->foldersAboutToBeRemoved(parentFolder, toRemove);
QList<FolderNode*>::const_iterator toRemoveIter = toRemove.constBegin();
QList<FolderNode*>::iterator folderIter = parentFolder->m_subFolderNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
QTC_ASSERT((*toRemoveIter)->nodeType() != ProjectNodeType,
qDebug("project nodes have to be removed via removeProjectNodes"));
while (*folderIter != *toRemoveIter) {
++folderIter;
QTC_ASSERT(folderIter != parentFolder->m_subFolderNodes.end(),
qDebug("Folder to remove is not part of specified folder!"));
}
delete *folderIter;
folderIter = parentFolder->m_subFolderNodes.erase(folderIter);
}
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
emit watcher->foldersRemoved();
}
}
/*!
Adds file nodes specified by \a files to the internal list in the location
specified by \a folder and emits the corresponding signals.
This function should be called within an implementation of the public function
addFiles.
*/
void ProjectNode::addFileNodes(const QList<FileNode*> &files, FolderNode *folder)
{
Q_ASSERT(folder);
if (!files.isEmpty()) {
const bool emitSignals = (folder->projectNode() == this);
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
emit watcher->filesAboutToBeAdded(folder, files);
foreach (FileNode *file, files) {
QTC_ASSERT(!file->parentFolderNode(),
qDebug("File node has already a parent folder"));
file->setParentFolderNode(folder);
file->setProjectNode(this);
// Now find the correct place to insert file
if (folder->m_fileNodes.count() == 0
|| folder->m_fileNodes.last() < file) {
// empty list or greater then last node
folder->m_fileNodes.append(file);
} else {
QList<FileNode *>::iterator it
= qLowerBound(folder->m_fileNodes.begin(),
folder->m_fileNodes.end(),
file);
folder->m_fileNodes.insert(it, file);
}
}
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
emit watcher->filesAdded();
}
}
/*!
Removes \a files from the internal list and emits the corresponding signals.
All objects in the \a files list are deleted.
This function should be called within an implementation of the public function
removeFiles.
*/
void ProjectNode::removeFileNodes(const QList<FileNode*> &files, FolderNode *folder)
{
Q_ASSERT(folder);
if (!files.isEmpty()) {
const bool emitSignals = (folder->projectNode() == this);
QList<FileNode*> toRemove = files;
qSort(toRemove.begin(), toRemove.end());
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
emit watcher->filesAboutToBeRemoved(folder, toRemove);
QList<FileNode*>::const_iterator toRemoveIter = toRemove.constBegin();
QList<FileNode*>::iterator filesIter = folder->m_fileNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
while (*filesIter != *toRemoveIter) {
++filesIter;
QTC_ASSERT(filesIter != folder->m_fileNodes.end(),
qDebug("File to remove is not part of specified folder!"));
}
delete *filesIter;
filesIter = folder->m_fileNodes.erase(filesIter);
}
if (emitSignals)
foreach (NodesWatcher *watcher, m_watchers)
emit watcher->filesRemoved();
}
}
void ProjectNode::watcherDestroyed(QObject *watcher)
{
// cannot use qobject_cast here
......
......@@ -146,6 +146,7 @@ public:
private:
// managed by ProjectNode
friend class FolderNode;
friend class ProjectNode;
FileType m_fileType;
......@@ -178,6 +179,12 @@ public:
virtual bool deleteFiles(const QStringList &filePaths);
virtual bool renameFile(const QString &filePath, const QString &newFilePath);
void addFileNodes(const QList<FileNode*> &files);
void removeFileNodes(const QList<FileNode*> &files);
void addFolderNodes(const QList<FolderNode*> &subFolders);
void removeFolderNodes(const QList<FolderNode*> &subFolders);
protected:
QList<FolderNode*> m_subFolderNodes;
QList<FileNode*> m_fileNodes;
......@@ -239,12 +246,6 @@ public:
bool isEnabled() const { return true; }
void addFolderNodes(const QList<FolderNode*> &subFolders, FolderNode *parentFolder);
void removeFolderNodes(const QList<FolderNode*> &subFolders, FolderNode *parentFolder);
void addFileNodes(const QList<FileNode*> &files, FolderNode *parentFolder);
void removeFileNodes(const QList<FileNode*> &files, FolderNode *parentFolder);
// to be called in implementation of
// the corresponding public functions
void addProjectNodes(const QList<ProjectNode*> &subProjects);
......
......@@ -325,7 +325,7 @@ QbsGroupNode::QbsGroupNode(const qbs::GroupData *grp, const QString &productPath
QbsFileNode *idx = new QbsFileNode(grp->location().fileName(),
ProjectExplorer::ProjectFileType, false,
grp->location().line());
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this);
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx);
updateQbsGroupData(grp, productPath, true, true);
}
......@@ -435,7 +435,7 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root,
FolderNode *fn = root->findSubFolder(c->path());
if (!fn) {
fn = new FolderNode(c->path());
root->projectNode()->addFolderNodes(QList<FolderNode *>() << fn, root);
root->addFolderNodes(QList<FolderNode *>() << fn);
} else {
foldersToRemove.removeOne(fn);
if (updateExisting)
......@@ -446,9 +446,9 @@ void QbsGroupNode::setupFolder(ProjectExplorer::FolderNode *root,
setupFolder(fn, c, c->path(), updateExisting);
}
}
root->projectNode()->removeFileNodes(filesToRemove, root);
root->projectNode()->removeFolderNodes(foldersToRemove, root);
root->projectNode()->addFileNodes(filesToAdd, root);
root->removeFileNodes(filesToRemove);
root->removeFolderNodes(foldersToRemove);
root->addFileNodes(filesToAdd);
}
// --------------------------------------------------------------------
......@@ -466,7 +466,7 @@ QbsProductNode::QbsProductNode(const qbs::ProductData &prd) :
ProjectExplorer::FileNode *idx = new QbsFileNode(prd.location().fileName(),
ProjectExplorer::ProjectFileType, false,
prd.location().line());
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx, this);
addFileNodes(QList<ProjectExplorer::FileNode *>() << idx);
setQbsProductData(prd);
}
......@@ -656,7 +656,7 @@ void QbsProjectNode::ctor()
setIcon(m_projectIcon);
addFileNodes(QList<ProjectExplorer::FileNode *>()
<< new ProjectExplorer::FileNode(path(), ProjectExplorer::ProjectFileType, false), this);
<< new ProjectExplorer::FileNode(path(), ProjectExplorer::ProjectFileType, false));
}
QbsProductNode *QbsProjectNode::findProductNode(const QString &name)
......
......@@ -384,9 +384,9 @@ struct InternalNode
}
// Makes the projectNode's subtree below the given folder match this internal node's subtree
void updateSubFolders(QmakeProjectManager::QmakePriFileNode *projectNode, ProjectExplorer::FolderNode *folder)
void updateSubFolders(ProjectExplorer::FolderNode *folder)
{
updateFiles(projectNode, folder, type);
updateFiles(folder, type);
// updateFolders
QMultiMap<QString, FolderNode *> existingFolderNodes;
......@@ -466,16 +466,16 @@ struct InternalNode
foldersToRemove << jit.value();
if (!foldersToRemove.isEmpty())
projectNode->removeFolderNodes(foldersToRemove, folder);
folder->removeFolderNodes(foldersToRemove);
if (!foldersToAdd.isEmpty())
projectNode->addFolderNodes(foldersToAdd, folder);
folder->addFolderNodes(foldersToAdd);
foreach (const NodePair &np, nodesToUpdate)
np.first->updateSubFolders(projectNode, np.second);
np.first->updateSubFolders(np.second);
}
// Makes the folder's files match this internal node's file list
void updateFiles(QmakeProjectManager::QmakePriFileNode *projectNode, FolderNode *folder, FileType type)
void updateFiles(FolderNode *folder, FileType type)
{
QList<FileNode*> existingFileNodes;
foreach (FileNode *fileNode, folder->fileNodes()) {
......@@ -514,9 +514,9 @@ struct InternalNode
}
if (!filesToRemove.isEmpty())
projectNode->removeFileNodes(filesToRemove, folder);
folder->removeFileNodes(filesToRemove);
if (!filesToAdd.isEmpty())
projectNode->addFileNodes(filesToAdd, folder);
folder->addFileNodes(filesToAdd);
}
};
}
......@@ -569,7 +569,7 @@ void QmakePriFileNode::update(ProFile *includeFileExact, QtSupport::ProFileReade
{
// add project file node
if (m_fileNodes.isEmpty())
addFileNodes(QList<FileNode*>() << new ProjectExplorer::FileNode(m_projectFilePath, ProjectExplorer::ProjectFileType, false), this);
addFileNodes(QList<FileNode*>() << new ProjectExplorer::FileNode(m_projectFilePath, ProjectExplorer::ProjectFileType, false));
const QString &projectDir = m_qmakeProFileNode->m_projectDir;
......@@ -695,7 +695,7 @@ void QmakePriFileNode::update(ProFile *includeFileExact, QtSupport::ProFileReade
}
}
contents.updateSubFolders(this, this);
contents.updateSubFolders(this);
}
void QmakePriFileNode::watchFolders(const QSet<QString> &folders)
......@@ -772,7 +772,7 @@ bool QmakePriFileNode::folderChanged(const QString &changedFolder, const QSet<Ut
}
}
contents.updateSubFolders(this, this);
contents.updateSubFolders(this);
return true;
}
......@@ -1726,9 +1726,9 @@ void QmakeProFileNode::applyEvaluate(EvalResult evalResult, bool async)
return;
// delete files && folders && projects
removeFileNodes(fileNodes(), this);
removeFileNodes(fileNodes());
removeProjectNodes(subProjectNodes());
removeFolderNodes(subFolderNodes(), this);
removeFolderNodes(subFolderNodes());
// change project type
QmakeProjectType oldType = m_projectType;
......@@ -1757,9 +1757,9 @@ void QmakeProFileNode::applyEvaluate(EvalResult evalResult, bool async)
}
}
removeFileNodes(fileNodes(), this);
removeFileNodes(fileNodes());
removeProjectNodes(subProjectNodes());
removeFolderNodes(subFolderNodes(), this);
removeFolderNodes(subFolderNodes());
bool changesHasBuildTargets = hasBuildTargets() ^ hasBuildTargets(projectType);
......
......@@ -69,8 +69,8 @@ void QmlProjectNode::refresh()
using namespace ProjectExplorer;
// remove the existing nodes.
removeFileNodes(fileNodes(), this);
removeFolderNodes(subFolderNodes(), this);
removeFileNodes(fileNodes());
removeFolderNodes(subFolderNodes());
//ProjectExplorerPlugin::instance()->setCurrentNode(0); // ### remove me