Add QObjectBindableProperyt::notify
This mirrors the functionality of QObjectCompatProperty::notify, and can be useful to delay notifications until a class invariant has been restored. Change-Id: I1c16a0b1537a1b53d144c8abe48e546553edf877 Reviewed-by: Andreas Buhr <andreas.buhr@qt.io> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
6969496e00
commit
d558ebf79b
@ -1567,7 +1567,6 @@ QString QPropertyBindingError::description() const
|
|||||||
owner is notified via the Callback function.
|
owner is notified via the Callback function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn template <typename Class, typename T, auto offset, auto Callback> template <typename Functor> QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty(Functor &&f)
|
\fn template <typename Class, typename T, auto offset, auto Callback> template <typename Functor> QObjectBindableProperty<Class, T, offset, Callback>::QObjectBindableProperty(Functor &&f)
|
||||||
|
|
||||||
@ -1600,14 +1599,18 @@ QString QPropertyBindingError::description() const
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn template <typename Class, typename T, auto offset, auto Callback> void QObjectBindableProperty<Class, T, offset, Callback>::markDirty()
|
\fn template <typename Class, typename T, auto offset, auto Callback> void QObjectBindableProperty<Class, T, offset, Callback>::notify()
|
||||||
|
|
||||||
Programatically sets the property dirty. Any binding which depend on it will
|
Programmatically signals a change of the property. Any binding which depend on it will
|
||||||
be notified.
|
be notified, and if the property has a signal, it will be emitted.
|
||||||
This can be useful for properties which do not only depend on bindable properties,
|
|
||||||
but also on non-bindable properties or some other state.
|
|
||||||
|
|
||||||
\sa QProperty::markDirty()
|
This can be useful in combination with setValueBypassingBindings to defer signalling the change
|
||||||
|
until a class invariant has been restored.
|
||||||
|
|
||||||
|
\note If this property has a binding (i.e. hasBinding() returns true), that binding is not reevaluated when
|
||||||
|
notify() is called. Any binding depending on this property is still reevaluated as usual.
|
||||||
|
|
||||||
|
\sa Qt::beginProperytUpdateGroup(), setValueBypassingBindings()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -962,6 +962,11 @@ public:
|
|||||||
notify(bd);
|
notify(bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void notify() {
|
||||||
|
auto *bd = qGetBindingStorage(owner())->bindingData(this);
|
||||||
|
notify(bd);
|
||||||
|
}
|
||||||
|
|
||||||
void setValue(rvalue_ref t)
|
void setValue(rvalue_ref t)
|
||||||
{
|
{
|
||||||
auto *bd = qGetBindingStorage(owner())->bindingData(this);
|
auto *bd = qGetBindingStorage(owner())->bindingData(this);
|
||||||
|
@ -82,6 +82,7 @@ private slots:
|
|||||||
void bindingValueReplacement();
|
void bindingValueReplacement();
|
||||||
void quntypedBindableApi();
|
void quntypedBindableApi();
|
||||||
void readonlyConstQBindable();
|
void readonlyConstQBindable();
|
||||||
|
void qobjectBindableManualNotify();
|
||||||
|
|
||||||
void testNewStuff();
|
void testNewStuff();
|
||||||
void qobjectObservers();
|
void qobjectObservers();
|
||||||
@ -1137,6 +1138,50 @@ public:
|
|||||||
Q_OBJECT_COMPAT_PROPERTY(MyQObject, int, compatData, &MyQObject::setCompat)
|
Q_OBJECT_COMPAT_PROPERTY(MyQObject, int, compatData, &MyQObject::setCompat)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void tst_QProperty::qobjectBindableManualNotify()
|
||||||
|
{
|
||||||
|
// Given an object of type MyQObject,
|
||||||
|
MyQObject object;
|
||||||
|
// track its foo property's change count
|
||||||
|
auto bindable = object.bindableFoo();
|
||||||
|
int fooChangeCount = 0;
|
||||||
|
auto changeHandler = bindable.onValueChanged([&](){++fooChangeCount;});
|
||||||
|
// and how many changed signals it emits.
|
||||||
|
QSignalSpy fooChangedSpy(&object, &MyQObject::fooChanged);
|
||||||
|
|
||||||
|
// If we bypass the bindings system,
|
||||||
|
object.fooData.setValueBypassingBindings(42);
|
||||||
|
// there is no change.
|
||||||
|
QCOMPARE(fooChangeCount, 0);
|
||||||
|
QCOMPARE(fooChangedSpy.count(), 0);
|
||||||
|
// Once we notify manually
|
||||||
|
object.fooData.notify();
|
||||||
|
// observers are notified and the signal arrives.
|
||||||
|
QCOMPARE(fooChangeCount, 1);
|
||||||
|
QCOMPARE(fooChangedSpy.count(), 1);
|
||||||
|
|
||||||
|
// If we set a binding
|
||||||
|
int i = 1;
|
||||||
|
object.fooData.setBinding([&](){return i;});
|
||||||
|
// then the value changes
|
||||||
|
QCOMPARE(object.foo(), 1);
|
||||||
|
// and the change and signal count are incremented.
|
||||||
|
QCOMPARE(fooChangeCount, 2);
|
||||||
|
QCOMPARE(fooChangedSpy.count(), 2);
|
||||||
|
// Changing a non-property won't trigger any notification.
|
||||||
|
i = 2;
|
||||||
|
QCOMPARE(fooChangeCount, 2);
|
||||||
|
QCOMPARE(fooChangedSpy.count(), 2);
|
||||||
|
// Manually triggering the notification
|
||||||
|
object.fooData.notify();
|
||||||
|
// increments the change count
|
||||||
|
QCOMPARE(fooChangeCount, 3);
|
||||||
|
QCOMPARE(fooChangedSpy.count(), 3);
|
||||||
|
// but doesn't actually cause a binding reevaluation.
|
||||||
|
QCOMPARE(object.foo(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QProperty::testNewStuff()
|
void tst_QProperty::testNewStuff()
|
||||||
{
|
{
|
||||||
MyQObject testReadOnly;
|
MyQObject testReadOnly;
|
||||||
|
Loading…
Reference in New Issue
Block a user