1/*
2 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6
7#include "ItemBuilder.h"
8
9class ItemIncubator : public QQmlIncubator
10{
11public:
12 ItemIncubator(QQmlComponent *component, QQmlContext *context)
13 {
14 m_component = component;
15 m_context = context;
16 }
17
18 void setStateCallback(std::function<void(QQuickItem*)> callback)
19 {
20 m_stateCallback = callback;
21 }
22
23 void setCompletedCallback(std::function<void(ItemIncubator*)> callback)
24 {
25 m_completedCallback = callback;
26 }
27
28 void create()
29 {
30 m_component->create(*this, context: m_context);
31 }
32
33 bool isFinished()
34 {
35 return m_finished;
36 }
37
38private:
39 void setInitialState(QObject *object) override
40 {
41 auto item = qobject_cast<QQuickItem*>(o: object);
42 if (item) {
43 m_stateCallback(item);
44 }
45 }
46
47 void statusChanged(QQmlIncubator::Status status) override
48 {
49 if (status == QQmlIncubator::Error) {
50 qWarning() << "Could not create delegate in ItemBuilder";
51 const auto e = errors();
52 for (const auto &error : e) {
53 qWarning() << error;
54 }
55 m_finished = true;
56 }
57
58 if (status == QQmlIncubator::Ready) {
59 m_completedCallback(this);
60 m_finished = true;
61 }
62 }
63
64 QQmlComponent *m_component;
65 QQmlContext *m_context;
66 std::function<void(QQuickItem*)> m_stateCallback;
67 std::function<void(ItemIncubator*)> m_completedCallback;
68 bool m_finished = false;
69};
70
71ItemBuilder::ItemBuilder(QObject *parent)
72 : QObject(parent)
73{
74}
75
76ItemBuilder::~ItemBuilder()
77{
78 clear();
79}
80
81QQmlComponent *ItemBuilder::component() const
82{
83 return m_component;
84}
85
86void ItemBuilder::setComponent(QQmlComponent *newComponent)
87{
88 if (newComponent == m_component) {
89 return;
90 }
91
92 m_component = newComponent;
93 clear();
94}
95
96QQmlContext *ItemBuilder::context() const
97{
98 return m_context;
99}
100
101void ItemBuilder::setContext(QQmlContext *newContext)
102{
103 if (newContext == m_context) {
104 return;
105 }
106
107 m_context = newContext;
108 clear();
109}
110
111
112int ItemBuilder::count() const
113{
114 return m_count;
115}
116
117void ItemBuilder::setCount(int newCount)
118{
119 if (newCount == m_count) {
120 return;
121 }
122
123 m_count = newCount;
124 clear();
125}
126
127QQmlIncubator::IncubationMode ItemBuilder::incubationMode() const
128{
129 return m_incubationMode;
130}
131
132void ItemBuilder::setIncubationMode(QQmlIncubator::IncubationMode newIncubationMode)
133{
134 if (newIncubationMode == m_incubationMode) {
135 return;
136 }
137
138 m_incubationMode = newIncubationMode;
139}
140
141QVariantMap ItemBuilder::initialProperties() const
142{
143 return m_initialProperties;
144}
145
146void ItemBuilder::setInitialProperties(const QVariantMap & newInitialProperties)
147{
148 if (newInitialProperties == m_initialProperties) {
149 return;
150 }
151
152 m_initialProperties = newInitialProperties;
153}
154
155void ItemBuilder::build(QQuickItem *parent)
156{
157 if ((int(m_items.size()) == m_count && m_incubators.empty()) || !m_incubators.empty() || !m_component) {
158 return;
159 }
160
161 m_incubators.reserve(n: m_count);
162 std::fill_n(first: std::back_inserter(x&: m_items), n: m_count, value: std::shared_ptr<QQuickItem>());
163
164 for (int i = 0; i < m_count; ++i) {
165 auto context = m_context ? m_context : qmlContext(m_component);
166 auto incubator = std::make_unique<ItemIncubator>(args&: m_component, args&: context);
167
168 incubator->setStateCallback([this, parent, i](QQuickItem *item) {
169 item->setParentItem(parent);
170
171 for (auto itr = m_initialProperties.keyValueBegin(); itr != m_initialProperties.keyValueEnd(); ++itr) {
172 item->setProperty(name: (*itr).first.toUtf8().data(), value: (*itr).second);
173 }
174
175 Q_EMIT beginCreate(index: i, item);
176 });
177
178 incubator->setCompletedCallback([this, i](ItemIncubator *incubator) {
179 auto item = std::shared_ptr<QQuickItem>(qobject_cast<QQuickItem*>(o: incubator->object()));
180 m_items[i] = item;
181
182 Q_EMIT endCreate(index: i, item: item.get());
183
184 m_completed++;
185 if (m_completed == m_count) {
186 QMetaObject::invokeMethod(object: this, function: [this]() {
187 m_incubators.clear();
188 }, type: Qt::QueuedConnection);
189 Q_EMIT finished();
190 }
191 });
192
193 incubator->create();
194
195 m_incubators.push_back(x: std::move(incubator));
196 }
197}
198
199bool ItemBuilder::isFinished() const
200{
201 return m_completed == m_count;
202}
203
204std::vector<std::shared_ptr<QQuickItem>> ItemBuilder::items() const
205{
206 return m_items;
207}
208
209void ItemBuilder::clear()
210{
211 m_items.clear();
212
213 if (m_incubators.size() > 0) {
214 for (auto &incubator : m_incubators) {
215 incubator->clear();
216 }
217 }
218 m_incubators.clear();
219
220 m_completed = 0;
221}
222
223#include "moc_ItemBuilder.cpp"
224

source code of kquickcharts/src/ItemBuilder.cpp