1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
5
6#include "declarativetheme_p.h"
7
8QT_BEGIN_NAMESPACE
9
10DeclarativeTheme3D::DeclarativeTheme3D(QObject *parent)
11 : Q3DTheme(parent),
12 m_colors(QList<DeclarativeColor *>()),
13 m_gradients(QList<ColorGradient *>()),
14 m_singleHLGradient(0),
15 m_multiHLGradient(0),
16 m_dummyGradients(false),
17 m_dummyColors(false)
18{
19 connect(sender: this, signal: &Q3DTheme::typeChanged, context: this, slot: &DeclarativeTheme3D::handleTypeChange);
20}
21
22DeclarativeTheme3D::~DeclarativeTheme3D()
23{
24}
25
26QQmlListProperty<QObject> DeclarativeTheme3D::themeChildren()
27{
28 return QQmlListProperty<QObject>(this, this, &DeclarativeTheme3D::appendThemeChildren,
29 0, 0, 0);
30}
31
32void DeclarativeTheme3D::appendThemeChildren(QQmlListProperty<QObject> *list, QObject *element)
33{
34 Q_UNUSED(list);
35 Q_UNUSED(element);
36 // Nothing to do, themeChildren is there only to enable scoping gradient items in Theme3D item.
37}
38
39void DeclarativeTheme3D::handleTypeChange(Theme themeType)
40{
41 Q_UNUSED(themeType);
42
43 // Theme changed, disconnect base color/gradient connections
44 if (!m_colors.isEmpty()) {
45 foreach (DeclarativeColor *item, m_colors)
46 disconnect(sender: item, signal: 0, receiver: this, member: 0);
47 m_colors.clear();
48 }
49 if (!m_gradients.isEmpty()) {
50 foreach (ColorGradient *item, m_gradients)
51 disconnect(sender: item, signal: 0, receiver: this, member: 0);
52 m_gradients.clear();
53 }
54}
55
56void DeclarativeTheme3D::handleBaseColorUpdate()
57{
58 int colorCount = m_colors.size();
59 int changed = 0;
60 // Check which one changed
61 DeclarativeColor *color = qobject_cast<DeclarativeColor *>(object: QObject::sender());
62 for (int i = 0; i < colorCount; i++) {
63 if (color == m_colors.at(i)) {
64 changed = i;
65 break;
66 }
67 }
68 // Update the changed one from the list
69 QList<QColor> list = Q3DTheme::baseColors();
70 list[changed] = m_colors.at(i: changed)->color();
71 // Set the changed list
72 Q3DTheme::setBaseColors(list);
73}
74
75void DeclarativeTheme3D::handleBaseGradientUpdate()
76{
77 int gradientCount = m_gradients.size();
78 int changed = 0;
79 // Check which one changed
80 ColorGradient *gradient = qobject_cast<ColorGradient *>(object: QObject::sender());
81 for (int i = 0; i < gradientCount; i++) {
82 if (gradient == m_gradients.at(i)) {
83 changed = i;
84 break;
85 }
86 }
87 // Update the changed one from the list
88 QList<QLinearGradient> list = Q3DTheme::baseGradients();
89 list[changed] = convertGradient(gradient);
90 // Set the changed list
91 Q3DTheme::setBaseGradients(list);
92}
93
94void DeclarativeTheme3D::handleSingleHLGradientUpdate()
95{
96 if (m_singleHLGradient)
97 setThemeGradient(gradient: m_singleHLGradient, type: GradientTypeSingleHL);
98}
99
100void DeclarativeTheme3D::handleMultiHLGradientUpdate()
101{
102 if (m_multiHLGradient)
103 setThemeGradient(gradient: m_multiHLGradient, type: GradientTypeMultiHL);
104}
105
106void DeclarativeTheme3D::setSingleHighlightGradient(ColorGradient *gradient)
107{
108 // connect new / disconnect old
109 if (gradient != m_singleHLGradient) {
110 if (m_singleHLGradient)
111 QObject::disconnect(sender: m_singleHLGradient, signal: 0, receiver: this, member: 0);
112
113 m_singleHLGradient = gradient;
114
115 if (m_singleHLGradient) {
116 QObject::connect(sender: m_singleHLGradient, signal: &ColorGradient::updated, context: this,
117 slot: &DeclarativeTheme3D::handleSingleHLGradientUpdate);
118 }
119
120 emit singleHighlightGradientChanged(gradient: m_singleHLGradient);
121 }
122
123 if (m_singleHLGradient)
124 setThemeGradient(gradient: m_singleHLGradient, type: GradientTypeSingleHL);
125}
126
127ColorGradient *DeclarativeTheme3D::singleHighlightGradient() const
128{
129 return m_singleHLGradient;
130}
131
132void DeclarativeTheme3D::setMultiHighlightGradient(ColorGradient *gradient)
133{
134 // connect new / disconnect old
135 if (gradient != m_multiHLGradient) {
136 if (m_multiHLGradient)
137 QObject::disconnect(sender: m_multiHLGradient, signal: 0, receiver: this, member: 0);
138
139 m_multiHLGradient = gradient;
140
141 if (m_multiHLGradient) {
142 QObject::connect(sender: m_multiHLGradient, signal: &ColorGradient::updated, context: this,
143 slot: &DeclarativeTheme3D::handleMultiHLGradientUpdate);
144 }
145
146 emit multiHighlightGradientChanged(gradient: m_multiHLGradient);
147 }
148
149 if (m_multiHLGradient)
150 setThemeGradient(gradient: m_multiHLGradient, type: GradientTypeMultiHL);
151}
152
153ColorGradient *DeclarativeTheme3D::multiHighlightGradient() const
154{
155 return m_multiHLGradient;
156}
157
158void DeclarativeTheme3D::classBegin()
159{
160 // Turn off predefined type forcing for the duration of initial class construction
161 // so that predefined type customization can be done.
162 d_ptr->setForcePredefinedType(false);
163}
164
165void DeclarativeTheme3D::componentComplete()
166{
167 d_ptr->setForcePredefinedType(true);
168}
169
170
171void DeclarativeTheme3D::setThemeGradient(ColorGradient *gradient, GradientType type)
172{
173 QLinearGradient newGradient = convertGradient(gradient);
174
175 switch (type) {
176 case GradientTypeSingleHL:
177 Q3DTheme::setSingleHighlightGradient(newGradient);
178 break;
179 case GradientTypeMultiHL:
180 Q3DTheme::setMultiHighlightGradient(newGradient);
181 break;
182 default:
183 qWarning(msg: "Incorrect usage. Type may be GradientTypeSingleHL or GradientTypeMultiHL.");
184 break;
185 }
186}
187
188QLinearGradient DeclarativeTheme3D::convertGradient(ColorGradient *gradient)
189{
190 QLinearGradient newGradient;
191 QGradientStops stops;
192 QList<ColorGradientStop *> qmlstops = gradient->m_stops;
193
194 // Get sorted gradient stops
195 for (int i = 0; i < qmlstops.size(); i++) {
196 int j = 0;
197 while (j < stops.size() && stops.at(i: j).first < qmlstops[i]->position())
198 j++;
199 stops.insert(i: j, t: QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color()));
200 }
201
202 newGradient.setStops(stops);
203
204 return newGradient;
205}
206
207ColorGradient *DeclarativeTheme3D::convertGradient(const QLinearGradient &gradient)
208{
209 ColorGradient *newGradient = new ColorGradient(this);
210 QGradientStops stops = gradient.stops();
211 ColorGradientStop *qmlstop;
212
213 // Convert stops
214 for (int i = 0; i < stops.size(); i++) {
215 qmlstop = new ColorGradientStop(newGradient);
216 qmlstop->setColor(stops.at(i).second);
217 qmlstop->setPosition(stops.at(i).first);
218 newGradient->m_stops.append(t: qmlstop);
219 }
220
221 return newGradient;
222}
223
224void DeclarativeTheme3D::addColor(DeclarativeColor *color)
225{
226 if (!color) {
227 qWarning(msg: "Color is invalid, use ThemeColor");
228 return;
229 }
230 clearDummyColors();
231 m_colors.append(t: color);
232 connect(sender: color, signal: &DeclarativeColor::colorChanged,
233 context: this, slot: &DeclarativeTheme3D::handleBaseColorUpdate);
234 QList<QColor> list = Q3DTheme::baseColors();
235 list.append(t: color->color());
236 Q3DTheme::setBaseColors(list);
237}
238
239QList<DeclarativeColor *> DeclarativeTheme3D::colorList()
240{
241 if (m_colors.isEmpty()) {
242 // Create dummy ThemeColors from theme's colors
243 m_dummyColors = true;
244 QList<QColor> list = Q3DTheme::baseColors();
245 foreach (QColor item, list) {
246 DeclarativeColor *color = new DeclarativeColor(this);
247 color->setColor(item);
248 m_colors.append(t: color);
249 connect(sender: color, signal: &DeclarativeColor::colorChanged,
250 context: this, slot: &DeclarativeTheme3D::handleBaseColorUpdate);
251 }
252 }
253 return m_colors;
254}
255
256void DeclarativeTheme3D::clearColors()
257{
258 clearDummyColors();
259 foreach (DeclarativeColor *item, m_colors)
260 disconnect(sender: item, signal: 0, receiver: this, member: 0);
261 m_colors.clear();
262 Q3DTheme::setBaseColors(QList<QColor>());
263}
264
265void DeclarativeTheme3D::clearDummyColors()
266{
267 if (m_dummyColors) {
268 foreach (DeclarativeColor *item, m_colors)
269 delete item;
270 m_colors.clear();
271 m_dummyColors = false;
272 }
273}
274
275void DeclarativeTheme3D::addGradient(ColorGradient *gradient)
276{
277 if (!gradient) {
278 qWarning(msg: "Gradient is invalid, use ColorGradient");
279 return;
280 }
281 clearDummyGradients();
282 m_gradients.append(t: gradient);
283 connect(sender: gradient, signal: &ColorGradient::updated,
284 context: this, slot: &DeclarativeTheme3D::handleBaseGradientUpdate);
285 QList<QLinearGradient> list = Q3DTheme::baseGradients();
286 list.append(t: convertGradient(gradient));
287 Q3DTheme::setBaseGradients(list);
288}
289
290QList<ColorGradient *> DeclarativeTheme3D::gradientList()
291{
292 if (m_gradients.isEmpty()) {
293 // Create dummy ColorGradients from theme's gradients
294 m_dummyGradients = true;
295 QList<QLinearGradient> list = Q3DTheme::baseGradients();
296 foreach (QLinearGradient item, list) {
297 ColorGradient *gradient = convertGradient(gradient: item);
298 m_gradients.append(t: gradient);
299 connect(sender: gradient, signal: &ColorGradient::updated,
300 context: this, slot: &DeclarativeTheme3D::handleBaseGradientUpdate);
301 }
302 }
303
304 return m_gradients;
305}
306
307void DeclarativeTheme3D::clearGradients()
308{
309 clearDummyGradients();
310 foreach (ColorGradient *item, m_gradients)
311 disconnect(sender: item, signal: 0, receiver: this, member: 0);
312 m_gradients.clear();
313 Q3DTheme::setBaseGradients(QList<QLinearGradient>());
314}
315
316void DeclarativeTheme3D::clearDummyGradients()
317{
318 if (m_dummyGradients) {
319 foreach (ColorGradient *item, m_gradients)
320 delete item;
321 m_gradients.clear();
322 m_dummyGradients = false;
323 }
324}
325
326QQmlListProperty<DeclarativeColor> DeclarativeTheme3D::baseColors()
327{
328 return QQmlListProperty<DeclarativeColor>(this, this,
329 &DeclarativeTheme3D::appendBaseColorsFunc,
330 &DeclarativeTheme3D::countBaseColorsFunc,
331 &DeclarativeTheme3D::atBaseColorsFunc,
332 &DeclarativeTheme3D::clearBaseColorsFunc);
333}
334
335void DeclarativeTheme3D::appendBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list,
336 DeclarativeColor *color)
337{
338 reinterpret_cast<DeclarativeTheme3D *>(list->data)->addColor(color);
339}
340
341qsizetype DeclarativeTheme3D::countBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list)
342{
343 return reinterpret_cast<DeclarativeTheme3D *>(list->data)->colorList().size();
344}
345
346DeclarativeColor *DeclarativeTheme3D::atBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list,
347 qsizetype index)
348{
349 return reinterpret_cast<DeclarativeTheme3D *>(list->data)->colorList().at(i: index);
350}
351
352void DeclarativeTheme3D::clearBaseColorsFunc(QQmlListProperty<DeclarativeColor> *list)
353{
354 reinterpret_cast<DeclarativeTheme3D *>(list->data)->clearColors();
355}
356
357QQmlListProperty<ColorGradient> DeclarativeTheme3D::baseGradients()
358{
359 return QQmlListProperty<ColorGradient>(this, this,
360 &DeclarativeTheme3D::appendBaseGradientsFunc,
361 &DeclarativeTheme3D::countBaseGradientsFunc,
362 &DeclarativeTheme3D::atBaseGradientsFunc,
363 &DeclarativeTheme3D::clearBaseGradientsFunc);
364}
365
366void DeclarativeTheme3D::appendBaseGradientsFunc(QQmlListProperty<ColorGradient> *list,
367 ColorGradient *gradient)
368{
369 reinterpret_cast<DeclarativeTheme3D *>(list->data)->addGradient(gradient);
370}
371
372qsizetype DeclarativeTheme3D::countBaseGradientsFunc(QQmlListProperty<ColorGradient> *list)
373{
374 return reinterpret_cast<DeclarativeTheme3D *>(list->data)->gradientList().size();
375}
376
377ColorGradient *DeclarativeTheme3D::atBaseGradientsFunc(QQmlListProperty<ColorGradient> *list,
378 qsizetype index)
379{
380 return reinterpret_cast<DeclarativeTheme3D *>(list->data)->gradientList().at(i: index);
381}
382
383void DeclarativeTheme3D::clearBaseGradientsFunc(QQmlListProperty<ColorGradient> *list)
384{
385 reinterpret_cast<DeclarativeTheme3D *>(list->data)->clearGradients();
386}
387
388QT_END_NAMESPACE
389

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtdatavis3d/src/datavisualizationqml/declarativetheme.cpp