[Development] RFC: RAII for property changes
Alan Alpert
416365416c at gmail.com
Wed Apr 15 19:55:12 CEST 2015
On Wed, Apr 15, 2015 at 8:08 AM, Matthew Woehlke
<mw_triad at users.sourceforge.net> wrote:
> On 2015-04-15 10:43, Marc Mutz wrote:
>> On Wednesday 15 April 2015 11:49:56 André Somers wrote:
>>> void MyClass::setFoo(QString value)
>>> {
>>> PropertyGuard guard(this, "foo"); //foo is the name of the Q_PROPERTY
>>> Q_UNUSED(guard);
>>>
>>> m_foo = value;
>>> }
>>
>> This is an interesting idea, though I don't think I have encountered the
>> problems with which you motivate PropertyGuard.
I have, it comes up a lot in objects used as an interface to QML
(where every fooChanged signal will probably trigger binding
re-evaluation or JS blocks). I don't think it's that hard to manage,
but PropertyGuard does look easier and saves some boilerplate code.
>> For use in a library, though, I fear the string-based mechanism is too
>> inefficient. For use within QtWidgets, say, I'd suggest a mechanism that works
>> on the member data directly.
I think it's fine to tie it to the property system, since conceptually
it needs a both a read and a notify on the datum.
For performance, allow passing in a metaproperty index instead of a
property name string. It will still invoke the getter, but they're
rarely that complicated (and when they are, you need to go off the
getter value*).
> FWIW I had the same thought; also, I'm not a fan of needing the
> Q_UNUSED, or using a macro to 'hide' it.
>
> What about something like this?
>
> QPropertyGuard g{this};
> g.addProperty("a"); // use QObject::property
> g.addProperty("b", m_b); // take value member by reference
> g.addProperty(m_c, &cChanged); // ...and also slot address
>
> It's slightly redundant because declaring the guard and adding a
> property are separate, but there is no unused object, and you can use
> the same guard for multiple properties.
The common case is one property I think, so keep that case to one
line. I'd envision using it in all my basic setters to save code at
the start of a project, and then when the features start to creep in
it's easier to add complexity into the setters.
Still, you could always leave in a convenience constructor or just
wrap it in a macro as before.
* Example of when you need to go off getter value instead of member is
usually sometime like implicit width, where the getter looks like
getWidth() {
if (m_width == -1)
return m_implicitWidth;
return m_width;
}
In this case, if you have m_width = 80, m_implicitWidth = 80, and call
setWidth(-1), then you actually don't want to emit widthChanged even
though m_width is updated.
That was just an example, not how implicit width actually is
implemented in QtQuick.
--
Alan Alpert
More information about the Development
mailing list