From 00174e493f8a20d5955015b5521c3e6d860ff671 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Fri, 31 May 2024 16:09:02 +0200 Subject: [PATCH] ProjectExplorer: Add WorkspaceProjectRunConfig Change-Id: I66f25165f652f371130555279eddc0437b011887 Reviewed-by: hjk --- .../projectexplorer/workspaceproject.cpp | 129 +++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/workspaceproject.cpp b/src/plugins/projectexplorer/workspaceproject.cpp index d380f7cea88..2a22c65c4be 100644 --- a/src/plugins/projectexplorer/workspaceproject.cpp +++ b/src/plugins/projectexplorer/workspaceproject.cpp @@ -9,6 +9,9 @@ #include "projectexplorertr.h" #include "projectmanager.h" #include "projecttree.h" +#include "runconfiguration.h" +#include "runconfigurationaspects.h" +#include "runcontrol.h" #include "target.h" #include "treescanner.h" @@ -24,6 +27,7 @@ const QLatin1StringView FOLDER_MIMETYPE{"inode/directory"}; const QLatin1StringView WORKSPACE_MIMETYPE{"text/x-workspace-project"}; const QLatin1StringView WORKSPACE_PROJECT_ID{"ProjectExplorer.WorkspaceProject"}; +const QLatin1StringView WORKSPACE_PROJECT_RUNCONFIG_ID{"WorkspaceProject.RunConfiguration:"}; const QLatin1StringView PROJECT_NAME_KEY{"project.name"}; const QLatin1StringView FILES_EXCLUDE_KEY{"files.exclude"}; @@ -100,7 +104,7 @@ public: if (projectNameValue.isString()) project()->setDisplayName(projectNameValue.toString()); const QJsonArray excludesJson = json.value(FILES_EXCLUDE_KEY).toArray(); - for (QJsonValue excludeJson : excludesJson) { + for (const QJsonValue &excludeJson : excludesJson) { if (excludeJson.isString()) { FilePath absolute = projectPath.pathAppended(excludeJson.toString()); if (absolute.isDir()) @@ -111,6 +115,46 @@ public: } } + QList targetInfos; + + const QJsonArray targets = json.value("targets").toArray(); + int i = 0; + for (const QJsonValue &target : targets) { + i++; + QTC_ASSERT(target.isObject(), continue); + const QJsonObject targetObject = target.toObject(); + + QJsonArray args = targetObject["arguments"].toArray(); + QStringList arguments = Utils::transform(args, [](const QJsonValue &arg) { + return arg.toString(); + }); + FilePath workingDirectory = FilePath::fromUserInput( + targetObject["workingDirectory"].toString()); + + if (!workingDirectory.isDir()) + workingDirectory = FilePath::currentWorkingPath(); + + const QString name = targetObject["name"].toString(); + const FilePath executable = FilePath::fromUserInput( + targetObject["executable"].toString()); + + if (name.isEmpty() || executable.isEmpty()) + continue; + + BuildTargetInfo bti; + bti.buildKey = name + QString::number(i); + bti.displayName = name; + bti.displayNameUniquifier = QString(" (%1)").arg(i); + bti.targetFilePath = executable; + bti.projectFilePath = projectPath; + bti.workingDirectory = workingDirectory; + bti.additionalData = QVariantMap{{"arguments", arguments}}; + + targetInfos << bti; + } + + setApplicationTargets(targetInfos); + m_parseGuard = guardParsingRun(); m_scanner.asyncScanForFiles(target()->project()->projectDirectory()); } @@ -123,6 +167,86 @@ private: TreeScanner m_scanner; }; +class WorkspaceRunConfiguration : public RunConfiguration +{ +public: + WorkspaceRunConfiguration(Target *target, Id id) + : RunConfiguration(target, id) + { + hint.setText( + Tr::tr("You can edit this configuration inside the .qtcreator/project.json file.")); + + const BuildTargetInfo bti = buildTargetInfo(); + executable.setLabelText(Tr::tr("Executable:")); + executable.setReadOnly(true); + executable.setValue(bti.targetFilePath); + executable.setMacroExpanderProvider( + [this]() -> MacroExpander * { return const_cast(macroExpander()); }); + + auto argumentsAsString = [this]() { + return CommandLine{ + "", buildTargetInfo().additionalData.toMap()["arguments"].toStringList()} + .arguments(); + }; + + arguments.setLabelText(Tr::tr("Arguments:")); + arguments.setReadOnly(true); + arguments.setMacroExpander(macroExpander()); + arguments.setArguments(argumentsAsString()); + + workingDirectory.setLabelText(Tr::tr("Working directory:")); + workingDirectory.setReadOnly(true); + workingDirectory.setDefaultWorkingDirectory(bti.workingDirectory); + + setCommandLineGetter([this] { + const BuildTargetInfo bti = buildTargetInfo(); + CommandLine cmdLine{ + macroExpander()->expand(bti.targetFilePath), + Utils::transform( + bti.additionalData.toMap()["arguments"].toStringList(), + [this](const QString &arg) { return macroExpander()->expand(arg); })}; + + return cmdLine; + }); + + setUpdater([this, argumentsAsString] { + const BuildTargetInfo bti = buildTargetInfo(); + executable.setValue(bti.targetFilePath); + arguments.setArguments(argumentsAsString()); + workingDirectory.setDefaultWorkingDirectory(bti.workingDirectory); + }); + + connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update); + } + + TextDisplay hint{this}; + FilePathAspect executable{this}; + ArgumentsAspect arguments{this}; + WorkingDirectoryAspect workingDirectory{this}; +}; + +class WorkspaceProjectRunConfigurationFactory : public RunConfigurationFactory +{ +public: + WorkspaceProjectRunConfigurationFactory() + { + registerRunConfiguration( + Id::fromString(WORKSPACE_PROJECT_RUNCONFIG_ID)); + addSupportedProjectType(Id::fromString(WORKSPACE_PROJECT_ID)); + } +}; + +class WorkspaceProjectRunWorkerFactory : public RunWorkerFactory +{ +public: + WorkspaceProjectRunWorkerFactory() + { + setProduct(); + addSupportedRunMode(Constants::NORMAL_RUN_MODE); + addSupportedRunConfig(Id::fromString(WORKSPACE_PROJECT_RUNCONFIG_ID)); + } +}; + class WorkspaceProject : public Project { Q_OBJECT @@ -203,6 +327,9 @@ void setupWorkspaceProject(QObject *guard) QTC_ASSERT(project, return); project->excludeNode(node); }); + + static WorkspaceProjectRunConfigurationFactory theRunConfigurationFactory; + static WorkspaceProjectRunWorkerFactory theRunWorkerFactory; } } // namespace ProjectExplorer