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
qquickstateoperations.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#include "qquickitem_p.h"
7
8#include <private/qquickstate_p_p.h>
9
10#include <QtQml/qqmlinfo.h>
11
12#include <QtCore/qmath.h>
13#include <QtCore/qpointer.h>
14
15#include <memory>
16
17QT_BEGIN_NAMESPACE
18
19class QQuickParentChangePrivate : public QQuickStateOperationPrivate
20{
21 Q_DECLARE_PUBLIC(QQuickParentChange)
22public:
23 QQuickItem *target = nullptr;
24 QPointer<QQuickItem> parent;
25
26 struct StateSnapshot {
27 QPointer<QQuickItem> parent;
28 QPointer<QQuickItem> stackBefore;
29 qreal x = 0, y = 0, width = 0, height = 0, scale = 0, rotation = 0;
30 };
31
32 std::unique_ptr<StateSnapshot> orig;
33 std::unique_ptr<StateSnapshot> rewind;
34
35 QQmlNullableValue<QQmlScriptString> xString;
36 QQmlNullableValue<QQmlScriptString> yString;
37 QQmlNullableValue<QQmlScriptString> widthString;
38 QQmlNullableValue<QQmlScriptString> heightString;
39 QQmlNullableValue<QQmlScriptString> scaleString;
40 QQmlNullableValue<QQmlScriptString> rotationString;
41
42 void doChange(QQuickItem *targetParent);
43 void reverseRewindHelper(const std::unique_ptr<StateSnapshot> &snapshot);
44};
45
46void QQuickParentChangePrivate::doChange(QQuickItem *targetParent)
47{
48 if (targetParent && target && target->parentItem()) {
49 Q_Q(QQuickParentChange);
50 bool ok;
51 const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok);
52 if (transform.type() >= QTransform::TxShear || !ok) {
53 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under complex transform");
54 ok = false;
55 }
56
57 qreal scale = 1;
58 qreal rotation = 0;
59 bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
60 if (ok && !isRotate) {
61 if (transform.m11() == transform.m22())
62 scale = transform.m11();
63 else {
64 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
65 ok = false;
66 }
67 } else if (ok && isRotate) {
68 if (transform.m11() == transform.m22())
69 scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
70 else {
71 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
72 ok = false;
73 }
74
75 if (scale != 0)
76 rotation = qRadiansToDegrees(qAtan2(transform.m12() / scale, transform.m11() / scale));
77 else {
78 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0");
79 ok = false;
80 }
81 }
82
83 const QPointF &point = transform.map(QPointF(target->x(),target->y()));
84 qreal x = point.x();
85 qreal y = point.y();
86
87 // setParentItem will update the transformOriginPoint if needed
88 target->setParentItem(targetParent);
89
90 if (ok && target->transformOrigin() != QQuickItem::TopLeft) {
91 qreal tempxt = target->transformOriginPoint().x();
92 qreal tempyt = target->transformOriginPoint().y();
93 QTransform t;
94 t.translate(-tempxt, -tempyt);
95 t.rotate(rotation);
96 t.scale(scale, scale);
97 t.translate(tempxt, tempyt);
98 const QPointF &offset = t.map(QPointF(0,0));
99 x += offset.x();
100 y += offset.y();
101 }
102
103 if (ok) {
104 //qDebug() << x << y << rotation << scale;
105 target->setPosition(QPointF(x, y));
106 target->setRotation(target->rotation() + rotation);
107 target->setScale(target->scale() * scale);
108 }
109 } else if (target) {
110 target->setParentItem(targetParent);
111 }
112}
113
114/*!
115 \qmltype ParentChange
116 \nativetype QQuickParentChange
117 \inqmlmodule QtQuick
118 \ingroup qtquick-states
119 \brief Specifies how to reparent an Item in a state change.
120
121 ParentChange reparents an item while preserving its visual appearance (position, size,
122 rotation, and scale) on screen. You can then specify a transition to move/resize/rotate/scale
123 the item to its final intended appearance.
124
125 ParentChange can only preserve visual appearance if no complex transforms are involved.
126 More specifically, it will not work if the transform property has been set for any
127 items involved in the reparenting (i.e. items in the common ancestor tree
128 for the original and new parent).
129
130 The example below displays a large red rectangle and a small blue rectangle, side by side.
131 When the \c blueRect is clicked, it changes to the "reparented" state: its parent is changed to \c redRect and it is
132 positioned at (10, 10) within the red rectangle, as specified in the ParentChange.
133
134 \snippet qml/parentchange.qml 0
135
136 \image parentchange.png {Blue square state change affecting parent
137 reassignment}
138
139 You can specify at which point in a transition you want a ParentChange to occur by
140 using a ParentAnimation.
141
142 Note that unlike PropertyChanges, ParentChange expects an Item-based target; it will not work with
143 arbitrary objects (for example, you couldn't use it to reparent a Timer).
144*/
145
146QQuickParentChange::QQuickParentChange(QObject *parent)
147 : QQuickStateOperation(*(new QQuickParentChangePrivate), parent)
148{
149}
150
151/*!
152 \qmlproperty real QtQuick::ParentChange::x
153 \qmlproperty real QtQuick::ParentChange::y
154 \qmlproperty real QtQuick::ParentChange::width
155 \qmlproperty real QtQuick::ParentChange::height
156 \qmlproperty real QtQuick::ParentChange::scale
157 \qmlproperty real QtQuick::ParentChange::rotation
158 These properties hold the new position, size, scale, and rotation
159 for the item in this state.
160*/
161QQmlScriptString QQuickParentChange::x() const
162{
163 Q_D(const QQuickParentChange);
164 return d->xString.value();
165}
166
167void QQuickParentChange::setX(const QQmlScriptString &x)
168{
169 Q_D(QQuickParentChange);
170 d->xString = x;
171}
172
173bool QQuickParentChange::xIsSet() const
174{
175 Q_D(const QQuickParentChange);
176 return d->xString.isValid();
177}
178
179QQmlScriptString QQuickParentChange::y() const
180{
181 Q_D(const QQuickParentChange);
182 return d->yString.value();
183}
184
185void QQuickParentChange::setY(const QQmlScriptString &y)
186{
187 Q_D(QQuickParentChange);
188 d->yString = y;
189}
190
191bool QQuickParentChange::yIsSet() const
192{
193 Q_D(const QQuickParentChange);
194 return d->yString.isValid();
195}
196
197QQmlScriptString QQuickParentChange::width() const
198{
199 Q_D(const QQuickParentChange);
200 return d->widthString.value();
201}
202
203void QQuickParentChange::setWidth(const QQmlScriptString &width)
204{
205 Q_D(QQuickParentChange);
206 d->widthString = width;
207}
208
209bool QQuickParentChange::widthIsSet() const
210{
211 Q_D(const QQuickParentChange);
212 return d->widthString.isValid();
213}
214
215QQmlScriptString QQuickParentChange::height() const
216{
217 Q_D(const QQuickParentChange);
218 return d->heightString.value();
219}
220
221void QQuickParentChange::setHeight(const QQmlScriptString &height)
222{
223 Q_D(QQuickParentChange);
224 d->heightString = height;
225}
226
227bool QQuickParentChange::heightIsSet() const
228{
229 Q_D(const QQuickParentChange);
230 return d->heightString.isValid();
231}
232
233QQmlScriptString QQuickParentChange::scale() const
234{
235 Q_D(const QQuickParentChange);
236 return d->scaleString.value();
237}
238
239void QQuickParentChange::setScale(const QQmlScriptString &scale)
240{
241 Q_D(QQuickParentChange);
242 d->scaleString = scale;
243}
244
245bool QQuickParentChange::scaleIsSet() const
246{
247 Q_D(const QQuickParentChange);
248 return d->scaleString.isValid();
249}
250
251QQmlScriptString QQuickParentChange::rotation() const
252{
253 Q_D(const QQuickParentChange);
254 return d->rotationString.value();
255}
256
257void QQuickParentChange::setRotation(const QQmlScriptString &rotation)
258{
259 Q_D(QQuickParentChange);
260 d->rotationString = rotation;
261}
262
263bool QQuickParentChange::rotationIsSet() const
264{
265 Q_D(const QQuickParentChange);
266 return d->rotationString.isValid();
267}
268
269QQuickItem *QQuickParentChange::originalParent() const
270{
271 Q_D(const QQuickParentChange);
272 return d->orig ? d->orig->parent : nullptr;
273}
274
275/*!
276 \qmlproperty Item QtQuick::ParentChange::target
277 This property holds the item to be reparented
278*/
279QQuickItem *QQuickParentChange::object() const
280{
281 Q_D(const QQuickParentChange);
282 return d->target;
283}
284
285void QQuickParentChange::setObject(QQuickItem *target)
286{
287 Q_D(QQuickParentChange);
288 d->target = target;
289}
290
291/*!
292 \qmlproperty Item QtQuick::ParentChange::parent
293 This property holds the new parent for the item in this state.
294*/
295QQuickItem *QQuickParentChange::parent() const
296{
297 Q_D(const QQuickParentChange);
298 return d->parent;
299}
300
301void QQuickParentChange::setParent(QQuickItem *parent)
302{
303 Q_D(QQuickParentChange);
304 d->parent = parent;
305}
306
307QQuickStateOperation::ActionList QQuickParentChange::actions()
308{
309 Q_D(QQuickParentChange);
310 if (!d->target || !d->parent)
311 return ActionList();
312
313 ActionList actions;
314
315 QQuickStateAction a;
316 a.event = this;
317 actions << a;
318
319 if (d->xString.isValid()) {
320 bool ok = false;
321 qreal x = d->xString.value().numberLiteral(&ok);
322 if (ok) {
323 QQuickStateAction xa(d->target, QLatin1String("x"), x);
324 actions << xa;
325 } else {
326 QQmlProperty property(d->target, QLatin1String("x"));
327 auto newBinding = QQmlAnyBinding::createFromScriptString(
328 property, d->xString.value(), d->target, qmlContext(this));
329 QQuickStateAction xa;
330 xa.property = property;
331 xa.toBinding = newBinding;
332 xa.fromValue = xa.property.read();
333 xa.deletableToBinding = true;
334 actions << xa;
335 }
336 }
337
338 if (d->yString.isValid()) {
339 bool ok = false;
340 qreal y = d->yString.value().numberLiteral(&ok);
341 if (ok) {
342 QQuickStateAction ya(d->target, QLatin1String("y"), y);
343 actions << ya;
344 } else {
345 QQmlProperty property(d->target, QLatin1String("y"));
346 auto newBinding = QQmlAnyBinding::createFromScriptString(
347 property, d->yString.value(), d->target, qmlContext(this));
348 QQuickStateAction ya;
349 ya.property = property;
350 ya.toBinding = newBinding;
351 ya.fromValue = ya.property.read();
352 ya.deletableToBinding = true;
353 actions << ya;
354 }
355 }
356
357 if (d->scaleString.isValid()) {
358 bool ok = false;
359 qreal scale = d->scaleString.value().numberLiteral(&ok);
360 if (ok) {
361 QQuickStateAction sa(d->target, QLatin1String("scale"), scale);
362 actions << sa;
363 } else {
364 QQmlProperty property(d->target, QLatin1String("scale"));
365 auto newBinding = QQmlAnyBinding::createFromScriptString(
366 property, d->scaleString.value(), d->target, qmlContext(this));
367 QQuickStateAction sa;
368 sa.property = property;
369 sa.toBinding = newBinding;
370 sa.fromValue = sa.property.read();
371 sa.deletableToBinding = true;
372 actions << sa;
373 }
374 }
375
376 if (d->rotationString.isValid()) {
377 bool ok = false;
378 qreal rotation = d->rotationString.value().numberLiteral(&ok);
379 if (ok) {
380 QQuickStateAction ra(d->target, QLatin1String("rotation"), rotation);
381 actions << ra;
382 } else {
383 QQmlProperty property(d->target, QLatin1String("rotation"));
384 auto newBinding = QQmlAnyBinding::createFromScriptString(
385 property, d->rotationString.value(), d->target, qmlContext(this));
386 QQuickStateAction ra;
387 ra.property = property;
388 ra.toBinding = newBinding;
389 ra.fromValue = ra.property.read();
390 ra.deletableToBinding = true;
391 actions << ra;
392 }
393 }
394
395 if (d->widthString.isValid()) {
396 bool ok = false;
397 qreal width = d->widthString.value().numberLiteral(&ok);
398 if (ok) {
399 QQuickStateAction wa(d->target, QLatin1String("width"), width);
400 actions << wa;
401 } else {
402 QQmlProperty property(d->target, QLatin1String("width"));
403 auto newBinding = QQmlAnyBinding::createFromScriptString(property, d->widthString, d->target, qmlContext(this));
404 QQuickStateAction wa;
405 wa.property = property;
406 wa.toBinding = newBinding;
407 wa.fromValue = wa.property.read();
408 wa.deletableToBinding = true;
409 actions << wa;
410 }
411 }
412
413 if (d->heightString.isValid()) {
414 bool ok = false;
415 qreal height = d->heightString.value().numberLiteral(&ok);
416 if (ok) {
417 QQuickStateAction ha(d->target, QLatin1String("height"), height);
418 actions << ha;
419 } else {
420 QQmlProperty property(d->target, QLatin1String("height"));
421 auto newBinding = QQmlAnyBinding::createFromScriptString(property, d->heightString, d->target, qmlContext(this));
422 QQuickStateAction ha;
423 ha.property = property;
424 ha.toBinding = newBinding;
425 ha.fromValue = ha.property.read();
426 ha.deletableToBinding = true;
427 actions << ha;
428 }
429 }
430
431 return actions;
432}
433
434void QQuickParentChange::saveOriginals()
435{
436 Q_D(QQuickParentChange);
437 saveCurrentValues();
438 if (!d->orig)
439 d->orig.reset(new QQuickParentChangePrivate::StateSnapshot);
440 *d->orig = *d->rewind;
441}
442
443void QQuickParentChange::execute()
444{
445 Q_D(QQuickParentChange);
446 d->doChange(d->parent);
447}
448
449bool QQuickParentChange::isReversable()
450{
451 return true;
452}
453
454void QQuickParentChangePrivate::reverseRewindHelper(const std::unique_ptr<QQuickParentChangePrivate::StateSnapshot> &snapshot)
455{
456 if (!target || !snapshot)
457 return;
458
459 // leave existing bindings alive; new bindings are applied in applyBindings
460 // setPosition and setSize update the geometry without invalidating bindings
461 target->setPosition(QPointF(snapshot->x, snapshot->y));
462 target->setSize(QSizeF(snapshot->width, snapshot->height));
463
464 target->setScale(snapshot->scale);
465 target->setRotation(snapshot->rotation);
466 target->setParentItem(snapshot->parent);
467 if (snapshot->stackBefore)
468 target->stackBefore(snapshot->stackBefore);
469}
470
471
472void QQuickParentChange::reverse()
473{
474 Q_D(QQuickParentChange);
475 d->reverseRewindHelper(d->orig);
476}
477
478QQuickStateActionEvent::EventType QQuickParentChange::type() const
479{
480 return ParentChange;
481}
482
483bool QQuickParentChange::mayOverride(QQuickStateActionEvent*other)
484{
485 Q_D(QQuickParentChange);
486 if (other->type() != ParentChange)
487 return false;
488 if (QQuickParentChange *otherPC = static_cast<QQuickParentChange*>(other))
489 return (d->target == otherPC->object());
490 return false;
491}
492
493void QQuickParentChange::saveCurrentValues()
494{
495 Q_D(QQuickParentChange);
496 if (!d->target) {
497 d->rewind = nullptr;
498 return;
499 }
500
501 d->rewind.reset(new QQuickParentChangePrivate::StateSnapshot);
502 d->rewind->x = d->target->x();
503 d->rewind->y = d->target->y();
504 d->rewind->scale = d->target->scale();
505 d->rewind->width = d->target->width();
506 d->rewind->height = d->target->height();
507 d->rewind->rotation = d->target->rotation();
508
509 d->rewind->parent = d->target->parentItem();
510 d->rewind->stackBefore = nullptr;
511
512 if (!d->rewind->parent)
513 return;
514
515 QList<QQuickItem *> children = d->rewind->parent->childItems();
516 for (int ii = 0; ii < children.size() - 1; ++ii) {
517 if (children.at(ii) == d->target) {
518 d->rewind->stackBefore = children.at(ii + 1);
519 break;
520 }
521 }
522}
523
524void QQuickParentChange::rewind()
525{
526 Q_D(QQuickParentChange);
527 d->reverseRewindHelper(d->rewind);
528 d->rewind.reset();
529}
530
531/*!
532 \qmltype AnchorChanges
533 \nativetype QQuickAnchorChanges
534 \inqmlmodule QtQuick
535 \ingroup qtquick-states
536 \brief Specifies how to change the anchors of an item in a state.
537
538 The AnchorChanges type is used to modify the anchors of an item in a \l State.
539
540 AnchorChanges cannot be used to modify the margins on an item. For this, use
541 PropertyChanges instead.
542
543 In the following example we change the top and bottom anchors of an item
544 using AnchorChanges, and the top and bottom anchor margins using
545 PropertyChanges:
546
547 \snippet qml/anchorchanges.qml 0
548
549 \image anchorchanges.png {Red square changing anchor position
550 between two states}
551
552 AnchorChanges can be animated using AnchorAnimation.
553 \qml
554 //animate our anchor changes
555 Transition {
556 AnchorAnimation {}
557 }
558 \endqml
559
560 Changes to anchor margins can be animated using NumberAnimation.
561
562 For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
563*/
564
580
581QQuickAnchorSet::QQuickAnchorSet(QObject *parent)
582 : QObject(*new QQuickAnchorSetPrivate, parent)
583{
584}
585
586QQuickAnchorSet::~QQuickAnchorSet()
587{
588}
589
590QQmlScriptString QQuickAnchorSet::top() const
591{
592 Q_D(const QQuickAnchorSet);
593 return d->topScript;
594}
595
596void QQuickAnchorSet::setTop(const QQmlScriptString &edge)
597{
598 Q_D(QQuickAnchorSet);
599 d->usedAnchors |= QQuickAnchors::TopAnchor;
600 d->topScript = edge;
601 if (edge.isUndefinedLiteral())
602 resetTop();
603}
604
605void QQuickAnchorSet::resetTop()
606{
607 Q_D(QQuickAnchorSet);
608 d->usedAnchors &= ~QQuickAnchors::TopAnchor;
609 d->resetAnchors |= QQuickAnchors::TopAnchor;
610}
611
612QQmlScriptString QQuickAnchorSet::bottom() const
613{
614 Q_D(const QQuickAnchorSet);
615 return d->bottomScript;
616}
617
618void QQuickAnchorSet::setBottom(const QQmlScriptString &edge)
619{
620 Q_D(QQuickAnchorSet);
621 d->usedAnchors |= QQuickAnchors::BottomAnchor;
622 d->bottomScript = edge;
623 if (edge.isUndefinedLiteral())
624 resetBottom();
625}
626
627void QQuickAnchorSet::resetBottom()
628{
629 Q_D(QQuickAnchorSet);
630 d->usedAnchors &= ~QQuickAnchors::BottomAnchor;
631 d->resetAnchors |= QQuickAnchors::BottomAnchor;
632}
633
634QQmlScriptString QQuickAnchorSet::verticalCenter() const
635{
636 Q_D(const QQuickAnchorSet);
637 return d->vCenterScript;
638}
639
640void QQuickAnchorSet::setVerticalCenter(const QQmlScriptString &edge)
641{
642 Q_D(QQuickAnchorSet);
643 d->usedAnchors |= QQuickAnchors::VCenterAnchor;
644 d->vCenterScript = edge;
645 if (edge.isUndefinedLiteral())
646 resetVerticalCenter();
647}
648
649void QQuickAnchorSet::resetVerticalCenter()
650{
651 Q_D(QQuickAnchorSet);
652 d->usedAnchors &= ~QQuickAnchors::VCenterAnchor;
653 d->resetAnchors |= QQuickAnchors::VCenterAnchor;
654}
655
656QQmlScriptString QQuickAnchorSet::baseline() const
657{
658 Q_D(const QQuickAnchorSet);
659 return d->baselineScript;
660}
661
662void QQuickAnchorSet::setBaseline(const QQmlScriptString &edge)
663{
664 Q_D(QQuickAnchorSet);
665 d->usedAnchors |= QQuickAnchors::BaselineAnchor;
666 d->baselineScript = edge;
667 if (edge.isUndefinedLiteral())
668 resetBaseline();
669}
670
671void QQuickAnchorSet::resetBaseline()
672{
673 Q_D(QQuickAnchorSet);
674 d->usedAnchors &= ~QQuickAnchors::BaselineAnchor;
675 d->resetAnchors |= QQuickAnchors::BaselineAnchor;
676}
677
678QQmlScriptString QQuickAnchorSet::left() const
679{
680 Q_D(const QQuickAnchorSet);
681 return d->leftScript;
682}
683
684void QQuickAnchorSet::setLeft(const QQmlScriptString &edge)
685{
686 Q_D(QQuickAnchorSet);
687 d->usedAnchors |= QQuickAnchors::LeftAnchor;
688 d->leftScript = edge;
689 if (edge.isUndefinedLiteral())
690 resetLeft();
691}
692
693void QQuickAnchorSet::resetLeft()
694{
695 Q_D(QQuickAnchorSet);
696 d->usedAnchors &= ~QQuickAnchors::LeftAnchor;
697 d->resetAnchors |= QQuickAnchors::LeftAnchor;
698}
699
700QQmlScriptString QQuickAnchorSet::right() const
701{
702 Q_D(const QQuickAnchorSet);
703 return d->rightScript;
704}
705
706void QQuickAnchorSet::setRight(const QQmlScriptString &edge)
707{
708 Q_D(QQuickAnchorSet);
709 d->usedAnchors |= QQuickAnchors::RightAnchor;
710 d->rightScript = edge;
711 if (edge.isUndefinedLiteral())
712 resetRight();
713}
714
715void QQuickAnchorSet::resetRight()
716{
717 Q_D(QQuickAnchorSet);
718 d->usedAnchors &= ~QQuickAnchors::RightAnchor;
719 d->resetAnchors |= QQuickAnchors::RightAnchor;
720}
721
722QQmlScriptString QQuickAnchorSet::horizontalCenter() const
723{
724 Q_D(const QQuickAnchorSet);
725 return d->hCenterScript;
726}
727
728void QQuickAnchorSet::setHorizontalCenter(const QQmlScriptString &edge)
729{
730 Q_D(QQuickAnchorSet);
731 d->usedAnchors |= QQuickAnchors::HCenterAnchor;
732 d->hCenterScript = edge;
733 if (edge.isUndefinedLiteral())
734 resetHorizontalCenter();
735}
736
737void QQuickAnchorSet::resetHorizontalCenter()
738{
739 Q_D(QQuickAnchorSet);
740 d->usedAnchors &= ~QQuickAnchors::HCenterAnchor;
741 d->resetAnchors |= QQuickAnchors::HCenterAnchor;
742}
743
745{
746public:
748 : target(nullptr), anchorSet(new QQuickAnchorSet)
749 {
750
751 }
752 ~QQuickAnchorChangesPrivate() { delete anchorSet; }
753
754 QQuickItem *target;
756
764
772
773 QQuickAnchorLine rewindLeft;
774 QQuickAnchorLine rewindRight;
775 QQuickAnchorLine rewindHCenter;
776 QQuickAnchorLine rewindTop;
777 QQuickAnchorLine rewindBottom;
778 QQuickAnchorLine rewindVCenter;
779 QQuickAnchorLine rewindBaseline;
780
785
790
795
803
808
816};
817
818QQuickAnchorChanges::QQuickAnchorChanges(QObject *parent)
819 : QQuickStateOperation(*(new QQuickAnchorChangesPrivate), parent)
820{
821}
822
823QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions()
824{
825 Q_D(QQuickAnchorChanges);
826 //### ASSERT these are all 0?
827 d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding
828 = d->bottomBinding = d->vCenterBinding = d->baselineBinding = nullptr;
829
830 d->leftProp = QQmlProperty(d->target, QLatin1String("anchors.left"));
831 d->rightProp = QQmlProperty(d->target, QLatin1String("anchors.right"));
832 d->hCenterProp = QQmlProperty(d->target, QLatin1String("anchors.horizontalCenter"));
833 d->topProp = QQmlProperty(d->target, QLatin1String("anchors.top"));
834 d->bottomProp = QQmlProperty(d->target, QLatin1String("anchors.bottom"));
835 d->vCenterProp = QQmlProperty(d->target, QLatin1String("anchors.verticalCenter"));
836 d->baselineProp = QQmlProperty(d->target, QLatin1String("anchors.baseline"));
837
838 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::LeftAnchor) {
839 d->leftBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->leftProp)->core, d->anchorSet->d_func()->leftScript, d->target, qmlContext(this));
840 d->leftBinding->setTarget(d->leftProp);
841 }
842 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::RightAnchor) {
843 d->rightBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->rightProp)->core, d->anchorSet->d_func()->rightScript, d->target, qmlContext(this));
844 d->rightBinding->setTarget(d->rightProp);
845 }
846 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::HCenterAnchor) {
847 d->hCenterBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->hCenterProp)->core, d->anchorSet->d_func()->hCenterScript, d->target, qmlContext(this));
848 d->hCenterBinding->setTarget(d->hCenterProp);
849 }
850 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::TopAnchor) {
851 d->topBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->topProp)->core, d->anchorSet->d_func()->topScript, d->target, qmlContext(this));
852 d->topBinding->setTarget(d->topProp);
853 }
854 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::BottomAnchor) {
855 d->bottomBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->bottomProp)->core, d->anchorSet->d_func()->bottomScript, d->target, qmlContext(this));
856 d->bottomBinding->setTarget(d->bottomProp);
857 }
858 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::VCenterAnchor) {
859 d->vCenterBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->vCenterProp)->core, d->anchorSet->d_func()->vCenterScript, d->target, qmlContext(this));
860 d->vCenterBinding->setTarget(d->vCenterProp);
861 }
862 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::BaselineAnchor) {
863 d->baselineBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->baselineProp)->core, d->anchorSet->d_func()->baselineScript, d->target, qmlContext(this));
864 d->baselineBinding->setTarget(d->baselineProp);
865 }
866
867 QQuickStateAction a;
868 a.event = this;
869 return ActionList() << a;
870}
871
872QQuickAnchorSet *QQuickAnchorChanges::anchors() const
873{
874 Q_D(const QQuickAnchorChanges);
875 return d->anchorSet;
876}
877
878/*!
879 \qmlproperty Item QtQuick::AnchorChanges::target
880 This property holds the \l Item for which the anchor changes will be applied.
881*/
882QQuickItem *QQuickAnchorChanges::object() const
883{
884 Q_D(const QQuickAnchorChanges);
885 return d->target;
886}
887
888void QQuickAnchorChanges::setObject(QQuickItem *target)
889{
890 Q_D(QQuickAnchorChanges);
891 d->target = target;
892}
893
894/*!
895 \qmlpropertygroup QtQuick::AnchorChanges::anchors
896 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.left
897 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.right
898 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.horizontalCenter
899 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.top
900 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.bottom
901 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.verticalCenter
902 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.baseline
903
904 These properties change the respective anchors of the item.
905
906 To reset an anchor you can assign \c undefined:
907 \qml
908 AnchorChanges {
909 target: myItem
910 anchors.left: undefined //remove myItem's left anchor
911 anchors.right: otherItem.right
912 }
913 \endqml
914*/
915
916void QQuickAnchorChanges::execute()
917{
918 Q_D(QQuickAnchorChanges);
919 if (!d->target)
920 return;
921
922 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
923 //incorporate any needed "reverts"
924 if (d->applyOrigLeft) {
925 if (!d->origLeftBinding)
926 targetPrivate->anchors()->resetLeft();
927 QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
928 }
929 if (d->applyOrigRight) {
930 if (!d->origRightBinding)
931 targetPrivate->anchors()->resetRight();
932 QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
933 }
934 if (d->applyOrigHCenter) {
935 if (!d->origHCenterBinding)
936 targetPrivate->anchors()->resetHorizontalCenter();
937 QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
938 }
939 if (d->applyOrigTop) {
940 if (!d->origTopBinding)
941 targetPrivate->anchors()->resetTop();
942 QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
943 }
944 if (d->applyOrigBottom) {
945 if (!d->origBottomBinding)
946 targetPrivate->anchors()->resetBottom();
947 QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
948 }
949 if (d->applyOrigVCenter) {
950 if (!d->origVCenterBinding)
951 targetPrivate->anchors()->resetVerticalCenter();
952 QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
953 }
954 if (d->applyOrigBaseline) {
955 if (!d->origBaselineBinding)
956 targetPrivate->anchors()->resetBaseline();
957 QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
958 }
959
960 //reset any anchors that have been specified as "undefined"
961 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::LeftAnchor) {
962 targetPrivate->anchors()->resetLeft();
963 QQmlPropertyPrivate::removeBinding(d->leftProp);
964 }
965 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) {
966 targetPrivate->anchors()->resetRight();
967 QQmlPropertyPrivate::removeBinding(d->rightProp);
968 }
969 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) {
970 targetPrivate->anchors()->resetHorizontalCenter();
971 QQmlPropertyPrivate::removeBinding(d->hCenterProp);
972 }
973 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) {
974 targetPrivate->anchors()->resetTop();
975 QQmlPropertyPrivate::removeBinding(d->topProp);
976 }
977 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) {
978 targetPrivate->anchors()->resetBottom();
979 QQmlPropertyPrivate::removeBinding(d->bottomProp);
980 }
981 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) {
982 targetPrivate->anchors()->resetVerticalCenter();
983 QQmlPropertyPrivate::removeBinding(d->vCenterProp);
984 }
985 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) {
986 targetPrivate->anchors()->resetBaseline();
987 QQmlPropertyPrivate::removeBinding(d->baselineProp);
988 }
989
990 //set any anchors that have been specified
991 if (d->leftBinding)
992 QQmlPropertyPrivate::setBinding(d->leftBinding.data());
993 if (d->rightBinding)
994 QQmlPropertyPrivate::setBinding(d->rightBinding.data());
995 if (d->hCenterBinding)
996 QQmlPropertyPrivate::setBinding(d->hCenterBinding.data());
997 if (d->topBinding)
998 QQmlPropertyPrivate::setBinding(d->topBinding.data());
999 if (d->bottomBinding)
1000 QQmlPropertyPrivate::setBinding(d->bottomBinding.data());
1001 if (d->vCenterBinding)
1002 QQmlPropertyPrivate::setBinding(d->vCenterBinding.data());
1003 if (d->baselineBinding)
1004 QQmlPropertyPrivate::setBinding(d->baselineBinding.data());
1005}
1006
1007bool QQuickAnchorChanges::isReversable()
1008{
1009 return true;
1010}
1011
1012void QQuickAnchorChanges::reverse()
1013{
1014 Q_D(QQuickAnchorChanges);
1015 if (!d->target)
1016 return;
1017
1018 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1019 //reset any anchors set by the state
1020 if (d->leftBinding) {
1021 targetPrivate->anchors()->resetLeft();
1022 QQmlPropertyPrivate::removeBinding(d->leftBinding.data());
1023 }
1024 if (d->rightBinding) {
1025 targetPrivate->anchors()->resetRight();
1026 QQmlPropertyPrivate::removeBinding(d->rightBinding.data());
1027 }
1028 if (d->hCenterBinding) {
1029 targetPrivate->anchors()->resetHorizontalCenter();
1030 QQmlPropertyPrivate::removeBinding(d->hCenterBinding.data());
1031 }
1032 if (d->topBinding) {
1033 targetPrivate->anchors()->resetTop();
1034 QQmlPropertyPrivate::removeBinding(d->topBinding.data());
1035 }
1036 if (d->bottomBinding) {
1037 targetPrivate->anchors()->resetBottom();
1038 QQmlPropertyPrivate::removeBinding(d->bottomBinding.data());
1039 }
1040 if (d->vCenterBinding) {
1041 targetPrivate->anchors()->resetVerticalCenter();
1042 QQmlPropertyPrivate::removeBinding(d->vCenterBinding.data());
1043 }
1044 if (d->baselineBinding) {
1045 targetPrivate->anchors()->resetBaseline();
1046 QQmlPropertyPrivate::removeBinding(d->baselineBinding.data());
1047 }
1048
1049 //restore previous anchors
1050 if (d->origLeftBinding)
1051 QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
1052 if (d->origRightBinding)
1053 QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
1054 if (d->origHCenterBinding)
1055 QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
1056 if (d->origTopBinding)
1057 QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
1058 if (d->origBottomBinding)
1059 QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
1060 if (d->origVCenterBinding)
1061 QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
1062 if (d->origBaselineBinding)
1063 QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
1064
1065 //restore any absolute geometry changed by the state's anchors
1066 QQuickAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Vertical_Mask;
1067 QQuickAnchors::Anchors origVAnchors = targetPrivate->anchors()->usedAnchors() & QQuickAnchors::Vertical_Mask;
1068 QQuickAnchors::Anchors resetVAnchors = d->anchorSet->d_func()->resetAnchors & QQuickAnchors::Vertical_Mask;
1069 QQuickAnchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Horizontal_Mask;
1070 QQuickAnchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QQuickAnchors::Horizontal_Mask;
1071 QQuickAnchors::Anchors resetHAnchors = d->anchorSet->d_func()->resetAnchors & QQuickAnchors::Horizontal_Mask;
1072
1073 const QRectF oldGeometry(d->target->position(), d->target->size());
1074 bool stateSetWidth = (stateHAnchors &&
1075 stateHAnchors != QQuickAnchors::LeftAnchor &&
1076 stateHAnchors != QQuickAnchors::RightAnchor &&
1077 stateHAnchors != QQuickAnchors::HCenterAnchor);
1078 // in case of an additive AnchorChange, we _did_ end up modifying the width, unless opposite
1079 // edge was set to undefined in state
1080 stateSetWidth |= ((stateHAnchors & QQuickAnchors::LeftAnchor)
1081 && (origHAnchors & QQuickAnchors::RightAnchor)
1082 && !(resetHAnchors & QQuickAnchors::RightAnchor))
1083 || ((stateHAnchors & QQuickAnchors::RightAnchor)
1084 && (origHAnchors & QQuickAnchors::LeftAnchor)
1085 && !(resetHAnchors & QQuickAnchors::LeftAnchor));
1086 bool origSetWidth = (origHAnchors &&
1087 origHAnchors != QQuickAnchors::LeftAnchor &&
1088 origHAnchors != QQuickAnchors::RightAnchor &&
1089 origHAnchors != QQuickAnchors::HCenterAnchor);
1090 if (d->origWidth.isValid() && stateSetWidth && !origSetWidth && !qt_is_nan(d->origWidth)) {
1091 targetPrivate->widthValidFlag = true;
1092 if (targetPrivate->width != d->origWidth)
1093 targetPrivate->width.setValueBypassingBindings(d->origWidth);
1094 }
1095
1096 bool stateSetHeight = (stateVAnchors &&
1097 stateVAnchors != QQuickAnchors::TopAnchor &&
1098 stateVAnchors != QQuickAnchors::BottomAnchor &&
1099 stateVAnchors != QQuickAnchors::VCenterAnchor &&
1100 stateVAnchors != QQuickAnchors::BaselineAnchor);
1101 // in case of an additive AnchorChange, we _did_ end up modifying the height, unless opposite
1102 // edge was set to undefined in state
1103 stateSetHeight |= ((stateVAnchors & QQuickAnchors::TopAnchor)
1104 && (origVAnchors & QQuickAnchors::BottomAnchor)
1105 && !(resetVAnchors & QQuickAnchors::BottomAnchor))
1106 || ((stateVAnchors & QQuickAnchors::BottomAnchor)
1107 && (origVAnchors & QQuickAnchors::TopAnchor)
1108 && !(resetVAnchors & QQuickAnchors::TopAnchor));
1109 bool origSetHeight = (origVAnchors &&
1110 origVAnchors != QQuickAnchors::TopAnchor &&
1111 origVAnchors != QQuickAnchors::BottomAnchor &&
1112 origVAnchors != QQuickAnchors::VCenterAnchor &&
1113 origVAnchors != QQuickAnchors::BaselineAnchor);
1114 if (d->origHeight.isValid() && stateSetHeight && !origSetHeight && !qt_is_nan(d->origHeight)) {
1115 targetPrivate->heightValidFlag = true;
1116 if (targetPrivate->height != d->origHeight)
1117 targetPrivate->height.setValueBypassingBindings(d->origHeight);
1118 }
1119
1120 if (stateHAnchors && !origHAnchors && !qt_is_nan(d->origX) && d->origX != targetPrivate->x)
1121 targetPrivate->x.setValueBypassingBindings(d->origX);
1122
1123 if (stateVAnchors && !origVAnchors && !qt_is_nan(d->origY) && d->origY != targetPrivate->y)
1124 targetPrivate->y.setValueBypassingBindings(d->origY);
1125
1126 const QRectF newGeometry(d->target->position(), d->target->size());
1127 if (newGeometry != oldGeometry) {
1128 QQuickItemPrivate::DirtyType dirtyFlags {};
1129 if (newGeometry.topLeft() != oldGeometry.topLeft())
1130 dirtyFlags = QQuickItemPrivate::DirtyType(dirtyFlags | QQuickItemPrivate::Position);
1131 if (newGeometry.size() != oldGeometry.size())
1132 dirtyFlags = QQuickItemPrivate::DirtyType(dirtyFlags | QQuickItemPrivate::Size);
1133 targetPrivate->dirty(dirtyFlags);
1134 d->target->geometryChange(newGeometry, oldGeometry);
1135 }
1136}
1137
1138QQuickStateActionEvent::EventType QQuickAnchorChanges::type() const
1139{
1140 return AnchorChanges;
1141}
1142
1143QList<QQuickStateAction> QQuickAnchorChanges::additionalActions() const
1144{
1145 Q_D(const QQuickAnchorChanges);
1146 QList<QQuickStateAction> extra;
1147
1148 QQuickAnchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors;
1149 bool hChange = combined & QQuickAnchors::Horizontal_Mask;
1150 bool vChange = combined & QQuickAnchors::Vertical_Mask;
1151
1152 if (d->target) {
1153 QQuickStateAction a;
1154 if (hChange && d->fromX != d->toX) {
1155 a.property = QQmlProperty(d->target, QLatin1String("x"));
1156 a.toValue = d->toX;
1157 extra << a;
1158 }
1159 if (vChange && d->fromY != d->toY) {
1160 a.property = QQmlProperty(d->target, QLatin1String("y"));
1161 a.toValue = d->toY;
1162 extra << a;
1163 }
1164 if (hChange && d->fromWidth != d->toWidth) {
1165 a.property = QQmlProperty(d->target, QLatin1String("width"));
1166 a.toValue = d->toWidth;
1167 extra << a;
1168 }
1169 if (vChange && d->fromHeight != d->toHeight) {
1170 a.property = QQmlProperty(d->target, QLatin1String("height"));
1171 a.toValue = d->toHeight;
1172 extra << a;
1173 }
1174 }
1175
1176 return extra;
1177}
1178
1179bool QQuickAnchorChanges::changesBindings()
1180{
1181 return true;
1182}
1183
1184void QQuickAnchorChanges::saveOriginals()
1185{
1186 Q_D(QQuickAnchorChanges);
1187 if (!d->target)
1188 return;
1189
1190 d->origLeftBinding = QQmlPropertyPrivate::binding(d->leftProp);
1191 d->origRightBinding = QQmlPropertyPrivate::binding(d->rightProp);
1192 d->origHCenterBinding = QQmlPropertyPrivate::binding(d->hCenterProp);
1193 d->origTopBinding = QQmlPropertyPrivate::binding(d->topProp);
1194 d->origBottomBinding = QQmlPropertyPrivate::binding(d->bottomProp);
1195 d->origVCenterBinding = QQmlPropertyPrivate::binding(d->vCenterProp);
1196 d->origBaselineBinding = QQmlPropertyPrivate::binding(d->baselineProp);
1197
1198 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1199 if (targetPrivate->widthValid())
1200 d->origWidth = d->target->width();
1201 if (targetPrivate->heightValid())
1202 d->origHeight = d->target->height();
1203 d->origX = d->target->x();
1204 d->origY = d->target->y();
1205
1206 d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
1207 = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
1208
1209 saveCurrentValues();
1210}
1211
1212void QQuickAnchorChanges::copyOriginals(QQuickStateActionEvent *other)
1213{
1214 Q_D(QQuickAnchorChanges);
1215 QQuickAnchorChanges *ac = static_cast<QQuickAnchorChanges*>(other);
1216 QQuickAnchorChangesPrivate *acp = ac->d_func();
1217
1218 QQuickAnchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors |
1219 acp->anchorSet->d_func()->resetAnchors;
1220
1221 //probably also need to revert some things
1222 d->applyOrigLeft = (combined & QQuickAnchors::LeftAnchor);
1223 d->applyOrigRight = (combined & QQuickAnchors::RightAnchor);
1224 d->applyOrigHCenter = (combined & QQuickAnchors::HCenterAnchor);
1225 d->applyOrigTop = (combined & QQuickAnchors::TopAnchor);
1226 d->applyOrigBottom = (combined & QQuickAnchors::BottomAnchor);
1227 d->applyOrigVCenter = (combined & QQuickAnchors::VCenterAnchor);
1228 d->applyOrigBaseline = (combined & QQuickAnchors::BaselineAnchor);
1229
1230 d->origLeftBinding = acp->origLeftBinding;
1231 d->origRightBinding = acp->origRightBinding;
1232 d->origHCenterBinding = acp->origHCenterBinding;
1233 d->origTopBinding = acp->origTopBinding;
1234 d->origBottomBinding = acp->origBottomBinding;
1235 d->origVCenterBinding = acp->origVCenterBinding;
1236 d->origBaselineBinding = acp->origBaselineBinding;
1237
1238 d->origWidth = acp->origWidth;
1239 d->origHeight = acp->origHeight;
1240 d->origX = acp->origX;
1241 d->origY = acp->origY;
1242
1243 //clear old values from other
1244 //### could this be generalized for all QQuickStateActionEvents, and called after copyOriginals?
1245 acp->leftBinding = nullptr;
1246 acp->rightBinding = nullptr;
1247 acp->hCenterBinding = nullptr;
1248 acp->topBinding = nullptr;
1249 acp->bottomBinding = nullptr;
1250 acp->vCenterBinding = nullptr;
1251 acp->baselineBinding = nullptr;
1252 acp->origLeftBinding = nullptr;
1253 acp->origRightBinding = nullptr;
1254 acp->origHCenterBinding = nullptr;
1255 acp->origTopBinding = nullptr;
1256 acp->origBottomBinding = nullptr;
1257 acp->origVCenterBinding = nullptr;
1258 acp->origBaselineBinding = nullptr;
1259
1260 saveCurrentValues();
1261}
1262
1263void QQuickAnchorChanges::clearBindings()
1264{
1265 Q_D(QQuickAnchorChanges);
1266 if (!d->target)
1267 return;
1268
1269 //### should this (saving "from" values) be moved to saveCurrentValues()?
1270 d->fromX = d->target->x();
1271 d->fromY = d->target->y();
1272 d->fromWidth = d->target->width();
1273 d->fromHeight = d->target->height();
1274
1275 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1276 //reset any anchors with corresponding reverts
1277 //reset any anchors that have been specified as "undefined"
1278 //reset any anchors that we'll be setting in the state
1279 QQuickAnchors::Anchors combined = d->anchorSet->d_func()->resetAnchors |
1280 d->anchorSet->d_func()->usedAnchors;
1281 if (d->applyOrigLeft || (combined & QQuickAnchors::LeftAnchor)) {
1282 targetPrivate->anchors()->resetLeft();
1283 QQmlPropertyPrivate::removeBinding(d->leftProp);
1284 }
1285 if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) {
1286 targetPrivate->anchors()->resetRight();
1287 QQmlPropertyPrivate::removeBinding(d->rightProp);
1288 }
1289 if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) {
1290 targetPrivate->anchors()->resetHorizontalCenter();
1291 QQmlPropertyPrivate::removeBinding(d->hCenterProp);
1292 }
1293 if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) {
1294 targetPrivate->anchors()->resetTop();
1295 QQmlPropertyPrivate::removeBinding(d->topProp);
1296 }
1297 if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) {
1298 targetPrivate->anchors()->resetBottom();
1299 QQmlPropertyPrivate::removeBinding(d->bottomProp);
1300 }
1301 if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) {
1302 targetPrivate->anchors()->resetVerticalCenter();
1303 QQmlPropertyPrivate::removeBinding(d->vCenterProp);
1304 }
1305 if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) {
1306 targetPrivate->anchors()->resetBaseline();
1307 QQmlPropertyPrivate::removeBinding(d->baselineProp);
1308 }
1309}
1310
1311bool QQuickAnchorChanges::mayOverride(QQuickStateActionEvent*other)
1312{
1313 if (other->type() != AnchorChanges)
1314 return false;
1315 if (static_cast<QQuickStateActionEvent*>(this) == other)
1316 return true;
1317 if (static_cast<QQuickAnchorChanges*>(other)->object() == object())
1318 return true;
1319 return false;
1320}
1321
1322void QQuickAnchorChanges::rewind()
1323{
1324 Q_D(QQuickAnchorChanges);
1325 if (!d->target)
1326 return;
1327
1328 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1329 const QRectF oldGeometry(d->target->position(), d->target->size());
1330
1331 // Restore previous values (but not previous bindings, i.e. anchors).
1332 // Also, don't drop any new bindings.
1333 if (!qt_is_nan(d->rewindX) && d->rewindX != targetPrivate->x)
1334 targetPrivate->x.setValueBypassingBindings(d->rewindX);
1335 if (!qt_is_nan(d->rewindY) && d->rewindY != targetPrivate->y)
1336 targetPrivate->y.setValueBypassingBindings(d->rewindY);
1337
1338 if (targetPrivate->widthValid() && !qt_is_nan(d->rewindWidth)) {
1339 targetPrivate->widthValidFlag = true;
1340 if (d->rewindWidth != targetPrivate->width)
1341 targetPrivate->width.setValueBypassingBindings(d->rewindWidth);
1342 }
1343
1344 if (targetPrivate->heightValid() && !qt_is_nan(d->rewindHeight)) {
1345 targetPrivate->heightValidFlag = true;
1346 if (d->rewindHeight != targetPrivate->height)
1347 targetPrivate->height.setValueBypassingBindings(d->rewindHeight);
1348 }
1349
1350 const QRectF newGeometry(d->target->position(), d->target->size());
1351 if (newGeometry != oldGeometry) {
1352 targetPrivate->dirty(QQuickItemPrivate::Position);
1353 d->target->geometryChange(newGeometry, oldGeometry);
1354 }
1355}
1356
1357void QQuickAnchorChanges::saveCurrentValues()
1358{
1359 Q_D(QQuickAnchorChanges);
1360 if (!d->target)
1361 return;
1362
1363 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1364 d->rewindLeft = targetPrivate->anchors()->left();
1365 d->rewindRight = targetPrivate->anchors()->right();
1366 d->rewindHCenter = targetPrivate->anchors()->horizontalCenter();
1367 d->rewindTop = targetPrivate->anchors()->top();
1368 d->rewindBottom = targetPrivate->anchors()->bottom();
1369 d->rewindVCenter = targetPrivate->anchors()->verticalCenter();
1370 d->rewindBaseline = targetPrivate->anchors()->baseline();
1371
1372 d->rewindX = d->target->x();
1373 d->rewindY = d->target->y();
1374 d->rewindWidth = d->target->width();
1375 d->rewindHeight = d->target->height();
1376}
1377
1378void QQuickAnchorChanges::saveTargetValues()
1379{
1380 Q_D(QQuickAnchorChanges);
1381 if (!d->target)
1382 return;
1383
1384 d->toX = d->target->x();
1385 d->toY = d->target->y();
1386 d->toWidth = d->target->width();
1387 d->toHeight = d->target->height();
1388}
1389
1390QT_END_NAMESPACE
1391
1392#include <moc_qquickstateoperations_p.cpp>
QQmlNullableValue< qreal > origWidth
QQmlAbstractBinding::Ptr origLeftBinding
QQmlAbstractBinding::Ptr origBottomBinding
QQmlAbstractBinding::Ptr origTopBinding
QQmlAbstractBinding::Ptr origHCenterBinding
QQmlAbstractBinding::Ptr origRightBinding
QQmlNullableValue< qreal > origHeight
QQmlAbstractBinding::Ptr origVCenterBinding
QQmlAbstractBinding::Ptr origBaselineBinding
QQuickAnchors::Anchors resetAnchors