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. Is it safe to set QObject::setParent for qml object with JavaScriptOwnership?

Is it safe to set QObject::setParent for qml object with JavaScriptOwnership?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
2 Posts 2 Posters 295 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.
  • C Offline
    C Offline
    chocis
    wrote on 18 Jun 2023, 18:02 last edited by
    #1

    Hi, I have specific requirement that QML_ELEMENT class should be instaniated on c++ side and is used/returned to QML. In this example according to documentation returned object is owned by javascript (which is what I want).

        Q_INVOKABLE ButtonModel *getModel() {
            return new ButtonModel();
        }
    

    On QML side this Object is used together with some visual element (and so is made a property). Example:

        Component {
            id: _dynamicBtn
            Button {
                required property ButtonModel model
                text: "hello"
            }
        }
    

    My requirement is that ButtonModel is destroyed together with its visual element. Unfortunatelly, because of garbage collection ButtonModel is destroyed some time in future, which is not good.
    If I expose and set manually parent(owner), then everything seem to work as expected.

        // ButtonModel
        Q_INVOKABLE void setOwner(QObject *parent) {
            QObject::setParent(parent);
        }
    
        // qml   
        let mod = _btnMngr.getModel();
        let o = _dynamicBtn.createObject(_flow, {model: mod});
        mod.setOwner(o);
    

    I am just worried if this is ok, but can't find confirmation if this is safe. I am afraid that if parent later is changed in c++, then Qml Engine doesn't know about it. By testing seems to be fine.

    J 1 Reply Last reply 19 Jun 2023, 00:08
    0
    • C chocis
      18 Jun 2023, 18:02

      Hi, I have specific requirement that QML_ELEMENT class should be instaniated on c++ side and is used/returned to QML. In this example according to documentation returned object is owned by javascript (which is what I want).

          Q_INVOKABLE ButtonModel *getModel() {
              return new ButtonModel();
          }
      

      On QML side this Object is used together with some visual element (and so is made a property). Example:

          Component {
              id: _dynamicBtn
              Button {
                  required property ButtonModel model
                  text: "hello"
              }
          }
      

      My requirement is that ButtonModel is destroyed together with its visual element. Unfortunatelly, because of garbage collection ButtonModel is destroyed some time in future, which is not good.
      If I expose and set manually parent(owner), then everything seem to work as expected.

          // ButtonModel
          Q_INVOKABLE void setOwner(QObject *parent) {
              QObject::setParent(parent);
          }
      
          // qml   
          let mod = _btnMngr.getModel();
          let o = _dynamicBtn.createObject(_flow, {model: mod});
          mod.setOwner(o);
      

      I am just worried if this is ok, but can't find confirmation if this is safe. I am afraid that if parent later is changed in c++, then Qml Engine doesn't know about it. By testing seems to be fine.

      J Offline
      J Offline
      jeremy_k
      wrote on 19 Jun 2023, 00:08 last edited by
      #2

      @chocis said in Is it safe to set QObject::setParent for qml object with JavaScriptOwnership?:

      Hi, I have specific requirement that QML_ELEMENT class should be instaniated on c++ side and is used/returned to QML. In this example according to documentation returned object is owned by javascript (which is what I want).

          Q_INVOKABLE ButtonModel *getModel() {
      

      While this is a quick and easy solution, I generally find it to be more difficult to reason about. It's a pattern that seems to turn up frequently in projects where contributors are not comfortable with QML, which leads to other issues. My suggestion is to register the type to the QML engine, and instantiate it as any other QML component. If some initialization action needs to be delayed, use a property change to trigger that action.

      If I expose and set manually parent(owner), then everything seem to work as expected.

          // ButtonModel
          Q_INVOKABLE void setOwner(QObject *parent) {
              QObject::setParent(parent);
          }
      

      This "works" because the garbage collection engine won't touch it. The normal QObject destructor of the parent item will delete it and all other QObject children. The same thing will happen if ownership is left as CppOwnership.

      https://doc.qt.io/qt-6/qjsengine.html#ObjectOwnership-enum:

      The object is owned by JavaScript. When the object is returned to the JavaScript memory manager as the return value of a method call, the JavaScript memory manager will track it and delete it if there are no remaining JavaScript references to it and it has no QObject::parent().

      Asking a question about code? http://eel.is/iso-c++/testcase/

      1 Reply Last reply
      0
      • C chocis has marked this topic as solved on 9 Jul 2023, 08:31

      1/2

      18 Jun 2023, 18:02

      • Login

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