summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-06-17 12:33:54 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-06-17 19:13:08 +0000
commit6900bd8a3672cca6f50252bfe59ddaeeae033243 (patch)
tree9d8e491f8bc3f31cd6a769cb5f08176be253bf9b /src
parent4d4e13c68474ac7b1a64d64d5bada58bbe8b47ba (diff)
QBindable: Use setter in setValue for QObjectCompatProperty
Directly writing to the underlying property storage has the potential of breaking all kinds of internal invariants. As we return QBindable in the public interface, we should not grant callers access to the internals of the object. Change-Id: I737ff293b9d921b7de861da5ae23356c17690b78 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Andreas Buhr <andreas.buhr@qt.io> (cherry picked from commit 6b36e783521993df8de6477c789aa26c38803656) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qproperty_p.h31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h
index e92c8f878a..2883308299 100644
--- a/src/corelib/kernel/qproperty_p.h
+++ b/src/corelib/kernel/qproperty_p.h
@@ -396,6 +396,9 @@ namespace QtPrivate {
template<typename Class, typename T, auto Offset, auto Setter, auto Signal=nullptr>
class QObjectCompatProperty : public QPropertyData<T>
{
+ template<typename Property, typename>
+ friend class QtPrivate::QBindableInterfaceForProperty;
+
using ThisType = QObjectCompatProperty<Class, T, Offset, Setter, Signal>;
using SignalTakesValue = std::is_invocable<decltype(Signal), Class, T>;
Class *owner()
@@ -408,6 +411,7 @@ class QObjectCompatProperty : public QPropertyData<T>
char *that = const_cast<char *>(reinterpret_cast<const char *>(this));
return reinterpret_cast<Class *>(that - QtPrivate::detail::getOffset(Offset));
}
+
static bool bindingWrapper(QMetaType type, QUntypedPropertyData *dataPtr, QtPrivate::QPropertyBindingFunction binding)
{
auto *thisData = static_cast<ThisType *>(dataPtr);
@@ -591,6 +595,33 @@ private:
}
};
+namespace QtPrivate {
+template<typename Class, typename Ty, auto Offset, auto Setter, auto Signal>
+class QBindableInterfaceForProperty<QObjectCompatProperty<Class, Ty, Offset, Setter, Signal>, std::void_t<Class>>
+{
+ using Property = QObjectCompatProperty<Class, Ty, Offset, Setter, Signal>;
+ using T = typename Property::value_type;
+public:
+ static constexpr QBindableInterface iface = {
+ [](const QUntypedPropertyData *d, void *value) -> void
+ { *static_cast<T*>(value) = static_cast<const Property *>(d)->value(); },
+ [](QUntypedPropertyData *d, const void *value) -> void
+ {
+ (static_cast<Property *>(d)->owner()->*Setter)(*static_cast<const T*>(value));
+ },
+ [](const QUntypedPropertyData *d) -> QUntypedPropertyBinding
+ { return static_cast<const Property *>(d)->binding(); },
+ [](QUntypedPropertyData *d, const QUntypedPropertyBinding &binding) -> QUntypedPropertyBinding
+ { return static_cast<Property *>(d)->setBinding(static_cast<const QPropertyBinding<T> &>(binding)); },
+ [](const QUntypedPropertyData *d, const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding
+ { return Qt::makePropertyBinding([d]() -> T { return static_cast<const Property *>(d)->value(); }, location); },
+ [](const QUntypedPropertyData *d, QPropertyObserver *observer) -> void
+ { observer->setSource(static_cast<const Property *>(d)->bindingData()); },
+ []() { return QMetaType::fromType<T>(); }
+ };
+};
+}
+
#define QT_OBJECT_COMPAT_PROPERTY_4(Class, Type, name, setter) \
static constexpr size_t _qt_property_##name##_offset() { \
QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \