forked from qt-creator/qt-creator
ProjectExplorer: add workspace build configurations
Change-Id: Iaa23a50052ec46e50f43e79d378c07ccec5ef2e1 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -52,6 +52,60 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"build.configuration": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "A list of build configurations",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"steps": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"arguments": {
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Arguments to pass to the executable"
|
||||||
|
},
|
||||||
|
"executable": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The executable to run"
|
||||||
|
},
|
||||||
|
"workingDirectory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The working directory to run the executable in"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"executable"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "The steps required for the build"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the build configuration"
|
||||||
|
},
|
||||||
|
"buildDirectory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The directory to build the project in"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"steps",
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -371,6 +371,13 @@ void BuildConfiguration::appendInitialCleanStep(Utils::Id id)
|
|||||||
d->m_initialCleanSteps.append(id);
|
d->m_initialCleanSteps.append(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BuildConfiguration *BuildConfiguration::clone(Target *target) const
|
||||||
|
{
|
||||||
|
Store map;
|
||||||
|
toMap(map);
|
||||||
|
return BuildConfigurationFactory::restore(target, map);
|
||||||
|
}
|
||||||
|
|
||||||
void BuildConfiguration::toMap(Store &map) const
|
void BuildConfiguration::toMap(Store &map) const
|
||||||
{
|
{
|
||||||
ProjectConfiguration::toMap(map);
|
ProjectConfiguration::toMap(map);
|
||||||
@@ -834,12 +841,4 @@ BuildConfiguration *BuildConfigurationFactory::restore(Target *parent, const Sto
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildConfiguration *BuildConfigurationFactory::clone(Target *parent,
|
|
||||||
const BuildConfiguration *source)
|
|
||||||
{
|
|
||||||
Store map;
|
|
||||||
source->toMap(map);
|
|
||||||
return restore(parent, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -68,6 +68,7 @@ public:
|
|||||||
void appendInitialBuildStep(Utils::Id id);
|
void appendInitialBuildStep(Utils::Id id);
|
||||||
void appendInitialCleanStep(Utils::Id id);
|
void appendInitialCleanStep(Utils::Id id);
|
||||||
|
|
||||||
|
virtual BuildConfiguration *clone(Target *target) const;
|
||||||
void fromMap(const Utils::Store &map) override;
|
void fromMap(const Utils::Store &map) override;
|
||||||
void toMap(Utils::Store &map) const override;
|
void toMap(Utils::Store &map) const override;
|
||||||
|
|
||||||
@@ -149,7 +150,6 @@ public:
|
|||||||
BuildConfiguration *create(Target *parent, const BuildInfo &info) const;
|
BuildConfiguration *create(Target *parent, const BuildInfo &info) const;
|
||||||
|
|
||||||
static BuildConfiguration *restore(Target *parent, const Utils::Store &map);
|
static BuildConfiguration *restore(Target *parent, const Utils::Store &map);
|
||||||
static BuildConfiguration *clone(Target *parent, const BuildConfiguration *source);
|
|
||||||
|
|
||||||
static BuildConfigurationFactory *find(const Kit *k, const Utils::FilePath &projectPath);
|
static BuildConfigurationFactory *find(const Kit *k, const Utils::FilePath &projectPath);
|
||||||
static BuildConfigurationFactory *find(Target *parent);
|
static BuildConfigurationFactory *find(Target *parent);
|
||||||
|
@@ -187,7 +187,7 @@ void BuildSettingsWidget::currentIndexChanged(int index)
|
|||||||
|
|
||||||
void BuildSettingsWidget::updateActiveConfiguration()
|
void BuildSettingsWidget::updateActiveConfiguration()
|
||||||
{
|
{
|
||||||
if (!m_buildConfiguration || m_buildConfiguration == m_target->activeBuildConfiguration())
|
if (m_buildConfiguration == m_target->activeBuildConfiguration())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_buildConfiguration = m_target->activeBuildConfiguration();
|
m_buildConfiguration = m_target->activeBuildConfiguration();
|
||||||
@@ -281,7 +281,7 @@ void BuildSettingsWidget::cloneConfiguration()
|
|||||||
// Save the current build configuration settings, so that the clone gets all the settings
|
// Save the current build configuration settings, so that the clone gets all the settings
|
||||||
m_target->project()->saveSettings();
|
m_target->project()->saveSettings();
|
||||||
|
|
||||||
BuildConfiguration *bc = BuildConfigurationFactory::clone(m_target, m_buildConfiguration);
|
BuildConfiguration *bc = m_buildConfiguration->clone(m_target);
|
||||||
if (!bc)
|
if (!bc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -508,7 +508,7 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
|
|||||||
|
|
||||||
const Project * const project = newTarget->project();
|
const Project * const project = newTarget->project();
|
||||||
for (BuildConfiguration *sourceBc : sourceTarget->buildConfigurations()) {
|
for (BuildConfiguration *sourceBc : sourceTarget->buildConfigurations()) {
|
||||||
BuildConfiguration *newBc = BuildConfigurationFactory::clone(newTarget, sourceBc);
|
BuildConfiguration *newBc = sourceBc->clone(newTarget);
|
||||||
if (!newBc) {
|
if (!newBc) {
|
||||||
buildconfigurationError << sourceBc->displayName();
|
buildconfigurationError << sourceBc->displayName();
|
||||||
continue;
|
continue;
|
||||||
|
@@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
#include "buildconfiguration.h"
|
#include "buildconfiguration.h"
|
||||||
#include "buildinfo.h"
|
#include "buildinfo.h"
|
||||||
|
#include "buildsteplist.h"
|
||||||
#include "buildsystem.h"
|
#include "buildsystem.h"
|
||||||
|
#include "processstep.h"
|
||||||
#include "projectexplorer.h"
|
#include "projectexplorer.h"
|
||||||
#include "projectexplorerconstants.h"
|
#include "projectexplorerconstants.h"
|
||||||
#include "projectexplorertr.h"
|
#include "projectexplorertr.h"
|
||||||
@@ -35,7 +37,8 @@ using namespace Core;
|
|||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(wsbs, "qtc.projectexplorer.workspacebuildsystem", QtWarningMsg);
|
Q_LOGGING_CATEGORY(wsbs, "qtc.projectexplorer.workspace.buildsystem", QtWarningMsg);
|
||||||
|
Q_LOGGING_CATEGORY(wsp, "qtc.projectexplorer.workspace.project", QtWarningMsg);
|
||||||
|
|
||||||
const QLatin1StringView FOLDER_MIMETYPE{"inode/directory"};
|
const QLatin1StringView FOLDER_MIMETYPE{"inode/directory"};
|
||||||
const QLatin1StringView WORKSPACE_MIMETYPE{"text/x-workspace-project"};
|
const QLatin1StringView WORKSPACE_MIMETYPE{"text/x-workspace-project"};
|
||||||
@@ -47,9 +50,9 @@ const QLatin1StringView FILES_EXCLUDE_KEY{"files.exclude"};
|
|||||||
const char EXCLUDE_ACTION_ID[] = "ProjectExplorer.ExcludeFromWorkspace";
|
const char EXCLUDE_ACTION_ID[] = "ProjectExplorer.ExcludeFromWorkspace";
|
||||||
const char RESCAN_ACTION_ID[] = "ProjectExplorer.RescanWorkspace";
|
const char RESCAN_ACTION_ID[] = "ProjectExplorer.RescanWorkspace";
|
||||||
|
|
||||||
const expected_str<QJsonObject> projectDefinition(const Project *project)
|
const expected_str<QJsonObject> projectDefinition(const FilePath &path)
|
||||||
{
|
{
|
||||||
if (auto fileContents = project->projectFilePath().fileContents())
|
if (auto fileContents = path.fileContents())
|
||||||
return QJsonDocument::fromJson(*fileContents).object();
|
return QJsonDocument::fromJson(*fileContents).object();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -156,7 +159,7 @@ WorkspaceBuildSystem::WorkspaceBuildSystem(Target *t)
|
|||||||
scanNext();
|
scanNext();
|
||||||
});
|
});
|
||||||
m_scanner.setDirFilter(workspaceDirFilter);
|
m_scanner.setDirFilter(workspaceDirFilter);
|
||||||
m_scanner.setFilter([&](const Utils::MimeType &, const Utils::FilePath &filePath) {
|
m_scanner.setFilter([&](const MimeType &, const FilePath &filePath) {
|
||||||
return Utils::anyOf(m_filters, [filePath](const QRegularExpression &filter) {
|
return Utils::anyOf(m_filters, [filePath](const QRegularExpression &filter) {
|
||||||
return filter.match(filePath.path()).hasMatch();
|
return filter.match(filePath.path()).hasMatch();
|
||||||
});
|
});
|
||||||
@@ -176,7 +179,7 @@ void WorkspaceBuildSystem::reparse(bool force)
|
|||||||
m_filters.clear();
|
m_filters.clear();
|
||||||
FilePath projectPath = project()->projectDirectory();
|
FilePath projectPath = project()->projectDirectory();
|
||||||
|
|
||||||
const QJsonObject json = projectDefinition(project()).value_or(QJsonObject());
|
const QJsonObject json = projectDefinition(project()->projectFilePath()).value_or(QJsonObject());
|
||||||
const QJsonValue projectNameValue = json.value(PROJECT_NAME_KEY);
|
const QJsonValue projectNameValue = json.value(PROJECT_NAME_KEY);
|
||||||
if (projectNameValue.isString())
|
if (projectNameValue.isString())
|
||||||
project()->setDisplayName(projectNameValue.toString());
|
project()->setDisplayName(projectNameValue.toString());
|
||||||
@@ -434,40 +437,146 @@ public:
|
|||||||
|
|
||||||
class WorkspaceBuildConfiguration : public BuildConfiguration
|
class WorkspaceBuildConfiguration : public BuildConfiguration
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
WorkspaceBuildConfiguration(Target *target, Id id)
|
WorkspaceBuildConfiguration(Target *target, Id id)
|
||||||
: BuildConfiguration(target, id)
|
: BuildConfiguration(target, id)
|
||||||
{
|
{
|
||||||
|
setInitializer([this](const BuildInfo &info) {
|
||||||
|
const QVariantMap extraInfos = info.extraInfo.toMap();
|
||||||
|
if (extraInfos.empty())
|
||||||
|
return;
|
||||||
|
BuildStepList *steps = buildSteps();
|
||||||
|
for (const QVariant &buildStep : extraInfos["steps"].toList()) {
|
||||||
|
const QVariantMap bs = buildStep.toMap();
|
||||||
|
auto step = new Internal::ProcessStep(steps, Constants::CUSTOM_PROCESS_STEP);
|
||||||
|
step->setCommand(FilePath::fromUserInput(bs["executable"].toString()));
|
||||||
|
step->setArguments(bs["arguments"].toStringList());
|
||||||
|
FilePath wd = FilePath::fromUserInput(bs["workingDirectory"].toString());
|
||||||
|
if (wd.isEmpty())
|
||||||
|
wd = "%{ActiveProject:BuildConfig:Path}";
|
||||||
|
else if (wd.isRelativePath())
|
||||||
|
wd = project()->projectDirectory().resolvePath(wd);
|
||||||
|
step->setWorkingDirectory(wd);
|
||||||
|
steps->appendStep(step);
|
||||||
|
}
|
||||||
|
initializeExtraInfo(extraInfos);
|
||||||
|
});
|
||||||
setBuildDirectoryHistoryCompleter("Workspace.BuildDir.History");
|
setBuildDirectoryHistoryCompleter("Workspace.BuildDir.History");
|
||||||
setConfigWidgetDisplayName(Tr::tr("Workspace Manager"));
|
setConfigWidgetDisplayName(Tr::tr("Workspace Manager"));
|
||||||
|
|
||||||
//appendInitialBuildStep(Constants::CUSTOM_PROCESS_STEP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initializeExtraInfo(const QVariantMap &extraInfos)
|
||||||
|
{
|
||||||
|
resetExtraInfo();
|
||||||
|
if (extraInfos["forSetup"].toBool()) {
|
||||||
|
originalExtraInfo = extraInfos;
|
||||||
|
buildInfoResetConnection = connect(
|
||||||
|
this, &BaseAspect::changed, this, &WorkspaceBuildConfiguration::resetExtraInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fromMap(const Utils::Store &map) override
|
||||||
|
{
|
||||||
|
BuildConfiguration::fromMap(map);
|
||||||
|
initializeExtraInfo(mapFromStore(storeFromVariant(map.value("extraInfo"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void toMap(Utils::Store &map) const override
|
||||||
|
{
|
||||||
|
BuildConfiguration::toMap(map);
|
||||||
|
if (originalExtraInfo)
|
||||||
|
map.insert("extraInfo", *originalExtraInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfiguration *clone(Target *target) const override
|
||||||
|
{
|
||||||
|
auto clone = BuildConfiguration::clone(target);
|
||||||
|
if (auto bc = qobject_cast<WorkspaceBuildConfiguration *>(clone); QTC_GUARD(bc))
|
||||||
|
bc->resetExtraInfo();
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetExtraInfo()
|
||||||
|
{
|
||||||
|
originalExtraInfo.reset();
|
||||||
|
disconnect(buildInfoResetConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<QVariantMap> originalExtraInfo;
|
||||||
|
QMetaObject::Connection buildInfoResetConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspaceBuildConfigurationFactory : public BuildConfigurationFactory
|
class WorkspaceBuildConfigurationFactory : public BuildConfigurationFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static WorkspaceBuildConfigurationFactory *m_instance;
|
||||||
|
|
||||||
WorkspaceBuildConfigurationFactory()
|
WorkspaceBuildConfigurationFactory()
|
||||||
{
|
{
|
||||||
|
QTC_CHECK(m_instance == nullptr);
|
||||||
|
m_instance = this;
|
||||||
registerBuildConfiguration<WorkspaceBuildConfiguration>
|
registerBuildConfiguration<WorkspaceBuildConfiguration>
|
||||||
("WorkspaceProject.BuildConfiguration");
|
("WorkspaceProject.BuildConfiguration");
|
||||||
|
|
||||||
setSupportedProjectType(WORKSPACE_PROJECT_ID);
|
setSupportedProjectType(WORKSPACE_PROJECT_ID);
|
||||||
|
setSupportedProjectMimeTypeName(WORKSPACE_MIMETYPE);
|
||||||
|
|
||||||
setBuildGenerator([](const Kit *, const FilePath &projectPath, bool forSetup) {
|
setBuildGenerator([this](const Kit *, const FilePath &projectPath, bool forSetup) {
|
||||||
|
QList<BuildInfo> result = parseBuildConfigurations(projectPath, forSetup);
|
||||||
|
if (!forSetup) {
|
||||||
BuildInfo info;
|
BuildInfo info;
|
||||||
|
info.factory = this;
|
||||||
info.typeName = ::ProjectExplorer::Tr::tr("Build");
|
info.typeName = ::ProjectExplorer::Tr::tr("Build");
|
||||||
info.buildDirectory = projectPath.parentDir().parentDir().pathAppended("build");
|
info.buildDirectory = projectPath.parentDir().parentDir().pathAppended("build");
|
||||||
if (forSetup) {
|
|
||||||
//: The name of the build configuration created by default for a workspace project.
|
|
||||||
info.displayName = ::ProjectExplorer::Tr::tr("Default");
|
info.displayName = ::ProjectExplorer::Tr::tr("Default");
|
||||||
|
result << info;
|
||||||
}
|
}
|
||||||
return QList<BuildInfo>{info};
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QList<BuildInfo> parseBuildConfigurations(const FilePath &projectPath, bool forSetup = false)
|
||||||
|
{
|
||||||
|
const QJsonObject json = projectDefinition(projectPath).value_or(QJsonObject());
|
||||||
|
const QJsonArray buildConfigs = json.value("build.configuration").toArray();
|
||||||
|
QList<BuildInfo> buildInfos;
|
||||||
|
for (const QJsonValue &buildConfig : buildConfigs) {
|
||||||
|
QTC_ASSERT(buildConfig.isObject(), continue);
|
||||||
|
|
||||||
|
BuildInfo buildInfo;
|
||||||
|
const QJsonObject buildConfigObject = buildConfig.toObject();
|
||||||
|
buildInfo.displayName = buildConfigObject["name"].toString();
|
||||||
|
if (buildInfo.displayName.isEmpty())
|
||||||
|
continue;
|
||||||
|
buildInfo.typeName = buildInfo.displayName;
|
||||||
|
buildInfo.factory = m_instance;
|
||||||
|
buildInfo.buildDirectory = FilePath::fromUserInput(
|
||||||
|
buildConfigObject["buildDirectory"].toString());
|
||||||
|
if (buildInfo.buildDirectory.isRelativePath()) {
|
||||||
|
buildInfo.buildDirectory = projectPath.parentDir().parentDir().resolvePath(
|
||||||
|
buildInfo.buildDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList buildSteps;
|
||||||
|
for (const QJsonValue &step : buildConfigObject["steps"].toArray()) {
|
||||||
|
if (step.isObject() && step.toObject().contains("executable"))
|
||||||
|
buildSteps.append(step.toObject().toVariantMap());
|
||||||
|
}
|
||||||
|
if (buildSteps.isEmpty())
|
||||||
|
continue;
|
||||||
|
QVariantMap extraInfo = buildConfigObject.toVariantMap();
|
||||||
|
extraInfo["forSetup"] = forSetup;
|
||||||
|
buildInfo.extraInfo = extraInfo;
|
||||||
|
|
||||||
|
buildInfos.append(buildInfo);
|
||||||
|
}
|
||||||
|
return buildInfos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WorkspaceBuildConfigurationFactory *WorkspaceBuildConfigurationFactory::m_instance = nullptr;
|
||||||
|
|
||||||
class WorkspaceProject : public Project
|
class WorkspaceProject : public Project
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -486,6 +595,48 @@ public:
|
|||||||
setId(WORKSPACE_PROJECT_ID);
|
setId(WORKSPACE_PROJECT_ID);
|
||||||
setDisplayName(projectDirectory().fileName());
|
setDisplayName(projectDirectory().fileName());
|
||||||
setBuildSystemCreator<WorkspaceBuildSystem>();
|
setBuildSystemCreator<WorkspaceBuildSystem>();
|
||||||
|
|
||||||
|
connect(this, &Project::projectFileIsDirty, this, &WorkspaceProject::updateBuildConfigurations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBuildConfigurations()
|
||||||
|
{
|
||||||
|
qCDebug(wsp) << "Updating build configurations for" << displayName();
|
||||||
|
const QList<BuildInfo> buildInfos
|
||||||
|
= WorkspaceBuildConfigurationFactory::parseBuildConfigurations(projectFilePath(), true);
|
||||||
|
for (Target *target : targets()) {
|
||||||
|
qCDebug(wsp) << "Updating build configurations for target" << target->displayName();
|
||||||
|
QList<BuildInfo> toAdd = buildInfos;
|
||||||
|
QString removedActiveBuildConfiguration;
|
||||||
|
for (BuildConfiguration *bc : target->buildConfigurations()) {
|
||||||
|
auto *wbc = qobject_cast<WorkspaceBuildConfiguration *>(bc);
|
||||||
|
if (!wbc)
|
||||||
|
continue;
|
||||||
|
if (std::optional<QVariantMap> extraInfo = wbc->originalExtraInfo) {
|
||||||
|
// remove the buildConfiguration if it is unchanged from the project file
|
||||||
|
auto equalExtraInfo = [&extraInfo](const BuildInfo &info) {
|
||||||
|
return info.extraInfo == *extraInfo;
|
||||||
|
};
|
||||||
|
if (toAdd.removeIf(equalExtraInfo) == 0) {
|
||||||
|
qCDebug(wsp) << " Removing build configuration" << wbc->displayName();
|
||||||
|
if (target->activeBuildConfiguration() == wbc)
|
||||||
|
removedActiveBuildConfiguration = wbc->displayName();
|
||||||
|
target->removeBuildConfiguration(bc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const BuildInfo &buildInfo : toAdd) {
|
||||||
|
if (BuildConfiguration *bc = buildInfo.factory->create(target, buildInfo)) {
|
||||||
|
qCDebug(wsp) << " Adding build configuration" << bc->displayName();
|
||||||
|
target->addBuildConfiguration(bc);
|
||||||
|
if (!removedActiveBuildConfiguration.isEmpty()
|
||||||
|
&& (bc->displayName() == removedActiveBuildConfiguration
|
||||||
|
|| toAdd.size() == 1)) {
|
||||||
|
target->setActiveBuildConfiguration(bc, SetActive::NoCascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath projectDirectory() const override
|
FilePath projectDirectory() const override
|
||||||
@@ -503,7 +654,7 @@ public:
|
|||||||
void excludePath(const FilePath &path)
|
void excludePath(const FilePath &path)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(projectFilePath().exists(), return);
|
QTC_ASSERT(projectFilePath().exists(), return);
|
||||||
if (expected_str<QJsonObject> json = projectDefinition(this)) {
|
if (expected_str<QJsonObject> json = projectDefinition(projectFilePath())) {
|
||||||
QJsonArray excludes = (*json)[FILES_EXCLUDE_KEY].toArray();
|
QJsonArray excludes = (*json)[FILES_EXCLUDE_KEY].toArray();
|
||||||
const QString relative = path.relativePathFrom(projectDirectory()).path();
|
const QString relative = path.relativePathFrom(projectDirectory()).path();
|
||||||
if (excludes.contains(relative))
|
if (excludes.contains(relative))
|
||||||
|
Reference in New Issue
Block a user