1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCharts/QAbstractSeries>
5#include <private/qabstractseries_p.h>
6#include <private/chartdataset_p.h>
7#include <QtCharts/QChart>
8#include <private/qchart_p.h>
9#include <private/chartitem_p.h>
10#include <private/xydomain_p.h>
11#include <private/xlogydomain_p.h>
12#include <private/logxydomain_p.h>
13#include <private/logxlogydomain_p.h>
14
15QT_BEGIN_NAMESPACE
16
17/*!
18 \class QAbstractSeries
19 \inmodule QtCharts
20 \brief The QAbstractSeries class is a base class for all Qt Chart series.
21
22 Usually, the series type specific inherited classes are used instead of the base class.
23
24 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QAbstractBarSeries
25 \sa QBarSeries, QStackedBarSeries, QPercentBarSeries, QHorizontalBarSeries
26 \sa QHorizontalStackedBarSeries, QHorizontalPercentBarSeries, QPieSeries
27*/
28/*!
29 \qmltype AbstractSeries
30 \instantiates QAbstractSeries
31 \inqmlmodule QtCharts
32
33 \brief Base type for all Qt Chart series types.
34
35 This type cannot be instantiated directly. Instead, one of the following derived types
36 should be used to create a series: LineSeries, AreaSeries, BarSeries, StackedBarSeries,
37 PercentBarSeries, HorizontalBarSeries, HorizontalStackedBarSeries, HorizontalPercentBarSeries,
38 PieSeries, ScatterSeries, SplineSeries, BoxPlotSeries, or CandlestickSeries.
39*/
40
41/*!
42 \enum QAbstractSeries::SeriesType
43
44 This enum describes the type of the series.
45
46 \value SeriesTypeLine A line chart.
47 \value SeriesTypeArea An area chart.
48 \value SeriesTypeBar A vertical bar chart.
49 \value SeriesTypeStackedBar A vertical stacked bar chart.
50 \value SeriesTypePercentBar A vertical percent bar chart.
51 \value SeriesTypePie A pie chart.
52 \value SeriesTypeScatter A scatter chart.
53 \value SeriesTypeSpline A spline chart.
54 \value SeriesTypeHorizontalBar A horizontal bar chart.
55 \value SeriesTypeHorizontalStackedBar A horizontal stacked bar chart.
56 \value SeriesTypeHorizontalPercentBar A horizontal percent bar chart.
57 \value SeriesTypeBoxPlot A box plot chart.
58 \value SeriesTypeCandlestick A candlestick chart.
59*/
60
61/*!
62 \property QAbstractSeries::type
63 \brief The type of the series.
64*/
65/*!
66 \qmlproperty enumeration AbstractSeries::type
67
68 The type of the series.
69
70 \value AbstractSeries.SeriesTypeLine A line chart.
71 \value AbstractSeries.SeriesTypeArea An area chart.
72 \value AbstractSeries.SeriesTypeBar A vertical bar chart.
73 \value AbstractSeries.SeriesTypeStackedBar A vertical stacked bar chart.
74 \value AbstractSeries.SeriesTypePercentBar A vertical percent bar chart.
75 \value AbstractSeries.SeriesTypePie A pie chart.
76 \value AbstractSeries.SeriesTypeScatter A scatter chart.
77 \value AbstractSeries.SeriesTypeSpline A spline chart.
78 \value AbstractSeries.SeriesTypeHorizontalBar A horizontal bar chart.
79 \value AbstractSeries.SeriesTypeHorizontalStackedBar A horizontal stacked bar chart.
80 \value AbstractSeries.SeriesTypeHorizontalPercentBar A horizontal percent bar chart.
81 \value AbstractSeries.SeriesTypeBoxPlot A box plot chart.
82 \value AbstractSeries.SeriesTypeCandlestick A candlestick chart.
83*/
84
85/*!
86 \property QAbstractSeries::name
87 \brief The name of the series.
88
89 The name is displayed in the legend for the series and it supports HTML formatting.
90*/
91/*!
92 \qmlproperty string AbstractSeries::name
93 The name of the series. It is displayed in the legend for the series and it
94 supports HTML formatting.
95*/
96
97/*!
98 \fn void QAbstractSeries::nameChanged()
99 This signal is emitted when the series name changes.
100*/
101
102/*!
103 \property QAbstractSeries::visible
104 \brief whether the series is visible or not.
105
106 By default, \c true.
107*/
108/*!
109 \qmlproperty bool AbstractSeries::visible
110 Visibility of the series. By default, \c true.
111*/
112
113/*!
114 \fn void QAbstractSeries::visibleChanged()
115 This signal is emitted when the series visibility changes.
116*/
117
118/*!
119 \property QAbstractSeries::opacity
120 \brief The opacity of the series.
121
122 By default, the opacity is 1.0. The valid values range from 0.0 (transparent) to 1.0 (opaque).
123*/
124/*!
125 \qmlproperty real AbstractSeries::opacity
126 The opacity of the series. By default, the opacity is 1.0.
127 The valid values range from 0.0 (transparent) to 1.0 (opaque).
128*/
129
130/*!
131 \fn void QAbstractSeries::opacityChanged()
132 This signal is emitted when the opacity of the series changes.
133*/
134
135/*!
136 \property QAbstractSeries::useOpenGL
137 \brief Specifies whether or not drawing the series is accelerated by using OpenGL.
138
139 Acceleration using OpenGL is supported only for QLineSeries and QScatterSeries.
140 A line series used as an edge series for QAreaSeries cannot use OpenGL acceleration.
141 When a chart contains any series that are drawn with OpenGL, a transparent QOpenGLWidget
142 is created on top of the chart plot area. The accelerated series are not drawn on the underlying
143 QGraphicsView, but are instead drawn on the created QOpenGLWidget.
144
145 Performance gained from using OpenGL to accelerate series drawing depends on the underlying
146 hardware, but in most cases it is significant. For example, on a standard desktop computer,
147 enabling OpenGL acceleration for a series typically allows rendering at least a hundred times
148 more points without reduction on the frame rate.
149 Chart size also has less effect on the frame rate.
150
151 The OpenGL acceleration of series drawing is meant for use cases that need fast drawing of
152 large numbers of points. It is optimized for efficiency, and therefore the series using
153 it lack support for many features available to non-accelerated series:
154
155 \list
156 \li Series animations are not supported for accelerated series.
157 \li Point labels are not supported for accelerated series.
158 \li Pen styles, marker shapes and light markers are ignored for accelerated series.
159 Only solid lines and plain scatter dots are supported.
160 The scatter dots may be circular or rectangular, depending on the underlying graphics
161 hardware and drivers.
162 \li Polar charts do not support accelerated series.
163 \li Enabling chart drop shadow or using transparent chart background color is not recommended
164 when using accelerated series, as that can slow the frame rate down significantly.
165 \endlist
166
167 These additional restrictions stem from the fact that the accelerated series is drawn on a
168 separate widget on top of the chart:
169
170 \list
171 \li If you draw any graphics items on top of a chart containing an accelerated series,
172 the accelerated series is drawn over those items.
173 \li To enable QOpenGLWidget to be partially transparent, it needs to be stacked on top of
174 all other widgets. This means you cannot have other widgets partially covering the
175 chart when using accelerated series.
176 \li Accelerated series are not supported for use cases where the graphics scene has more than
177 one graphics view attached to it.
178 \li Accelerated series are not supported for use cases where the chart has non-default geometry.
179 For example, adding transforms to the graphics view causes the accelerated series to
180 be drawn in an incorrect position related to the chart.
181 \endlist
182
183 The default value is \c{false}.
184*/
185/*!
186 \qmlproperty bool AbstractSeries::useOpenGL
187 Specifies whether or not the series is drawn with OpenGL.
188
189 Acceleration using OpenGL is supported only for LineSeries and ScatterSeries.
190 A line series used as an edge series for a AreaSeries cannot use OpenGL acceleration.
191 When a chart contains any series that are drawn with OpenGL, an additional transparent child
192 node is created for the ChartView node. The accelerated series are not drawn on the
193 ChartView node, but are instead drawn on the child node.
194
195 Performance gained from using OpenGL to accelerate series drawing depends on the underlying
196 hardware, but in most cases it is significant. For example, on a standard desktop computer,
197 enabling OpenGL acceleration for a series typically allows rendering at least hundred times
198 more points without reduction on the frame rate.
199 Chart size also has less effect on the frame rate.
200 The biggest performance sink when rendering ChartView is rendering and uploading the underlying
201 chart texture. If the underlying chart itself is not changing rapidly, significant extra
202 performance is gained from not needing to regenerate the chart texture for each frame.
203
204 The OpenGL acceleration of series drawing is meant for use cases that need fast drawing of
205 large numbers of points. It is optimized for efficiency, and therefore the series using
206 it lack support for many features available to non-accelerated series:
207
208 \list
209 \li Series animations are not supported for accelerated series.
210 \li Point labels are not supported for accelerated series.
211 \li Pen styles, marker shapes and light markers are ignored for accelerated series.
212 Only solid lines and plain scatter dots are supported.
213 The scatter dots may be circular or rectangular, depending on the underlying graphics
214 hardware and drivers.
215 \li Polar charts do not support accelerated series.
216 \li Mouse events for series are reported asynchronously.
217 \li Enabling chart drop shadow or using transparent chart background color is not recommended
218 when using accelerated series, as that can slow the frame rate down significantly.
219 \endlist
220
221 The default value is \c{false}.
222*/
223
224/*!
225 \fn void QAbstractSeries::useOpenGLChanged()
226 This signal is emitted when accelerating the drawing of the series by using OpenGL
227 is enabled or disabled.
228*/
229
230/*!
231 \internal
232 \brief Constructs QAbstractSeries object with \a parent.
233*/
234QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
235 QObject(parent),
236 d_ptr(&d)
237{
238}
239
240/*!
241 \brief Virtual destructor for the chart series.
242*/
243QAbstractSeries::~QAbstractSeries()
244{
245 if (d_ptr->m_chart)
246 qFatal(msg: "Series still bound to a chart when destroyed!");
247}
248
249void QAbstractSeries::setName(const QString &name)
250{
251 if (name != d_ptr->m_name) {
252 d_ptr->m_name = name;
253 emit nameChanged();
254 }
255}
256
257QString QAbstractSeries::name() const
258{
259 return d_ptr->m_name;
260}
261
262void QAbstractSeries::setVisible(bool visible)
263{
264 if (visible != d_ptr->m_visible) {
265 d_ptr->m_visible = visible;
266 emit visibleChanged();
267 }
268}
269
270bool QAbstractSeries::isVisible() const
271{
272 return d_ptr->m_visible;
273}
274
275qreal QAbstractSeries::opacity() const
276{
277 return d_ptr->m_opacity;
278}
279
280void QAbstractSeries::setOpacity(qreal opacity)
281{
282 if (opacity != d_ptr->m_opacity) {
283 d_ptr->m_opacity = opacity;
284 emit opacityChanged();
285 }
286}
287
288void QAbstractSeries::setUseOpenGL(bool enable)
289{
290#ifdef QT_NO_OPENGL
291 Q_UNUSED(enable);
292#else
293 bool polarChart = d_ptr->m_chart && d_ptr->m_chart->chartType() == QChart::ChartTypePolar;
294 bool supportedSeries = (type() == SeriesTypeLine || type() == SeriesTypeScatter);
295 if ((!enable || !d_ptr->m_blockOpenGL)
296 && supportedSeries
297 && enable != d_ptr->m_useOpenGL
298 && (!enable || !polarChart)) {
299 d_ptr->m_useOpenGL = enable;
300 emit useOpenGLChanged();
301 }
302#endif
303}
304
305bool QAbstractSeries::useOpenGL() const
306{
307 return d_ptr->m_useOpenGL;
308}
309
310/*!
311 Returns the chart that the series belongs to.
312
313 Set automatically when the series is added to the chart,
314 and unset when the series is removed from the chart.
315*/
316QChart *QAbstractSeries::chart() const
317{
318 return d_ptr->m_chart;
319}
320
321/*!
322 Sets the visibility of the series to \c true.
323
324 \sa setVisible(), isVisible()
325*/
326void QAbstractSeries::show()
327{
328 setVisible(true);
329}
330
331/*!
332 Sets the visibility of the series to \c false.
333
334 \sa setVisible(), isVisible()
335*/
336void QAbstractSeries::hide()
337{
338 setVisible(false);
339}
340
341/*!
342 Attaches the axis specified by \a axis to the series.
343
344 Returns \c true if the axis was attached successfully, \c false otherwise.
345
346 \note If multiple axes of the same orientation are attached to the same series,
347 they will have the same minimum and maximum values.
348
349 \sa QChart::addAxis(), QChart::createDefaultAxes()
350 */
351bool QAbstractSeries::attachAxis(QAbstractAxis* axis)
352{
353 if (d_ptr->m_chart)
354 return d_ptr->m_chart->d_ptr->m_dataset->attachAxis(series: this, axis);
355
356 qWarning(msg: "Series not in the chart. Please addSeries to chart first.");
357 return false;
358}
359
360/*!
361 Detaches the axis specified by \a axis from the series.
362
363 Returns \c true if the axis was detached successfully, \c false otherwise.
364
365 \sa QChart::removeAxis()
366 */
367bool QAbstractSeries::detachAxis(QAbstractAxis* axis)
368{
369 if (d_ptr->m_chart)
370 return d_ptr->m_chart->d_ptr->m_dataset->detachAxis(series: this, axis);
371
372 qWarning(msg: "Series not in the chart. Please addSeries to chart first.");
373 return false;
374}
375
376/*!
377 Returns the list of axes attached to the series. Usually, an x-axis and a y-axis
378 are attached to a series, except for QPieSeries, which does not have any axes attached.
379 \sa attachAxis(), detachAxis()
380 */
381QList<QAbstractAxis*> QAbstractSeries::attachedAxes()
382{
383 return d_ptr->m_axes;
384}
385
386///////////////////////////////////////////////////////////////////////////////////////////////////
387
388QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries *q)
389 : q_ptr(q),
390 m_chart(nullptr),
391 m_item(nullptr),
392 m_domain(new XYDomain()),
393 m_visible(true),
394 m_opacity(1.0),
395 m_useOpenGL(false),
396 m_blockOpenGL(false)
397{
398}
399
400QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
401{
402}
403
404void QAbstractSeriesPrivate::setDomain(AbstractDomain* domain)
405{
406 Q_ASSERT(domain);
407 if(m_domain.data()!=domain) {
408 if (m_item)
409 QObject::disconnect(sender: m_domain.data(), SIGNAL(updated()), receiver: m_item.get(), SLOT(handleDomainUpdated()));
410 m_domain.reset(other: domain);
411 if (m_item) {
412 QObject::connect(sender: m_domain.data(), SIGNAL(updated()), receiver: m_item.get(), SLOT(handleDomainUpdated()));
413 m_item->handleDomainUpdated();
414 }
415 }
416}
417
418void QAbstractSeriesPrivate::setPresenter(ChartPresenter *presenter)
419{
420 m_presenter = presenter;
421}
422
423ChartPresenter *QAbstractSeriesPrivate::presenter() const
424{
425 return m_presenter;
426}
427
428void QAbstractSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
429{
430 Q_ASSERT(m_item);
431 Q_UNUSED(parent);
432 QObject::connect(sender: m_domain.data(), SIGNAL(updated()), receiver: m_item.get(), SLOT(handleDomainUpdated()));
433}
434
435void QAbstractSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
436 QEasingCurve &curve)
437{
438 Q_UNUSED(options);
439 Q_UNUSED(duration);
440 Q_UNUSED(curve);
441}
442
443// This function can be used to explicitly block OpenGL use from some otherwise supported series,
444// such as the line series used as edge series of an area series.
445void QAbstractSeriesPrivate::setBlockOpenGL(bool enable)
446{
447 m_blockOpenGL = enable;
448 if (enable)
449 q_ptr->setUseOpenGL(false);
450}
451
452QT_END_NAMESPACE
453
454#include "moc_qabstractseries.cpp"
455#include "moc_qabstractseries_p.cpp"
456

source code of qtcharts/src/charts/qabstractseries.cpp