diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index dc2e7fbf7ff178081c4a62838d5f7bbe9ffa45bf..1f2d1f42124129f10a8da9a7bba08f30087a0e0a 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -91,7 +91,7 @@ CMakeProject::CMakeProject(CMakeManager *manager, const FileName &fileName)
     setProjectManager(manager);
     setDocument(new Internal::CMakeFile(this, fileName));
 
-    setRootProjectNode(new CMakeProjectNode(fileName));
+    setRootProjectNode(new CMakeProjectNode(Utils::FileName::fromString(fileName.toFileInfo().absolutePath())));
     setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
     setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
 
@@ -244,7 +244,8 @@ void CMakeProject::updateProjectData()
         m_watchedFiles.insert(cm);
     }
 
-    buildTree(static_cast<CMakeProjectNode *>(rootProjectNode()), bdm->files());
+    QList<FileNode *> fileNodes = bdm->files();
+    rootProjectNode()->buildTree(fileNodes);
     bdm->clearFiles(); // Some of the FileNodes in files() were deleted!
 
     updateApplicationAndDeploymentTargets();
@@ -416,98 +417,6 @@ bool CMakeProject::hasBuildTarget(const QString &title) const
     return Utils::anyOf(buildTargets(), [title](const CMakeBuildTarget &ct) { return ct.title == title; });
 }
 
