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