1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #ifndef QQMLABSTRACTBINDING_P_H
43 #define QQMLABSTRACTBINDING_P_H
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
56 #include <QtCore/qsharedpointer.h>
57 #include <private/qtqmlglobal_p.h>
58 #include <private/qqmlproperty_p.h>
59 #include <private/qpointervaluepair_p.h>
63 class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding
68 // The binding should disconnect itself upon destroy
71 // The binding doesn't need to disconnect itself, but it can if it wants to.
73 // This is used in QQmlData::destroyed() - at the point at which the bindings are
74 // destroyed, the notifiers are already disconnected, so no need to disconnect each
77 // Bindings can use this flag to speed up destruction, especially for v4 bindings
78 // disconnecting a single binding might be slow.
83 void (*destroy)(QQmlAbstractBinding *, DestroyMode destroyMode);
84 QString (*expression)(const QQmlAbstractBinding *);
85 int (*propertyIndex)(const QQmlAbstractBinding *);
86 QObject *(*object)(const QQmlAbstractBinding *);
87 void (*setEnabled)(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags);
88 void (*update)(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags);
89 void (*retargetBinding)(QQmlAbstractBinding *, QObject *, int);
92 typedef QWeakPointer<QQmlAbstractBinding> Pointer;
94 enum BindingType { Binding = 0, V4 = 1, V8 = 2, ValueTypeProxy = 3 };
95 inline BindingType bindingType() const;
97 // Destroy the binding. Use this instead of calling delete.
98 // Bindings are free to implement their own memory management, so the delete operator is
99 // not necessarily safe. The default implementation clears the binding, removes it from
100 // the object and calls delete.
101 void destroy(DestroyMode destroyMode = DisconnectBinding)
102 { vtable()->destroy(this, destroyMode); }
104 QString expression() const { return vtable()->expression(this); }
106 // Should return the encoded property index for the binding. Should return this value
107 // even if the binding is not enabled or added to an object.
108 // Encoding is: coreIndex | (valueTypeIndex << 16)
109 int propertyIndex() const { return vtable()->propertyIndex(this); }
111 // Should return the object for the binding. Should return this object even if the
112 // binding is not enabled or added to the object.
113 QObject *object() const { return vtable()->object(this); }
115 void setEnabled(bool e) { setEnabled(e, QQmlPropertyPrivate::DontRemoveBinding); }
116 void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f) { vtable()->setEnabled(this, e, f); }
118 void update() { update(QQmlPropertyPrivate::DontRemoveBinding); }
119 void update(QQmlPropertyPrivate::WriteFlags f) { vtable()->update(this, f); }
122 void removeFromObject();
124 static inline Pointer getPointer(QQmlAbstractBinding *p);
125 static void printBindingLoopError(QQmlProperty &prop);
127 // Default implementation for some VTable functions
129 static void default_destroy(QQmlAbstractBinding *, DestroyMode);
130 static QString default_expression(const QQmlAbstractBinding *);
131 static void default_retargetBinding(QQmlAbstractBinding *, QObject *, int);
134 QQmlAbstractBinding(BindingType);
135 ~QQmlAbstractBinding();
138 // Called by QQmlPropertyPrivate to "move" a binding to a different property.
139 // This is only used for alias properties. The default implementation qFatal()'s
140 // to ensure that the method is never called for binding types that don't support it.
141 void retargetBinding(QObject *o, int i) { vtable()->retargetBinding(this, o, i); }
144 Pointer weakPointer();
146 friend class QQmlData;
147 friend class QQmlComponentPrivate;
148 friend class QQmlValueTypeProxyBinding;
149 friend class QQmlPropertyPrivate;
150 friend class QQmlVME;
151 friend class QtSharedPointer::ExternalRefCount<QQmlAbstractBinding>;
152 friend class QV8QObjectWrapper;
153 friend class QV4Bindings;
155 typedef QSharedPointer<QQmlAbstractBinding> SharedPointer;
156 // To save memory, we also store the rarely used weakPointer() instance in here
157 // We also use the flag bits:
158 // m_mePtr.flag1: added to object
159 QPointerValuePair<QQmlAbstractBinding*, SharedPointer> m_mePtr;
161 inline void setAddedToObject(bool v);
162 inline bool isAddedToObject() const;
164 inline QQmlAbstractBinding *nextBinding() const;
165 inline void setNextBinding(QQmlAbstractBinding *);
167 // Pointer to the next binding in the linked list of bindings.
168 // Being a pointer, the address is always aligned to at least 4 bytes, which means the last two
169 // bits of the pointer are free to be used for something else. They are used to store the binding
170 // type. The binding type serves as an index into the static vTables array, which is used instead
171 // of a compiler-generated vTable. Instead of virtual functions, pointers to static functions in
172 // the vTables array are used for dispatching.
173 // This saves a compiler-generated pointer to a compiler-generated vTable, and thus reduces
174 // the binding object size by sizeof(void*).
175 uintptr_t m_nextBindingPtr;
177 static VTable *vTables[];
178 inline const VTable *vtable() const { return vTables[bindingType()]; }
181 QQmlAbstractBinding::Pointer
182 QQmlAbstractBinding::getPointer(QQmlAbstractBinding *p)
184 return p ? p->weakPointer() : Pointer();
187 void QQmlAbstractBinding::setAddedToObject(bool v)
189 m_mePtr.setFlagValue(v);
192 bool QQmlAbstractBinding::isAddedToObject() const
194 return m_mePtr.flag();
197 QQmlAbstractBinding *QQmlAbstractBinding::nextBinding() const
199 return (QQmlAbstractBinding *)(m_nextBindingPtr & ~0x3);
202 void QQmlAbstractBinding::setNextBinding(QQmlAbstractBinding *b)
204 m_nextBindingPtr = uintptr_t(b) | (m_nextBindingPtr & 0x3);
207 QQmlAbstractBinding::BindingType QQmlAbstractBinding::bindingType() const
209 return (BindingType)(m_nextBindingPtr & 0x3);
213 void QQmlAbstractBinding::default_destroy(QQmlAbstractBinding *This, DestroyMode mode)
215 // Assume the binding disconnects itself in the destructor, which for example QQmlBinding
216 // does in the destructor of its base class, QQmlJavaScriptExpression
219 This->removeFromObject();
221 delete static_cast<T *>(This);
226 #endif // QQMLABSTRACTBINDING_P_H