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>
This commit is contained in:
parent
d558ebf79b
commit
cdabe1d64c
@ -1344,6 +1344,10 @@ QString QPropertyBindingError::description() const
|
|||||||
|
|
||||||
\snippet code/src_corelib_kernel_qproperty.cpp 2
|
\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
|
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
|
"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
|
of the Q_OBJECT_BINDABLE_PROPERTY and Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS
|
||||||
|
@ -884,6 +884,7 @@ class QObjectBindableProperty : public QPropertyData<T>
|
|||||||
{
|
{
|
||||||
using ThisType = QObjectBindableProperty<Class, T, Offset, Signal>;
|
using ThisType = QObjectBindableProperty<Class, T, Offset, Signal>;
|
||||||
static bool constexpr HasSignal = !std::is_same_v<decltype(Signal), std::nullptr_t>;
|
static bool constexpr HasSignal = !std::is_same_v<decltype(Signal), std::nullptr_t>;
|
||||||
|
using SignalTakesValue = std::is_invocable<decltype(Signal), Class, T>;
|
||||||
Class *owner()
|
Class *owner()
|
||||||
{
|
{
|
||||||
char *that = reinterpret_cast<char *>(this);
|
char *that = reinterpret_cast<char *>(this);
|
||||||
@ -897,8 +898,12 @@ class QObjectBindableProperty : public QPropertyData<T>
|
|||||||
static void signalCallBack(QUntypedPropertyData *o)
|
static void signalCallBack(QUntypedPropertyData *o)
|
||||||
{
|
{
|
||||||
QObjectBindableProperty *that = static_cast<QObjectBindableProperty *>(o);
|
QObjectBindableProperty *that = static_cast<QObjectBindableProperty *>(o);
|
||||||
if constexpr (HasSignal)
|
if constexpr (HasSignal) {
|
||||||
(that->owner()->*Signal)();
|
if constexpr (SignalTakesValue::value)
|
||||||
|
(that->owner()->*Signal)(that->valueBypassingBindings());
|
||||||
|
else
|
||||||
|
(that->owner()->*Signal)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
using value_type = typename QPropertyData<T>::value_type;
|
using value_type = typename QPropertyData<T>::value_type;
|
||||||
@ -1060,8 +1065,12 @@ private:
|
|||||||
{
|
{
|
||||||
if (binding)
|
if (binding)
|
||||||
binding->notifyObservers(this);
|
binding->notifyObservers(this);
|
||||||
if constexpr (HasSignal)
|
if constexpr (HasSignal) {
|
||||||
(owner()->*Signal)();
|
if constexpr (SignalTakesValue::value)
|
||||||
|
(owner()->*Signal)(this->valueBypassingBindings());
|
||||||
|
else
|
||||||
|
(owner()->*Signal)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ private slots:
|
|||||||
void quntypedBindableApi();
|
void quntypedBindableApi();
|
||||||
void readonlyConstQBindable();
|
void readonlyConstQBindable();
|
||||||
void qobjectBindableManualNotify();
|
void qobjectBindableManualNotify();
|
||||||
|
void qobjectBindableSignalTakingNewValue();
|
||||||
|
|
||||||
void testNewStuff();
|
void testNewStuff();
|
||||||
void qobjectObservers();
|
void qobjectObservers();
|
||||||
@ -1088,7 +1089,7 @@ class MyQObject : public QObject
|
|||||||
Q_PROPERTY(int compat READ compat WRITE setCompat NOTIFY compatChanged)
|
Q_PROPERTY(int compat READ compat WRITE setCompat NOTIFY compatChanged)
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void fooChanged();
|
void fooChanged(int newFoo);
|
||||||
void barChanged();
|
void barChanged();
|
||||||
void compatChanged();
|
void compatChanged();
|
||||||
|
|
||||||
@ -1182,6 +1183,28 @@ void tst_QProperty::qobjectBindableManualNotify()
|
|||||||
QCOMPARE(object.foo(), 1);
|
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()
|
void tst_QProperty::testNewStuff()
|
||||||
{
|
{
|
||||||
MyQObject testReadOnly;
|
MyQObject testReadOnly;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user