18#include <private/qglobal_p.h>
25#include <QtCore/QVarLengthArray>
74 return ptr->binding();
79 auto &
d =
ptr->d_ref();
89 inline int observerCount()
const;
108 m_placeHolder.next =
next;
111 next->prev = &m_placeHolder.next;
112 m_placeHolder.prev = &observer->next;
129#if QT_DEPRECATED_SINCE(6, 6)
131 if (
ptr->next.tag() == QPropertyObserver::ObserverIsAlias)
132 ptr->aliasData =
nullptr;
139#if QT_DEPRECATED_SINCE(6, 6)
141 Q_ASSERT(
ptr->next.tag() != QPropertyObserver::ObserverIsAlias);
150 ptr->binding = binding;
157 enum class Notify {Everything, OnlyChangeHandlers};
168 explicit operator bool()
const {
return ptr !=
nullptr; }
182 ptr->next->prev =
ptr->prev;
184 ptr->prev.setPointer(
ptr->next.data());
204 *currentState = previousState;
225 *currentState = previousState;
226 *currentlyEvaluatingBindingList = bindingState;
247 : status(&status->currentCompatProperty)
248 , stolen(
std::exchange(status->currentCompatProperty,
nullptr))
270 using ObserverArray = std::array<QPropertyObserver, 4>;
275 bool updating =
false;
276 bool hasStaticObserver =
false;
277 bool pendingNotify =
false;
278 bool hasBindingWrapper:1;
280 bool isQQmlPropertyBinding:1;
293 ObserverArray inlineDependencyObservers;
296 std::unique_ptr<std::vector<QPropertyObserver>> heapObservers;
323 constexpr auto align =
alignof (std::max_align_t) - 1;
325 static_assert (sizeEnsuringAlignment %
alignof (std::max_align_t) == 0,
326 "Required for placement new'ing the function behind it.");
327 return sizeEnsuringAlignment;
332 size_t dependencyObserverCount = 0;
341 : hasBindingWrapper(
false)
342 , isQQmlPropertyBinding(isQQmlPropertyBinding)
354 Q_ASSERT(!(callback && bindingWrapper));
356 hasStaticObserver =
true;
357 hasBindingWrapper =
false;
358 staticObserverCallback = callback;
359 }
else if (bindingWrapper) {
360 hasStaticObserver =
false;
361 hasBindingWrapper =
true;
362 staticBindingWrapper = bindingWrapper;
364 hasStaticObserver =
false;
365 hasBindingWrapper =
false;
366 staticObserverCallback =
nullptr;
372 firstObserver = observer;
377 auto observers = firstObserver;
378 firstObserver.
ptr =
nullptr;
382 void clearDependencyObservers();
385 if (dependencyObserverCount < inlineDependencyObservers.size()) {
386 ++dependencyObserverCount;
387 return {&inlineDependencyObservers[dependencyObserverCount - 1]};
389 return allocateDependencyObserver_slow();
396 if (!hasCustomVTable())
399 constexpr auto msg =
"Custom location";
406 void unlinkAndDeref();
414 NotificationState notifyNonRecursive();
420 {
error = std::move(e); }
424 hasStaticObserver =
false;
425 hasBindingWrapper =
false;
426 propertyDataPtr =
nullptr;
427 clearDependencyObservers();
434 return vtable->
size == 0;
438 if (
priv->hasCustomVTable()) {
443 priv->~QPropertyBindingPrivate();
444 delete[]
reinterpret_cast<std::byte *
>(
priv);
452 b->firstObserver.ptr = observer;
455 auto &
d =
ptr->d_ref();
456 d =
reinterpret_cast<quintptr>(observer);
461 auto &
d =
ptr->d_ref();
462 if (
ptr->isNotificationDelayed()) {
479 return b->firstObserver;
489 if (!
ptr->isNotificationDelayed())
491 return ptr->proxyData();
497 for (
auto observer = firstObserver(); observer; observer = observer.nextObserver())
504 void Q_CORE_EXPORT initBindingStatusThreadId();
511 template<
typename Property,
typename>
514 using ThisType = QObjectCompatProperty<Class, T, Offset, Setter, Signal, Getter>;
515 using SignalTakesValue = std::is_invocable<
decltype(Signal), Class, T>;
518 char *that =
reinterpret_cast<char *
>(
this);
521 const Class *owner()
const
523 char *that =
const_cast<char *
>(
reinterpret_cast<const char *
>(
this));
529 auto *thisData =
static_cast<ThisType *
>(dataPtr);
531 QPropertyData<T>
copy;
535 if constexpr (QTypeTraits::has_operator_equal_v<T>)
536 if (
copy.valueBypassingBindings() == thisData->valueBypassingBindings())
541 (thisData->owner()->*
Setter)(
copy.valueBypassingBindings());
546 return storage->bindingStatus &&
storage->bindingStatus->currentCompatProperty
551 auto prop =
static_cast<const ThisType *
>(
d);
552 if constexpr (std::is_null_pointer_v<
decltype(
Getter)>)
553 return prop->value();
555 return (prop->owner()->*
Getter)();
571 if (
storage->bindingStatus &&
storage->bindingStatus->currentlyEvaluatingBinding && !inBindingWrapper(
storage))
572 storage->registerDependency_helper(
this);
578 if constexpr (QTypeTraits::is_dereferenceable_v<T>) {
580 }
else if constexpr (std::is_pointer_v<T>) {
601 if (
auto *bd =
storage->bindingData(
this)) {
603 if (bd->hasBinding() && !inBindingWrapper(
storage))
604 bd->removeBinding_helper();
615 QPropertyBinding<T>
setBinding(
const QPropertyBinding<T> &newBinding)
620 return static_cast<QPropertyBinding<T> &
>(oldBinding);
627 setBinding(
static_cast<const QPropertyBinding<T> &
>(newBinding));
632 template <
typename Functor>
635 std::enable_if_t<std::is_invocable_v<Functor>> * =
nullptr)
640 template <
typename Functor>
641 QPropertyBinding<T> setBinding(
Functor f);
646 return bd && bd->
binding() !=
nullptr;
652 if (
auto *bd =
storage->bindingData(
this)) {
654 if (bd->hasBinding() && !inBindingWrapper(
storage))
655 bd->removeBinding_helper();
662 if (
auto bd =
storage->bindingData(
this,
false)) {
666 if (!bd->isNotificationDelayed()) {
669 if (!inBindingWrapper(
storage)) {
671 if (bd->notifyObserver_helper(
this,
storage, observer, bindingObservers)
672 == QtPrivate::QPropertyBindingData::Evaluated) {
675 observer.notify(
this);
676 for (
auto&& bindingObserver: bindingObservers)
677 bindingObserver.binding()->notifyNonRecursive();
683 if constexpr (!std::is_null_pointer_v<
decltype(Signal)>) {
684 if constexpr (SignalTakesValue::value)
685 (owner()->*Signal)(getPropertyValue(
this));
687 (owner()->*Signal)();
699 return setBinding(QPropertyBinding<T>());
702 template<
typename Functor>
705 static_assert(std::is_invocable_v<Functor>,
"Functor callback must be callable without any parameters");
706 return QPropertyChangeHandler<Functor>(*
this,
f);
709 template<
typename Functor>
712 static_assert(std::is_invocable_v<Functor>,
"Functor callback must be callable without any parameters");
714 return onValueChanged(
f);
717 template<
typename Functor>
720 static_assert(std::is_invocable_v<Functor>,
"Functor callback must be callable without any parameters");
732template<
typename Class,
typename Ty, auto Offset, auto Setter, auto Signal, auto Getter>
736 using Property = QObjectCompatProperty<Class, Ty, Offset, Setter, Signal, Getter>;
737 using T =
typename Property::value_type;
741 { *
static_cast<T*
>(
value) = Property::getPropertyValue(
d); },
744 (
static_cast<Property *
>(
d)->owner()->*Setter)(*
static_cast<const T*
>(
value));
747 {
return static_cast<const Property *
>(
d)->binding(); },
749 {
return static_cast<Property *
>(
d)->setBinding(
static_cast<const QPropertyBinding<T> &
>(binding)); },
753 { observer->setSource(
static_cast<const Property *
>(
d)->bindingData()); },
754 []() {
return QMetaType::fromType<T>(); }
759#define QT_OBJECT_COMPAT_PROPERTY_4(Class, Type, name, setter) \
760 static constexpr size_t _qt_property_##name##_offset() { \
761 QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
762 return offsetof(Class, name); \
765 QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name;
767#define QT_OBJECT_COMPAT_PROPERTY_5(Class, Type, name, setter, signal) \
768 static constexpr size_t _qt_property_##name##_offset() { \
769 QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
770 return offsetof(Class, name); \
773 QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, signal> name;
775#define Q_OBJECT_COMPAT_PROPERTY(...) \
776 QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
777 QT_OVERLOADED_MACRO(QT_OBJECT_COMPAT_PROPERTY, __VA_ARGS__) \
780#define QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS_5(Class, Type, name, setter, value) \
781 static constexpr size_t _qt_property_##name##_offset() { \
782 QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
783 return offsetof(Class, name); \
786 QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter> name = \
787 QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter>( \
790#define QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS_6(Class, Type, name, setter, signal, value) \
791 static constexpr size_t _qt_property_##name##_offset() { \
792 QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
793 return offsetof(Class, name); \
796 QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, signal> name = \
797 QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, \
800#define QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS_7(Class, Type, name, setter, signal, getter, value) \
801 static constexpr size_t _qt_property_##name##_offset() { \
802 QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
803 return offsetof(Class, name); \
806 QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, signal, getter>\
807 name = QObjectCompatProperty<Class, Type, Class::_qt_property_##name##_offset, setter, \
808 signal, getter>(value);
810#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(...) \
811 QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
812 QT_OVERLOADED_MACRO(QT_OBJECT_COMPAT_PROPERTY_WITH_ARGS, __VA_ARGS__) \
817Q_CORE_EXPORT BindingEvaluationState *suspendCurrentBindingStatus();
818Q_CORE_EXPORT
void restoreBindingStatus(BindingEvaluationState *status);
825 return bindable.
iface;
830 return bindable.
data;
838 if (isQQmlPropertyBinding)
853 QScopedValueRollback<bool> updateGuard(updating,
true);
857 auto bindingFunctor =
reinterpret_cast<std::byte *
>(
this) +
859 bool changed =
false;
860 if (hasBindingWrapper) {
861 changed = staticBindingWrapper(metaType, propertyDataPtr,
862 {vtable, bindingFunctor});
864 changed = vtable->call(metaType, propertyDataPtr, bindingFunctor);
868 pendingNotify = pendingNotify || changed;
869 if (!changed || !firstObserver)
872 firstObserver.noSelfDependencies(
this);
873 firstObserver.evaluateBindings(bindingObservers, status);
910 auto handlerToCall = observer->changeHandler;
913 observer =
next->next.data();
918 handlerToCall(observer, propertyDataPtr);
919 next = protector.next();
927#if QT_DEPRECATED_SINCE(6, 6)
929 case QPropertyObserver::ObserverIsAlias:
933 default: Q_UNREACHABLE();
957 if (!bindingPrivate->deref())
972#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
983 if (
ptr->isImpl(&QPropertyAdaptorSlotObject::impl)) {
985 if (
p->metaProperty_.propertyIndex() == propertyIndex)
996 friend class QT_PREPEND_NAMESPACE(QUntypedBindable);
QtPrivate::QPropertyBindingData * bindingData(const QUntypedPropertyData *data) const
\macro Q_OBJECT_BINDABLE_PROPERTY(containingClass, type, name, signal)
QPropertyBinding< T > binding() const
typename QPropertyData< T >::value_type value_type
QtPrivate::QPropertyBindingData & bindingData() const
QObjectCompatProperty & operator=(parameter_type newValue)
typename QPropertyData< T >::arrow_operator_result arrow_operator_result
typename QPropertyData< T >::parameter_type parameter_type
parameter_type value() const
QObjectCompatProperty()=default
QPropertyChangeHandler< Functor > onValueChanged(Functor f)
void setValue(parameter_type t)
void removeBindingUnlessInWrapper()
bool setBinding(const QUntypedPropertyBinding &newBinding)
QPropertyBinding< T > setBinding(Functor &&f, const QPropertyBindingSourceLocation &location=QT_PROPERTY_DEFAULT_BINDING_LOCATION, std::enable_if_t< std::is_invocable_v< Functor > > *=nullptr)
arrow_operator_result operator->() const
QObjectCompatProperty(T &&initialValue)
QPropertyNotifier addNotifier(Functor f)
parameter_type operator*() const
QObjectCompatProperty(const T &initialValue)
QPropertyBinding< T > takeBinding()
QPropertyChangeHandler< Functor > subscribe(Functor f)
QPropertyBinding< T > setBinding(const QPropertyBinding< T > &newBinding)
Type
This enum specifies which error occurred.
T * data() const noexcept
void detachFromProperty()
QPropertyBindingError bindingError() const
QMetaType valueMetaType() const
void setStaticObserver(QtPrivate::QPropertyObserverCallback callback, QtPrivate::QPropertyBindingWrapper bindingWrapper)
QPropertyBindingSourceLocation sourceLocation() const
QPropertyBindingSourceLocation location
QPropertyObserverPointer takeObservers()
void setSticky(bool keep=true)
static constexpr size_t getSizeEnsuringAlignment()
void setProperty(QUntypedPropertyData *propertyPtr)
QPropertyBindingPrivate(QMetaType metaType, const QtPrivate::BindingFunctionVTable *vtable, const QPropertyBindingSourceLocation &location, bool isQQmlPropertyBinding=false)
static void destroyAndFreeMemory(QPropertyBindingPrivate *priv)
Q_ALWAYS_INLINE QPropertyObserverPointer allocateDependencyObserver()
bool hasCustomVTable() const
void setError(QPropertyBindingError &&e)
bool Q_ALWAYS_INLINE evaluateRecursive_inline(PendingBindingObserverList &bindingObservers, QBindingStatus *status)
void(*)(QPropertyBindingPrivate *) DeclarativeErrorCallback
static QPropertyBindingPrivate * get(const QUntypedPropertyBinding &binding)
DeclarativeErrorCallback errorCallBack
QtPrivate::QPropertyBindingWrapper staticBindingWrapper
void prependObserver(QPropertyObserverPointer observer)
std::conditional_t< std::is_pointer_v< T >, const T &, std::conditional_t< QTypeTraits::is_dereferenceable_v< T >, const T &, void > > arrow_operator_result
std::conditional_t< UseReferences, const T &, T > parameter_type
@ ObserverNotifiesBinding
@ ObserverNotifiesChangeHandler
void(*)(QPropertyObserver *, QUntypedPropertyData *) ChangeHandler
\macro QT_RESTRICTED_CAST_FROM_ASCII
const QtPrivate::QBindableInterface * iface
QUntypedPropertyData * data
QMetaType valueMetaType() const
Returns the meta-type of the binding.
bool isNull() const
Returns true if the QUntypedPropertyBinding is null.
QPropertyBindingData & bindingData()
const QMetaProperty & metaProperty() const
static QPropertyAdaptorSlotObject * cast(QSlotObjectBase *ptr, int propertyIndex)
const QPropertyBindingData & bindingData() const
QPropertyBindingPrivate * binding() const
static constexpr quintptr BindingBit
Combined button and popup list for selecting options.
bool bindingWrapper(QMetaType type, QUntypedPropertyData *d, QtPrivate::QPropertyBindingFunction binding, QUntypedPropertyData *temp, void *value)
constexpr size_t getOffset(size_t o)
bool isAnyBindingEvaluating()
void(*)(QUntypedPropertyData *) QPropertyObserverCallback
bool(*)(QMetaType, QUntypedPropertyData *dataPtr, QPropertyBindingFunction) QPropertyBindingWrapper
bool isPropertyInBindingWrapper(const QUntypedPropertyData *property)
auto makePropertyBinding(Functor &&f, const QPropertyBindingSourceLocation &location=QT_PROPERTY_DEFAULT_BINDING_LOCATION, std::enable_if_t< std::is_invocable_v< Functor > > *=nullptr)
static jboolean copy(JNIEnv *, jobject)
#define QT_WARNING_DISABLE_DEPRECATED
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static ControlElement< T > * ptr(QWidget *widget)
const QBindingStorage * qGetBindingStorage(const QObject *o)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
#define QT_PROPERTY_DEFAULT_BINDING_LOCATION
constexpr void qt_ptr_swap(T *&lhs, T *&rhs) noexcept
settings setValue("DataPump/bgcolor", color)
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QBindingObserverPtr)
QBindingObserverPtr(QBindingObserverPtr &&other) noexcept
QBindingObserverPtr()=default
void swap(QBindingObserverPtr &other) noexcept
QPropertyObserver * operator->()
QPropertyBindingPrivate * binding() const noexcept
Q_DISABLE_COPY(QBindingObserverPtr)
static QPropertyProxyBindingData * proxyData(QtPrivate::QPropertyBindingData *ptr)
static void fixupAfterMove(QtPrivate::QPropertyBindingData *ptr)
int observerCount() const
static QPropertyBindingDataPointer get(QProperty< T > &property)
QPropertyBindingPrivate * binding() const
void setObservers(QPropertyObserver *observer)
QPropertyObserverPointer firstObserver() const
void setFirstObserver(QPropertyObserver *observer)
~QPropertyObserverNodeProtector()
QPropertyObserver * next() const
void notify(QUntypedPropertyData *propertyDataPtr)
QPropertyBindingPrivate * binding() const
QPropertyObserverPointer nextObserver() const
void setBindingToNotify(QPropertyBindingPrivate *binding)
static QtPrivate::QBindableInterface const * getInterface(const QUntypedBindable &bindable)
static QUntypedPropertyData * getPropertyData(const QUntypedBindable &bindable)
QPropertyBindingPrivate * binding
QVarLengthArray< const QPropertyBindingData *, 8 > alreadyCaptureProperties
~BindingEvaluationState()
~CompatPropertySafePoint()
QUntypedPropertyData * property
CurrentCompatPropertyThief(QBindingStatus *status)
~CurrentCompatPropertyThief()
const QtPrivate::BindingFunctionVTable * vtable