Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
49
53
55{
56 return false;
57}
58
62
64{
65 return false;
66}
67
71
77
82
118: QObject(*(new QQuickStatePrivate), parent)
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
231QQmlListProperty<QQuickStateOperation> QQuickState::changes()
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()) {
297 QList<QQuickState *> states = group ? group->states() : QList<QQuickState *>();
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
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) {
394 QQmlPropertyPrivate::removeBinding(simpleAction.property());
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](const 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.removeIf(actionMatchesTarget);
440 }
441}
442
443void QQuickState::addEntriesToRevertList(const QList<QQuickStateAction> &actionList)
444{
445 Q_D(QQuickState);
446 if (isStateActive()) {
447 QList<QQuickSimpleAction> simpleActionList;
448 simpleActionList.reserve(actionList.size());
449
450 for (const QQuickStateAction &action : actionList) {
451 QQuickSimpleAction simpleAction(action);
452 action.property.write(action.toValue);
453 if (auto binding = action.toBinding; binding)
454 binding.installOn(action.property);
455
456 simpleActionList.append(simpleAction);
457 }
458
459 d->revertList.append(simpleActionList);
460 }
461}
462
464{
465 Q_D(const QQuickState);
466
467 if (isStateActive()) {
468 for (const QQuickSimpleAction &simpleAction : d->revertList) {
469 if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
470 return simpleAction.value();
471 }
472 }
473
474 return QVariant();
475}
476
478{
479 Q_D(const QQuickState);
480
481 if (isStateActive()) {
482 for (const QQuickSimpleAction &simpleAction : d->revertList) {
483 if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
484 return simpleAction.binding();
485 }
486 }
487
488 return nullptr;
489}
490
492{
493 return stateGroup() && stateGroup()->state() == name();
494}
495
497{
498 Q_D(QQuickState);
499
500 qmlExecuteDeferred(this);
501
502 cancel();
503 if (revert)
504 revert->cancel();
505 d->revertList.clear();
506 d->reverting.clear();
507
508 if (revert) {
509 QQuickStatePrivate *revertPrivate =
510 static_cast<QQuickStatePrivate*>(revert->d_func());
511 d->revertList = revertPrivate->revertList;
512 revertPrivate->revertList.clear();
513 }
514
515 // List of actions caused by this state
516 QQuickStateOperation::ActionList applyList = d->generateActionList();
517
518 // List of actions that need to be reverted to roll back (just) this state
519 QQuickStatePrivate::SimpleActionList additionalReverts;
520 // First add the reverse of all the applyList actions
521 for (int ii = 0; ii < applyList.size(); ++ii) {
522 QQuickStateAction &action = applyList[ii];
523
524 if (action.event) {
525 if (!action.event->isReversable())
526 continue;
527 bool found = false;
528 for (int jj = 0; jj < d->revertList.size(); ++jj) {
529 QQuickStateActionEvent *event = d->revertList.at(jj).event();
530 if (event && event->type() == action.event->type()) {
531 if (action.event->mayOverride(event)) {
532 found = true;
533
534 if (action.event != d->revertList.at(jj).event() && action.event->needsCopy()) {
535 action.event->copyOriginals(d->revertList.at(jj).event());
536
537 QQuickSimpleAction r(action);
538 additionalReverts << r;
539 d->revertList.removeAt(jj);
540 --jj;
541 } else if (action.event->isRewindable()) //###why needed?
542 action.event->saveCurrentValues();
543
544 break;
545 }
546 }
547 }
548 if (!found) {
549 action.event->saveOriginals();
550 // Only need to revert the applyList action if the previous
551 // state doesn't have a higher priority revert already
552 QQuickSimpleAction r(action);
553 additionalReverts << r;
554 }
555 } else {
556 bool found = false;
558
559 for (int jj = 0; jj < d->revertList.size(); ++jj) {
560 if (d->revertList.at(jj).property() == action.property) {
561 found = true;
562 if (d->revertList.at(jj).binding() != action.fromBinding) {
563 action.deleteFromBinding();
564 }
565 break;
566 }
567 }
568
569 if (!found) {
570 if (!action.restore) {
571 action.deleteFromBinding();;
572 } else {
573 // Only need to revert the applyList action if the previous
574 // state doesn't have a higher priority revert already
575 QQuickSimpleAction r(action);
576 additionalReverts << r;
577 }
578 }
579 }
580 }
581
582 // Any reverts from a previous state that aren't carried forth
583 // into this state need to be translated into apply actions
584 for (int ii = 0; ii < d->revertList.size(); ++ii) {
585 bool found = false;
586 if (d->revertList.at(ii).event()) {
587 QQuickStateActionEvent *event = d->revertList.at(ii).event();
588 if (!event->isReversable())
589 continue;
590 for (int jj = 0; !found && jj < applyList.size(); ++jj) {
591 const QQuickStateAction &action = applyList.at(jj);
592 if (action.event && action.event->type() == event->type()) {
593 if (action.event->mayOverride(event))
594 found = true;
595 }
596 }
597 } else {
598 for (int jj = 0; !found && jj < applyList.size(); ++jj) {
599 const QQuickStateAction &action = applyList.at(jj);
600 if (action.property == d->revertList.at(ii).property())
601 found = true;
602 }
603 }
604 if (!found) {
605 // If revert list contains bindings assigned to deleted objects, we need to
606 // prevent reverting properties of those objects.
607 if (d->revertList.at(ii).binding() && !d->revertList.at(ii).property().object()) {
608 continue;
609 }
610 QVariant cur = d->revertList.at(ii).property().read();
611 QQmlProperty prop = d->revertList.at(ii).property();
613
615 a.property = d->revertList.at(ii).property();
616 a.fromValue = cur;
617 a.toValue = d->revertList.at(ii).value();
618 a.toBinding = d->revertList.at(ii).binding();
619 a.specifiedObject = d->revertList.at(ii).specifiedObject();
620 a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
621 a.event = d->revertList.at(ii).event();
622 a.reverseEvent = d->revertList.at(ii).reverseEvent();
623 if (a.event && a.event->isRewindable())
624 a.event->saveCurrentValues();
625 applyList << a;
626 // Store these special reverts in the reverting list
627 if (a.event)
628 d->reverting << a.event;
629 else
630 d->reverting << a.property;
631 }
632 }
633 // All the local reverts now become part of the ongoing revertList
634 d->revertList << additionalReverts;
635
636 if (lcStates().isDebugEnabled()) {
637 for (const QQuickStateAction &action : std::as_const(applyList)) {
638 if (action.event)
639 qCDebug(lcStates) << "QQuickStateAction event:" << action.event->type();
640 else
641 qCDebug(lcStates) << "QQuickStateAction on" << action.property.object()
642 << action.property.name() << "from:" << action.fromValue
643 << "to:" << action.toValue;
644 }
645 }
646
647 d->transitionManager.transition(applyList, trans);
648}
649
654
656{
657 Q_D(const QQuickStateOperation);
658 return d->m_state;
659}
660
666
668
669#include "moc_qquickstate_p.cpp"
qsizetype size() const noexcept
Definition qlist.h:397
void removeAt(qsizetype i)
Definition qlist.h:590
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void clear()
Definition qlist.h:434
\inmodule QtCore
Definition qobject.h:103
QQmlAnyBinding is an abstraction over the various bindings in QML.
static void removeBindingFrom(QQmlProperty &prop)
bool isAbstractPropertyBinding() const
static QQmlAnyBinding ofProperty(const QQmlProperty &prop)
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.
QQuickStateActionEvent * event
QQuickStateActionEvent * event() const
const QQmlProperty & property() 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)
iterator begin()
Definition qset.h:136
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
Definition qvariant.h:65
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:49
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:80
#define emit
#define Q_UNUSED(x)
const char property[13]
Definition qwizard.cpp:101
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]