Platform: prepare() hook and app-specific command-line options

prepare() runs once mode and app key are known, before engine, surfaces
and SteamVR; returning false ends exec() with exit code 1 (D21). The base
constructor takes the app's own QCommandLineOptions, parses them with its
own and exposes them via isOptionSet()/optionValue() (D38).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 22:06:09 +02:00
co-authored by Claude Opus 5.5
parent 6bdf0c2690
commit 4f47874a4b
4 changed files with 85 additions and 9 deletions
+21 -2
View File
@@ -128,6 +128,8 @@ struct DashboardApplication::Options {
int maxFps = 60;
QString appKey; // --app-key, empty: not given
QString appName; // --app-name, empty: not given
// Kept for the app's own options (isOptionSet() / optionValue()).
QCommandLineParser parser;
};
const char* dashboardModeName(DashboardMode mode) {
@@ -165,7 +167,8 @@ void DashboardApplication::setDefaultQmlModule(const char* uri) {
defaultQmlModule() = QString::fromUtf8(uri);
}
DashboardApplication::DashboardApplication(int& argc, char** argv)
DashboardApplication::DashboardApplication(
int& argc, char** argv, const QList<QCommandLineOption>& appOptions)
: m_options(std::make_unique<Options>()), m_qmlModule(defaultQmlModule()) {
// When launched by SteamVR, stderr is not a TTY and Qt would log to
// journald only; keep messages on stderr so they show up wherever the
@@ -189,7 +192,7 @@ DashboardApplication::DashboardApplication(int& argc, char** argv)
QCoreApplication::setApplicationVersion(
QString::fromLatin1(AppConfig::kVersion));
QCommandLineParser parser;
QCommandLineParser& parser = o.parser;
parser.setApplicationDescription(QStringLiteral("SteamVR dashboard overlay"));
parser.addHelpOption();
parser.addVersionOption();
@@ -247,6 +250,11 @@ DashboardApplication::DashboardApplication(int& argc, char** argv)
parser.addOptions({desktopOption, snapshotOption, benchmarkOption, apiOption,
keyOption, nameOption, fpsOption, installOption,
uninstallOption, manifestOption, launchOption, logOption});
for (const QCommandLineOption& option : appOptions) {
if (!parser.addOption(option))
o.error = QStringLiteral("App option --%1 clashes with another option")
.arg(option.names().constFirst());
}
parser.process(*m_app); // exits for --help / --version
if (parser.isSet(logOption)) {
@@ -319,6 +327,8 @@ void DashboardApplication::setQuickStyle(const QString& style) {
m_quickStyle = style;
}
bool DashboardApplication::prepare(QString*) { return true; }
void DashboardApplication::loading() {}
void DashboardApplication::started() {}
@@ -329,6 +339,14 @@ QList<Surface*> DashboardApplication::surfaces() const {
return result;
}
bool DashboardApplication::isOptionSet(const QString& name) const {
return m_options->parser.isSet(name);
}
QString DashboardApplication::optionValue(const QString& name) const {
return m_options->parser.value(name);
}
Surface* DashboardApplication::surface() const {
return m_surfaces.empty() ? nullptr : m_surfaces.front().get();
}
@@ -383,6 +401,7 @@ int DashboardApplication::exec() {
? m_configDisplayName
: QString::fromUtf8(AppConfig::kDisplayName);
QCoreApplication::setApplicationName(m_appName);
if (!prepare(&error)) return fail(error);
if (!m_quickStyle.isEmpty()) QQuickStyle::setStyle(m_quickStyle);
m_engine = std::make_unique<QQmlEngine>();
+14 -1
View File
@@ -1,5 +1,6 @@
#pragma once
#include <QCommandLineOption>
#include <QImage>
#include <QList>
#include <QObject>
@@ -53,7 +54,11 @@ class DashboardApplication : public QObject {
Q_OBJECT
public:
// Creates the Qt application object and parses the command line.
DashboardApplication(int& argc, char** argv);
// `appOptions` are the app's own command-line options: parsed and listed
// in --help together with the built-in ones (names must not clash); read
// them with isOptionSet() / optionValue().
DashboardApplication(int& argc, char** argv,
const QList<QCommandLineOption>& appOptions = {});
~DashboardApplication() override;
// Runs the mode selected on the command line; returns the exit code.
@@ -81,6 +86,11 @@ class DashboardApplication : public QObject {
void setQuickStyle(const QString& style);
// --- Lifecycle hooks ---
// First hook, once mode and app key are known: before the QML engine, the
// surfaces and the SteamVR connection exist (not called for manifest
// commands). Return false and set *error to abort: exec() then logs the
// error and returns 1.
virtual bool prepare(QString* error);
// Before the QML scenes are created: the shared engine, the surfaces and
// (except in desktop preview) their render backends exist.
virtual void loading();
@@ -91,6 +101,9 @@ class DashboardApplication : public QObject {
DashboardMode mode() const { return m_mode; }
QString appKey() const { return m_appKey; }
QString appName() const { return m_appName; }
// The app's own command-line options (see the constructor), by name.
bool isOptionSet(const QString& name) const;
QString optionValue(const QString& name) const;
// Shared by all surfaces.
QQmlEngine* engine() const { return m_engine.get(); }
// All views, in addSurface() order; the primary (first) one; one by id.