1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "q3dtheme_p.h"
5#include "thememanager_p.h"
6#include "utils_p.h"
7
8QT_BEGIN_NAMESPACE
9
10/*!
11 * \class Q3DTheme
12 * \inmodule QtGraphs
13 * \brief Q3DTheme class provides a visual style for graphs.
14 *
15 * Specifies visual properties that affect the whole graph. There are several
16 * built-in themes that can be used as is or modified freely.
17 *
18 * The following properties can be overridden by using QAbstract3DSeries
19 * properties to set them explicitly in the series: baseColors, baseGradients,
20 * and colorStyle.
21 *
22 * Themes can be created from scratch using the ThemeUserDefined enum value.
23 * Creating a theme using the default constructor produces a new user-defined
24 * theme.
25 *
26 * \section1 Default Theme
27 *
28 * The following table lists the properties controlled by themes and the
29 * default values for ThemeUserDefined.
30 *
31 * \table
32 * \header
33 * \li Property
34 * \li Default Value
35 * \row
36 * \li ambientLightStrength
37 * \li 0.25
38 * \row
39 * \li backgroundColor
40 * \li Qt::black
41 * \row
42 * \li backgroundEnabled
43 * \li \c true
44 * \row
45 * \li baseColors
46 * \li Qt::black
47 * \row
48 * \li baseGradients
49 * \li QLinearGradient. Essentially fully black.
50 * \row
51 * \li colorStyle
52 * \li ColorStyleUniform
53 * \row
54 * \li \l font
55 * \li QFont
56 * \row
57 * \li gridEnabled
58 * \li \c true
59 * \row
60 * \li gridLineColor
61 * \li Qt::white
62 * \row
63 * \li highlightLightStrength
64 * \li 7.5
65 * \row
66 * \li labelBackgroundColor
67 * \li Qt::gray
68 * \row
69 * \li labelBackgroundEnabled
70 * \li \c true
71 * \row
72 * \li labelBorderEnabled
73 * \li \c true
74 * \row
75 * \li labelTextColor
76 * \li Qt::white
77 * \row
78 * \li labelsEnabled
79 * \li \c true
80 * \row
81 * \li lightColor
82 * \li Qt::white
83 * \row
84 * \li lightStrength
85 * \li 5.0
86 * \row
87 * \li multiHighlightColor
88 * \li Qt::blue
89 * \row
90 * \li multiHighlightGradient
91 * \li QLinearGradient. Essentially fully black.
92 * \row
93 * \li shadowStrength
94 * \li 25.0
95 * \row
96 * \li singleHighlightColor
97 * \li Qt::red
98 * \row
99 * \li singleHighlightGradient
100 * \li QLinearGradient. Essentially fully black.
101 * \row
102 * \li windowColor
103 * \li Qt::black
104 * \endtable
105 *
106 * \section1 Usage Examples
107 *
108 * Creating a built-in theme without any modifications:
109 *
110 * \snippet doc_src_q3dtheme.cpp 0
111 *
112 * Creating a built-in theme and modifying some properties:
113 *
114 * \snippet doc_src_q3dtheme.cpp 1
115 *
116 * Creating a user-defined theme:
117 *
118 * \snippet doc_src_q3dtheme.cpp 2
119 *
120 * Creating a built-in theme and modifying some properties after it has been set:
121 *
122 * \snippet doc_src_q3dtheme.cpp 3
123 *
124 */
125
126/*!
127 * \enum Q3DTheme::ColorStyle
128 *
129 * Color styles.
130 *
131 * \value ColorStyleUniform
132 * Objects are rendered in a single color. The color used is specified in baseColors,
133 * singleHighlightColor and multiHighlightColor properties.
134 * \value ColorStyleObjectGradient
135 * Objects are colored using a full gradient for each object regardless of object height. The
136 * gradient used is specified in baseGradients, singleHighlightGradient and
137 * multiHighlightGradient properties.
138 * \value ColorStyleRangeGradient
139 * Objects are colored using a portion of the full gradient determined by the object's
140 * height and its position on the Y-axis. The gradient used is specified in baseGradients,
141 * singleHighlightGradient and multiHighlightGradient properties.
142 */
143
144/*!
145 * \enum Q3DTheme::Theme
146 *
147 * Built-in themes.
148 *
149 * \value ThemeQt
150 * A light theme with green as the base color.
151 * \value ThemePrimaryColors
152 * A light theme with yellow as the base color.
153 * \value ThemeDigia
154 * A light theme with gray as the base color.
155 * \value ThemeStoneMoss
156 * A medium dark theme with yellow as the base color.
157 * \value ThemeArmyBlue
158 * A medium light theme with blue as the base color.
159 * \value ThemeRetro
160 * A medium light theme with brown as the base color.
161 * \value ThemeEbony
162 * A dark theme with white as the base color.
163 * \value ThemeIsabelle
164 * A dark theme with yellow as the base color.
165 * \value ThemeUserDefined
166 * A user-defined theme. For more information, see \l {Default Theme}.
167 */
168
169/*!
170 * \qmltype Theme3D
171 * \inqmlmodule QtGraphs
172 * \ingroup graphs_qml
173 * \instantiates Q3DTheme
174 * \brief A visual style for graphs.
175 *
176 * This type is used to specify visual properties that affect the whole graph. There are several
177 * built-in themes that can be used as is or modified freely.
178 *
179 * The following properties can be overridden by using Abstract3DSeries
180 * properties to set them explicitly in the series:
181 * baseColors, baseGradients, and colorStyle.
182 *
183 * Themes can be created from scratch by using the
184 * \l{Q3DTheme::ThemeUserDefined}{Theme3D.ThemeUserDefined} enum value.
185 *
186 * \section1 Default Theme
187 *
188 * The following table lists the properties controlled by themes and the
189 * default values for \l{Q3DTheme::ThemeUserDefined}
190 * {Theme3D.ThemeUserDefined}.
191 *
192 * \table
193 * \header
194 * \li Property
195 * \li Default Value
196 * \row
197 * \li ambientLightStrength
198 * \li 0.25
199 * \row
200 * \li backgroundColor
201 * \li "black". For more information, see \l [QtQuick] color.
202 * \row
203 * \li backgroundEnabled
204 * \li \c true
205 * \row
206 * \li baseColors
207 * \li "black"
208 * \row
209 * \li baseGradients
210 * \li QLinearGradient. Essentially fully black.
211 * \row
212 * \li colorStyle
213 * \li ColorStyleUniform
214 * \row
215 * \li \l font
216 * \li \l [QtQuick] font
217 * \row
218 * \li gridEnabled
219 * \li \c true
220 * \row
221 * \li gridLineColor
222 * \li "white"
223 * \row
224 * \li highlightLightStrength
225 * \li 7.5
226 * \row
227 * \li labelBackgroundColor
228 * \li "gray"
229 * \row
230 * \li labelBackgroundEnabled
231 * \li \c true
232 * \row
233 * \li labelBorderEnabled
234 * \li \c true
235 * \row
236 * \li labelTextColor
237 * \li "white"
238 * \row
239 * \li labelsEnabled
240 * \li \c true
241 * \row
242 * \li lightColor
243 * \li "white"
244 * \row
245 * \li lightStrength
246 * \li 5.0
247 * \row
248 * \li multiHighlightColor
249 * \li "blue"
250 * \row
251 * \li multiHighlightGradient
252 * \li QLinearGradient. Essentially fully black.
253 * \row
254 * \li singleHighlightColor
255 * \li "red"
256 * \row
257 * \li singleHighlightGradient
258 * \li QLinearGradient. Essentially fully black.
259 * \row
260 * \li windowColor
261 * \li "black"
262 * \endtable
263 *
264 * \section1 Usage examples
265 *
266 * Using a built-in theme without any modifications:
267 *
268 * \snippet doc_src_q3dtheme.cpp 4
269 *
270 * Using a built-in theme and modifying some properties:
271 *
272 * \snippet doc_src_q3dtheme.cpp 5
273 *
274 * Using a user-defined theme:
275 *
276 * \snippet doc_src_q3dtheme.cpp 6
277 *
278 * For Theme3D enums, see \l Q3DTheme::ColorStyle and \l{Q3DTheme::Theme}.
279 */
280
281/*!
282 * \qmlproperty list<ThemeColor> Theme3D::baseColors
283 *
284 * The list of base colors to be used for all the objects in the graph, series by series. If there
285 * are more series than colors, color list wraps and starts again with the first color in the list.
286 * Has no immediate effect if colorStyle is not \c Theme3D.ColorStyleUniform.
287 *
288 * This can be overridden by setting \l{Abstract3DSeries::baseColor}
289 * {Abstract3DSeries.baseColor} explicitly in the series.
290 */
291
292/*!
293 * \qmlproperty color Theme3D::backgroundColor
294 *
295 * The color of the graph background.
296 */
297
298/*!
299 * \qmlproperty color Theme3D::windowColor
300 *
301 * The color of the application window the graph is drawn into.
302 */
303
304/*!
305 * \qmlproperty color Theme3D::labelTextColor
306 *
307 * The color of the font used for labels.
308 */
309
310/*!
311 * \qmlproperty color Theme3D::labelBackgroundColor
312 *
313 * The color of the label backgrounds. Has no effect if labelBackgroundEnabled is \c false.
314 */
315
316/*!
317 * \qmlproperty color Theme3D::gridLineColor
318 *
319 * The color of the grid lines.
320 */
321
322/*!
323 * \qmlproperty color Theme3D::singleHighlightColor
324 *
325 * The highlight color for a selected object. Used if
326 * \l{AbstractGraph3D::selectionMode}{selectionMode}
327 * has the \c AbstractGraph3D.SelectionItem flag set.
328 */
329
330/*!
331 * \qmlproperty color Theme3D::multiHighlightColor
332 *
333 * The highlight color for selected objects. Used if
334 * \l{AbstractGraph3D::selectionMode}{selectionMode}
335 * has the \c AbstractGraph3D.SelectionRow or \c AbstractGraph3D.SelectionColumn
336 * flag set.
337 */
338
339/*!
340 * \qmlproperty color Theme3D::lightColor
341 *
342 * The color of the ambient and specular light defined in Scene3D.
343 */
344
345/*!
346 * \qmlproperty list<ColorGradient> Theme3D::baseGradients
347 *
348 * The list of base gradients to be used for all the objects in the graph,
349 * series by series. If there are more series than gradients, the gradient list
350 * wraps and starts again with the first gradient in the list.
351 *
352 * Has no immediate effect if colorStyle is \l{Q3DTheme::ColorStyleUniform}
353 * {Theme3D.ColorStyleUniform}.
354 *
355 * This value can be overridden by setting \l{Abstract3DSeries::baseGradient}
356 *{Abstract3DSeries.baseGradient} explicitly in the series.
357 */
358
359/*!
360 * \qmlproperty ColorGradient Theme3D::singleHighlightGradient
361 *
362 * The highlight gradient for a selected object. Used if
363 * \l{AbstractGraph3D::selectionMode}{selectionMode}
364 * has the \c AbstractGraph3D.SelectionItem flag set.
365 */
366
367/*!
368 * \qmlproperty ColorGradient Theme3D::multiHighlightGradient
369 *
370 * The highlight gradient for selected objects. Used if
371 * \l{AbstractGraph3D::selectionMode}{selectionMode}
372 * has the \c AbstractGraph3D.SelectionRow or \c AbstractGraph3D.SelectionColumn
373 * flag set.
374 */
375
376/*!
377 * \qmlproperty real Theme3D::lightStrength
378 *
379 * The specular light strength for the whole graph. The value must be between
380 * \c 0.0 and \c 10.0.
381 *
382 * This value affects the light specified in Scene3D.
383 */
384
385/*!
386 * \qmlproperty real Theme3D::ambientLightStrength
387 *
388 * The ambient light strength for the whole graph. This value determines how
389 * evenly and brightly the colors are shown throughout the graph regardless of
390 * the light position. The value must be between \c 0.0 and \c 1.0.
391 */
392
393/*!
394 * \qmlproperty real Theme3D::highlightLightStrength
395 *
396 * The specular light strength for selected objects. The value must be
397 * between \c 0.0 and \c 10.0.
398 */
399
400/*!
401 * \qmlproperty bool Theme3D::labelBorderEnabled
402 *
403 * Defines whether label borders are drawn for labels that have a background.
404 * Has no effect if labelBackgroundEnabled is \c false.
405 */
406
407/*!
408 * \qmlproperty font Theme3D::font
409 *
410 * Sets the font to be used for labels.
411 */
412
413/*!
414 * \qmlproperty bool Theme3D::backgroundEnabled
415 *
416 * Defines whether the background is drawn by using the value of
417 * backgroundColor.
418 */
419
420/*!
421 * \qmlproperty bool Theme3D::gridEnabled
422 *
423 * Defines whether the grid lines are drawn. This value affects all grid lines.
424 */
425
426/*!
427 * \qmlproperty bool Theme3D::labelBackgroundEnabled
428 *
429 * Defines whether the label is drawn with a background that uses
430 * labelBackgroundColor (including alpha), or with a fully transparent
431 * background. Labels with a background are drawn to equal sizes per axis based
432 * on the longest label, and the text is centered in them. Labels without
433 * a background are drawn as is and are left or right aligned based on their
434 * position in the graph.
435 */
436
437/*!
438 * \qmlproperty Theme3D.ColorStyle Theme3D::colorStyle
439 *
440 * The style of the graph colors. One of Q3DTheme::ColorStyle enum values.
441 *
442 * This value can be overridden by setting \l{Abstract3DSeries::colorStyle}
443 * {Abstract3DSeries.colorStyle} explicitly in the series.
444 *
445 * \sa Q3DTheme::ColorStyle
446 */
447
448/*!
449 * \qmlproperty bool Theme3D::labelsEnabled
450 *
451 * Defines whether labels are drawn at all. If this is \c{false}, all other label properties
452 * have no effect.
453 */
454
455/*!
456 * \qmlproperty Theme3D.Theme Theme3D::type
457 *
458 * The type of the theme. If no type is set, the type is
459 * \l{Q3DTheme::ThemeUserDefined}{Theme3D.ThemeUserDefined}.
460 * Changing the theme type after the item has been constructed will change all other properties
461 * of the theme to what the predefined theme specifies. Changing the theme type of the active theme
462 * of the graph will also reset all attached series to use the new theme.
463 */
464
465/*!
466 * \qmlproperty real Theme3D::shadowStrength
467 *
468 * The shadow strength for the whole graph. The higher the number, the darker the shadows will be.
469 * The value must be between \c 0.0 and \c 100.0.
470 *
471 * This value affects the light specified in Scene3D.
472 */
473
474/*!
475 * Constructs a new theme of type ThemeUserDefined. An optional \a parent parameter
476 * can be given and is then passed to QObject constructor.
477 */
478Q3DTheme::Q3DTheme(QObject *parent)
479 : QObject(parent),
480 d_ptr(new Q3DThemePrivate(this))
481{
482}
483
484/*!
485 * Constructs a new theme with \a themeType, which can be one of the built-in themes from
486 * \l Theme. An optional \a parent parameter can be given and is then passed to QObject
487 * constructor.
488 */
489Q3DTheme::Q3DTheme(Theme themeType, QObject *parent)
490 : QObject(parent),
491 d_ptr(new Q3DThemePrivate(this))
492{
493 setType(themeType);
494}
495
496/*!
497 * \internal
498 */
499Q3DTheme::Q3DTheme(Q3DThemePrivate *d, Theme themeType,
500 QObject *parent) :
501 QObject(parent),
502 d_ptr(d)
503{
504 setType(themeType);
505}
506
507/*!
508 * Destroys the theme.
509 */
510Q3DTheme::~Q3DTheme()
511{
512}
513
514/*!
515 * \property Q3DTheme::baseColors
516 *
517 * \brief The list of base colors to be used for all the objects in the graph,
518 * series by series.
519 *
520 * If there are more series than colors, the color list wraps and starts again
521 * with the first color in the list.
522 *
523 * Has no immediate effect if colorStyle is not ColorStyleUniform.
524 *
525 * This value can be overridden by setting the \l{QAbstract3DSeries::baseColor}
526 * {baseColor} explicitly in the series.
527 */
528void Q3DTheme::setBaseColors(const QList<QColor> &colors)
529{
530 Q_D(Q3DTheme);
531 if (colors.size()) {
532 d->m_dirtyBits.baseColorDirty = true;
533 if (d->m_baseColors != colors) {
534 d->m_baseColors.clear();
535 d->m_baseColors = colors;
536 emit baseColorsChanged(colors);
537 }
538 } else {
539 d->m_baseColors.clear();
540 }
541}
542
543QList<QColor> Q3DTheme::baseColors() const
544{
545 const Q_D(Q3DTheme);
546 return d->m_baseColors;
547}
548
549/*!
550 * \property Q3DTheme::backgroundColor
551 *
552 * \brief The color of the graph background.
553 */
554void Q3DTheme::setBackgroundColor(const QColor &color)
555{
556 Q_D(Q3DTheme);
557 d->m_dirtyBits.backgroundColorDirty = true;
558 if (d->m_backgroundColor != color) {
559 d->m_backgroundColor = color;
560 emit backgroundColorChanged(color);
561 emit d->needRender();
562 }
563}
564
565QColor Q3DTheme::backgroundColor() const
566{
567 const Q_D(Q3DTheme);
568 return d->m_backgroundColor;
569}
570
571/*!
572 * \property Q3DTheme::windowColor
573 *
574 * \brief The color of the application window the graph is drawn into.
575 */
576void Q3DTheme::setWindowColor(const QColor &color)
577{
578 Q_D(Q3DTheme);
579 d->m_dirtyBits.windowColorDirty = true;
580 if (d->m_windowColor != color) {
581 d->m_windowColor = color;
582 emit windowColorChanged(color);
583 emit d->needRender();
584 }
585}
586
587QColor Q3DTheme::windowColor() const
588{
589 const Q_D(Q3DTheme);
590 return d->m_windowColor;
591}
592
593/*!
594 * \property Q3DTheme::labelTextColor
595 *
596 * \brief The color of the font used for labels.
597 */
598void Q3DTheme::setLabelTextColor(const QColor &color)
599{
600 Q_D(Q3DTheme);
601 d->m_dirtyBits.labelTextColorDirty = true;
602 if (d->m_textColor != color) {
603 d->m_textColor = color;
604 emit labelTextColorChanged(color);
605 emit d->needRender();
606 }
607}
608
609QColor Q3DTheme::labelTextColor() const
610{
611 const Q_D(Q3DTheme);
612 return d->m_textColor;
613}
614
615/*!
616 * \property Q3DTheme::labelBackgroundColor
617 *
618 * \brief The color of the label backgrounds.
619 *
620 * Has no effect if labelBackgroundEnabled is \c false.
621 */
622void Q3DTheme::setLabelBackgroundColor(const QColor &color)
623{
624 Q_D(Q3DTheme);
625 d->m_dirtyBits.labelBackgroundColorDirty = true;
626 if (d->m_textBackgroundColor != color) {
627 d->m_textBackgroundColor = color;
628 emit labelBackgroundColorChanged(color);
629 emit d->needRender();
630 }
631}
632
633QColor Q3DTheme::labelBackgroundColor() const
634{
635 const Q_D(Q3DTheme);
636 return d->m_textBackgroundColor;
637}
638
639/*!
640 * \property Q3DTheme::gridLineColor
641 *
642 * \brief The color of the grid lines.
643 */
644void Q3DTheme::setGridLineColor(const QColor &color)
645{
646 Q_D(Q3DTheme);
647 d->m_dirtyBits.gridLineColorDirty = true;
648 if (d->m_gridLineColor != color) {
649 d->m_gridLineColor = color;
650 emit gridLineColorChanged(color);
651 emit d->needRender();
652 }
653}
654
655QColor Q3DTheme::gridLineColor() const
656{
657 const Q_D(Q3DTheme);
658 return d->m_gridLineColor;
659}
660
661/*!
662 * \property Q3DTheme::singleHighlightColor
663 *
664 * \brief The highlight color for a selected object.
665 *
666 * Used if \l{QAbstract3DGraph::selectionMode}{selectionMode} has the
667 * \c QAbstract3DGraph::SelectionItem flag set.
668 */
669void Q3DTheme::setSingleHighlightColor(const QColor &color)
670{
671 Q_D(Q3DTheme);
672 d->m_dirtyBits.singleHighlightColorDirty = true;
673 if (d->m_singleHighlightColor != color) {
674 d->m_singleHighlightColor = color;
675 emit singleHighlightColorChanged(color);
676 }
677}
678
679QColor Q3DTheme::singleHighlightColor() const
680{
681 const Q_D(Q3DTheme);
682 return d->m_singleHighlightColor;
683}
684
685/*!
686 * \property Q3DTheme::multiHighlightColor
687 *
688 * \brief The highlight color for selected objects.
689 *
690 * Used if \l{QAbstract3DGraph::selectionMode}{selectionMode} has the
691 * \c QAbstract3DGraph::SelectionRow or \c QAbstract3DGraph::SelectionColumn
692 * flag set.
693 */
694void Q3DTheme::setMultiHighlightColor(const QColor &color)
695{
696 Q_D(Q3DTheme);
697 d->m_dirtyBits.multiHighlightColorDirty = true;
698 if (d->m_multiHighlightColor != color) {
699 d->m_multiHighlightColor = color;
700 emit multiHighlightColorChanged(color);
701 }
702}
703
704QColor Q3DTheme::multiHighlightColor() const
705{
706 const Q_D(Q3DTheme);
707 return d->m_multiHighlightColor;
708}
709
710/*!
711 * \property Q3DTheme::lightColor
712 *
713 * \brief The color for the ambient and specular light.
714 *
715 * This value affects the light specified in Q3DScene.
716 */
717void Q3DTheme::setLightColor(const QColor &color)
718{
719 Q_D(Q3DTheme);
720 d->m_dirtyBits.lightColorDirty = true;
721 if (d->m_lightColor != color) {
722 d->m_lightColor = color;
723 emit lightColorChanged(color);
724 emit d->needRender();
725 }
726}
727
728QColor Q3DTheme::lightColor() const
729{
730 const Q_D(Q3DTheme);
731 return d->m_lightColor;
732}
733
734/*!
735 * \property Q3DTheme::baseGradients
736 *
737 * \brief The list of base gradients to be used for all the objects in the
738 * graph, series by series.
739 *
740 * If there are more series than gradients, the gradient list wraps and starts
741 * again with the first gradient in the list
742 *
743 * Has no immediate effect if colorStyle is ColorStyleUniform.
744 *
745 * This value can be overridden by setting the
746 * \l{QAbstract3DSeries::baseGradient}{baseGradient} explicitly in the series.
747 */
748void Q3DTheme::setBaseGradients(const QList<QLinearGradient> &gradients)
749{
750 Q_D(Q3DTheme);
751 if (gradients.size()) {
752 d->m_dirtyBits.baseGradientDirty = true;
753 if (d->m_baseGradients != gradients) {
754 d->m_baseGradients.clear();
755 d->m_baseGradients = gradients;
756 emit baseGradientsChanged(gradients);
757 }
758 } else {
759 d->m_baseGradients.clear();
760 }
761}
762
763QList<QLinearGradient> Q3DTheme::baseGradients() const
764{
765 const Q_D(Q3DTheme);
766 return d->m_baseGradients;
767}
768
769/*!
770 * \property Q3DTheme::singleHighlightGradient
771 *
772 * \brief The highlight gradient for a selected object.
773 *
774 * Used if \l{QAbstract3DGraph::selectionMode}{selectionMode}
775 * has the \c QAbstract3DGraph::SelectionItem flag set.
776 */
777void Q3DTheme::setSingleHighlightGradient(const QLinearGradient &gradient)
778{
779 Q_D(Q3DTheme);
780 d->m_dirtyBits.singleHighlightGradientDirty = true;
781 if (d->m_singleHighlightGradient != gradient) {
782 Utils::verifyGradientCompleteness(gradient&: d->m_singleHighlightGradient);
783 d->m_singleHighlightGradient = gradient;
784 emit singleHighlightGradientChanged(gradient);
785 }
786}
787
788QLinearGradient Q3DTheme::singleHighlightGradient() const
789{
790 const Q_D(Q3DTheme);
791 return d->m_singleHighlightGradient;
792}
793
794/*!
795 * \property Q3DTheme::multiHighlightGradient
796 *
797 * \brief The highlight gradient for selected objects.
798 *
799 * Used if \l{QAbstract3DGraph::selectionMode}{selectionMode}
800 * has the \c QAbstract3DGraph::SelectionRow or
801 * \c QAbstract3DGraph::SelectionColumn flag set.
802 */
803void Q3DTheme::setMultiHighlightGradient(const QLinearGradient &gradient)
804{
805 Q_D(Q3DTheme);
806 d->m_dirtyBits.multiHighlightGradientDirty = true;
807 if (d->m_multiHighlightGradient != gradient) {
808 Utils::verifyGradientCompleteness(gradient&: d->m_multiHighlightGradient);
809 d->m_multiHighlightGradient = gradient;
810 emit multiHighlightGradientChanged(gradient);
811 }
812}
813
814QLinearGradient Q3DTheme::multiHighlightGradient() const
815{
816 const Q_D(Q3DTheme);
817 return d->m_multiHighlightGradient;
818}
819
820/*!
821 * \property Q3DTheme::lightStrength
822 *
823 * \brief The specular light strength for the whole graph.
824 *
825 * The value must be between \c 0.0f and \c 10.0f.
826 *
827 * This value affects the light specified in Q3DScene.
828 */
829void Q3DTheme::setLightStrength(float strength)
830{
831 Q_D(Q3DTheme);
832 d->m_dirtyBits.lightStrengthDirty = true;
833 if (strength < 0.0f || strength > 10.0f) {
834 qWarning(msg: "Invalid value. Valid range for lightStrength is between 0.0f and 10.0f");
835 } else if (d->m_lightStrength != strength) {
836 d->m_lightStrength = strength;
837 emit lightStrengthChanged(strength);
838 emit d->needRender();
839 }
840}
841
842float Q3DTheme::lightStrength() const
843{
844 const Q_D(Q3DTheme);
845 return d->m_lightStrength;
846}
847
848/*!
849 * \property Q3DTheme::ambientLightStrength
850 *
851 * \brief The ambient light strength for the whole graph.
852 *
853 * This value determines how evenly and brightly the colors are shown throughout
854 * the graph regardless of the light position.
855 *
856 * The value must be between \c 0.0f and \c 1.0f.
857 */
858void Q3DTheme::setAmbientLightStrength(float strength)
859{
860 Q_D(Q3DTheme);
861 d->m_dirtyBits.ambientLightStrengthDirty = true;
862 if (strength < 0.0f || strength > 1.0f) {
863 qWarning(msg: "Invalid value. Valid range for ambientLightStrength is between 0.0f and 1.0f");
864 } else if (d->m_ambientLightStrength != strength) {
865 d->m_ambientLightStrength = strength;
866 emit ambientLightStrengthChanged(strength);
867 emit d->needRender();
868 }
869}
870
871float Q3DTheme::ambientLightStrength() const
872{
873 const Q_D(Q3DTheme);
874 return d->m_ambientLightStrength;
875}
876
877/*!
878 * \property Q3DTheme::highlightLightStrength
879 *
880 * \brief The specular light strength for selected objects.
881 *
882 * The value must be between \c 0.0f and \c 10.0f.
883 */
884void Q3DTheme::setHighlightLightStrength(float strength)
885{
886 Q_D(Q3DTheme);
887 d->m_dirtyBits.highlightLightStrengthDirty = true;
888 if (strength < 0.0f || strength > 10.0f) {
889 qWarning(msg: "Invalid value. Valid range for highlightLightStrength is between 0.0f and 10.0f");
890 } else if (d->m_highlightLightStrength != strength) {
891 d->m_highlightLightStrength = strength;
892 emit highlightLightStrengthChanged(strength);
893 emit d->needRender();
894 }
895}
896
897float Q3DTheme::highlightLightStrength() const
898{
899 const Q_D(Q3DTheme);
900 return d->m_highlightLightStrength;
901}
902
903/*!
904 * \property Q3DTheme::labelBorderEnabled
905 *
906 * \brief Whether label borders are drawn for labels that have a background.
907 *
908 * Has no effect if labelBackgroundEnabled is \c false.
909 */
910void Q3DTheme::setLabelBorderEnabled(bool enabled)
911{
912 Q_D(Q3DTheme);
913 d->m_dirtyBits.labelBorderEnabledDirty = true;
914 if (d->m_labelBorders != enabled) {
915 d->m_labelBorders = enabled;
916 emit labelBorderEnabledChanged(enabled);
917 emit d->needRender();
918 }
919}
920
921bool Q3DTheme::isLabelBorderEnabled() const
922{
923 const Q_D(Q3DTheme);
924 return d->m_labelBorders;
925}
926
927/*!
928 * \property Q3DTheme::font
929 *
930 * \brief The font to be used for labels.
931 */
932void Q3DTheme::setFont(const QFont &font)
933{
934 Q_D(Q3DTheme);
935 d->m_dirtyBits.fontDirty = true;
936 if (d->m_font != font) {
937 d->m_font = font;
938 emit fontChanged(font);
939 emit d->needRender();
940 }
941}
942
943QFont Q3DTheme::font() const
944{
945 const Q_D(Q3DTheme);
946 return d->m_font;
947}
948
949/*!
950 * \property Q3DTheme::backgroundEnabled
951 *
952 * \brief Whether the background is visible.
953 *
954 * The background is drawn by using the value of backgroundColor.
955 */
956void Q3DTheme::setBackgroundEnabled(bool enabled)
957{
958 Q_D(Q3DTheme);
959 d->m_dirtyBits.backgroundEnabledDirty = true;
960 if (d->m_backgoundEnabled != enabled) {
961 d->m_backgoundEnabled = enabled;
962 emit backgroundEnabledChanged(enabled);
963 emit d->needRender();
964 }
965}
966
967bool Q3DTheme::isBackgroundEnabled() const
968{
969 const Q_D(Q3DTheme);
970 return d->m_backgoundEnabled;
971}
972
973/*!
974 * \property Q3DTheme::gridEnabled
975 *
976 * \brief Whether the grid lines are drawn.
977 *
978 * This value affects all grid lines.
979 */
980void Q3DTheme::setGridEnabled(bool enabled)
981{
982 Q_D(Q3DTheme);
983 d->m_dirtyBits.gridEnabledDirty = true;
984 if (d->m_gridEnabled != enabled) {
985 d->m_gridEnabled = enabled;
986 emit gridEnabledChanged(enabled);
987 emit d->needRender();
988 }
989}
990
991bool Q3DTheme::isGridEnabled() const
992{
993 const Q_D(Q3DTheme);
994 return d->m_gridEnabled;
995}
996
997/*!
998 * \property Q3DTheme::labelBackgroundEnabled
999 *
1000 *\brief Whether the label is drawn with a color background or with a fully
1001 * transparent background.
1002 *
1003 * The labelBackgroundColor value (including alpha) is used for drawing the
1004 * background.
1005 *
1006 * Labels with a background are drawn to equal sizes per axis based
1007 * on the longest label, and the text is centered in them. Labels without a
1008 * background are drawn as is and are left or right aligned based on their
1009 * position in the graph.
1010 */
1011void Q3DTheme::setLabelBackgroundEnabled(bool enabled)
1012{
1013 Q_D(Q3DTheme);
1014 d->m_dirtyBits.labelBackgroundEnabledDirty = true;
1015 if (d->m_labelBackground != enabled) {
1016 d->m_labelBackground = enabled;
1017 emit labelBackgroundEnabledChanged(enabled);
1018 emit d->needRender();
1019 }
1020}
1021
1022bool Q3DTheme::isLabelBackgroundEnabled() const
1023{
1024 const Q_D(Q3DTheme);
1025 return d->m_labelBackground;
1026}
1027
1028/*!
1029 * \property Q3DTheme::colorStyle
1030 *
1031 * \brief The style of the graph colors.
1032 *
1033 * One of the ColorStyle enum values.
1034 *
1035 * This value can be overridden by setting \l{Abstract3DSeries::colorStyle}
1036 * {colorStyle} explicitly in the series.
1037 */
1038void Q3DTheme::setColorStyle(Q3DTheme::ColorStyle style)
1039{
1040 Q_D(Q3DTheme);
1041 d->m_dirtyBits.colorStyleDirty = true;
1042 if (d->m_colorStyle != style) {
1043 d->m_colorStyle = style;
1044 emit colorStyleChanged(style);
1045 }
1046}
1047
1048Q3DTheme::ColorStyle Q3DTheme::colorStyle() const
1049{
1050 const Q_D(Q3DTheme);
1051 return d->m_colorStyle;
1052}
1053
1054/*!
1055 * \property Q3DTheme::labelsEnabled
1056 *
1057 * \brief Whether labels are drawn at all.
1058 *
1059 * If this is \c{false}, all other label properties have no effect.
1060 */
1061void Q3DTheme::setLabelsEnabled(bool enabled)
1062{
1063 Q_D(Q3DTheme);
1064 d->m_dirtyBits.labelsEnabledDirty = true;
1065 if (d->m_labelsEnabled != enabled) {
1066 d->m_labelsEnabled = enabled;
1067 emit labelsEnabledChanged(enabled);
1068 emit d->needRender();
1069 }
1070}
1071
1072bool Q3DTheme::isLabelsEnabled() const
1073{
1074 const Q_D(Q3DTheme);
1075 return d->m_labelsEnabled;
1076}
1077
1078/*!
1079 * \property Q3DTheme::type
1080 *
1081 * \brief The type of the theme.
1082 *
1083 * The type is automatically set when constructing a theme,
1084 * but can also be changed later. Changing the theme type will change all other
1085 * properties of the theme to what the predefined theme specifies.
1086 * Changing the theme type of the active theme of the graph will also reset all
1087 * attached series to use the new theme.
1088 */
1089void Q3DTheme::setType(Q3DTheme::Theme themeType)
1090{
1091 Q_D(Q3DTheme);
1092 d->m_dirtyBits.themeIdDirty = true;
1093 if (d->m_themeId != themeType) {
1094 d->m_themeId = themeType;
1095 ThemeManager::setPredefinedPropertiesToTheme(theme: this, type: themeType);
1096 emit typeChanged(themeType);
1097 }
1098}
1099
1100Q3DTheme::Theme Q3DTheme::type() const
1101{
1102 const Q_D(Q3DTheme);
1103 return d->m_themeId;
1104}
1105
1106/*!
1107 * \property Q3DTheme::shadowStrength
1108 *
1109 * \brief The shadow strength for the whole graph.
1110 *
1111 * The higher the number, the darker the shadows will be. The value must be between \c 0.0 and
1112 * \c 100.0.
1113 *
1114 * This value affects the light specified in Q3DScene.
1115 */
1116void Q3DTheme::setShadowStrength(float strength)
1117{
1118 Q_D(Q3DTheme);
1119 d->m_dirtyBits.shadowStrengthDirty = true;
1120 if (strength < 0.0f || strength > 100.0f) {
1121 qWarning(msg: "Invalid value. Valid range for shadowStrength is between 0.0f and 100.0f");
1122 } else if (d->m_shadowStrength != strength) {
1123 d->m_shadowStrength = strength;
1124 emit shadowStrengthChanged(strength);
1125 emit d->needRender();
1126 }
1127}
1128
1129float Q3DTheme::shadowStrength() const
1130{
1131 const Q_D(Q3DTheme);
1132 return d->m_shadowStrength;
1133}
1134
1135// Q3DThemePrivate
1136
1137Q3DThemePrivate::Q3DThemePrivate(Q3DTheme *q)
1138 : m_themeId(Q3DTheme::ThemeUserDefined),
1139 m_colorStyle(Q3DTheme::ColorStyleUniform),
1140 m_backgroundColor(Qt::black),
1141 m_gridLineColor(Qt::white),
1142 m_lightColor(Qt::white),
1143 m_multiHighlightColor(Qt::blue),
1144 m_singleHighlightColor(Qt::red),
1145 m_textBackgroundColor(Qt::gray),
1146 m_textColor(Qt::white),
1147 m_windowColor(Qt::black),
1148 m_font(QFont()),
1149 m_multiHighlightGradient(QLinearGradient(gradientTextureWidth,
1150 gradientTextureHeight,
1151 0.0, 0.0)),
1152 m_singleHighlightGradient(QLinearGradient(gradientTextureWidth,
1153 gradientTextureHeight,
1154 0.0, 0.0)),
1155 m_backgoundEnabled(true),
1156 m_forcePredefinedType(true),
1157 m_gridEnabled(true),
1158 m_isDefaultTheme(false),
1159 m_labelBackground(true),
1160 m_labelBorders(true),
1161 m_labelsEnabled(true),
1162 m_ambientLightStrength(0.25f),
1163 m_highlightLightStrength(7.5f),
1164 m_lightStrength(5.0f),
1165 m_shadowStrength(25.0f),
1166 q_ptr(q)
1167{
1168 m_baseColors.append(t: QColor(Qt::black));
1169 m_baseGradients.append(t: QLinearGradient(gradientTextureWidth,
1170 gradientTextureHeight,
1171 0.0, 0.0));
1172}
1173
1174Q3DThemePrivate::~Q3DThemePrivate()
1175{
1176}
1177
1178void Q3DThemePrivate::resetDirtyBits()
1179{
1180 m_dirtyBits.ambientLightStrengthDirty = true;
1181 m_dirtyBits.backgroundColorDirty = true;
1182 m_dirtyBits.backgroundEnabledDirty = true;
1183 m_dirtyBits.baseColorDirty = true;
1184 m_dirtyBits.baseGradientDirty = true;
1185 m_dirtyBits.colorStyleDirty = true;
1186 m_dirtyBits.fontDirty = true;
1187 m_dirtyBits.gridEnabledDirty = true;
1188 m_dirtyBits.gridLineColorDirty = true;
1189 m_dirtyBits.highlightLightStrengthDirty = true;
1190 m_dirtyBits.labelBackgroundColorDirty = true;
1191 m_dirtyBits.labelBackgroundEnabledDirty = true;
1192 m_dirtyBits.labelBorderEnabledDirty = true;
1193 m_dirtyBits.labelTextColorDirty = true;
1194 m_dirtyBits.lightColorDirty = true;
1195 m_dirtyBits.lightStrengthDirty = true;
1196 m_dirtyBits.multiHighlightColorDirty = true;
1197 m_dirtyBits.multiHighlightGradientDirty = true;
1198 m_dirtyBits.shadowStrengthDirty = true;
1199 m_dirtyBits.singleHighlightColorDirty = true;
1200 m_dirtyBits.singleHighlightGradientDirty = true;
1201 m_dirtyBits.themeIdDirty = true;
1202 m_dirtyBits.windowColorDirty = true;
1203}
1204
1205bool Q3DThemePrivate::sync(Q3DThemePrivate &other)
1206{
1207 bool updateDrawer = false;
1208 if (m_dirtyBits.ambientLightStrengthDirty) {
1209 other.q_func()->setAmbientLightStrength(m_ambientLightStrength);
1210 m_dirtyBits.ambientLightStrengthDirty = false;
1211 }
1212 if (m_dirtyBits.backgroundColorDirty) {
1213 other.q_func()->setBackgroundColor(m_backgroundColor);
1214 m_dirtyBits.backgroundColorDirty = false;
1215 }
1216 if (m_dirtyBits.backgroundEnabledDirty) {
1217 other.q_func()->setBackgroundEnabled(m_backgoundEnabled);
1218 m_dirtyBits.backgroundEnabledDirty = false;
1219 }
1220 if (m_dirtyBits.baseColorDirty) {
1221 other.q_func()->setBaseColors(m_baseColors);
1222 m_dirtyBits.baseColorDirty = false;
1223 }
1224 if (m_dirtyBits.baseGradientDirty) {
1225 other.q_func()->setBaseGradients(m_baseGradients);
1226 m_dirtyBits.baseGradientDirty = false;
1227 }
1228 if (m_dirtyBits.colorStyleDirty) {
1229 other.q_func()->setColorStyle(m_colorStyle);
1230 m_dirtyBits.colorStyleDirty = false;
1231 }
1232 if (m_dirtyBits.fontDirty) {
1233 other.q_func()->setFont(m_font);
1234 m_dirtyBits.fontDirty = false;
1235 updateDrawer = true;
1236 }
1237 if (m_dirtyBits.gridEnabledDirty) {
1238 other.q_func()->setGridEnabled(m_gridEnabled);
1239 m_dirtyBits.gridEnabledDirty = false;
1240 }
1241 if (m_dirtyBits.gridLineColorDirty) {
1242 other.q_func()->setGridLineColor(m_gridLineColor);
1243 m_dirtyBits.gridLineColorDirty = false;
1244 }
1245 if (m_dirtyBits.highlightLightStrengthDirty) {
1246 other.q_func()->setHighlightLightStrength(m_highlightLightStrength);
1247 m_dirtyBits.highlightLightStrengthDirty = false;
1248 }
1249 if (m_dirtyBits.labelBackgroundColorDirty) {
1250 other.q_func()->setLabelBackgroundColor(m_textBackgroundColor);
1251 m_dirtyBits.labelBackgroundColorDirty = false;
1252 updateDrawer = true;
1253 }
1254 if (m_dirtyBits.labelBackgroundEnabledDirty) {
1255 other.q_func()->setLabelBackgroundEnabled(m_labelBackground);
1256 m_dirtyBits.labelBackgroundEnabledDirty = false;
1257 updateDrawer = true;
1258 }
1259 if (m_dirtyBits.labelBorderEnabledDirty) {
1260 other.q_func()->setLabelBorderEnabled(m_labelBorders);
1261 m_dirtyBits.labelBorderEnabledDirty = false;
1262 updateDrawer = true;
1263 }
1264 if (m_dirtyBits.labelTextColorDirty) {
1265 other.q_func()->setLabelTextColor(m_textColor);
1266 m_dirtyBits.labelTextColorDirty = false;
1267 updateDrawer = true;
1268 }
1269 if (m_dirtyBits.lightColorDirty) {
1270 other.q_func()->setLightColor(m_lightColor);
1271 m_dirtyBits.lightColorDirty = false;
1272 }
1273 if (m_dirtyBits.lightStrengthDirty) {
1274 other.q_func()->setLightStrength(m_lightStrength);
1275 m_dirtyBits.lightStrengthDirty = false;
1276 }
1277 if (m_dirtyBits.multiHighlightColorDirty) {
1278 other.q_func()->setMultiHighlightColor(m_multiHighlightColor);
1279 m_dirtyBits.multiHighlightColorDirty = false;
1280 }
1281 if (m_dirtyBits.multiHighlightGradientDirty) {
1282 other.q_func()->setMultiHighlightGradient(m_multiHighlightGradient);
1283 m_dirtyBits.multiHighlightGradientDirty = false;
1284 }
1285 if (m_dirtyBits.shadowStrengthDirty) {
1286 other.q_func()->setShadowStrength(m_shadowStrength);
1287 m_dirtyBits.shadowStrengthDirty = false;
1288 }
1289 if (m_dirtyBits.singleHighlightColorDirty) {
1290 other.q_func()->setSingleHighlightColor(m_singleHighlightColor);
1291 m_dirtyBits.singleHighlightColorDirty = false;
1292 }
1293 if (m_dirtyBits.singleHighlightGradientDirty) {
1294 other.q_func()->setSingleHighlightGradient(m_singleHighlightGradient);
1295 m_dirtyBits.singleHighlightGradientDirty = false;
1296 }
1297 if (m_dirtyBits.themeIdDirty) {
1298 other.m_themeId = m_themeId; // Set directly to avoid a call to ThemeManager's useTheme()
1299 m_dirtyBits.themeIdDirty = false;
1300 }
1301 if (m_dirtyBits.windowColorDirty) {
1302 other.q_func()->setWindowColor(m_windowColor);
1303 m_dirtyBits.windowColorDirty = false;
1304 }
1305
1306 return updateDrawer;
1307}
1308
1309QT_END_NAMESPACE
1310

source code of qtgraphs/src/graphs/theme/q3dtheme.cpp