[QML / C++] Data type conversion handling in Qt6
-
Dear all,
I've got some doubts on how QML engine handle data type conversion between QML and C++.
Mainly, there are two cases:
- Value type data
These kinds of data are barely copy between Qml and C++, so on Qml side there is just a value copied - 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: howNode*
is treated by QML Engine when it is send from C++ to Qml? I don't declareNode
using neitherQ_DECLARE_METATYPE(Node)
norQ_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 ofNode*
using aQVariant
, as explained here?
Might beNode
type known from QVariant thanks to new Metatype system introduced with Qt6?Thanks,
Nicola - Value type data
-
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
norQ_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
-