diff options
Diffstat (limited to 'src/corelib/kernel/qproperty_p.h')
-rw-r--r-- | src/corelib/kernel/qproperty_p.h | 79 |
1 files changed, 68 insertions, 11 deletions
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index dbf5535143..376482a6af 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -19,12 +19,13 @@ #include <qproperty.h> #include <qmetaobject.h> -#include <qscopedpointer.h> #include <qscopedvaluerollback.h> #include <qvariant.h> #include <vector> #include <QtCore/QVarLengthArray> +#include <memory> + QT_BEGIN_NAMESPACE namespace QtPrivate { @@ -94,11 +95,12 @@ struct QPropertyBindingDataPointer } }; -struct [[nodiscard]] QPropertyObserverNodeProtector +struct QPropertyObserverNodeProtector { Q_DISABLE_COPY_MOVE(QPropertyObserverNodeProtector) QPropertyObserverBase m_placeHolder; + Q_NODISCARD_CTOR QPropertyObserverNodeProtector(QPropertyObserver *observer) { // insert m_placeholder after observer into the linked list @@ -125,20 +127,30 @@ struct QPropertyObserverPointer { unlink_common(); #if QT_DEPRECATED_SINCE(6, 6) + QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED if (ptr->next.tag() == QPropertyObserver::ObserverIsAlias) ptr->aliasData = nullptr; + QT_WARNING_POP #endif } void unlink_fast() { #if QT_DEPRECATED_SINCE(6, 6) + QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsAlias); + QT_WARNING_POP #endif unlink_common(); } - void setBindingToNotify(QPropertyBindingPrivate *binding); + void setBindingToNotify(QPropertyBindingPrivate *binding) + { + Q_ASSERT(ptr->next.tag() != QPropertyObserver::ObserverIsPlaceholder); + ptr->binding = binding; + ptr->next.setTag(QPropertyObserver::ObserverNotifiesBinding); + } + void setBindingToNotify_unsafe(QPropertyBindingPrivate *binding); void setChangeHandler(QPropertyObserver::ChangeHandler changeHandler); @@ -161,7 +173,7 @@ struct QPropertyObserverPointer { Q_ASSERT(ptr->next.tag() == QPropertyObserver::ObserverNotifiesBinding); return ptr->binding; - }; + } private: void unlink_common() @@ -195,6 +207,7 @@ struct BindingEvaluationState QPropertyBindingPrivate *binding; BindingEvaluationState *previousState = nullptr; BindingEvaluationState **currentState = nullptr; + QVarLengthArray<const QPropertyBindingData *, 8> alreadyCaptureProperties; }; /*! @@ -219,6 +232,33 @@ struct CompatPropertySafePoint QtPrivate::BindingEvaluationState *bindingState = nullptr; }; +/*! + * \internal + * While the regular QProperty notification for a compat property runs we + * don't want to have any currentCompatProperty set. This would be a _different_ + * one than the one we are current evaluating. Therefore it's misleading and + * prevents the registering of actual dependencies. + */ +struct CurrentCompatPropertyThief +{ + Q_DISABLE_COPY_MOVE(CurrentCompatPropertyThief) +public: + CurrentCompatPropertyThief(QBindingStatus *status) + : status(&status->currentCompatProperty) + , stolen(std::exchange(status->currentCompatProperty, nullptr)) + { + } + + ~CurrentCompatPropertyThief() + { + *status = stolen; + } + +private: + CompatPropertySafePoint **status = nullptr; + CompatPropertySafePoint *stolen = nullptr; +}; + } class Q_CORE_EXPORT QPropertyBindingPrivate : public QtPrivate::RefCounted @@ -253,7 +293,7 @@ private: ObserverArray inlineDependencyObservers; // for things we are observing QPropertyObserverPointer firstObserver; // list of observers observing us - QScopedPointer<std::vector<QPropertyObserver>> heapObservers; // for things we are observing + std::unique_ptr<std::vector<QPropertyObserver>> heapObservers; // for things we are observing protected: QUntypedPropertyData *propertyDataPtr = nullptr; @@ -487,13 +527,16 @@ class QObjectCompatProperty : public QPropertyData<T> static bool bindingWrapper(QMetaType type, QUntypedPropertyData *dataPtr, QtPrivate::QPropertyBindingFunction binding) { auto *thisData = static_cast<ThisType *>(dataPtr); + QBindingStorage *storage = qGetBindingStorage(thisData->owner()); QPropertyData<T> copy; - binding.vtable->call(type, ©, binding.functor); - if constexpr (QTypeTraits::has_operator_equal_v<T>) - if (copy.valueBypassingBindings() == thisData->valueBypassingBindings()) - return false; + { + QtPrivate::CurrentCompatPropertyThief thief(storage->bindingStatus); + binding.vtable->call(type, ©, binding.functor); + if constexpr (QTypeTraits::has_operator_equal_v<T>) + if (copy.valueBypassingBindings() == thisData->valueBypassingBindings()) + return false; + } // ensure value and setValue know we're currently evaluating our binding - QBindingStorage *storage = qGetBindingStorage(thisData->owner()); QtPrivate::CompatPropertySafePoint guardThis(storage->bindingStatus, thisData); (thisData->owner()->*Setter)(copy.valueBypassingBindings()); return true; @@ -882,8 +925,10 @@ inline void QPropertyObserverPointer::notify(QUntypedPropertyData *propertyDataP // recursion is already properly handled somewhere else break; #if QT_DEPRECATED_SINCE(6, 6) + QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED case QPropertyObserver::ObserverIsAlias: break; + QT_WARNING_POP #endif default: Q_UNREACHABLE(); } @@ -903,7 +948,15 @@ QBindingObserverPtr::QBindingObserverPtr(QPropertyObserver *observer) noexcept : QPropertyObserverPointer{d}.binding()->addRef(); } -QBindingObserverPtr::~QBindingObserverPtr() { if (d) QPropertyObserverPointer{d}.binding()->deref(); } +QBindingObserverPtr::~QBindingObserverPtr() +{ + if (!d) + return; + + QPropertyBindingPrivate *bindingPrivate = binding(); + if (!bindingPrivate->deref()) + QPropertyBindingPrivate::destroyAndFreeMemory(bindingPrivate); +} QPropertyBindingPrivate *QBindingObserverPtr::binding() const noexcept { return QPropertyObserverPointer{d}.binding(); } @@ -916,7 +969,11 @@ class QPropertyAdaptorSlotObject : public QUntypedPropertyData, public QSlotObje QObject *obj; QMetaProperty metaProperty_; +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret); +#else + static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret); +#endif QPropertyAdaptorSlotObject(QObject *o, const QMetaProperty& p); |