25 Q_DECLARE_PUBLIC(QQuickStateGroup)
34 static void append_state(QQmlListProperty<QQuickState> *list, QQuickState *state);
36 static QQuickState *
at_state(QQmlListProperty<QQuickState> *list, qsizetype index);
38 static void replace_states(QQmlListProperty<QQuickState> *list, qsizetype index, QQuickState *state);
41 static void append_transition(QQmlListProperty<QQuickTransition> *list, QQuickTransition *state);
43 static QQuickTransition *
at_transition(QQmlListProperty<QQuickTransition> *list, qsizetype index);
132QQmlListProperty<QQuickState> QQuickStateGroup::statesProperty()
134 Q_D(QQuickStateGroup);
135 return QQmlListProperty<QQuickState>(
this, &d->states,
136 &QQuickStateGroupPrivate::append_state,
137 &QQuickStateGroupPrivate::count_state,
138 &QQuickStateGroupPrivate::at_state,
139 &QQuickStateGroupPrivate::clear_states,
140 &QQuickStateGroupPrivate::replace_states,
141 &QQuickStateGroupPrivate::removeLast_states);
146 QQuickStateGroup *_this =
static_cast<QQuickStateGroup *>(list->object);
147 _this->d_func()->states.append(state);
149 state->setStateGroup(_this);
177 auto *self =
static_cast<QQuickStateGroup *>(list->object);
178 auto *d = self->d_func();
179 auto *oldState = d->states.at(index);
180 if (oldState != state) {
182 oldState->setStateGroup(
nullptr);
185 state->setStateGroup(self);
186 d->states.replace(index, state);
187 if (!oldState || d->currentState == oldState->name())
188 d->setCurrentStateInternal(state ? state->name() : QString(),
true);
194 auto *d =
static_cast<QQuickStateGroup *>(list->object)->d_func();
195 if (QQuickState *last = d->states.last()) {
196 if (d->currentState == last->name()) {
197 QQuickState *first = d->states.size() > 1 ? d->states.first() :
nullptr;
198 d->setCurrentStateInternal(first ? first->name() : QString(),
true);
200 last->setStateGroup(
nullptr);
202 d->states.removeLast();
225QQmlListProperty<QQuickTransition> QQuickStateGroup::transitionsProperty()
227 Q_D(QQuickStateGroup);
228 return QQmlListProperty<QQuickTransition>(
this, &d->transitions, &QQuickStateGroupPrivate::append_transition,
229 &QQuickStateGroupPrivate::count_transitions,
230 &QQuickStateGroupPrivate::at_transition,
231 &QQuickStateGroupPrivate::clear_transitions);
303void QQuickStateGroup::componentComplete()
305 Q_D(QQuickStateGroup);
306 d->componentComplete =
true;
308 QVarLengthArray<QString, 4> names;
309 names.reserve(d->states.size());
310 for (QQuickState *state : std::as_const(d->states)) {
314 if (!state->isNamed())
315 state->setName(QLatin1String(
"anonymousState") + QString::number(++d->unnamedCount));
317 QString stateName = state->name();
318 if (names.contains(stateName))
319 qmlWarning(state->parent()) <<
"Found duplicate state name: " << stateName;
321 names.append(std::move(stateName));
324 if (d->updateAutoState()) {
326 }
else if (!d->currentState.isEmpty()) {
327 QString cs = d->currentState;
328 d->currentState.clear();
329 d->setCurrentStateInternal(cs,
true);
344 Q_Q(QQuickStateGroup);
349 for (QQuickState *state : std::as_const(states)) {
350 if (!state || !state->isWhenKnown() || !state->isNamed())
353 bool whenValue = state->when();
354 const QQmlPropertyIndex whenIndex(state->metaObject()->indexOfProperty(
"when"));
355 const auto potentialWhenBinding = QQmlAnyBinding::ofProperty(state, whenIndex);
356 Q_ASSERT(!potentialWhenBinding.isUntypedPropertyBinding());
360 QQmlAbstractBinding *abstractBinding = potentialWhenBinding.asAbstractBinding();
361 if (abstractBinding && abstractBinding->kind() == QQmlAbstractBinding::QmlBinding) {
362 QQmlBinding *binding =
static_cast<QQmlBinding *>(abstractBinding);
363 if (binding->hasValidContext()) {
364 const auto boolType = QMetaType::fromType<
bool>();
365 const bool isUndefined = !binding->evaluate(&whenValue, boolType);
372 qCDebug(lcStates) <<
"Setting auto state due to expression";
373 if (currentState != state->name()) {
374 q->setState(state->name());
379 }
else if (state->name() == currentState) {
384 bool rv = !currentState.isEmpty();
385 q->setState(QString());
394 QQuickTransition *highest =
nullptr;
396 bool reversed =
false;
399 for (
int ii = 0; !done && ii < transitions.size(); ++ii) {
400 QQuickTransition *t = transitions.at(ii);
403 for (
int ii = 0; ii < 2; ++ii)
405 if (ii && (!t->reversible() ||
406 (t->fromState() == QLatin1String(
"*") &&
407 t->toState() == QLatin1String(
"*"))))
409 const QString fromStateStr = t->fromState();
410 const QString toStateStr = t->toState();
412 auto fromState = QStringView{fromStateStr}.split(QLatin1Char(
','));
413 for (
int jj = 0; jj < fromState.size(); ++jj)
414 fromState[jj] = fromState.at(jj).trimmed();
415 auto toState = QStringView{toStateStr}.split(QLatin1Char(
','));
416 for (
int jj = 0; jj < toState.size(); ++jj)
417 toState[jj] = toState.at(jj).trimmed();
419 qSwap(fromState, toState);
421 const QString asterisk = QStringLiteral(
"*");
422 if (fromState.contains(QStringView(from)))
424 else if (fromState.contains(QStringView(asterisk)))
429 if (toState.contains(QStringView(to)))
431 else if (toState.contains(QStringView(asterisk)))
445 }
else if (tScore > score) {
453 highest->setReversed(reversed);
461 Q_Q(QQuickStateGroup);
463 currentState = state;
468 qmlWarning(q) <<
"Can't apply a state change as part of a state definition.";
474 QQuickTransition *transition = ignoreTrans ?
nullptr : findTransition(currentState, state);
475 if (lcStates().isDebugEnabled()) {
476 qCDebug(lcStates) <<
this <<
"changing state from:" << currentState <<
"to:" << state;
478 qCDebug(lcStates) <<
" using transition" << transition->fromState()
479 << transition->toState();
482 QQuickState *oldState =
nullptr;
483 if (!currentState.isEmpty()) {
484 for (QQuickState *state : std::as_const(states)) {
485 if (state && state->name() == currentState) {
492 currentState = state;
493 emit q->stateChanged(currentState);
495 QQuickState *newState =
nullptr;
496 for (QQuickState *state : std::as_const(states)) {
497 if (state && state->name() == currentState) {
503 if (oldState ==
nullptr || newState ==
nullptr) {
505 nullState =
new QQuickState;
513 newState->apply(transition, oldState);