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 #include "qqmlabstractbinding_p.h"
44 #include <QtQml/qqmlinfo.h>
45 #include <private/qqmlbinding_p.h>
46 #include <private/qqmlvaluetypeproxybinding_p.h>
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;
55 QQmlAbstractBinding::VTable *QQmlAbstractBinding::vTables[] = {
57 &QV4Bindings_Binding_vtable,
58 &QV8Bindings_Binding_vtable,
59 &QQmlValueTypeProxyBinding_vtable
62 QQmlAbstractBinding::QQmlAbstractBinding(BindingType bt)
63 : m_nextBindingPtr(bt)
68 QQmlAbstractBinding::~QQmlAbstractBinding()
70 Q_ASSERT(isAddedToObject() == false);
71 Q_ASSERT(nextBinding() == 0);
72 Q_ASSERT(*m_mePtr == 0);
76 Add this binding to \a object.
78 This transfers ownership of the binding to the object, marks the object's property as
81 However, it does not enable the binding itself or call update() on it.
83 void QQmlAbstractBinding::addToObject()
85 Q_ASSERT(!nextBinding());
86 Q_ASSERT(isAddedToObject() == false);
88 QObject *obj = object();
91 int index = propertyIndex();
93 QQmlData *data = QQmlData::get(obj, true);
95 if (index & 0xFF000000) {
98 int coreIndex = index & 0xFFFFFF;
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);
111 proxy = new QQmlValueTypeProxyBinding(obj, coreIndex);
113 Q_ASSERT(proxy->propertyIndex() == coreIndex);
114 Q_ASSERT(proxy->object() == obj);
116 proxy->addToObject();
119 setNextBinding(proxy->m_bindings);
120 proxy->m_bindings = this;
123 setNextBinding(data->bindings);
124 data->bindings = this;
126 data->setBindingBit(obj, index);
129 setAddedToObject(true);
133 Remove the binding from the object.
135 void QQmlAbstractBinding::removeFromObject()
137 if (isAddedToObject()) {
138 QObject *obj = object();
139 int index = propertyIndex();
141 QQmlData *data = QQmlData::get(obj, false);
144 if (index & 0xFF000000) {
146 // Find the value type binding
147 QQmlAbstractBinding *vtbinding = data->bindings;
148 while (vtbinding->propertyIndex() != (index & 0xFFFFFF)) {
149 vtbinding = vtbinding->nextBinding();
152 Q_ASSERT(vtbinding->bindingType() == QQmlAbstractBinding::ValueTypeProxy);
154 QQmlValueTypeProxyBinding *vtproxybinding =
155 static_cast<QQmlValueTypeProxyBinding *>(vtbinding);
157 QQmlAbstractBinding *binding = vtproxybinding->m_bindings;
158 if (binding == this) {
159 vtproxybinding->m_bindings = nextBinding();
161 while (binding->nextBinding() != this) {
162 binding = binding->nextBinding();
165 binding->setNextBinding(nextBinding());
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.
174 if (data->bindings == this) {
175 data->bindings = nextBinding();
177 QQmlAbstractBinding *binding = data->bindings;
178 while (binding->nextBinding() != this) {
179 binding = binding->nextBinding();
182 binding->setNextBinding(nextBinding());
185 data->clearBindingBit(index);
189 setAddedToObject(false);
193 void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop)
195 qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name());
199 static void bindingDummyDeleter(QQmlAbstractBinding *)
203 QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer()
205 if (m_mePtr.value().isNull())
206 m_mePtr.value() = QSharedPointer<QQmlAbstractBinding>(this, bindingDummyDeleter);
208 return m_mePtr.value().toWeakRef();
211 void QQmlAbstractBinding::clear()
213 if (!m_mePtr.isNull()) {
219 void QQmlAbstractBinding::default_retargetBinding(QQmlAbstractBinding *, QObject *, int)
221 qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding.");
224 QString QQmlAbstractBinding::default_expression(const QQmlAbstractBinding *)
226 return QLatin1String("<Unknown>");