Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquickstategroup.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
5
7
8#include <private/qqmlbinding_p.h>
9#include <private/qqmlglobal_p.h>
10
11#include <QtCore/qstringlist.h>
12#include <QtCore/qdebug.h>
13#include <QtCore/qvector.h>
14
15#include <private/qobject_p.h>
16#include <qqmlinfo.h>
17
19
20using namespace Qt::StringLiterals;
21
23
25{
26 Q_DECLARE_PUBLIC(QQuickStateGroup)
27public:
29 : nullState(nullptr), componentComplete(true),
30 ignoreTrans(false), applyingState(false), unnamedCount(0) {}
31
34
35 static void append_state(QQmlListProperty<QQuickState> *list, QQuickState *state);
36 static qsizetype count_state(QQmlListProperty<QQuickState> *list);
38 static void clear_states(QQmlListProperty<QQuickState> *list);
39 static void replace_states(QQmlListProperty<QQuickState> *list, qsizetype index, QQuickState *state);
40 static void removeLast_states(QQmlListProperty<QQuickState> *list);
41
42 static void append_transition(QQmlListProperty<QQuickTransition> *list, QQuickTransition *state);
43 static qsizetype count_transitions(QQmlListProperty<QQuickTransition> *list);
45 static void clear_transitions(QQmlListProperty<QQuickTransition> *list);
46
49
54
55 QQuickTransition *findTransition(const QString &from, const QString &to);
56 void setCurrentStateInternal(const QString &state, bool = false);
57 bool updateAutoState();
58};
59
93{
94}
95
97{
98 Q_D(const QQuickStateGroup);
99 for (int i = 0; i < d->states.size(); ++i) {
100 if (d->states.at(i))
101 d->states.at(i)->setStateGroup(nullptr);
102 }
103 if (d->nullState)
104 d->nullState->setStateGroup(nullptr);
105}
106
108{
109 Q_D(const QQuickStateGroup);
110 return d->states;
111}
112
134{
135 Q_D(QQuickStateGroup);
136 return QQmlListProperty<QQuickState>(this, &d->states,
143}
144
146{
147 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
148 _this->d_func()->states.append(state);
149 if (state)
150 state->setStateGroup(_this);
151}
152
154{
155 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
156 return _this->d_func()->states.size();
157}
158
160{
161 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
162 return _this->d_func()->states.at(index);
163}
164
166{
167 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
168 _this->d_func()->setCurrentStateInternal(QString(), true);
169 for (qsizetype i = 0; i < _this->d_func()->states.size(); ++i) {
170 if (_this->d_func()->states.at(i))
171 _this->d_func()->states.at(i)->setStateGroup(nullptr);
172 }
173 _this->d_func()->states.clear();
174}
175
177{
178 auto *self = static_cast<QQuickStateGroup *>(list->object);
179 auto *d = self->d_func();
180 auto *oldState = d->states.at(index);
181 if (oldState != state) {
182 if (oldState)
183 oldState->setStateGroup(nullptr);
184 state->setStateGroup(self);
185 d->states.replace(index, state);
186 if (!oldState || d->currentState == oldState->name())
187 d->setCurrentStateInternal(state->name(), true);
188 }
189}
190
192{
193 auto *d = static_cast<QQuickStateGroup *>(list->object)->d_func();
194 if (d->currentState == d->states.last()->name())
195 d->setCurrentStateInternal(d->states.size() > 1 ? d->states.first()->name() : QString(), true);
196 d->states.last()->setStateGroup(nullptr);
197 d->states.removeLast();
198}
199
221{
222 Q_D(QQuickStateGroup);
227}
228
230{
231 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
232 if (trans)
233 _this->d_func()->transitions.append(trans);
234}
235
237{
238 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
239 return _this->d_func()->transitions.size();
240}
241
243{
244 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
245 return _this->d_func()->transitions.at(index);
246}
247
249{
250 QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
251 _this->d_func()->transitions.clear();
252}
253
278{
279 Q_D(const QQuickStateGroup);
280 return d->currentState;
281}
282
284{
285 Q_D(QQuickStateGroup);
286 if (d->currentState == state)
287 return;
288
289 d->setCurrentStateInternal(state);
290}
291
293{
294 Q_D(QQuickStateGroup);
295 d->componentComplete = false;
296}
297
299{
300 Q_D(QQuickStateGroup);
301 d->componentComplete = true;
302
304 names.reserve(d->states.size());
305 for (int ii = 0; ii < d->states.size(); ++ii) {
306 QQuickState *state = d->states.at(ii);
307 if (!state->isNamed())
308 state->setName(QLatin1String("anonymousState") + QString::number(++d->unnamedCount));
309
310 QString stateName = state->name();
311 if (names.contains(stateName)) {
312 qmlWarning(state->parent()) << "Found duplicate state name: " << stateName;
313 } else {
314 names.append(std::move(stateName));
315 }
316 }
317
318 if (d->updateAutoState()) {
319 return;
320 } else if (!d->currentState.isEmpty()) {
321 QString cs = d->currentState;
322 d->currentState.clear();
323 d->setCurrentStateInternal(cs, true);
324 }
325}
326
330bool QQuickStateGroup::updateAutoState()
331{
332 Q_D(QQuickStateGroup);
333 return d->updateAutoState();
334}
335
337{
338 Q_Q(QQuickStateGroup);
340 return false;
341
342 bool revert = false;
343 for (int ii = 0; ii < states.size(); ++ii) {
344 QQuickState *state = states.at(ii);
345 if (state->isWhenKnown()) {
346 if (state->isNamed()) {
347 bool whenValue = state->when();
348 const QQmlProperty whenProp(state, u"when"_s);
349 const auto potentialWhenBinding = QQmlAnyBinding::ofProperty(whenProp);
350 Q_ASSERT(!potentialWhenBinding.isUntypedPropertyBinding());
351
352 // if there is a binding, the value in when might not be up-to-date at this point
353 // so we manually re-evaluate the binding
354 QQmlAbstractBinding *abstractBinding = potentialWhenBinding.asAbstractBinding();
355 if (abstractBinding && abstractBinding->kind() == QQmlAbstractBinding::QmlBinding) {
356 QQmlBinding *binding = static_cast<QQmlBinding *>(abstractBinding);
357 if (binding->hasValidContext()) {
358 const auto boolType = QMetaType::fromType<bool>();
359 const bool isUndefined = !binding->evaluate(&whenValue, boolType);
360 if (isUndefined)
361 whenValue = false;
362 }
363 }
364
365 if (whenValue) {
366 qCDebug(lcStates) << "Setting auto state due to expression";
367 if (currentState != state->name()) {
368 q->setState(state->name());
369 return true;
370 } else {
371 return false;
372 }
373 } else if (state->name() == currentState) {
374 revert = true;
375 }
376 }
377 }
378 }
379 if (revert) {
380 bool rv = !currentState.isEmpty();
381 q->setState(QString());
382 return rv;
383 } else {
384 return false;
385 }
386}
387
389{
390 QQuickTransition *highest = nullptr;
391 int score = 0;
392 bool reversed = false;
393 bool done = false;
394
395 for (int ii = 0; !done && ii < transitions.size(); ++ii) {
397 if (!t->enabled())
398 continue;
399 for (int ii = 0; ii < 2; ++ii)
400 {
401 if (ii && (!t->reversible() ||
402 (t->fromState() == QLatin1String("*") &&
403 t->toState() == QLatin1String("*"))))
404 break;
405 const QString fromStateStr = t->fromState();
406 const QString toStateStr = t->toState();
407
408 auto fromState = QStringView{fromStateStr}.split(QLatin1Char(','));
409 for (int jj = 0; jj < fromState.size(); ++jj)
410 fromState[jj] = fromState.at(jj).trimmed();
411 auto toState = QStringView{toStateStr}.split(QLatin1Char(','));
412 for (int jj = 0; jj < toState.size(); ++jj)
413 toState[jj] = toState.at(jj).trimmed();
414 if (ii == 1)
415 qSwap(fromState, toState);
416 int tScore = 0;
417 const QString asterisk = QStringLiteral("*");
418 if (fromState.contains(QStringView(from)))
419 tScore += 2;
420 else if (fromState.contains(QStringView(asterisk)))
421 tScore += 1;
422 else
423 continue;
424
425 if (toState.contains(QStringView(to)))
426 tScore += 2;
427 else if (toState.contains(QStringView(asterisk)))
428 tScore += 1;
429 else
430 continue;
431
432 if (ii == 1)
433 reversed = true;
434 else
435 reversed = false;
436
437 if (tScore == 4) {
438 highest = t;
439 done = true;
440 break;
441 } else if (tScore > score) {
442 score = tScore;
443 highest = t;
444 }
445 }
446 }
447
448 if (highest)
449 highest->setReversed(reversed);
450
451 return highest;
452}
453
455 bool ignoreTrans)
456{
457 Q_Q(QQuickStateGroup);
458 if (!componentComplete) {
460 return;
461 }
462
463 if (applyingState) {
464 qmlWarning(q) << "Can't apply a state change as part of a state definition.";
465 return;
466 }
467
468 applyingState = true;
469
471 if (lcStates().isDebugEnabled()) {
472 qCDebug(lcStates) << this << "changing state from:" << currentState << "to:" << state;
473 if (transition)
474 qCDebug(lcStates) << " using transition" << transition->fromState()
475 << transition->toState();
476 }
477
478 QQuickState *oldState = nullptr;
479 if (!currentState.isEmpty()) {
480 for (int ii = 0; ii < states.size(); ++ii) {
481 if (states.at(ii)->name() == currentState) {
482 oldState = states.at(ii);
483 break;
484 }
485 }
486 }
487
489 emit q->stateChanged(currentState);
490
491 QQuickState *newState = nullptr;
492 for (int ii = 0; ii < states.size(); ++ii) {
493 if (states.at(ii)->name() == currentState) {
494 newState = states.at(ii);
495 break;
496 }
497 }
498
499 if (oldState == nullptr || newState == nullptr) {
500 if (!nullState) {
504 }
505 if (!oldState) oldState = nullState;
507 }
508
509 newState->apply(transition, oldState);
510 applyingState = false; //### consider removing this (don't allow state changes in transition)
511}
512
514{
515 Q_D(const QQuickStateGroup);
516 for (int i = 0; i < d->states.size(); ++i) {
517 QQuickState *state = d->states.at(i);
518 if (state->name() == name)
519 return state;
520 }
521
522 return nullptr;
523}
524
526{
527 Q_D(QQuickStateGroup);
528 d->states.removeOne(state);
529}
530
531void QQuickStateGroup::stateAboutToComplete()
532{
533 Q_D(QQuickStateGroup);
534 d->applyingState = false;
535}
536
538
539
540#include "moc_qquickstategroup_p.cpp"
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
\inmodule QtCore
Definition qobject.h:90
virtual Kind kind() const =0
static QQmlAnyBinding ofProperty(const QQmlProperty &prop)
QVariant evaluate()
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
Definition qqmllist.h:24
The QQmlProperty class abstracts accessing properties on objects created from QML.
static qsizetype count_transitions(QQmlListProperty< QQuickTransition > *list)
QList< QQuickTransition * > transitions
static void clear_states(QQmlListProperty< QQuickState > *list)
static void replace_states(QQmlListProperty< QQuickState > *list, qsizetype index, QQuickState *state)
static void removeLast_states(QQmlListProperty< QQuickState > *list)
void setCurrentStateInternal(const QString &state, bool=false)
static QQuickTransition * at_transition(QQmlListProperty< QQuickTransition > *list, qsizetype index)
static QQuickState * at_state(QQmlListProperty< QQuickState > *list, qsizetype index)
static void clear_transitions(QQmlListProperty< QQuickTransition > *list)
static void append_transition(QQmlListProperty< QQuickTransition > *list, QQuickTransition *state)
QQuickTransition * findTransition(const QString &from, const QString &to)
static qsizetype count_state(QQmlListProperty< QQuickState > *list)
static void append_state(QQmlListProperty< QQuickState > *list, QQuickState *state)
QList< QQuickState * > states
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void removeState(QQuickState *state)
QQmlListProperty< QQuickTransition > transitionsProperty()
\qmlproperty list<Transition> QtQuick::StateGroup::transitions This property holds a list of transiti...
QQuickStateGroup(QObject *=nullptr)
\qmltype StateGroup \instantiates QQuickStateGroup \inqmlmodule QtQuick
QQuickState * findState(const QString &name) const
QQmlListProperty< QQuickState > states
void setState(const QString &)
QQmlListProperty< QQuickState > statesProperty()
\qmlproperty list<State> QtQuick::StateGroup::states This property holds a list of states defined by ...
void classBegin() override
Invoked after class creation, but before any properties have been set.
QQmlListProperty< QQuickTransition > transitions
void setStateGroup(QQuickStateGroup *)
QString fromState() const
\qmlproperty string QtQuick::Transition::from \qmlproperty string QtQuick::Transition::to
QString toState() const
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
QString & append(QChar c)
Definition qstring.cpp:3227
qSwap(pi, e)
else opt state
[0]
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLuint index
[2]
GLuint name
GLuint GLuint * names
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint * states
void QQml_setParent_noEvent(QObject *object, QObject *parent)
Makes the object a child of parent.
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define emit
ptrdiff_t qsizetype
Definition qtypes.h:70
QList< int > list
[14]
QObject::connect nullptr
\inmodule QtCore \reentrant
Definition qchar.h:17
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent