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