source: trunk/src/declarative/util/qdeclarativepropertychanges.cpp@ 918

Last change on this file since 918 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 27.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "private/qdeclarativepropertychanges_p.h"
43
44#include "private/qdeclarativeopenmetaobject_p.h"
45
46#include <qdeclarativeinfo.h>
47#include <qdeclarativecustomparser_p.h>
48#include <qdeclarativeparser_p.h>
49#include <qdeclarativeexpression.h>
50#include <qdeclarativebinding_p.h>
51#include <qdeclarativecontext.h>
52#include <qdeclarativeguard_p.h>
53#include <qdeclarativeproperty_p.h>
54#include <qdeclarativecontext_p.h>
55#include <qdeclarativestate_p_p.h>
56
57#include <QtCore/qdebug.h>
58
59#include <private/qobject_p.h>
60
61QT_BEGIN_NAMESPACE
62
63/*!
64 \qmlclass PropertyChanges QDeclarativePropertyChanges
65 \ingroup qml-state-elements
66 \since 4.7
67 \brief The PropertyChanges element describes new property bindings or values for a state.
68
69 PropertyChanges is used to define the property values or bindings in a
70 \l State. This enables an item's property values to be changed when it
71 \l {QML States}{changes between states}.
72
73 To create a PropertyChanges object, specify the \l target item whose
74 properties are to be modified, and define the new property values or
75 bindings. For example:
76
77 \snippet doc/src/snippets/declarative/propertychanges.qml import
78 \codeline
79 \snippet doc/src/snippets/declarative/propertychanges.qml 0
80
81 When the mouse is pressed, the \l Rectangle changes to the \e resized
82 state. In this state, the PropertyChanges object sets the rectangle's
83 color to blue and the \c height value to that of \c container.height.
84
85 Note this automatically binds \c rect.height to \c container.height
86 in the \e resized state. If a property binding should not be
87 established, and the height should just be set to the value of
88 \c container.height at the time of the state change, set the \l explicit
89 property to \c true.
90
91 A PropertyChanges object can also override the default signal handler
92 for an object to implement a signal handler specific to the new state:
93
94 \qml
95 PropertyChanges {
96 target: myMouseArea
97 onClicked: doSomethingDifferent()
98 }
99 \endqml
100
101 \note PropertyChanges can be used to change anchor margins, but not other anchor
102 values; use AnchorChanges for this instead. Similarly, to change an \l Item's
103 \l {Item::}{parent} value, use ParentChanges instead.
104
105
106 \section2 Resetting property values
107
108 The \c undefined value can be used to reset the property value for a state.
109 In the following example, when \c theText changes to the \e widerText
110 state, its \c width property is reset, giving the text its natural width
111 and displaying the whole string on a single line.
112
113 \snippet doc/src/snippets/declarative/propertychanges.qml reset
114
115
116 \section2 Immediate property changes in transitions
117
118 When \l Transitions are used to animate state changes, they animate
119 properties from their values in the current state to those defined in the
120 new state (as defined by PropertyChanges objects). However,
121 it is sometimes desirable to set a property value \e immediately during a
122 \l Transition, without animation; in these cases, the PropertyAction
123 element can be used to force an immediate property change.
124
125 See the PropertyAction documentation for more details.
126
127 \sa {declarative/animation/states}{states example}, {qmlstate}{States}, QtDeclarative
128*/
129
130/*!
131 \qmlproperty Object PropertyChanges::target
132 This property holds the object which contains the properties to be changed.
133*/
134
135class QDeclarativeReplaceSignalHandler : public QDeclarativeActionEvent
136{
137public:
138 QDeclarativeReplaceSignalHandler() : expression(0), reverseExpression(0),
139 rewindExpression(0), ownedExpression(0) {}
140 ~QDeclarativeReplaceSignalHandler() {
141 delete ownedExpression;
142 }
143
144 virtual QString typeName() const { return QLatin1String("ReplaceSignalHandler"); }
145
146 QDeclarativeProperty property;
147 QDeclarativeExpression *expression;
148 QDeclarativeExpression *reverseExpression;
149 QDeclarativeExpression *rewindExpression;
150 QDeclarativeGuard<QDeclarativeExpression> ownedExpression;
151
152 virtual void execute(Reason) {
153 ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, expression);
154 if (ownedExpression == expression)
155 ownedExpression = 0;
156 }
157
158 virtual bool isReversable() { return true; }
159 virtual void reverse(Reason) {
160 ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, reverseExpression);
161 if (ownedExpression == reverseExpression)
162 ownedExpression = 0;
163 }
164
165 virtual void saveOriginals() {
166 saveCurrentValues();
167 reverseExpression = rewindExpression;
168 }
169
170 /*virtual void copyOriginals(QDeclarativeActionEvent *other)
171 {
172 QDeclarativeReplaceSignalHandler *rsh = static_cast<QDeclarativeReplaceSignalHandler*>(other);
173 saveCurrentValues();
174 if (rsh == this)
175 return;
176 reverseExpression = rsh->reverseExpression;
177 if (rsh->ownedExpression == reverseExpression) {
178 ownedExpression = rsh->ownedExpression;
179 rsh->ownedExpression = 0;
180 }
181 }*/
182
183 virtual void rewind() {
184 ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, rewindExpression);
185 if (ownedExpression == rewindExpression)
186 ownedExpression = 0;
187 }
188 virtual void saveCurrentValues() {
189 rewindExpression = QDeclarativePropertyPrivate::signalExpression(property);
190 }
191
192 virtual bool override(QDeclarativeActionEvent*other) {
193 if (other == this)
194 return true;
195 if (other->typeName() != typeName())
196 return false;
197 if (static_cast<QDeclarativeReplaceSignalHandler*>(other)->property == property)
198 return true;
199 return false;
200 }
201};
202
203
204class QDeclarativePropertyChangesPrivate : public QDeclarativeStateOperationPrivate
205{
206 Q_DECLARE_PUBLIC(QDeclarativePropertyChanges)
207public:
208 QDeclarativePropertyChangesPrivate() : decoded(true), restore(true),
209 isExplicit(false) {}
210
211 QDeclarativeGuard<QObject> object;
212 QByteArray data;
213
214 bool decoded : 1;
215 bool restore : 1;
216 bool isExplicit : 1;
217
218 void decode();
219
220 QList<QPair<QByteArray, QVariant> > properties;
221 QList<QPair<QByteArray, QDeclarativeExpression *> > expressions;
222 QList<QDeclarativeReplaceSignalHandler*> signalReplacements;
223
224 QDeclarativeProperty property(const QByteArray &);
225};
226
227void
228QDeclarativePropertyChangesParser::compileList(QList<QPair<QByteArray, QVariant> > &list,
229 const QByteArray &pre,
230 const QDeclarativeCustomParserProperty &prop)
231{
232 QByteArray propName = pre + prop.name();
233
234 QList<QVariant> values = prop.assignedValues();
235 for (int ii = 0; ii < values.count(); ++ii) {
236 const QVariant &value = values.at(ii);
237
238 if (value.userType() == qMetaTypeId<QDeclarativeCustomParserNode>()) {
239 error(qvariant_cast<QDeclarativeCustomParserNode>(value),
240 QDeclarativePropertyChanges::tr("PropertyChanges does not support creating state-specific objects."));
241 continue;
242 } else if(value.userType() == qMetaTypeId<QDeclarativeCustomParserProperty>()) {
243
244 QDeclarativeCustomParserProperty prop =
245 qvariant_cast<QDeclarativeCustomParserProperty>(value);
246 QByteArray pre = propName + '.';
247 compileList(list, pre, prop);
248
249 } else {
250 list << qMakePair(propName, value);
251 }
252 }
253}
254
255QByteArray
256QDeclarativePropertyChangesParser::compile(const QList<QDeclarativeCustomParserProperty> &props)
257{
258 QList<QPair<QByteArray, QVariant> > data;
259 for(int ii = 0; ii < props.count(); ++ii)
260 compileList(data, QByteArray(), props.at(ii));
261
262 QByteArray rv;
263 QDataStream ds(&rv, QIODevice::WriteOnly);
264
265 ds << data.count();
266 for(int ii = 0; ii < data.count(); ++ii) {
267 QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(data.at(ii).second);
268 QVariant var;
269 bool isScript = v.isScript();
270 switch(v.type()) {
271 case QDeclarativeParser::Variant::Boolean:
272 var = QVariant(v.asBoolean());
273 break;
274 case QDeclarativeParser::Variant::Number:
275 var = QVariant(v.asNumber());
276 break;
277 case QDeclarativeParser::Variant::String:
278 var = QVariant(v.asString());
279 break;
280 case QDeclarativeParser::Variant::Invalid:
281 case QDeclarativeParser::Variant::Script:
282 var = QVariant(v.asScript());
283 break;
284 }
285
286 ds << data.at(ii).first << isScript << var;
287 }
288
289 return rv;
290}
291
292void QDeclarativePropertyChangesPrivate::decode()
293{
294 Q_Q(QDeclarativePropertyChanges);
295 if (decoded)
296 return;
297
298 QDataStream ds(&data, QIODevice::ReadOnly);
299
300 int count;
301 ds >> count;
302 for (int ii = 0; ii < count; ++ii) {
303 QByteArray name;
304 bool isScript;
305 QVariant data;
306 ds >> name;
307 ds >> isScript;
308 ds >> data;
309
310 QDeclarativeProperty prop = property(name); //### better way to check for signal property?
311 if (prop.type() & QDeclarativeProperty::SignalProperty) {
312 QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), object, data.toString());
313 QDeclarativeData *ddata = QDeclarativeData::get(q);
314 if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
315 expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
316 QDeclarativeReplaceSignalHandler *handler = new QDeclarativeReplaceSignalHandler;
317 handler->property = prop;
318 handler->expression = expression;
319 signalReplacements << handler;
320 } else if (isScript) {
321 QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), object, data.toString());
322 QDeclarativeData *ddata = QDeclarativeData::get(q);
323 if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
324 expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
325 expressions << qMakePair(name, expression);
326 } else {
327 properties << qMakePair(name, data);
328 }
329 }
330
331 decoded = true;
332 data.clear();
333}
334
335void QDeclarativePropertyChangesParser::setCustomData(QObject *object,
336 const QByteArray &data)
337{
338 QDeclarativePropertyChangesPrivate *p =
339 static_cast<QDeclarativePropertyChangesPrivate *>(QObjectPrivate::get(object));
340 p->data = data;
341 p->decoded = false;
342}
343
344QDeclarativePropertyChanges::QDeclarativePropertyChanges()
345: QDeclarativeStateOperation(*(new QDeclarativePropertyChangesPrivate))
346{
347}
348
349QDeclarativePropertyChanges::~QDeclarativePropertyChanges()
350{
351 Q_D(QDeclarativePropertyChanges);
352 for(int ii = 0; ii < d->expressions.count(); ++ii)
353 delete d->expressions.at(ii).second;
354 for(int ii = 0; ii < d->signalReplacements.count(); ++ii)
355 delete d->signalReplacements.at(ii);
356}
357
358QObject *QDeclarativePropertyChanges::object() const
359{
360 Q_D(const QDeclarativePropertyChanges);
361 return d->object;
362}
363
364void QDeclarativePropertyChanges::setObject(QObject *o)
365{
366 Q_D(QDeclarativePropertyChanges);
367 d->object = o;
368}
369
370/*!
371 \qmlproperty bool PropertyChanges::restoreEntryValues
372
373 This property holds whether the previous values should be restored when
374 leaving the state.
375
376 The default value is \c true. Setting this value to \c false creates a
377 temporary state that has permanent effects on property values.
378*/
379bool QDeclarativePropertyChanges::restoreEntryValues() const
380{
381 Q_D(const QDeclarativePropertyChanges);
382 return d->restore;
383}
384
385void QDeclarativePropertyChanges::setRestoreEntryValues(bool v)
386{
387 Q_D(QDeclarativePropertyChanges);
388 d->restore = v;
389}
390
391QDeclarativeProperty
392QDeclarativePropertyChangesPrivate::property(const QByteArray &property)
393{
394 Q_Q(QDeclarativePropertyChanges);
395 QDeclarativeProperty prop(object, QString::fromUtf8(property), qmlContext(q));
396 if (!prop.isValid()) {
397 qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(property));
398 return QDeclarativeProperty();
399 } else if (!(prop.type() & QDeclarativeProperty::SignalProperty) && !prop.isWritable()) {
400 qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(QString::fromUtf8(property));
401 return QDeclarativeProperty();
402 }
403 return prop;
404}
405
406QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions()
407{
408 Q_D(QDeclarativePropertyChanges);
409
410 d->decode();
411
412 ActionList list;
413
414 for (int ii = 0; ii < d->properties.count(); ++ii) {
415
416 QByteArray property = d->properties.at(ii).first;
417
418 QDeclarativeAction a(d->object, QString::fromUtf8(property),
419 qmlContext(this), d->properties.at(ii).second);
420
421 if (a.property.isValid()) {
422 a.restore = restoreEntryValues();
423 list << a;
424 }
425 }
426
427 for (int ii = 0; ii < d->signalReplacements.count(); ++ii) {
428
429 QDeclarativeReplaceSignalHandler *handler = d->signalReplacements.at(ii);
430
431 if (handler->property.isValid()) {
432 QDeclarativeAction a;
433 a.event = handler;
434 list << a;
435 }
436 }
437
438 for (int ii = 0; ii < d->expressions.count(); ++ii) {
439
440 QByteArray property = d->expressions.at(ii).first;
441 QDeclarativeProperty prop = d->property(property);
442
443 if (prop.isValid()) {
444 QDeclarativeAction a;
445 a.restore = restoreEntryValues();
446 a.property = prop;
447 a.fromValue = a.property.read();
448 a.specifiedObject = d->object;
449 a.specifiedProperty = QString::fromUtf8(property);
450
451 if (d->isExplicit) {
452 a.toValue = d->expressions.at(ii).second->evaluate();
453 } else {
454 QDeclarativeExpression *e = d->expressions.at(ii).second;
455 QDeclarativeBinding *newBinding =
456 new QDeclarativeBinding(e->expression(), object(), qmlContext(this));
457 newBinding->setTarget(prop);
458 newBinding->setSourceLocation(e->sourceFile(), e->lineNumber());
459 a.toBinding = newBinding;
460 a.deletableToBinding = true;
461 }
462
463 list << a;
464 }
465 }
466
467 return list;
468}
469
470/*!
471 \qmlproperty bool PropertyChanges::explicit
472
473 If explicit is set to true, any potential bindings will be interpreted as
474 once-off assignments that occur when the state is entered.
475
476 In the following example, the addition of explicit prevents \c myItem.width from
477 being bound to \c parent.width. Instead, it is assigned the value of \c parent.width
478 at the time of the state change.
479 \qml
480 PropertyChanges {
481 target: myItem
482 explicit: true
483 width: parent.width
484 }
485 \endqml
486
487 By default, explicit is false.
488*/
489bool QDeclarativePropertyChanges::isExplicit() const
490{
491 Q_D(const QDeclarativePropertyChanges);
492 return d->isExplicit;
493}
494
495void QDeclarativePropertyChanges::setIsExplicit(bool e)
496{
497 Q_D(QDeclarativePropertyChanges);
498 d->isExplicit = e;
499}
500
501bool QDeclarativePropertyChanges::containsValue(const QByteArray &name) const
502{
503 Q_D(const QDeclarativePropertyChanges);
504 typedef QPair<QByteArray, QVariant> PropertyEntry;
505
506 QListIterator<PropertyEntry> propertyIterator(d->properties);
507 while (propertyIterator.hasNext()) {
508 const PropertyEntry &entry = propertyIterator.next();
509 if (entry.first == name) {
510 return true;
511 }
512 }
513
514 return false;
515}
516
517bool QDeclarativePropertyChanges::containsExpression(const QByteArray &name) const
518{
519 Q_D(const QDeclarativePropertyChanges);
520 typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry;
521
522 QListIterator<ExpressionEntry> expressionIterator(d->expressions);
523 while (expressionIterator.hasNext()) {
524 const ExpressionEntry &entry = expressionIterator.next();
525 if (entry.first == name) {
526 return true;
527 }
528 }
529
530 return false;
531}
532
533bool QDeclarativePropertyChanges::containsProperty(const QByteArray &name) const
534{
535 return containsValue(name) || containsExpression(name);
536}
537
538void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVariant &value)
539{
540 Q_D(QDeclarativePropertyChanges);
541 typedef QPair<QByteArray, QVariant> PropertyEntry;
542 typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry;
543
544 QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
545 while (expressionIterator.hasNext()) {
546 const ExpressionEntry &entry = expressionIterator.next();
547 if (entry.first == name) {
548 expressionIterator.remove();
549 if (state() && state()->isStateActive()) {
550 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name));
551 if (oldBinding) {
552 QDeclarativePropertyPrivate::setBinding(d->property(name), 0);
553 oldBinding->destroy();
554 }
555 d->property(name).write(value);
556 }
557
558 d->properties.append(PropertyEntry(name, value));
559 return;
560 }
561 }
562
563 QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
564 while (propertyIterator.hasNext()) {
565 PropertyEntry &entry = propertyIterator.next();
566 if (entry.first == name) {
567 entry.second = value;
568 if (state() && state()->isStateActive())
569 d->property(name).write(value);
570 return;
571 }
572 }
573
574 QDeclarativeAction action;
575 action.restore = restoreEntryValues();
576 action.property = d->property(name);
577 action.fromValue = action.property.read();
578 action.specifiedObject = object();
579 action.specifiedProperty = QString::fromUtf8(name);
580 action.toValue = value;
581
582 propertyIterator.insert(PropertyEntry(name, value));
583 if (state() && state()->isStateActive()) {
584 state()->addEntryToRevertList(action);
585 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(action.property);
586 if (oldBinding)
587 oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
588 d->property(name).write(value);
589 }
590}
591
592void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const QString &expression)
593{
594 Q_D(QDeclarativePropertyChanges);
595 typedef QPair<QByteArray, QVariant> PropertyEntry;
596 typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry;
597
598 bool hadValue = false;
599
600 QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
601 while (propertyIterator.hasNext()) {
602 PropertyEntry &entry = propertyIterator.next();
603 if (entry.first == name) {
604 propertyIterator.remove();
605 hadValue = true;
606 break;
607 }
608 }
609
610 QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
611 while (expressionIterator.hasNext()) {
612 const ExpressionEntry &entry = expressionIterator.next();
613 if (entry.first == name) {
614 entry.second->setExpression(expression);
615 if (state() && state()->isStateActive()) {
616 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name));
617 if (oldBinding) {
618 QDeclarativePropertyPrivate::setBinding(d->property(name), 0);
619 oldBinding->destroy();
620 }
621
622 QDeclarativeBinding *newBinding = new QDeclarativeBinding(expression, object(), qmlContext(this));
623 newBinding->setTarget(d->property(name));
624 QDeclarativePropertyPrivate::setBinding(d->property(name), newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
625 }
626 return;
627 }
628 }
629
630 QDeclarativeExpression *newExpression = new QDeclarativeExpression(qmlContext(this), d->object, expression);
631 expressionIterator.insert(ExpressionEntry(name, newExpression));
632
633 if (state() && state()->isStateActive()) {
634 if (hadValue) {
635 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name));
636 if (oldBinding) {
637 oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
638 state()->changeBindingInRevertList(object(), name, oldBinding);
639 }
640
641 QDeclarativeBinding *newBinding = new QDeclarativeBinding(expression, object(), qmlContext(this));
642 newBinding->setTarget(d->property(name));
643 QDeclarativePropertyPrivate::setBinding(d->property(name), newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
644 } else {
645 QDeclarativeAction action;
646 action.restore = restoreEntryValues();
647 action.property = d->property(name);
648 action.fromValue = action.property.read();
649 action.specifiedObject = object();
650 action.specifiedProperty = QString::fromUtf8(name);
651
652
653 if (d->isExplicit) {
654 action.toValue = newExpression->evaluate();
655 } else {
656 QDeclarativeBinding *newBinding = new QDeclarativeBinding(newExpression->expression(), object(), qmlContext(this));
657 newBinding->setTarget(d->property(name));
658 action.toBinding = newBinding;
659 action.deletableToBinding = true;
660
661 state()->addEntryToRevertList(action);
662 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(action.property);
663 if (oldBinding)
664 oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
665
666 QDeclarativePropertyPrivate::setBinding(action.property, newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor);
667 }
668 }
669 }
670 // what about the signal handler?
671}
672
673QVariant QDeclarativePropertyChanges::property(const QByteArray &name) const
674{
675 Q_D(const QDeclarativePropertyChanges);
676 typedef QPair<QByteArray, QVariant> PropertyEntry;
677 typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry;
678
679 QListIterator<PropertyEntry> propertyIterator(d->properties);
680 while (propertyIterator.hasNext()) {
681 const PropertyEntry &entry = propertyIterator.next();
682 if (entry.first == name) {
683 return entry.second;
684 }
685 }
686
687 QListIterator<ExpressionEntry> expressionIterator(d->expressions);
688 while (expressionIterator.hasNext()) {
689 const ExpressionEntry &entry = expressionIterator.next();
690 if (entry.first == name) {
691 return QVariant(entry.second->expression());
692 }
693 }
694
695 return QVariant();
696}
697
698void QDeclarativePropertyChanges::removeProperty(const QByteArray &name)
699{
700 Q_D(QDeclarativePropertyChanges);
701 typedef QPair<QByteArray, QVariant> PropertyEntry;
702 typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry;
703
704 QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
705 while (expressionIterator.hasNext()) {
706 const ExpressionEntry &entry = expressionIterator.next();
707 if (entry.first == name) {
708 expressionIterator.remove();
709 state()->removeEntryFromRevertList(object(), name);
710 return;
711 }
712 }
713
714 QMutableListIterator<PropertyEntry> propertyIterator(d->properties);
715 while (propertyIterator.hasNext()) {
716 const PropertyEntry &entry = propertyIterator.next();
717 if (entry.first == name) {
718 propertyIterator.remove();
719 state()->removeEntryFromRevertList(object(), name);
720 return;
721 }
722 }
723}
724
725QVariant QDeclarativePropertyChanges::value(const QByteArray &name) const
726{
727 Q_D(const QDeclarativePropertyChanges);
728 typedef QPair<QByteArray, QVariant> PropertyEntry;
729
730 QListIterator<PropertyEntry> propertyIterator(d->properties);
731 while (propertyIterator.hasNext()) {
732 const PropertyEntry &entry = propertyIterator.next();
733 if (entry.first == name) {
734 return entry.second;
735 }
736 }
737
738 return QVariant();
739}
740
741QString QDeclarativePropertyChanges::expression(const QByteArray &name) const
742{
743 Q_D(const QDeclarativePropertyChanges);
744 typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry;
745
746 QListIterator<ExpressionEntry> expressionIterator(d->expressions);
747 while (expressionIterator.hasNext()) {
748 const ExpressionEntry &entry = expressionIterator.next();
749 if (entry.first == name) {
750 return entry.second->expression();
751 }
752 }
753
754 return QString();
755}
756
757void QDeclarativePropertyChanges::detachFromState()
758{
759 if (state())
760 state()->removeAllEntriesFromRevertList(object());
761}
762
763void QDeclarativePropertyChanges::attachToState()
764{
765 if (state())
766 state()->addEntriesToRevertList(actions());
767}
768
769QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.