Hi, When writing QObject-derived classes with properties, I often found myself writing code like this:
void MyClass::setFoo(QString value) { if (m_foo != value) { m_foo = value; emit fooChanged(m_foo); } } Trivial enough, in the simple case. However, when more than one property is involved at the same time, or properties depend on each other, things can get way less simple and more error-phrone quickly, I found. If the order of signals matters (and I found it does some times!), it gets even more tricky to get things right. This is especially tricky because you really would like to emit the signal at the moment the class is in a consistent state. That is, if you have a method that sets both width and height of an object at the same time, you really don't want to emit the signal about the change of one property before the change of another property is also set. In this case, the change may be harmless (but potentially expensive, as perhaps two relayouts are triggered when only one was needed), but there are cases where you'd really expose the class in an inconsistent state if you emit too soon. Considder that at the moment you emit, you give other code the change to do whatever its wants again, including calling methods on your class, even the very same method they just called, or worse, delete it... Your class better be in a consistent state when they do such things. That's why I have been working with a RAII implementation to monitor property changes for a while now. The idea is that you instantiate a RAII class to monitor a property at the beginning of a method that _may_ change the property value, and then do all you want. Upon destruction of the RAII class, it checks if the property value changed and if it did, emit the associated signal. The code I now write looks like this: void MyClass::setFoo(QString value) { PropertyGuard guard(this, "foo"); //foo is the name of the Q_PROPERTY Q_UNUSED(guard); m_foo = value; } which then is further simplified by creating a small macro called guardProperty to this: void MyClass::setFoo(QString value) { guardProperty(foo); //foo is the name of the Q_PROPERTY m_foo = value; } Note that you can guard as many properties as you need: void MyClass::setFoo(QString value) { guardProperty(foo); //foo is the name of the Q_PROPERTY guardProperty(isValid); //the isValid property depends on m_foo as well m_foo = value; } The PropertyGuard class itself is quite simple in its basic form. It uses QMetaObject to read the current value and find the notify signal for the property. Upon desctruction, it compares the current value to the initial value stored at creation, and if the two don't match, the signal is emitted. The code deals with signals with zero or one arguments, assuming that in the latter case the one argument is the new property value. I found this little device to be very useful in practice. Not so much in trivial setters like the ones on top (but still useful there, as the intent is clearer and there is less typing), but very much so in non-trivial cases where more than one property may change at a time or other complex interactions take place. In cases where a method changing should trigger other property changes as well, while not exposing inconsistent states of the class I found the device to be extremely valuable, as I can be sure that the emits are done at a moment where the state of class is fully consistent. I find myself writing emit less and less. So, what are your opinions on using a mechanism like this? I have not found it in Qt itself, but perhaps others here are already using similar methods or perhaps very different methods to tackle the issues I described? Looking forward to your comments, André Somers _______________________________________________ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development