summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qpropertyprivate.h
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-02-05 10:07:50 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-04-16 16:49:29 +0200
commitfdedcb6ec650236bef4a8c8f005b5dd24ef7d77a (patch)
tree430f0e1dc295f0c0a03008db9ef426c192f391ba /src/corelib/kernel/qpropertyprivate.h
parentbb44c18b673e2955592ee86774eb7cc25d390c17 (diff)
Add support for grouped property changes
Add Qt::begin/endPropertyUpdateGroup() methods. These methods will group a set of property updates together and delay bindings evaluations or change notifications until the end of the update group. In cases where many properties get updated, this can avoid duplicated recalculations and change notifications. Change-Id: Ia78ae1d46abc6b7e5da5023442e081cb5c5ae67b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Andreas Buhr <andreas.buhr@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/kernel/qpropertyprivate.h')
-rw-r--r--src/corelib/kernel/qpropertyprivate.h60
1 files changed, 56 insertions, 4 deletions
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index b6d93529d1..f59221c4df 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -143,7 +143,6 @@ private:
QtPrivate::RefCounted *d;
};
-
class QUntypedPropertyBinding;
class QPropertyBindingPrivate;
struct QPropertyBindingDataPointer;
@@ -158,6 +157,24 @@ public:
template <typename T>
class QPropertyData;
+// Used for grouped property evaluations
+namespace QtPrivate {
+class QPropertyBindingData;
+}
+struct QPropertyDelayedNotifications;
+struct QPropertyProxyBindingData
+{
+ // acts as QPropertyBindingData::d_ptr
+ quintptr d_ptr;
+ /*
+ The two members below store the original binding data and property
+ data pointer of the property which gets proxied.
+ They are set in QPropertyDelayedNotifications::addProperty
+ */
+ const QtPrivate::QPropertyBindingData *originalBindingData;
+ QUntypedPropertyData *propertyData;
+};
+
namespace QtPrivate {
struct BindingEvaluationState;
@@ -218,6 +235,16 @@ struct QPropertyBindingFunction {
using QPropertyObserverCallback = void (*)(QUntypedPropertyData *);
using QPropertyBindingWrapper = bool(*)(QMetaType, QUntypedPropertyData *dataPtr, QPropertyBindingFunction);
+/*!
+ \internal
+ A property normally consists of the actual property value and metadata for the binding system.
+ QPropertyBindingData is the latter part. It stores a pointer to either
+ - a (potentially empty) linked list of notifiers, in case there is no binding set,
+ - an actual QUntypedPropertyBinding when the property has a binding,
+ - or a pointer to QPropertyProxyBindingData when notifications occur inside a grouped update.
+
+ \sa QPropertyDelayedNotifications, beginPropertyUpdateGroup
+ */
class Q_CORE_EXPORT QPropertyBindingData
{
// Mutable because the address of the observer of the currently evaluating binding is stored here, for
@@ -225,6 +252,7 @@ class Q_CORE_EXPORT QPropertyBindingData
mutable quintptr d_ptr = 0;
friend struct QT_PREPEND_NAMESPACE(QPropertyBindingDataPointer);
friend class QT_PREPEND_NAMESPACE(QQmlPropertyBinding);
+ friend struct QT_PREPEND_NAMESPACE(QPropertyDelayedNotifications);
Q_DISABLE_COPY(QPropertyBindingData)
public:
QPropertyBindingData() = default;
@@ -232,9 +260,13 @@ public:
QPropertyBindingData &operator=(QPropertyBindingData &&other) = delete;
~QPropertyBindingData();
- static inline constexpr quintptr BindingBit = 0x1; // Is d_ptr pointing to a binding (1) or list of notifiers (0)?
+ // Is d_ptr pointing to a binding (1) or list of notifiers (0)?
+ static inline constexpr quintptr BindingBit = 0x1;
+ // Is d_ptr pointing to QPropertyProxyBindingData (1) or to an actual binding/list of notifiers?
+ static inline constexpr quintptr DelayedNotificationBit = 0x2;
bool hasBinding() const { return d_ptr & BindingBit; }
+ bool isNotificationDelayed() const { return d_ptr & DelayedNotificationBit; }
QUntypedPropertyBinding setBinding(const QUntypedPropertyBinding &newBinding,
QUntypedPropertyData *propertyDataPtr,
@@ -243,8 +275,9 @@ public:
QPropertyBindingPrivate *binding() const
{
- if (d_ptr & BindingBit)
- return reinterpret_cast<QPropertyBindingPrivate*>(d_ptr - BindingBit);
+ quintptr dd = d();
+ if (dd & BindingBit)
+ return reinterpret_cast<QPropertyBindingPrivate*>(dd - BindingBit);
return nullptr;
}
@@ -266,6 +299,25 @@ public:
void registerWithCurrentlyEvaluatingBinding() const;
void notifyObservers(QUntypedPropertyData *propertyDataPtr) const;
private:
+ /*!
+ \internal
+ Returns a reference to d_ptr, except when d_ptr points to a proxy.
+ In that case, a reference to proxy->d_ptr is returned instead.
+
+ To properly support proxying, direct access to d_ptr only occcurs when
+ - a function actually deals with proxying (e.g.
+ QPropertyDelayedNotifications::addProperty),
+ - only the tag value is accessed (e.g. hasBinding) or
+ - inside a constructor.
+ */
+ quintptr &d_ref() const
+ {
+ quintptr &d = d_ptr;
+ if (isNotificationDelayed())
+ return reinterpret_cast<QPropertyProxyBindingData *>(d_ptr & ~(BindingBit|DelayedNotificationBit))->d_ptr;
+ return d;
+ }
+ quintptr d() const { return d_ref(); }
void registerWithCurrentlyEvaluatingBinding_helper(BindingEvaluationState *currentBinding) const;
void removeBinding_helper();
};