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. [QML / C++] Data type conversion handling in Qt6
QtWS25 Last Chance

[QML / C++] Data type conversion handling in Qt6

Scheduled Pinned Locked Moved Solved QML and Qt Quick
2 Posts 1 Posters 444 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.
  • N Offline
    N Offline
    nico88desmo
    wrote on last edited by nico88desmo
    #1

    Dear all,

    I've got some doubts on how QML engine handle data type conversion between QML and C++.

    Mainly, there are two cases:

    1. Value type data
      These kinds of data are barely copy between Qml and C++, so on Qml side there is just a value copied
    2. QML/Qt Objects these are passed from C++ to QML by reference (pointer?), so on QML side there exists just an address value
      This object is usable or not from QML, depends if it has been exposed to QML using any of QML_* keywords

    Now I'm going to introduce another case, i.e. a C++ bare pointer data

    Supposing the following:

    • having a tree structure, where its base node is class Node
    • tree structure is "installed" onto a Model, and then I filter this model using a AProxyModel where I put as root a node that is a subtree of the main data structure
    • create AProxyModel from QML document

    Here are main points of this logic:

    class Node {
    public:
        ...
        Data* parent
        Data* child
    };
    // Q_DECLARE_METATYPE(Node)    // <--- is needed ???
    // Q_DECLARE_METATYPE(Node*)   // <--- is needed ???
    
    
    class AProxyModel : public QAbstractProxyModel {
        Q_OBJECT
        QML_ELEMENT
    
    public:
        Q_PROPERTY(TreeNode::Ptr pRoot READ getRoot WRITE setRoot NOTIFY rootChanged)
        ...
        Data* m_root;
    }
    
    
    class QMLPageController : public QObject {
        Q_OBJECT
        QML_ELEMENT
    
    public:
        Q_PROPERTY(AProxyModel* proxyModel READ getProxyModel CONSTANT)
        Q_PROPERTY(Node* root READ getRoot CONSTANT)
    
    public:
        explicit QMLPageController(QObject* parent = nullptr) { ... }
        ~QMLPageController() { ... }
    
        AProxyModel* getProxyModel() const { return m_proxyModel; }
        Node* getRoot() const { return m_root; }
    
    private:
        AProxyModel* m_proxyModel;
        TreeNode* m_root;
    }
    

    And from QML side

    Window {
        QMLPageController { id: controller }
    
        ListView {
            model: AProxyModel {
               pRoot: controller.root
               sourceModel: controller.proxyModel
            }
        }
    }
    

    From my first tests, it seems working correctly, although I have some doubts about its correctness.
    My question is: how Node* is treated by QML Engine when it is send from C++ to Qml? I don't declare Node using neither Q_DECLARE_METATYPE(Node) nor Q_DECLARE_METATYPE(Node*); from C++ to QML I'm surely passing a pointer, that is passed by value (1) (I think).
    Is there an implicit conversion of Node* using a QVariant, as explained here?
    Might be Node type known from QVariant thanks to new Metatype system introduced with Qt6?

    Thanks,
    Nicola

    N 1 Reply Last reply
    0
    • N nico88desmo

      Dear all,

      I've got some doubts on how QML engine handle data type conversion between QML and C++.

      Mainly, there are two cases:

      1. Value type data
        These kinds of data are barely copy between Qml and C++, so on Qml side there is just a value copied
      2. QML/Qt Objects these are passed from C++ to QML by reference (pointer?), so on QML side there exists just an address value
        This object is usable or not from QML, depends if it has been exposed to QML using any of QML_* keywords

      Now I'm going to introduce another case, i.e. a C++ bare pointer data

      Supposing the following:

      • having a tree structure, where its base node is class Node
      • tree structure is "installed" onto a Model, and then I filter this model using a AProxyModel where I put as root a node that is a subtree of the main data structure
      • create AProxyModel from QML document

      Here are main points of this logic:

      class Node {
      public:
          ...
          Data* parent
          Data* child
      };
      // Q_DECLARE_METATYPE(Node)    // <--- is needed ???
      // Q_DECLARE_METATYPE(Node*)   // <--- is needed ???
      
      
      class AProxyModel : public QAbstractProxyModel {
          Q_OBJECT
          QML_ELEMENT
      
      public:
          Q_PROPERTY(TreeNode::Ptr pRoot READ getRoot WRITE setRoot NOTIFY rootChanged)
          ...
          Data* m_root;
      }
      
      
      class QMLPageController : public QObject {
          Q_OBJECT
          QML_ELEMENT
      
      public:
          Q_PROPERTY(AProxyModel* proxyModel READ getProxyModel CONSTANT)
          Q_PROPERTY(Node* root READ getRoot CONSTANT)
      
      public:
          explicit QMLPageController(QObject* parent = nullptr) { ... }
          ~QMLPageController() { ... }
      
          AProxyModel* getProxyModel() const { return m_proxyModel; }
          Node* getRoot() const { return m_root; }
      
      private:
          AProxyModel* m_proxyModel;
          TreeNode* m_root;
      }
      

      And from QML side

      Window {
          QMLPageController { id: controller }
      
          ListView {
              model: AProxyModel {
                 pRoot: controller.root
                 sourceModel: controller.proxyModel
              }
          }
      }
      

      From my first tests, it seems working correctly, although I have some doubts about its correctness.
      My question is: how Node* is treated by QML Engine when it is send from C++ to Qml? I don't declare Node using neither Q_DECLARE_METATYPE(Node) nor Q_DECLARE_METATYPE(Node*); from C++ to QML I'm surely passing a pointer, that is passed by value (1) (I think).
      Is there an implicit conversion of Node* using a QVariant, as explained here?
      Might be Node type known from QVariant thanks to new Metatype system introduced with Qt6?

      Thanks,
      Nicola

      N Offline
      N Offline
      nico88desmo
      wrote on last edited by
      #2

      Maybe I've found the answer in this video at 7:35 time, where Jesper Pedersen (KDAB) is talking about how C++ pass data type to QML, this sentence is the answer I was looking for:

      If Qt doesn't know about them (types), then you can still send them up there. But, all you can do on the QML side is give them back into C++, which might still be useful in different situations.

      Qt doesn't know about them = Custom type hasn't been declared using neither Q_OBJECT nor Q_GADGET

      However, any unknown Type object pass from C++ to QML must be declared using:

      • Q_DECLARE_METATYPE(Type)
      • Q_DECLARE_METATYPE(Type*)

      because QMLEngine will pass this object type as QVariant, and a custom type is manageable from QVariant class iff that type has been declared in that way (this is true, even if using Qt-6 and C++-17 feature, it seems this requirement has been relaxed).

      On QML side, unknown types are treated as var value types variables, and they hold just a variant copy of the C++ side object.

      If everything I wrote upwards is correct, there might be not a bad idea to add a paragraph on Qt documentation page Data Type Conversion Between QML and C++ about these notes, because or I haven't read with attention, or documentation page lacks these details

      1 Reply Last reply
      1
      • N nico88desmo has marked this topic as solved on

      • Login

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