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
7QT_BEGIN_NAMESPACE
8
9static 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
40static 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
76DeclarativeBar3DSeries::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
87DeclarativeBar3DSeries::~DeclarativeBar3DSeries()
88{
89}
90
91QQmlListProperty<QObject> DeclarativeBar3DSeries::seriesChildren()
92{
93 return QQmlListProperty<QObject>(this, this, &DeclarativeBar3DSeries::appendSeriesChildren
94 , 0, 0, 0);
95}
96
97void 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
104void DeclarativeBar3DSeries::setSelectedBar(const QPointF &position)
105{
106 QBar3DSeries::setSelectedBar(position.toPoint());
107}
108
109QPointF DeclarativeBar3DSeries::selectedBar() const
110{
111 return QPointF(QBar3DSeries::selectedBar());
112}
113
114QPointF DeclarativeBar3DSeries::invalidSelectionPosition() const
115{
116 return QPointF(QBar3DSeries::invalidSelectionPosition());
117}
118
119void DeclarativeBar3DSeries::setBaseGradient(ColorGradient *gradient)
120{
121 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeBase, memberGradient: &m_baseGradient);
122}
123
124ColorGradient *DeclarativeBar3DSeries::baseGradient() const
125{
126 return m_baseGradient;
127}
128
129void DeclarativeBar3DSeries::setSingleHighlightGradient(ColorGradient *gradient)
130{
131 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeSingle, memberGradient: &m_singleHighlightGradient);
132}
133
134ColorGradient *DeclarativeBar3DSeries::singleHighlightGradient() const
135{
136 return m_singleHighlightGradient;
137}
138
139void DeclarativeBar3DSeries::setMultiHighlightGradient(ColorGradient *gradient)
140{
141 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeMulti, memberGradient: &m_multiHighlightGradient);
142}
143
144ColorGradient *DeclarativeBar3DSeries::multiHighlightGradient() const
145{
146 return m_multiHighlightGradient;
147}
148
149QQmlListProperty<DeclarativeColor> DeclarativeBar3DSeries::rowColors()
150{
151 return QQmlListProperty<DeclarativeColor>(this, this,
152 &DeclarativeBar3DSeries::appendRowColorsFunc,
153 &DeclarativeBar3DSeries::countRowColorsFunc,
154 &DeclarativeBar3DSeries::atRowColorsFunc,
155 &DeclarativeBar3DSeries::clearRowColorsFunc);
156}
157
158void DeclarativeBar3DSeries::appendRowColorsFunc(QQmlListProperty<DeclarativeColor> *list,
159 DeclarativeColor *color)
160{
161 reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->addColor(color);
162}
163
164qsizetype DeclarativeBar3DSeries::countRowColorsFunc(QQmlListProperty<DeclarativeColor> *list)
165{
166 return reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->colorList().size();
167}
168
169DeclarativeColor *DeclarativeBar3DSeries::atRowColorsFunc(QQmlListProperty<DeclarativeColor> *list,
170 qsizetype index)
171{
172 return reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->colorList().at(i: index);
173}
174
175void DeclarativeBar3DSeries::clearRowColorsFunc(QQmlListProperty<DeclarativeColor> *list)
176{
177 reinterpret_cast<DeclarativeBar3DSeries *>(list->data)->clearColors();
178}
179
180void DeclarativeBar3DSeries::handleBaseGradientUpdate()
181{
182 if (m_baseGradient)
183 setSeriesGradient(series: this, gradient: *m_baseGradient, type: GradientTypeBase);
184}
185
186void DeclarativeBar3DSeries::handleSingleHighlightGradientUpdate()
187{
188 if (m_singleHighlightGradient)
189 setSeriesGradient(series: this, gradient: *m_singleHighlightGradient, type: GradientTypeSingle);
190}
191
192void DeclarativeBar3DSeries::handleMultiHighlightGradientUpdate()
193{
194 if (m_multiHighlightGradient)
195 setSeriesGradient(series: this, gradient: *m_multiHighlightGradient, type: GradientTypeMulti);
196}
197
198void 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
215void 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
230QList<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
246void 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
256void DeclarativeBar3DSeries::clearDummyColors()
257{
258 if (m_dummyColors) {
259 qDeleteAll(c: m_rowColors);
260 m_rowColors.clear();
261 m_dummyColors = false;
262 }
263}
264
265DeclarativeScatter3DSeries::DeclarativeScatter3DSeries(QObject *parent)
266 : QScatter3DSeries(parent),
267 m_baseGradient(0),
268 m_singleHighlightGradient(0),
269 m_multiHighlightGradient(0)
270{
271}
272
273DeclarativeScatter3DSeries::~DeclarativeScatter3DSeries()
274{
275}
276
277QQmlListProperty<QObject> DeclarativeScatter3DSeries::seriesChildren()
278{
279 return QQmlListProperty<QObject>(this, this, &DeclarativeScatter3DSeries::appendSeriesChildren
280 , 0, 0, 0);
281}
282
283void 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
291void DeclarativeScatter3DSeries::setBaseGradient(ColorGradient *gradient)
292{
293 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeBase, memberGradient: &m_baseGradient);
294}
295
296ColorGradient *DeclarativeScatter3DSeries::baseGradient() const
297{
298 return m_baseGradient;
299}
300
301void DeclarativeScatter3DSeries::setSingleHighlightGradient(ColorGradient *gradient)
302{
303 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeSingle, memberGradient: &m_singleHighlightGradient);
304}
305
306ColorGradient *DeclarativeScatter3DSeries::singleHighlightGradient() const
307{
308 return m_singleHighlightGradient;
309}
310
311void DeclarativeScatter3DSeries::setMultiHighlightGradient(ColorGradient *gradient)
312{
313 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeMulti, memberGradient: &m_multiHighlightGradient);
314}
315
316ColorGradient *DeclarativeScatter3DSeries::multiHighlightGradient() const
317{
318 return m_multiHighlightGradient;
319}
320
321int DeclarativeScatter3DSeries::invalidSelectionIndex() const
322{
323 return QScatter3DSeries::invalidSelectionIndex();
324}
325
326void DeclarativeScatter3DSeries::handleBaseGradientUpdate()
327{
328 if (m_baseGradient)
329 setSeriesGradient(series: this, gradient: *m_baseGradient, type: GradientTypeBase);
330}
331
332void DeclarativeScatter3DSeries::handleSingleHighlightGradientUpdate()
333{
334 if (m_singleHighlightGradient)
335 setSeriesGradient(series: this, gradient: *m_singleHighlightGradient, type: GradientTypeSingle);
336}
337
338void DeclarativeScatter3DSeries::handleMultiHighlightGradientUpdate()
339{
340 if (m_multiHighlightGradient)
341 setSeriesGradient(series: this, gradient: *m_multiHighlightGradient, type: GradientTypeMulti);
342}
343
344DeclarativeSurface3DSeries::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
354DeclarativeSurface3DSeries::~DeclarativeSurface3DSeries()
355{
356}
357
358void DeclarativeSurface3DSeries::setSelectedPoint(const QPointF &position)
359{
360 QSurface3DSeries::setSelectedPoint(position.toPoint());
361}
362
363QPointF DeclarativeSurface3DSeries::selectedPoint() const
364{
365 return QPointF(QSurface3DSeries::selectedPoint());
366}
367
368QPointF DeclarativeSurface3DSeries::invalidSelectionPosition() const
369{
370 return QPointF(QSurface3DSeries::invalidSelectionPosition());
371}
372
373QQmlListProperty<QObject> DeclarativeSurface3DSeries::seriesChildren()
374{
375 return QQmlListProperty<QObject>(this, this, &DeclarativeSurface3DSeries::appendSeriesChildren
376 , 0, 0, 0);
377}
378
379void 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
387void DeclarativeSurface3DSeries::setBaseGradient(ColorGradient *gradient)
388{
389 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeBase, memberGradient: &m_baseGradient);
390}
391
392ColorGradient *DeclarativeSurface3DSeries::baseGradient() const
393{
394 return m_baseGradient;
395}
396
397void DeclarativeSurface3DSeries::setSingleHighlightGradient(ColorGradient *gradient)
398{
399 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeSingle, memberGradient: &m_singleHighlightGradient);
400}
401
402ColorGradient *DeclarativeSurface3DSeries::singleHighlightGradient() const
403{
404 return m_singleHighlightGradient;
405}
406
407void DeclarativeSurface3DSeries::setMultiHighlightGradient(ColorGradient *gradient)
408{
409 connectSeriesGradient(series: this, newGradient: gradient, type: GradientTypeMulti, memberGradient: &m_multiHighlightGradient);
410}
411
412ColorGradient *DeclarativeSurface3DSeries::multiHighlightGradient() const
413{
414 return m_multiHighlightGradient;
415}
416
417void DeclarativeSurface3DSeries::handleBaseGradientUpdate()
418{
419 if (m_baseGradient)
420 setSeriesGradient(series: this, gradient: *m_baseGradient, type: GradientTypeBase);
421}
422
423void DeclarativeSurface3DSeries::handleSingleHighlightGradientUpdate()
424{
425 if (m_singleHighlightGradient)
426 setSeriesGradient(series: this, gradient: *m_singleHighlightGradient, type: GradientTypeSingle);
427}
428
429void DeclarativeSurface3DSeries::handleMultiHighlightGradientUpdate()
430{
431 if (m_multiHighlightGradient)
432 setSeriesGradient(series: this, gradient: *m_multiHighlightGradient, type: GradientTypeMulti);
433}
434
435QT_END_NAMESPACE
436

source code of qtgraphs/src/graphs/qml/declarativeseries.cpp