-void CMakeProject::gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list) const
-{
-    foreach (ProjectExplorer::FolderNode *folder, parent->subFolderNodes())
-        gatherFileNodes(folder, list);
-    foreach (ProjectExplorer::FileNode *file, parent->fileNodes())
-        list.append(file);
-}
-
-bool sortNodesByPath(Node *a, Node *b)
-{
-    return a->filePath() < b->filePath();
-}
-
-void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> newList)
-{
-    // Gather old list
-    QList<ProjectExplorer::FileNode *> oldList;
-    gatherFileNodes(rootNode, oldList);
-    Utils::sort(oldList, sortNodesByPath);
-    Utils::sort(newList, sortNodesByPath);
-
-    QList<ProjectExplorer::FileNode *> added;
-    QList<ProjectExplorer::FileNode *> deleted;
-
-    ProjectExplorer::compareSortedLists(oldList, newList, deleted, added, sortNodesByPath);
-
-    qDeleteAll(ProjectExplorer::subtractSortedList(newList, added, sortNodesByPath));
-
-    QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > addedFolderMapping;
-    QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > deletedFolderMapping;
-
-    // add added nodes
-    foreach (ProjectExplorer::FileNode *fn, added) {
-        // Get relative path to rootNode
-        QString parentDir = fn->filePath().toFileInfo().absolutePath();
-        ProjectExplorer::FolderNode *folder = findOrCreateFolder(rootNode, parentDir);
-        addedFolderMapping[folder] << fn;
-    }
-
-    for (auto i = addedFolderMapping.constBegin(); i != addedFolderMapping.constEnd(); ++i)
-        i.key()->addFileNodes(i.value());
-
-    // remove old file nodes and check whether folder nodes can be removed
-    foreach (ProjectExplorer::FileNode *fn, deleted)
-        deletedFolderMapping[fn->parentFolderNode()] << fn;
-
-    for (auto i = deletedFolderMapping.constBegin(); i != deletedFolderMapping.constEnd(); ++i) {
-        ProjectExplorer::FolderNode *parent = i.key();
-        parent->removeFileNodes(i.value());
-        // Check for empty parent
-        while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) {
-            ProjectExplorer::FolderNode *grandparent = parent->parentFolderNode();
-            grandparent->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent);
-            parent = grandparent;
-            if (parent == rootNode)
-                break;
-        }
-    }
-}
-
-ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode *rootNode, QString directory)
-{
-    FileName path = rootNode->filePath().parentDir();
-    QDir rootParentDir(path.toString());
-    QString relativePath = rootParentDir.relativeFilePath(directory);
-    if (relativePath == QLatin1String("."))
-        relativePath.clear();
-    QStringList parts = relativePath.split(QLatin1Char('/'), QString::SkipEmptyParts);
-    ProjectExplorer::FolderNode *parent = rootNode;
-    foreach (const QString &part, parts) {
-        path.appendPath(part);
-        // Find folder in subFolders
-        bool found = false;
-        foreach (ProjectExplorer::FolderNode *folder, parent->subFolderNodes()) {
-            if (folder->filePath() == path) {
-                // yeah found something :)
-                parent = folder;
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
-            // No FolderNode yet, so create it
-            auto tmp = new ProjectExplorer::FolderNode(path);
-            tmp->setDisplayName(part);
-            parent->addFolderNodes(QList<ProjectExplorer::FolderNode *>() << tmp);
-            parent = tmp;
-        }
-    }
-    return parent;
-}
-
 QString CMakeProject::displayName() const
 {
     return rootProjectNode()->displayName();
@@ -515,9 +424,8 @@ QString CMakeProject::displayName() const
 
 QStringList CMakeProject::files(FilesMode fileMode) const
 {
-    QList<FileNode *> nodes;
-    gatherFileNodes(rootProjectNode(), nodes);
-    nodes = Utils::filtered(nodes, [fileMode](const FileNode *fn) {
+    const QList<FileNode *> nodes = Utils::filtered(rootProjectNode()->recursiveFileNodes(),
+                                                    [fileMode](const FileNode *fn) {
         const bool isGenerated = fn->isGenerated();
         switch (fileMode)
         {
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index f214592d8fdcdcdfcc73eb43556e10712507b40a..334cca4f6c778e98cdbec80b8e6449f922c9b095 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -118,9 +118,6 @@ private:
     void updateProjectData();
     void updateQmlJSCodeModel();
 
-    void buildTree(Internal::CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list);
-    void gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list) const;
-    ProjectExplorer::FolderNode *findOrCreateFolder(Internal::CMakeProjectNode *rootNode, QString directory);
     void createGeneratedCodeModelSupport();
     QStringList filesGeneratedFrom(const QString &sourceFile) const final;
     void updateTargetRunConfigurations(ProjectExplorer::Target *t);
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
index 73c6378ca9e9aaae55d74bc41d7bc14f469586ee..f42d08c6278cf4ec7f2b1accff5e3213a41a8b26 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp
@@ -28,8 +28,8 @@
 using namespace CMakeProjectManager;
 using namespace CMakeProjectManager::Internal;
 
-CMakeProjectNode::CMakeProjectNode(const Utils::FileName &fileName)
-    : ProjectExplorer::ProjectNode(fileName)
+CMakeProjectNode::CMakeProjectNode(const Utils::FileName &dirName)
+    : ProjectExplorer::ProjectNode(dirName)
 {
 }
 
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h
index 9dcb720767f9dac376fa42e2ee39227223e08985..34a2e73619ad1eaf89b753a83ec47616022bda19 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h
@@ -35,7 +35,7 @@ namespace Internal {
 class CMakeProjectNode : public ProjectExplorer::ProjectNode
 {
 public:
-    CMakeProjectNode(const Utils::FileName &fileName);
+    CMakeProjectNode(const Utils::FileName &dirName);
     bool showInSimpleTree() const override;
     QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const override;
 };
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index eb110272cc9a143c84abd888a8b6173ecada3509..9d97dff94134b1e0d79ca07140989c6fa7ad43ab 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -269,11 +269,102 @@ QList<FileNode*> FolderNode::fileNodes() const
     return m_fileNodes;
 }
 
+QList<FileNode *> FolderNode::recursiveFileNodes() const
+{
+    QList<FileNode *> result = fileNodes();
+    foreach (ProjectExplorer::FolderNode *folder, subFolderNodes())
+        result.append(folder->recursiveFileNodes());
+    return result;
+}
+
 QList<FolderNode*> FolderNode::subFolderNodes() const
 {
     return m_subFolderNodes;
 }
 
+FolderNode *FolderNode::findOrCreateSubFolderNode(const QString &directory)
+{
+    Utils::FileName path = filePath();
+    QDir parentDir(path.toString());
+    QString relativePath = parentDir.relativeFilePath(directory);
+    if (relativePath == ".")
+        relativePath.clear();
+    QStringList parts = relativePath.split('/', QString::SkipEmptyParts);
+    ProjectExplorer::FolderNode *parent = this;
+    foreach (const QString &part, parts) {
+        path.appendPath(part);
+        // Find folder in subFolders
+        bool found = false;
+        foreach (ProjectExplorer::FolderNode *folder, parent->subFolderNodes()) {
+            if (folder->filePath() == path) {
+                // yeah found something :)
+                parent = folder;
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            // No FolderNode yet, so create it
+            auto tmp = new ProjectExplorer::FolderNode(path);
+            tmp->setDisplayName(part);
+            parent->addFolderNodes(QList<ProjectExplorer::FolderNode *>({ tmp }));
+            parent = tmp;
+        }
+    }
+    return parent;
+}
+
+static bool sortNodesByPath(Node *a, Node *b)
+{
+    return a->filePath() < b->filePath();
+}
+
+void FolderNode::buildTree(QList<FileNode *> &files)
+{
+    // Gather old list
+    QList<ProjectExplorer::FileNode *> oldFiles = recursiveFileNodes();
+    Utils::sort(oldFiles, sortNodesByPath);
+    Utils::sort(files, sortNodesByPath);
+
+    QList<ProjectExplorer::FileNode *> added;
+    QList<ProjectExplorer::FileNode *> deleted;
+
+    ProjectExplorer::compareSortedLists(oldFiles, files, deleted, added, sortNodesByPath);
+
+    qDeleteAll(ProjectExplorer::subtractSortedList(files, added, sortNodesByPath));
+
+    QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > addedFolderMapping;
+    QHash<ProjectExplorer::FolderNode *, QList<ProjectExplorer::FileNode *> > deletedFolderMapping;
+
+    // add added nodes
+    foreach (ProjectExplorer::FileNode *fn, added) {
+        // Get relative path to rootNode
+        QString parentDir = fn->filePath().toFileInfo().absolutePath();
+        ProjectExplorer::FolderNode *folder = findOrCreateSubFolderNode(parentDir);
+        addedFolderMapping[folder] << fn;
+    }
+
+    for (auto i = addedFolderMapping.constBegin(); i != addedFolderMapping.constEnd(); ++i)
+        i.key()->addFileNodes(i.value());
+
+    // remove old file nodes and check whether folder nodes can be removed
+    foreach (ProjectExplorer::FileNode *fn, deleted)
+        deletedFolderMapping[fn->parentFolderNode()] << fn;
+
+    for (auto i = deletedFolderMapping.constBegin(); i != deletedFolderMapping.constEnd(); ++i) {
+        ProjectExplorer::FolderNode *parent = i.key();
+        parent->removeFileNodes(i.value());
+        // Check for empty parent
+        while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) {
+            ProjectExplorer::FolderNode *grandparent = parent->parentFolderNode();
+            grandparent->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent);
+            parent = grandparent;
+            if (parent == this)
+                break;
+        }
+    }
+}
+
 void FolderNode::accept(NodesVisitor *visitor)
 {
     visitor->visitFolderNode(this);
@@ -707,7 +798,7 @@ ProjectNode *ProjectNode::asProjectNode()
 */
 
 SessionNode::SessionNode() :
-    FolderNode(Utils::FileName::fromString(QLatin1String("session")), SessionNodeType)
+    FolderNode(Utils::FileName::fromString("session"), SessionNodeType)
 { }
 
 QList<ProjectAction> SessionNode::supportedActions(Node *node) const
@@ -747,7 +838,7 @@ QList<ProjectNode*> SessionNode::projectNodes() const
 
 QString SessionNode::addFileFilter() const
 {
-    return QLatin1String("*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;");
+    return QString::fromLatin1("*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;");
 }
 
 void SessionNode::addProjectNodes(const QList<ProjectNode*> &projectNodes)
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index de7bf243898bf32b266673bf4f868b613c0583cf..a4b4ea47654e01ab7c3177100ecfc5479314308e 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -172,8 +172,11 @@ public:
     QString displayName() const override;
     QIcon icon() const;
 
-    QList<FileNode*> fileNodes() const;
-    QList<FolderNode*> subFolderNodes() const;
+    QList<FileNode *> fileNodes() const;
+    QList<FileNode *> recursiveFileNodes() const;
+    QList<FolderNode *> subFolderNodes() const;
+    FolderNode *findOrCreateSubFolderNode(const QString &directory);
+    void buildTree(QList<FileNode *> &files);
 
     virtual void accept(NodesVisitor *visitor);