|
| 1 | +# Generated Settings Pages |
| 2 | + |
| 3 | +This page explains how the new Application Settings pages are generated and how to extend them. |
| 4 | + |
| 5 | +## Architecture Overview |
| 6 | + |
| 7 | +The runtime stack is: |
| 8 | + |
| 9 | +1. Fact metadata in `src/Settings/*.SettingsGroup.json` |
| 10 | +2. Settings Fact accessors in `src/Settings/*Settings.h/.cc` |
| 11 | +3. Settings UI page definitions in `src/UI/AppSettings/pages/*.SettingsUI.json` |
| 12 | +4. Page list in `src/UI/AppSettings/pages/SettingsPages.json` |
| 13 | +5. Python generator in `tools/generators/settings_qml` |
| 14 | +6. Generated QML loaded by `src/QmlControls/AppSettings.qml` |
| 15 | + |
| 16 | +At build time, CMake runs the generator and places generated QML in the build tree. Those files are then compiled into the `QGroundControl.AppSettings` QML module. |
| 17 | + |
| 18 | +## Where Generation Is Wired |
| 19 | + |
| 20 | +Generation is configured in [src/UI/AppSettings/CMakeLists.txt](../../../../src/UI/AppSettings/CMakeLists.txt): |
| 21 | + |
| 22 | +- Custom command runs: |
| 23 | + - `python -m tools.generators.settings_qml.generate_pages --output-dir <build>/generated` |
| 24 | +- Inputs: |
| 25 | + - `src/UI/AppSettings/pages/*.json` |
| 26 | + - `src/Settings/*.SettingsGroup.json` |
| 27 | +- Outputs: |
| 28 | + - Generated page QML files (for example `AppSettings.qml`, `FlyViewSettings.qml`, ...) |
| 29 | + - `SettingsPagesModel.qml` |
| 30 | + |
| 31 | +The generator entry point is [tools/generators/settings_qml/generate_pages.py](../../../../tools/generators/settings_qml/generate_pages.py), with most logic in [tools/generators/settings_qml/page_generator.py](../../../../tools/generators/settings_qml/page_generator.py). |
| 32 | + |
| 33 | +## JSON Files and Their Roles |
| 34 | + |
| 35 | +1. `SettingsPages.json` controls sidebar/page registration: |
| 36 | +- Page name |
| 37 | +- Icon |
| 38 | +- Generated QML file name (`qml`) |
| 39 | +- Source page definition JSON (`pageDefinition`) |
| 40 | +- Optional visibility expression (`visible`) |
| 41 | +- Optional divider entries |
| 42 | + |
| 43 | +2. `<Page>.SettingsUI.json` controls page content: |
| 44 | +- `bindings`: reusable QML expressions |
| 45 | +- `groups`: section blocks |
| 46 | +- Group options: |
| 47 | + - `heading` |
| 48 | + - `sectionName` (sidebar label override) |
| 49 | + - `showWhen`, `enableWhen` |
| 50 | + - `component` (embed a custom QML component) |
| 51 | + - `keywords` (for search on component-only groups) |
| 52 | +- Control options: |
| 53 | + - `setting` (required), format: `<settingsManager accessor>.<factName>` |
| 54 | + - Optional `control` override (`checkbox`, `combobox`, `textfield`, `slider`, `browse`, `scaler`) |
| 55 | + - Optional `label`, `showWhen`, `enableWhen`, `placeholder` |
| 56 | + - Slider-specific `enableCheckbox` and `button` |
| 57 | + |
| 58 | +3. `*.SettingsGroup.json` provides Fact metadata used by both runtime and generation: |
| 59 | +- Type |
| 60 | +- Label/descriptions |
| 61 | +- Enum values |
| 62 | +- Visibility/user visibility |
| 63 | +- Search `keywords` |
| 64 | + |
| 65 | +## How Controls Are Chosen |
| 66 | + |
| 67 | +When `control` is omitted, the generator auto-selects from Fact metadata: |
| 68 | + |
| 69 | +- `bool` -> checkbox control |
| 70 | +- Enum-backed facts -> combobox |
| 71 | +- Other types -> text field |
| 72 | + |
| 73 | +Explicit `control` in `*.SettingsUI.json` overrides auto-selection. |
| 74 | + |
| 75 | +## Sidebar, Sections, and Search |
| 76 | + |
| 77 | +Generated `SettingsPagesModel.qml` is built from `SettingsPages.json` and each page definition. |
| 78 | + |
| 79 | +It includes: |
| 80 | + |
| 81 | +- `sections`: section names for expandable sidebar rows |
| 82 | +- `searchTerms`: page/section/fact keyword tokens used by the search field in [src/QmlControls/AppSettings.qml](../../../../src/QmlControls/AppSettings.qml) |
| 83 | + |
| 84 | +Search terms are derived from: |
| 85 | + |
| 86 | +- Page name |
| 87 | +- Section heading/section name |
| 88 | +- Fact metadata `keywords` |
| 89 | +- Group-level `keywords` when using `component` groups without explicit controls |
| 90 | + |
| 91 | +## Add a New Setting to an Existing Generated Page |
| 92 | + |
| 93 | +1. Add Fact metadata entry to the appropriate `src/Settings/<Group>.SettingsGroup.json` file. |
| 94 | +2. Expose that Fact through the corresponding settings class: |
| 95 | +- Add `DEFINE_SETTINGFACT(<factName>)` in the matching `*Settings.h`. |
| 96 | +- Ensure `DECLARE_SETTINGSFACT` exists in `*Settings.cc` if required by that file pattern. |
| 97 | +3. Add a control entry in the page JSON: |
| 98 | +- File: `src/UI/AppSettings/pages/<Page>.SettingsUI.json` |
| 99 | +- Add control: `{ "setting": "<accessor>.<factName>" }` |
| 100 | +4. Build QGC. CMake regenerates the QML page automatically. |
| 101 | + |
| 102 | +## Add a New Generated Settings Page |
| 103 | + |
| 104 | +1. Create a new page definition JSON in `src/UI/AppSettings/pages`, for example `MyFeature.SettingsUI.json`. |
| 105 | +2. Add a new entry to `src/UI/AppSettings/pages/SettingsPages.json`: |
| 106 | +- `name` |
| 107 | +- `icon` |
| 108 | +- `qml` (output file name, for example `MyFeatureSettings.qml`) |
| 109 | +- `pageDefinition` (your new JSON file) |
| 110 | +- Optional `visible` expression |
| 111 | +3. Update generated outputs list in [src/UI/AppSettings/CMakeLists.txt](../../../../src/UI/AppSettings/CMakeLists.txt): |
| 112 | +- Add your new QML file name to `_generated_qml_names`. |
| 113 | +4. Build QGC to generate and include the new page. |
| 114 | + |
| 115 | +## Important Notes and Gotchas |
| 116 | + |
| 117 | +- If a page exists in `SettingsPages.json` but has no `pageDefinition`, it is not generated; it is treated as hand-written QML/URL content. |
| 118 | +- The CMake `_generated_qml_names` list is explicit. If you forget to add a new page output file name there, generation/build integration will be incomplete. |
| 119 | +- The `setting` path in `*.SettingsUI.json` must match a valid `QGroundControl.settingsManager.<group>.<fact>` accessor. |
| 120 | +- Fact labels should be present in metadata. Missing labels are logged at runtime by `SettingsGroup`. |
| 121 | + |
| 122 | +## Runtime Override Support |
| 123 | + |
| 124 | +`SettingsManager` can load external settings override files (from `settingsSavePath()` with the configured settings file extension), then apply metadata/value/visibility overrides in `SettingsManager::adjustSettingMetaData(...)`. |
| 125 | + |
| 126 | +This is separate from page generation, but it affects visibility/defaults in generated UI. |
0 commit comments