##// END OF EJS Templates
Clear chart image to transparent when necessary....
Miikka Heikkinen -
r2850:57e4c71e5532
parent child
Show More
@@ -1,500 +1,500
1 1 /******************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd.
4 4 ** Contact: http://www.qt.io/licensing/
5 5 **
6 6 ** This file is part of the Qt Charts module.
7 7 **
8 8 ** $QT_BEGIN_LICENSE:COMM$
9 9 **
10 10 ** Commercial License Usage
11 11 ** Licensees holding valid commercial Qt licenses may use this file in
12 12 ** accordance with the commercial license agreement provided with the
13 13 ** Software or, alternatively, in accordance with the terms contained in
14 14 ** a written agreement between you and The Qt Company. For licensing terms
15 15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 16 ** information use the contact form at http://www.qt.io/contact-us.
17 17 **
18 18 ** $QT_END_LICENSE$
19 19 **
20 20 ******************************************************************************/
21 21
22 22 #include <QtCharts/QAbstractSeries>
23 23 #include <private/qabstractseries_p.h>
24 24 #include <private/chartdataset_p.h>
25 25 #include <QtCharts/QChart>
26 26 #include <private/qchart_p.h>
27 27 #include <private/chartitem_p.h>
28 28 #include <private/xydomain_p.h>
29 29 #include <private/xlogydomain_p.h>
30 30 #include <private/logxydomain_p.h>
31 31 #include <private/logxlogydomain_p.h>
32 32
33 33 QT_CHARTS_BEGIN_NAMESPACE
34 34
35 35 /*!
36 36 \class QAbstractSeries
37 37 \inmodule Qt Charts
38 38 \brief Base class for all Qt Chart series.
39 39
40 40 Usually you use the series type specific inherited classes instead of the base class.
41 41 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QAbstractBarSeries, QStackedBarSeries,
42 42 QPercentBarSeries, QPieSeries
43 43 */
44 44 /*!
45 45 \qmltype AbstractSeries
46 46 \instantiates QAbstractSeries
47 47 \inqmlmodule QtCharts
48 48
49 49 \brief Base class for all Qt Chart series.
50 50
51 51 AbstractSeries is the base class for all series.
52 52 The class cannot be instantiated by the user.
53 53 */
54 54
55 55 /*!
56 56 \enum QAbstractSeries::SeriesType
57 57
58 58 The type of the series object.
59 59
60 60 \value SeriesTypeLine
61 61 \value SeriesTypeArea
62 62 \value SeriesTypeBar
63 63 \value SeriesTypeStackedBar
64 64 \value SeriesTypePercentBar
65 65 \value SeriesTypePie
66 66 \value SeriesTypeScatter
67 67 \value SeriesTypeSpline
68 68 \value SeriesTypeHorizontalBar
69 69 \value SeriesTypeHorizontalStackedBar
70 70 \value SeriesTypeHorizontalPercentBar
71 71 \value SeriesTypeBoxPlot
72 72 */
73 73
74 74 /*!
75 75 \property QAbstractSeries::type
76 76 The type of the series.
77 77 */
78 78 /*!
79 79 \qmlproperty ChartView.SeriesType AbstractSeries::type
80 80 The type of the series.
81 81 */
82 82
83 83 /*!
84 84 \property QAbstractSeries::name
85 85 \brief name of the series property. The name is shown in legend for series and supports html formatting.
86 86 */
87 87 /*!
88 88 \qmlproperty string AbstractSeries::name
89 89 Name of the series. The name is shown in legend for series and supports html formatting.
90 90 */
91 91
92 92 /*!
93 93 \fn void QAbstractSeries::nameChanged()
94 94 This signal is emitted when the series name changes.
95 95 */
96 96 /*!
97 97 \qmlsignal AbstractSeries::onNameChanged()
98 98 This signal is emitted when the series name changes.
99 99 */
100 100
101 101 /*!
102 102 \property QAbstractSeries::visible
103 103 \brief whether the series is visible or not; true by default.
104 104 */
105 105 /*!
106 106 \qmlproperty bool AbstractSeries::visible
107 107 Visibility of the series. True by default.
108 108 */
109 109
110 110 /*!
111 111 \fn void QAbstractSeries::visibleChanged()
112 112 Emitted when the series visibility changes.
113 113 */
114 114 /*!
115 115 \qmlsignal AbstractSeries::onVisibleChanged()
116 116 Emitted when the series visibility changes.
117 117 */
118 118
119 119 /*!
120 120 \property QAbstractSeries::opacity
121 121 \brief The opacity of the series.
122 122
123 123 By default the opacity is 1.0. The valid values range from 0.0 (transparent) to 1.0 (opaque).
124 124 */
125 125 /*!
126 126 \qmlproperty real AbstractSeries::opacity
127 127 The opacity of the series. By default the opacity is 1.0.
128 128 The valid values range from 0.0 (transparent) to 1.0 (opaque).
129 129 */
130 130
131 131 /*!
132 132 \fn void QAbstractSeries::opacityChanged()
133 133 Emitted when the opacity of the series changes.
134 134 */
135 135 /*!
136 136 \qmlsignal AbstractSeries::onOpacityChanged()
137 137 Emitted when the opacity of the series changes.
138 138 */
139 139
140 140 /*!
141 141 \property QAbstractSeries::useOpenGL
142 142 \brief Specifies whether or not the series drawing is accelerated with OpenGL.
143 143
144 144 Drawing series with OpenGL is supported only for QLineSeries and QScatterSeries.
145 145 Line series used as edge series for a QAreaSeries cannot use OpenGL acceleration.
146 146 When a chart contains any series that are drawn with OpenGL, a transparent QOpenGLWidget
147 147 is created on top of the chart plot area. The accelerated series are not drawn on the underlying
148 148 QGraphicsView, but are instead drawn on the created QOpenGLWidget.
149 149
150 150 Performance gained from using OpenGL to accelerate series drawing depends on the underlying
151 151 hardware, but in most cases it is significant. For example, on a standard desktop computer,
152 152 enabling OpenGL acceleration for a series typically allows rendering at least hundred times
153 153 more points without reduction on the frame rate.
154 154 Chart size also has less effect on the frame rate.
155 155
156 156 The OpenGL acceleration of series drawing is meant for use cases that need fast drawing of
157 157 large numbers of points. It is optimized for efficiency, and therefore the series using
158 158 it lack support for many features available to non-accelerated series:
159 159
160 160 \list
161 161 \li Series animations are not supported for accelerated series.
162 162 \li Antialiasing is not supported for accelerated series.
163 163 \li Point labels are not supported for accelerated series.
164 164 \li Pen styles and marker shapes are ignored for accelerated series.
165 165 Only solid lines and plain scatter dots are supported.
166 166 The scatter dots may be circular or rectangular, depending on the underlying graphics
167 167 hardware and drivers.
168 168 \li Polar charts do not support accelerated series.
169 169 \li Mouse events are not supported for accelerated series.
170 \li Enabling chart drop shadow is not recommended when using accelerated series,
171 as that can slow the frame rate down significantly.
170 \li Enabling chart drop shadow or using transparent chart background color is not recommended
171 when using accelerated series, as that can slow the frame rate down significantly.
172 172 \endlist
173 173
174 174 These additional restrictions stem from the fact that the accelerated series is drawn on a
175 175 separate widget on top of the chart:
176 176
177 177 \list
178 178 \li If you draw any graphics items on top of a chart containing an accelerated series,
179 179 the accelerated series is drawn over those items.
180 180 \li To enable QOpenGLWidget to be partially transparent, it needs to be stacked on top of
181 181 all other widgets. This means you cannot have other widgets partially covering the
182 182 chart when using accelerated series.
183 183 \li Accelerated series are not supported for use cases where the graphics scene has more than
184 184 one graphics view attached to it.
185 185 \li Accelerated series are not supported for use cases where the chart doesn't fill the entire
186 186 graphics view or has non-default geometry. For example, scrolling the view with scroll
187 187 bars or adding transformations to the graphics view cause the accelerated series to
188 188 be drawn in incorrect position related to the chart.
189 189 \endlist
190 190
191 191 The default value is \c{false}.
192 192 */
193 193 /*!
194 194 \qmlproperty bool AbstractSeries::useOpenGL
195 195 Specifies whether or not the series is drawn with OpenGL.
196 196
197 197 Drawing series with OpenGL is supported only for LineSeries and ScatterSeries.
198 198 Line series used as edge series for a AreaSeries cannot use OpenGL acceleration.
199 199 When a chart contains any series that are drawn with OpenGL, an additional transparent child
200 200 node is created for the ChartView node. The accelerated series are not drawn on the
201 201 ChartView node, but are instead drawn on the child node.
202 202
203 203 Performance gained from using OpenGL to accelerate series drawing depends on the underlying
204 204 hardware, but in most cases it is significant. For example, on a standard desktop computer,
205 205 enabling OpenGL acceleration for a series typically allows rendering at least hundred times
206 206 more points without reduction on the frame rate.
207 207 Chart size also has less effect on the frame rate.
208 208 The biggest performance sink when rendering ChartView is rendering and uploading the underlying
209 209 chart texture. If the underlying chart itself is not changing rapidly, significant extra
210 210 performance is gained from not needing to regenerate the chart texture for each frame.
211 211
212 212 The OpenGL acceleration of series drawing is meant for use cases that need fast drawing of
213 213 large numbers of points. It is optimized for efficiency, and therefore the series using
214 214 it lack support for many features available to non-accelerated series:
215 215
216 216 \list
217 217 \li Series animations are not supported for accelerated series.
218 218 \li Antialiasing is not supported for accelerated series.
219 219 \li Point labels are not supported for accelerated series.
220 220 \li Marker shapes are ignored for accelerated series.
221 221 Only plain scatter dots are supported.
222 222 The scatter dots may be circular or rectangular, depending on the underlying graphics
223 223 hardware and drivers.
224 224 \li Polar charts do not support accelerated series.
225 225 \li Mouse events are not supported for accelerated series.
226 \li Enabling chart drop shadow is not recommended when using accelerated series,
227 as that can slow the frame rate down significantly.
226 \li Enabling chart drop shadow or using transparent chart background color is not recommended
227 when using accelerated series, as that can slow the frame rate down significantly.
228 228 \endlist
229 229
230 230 The default value is \c{false}.
231 231 */
232 232
233 233 /*!
234 234 \fn void QAbstractSeries::useOpenGLChanged()
235 235 Emitted when the useOpenGL property value changes.
236 236 */
237 237 /*!
238 238 \qmlsignal AbstractSeries::onUseOpenGLChanged()
239 239 Emitted when the useOpenGL property value changes.
240 240 */
241 241
242 242 /*!
243 243 \internal
244 244 \brief Constructs QAbstractSeries object with \a parent.
245 245 */
246 246 QAbstractSeries::QAbstractSeries(QAbstractSeriesPrivate &d, QObject *parent) :
247 247 QObject(parent),
248 248 d_ptr(&d)
249 249 {
250 250 }
251 251
252 252 /*!
253 253 \brief Virtual destructor for the chart series.
254 254 */
255 255 QAbstractSeries::~QAbstractSeries()
256 256 {
257 257 if (d_ptr->m_chart)
258 258 qFatal("Series still bound to a chart when destroyed!");
259 259 }
260 260
261 261 void QAbstractSeries::setName(const QString &name)
262 262 {
263 263 if (name != d_ptr->m_name) {
264 264 d_ptr->m_name = name;
265 265 emit nameChanged();
266 266 }
267 267 }
268 268
269 269 QString QAbstractSeries::name() const
270 270 {
271 271 return d_ptr->m_name;
272 272 }
273 273
274 274 void QAbstractSeries::setVisible(bool visible)
275 275 {
276 276 if (visible != d_ptr->m_visible) {
277 277 d_ptr->m_visible = visible;
278 278 emit visibleChanged();
279 279 }
280 280 }
281 281
282 282 bool QAbstractSeries::isVisible() const
283 283 {
284 284 return d_ptr->m_visible;
285 285 }
286 286
287 287 qreal QAbstractSeries::opacity() const
288 288 {
289 289 return d_ptr->m_opacity;
290 290 }
291 291
292 292 void QAbstractSeries::setOpacity(qreal opacity)
293 293 {
294 294 if (opacity != d_ptr->m_opacity) {
295 295 d_ptr->m_opacity = opacity;
296 296 emit opacityChanged();
297 297 }
298 298 }
299 299
300 300 void QAbstractSeries::setUseOpenGL(bool enable)
301 301 {
302 302 #ifdef QT_NO_OPENGL
303 303 Q_UNUSED(enable)
304 304 #else
305 305 bool polarChart = d_ptr->m_chart && d_ptr->m_chart->chartType() == QChart::ChartTypePolar;
306 306 bool supportedSeries = (type() == SeriesTypeLine || type() == SeriesTypeScatter);
307 307 if ((!enable || !d_ptr->m_blockOpenGL)
308 308 && supportedSeries
309 309 && enable != d_ptr->m_useOpenGL
310 310 && (!enable || !polarChart)) {
311 311 d_ptr->m_useOpenGL = enable;
312 312 emit useOpenGLChanged();
313 313 }
314 314 #endif
315 315 }
316 316
317 317 bool QAbstractSeries::useOpenGL() const
318 318 {
319 319 return d_ptr->m_useOpenGL;
320 320 }
321 321
322 322 /*!
323 323 \brief Returns the chart where series belongs to.
324 324
325 325 Set automatically when the series is added to the chart
326 326 and unset when the series is removed from the chart.
327 327 */
328 328 QChart *QAbstractSeries::chart() const
329 329 {
330 330 return d_ptr->m_chart;
331 331 }
332 332
333 333 /*!
334 334 \brief Sets the visibility of the series to true.
335 335
336 336 \sa setVisible(), isVisible()
337 337 */
338 338 void QAbstractSeries::show()
339 339 {
340 340 setVisible(true);
341 341 }
342 342
343 343 /*!
344 344 \brief Sets the visibility of the series to false.
345 345
346 346 \sa setVisible(), isVisible()
347 347 */
348 348 void QAbstractSeries::hide()
349 349 {
350 350 setVisible(false);
351 351 }
352 352
353 353 /*!
354 354 Attach \a axis to the series.
355 355 \return true if the axis was attached successfully, false otherwise.
356 356 \note If multiple axes of same orientation are attached to same series,
357 357 they will have same min/max ranges.
358 358 \sa QChart::addAxis(), QChart::createDefaultAxes()
359 359 */
360 360 bool QAbstractSeries::attachAxis(QAbstractAxis* axis)
361 361 {
362 362 if(d_ptr->m_chart) {
363 363 return d_ptr->m_chart->d_ptr->m_dataset->attachAxis(this, axis);
364 364 } else {
365 365 qWarning()<<"Series not in the chart. Please addSeries to chart first.";
366 366 return false;
367 367 }
368 368 }
369 369
370 370 /*!
371 371 Detach \a axis from the series.
372 372 \return true if the axis was detached successfully, false otherwise.
373 373 \sa QChart::removeAxis()
374 374 */
375 375 bool QAbstractSeries::detachAxis(QAbstractAxis* axis)
376 376 {
377 377 if(d_ptr->m_chart) {
378 378 return d_ptr->m_chart->d_ptr->m_dataset->detachAxis(this, axis);
379 379 }
380 380 else {
381 381 qWarning()<<"Series not in the chart. Please addSeries to chart first.";
382 382 return false;
383 383 }
384 384 }
385 385
386 386 /*!
387 387 Returns the list of axes attached to the series. Usually there is an x-axis and a y-axis attached to a series, except
388 388 in case of a QPieSeries, which does not have any axes attached.
389 389 \sa attachAxis(), detachAxis()
390 390 */
391 391 QList<QAbstractAxis*> QAbstractSeries::attachedAxes()
392 392 {
393 393 return d_ptr->m_axes;
394 394 }
395 395
396 396 ///////////////////////////////////////////////////////////////////////////////////////////////////
397 397
398 398 QAbstractSeriesPrivate::QAbstractSeriesPrivate(QAbstractSeries *q)
399 399 : q_ptr(q),
400 400 m_chart(0),
401 401 m_item(0),
402 402 m_domain(new XYDomain()),
403 403 m_visible(true),
404 404 m_opacity(1.0),
405 405 m_useOpenGL(false),
406 406 m_blockOpenGL(false)
407 407 {
408 408 }
409 409
410 410 QAbstractSeriesPrivate::~QAbstractSeriesPrivate()
411 411 {
412 412 }
413 413
414 414 void QAbstractSeriesPrivate::setDomain(AbstractDomain* domain)
415 415 {
416 416 Q_ASSERT(domain);
417 417 if(m_domain.data()!=domain) {
418 418 if(!m_item.isNull()) QObject::disconnect(m_domain.data(), SIGNAL(updated()), m_item.data(), SLOT(handleDomainUpdated()));
419 419 m_domain.reset(domain);
420 420 if(!m_item.isNull()) {
421 421 QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
422 422 m_item->handleDomainUpdated();
423 423 }
424 424 }
425 425 }
426 426
427 427 void QAbstractSeriesPrivate::setPresenter(ChartPresenter *presenter)
428 428 {
429 429 m_presenter = presenter;
430 430 }
431 431
432 432 ChartPresenter *QAbstractSeriesPrivate::presenter() const
433 433 {
434 434 return m_presenter;
435 435 }
436 436
437 437 void QAbstractSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
438 438 {
439 439 Q_ASSERT(!m_item.isNull());
440 440 Q_UNUSED(parent);
441 441 QObject::connect(m_domain.data(), SIGNAL(updated()),m_item.data(), SLOT(handleDomainUpdated()));
442 442 }
443 443
444 444 void QAbstractSeriesPrivate::initializeAnimations(QChart::AnimationOptions options, int duration,
445 445 QEasingCurve &curve)
446 446 {
447 447 Q_UNUSED(options);
448 448 Q_UNUSED(duration);
449 449 Q_UNUSED(curve);
450 450 }
451 451
452 452 bool QAbstractSeriesPrivate::reverseXAxis()
453 453 {
454 454 bool reverseXAxis = false;
455 455 if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
456 456 int i = 0;
457 457 while (i < m_axes.size()) {
458 458 if (m_axes.at(i)->orientation() == Qt::Horizontal && m_axes.at(i)->isReverse()) {
459 459 reverseXAxis = true;
460 460 break;
461 461 }
462 462 i++;
463 463 }
464 464 }
465 465
466 466 return reverseXAxis;
467 467 }
468 468
469 469 bool QAbstractSeriesPrivate::reverseYAxis()
470 470 {
471 471 bool reverseYAxis = false;
472 472 if (m_axes.size() != 0 && !(m_chart->chartType() == QChart::ChartTypePolar)) {
473 473 int i = 0;
474 474 while (i < m_axes.size()) {
475 475 if (m_axes.at(i)->orientation() == Qt::Vertical && m_axes.at(i)->isReverse()) {
476 476 reverseYAxis = true;
477 477 break;
478 478 }
479 479 i++;
480 480 }
481 481 }
482 482
483 483 return reverseYAxis;
484 484 }
485 485
486 486 // This function can be used to explicitly block OpenGL use from some otherwise supported series,
487 487 // such as the line series used as edge series of an area series.
488 488 void QAbstractSeriesPrivate::setBlockOpenGL(bool enable)
489 489 {
490 490 m_blockOpenGL = enable;
491 491 if (enable)
492 492 q_ptr->setUseOpenGL(false);
493 493 }
494 494
495 495 #include "moc_qabstractseries.cpp"
496 496 #include "moc_qabstractseries_p.cpp"
497 497
498 498 QT_CHARTS_END_NAMESPACE
499 499
500 500
@@ -1,1229 +1,1240
1 1 /******************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd.
4 4 ** Contact: http://www.qt.io/licensing/
5 5 **
6 6 ** This file is part of the Qt Charts module.
7 7 **
8 8 ** $QT_BEGIN_LICENSE:COMM$
9 9 **
10 10 ** Commercial License Usage
11 11 ** Licensees holding valid commercial Qt licenses may use this file in
12 12 ** accordance with the commercial license agreement provided with the
13 13 ** Software or, alternatively, in accordance with the terms contained in
14 14 ** a written agreement between you and The Qt Company. For licensing terms
15 15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 16 ** information use the contact form at http://www.qt.io/contact-us.
17 17 **
18 18 ** $QT_END_LICENSE$
19 19 **
20 20 ******************************************************************************/
21 21
22 22 #include "declarativechart.h"
23 23 #include <QtGui/QPainter>
24 24 #include "declarativelineseries.h"
25 25 #include "declarativeareaseries.h"
26 26 #include "declarativebarseries.h"
27 27 #include "declarativepieseries.h"
28 28 #include "declarativesplineseries.h"
29 29 #include "declarativeboxplotseries.h"
30 30 #include "declarativescatterseries.h"
31 31 #include "declarativechartnode.h"
32 32 #include "declarativerendernode.h"
33 33 #include <QtCharts/QBarCategoryAxis>
34 34 #include <QtCharts/QValueAxis>
35 35 #include <QtCharts/QLogValueAxis>
36 36 #include <QtCharts/QCategoryAxis>
37 37 #include <private/qabstractseries_p.h>
38 38 #include "declarativemargins.h"
39 39 #include <private/chartdataset_p.h>
40 40 #include "declarativeaxes.h"
41 41 #include <private/qchart_p.h>
42 42 #include <private/chartpresenter_p.h>
43 43 #include <QtCharts/QPolarChart>
44 44
45 45 #ifndef QT_ON_ARM
46 46 #include <QtCharts/QDateTimeAxis>
47 47 #endif
48 48
49 49 #include <QtWidgets/QGraphicsSceneMouseEvent>
50 50 #include <QtWidgets/QGraphicsSceneHoverEvent>
51 51 #include <QtWidgets/QApplication>
52 52 #include <QtCore/QTimer>
53 53 #include <QtCore/QThread>
54 54
55 55 QT_CHARTS_BEGIN_NAMESPACE
56 56
57 57 /*!
58 58 \qmltype ChartView
59 59 \instantiates DeclarativeChart
60 60 \inqmlmodule QtCharts
61 61
62 62 \brief Chart element.
63 63
64 64 ChartView element is the parent that is responsible for showing different chart series types.
65 65
66 66 The following QML shows how to create a simple chart with one pie series:
67 67 \snippet qmlpiechart/qml/qmlpiechart/main.qml 1
68 68 \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
69 69 \snippet qmlpiechart/qml/qmlpiechart/main.qml 3
70 70
71 71 \beginfloatleft
72 72 \image examples_qmlpiechart.png
73 73 \endfloat
74 74 \clearfloat
75 75 */
76 76
77 77 /*!
78 78 \qmlproperty Theme ChartView::theme
79 79 Theme defines the visual appearance of the chart, including for example colors, fonts, line
80 80 widths and chart background.
81 81 */
82 82
83 83 /*!
84 84 \qmlproperty Animation ChartView::animationOptions
85 85 Animation configuration of the chart. One of ChartView.NoAnimation, ChartView.GridAxisAnimations,
86 86 ChartView.SeriesAnimations or ChartView.AllAnimations.
87 87 */
88 88
89 89 /*!
90 90 \qmlproperty int ChartView::animationDuration
91 91 The duration of the animation for the chart.
92 92 */
93 93
94 94 /*!
95 95 \qmlproperty easing ChartView::animationEasingCurve
96 96 The easing curve of the animation for the chart.
97 97 */
98 98
99 99 /*!
100 100 \qmlproperty Font ChartView::titleFont
101 101 The title font of the chart.
102 102
103 103 See the Qt documentation for more details of Font.
104 104 */
105 105
106 106 /*!
107 107 \qmlproperty string ChartView::title
108 108 The title of the chart, shown on top of the chart.
109 109 \sa ChartView::titleColor
110 110 */
111 111
112 112 /*!
113 113 \qmlproperty color ChartView::titleColor
114 114 The color of the title text.
115 115 */
116 116
117 117 /*!
118 118 \qmlproperty Legend ChartView::legend
119 119 The legend of the chart. Legend lists all the series, pie slices and bar sets added on the chart.
120 120 */
121 121
122 122 /*!
123 123 \qmlproperty int ChartView::count
124 124 The count of series added to the chart.
125 125 */
126 126
127 127 /*!
128 128 \qmlproperty color ChartView::backgroundColor
129 129 The color of the chart's background. By default background color is defined by chart theme.
130 130 \sa ChartView::theme
131 131 */
132 132
133 133 /*!
134 134 \qmlproperty real ChartView::backgroundRoundness
135 135 The diameter of the rounding circle at the corners of the chart background.
136 136 */
137 137
138 138 /*!
139 139 \qmlproperty color ChartView::plotAreaColor
140 140 The color of the background of the chart's plot area. By default plot area background uses chart's
141 141 background color.
142 142 \sa ChartView::backgroundColor
143 143 */
144 144
145 145 /*!
146 146 \qmlproperty list<AbstractAxis> ChartView::axes
147 147 The axes of the ChartView.
148 148 */
149 149
150 150 /*!
151 151 \qmlproperty bool ChartView::dropShadowEnabled
152 152 The chart's border drop shadow. Set to true to enable drop shadow.
153 153 */
154 154
155 155 /*!
156 156 \qmlproperty rect ChartView::plotArea
157 157 The area on the ChartView that is used for drawing series. This is the ChartView rect without the
158 158 margins.
159 159 \sa ChartView::margins
160 160 */
161 161
162 162 /*!
163 163 \qmlproperty Margins ChartView::margins
164 164 The minimum margins allowed between the outer bounds and the plotArea of the ChartView. Margins
165 165 area of ChartView is used for drawing title, axes and legend.
166 166 */
167 167
168 168 /*!
169 169 \qmlproperty bool ChartView::localizeNumbers
170 170 \since QtCharts 2.0
171 171 When \c{true}, all generated numbers appearing in various series and axis labels will be
172 172 localized using the default QLocale of the application, which defaults to the system locale.
173 173 When \c{false}, the "C" locale is always used.
174 174 Defaults to \c{false}.
175 175
176 176 \sa locale
177 177 */
178 178
179 179 /*!
180 180 \qmlproperty locale ChartView::locale
181 181 \since QtCharts 2.0
182 182 Sets the locale used to format various chart labels when localizeNumbers is \c{true}.
183 183 This also determines the locale used to format DateTimeAxis labels regardless of
184 184 localizeNumbers property.
185 185 Defaults to application default locale at the time the chart is constructed.
186 186
187 187 \sa localizeNumbers
188 188 */
189 189
190 190 /*!
191 191 \qmlmethod AbstractSeries ChartView::series(int index)
192 192 Returns the series with \a index on the chart. This allows you to loop through the series of a chart together with
193 193 the count property of the chart.
194 194 */
195 195
196 196 /*!
197 197 \qmlmethod AbstractSeries ChartView::series(string name)
198 198 Returns the first series on the chart with \a name. If there is no series with that name, returns null.
199 199 */
200 200
201 201 /*!
202 202 \qmlmethod AbstractSeries ChartView::createSeries(SeriesType type, string name, AbstractAxis axisX, AbstractAxis axisY)
203 203 Creates a series object of \a type to the chart with name \a name, optional axis \a axisX and
204 204 optional axis \a axisY. For example:
205 205 \code
206 206 // lineSeries is a LineSeries object that has already been added to the ChartView; re-use it's axes
207 207 var myAxisX = chartView.axisX(lineSeries);
208 208 var myAxisY = chartView.axisY(lineSeries);
209 209 var scatter = chartView.createSeries(ChartView.SeriesTypeScatter, "scatter series", myAxisX, myAxisY);
210 210 \endcode
211 211 */
212 212
213 213 /*!
214 214 \qmlmethod ChartView::removeSeries(AbstractSeries series)
215 215 Removes the \a series from the chart. The series object is also destroyed.
216 216 */
217 217
218 218 /*!
219 219 \qmlmethod ChartView::removeAllSeries()
220 220 Removes all series from the chart. All the series objects are also destroyed.
221 221 */
222 222
223 223 /*!
224 224 \qmlmethod Axis ChartView::axisX(AbstractSeries series)
225 225 The x-axis of the series.
226 226 */
227 227
228 228 /*!
229 229 \qmlmethod ChartView::setAxisX(AbstractAxis axis, AbstractSeries series)
230 230 Set the x-axis of the series.
231 231 */
232 232
233 233 /*!
234 234 \qmlmethod Axis ChartView::axisY(AbstractSeries series)
235 235 The y-axis of the series.
236 236 */
237 237
238 238 /*!
239 239 \qmlmethod ChartView::setAxisY(AbstractAxis axis, AbstractSeries series)
240 240 Set the y-axis of the series.
241 241 */
242 242
243 243 /*!
244 244 \qmlmethod ChartView::zoom(real factor)
245 245 Zooms in by \a factor on the center of the chart.
246 246
247 247 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
248 248 */
249 249
250 250 /*!
251 251 \qmlmethod ChartView::zoomIn()
252 252 Zooms in the view by a factor of two.
253 253 */
254 254
255 255 /*!
256 256 \qmlmethod ChartView::zoomIn(rect rectangle)
257 257 Zooms in the view to a maximum level at which \a rectangle is still fully visible.
258 258 \note This is not supported for polar charts.
259 259 */
260 260
261 261 /*!
262 262 \qmlmethod ChartView::zoomOut()
263 263 Zooms out the view by a factor of two.
264 264 */
265 265
266 266 /*!
267 267 \qmlmethod ChartView::zoomReset()
268 268 Resets the series domains to what they were before any zoom method was called.
269 269 Note that this will also reset any scrolls and explicit axis range settings done between
270 270 the first zoom operation and calling this method. If no zoom operation has been
271 271 done, this method does nothing.
272 272 */
273 273
274 274 /*!
275 275 \qmlmethod ChartView::isZoomed()
276 276 Returns true if any series has a zoomed domain.
277 277 */
278 278
279 279 /*!
280 280 \qmlmethod ChartView::scrollLeft(real pixels)
281 281 Scrolls to left by \a pixels. This is a convenience function that suits for example for key navigation.
282 282 */
283 283
284 284 /*!
285 285 \qmlmethod ChartView::scrollRight(real pixels)
286 286 Scrolls to right by \a pixels. This is a convenience function that suits for example for key navigation.
287 287 */
288 288
289 289 /*!
290 290 \qmlmethod ChartView::scrollUp(real pixels)
291 291 Scrolls up by \a pixels. This is a convenience function that suits for example for key navigation.
292 292 */
293 293
294 294 /*!
295 295 \qmlmethod ChartView::scrollDown(real pixels)
296 296 Scrolls down by \a pixels. This is a convenience function that suits for example for key navigation.
297 297 */
298 298
299 299 /*!
300 300 \qmlmethod point ChartView::mapToValue(point position, AbstractSeries series)
301 301 Returns the value in the \a series domain that corresponds to the \a position relative to the
302 302 chart.
303 303 */
304 304
305 305 /*!
306 306 \qmlmethod point ChartView::mapToPosition(point value, AbstractSeries series)
307 307 Returns the position on the chart that corresponds to the \a value in the \a series domain.
308 308 */
309 309
310 310 /*!
311 311 \qmlsignal ChartView::seriesAdded(AbstractSeries series)
312 312 The \a series has been added to the chart.
313 313 */
314 314
315 315 /*!
316 316 \qmlsignal ChartView::seriesRemoved(AbstractSeries series)
317 317 The \a series has been removed from the chart. Please note that \a series is no longer a valid
318 318 object after the signal handler has completed.
319 319 */
320 320
321 321 DeclarativeChart::DeclarativeChart(QQuickItem *parent)
322 322 : QQuickItem(parent)
323 323 {
324 324 initChart(QChart::ChartTypeCartesian);
325 325 }
326 326
327 327 DeclarativeChart::DeclarativeChart(QChart::ChartType type, QQuickItem *parent)
328 328 : QQuickItem(parent)
329 329 {
330 330 initChart(type);
331 331 }
332 332
333 333 void DeclarativeChart::initChart(QChart::ChartType type)
334 334 {
335 335 m_sceneImage = 0;
336 336 m_sceneImageDirty = false;
337 m_sceneImageNeedsClear = false;
337 338 m_guiThreadId = QThread::currentThreadId();
338 339 m_paintThreadId = 0;
339 340 m_updatePending = false;
340 341
341 342 setFlag(ItemHasContents, true);
342 343
343 344 if (type == QChart::ChartTypePolar)
344 345 m_chart = new QPolarChart();
345 346 else
346 347 m_chart = new QChart();
347 348
348 349 m_chart->d_ptr->m_presenter->glSetUseWidget(false);
349 350 m_glXYDataManager = m_chart->d_ptr->m_dataset->glXYSeriesDataManager();
350 351
351 352 m_scene = new QGraphicsScene(this);
352 353 m_scene->addItem(m_chart);
353 354
354 355 setAntialiasing(QQuickItem::antialiasing());
355 356 connect(m_scene, &QGraphicsScene::changed, this, &DeclarativeChart::sceneChanged);
356 357 connect(this, &DeclarativeChart::needRender, this, &DeclarativeChart::renderScene,
357 358 Qt::QueuedConnection);
358 359 connect(this, SIGNAL(antialiasingChanged(bool)), this, SLOT(handleAntialiasingChanged(bool)));
359 360
360 361 setAcceptedMouseButtons(Qt::AllButtons);
361 362 setAcceptHoverEvents(true);
362 363
363 364 m_margins = new DeclarativeMargins(this);
364 365 m_margins->setTop(m_chart->margins().top());
365 366 m_margins->setLeft(m_chart->margins().left());
366 367 m_margins->setRight(m_chart->margins().right());
367 368 m_margins->setBottom(m_chart->margins().bottom());
368 369 connect(m_margins, SIGNAL(topChanged(int,int,int,int)),
369 370 this, SLOT(changeMargins(int,int,int,int)));
370 371 connect(m_margins, SIGNAL(bottomChanged(int,int,int,int)),
371 372 this, SLOT(changeMargins(int,int,int,int)));
372 373 connect(m_margins, SIGNAL(leftChanged(int,int,int,int)),
373 374 this, SLOT(changeMargins(int,int,int,int)));
374 375 connect(m_margins, SIGNAL(rightChanged(int,int,int,int)),
375 376 this, SLOT(changeMargins(int,int,int,int)));
376 377 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesAdded(QAbstractSeries*)));
377 378 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SIGNAL(seriesRemoved(QAbstractSeries*)));
378 379 connect(m_chart, &QChart::plotAreaChanged, this, &DeclarativeChart::plotAreaChanged);
379 380 }
380 381
381 382 void DeclarativeChart::handleSeriesAdded(QAbstractSeries *series)
382 383 {
383 384 emit seriesAdded(series);
384 385 }
385 386
386 387 void DeclarativeChart::changeMargins(int top, int bottom, int left, int right)
387 388 {
388 389 m_chart->setMargins(QMargins(left, top, right, bottom));
389 390 emit marginsChanged();
390 391 }
391 392
392 393 DeclarativeChart::~DeclarativeChart()
393 394 {
394 395 delete m_chart;
395 396 delete m_sceneImage;
396 397 }
397 398
398 399 void DeclarativeChart::childEvent(QChildEvent *event)
399 400 {
400 401 if (event->type() == QEvent::ChildAdded) {
401 402 if (qobject_cast<QAbstractSeries *>(event->child())) {
402 403 m_chart->addSeries(qobject_cast<QAbstractSeries *>(event->child()));
403 404 }
404 405 }
405 406 }
406 407
407 408 void DeclarativeChart::componentComplete()
408 409 {
409 410 foreach (QObject *child, children()) {
410 411 if (qobject_cast<QAbstractSeries *>(child)) {
411 412 // Add series to the chart
412 413 QAbstractSeries *series = qobject_cast<QAbstractSeries *>(child);
413 414 m_chart->addSeries(series);
414 415
415 416 // Connect to axis changed signals (unless this is a pie series)
416 417 if (!qobject_cast<DeclarativePieSeries *>(series)) {
417 418 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
418 419 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXTopSet(QAbstractAxis*)));
419 420 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
420 421 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
421 422 }
422 423
423 424 initializeAxes(series);
424 425 }
425 426 }
426 427
427 428 QQuickItem::componentComplete();
428 429 }
429 430
430 431 void DeclarativeChart::seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
431 432 Qt::Orientations orientation,
432 433 Qt::Alignment alignment)
433 434 {
434 435 if (!series->attachedAxes().contains(axis)) {
435 436 // Remove & delete old axes that are not attached to any other series
436 437 foreach (QAbstractAxis* oldAxis, m_chart->axes(orientation, series)) {
437 438 bool otherAttachments = false;
438 439 if (oldAxis != axis) {
439 440 foreach (QAbstractSeries *oldSeries, m_chart->series()) {
440 441 if (oldSeries != series && oldSeries->attachedAxes().contains(oldAxis)) {
441 442 otherAttachments = true;
442 443 break;
443 444 }
444 445 }
445 446 if (!otherAttachments) {
446 447 m_chart->removeAxis(oldAxis);
447 448 delete oldAxis;
448 449 }
449 450 }
450 451 }
451 452 if (!m_chart->axes(orientation).contains(axis))
452 453 m_chart->addAxis(axis, alignment);
453 454
454 455 series->attachAxis(axis);
455 456 }
456 457 }
457 458
458 459 void DeclarativeChart::handleAxisXSet(QAbstractAxis *axis)
459 460 {
460 461 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
461 462 if (axis && s) {
462 463 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignBottom);
463 464 } else {
464 465 qWarning() << "Trying to set axisX to null.";
465 466 }
466 467 }
467 468
468 469 void DeclarativeChart::handleAxisXTopSet(QAbstractAxis *axis)
469 470 {
470 471 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
471 472 if (axis && s) {
472 473 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignTop);
473 474 } else {
474 475 qWarning() << "Trying to set axisXTop to null.";
475 476 }
476 477 }
477 478
478 479 void DeclarativeChart::handleAxisYSet(QAbstractAxis *axis)
479 480 {
480 481 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
481 482 if (axis && s) {
482 483 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignLeft);
483 484 } else {
484 485 qWarning() << "Trying to set axisY to null.";
485 486 }
486 487 }
487 488
488 489 void DeclarativeChart::handleAxisYRightSet(QAbstractAxis *axis)
489 490 {
490 491 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
491 492 if (axis && s) {
492 493 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignRight);
493 494 } else {
494 495 qWarning() << "Trying to set axisYRight to null.";
495 496 }
496 497 }
497 498
498 499 void DeclarativeChart::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
499 500 {
500 501 if (newGeometry.isValid()) {
501 502 if (newGeometry.width() > 0 && newGeometry.height() > 0) {
502 503 m_chart->resize(newGeometry.width(), newGeometry.height());
503 504 }
504 505 }
505 506 QQuickItem::geometryChanged(newGeometry, oldGeometry);
506 507 }
507 508
508 509 QSGNode *DeclarativeChart::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
509 510 {
510 511 DeclarativeChartNode *node = static_cast<DeclarativeChartNode *>(oldNode);
511 512
512 513 if (!node) {
513 514 node = new DeclarativeChartNode(window());
514 515 connect(window(), &QQuickWindow::beforeRendering,
515 516 node->glRenderNode(), &DeclarativeRenderNode::render);
516 517 }
517 518
518 519 const QRectF &bRect = boundingRect();
519 520
520 521 // Update GL data
521 522 if (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty()) {
522 523 const QRectF &plotArea = m_chart->plotArea();
523 524 const QSizeF &chartAreaSize = m_chart->size();
524 525
525 526 // We can't use chart's plot area directly, as graphicscene has some internal minimum size
526 527 const qreal normalizedX = plotArea.x() / chartAreaSize.width();
527 528 const qreal normalizedY = plotArea.y() / chartAreaSize.height();
528 529 const qreal normalizedWidth = plotArea.width() / chartAreaSize.width();
529 530 const qreal normalizedHeight = plotArea.height() / chartAreaSize.height();
530 531
531 532 QRectF adjustedPlotArea(normalizedX * bRect.width(),
532 533 normalizedY * bRect.height(),
533 534 normalizedWidth * bRect.width(),
534 535 normalizedHeight * bRect.height());
535 536
536 537 const QSize &adjustedPlotSize = adjustedPlotArea.size().toSize();
537 538 if (adjustedPlotSize != node->glRenderNode()->textureSize())
538 539 node->glRenderNode()->setTextureSize(adjustedPlotSize);
539 540
540 541 node->glRenderNode()->setRect(adjustedPlotArea);
541 542 node->glRenderNode()->setSeriesData(m_glXYDataManager->mapDirty(),
542 543 m_glXYDataManager->dataMap());
543 544
544 545 // Clear dirty flags from original xy data
545 546 m_glXYDataManager->clearAllDirty();
546 547 }
547 548
548 549 // Copy chart (if dirty) to chart node
549 550 if (m_sceneImageDirty) {
550 551 node->createTextureFromImage(*m_sceneImage);
551 552 m_sceneImageDirty = false;
552 553 }
553 554
554 555 node->setRect(bRect);
555 556
556 557 return node;
557 558 }
558 559
559 560 void DeclarativeChart::sceneChanged(QList<QRectF> region)
560 561 {
561 562 const int count = region.size();
562 563 const qreal limitSize = 0.01;
563 564 if (count && !m_updatePending) {
564 565 qreal totalSize = 0.0;
565 566 for (int i = 0; i < count; i++) {
566 567 const QRectF &reg = region.at(i);
567 568 totalSize += (reg.height() * reg.width());
568 569 if (totalSize >= limitSize)
569 570 break;
570 571 }
571 572 // Ignore region updates that change less than small fraction of a pixel, as there is
572 573 // little point regenerating the image in these cases. These are typically cases
573 574 // where OpenGL series are drawn to otherwise static chart.
574 575 if (totalSize >= limitSize) {
575 576 m_updatePending = true;
576 577 // Do async render to avoid some unnecessary renders.
577 578 emit needRender();
578 579 } else {
579 580 // We do want to call update to trigger possible gl series updates.
580 581 update();
581 582 }
582 583 }
583 584 }
584 585
585 586 void DeclarativeChart::renderScene()
586 587 {
587 588 m_updatePending = false;
588 589 m_sceneImageDirty = true;
589 590 QSize chartSize = m_chart->size().toSize();
590 591 if (!m_sceneImage || chartSize != m_sceneImage->size()) {
591 592 delete m_sceneImage;
592 593 m_sceneImage = new QImage(chartSize, QImage::Format_ARGB32);
593 m_sceneImage->fill(Qt::transparent);
594 m_sceneImageNeedsClear = true;
594 595 }
595 596
597 if (m_sceneImageNeedsClear) {
598 m_sceneImage->fill(Qt::transparent);
599 // Don't clear the flag if chart background has any transparent element to it
600 if (m_chart->backgroundBrush().color().alpha() == 0xff && !m_chart->isDropShadowEnabled())
601 m_sceneImageNeedsClear = false;
602 }
596 603 QPainter painter(m_sceneImage);
597 604 if (antialiasing()) {
598 605 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
599 606 | QPainter::SmoothPixmapTransform);
600 607 }
601 608 QRect renderRect(QPoint(0, 0), chartSize);
602 609 m_scene->render(&painter, renderRect, renderRect);
603 610 update();
604 611 }
605 612
606 613 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
607 614 {
608 615 m_mousePressScenePoint = event->pos();
609 616 m_mousePressScreenPoint = event->globalPos();
610 617 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
611 618 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
612 619 m_mousePressButton = event->button();
613 620 m_mousePressButtons = event->buttons();
614 621
615 622 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
616 623 mouseEvent.setWidget(0);
617 624 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
618 625 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
619 626 mouseEvent.setScenePos(m_mousePressScenePoint);
620 627 mouseEvent.setScreenPos(m_mousePressScreenPoint);
621 628 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
622 629 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
623 630 mouseEvent.setButtons(m_mousePressButtons);
624 631 mouseEvent.setButton(m_mousePressButton);
625 632 mouseEvent.setModifiers(event->modifiers());
626 633 mouseEvent.setAccepted(false);
627 634
628 635 QApplication::sendEvent(m_scene, &mouseEvent);
629 636 }
630 637
631 638 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
632 639 {
633 640 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
634 641 mouseEvent.setWidget(0);
635 642 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
636 643 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
637 644 mouseEvent.setScenePos(event->pos());
638 645 mouseEvent.setScreenPos(event->globalPos());
639 646 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
640 647 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
641 648 mouseEvent.setButtons(event->buttons());
642 649 mouseEvent.setButton(event->button());
643 650 mouseEvent.setModifiers(event->modifiers());
644 651 mouseEvent.setAccepted(false);
645 652
646 653 QApplication::sendEvent(m_scene, &mouseEvent);
647 654
648 655 m_mousePressButtons = event->buttons();
649 656 m_mousePressButton = Qt::NoButton;
650 657 }
651 658
652 659 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
653 660 {
654 661 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
655 662 // QGraphicsScene generates hover events from mouse move events, so we don't need
656 663 // to pass hover events there.
657 664 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
658 665 mouseEvent.setWidget(0);
659 666 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
660 667 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
661 668 mouseEvent.setScenePos(event->pos());
662 669 // Hover events do not have global pos in them, and the screen position doesn't seem to
663 670 // matter anyway in this use case, so just pass event pos instead of trying to
664 671 // calculate the real screen position.
665 672 mouseEvent.setScreenPos(event->pos());
666 673 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
667 674 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
668 675 mouseEvent.setButtons(m_mousePressButtons);
669 676 mouseEvent.setButton(m_mousePressButton);
670 677 mouseEvent.setModifiers(event->modifiers());
671 678 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
672 679 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
673 680 mouseEvent.setAccepted(false);
674 681
675 682 QApplication::sendEvent(m_scene, &mouseEvent);
676 683 }
677 684
678 685 void DeclarativeChart::mouseDoubleClickEvent(QMouseEvent *event)
679 686 {
680 687 m_mousePressScenePoint = event->pos();
681 688 m_mousePressScreenPoint = event->globalPos();
682 689 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
683 690 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
684 691 m_mousePressButton = event->button();
685 692 m_mousePressButtons = event->buttons();
686 693
687 694 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
688 695 mouseEvent.setWidget(0);
689 696 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
690 697 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
691 698 mouseEvent.setScenePos(m_mousePressScenePoint);
692 699 mouseEvent.setScreenPos(m_mousePressScreenPoint);
693 700 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
694 701 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
695 702 mouseEvent.setButtons(m_mousePressButtons);
696 703 mouseEvent.setButton(m_mousePressButton);
697 704 mouseEvent.setModifiers(event->modifiers());
698 705 mouseEvent.setAccepted(false);
699 706
700 707 QApplication::sendEvent(m_scene, &mouseEvent);
701 708 }
702 709
703 710 void DeclarativeChart::handleAntialiasingChanged(bool enable)
704 711 {
705 712 setAntialiasing(enable);
706 713 }
707 714
708 715 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
709 716 {
710 717 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
711 718 if (chartTheme != m_chart->theme())
712 719 m_chart->setTheme(chartTheme);
713 720 }
714 721
715 722 DeclarativeChart::Theme DeclarativeChart::theme()
716 723 {
717 724 return (DeclarativeChart::Theme) m_chart->theme();
718 725 }
719 726
720 727 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
721 728 {
722 729 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
723 730 if (animationOptions != m_chart->animationOptions())
724 731 m_chart->setAnimationOptions(animationOptions);
725 732 }
726 733
727 734 DeclarativeChart::Animation DeclarativeChart::animationOptions()
728 735 {
729 736 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
730 737 return DeclarativeChart::AllAnimations;
731 738 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
732 739 return DeclarativeChart::GridAxisAnimations;
733 740 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
734 741 return DeclarativeChart::SeriesAnimations;
735 742 else
736 743 return DeclarativeChart::NoAnimation;
737 744 }
738 745
739 746 void DeclarativeChart::setAnimationDuration(int msecs)
740 747 {
741 748 if (msecs != m_chart->animationDuration()) {
742 749 m_chart->setAnimationDuration(msecs);
743 750 emit animationDurationChanged(msecs);
744 751 }
745 752 }
746 753
747 754 int DeclarativeChart::animationDuration() const
748 755 {
749 756 return m_chart->animationDuration();
750 757 }
751 758
752 759 void DeclarativeChart::setAnimationEasingCurve(const QEasingCurve &curve)
753 760 {
754 761 if (curve != m_chart->animationEasingCurve()) {
755 762 m_chart->setAnimationEasingCurve(curve);
756 763 emit animationEasingCurveChanged(curve);
757 764 }
758 765 }
759 766
760 767 QEasingCurve DeclarativeChart::animationEasingCurve() const
761 768 {
762 769 return m_chart->animationEasingCurve();
763 770 }
764 771
765 772 void DeclarativeChart::setTitle(QString title)
766 773 {
767 774 if (title != m_chart->title())
768 775 m_chart->setTitle(title);
769 776 }
770 777 QString DeclarativeChart::title()
771 778 {
772 779 return m_chart->title();
773 780 }
774 781
775 782 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
776 783 {
777 784 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
778 785 if (axes.count())
779 786 return axes[0];
780 787 return 0;
781 788 }
782 789
783 790 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
784 791 {
785 792 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
786 793 if (axes.count())
787 794 return axes[0];
788 795 return 0;
789 796 }
790 797
791 798 QLegend *DeclarativeChart::legend()
792 799 {
793 800 return m_chart->legend();
794 801 }
795 802
796 803 void DeclarativeChart::setTitleColor(QColor color)
797 804 {
798 805 QBrush b = m_chart->titleBrush();
799 806 if (color != b.color()) {
800 807 b.setColor(color);
801 808 m_chart->setTitleBrush(b);
802 809 emit titleColorChanged(color);
803 810 }
804 811 }
805 812
806 813 QFont DeclarativeChart::titleFont() const
807 814 {
808 815 return m_chart->titleFont();
809 816 }
810 817
811 818 void DeclarativeChart::setTitleFont(const QFont &font)
812 819 {
813 820 m_chart->setTitleFont(font);
814 821 }
815 822
816 823 QColor DeclarativeChart::titleColor()
817 824 {
818 825 return m_chart->titleBrush().color();
819 826 }
820 827
821 828 void DeclarativeChart::setBackgroundColor(QColor color)
822 829 {
823 830 QBrush b = m_chart->backgroundBrush();
824 831 if (b.style() != Qt::SolidPattern || color != b.color()) {
832 if (color.alpha() < 0xff)
833 m_sceneImageNeedsClear = true;
825 834 b.setStyle(Qt::SolidPattern);
826 835 b.setColor(color);
827 836 m_chart->setBackgroundBrush(b);
828 837 emit backgroundColorChanged();
829 838 }
830 839 }
831 840
832 841 QColor DeclarativeChart::backgroundColor()
833 842 {
834 843 return m_chart->backgroundBrush().color();
835 844 }
836 845
837 846 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
838 847 {
839 848 QBrush b = m_chart->plotAreaBackgroundBrush();
840 849 if (b.style() != Qt::SolidPattern || color != b.color()) {
841 850 b.setStyle(Qt::SolidPattern);
842 851 b.setColor(color);
843 852 m_chart->setPlotAreaBackgroundBrush(b);
844 853 m_chart->setPlotAreaBackgroundVisible(true);
845 854 emit plotAreaColorChanged();
846 855 }
847 856 }
848 857
849 858 QColor QtCharts::DeclarativeChart::plotAreaColor()
850 859 {
851 860 return m_chart->plotAreaBackgroundBrush().color();
852 861 }
853 862
854 863 void DeclarativeChart::setLocalizeNumbers(bool localize)
855 864 {
856 865 if (m_chart->localizeNumbers() != localize) {
857 866 m_chart->setLocalizeNumbers(localize);
858 867 emit localizeNumbersChanged();
859 868 }
860 869 }
861 870
862 871 bool DeclarativeChart::localizeNumbers() const
863 872 {
864 873 return m_chart->localizeNumbers();
865 874 }
866 875
867 876 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
868 877 {
869 878 if (m_chart->locale() != locale) {
870 879 m_chart->setLocale(locale);
871 880 emit localeChanged();
872 881 }
873 882 }
874 883
875 884 QLocale QtCharts::DeclarativeChart::locale() const
876 885 {
877 886 return m_chart->locale();
878 887 }
879 888
880 889 int DeclarativeChart::count()
881 890 {
882 891 return m_chart->series().count();
883 892 }
884 893
885 894 void DeclarativeChart::setDropShadowEnabled(bool enabled)
886 895 {
887 896 if (enabled != m_chart->isDropShadowEnabled()) {
897 m_sceneImageNeedsClear = true;
888 898 m_chart->setDropShadowEnabled(enabled);
889 899 dropShadowEnabledChanged(enabled);
890 900 }
891 901 }
892 902
893 903 bool DeclarativeChart::dropShadowEnabled()
894 904 {
895 905 return m_chart->isDropShadowEnabled();
896 906 }
897 907
898 908 qreal DeclarativeChart::backgroundRoundness() const
899 909 {
900 910 return m_chart->backgroundRoundness();
901 911 }
902 912
903 913 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
904 914 {
905 915 if (m_chart->backgroundRoundness() != diameter) {
916 m_sceneImageNeedsClear = true;
906 917 m_chart->setBackgroundRoundness(diameter);
907 918 emit backgroundRoundnessChanged(diameter);
908 919 }
909 920 }
910 921
911 922 void DeclarativeChart::zoom(qreal factor)
912 923 {
913 924 m_chart->zoom(factor);
914 925 }
915 926
916 927 void DeclarativeChart::zoomIn()
917 928 {
918 929 m_chart->zoomIn();
919 930 }
920 931
921 932 void DeclarativeChart::zoomIn(const QRectF &rectangle)
922 933 {
923 934 m_chart->zoomIn(rectangle);
924 935 }
925 936
926 937 void DeclarativeChart::zoomOut()
927 938 {
928 939 m_chart->zoomOut();
929 940 }
930 941
931 942 void DeclarativeChart::zoomReset()
932 943 {
933 944 m_chart->zoomReset();
934 945 }
935 946
936 947 bool DeclarativeChart::isZoomed()
937 948 {
938 949 return m_chart->isZoomed();
939 950 }
940 951
941 952 void DeclarativeChart::scrollLeft(qreal pixels)
942 953 {
943 954 m_chart->scroll(-pixels, 0);
944 955 }
945 956
946 957 void DeclarativeChart::scrollRight(qreal pixels)
947 958 {
948 959 m_chart->scroll(pixels, 0);
949 960 }
950 961
951 962 void DeclarativeChart::scrollUp(qreal pixels)
952 963 {
953 964 m_chart->scroll(0, pixels);
954 965 }
955 966
956 967 void DeclarativeChart::scrollDown(qreal pixels)
957 968 {
958 969 m_chart->scroll(0, -pixels);
959 970 }
960 971
961 972 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
962 973 {
963 974 return QQmlListProperty<QAbstractAxis>(this, 0,
964 975 &DeclarativeChart::axesAppendFunc,
965 976 &DeclarativeChart::axesCountFunc,
966 977 &DeclarativeChart::axesAtFunc,
967 978 &DeclarativeChart::axesClearFunc);
968 979 }
969 980
970 981 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
971 982 {
972 983 // Empty implementation
973 984 Q_UNUSED(list);
974 985 Q_UNUSED(element);
975 986 }
976 987
977 988 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
978 989 {
979 990 if (qobject_cast<DeclarativeChart *>(list->object)) {
980 991 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
981 992 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
982 993 }
983 994 return 0;
984 995 }
985 996
986 997 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
987 998 {
988 999 if (qobject_cast<DeclarativeChart *>(list->object)) {
989 1000 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
990 1001 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
991 1002 return axes.at(index);
992 1003 }
993 1004 return 0;
994 1005 }
995 1006
996 1007 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
997 1008 {
998 1009 // Empty implementation
999 1010 Q_UNUSED(list);
1000 1011 }
1001 1012
1002 1013
1003 1014 QAbstractSeries *DeclarativeChart::series(int index)
1004 1015 {
1005 1016 if (index < m_chart->series().count()) {
1006 1017 return m_chart->series().at(index);
1007 1018 }
1008 1019 return 0;
1009 1020 }
1010 1021
1011 1022 QAbstractSeries *DeclarativeChart::series(QString seriesName)
1012 1023 {
1013 1024 foreach (QAbstractSeries *series, m_chart->series()) {
1014 1025 if (series->name() == seriesName)
1015 1026 return series;
1016 1027 }
1017 1028 return 0;
1018 1029 }
1019 1030
1020 1031 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
1021 1032 {
1022 1033 QAbstractSeries *series = 0;
1023 1034
1024 1035 switch (type) {
1025 1036 case DeclarativeChart::SeriesTypeLine:
1026 1037 series = new DeclarativeLineSeries();
1027 1038 break;
1028 1039 case DeclarativeChart::SeriesTypeArea: {
1029 1040 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
1030 1041 DeclarativeLineSeries *line = new DeclarativeLineSeries();
1031 1042 line->setParent(area);
1032 1043 area->setUpperSeries(line);
1033 1044 series = area;
1034 1045 break;
1035 1046 }
1036 1047 case DeclarativeChart::SeriesTypeStackedBar:
1037 1048 series = new DeclarativeStackedBarSeries();
1038 1049 break;
1039 1050 case DeclarativeChart::SeriesTypePercentBar:
1040 1051 series = new DeclarativePercentBarSeries();
1041 1052 break;
1042 1053 case DeclarativeChart::SeriesTypeBar:
1043 1054 series = new DeclarativeBarSeries();
1044 1055 break;
1045 1056 case DeclarativeChart::SeriesTypeHorizontalBar:
1046 1057 series = new DeclarativeHorizontalBarSeries();
1047 1058 break;
1048 1059 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
1049 1060 series = new DeclarativeHorizontalPercentBarSeries();
1050 1061 break;
1051 1062 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
1052 1063 series = new DeclarativeHorizontalStackedBarSeries();
1053 1064 break;
1054 1065 case DeclarativeChart::SeriesTypeBoxPlot:
1055 1066 series = new DeclarativeBoxPlotSeries();
1056 1067 break;
1057 1068 case DeclarativeChart::SeriesTypePie:
1058 1069 series = new DeclarativePieSeries();
1059 1070 break;
1060 1071 case DeclarativeChart::SeriesTypeScatter:
1061 1072 series = new DeclarativeScatterSeries();
1062 1073 break;
1063 1074 case DeclarativeChart::SeriesTypeSpline:
1064 1075 series = new DeclarativeSplineSeries();
1065 1076 break;
1066 1077 default:
1067 1078 qWarning() << "Illegal series type";
1068 1079 }
1069 1080
1070 1081 if (series) {
1071 1082 // Connect to axis changed signals (unless this is a pie series)
1072 1083 if (!qobject_cast<DeclarativePieSeries *>(series)) {
1073 1084 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1074 1085 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1075 1086 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
1076 1087 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
1077 1088 }
1078 1089
1079 1090 series->setName(name);
1080 1091 m_chart->addSeries(series);
1081 1092
1082 1093 if (!axisX || !axisY)
1083 1094 initializeAxes(series);
1084 1095
1085 1096 if (axisX)
1086 1097 setAxisX(axisX, series);
1087 1098 if (axisY)
1088 1099 setAxisY(axisY, series);
1089 1100 }
1090 1101
1091 1102 return series;
1092 1103 }
1093 1104
1094 1105 void DeclarativeChart::removeSeries(QAbstractSeries *series)
1095 1106 {
1096 1107 if (series)
1097 1108 m_chart->removeSeries(series);
1098 1109 else
1099 1110 qWarning("removeSeries: cannot remove null");
1100 1111 }
1101 1112
1102 1113 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
1103 1114 {
1104 1115 if (axis && series)
1105 1116 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
1106 1117 }
1107 1118
1108 1119 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
1109 1120 {
1110 1121 if (axis && series)
1111 1122 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
1112 1123 }
1113 1124
1114 1125 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
1115 1126 {
1116 1127 if (!series) {
1117 1128 qWarning() << "No axis type defined for null series";
1118 1129 return 0;
1119 1130 }
1120 1131
1121 1132 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
1122 1133 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
1123 1134 return existingAxis;
1124 1135 }
1125 1136
1126 1137 switch (series->d_ptr->defaultAxisType(orientation)) {
1127 1138 case QAbstractAxis::AxisTypeValue:
1128 1139 return new QValueAxis(this);
1129 1140 case QAbstractAxis::AxisTypeBarCategory:
1130 1141 return new QBarCategoryAxis(this);
1131 1142 case QAbstractAxis::AxisTypeCategory:
1132 1143 return new QCategoryAxis(this);
1133 1144 #ifndef QT_ON_ARM
1134 1145 case QAbstractAxis::AxisTypeDateTime:
1135 1146 return new QDateTimeAxis(this);
1136 1147 #endif
1137 1148 case QAbstractAxis::AxisTypeLogValue:
1138 1149 return new QLogValueAxis(this);
1139 1150 default:
1140 1151 // assume AxisTypeNoAxis
1141 1152 return 0;
1142 1153 }
1143 1154 }
1144 1155
1145 1156 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1146 1157 {
1147 1158 if (qobject_cast<DeclarativeLineSeries *>(series))
1148 1159 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1149 1160 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1150 1161 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1151 1162 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1152 1163 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1153 1164 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1154 1165 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1155 1166 else if (qobject_cast<DeclarativeBarSeries *>(series))
1156 1167 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1157 1168 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1158 1169 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1159 1170 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1160 1171 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1161 1172 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1162 1173 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1163 1174 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1164 1175 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1165 1176 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1166 1177 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1167 1178 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1168 1179 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1169 1180 // else: do nothing
1170 1181 }
1171 1182
1172 1183 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1173 1184 {
1174 1185 qreal min;
1175 1186 qreal max;
1176 1187 // Initialize axis X
1177 1188 if (axes->axisX()) {
1178 1189 axes->emitAxisXChanged();
1179 1190 } else if (axes->axisXTop()) {
1180 1191 axes->emitAxisXTopChanged();
1181 1192 } else {
1182 1193 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1183 1194 findMinMaxForSeries(series, Qt::Horizontal, min, max);
1184 1195 axes->axisX()->setRange(min, max);
1185 1196 }
1186 1197
1187 1198 // Initialize axis Y
1188 1199 if (axes->axisY()) {
1189 1200 axes->emitAxisYChanged();
1190 1201 } else if (axes->axisYRight()) {
1191 1202 axes->emitAxisYRightChanged();
1192 1203 } else {
1193 1204 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1194 1205 findMinMaxForSeries(series, Qt::Vertical, min, max);
1195 1206 axes->axisY()->setRange(min, max);
1196 1207 }
1197 1208 }
1198 1209
1199 1210 void DeclarativeChart::findMinMaxForSeries(QAbstractSeries *series, Qt::Orientations orientation,
1200 1211 qreal &min, qreal &max)
1201 1212 {
1202 1213 if (!series) {
1203 1214 min = 0.5;
1204 1215 max = 0.5;
1205 1216 } else {
1206 1217 AbstractDomain *domain = series->d_ptr->domain();
1207 1218 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
1208 1219 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
1209 1220
1210 1221 if (min == max) {
1211 1222 min -= 0.5;
1212 1223 max += 0.5;
1213 1224 }
1214 1225 }
1215 1226 }
1216 1227
1217 1228 QPointF DeclarativeChart::mapToValue(const QPointF &position, QAbstractSeries *series)
1218 1229 {
1219 1230 return m_chart->mapToValue(position, series);
1220 1231 }
1221 1232
1222 1233 QPointF DeclarativeChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
1223 1234 {
1224 1235 return m_chart->mapToPosition(value, series);
1225 1236 }
1226 1237
1227 1238 #include "moc_declarativechart.cpp"
1228 1239
1229 1240 QT_CHARTS_END_NAMESPACE
@@ -1,245 +1,246
1 1 /******************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd.
4 4 ** Contact: http://www.qt.io/licensing/
5 5 **
6 6 ** This file is part of the Qt Charts module.
7 7 **
8 8 ** $QT_BEGIN_LICENSE:COMM$
9 9 **
10 10 ** Commercial License Usage
11 11 ** Licensees holding valid commercial Qt licenses may use this file in
12 12 ** accordance with the commercial license agreement provided with the
13 13 ** Software or, alternatively, in accordance with the terms contained in
14 14 ** a written agreement between you and The Qt Company. For licensing terms
15 15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 16 ** information use the contact form at http://www.qt.io/contact-us.
17 17 **
18 18 ** $QT_END_LICENSE$
19 19 **
20 20 ******************************************************************************/
21 21
22 22 #ifndef DECLARATIVECHART_H
23 23 #define DECLARATIVECHART_H
24 24
25 25 #include <private/glxyseriesdata_p.h>
26 26
27 27 #include <QtCore/QtGlobal>
28 28 #include <QtQuick/QQuickItem>
29 29 #include <QtWidgets/QGraphicsScene>
30 30
31 31 #include <QtCharts/QChart>
32 32 #include <QtCore/QLocale>
33 33
34 34 QT_CHARTS_BEGIN_NAMESPACE
35 35
36 36 class DeclarativeMargins;
37 37 class Domain;
38 38 class DeclarativeAxes;
39 39
40 40 class DeclarativeChart : public QQuickItem
41 41 {
42 42 Q_OBJECT
43 43 Q_PROPERTY(Theme theme READ theme WRITE setTheme)
44 44 Q_PROPERTY(Animation animationOptions READ animationOptions WRITE setAnimationOptions)
45 45 Q_PROPERTY(int animationDuration READ animationDuration WRITE setAnimationDuration NOTIFY animationDurationChanged REVISION 5)
46 46 Q_PROPERTY(QEasingCurve animationEasingCurve READ animationEasingCurve WRITE setAnimationEasingCurve NOTIFY animationEasingCurveChanged REVISION 5)
47 47 Q_PROPERTY(QString title READ title WRITE setTitle)
48 48 Q_PROPERTY(QFont titleFont READ titleFont WRITE setTitleFont)
49 49 Q_PROPERTY(QColor titleColor READ titleColor WRITE setTitleColor NOTIFY titleColorChanged)
50 50 Q_PROPERTY(QLegend *legend READ legend CONSTANT)
51 51 Q_PROPERTY(int count READ count)
52 52 Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
53 53 Q_PROPERTY(bool dropShadowEnabled READ dropShadowEnabled WRITE setDropShadowEnabled NOTIFY dropShadowEnabledChanged)
54 54 Q_PROPERTY(qreal backgroundRoundness READ backgroundRoundness WRITE setBackgroundRoundness NOTIFY backgroundRoundnessChanged REVISION 3)
55 55 Q_PROPERTY(DeclarativeMargins *margins READ margins NOTIFY marginsChanged REVISION 2)
56 56 Q_PROPERTY(QRectF plotArea READ plotArea NOTIFY plotAreaChanged REVISION 1)
57 57 Q_PROPERTY(QColor plotAreaColor READ plotAreaColor WRITE setPlotAreaColor NOTIFY plotAreaColorChanged REVISION 3)
58 58 Q_PROPERTY(QQmlListProperty<QAbstractAxis> axes READ axes REVISION 2)
59 59 Q_PROPERTY(bool localizeNumbers READ localizeNumbers WRITE setLocalizeNumbers NOTIFY localizeNumbersChanged REVISION 4)
60 60 Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged REVISION 4)
61 61 Q_ENUMS(Animation)
62 62 Q_ENUMS(Theme)
63 63 Q_ENUMS(SeriesType)
64 64
65 65 public:
66 66 // duplicating enums from QChart to make the QML api namings 1-to-1 with the C++ api
67 67 enum Theme {
68 68 ChartThemeLight = 0,
69 69 ChartThemeBlueCerulean,
70 70 ChartThemeDark,
71 71 ChartThemeBrownSand,
72 72 ChartThemeBlueNcs,
73 73 ChartThemeHighContrast,
74 74 ChartThemeBlueIcy,
75 75 ChartThemeQt
76 76 };
77 77
78 78 enum Animation {
79 79 NoAnimation = 0x0,
80 80 GridAxisAnimations = 0x1,
81 81 SeriesAnimations = 0x2,
82 82 AllAnimations = 0x3
83 83 };
84 84
85 85 enum SeriesType {
86 86 SeriesTypeLine,
87 87 SeriesTypeArea,
88 88 SeriesTypeBar,
89 89 SeriesTypeStackedBar,
90 90 SeriesTypePercentBar,
91 91 SeriesTypeBoxPlot,
92 92 SeriesTypePie,
93 93 SeriesTypeScatter,
94 94 SeriesTypeSpline,
95 95 SeriesTypeHorizontalBar,
96 96 SeriesTypeHorizontalStackedBar,
97 97 SeriesTypeHorizontalPercentBar
98 98 };
99 99
100 100 public:
101 101 DeclarativeChart(QQuickItem *parent = 0);
102 102 ~DeclarativeChart();
103 103
104 104 public: // From parent classes
105 105 void childEvent(QChildEvent *event);
106 106 void componentComplete();
107 107 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
108 108 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
109 109 protected:
110 110 void mousePressEvent(QMouseEvent *event);
111 111 void mouseReleaseEvent(QMouseEvent *event);
112 112 void hoverMoveEvent(QHoverEvent *event);
113 113 void mouseDoubleClickEvent(QMouseEvent *event);
114 114 private Q_SLOTS:
115 115 void handleAntialiasingChanged(bool enable);
116 116 void sceneChanged(QList<QRectF> region);
117 117 void renderScene();
118 118
119 119 public:
120 120 void setTheme(DeclarativeChart::Theme theme);
121 121 DeclarativeChart::Theme theme();
122 122 void setAnimationOptions(DeclarativeChart::Animation animations);
123 123 DeclarativeChart::Animation animationOptions();
124 124 void setAnimationDuration(int msecs);
125 125 int animationDuration() const;
126 126 void setAnimationEasingCurve(const QEasingCurve &curve);
127 127 QEasingCurve animationEasingCurve() const;
128 128 void setTitle(QString title);
129 129 QString title();
130 130 QLegend *legend();
131 131 QFont titleFont() const;
132 132 void setTitleFont(const QFont &font);
133 133 void setTitleColor(QColor color);
134 134 QColor titleColor();
135 135 void setBackgroundColor(QColor color);
136 136 QColor backgroundColor();
137 137 void setPlotAreaColor(QColor color);
138 138 QColor plotAreaColor();
139 139 void setLocalizeNumbers(bool localize);
140 140 bool localizeNumbers() const;
141 141 void setLocale(const QLocale &locale);
142 142 QLocale locale() const;
143 143
144 144 int count();
145 145 void setDropShadowEnabled(bool enabled);
146 146 bool dropShadowEnabled();
147 147 qreal backgroundRoundness() const;
148 148 void setBackgroundRoundness(qreal diameter);
149 149
150 150 // Margins & plotArea
151 151 DeclarativeMargins *margins() { return m_margins; }
152 152 QRectF plotArea() { return m_chart->plotArea(); }
153 153
154 154 // Axis handling
155 155 QAbstractAxis *defaultAxis(Qt::Orientation orientation, QAbstractSeries *series);
156 156 void initializeAxes(QAbstractSeries *series);
157 157 void doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes);
158 158 QQmlListProperty<QAbstractAxis> axes();
159 159 static void axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element);
160 160 static int axesCountFunc(QQmlListProperty<QAbstractAxis> *list);
161 161 static QAbstractAxis *axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index);
162 162 static void axesClearFunc(QQmlListProperty<QAbstractAxis> *list);
163 163
164 164 public:
165 165 Q_INVOKABLE QAbstractSeries *series(int index);
166 166 Q_INVOKABLE QAbstractSeries *series(QString seriesName);
167 167 Q_INVOKABLE QAbstractSeries *createSeries(int type, QString name = "", QAbstractAxis *axisX = 0, QAbstractAxis *axisY = 0);
168 168 Q_INVOKABLE void removeSeries(QAbstractSeries *series);
169 169 Q_INVOKABLE void removeAllSeries() { m_chart->removeAllSeries(); }
170 170 Q_INVOKABLE void setAxisX(QAbstractAxis *axis, QAbstractSeries *series = 0);
171 171 Q_INVOKABLE void setAxisY(QAbstractAxis *axis, QAbstractSeries *series = 0);
172 172 Q_INVOKABLE QAbstractAxis *axisX(QAbstractSeries *series = 0);
173 173 Q_INVOKABLE QAbstractAxis *axisY(QAbstractSeries *series = 0);
174 174 Q_INVOKABLE void zoom(qreal factor);
175 175 Q_REVISION(5) Q_INVOKABLE void zoomIn();
176 176 Q_REVISION(5) Q_INVOKABLE void zoomIn(const QRectF &rectangle);
177 177 Q_REVISION(5) Q_INVOKABLE void zoomOut();
178 178 Q_REVISION(5) Q_INVOKABLE void zoomReset();
179 179 Q_REVISION(5) Q_INVOKABLE bool isZoomed();
180 180 Q_INVOKABLE void scrollLeft(qreal pixels);
181 181 Q_INVOKABLE void scrollRight(qreal pixels);
182 182 Q_INVOKABLE void scrollUp(qreal pixels);
183 183 Q_INVOKABLE void scrollDown(qreal pixels);
184 184 Q_REVISION(5) Q_INVOKABLE QPointF mapToValue(const QPointF &position,
185 185 QAbstractSeries *series = 0);
186 186 Q_REVISION(5) Q_INVOKABLE QPointF mapToPosition(const QPointF &value,
187 187 QAbstractSeries *series = 0);
188 188
189 189
190 190 Q_SIGNALS:
191 191 void axisLabelsChanged();
192 192 void titleColorChanged(QColor color);
193 193 void backgroundColorChanged();
194 194 void dropShadowEnabledChanged(bool enabled);
195 195 Q_REVISION(2) void marginsChanged();
196 196 void plotAreaChanged(QRectF plotArea);
197 197 void seriesAdded(QAbstractSeries *series);
198 198 void seriesRemoved(QAbstractSeries *series);
199 199 Q_REVISION(3) void plotAreaColorChanged();
200 200 Q_REVISION(3) void backgroundRoundnessChanged(qreal diameter);
201 201 Q_REVISION(4) void localizeNumbersChanged();
202 202 Q_REVISION(4) void localeChanged();
203 203 Q_REVISION(5) void animationDurationChanged(int msecs);
204 204 Q_REVISION(5) void animationEasingCurveChanged(QEasingCurve curve);
205 205 void needRender();
206 206
207 207 private Q_SLOTS:
208 208 void changeMargins(int top, int bottom, int left, int right);
209 209 void handleAxisXSet(QAbstractAxis *axis);
210 210 void handleAxisYSet(QAbstractAxis *axis);
211 211 void handleAxisXTopSet(QAbstractAxis *axis);
212 212 void handleAxisYRightSet(QAbstractAxis *axis);
213 213 void handleSeriesAdded(QAbstractSeries *series);
214 214
215 215 protected:
216 216 explicit DeclarativeChart(QChart::ChartType type, QQuickItem *parent);
217 217
218 218 private:
219 219 void initChart(QChart::ChartType type);
220 220 void seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
221 221 Qt::Orientations orientation, Qt::Alignment alignment);
222 222 void findMinMaxForSeries(QAbstractSeries *series,Qt::Orientations orientation,
223 223 qreal &min, qreal &max);
224 224 // Extending QChart with DeclarativeChart is not possible because QObject does not support
225 225 // multi inheritance, so we now have a QChart as a member instead
226 226 QChart *m_chart;
227 227 QGraphicsScene *m_scene;
228 228 QPointF m_mousePressScenePoint;
229 229 QPoint m_mousePressScreenPoint;
230 230 QPointF m_lastMouseMoveScenePoint;
231 231 QPoint m_lastMouseMoveScreenPoint;
232 232 Qt::MouseButton m_mousePressButton;
233 233 Qt::MouseButtons m_mousePressButtons;
234 234 QImage *m_sceneImage;
235 235 bool m_sceneImageDirty;
236 236 bool m_updatePending;
237 237 Qt::HANDLE m_paintThreadId;
238 238 Qt::HANDLE m_guiThreadId;
239 239 DeclarativeMargins *m_margins;
240 240 GLXYSeriesDataManager *m_glXYDataManager;
241 bool m_sceneImageNeedsClear;
241 242 };
242 243
243 244 QT_CHARTS_END_NAMESPACE
244 245
245 246 #endif // DECLARATIVECHART_H
General Comments 0
You need to be logged in to leave comments. Login now