[Development] QProperty and library coding guide
Ulf Hermann
ulf.hermann at qt.io
Fri Jul 17 14:37:19 CEST 2020
>> item->width.setBinding([]() { return otherItem->height(); });
> ...
>> item->widthSetBinding([]() { return otherItem->height(); });
> ...
>> See the definition of Q_PRIVATE_QPROPERTY for the different methods we
> generate into the structs.
>
> It sounds like there are two overlapping elements to these changes.
> First is the ability to compress getters/setters/onChanged in to a
> single name, and second, an extension to allow "lazy" binding? Is this
> correct? I understand the struct would allow both, I'm asking about the
> intent, not the implementation. I.e., how this is expected to be used.
If you start your exploration from Q_PRIVATE_QPROPERTY with NOTIFY it's
all backwards and you're going to have a hard time understanding what
it's all about. I recommend starting from plain QProperty.
QProperty's main feature is accepting lazily evaluated bindings in place
of a plain value. It can also notify eagerly if you use the subscribe()
and onValueChanged() methods, but you'd usually avoid that as best as
you can.
A QProperty can be exposed to the metaobject system using a simplified
Q_PROPERTY macro:
class Xyz : public QObject
{
Q_OBJECT
Q_PROPERTY(int someInt)
public:
QProperty<int> someInt;
};
This looks much nicer than all the other stuff we've been discussing,
doesn't it? This is what I envision for most user code.
However, we don't want to follow this pattern in our public API, because
QProperty has a size and we want to be able to extend our public classes
without increasing the size. Therefore, Q_PRIVATE_QPROPERTY was
invented. Q_PRIVATE_QPROPERTY creates an almost size-less wrapper around
a QProperty living in the private object. The idea is that the wrapper
provides the same interface as QProperty, and therefore it's a somewhat
unpleasant looking struct with a number of methods but no data members.
That aspect could be changed.
On top of this, a plain QProperty doesn't know the object it belongs to.
Therefore, it cannot send signals on behalf of that object from it's
subscribe callback. In order to enable backwards compatibility with
properties that do send signals, QNotifiedProperty was invented.
QNotifiedProperty takes the pointer to the owning object as argument for
every method that might require sending a signal. It then invokes a
callback on that object as notification. That is really not the nicest
thing to use, but luckily we only need it for those old properties that
still require change signals. Once we can get rid of all the change
signals, we won't need QNotifiedProperty anymore.
As most of the getter/setter/signal properties in public API do indeed
have signals, we then get to wrap QNotifiedProperty into
Q_PRIVATE_QPROPERTY, and you can ask the protagonists of the interest
mailing list drama for the best words to describe that. Yet, again, this
is only for compatibility reasons, and we should strive to eventually
get rid of those warts, or at least not produce new ones in new code.
best,
Ulf
More information about the Development
mailing list