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

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