diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2023-02-03 14:35:55 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2023-02-07 22:27:37 +0100 |
commit | 55ca636180db2b7870b5b519c4163487b672a9f1 (patch) | |
tree | fa04d15d2bc506e3fdee6ede4b54624df1464071 /src/corelib/kernel | |
parent | efce30bb4309ee0ae6af35b8fe6f62ccfb67622c (diff) |
Fix proxy-data handling
This addresses two different issues:
- Firstly, we were casting the resolved binding data pointer to
QPropertyProxyBindingData, instead of the d_ptr of
QPropertyBindingData. Fix this by introducing a helper function,
and consistently using it to access the proxy data.
- Secondly, we were not resetting the originalBindingData when the
pointed to object was destoyed. Fix that, too.
Pick-to: 6.5 6.4 6.2
Task-number: QTBUG-110899
Change-Id: I7691c9df5cc26e761f6b0e5f16d152f7f2183208
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty_p.h | 18 | ||||
-rw-r--r-- | src/corelib/kernel/qpropertyprivate.h | 7 |
3 files changed, 23 insertions, 4 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 4836b9c857..f54cd73278 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -446,6 +446,8 @@ QMetaType QUntypedPropertyBinding::valueMetaType() const QPropertyBindingData::~QPropertyBindingData() { QPropertyBindingDataPointer d{this}; + if (isNotificationDelayed()) + proxyData()->originalBindingData = nullptr; for (auto observer = d.firstObserver(); observer;) { auto next = observer.nextObserver(); observer.unlink(); diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index a7fb9e9a1a..42daca036a 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -83,6 +83,7 @@ struct QPropertyBindingDataPointer void Q_ALWAYS_INLINE addObserver(QPropertyObserver *observer); inline void setFirstObserver(QPropertyObserver *observer); inline QPropertyObserverPointer firstObserver() const; + static QPropertyProxyBindingData *proxyData(QtPrivate::QPropertyBindingData *ptr); inline int observerCount() const; @@ -418,9 +419,9 @@ inline void QPropertyBindingDataPointer::fixupAfterMove(QtPrivate::QPropertyBind { auto &d = ptr->d_ref(); if (ptr->isNotificationDelayed()) { - QPropertyProxyBindingData *proxyData - = reinterpret_cast<QPropertyProxyBindingData*>(d & ~QtPrivate::QPropertyBindingData::BindingBit); - proxyData->originalBindingData = ptr; + QPropertyProxyBindingData *proxy = ptr->proxyData(); + Q_ASSERT(proxy); + proxy->originalBindingData = ptr; } // If QPropertyBindingData has been moved, and it has an observer // we have to adjust the firstObserver's prev pointer to point to @@ -438,6 +439,17 @@ inline QPropertyObserverPointer QPropertyBindingDataPointer::firstObserver() con return { reinterpret_cast<QPropertyObserver *>(ptr->d()) }; } +/*! + \internal + Returns the proxy data of \a ptr, or \c nullptr if \a ptr has no delayed notification + */ +inline QPropertyProxyBindingData *QPropertyBindingDataPointer::proxyData(QtPrivate::QPropertyBindingData *ptr) +{ + if (!ptr->isNotificationDelayed()) + return nullptr; + return ptr->proxyData(); +} + inline int QPropertyBindingDataPointer::observerCount() const { int count = 0; diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h index 4387f0fbeb..aca6d14c96 100644 --- a/src/corelib/kernel/qpropertyprivate.h +++ b/src/corelib/kernel/qpropertyprivate.h @@ -303,10 +303,15 @@ private: { quintptr &d = d_ptr; if (isNotificationDelayed()) - return reinterpret_cast<QPropertyProxyBindingData *>(d_ptr & ~(BindingBit|DelayedNotificationBit))->d_ptr; + return proxyData()->d_ptr; return d; } quintptr d() const { return d_ref(); } + QPropertyProxyBindingData *proxyData() const + { + Q_ASSERT(isNotificationDelayed()); + return reinterpret_cast<QPropertyProxyBindingData *>(d_ptr & ~(BindingBit|DelayedNotificationBit)); + } void registerWithCurrentlyEvaluatingBinding_helper(BindingEvaluationState *currentBinding) const; void removeBinding_helper(); |