1// Copyright (C) 2016 Ford Motor Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQMLCHILDRENPRIVATE_H
5#define QQMLCHILDRENPRIVATE_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QAbstractState>
19#include <QAbstractTransition>
20#include <QStateMachine>
21#include <QQmlInfo>
22#include <QQmlListProperty>
23#include <private/qglobal_p.h>
24
25enum class ChildrenMode {
26 None = 0x0,
27 State = 0x1,
28 Transition = 0x2,
29 StateOrTransition = State | Transition
30};
31
32template<typename T>
33static T *parentObject(QQmlListProperty<QObject> *prop) { return static_cast<T *>(prop->object); }
34
35template<class T, ChildrenMode Mode>
36struct ParentHandler
37{
38 static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem);
39 static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item);
40};
41
42template<class T>
43struct ParentHandler<T, ChildrenMode::None>
44{
45 static bool unparentItem(QQmlListProperty<QObject> *, QObject *) { return true; }
46 static bool parentItem(QQmlListProperty<QObject> *, QObject *) { return true; }
47};
48
49template<class T>
50struct ParentHandler<T, ChildrenMode::State>
51{
52 static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item)
53 {
54 if (QAbstractState *state = qobject_cast<QAbstractState *>(object: item)) {
55 state->setParent(parentObject<T>(prop));
56 return true;
57 }
58 return false;
59 }
60
61 static bool unparentItem(QQmlListProperty<QObject> *, QObject *oldItem)
62 {
63 if (QAbstractState *state = qobject_cast<QAbstractState *>(object: oldItem)) {
64 state->setParent(nullptr);
65 return true;
66 }
67 return false;
68 }
69};
70
71template<class T>
72struct ParentHandler<T, ChildrenMode::Transition>
73{
74 static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item)
75 {
76 if (QAbstractTransition *trans = qobject_cast<QAbstractTransition *>(object: item)) {
77 parentObject<T>(prop)->addTransition(trans);
78 return true;
79 }
80 return false;
81 }
82
83 static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem)
84 {
85 if (QAbstractTransition *trans = qobject_cast<QAbstractTransition *>(object: oldItem)) {
86 parentObject<T>(prop)->removeTransition(trans);
87 return true;
88 }
89 return false;
90 }
91};
92
93template<class T>
94struct ParentHandler<T, ChildrenMode::StateOrTransition>
95{
96 static bool parentItem(QQmlListProperty<QObject> *prop, QObject *oldItem)
97 {
98 return ParentHandler<T, ChildrenMode::State>::parentItem(prop, oldItem)
99 || ParentHandler<T, ChildrenMode::Transition>::parentItem(prop, oldItem);
100 }
101
102 static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem)
103 {
104 return ParentHandler<T, ChildrenMode::State>::unparentItem(prop, oldItem)
105 || ParentHandler<T, ChildrenMode::Transition>::unparentItem(prop, oldItem);
106 }
107};
108
109template <class T, ChildrenMode Mode>
110class ChildrenPrivate
111{
112public:
113 static void append(QQmlListProperty<QObject> *prop, QObject *item)
114 {
115 Handler::parentItem(prop, item);
116 static_cast<Self *>(prop->data)->children.append(item);
117 parentObject<T>(prop)->childrenContentChanged();
118 }
119
120 static qsizetype count(QQmlListProperty<QObject> *prop)
121 {
122 return static_cast<Self *>(prop->data)->children.size();
123 }
124
125 static QObject *at(QQmlListProperty<QObject> *prop, qsizetype index)
126 {
127 return static_cast<Self *>(prop->data)->children.at(index);
128 }
129
130 static void clear(QQmlListProperty<QObject> *prop)
131 {
132 auto &children = static_cast<Self *>(prop->data)->children;
133 for (QObject *oldItem : std::as_const(children))
134 Handler::unparentItem(prop, oldItem);
135
136 children.clear();
137 parentObject<T>(prop)->childrenContentChanged();
138 }
139
140 static void replace(QQmlListProperty<QObject> *prop, qsizetype index, QObject *item)
141 {
142 auto &children = static_cast<Self *>(prop->data)->children;
143
144 Handler::unparentItem(prop, children.at(index));
145 Handler::parentItem(prop, item);
146
147 children.replace(index, item);
148 parentObject<T>(prop)->childrenContentChanged();
149 }
150
151 static void removeLast(QQmlListProperty<QObject> *prop)
152 {
153 Handler::unparentItem(prop, static_cast<Self *>(prop->data)->children.takeLast());
154 parentObject<T>(prop)->childrenContentChanged();
155 }
156
157private:
158 using Self = ChildrenPrivate<T, Mode>;
159 using Handler = ParentHandler<T, Mode>;
160
161 QList<QObject *> children;
162};
163
164#endif
165

source code of qtscxml/src/statemachineqml/childrenprivate_p.h