1 | // Copyright (C) 2016 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 QQMLABSTRACTBINDING_P_H |
5 | #define QQMLABSTRACTBINDING_P_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/qsharedpointer.h> |
19 | #include <QtCore/qshareddata.h> |
20 | #include <private/qtqmlglobal_p.h> |
21 | #include <private/qqmlproperty_p.h> |
22 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | class QQmlObjectCreator; |
26 | class QQmlAnyBinding; |
27 | |
28 | class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding |
29 | { |
30 | friend class QQmlAnyBinding; |
31 | protected: |
32 | QQmlAbstractBinding(); |
33 | public: |
34 | enum Kind { |
35 | ValueTypeProxy, |
36 | QmlBinding, |
37 | PropertyToPropertyBinding, |
38 | }; |
39 | |
40 | virtual ~QQmlAbstractBinding(); |
41 | |
42 | typedef QExplicitlySharedDataPointer<QQmlAbstractBinding> Ptr; |
43 | |
44 | virtual QString expression() const; |
45 | |
46 | virtual Kind kind() const = 0; |
47 | |
48 | // Should return the encoded property index for the binding. Should return this value |
49 | // even if the binding is not enabled or added to an object. |
50 | // Encoding is: coreIndex | (valueTypeIndex << 16) |
51 | QQmlPropertyIndex targetPropertyIndex() const { return m_targetIndex; } |
52 | |
53 | // Should return the object for the binding. Should return this object even if the |
54 | // binding is not enabled or added to the object. |
55 | QObject *targetObject() const { return m_target.data(); } |
56 | |
57 | void setTarget(const QQmlProperty &); |
58 | bool setTarget(QObject *, const QQmlPropertyData &, const QQmlPropertyData *valueType); |
59 | bool setTarget(QObject *, int coreIndex, bool coreIsAlias, int valueTypeIndex); |
60 | |
61 | virtual void setEnabled(bool e, QQmlPropertyData::WriteFlags f = QQmlPropertyData::DontRemoveBinding) = 0; |
62 | |
63 | void addToObject(); |
64 | void removeFromObject(); |
65 | |
66 | static void printBindingLoopError(const QQmlProperty &prop); |
67 | |
68 | inline QQmlAbstractBinding *nextBinding() const; |
69 | |
70 | inline bool canUseAccessor() const |
71 | { return m_nextBinding.tag().testFlag(flag: CanUseAccessor); } |
72 | void setCanUseAccessor(bool canUseAccessor) |
73 | { m_nextBinding.setTag(m_nextBinding.tag().setFlag(flag: CanUseAccessor, on: canUseAccessor)); } |
74 | |
75 | struct RefCount { |
76 | RefCount() {} |
77 | int refCount = 0; |
78 | void ref() { ++refCount; } |
79 | int deref() { return --refCount; } |
80 | operator int() const { return refCount; } |
81 | }; |
82 | RefCount ref; |
83 | |
84 | enum TargetTag { |
85 | NoTargetTag = 0x0, |
86 | UpdatingBinding = 0x1, |
87 | BindingEnabled = 0x2 |
88 | }; |
89 | Q_DECLARE_FLAGS(TargetTags, TargetTag) |
90 | |
91 | enum NextBindingTag { |
92 | NoBindingTag = 0x0, |
93 | AddedToObject = 0x1, |
94 | CanUseAccessor = 0x2 |
95 | }; |
96 | Q_DECLARE_FLAGS(NextBindingTags, NextBindingTag) |
97 | |
98 | protected: |
99 | friend class QQmlData; |
100 | friend class QQmlValueTypeProxyBinding; |
101 | friend class QQmlObjectCreator; |
102 | |
103 | inline void setAddedToObject(bool v); |
104 | inline bool isAddedToObject() const; |
105 | |
106 | inline void setNextBinding(QQmlAbstractBinding *); |
107 | |
108 | void getPropertyData( |
109 | const QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const; |
110 | |
111 | inline bool updatingFlag() const; |
112 | inline void setUpdatingFlag(bool); |
113 | inline bool enabledFlag() const; |
114 | inline void setEnabledFlag(bool); |
115 | void updateCanUseAccessor(); |
116 | |
117 | QQmlPropertyIndex m_targetIndex; |
118 | |
119 | // Pointer is the target object to which the binding binds |
120 | QTaggedPointer<QObject, TargetTags> m_target; |
121 | |
122 | // Pointer to the next binding in the linked list of bindings. |
123 | QTaggedPointer<QQmlAbstractBinding, NextBindingTags> m_nextBinding; |
124 | }; |
125 | |
126 | Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlAbstractBinding::TargetTags) |
127 | Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlAbstractBinding::NextBindingTags) |
128 | |
129 | void QQmlAbstractBinding::setAddedToObject(bool v) |
130 | { |
131 | m_nextBinding.setTag(m_nextBinding.tag().setFlag(flag: AddedToObject, on: v)); |
132 | } |
133 | |
134 | bool QQmlAbstractBinding::isAddedToObject() const |
135 | { |
136 | return m_nextBinding.tag().testFlag(flag: AddedToObject); |
137 | } |
138 | |
139 | QQmlAbstractBinding *QQmlAbstractBinding::nextBinding() const |
140 | { |
141 | return m_nextBinding.data(); |
142 | } |
143 | |
144 | void QQmlAbstractBinding::setNextBinding(QQmlAbstractBinding *b) |
145 | { |
146 | if (b) |
147 | b->ref.ref(); |
148 | if (m_nextBinding.data() && !m_nextBinding->ref.deref()) |
149 | delete m_nextBinding.data(); |
150 | m_nextBinding = b; |
151 | } |
152 | |
153 | bool QQmlAbstractBinding::updatingFlag() const |
154 | { |
155 | return m_target.tag().testFlag(flag: UpdatingBinding); |
156 | } |
157 | |
158 | void QQmlAbstractBinding::setUpdatingFlag(bool v) |
159 | { |
160 | m_target.setTag(m_target.tag().setFlag(flag: UpdatingBinding, on: v)); |
161 | } |
162 | |
163 | bool QQmlAbstractBinding::enabledFlag() const |
164 | { |
165 | return m_target.tag().testFlag(flag: BindingEnabled); |
166 | } |
167 | |
168 | void QQmlAbstractBinding::setEnabledFlag(bool v) |
169 | { |
170 | m_target.setTag(m_target.tag().setFlag(flag: BindingEnabled, on: v)); |
171 | } |
172 | |
173 | QT_END_NAMESPACE |
174 | |
175 | #endif // QQMLABSTRACTBINDING_P_H |
176 | |