[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