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 "qquickbind_p.h"
44 #include <private/qqmlnullablevalue_p_p.h>
45 #include <private/qqmlproperty_p.h>
46 #include <private/qqmlbinding_p.h>
47 #include <private/qqmlguard_p.h>
49 #include <qqmlengine.h>
50 #include <qqmlcontext.h>
51 #include <qqmlproperty.h>
54 #include <QtCore/qfile.h>
55 #include <QtCore/qdebug.h>
57 #include <private/qobject_p.h>
61 class QQuickBindPrivate : public QObjectPrivate
64 QQuickBindPrivate() : componentComplete(true), obj(0), prevBind(0) {}
65 ~QQuickBindPrivate() { if (prevBind) prevBind->destroy(); }
67 QQmlNullableValue<bool> when;
68 bool componentComplete;
69 QQmlGuard<QObject> obj;
71 QQmlNullableValue<QVariant> value;
73 QQmlAbstractBinding *prevBind;
78 \qmlclass Binding QQuickBind
79 \inqmlmodule QtQuick 2
80 \ingroup qml-working-with-data
81 \brief The Binding element allows arbitrary property bindings to be created.
83 \section1 Binding to an inaccessible property
85 Sometimes it is necessary to bind to a property of an object that wasn't
86 directly instantiated by QML - generally a property of a class exported
87 to QML by C++. In these cases, regular property binding doesn't work. Binding
88 allows you to bind any value to any property.
90 For example, imagine a C++ application that maps an "app.enteredText"
91 property into QML. You could use Binding to update the enteredText property
94 TextEdit { id: myTextField; text: "Please type here..." }
95 Binding { target: app; property: "enteredText"; value: myTextField.text }
97 Whenever the text in the TextEdit is updated, the C++ property will be
100 \section1 "Single-branch" conditional binding
102 In some circumstances you may want to control the value of a property
103 only when a certain condition is true (and relinquish control in all
104 other cirumstances). This often isn't possible to accomplish with a direct
105 binding, as you need to supply values for all possible branches.
108 // warning: "Unable to assign [undefined] to double value"
109 value: if (mouse.pressed) mouse.mouseX
112 The above example will produce a warning whenever we release the mouse, as the value
113 of the binding is undefined when the mouse isn't pressed. We can use the Binding
114 element to rewrite the above code and avoid the warning.
123 The Binding element will also restore any previously set direct bindings on
124 the property. In that sense, it functions much like a simplified State.
127 // this is equivilant to the above Binding
138 If the binding target or binding property is changed, the bound value is
139 immediately pushed onto the new target.
143 QQuickBind::QQuickBind(QObject *parent)
144 : QObject(*(new QQuickBindPrivate), parent)
148 QQuickBind::~QQuickBind()
153 \qmlproperty bool QtQuick2::Binding::when
155 This property holds when the binding is active.
156 This should be set to an expression that evaluates to true when you want the binding to be active.
160 target: contactName; property: 'text'
161 value: name; when: list.ListView.isCurrentItem
165 When the binding becomes inactive again, any direct bindings that were previously
166 set on the property will be restored.
168 bool QQuickBind::when() const
170 Q_D(const QQuickBind);
174 void QQuickBind::setWhen(bool v)
177 if (!d->when.isNull && d->when == v)
185 \qmlproperty Object QtQuick2::Binding::target
187 The object to be updated.
189 QObject *QQuickBind::object()
191 Q_D(const QQuickBind);
195 void QQuickBind::setObject(QObject *obj)
198 if (d->obj && d->when.isValid() && d->when) {
199 /* if we switch the object at runtime, we need to restore the
200 previous binding on the old object before continuing */
206 if (d->componentComplete)
207 d->prop = QQmlProperty(d->obj, d->propName);
212 \qmlproperty string QtQuick2::Binding::property
214 The property to be updated.
216 QString QQuickBind::property() const
218 Q_D(const QQuickBind);
222 void QQuickBind::setProperty(const QString &p)
225 if (!d->propName.isEmpty() && d->when.isValid() && d->when) {
226 /* if we switch the property name at runtime, we need to restore the
227 previous binding on the old object before continuing */
233 if (d->componentComplete)
234 d->prop = QQmlProperty(d->obj, d->propName);
239 \qmlproperty any QtQuick2::Binding::value
241 The value to be set on the target object and property. This can be a
242 constant (which isn't very useful), or a bound expression.
244 QVariant QQuickBind::value() const
246 Q_D(const QQuickBind);
247 return d->value.value;
250 void QQuickBind::setValue(const QVariant &v)
257 void QQuickBind::setTarget(const QQmlProperty &p)
263 void QQuickBind::classBegin()
266 d->componentComplete = false;
269 void QQuickBind::componentComplete()
272 d->componentComplete = true;
273 if (!d->prop.isValid())
274 d->prop = QQmlProperty(d->obj, d->propName);
278 void QQuickBind::eval()
281 if (!d->prop.isValid() || d->value.isNull || !d->componentComplete)
284 if (d->when.isValid()) {
286 //restore any previous binding
288 QQmlAbstractBinding *tmp = d->prevBind;
290 tmp = QQmlPropertyPrivate::setBinding(d->prop, tmp);
291 if (tmp) //should this ever be true?
297 //save any set binding for restoration
298 QQmlAbstractBinding *tmp;
299 tmp = QQmlPropertyPrivate::setBinding(d->prop, 0);
300 if (tmp && d->prevBind)
301 d->prevBind->destroy();
302 else if (!d->prevBind)
306 d->prop.write(d->value.value);