App commands and --ha-remove (iteration 2, step 6)

The platform accepts app commands (D43): flags that get a
QCoreApplication like the manifest commands and run prepare() and then
the new hook runCommand(). The app's --ha-remove clears the device's
retained topics, so HA deletes the device; uninstall.sh runs it after
stopping the app and before unregistering from SteamVR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 16:32:51 +02:00
co-authored by Claude Opus 5.5
parent 148ae663cf
commit 0bdcaddcd5
12 changed files with 219 additions and 47 deletions
+9 -7
View File
@@ -112,19 +112,21 @@ into Qt events.
- `src/app/DashboardApplication` is the **base class of every app** (in `vrdashboard_core`):
CLI, logging, SteamVR connection, backend selection, surfaces, controller navigation, and the
modes (overlay, `--desktop`, `--desktop-novr`, `--snapshot`, `--benchmark`, manifest
install).
install, app commands).
- **Inheritance for the app, components for the surfaces** (the user's decision, after
trying composition): the app derives from `DashboardApplication`. In its constructor it
configures (`addSurface`, optional `setAppKey`/`setDisplayName`) and passes its own
command-line options (`QCommandLineOption` list) to the base constructor. It overrides
the hooks `prepare(QString*)` (first; mode and app key known, no engine/surfaces/SteamVR
yet; returning false ends `exec()` with exit code 1), `loading()` (backends + shared
engine exist, QML not loaded) and `started()` (everything runs). In the hooks, protected
command-line options and its commands (two `QCommandLineOption` lists, D38, D43) to the
base constructor. It overrides the hooks `prepare(QString*)` (first; mode and app key
known, no engine/surfaces/SteamVR yet; returning false ends `exec()` with exit code 1),
`loading()` (backends + shared engine exist, QML not loaded), `started()` (everything
runs) and `runCommand(name)` (mode `Command`, after `prepare()`, nothing else exists). In the hooks, protected
accessors give the running state: `mode()`, `appKey()`, `appName()`, `isOptionSet()`,
`optionValue()`, `engine()`, `surfaces()`, `surface()` (primary), `surface(id)`,
`vrRuntime()`, `navigation()`. The app is `src/Dashboard.h/.cpp`.
- The base constructor creates the `QGuiApplication` (`QCoreApplication` for manifest
commands), so derived members can be QObjects with timers.
- The base constructor creates the `QGuiApplication` (`QCoreApplication` for manifest and
app commands: decided from the raw `argv` before parsing), so derived members can be
QObjects with timers.
- All QML and surfaces are torn down **at the end of `exec()`**, while the derived object
and its members (e.g. QML singletons) still exist.
- `src/app/Surface` is **one view**: its QML root (from the app's module), renderer, render