Docs - add missing images and code, clean up sections
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlabstractbinding.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qqmlabstractbinding_p.h"
43
44 #include <QtQml/qqmlinfo.h>
45 #include <private/qqmlbinding_p.h>
46 #include <private/qqmlvaluetypeproxybinding_p.h>
47
48 QT_BEGIN_NAMESPACE
49
50 extern QQmlAbstractBinding::VTable QQmlBinding_vtable;
51 extern QQmlAbstractBinding::VTable QQmlValueTypeProxyBinding_vtable;
52 extern QQmlAbstractBinding::VTable QV4Bindings_Binding_vtable;
53 extern QQmlAbstractBinding::VTable QV8Bindings_Binding_vtable;
54
55 QQmlAbstractBinding::VTable *QQmlAbstractBinding::vTables[] = {
56     &QQmlBinding_vtable,
57     &QV4Bindings_Binding_vtable,
58     &QV8Bindings_Binding_vtable,
59     &QQmlValueTypeProxyBinding_vtable
60 };
61
62 QQmlAbstractBinding::QQmlAbstractBinding(BindingType bt)
63 : m_nextBindingPtr(bt)
64 {
65     Q_ASSERT(bt <= 0x03);
66 }
67
68 QQmlAbstractBinding::~QQmlAbstractBinding()
69 {
70     Q_ASSERT(isAddedToObject() == false);
71     Q_ASSERT(nextBinding() == 0);
72     Q_ASSERT(*m_mePtr == 0);
73 }
74
75 /*!
76 Add this binding to \a object.
77
78 This transfers ownership of the binding to the object, marks the object's property as
79 being bound.
80
81 However, it does not enable the binding itself or call update() on it.
82 */
83 void QQmlAbstractBinding::addToObject()
84 {
85     Q_ASSERT(!nextBinding());
86     Q_ASSERT(isAddedToObject() == false);
87
88     QObject *obj = object();
89     Q_ASSERT(obj);
90
91     int index = propertyIndex();
92
93     QQmlData *data = QQmlData::get(obj, true);
94
95     if (index & 0xFFFF0000) {
96         // Value type
97
98         int coreIndex = index & 0x0000FFFF;
99
100         // Find the value type proxy (if there is one)
101         QQmlValueTypeProxyBinding *proxy = 0;
102         if (data->hasBindingBit(coreIndex)) {
103             QQmlAbstractBinding *b = data->bindings;
104             while (b && b->propertyIndex() != coreIndex)
105                 b = b->nextBinding();
106             Q_ASSERT(b && b->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
107             proxy = static_cast<QQmlValueTypeProxyBinding *>(b);
108         }
109
110         if (!proxy) {
111             proxy = new QQmlValueTypeProxyBinding(obj, coreIndex);
112
113             Q_ASSERT(proxy->propertyIndex() == coreIndex);
114             Q_ASSERT(proxy->object() == obj);
115
116             proxy->addToObject();
117         }
118
119         setNextBinding(proxy->m_bindings);
120         proxy->m_bindings = this;
121
122     } else {
123         setNextBinding(data->bindings);
124         data->bindings = this;
125
126         data->setBindingBit(obj, index);
127     }
128
129     setAddedToObject(true);
130 }
131
132 /*!
133 Remove the binding from the object.
134 */
135 void QQmlAbstractBinding::removeFromObject()
136 {
137     if (isAddedToObject()) {
138         QObject *obj = object();
139         int index = propertyIndex();
140
141         QQmlData *data = QQmlData::get(obj, false);
142         Q_ASSERT(data);
143
144         if (index & 0xFFFF0000) {
145
146             // Find the value type binding
147             QQmlAbstractBinding *vtbinding = data->bindings;
148             while (vtbinding->propertyIndex() != (index & 0x0000FFFF)) {
149                 vtbinding = vtbinding->nextBinding();
150                 Q_ASSERT(vtbinding);
151             }
152             Q_ASSERT(vtbinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
153
154             QQmlValueTypeProxyBinding *vtproxybinding =
155                 static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
156
157             QQmlAbstractBinding *binding = vtproxybinding->m_bindings;
158             if (binding == this) {
159                 vtproxybinding->m_bindings = nextBinding();
160             } else {
161                while (binding->nextBinding() != this) {
162                   binding = binding->nextBinding();
163                   Q_ASSERT(binding);
164                }
165                binding->setNextBinding(nextBinding());
166             }
167
168             // Value type - we don't remove the proxy from the object.  It will sit their happily
169             // doing nothing until it is removed by a write, a binding change or it is reused
170             // to hold more sub-bindings.
171
172         } else {
173
174             if (data->bindings == this) {
175                 data->bindings = nextBinding();
176             } else {
177                 QQmlAbstractBinding *binding = data->bindings;
178                 while (binding->nextBinding() != this) {
179                     binding = binding->nextBinding();
180                     Q_ASSERT(binding);
181                 }
182                 binding->setNextBinding(nextBinding());
183             }
184
185             data->clearBindingBit(index);
186         }
187
188         setNextBinding(0);
189         setAddedToObject(false);
190     }
191 }
192
193 void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
194 {
195     qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
196 }
197
198
199 static void bindingDummyDeleter(QQmlAbstractBinding *)
200 {
201 }
202
203 QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer()
204 {
205     if (m_mePtr.value().isNull())
206         m_mePtr.value() = QSharedPointer<QQmlAbstractBinding>(this, bindingDummyDeleter);
207
208     return m_mePtr.value().toWeakRef();
209 }
210
211 void QQmlAbstractBinding::clear()
212 {
213     if (!m_mePtr.isNull()) {
214         **m_mePtr = 0;
215         m_mePtr = 0;
216     }
217 }
218
219 void QQmlAbstractBinding::default_retargetBinding(QQmlAbstractBinding *, QObject *, int)
220 {
221     qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding.");
222 }
223
224 QString QQmlAbstractBinding::default_expression(const QQmlAbstractBinding *)
225 {
226     return QLatin1String("<Unknown>");
227 }
228
229 QT_END_NAMESPACE