1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qabstract3dseries_p.h"
5#include "qabstractdataproxy_p.h"
6#include "qquickgraphsitem_p.h"
7#include "utils_p.h"
8#include "qgraphs3dlogging_p.h"
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 * \class QAbstract3DSeries
14 * \inmodule QtGraphs
15 * \ingroup graphs_3D
16 * \brief The QAbstract3DSeries class is a base class for all 3D data series.
17 *
18 * There are inherited classes for each supported series type: QBar3DSeries,
19 * QScatter3DSeries, and QSurface3DSeries.
20 *
21 * For more information, see \l{Qt Graphs Data Handling with 3D}.
22 */
23
24/*!
25 * \class QAbstract3DSeriesChangeBitField
26 * \internal
27 */
28
29/*!
30 * \class QAbstract3DSeriesThemeOverrideBitField
31 * \internal
32 */
33
34/*!
35 * \qmltype Abstract3DSeries
36 * \qmlabstract
37 * \inqmlmodule QtGraphs
38 * \ingroup graphs_qml_3D
39 * \nativetype QAbstract3DSeries
40 * \brief A base type for all 3D data series.
41 *
42 * This abstract class serves as a base class for the following subtypes:
43 * Bar3DSeries, Scatter3DSeries, and Surface3DSeries.
44 *
45 * For more information, see \l{Qt Graphs Data Handling with 3D}.
46 */
47
48/*!
49 * \enum QAbstract3DSeries::SeriesType
50 *
51 * Type of the series.
52 *
53 * \value None
54 * No series type.
55 * \value Bar
56 * Series type for Q3DBarsWidgetItem.
57 * \value Scatter
58 * Series type for Q3DScatterWidgetItem.
59 * \value Surface
60 * Series type for Q3DSurfaceWidgetItem.
61 */
62
63
64/*!
65 * \enum QAbstract3DSeries::Mesh
66 *
67 * Predefined mesh types. All styles are not usable with all graphs types.
68 *
69 * \value UserDefined
70 * User defined mesh, set via QAbstract3DSeries::userDefinedMesh property.
71 * \value Bar
72 * Basic rectangular bar.
73 * \value Cube
74 * Basic cube.
75 * \value Pyramid
76 * Four-sided pyramid.
77 * \value Cone
78 * Basic cone.
79 * \value Cylinder
80 * Basic cylinder.
81 * \value BevelBar
82 * Slightly beveled (rounded) rectangular bar.
83 * \value BevelCube
84 * Slightly beveled (rounded) cube.
85 * \value Sphere
86 * Sphere.
87 * \value Minimal
88 * The minimal 3D mesh: a triangular pyramid. Usable only with Q3DScatterWidgetItem.
89 * \value Arrow
90 * Arrow pointing upwards.
91 * \value Point
92 * 2D point. Usable only with Q3DScatterWidgetItem.
93 * Shadows do not affect this style. Color style QGraphsTheme::ColorStyle::ObjectGradient
94 * is not supported by this style.
95 */
96
97/*!
98 * \enum QAbstract3DSeries::LightingMode
99 *
100 * Predefined lighting modes
101 *
102 * \value Shaded
103 * Graphs respond to real time lighting
104 * \value Unshaded
105 * Graphs do not respond to real time lighting
106 */
107
108/*!
109 * \qmlproperty Abstract3DSeries.SeriesType Abstract3DSeries::type
110 * The type of the series. One of the QAbstract3DSeries::SeriesType values.
111 *
112 */
113
114/*!
115 * \qmlproperty string Abstract3DSeries::itemLabelFormat
116 *
117 * The label format for data items in this series. This format is used for
118 * single item labels, for example, when an item is selected. How the format is
119 * interpreted depends on series type.
120 *
121 * \sa Bar3DSeries, Scatter3DSeries, Surface3DSeries.
122 */
123
124/*!
125 * \qmlproperty bool Abstract3DSeries::visible
126 * The visibility of the series. If \c false, the series is not rendered.
127 */
128
129/*!
130 * \qmlproperty Abstract3DSeries.Mesh Abstract3DSeries::mesh
131 *
132 * The mesh of the items in the series, or the selection pointer in case of
133 * Surface3DSeries. If the mesh is
134 * \l{QAbstract3DSeries::Mesh::UserDefined}{Abstract3DSeries.Mesh.UserDefined},
135 * then the userDefinedMesh property must also be set for items to render
136 * properly. The default value depends on the graph type.
137 *
138 * \sa QAbstract3DSeries::Mesh
139 */
140
141/*!
142 * \qmlproperty bool Abstract3DSeries::meshSmooth
143 *
144 * If \c true, smooth versions of predefined meshes set via the \l mesh property
145 * are used. This property does not affect custom meshes used when the mesh is
146 * set to
147 * \l{QAbstract3DSeries::Mesh::UserDefined}{Abstract3DSeries.Mesh.UserDefined}.
148 * Defaults to \c{false}.
149 */
150
151/*!
152 * \qmlproperty quaternion Abstract3DSeries::meshRotation
153 *
154 * The mesh rotation that is applied to all items of the series.
155 * The rotation should be a normalized quaternion.
156 * For those series types that support item specific rotation, the rotations are
157 * multiplied together.
158 * Bar3DSeries ignores any rotation that is not around the y-axis.
159 * Surface3DSeries applies the rotation only to the selection pointer.
160 * Defaults to no rotation.
161 */
162
163/*!
164 * \qmlproperty string Abstract3DSeries::userDefinedMesh
165 *
166 * The filename for a user defined custom mesh for objects that is used
167 * when \l mesh is
168 * \l{QAbstract3DSeries::Mesh::UserDefined}{Abstract3DSeries.Mesh.UserDefined}.
169 * \note The file needs to be in the QtQuick3D mesh format. Use the \c balsam
170 * conversion tool to create a mesh from other 3D model formats.
171 */
172
173/*!
174 * \qmlproperty GraphsTheme.ColorStyle Abstract3DSeries::colorStyle
175 *
176 * The color style for the series.
177 *
178 * \sa {QGraphsTheme::ColorStyle}{GraphsTheme.ColorStyle}
179 */
180
181/*!
182 * \qmlproperty color Abstract3DSeries::baseColor
183 *
184 * The base color of the series.
185 *
186 * \sa colorStyle, {GraphsTheme::seriesColors}{GraphsTheme.seriesColors}
187 */
188
189/*!
190 * \qmlproperty Gradient Abstract3DSeries::baseGradient
191 *
192 * The base gradient of the series.
193 *
194 * \sa colorStyle
195 */
196
197/*!
198 * \qmlproperty color Abstract3DSeries::singleHighlightColor
199 *
200 * The single item highlight color of the series.
201 *
202 * \sa colorStyle, {GraphsTheme::singleHighlightColor}{GraphsTheme.singleHighlightColor}
203 */
204
205/*!
206 * \qmlproperty Gradient Abstract3DSeries::singleHighlightGradient
207 *
208 * The single item highlight gradient of the series.
209 *
210 * \sa colorStyle,
211 * {GraphsTheme::singleHighlightGradient}{GraphsTheme.singleHighlightGradient}
212 */
213
214/*!
215 * \qmlproperty color Abstract3DSeries::multiHighlightColor
216 *
217 * The multiple item highlight color of the series.
218 *
219 * \sa colorStyle, {GraphsTheme::multiHighlightColor}{GraphsTheme.multiHighlightColor}
220 */
221
222/*!
223 * \qmlproperty Gradient Abstract3DSeries::multiHighlightGradient
224 *
225 * The multiple item highlight gradient of the series.
226 *
227 * \sa colorStyle,
228 * {GraphsTheme::multiHighlightGradient}{GraphsTheme.multiHighlightGradient}
229 */
230
231/*!
232 * \qmlproperty Abstract3DSeries.LightingMode Abstract3DSeries::lightingMode
233 * \since 6.10
234 *
235 * The lighting mode of the items in the series.
236 * The default value is \l{QAbstract3DSeries::LightingMode::Shaded}
237 *
238 * \sa QAbstract3DSeries::LightingMode
239 */
240
241/*!
242 * \qmlproperty string Abstract3DSeries::name
243 *
244 * The series name.
245 * It can be used in item label format with the tag \c{@seriesName}.
246 *
247 * \sa itemLabelFormat
248 */
249
250/*!
251 * \qmlproperty string Abstract3DSeries::itemLabel
252 *
253 * The formatted item label. If there is no selected item or the selected item
254 * is not visible, returns an empty string.
255 *
256 * \sa itemLabelFormat
257 */
258
259/*!
260 * \qmlproperty bool Abstract3DSeries::itemLabelVisible
261 *
262 * If \c true, item labels are drawn as floating labels in the graph. Otherwise,
263 * item labels are not drawn. To show the item label in an external control,
264 * this property is set to \c false. Defaults to \c true.
265 *
266 * \sa itemLabelFormat, itemLabel
267 */
268
269/*!
270 * \qmlmethod void Abstract3DSeries::setMeshAxisAndAngle(vector3d axis, real
271 * angle)
272 *
273 * A convenience function to construct a mesh rotation quaternion from \a axis
274 * and \a angle.
275 *
276 * \sa meshRotation
277 */
278
279/*!
280 \qmlsignal Abstract3DSeries::itemLabelFormatChanged(string format)
281
282 This signal is emitted when itemLabelFormat changes to \a format.
283*/
284/*!
285 \qmlsignal Abstract3DSeries::visibilityChanged(bool visible)
286
287 This signal is emitted when the series visibility changes to \a visible.
288*/
289/*!
290 \qmlsignal Abstract3DSeries::meshChanged(Abstract3DSeries.Mesh mesh)
291
292 This signal is emitted when \l mesh changes to \a mesh.
293*/
294/*!
295 \qmlsignal Abstract3DSeries::meshSmoothChanged(bool enabled)
296
297 This signal is emitted when meshSmooth changes to \a enabled.
298*/
299/*!
300 \qmlsignal Abstract3DSeries::meshRotationChanged(quaternion rotation)
301
302 This signal is emitted when meshRotation changes to \a rotation.
303*/
304/*!
305 \qmlsignal Abstract3DSeries::userDefinedMeshChanged(string fileName)
306
307 This signal is emitted when userDefinedMesh changes to \a fileName.
308*/
309/*!
310 \qmlsignal Abstract3DSeries::colorStyleChanged(GraphsTheme.ColorStyle style)
311
312 This signal is emitted when colorStyle changes to \a style.
313*/
314/*!
315 \qmlsignal Abstract3DSeries::baseColorChanged(color color)
316
317 This signal is emitted when baseColor changes to \a color.
318*/
319/*!
320 \qmlsignal Abstract3DSeries::baseGradientChanged(Gradient gradient)
321
322 This signal is emitted when baseGradient changes to \a gradient.
323*/
324/*!
325 \qmlsignal Abstract3DSeries::singleHighlightColorChanged(color color)
326
327 This signal is emitted when singleHighlightColor changes to \a color.
328*/
329/*!
330 \qmlsignal Abstract3DSeries::singleHighlightGradientChanged(Gradient gradient)
331
332 This signal is emitted when singleHighlightGradient changes to \a gradient.
333*/
334/*!
335 \qmlsignal Abstract3DSeries::multiHighlightColorChanged(color color)
336
337 This signal is emitted when multiHighlightColor changes to \a color.
338*/
339/*!
340 \qmlsignal Abstract3DSeries::multiHighlightGradientChanged(Gradient gradient)
341
342 This signal is emitted when multiHighlightGradient changes to \a gradient.
343*/
344/*!
345 \qmlsignal Abstract3DSeries::lightingModeChanged(Abstract3DSeries.LightingMode lightingMode)
346
347 This signal is emitted when \l lightingMode changes to \a lightingMode.
348 \since 6.10
349*/
350/*!
351 \qmlsignal Abstract3DSeries::nameChanged(string name)
352
353 This signal is emitted when \l name changes to \a name.
354*/
355/*!
356 \qmlsignal Abstract3DSeries::itemLabelChanged(string label)
357
358 This signal is emitted when itemLabel changes to \a label.
359*/
360/*!
361 \qmlsignal Abstract3DSeries::itemLabelVisibilityChanged(bool visible)
362
363 This signal is emitted when itemLabelVisibility changes to \a visible.
364*/
365
366/*!
367 * \internal
368 */
369QAbstract3DSeries::QAbstract3DSeries(QAbstract3DSeriesPrivate &d, QObject *parent)
370 : QObject(d, parent)
371{}
372
373/*!
374 * Deletes the abstract 3D series.
375 */
376QAbstract3DSeries::~QAbstract3DSeries() {}
377
378/*!
379 * \property QAbstract3DSeries::type
380 *
381 * \brief The type of the series.
382 */
383QAbstract3DSeries::SeriesType QAbstract3DSeries::type() const
384{
385 Q_D(const QAbstract3DSeries);
386 return d->m_type;
387}
388
389/*!
390 * \property QAbstract3DSeries::itemLabelFormat
391 *
392 * \brief The label format for data items in this series.
393 *
394 * This format is used for single item labels,
395 * for example, when an item is selected. How the format is interpreted depends
396 * on series type.
397 *
398 * \sa QBar3DSeries, QScatter3DSeries, QSurface3DSeries.
399 */
400void QAbstract3DSeries::setItemLabelFormat(const QString &format)
401{
402 Q_D(QAbstract3DSeries);
403 if (d->m_itemLabelFormat == format) {
404 qCDebug(lcProperties3D, "%s value: %s is same than it already was.",
405 qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(format));
406 return;
407 }
408
409 d->setItemLabelFormat(format);
410 emit itemLabelFormatChanged(format);
411}
412
413QString QAbstract3DSeries::itemLabelFormat() const
414{
415 Q_D(const QAbstract3DSeries);
416 return d->m_itemLabelFormat;
417}
418
419/*!
420 * \property QAbstract3DSeries::visible
421 *
422 * \brief The visibility of the series.
423 *
424 * If this property is \c false, the series is not rendered.
425 * Defaults to \c{true}.
426 */
427void QAbstract3DSeries::setVisible(bool visible)
428{
429 Q_D(QAbstract3DSeries);
430 if (d->m_visible == visible) {
431 qCDebug(lcProperties3D) << __FUNCTION__
432 << "value is already set to:" << visible;
433 return;
434 }
435
436 d->setVisible(visible);
437 emit visibleChanged(visible);
438}
439
440bool QAbstract3DSeries::isVisible() const
441{
442 Q_D(const QAbstract3DSeries);
443 return d->m_visible;
444}
445
446/*!
447 * \property QAbstract3DSeries::mesh
448 *
449 * \brief The mesh of the items in the series.
450 *
451 * For QSurface3DSeries, this property holds the selection pointer.
452 *
453 * If the mesh is MeshUserDefined, then the userDefinedMesh property
454 * must also be set for items to render properly. The default value depends on
455 * the graph type.
456 */
457void QAbstract3DSeries::setMesh(QAbstract3DSeries::Mesh mesh)
458{
459 Q_D(QAbstract3DSeries);
460 if ((mesh == QAbstract3DSeries::Mesh::Point || mesh == QAbstract3DSeries::Mesh::Minimal
461 || mesh == QAbstract3DSeries::Mesh::Arrow)
462 && type() != QAbstract3DSeries::SeriesType::Scatter) {
463 qCWarning(lcProperties3D, "%s specified style is only supported for QScatter3DSeries.",
464 qUtf8Printable(QLatin1String(__FUNCTION__)));
465 return;
466 } else if (d->m_mesh == mesh) {
467 qCDebug(lcProperties3D) << __FUNCTION__
468 << "value is already set to:" << mesh;
469 return;
470 }
471
472 d->setMesh(mesh);
473 emit meshChanged(mesh);
474}
475
476QAbstract3DSeries::Mesh QAbstract3DSeries::mesh() const
477{
478 Q_D(const QAbstract3DSeries);
479 return d->m_mesh;
480}
481
482/*!
483 * \property QAbstract3DSeries::meshSmooth
484 *
485 * \brief Whether smooth versions of predefined meshes are used.
486 *
487 * If \c true, smooth versions set via the \l mesh property are used.
488 * This property does not affect custom meshes used when the mesh is set to
489 * MeshUserDefined. Defaults to \c{false}.
490 */
491void QAbstract3DSeries::setMeshSmooth(bool enable)
492{
493 Q_D(QAbstract3DSeries);
494 if (d->m_meshSmooth == enable) {
495 qCDebug(lcProperties3D) << __FUNCTION__
496 << "value is already set to:" << enable;
497 return;
498 }
499
500 d->setMeshSmooth(enable);
501 emit meshSmoothChanged(enabled: enable);
502}
503
504bool QAbstract3DSeries::isMeshSmooth() const
505{
506 Q_D(const QAbstract3DSeries);
507 return d->m_meshSmooth;
508}
509
510/*!
511 * \property QAbstract3DSeries::meshRotation
512 *
513 * \brief The mesh rotation that is applied to all items of the series.
514 *
515 * The rotation should be a normalized QQuaternion.
516 * For those series types that support item specific rotation, the rotations are
517 * multiplied together.
518 * QBar3DSeries ignores any rotation that is not around the y-axis.
519 * QSurface3DSeries applies the rotation only to the selection pointer.
520 * Defaults to no rotation.
521 */
522void QAbstract3DSeries::setMeshRotation(const QQuaternion &rotation)
523{
524 Q_D(QAbstract3DSeries);
525 if (d->m_meshRotation == rotation) {
526 qCDebug(lcProperties3D) << __FUNCTION__
527 << "value is already set to:" << rotation;
528 return;
529 }
530
531 d->setMeshRotation(rotation);
532 emit meshRotationChanged(rotation);
533}
534
535QQuaternion QAbstract3DSeries::meshRotation() const
536{
537 Q_D(const QAbstract3DSeries);
538 return d->m_meshRotation;
539}
540
541/*!
542 * A convenience function to construct a mesh rotation quaternion from
543 * \a axis and \a angle.
544 *
545 * \sa meshRotation
546 */
547void QAbstract3DSeries::setMeshAxisAndAngle(QVector3D axis, float angle)
548{
549 setMeshRotation(QQuaternion::fromAxisAndAngle(axis, angle));
550}
551
552/*!
553 * \property QAbstract3DSeries::userDefinedMesh
554 *
555 * \brief The filename for a user defined custom mesh for objects.
556 *
557 * The custom mesh is used when \l mesh is MeshUserDefined.
558 * \note The file needs to be in the QtQuick3D mesh format. Use the \c balsam
559 * conversion tool to create a mesh from other 3D model formats.
560 */
561void QAbstract3DSeries::setUserDefinedMesh(const QString &fileName)
562{
563 Q_D(QAbstract3DSeries);
564 if (d->m_userDefinedMesh == fileName) {
565 qCDebug(lcProperties3D, "%s value %s is same than what is already being used.",
566 qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(fileName));
567 return;
568 }
569
570 d->setUserDefinedMesh(fileName);
571 emit userDefinedMeshChanged(fileName);
572}
573
574QString QAbstract3DSeries::userDefinedMesh() const
575{
576 Q_D(const QAbstract3DSeries);
577 return d->m_userDefinedMesh;
578}
579
580/*!
581 * \property QAbstract3DSeries::colorStyle
582 *
583 * \brief The color style for the series.
584 *
585 * \sa QGraphsTheme::ColorStyle
586 */
587void QAbstract3DSeries::setColorStyle(QGraphsTheme::ColorStyle style)
588{
589 Q_D(QAbstract3DSeries);
590 if (d->m_colorStyle == style) {
591 qCDebug(lcProperties3D) << __FUNCTION__
592 << "value is already set to:" << style;
593 d->m_themeTracker.colorStyleOverride = true;
594 return;
595 }
596
597 d->setColorStyle(style);
598 emit colorStyleChanged(style);
599
600 d->m_themeTracker.colorStyleOverride = true;
601}
602
603QGraphsTheme::ColorStyle QAbstract3DSeries::colorStyle() const
604{
605 Q_D(const QAbstract3DSeries);
606 return d->m_colorStyle;
607}
608
609/*!
610 * \property QAbstract3DSeries::baseColor
611 *
612 * \brief The base color of the series.
613 *
614 * \sa colorStyle, QGraphsTheme::seriesColors
615 */
616void QAbstract3DSeries::setBaseColor(QColor color)
617{
618 Q_D(QAbstract3DSeries);
619 if (d->m_baseColor == color) {
620 qCDebug(lcProperties3D, "%s value is already set to: %s",
621 qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(color.name()));
622 d->m_themeTracker.baseColorOverride = true;
623 return;
624 }
625
626 d->setBaseColor(color);
627 emit baseColorChanged(color);
628
629 d->m_themeTracker.baseColorOverride = true;
630}
631
632QColor QAbstract3DSeries::baseColor() const
633{
634 Q_D(const QAbstract3DSeries);
635 return d->m_baseColor;
636}
637
638/*!
639 * \property QAbstract3DSeries::baseGradient
640 *
641 * \brief The base gradient of the series.
642 *
643 * \sa colorStyle, QGraphsTheme::seriesGradients
644 */
645void QAbstract3DSeries::setBaseGradient(const QLinearGradient &gradient)
646{
647 Q_D(QAbstract3DSeries);
648 if (d->m_baseGradient == gradient) {
649 qCDebug(lcProperties3D) << __FUNCTION__
650 << "value is already set to:" << gradient;
651 d->m_themeTracker.baseGradientOverride = true;
652 return;
653 }
654 d->setBaseGradient(gradient);
655 emit baseGradientChanged(gradient);
656
657 d->m_themeTracker.baseGradientOverride = true;
658}
659
660QLinearGradient QAbstract3DSeries::baseGradient() const
661{
662 Q_D(const QAbstract3DSeries);
663 return d->m_baseGradient;
664}
665
666/*!
667 * \property QAbstract3DSeries::singleHighlightColor
668 *
669 * \brief The single item highlight color of the series.
670 *
671 * \sa colorStyle, QGraphsTheme::singleHighlightColor
672 */
673void QAbstract3DSeries::setSingleHighlightColor(QColor color)
674{
675 Q_D(QAbstract3DSeries);
676 if (d->m_singleHighlightColor == color) {
677 qCDebug(lcProperties3D, "%s value is already set to: %s",
678 qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(color.name()));
679 d->m_themeTracker.singleHighlightColorOverride = true;
680 return;
681 }
682
683 d->setSingleHighlightColor(color);
684 emit singleHighlightColorChanged(color);
685 d->m_themeTracker.singleHighlightColorOverride = true;
686}
687
688QColor QAbstract3DSeries::singleHighlightColor() const
689{
690 Q_D(const QAbstract3DSeries);
691 return d->m_singleHighlightColor;
692}
693
694/*!
695 * \property QAbstract3DSeries::singleHighlightGradient
696 *
697 * \brief The single item highlight gradient of the series.
698 *
699 * \sa colorStyle, QGraphsTheme::singleHighlightGradient
700 */
701void QAbstract3DSeries::setSingleHighlightGradient(const QLinearGradient &gradient)
702{
703 Q_D(QAbstract3DSeries);
704 if (d->m_singleHighlightGradient == gradient) {
705 qCDebug(lcProperties3D) << __FUNCTION__
706 << "value is already set to:" << gradient;
707 d->m_themeTracker.singleHighlightGradientOverride = true;
708 return;
709 }
710
711 d->setSingleHighlightGradient(gradient);
712 emit singleHighlightGradientChanged(gradient);
713 d->m_themeTracker.singleHighlightGradientOverride = true;
714}
715
716QLinearGradient QAbstract3DSeries::singleHighlightGradient() const
717{
718 Q_D(const QAbstract3DSeries);
719 return d->m_singleHighlightGradient;
720}
721
722/*!
723 * \property QAbstract3DSeries::multiHighlightColor
724 *
725 * \brief The multiple item highlight color of the series.
726 *
727 * \sa colorStyle, QGraphsTheme::multiHighlightColor
728 */
729void QAbstract3DSeries::setMultiHighlightColor(QColor color)
730{
731 Q_D(QAbstract3DSeries);
732 if (d->m_multiHighlightColor == color) {
733 qCDebug(lcProperties3D, "%s value is already set to: %s",
734 qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(color.name()));
735 d->m_themeTracker.multiHighlightColorOverride = true;
736 return;
737 }
738
739 d->setMultiHighlightColor(color);
740 emit multiHighlightColorChanged(color);
741 d->m_themeTracker.multiHighlightColorOverride = true;
742}
743
744QColor QAbstract3DSeries::multiHighlightColor() const
745{
746 Q_D(const QAbstract3DSeries);
747 return d->m_multiHighlightColor;
748}
749
750/*!
751 * \property QAbstract3DSeries::multiHighlightGradient
752 *
753 * \brief The multiple item highlight gradient of the series.
754 *
755 * \sa colorStyle, QGraphsTheme::multiHighlightGradient
756 */
757void QAbstract3DSeries::setMultiHighlightGradient(const QLinearGradient &gradient)
758{
759 Q_D(QAbstract3DSeries);
760 if (d->m_multiHighlightGradient == gradient) {
761 qCDebug(lcProperties3D) << __FUNCTION__
762 << "value is already set to:" << gradient;
763 d->m_themeTracker.multiHighlightGradientOverride = true;
764 return;
765 }
766
767 d->setMultiHighlightGradient(gradient);
768 emit multiHighlightGradientChanged(gradient);
769 d->m_themeTracker.multiHighlightGradientOverride = true;
770}
771
772QLinearGradient QAbstract3DSeries::multiHighlightGradient() const
773{
774 Q_D(const QAbstract3DSeries);
775 return d->m_multiHighlightGradient;
776}
777
778/*!
779 * \property QAbstract3DSeries::lightingMode
780 *
781 * \brief The lighting mode of the series
782 * \since 6.10
783 * \sa LightingMode
784 */
785void QAbstract3DSeries::setLightingMode(LightingMode lightingMode)
786{
787 Q_D(QAbstract3DSeries);
788 if (d->m_lightingMode != lightingMode) {
789 d->setLightingMode(lightingMode);
790 emit lightingModeChanged(lightingMode);
791 }
792}
793
794QAbstract3DSeries::LightingMode QAbstract3DSeries::lightingMode() const
795{
796 Q_D(const QAbstract3DSeries);
797 return d->m_lightingMode;
798}
799
800/*!
801 * \property QAbstract3DSeries::name
802 *
803 * \brief The series name.
804 *
805 * The series name can be used in item label format with the tag
806 * \c{@seriesName}.
807 *
808 * \sa itemLabelFormat
809 */
810void QAbstract3DSeries::setName(const QString &name)
811{
812 Q_D(QAbstract3DSeries);
813 if (d->m_name == name) {
814 qCDebug(lcProperties3D, "%s value is already set to: %s",
815 qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(name));
816 return;
817 }
818
819 d->setName(name);
820 emit nameChanged(name);
821}
822
823QString QAbstract3DSeries::name() const
824{
825 Q_D(const QAbstract3DSeries);
826 return d->m_name;
827}
828
829/*!
830 * \property QAbstract3DSeries::itemLabel
831 *
832 * \brief The formatted item label.
833 *
834 * If there is no selected item or the selected item is not
835 * visible, returns an empty string.
836 *
837 * \sa itemLabelFormat
838 */
839QString QAbstract3DSeries::itemLabel()
840{
841 Q_D(QAbstract3DSeries);
842 return d->itemLabel();
843}
844
845/*!
846 * \property QAbstract3DSeries::itemLabelVisible
847 *
848 * \brief The visibility of item labels in the graph.
849 *
850 * If \c true, item labels are drawn as floating labels in the graph. Otherwise,
851 * item labels are not drawn. To show the item label in an external control,
852 * this property is set to \c false. Defaults to \c true.
853 *
854 * \sa itemLabelFormat, itemLabel
855 */
856void QAbstract3DSeries::setItemLabelVisible(bool visible)
857{
858 Q_D(QAbstract3DSeries);
859 if (d->m_itemLabelVisible == visible) {
860 qCDebug(lcProperties3D) << __FUNCTION__
861 << "value is already set to:" << visible;
862 return;
863 }
864
865 d->setItemLabelVisible(visible);
866 emit itemLabelVisibleChanged(visible);
867}
868
869bool QAbstract3DSeries::isItemLabelVisible() const
870{
871 Q_D(const QAbstract3DSeries);
872 return d->m_itemLabelVisible;
873}
874
875// QAbstract3DSeriesPrivate
876
877QAbstract3DSeriesPrivate::QAbstract3DSeriesPrivate(QAbstract3DSeries::SeriesType type)
878 : m_type(type)
879 , m_dataProxy(0)
880 , m_visible(true)
881 , m_graph(0)
882 , m_mesh(QAbstract3DSeries::Mesh::Cube)
883 , m_meshSmooth(false)
884 , m_colorStyle(QGraphsTheme::ColorStyle::Uniform)
885 , m_baseColor(Qt::black)
886 , m_singleHighlightColor(Qt::black)
887 , m_multiHighlightColor(Qt::black)
888 , m_itemLabelDirty(true)
889 , m_itemLabelVisible(true)
890 , m_lightingMode(QAbstract3DSeries::LightingMode::Shaded)
891{}
892
893QAbstract3DSeriesPrivate::~QAbstract3DSeriesPrivate() {}
894
895QAbstractDataProxy *QAbstract3DSeriesPrivate::dataProxy() const
896{
897 return m_dataProxy;
898}
899
900void QAbstract3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy)
901{
902 Q_Q(QAbstract3DSeries);
903 Q_ASSERT(proxy && proxy != m_dataProxy && !proxy->d_func()->series());
904
905 delete m_dataProxy;
906 m_dataProxy = proxy;
907
908 proxy->d_func()->setSeries(q); // also sets parent
909
910 if (m_graph) {
911 connectGraphAndProxy(newGraph: m_graph);
912 m_graph->markDataDirty();
913 }
914}
915
916void QAbstract3DSeriesPrivate::setGraph(QQuickGraphsItem *graph)
917{
918 Q_Q(QAbstract3DSeries);
919 m_graph = graph;
920 q->setParent(graph);
921 connectGraphAndProxy(newGraph: graph);
922 markItemLabelDirty();
923}
924
925void QAbstract3DSeriesPrivate::setItemLabelFormat(const QString &format)
926{
927 m_itemLabelFormat = format;
928 markItemLabelDirty();
929}
930
931void QAbstract3DSeriesPrivate::setVisible(bool visible)
932{
933 m_visible = visible;
934 markItemLabelDirty();
935}
936
937void QAbstract3DSeriesPrivate::setMesh(QAbstract3DSeries::Mesh mesh)
938{
939 m_mesh = mesh;
940 m_changeTracker.meshChanged = true;
941 if (m_graph) {
942 m_graph->markSeriesVisualsDirty();
943
944 if (m_graph->optimizationHint() == QtGraphs3D::OptimizationHint::Default)
945 m_graph->markDataDirty();
946 }
947}
948
949void QAbstract3DSeriesPrivate::setMeshSmooth(bool enable)
950{
951 m_meshSmooth = enable;
952 m_changeTracker.meshSmoothChanged = true;
953 if (m_graph) {
954 m_graph->markSeriesVisualsDirty();
955
956 if (m_graph->optimizationHint() == QtGraphs3D::OptimizationHint::Default)
957 m_graph->markDataDirty();
958 }
959}
960
961void QAbstract3DSeriesPrivate::setMeshRotation(const QQuaternion &rotation)
962{
963 m_meshRotation = rotation;
964 m_changeTracker.meshRotationChanged = true;
965 if (m_graph) {
966 m_graph->markSeriesVisualsDirty();
967
968 if (m_graph->optimizationHint() == QtGraphs3D::OptimizationHint::Default)
969 m_graph->markDataDirty();
970 }
971}
972
973void QAbstract3DSeriesPrivate::setUserDefinedMesh(const QString &meshFile)
974{
975 m_userDefinedMesh = meshFile;
976 m_changeTracker.userDefinedMeshChanged = true;
977 if (m_graph) {
978 m_graph->markSeriesVisualsDirty();
979
980 if (m_graph->optimizationHint() == QtGraphs3D::OptimizationHint::Default)
981 m_graph->markDataDirty();
982 }
983}
984
985void QAbstract3DSeriesPrivate::setColorStyle(QGraphsTheme::ColorStyle style)
986{
987 m_colorStyle = style;
988 m_changeTracker.colorStyleChanged = true;
989 if (m_graph)
990 m_graph->markSeriesVisualsDirty();
991}
992
993void QAbstract3DSeriesPrivate::setBaseColor(QColor color)
994{
995 m_baseColor = color;
996 m_changeTracker.baseColorChanged = true;
997 if (m_graph)
998 m_graph->markSeriesVisualsDirty();
999}
1000
1001void QAbstract3DSeriesPrivate::setBaseGradient(const QLinearGradient &gradient)
1002{
1003 m_baseGradient = gradient;
1004 Utils::verifyGradientCompleteness(gradient&: m_baseGradient);
1005 m_changeTracker.baseGradientChanged = true;
1006 if (m_graph)
1007 m_graph->markSeriesVisualsDirty();
1008}
1009
1010void QAbstract3DSeriesPrivate::setSingleHighlightColor(QColor color)
1011{
1012 m_singleHighlightColor = color;
1013 m_changeTracker.singleHighlightColorChanged = true;
1014 if (m_graph)
1015 m_graph->markSeriesVisualsDirty();
1016}
1017
1018void QAbstract3DSeriesPrivate::setSingleHighlightGradient(const QLinearGradient &gradient)
1019{
1020 m_singleHighlightGradient = gradient;
1021 Utils::verifyGradientCompleteness(gradient&: m_singleHighlightGradient);
1022 m_changeTracker.singleHighlightGradientChanged = true;
1023 if (m_graph)
1024 m_graph->markSeriesVisualsDirty();
1025}
1026
1027void QAbstract3DSeriesPrivate::setMultiHighlightColor(QColor color)
1028{
1029 m_multiHighlightColor = color;
1030 m_changeTracker.multiHighlightColorChanged = true;
1031 if (m_graph)
1032 m_graph->markSeriesVisualsDirty();
1033}
1034
1035void QAbstract3DSeriesPrivate::setMultiHighlightGradient(const QLinearGradient &gradient)
1036{
1037 m_multiHighlightGradient = gradient;
1038 Utils::verifyGradientCompleteness(gradient&: m_multiHighlightGradient);
1039 m_changeTracker.multiHighlightGradientChanged = true;
1040 if (m_graph)
1041 m_graph->markSeriesVisualsDirty();
1042}
1043
1044void QAbstract3DSeriesPrivate::setLightingMode(QAbstract3DSeries::LightingMode lightingMode)
1045{
1046 m_lightingMode = lightingMode;
1047 if (m_graph)
1048 m_graph->markSeriesVisualsDirty();
1049 m_changeTracker.lightingModeChanged = true;
1050}
1051
1052void QAbstract3DSeriesPrivate::setName(const QString &name)
1053{
1054 m_name = name;
1055 markItemLabelDirty();
1056 m_changeTracker.nameChanged = true;
1057}
1058
1059void QAbstract3DSeriesPrivate::resetToTheme(const QGraphsTheme &theme, qsizetype seriesIndex, bool force)
1060{
1061 Q_Q(QAbstract3DSeries);
1062 qsizetype themeIndex = seriesIndex;
1063 if (force || !m_themeTracker.colorStyleOverride) {
1064 q->setColorStyle(theme.colorStyle());
1065 m_themeTracker.colorStyleOverride = false;
1066 }
1067 if (theme.seriesColors().size() && (force || !m_themeTracker.baseColorOverride)) {
1068 if (theme.seriesColors().size() <= seriesIndex)
1069 themeIndex = seriesIndex % theme.seriesColors().size();
1070 q->setBaseColor(theme.seriesColors().at(i: themeIndex));
1071 m_themeTracker.baseColorOverride = false;
1072 }
1073 if (theme.seriesGradients().size() && (force || !m_themeTracker.baseGradientOverride)) {
1074 if (theme.seriesGradients().size() <= seriesIndex)
1075 themeIndex = seriesIndex % theme.seriesGradients().size();
1076 q->setBaseGradient(theme.seriesGradients().at(i: themeIndex));
1077 m_themeTracker.baseGradientOverride = false;
1078 }
1079 if (force || !m_themeTracker.singleHighlightColorOverride) {
1080 q->setSingleHighlightColor(theme.singleHighlightColor());
1081 m_themeTracker.singleHighlightColorOverride = false;
1082 }
1083 if (force || !m_themeTracker.singleHighlightGradientOverride) {
1084 q->setSingleHighlightGradient(theme.singleHighlightGradient());
1085 m_themeTracker.singleHighlightGradientOverride = false;
1086 }
1087 if (force || !m_themeTracker.multiHighlightColorOverride) {
1088 q->setMultiHighlightColor(theme.multiHighlightColor());
1089 m_themeTracker.multiHighlightColorOverride = false;
1090 }
1091 if (force || !m_themeTracker.multiHighlightGradientOverride) {
1092 q->setMultiHighlightGradient(theme.multiHighlightGradient());
1093 m_themeTracker.multiHighlightGradientOverride = false;
1094 }
1095}
1096
1097QString QAbstract3DSeriesPrivate::itemLabel()
1098{
1099 Q_Q(QAbstract3DSeries);
1100 if (m_itemLabelDirty) {
1101 QString oldLabel = m_itemLabel;
1102 if (m_graph && m_visible)
1103 createItemLabel();
1104 else
1105 m_itemLabel = QString();
1106 m_itemLabelDirty = false;
1107
1108 if (oldLabel != m_itemLabel)
1109 emit q->itemLabelChanged(label: m_itemLabel);
1110 }
1111
1112 return m_itemLabel;
1113}
1114
1115void QAbstract3DSeriesPrivate::markItemLabelDirty()
1116{
1117 m_itemLabelDirty = true;
1118 m_changeTracker.itemLabelChanged = true;
1119}
1120
1121void QAbstract3DSeriesPrivate::setItemLabelVisible(bool visible)
1122{
1123 m_itemLabelVisible = visible;
1124 markItemLabelDirty();
1125 m_changeTracker.itemLabelVisibilityChanged = true;
1126}
1127
1128bool QAbstract3DSeriesPrivate::isUsingGradient()
1129{
1130 return m_colorStyle != QGraphsTheme::ColorStyle::Uniform ? true : false;
1131}
1132
1133QT_END_NAMESPACE
1134

source code of qtgraphs/src/graphs3d/data/qabstract3dseries.cpp