Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickpropertychanges.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
7#include <private/qqmlopenmetaobject_p.h>
8#include <private/qqmlengine_p.h>
9
10#include <qqmlinfo.h>
11#include <private/qqmlcustomparser_p.h>
12#include <qqmlexpression.h>
13#include <private/qqmlbinding_p.h>
14#include <qqmlcontext.h>
15#include <private/qqmlproperty_p.h>
16#include <private/qqmlcontext_p.h>
17#include <private/qquickstate_p_p.h>
18#include <private/qqmlboundsignal_p.h>
19#include <private/qv4qmlcontext_p.h>
20#include <private/qqmlpropertybinding_p.h>
21#include <private/qqmlirbuilder_p.h>
22
23#include <QtCore/qdebug.h>
24#include <QtQml/private/qqmlsignalnames_p.h>
25
26#include <private/qobject_p.h>
27#include <QtCore/qpointer.h>
28
30
31/*!
32 \qmltype PropertyChanges
33 \inqmlmodule QtQuick
34 \ingroup qtquick-states
35 \brief Describes new property bindings or values for a state.
36
37 PropertyChanges is used to define the property values or bindings in a
38 \l State. This enables an item's property values to be changed when it
39 \l {Qt Quick States}{changes between states}.
40
41 To create a PropertyChanges object, bind to properties of the target
42 item like you would bind to local properties. This way you can define
43 the new property values or bindings. For example:
44
45 \snippet qml/propertychanges.qml import
46 \codeline
47 \snippet qml/propertychanges.qml 0
48
49 When the mouse is pressed, the \l Rectangle changes to the \e resized
50 state. In this state, the PropertyChanges object sets the rectangle's
51 color to blue and the \c height value to that of \c container.height.
52
53 Note this automatically binds \c rect.height to \c container.height
54 in the \e resized state. If a property binding should not be
55 established, and the height should just be set to the value of
56 \c container.height at the time of the state change, set the \l explicit
57 property to \c true.
58
59 A PropertyChanges object can also override the default signal handler
60 for an object to implement a signal handler specific to the new state:
61
62 \qml
63 PropertyChanges {
64 myMouseArea.onClicked: doSomethingDifferent()
65 }
66 \endqml
67
68 \note PropertyChanges can be used to change anchor margins, but not other anchor
69 values; use AnchorChanges for this instead. Similarly, to change an \l Item's
70 \l {Item::}{parent} value, use ParentChange instead.
71
72
73 \section2 Resetting Property Values
74
75 The \c undefined value can be used to reset the property value for a state.
76 In the following example, when \c myText changes to the \e widerText
77 state, its \c width property is reset, giving the text its natural width
78 and displaying the whole string on a single line.
79
80 \snippet qml/propertychanges.qml reset
81
82
83 \section2 Immediate Property Changes in Transitions
84
85 When \l{Animation and Transitions in Qt Quick}{Transitions} are used to animate
86 state changes, they animate properties from their values in the current
87 state to those defined in the new state (as defined by PropertyChanges
88 objects). However, it is sometimes desirable to set a property value
89 \e immediately during a \l Transition, without animation; in these cases,
90 the PropertyAction type can be used to force an immediate property
91 change.
92
93 See the PropertyAction documentation for more details.
94
95 \note The \l{Item::}{visible} and \l{Item::}{enabled} properties of \l Item do not behave
96 exactly the same as other properties in PropertyChanges. Since these properties can be
97 changed implicitly through their parent's state, they should be set explicitly in all PropertyChanges.
98 An item will still not be enabled/visible if one of its parents is not enabled or visible.
99
100 \note For backwards compatibility with Qt 5, you can also specify PropertyChanges using
101 the \l target property and plain property names without IDs. For example:
102 \c {PropertyChanges { target: myItem; x: 15 }}. The form with ID instead of \l target
103 is recommended. You may also need to use the form with \l target if the file is to be
104 edited with \l{Qt Design Studio}. Mind that \l{Qt Design Studio} also imposes a number
105 of further restrictions on the files it can work with.
106
107 \sa {Qt Quick Examples - Animation#States}{States example}, {Qt Quick States}, {Qt Qml}
108*/
109
110/*!
111 \qmlproperty QtObject QtQuick::PropertyChanges::target
112 This property holds the object which contains the properties to be changed.
113
114 \note You generally don't have to use this property. It only exists for
115 compatibility with Qt 5 and for compatibility with \l{Qt Design Studio}.
116*/
117
119{
120public:
123
124 EventType type() const override { return SignalHandler; }
125
130
132 QQmlPropertyPrivate::setSignalExpression(property, expression.data());
133 }
134
135 bool isReversable() override { return true; }
137 QQmlPropertyPrivate::setSignalExpression(property, reverseExpression.data());
138 }
139
142 reverseExpression = rewindExpression;
143 }
144
145 bool needsCopy() override { return true; }
146 void copyOriginals(QQuickStateActionEvent *other) override
147 {
148 QQuickReplaceSignalHandler *rsh = static_cast<QQuickReplaceSignalHandler*>(other);
150 if (rsh == this)
151 return;
152 reverseExpression = rsh->reverseExpression;
153 }
154
156 QQmlPropertyPrivate::setSignalExpression(property, rewindExpression.data());
157 }
159 rewindExpression = QQmlPropertyPrivate::signalExpression(property);
160 }
161
162 bool mayOverride(QQuickStateActionEvent *other) override {
163 if (other == this)
164 return true;
165 if (other->type() != type())
166 return false;
167 if (static_cast<QQuickReplaceSignalHandler*>(other)->property == property)
168 return true;
169 return false;
170 }
171};
172
173
175{
176 Q_DECLARE_PUBLIC(QQuickPropertyChanges)
177public:
180
184
185 bool decoded : 1;
186 bool restore : 1;
187 bool isExplicit : 1;
188
189 void decode();
190 void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlUnit, const QV4::CompiledData::Binding *binding);
191
193 public:
194 ExpressionChange(const QString &_name,
195 const QV4::CompiledData::Binding *_binding,
196 QQmlBinding::Identifier _id,
197 const QString& _expr,
198 const QUrl &_url,
199 int _line,
200 int _column)
201 : name(_name), binding(_binding), id(_id), expression(_expr), url(_url), line(_line), column(_column) {}
202 QString name;
205 QString expression;
207 int line;
209 };
210
214
215 QQmlProperty property(const QString &);
216};
217
219 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit,
220 const QV4::CompiledData::Binding *binding)
221{
222 switch (binding->type()) {
223 case QV4::CompiledData::Binding::Type_Object:
224 error(compilationUnit->objectAt(binding->value.objectIndex),
225 QQuickPropertyChanges::tr(
226 "PropertyChanges does not support creating state-specific objects."));
227 break;
228 case QV4::CompiledData::Binding::Type_GroupProperty:
229 case QV4::CompiledData::Binding::Type_AttachedProperty: {
230 const QV4::CompiledData::Object *subObj = compilationUnit->objectAt(binding->value.objectIndex);
231 const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
232 for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding)
233 verifyList(compilationUnit, subBinding);
234 break;
235 }
236 default:
237 break;
238 }
239}
240
242{
243 if (decoded)
244 return;
245
246 for (const QV4::CompiledData::Binding *binding : std::as_const(bindings))
247 decodeBinding(QString(), compilationUnit, binding);
248
249 bindings.clear();
250
251 decoded = true;
252}
253
254void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
255{
256 Q_Q(QQuickPropertyChanges);
257
258 QString propertyName = propertyPrefix + compilationUnit->stringAt(binding->propertyNameIndex);
259
260 switch (binding->type()) {
261 case QV4::CompiledData::Binding::Type_GroupProperty:
262 case QV4::CompiledData::Binding::Type_AttachedProperty: {
263 QString pre = propertyName + QLatin1Char('.');
264 const QV4::CompiledData::Object *subObj = compilationUnit->objectAt(binding->value.objectIndex);
265 const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
266 for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding) {
267 decodeBinding(pre, compilationUnit, subBinding);
268 }
269 return;
270 }
271 default:
272 break;
273 }
274
275 if (binding->isSignalHandler() || QQmlSignalNames::isHandlerName(propertyName)) {
276 QQmlProperty prop = property(propertyName);
277 if (prop.isSignalProperty()) {
279 handler->property = prop;
280 handler->expression.adopt(
281 new QQmlBoundSignalExpression(
282 prop.object(), QQmlPropertyPrivate::get(prop)->signalIndex(),
283 QQmlContextData::get(qmlContext(q)), prop.object(),
284 compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex)));
285 signalReplacements << handler;
286 return;
287 }
288 }
289
290 if (binding->type() == QV4::CompiledData::Binding::Type_Script
291 || binding->isTranslationBinding()) {
292 QUrl url = QUrl();
293 int line = -1;
294 int column = -1;
295
296 QQmlData *ddata = QQmlData::get(q);
297 if (ddata && ddata->outerContext && !ddata->outerContext->url().isEmpty()) {
298 url = ddata->outerContext->url();
299 line = ddata->lineNumber;
300 column = ddata->columnNumber;
301 }
302
303 QString expression;
304 QQmlBinding::Identifier id = QQmlBinding::Invalid;
305
306 if (!binding->isTranslationBinding()) {
307 expression = compilationUnit->bindingValueAsString(binding);
308 id = binding->value.compiledScriptIndex;
309 }
310 expressions << ExpressionChange(propertyName, binding, id, expression, url, line, column);
311 return;
312 }
313
314 QVariant var;
315 switch (binding->type()) {
316 case QV4::CompiledData::Binding::Type_Script:
317 case QV4::CompiledData::Binding::Type_Translation:
318 case QV4::CompiledData::Binding::Type_TranslationById:
319 Q_UNREACHABLE();
320 case QV4::CompiledData::Binding::Type_String:
321 var = compilationUnit->bindingValueAsString(binding);
322 break;
323 case QV4::CompiledData::Binding::Type_Number:
324 var = compilationUnit->bindingValueAsNumber(binding);
325 break;
326 case QV4::CompiledData::Binding::Type_Boolean:
327 var = binding->valueAsBoolean();
328 break;
329 case QV4::CompiledData::Binding::Type_Null:
330 var = QVariant::fromValue(nullptr);
331 break;
332 default:
333 break;
334 }
335
336 properties << std::make_pair(propertyName, var);
337}
338
340 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit,
341 const QList<const QV4::CompiledData::Binding *> &props)
342{
343 for (int ii = 0; ii < props.size(); ++ii)
344 verifyList(compilationUnit, props.at(ii));
345}
346
348 QObject *obj, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
349 const QList<const QV4::CompiledData::Binding *> &bindings)
350{
352 static_cast<QQuickPropertyChangesPrivate *>(QObjectPrivate::get(obj));
353 p->bindings = bindings;
354 p->compilationUnit = compilationUnit;
355 p->decoded = false;
356
357 QQmlData *data = QQmlData::get(obj);
358 Q_ASSERT(data && !data->wasDeleted(obj));
359 data->releaseDeferredData();
360}
361
362QQuickPropertyChanges::QQuickPropertyChanges()
363: QQuickStateOperation(*(new QQuickPropertyChangesPrivate))
364{
365}
366
367QQuickPropertyChanges::~QQuickPropertyChanges()
368{
369 Q_D(QQuickPropertyChanges);
370 for(int ii = 0; ii < d->signalReplacements.size(); ++ii)
371 delete d->signalReplacements.at(ii);
372}
373
374QObject *QQuickPropertyChanges::object() const
375{
376 Q_D(const QQuickPropertyChanges);
377 return d->object;
378}
379
380void QQuickPropertyChanges::setObject(QObject *o)
381{
382 Q_D(QQuickPropertyChanges);
383 if (o != d->object) {
384 d->object = o;
385 emit objectChanged();
386 }
387}
388
389/*!
390 \qmlproperty bool QtQuick::PropertyChanges::restoreEntryValues
391
392 This property holds whether the previous values should be restored when
393 leaving the state.
394
395 The default value is \c true. Setting this value to \c false creates a
396 temporary state that has permanent effects on property values.
397*/
398bool QQuickPropertyChanges::restoreEntryValues() const
399{
400 Q_D(const QQuickPropertyChanges);
401 return d->restore;
402}
403
404void QQuickPropertyChanges::setRestoreEntryValues(bool v)
405{
406 Q_D(QQuickPropertyChanges);
407 if (v != d->restore) {
408 d->restore = v;
409 emit restoreEntryValuesChanged();
410 }
411}
412
414QQuickPropertyChangesPrivate::property(const QString &property)
415{
416 Q_Q(QQuickPropertyChanges);
417 QQmlData *ddata = QQmlData::get(q);
418 QQmlProperty prop = QQmlPropertyPrivate::create(
419 object, property, ddata ? ddata->outerContext : QQmlRefPointer<QQmlContextData>(),
420 QQmlPropertyPrivate::InitFlag::AllowId | QQmlPropertyPrivate::InitFlag::AllowSignal);
421 if (!prop.isValid()) {
422 qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property);
423 return QQmlProperty();
424 } else if (!(prop.type() & QQmlProperty::SignalProperty) && !prop.isWritable()) {
425 qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(property);
426 return QQmlProperty();
427 }
428 return prop;
429}
430
431QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
432{
433 Q_D(QQuickPropertyChanges);
434
435 d->decode();
436
437 ActionList list;
438
439 for (int ii = 0; ii < d->properties.size(); ++ii) {
440 QQmlProperty prop = d->property(d->properties.at(ii).first);
441
442 QQuickStateAction a(d->object, prop, d->properties.at(ii).first,
443 d->properties.at(ii).second);
444
445 if (a.property.isValid()) {
446 a.restore = restoreEntryValues();
447 list << a;
448 }
449 }
450
451 for (int ii = 0; ii < d->signalReplacements.size(); ++ii) {
452 QQuickReplaceSignalHandler *handler = d->signalReplacements.at(ii);
453
454 if (handler->property.isValid()) {
455 QQuickStateAction a;
456 a.event = handler;
457 list << a;
458 }
459 }
460
461 for (int ii = 0; ii < d->expressions.size(); ++ii) {
462
463 QQuickPropertyChangesPrivate::ExpressionChange e = d->expressions.at(ii);
464 const QString &property = e.name;
465 QQmlProperty prop = d->property(property);
466
467 if (prop.isValid()) {
468 QQuickStateAction a;
469 a.restore = restoreEntryValues();
470 a.property = prop;
471 a.fromValue = a.property.read();
472 a.specifiedObject = d->object;
473 a.specifiedProperty = property;
474
475 QQmlRefPointer<QQmlContextData> context = QQmlContextData::get(qmlContext(this));
476 QV4::Scope scope(qmlEngine(this)->handle());
477 QV4::Scoped<QV4::QmlContext> qmlCtxt(scope, QV4::QmlContext::create(scope.engine->rootContext(), context, object()));
478
479 if (d->isExplicit) {
480 // in this case, we don't want to assign a binding, per se,
481 // so we evaluate the expression and assign the result.
482 // XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
483 // so that we can avoid creating then destroying the binding in this case.
484 std::unique_ptr<QQmlBinding> newBinding = nullptr;
485 if (e.binding && e.binding->isTranslationBinding()) {
486 newBinding.reset(QQmlBinding::createTranslationBinding(d->compilationUnit, e.binding, object(), context));
487 } else if (e.id != QQmlBinding::Invalid) {
488 newBinding.reset(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, d->compilationUnit->runtimeFunctions.at(e.id), object(), context, qmlCtxt));
489 } else {
490 newBinding.reset(QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core, e.expression, object(), context, e.url.toString(), e.line));
491 }
492 a.toValue = newBinding->evaluate();
493 } else {
494 QQmlAnyBinding newBinding = nullptr;
495 if (e.binding && e.binding->isTranslationBinding()) {
496 newBinding = QQmlAnyBinding::createTranslationBinding(prop, d->compilationUnit, e.binding, object(), context);
497 } else if (e.id != QQmlBinding::Invalid) {
498 newBinding = QQmlAnyBinding::createFromFunction(prop,
499 d->compilationUnit->runtimeFunctions.at(e.id),
500 object(), context, qmlCtxt);
501 } else {
502 newBinding = QQmlAnyBinding::createFromCodeString(prop, e.expression, object(), context, e.url.toString(), e.line);
503 }
504
505 a.toBinding = newBinding;
506 a.deletableToBinding = true;
507 }
508
509 list << a;
510 }
511 }
512
513 return list;
514}
515
516/*!
517 \qmlproperty bool QtQuick::PropertyChanges::explicit
518
519 If explicit is set to true, bindings will be interpreted as assignments.
520 The expression will only be evaluated once, and no updates happen, even if
521 dependencies change.
522
523 In the following example, the addition of explicit prevents \c myItem.width from
524 being bound to \c parent.width. Instead, it is assigned the value of \c parent.width
525 at the time of the state change.
526 \qml
527 PropertyChanges {
528 target: myItem
529 explicit: true
530 width: parent.width
531 }
532 \endqml
533
534 By default, explicit is false.
535*/
536bool QQuickPropertyChanges::isExplicit() const
537{
538 Q_D(const QQuickPropertyChanges);
539 return d->isExplicit;
540}
541
542void QQuickPropertyChanges::setIsExplicit(bool e)
543{
544 Q_D(QQuickPropertyChanges);
545 if (e != d->isExplicit) {
546 d->isExplicit = e;
547 emit isExplicitChanged();
548 }
549}
550
551bool QQuickPropertyChanges::containsValue(const QString &name) const
552{
553 Q_D(const QQuickPropertyChanges);
554 typedef std::pair<QString, QVariant> PropertyEntry;
555
556 for (const PropertyEntry &entry : d->properties) {
557 if (entry.first == name) {
558 return true;
559 }
560 }
561
562 return false;
563}
564
565bool QQuickPropertyChanges::containsExpression(const QString &name) const
566{
567 Q_D(const QQuickPropertyChanges);
568 typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
569
570 for (const ExpressionEntry &entry : d->expressions) {
571 if (entry.name == name) {
572 return true;
573 }
574 }
575
576 return false;
577}
578
579bool QQuickPropertyChanges::containsProperty(const QString &name) const
580{
581 return containsValue(name) || containsExpression(name);
582}
583
584void QQuickPropertyChanges::changeValue(const QString &name, const QVariant &value)
585{
586 Q_D(QQuickPropertyChanges);
587 typedef std::pair<QString, QVariant> PropertyEntry;
588
589 for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) {
590 if (it->name == name) {
591 d->expressions.erase(it);
592 if (state() && state()->isStateActive()) {
593 QQmlPropertyPrivate::removeBinding(d->property(name));
594 d->property(name).write(value);
595 }
596
597 d->properties.append(PropertyEntry(name, value));
598 return;
599 }
600 }
601
602 for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) {
603 if (it->first == name) {
604 it->second = value;
605 if (state() && state()->isStateActive())
606 d->property(name).write(value);
607 return;
608 }
609 }
610
611 QQuickStateAction action;
612 action.restore = restoreEntryValues();
613 action.property = d->property(name);
614 action.fromValue = action.property.read();
615 action.specifiedObject = object();
616 action.specifiedProperty = name;
617 action.toValue = value;
618
619 d->properties.append(PropertyEntry(name, value));
620 if (state() && state()->isStateActive()) {
621 state()->addEntryToRevertList(action);
622 QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(action.property);
623 if (oldBinding)
624 oldBinding->setEnabled(false, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
625 d->property(name).write(value);
626 }
627}
628
629void QQuickPropertyChanges::changeExpression(const QString &name, const QString &expression)
630{
631 Q_D(QQuickPropertyChanges);
632 typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
633
634 bool hadValue = false;
635
636 for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) {
637 if (it->first == name) {
638 d->properties.erase(it);
639 hadValue = true;
640 break;
641 }
642 }
643
644 for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) {
645 if (it->name == name) {
646 it->expression = expression;
647 if (state() && state()->isStateActive()) {
648 auto prop = d->property(name);
649 auto context = QQmlContextData::get(qmlContext(this));
650 QString url;
651 int lineNumber = 0;
652 QQmlAnyBinding::createFromCodeString(prop, expression, object(), context, url, lineNumber).installOn(prop);
653 }
654 return;
655 }
656 }
657
658 // adding a new expression.
659 d->expressions.append(ExpressionEntry(name, nullptr, QQmlBinding::Invalid, expression, QUrl(), -1, -1));
660
661 const QString url;
662 const quint16 lineNumber = 0;
663 if (state() && state()->isStateActive()) {
664 if (hadValue) {
665 auto prop = d->property(name);
666 QQmlAnyBinding oldBinding = QQmlAnyBinding::takeFrom(prop);
667 if (oldBinding)
668 state()->changeBindingInRevertList(object(), name, oldBinding);
669
670 QQmlAnyBinding::createFromCodeString(prop, expression, object(), QQmlContextData::get(qmlContext(this)), url, lineNumber).installOn(prop);
671 } else {
672 QQuickStateAction action;
673 action.restore = restoreEntryValues();
674 action.property = d->property(name);
675 action.fromValue = action.property.read();
676 action.specifiedObject = object();
677 action.specifiedProperty = name;
678
679 QQmlAnyBinding newBinding;
680 if (d->isExplicit) {
681 newBinding = QQmlBinding::create(
682 &QQmlPropertyPrivate::get(action.property)->core, expression,
683 object(), QQmlContextData::get(qmlContext(this)));
684 } else {
685 const auto prop = action.property;
686 const auto context = QQmlContextData::get(qmlContext(this));
687 newBinding = QQmlAnyBinding::createFromCodeString(prop, expression, object(), context, url, lineNumber);
688 }
689 if (d->isExplicit) {
690 // don't assign the binding, merely evaluate the expression.
691 // XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
692 // so that we can avoid creating then destroying the binding in this case.
693 action.toValue = static_cast<QQmlBinding *>(newBinding.asAbstractBinding())->evaluate();
694 } else {
695 // TODO: replace binding would be more efficient for new-style properties
696 QQmlAnyBinding::removeBindingFrom(action.property);
697 newBinding.installOn(action.property);
698 action.toBinding = newBinding;
699 action.deletableToBinding = true;
700 state()->addEntryToRevertList(action);
701 }
702 }
703 }
704 // what about the signal handler?
705}
706
707QVariant QQuickPropertyChanges::property(const QString &name) const
708{
709 Q_D(const QQuickPropertyChanges);
710 typedef std::pair<QString, QVariant> PropertyEntry;
711 typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
712
713 for (const PropertyEntry &entry : d->properties) {
714 if (entry.first == name) {
715 return entry.second;
716 }
717 }
718
719 for (const ExpressionEntry &entry : d->expressions) {
720 if (entry.name == name) {
721 return QVariant(entry.expression);
722 }
723 }
724
725 return QVariant();
726}
727
728void QQuickPropertyChanges::removeProperty(const QString &name)
729{
730 Q_D(QQuickPropertyChanges);
731
732 for (auto it = d->expressions.begin(), end = d->expressions.end(); it != end; ++it) {
733 if (it->name == name) {
734 d->expressions.erase(it);
735 state()->removeEntryFromRevertList(object(), name);
736 return;
737 }
738 }
739
740 for (auto it = d->properties.begin(), end = d->properties.end(); it != end; ++it) {
741 if (it->first == name) {
742 d->properties.erase(it);
743 state()->removeEntryFromRevertList(object(), name);
744 return;
745 }
746 }
747}
748
749QVariant QQuickPropertyChanges::value(const QString &name) const
750{
751 Q_D(const QQuickPropertyChanges);
752 typedef std::pair<QString, QVariant> PropertyEntry;
753
754 for (const PropertyEntry &entry : d->properties) {
755 if (entry.first == name) {
756 return entry.second;
757 }
758 }
759
760 return QVariant();
761}
762
763QString QQuickPropertyChanges::expression(const QString &name) const
764{
765 Q_D(const QQuickPropertyChanges);
766 typedef QQuickPropertyChangesPrivate::ExpressionChange ExpressionEntry;
767
768 for (const ExpressionEntry &entry : d->expressions) {
769 if (entry.name == name) {
770 return entry.expression;
771 }
772 }
773
774 return QString();
775}
776
777void QQuickPropertyChanges::detachFromState()
778{
779 if (state())
780 state()->removeAllEntriesFromRevertList(object());
781}
782
783void QQuickPropertyChanges::attachToState()
784{
785 if (state())
786 state()->addEntriesToRevertList(actions());
787}
788
789QT_END_NAMESPACE
790
791#include "moc_qquickpropertychanges_p.cpp"
The QQmlProperty class abstracts accessing properties on objects created from QML.
void verifyBindings(const QQmlRefPointer< QV4::CompiledData::CompilationUnit > &compilationUnit, const QList< const QV4::CompiledData::Binding * > &props) override
void verifyList(const QQmlRefPointer< QV4::CompiledData::CompilationUnit > &compilationUnit, const QV4::CompiledData::Binding *binding)
void applyBindings(QObject *obj, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit, const QList< const QV4::CompiledData::Binding * > &bindings) override
ExpressionChange(const QString &_name, const QV4::CompiledData::Binding *_binding, QQmlBinding::Identifier _id, const QString &_expr, const QUrl &_url, int _line, int _column)
QQmlProperty property(const QString &)
QQmlRefPointer< QV4::ExecutableCompilationUnit > compilationUnit
void decodeBinding(const QString &propertyPrefix, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &qmlUnit, const QV4::CompiledData::Binding *binding)
QList< QQuickReplaceSignalHandler * > signalReplacements
QList< ExpressionChange > expressions
QList< const QV4::CompiledData::Binding * > bindings
\qmltype PropertyChanges \inqmlmodule QtQuick
void copyOriginals(QQuickStateActionEvent *other) override
bool mayOverride(QQuickStateActionEvent *other) override
EventType type() const override
QQmlRefPointer< QQmlBoundSignalExpression > rewindExpression
QQmlRefPointer< QQmlBoundSignalExpression > reverseExpression
QQmlRefPointer< QQmlBoundSignalExpression > expression