diff options
| author | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-04-20 11:00:46 +0200 |
|---|---|---|
| committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-04-22 16:15:41 +0200 |
| commit | cdabe1d64c1ac3f99aa23be873daa45042f957cf (patch) | |
| tree | e7eb1b8a1baf5cefc08e099b61e355e056ba49a6 | |
| parent | d558ebf79b76e1a428a350d28950813a4db0755d (diff) | |
QObjectBindableProperty: Allow signals taking a value
If the signal takes a value, we pass the current value of the property
to it.
As we now use eager evaluation, accessing the current value is now
possible.
Change-Id: I5e6947a6575bfa8ca5143f56620c645d4750a686
Reviewed-by: Andreas Buhr <andreas.buhr@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
| -rw-r--r-- | src/corelib/kernel/qproperty.cpp | 4 | ||||
| -rw-r--r-- | src/corelib/kernel/qproperty.h | 17 | ||||
| -rw-r--r-- | tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp | 25 |
3 files changed, 41 insertions, 5 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 6fe32e842ad..8f95b5fd5e3 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -1344,6 +1344,10 @@ QString QPropertyBindingError::description() const \snippet code/src_corelib_kernel_qproperty.cpp 2 + The change handler can optionally accept one argument, of the same type as the property, + in which case it is passed the new value of the property. Otherwise, it should take no + arguments. + If the property does not need a changed notification, you can leave out the "NOTIFY xChanged" in the Q_PROPERTY macro as well as the last argument of the Q_OBJECT_BINDABLE_PROPERTY and Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 6cf8c6a34e0..108f041d4fc 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -884,6 +884,7 @@ class QObjectBindableProperty : public QPropertyData<T> { using ThisType = QObjectBindableProperty<Class, T, Offset, Signal>; static bool constexpr HasSignal = !std::is_same_v<decltype(Signal), std::nullptr_t>; + using SignalTakesValue = std::is_invocable<decltype(Signal), Class, T>; Class *owner() { char *that = reinterpret_cast<char *>(this); @@ -897,8 +898,12 @@ class QObjectBindableProperty : public QPropertyData<T> static void signalCallBack(QUntypedPropertyData *o) { QObjectBindableProperty *that = static_cast<QObjectBindableProperty *>(o); - if constexpr (HasSignal) - (that->owner()->*Signal)(); + if constexpr (HasSignal) { + if constexpr (SignalTakesValue::value) + (that->owner()->*Signal)(that->valueBypassingBindings()); + else + (that->owner()->*Signal)(); + } } public: using value_type = typename QPropertyData<T>::value_type; @@ -1060,8 +1065,12 @@ private: { if (binding) binding->notifyObservers(this); - if constexpr (HasSignal) - (owner()->*Signal)(); + if constexpr (HasSignal) { + if constexpr (SignalTakesValue::value) + (owner()->*Signal)(this->valueBypassingBindings()); + else + (owner()->*Signal)(); + } } }; diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 5197be3912e..6d28fd6747d 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -83,6 +83,7 @@ private slots: void quntypedBindableApi(); void readonlyConstQBindable(); void qobjectBindableManualNotify(); + void qobjectBindableSignalTakingNewValue(); void testNewStuff(); void qobjectObservers(); @@ -1088,7 +1089,7 @@ class MyQObject : public QObject Q_PROPERTY(int compat READ compat WRITE setCompat NOTIFY compatChanged) signals: - void fooChanged(); + void fooChanged(int newFoo); void barChanged(); void compatChanged(); @@ -1182,6 +1183,28 @@ void tst_QProperty::qobjectBindableManualNotify() QCOMPARE(object.foo(), 1); } +void tst_QProperty::qobjectBindableSignalTakingNewValue() +{ + // Given an object of type MyQObject, + MyQObject object; + // and tracking the values emitted via its fooChanged signal, + int newValue = -1; + QObject::connect(&object, &MyQObject::fooChanged, [&](int i){ newValue = i; } ); + + // when we change the property's value via the bindable interface + object.bindableFoo().setValue(1); + // we obtain the newly set value. + QCOMPARE(newValue, 1); + + // The same holds true when we set a binding + QProperty<int> i {2}; + object.bindableFoo().setBinding(Qt::makePropertyBinding(i)); + QCOMPARE(newValue, 2); + // and when the binding gets reevaluated to a new value + i = 3; + QCOMPARE(newValue, 3); +} + void tst_QProperty::testNewStuff() { MyQObject testReadOnly; |
