forked from qt-creator/qt-creator
cmake: Add support for custom startup programs for executable targets
CMake supports the use of custom startup programs that are provided in the IDE to simplify execution. If the build system provides launchers, these are provided as an additional selection field of the run configuration including an entry without launcher. As of cmake version 3.29, the start programs are extracted from the API of the cmake file. For older cmake versions, a launcher is initialized from the cmake variable CMAKE_CROSSCOMPILING_EMULATOR, if available. Fixes: QTCREATORBUG-29880 Change-Id: I4345b56c9ca5befb5876a361e7da4675590399ca Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
@@ -1977,6 +1977,9 @@ static FilePaths librarySearchPaths(const CMakeBuildSystem *bs, const QString &b
|
|||||||
|
|
||||||
const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
||||||
{
|
{
|
||||||
|
const CMakeConfig &cm = configurationFromCMake();
|
||||||
|
QString emulator = cm.stringValueOf("CMAKE_CROSSCOMPILING_EMULATOR");
|
||||||
|
|
||||||
QList<BuildTargetInfo> appTargetList;
|
QList<BuildTargetInfo> appTargetList;
|
||||||
const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(kit())
|
const bool forAndroid = DeviceTypeKitAspect::deviceTypeId(kit())
|
||||||
== Android::Constants::ANDROID_DEVICE_TYPE;
|
== Android::Constants::ANDROID_DEVICE_TYPE;
|
||||||
@@ -1989,6 +1992,15 @@ const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
|
|||||||
|
|
||||||
BuildTargetInfo bti;
|
BuildTargetInfo bti;
|
||||||
bti.displayName = ct.title;
|
bti.displayName = ct.title;
|
||||||
|
if (ct.launchers.size() > 0)
|
||||||
|
bti.launchers = ct.launchers;
|
||||||
|
else if (!emulator.isEmpty()) {
|
||||||
|
// fallback for cmake < 3.29
|
||||||
|
QStringList args = emulator.split(";");
|
||||||
|
FilePath command = FilePath::fromString(args.takeFirst());
|
||||||
|
LauncherInfo launcherInfo = { "emulator", command, args };
|
||||||
|
bti.launchers.append(Launcher(launcherInfo, ct.sourceDirectory));
|
||||||
|
}
|
||||||
bti.targetFilePath = ct.executable;
|
bti.targetFilePath = ct.executable;
|
||||||
bti.projectFilePath = ct.sourceDirectory.cleanPath();
|
bti.projectFilePath = ct.sourceDirectory.cleanPath();
|
||||||
bti.workingDirectory = ct.workingDirectory;
|
bti.workingDirectory = ct.workingDirectory;
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <projectexplorer/projectmacro.h>
|
#include <projectexplorer/projectmacro.h>
|
||||||
#include <projectexplorer/projectnodes.h>
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <projectexplorer/runconfigurationaspects.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ class CMAKE_EXPORT CMakeBuildTarget
|
|||||||
public:
|
public:
|
||||||
QString title;
|
QString title;
|
||||||
Utils::FilePath executable; // TODO: rename to output?
|
Utils::FilePath executable; // TODO: rename to output?
|
||||||
|
QList<ProjectExplorer::Launcher> launchers;
|
||||||
TargetType targetType = UtilityType;
|
TargetType targetType = UtilityType;
|
||||||
bool linksToQtGui = false;
|
bool linksToQtGui = false;
|
||||||
bool qtcRunnable = true;
|
bool qtcRunnable = true;
|
||||||
|
@@ -342,6 +342,22 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
|||||||
}
|
}
|
||||||
ct.libraryDirectories = filteredUnique(librarySeachPaths);
|
ct.libraryDirectories = filteredUnique(librarySeachPaths);
|
||||||
qCInfo(cmakeLogger) << "libraryDirectories for target" << ct.title << ":" << ct.libraryDirectories;
|
qCInfo(cmakeLogger) << "libraryDirectories for target" << ct.title << ":" << ct.libraryDirectories;
|
||||||
|
|
||||||
|
// If there are start programs, there should also be an option to select none
|
||||||
|
if (!t.launcherInfos.isEmpty()) {
|
||||||
|
LauncherInfo info { "unused", Utils::FilePath(), QStringList() };
|
||||||
|
ct.launchers.append(Launcher(info, sourceDirectory));
|
||||||
|
}
|
||||||
|
// if there is a test and an emulator launcher, add the emulator and
|
||||||
|
// also a combination as the last entry, but not the "test" launcher
|
||||||
|
// as it will not work for cross-compiled executables
|
||||||
|
if (t.launcherInfos.size() == 2 && t.launcherInfos[0].type == "test" && t.launcherInfos[1].type == "emulator") {
|
||||||
|
ct.launchers.append(Launcher(t.launcherInfos[1], sourceDirectory));
|
||||||
|
ct.launchers.append(Launcher(t.launcherInfos[0], t.launcherInfos[1], sourceDirectory));
|
||||||
|
} else if (t.launcherInfos.size() == 1) {
|
||||||
|
Launcher launcher(t.launcherInfos[0], sourceDirectory);
|
||||||
|
ct.launchers.append(launcher);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ct;
|
return ct;
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <projectexplorer/rawprojectpart.h>
|
#include <projectexplorer/rawprojectpart.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/filepath.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
@@ -650,6 +651,19 @@ static TargetDetails extractTargetDetails(const QJsonObject &root, QString &erro
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const QJsonArray launchers = root.value("launchers").toArray();
|
||||||
|
if (launchers.size() > 0) {
|
||||||
|
t.launcherInfos = transform<QList>(launchers, [](const QJsonValue &v) {
|
||||||
|
const QJsonObject o = v.toObject();
|
||||||
|
QList<QString> arguments;
|
||||||
|
for (const QJsonValue &arg : o.value("arguments").toArray())
|
||||||
|
arguments.append(arg.toString());
|
||||||
|
FilePath command = FilePath::fromString(o.value("command").toString());
|
||||||
|
return ProjectExplorer::LauncherInfo { o.value("type").toString(), command, arguments };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@@ -197,6 +197,7 @@ public:
|
|||||||
QList<Utils::FilePath> artifacts;
|
QList<Utils::FilePath> artifacts;
|
||||||
QString installPrefix;
|
QString installPrefix;
|
||||||
std::vector<InstallDestination> installDestination;
|
std::vector<InstallDestination> installDestination;
|
||||||
|
QList<ProjectExplorer::LauncherInfo> launcherInfos;
|
||||||
std::optional<LinkInfo> link;
|
std::optional<LinkInfo> link;
|
||||||
std::optional<ArchiveInfo> archive;
|
std::optional<ArchiveInfo> archive;
|
||||||
std::vector<DependencyInfo> dependencies;
|
std::vector<DependencyInfo> dependencies;
|
||||||
|
@@ -5,12 +5,15 @@
|
|||||||
|
|
||||||
#include "projectexplorer_export.h"
|
#include "projectexplorer_export.h"
|
||||||
|
|
||||||
|
#include "runconfiguration.h"
|
||||||
|
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
class Launcher;
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT BuildTargetInfo
|
class PROJECTEXPLORER_EXPORT BuildTargetInfo
|
||||||
{
|
{
|
||||||
@@ -19,6 +22,7 @@ public:
|
|||||||
QString displayName;
|
QString displayName;
|
||||||
QString displayNameUniquifier;
|
QString displayNameUniquifier;
|
||||||
|
|
||||||
|
QList<Launcher> launchers;
|
||||||
Utils::FilePath targetFilePath;
|
Utils::FilePath targetFilePath;
|
||||||
Utils::FilePath projectFilePath;
|
Utils::FilePath projectFilePath;
|
||||||
Utils::FilePath workingDirectory;
|
Utils::FilePath workingDirectory;
|
||||||
|
@@ -70,6 +70,7 @@ private:
|
|||||||
FilePath executableToRun(const BuildTargetInfo &targetInfo) const;
|
FilePath executableToRun(const BuildTargetInfo &targetInfo) const;
|
||||||
|
|
||||||
const Kind m_kind;
|
const Kind m_kind;
|
||||||
|
LauncherAspect launcher{this};
|
||||||
EnvironmentAspect environment{this};
|
EnvironmentAspect environment{this};
|
||||||
ExecutableAspect executable{this};
|
ExecutableAspect executable{this};
|
||||||
ArgumentsAspect arguments{this};
|
ArgumentsAspect arguments{this};
|
||||||
@@ -90,6 +91,8 @@ void DesktopRunConfiguration::updateTargetInformation()
|
|||||||
auto terminalAspect = aspect<TerminalAspect>();
|
auto terminalAspect = aspect<TerminalAspect>();
|
||||||
terminalAspect->setUseTerminalHint(bti.targetFilePath.needsDevice() ? false : bti.usesTerminal);
|
terminalAspect->setUseTerminalHint(bti.targetFilePath.needsDevice() ? false : bti.usesTerminal);
|
||||||
terminalAspect->setEnabled(!bti.targetFilePath.needsDevice());
|
terminalAspect->setEnabled(!bti.targetFilePath.needsDevice());
|
||||||
|
auto launcherAspect = aspect<LauncherAspect>();
|
||||||
|
launcherAspect->setVisible(false);
|
||||||
|
|
||||||
if (m_kind == Qmake) {
|
if (m_kind == Qmake) {
|
||||||
|
|
||||||
@@ -121,6 +124,12 @@ void DesktopRunConfiguration::updateTargetInformation()
|
|||||||
|
|
||||||
} else if (m_kind == CMake) {
|
} else if (m_kind == CMake) {
|
||||||
|
|
||||||
|
if (bti.launchers.size() > 0) {
|
||||||
|
launcherAspect->setVisible(true);
|
||||||
|
// Use start program by default, if defined (see toBuildTarget() for details)
|
||||||
|
launcherAspect->setDefaultLauncher(bti.launchers.last());
|
||||||
|
launcherAspect->updateLaunchers(bti.launchers);
|
||||||
|
}
|
||||||
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
|
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
|
||||||
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
|
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
|
||||||
emit aspect<EnvironmentAspect>()->environmentChanged();
|
emit aspect<EnvironmentAspect>()->environmentChanged();
|
||||||
|
@@ -173,6 +173,9 @@ RunConfiguration::RunConfiguration(Target *target, Utils::Id id)
|
|||||||
|
|
||||||
|
|
||||||
m_commandLineGetter = [this] {
|
m_commandLineGetter = [this] {
|
||||||
|
Launcher launcher;
|
||||||
|
if (const auto launcherAspect = aspect<LauncherAspect>())
|
||||||
|
launcher = launcherAspect->currentLauncher();
|
||||||
FilePath executable;
|
FilePath executable;
|
||||||
if (const auto executableAspect = aspect<ExecutableAspect>())
|
if (const auto executableAspect = aspect<ExecutableAspect>())
|
||||||
executable = executableAspect->executable();
|
executable = executableAspect->executable();
|
||||||
@@ -180,7 +183,14 @@ RunConfiguration::RunConfiguration(Target *target, Utils::Id id)
|
|||||||
if (const auto argumentsAspect = aspect<ArgumentsAspect>())
|
if (const auto argumentsAspect = aspect<ArgumentsAspect>())
|
||||||
arguments = argumentsAspect->arguments();
|
arguments = argumentsAspect->arguments();
|
||||||
|
|
||||||
|
if (launcher.command.isEmpty())
|
||||||
return CommandLine{executable, arguments, CommandLine::Raw};
|
return CommandLine{executable, arguments, CommandLine::Raw};
|
||||||
|
|
||||||
|
CommandLine launcherCommand(launcher.command, launcher.arguments);
|
||||||
|
launcherCommand.addArg(executable.toString());
|
||||||
|
launcherCommand.addArgs(arguments, CommandLine::Raw);
|
||||||
|
|
||||||
|
return launcherCommand;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,6 +28,51 @@ class RunConfigurationFactory;
|
|||||||
class RunConfiguration;
|
class RunConfiguration;
|
||||||
class RunConfigurationCreationInfo;
|
class RunConfigurationCreationInfo;
|
||||||
class Target;
|
class Target;
|
||||||
|
class BuildTargetInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains start program entries that are retrieved
|
||||||
|
* from the cmake file api
|
||||||
|
*/
|
||||||
|
class LauncherInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString type;
|
||||||
|
Utils::FilePath command;
|
||||||
|
QStringList arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a start program entry that is displayed in the run configuration interface.
|
||||||
|
*
|
||||||
|
* This follows the design for the use of "Test Launcher", the
|
||||||
|
* Wrappers for running executables on the host system and "Emulator",
|
||||||
|
* wrappers for cross-compiled applications, which are supported for
|
||||||
|
* example by the cmake build system.
|
||||||
|
*/
|
||||||
|
class PROJECTEXPLORER_EXPORT Launcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Launcher() = default;
|
||||||
|
|
||||||
|
/// Create a single launcher from the \p launcherInfo parameter, which can be of type "Test launcher" or "Emulator"
|
||||||
|
Launcher(const LauncherInfo &launcherInfo, const Utils::FilePath &sourceDirectory);
|
||||||
|
|
||||||
|
/// Create a combined launcher from the passed info parameters, with \p testLauncherInfo
|
||||||
|
/// as first and \p emulatorLauncherInfo appended
|
||||||
|
Launcher(const LauncherInfo &testLauncherInfo, const LauncherInfo &emulatorlauncherInfo, const Utils::FilePath &sourceDirectory);
|
||||||
|
|
||||||
|
bool operator==(const Launcher &other) const
|
||||||
|
{
|
||||||
|
return id == other.id && displayName == other.displayName && command == other.command
|
||||||
|
&& arguments == other.arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString id;
|
||||||
|
QString displayName;
|
||||||
|
Utils::FilePath command;
|
||||||
|
QStringList arguments;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface to facilitate switching between hunks of
|
* An interface to facilitate switching between hunks of
|
||||||
|
@@ -797,6 +797,156 @@ Interpreter::Interpreter(const QString &_id,
|
|||||||
, autoDetected(_autoDetected)
|
, autoDetected(_autoDetected)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
static QString launcherType2UiString(const QString &type)
|
||||||
|
{
|
||||||
|
if (type == "test")
|
||||||
|
return Tr::tr("Test");
|
||||||
|
else if (type == "emulator")
|
||||||
|
return Tr::tr("Emulator");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Launcher::Launcher(const LauncherInfo &launcherInfo, const FilePath &sourceDirectory)
|
||||||
|
: id(launcherInfo.type)
|
||||||
|
, arguments(launcherInfo.arguments)
|
||||||
|
{
|
||||||
|
if (launcherInfo.type != "unused") {
|
||||||
|
command = launcherInfo.command;
|
||||||
|
if (command.isRelativePath())
|
||||||
|
command = sourceDirectory.resolvePath(command);
|
||||||
|
displayName = QString("%1 (%2)").arg(launcherType2UiString(launcherInfo.type),
|
||||||
|
CommandLine(command, arguments).displayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Launcher::Launcher(const LauncherInfo &testLauncherInfo, const LauncherInfo &emulatorLauncherInfo, const Utils::FilePath &sourceDirectory)
|
||||||
|
: id(testLauncherInfo.type + " + " + emulatorLauncherInfo.type)
|
||||||
|
, command(testLauncherInfo.command)
|
||||||
|
, arguments(testLauncherInfo.arguments)
|
||||||
|
{
|
||||||
|
if (command.isRelativePath())
|
||||||
|
command = sourceDirectory.resolvePath(command);
|
||||||
|
FilePath command1 = emulatorLauncherInfo.command;
|
||||||
|
if (command1.isRelativePath())
|
||||||
|
command1 = sourceDirectory.resolvePath(command1);
|
||||||
|
arguments.append(command1.toString());
|
||||||
|
arguments.append(emulatorLauncherInfo.arguments);
|
||||||
|
displayName = QString("%1 + %2 (%3)").arg(launcherType2UiString(testLauncherInfo.type),
|
||||||
|
launcherType2UiString(emulatorLauncherInfo.type),
|
||||||
|
CommandLine(command, arguments).displayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class ProjectExplorer::LauncherAspect
|
||||||
|
\inmodule QtCreator
|
||||||
|
|
||||||
|
\brief With the LauncherAspect class, a user can specify a launcher program for
|
||||||
|
use with executable files for which a launcher program is optionally available.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LauncherAspect::LauncherAspect(AspectContainer *container)
|
||||||
|
: BaseAspect(container)
|
||||||
|
{
|
||||||
|
addDataExtractor(this, &LauncherAspect::currentLauncher, &Data::launcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
Launcher LauncherAspect::currentLauncher() const
|
||||||
|
{
|
||||||
|
return Utils::findOrDefault(m_launchers, Utils::equal(&Launcher::id, m_currentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::updateLaunchers(const QList<Launcher> &launchers)
|
||||||
|
{
|
||||||
|
if (m_launchers == launchers)
|
||||||
|
return;
|
||||||
|
m_launchers = launchers;
|
||||||
|
if (m_comboBox)
|
||||||
|
updateComboBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::setDefaultLauncher(const Launcher &launcher)
|
||||||
|
{
|
||||||
|
if (m_defaultId == launcher.id)
|
||||||
|
return;
|
||||||
|
m_defaultId = launcher.id;
|
||||||
|
if (m_currentId.isEmpty())
|
||||||
|
setCurrentLauncher(launcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::setCurrentLauncher(const Launcher &launcher)
|
||||||
|
{
|
||||||
|
if (m_comboBox) {
|
||||||
|
const int index = m_launchers.indexOf(launcher);
|
||||||
|
if (index < 0 || index >= m_comboBox->count())
|
||||||
|
return;
|
||||||
|
m_comboBox->setCurrentIndex(index);
|
||||||
|
} else {
|
||||||
|
setCurrentLauncherId(launcher.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::fromMap(const Store &map)
|
||||||
|
{
|
||||||
|
setCurrentLauncherId(map.value(settingsKey(), m_defaultId).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::toMap(Store &map) const
|
||||||
|
{
|
||||||
|
if (m_currentId != m_defaultId)
|
||||||
|
saveToMap(map, m_currentId, QString(), settingsKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::addToLayout(Layout &builder)
|
||||||
|
{
|
||||||
|
if (QTC_GUARD(m_comboBox.isNull()))
|
||||||
|
m_comboBox = new QComboBox;
|
||||||
|
|
||||||
|
updateComboBox();
|
||||||
|
connect(m_comboBox, &QComboBox::currentIndexChanged,
|
||||||
|
this, &LauncherAspect::updateCurrentLauncher);
|
||||||
|
|
||||||
|
builder.addItems({Tr::tr("Launcher:"), m_comboBox.data()});
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::setCurrentLauncherId(const QString &id)
|
||||||
|
{
|
||||||
|
if (id == m_currentId)
|
||||||
|
return;
|
||||||
|
m_currentId = id;
|
||||||
|
emit changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::updateCurrentLauncher()
|
||||||
|
{
|
||||||
|
const int index = m_comboBox->currentIndex();
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
QTC_ASSERT(index < m_launchers.size(), return);
|
||||||
|
m_comboBox->setToolTip(m_launchers[index].command.toUserOutput());
|
||||||
|
setCurrentLauncherId(m_launchers[index].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LauncherAspect::updateComboBox()
|
||||||
|
{
|
||||||
|
int currentIndex = -1;
|
||||||
|
int defaultIndex = -1;
|
||||||
|
m_comboBox->clear();
|
||||||
|
for (const Launcher &launcher : std::as_const(m_launchers)) {
|
||||||
|
int index = m_comboBox->count();
|
||||||
|
m_comboBox->addItem(launcher.displayName);
|
||||||
|
m_comboBox->setItemData(index, launcher.command.toUserOutput(), Qt::ToolTipRole);
|
||||||
|
if (launcher.id == m_currentId)
|
||||||
|
currentIndex = index;
|
||||||
|
if (launcher.id == m_defaultId)
|
||||||
|
defaultIndex = index;
|
||||||
|
}
|
||||||
|
if (currentIndex >= 0)
|
||||||
|
m_comboBox->setCurrentIndex(currentIndex);
|
||||||
|
else if (defaultIndex >= 0)
|
||||||
|
m_comboBox->setCurrentIndex(defaultIndex);
|
||||||
|
updateCurrentLauncher();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class ProjectExplorer::X11ForwardingAspect
|
\class ProjectExplorer::X11ForwardingAspect
|
||||||
\inmodule QtCreator
|
\inmodule QtCreator
|
||||||
|
@@ -227,6 +227,36 @@ public:
|
|||||||
QString detectionSource;
|
QString detectionSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PROJECTEXPLORER_EXPORT LauncherAspect : public Utils::BaseAspect
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
LauncherAspect(Utils::AspectContainer *container = nullptr);
|
||||||
|
|
||||||
|
Launcher currentLauncher() const;
|
||||||
|
void updateLaunchers(const QList<Launcher> &launchers);
|
||||||
|
void setDefaultLauncher(const Launcher &launcher);
|
||||||
|
void setCurrentLauncher(const Launcher &launcher);
|
||||||
|
void setSettingsDialogId(Utils::Id id) { m_settingsDialogId = id; }
|
||||||
|
|
||||||
|
void fromMap(const Utils::Store &) override;
|
||||||
|
void toMap(Utils::Store &) const override;
|
||||||
|
void addToLayout(Layouting::Layout &parent) override;
|
||||||
|
|
||||||
|
struct Data : Utils::BaseAspect::Data { Launcher launcher; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setCurrentLauncherId(const QString &id);
|
||||||
|
void updateCurrentLauncher();
|
||||||
|
void updateComboBox();
|
||||||
|
QList<Launcher> m_launchers;
|
||||||
|
QPointer<QComboBox> m_comboBox;
|
||||||
|
QString m_defaultId;
|
||||||
|
QString m_currentId;
|
||||||
|
Utils::Id m_settingsDialogId;
|
||||||
|
};
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT MainScriptAspect : public Utils::FilePathAspect
|
class PROJECTEXPLORER_EXPORT MainScriptAspect : public Utils::FilePathAspect
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Reference in New Issue
Block a user