Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
// Qt-Security score:significant reason:default
4
5
#
include
"qquickstategroup_p.h"
6
7
#
include
"qquicktransition_p.h"
8
9
#
include
<
private
/
qqmlbinding_p
.
h
>
10
#
include
<
private
/
qqmlglobal_p
.
h
>
11
12
#
include
<
QtCore
/
qstringlist
.
h
>
13
#
include
<
QtCore
/
qdebug
.
h
>
14
#
include
<
QtCore
/
qvector
.
h
>
15
16
#
include
<
private
/
qobject_p
.
h
>
17
#
include
<
qqmlinfo
.
h
>
18
19
QT_BEGIN_NAMESPACE
20
21
using
namespace
Qt::StringLiterals;
22
23
class
QQuickStateGroupPrivate
:
public
QObjectPrivate
24
{
25
Q_DECLARE_PUBLIC(QQuickStateGroup)
26
public
:
27
QQuickStateGroupPrivate
()
28
:
nullState
(
nullptr
),
componentComplete
(
true
),
29
ignoreTrans
(
false
),
applyingState
(
false
),
unnamedCount
(0) {}
30
31
QString
currentState
;
32
QQuickState *
nullState
;
33
34
static
void
append_state
(QQmlListProperty<QQuickState> *list, QQuickState *state);
35
static
qsizetype
count_state
(QQmlListProperty<QQuickState> *list);
36
static
QQuickState *
at_state
(QQmlListProperty<QQuickState> *list, qsizetype index);
37
static
void
clear_states
(QQmlListProperty<QQuickState> *list);
38
static
void
replace_states
(QQmlListProperty<QQuickState> *list, qsizetype index, QQuickState *state);
39
static
void
removeLast_states
(QQmlListProperty<QQuickState> *list);
40
41
static
void
append_transition
(QQmlListProperty<QQuickTransition> *list, QQuickTransition *state);
42
static
qsizetype
count_transitions
(QQmlListProperty<QQuickTransition> *list);
43
static
QQuickTransition *
at_transition
(QQmlListProperty<QQuickTransition> *list, qsizetype index);
44
static
void
clear_transitions
(QQmlListProperty<QQuickTransition> *list);
45
46
QList
<
QQuickState
*>
states
;
47
QList
<
QQuickTransition
*>
transitions
;
48
49
bool
componentComplete
;
50
bool
ignoreTrans
;
51
bool
applyingState
;
52
int
unnamedCount
;
53
54
QQuickTransition *
findTransition
(
const
QString &from,
const
QString &to);
55
void
setCurrentStateInternal
(
const
QString &state,
bool
=
false
);
56
bool
updateAutoState
();
57
};
58
59
/*!
60
\qmltype StateGroup
61
\nativetype QQuickStateGroup
62
\inqmlmodule QtQuick
63
\ingroup qtquick-states
64
\brief Provides built-in state support for non-Item types.
65
66
Item (and all derived types) provides built in support for states and transitions
67
via its \l{Item::state}{state}, \l{Item::states}{states} and \l{Item::transitions}{transitions} properties. StateGroup provides an easy way to
68
use this support in other (non-Item-derived) types.
69
70
\qml
71
MyCustomObject {
72
StateGroup {
73
id: myStateGroup
74
states: State {
75
name: "state1"
76
// ...
77
}
78
transitions: Transition {
79
// ...
80
}
81
}
82
83
onSomethingHappened: myStateGroup.state = "state1";
84
}
85
\endqml
86
87
\sa {Qt Quick States}{Qt Quick States}, {Animation and Transitions in Qt Quick}{Transitions}, {Qt Qml}
88
*/
89
90
QQuickStateGroup::QQuickStateGroup(QObject *parent)
91
: QObject(*(
new
QQuickStateGroupPrivate), parent)
92
{
93
}
94
95
QQuickStateGroup::~QQuickStateGroup()
96
{
97
Q_D(
const
QQuickStateGroup);
98
for
(QQuickState *state : std::as_const(d->states)) {
99
if
(state)
100
state->setStateGroup(
nullptr
);
101
}
102
if
(d->nullState)
103
d->nullState->setStateGroup(
nullptr
);
104
}
105
106
QList<QQuickState *> QQuickStateGroup::states()
const
107
{
108
Q_D(
const
QQuickStateGroup);
109
return
d->states;
110
}
111
112
/*!
113
\qmlproperty list<State> QtQuick::StateGroup::states
114
This property holds a list of states defined by the state group.
115
116
\qml
117
StateGroup {
118
states: [
119
State {
120
// State definition...
121
},
122
State {
123
// ...
124
}
125
// Other states...
126
]
127
}
128
\endqml
129
130
\sa {Qt Quick States}{Qt Quick States}
131
*/
132
QQmlListProperty<QQuickState> QQuickStateGroup::statesProperty()
133
{
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);
142
}
143
144
void
QQuickStateGroupPrivate
::append_state(QQmlListProperty<QQuickState> *list, QQuickState *state)
145
{
146
QQuickStateGroup *_this =
static_cast
<QQuickStateGroup *>(list->object);
147
_this->d_func()->states.append(state);
148
if
(state)
149
state->setStateGroup(_this);
150
}
151
152
qsizetype
QQuickStateGroupPrivate
::count_state(QQmlListProperty<QQuickState> *list)
153
{
154
QQuickStateGroup *_this =
static_cast
<QQuickStateGroup *>(list->object);
155
return
_this->d_func()->states.size();
156
}
157
158
QQuickState *
QQuickStateGroupPrivate
::at_state(QQmlListProperty<QQuickState> *list, qsizetype index)
159
{
160
QQuickStateGroup *_this =
static_cast
<QQuickStateGroup *>(list->object);
161
return
_this->d_func()->states.at(index);
162
}
163
164
void
QQuickStateGroupPrivate
::clear_states(QQmlListProperty<QQuickState> *list)
165
{
166
QQuickStateGroupPrivate
*d =
static_cast
<QQuickStateGroup *>(list->object)->d_func();
167
d->setCurrentStateInternal(QString(),
true
);
168
for
(QQuickState *state : std::as_const(d->states)) {
169
if
(state)
170
state->setStateGroup(
nullptr
);
171
}
172
d->states.clear();
173
}
174
175
void
QQuickStateGroupPrivate
::replace_states(QQmlListProperty<QQuickState> *list, qsizetype index, QQuickState *state)
176
{
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) {
181
if
(oldState)
182
oldState->setStateGroup(
nullptr
);
183
184
if
(state)
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
);
189
}
190
}
191
192
void
QQuickStateGroupPrivate
::removeLast_states(QQmlListProperty<QQuickState> *list)
193
{
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
);
199
}
200
last->setStateGroup(
nullptr
);
201
}
202
d->states.removeLast();
203
}
204
205
/*!
206
\qmlproperty list<Transition> QtQuick::StateGroup::transitions
207
This property holds a list of transitions defined by the state group.
208
209
\qml
210
StateGroup {
211
transitions: [
212
Transition {
213
// ...
214
},
215
Transition {
216
// ...
217
}
218
// ...
219
]
220
}
221
\endqml
222
223
\sa {Animation and Transitions in Qt Quick}{Transitions}
224
*/
225
QQmlListProperty<QQuickTransition> QQuickStateGroup::transitionsProperty()
226
{
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);
232
}
233
234
void
QQuickStateGroupPrivate
::append_transition(QQmlListProperty<QQuickTransition> *list, QQuickTransition *trans)
235
{
236
QQuickStateGroup *_this =
static_cast
<QQuickStateGroup *>(list->object);
237
if
(trans)
238
_this->d_func()->transitions.append(trans);
239
}
240
241
qsizetype
QQuickStateGroupPrivate
::count_transitions(QQmlListProperty<QQuickTransition> *list)
242
{
243
QQuickStateGroup *_this =
static_cast
<QQuickStateGroup *>(list->object);
244
return
_this->d_func()->transitions.size();
245
}
246
247
QQuickTransition *
QQuickStateGroupPrivate
::at_transition(QQmlListProperty<QQuickTransition> *list, qsizetype index)
248
{
249
QQuickStateGroup *_this =
static_cast
<QQuickStateGroup *>(list->object);
250
return
_this->d_func()->transitions.at(index);
251
}
252
253
void
QQuickStateGroupPrivate
::clear_transitions(QQmlListProperty<QQuickTransition> *list)
254
{
255
QQuickStateGroup *_this =
static_cast
<QQuickStateGroup *>(list->object);
256
_this->d_func()->transitions.clear();
257
}
258
259
/*!
260
\qmlproperty string QtQuick::StateGroup::state
261
262
This property holds the name of the current state of the state group.
263
264
This property is often used in scripts to change between states. For
265
example:
266
267
\qml
268
function toggle() {
269
if (button.state == 'On')
270
button.state = 'Off';
271
else
272
button.state = 'On';
273
}
274
\endqml
275
276
If the state group is in its base state (i.e. no explicit state has been
277
set), \c state will be a blank string. Likewise, you can return a
278
state group to its base state by setting its current state to \c ''.
279
280
\sa {Qt Quick States}{Qt Quick States}
281
*/
282
QString QQuickStateGroup::state()
const
283
{
284
Q_D(
const
QQuickStateGroup);
285
return
d->currentState;
286
}
287
288
void
QQuickStateGroup::setState(
const
QString &state)
289
{
290
Q_D(QQuickStateGroup);
291
if
(d->currentState == state)
292
return
;
293
294
d->setCurrentStateInternal(state);
295
}
296
297
void
QQuickStateGroup::classBegin()
298
{
299
Q_D(QQuickStateGroup);
300
d->componentComplete =
false
;
301
}
302
303
void
QQuickStateGroup::componentComplete()
304
{
305
Q_D(QQuickStateGroup);
306
d->componentComplete =
true
;
307
308
QVarLengthArray<QString, 4> names;
309
names.reserve(d->states.size());
310
for
(QQuickState *state : std::as_const(d->states)) {
311
if
(!state)
312
continue
;
313
314
if
(!state->isNamed())
315
state->setName(QLatin1String(
"anonymousState"
) + QString::number(++d->unnamedCount));
316
317
QString stateName = state->name();
318
if
(names.contains(stateName))
319
qmlWarning(state->parent()) <<
"Found duplicate state name: "
<< stateName;
320
else
321
names.append(std::move(stateName));
322
}
323
324
if
(d->updateAutoState()) {
325
return
;
326
}
else
if
(!d->currentState.isEmpty()) {
327
QString cs = d->currentState;
328
d->currentState.clear();
329
d->setCurrentStateInternal(cs,
true
);
330
}
331
}
332
333
/*!
334
Returns true if the state was changed, otherwise false.
335
*/
336
bool
QQuickStateGroup::updateAutoState()
337
{
338
Q_D(QQuickStateGroup);
339
return
d->updateAutoState();
340
}
341
342
bool
QQuickStateGroupPrivate
::
updateAutoState
()
343
{
344
Q_Q(QQuickStateGroup);
345
if
(!
componentComplete
)
346
return
false
;
347
348
bool
revert =
false
;
349
for
(QQuickState *state : std::as_const(states)) {
350
if
(!state || !state->isWhenKnown() || !state->isNamed())
351
continue
;
352
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());
357
358
// if there is a binding, the value in when might not be up-to-date at this point
359
// so we manually re-evaluate the binding
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);
366
if
(isUndefined)
367
whenValue =
false
;
368
}
369
}
370
371
if
(whenValue) {
372
qCDebug(lcStates) <<
"Setting auto state due to expression"
;
373
if
(currentState != state->name()) {
374
q->setState(state->name());
375
return
true
;
376
}
else
{
377
return
false
;
378
}
379
}
else
if
(state->name() == currentState) {
380
revert =
true
;
381
}
382
}
383
if
(revert) {
384
bool
rv = !currentState.isEmpty();
385
q->setState(QString());
386
return
rv;
387
}
else
{
388
return
false
;
389
}
390
}
391
392
QQuickTransition *
QQuickStateGroupPrivate
::
findTransition
(
const
QString &from,
const
QString &to)
393
{
394
QQuickTransition *highest =
nullptr
;
395
int
score = 0;
396
bool
reversed =
false
;
397
bool
done =
false
;
398
399
for
(
int
ii = 0; !done && ii < transitions.size(); ++ii) {
400
QQuickTransition *t = transitions.at(ii);
401
if
(!t->enabled())
402
continue
;
403
for
(
int
ii = 0; ii < 2; ++ii)
404
{
405
if
(ii && (!t->reversible() ||
406
(t->fromState() == QLatin1String(
"*"
) &&
407
t->toState() == QLatin1String(
"*"
))))
408
break
;
409
const
QString fromStateStr = t->fromState();
410
const
QString toStateStr = t->toState();
411
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();
418
if
(ii == 1)
419
qSwap(fromState, toState);
420
int
tScore = 0;
421
const
QString asterisk = QStringLiteral(
"*"
);
422
if
(fromState.contains(QStringView(from)))
423
tScore += 2;
424
else
if
(fromState.contains(QStringView(asterisk)))
425
tScore += 1;
426
else
427
continue
;
428
429
if
(toState.contains(QStringView(to)))
430
tScore += 2;
431
else
if
(toState.contains(QStringView(asterisk)))
432
tScore += 1;
433
else
434
continue
;
435
436
if
(ii == 1)
437
reversed =
true
;
438
else
439
reversed =
false
;
440
441
if
(tScore == 4) {
442
highest = t;
443
done =
true
;
444
break
;
445
}
else
if
(tScore > score) {
446
score = tScore;
447
highest = t;
448
}
449
}
450
}
451
452
if
(highest)
453
highest->setReversed(reversed);
454
455
return
highest;
456
}
457
458
void
QQuickStateGroupPrivate
::
setCurrentStateInternal
(
const
QString &state,
459
bool
ignoreTrans)
460
{
461
Q_Q(QQuickStateGroup);
462
if
(!
componentComplete
) {
463
currentState = state;
464
return
;
465
}
466
467
if
(
applyingState
) {
468
qmlWarning(q) <<
"Can't apply a state change as part of a state definition."
;
469
return
;
470
}
471
472
applyingState
=
true
;
473
474
QQuickTransition *transition = ignoreTrans ?
nullptr
: findTransition(currentState, state);
475
if
(lcStates().isDebugEnabled()) {
476
qCDebug(lcStates) <<
this
<<
"changing state from:"
<< currentState <<
"to:"
<< state;
477
if
(transition)
478
qCDebug(lcStates) <<
" using transition"
<< transition->fromState()
479
<< transition->toState();
480
}
481
482
QQuickState *oldState =
nullptr
;
483
if
(!currentState.isEmpty()) {
484
for
(QQuickState *state : std::as_const(states)) {
485
if
(state && state->name() == currentState) {
486
oldState = state;
487
break
;
488
}
489
}
490
}
491
492
currentState = state;
493
emit q->stateChanged(currentState);
494
495
QQuickState *newState =
nullptr
;
496
for
(QQuickState *state : std::as_const(states)) {
497
if
(state && state->name() == currentState) {
498
newState = state;
499
break
;
500
}
501
}
502
503
if
(oldState ==
nullptr
|| newState ==
nullptr
) {
504
if
(!
nullState
) {
505
nullState
=
new
QQuickState;
506
QQml_setParent_noEvent(
nullState
, q);
507
nullState
->setStateGroup(q);
508
}
509
if
(!oldState) oldState =
nullState
;
510
if
(!newState) newState =
nullState
;
511
}
512
513
newState->apply(transition, oldState);
514
applyingState
=
false
;
//### consider removing this (don't allow state changes in transition)
515
}
516
517
QQuickState *QQuickStateGroup::findState(
const
QString &name)
const
518
{
519
Q_D(
const
QQuickStateGroup);
520
for
(QQuickState *state : std::as_const(d->states)) {
521
if
(state && state->name() == name)
522
return
state;
523
}
524
525
return
nullptr
;
526
}
527
528
void
QQuickStateGroup::removeState(QQuickState *state)
529
{
530
Q_D(QQuickStateGroup);
531
d->states.removeOne(state);
532
}
533
534
void
QQuickStateGroup::stateAboutToComplete()
535
{
536
Q_D(QQuickStateGroup);
537
d->applyingState =
false
;
538
}
539
540
QT_END_NAMESPACE
541
542
543
#
include
"moc_qquickstategroup_p.cpp"
QQuickStateGroupPrivate
Definition
qquickstategroup.cpp:24
QQuickStateGroupPrivate::count_transitions
static qsizetype count_transitions(QQmlListProperty< QQuickTransition > *list)
Definition
qquickstategroup.cpp:241
QQuickStateGroupPrivate::nullState
QQuickState * nullState
Definition
qquickstategroup.cpp:32
QQuickStateGroupPrivate::clear_states
static void clear_states(QQmlListProperty< QQuickState > *list)
Definition
qquickstategroup.cpp:164
QQuickStateGroupPrivate::ignoreTrans
bool ignoreTrans
Definition
qquickstategroup.cpp:50
QQuickStateGroupPrivate::replace_states
static void replace_states(QQmlListProperty< QQuickState > *list, qsizetype index, QQuickState *state)
Definition
qquickstategroup.cpp:175
QQuickStateGroupPrivate::removeLast_states
static void removeLast_states(QQmlListProperty< QQuickState > *list)
Definition
qquickstategroup.cpp:192
QQuickStateGroupPrivate::updateAutoState
bool updateAutoState()
Definition
qquickstategroup.cpp:342
QQuickStateGroupPrivate::setCurrentStateInternal
void setCurrentStateInternal(const QString &state, bool=false)
Definition
qquickstategroup.cpp:458
QQuickStateGroupPrivate::componentComplete
bool componentComplete
Definition
qquickstategroup.cpp:49
QQuickStateGroupPrivate::at_transition
static QQuickTransition * at_transition(QQmlListProperty< QQuickTransition > *list, qsizetype index)
Definition
qquickstategroup.cpp:247
QQuickStateGroupPrivate::at_state
static QQuickState * at_state(QQmlListProperty< QQuickState > *list, qsizetype index)
Definition
qquickstategroup.cpp:158
QQuickStateGroupPrivate::clear_transitions
static void clear_transitions(QQmlListProperty< QQuickTransition > *list)
Definition
qquickstategroup.cpp:253
QQuickStateGroupPrivate::append_transition
static void append_transition(QQmlListProperty< QQuickTransition > *list, QQuickTransition *state)
Definition
qquickstategroup.cpp:234
QQuickStateGroupPrivate::findTransition
QQuickTransition * findTransition(const QString &from, const QString &to)
Definition
qquickstategroup.cpp:392
QQuickStateGroupPrivate::count_state
static qsizetype count_state(QQmlListProperty< QQuickState > *list)
Definition
qquickstategroup.cpp:152
QQuickStateGroupPrivate::append_state
static void append_state(QQmlListProperty< QQuickState > *list, QQuickState *state)
Definition
qquickstategroup.cpp:144
QQuickStateGroupPrivate::unnamedCount
int unnamedCount
Definition
qquickstategroup.cpp:52
QQuickStateGroupPrivate::transitions
QList< QQuickTransition * > transitions
Definition
qquickstategroup.cpp:47
QQuickStateGroupPrivate::states
QList< QQuickState * > states
Definition
qquickstategroup.cpp:46
QQuickStateGroupPrivate::applyingState
bool applyingState
Definition
qquickstategroup.cpp:51
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtdeclarative
src
quick
util
qquickstategroup.cpp
Generated on
for Qt by
1.18.0