1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "declarativeseries_p.h" |
5 | #include <QtCore/QMetaMethod> |
6 | |
7 | QT_BEGIN_NAMESPACE |
8 | |
9 | static void setSeriesGradient(QAbstract3DSeries *series, const ColorGradient &gradient, |
10 | GradientType type) |
11 | { |
12 | QLinearGradient newGradient; |
13 | QGradientStops stops; |
14 | QList<ColorGradientStop *> qmlstops = gradient.m_stops; |
15 | |
16 | // Get sorted gradient stops |
17 | for (int i = 0; i < qmlstops.size(); i++) { |
18 | int j = 0; |
19 | while (j < stops.size() && stops.at(i: j).first < qmlstops[i]->position()) |
20 | j++; |
21 | stops.insert(i: j, t: QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color())); |
22 | } |
23 | |
24 | newGradient.setStops(stops); |
25 | switch (type) { |
26 | case GradientTypeBase: |
27 | series->setBaseGradient(newGradient); |
28 | break; |
29 | case GradientTypeSingle: |
30 | series->setSingleHighlightGradient(newGradient); |
31 | break; |
32 | case GradientTypeMulti: |
33 | series->setMultiHighlightGradient(newGradient); |
34 | break; |
35 | default: // Never goes here |
36 | break; |
37 | } |
38 | } |
39 | |
40 | static void connectSeriesGradient(QAbstract3DSeries *series, ColorGradient *newGradient, |
41 | GradientType type, ColorGradient **memberGradient) |
42 | { |
43 | // connect new / disconnect old |
44 | if (newGradient != *memberGradient) { |
45 | if (*memberGradient) |
46 | QObject::disconnect(sender: *memberGradient, signal: 0, receiver: series, member: 0); |
47 | |
48 | *memberGradient = newGradient; |
49 | |
50 | int updatedIndex = newGradient->metaObject()->indexOfSignal(signal: "updated()" ); |
51 | QMetaMethod updateFunction = newGradient->metaObject()->method(index: updatedIndex); |
52 | int handleIndex = -1; |
53 | switch (type) { |
54 | case GradientTypeBase: |
55 | handleIndex = series->metaObject()->indexOfSlot(slot: "handleBaseGradientUpdate()" ); |
56 | break; |
57 | case GradientTypeSingle: |
58 | handleIndex = series->metaObject()->indexOfSlot(slot: "handleSingleHighlightGradientUpdate()" ); |
59 | break; |
60 | case GradientTypeMulti: |
61 | handleIndex = series->metaObject()->indexOfSlot(slot: "handleMultiHighlightGradientUpdate()" ); |
62 | break; |
63 | default: // Never goes here |
64 | break; |
65 | } |
66 | QMetaMethod handleFunction = series->metaObject()->method(index: handleIndex); |
67 | |
68 | if (*memberGradient) |
69 | QObject::connect(sender: *memberGradient, signal: updateFunction, receiver: series, method: handleFunction); |
70 | } |
71 | |
72 | if (*memberGradient) |
73 | setSeriesGradient(series, gradient: **memberGradient, type); |
74 | } |
75 | |
76 | DeclarativeBar3DSeries::DeclarativeBar3DSeries(QObject *parent) |
77 | : QBar3DSeries(parent), |
78 | m_baseGradient(0), |
79 | m_singleHighlightGradient(0), |
80 | m_multiHighlightGradient(0), |
81 | m_dummyColors(false) |
82 | { |
83 | QObject::connect(sender: this, signal: &QBar3DSeries::selectedBarChanged, context: this, |
84 | slot: &DeclarativeBar3DSeries::selectedBarChanged); |
85 | } |
86 | |
87 | DeclarativeBar3DSeries::~DeclarativeBar3DSeries() |
88 | { |
89 | } |
90 | |
91 | QQmlListProperty<QObject> DeclarativeBar3DSeries::seriesChildren() |
92 | { |
93 | return QQmlListProperty<QObject>(this, this, &DeclarativeBar3DSeries::appendSeriesChildren |
94 | , 0, 0, 0); |
95 | } |
96 | |
97 | void DeclarativeBar3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element) |
98 | { |
99 | QBarDataProxy *proxy = qobject_cast<QBarDataProxy *>(object: element); |
100 | if (proxy) |
101 | reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->setDataProxy(proxy); |
102 | } |
103 | |
104 | void DeclarativeBar3DSeries::setSelectedBar(const QPointF &position) |
105 | { |
106 | QBar3DSeries::setSelectedBar(position.toPoint()); |
107 | } |
108 | |
109 | QPointF DeclarativeBar3DSeries::selectedBar() const |
110 | { |
111 | return QPointF(QBar3DSeries::selectedBar()); |
112 | } |
113 | |
114 | QPointF DeclarativeBar3DSeries::invalidSelectionPosition() const |
115 | { |
116 | return QPointF(QBar3DSeries::invalidSelectionPosition()); |
117 | } |
118 | |
119 | void DeclarativeBar3DSeries::setBaseGradient(ColorGradient *gradient) |
120 | { |
121 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeBase, memberGradient: &m_baseGradient); |
122 | } |
123 | |
124 | ColorGradient *DeclarativeBar3DSeries::baseGradient() const |
125 | { |
126 | return m_baseGradient; |
127 | } |
128 | |
129 | void DeclarativeBar3DSeries::setSingleHighlightGradient(ColorGradient *gradient) |
130 | { |
131 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeSingle, memberGradient: &m_singleHighlightGradient); |
132 | } |
133 | |
134 | ColorGradient *DeclarativeBar3DSeries::singleHighlightGradient() const |
135 | { |
136 | return m_singleHighlightGradient; |
137 | } |
138 | |
139 | void DeclarativeBar3DSeries::setMultiHighlightGradient(ColorGradient *gradient) |
140 | { |
141 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeMulti, memberGradient: &m_multiHighlightGradient); |
142 | } |
143 | |
144 | ColorGradient *DeclarativeBar3DSeries::multiHighlightGradient() const |
145 | { |
146 | return m_multiHighlightGradient; |
147 | } |
148 | |
149 | QQmlListProperty<DeclarativeColor> DeclarativeBar3DSeries::rowColors() |
150 | { |
151 | return QQmlListProperty<DeclarativeColor>(this, this, |
152 | &DeclarativeBar3DSeries::appendRowColorsFunc, |
153 | &DeclarativeBar3DSeries::countRowColorsFunc, |
154 | &DeclarativeBar3DSeries::atRowColorsFunc, |
155 | &DeclarativeBar3DSeries::clearRowColorsFunc); |
156 | } |
157 | |
158 | void DeclarativeBar3DSeries::appendRowColorsFunc(QQmlListProperty<DeclarativeColor> *list, |
159 | DeclarativeColor *color) |
160 | { |
161 | reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->addColor(color); |
162 | } |
163 | |
164 | qsizetype DeclarativeBar3DSeries::countRowColorsFunc(QQmlListProperty<DeclarativeColor> *list) |
165 | { |
166 | return reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->colorList().size(); |
167 | } |
168 | |
169 | DeclarativeColor *DeclarativeBar3DSeries::atRowColorsFunc(QQmlListProperty<DeclarativeColor> *list, |
170 | qsizetype index) |
171 | { |
172 | return reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->colorList().at(i: index); |
173 | } |
174 | |
175 | void DeclarativeBar3DSeries::clearRowColorsFunc(QQmlListProperty<DeclarativeColor> *list) |
176 | { |
177 | reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->clearColors(); |
178 | } |
179 | |
180 | void DeclarativeBar3DSeries::handleBaseGradientUpdate() |
181 | { |
182 | if (m_baseGradient) |
183 | setSeriesGradient(series: this, gradient: *m_baseGradient, type: GradientTypeBase); |
184 | } |
185 | |
186 | void DeclarativeBar3DSeries::handleSingleHighlightGradientUpdate() |
187 | { |
188 | if (m_singleHighlightGradient) |
189 | setSeriesGradient(series: this, gradient: *m_singleHighlightGradient, type: GradientTypeSingle); |
190 | } |
191 | |
192 | void DeclarativeBar3DSeries::handleMultiHighlightGradientUpdate() |
193 | { |
194 | if (m_multiHighlightGradient) |
195 | setSeriesGradient(series: this, gradient: *m_multiHighlightGradient, type: GradientTypeMulti); |
196 | } |
197 | |
198 | void DeclarativeBar3DSeries::handleRowColorUpdate() |
199 | { |
200 | int colorCount = m_rowColors.size(); |
201 | int changed = 0; |
202 | |
203 | DeclarativeColor *color = qobject_cast<DeclarativeColor*>(object: QObject::sender()); |
204 | for (int i = 0; i < colorCount; i++) { |
205 | if (color == m_rowColors.at(i)) { |
206 | changed = i; |
207 | break; |
208 | } |
209 | } |
210 | QList<QColor> list = QBar3DSeries::rowColors(); |
211 | list[changed] = m_rowColors.at(i: changed)->color(); |
212 | QBar3DSeries::setRowColors(list); |
213 | } |
214 | |
215 | void DeclarativeBar3DSeries::addColor(DeclarativeColor *color) |
216 | { |
217 | if (!color) { |
218 | qWarning(msg: "Color is invalid, use ThemeColor" ); |
219 | return; |
220 | } |
221 | clearDummyColors(); |
222 | m_rowColors.append(t: color); |
223 | connect(sender: color, signal: &DeclarativeColor::colorChanged, context: this, |
224 | slot: &DeclarativeBar3DSeries::handleRowColorUpdate); |
225 | QList<QColor> list = QBar3DSeries::rowColors(); |
226 | list.append(t: color->color()); |
227 | QBar3DSeries::setRowColors(list); |
228 | } |
229 | |
230 | QList<DeclarativeColor *> DeclarativeBar3DSeries::colorList() |
231 | { |
232 | if (m_rowColors.isEmpty()) { |
233 | m_dummyColors = true; |
234 | const QList<QColor> list = QBar3DSeries::rowColors(); |
235 | for (const QColor &item : list) { |
236 | DeclarativeColor *color = new DeclarativeColor(this); |
237 | color->setColor(item); |
238 | m_rowColors.append(t: color); |
239 | connect(sender: color, signal: &DeclarativeColor::colorChanged, context: this, |
240 | slot: &DeclarativeBar3DSeries::handleRowColorUpdate); |
241 | } |
242 | } |
243 | return m_rowColors; |
244 | } |
245 | |
246 | void DeclarativeBar3DSeries::clearColors() |
247 | { |
248 | clearDummyColors(); |
249 | for (const auto color : std::as_const(t&: m_rowColors)) |
250 | disconnect(sender: color, signal: 0, receiver: this, member: 0); |
251 | |
252 | m_rowColors.clear(); |
253 | QBar3DSeries::setRowColors(QList<QColor>()); |
254 | } |
255 | |
256 | void DeclarativeBar3DSeries::clearDummyColors() |
257 | { |
258 | if (m_dummyColors) { |
259 | qDeleteAll(c: m_rowColors); |
260 | m_rowColors.clear(); |
261 | m_dummyColors = false; |
262 | } |
263 | } |
264 | |
265 | DeclarativeScatter3DSeries::DeclarativeScatter3DSeries(QObject *parent) |
266 | : QScatter3DSeries(parent), |
267 | m_baseGradient(0), |
268 | m_singleHighlightGradient(0), |
269 | m_multiHighlightGradient(0) |
270 | { |
271 | } |
272 | |
273 | DeclarativeScatter3DSeries::~DeclarativeScatter3DSeries() |
274 | { |
275 | } |
276 | |
277 | QQmlListProperty<QObject> DeclarativeScatter3DSeries::seriesChildren() |
278 | { |
279 | return QQmlListProperty<QObject>(this, this, &DeclarativeScatter3DSeries::appendSeriesChildren |
280 | , 0, 0, 0); |
281 | } |
282 | |
283 | void DeclarativeScatter3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, |
284 | QObject *element) |
285 | { |
286 | QScatterDataProxy *proxy = qobject_cast<QScatterDataProxy *>(object: element); |
287 | if (proxy) |
288 | reinterpret_cast<DeclarativeScatter3DSeries *>(list->data)->setDataProxy(proxy); |
289 | } |
290 | |
291 | void DeclarativeScatter3DSeries::setBaseGradient(ColorGradient *gradient) |
292 | { |
293 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeBase, memberGradient: &m_baseGradient); |
294 | } |
295 | |
296 | ColorGradient *DeclarativeScatter3DSeries::baseGradient() const |
297 | { |
298 | return m_baseGradient; |
299 | } |
300 | |
301 | void DeclarativeScatter3DSeries::setSingleHighlightGradient(ColorGradient *gradient) |
302 | { |
303 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeSingle, memberGradient: &m_singleHighlightGradient); |
304 | } |
305 | |
306 | ColorGradient *DeclarativeScatter3DSeries::singleHighlightGradient() const |
307 | { |
308 | return m_singleHighlightGradient; |
309 | } |
310 | |
311 | void DeclarativeScatter3DSeries::setMultiHighlightGradient(ColorGradient *gradient) |
312 | { |
313 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeMulti, memberGradient: &m_multiHighlightGradient); |
314 | } |
315 | |
316 | ColorGradient *DeclarativeScatter3DSeries::multiHighlightGradient() const |
317 | { |
318 | return m_multiHighlightGradient; |
319 | } |
320 | |
321 | int DeclarativeScatter3DSeries::invalidSelectionIndex() const |
322 | { |
323 | return QScatter3DSeries::invalidSelectionIndex(); |
324 | } |
325 | |
326 | void DeclarativeScatter3DSeries::handleBaseGradientUpdate() |
327 | { |
328 | if (m_baseGradient) |
329 | setSeriesGradient(series: this, gradient: *m_baseGradient, type: GradientTypeBase); |
330 | } |
331 | |
332 | void DeclarativeScatter3DSeries::handleSingleHighlightGradientUpdate() |
333 | { |
334 | if (m_singleHighlightGradient) |
335 | setSeriesGradient(series: this, gradient: *m_singleHighlightGradient, type: GradientTypeSingle); |
336 | } |
337 | |
338 | void DeclarativeScatter3DSeries::handleMultiHighlightGradientUpdate() |
339 | { |
340 | if (m_multiHighlightGradient) |
341 | setSeriesGradient(series: this, gradient: *m_multiHighlightGradient, type: GradientTypeMulti); |
342 | } |
343 | |
344 | DeclarativeSurface3DSeries::DeclarativeSurface3DSeries(QObject *parent) |
345 | : QSurface3DSeries(parent), |
346 | m_baseGradient(0), |
347 | m_singleHighlightGradient(0), |
348 | m_multiHighlightGradient(0) |
349 | { |
350 | QObject::connect(sender: this, signal: &QSurface3DSeries::selectedPointChanged, context: this, |
351 | slot: &DeclarativeSurface3DSeries::selectedPointChanged); |
352 | } |
353 | |
354 | DeclarativeSurface3DSeries::~DeclarativeSurface3DSeries() |
355 | { |
356 | } |
357 | |
358 | void DeclarativeSurface3DSeries::setSelectedPoint(const QPointF &position) |
359 | { |
360 | QSurface3DSeries::setSelectedPoint(position.toPoint()); |
361 | } |
362 | |
363 | QPointF DeclarativeSurface3DSeries::selectedPoint() const |
364 | { |
365 | return QPointF(QSurface3DSeries::selectedPoint()); |
366 | } |
367 | |
368 | QPointF DeclarativeSurface3DSeries::invalidSelectionPosition() const |
369 | { |
370 | return QPointF(QSurface3DSeries::invalidSelectionPosition()); |
371 | } |
372 | |
373 | QQmlListProperty<QObject> DeclarativeSurface3DSeries::seriesChildren() |
374 | { |
375 | return QQmlListProperty<QObject>(this, this, &DeclarativeSurface3DSeries::appendSeriesChildren |
376 | , 0, 0, 0); |
377 | } |
378 | |
379 | void DeclarativeSurface3DSeries::appendSeriesChildren(QQmlListProperty<QObject> *list, |
380 | QObject *element) |
381 | { |
382 | QSurfaceDataProxy *proxy = qobject_cast<QSurfaceDataProxy *>(object: element); |
383 | if (proxy) |
384 | reinterpret_cast<DeclarativeSurface3DSeries *>(list->data)->setDataProxy(proxy); |
385 | } |
386 | |
387 | void DeclarativeSurface3DSeries::setBaseGradient(ColorGradient *gradient) |
388 | { |
389 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeBase, memberGradient: &m_baseGradient); |
390 | } |
391 | |
392 | ColorGradient *DeclarativeSurface3DSeries::baseGradient() const |
393 | { |
394 | return m_baseGradient; |
395 | } |
396 | |
397 | void DeclarativeSurface3DSeries::setSingleHighlightGradient(ColorGradient *gradient) |
398 | { |
399 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeSingle, memberGradient: &m_singleHighlightGradient); |
400 | } |
401 | |
402 | ColorGradient *DeclarativeSurface3DSeries::singleHighlightGradient() const |
403 | { |
404 | return m_singleHighlightGradient; |
405 | } |
406 | |
407 | void DeclarativeSurface3DSeries::setMultiHighlightGradient(ColorGradient *gradient) |
408 | { |
409 | connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeMulti, memberGradient: &m_multiHighlightGradient); |
410 | } |
411 | |
412 | ColorGradient *DeclarativeSurface3DSeries::multiHighlightGradient() const |
413 | { |
414 | return m_multiHighlightGradient; |
415 | } |
416 | |
417 | void DeclarativeSurface3DSeries::handleBaseGradientUpdate() |
418 | { |
419 | if (m_baseGradient) |
420 | setSeriesGradient(series: this, gradient: *m_baseGradient, type: GradientTypeBase); |
421 | } |
422 | |
423 | void DeclarativeSurface3DSeries::handleSingleHighlightGradientUpdate() |
424 | { |
425 | if (m_singleHighlightGradient) |
426 | setSeriesGradient(series: this, gradient: *m_singleHighlightGradient, type: GradientTypeSingle); |
427 | } |
428 | |
429 | void DeclarativeSurface3DSeries::handleMultiHighlightGradientUpdate() |
430 | { |
431 | if (m_multiHighlightGradient) |
432 | setSeriesGradient(series: this, gradient: *m_multiHighlightGradient, type: GradientTypeMulti); |
433 | } |
434 | |
435 | QT_END_NAMESPACE |
436 | |