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 #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 & 0xFFFF0000) {
98 int coreIndex = index & 0x0000FFFF;
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 & 0xFFFF0000) {
146 // Find the value type binding
147 QQmlAbstractBinding *vtbinding = data->bindings;
148 while (vtbinding->propertyIndex() != (index & 0x0000FFFF)) {
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>");