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. How to set a non-global context property for a single QQmlComponent?
Forum Updated to NodeBB v4.3 + New Features

How to set a non-global context property for a single QQmlComponent?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
9 Posts 3 Posters 1.3k Views 1 Watching
  • 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.
  • P Offline
    P Offline
    patrickkidd
    wrote on last edited by
    #1

    This was previously asked here, but didn't get any responses: Setting context property for individual QML UI element

    Surely there must be a way to set a context property on a single component without having to set it globally on the entire engine? Indeed, the documentation is silent on this point.

    Help??

    https://alaskafamilysystems.com/

    J.HilkJ 1 Reply Last reply
    0
    • P patrickkidd

      This was previously asked here, but didn't get any responses: Setting context property for individual QML UI element

      Surely there must be a way to set a context property on a single component without having to set it globally on the entire engine? Indeed, the documentation is silent on this point.

      Help??

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #2

      @patrickkidd I don't think this is possible.

      Assigning stuff to the root context is supposed to be global for all qml files.

      If you want a c++ class that is independent from other aktive instances of your c++ backend and only access it via qml, than you can do that via qmlRegisterType
      If you want it to access an instance from other c++ instances and only access it from specific QML files, than a Singelton is your only way via qmlRegisterSingletonType


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      P 1 Reply Last reply
      0
      • J.HilkJ J.Hilk

        @patrickkidd I don't think this is possible.

        Assigning stuff to the root context is supposed to be global for all qml files.

        If you want a c++ class that is independent from other aktive instances of your c++ backend and only access it via qml, than you can do that via qmlRegisterType
        If you want it to access an instance from other c++ instances and only access it from specific QML files, than a Singelton is your only way via qmlRegisterSingletonType

        P Offline
        P Offline
        patrickkidd
        wrote on last edited by
        #3

        @J.Hilk said in How to set a non-global context property for a single QQmlComponent?:

        @patrickkidd I don't think this is possible.

        Assigning stuff to the root context is supposed to be global for all qml files.

        If you want a c++ class that is independent from other aktive instances of your c++ backend and only access it via qml, than you can do that via qmlRegisterType
        If you want it to access an instance from other c++ instances and only access it from specific QML files, than a Singelton is your only way via qmlRegisterSingletonType

        I am wondering about exposing object instances, not types, to a single QQmlComponent.

        https://alaskafamilysystems.com/

        J.HilkJ 1 Reply Last reply
        0
        • P patrickkidd

          @J.Hilk said in How to set a non-global context property for a single QQmlComponent?:

          @patrickkidd I don't think this is possible.

          Assigning stuff to the root context is supposed to be global for all qml files.

          If you want a c++ class that is independent from other aktive instances of your c++ backend and only access it via qml, than you can do that via qmlRegisterType
          If you want it to access an instance from other c++ instances and only access it from specific QML files, than a Singelton is your only way via qmlRegisterSingletonType

          I am wondering about exposing object instances, not types, to a single QQmlComponent.

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by J.Hilk
          #4

          @patrickkidd than take a look at his section

          https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterSingletonType

          an example how to register and access the class - taken from my current project

          //main.cpp
          
          qmlRegisterSingletonType<BluetoothDevice>("BluetoothBackend", 1, 0, "Bluetooth", BluetoothDevice::instance);
          
          //in my qml file
          import BluetoothBackend 1.0
          
          ....
          ListView {
                      id:lView
                      anchors.fill: parent
          
                      model: Bluetooth.devices
                      ....
                      onClicked:{
                            Bluetooth.connectToDevice(modelData.deviceAddress)
                      }
          
          
          //the c++ callback, because the docu is not that great in that instance
          
          static QObject *instance(QQmlEngine *engine, QJSEngine *scriptEngine)
              {
                  Q_UNUSED(scriptEngine)
          
                  if(BluetoothBackend)
                      return BluetoothBackend;
          
                  BluetoothBackend = new BluetoothDevice();
                  engine->setObjectOwnership(BluetoothBackend,QQmlEngine::CppOwnership);
                  return BluetoothBackend;
              }
          

          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          P 1 Reply Last reply
          0
          • J.HilkJ J.Hilk

            @patrickkidd than take a look at his section

            https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterSingletonType

            an example how to register and access the class - taken from my current project

            //main.cpp
            
            qmlRegisterSingletonType<BluetoothDevice>("BluetoothBackend", 1, 0, "Bluetooth", BluetoothDevice::instance);
            
            //in my qml file
            import BluetoothBackend 1.0
            
            ....
            ListView {
                        id:lView
                        anchors.fill: parent
            
                        model: Bluetooth.devices
                        ....
                        onClicked:{
                              Bluetooth.connectToDevice(modelData.deviceAddress)
                        }
            
            
            //the c++ callback, because the docu is not that great in that instance
            
            static QObject *instance(QQmlEngine *engine, QJSEngine *scriptEngine)
                {
                    Q_UNUSED(scriptEngine)
            
                    if(BluetoothBackend)
                        return BluetoothBackend;
            
                    BluetoothBackend = new BluetoothDevice();
                    engine->setObjectOwnership(BluetoothBackend,QQmlEngine::CppOwnership);
                    return BluetoothBackend;
                }
            
            P Offline
            P Offline
            patrickkidd
            wrote on last edited by
            #5

            @J.Hilk said in How to set a non-global context property for a single QQmlComponent?:

            @patrickkidd than take a look at his section

            https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterSingletonType

            an example how to register and access the class - taken from my current project

            //main.cpp
            
            qmlRegisterSingletonType<BluetoothDevice>("BluetoothBackend", 1, 0, "Bluetooth", BluetoothDevice::instance);
            
            //in my qml file
            import BluetoothBackend 1.0
            
            ....
            ListView {
                        id:lView
                        anchors.fill: parent
            
                        model: Bluetooth.devices
                        ....
                        onClicked:{
                              Bluetooth.connectToDevice(modelData.deviceAddress)
                        }
            

            I'm sorry, that is still not what I am asking. I am specifically asking how to set a context property that only one component can see. For example, I would set one object as a "dateModel" context property on one component, and different object to the "dateModel" context property on another component.

            https://alaskafamilysystems.com/

            J.HilkJ B 2 Replies Last reply
            0
            • P patrickkidd

              @J.Hilk said in How to set a non-global context property for a single QQmlComponent?:

              @patrickkidd than take a look at his section

              https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterSingletonType

              an example how to register and access the class - taken from my current project

              //main.cpp
              
              qmlRegisterSingletonType<BluetoothDevice>("BluetoothBackend", 1, 0, "Bluetooth", BluetoothDevice::instance);
              
              //in my qml file
              import BluetoothBackend 1.0
              
              ....
              ListView {
                          id:lView
                          anchors.fill: parent
              
                          model: Bluetooth.devices
                          ....
                          onClicked:{
                                Bluetooth.connectToDevice(modelData.deviceAddress)
                          }
              

              I'm sorry, that is still not what I am asking. I am specifically asking how to set a context property that only one component can see. For example, I would set one object as a "dateModel" context property on one component, and different object to the "dateModel" context property on another component.

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #6

              @patrickkidd
              again not possible with contextProperty

              0_1563356026012_2ef737a4-95e3-4a5f-aecd-c3ab46e22ac9-image.png
              https://doc.qt.io/archives/qt-5.11/images/cpp-qml-integration-flowchart.pnghttps://doc.qt.io/archives/qt-5.11/images/cpp-qml-integration-flowchart.png


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              1 Reply Last reply
              0
              • P patrickkidd

                @J.Hilk said in How to set a non-global context property for a single QQmlComponent?:

                @patrickkidd than take a look at his section

                https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterSingletonType

                an example how to register and access the class - taken from my current project

                //main.cpp
                
                qmlRegisterSingletonType<BluetoothDevice>("BluetoothBackend", 1, 0, "Bluetooth", BluetoothDevice::instance);
                
                //in my qml file
                import BluetoothBackend 1.0
                
                ....
                ListView {
                            id:lView
                            anchors.fill: parent
                
                            model: Bluetooth.devices
                            ....
                            onClicked:{
                                  Bluetooth.connectToDevice(modelData.deviceAddress)
                            }
                

                I'm sorry, that is still not what I am asking. I am specifically asking how to set a context property that only one component can see. For example, I would set one object as a "dateModel" context property on one component, and different object to the "dateModel" context property on another component.

                B Offline
                B Offline
                Bob64
                wrote on last edited by Bob64
                #7

                @patrickkidd As already answered, there is no way to use the context property mechanism to do what you want. However, if you expose a C++ class to QML via qmlRegisterType, you can create an instance of that type in your QML component:

                class MyType: public QObject
                {
                    Q_OBJECT
                    // properties
                    Q_PROPERTY(bool isValid READ isValid WRITE setIsValid NOTIFY isValidChanged)
                    ...
                public: //methods
                    Q_INVOKABLE void doSomething(...);
                    ...
                
                // QML component
                Item {
                    MyType {
                         id: myType
                         isValid: false
                         ...
                    }
                
                    // reference properties and methods as required:
                   //    myType.isValid
                   //    myType.doSomething(...)
                

                The point is that you have the freedom to do what you want in your C++ object. You could expose a model as a property of it for example.

                Also, in this way you are in control of what is visible in your component. Note that this naturally instantiates an instance of your C++ object per QML component instance, but you have room for manoeuvre in the C++ backend. If, for example, you want what would effectively be a singleton to share between the QML components that reference it you could implement it as a Monostate-like class.

                P 1 Reply Last reply
                0
                • B Bob64

                  @patrickkidd As already answered, there is no way to use the context property mechanism to do what you want. However, if you expose a C++ class to QML via qmlRegisterType, you can create an instance of that type in your QML component:

                  class MyType: public QObject
                  {
                      Q_OBJECT
                      // properties
                      Q_PROPERTY(bool isValid READ isValid WRITE setIsValid NOTIFY isValidChanged)
                      ...
                  public: //methods
                      Q_INVOKABLE void doSomething(...);
                      ...
                  
                  // QML component
                  Item {
                      MyType {
                           id: myType
                           isValid: false
                           ...
                      }
                  
                      // reference properties and methods as required:
                     //    myType.isValid
                     //    myType.doSomething(...)
                  

                  The point is that you have the freedom to do what you want in your C++ object. You could expose a model as a property of it for example.

                  Also, in this way you are in control of what is visible in your component. Note that this naturally instantiates an instance of your C++ object per QML component instance, but you have room for manoeuvre in the C++ backend. If, for example, you want what would effectively be a singleton to share between the QML components that reference it you could implement it as a Monostate-like class.

                  P Offline
                  P Offline
                  patrickkidd
                  wrote on last edited by
                  #8

                  @Bob64 @J-Hilk

                  You arguments make sense, and it seems clear from the flow chart that setting up a context specific to the component is not possible. Further, it probably is better practice to just create a var property in the component and assign the QAbstractItemModel to it, if That model actually must be created in C++ (for example if it is handed to one or more other components).

                  Just for my own understanding, I did get a reply from the Qt-interest mailing list that you can create a sub-context like the following snippet, though this isn't possible with a QQuickWidget at current. Also, to my knowledge there is no way to show an item created with QQmlComponent::create in a widget....I could be wrong though. Doesn't this create a sub-scope as in the original question though?

                  QQmlContext *context = new QQmlContext(engine->rootContext());
                  QQmlComponent *comp = new QQmlComponent(mySource);
                  context->setContextProperty("myModel", myModel);
                  comp->create(context);
                  

                  https://alaskafamilysystems.com/

                  P 1 Reply Last reply
                  0
                  • P patrickkidd

                    @Bob64 @J-Hilk

                    You arguments make sense, and it seems clear from the flow chart that setting up a context specific to the component is not possible. Further, it probably is better practice to just create a var property in the component and assign the QAbstractItemModel to it, if That model actually must be created in C++ (for example if it is handed to one or more other components).

                    Just for my own understanding, I did get a reply from the Qt-interest mailing list that you can create a sub-context like the following snippet, though this isn't possible with a QQuickWidget at current. Also, to my knowledge there is no way to show an item created with QQmlComponent::create in a widget....I could be wrong though. Doesn't this create a sub-scope as in the original question though?

                    QQmlContext *context = new QQmlContext(engine->rootContext());
                    QQmlComponent *comp = new QQmlComponent(mySource);
                    context->setContextProperty("myModel", myModel);
                    comp->create(context);
                    
                    P Offline
                    P Offline
                    patrickkidd
                    wrote on last edited by
                    #9

                    I have been pursuing the route of setting a property on the root QQuickWidget component. Qml's property inheritance makes it so that all child components can see that property set on the root, so this works in theory.

                    One reason I was avoiding this was that there would be a delay between creating the root component and setting the property and all of the references to the property would fail, particularly if I initialize the root property to null. I imagine the workaround is to initialize the property value to a dummy object or uninitialized object of the same class, and then overwrite it with QQuickItem::setProperty after the Component is initialized from qml source.

                    Now, the problem I am running into with this solution is that the dummy objects are not destroyed when I overwrite them with QQuickItem::setProperty. I checked this by starting a C++ timer on them with a print statement. But this could be because I am using PyQt and a reference is still around somewhere (although the C++ object should have been deleted anyway...) or because QObject::startTimer keeps the object around. Or maybe I should just ignore these "leaked" objects anyway.

                    At any rate, this looks to me like an important design principle to nail down.

                    https://alaskafamilysystems.com/

                    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