1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
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>;
153 typedef QSharedPointer<QQmlAbstractBinding> SharedPointer;
154 // To save memory, we also store the rarely used weakPointer() instance in here
155 // We also use the flag bits:
156 // m_mePtr.flag1: added to object
157 QPointerValuePair<QQmlAbstractBinding*, SharedPointer> m_mePtr;
159 inline void setAddedToObject(bool v);
160 inline bool isAddedToObject() const;
162 inline QQmlAbstractBinding *nextBinding() const;
163 inline void setNextBinding(QQmlAbstractBinding *);
165 // Pointer to the next binding in the linked list of bindings.
166 // Being a pointer, the address is always aligned to at least 4 bytes, which means the last two
167 // bits of the pointer are free to be used for something else. They are used to store the binding
168 // type. The binding type serves as an index into the static vTables array, which is used instead
169 // of a compiler-generated vTable. Instead of virtual functions, pointers to static functions in
170 // the vTables array are used for dispatching.
171 // This saves a compiler-generated pointer to a compiler-generated vTable, and thus reduces
172 // the binding object size by sizeof(void*).
173 uintptr_t m_nextBindingPtr;
175 static VTable *vTables[];
176 inline const VTable *vtable() const { return vTables[bindingType()]; }
179 QQmlAbstractBinding::Pointer
180 QQmlAbstractBinding::getPointer(QQmlAbstractBinding *p)
182 return p ? p->weakPointer() : Pointer();
185 void QQmlAbstractBinding::setAddedToObject(bool v)
187 m_mePtr.setFlagValue(v);
190 bool QQmlAbstractBinding::isAddedToObject() const
192 return m_mePtr.flag();
195 QQmlAbstractBinding *QQmlAbstractBinding::nextBinding() const
197 return (QQmlAbstractBinding *)(m_nextBindingPtr & ~0x3);
200 void QQmlAbstractBinding::setNextBinding(QQmlAbstractBinding *b)
202 m_nextBindingPtr = uintptr_t(b) | (m_nextBindingPtr & 0x3);
205 QQmlAbstractBinding::BindingType QQmlAbstractBinding::bindingType() const
207 return (BindingType)(m_nextBindingPtr & 0x3);
211 void QQmlAbstractBinding::default_destroy(QQmlAbstractBinding *This, DestroyMode mode)
213 // Assume the binding disconnects itself in the destructor, which for example QQmlBinding
214 // does in the destructor of its base class, QQmlJavaScriptExpression
217 This->removeFromObject();
219 delete static_cast<T *>(This);
224 #endif // QQMLABSTRACTBINDING_P_H