##// END OF EJS Templates
Fix another memory leak....
Miikka Heikkinen -
r2735:7d77c52a3f95
parent child
Show More
@@ -1,1057 +1,1059
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2014 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Enterprise Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Enterprise licenses may use this file in
11 11 ** accordance with the Qt Enterprise License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "declarativechart.h"
22 22 #include <QtGui/QPainter>
23 23 #include "declarativelineseries.h"
24 24 #include "declarativeareaseries.h"
25 25 #include "declarativebarseries.h"
26 26 #include "declarativepieseries.h"
27 27 #include "declarativesplineseries.h"
28 28 #include "declarativeboxplotseries.h"
29 29 #include "declarativescatterseries.h"
30 30 #include <QtCharts/QBarCategoryAxis>
31 31 #include <QtCharts/QValueAxis>
32 32 #include <QtCharts/QLogValueAxis>
33 33 #include <QtCharts/QCategoryAxis>
34 34 #include <private/qabstractseries_p.h>
35 35 #include "declarativemargins.h"
36 36 #include <private/chartdataset_p.h>
37 37 #include "declarativeaxes.h"
38 38 #include <private/qchart_p.h>
39 39 #include <QtCharts/QPolarChart>
40 40
41 41 #ifndef QT_ON_ARM
42 42 #include <QtCharts/QDateTimeAxis>
43 43 #endif
44 44
45 45 #include <QtWidgets/QGraphicsSceneMouseEvent>
46 46 #include <QtWidgets/QGraphicsSceneHoverEvent>
47 47 #include <QtWidgets/QApplication>
48 48 #include <QtCore/QTimer>
49 49 #include <QtCore/QThread>
50 50
51 51 QT_CHARTS_BEGIN_NAMESPACE
52 52
53 53 /*!
54 54 \qmltype ChartView
55 55 \instantiates DeclarativeChart
56 56 \inqmlmodule QtCharts
57 57
58 58 \brief Chart element.
59 59
60 60 ChartView element is the parent that is responsible for showing different chart series types.
61 61
62 62 The following QML shows how to create a simple chart with one pie series:
63 63 \snippet qmlpiechart/qml/qmlpiechart/main.qml 1
64 64 \snippet qmlpiechart/qml/qmlpiechart/main.qml 2
65 65 \snippet qmlpiechart/qml/qmlpiechart/main.qml 3
66 66
67 67 \beginfloatleft
68 68 \image examples_qmlpiechart.png
69 69 \endfloat
70 70 \clearfloat
71 71 */
72 72
73 73 /*!
74 74 \qmlproperty Theme ChartView::theme
75 75 Theme defines the visual appearance of the chart, including for example colors, fonts, line
76 76 widths and chart background.
77 77 */
78 78
79 79 /*!
80 80 \qmlproperty Animation ChartView::animationOptions
81 81 Animation configuration of the chart. One of ChartView.NoAnimation, ChartView.GridAxisAnimations,
82 82 ChartView.SeriesAnimations or ChartView.AllAnimations.
83 83 */
84 84
85 85 /*!
86 86 \qmlproperty Font ChartView::titleFont
87 87 The title font of the chart.
88 88
89 89 See the Qt documentation for more details of Font.
90 90 */
91 91
92 92 /*!
93 93 \qmlproperty string ChartView::title
94 94 The title of the chart, shown on top of the chart.
95 95 \sa ChartView::titleColor
96 96 */
97 97
98 98 /*!
99 99 \qmlproperty color ChartView::titleColor
100 100 The color of the title text.
101 101 */
102 102
103 103 /*!
104 104 \qmlproperty Legend ChartView::legend
105 105 The legend of the chart. Legend lists all the series, pie slices and bar sets added on the chart.
106 106 */
107 107
108 108 /*!
109 109 \qmlproperty int ChartView::count
110 110 The count of series added to the chart.
111 111 */
112 112
113 113 /*!
114 114 \qmlproperty color ChartView::backgroundColor
115 115 The color of the chart's background. By default background color is defined by chart theme.
116 116 \sa ChartView::theme
117 117 */
118 118
119 119 /*!
120 120 \qmlproperty real ChartView::backgroundRoundness
121 121 The diameter of the rounding cirle at the corners of the chart background.
122 122 */
123 123
124 124 /*!
125 125 \qmlproperty color ChartView::plotAreaColor
126 126 The color of the background of the chart's plot area. By default plot area background uses chart's
127 127 background color.
128 128 \sa ChartView::backgroundColor
129 129 */
130 130
131 131 /*!
132 132 \qmlproperty bool ChartView::dropShadowEnabled
133 133 The chart's border drop shadow. Set to true to enable drop shadow.
134 134 */
135 135
136 136 /*!
137 137 \qmlproperty real ChartView::topMargin
138 138 Deprecated; use margins instead.
139 139 */
140 140
141 141 /*!
142 142 \qmlproperty real ChartView::bottomMargin
143 143 Deprecated; use margins instead.
144 144 */
145 145
146 146 /*!
147 147 \qmlproperty real ChartView::leftMargin
148 148 Deprecated; use margins instead.
149 149 */
150 150
151 151 /*!
152 152 \qmlproperty real ChartView::rightMargin
153 153 Deprecated; use margins instead.
154 154 */
155 155
156 156 /*!
157 157 \qmlproperty Margins ChartView::minimumMargins
158 158 Deprecated; use margins instead.
159 159 The minimum margins allowed between the outer bounds and the plotArea of the ChartView. Margins
160 160 area of ChartView is used for drawing title, axes and legend. Please note that setting the
161 161 properties of minimumMargins may be bigger than the defined value, depending on other ChartView
162 162 properties that affect it's layout. If you need to know the actual plotting area used at any
163 163 given time, you can check ChartView::plotArea instead.
164 164 */
165 165
166 166 /*!
167 167 \qmlproperty rect ChartView::plotArea
168 168 The area on the ChartView that is used for drawing series. This is the ChartView rect without the
169 169 margins.
170 170 \sa ChartView::minimumMargins
171 171 */
172 172
173 173 /*!
174 174 \qmlproperty Margins ChartView::margins
175 175 The minimum margins allowed between the outer bounds and the plotArea of the ChartView. Margins
176 176 area of ChartView is used for drawing title, axes and legend.
177 177 */
178 178
179 179 /*!
180 180 \qmlproperty bool ChartView::localizeNumbers
181 181 \since QtCharts 2.0
182 182 When \c{true}, all generated numbers appearing in various series and axis labels will be
183 183 localized using the default QLocale of the application, which defaults to the system locale.
184 184 When \c{false}, the "C" locale is always used.
185 185 Defaults to \c{false}.
186 186
187 187 \sa locale
188 188 */
189 189
190 190 /*!
191 191 \qmlproperty locale ChartView::locale
192 192 \since QtCharts 2.0
193 193 Sets the locale used to format various chart labels when localizeNumbers is \c{true}.
194 194 This also determines the locale used to format DateTimeAxis labels regardless of
195 195 localizeNumbers property.
196 196 Defaults to application default locale at the time the chart is constructed.
197 197
198 198 \sa localizeNumbers
199 199 */
200 200
201 201 /*!
202 202 \qmlmethod AbstractSeries ChartView::series(int index)
203 203 Returns the series with \a index on the chart. This allows you to loop through the series of a chart together with
204 204 the count property of the chart.
205 205 */
206 206
207 207 /*!
208 208 \qmlmethod AbstractSeries ChartView::series(string name)
209 209 Returns the first series on the chart with \a name. If there is no series with that name, returns null.
210 210 */
211 211
212 212 /*!
213 213 \qmlmethod AbstractSeries ChartView::createSeries(SeriesType type, string name, AbstractAxis axisX, AbstractAxis axisY)
214 214 Creates a series object of \a type to the chart with name \a name, optional axis \a axisX and
215 215 optional axis \a axisY. For example:
216 216 \code
217 217 // lineSeries is a LineSeries object that has already been added to the ChartView; re-use it's axes
218 218 var myAxisX = chartView.axisX(lineSeries);
219 219 var myAxisY = chartView.axisY(lineSeries);
220 220 var scatter = chartView.createSeries(ChartView.SeriesTypeScatter, "scatter series", myAxisX, myAxisY);
221 221 \endcode
222 222 */
223 223
224 224 /*!
225 225 \qmlmethod ChartView::removeSeries(AbstractSeries series)
226 226 Removes the \a series from the chart. The series object is also destroyed.
227 227 */
228 228
229 229 /*!
230 230 \qmlmethod ChartView::removeAllSeries()
231 231 Removes all series from the chart. All the series objects are also destroyed.
232 232 */
233 233
234 234 /*!
235 235 \qmlmethod Axis ChartView::axisX(AbstractSeries series)
236 236 The x-axis of the series.
237 237 */
238 238
239 239 /*!
240 240 \qmlmethod Axis ChartView::axisY(AbstractSeries series)
241 241 The y-axis of the series.
242 242 */
243 243
244 244 /*!
245 245 \qmlmethod ChartView::zoomY(real factor)
246 246 Zooms in by \a factor on the center of the chart.
247 247 */
248 248
249 249 /*!
250 250 \qmlmethod ChartView::scrollLeft(real pixels)
251 251 Scrolls to left by \a pixels. This is a convenience function that suits for example for key navigation.
252 252 */
253 253
254 254 /*!
255 255 \qmlmethod ChartView::scrollRight(real pixels)
256 256 Scrolls to right by \a pixels. This is a convenience function that suits for example for key navigation.
257 257 */
258 258
259 259 /*!
260 260 \qmlmethod ChartView::scrollUp(real pixels)
261 261 Scrolls up by \a pixels. This is a convenience function that suits for example for key navigation.
262 262 */
263 263
264 264 /*!
265 265 \qmlmethod ChartView::scrollDown(real pixels)
266 266 Scrolls down by \a pixels. This is a convenience function that suits for example for key navigation.
267 267 */
268 268
269 269 /*!
270 270 \qmlsignal ChartView::seriesAdded(AbstractSeries series)
271 271 The \a series has been added to the chart.
272 272 */
273 273
274 274 /*!
275 275 \qmlsignal ChartView::seriesRemoved(AbstractSeries series)
276 276 The \a series has been removed from the chart. Please note that \a series is no longer a valid
277 277 object after the signal handler has completed.
278 278 */
279 279
280 280 DeclarativeChart::DeclarativeChart(QQuickItem *parent)
281 281 : QQuickPaintedItem(parent)
282 282 {
283 283 initChart(QChart::ChartTypeCartesian);
284 284 }
285 285
286 286 DeclarativeChart::DeclarativeChart(QChart::ChartType type, QQuickItem *parent)
287 287 : QQuickPaintedItem(parent)
288 288 {
289 289 initChart(type);
290 290 }
291 291
292 292 void DeclarativeChart::initChart(QChart::ChartType type)
293 293 {
294 294 m_currentSceneImage = 0;
295 295 m_guiThreadId = QThread::currentThreadId();
296 296 m_paintThreadId = 0;
297 297 m_updatePending = false;
298 298
299 299 if (type == QChart::ChartTypePolar)
300 300 m_chart = new QPolarChart();
301 301 else
302 302 m_chart = new QChart();
303 303
304 304 m_scene = new QGraphicsScene(this);
305 305 m_scene->addItem(m_chart);
306 306
307 307 setAntialiasing(QQuickItem::antialiasing());
308 308 connect(m_scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(sceneChanged(QList<QRectF>)));
309 309 connect(this, SIGNAL(antialiasingChanged(bool)), this, SLOT(handleAntialiasingChanged(bool)));
310 310
311 311 setAcceptedMouseButtons(Qt::AllButtons);
312 312 setAcceptHoverEvents(true);
313 313
314 314 m_margins = new DeclarativeMargins(this);
315 315 m_margins->setTop(m_chart->margins().top());
316 316 m_margins->setLeft(m_chart->margins().left());
317 317 m_margins->setRight(m_chart->margins().right());
318 318 m_margins->setBottom(m_chart->margins().bottom());
319 319 connect(m_margins, SIGNAL(topChanged(int,int,int,int)), this, SLOT(changeMinimumMargins(int,int,int,int)));
320 320 connect(m_margins, SIGNAL(bottomChanged(int,int,int,int)), this, SLOT(changeMinimumMargins(int,int,int,int)));
321 321 connect(m_margins, SIGNAL(leftChanged(int,int,int,int)), this, SLOT(changeMinimumMargins(int,int,int,int)));
322 322 connect(m_margins, SIGNAL(rightChanged(int,int,int,int)), this, SLOT(changeMinimumMargins(int,int,int,int)));
323 323 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesAdded(QAbstractSeries*)));
324 324 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SIGNAL(seriesRemoved(QAbstractSeries*)));
325 325 connect(m_chart, &QChart::plotAreaChanged, this, &DeclarativeChart::plotAreaChanged);
326 326 }
327 327
328 328 void DeclarativeChart::handleSeriesAdded(QAbstractSeries *series)
329 329 {
330 330 emit seriesAdded(series);
331 331 }
332 332
333 333 void DeclarativeChart::changeMinimumMargins(int top, int bottom, int left, int right)
334 334 {
335 335 m_chart->setMargins(QMargins(left, top, right, bottom));
336 336 emit minimumMarginsChanged();
337 337 }
338 338
339 339 DeclarativeChart::~DeclarativeChart()
340 340 {
341 341 delete m_chart;
342 342 m_sceneImageLock.lock();
343 343 delete m_currentSceneImage;
344 344 m_currentSceneImage = 0;
345 345 m_sceneImageLock.unlock();
346 346 }
347 347
348 348 void DeclarativeChart::childEvent(QChildEvent *event)
349 349 {
350 350 if (event->type() == QEvent::ChildAdded) {
351 351 if (qobject_cast<QAbstractSeries *>(event->child())) {
352 352 m_chart->addSeries(qobject_cast<QAbstractSeries *>(event->child()));
353 353 }
354 354 }
355 355 }
356 356
357 357 void DeclarativeChart::componentComplete()
358 358 {
359 359 foreach (QObject *child, children()) {
360 360 if (qobject_cast<QAbstractSeries *>(child)) {
361 361 // Add series to the chart
362 362 QAbstractSeries *series = qobject_cast<QAbstractSeries *>(child);
363 363 m_chart->addSeries(series);
364 364
365 365 // Connect to axis changed signals (unless this is a pie series)
366 366 if (!qobject_cast<DeclarativePieSeries *>(series)) {
367 367 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
368 368 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXTopSet(QAbstractAxis*)));
369 369 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
370 370 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
371 371 }
372 372
373 373 initializeAxes(series);
374 374 }
375 375 }
376 376
377 377 QQuickItem::componentComplete();
378 378 }
379 379
380 380 void DeclarativeChart::seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
381 381 Qt::Orientations orientation,
382 382 Qt::Alignment alignment)
383 383 {
384 384 if (!series->attachedAxes().contains(axis)) {
385 385 // Remove & delete old axes that are not attached to any other series
386 386 foreach (QAbstractAxis* oldAxis, m_chart->axes(orientation, series)) {
387 387 bool otherAttachments = false;
388 388 if (oldAxis != axis) {
389 389 foreach (QAbstractSeries *oldSeries, m_chart->series()) {
390 390 if (oldSeries != series && oldSeries->attachedAxes().contains(oldAxis)) {
391 391 otherAttachments = true;
392 392 break;
393 393 }
394 394 }
395 395 if (!otherAttachments) {
396 396 m_chart->removeAxis(oldAxis);
397 397 delete oldAxis;
398 398 }
399 399 }
400 400 }
401 401 if (!m_chart->axes(orientation).contains(axis))
402 402 m_chart->addAxis(axis, alignment);
403 403
404 404 series->attachAxis(axis);
405 405 }
406 406 }
407 407
408 408 void DeclarativeChart::handleAxisXSet(QAbstractAxis *axis)
409 409 {
410 410 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
411 411 if (axis && s) {
412 412 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignBottom);
413 413 } else {
414 414 qWarning() << "Trying to set axisX to null.";
415 415 }
416 416 }
417 417
418 418 void DeclarativeChart::handleAxisXTopSet(QAbstractAxis *axis)
419 419 {
420 420 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
421 421 if (axis && s) {
422 422 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignTop);
423 423 } else {
424 424 qWarning() << "Trying to set axisXTop to null.";
425 425 }
426 426 }
427 427
428 428 void DeclarativeChart::handleAxisYSet(QAbstractAxis *axis)
429 429 {
430 430 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
431 431 if (axis && s) {
432 432 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignLeft);
433 433 } else {
434 434 qWarning() << "Trying to set axisY to null.";
435 435 }
436 436 }
437 437
438 438 void DeclarativeChart::handleAxisYRightSet(QAbstractAxis *axis)
439 439 {
440 440 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
441 441 if (axis && s) {
442 442 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignRight);
443 443 } else {
444 444 qWarning() << "Trying to set axisYRight to null.";
445 445 }
446 446 }
447 447
448 448 void DeclarativeChart::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
449 449 {
450 450 if (newGeometry.isValid()) {
451 451 if (newGeometry.width() > 0 && newGeometry.height() > 0) {
452 452 m_chart->resize(newGeometry.width(), newGeometry.height());
453 453 }
454 454 }
455 455 QQuickItem::geometryChanged(newGeometry, oldGeometry);
456 456 }
457 457
458 458 void DeclarativeChart::sceneChanged(QList<QRectF> region)
459 459 {
460 460 Q_UNUSED(region);
461 461
462 462 if (m_guiThreadId == m_paintThreadId) {
463 463 // Rendering in gui thread, no need for shenannigans, just update
464 464 update();
465 465 } else {
466 466 // Multi-threaded rendering, need to ensure scene is actually rendered in gui thread
467 467 if (!m_updatePending) {
468 468 m_updatePending = true;
469 469 // Do async render to avoid some unnecessary renders.
470 470 QTimer::singleShot(0, this, SLOT(renderScene()));
471 471 }
472 472 }
473 473 }
474 474
475 475 void DeclarativeChart::renderScene()
476 476 {
477 477 m_updatePending = false;
478 478 m_sceneImageLock.lock();
479 479 delete m_currentSceneImage;
480 480 m_currentSceneImage = new QImage(m_chart->size().toSize(), QImage::Format_ARGB32);
481 481 m_currentSceneImage->fill(Qt::transparent);
482 482 QPainter painter(m_currentSceneImage);
483 483 if (antialiasing())
484 484 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
485 485 QRect renderRect(QPoint(0, 0), m_chart->size().toSize());
486 486 m_scene->render(&painter, renderRect, renderRect);
487 487 m_sceneImageLock.unlock();
488 488
489 489 update();
490 490 }
491 491
492 492 void DeclarativeChart::paint(QPainter *painter)
493 493 {
494 494 if (!m_paintThreadId) {
495 495 m_paintThreadId = QThread::currentThreadId();
496 496 if (m_guiThreadId == m_paintThreadId) {
497 497 // No need for scene image in single threaded rendering, so delete
498 498 // the one that got made by default before the rendering type was
499 499 // detected.
500 500 delete m_currentSceneImage;
501 501 m_currentSceneImage = 0;
502 502 }
503 503 }
504 504
505 505 if (m_guiThreadId == m_paintThreadId) {
506 506 QRectF renderRect(QPointF(0, 0), m_chart->size());
507 507 m_scene->render(painter, renderRect, renderRect);
508 508 } else {
509 509 m_sceneImageLock.lock();
510 510 if (m_currentSceneImage) {
511 511 QRect imageRect(QPoint(0, 0), m_currentSceneImage->size());
512 512 QRect itemRect(QPoint(0, 0), QSize(width(), height()));
513 513 painter->drawImage(itemRect, *m_currentSceneImage, imageRect);
514 514 }
515 515 m_sceneImageLock.unlock();
516 516 }
517 517 }
518 518
519 519 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
520 520 {
521 521 m_mousePressScenePoint = event->pos();
522 522 m_mousePressScreenPoint = event->globalPos();
523 523 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
524 524 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
525 525 m_mousePressButton = event->button();
526 526 m_mousePressButtons = event->buttons();
527 527
528 528 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
529 529 mouseEvent.setWidget(0);
530 530 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
531 531 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
532 532 mouseEvent.setScenePos(m_mousePressScenePoint);
533 533 mouseEvent.setScreenPos(m_mousePressScreenPoint);
534 534 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
535 535 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
536 536 mouseEvent.setButtons(m_mousePressButtons);
537 537 mouseEvent.setButton(m_mousePressButton);
538 538 mouseEvent.setModifiers(event->modifiers());
539 539 mouseEvent.setAccepted(false);
540 540
541 541 QApplication::sendEvent(m_scene, &mouseEvent);
542 542 }
543 543
544 544 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
545 545 {
546 546 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
547 547 mouseEvent.setWidget(0);
548 548 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
549 549 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
550 550 mouseEvent.setScenePos(event->pos());
551 551 mouseEvent.setScreenPos(event->globalPos());
552 552 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
553 553 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
554 554 mouseEvent.setButtons(event->buttons());
555 555 mouseEvent.setButton(event->button());
556 556 mouseEvent.setModifiers(event->modifiers());
557 557 mouseEvent.setAccepted(false);
558 558
559 559 QApplication::sendEvent(m_scene, &mouseEvent);
560 560
561 561 m_mousePressButtons = event->buttons();
562 562 m_mousePressButton = Qt::NoButton;
563 563 }
564 564
565 565 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
566 566 {
567 567 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
568 568 // QGraphicsScene generates hover events from mouse move events, so we don't need
569 569 // to pass hover events there.
570 570 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
571 571 mouseEvent.setWidget(0);
572 572 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
573 573 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
574 574 mouseEvent.setScenePos(event->pos());
575 575 // Hover events do not have global pos in them, and the screen position doesn't seem to
576 576 // matter anyway in this use case, so just pass event pos instead of trying to
577 577 // calculate the real screen position.
578 578 mouseEvent.setScreenPos(event->pos());
579 579 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
580 580 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
581 581 mouseEvent.setButtons(m_mousePressButtons);
582 582 mouseEvent.setButton(m_mousePressButton);
583 583 mouseEvent.setModifiers(event->modifiers());
584 584 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
585 585 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
586 586 mouseEvent.setAccepted(false);
587 587
588 588 QApplication::sendEvent(m_scene, &mouseEvent);
589 589 }
590 590
591 591 void DeclarativeChart::handleAntialiasingChanged(bool enable)
592 592 {
593 593 setAntialiasing(enable);
594 594 }
595 595
596 596 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
597 597 {
598 598 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
599 599 if (chartTheme != m_chart->theme())
600 600 m_chart->setTheme(chartTheme);
601 601 }
602 602
603 603 DeclarativeChart::Theme DeclarativeChart::theme()
604 604 {
605 605 return (DeclarativeChart::Theme) m_chart->theme();
606 606 }
607 607
608 608 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
609 609 {
610 610 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
611 611 if (animationOptions != m_chart->animationOptions())
612 612 m_chart->setAnimationOptions(animationOptions);
613 613 }
614 614
615 615 DeclarativeChart::Animation DeclarativeChart::animationOptions()
616 616 {
617 617 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
618 618 return DeclarativeChart::AllAnimations;
619 619 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
620 620 return DeclarativeChart::GridAxisAnimations;
621 621 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
622 622 return DeclarativeChart::SeriesAnimations;
623 623 else
624 624 return DeclarativeChart::NoAnimation;
625 625 }
626 626
627 627 void DeclarativeChart::setTitle(QString title)
628 628 {
629 629 if (title != m_chart->title())
630 630 m_chart->setTitle(title);
631 631 }
632 632 QString DeclarativeChart::title()
633 633 {
634 634 return m_chart->title();
635 635 }
636 636
637 637 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
638 638 {
639 639 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
640 640 if (axes.count())
641 641 return axes[0];
642 642 return 0;
643 643 }
644 644
645 645 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
646 646 {
647 647 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
648 648 if (axes.count())
649 649 return axes[0];
650 650 return 0;
651 651 }
652 652
653 653 QLegend *DeclarativeChart::legend()
654 654 {
655 655 return m_chart->legend();
656 656 }
657 657
658 658 void DeclarativeChart::setTitleColor(QColor color)
659 659 {
660 660 QBrush b = m_chart->titleBrush();
661 661 if (color != b.color()) {
662 662 b.setColor(color);
663 663 m_chart->setTitleBrush(b);
664 664 emit titleColorChanged(color);
665 665 }
666 666 }
667 667
668 668 QFont DeclarativeChart::titleFont() const
669 669 {
670 670 return m_chart->titleFont();
671 671 }
672 672
673 673 void DeclarativeChart::setTitleFont(const QFont &font)
674 674 {
675 675 m_chart->setTitleFont(font);
676 676 }
677 677
678 678 QColor DeclarativeChart::titleColor()
679 679 {
680 680 return m_chart->titleBrush().color();
681 681 }
682 682
683 683 void DeclarativeChart::setBackgroundColor(QColor color)
684 684 {
685 685 QBrush b = m_chart->backgroundBrush();
686 686 if (b.style() != Qt::SolidPattern || color != b.color()) {
687 687 b.setStyle(Qt::SolidPattern);
688 688 b.setColor(color);
689 689 m_chart->setBackgroundBrush(b);
690 690 emit backgroundColorChanged();
691 691 }
692 692 }
693 693
694 694 QColor DeclarativeChart::backgroundColor()
695 695 {
696 696 return m_chart->backgroundBrush().color();
697 697 }
698 698
699 699 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
700 700 {
701 701 QBrush b = m_chart->plotAreaBackgroundBrush();
702 702 if (b.style() != Qt::SolidPattern || color != b.color()) {
703 703 b.setStyle(Qt::SolidPattern);
704 704 b.setColor(color);
705 705 m_chart->setPlotAreaBackgroundBrush(b);
706 706 m_chart->setPlotAreaBackgroundVisible(true);
707 707 emit plotAreaColorChanged();
708 708 }
709 709 }
710 710
711 711 QColor QtCharts::DeclarativeChart::plotAreaColor()
712 712 {
713 713 return m_chart->plotAreaBackgroundBrush().color();
714 714 }
715 715
716 716 void DeclarativeChart::setLocalizeNumbers(bool localize)
717 717 {
718 718 if (m_chart->localizeNumbers() != localize) {
719 719 m_chart->setLocalizeNumbers(localize);
720 720 emit localizeNumbersChanged();
721 721 }
722 722 }
723 723
724 724 bool DeclarativeChart::localizeNumbers() const
725 725 {
726 726 return m_chart->localizeNumbers();
727 727 }
728 728
729 729 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
730 730 {
731 731 if (m_chart->locale() != locale) {
732 732 m_chart->setLocale(locale);
733 733 emit localeChanged();
734 734 }
735 735 }
736 736
737 737 QLocale QtCharts::DeclarativeChart::locale() const
738 738 {
739 739 return m_chart->locale();
740 740 }
741 741
742 742 int DeclarativeChart::count()
743 743 {
744 744 return m_chart->series().count();
745 745 }
746 746
747 747 void DeclarativeChart::setDropShadowEnabled(bool enabled)
748 748 {
749 749 if (enabled != m_chart->isDropShadowEnabled()) {
750 750 m_chart->setDropShadowEnabled(enabled);
751 751 dropShadowEnabledChanged(enabled);
752 752 }
753 753 }
754 754
755 755 bool DeclarativeChart::dropShadowEnabled()
756 756 {
757 757 return m_chart->isDropShadowEnabled();
758 758 }
759 759
760 760 qreal DeclarativeChart::backgroundRoundness() const
761 761 {
762 762 return m_chart->backgroundRoundness();
763 763 }
764 764
765 765 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
766 766 {
767 767 if (m_chart->backgroundRoundness() != diameter) {
768 768 m_chart->setBackgroundRoundness(diameter);
769 769 emit backgroundRoundnessChanged(diameter);
770 770 }
771 771 }
772 772
773 773 qreal DeclarativeChart::topMargin()
774 774 {
775 775 qWarning() << "ChartView.topMargin is deprecated. Use margins instead.";
776 776 return m_chart->margins().top();
777 777 }
778 778
779 779 qreal DeclarativeChart::bottomMargin()
780 780 {
781 781 qWarning() << "ChartView.bottomMargin is deprecated. Use margins instead.";
782 782 return m_chart->margins().bottom();
783 783 }
784 784
785 785 qreal DeclarativeChart::leftMargin()
786 786 {
787 787 qWarning() << "ChartView.leftMargin is deprecated. Use margins instead.";
788 788 return m_chart->margins().left();
789 789 }
790 790
791 791 qreal DeclarativeChart::rightMargin()
792 792 {
793 793 qWarning() << "ChartView.rightMargin is deprecated. Use margins instead.";
794 794 return m_chart->margins().right();
795 795 }
796 796
797 797 void DeclarativeChart::zoom(qreal factor)
798 798 {
799 799 m_chart->zoom(factor);
800 800 }
801 801
802 802 void DeclarativeChart::scrollLeft(qreal pixels)
803 803 {
804 804 m_chart->scroll(-pixels, 0);
805 805 }
806 806
807 807 void DeclarativeChart::scrollRight(qreal pixels)
808 808 {
809 809 m_chart->scroll(pixels, 0);
810 810 }
811 811
812 812 void DeclarativeChart::scrollUp(qreal pixels)
813 813 {
814 814 m_chart->scroll(0, pixels);
815 815 }
816 816
817 817 void DeclarativeChart::scrollDown(qreal pixels)
818 818 {
819 819 m_chart->scroll(0, -pixels);
820 820 }
821 821
822 822 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
823 823 {
824 824 return QQmlListProperty<QAbstractAxis>(this, 0,
825 825 &DeclarativeChart::axesAppendFunc,
826 826 &DeclarativeChart::axesCountFunc,
827 827 &DeclarativeChart::axesAtFunc,
828 828 &DeclarativeChart::axesClearFunc);
829 829 }
830 830
831 831 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
832 832 {
833 833 // Empty implementation
834 834 Q_UNUSED(list);
835 835 Q_UNUSED(element);
836 836 }
837 837
838 838 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
839 839 {
840 840 if (qobject_cast<DeclarativeChart *>(list->object)) {
841 841 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
842 842 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
843 843 }
844 844 return 0;
845 845 }
846 846
847 847 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
848 848 {
849 849 if (qobject_cast<DeclarativeChart *>(list->object)) {
850 850 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
851 851 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
852 852 return axes.at(index);
853 853 }
854 854 return 0;
855 855 }
856 856
857 857 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
858 858 {
859 859 // Empty implementation
860 860 Q_UNUSED(list);
861 861 }
862 862
863 863
864 864 QAbstractSeries *DeclarativeChart::series(int index)
865 865 {
866 866 if (index < m_chart->series().count()) {
867 867 return m_chart->series().at(index);
868 868 }
869 869 return 0;
870 870 }
871 871
872 872 QAbstractSeries *DeclarativeChart::series(QString seriesName)
873 873 {
874 874 foreach (QAbstractSeries *series, m_chart->series()) {
875 875 if (series->name() == seriesName)
876 876 return series;
877 877 }
878 878 return 0;
879 879 }
880 880
881 881 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
882 882 {
883 883 QAbstractSeries *series = 0;
884 884
885 885 switch (type) {
886 886 case DeclarativeChart::SeriesTypeLine:
887 887 series = new DeclarativeLineSeries();
888 888 break;
889 889 case DeclarativeChart::SeriesTypeArea: {
890 890 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
891 area->setUpperSeries(new DeclarativeLineSeries());
891 DeclarativeLineSeries *line = new DeclarativeLineSeries();
892 line->setParent(area);
893 area->setUpperSeries(line);
892 894 series = area;
893 895 break;
894 896 }
895 897 case DeclarativeChart::SeriesTypeStackedBar:
896 898 series = new DeclarativeStackedBarSeries();
897 899 break;
898 900 case DeclarativeChart::SeriesTypePercentBar:
899 901 series = new DeclarativePercentBarSeries();
900 902 break;
901 903 case DeclarativeChart::SeriesTypeBar:
902 904 series = new DeclarativeBarSeries();
903 905 break;
904 906 case DeclarativeChart::SeriesTypeHorizontalBar:
905 907 series = new DeclarativeHorizontalBarSeries();
906 908 break;
907 909 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
908 910 series = new DeclarativeHorizontalPercentBarSeries();
909 911 break;
910 912 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
911 913 series = new DeclarativeHorizontalStackedBarSeries();
912 914 break;
913 915 case DeclarativeChart::SeriesTypeBoxPlot:
914 916 series = new DeclarativeBoxPlotSeries();
915 917 break;
916 918 case DeclarativeChart::SeriesTypePie:
917 919 series = new DeclarativePieSeries();
918 920 break;
919 921 case DeclarativeChart::SeriesTypeScatter:
920 922 series = new DeclarativeScatterSeries();
921 923 break;
922 924 case DeclarativeChart::SeriesTypeSpline:
923 925 series = new DeclarativeSplineSeries();
924 926 break;
925 927 default:
926 928 qWarning() << "Illegal series type";
927 929 }
928 930
929 931 if (series) {
930 932 // Connect to axis changed signals (unless this is a pie series)
931 933 if (!qobject_cast<DeclarativePieSeries *>(series)) {
932 934 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
933 935 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
934 936 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
935 937 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
936 938 }
937 939
938 940 series->setName(name);
939 941 m_chart->addSeries(series);
940 942
941 943 if (!axisX || !axisY)
942 944 initializeAxes(series);
943 945
944 946 if (axisX)
945 947 setAxisX(axisX, series);
946 948 if (axisY)
947 949 setAxisY(axisY, series);
948 950 }
949 951
950 952 return series;
951 953 }
952 954
953 955 void DeclarativeChart::removeSeries(QAbstractSeries *series)
954 956 {
955 957 if (series)
956 958 m_chart->removeSeries(series);
957 959 else
958 960 qWarning("removeSeries: cannot remove null");
959 961 }
960 962
961 963 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
962 964 {
963 965 if (axis && series)
964 966 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
965 967 }
966 968
967 969 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
968 970 {
969 971 if (axis && series)
970 972 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
971 973 }
972 974
973 975 void DeclarativeChart::createDefaultAxes()
974 976 {
975 977 qWarning() << "ChartView.createDefaultAxes() is deprecated. Axes are created automatically.";
976 978 }
977 979
978 980 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
979 981 {
980 982 if (!series) {
981 983 qWarning() << "No axis type defined for null series";
982 984 return 0;
983 985 }
984 986
985 987 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
986 988 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
987 989 return existingAxis;
988 990 }
989 991
990 992 switch (series->d_ptr->defaultAxisType(orientation)) {
991 993 case QAbstractAxis::AxisTypeValue:
992 994 return new QValueAxis(this);
993 995 case QAbstractAxis::AxisTypeBarCategory:
994 996 return new QBarCategoryAxis(this);
995 997 case QAbstractAxis::AxisTypeCategory:
996 998 return new QCategoryAxis(this);
997 999 #ifndef QT_ON_ARM
998 1000 case QAbstractAxis::AxisTypeDateTime:
999 1001 return new QDateTimeAxis(this);
1000 1002 #endif
1001 1003 case QAbstractAxis::AxisTypeLogValue:
1002 1004 return new QLogValueAxis(this);
1003 1005 default:
1004 1006 // assume AxisTypeNoAxis
1005 1007 return 0;
1006 1008 }
1007 1009 }
1008 1010
1009 1011 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1010 1012 {
1011 1013 if (qobject_cast<DeclarativeLineSeries *>(series))
1012 1014 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1013 1015 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1014 1016 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1015 1017 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1016 1018 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1017 1019 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1018 1020 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1019 1021 else if (qobject_cast<DeclarativeBarSeries *>(series))
1020 1022 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1021 1023 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1022 1024 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1023 1025 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1024 1026 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1025 1027 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1026 1028 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1027 1029 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1028 1030 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1029 1031 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1030 1032 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1031 1033 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1032 1034 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1033 1035 // else: do nothing
1034 1036 }
1035 1037
1036 1038 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1037 1039 {
1038 1040 // Initialize axis X
1039 1041 if (axes->axisX())
1040 1042 axes->emitAxisXChanged();
1041 1043 else if (axes->axisXTop())
1042 1044 axes->emitAxisXTopChanged();
1043 1045 else
1044 1046 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1045 1047
1046 1048 // Initialize axis Y
1047 1049 if (axes->axisY())
1048 1050 axes->emitAxisYChanged();
1049 1051 else if (axes->axisYRight())
1050 1052 axes->emitAxisYRightChanged();
1051 1053 else
1052 1054 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1053 1055 }
1054 1056
1055 1057 #include "moc_declarativechart.cpp"
1056 1058
1057 1059 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now