Project: Add signal triggered by project files becoming dirty

Add a signal triggered by project files becoming dirty and add
a way to register more project files than just the default with the
project.

This change enables getting rid of filesystemwatchers in derived
classes.

Change-Id: If985b46edf7cb88dd49f1c574f35cf13b5ce82d4
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Tobias Hunger
2019-08-15 12:42:26 +02:00
parent 087396fe00
commit d13307b5bf
3 changed files with 59 additions and 14 deletions

View File

@@ -1272,6 +1272,20 @@ QSet<T> toSet(const QList<T> &list)
#endif #endif
} }
template<class T>
QSet<T> toSet(const QVector<T> &vec)
{
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
QSet<T> result;
for (const T &p : vec) {
result.insert(p);
}
return result;
#else
return QSet<T>(vec.begin(), vec.end());
#endif
}
template<class T> template<class T>
QList<T> toList(const QSet<T> &set) QList<T> toList(const QSet<T> &set)
{ {

View File

@@ -120,9 +120,9 @@ ProjectDocument::ProjectDocument(const QString &mimeType, const Utils::FilePath
const ProjectDocument::ProjectCallback &callback) : const ProjectDocument::ProjectCallback &callback) :
m_callback(callback) m_callback(callback)
{ {
QTC_CHECK(callback);
setFilePath(fileName); setFilePath(fileName);
setMimeType(mimeType); setMimeType(mimeType);
if (m_callback)
Core::DocumentManager::addDocument(this); Core::DocumentManager::addDocument(this);
} }
@@ -142,7 +142,6 @@ bool ProjectDocument::reload(QString *errorString, Core::IDocument::ReloadFlag f
Q_UNUSED(flag) Q_UNUSED(flag)
Q_UNUSED(type) Q_UNUSED(type)
if (m_callback)
m_callback(); m_callback();
return true; return true;
} }
@@ -153,12 +152,6 @@ bool ProjectDocument::reload(QString *errorString, Core::IDocument::ReloadFlag f
class ProjectPrivate class ProjectPrivate
{ {
public: public:
ProjectPrivate(const QString &mimeType, const Utils::FilePath &fileName,
const ProjectDocument::ProjectCallback &callback)
{
m_document = std::make_unique<ProjectDocument>(mimeType, fileName, callback);
}
~ProjectPrivate(); ~ProjectPrivate();
Core::Id m_id; Core::Id m_id;
@@ -170,6 +163,7 @@ public:
bool m_hasMakeInstallEquivalent = false; bool m_hasMakeInstallEquivalent = false;
bool m_needsBuildConfigurations = true; bool m_needsBuildConfigurations = true;
std::unique_ptr<Core::IDocument> m_document; std::unique_ptr<Core::IDocument> m_document;
std::vector<std::unique_ptr<Core::IDocument>> m_extraProjectDocuments;
std::unique_ptr<ProjectNode> m_rootProjectNode; std::unique_ptr<ProjectNode> m_rootProjectNode;
std::unique_ptr<ContainerNode> m_containerNode; std::unique_ptr<ContainerNode> m_containerNode;
std::vector<std::unique_ptr<Target>> m_targets; std::vector<std::unique_ptr<Target>> m_targets;
@@ -195,10 +189,19 @@ ProjectPrivate::~ProjectPrivate()
std::unique_ptr<ProjectNode> oldNode = std::move(m_rootProjectNode); std::unique_ptr<ProjectNode> oldNode = std::move(m_rootProjectNode);
} }
Project::Project(const QString &mimeType, const Utils::FilePath &fileName, Project::Project(const QString &mimeType,
const ProjectDocument::ProjectCallback &callback) : const Utils::FilePath &fileName,
d(new ProjectPrivate(mimeType, fileName, callback)) const ProjectDocument::ProjectCallback &callback)
: d(new ProjectPrivate)
{ {
d->m_document = std::make_unique<ProjectDocument>(mimeType,
fileName,
[this, fileName, callback]() {
emit projectFileIsDirty(fileName);
if (callback)
callback();
});
d->m_macroExpander.setDisplayName(tr("Project")); d->m_macroExpander.setDisplayName(tr("Project"));
d->m_macroExpander.registerVariable("Project:Name", tr("Project Name"), d->m_macroExpander.registerVariable("Project:Name", tr("Project Name"),
[this] { return displayName(); }); [this] { return displayName(); });
@@ -339,6 +342,28 @@ void Project::setNeedsInitialExpansion(bool needsExpansion)
d->m_needsInitialExpansion = needsExpansion; d->m_needsInitialExpansion = needsExpansion;
} }
void Project::setExtraProjectFiles(const QVector<Utils::FilePath> &projectDocumentPaths)
{
QSet<Utils::FilePath> uniqueNewFiles = Utils::toSet(projectDocumentPaths);
uniqueNewFiles.remove(projectFilePath()); // Make sure to never add the main project file!
QSet<Utils::FilePath> existingWatches = Utils::transform<QSet>(d->m_extraProjectDocuments,
&Core::IDocument::filePath);
QSet<Utils::FilePath> toAdd = uniqueNewFiles.subtract(existingWatches);
QSet<Utils::FilePath> toRemove = existingWatches.subtract(uniqueNewFiles);
Utils::erase(d->m_extraProjectDocuments, [&toRemove](const std::unique_ptr<Core::IDocument> &d) {
return toRemove.contains(d->filePath());
});
for (const Utils::FilePath &p : toAdd) {
d->m_extraProjectDocuments.emplace_back(
std::make_unique<ProjectDocument>(d->m_document->mimeType(), p, [this, p]() {
emit projectFileIsDirty(p);
}));
}
}
Target *Project::target(Core::Id id) const Target *Project::target(Core::Id id) const
{ {
return Utils::findOrDefault(d->m_targets, Utils::equal(&Target::id, id)); return Utils::findOrDefault(d->m_targets, Utils::equal(&Target::id, id));

View File

@@ -250,7 +250,13 @@ public:
// FIXME: Make this private and the BuildSystem a friend // FIXME: Make this private and the BuildSystem a friend
ParseGuard guardParsingRun() { return ParseGuard(this); } 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<Utils::FilePath> &projectDocumentPaths);
signals: signals:
void projectFileIsDirty(const Utils::FilePath &path);
void displayNameChanged(); void displayNameChanged();
void fileListChanged(); void fileListChanged();