Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qpropertyprivate.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QPROPERTYPRIVATE_H
5#define QPROPERTYPRIVATE_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qglobal.h>
19#include <QtCore/qtaggedpointer.h>
20#include <QtCore/qmetatype.h>
21#include <QtCore/qcontainerfwd.h>
22
23#include <functional>
24
26
27class QBindingStorage;
28
29template<typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter>
31
34
35namespace QtPrivate {
36// QPropertyBindingPrivatePtr operates on a RefCountingMixin solely so that we can inline
37// the constructor and copy constructor
38struct RefCounted {
39 int ref = 0;
40 void addRef() {++ref;}
41 bool deref() {--ref; return ref;}
42};
43}
44
48{
49public:
51 T &operator*() const { return *d; }
52 T *operator->() noexcept { return d; }
53 T *operator->() const noexcept { return d; }
54 explicit operator T *() { return d; }
55 explicit operator const T *() const noexcept { return d; }
56 T *data() const noexcept { return d; }
57 T *get() const noexcept { return d; }
58 const T *constData() const noexcept { return d; }
59 T *take() noexcept { T *x = d; d = nullptr; return x; }
60
61 QPropertyBindingPrivatePtr() noexcept : d(nullptr) { }
63 {
64 if (d && (--d->ref == 0))
66 }
67 Q_CORE_EXPORT void destroyAndFreeMemory();
68
69 explicit QPropertyBindingPrivatePtr(T *data) noexcept : d(data) { if (d) d->addRef(); }
71 : d(o.d) { if (d) d->addRef(); }
72
73 void reset(T *ptr = nullptr) noexcept;
74
76 {
77 reset(o.d);
78 return *this;
79 }
81 {
82 reset(o);
83 return *this;
84 }
85 QPropertyBindingPrivatePtr(QPropertyBindingPrivatePtr &&o) noexcept : d(std::exchange(o.d, nullptr)) {}
86 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QPropertyBindingPrivatePtr)
87
88 operator bool () const noexcept { return d != nullptr; }
89 bool operator!() const noexcept { return d == nullptr; }
90
92 { qt_ptr_swap(d, other.d); }
93
95 { return p1.d == p2.d; }
97 { return p1.d != p2.d; }
98 friend bool operator==(const QPropertyBindingPrivatePtr &p1, const T *ptr) noexcept
99 { return p1.d == ptr; }
100 friend bool operator!=(const QPropertyBindingPrivatePtr &p1, const T *ptr) noexcept
101 { return p1.d != ptr; }
102 friend bool operator==(const T *ptr, const QPropertyBindingPrivatePtr &p2) noexcept
103 { return ptr == p2.d; }
104 friend bool operator!=(const T *ptr, const QPropertyBindingPrivatePtr &p2) noexcept
105 { return ptr != p2.d; }
106 friend bool operator==(const QPropertyBindingPrivatePtr &p1, std::nullptr_t) noexcept
107 { return !p1; }
108 friend bool operator!=(const QPropertyBindingPrivatePtr &p1, std::nullptr_t) noexcept
109 { return p1; }
110 friend bool operator==(std::nullptr_t, const QPropertyBindingPrivatePtr &p2) noexcept
111 { return !p2; }
112 friend bool operator!=(std::nullptr_t, const QPropertyBindingPrivatePtr &p2) noexcept
113 { return p2; }
114
115private:
117};
118
124
126{
127public:
128 // sentinel to check whether a class inherits QUntypedPropertyData
130};
131
132template <typename T>
133class QPropertyData;
134
135// Used for grouped property evaluations
136namespace QtPrivate {
137class QPropertyBindingData;
138}
141{
142 // acts as QPropertyBindingData::d_ptr
144 /*
145 The two members below store the original binding data and property
146 data pointer of the property which gets proxied.
147 They are set in QPropertyDelayedNotifications::addProperty
148 */
151};
152
153namespace QtPrivate {
154struct BindingEvaluationState;
155
156/* used in BindingFunctionVTable::createFor; on all other compilers, void would work, but on
157 MSVC this causes C2182 when compiling in C++20 mode. As we only need to provide some default
158 value which gets ignored, we introduce this dummy type.
159*/
161
163{
164 using CallFn = bool(*)(QMetaType, QUntypedPropertyData *, void *);
165 using DtorFn = void(*)(void *);
166 using MoveCtrFn = void(*)(void *, void *);
171
172 template<typename Callable, typename PropertyType=MSVCWorkAround>
174 {
175 static_assert (alignof(Callable) <= alignof(std::max_align_t), "Bindings do not support overaligned functors!");
176 return {
177 /*call=*/[](QMetaType metaType, QUntypedPropertyData *dataPtr, void *f){
178 if constexpr (!std::is_invocable_v<Callable>) {
179 // we got an untyped callable
180 static_assert (std::is_invocable_r_v<bool, Callable, QMetaType, QUntypedPropertyData *> );
181 auto untypedEvaluationFunction = static_cast<Callable *>(f);
182 return std::invoke(*untypedEvaluationFunction, metaType, dataPtr);
183 } else if constexpr (!std::is_same_v<PropertyType, MSVCWorkAround>) {
184 Q_UNUSED(metaType);
185 QPropertyData<PropertyType> *propertyPtr = static_cast<QPropertyData<PropertyType> *>(dataPtr);
186 // That is allowed by POSIX even if Callable is a function pointer
187 auto evaluationFunction = static_cast<Callable *>(f);
188 PropertyType newValue = std::invoke(*evaluationFunction);
189 if constexpr (QTypeTraits::has_operator_equal_v<PropertyType>) {
190 if (newValue == propertyPtr->valueBypassingBindings())
191 return false;
192 }
193 propertyPtr->setValueBypassingBindings(std::move(newValue));
194 return true;
195 } else {
196 // Our code will never instantiate this
197 Q_UNREACHABLE_RETURN(false);
198 }
199 },
200 /*destroy*/[](void *f){ static_cast<Callable *>(f)->~Callable(); },
201 /*moveConstruct*/[](void *addr, void *other){
202 new (addr) Callable(std::move(*static_cast<Callable *>(other)));
203 },
204 /*size*/sizeof(Callable)
205 };
206 }
207};
208
209template<typename Callable, typename PropertyType=MSVCWorkAround>
210inline constexpr BindingFunctionVTable bindingFunctionVTable = BindingFunctionVTable::createFor<Callable, PropertyType>();
211
212
213// writes binding result into dataPtr
216 void *functor;
217};
218
221
232class Q_CORE_EXPORT QPropertyBindingData
233{
234 // Mutable because the address of the observer of the currently evaluating binding is stored here, for
235 // notification later when the value changes.
236 mutable quintptr d_ptr = 0;
237 friend struct QT_PREPEND_NAMESPACE(QPropertyBindingDataPointer);
238 friend class QT_PREPEND_NAMESPACE(QQmlPropertyBinding);
239 friend struct QT_PREPEND_NAMESPACE(QPropertyDelayedNotifications);
240
241 template<typename Class, typename T, auto Offset, auto Setter, auto Signal, auto Getter>
242 friend class QT_PREPEND_NAMESPACE(QObjectCompatProperty);
243
244 Q_DISABLE_COPY(QPropertyBindingData)
245public:
250
251 // Is d_ptr pointing to a binding (1) or list of notifiers (0)?
252 static inline constexpr quintptr BindingBit = 0x1;
253 // Is d_ptr pointing to QPropertyProxyBindingData (1) or to an actual binding/list of notifiers?
254 static inline constexpr quintptr DelayedNotificationBit = 0x2;
255
256 bool hasBinding() const { return d_ptr & BindingBit; }
257 bool isNotificationDelayed() const { return d_ptr & DelayedNotificationBit; }
258
259 QUntypedPropertyBinding setBinding(const QUntypedPropertyBinding &newBinding,
260 QUntypedPropertyData *propertyDataPtr,
261 QPropertyObserverCallback staticObserverCallback = nullptr,
262 QPropertyBindingWrapper bindingWrapper = nullptr);
263
265 {
266 quintptr dd = d();
267 if (dd & BindingBit)
268 return reinterpret_cast<QPropertyBindingPrivate*>(dd - BindingBit);
269 return nullptr;
270
271 }
272
273 void evaluateIfDirty(const QUntypedPropertyData *) const; // ### Kept for BC reasons, unused
274
276 {
277 if (hasBinding())
278 removeBinding_helper();
279 }
280
282 {
283 if (!currentBinding)
284 return;
285 registerWithCurrentlyEvaluatingBinding_helper(currentBinding);
286 }
287 void registerWithCurrentlyEvaluatingBinding() const;
288 void notifyObservers(QUntypedPropertyData *propertyDataPtr) const;
289 void notifyObservers(QUntypedPropertyData *propertyDataPtr, QBindingStorage *storage) const;
290private:
302 quintptr &d_ref() const
303 {
304 quintptr &d = d_ptr;
305 if (isNotificationDelayed())
306 return proxyData()->d_ptr;
307 return d;
308 }
309 quintptr d() const { return d_ref(); }
310 QPropertyProxyBindingData *proxyData() const
311 {
312 Q_ASSERT(isNotificationDelayed());
313 return reinterpret_cast<QPropertyProxyBindingData *>(d_ptr & ~(BindingBit|DelayedNotificationBit));
314 }
315 void registerWithCurrentlyEvaluatingBinding_helper(BindingEvaluationState *currentBinding) const;
316 void removeBinding_helper();
317
318 enum NotificationResult { Delayed, Evaluated };
319 NotificationResult notifyObserver_helper(
322 PendingBindingObserverList &bindingObservers) const;
323};
324
325template <typename T, typename Tag>
327{
328public:
329 constexpr QTagPreservingPointerToPointer() = default;
330
332 : d(reinterpret_cast<quintptr*>(ptr))
333 {}
334
336 {
337 d = reinterpret_cast<quintptr *>(ptr);
338 return *this;
339 }
340
342 {
343 d = reinterpret_cast<quintptr *>(ptr);
344 return *this;
345 }
346
347 void clear()
348 {
349 d = nullptr;
350 }
351
353 {
354 *d = reinterpret_cast<quintptr>(ptr) | (*d & QTaggedPointer<T, Tag>::tagMask());
355 }
356
357 T *get() const
358 {
359 return reinterpret_cast<T*>(*d & QTaggedPointer<T, Tag>::pointerMask());
360 }
361
362 explicit operator bool() const
363 {
364 return d != nullptr;
365 }
366
367private:
368 quintptr *d = nullptr;
369};
370
371namespace detail {
372 template <typename F>
374
375 template<typename T, typename C>
376 struct ExtractClassFromFunctionPointer<T C::*> { using Class = C; };
377
378 constexpr size_t getOffset(size_t o)
379 {
380 return o;
381 }
382 constexpr size_t getOffset(size_t (*offsetFn)())
383 {
384 return offsetFn();
385 }
386}
387
388} // namespace QtPrivate
389
391
392#endif // QPROPERTYPRIVATE_H
\inmodule QtCore
Definition qmetatype.h:320
\macro Q_OBJECT_BINDABLE_PROPERTY(containingClass, type, name, signal)
void swap(QPropertyBindingPrivatePtr &other) noexcept
QPropertyBindingPrivatePtr & operator=(T *o) noexcept
QtPrivate::RefCounted T
T * operator->() const noexcept
friend bool operator==(std::nullptr_t, const QPropertyBindingPrivatePtr &p2) noexcept
friend bool operator==(const T *ptr, const QPropertyBindingPrivatePtr &p2) noexcept
friend bool operator==(const QPropertyBindingPrivatePtr &p1, std::nullptr_t) noexcept
T * get() const noexcept
friend bool operator!=(const QPropertyBindingPrivatePtr &p1, const T *ptr) noexcept
Q_CORE_EXPORT void destroyAndFreeMemory()
Definition qproperty.cpp:21
QPropertyBindingPrivatePtr(QPropertyBindingPrivatePtr &&o) noexcept
friend bool operator==(const QPropertyBindingPrivatePtr &p1, const QPropertyBindingPrivatePtr &p2) noexcept
friend bool operator!=(std::nullptr_t, const QPropertyBindingPrivatePtr &p2) noexcept
friend bool operator==(const QPropertyBindingPrivatePtr &p1, const T *ptr) noexcept
bool operator!() const noexcept
QPropertyBindingPrivatePtr(const QPropertyBindingPrivatePtr &o) noexcept
T * data() const noexcept
const T * constData() const noexcept
friend bool operator!=(const QPropertyBindingPrivatePtr &p1, const QPropertyBindingPrivatePtr &p2) noexcept
friend bool operator!=(const QPropertyBindingPrivatePtr &p1, std::nullptr_t) noexcept
QPropertyBindingPrivatePtr(T *data) noexcept
friend bool operator!=(const T *ptr, const QPropertyBindingPrivatePtr &p2) noexcept
\inmodule QtCore
Definition qproperty.h:69
parameter_type valueBypassingBindings() const
Returns the data stored in this property.
Definition qproperty.h:88
void setValueBypassingBindings(parameter_type v)
Sets the data value stored in this property to v.
Definition qproperty.h:89
static constexpr quintptr pointerMask()
void registerWithCurrentlyEvaluatingBinding(QtPrivate::BindingEvaluationState *currentBinding) const
QPropertyBindingPrivate * binding() const
QPropertyBindingData & operator=(QPropertyBindingData &&other)=delete
QTagPreservingPointerToPointer< T, Tag > & operator=(T **ptr)
QTagPreservingPointerToPointer< T, Tag > & operator=(QTaggedPointer< T, Tag > *ptr)
constexpr QTagPreservingPointerToPointer()=default
QPixmap p2
QPixmap p1
[0]
quint64 getOffset(const unsigned char *&s, const ElfData &context)
Definition elfreader.cpp:56
Combined button and popup list for selecting options.
\macro QT_NAMESPACE
bool(*)(QMetaType, QUntypedPropertyData *dataPtr, QPropertyBindingFunction) QPropertyBindingWrapper
constexpr BindingFunctionVTable bindingFunctionVTable
std::conditional_t< FunctionPointer< std::decay_t< Func > >::ArgumentCount==-1, ZeroArgFunctor< std::decay_t< Func > >, FunctionPointer< std::decay_t< Func > > > Callable
void(*)(QUntypedPropertyData *) QPropertyObserverCallback
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
static ControlElement< T > * ptr(QWidget *widget)
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat f
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint ref
GLboolean reset
GLenum const void * addr
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
constexpr void qt_ptr_swap(T *&lhs, T *&rhs) noexcept
Definition qswap.h:43
#define Q_UNUSED(x)
size_t quintptr
Definition qtypes.h:72
ptrdiff_t qsizetype
Definition qtypes.h:70
QStorageInfo storage
[1]
QSharedPointer< T > other(t)
[5]
QUntypedPropertyData * propertyData
const QtPrivate::QPropertyBindingData * originalBindingData
bool(*)(QMetaType, QUntypedPropertyData *, void *) CallFn
static constexpr BindingFunctionVTable createFor()
void(*)(void *, void *) MoveCtrFn
const QtPrivate::BindingFunctionVTable * vtable