1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "graphs2d/qabstractseries.h"
5#include <QtGraphs/qabstractseries.h>
6#include <private/qabstractseries_p.h>
7#include <private/qgraphsview_p.h>
8
9QT_BEGIN_NAMESPACE
10
11/*!
12 \class QAbstractSeries
13 \inmodule QtGraphs
14 \ingroup graphs_2D
15 \brief The QAbstractSeries class is a base class for all Qt Graphs for 2D series.
16
17 Usually, the series type specific inherited classes are used instead of the base class.
18
19 \sa QLineSeries, QSplineSeries, QScatterSeries, QBarSeries, QXYSeries
20*/
21/*!
22 \qmltype AbstractSeries
23 \nativetype QAbstractSeries
24 \inqmlmodule QtGraphs
25 \ingroup graphs_qml_2D
26 \brief Base type for all Qt Graph series types.
27
28 This type cannot be instantiated directly. Instead, one of the following derived types
29 should be used to create a series: LineSeries, SplineSeries, BarSeries, or ScatterSeries.
30*/
31
32/*!
33 \class QLegendData
34 \inmodule QtGraphs
35 \ingroup graphs_2D
36 \brief The QLegendData struct contains information to display on a sets
37 legend marker.
38
39 The information needed to make a visual association between a set and a
40 marker include properties such as color, border color, and a name of a set.
41
42 \sa QLineSeries, QSplineSeries, QScatterSeries, QBarSeries, QXYSeries
43*/
44
45/*!
46 \qmlvaluetype legendData
47 \nativetype QLegendData
48 \inqmlmodule QtGraphs
49 \ingroup graphs_qml__2D
50 \brief The legendData value type contains information to display on a sets
51 legend marker.
52
53 The information needed to make a visual association between a set and a
54 marker include properties such as color, border color, and a name of a set.
55
56 \note Before Qt 6.10, this value type was only provided as an anonymous
57 type.
58*/
59
60/*!
61 \property QLegendData::color
62 \brief A legend marker's color.
63*/
64/*!
65 \qmlproperty color LegendData::color
66 \brief A legend marker's color.
67*/
68
69/*!
70 \property QLegendData::borderColor
71 \brief A border color of a legend marker.
72*/
73/*!
74 \qmlproperty color LegendData::borderColor
75 \brief A border color of a legend marker.
76*/
77
78/*!
79 \property QLegendData::label
80 \brief A name of a legend marker.
81*/
82/*!
83 \qmlproperty string LegendData::label
84 \brief A name of a legend marker.
85*/
86
87/*!
88 \enum QAbstractSeries::SeriesType
89
90 This enum describes the type of the series.
91
92 \value Line A line graph.
93 \value Bar A bar graph.
94 \value Scatter A scatter graph.
95 \value Pie A pie graph.
96 \value Spline A spline graph.
97 \value Area An area graph.
98*/
99
100/*!
101 \property QAbstractSeries::type
102 \brief The type of the series.
103*/
104/*!
105 \qmlproperty enumeration AbstractSeries::type
106
107 The type of the series.
108
109 \value AbstractSeries.SeriesType.Line A line graph.
110 \value AbstractSeries.SeriesType.Bar A bar graph.
111 \value AbstractSeries.SeriesType.Scatter A scatter graph.
112 \value AbstractSeries.SeriesType.Pie A pie graph.
113 \value AbstractSeries.SeriesType.Spline A spline graph.
114 \value AbstractSeries.SeriesType.Area An area graph.
115*/
116
117/*!
118 \property QAbstractSeries::name
119 \brief The name of the series.
120
121 The name is displayed in the legend for the series and it supports HTML formatting.
122*/
123/*!
124 \qmlproperty string AbstractSeries::name
125 The name of the series. The name is displayed in the legend for the series and it
126 supports HTML formatting.
127*/
128
129/*!
130 \property QAbstractSeries::visible
131 \brief Visibility of the series.
132
133 The visibility used for this series. By default, \a visible is set to \c true.
134*/
135/*!
136 \qmlproperty bool AbstractSeries::visible
137 The visibility used for this series. By default, \a visible is set to \c true.
138*/
139
140/*!
141 \property QAbstractSeries::selectable
142 \brief Controls if the series is selectable.
143
144 Controls if the series can be selected with mouse/touch.
145 By default, \a selectable is set to \c false.
146*/
147/*!
148 \qmlproperty bool AbstractSeries::selectable
149 Controls if the series can be selected with mouse/touch.
150 By default, \a selectable is set to \c false.
151*/
152
153/*!
154 \property QAbstractSeries::hoverable
155 \brief Controls if the series is hoverable.
156
157 Controls if the series can be hovered with mouse/touch.
158 By default, \a hoverable is set to \c false.
159*/
160/*!
161 \qmlproperty bool AbstractSeries::hoverable
162 Controls if the series can be hovered with mouse/touch.
163 By default, \a hoverable is set to \c false.
164*/
165
166/*!
167 \property QAbstractSeries::hovered
168 \brief Check whether a series is hovered on.
169
170 Can be used to check whether mouse/touch is currently
171 hovering on a series.
172 \sa QAbstractSeries::hovered
173*/
174/*!
175 \qmlproperty bool AbstractSeries::hovered
176 Can be used to check whether mouse/touch is currently
177 hovering on a series.
178 \sa QAbstractSeries::hovered
179*/
180
181/*!
182 \property QAbstractSeries::opacity
183 \brief The opacity of the series.
184
185 By default, the opacity is 1.0. The valid values range from 0.0 (transparent) to 1.0 (opaque).
186*/
187/*!
188 \qmlproperty real AbstractSeries::opacity
189 The opacity of the series. By default, the opacity is 1.0.
190 The valid values range from 0.0 (transparent) to 1.0 (opaque).
191*/
192
193/*!
194 \property QAbstractSeries::valuesMultiplier
195 \brief Controls the series values effective visible value.
196
197 This variable can be used for animating the series values so they scale from 0 to actual value size.
198 By default, the valuesMultiplier is 1.0. The valid values range from 0.0 (height 0) to 1.0 (full value).
199*/
200/*!
201 \qmlproperty real AbstractSeries::valuesMultiplier
202 This variable can be used for animating the series values so they scale from 0 to actual value size.
203 By default, the valuesMultiplier is 1.0. The valid values range from 0.0 (height 0) to 1.0 (full value).
204*/
205
206/*!
207 \property QAbstractSeries::axisX
208 \brief X-axis of this series.
209 \since 6.10
210
211 The x-axis used for this series. Creates a separate axis from the one defined
212 in GraphsView showing the user multiple axis per graph.
213*/
214/*!
215 \qmlproperty AbstractAxis AbstractSeries::axisX
216 \since 6.10
217 The x-axis used for this series. Creates a separate axis from the one defined
218 in GraphsView showing the user multiple axis per graph.
219 \sa axisY
220*/
221
222/*!
223 \property QAbstractSeries::axisY
224 \brief Y-axis of this series.
225 \since 6.10
226
227 The y-axis used for this series. Creates a separate axis from the one defined
228 in GraphsView showing the user multiple axis per graph.
229*/
230/*!
231 \qmlproperty AbstractAxis AbstractSeries::axisY
232 \since 6.10
233 The y-axis used for this series. Creates a separate axis from the one defined
234 in GraphsView showing the user multiple axis per graph.
235 \sa axisX
236*/
237
238/*!
239 \property QAbstractSeries::zValue
240 \brief Controls the order in which the series is drawn
241 \since 6.10
242
243 The series list of GraphsView is sorted by the zValue property. Since each series type is
244 rendered at once, the order mostly works as an internal order of each series type. The highest
245 zValue of each series type determines the order of rendering among series types. The default
246 value is 0.
247*/
248/*!
249 \qmlproperty int AbstractSeries::zValue
250 \since 6.10
251 The series list of GraphsView is sorted by the zValue property. Since each series type is
252 rendered at once, the order mostly works as an internal order of each series type. The highest
253 zValue of each series type determines the order of rendering among series types. The default
254 value is 0.
255*/
256
257/*!
258 \property QAbstractSeries::legendData
259 \brief Contains information needed to create a legend marker for a data set in a graph.
260 \sa QLegendData
261 */
262/*!
263 \qmlproperty list<LegendData> AbstractSeries::legendData
264 Contains information needed to create a legend marker for a data set in a graph.
265*/
266
267/*!
268 \qmlsignal AbstractSeries::legendDataChanged()
269 This signal is emitted when legend data changes.
270*/
271
272/*!
273 \qmlsignal AbstractSeries::themeChanged()
274 This signal is emitted when the series theme changes.
275*/
276
277/*!
278 \qmlsignal AbstractSeries::nameChanged()
279 This signal is emitted when the series \l name changes.
280*/
281
282/*!
283 \qmlsignal AbstractSeries::visibleChanged()
284 This signal is emitted when the series visibility changes.
285*/
286
287/*!
288 \qmlsignal AbstractSeries::selectableChanged()
289 This signal is emitted when the series \l selectable changes.
290*/
291
292/*!
293 \qmlsignal AbstractSeries::hoverableChanged()
294 This signal is emitted when the series \l hoverable changes.
295*/
296
297/*!
298 \qmlsignal AbstractSeries::hoveredChanged()
299 This signal is emitted when the series \l hovered changes.
300*/
301
302/*!
303 \qmlsignal AbstractSeries::opacityChanged()
304 This signal is emitted when the \l opacity of the series changes.
305*/
306
307/*!
308 \qmlsignal AbstractSeries::valuesMultiplierChanged()
309 This signal is emitted when the valuesMultiplier of the series changes.
310*/
311
312/*!
313 \qmlsignal QAbstractSeries::axisXChanged(QAbstractAxis *newAxis)
314 \since 6.10
315 This signal is emitted whenever the X axis in control changes.
316 The \a newAxis parameter holds the new axis.
317*/
318
319/*!
320 \qmlsignal QAbstractSeries::axisYChanged(QAbstractAxis *newAxis)
321 \since 6.10
322 This signal is emitted whenever the Y axis in control changes.
323 The \a newAxis parameter holds the new axis.
324*/
325
326/*!
327 \qmlsignal QAbstractSeries::zValueChanged(int newDrawOrder)
328 \since 6.10
329 This signal is emitted when the series draw order changes.
330 The \a newAxis parameter specifies the new order.
331*/
332
333/*!
334 \fn void QAbstractSeries::hoverEnter(const QString &seriesName, QPointF position, QPointF value)
335 This signal is emitted when the series hovering starts. The name of the series is in \a seriesName,
336 the mouse/touch position in \a position, and the series value in \a value.
337 \note This signal is only emitted when \l hoverable is set to true.
338 \note For Pie graph, the value represents (angle of position, start angle of hovering slice)
339*/
340
341/*!
342 \fn void QAbstractSeries::hoverExit(const QString &seriesName, QPointF position)
343 This signal is emitted when the series hovering ends. The name of the series is in \a seriesName,
344 and the mouse/touch position in \a position.
345 \note This signal is only emitted when \l hoverable is set to true.
346*/
347
348/*!
349 \fn void QAbstractSeries::hover(const QString &seriesName, QPointF position, QPointF value)
350 This signal is emitted when the series hovering changes. The name of the series is in \a seriesName,
351 the mouse/touch position in \a position, and the series value in \a value.
352 \note This signal is only emitted when \l hoverable is set to true.
353 \note For Pie graph, the value represents (angle of position, start angle of hovering slice)
354*/
355
356/*!
357 \internal
358 \brief Constructs QAbstractSeries object with \a parent.
359*/
360
361Q_LOGGING_CATEGORY(lcSeries2D, "qt.graphs2d.series")
362Q_LOGGING_CATEGORY(lcProperties2D, "qt.graphs2d.series.properties")
363
364QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &dd, QObject *parent)
365 : QObject(dd, parent)
366{}
367
368/*!
369 \brief Virtual destructor for the graph series.
370*/
371QAbstractSeries::~QAbstractSeries()
372{
373 Q_D(QAbstractSeries);
374 if (d->m_graph)
375 d->m_graph->removeSeries(series: this);
376}
377
378QString QAbstractSeries::name() const
379{
380 Q_D(const QAbstractSeries);
381 return d->m_name;
382}
383
384void QAbstractSeries::setName(const QString &name)
385{
386 Q_D(QAbstractSeries);
387 if (name != d->m_name) {
388 d->m_name = name;
389 emit update();
390 emit nameChanged();
391 } else {
392 qCDebug(lcProperties2D,"QAbstractSeries::setName. Name is already set to: %s",
393 qPrintable(name));
394 }
395}
396
397bool QAbstractSeries::isVisible() const
398{
399 Q_D(const QAbstractSeries);
400 return d->m_visible;
401}
402
403void QAbstractSeries::setVisible(bool visible)
404{
405 Q_D(QAbstractSeries);
406 if (visible != d->m_visible) {
407 d->m_visible = visible;
408 emit update();
409 emit visibleChanged();
410 } else {
411 qCDebug(lcProperties2D) << "QAbstractSeries::setVisible. series visibility already set to"
412 << visible;
413 }
414}
415
416bool QAbstractSeries::isSelectable() const
417{
418 Q_D(const QAbstractSeries);
419 return d->m_selectable;
420}
421
422void QAbstractSeries::setSelectable(bool selectable)
423{
424 Q_D(QAbstractSeries);
425 if (selectable != d->m_selectable) {
426 d->m_selectable = selectable;
427 emit update();
428 emit selectableChanged();
429 } else {
430 qCDebug(lcProperties2D) << "QAbstractSeries::setSelectable. Selectable already set to:"
431 << selectable;
432 }
433}
434
435bool QAbstractSeries::isHoverable() const
436{
437 Q_D(const QAbstractSeries);
438 return d->m_hoverable;
439}
440
441void QAbstractSeries::setHoverable(bool hoverable)
442{
443 Q_D(QAbstractSeries);
444 if (hoverable != d->m_hoverable) {
445 d->m_hoverable = hoverable;
446 emit update();
447 emit hoverableChanged();
448 } else {
449 qCDebug(lcProperties2D) << "QAbstractSeries::setHoverable. Hoverable already set to:"
450 << hoverable;
451 }
452}
453
454bool QAbstractSeries::hasLoaded() const
455{
456 Q_D(const QAbstractSeries);
457 return d->m_loaded;
458}
459
460bool QAbstractSeries::isHovered() const
461{
462 Q_D(const QAbstractSeries);
463 return d->m_hovered;
464}
465
466void QAbstractSeries::setHovered(bool enabled)
467{
468 Q_D(QAbstractSeries);
469
470 if (enabled != d->m_hovered) {
471 d->m_hovered = enabled;
472 emit hoveredChanged(hovered: d->m_hovered);
473 }
474}
475
476QAbstractAxis *QAbstractSeries::axisX() const
477{
478 Q_D(const QAbstractSeries);
479 return d->m_axisX;
480}
481
482void QAbstractSeries::setAxisX(QAbstractAxis *newAxisX)
483{
484 Q_D(QAbstractSeries);
485 if (d->m_axisX == newAxisX)
486 return;
487
488 if (d->m_axisX) {
489 disconnect(sender: d->m_axisX, signal: &QAbstractAxis::update, receiver: this, slot: &QAbstractSeries::update);
490
491 if (d->m_graph)
492 d->m_graph->removeAxis(axis: d->m_axisX);
493 }
494
495 if (newAxisX) {
496 if (newAxisX->alignment() != Qt::AlignBottom && newAxisX->alignment() != Qt::AlignTop)
497 newAxisX->setAlignment(Qt::AlignBottom);
498 connect(sender: newAxisX, signal: &QAbstractAxis::update, context: this, slot: &QAbstractSeries::update);
499
500 if (d->m_graph)
501 d->m_graph->addAxis(axis: newAxisX);
502 }
503
504 d->m_axisX = newAxisX;
505 emit update();
506 emit axisXChanged(newAxis: newAxisX);
507}
508
509QAbstractAxis *QAbstractSeries::axisY() const
510{
511 Q_D(const QAbstractSeries);
512 return d->m_axisY;
513}
514
515void QAbstractSeries::setAxisY(QAbstractAxis *newAxisY)
516{
517 Q_D(QAbstractSeries);
518 if (d->m_axisY == newAxisY)
519 return;
520
521 if (d->m_axisY) {
522 disconnect(sender: d->m_axisY, signal: &QAbstractAxis::update, receiver: this, slot: &QAbstractSeries::update);
523
524 if (d->m_graph)
525 d->m_graph->removeAxis(axis: d->m_axisY);
526 }
527
528 if (newAxisY) {
529 if (newAxisY->alignment() != Qt::AlignLeft && newAxisY->alignment() != Qt::AlignRight)
530 newAxisY->setAlignment(Qt::AlignLeft);
531 connect(sender: newAxisY, signal: &QAbstractAxis::update, context: this, slot: &QAbstractSeries::update);
532
533 if (d->m_graph)
534 d->m_graph->addAxis(axis: newAxisY);
535 }
536
537 d->m_axisY = newAxisY;
538 emit update();
539 emit axisYChanged(newAxis: newAxisY);
540}
541
542qreal QAbstractSeries::opacity() const
543{
544 Q_D(const QAbstractSeries);
545 return d->m_opacity;
546}
547
548void QAbstractSeries::setOpacity(qreal opacity)
549{
550 Q_D(QAbstractSeries);
551 if (opacity != d->m_opacity) {
552 d->m_opacity = opacity;
553 emit update();
554 emit opacityChanged();
555 } else {
556 qCDebug(lcProperties2D, "QAbstractSeries::setOpacity. Opacity is already set to: %f",
557 opacity);
558 }
559}
560
561qreal QAbstractSeries::valuesMultiplier() const
562{
563 Q_D(const QAbstractSeries);
564 return d->m_valuesMultiplier;
565}
566
567void QAbstractSeries::setValuesMultiplier(qreal valuesMultiplier)
568{
569 Q_D(QAbstractSeries);
570 valuesMultiplier = std::clamp<qreal>(val: valuesMultiplier, lo: 0.0, hi: 1.0);
571 if (valuesMultiplier != d->m_valuesMultiplier) {
572 d->m_valuesMultiplier = valuesMultiplier;
573 emit update();
574 emit valuesMultiplierChanged();
575 }
576}
577
578int QAbstractSeries::zValue() const
579{
580 Q_D(const QAbstractSeries);
581 return d->m_drawOrder;
582}
583
584void QAbstractSeries::setZValue(int newDrawOrder)
585{
586 Q_D(QAbstractSeries);
587 if (d->m_drawOrder == newDrawOrder)
588 return;
589 d->m_drawOrder = newDrawOrder;
590 emit update();
591 emit zValueChanged(z: newDrawOrder);
592}
593
594/*!
595 \internal
596 Returns the graph that the series belongs to.
597
598 Set automatically when the series is added to the graph,
599 and unset when the series is removed from the graph.
600*/
601QGraphsView *QAbstractSeries::graph() const
602{
603 Q_D(const QAbstractSeries);
604 return d->m_graph;
605}
606
607void QAbstractSeries::setGraph(QGraphsView *graph)
608{
609 Q_D(QAbstractSeries);
610 d->m_graph = graph;
611 if (graph) {
612 switch (type()) {
613 case SeriesType::Bar:
614#ifdef USE_BARGRAPH
615 graph->createBarsRenderer();
616#endif
617 break;
618 case SeriesType::Scatter:
619 case SeriesType::Line:
620 case SeriesType::Spline:
621#ifdef USE_POINTS
622 graph->createPointRenderer();
623#endif
624 break;
625 case SeriesType::Pie:
626#ifdef USE_PIEGRAPH
627 graph->createPieRenderer();
628#endif
629 break;
630 case SeriesType::Area:
631#ifdef USE_AREAGRAPH
632 graph->createAreaRenderer();
633#endif
634 break;
635 default:
636 break;
637 }
638 }
639}
640
641/*!
642 Sets the visibility of the series to \c true.
643
644 \sa setVisible(), isVisible()
645*/
646void QAbstractSeries::show()
647{
648 setVisible(true);
649}
650
651/*!
652 Sets the visibility of the series to \c false.
653
654 \sa setVisible(), isVisible()
655*/
656void QAbstractSeries::hide()
657{
658 setVisible(false);
659}
660
661const QList<QLegendData> QAbstractSeries::legendData() const
662{
663 Q_D(const QAbstractSeries);
664 return d->m_legendData;
665}
666
667QQmlListProperty<QObject> QAbstractSeries::seriesChildren()
668{
669 return QQmlListProperty<QObject>(this, 0, &QAbstractSeriesPrivate::appendSeriesChildren, 0, 0, 0);
670}
671
672void QAbstractSeries::classBegin()
673{
674}
675
676void QAbstractSeries::componentComplete()
677{
678 Q_D(QAbstractSeries);
679 d->m_loaded = true;
680}
681
682///////////////////////////////////////////////////////////////////////////////////////////////////
683
684QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries::SeriesType type)
685 : m_type(type)
686{
687}
688
689QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
690{
691}
692
693void QAbstractSeriesPrivate::setLegendData(const QList<QLegendData> &legendData)
694{
695 if (legendData.data() != m_legendData.data()) {
696 Q_Q(QAbstractSeries);
697 m_legendData = legendData;
698 emit q->legendDataChanged();
699 }
700}
701
702void QAbstractSeriesPrivate::clearLegendData()
703{
704 if (!m_legendData.empty()) {
705 Q_Q(QAbstractSeries);
706 m_legendData.clear();
707 emit q->legendDataChanged();
708 }
709}
710
711void QAbstractSeriesPrivate::appendSeriesChildren(QQmlListProperty<QObject> *list, QObject *element)
712{
713 // Empty implementation; the children are parsed in componentComplete instead
714 Q_UNUSED(list);
715 Q_UNUSED(element);
716}
717QT_END_NAMESPACE
718
719#include "moc_qabstractseries.cpp"
720#include "moc_qabstractseries_p.cpp"
721

source code of qtgraphs/src/graphs2d/qabstractseries.cpp