1/****************************************************************************
2**
3** Copyright (C) 2020 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QPROPERTYPRIVATE_H
41#define QPROPERTYPRIVATE_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists for the convenience
48// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
49// file may change from version to version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtCore/qglobal.h>
55#include <QtCore/QExplicitlySharedDataPointer>
56#include <QtCore/qtaggedpointer.h>
57#include <QtCore/qmetatype.h>
58
59#include <functional>
60
61QT_BEGIN_NAMESPACE
62
63class QUntypedPropertyBinding;
64class QPropertyBindingPrivate;
65using QPropertyBindingPrivatePtr = QExplicitlySharedDataPointer<QPropertyBindingPrivate>;
66struct QPropertyBindingDataPointer;
67
68class QUntypedPropertyData
69{
70public:
71 // sentinel to check whether a class inherits QUntypedPropertyData
72 struct InheritsQUntypedPropertyData {};
73};
74
75namespace QtPrivate {
76
77// writes binding result into dataPtr
78using QPropertyBindingFunction = std::function<bool(QMetaType metaType, QUntypedPropertyData *dataPtr)>;
79using QPropertyObserverCallback = void (*)(QUntypedPropertyData *);
80using QPropertyBindingWrapper = bool(*)(QMetaType, QUntypedPropertyData *dataPtr, const QPropertyBindingFunction &);
81
82class Q_CORE_EXPORT QPropertyBindingData
83{
84 // Mutable because the address of the observer of the currently evaluating binding is stored here, for
85 // notification later when the value changes.
86 mutable quintptr d_ptr = 0;
87 friend struct QT_PREPEND_NAMESPACE(QPropertyBindingDataPointer);
88 Q_DISABLE_COPY(QPropertyBindingData)
89public:
90 QPropertyBindingData() = default;
91 QPropertyBindingData(QPropertyBindingData &&other);
92 QPropertyBindingData &operator=(QPropertyBindingData &&other) = delete;
93 ~QPropertyBindingData();
94
95 bool hasBinding() const { return d_ptr & BindingBit; }
96
97 QUntypedPropertyBinding setBinding(const QUntypedPropertyBinding &newBinding,
98 QUntypedPropertyData *propertyDataPtr,
99 QPropertyObserverCallback staticObserverCallback = nullptr,
100 QPropertyBindingWrapper bindingWrapper = nullptr);
101
102 QPropertyBindingPrivate *binding() const;
103
104 void evaluateIfDirty(const QUntypedPropertyData *property) const;
105 void removeBinding();
106
107 void registerWithCurrentlyEvaluatingBinding() const;
108 void notifyObservers(QUntypedPropertyData *propertyDataPtr) const;
109
110 void setExtraBit(bool b)
111 {
112 if (b)
113 d_ptr |= ExtraBit;
114 else
115 d_ptr &= ~ExtraBit;
116 }
117
118 bool extraBit() const { return d_ptr & ExtraBit; }
119
120 static const quintptr ExtraBit = 0x1; // Used for QProperty<bool> specialization
121 static const quintptr BindingBit = 0x2; // Is d_ptr pointing to a binding (1) or list of notifiers (0)?
122 static const quintptr FlagMask = BindingBit | ExtraBit;
123};
124
125template <typename T, typename Tag>
126class QTagPreservingPointerToPointer
127{
128public:
129 constexpr QTagPreservingPointerToPointer() = default;
130
131 QTagPreservingPointerToPointer(T **ptr)
132 : d(reinterpret_cast<quintptr*>(ptr))
133 {}
134
135 QTagPreservingPointerToPointer<T, Tag> &operator=(T **ptr)
136 {
137 d = reinterpret_cast<quintptr *>(ptr);
138 return *this;
139 }
140
141 QTagPreservingPointerToPointer<T, Tag> &operator=(QTaggedPointer<T, Tag> *ptr)
142 {
143 d = reinterpret_cast<quintptr *>(ptr);
144 return *this;
145 }
146
147 void clear()
148 {
149 d = nullptr;
150 }
151
152 void setPointer(T *ptr)
153 {
154 *d = (reinterpret_cast<quintptr>(ptr) & QTaggedPointer<T, Tag>::pointerMask()) | (*d & QTaggedPointer<T, Tag>::tagMask());
155 }
156
157 T *get() const
158 {
159 return reinterpret_cast<T*>(*d & QTaggedPointer<T, Tag>::pointerMask());
160 }
161
162 explicit operator bool() const
163 {
164 return d != nullptr;
165 }
166
167private:
168 quintptr *d = nullptr;
169};
170
171namespace detail {
172 template <typename F>
173 struct ExtractClassFromFunctionPointer;
174
175 template<typename T, typename C>
176 struct ExtractClassFromFunctionPointer<T C::*> { using Class = C; };
177
178 constexpr size_t getOffset(size_t o)
179 {
180 return o;
181 }
182 constexpr size_t getOffset(size_t (*offsetFn)())
183 {
184 return offsetFn();
185 }
186}
187
188} // namespace QtPrivate
189
190QT_END_NAMESPACE
191
192#endif // QPROPERTYPRIVATE_H
193