victronenergy / gui-v2

Other
24 stars 9 forks source link

Allow custom QML to be inserted into gui-v2 #1071

Open blammit opened 4 months ago

blammit commented 4 months ago

Allow users to load custom QML content into gui-v2.

For example, for:

gui-v2 could load details from some json configuration. E.g. to customize the settings page, load some json file that defines the title and url to be loaded.

Initial work is to do some investigation and prototyping.

blammit commented 3 months ago

We need a solution that allows 3rd-party QML files to be accessible both 1) on device and 2) from wasm. 1) is easy because we can load files from the local filesystem, but 2) is more difficult as the wasm environment is sandboxed and you cannot access local files.

One possibility is for gui-v2 on device (or venus-platform) to read QML files and JSON configurations from a special directory on device and publish the details to some specific D-Bus/MQTT paths, to make them accessible to gui-v2 on both device and wasm.

When publishing the custom data, QML can be inserted as raw strings, and images as base64-encoded data. Alternatively the data could all be inserted as binary data and then extracted/decoded by gui-v2.

mr-manuel commented 3 months ago

Would be great if with a JSON settings file templates could be used (refer to https://community.victronenergy.com/questions/245056/venus-os-modifying-gui-v2.html?childToView=285975#comment-285975). Like:

    {
        "add": {
            "settings/display-and-language": [
                {
                    "title": "CustomSwitch",
                    "type": "switch",
                    "dbus-path": "com.victronenergy.settings/Custom/Path/Switch"
                },
                {
                    "title": "CustomInput",
                    "type": "textbox",
                    "dbus-path": "com.victronenergy.settings/Custom/Path/Text"
                },
                {
                    "title": "CustomSelect",
                    "type": "select",
                    "dbus-path": "com.victronenergy.settings/Custom/Path/Select",
                    "options": [
                        {
                            "value": "1",
                            "text": "Option 1"
                        },
                        {
                            "value": "2",
                            "text": "Option 2"
                        }
                    ]
                },
                {
                    "title": "CustomPage",
                    "type": "page",
                    "content": [
                        {
                            "title": "CustomSwitch",
                            "type": "switch",
                            "dbus-path": "com.victronenergy.settings/Custom/Path/Switch"
                        }
                    ]
                },
                {
                    "title": "CustomPage",
                    "type": "page",
                    "qml": "path-to-qml-file.qml"  // requires more maintenance of the plugin developer
                }
            ]
        },
        "remove": [
            "settings/relay/relay-1-on",
            "settings/some-other-item-or-page"
        ]
    }
jpetrell commented 3 months ago

I would limit JSON to a simple configuration file that points out where can the QML, translations and other assets be found.

Would be great if with a JSON settings file templates could be used

There has been such systems before, but overall feels silly to introduce a new settings UI declaration syntax in JSON when you can can assemble such a simple settings page with QML already, without the need to implement and support custom JSON schemas and formatters. I would consider declaring settings pages with JSON if we need to somehow limit what 3rd party "apps" are allowed to do.

JSON 
+ JSON is ubiquitous
+ Security, can more easily limit what such settings page is allowed to do
- More limited what kind of use cases can be accomplished
- Need to implement a new JSON schema/formatter/validator that supports all the needed elements and attributes
- No translation support
- Static declaration
QML
+ Actively used and tested internally
+ Optimized for writing GUI declarations
+ Access to the latest gui-v2 UI components
+ Supports translations out of the box
+ Not limited to simple forms, can do more custom use cases and layouts
- Not so much used outside embedded circles
- Supports advanced features that may confuse inexperienced developers

How you would write the above settings JSON currently in QML:

Page {
  GradientListView {
    model: ObjectListModel {
      ListSwitch {
        text: "CustomSwitch"
        dataItem.uid: "com.victronenergy.settings/Custom/Path/Switch"
      }
      ListTextField {
        text: "CustomInput"
        dataItem.uid: "com.victronenergy.settings/Custom/Path/Text"
      }
      ListRadioButtonGroup {
        text: "CustomInput"
        dataItem.uid: "com.victronenergy.settings/Custom/Path/Text"
        optionModel: [
          { display: "Option A", value: 1 },
          { display: "Option B", value: 2 }
        }
      }
      ListNavigationItem {
        text: "CustomPage"
        onClicked: Global.pageManager.pushPage("com.victronenergy.settings/Custom/Path/Switch")
      }
    }
  }
}

Which could be further simplified with few syntax improvements:

SettingsPage {
  ListSwitch {
    text: "CustomSwitch"
    uid: "com.victronenergy.settings/Custom/Path/Switch"
  }
  ...
}
mr-manuel commented 3 months ago

If you currently take a look at the scripts/packages that are available from the SetupHelper you will see that it is a lot of effort maintaining a project for different Venus OS versions, since for every different version a different QML is needed. This increases the maintenance for the package developer enormous. If we could use templates that are consistent indipendent of the version that would be very helping. If Victron changes something in the QML structure, it's automatically changed also in the template. This would mean the developers are not in a rush to update their packages (like Kevin does) because a new version was released any may cause a white screen for a lot of users.

Therefore it does not need to be a JSON file, but please provide the possibility to provide only settings without a QML structure for simple projects, where the QML is then generated from the settings file.

Edit: If a developer for a more complex project want to write a QML file and integrate it, he should be able to do it. But as far as I understood from @mpvader it should be as simple as possible for people to add packages without high maintaining effort.

mr-manuel commented 3 months ago
  • No translation support

This is not true, since you could also provide the different languages in the JSON and fallback to english, if a language is not provided.

kwindrem commented 3 months ago

I have a program (UpdatePackage) that scans a database Venus OS versions and indicates where file changes are needed. So not every file for every VenusOS version is needed. But yes it can be a lot of work to modify files for a new Venus OS version. I have a few ways around that, the most recent is the ability to patch files rather than replacing them with a version modified by the author. This reduces but does not eliminate the need for multiple versions of the same file.