Commit 16f272e0 authored by Daniel Teske's avatar Daniel Teske

GenericProject: Make node tree updates smarter

By not simpy removing all filenodes and foldernodes.
The algorithm is not optimal, since it searches for each difference
instead of traversing the two trees in lockstep, like for example the
qmake project manager does. But it seems good enough.

Task-number: QTCREATORBUG-7410
Change-Id: Ie7c0f4bc57cd3aff4e8b7a26845cfaf213329326
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent dc9f5999
......@@ -237,7 +237,7 @@ void GenericProject::refresh(RefreshOptions options)
parseProject(options);
if (options & Files)
m_rootNode->refresh();
m_rootNode->refresh(oldFileList);
CPlusPlus::CppModelManagerInterface *modelManager =
CPlusPlus::CppModelManagerInterface::instance();
......
......@@ -56,40 +56,9 @@ QString GenericProjectNode::projectFilePath() const
return m_projectFile->fileName();
}
void GenericProjectNode::refresh()
QHash<QString, QStringList> sortFilesIntoPaths(const QString &base, const QSet<QString> files)
{
// remove the existing nodes.
removeFileNodes(fileNodes(), this);
removeFolderNodes(subFolderNodes(), this);
//ProjectExplorerPlugin::instance()->setCurrentNode(0); // ### remove me
FileNode *projectFilesNode = new FileNode(m_project->filesFileName(),
ProjectFileType,
/* generated = */ false);
FileNode *projectIncludesNode = new FileNode(m_project->includesFileName(),
ProjectFileType,
/* generated = */ false);
FileNode *projectConfigNode = new FileNode(m_project->configFileName(),
ProjectFileType,
/* generated = */ false);
QStringList files = m_project->files();
files.removeAll(m_project->filesFileName());
files.removeAll(m_project->includesFileName());
files.removeAll(m_project->configFileName());
addFileNodes(QList<FileNode *>()
<< projectFilesNode
<< projectIncludesNode
<< projectConfigNode,
this);
QStringList filePaths;
QHash<QString, QStringList> filesInPath;
const QString base = QFileInfo(path()).absolutePath();
const QDir baseDir(base);
foreach (const QString &absoluteFileName, files) {
......@@ -104,19 +73,59 @@ void GenericProjectNode::refresh()
relativeFilePath = baseDir.relativeFilePath(absoluteFilePath.toString());
}
if (! filePaths.contains(relativeFilePath))
filePaths.append(relativeFilePath);
filesInPath[relativeFilePath].append(absoluteFileName);
}
return filesInPath;
}
void GenericProjectNode::refresh(QSet<QString> oldFileList)
{
if (oldFileList.isEmpty()) {
// Only do this once
FileNode *projectFilesNode = new FileNode(m_project->filesFileName(),
ProjectFileType,
/* generated = */ false);
FileNode *projectIncludesNode = new FileNode(m_project->includesFileName(),
ProjectFileType,
/* generated = */ false);
FileNode *projectConfigNode = new FileNode(m_project->configFileName(),
ProjectFileType,
/* generated = */ false);
addFileNodes(QList<FileNode *>()
<< projectFilesNode
<< projectIncludesNode
<< projectConfigNode,
this);
}
FolderByName folderByName;
foreach (const QString &filePath, filePaths) {
// Do those separately
oldFileList.remove(m_project->filesFileName());
oldFileList.remove(m_project->includesFileName());
oldFileList.remove(m_project->configFileName());
QSet<QString> newFileList = m_project->files().toSet();
newFileList.remove(m_project->filesFileName());
newFileList.remove(m_project->includesFileName());
newFileList.remove(m_project->configFileName());
QSet<QString> removed = oldFileList;
removed.subtract(newFileList);
QSet<QString> added = newFileList;
added.subtract(oldFileList);
QString baseDir = QFileInfo(path()).absolutePath();
QHash<QString, QStringList> filesInPaths = sortFilesIntoPaths(baseDir, added);
foreach (const QString &filePath, filesInPaths.keys()) {
QStringList components = filePath.split(QLatin1Char('/'));
FolderNode *folder = findOrCreateFolderByName(&folderByName, components, components.size());
FolderNode *folder = findFolderByName(components, components.size());
if (!folder)
folder = createFolderByName(components, components.size());
QList<FileNode *> fileNodes;
foreach (const QString &file, filesInPath.value(filePath)) {
foreach (const QString &file, filesInPaths.value(filePath)) {
FileType fileType = SourceType; // ### FIXME
FileNode *fileNode = new FileNode(file, fileType, /*generated = */ false);
fileNodes.append(fileNode);
......@@ -124,18 +133,45 @@ void GenericProjectNode::refresh()
addFileNodes(fileNodes, folder);
}
filesInPaths = sortFilesIntoPaths(baseDir, removed);
foreach (const QString &filePath, filesInPaths.keys()) {
QStringList components = filePath.split(QLatin1Char('/'));
FolderNode *folder = findFolderByName(components, components.size());
QList<FileNode *> fileNodes;
foreach (const QString &file, filesInPaths.value(filePath)) {
foreach (FileNode *fn, folder->fileNodes())
if (fn->path() == file)
fileNodes.append(fn);
}
removeFileNodes(fileNodes, folder);
}
foreach (FolderNode *fn, subFolderNodes())
removeEmptySubFolders(this, fn);
}
FolderNode *GenericProjectNode::findOrCreateFolderByName
(FolderByName *folderByName, const QStringList &components, int end)
void GenericProjectNode::removeEmptySubFolders(FolderNode *gparent, FolderNode *parent)
{
if (!end)
return 0;
foreach (FolderNode *fn, parent->subFolderNodes())
removeEmptySubFolders(parent, fn);
if (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty())
removeFolderNodes(QList<FolderNode*>() << parent, gparent);
}
FolderNode *GenericProjectNode::createFolderByName(const QStringList &components, int end)
{
if (end == 0)
return this;
QString folderName;
for (int i = 0; i < end; ++i) {
folderName.append(components.at(i));
folderName += QLatin1Char('/'); // ### FIXME
folderName += QLatin1Char('/');
}
const QString component = components.at(end - 1);
......@@ -143,22 +179,41 @@ FolderNode *GenericProjectNode::findOrCreateFolderByName
if (component.isEmpty())
return this;
else if (FolderNode *folder = folderByName->value(folderName))
return folder;
const QString baseDir = QFileInfo(path()).path();
FolderNode *folder = new FolderNode(baseDir + QLatin1Char('/') + folderName);
folder->setDisplayName(component);
folderByName->insert(folderName, folder);
FolderNode *parent = findOrCreateFolderByName(folderByName, components, end - 1);
FolderNode *parent = findFolderByName(components, end - 1);
if (!parent)
parent = this;
parent = createFolderByName(components, end - 1);
addFolderNodes(QList<FolderNode*>() << folder, parent);
return folder;
}
FolderNode *GenericProjectNode::findFolderByName(const QStringList &components, int end)
{
if (end == 0)
return this;
QString folderName;
for (int i = 0; i < end; ++i) {
folderName.append(components.at(i));
folderName += QLatin1Char('/');
}
FolderNode *parent = findFolderByName(components, end - 1);
if (!parent)
return 0;
const QString baseDir = QFileInfo(path()).path();
foreach (FolderNode *fn, parent->subFolderNodes())
if (fn->path() == baseDir + QLatin1Char('/') + folderName)
return fn;
return 0;
}
bool GenericProjectNode::hasBuildTargets() const
{
return true;
......
......@@ -34,6 +34,7 @@
#include <QStringList>
#include <QHash>
#include <QSet>
namespace Core {
class IDocument;
......@@ -77,12 +78,13 @@ public:
QList<ProjectExplorer::RunConfiguration *> runConfigurationsFor(Node *node);
void refresh();
void refresh(QSet<QString> oldFileList = QSet<QString>());
private:
typedef QHash<QString, FolderNode *> FolderByName;
FolderNode *findOrCreateFolderByName(FolderByName *folderByName,
const QStringList &components, int end);
FolderNode *createFolderByName(const QStringList &components, int end);
FolderNode *findFolderByName(const QStringList &components, int end);
void removeEmptySubFolders(FolderNode *gparent, FolderNode *parent);
private:
GenericProject *m_project;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment