summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-04-20 11:00:46 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2021-04-22 16:15:41 +0200
commitcdabe1d64c1ac3f99aa23be873daa45042f957cf (patch)
treee7eb1b8a1baf5cefc08e099b61e355e056ba49a6
parentd558ebf79b76e1a428a350d28950813a4db0755d (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.cpp4
-rw-r--r--src/corelib/kernel/qproperty.h17
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp25
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;