Bindable property with initialization
Implement Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS and Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS macros. They allow to directly initialize the property member. Task-number: QTBUG-85520 Change-Id: I76541d6785bbbf27976b9f0b865fb45be1e9beee Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
f8de5e5402
commit
f0668433c4
@ -68,3 +68,42 @@ private:
|
||||
Q_OBJECT_BINDABLE_PROPERTY(MyClass, int, xProp, &MyClass::xChanged)
|
||||
};
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
class MyClass : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged BINDABLE bindableX)
|
||||
public:
|
||||
int x() const { return xProp; }
|
||||
void setX(int x) { xProp = x; }
|
||||
QBindable<int> bindableX() { return QBindable<int>(&xProp); }
|
||||
|
||||
signals:
|
||||
void xChanged();
|
||||
|
||||
private:
|
||||
// Declare the instance of int bindable property data and
|
||||
// initialize it with the value 5.
|
||||
// This is similar to declaring
|
||||
// int xProp = 5;
|
||||
// without using the new QObjectBindableProperty class.
|
||||
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(MyClass, int, xProp, 5, &MyClass::xChanged)
|
||||
};
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
class CustomType
|
||||
{
|
||||
public:
|
||||
CustomType(int val, int otherVal) : value(val), anotherValue(otherVal) { }
|
||||
|
||||
private:
|
||||
int value = 0;
|
||||
int anotherValue = 0;
|
||||
};
|
||||
|
||||
// later when using CustomType as a property
|
||||
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(MyClass, CustomType xProp, CustomType(5, 10),
|
||||
&MyClass::xChanged)
|
||||
//! [2]
|
||||
|
@ -947,8 +947,22 @@ QString QPropertyBindingError::description() const
|
||||
|
||||
\snippet code/src_corelib_kernel_qproperty.cpp 0
|
||||
|
||||
If the property does not need a changed notification, you can leave out the "NOFITY xChanged" in the Q_PROPERTY macro as well as the last argument
|
||||
of the Q_OBJECT_BINDABLE_PROPERTY macro.
|
||||
If you need to directly initialize the property with some non-default value,
|
||||
you can use the Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS macro. It accepts a
|
||||
value for the initialization as one of its parameters.
|
||||
|
||||
\snippet code/src_corelib_kernel_qproperty.cpp 1
|
||||
|
||||
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS does not support multiple arguments
|
||||
directly. If your property requires multiple arguments for initialization,
|
||||
please explicitly call the specific constructor.
|
||||
|
||||
\snippet code/src_corelib_kernel_qproperty.cpp 2
|
||||
|
||||
If the property does not need a changed notification, you can leave out the
|
||||
"NOFITY 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
|
||||
macros.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -1031,6 +1031,29 @@ private:
|
||||
|
||||
#define Q_OBJECT_BINDABLE_PROPERTY(...) QT_OVERLOADED_MACRO(Q_OBJECT_BINDABLE_PROPERTY, __VA_ARGS__)
|
||||
|
||||
#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS4(Class, Type, name, value) \
|
||||
static constexpr size_t _qt_property_##name##_offset() \
|
||||
{ \
|
||||
QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF return offsetof(Class, name); \
|
||||
QT_WARNING_POP \
|
||||
} \
|
||||
QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr> name = \
|
||||
QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, nullptr>( \
|
||||
value);
|
||||
|
||||
#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS5(Class, Type, name, value, Signal) \
|
||||
static constexpr size_t _qt_property_##name##_offset() \
|
||||
{ \
|
||||
QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF return offsetof(Class, name); \
|
||||
QT_WARNING_POP \
|
||||
} \
|
||||
QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal> name = \
|
||||
QObjectBindableProperty<Class, Type, Class::_qt_property_##name##_offset, Signal>( \
|
||||
value);
|
||||
|
||||
#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(...) \
|
||||
QT_OVERLOADED_MACRO(Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS, __VA_ARGS__)
|
||||
|
||||
template<typename Class, typename T, auto Offset, auto Getter>
|
||||
class QObjectComputedProperty : public QUntypedPropertyData
|
||||
{
|
||||
|
@ -545,6 +545,15 @@ private:
|
||||
} \
|
||||
QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name;
|
||||
|
||||
#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(Class, Type, name, setter, value) \
|
||||
static constexpr size_t _qt_property_##name##_offset() \
|
||||
{ \
|
||||
QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF return offsetof(Class, name); \
|
||||
QT_WARNING_POP \
|
||||
} \
|
||||
QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name = \
|
||||
QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter>( \
|
||||
value);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -89,6 +89,8 @@ private slots:
|
||||
void compatPropertyNoDobuleNotification();
|
||||
|
||||
void noFakeDependencies();
|
||||
|
||||
void bindablePropertyWithInitialization();
|
||||
};
|
||||
|
||||
void tst_QProperty::functorBinding()
|
||||
@ -1416,6 +1418,68 @@ void tst_QProperty::noFakeDependencies()
|
||||
QCOMPARE(old, bindingFunctionCalled);
|
||||
}
|
||||
|
||||
struct CustomType
|
||||
{
|
||||
CustomType() = default;
|
||||
CustomType(int val) : value(val) { }
|
||||
CustomType(int val, int otherVal) : value(val), anotherValue(otherVal) { }
|
||||
CustomType(const CustomType &) = default;
|
||||
CustomType(CustomType &&) = default;
|
||||
~CustomType() = default;
|
||||
CustomType &operator=(const CustomType &) = default;
|
||||
CustomType &operator=(CustomType &&) = default;
|
||||
bool operator==(const CustomType &other) const
|
||||
{
|
||||
return (value == other.value) && (anotherValue == other.anotherValue);
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
int anotherValue = 0;
|
||||
};
|
||||
|
||||
class PropertyWithInitializationTester : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int prop1 READ prop1 WRITE setProp1 NOTIFY prop1Changed BINDABLE bindableProp1)
|
||||
Q_PROPERTY(CustomType prop2 READ prop2 WRITE setProp2 BINDABLE bindableProp2)
|
||||
Q_PROPERTY(CustomType prop3 READ prop3 WRITE setProp3 BINDABLE bindableProp3)
|
||||
signals:
|
||||
void prop1Changed();
|
||||
|
||||
public:
|
||||
PropertyWithInitializationTester(QObject *parent = nullptr) : QObject(parent) { }
|
||||
|
||||
int prop1() { return prop1Data.value(); }
|
||||
void setProp1(int i) { prop1Data = i; }
|
||||
QBindable<int> bindableProp1() { return QBindable<int>(&prop1Data); }
|
||||
|
||||
CustomType prop2() { return prop2Data.value(); }
|
||||
void setProp2(CustomType val) { prop2Data = val; }
|
||||
QBindable<CustomType> bindableProp2() { return QBindable<CustomType>(&prop2Data); }
|
||||
|
||||
CustomType prop3() { return prop3Data.value(); }
|
||||
void setProp3(CustomType val) { prop3Data = val; }
|
||||
QBindable<CustomType> bindableProp3() { return QBindable<CustomType>(&prop3Data); }
|
||||
|
||||
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(PropertyWithInitializationTester, int, prop1Data, 5,
|
||||
&PropertyWithInitializationTester::prop1Changed)
|
||||
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(PropertyWithInitializationTester, CustomType, prop2Data,
|
||||
CustomType(5))
|
||||
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(PropertyWithInitializationTester, CustomType, prop3Data,
|
||||
&PropertyWithInitializationTester::setProp3,
|
||||
CustomType(10, 20))
|
||||
};
|
||||
|
||||
void tst_QProperty::bindablePropertyWithInitialization()
|
||||
{
|
||||
PropertyWithInitializationTester tester;
|
||||
|
||||
QCOMPARE(tester.prop1(), 5);
|
||||
QCOMPARE(tester.prop2().value, 5);
|
||||
QCOMPARE(tester.prop3().value, 10);
|
||||
QCOMPARE(tester.prop3().anotherValue, 20);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QProperty);
|
||||
|
||||
#include "tst_qproperty.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user