Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Managing Settings
QtWS25 Last Chance

Managing Settings

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
settings
7 Posts 3 Posters 1.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    Larvae
    wrote on last edited by
    #1

    Hi,

    I'm wondering how to manage settings in my application.

    For QML there only sems to be Qt.labs.settings 1.0 which is based on QSettings. Using it I get persistent properties, but as far as i can tell I can't e.g. a list of all settings. It's also not (yet) possible to change how data is stored (like custom formats in QSettings).

    If I use a custom class I won't be able to use bindings (unless i make custom classes with all properties every time...), at least I don't know how to. I would have to do updates manually every time, but I could use a QMap (or QSettings) to access all settings. That would make it much easier to create a settings editor since settings will be spread across files.

    Right now I would probably go with either QSettings or a custom class to manage them in c++.

    Does someone have any advice or another strategy for this?

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      Use Settings and expose the same to QML using setContextProperty.

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      1 Reply Last reply
      0
      • L Offline
        L Offline
        Larvae
        wrote on last edited by
        #3

        Hi,

        thanks for your answer, but I'm not sure what you want me to do.

        I know how to expose a c++ class to qml, but how do I do this with Settings? Pull a reference and then push it to root?

        Could you maybe give me more information or a short example?

        1 Reply Last reply
        0
        • KillerSmathK Offline
          KillerSmathK Offline
          KillerSmath
          wrote on last edited by
          #4

          Hi @Larvae.
          I found an old topic where we have talked about how to expose a QSettings derived class and become it usable inside of qml context.
          https://forum.qt.io/topic/91783/access-qml-elements-from-c-classes/4

          @Computer Science Student - Brazil
          Web Developer and Researcher
          “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

          1 Reply Last reply
          0
          • dheerendraD Offline
            dheerendraD Offline
            dheerendra
            Qt Champions 2022
            wrote on last edited by
            #5

            @Larvae QSettings is QObject and you will be able to expose the same to QML as indicated by previous post. Issue is that Settings does not have any slots or functions which can be accessed from QML. So it is better your own class & expose the same to QML. Access all the property from your custom class using Q_PROPERTY

            Dheerendra
            @Community Service
            Certified Qt Specialist
            http://www.pthinks.com

            1 Reply Last reply
            0
            • L Offline
              L Offline
              Larvae
              wrote on last edited by
              #6

              Thanks.

              I will look into a custom approach and read the thread you posted.

              Any further advice from your experience I should take into account?

              1 Reply Last reply
              0
              • L Offline
                L Offline
                Larvae
                wrote on last edited by
                #7

                So, after some looking around and experimenting, this is what I got.


                The singleton is used to collect all settings. This is where a c++ backend will be used to actually store the settings an disk, probably using QSettings. Through this it will (probably) be possible to config the settings (format, path, file name, stuff like that).

                MySingleton.qml

                pragma Singleton
                import QtQuick 2.0
                
                Item {
                
                // holding all settings as key-value pairs
                    property var dataMap : ({})
                
                // list to filter out all the inherited base properties
                    property var filterObject : { "x":"", "y":"", "z":"", "width":"", "height":"",....... }
                
                }
                
                

                This element is the base for the settings elements. It's purpose is to sync to the singleton, writing the settings to the dataMap and, if they already exist, read on startup (the reading is missing atm). For this it will perform reading and writing on construction and destruction and (later) provide signals and slots for this.
                MySettings .qml

                import QtQuick 2.11
                import QtQml 2.11
                
                Item{
                    id:base
                
                    Component.onCompleted: {
                        console.log("Settings Created")
                        for(var prop in this){
                            if(!MySingleton.filterObject.hasOwnProperty(prop) && typeof this[prop] !=="function" )
                            {
                                MySingleton.dataMap[prop] = this[prop];
                
                                var component = Qt.createComponent("BidirecionalBinding.qml");
                                if (component.status === Component.Ready) {
                                    var binding = component.createObject(this,
                                                                         {"first": this, "second": MySingleton.dataMap,
                                                                             "firstProperty": prop, "secondProperty": prop} );
                                    console.log()
                                }
                            }
                        }
                    }
                
                
                    Component.onDestruction: {
                        console.log("Destructing Settings")
                        for(var prop in this){
                            if(!MySingleton.filterObject.hasOwnProperty(prop) && typeof this[prop] !=="function" )
                                console.log(prop + "(" + typeof this[prop] +"): " + this[prop])
                        }
                        console.log(JSON.stringify(MySingleton.dataMap))
                    }
                
                }
                

                The BidirectionBinding uses two Binding elements to make one bidirectional binding. I tested it using two buttons and bound the labels, worked without problem. It's intention is to keep the map and the settings elements properties in sync.

                BidirectionBinding.qml

                import QtQuick 2.11
                import QtQuick.Controls 2.4
                import QtQml 2.11
                
                Item {
                    id:bidirectionalBinding
                
                    property alias first: firstBinding.target
                    property alias second: secondBinding.target
                
                    property alias firstProperty: firstBinding.property
                    property alias secondProperty: secondBinding.property
                
                    property bool delayed: true
                
                    property alias firstWhen: firstBinding.when
                    property alias secondWhen: secondBinding.when
                
                    property alias firstValue: firstBinding.value
                    property alias secondValue: secondBinding.value
                
                    Binding { id: firstBinding; when: true; delayed: bidirectionalBinding.delayed; value: second[secondProperty] }
                    Binding { id: secondBinding; when: true; delayed: bidirectionalBinding.delayed; value: first[firstProperty] }
                
                }
                

                The last file it the main file. This is for testing and demonstation. Its just four buttons for printing and changing the values.

                main.qml

                import QtQuick 2.11
                import QtQuick.Window 2.11
                
                Window {
                    id: window
                    title: "Hello Settings"
                    visible: true
                    width: 280
                    height: 250
                
                    property MySettings settings: MySettings{
                        id: settings
                        property alias windowTitle: window.title
                        property alias rectWidth: rect.width
                    }
                
                    Rectangle {
                        id: rect
                        width: 80;height: 50;x: 50;y: 50;color: 'green'
                        Text {  text: "Set Title"
                            anchors.horizontalCenter: parent.horizontalCenter
                            anchors.verticalCenter: parent.verticalCenter }
                        MouseArea {
                            anchors.fill: parent
                            onClicked: window.title = "Hello New Title"
                        }
                    }
                    Rectangle {
                        width: 80;height: 50;x: 150;y: 50;color: 'green'
                        Text { text: "Set Alias"
                            anchors.horizontalCenter: parent.horizontalCenter
                            anchors.verticalCenter: parent.verticalCenter }
                        MouseArea {
                            anchors.fill: parent
                            onClicked: settings.windowTitle = "Hello New Alias"
                        }
                    }
                    Rectangle {
                        width: 80;height: 50;x: 50;y: 150;color: 'green'
                        Text {  text: "Set Map"
                            anchors.horizontalCenter: parent.horizontalCenter
                            anchors.verticalCenter: parent.verticalCenter }
                        MouseArea {
                            anchors.fill: parent
                            onClicked: MySingleton.dataMap["windowTitle"] = "Hello New Setting"
                        }
                    }
                    Rectangle {
                        width: 80;height: 50;x: 150;y: 150;color: 'green'
                        Text {  text: "Print"
                            anchors.horizontalCenter: parent.horizontalCenter
                            anchors.verticalCenter: parent.verticalCenter }
                        MouseArea {
                            anchors.fill: parent
                            onClicked: {
                                console.log(settings.windowTitle)
                                console.log(JSON.stringify(MySingleton.dataMap))
                                console.log()
                            }
                        }
                    }
                
                }
                

                Thats it so far. The advantage of this approach is, that it can be used like the Settings element from Qt. Also, it can easily be added to existing code later, the original code won't have to be changed (most likely).

                The problem right know, aside from missing things like the backend, are the bidirectional bindings. I get the error

                qrc:/BidirecionalBinding.qml:21: TypeError: Cannot read property 'rectWidth' of null
                qrc:/BidirecionalBinding.qml:21: TypeError: Cannot read property 'windowTitle' of null

                (line 21 is where the first Binding is declared)

                What do you think about this so far?

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved