diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h index 1e821a4bcb0..c337d93bb99 100644 --- a/src/libs/utils/algorithm.h +++ b/src/libs/utils/algorithm.h @@ -1272,7 +1272,21 @@ QSet toSet(const QList &list) #endif } -template +template +QSet toSet(const QVector &vec) +{ +#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) + QSet result; + for (const T &p : vec) { + result.insert(p); + } + return result; +#else + return QSet(vec.begin(), vec.end()); +#endif +} + +template QList toList(const QSet &set) { #if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 158863d39a2..1afc23a5a4c 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -120,10 +120,10 @@ ProjectDocument::ProjectDocument(const QString &mimeType, const Utils::FilePath const ProjectDocument::ProjectCallback &callback) : m_callback(callback) { + QTC_CHECK(callback); setFilePath(fileName); setMimeType(mimeType); - if (m_callback) - Core::DocumentManager::addDocument(this); + Core::DocumentManager::addDocument(this); } Core::IDocument::ReloadBehavior @@ -142,8 +142,7 @@ bool ProjectDocument::reload(QString *errorString, Core::IDocument::ReloadFlag f Q_UNUSED(flag) Q_UNUSED(type) - if (m_callback) - m_callback(); + m_callback(); return true; } @@ -153,12 +152,6 @@ bool ProjectDocument::reload(QString *errorString, Core::IDocument::ReloadFlag f class ProjectPrivate { public: - ProjectPrivate(const QString &mimeType, const Utils::FilePath &fileName, - const ProjectDocument::ProjectCallback &callback) - { - m_document = std::make_unique(mimeType, fileName, callback); - } - ~ProjectPrivate(); Core::Id m_id; @@ -170,6 +163,7 @@ public: bool m_hasMakeInstallEquivalent = false; bool m_needsBuildConfigurations = true; std::unique_ptr m_document; + std::vector> m_extraProjectDocuments; std::unique_ptr m_rootProjectNode; std::unique_ptr m_containerNode; std::vector> m_targets; @@ -195,10 +189,19 @@ ProjectPrivate::~ProjectPrivate() std::unique_ptr oldNode = std::move(m_rootProjectNode); } -Project::Project(const QString &mimeType, const Utils::FilePath &fileName, - const ProjectDocument::ProjectCallback &callback) : - d(new ProjectPrivate(mimeType, fileName, callback)) +Project::Project(const QString &mimeType, + const Utils::FilePath &fileName, + const ProjectDocument::ProjectCallback &callback) + : d(new ProjectPrivate) { + d->m_document = std::make_unique(mimeType, + fileName, + [this, fileName, callback]() { + emit projectFileIsDirty(fileName); + if (callback) + callback(); + }); + d->m_macroExpander.setDisplayName(tr("Project")); d->m_macroExpander.registerVariable("Project:Name", tr("Project Name"), [this] { return displayName(); }); @@ -339,6 +342,28 @@ void Project::setNeedsInitialExpansion(bool needsExpansion) d->m_needsInitialExpansion = needsExpansion; } +void Project::setExtraProjectFiles(const QVector &projectDocumentPaths) +{ + QSet uniqueNewFiles = Utils::toSet(projectDocumentPaths); + uniqueNewFiles.remove(projectFilePath()); // Make sure to never add the main project file! + + QSet existingWatches = Utils::transform(d->m_extraProjectDocuments, + &Core::IDocument::filePath); + + QSet toAdd = uniqueNewFiles.subtract(existingWatches); + QSet toRemove = existingWatches.subtract(uniqueNewFiles); + + Utils::erase(d->m_extraProjectDocuments, [&toRemove](const std::unique_ptr &d) { + return toRemove.contains(d->filePath()); + }); + for (const Utils::FilePath &p : toAdd) { + d->m_extraProjectDocuments.emplace_back( + std::make_unique(d->m_document->mimeType(), p, [this, p]() { + emit projectFileIsDirty(p); + })); + } +} + Target *Project::target(Core::Id id) const { return Utils::findOrDefault(d->m_targets, Utils::equal(&Target::id, id)); diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 1af8e6c34fe..45c8409d767 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -250,7 +250,13 @@ public: // FIXME: Make this private and the BuildSystem a friend ParseGuard guardParsingRun() { return ParseGuard(this); } + // Set project files that will be watched and trigger the same callback + // as the main project file. + void setExtraProjectFiles(const QVector &projectDocumentPaths); + signals: + void projectFileIsDirty(const Utils::FilePath &path); + void displayNameChanged(); void fileListChanged();