derM
derM

Reputation: 13711

Usage of QVariants in C++ and Properties in QML

When I write a new component for QML in C++, I use the macro:

Q_PROPERTY(type READ getter WRITE setter NOTIFY signal)

Here I might use different types, e.g. int or QVariant. I was wondering, if I have any benefit of not using QVariant here.

To quote the documentation:

Without QVariant, this would be a problem for QObject::property() and for database work, etc.

So - what happens if I read or write to a property on the QML side?
My guess is, that it calls:

QVariant QObject::property(const char *name) const
bool QObject::setProperty(const char *name, const QVariant &value)

which means, that my properties, neatly defined as int, dobule, QString, ... returned by my getter will be wrapped as QVariant to be transferred from C++ to QML - a process that would be unnecessary if I would have defined it as QVariant from the beginning.

If I have a Component in QML it is very likely that I have bindings from one property to multiple other properties, so reading happens quite often. So it would be a good idea to have the type in Q_PROPERTY QVariant, as otherwise I would wrap it tons of times.

On the C++-Side I might decide, whether it is read often. If so, I buffer the value in the original data type for access within C++ but create the QVariant when ever the value changes, so for QML it is unnecessary to create it multiple times. - Or is this happening automatically? Does a QML Object has all it's property values buffered as QVariant?

Upvotes: 1

Views: 3426

Answers (2)

derM
derM

Reputation: 13711

I performed some analysis and experiments on QML that lead me to this answer, which I deem very probable:

  1. Experiment: Add a property property var test to an object, and analyze its meta object in C++. What I found is:
    The QMetaObject::property() method always returns a QVariant as described in the signature of this method, but the type of the QVariant is always set to the type of the property. This means a property int someInt results in a QVariant::int while a property var someVar results in a QVariant::QVariant - which means at least here, we have to unpack the value twice. +1 for using the best fitting property type!

  2. Experiment: Add breakpoints to the source file of QVariant (QtCore/qvariant.h) at the line containing inline QVariant(QVariant &&other) Q_DECL_NOTHROW : d(other.d) and inline QVariant &operator=(QVariant &&other) Q_DECL_NOTHROW, which I found likely to be called when I change the value of a QVariant in QML.
    In QML I added a Button which incremented its x position upon click.
    As expected, when ever I clicked the Button, those two lines were called repeatedly. Unfortunately, I am missing the insight, which QVariants where changed, and whether one of them is indeed our property for the position. However I don't think that Qt will have tons of QVariants somewhere in the backend, so I deem it likely, that my assumption is true, and on the QML-side the properties are handled as QVariant.


Take home message: Though the properties in QML are handled as QVariant it is beneficial to declare the properties using a better fitting type, as otherwise the result is not a QVariant::int but maybe a QVariant::QVariant::int.


In my experiments I found no trace of QJSValues flying around which I would not have been surprised to find instead of QVariant::QVariant when having a property var ...

Upvotes: 0

Xplatforms
Xplatforms

Reputation: 2232

No, i think you don't. At least if you expose it to QML or use in any kind of subclasses from QAbstractListModel( all values there returned by data function and return type is QVariant)

I have just run my app throught debugger with breakpoints to see what happens with Q_PROPERTY variables. Just added simple code snipped in MouseArray onClicked function:

var p = ExContact.phone;
var e = ExContact.status;

phone is QString and status is qint8 Going throught breakpoints shows:

  1. p is undefined
  2. p becomes string
  3. p value is assigned
  4. e is undefined
  5. e becomes type number
  6. e value is assigned

Calls trace is complicated in view but I can see what the QVariant is used and QMetaType is used.

So it looks like any type exposed throught Q_PROPERTY becomes QVariant anyway..

Upvotes: 1

Related Questions