Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquickstate.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
4#include "qquickstate_p_p.h"
5#include "qquickstate_p.h"
6
9
10#include <private/qqmlglobal_p.h>
11
12#include <QtCore/qdebug.h>
13
15
16Q_LOGGING_CATEGORY(lcStates, "qt.qml.states")
17
19: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), fromBinding(nullptr), event(nullptr),
20 specifiedObject(nullptr)
21{
22}
23
25 const QVariant &value)
26: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
27 property(target, propertyName, qmlEngine(target)), toValue(value),
28 fromBinding(nullptr), event(nullptr),
29 specifiedObject(target), specifiedProperty(propertyName)
30{
31 if (property.isValid())
32 fromValue = property.read();
33}
34
36: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
37 property(property), toValue(value),
38 fromBinding(nullptr), event(nullptr),
39 specifiedObject(target), specifiedProperty(propertyName)
40{
41 if (property.isValid())
42 fromValue = property.read();
43}
44
45
47{
48}
49
51{
52}
53
55{
56 return false;
57}
58
60{
61}
62
64{
65 return false;
66}
67
69{
70}
71
73{
75 return false;
76}
77
79 : QObject(dd, parent)
80{
81}
82
119{
120 Q_D(QQuickState);
121 d->transitionManager.setState(this);
122}
123
125{
126 Q_D(QQuickState);
127 if (d->group)
128 d->group->removeState(this);
129}
130
138{
139 Q_D(const QQuickState);
140 return d->name;
141}
142
144{
145 Q_D(QQuickState);
146 d->name = n;
147 d->named = true;
148}
149
151{
152 Q_D(const QQuickState);
153 return d->named;
154}
155
157{
158 Q_D(const QQuickState);
159 return d->whenKnown;
160}
161
187{
188 Q_D(const QQuickState);
189 return d->when;
190}
191
192void QQuickState::setWhen(bool when)
193{
194 Q_D(QQuickState);
195 d->whenKnown = true;
196 d->when = when;
197 if (d->group)
198 d->group->updateAutoState();
199}
200
211{
212 Q_D(const QQuickState);
213 return d->extends;
214}
215
217{
218 Q_D(QQuickState);
219 d->extends = extends;
220}
221
232{
233 Q_D(QQuickState);
234 return QQmlListProperty<QQuickStateOperation>(this, &d->operations,
241}
242
244{
245 Q_D(const QQuickState);
246 return d->operations.size();
247}
248
250{
251 Q_D(const QQuickState);
252 return d->operations.at(index);
253}
254
256{
257 Q_D(QQuickState);
258 d->operations.append(QQuickStatePrivate::OperationGuard(op, &d->operations));
259 return *this;
260}
261
263{
264 Q_Q(QQuickState);
265
266 for (int ii = 0; ii < reverting.size(); ++ii) {
267 for (int jj = 0; jj < revertList.size(); ++jj) {
268 const QQuickRevertAction &revert = reverting.at(ii);
269 const QQuickSimpleAction &simple = revertList.at(jj);
270 if ((revert.event && simple.event() == revert.event) ||
271 simple.property() == revert.property) {
273 break;
274 }
275 }
276 }
278
279 if (group)
280 group->stateAboutToComplete();
281 emit q->completed();
282}
283
284// Generate a list of actions for this state. This includes coelescing state
285// actions that this state "extends"
288{
290 if (inState)
291 return applyList;
292
293 // Prevent "extends" recursion
294 inState = true;
295
296 if (!extends.isEmpty()) {
298 for (int ii = 0; ii < states.size(); ++ii)
299 if (states.at(ii)->name() == extends) {
301 applyList = static_cast<QQuickStatePrivate*>(states.at(ii)->d_func())->generateActionList();
302 }
303 }
304
306 applyList << op->actions();
307
308 inState = false;
309 return applyList;
310}
311
313{
314 Q_D(const QQuickState);
315 return d->group;
316}
317
319{
320 Q_D(QQuickState);
321 d->group = group;
322}
323
325{
326 Q_D(QQuickState);
327 d->transitionManager.cancel();
328}
329
331{
332 if (fromBinding) {
335 fromBinding = nullptr;
336 }
337 }
338}
339
341{
342 Q_D(const QQuickState);
343
344 if (isStateActive()) {
345 for (const QQuickSimpleAction &simpleAction : d->revertList) {
346 if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
347 return true;
348 }
349 }
350
351 return false;
352}
353
355{
356 Q_D(QQuickState);
357
358 if (isStateActive()) {
359 for (QQuickSimpleAction &simpleAction : d->revertList) {
360 if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
361 simpleAction.setValue(revertValue);
362 return true;
363 }
364 }
365 }
366
367 return false;
368}
369
371{
372 Q_D(QQuickState);
373
374 if (isStateActive()) {
375 for (QQuickSimpleAction &simpleAction : d->revertList) {
376 if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
377 simpleAction.setBinding(binding);
378 return true;
379 }
380 }
381 }
382
383 return false;
384}
385
387{
388 Q_D(QQuickState);
389
390 if (isStateActive()) {
391 for (auto it = d->revertList.begin(), end = d->revertList.end(); it != end; ++it) {
392 QQuickSimpleAction &simpleAction = *it;
393 if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
395
396 simpleAction.property().write(simpleAction.value());
397 if (auto binding = simpleAction.binding(); binding) {
398 QQmlProperty prop = simpleAction.property();
399 binding.installOn(prop);
400 }
401
402 d->revertList.erase(it);
403 return true;
404 }
405 }
406 }
407
408 return false;
409}
410
412{
413 Q_D(QQuickState);
414
415 QQuickSimpleAction simpleAction(action);
416
417 d->revertList.append(simpleAction);
418}
419
421{
422 Q_D(QQuickState);
423
424 if (isStateActive()) {
425 const auto actionMatchesTarget = [target](QQuickSimpleAction &simpleAction) {
426 if (simpleAction.property().object() == target) {
427 QQmlPropertyPrivate::removeBinding(simpleAction.property());
428 simpleAction.property().write(simpleAction.value());
429 if (auto binding = simpleAction.binding()) {
430 QQmlProperty prop = simpleAction.property();
431 binding.installOn(prop);
432 }
433
434 return true;
435 }
436 return false;
437 };
438
439 d->revertList.erase(std::remove_if(d->revertList.begin(), d->revertList.end(),
440 actionMatchesTarget),
441 d->revertList.end());
442 }
443}
444
446{
447 Q_D(QQuickState);
448 if (isStateActive()) {
449 QList<QQuickSimpleAction> simpleActionList;
450 simpleActionList.reserve(actionList.size());
451
452 for (const QQuickStateAction &action : actionList) {
453 QQuickSimpleAction simpleAction(action);
454 action.property.write(action.toValue);
455 if (auto binding = action.toBinding; binding)
456 binding.installOn(action.property);
457
458 simpleActionList.append(simpleAction);
459 }
460
461 d->revertList.append(simpleActionList);
462 }
463}
464
466{
467 Q_D(const QQuickState);
468
469 if (isStateActive()) {
470 for (const QQuickSimpleAction &simpleAction : d->revertList) {
471 if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
472 return simpleAction.value();
473 }
474 }
475
476 return QVariant();
477}
478
480{
481 Q_D(const QQuickState);
482
483 if (isStateActive()) {
484 for (const QQuickSimpleAction &simpleAction : d->revertList) {
485 if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
486 return simpleAction.binding();
487 }
488 }
489
490 return nullptr;
491}
492
494{
495 return stateGroup() && stateGroup()->state() == name();
496}
497
499{
500 Q_D(QQuickState);
501
502 qmlExecuteDeferred(this);
503
504 cancel();
505 if (revert)
506 revert->cancel();
507 d->revertList.clear();
508 d->reverting.clear();
509
510 if (revert) {
511 QQuickStatePrivate *revertPrivate =
512 static_cast<QQuickStatePrivate*>(revert->d_func());
513 d->revertList = revertPrivate->revertList;
514 revertPrivate->revertList.clear();
515 }
516
517 // List of actions caused by this state
518 QQuickStateOperation::ActionList applyList = d->generateActionList();
519
520 // List of actions that need to be reverted to roll back (just) this state
521 QQuickStatePrivate::SimpleActionList additionalReverts;
522 // First add the reverse of all the applyList actions
523 for (int ii = 0; ii < applyList.size(); ++ii) {
524 QQuickStateAction &action = applyList[ii];
525
526 if (action.event) {
527 if (!action.event->isReversable())
528 continue;
529 bool found = false;
530 for (int jj = 0; jj < d->revertList.size(); ++jj) {
531 QQuickStateActionEvent *event = d->revertList.at(jj).event();
532 if (event && event->type() == action.event->type()) {
533 if (action.event->mayOverride(event)) {
534 found = true;
535
536 if (action.event != d->revertList.at(jj).event() && action.event->needsCopy()) {
537 action.event->copyOriginals(d->revertList.at(jj).event());
538
539 QQuickSimpleAction r(action);
540 additionalReverts << r;
541 d->revertList.removeAt(jj);
542 --jj;
543 } else if (action.event->isRewindable()) //###why needed?
544 action.event->saveCurrentValues();
545
546 break;
547 }
548 }
549 }
550 if (!found) {
551 action.event->saveOriginals();
552 // Only need to revert the applyList action if the previous
553 // state doesn't have a higher priority revert already
554 QQuickSimpleAction r(action);
555 additionalReverts << r;
556 }
557 } else {
558 bool found = false;
560
561 for (int jj = 0; jj < d->revertList.size(); ++jj) {
562 if (d->revertList.at(jj).property() == action.property) {
563 found = true;
564 if (d->revertList.at(jj).binding() != action.fromBinding) {
565 action.deleteFromBinding();
566 }
567 break;
568 }
569 }
570
571 if (!found) {
572 if (!action.restore) {
573 action.deleteFromBinding();;
574 } else {
575 // Only need to revert the applyList action if the previous
576 // state doesn't have a higher priority revert already
577 QQuickSimpleAction r(action);
578 additionalReverts << r;
579 }
580 }
581 }
582 }
583
584 // Any reverts from a previous state that aren't carried forth
585 // into this state need to be translated into apply actions
586 for (int ii = 0; ii < d->revertList.size(); ++ii) {
587 bool found = false;
588 if (d->revertList.at(ii).event()) {
589 QQuickStateActionEvent *event = d->revertList.at(ii).event();
590 if (!event->isReversable())
591 continue;
592 for (int jj = 0; !found && jj < applyList.size(); ++jj) {
593 const QQuickStateAction &action = applyList.at(jj);
594 if (action.event && action.event->type() == event->type()) {
595 if (action.event->mayOverride(event))
596 found = true;
597 }
598 }
599 } else {
600 for (int jj = 0; !found && jj < applyList.size(); ++jj) {
601 const QQuickStateAction &action = applyList.at(jj);
602 if (action.property == d->revertList.at(ii).property())
603 found = true;
604 }
605 }
606 if (!found) {
607 // If revert list contains bindings assigned to deleted objects, we need to
608 // prevent reverting properties of those objects.
609 if (d->revertList.at(ii).binding() && !d->revertList.at(ii).property().object()) {
610 continue;
611 }
612 QVariant cur = d->revertList.at(ii).property().read();
613 QQmlProperty prop = d->revertList.at(ii).property();
615
617 a.property = d->revertList.at(ii).property();
618 a.fromValue = cur;
619 a.toValue = d->revertList.at(ii).value();
620 a.toBinding = d->revertList.at(ii).binding();
621 a.specifiedObject = d->revertList.at(ii).specifiedObject();
622 a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
623 a.event = d->revertList.at(ii).event();
624 a.reverseEvent = d->revertList.at(ii).reverseEvent();
625 if (a.event && a.event->isRewindable())
626 a.event->saveCurrentValues();
627 applyList << a;
628 // Store these special reverts in the reverting list
629 if (a.event)
630 d->reverting << a.event;
631 else
632 d->reverting << a.property;
633 }
634 }
635 // All the local reverts now become part of the ongoing revertList
636 d->revertList << additionalReverts;
637
638 if (lcStates().isDebugEnabled()) {
639 for (const QQuickStateAction &action : std::as_const(applyList)) {
640 if (action.event)
641 qCDebug(lcStates) << "QQuickStateAction event:" << action.event->type();
642 else
643 qCDebug(lcStates) << "QQuickStateAction on" << action.property.object()
644 << action.property.name() << "from:" << action.fromValue
645 << "to:" << action.toValue;
646 }
647 }
648
649 d->transitionManager.transition(applyList, trans);
650}
651
653{
654 return ActionList();
655}
656
658{
659 Q_D(const QQuickStateOperation);
660 return d->m_state;
661}
662
664{
666 d->m_state = state;
667}
668
670
671#include "moc_qquickstate_p.cpp"
qsizetype size() const noexcept
Definition qlist.h:386
void removeAt(qsizetype i)
Definition qlist.h:573
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qobject.h:90
QQmlAnyBinding is an abstraction over the various bindings in QML.
static void removeBindingFrom(QQmlProperty &prop)
bool isAbstractPropertyBinding() const
static QQmlAnyBinding ofProperty(const QQmlProperty &prop)
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
Definition qqmllist.h:24
static void removeBinding(const QQmlProperty &that)
The QQmlProperty class abstracts accessing properties on objects created from QML.
bool isValid() const
Returns true if the QQmlProperty refers to a valid property, otherwise false.
QMetaProperty property() const
Returns the \l{QMetaProperty} {Qt property} associated with this QML property.
QML_ANONYMOUSQObject * object
bool write(const QVariant &) const
Sets the property value to value.
QQuickStateActionEvent * event
const QVariant & value() const
QQuickStateActionEvent * event() const
const QQmlProperty & property() const
QQmlAnyBinding binding() const
virtual void saveOriginals()
virtual void saveCurrentValues()
virtual bool isReversable()
virtual bool needsCopy()
virtual ~QQuickStateActionEvent()
virtual void clearBindings()
virtual void reverse()
virtual bool changesBindings()
virtual bool isRewindable()
virtual void execute()
virtual bool mayOverride(QQuickStateActionEvent *other)
virtual EventType type() const =0
virtual void copyOriginals(QQuickStateActionEvent *)
QQmlProperty property
QQmlAnyBinding fromBinding
QQuickStateActionEvent * event
QQuickState * state() const
QQuickStateOperation(QObject *parent=nullptr)
QList< QQuickStateAction > ActionList
virtual ActionList actions()
void setState(QQuickState *state)
SimpleActionList revertList
static void operations_append(QQmlListProperty< QQuickStateOperation > *prop, QQuickStateOperation *op)
static qsizetype operations_count(QQmlListProperty< QQuickStateOperation > *prop)
static void operations_clear(QQmlListProperty< QQuickStateOperation > *prop)
static QQuickStateOperation * operations_at(QQmlListProperty< QQuickStateOperation > *prop, qsizetype index)
QList< QQuickRevertAction > reverting
static void operations_removeLast(QQmlListProperty< QQuickStateOperation > *prop)
QQuickStateOperation::ActionList generateActionList() const
QList< OperationGuard > operations
static void operations_replace(QQmlListProperty< QQuickStateOperation > *prop, qsizetype index, QQuickStateOperation *op)
bool isWhenKnown() const
QString extends() const
\qmlproperty string QtQuick::State::extend This property holds the state that this state extends.
QQuickState & operator<<(QQuickStateOperation *)
bool containsPropertyInRevertList(QObject *target, const QString &name) const
QQuickStateGroup * stateGroup() const
void setExtends(const QString &)
bool isStateActive() const
QVariant valueInRevertList(QObject *target, const QString &name) const
void setName(const QString &)
int operationCount() const
QQmlListProperty< QQuickStateOperation > changes
\qmlproperty list<Change> QtQuick::State::changes This property holds the changes to apply for this s...
QQuickState(QObject *parent=nullptr)
\qmltype State \instantiates QQuickState \inqmlmodule QtQuick
void removeAllEntriesFromRevertList(QObject *target)
bool removeEntryFromRevertList(QObject *target, const QString &name)
void addEntryToRevertList(const QQuickStateAction &action)
void apply(QQuickTransition *, QQuickState *revert)
void addEntriesToRevertList(const QList< QQuickStateAction > &actions)
QQmlAnyBinding bindingInRevertList(QObject *target, const QString &name) const
void setWhen(bool)
~QQuickState() override
void setStateGroup(QQuickStateGroup *)
bool isNamed() const
QQuickStateOperation * operationAt(int) const
bool changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue)
bool changeBindingInRevertList(QObject *target, const QString &name, QQmlAnyBinding binding)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
\inmodule QtCore
Definition qvariant.h:64
QSet< QString >::iterator it
else opt state
[0]
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLboolean GLuint group
GLenum target
GLuint name
GLfloat n
struct _cl_event * event
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint * states
void qmlExecuteDeferred(QObject *object)
Definition qqml.cpp:48
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
#define emit
#define Q_UNUSED(x)
const char property[13]
Definition qwizard.cpp:101
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent