aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qbsprojectmanager
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2020-02-04 14:59:08 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2020-02-06 17:00:56 +0000
commita6e6a53e82a06b0c78c20e44643f7bdc050862df (patch)
treec8f415570aa66040686282747d4c528d465e4e27 /src/plugins/qbsprojectmanager
parentede1d31a3f859ecdf0143d3e5b2aba208ede1b76 (diff)
QbsProjectManager: Build up the project tree in a dedicated thread
... and only switch the root node in the UI thread. Creating the project tree can take some time for larger projects; no need to block the UI for that. Task-number: QTCREATORBUG-18533 Change-Id: I093dc9fb8f3454011a3c64bcc0f785e8b7753b4e Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/plugins/qbsprojectmanager')
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp26
-rw-r--r--src/plugins/qbsprojectmanager/qbsnodetreebuilder.h15
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp75
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.h11
4 files changed, 81 insertions, 46 deletions
diff --git a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp
index bcf52a96f1f..18a994d3844 100644
--- a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp
+++ b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp
@@ -194,32 +194,32 @@ static QStringList unreferencedBuildSystemFiles(const QJsonObject &project)
return unreferenced;
}
-std::unique_ptr<QbsProjectNode> QbsNodeTreeBuilder::buildTree(const QbsBuildSystem *buildSystem)
+QbsProjectNode *QbsNodeTreeBuilder::buildTree(const QString &projectName,
+ const Utils::FilePath &projectFile,
+ const Utils::FilePath &projectDir,
+ const QJsonObject &projectData)
{
- const Project * const project = buildSystem->project();
- auto root = std::make_unique<QbsProjectNode>(buildSystem->projectData());
+ auto root = std::make_unique<QbsProjectNode>(projectData);
// If we have no project information at all (i.e. it could not be properly parsed),
// create the main project file node "manually".
- if (buildSystem->projectData().isEmpty()) {
- auto fileNode = std::make_unique<FileNode>(project->projectFilePath(), FileType::Project);
+ if (projectData.isEmpty()) {
+ auto fileNode = std::make_unique<FileNode>(projectFile, FileType::Project);
root->addNode(std::move(fileNode));
} else {
setupProjectNode(root.get());
}
if (root->displayName().isEmpty())
- root->setDisplayName(project->displayName());
+ root->setDisplayName(projectName);
if (root->displayName().isEmpty())
- root->setDisplayName(project->projectFilePath().toFileInfo().completeBaseName());
+ root->setDisplayName(projectFile.toFileInfo().completeBaseName());
- auto buildSystemFiles = std::make_unique<FolderNode>(project->projectDirectory());
+ auto buildSystemFiles = std::make_unique<FolderNode>(projectDir);
buildSystemFiles->setDisplayName(QCoreApplication::translate("QbsProjectNode", "Qbs files"));
- const FilePath projectDir = project->projectDirectory();
- const FilePath buildDir = FilePath::fromString(buildSystem->projectData()
- .value("build-directory").toString());
- const QStringList files = unreferencedBuildSystemFiles(buildSystem->projectData());
+ const FilePath buildDir = FilePath::fromString(projectData.value("build-directory").toString());
+ const QStringList files = unreferencedBuildSystemFiles(projectData);
for (const QString &f : files) {
const FilePath filePath = FilePath::fromString(f);
if (filePath.isChildOf(projectDir)) {
@@ -230,7 +230,7 @@ std::unique_ptr<QbsProjectNode> QbsNodeTreeBuilder::buildTree(const QbsBuildSyst
}
buildSystemFiles->compress();
root->addNode(std::move(buildSystemFiles));
- return root;
+ return root.release();
}
} // namespace Internal
diff --git a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.h b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.h
index 3c2cd450dc3..7bbff704ac8 100644
--- a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.h
+++ b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.h
@@ -25,18 +25,29 @@
#pragma once
+#include <QtGlobal>
+
#include <memory>
+QT_BEGIN_NAMESPACE
+class QJsonObject;
+class QString;
+QT_END_NAMESPACE
+
+namespace Utils { class FilePath; }
+
namespace QbsProjectManager {
namespace Internal {
-class QbsBuildSystem;
class QbsProjectNode;
class QbsNodeTreeBuilder
{
public:
- static std::unique_ptr<QbsProjectNode> buildTree(const QbsBuildSystem *buildSystem);
+ static QbsProjectNode *buildTree(const QString &projectName,
+ const Utils::FilePath &projectFile,
+ const Utils::FilePath &projectDir,
+ const QJsonObject &projectData);
};
} // namespace Internal
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index dba851338e0..f5b2538dc87 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -67,6 +67,7 @@
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
+#include <utils/runextensions.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljstools/qmljsmodelmanager.h>
#include <qtsupport/qtcppkitinfo.h>
@@ -214,8 +215,7 @@ QbsBuildSystem::QbsBuildSystem(QbsBuildConfiguration *bc)
connect(&m_parsingDelay, &QTimer::timeout, this, &QbsBuildSystem::triggerParsing);
connect(bc->project(), &Project::projectFileIsDirty, this, &QbsBuildSystem::delayParsing);
-
- rebuildProjectTree();
+ updateProjectNodes({});
}
QbsBuildSystem::~QbsBuildSystem()
@@ -447,6 +447,7 @@ bool QbsBuildSystem::checkCancelStatus()
qCDebug(qbsPmLog) << "Cancel request while parsing, starting re-parse";
m_qbsProjectParser->deleteLater();
m_qbsProjectParser = nullptr;
+ m_treeCreationWatcher = nullptr;
m_guard = {};
parseCurrentBuildConfiguration();
return true;
@@ -456,15 +457,18 @@ void QbsBuildSystem::updateAfterParse()
{
qCDebug(qbsPmLog) << "Updating data after parse";
OpTimer opTimer("updateAfterParse");
- updateProjectNodes();
- updateDocuments();
- updateBuildTargetData();
- updateCppCodeModel();
- updateExtraCompilers();
- updateQmlJsCodeModel();
- emit project()->fileListChanged();
- m_envCache.clear();
- emitBuildSystemUpdated();
+ updateProjectNodes([this] {
+ updateDocuments();
+ updateBuildTargetData();
+ updateCppCodeModel();
+ updateExtraCompilers();
+ updateQmlJsCodeModel();
+ emit project()->fileListChanged();
+ m_envCache.clear();
+ m_guard.markAsSuccess();
+ m_guard = {};
+ emitBuildSystemUpdated();
+ });
}
void QbsBuildSystem::delayedUpdateAfterParse()
@@ -472,10 +476,32 @@ void QbsBuildSystem::delayedUpdateAfterParse()
QTimer::singleShot(0, this, &QbsBuildSystem::updateAfterParse);
}
-void QbsBuildSystem::updateProjectNodes()
+void QbsBuildSystem::updateProjectNodes(const std::function<void ()> &continuation)
{
- OpTimer opTimer("updateProjectNodes");
- rebuildProjectTree();
+ m_treeCreationWatcher = new TreeCreationWatcher(this);
+ connect(m_treeCreationWatcher, &TreeCreationWatcher::finished, this,
+ [this, watcher = m_treeCreationWatcher, continuation] {
+ std::unique_ptr<QbsProjectNode> rootNode(m_treeCreationWatcher->result());
+ if (watcher != m_treeCreationWatcher) {
+ watcher->deleteLater();
+ return;
+ }
+ OpTimer("updateProjectNodes continuation");
+ m_treeCreationWatcher->deleteLater();
+ m_treeCreationWatcher = nullptr;
+ if (target() != project()->activeTarget()
+ || target()->activeBuildConfiguration()->buildSystem() != this) {
+ return;
+ }
+ project()->setDisplayName(rootNode->displayName());
+ setRootProjectNode(std::move(rootNode));
+ if (continuation)
+ continuation();
+ });
+ m_treeCreationWatcher->setFuture(runAsync(ProjectExplorerPlugin::sharedThreadPool(),
+ QThread::LowPriority, &QbsNodeTreeBuilder::buildTree,
+ project()->displayName(), project()->projectFilePath(), project()->projectDirectory(),
+ projectData()));
}
FilePath QbsBuildSystem::installRoot()
@@ -525,8 +551,10 @@ void QbsBuildSystem::handleQbsParsingDone(bool success)
delete m_qbsUpdateFutureInterface;
m_qbsUpdateFutureInterface = nullptr;
- if (dataChanged)
+ if (dataChanged) {
updateAfterParse();
+ return;
+ }
else if (envChanged)
updateCppCodeModel();
if (success)
@@ -539,13 +567,6 @@ void QbsBuildSystem::handleQbsParsingDone(bool success)
emitBuildSystemUpdated();
}
-void QbsBuildSystem::rebuildProjectTree()
-{
- std::unique_ptr<QbsProjectNode> newRoot = QbsNodeTreeBuilder::buildTree(this);
- project()->setDisplayName(newRoot->displayName());
- setRootProjectNode(std::move(newRoot));
-}
-
void QbsBuildSystem::changeActiveTarget(Target *t)
{
if (t)
@@ -609,6 +630,7 @@ void QbsBuildSystem::parseCurrentBuildConfiguration()
QTC_ASSERT(!m_qbsProjectParser, return);
m_qbsProjectParser = new QbsProjectParser(this, m_qbsUpdateFutureInterface);
+ m_treeCreationWatcher = nullptr;
connect(m_qbsProjectParser, &QbsProjectParser::done,
this, &QbsBuildSystem::handleQbsParsingDone);
@@ -636,10 +658,11 @@ void QbsBuildSystem::updateAfterBuild()
}
qCDebug(qbsPmLog) << "Updating data after build";
m_projectData = projectData;
- updateProjectNodes();
- updateBuildTargetData();
- updateExtraCompilers();
- m_envCache.clear();
+ updateProjectNodes([this] {
+ updateBuildTargetData();
+ updateExtraCompilers();
+ m_envCache.clear();
+ });
}
void QbsBuildSystem::generateErrors(const ErrorInfo &e)
diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h
index 8f19cc0f036..250d544e3b0 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.h
+++ b/src/plugins/qbsprojectmanager/qbsproject.h
@@ -36,10 +36,13 @@
#include <utils/environment.h>
+#include <QFutureWatcher>
#include <QHash>
#include <QJsonObject>
#include <QTimer>
+#include <functional>
+
namespace CppTools { class CppProjectUpdater; }
namespace QbsProjectManager {
@@ -125,11 +128,7 @@ private:
friend class QbsProject;
void handleQbsParsingDone(bool success);
-
- void rebuildProjectTree();
-
void changeActiveTarget(ProjectExplorer::Target *t);
-
void prepareForParsing();
void updateDocuments();
void updateCppCodeModel();
@@ -141,7 +140,7 @@ private:
bool checkCancelStatus();
void updateAfterParse();
void delayedUpdateAfterParse();
- void updateProjectNodes();
+ void updateProjectNodes(const std::function<void()> &continuation);
Utils::FilePath installRoot();
static bool ensureWriteableQbsFile(const QString &file);
@@ -153,6 +152,8 @@ private:
QTimer m_parsingDelay;
QbsProjectParser *m_qbsProjectParser = nullptr;
QFutureInterface<bool> *m_qbsUpdateFutureInterface = nullptr;
+ using TreeCreationWatcher = QFutureWatcher<QbsProjectNode *>;
+ TreeCreationWatcher *m_treeCreationWatcher = nullptr;
Utils::Environment m_lastParseEnv;
bool m_parsingScheduled = false;