diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2020-02-04 14:59:08 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2020-02-06 17:00:56 +0000 |
commit | a6e6a53e82a06b0c78c20e44643f7bdc050862df (patch) | |
tree | c8f415570aa66040686282747d4c528d465e4e27 /src/plugins/qbsprojectmanager | |
parent | ede1d31a3f859ecdf0143d3e5b2aba208ede1b76 (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.cpp | 26 | ||||
-rw-r--r-- | src/plugins/qbsprojectmanager/qbsnodetreebuilder.h | 15 | ||||
-rw-r--r-- | src/plugins/qbsprojectmanager/qbsproject.cpp | 75 | ||||
-rw-r--r-- | src/plugins/qbsprojectmanager/qbsproject.h | 11 |
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; |