##// END OF EJS Templates
Respect the devicePixelRatio when rendering the scene...
Andy Shaw -
r2859:e59db7a88a36
parent child
Show More
@@ -1,1240 +1,1242
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 337 m_sceneImageNeedsClear = false;
338 338 m_guiThreadId = QThread::currentThreadId();
339 339 m_paintThreadId = 0;
340 340 m_updatePending = false;
341 341
342 342 setFlag(ItemHasContents, true);
343 343
344 344 if (type == QChart::ChartTypePolar)
345 345 m_chart = new QPolarChart();
346 346 else
347 347 m_chart = new QChart();
348 348
349 349 m_chart->d_ptr->m_presenter->glSetUseWidget(false);
350 350 m_glXYDataManager = m_chart->d_ptr->m_dataset->glXYSeriesDataManager();
351 351
352 352 m_scene = new QGraphicsScene(this);
353 353 m_scene->addItem(m_chart);
354 354
355 355 setAntialiasing(QQuickItem::antialiasing());
356 356 connect(m_scene, &QGraphicsScene::changed, this, &DeclarativeChart::sceneChanged);
357 357 connect(this, &DeclarativeChart::needRender, this, &DeclarativeChart::renderScene,
358 358 Qt::QueuedConnection);
359 359 connect(this, SIGNAL(antialiasingChanged(bool)), this, SLOT(handleAntialiasingChanged(bool)));
360 360
361 361 setAcceptedMouseButtons(Qt::AllButtons);
362 362 setAcceptHoverEvents(true);
363 363
364 364 m_margins = new DeclarativeMargins(this);
365 365 m_margins->setTop(m_chart->margins().top());
366 366 m_margins->setLeft(m_chart->margins().left());
367 367 m_margins->setRight(m_chart->margins().right());
368 368 m_margins->setBottom(m_chart->margins().bottom());
369 369 connect(m_margins, SIGNAL(topChanged(int,int,int,int)),
370 370 this, SLOT(changeMargins(int,int,int,int)));
371 371 connect(m_margins, SIGNAL(bottomChanged(int,int,int,int)),
372 372 this, SLOT(changeMargins(int,int,int,int)));
373 373 connect(m_margins, SIGNAL(leftChanged(int,int,int,int)),
374 374 this, SLOT(changeMargins(int,int,int,int)));
375 375 connect(m_margins, SIGNAL(rightChanged(int,int,int,int)),
376 376 this, SLOT(changeMargins(int,int,int,int)));
377 377 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesAdded(QAbstractSeries*)));
378 378 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SIGNAL(seriesRemoved(QAbstractSeries*)));
379 379 connect(m_chart, &QChart::plotAreaChanged, this, &DeclarativeChart::plotAreaChanged);
380 380 }
381 381
382 382 void DeclarativeChart::handleSeriesAdded(QAbstractSeries *series)
383 383 {
384 384 emit seriesAdded(series);
385 385 }
386 386
387 387 void DeclarativeChart::changeMargins(int top, int bottom, int left, int right)
388 388 {
389 389 m_chart->setMargins(QMargins(left, top, right, bottom));
390 390 emit marginsChanged();
391 391 }
392 392
393 393 DeclarativeChart::~DeclarativeChart()
394 394 {
395 395 delete m_chart;
396 396 delete m_sceneImage;
397 397 }
398 398
399 399 void DeclarativeChart::childEvent(QChildEvent *event)
400 400 {
401 401 if (event->type() == QEvent::ChildAdded) {
402 402 if (qobject_cast<QAbstractSeries *>(event->child())) {
403 403 m_chart->addSeries(qobject_cast<QAbstractSeries *>(event->child()));
404 404 }
405 405 }
406 406 }
407 407
408 408 void DeclarativeChart::componentComplete()
409 409 {
410 410 foreach (QObject *child, children()) {
411 411 if (qobject_cast<QAbstractSeries *>(child)) {
412 412 // Add series to the chart
413 413 QAbstractSeries *series = qobject_cast<QAbstractSeries *>(child);
414 414 m_chart->addSeries(series);
415 415
416 416 // Connect to axis changed signals (unless this is a pie series)
417 417 if (!qobject_cast<DeclarativePieSeries *>(series)) {
418 418 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
419 419 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXTopSet(QAbstractAxis*)));
420 420 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
421 421 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
422 422 }
423 423
424 424 initializeAxes(series);
425 425 }
426 426 }
427 427
428 428 QQuickItem::componentComplete();
429 429 }
430 430
431 431 void DeclarativeChart::seriesAxisAttachHelper(QAbstractSeries *series, QAbstractAxis *axis,
432 432 Qt::Orientations orientation,
433 433 Qt::Alignment alignment)
434 434 {
435 435 if (!series->attachedAxes().contains(axis)) {
436 436 // Remove & delete old axes that are not attached to any other series
437 437 foreach (QAbstractAxis* oldAxis, m_chart->axes(orientation, series)) {
438 438 bool otherAttachments = false;
439 439 if (oldAxis != axis) {
440 440 foreach (QAbstractSeries *oldSeries, m_chart->series()) {
441 441 if (oldSeries != series && oldSeries->attachedAxes().contains(oldAxis)) {
442 442 otherAttachments = true;
443 443 break;
444 444 }
445 445 }
446 446 if (!otherAttachments) {
447 447 m_chart->removeAxis(oldAxis);
448 448 delete oldAxis;
449 449 }
450 450 }
451 451 }
452 452 if (!m_chart->axes(orientation).contains(axis))
453 453 m_chart->addAxis(axis, alignment);
454 454
455 455 series->attachAxis(axis);
456 456 }
457 457 }
458 458
459 459 void DeclarativeChart::handleAxisXSet(QAbstractAxis *axis)
460 460 {
461 461 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
462 462 if (axis && s) {
463 463 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignBottom);
464 464 } else {
465 465 qWarning() << "Trying to set axisX to null.";
466 466 }
467 467 }
468 468
469 469 void DeclarativeChart::handleAxisXTopSet(QAbstractAxis *axis)
470 470 {
471 471 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
472 472 if (axis && s) {
473 473 seriesAxisAttachHelper(s, axis, Qt::Horizontal, Qt::AlignTop);
474 474 } else {
475 475 qWarning() << "Trying to set axisXTop to null.";
476 476 }
477 477 }
478 478
479 479 void DeclarativeChart::handleAxisYSet(QAbstractAxis *axis)
480 480 {
481 481 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
482 482 if (axis && s) {
483 483 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignLeft);
484 484 } else {
485 485 qWarning() << "Trying to set axisY to null.";
486 486 }
487 487 }
488 488
489 489 void DeclarativeChart::handleAxisYRightSet(QAbstractAxis *axis)
490 490 {
491 491 QAbstractSeries *s = qobject_cast<QAbstractSeries *>(sender());
492 492 if (axis && s) {
493 493 seriesAxisAttachHelper(s, axis, Qt::Vertical, Qt::AlignRight);
494 494 } else {
495 495 qWarning() << "Trying to set axisYRight to null.";
496 496 }
497 497 }
498 498
499 499 void DeclarativeChart::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
500 500 {
501 501 if (newGeometry.isValid()) {
502 502 if (newGeometry.width() > 0 && newGeometry.height() > 0) {
503 503 m_chart->resize(newGeometry.width(), newGeometry.height());
504 504 }
505 505 }
506 506 QQuickItem::geometryChanged(newGeometry, oldGeometry);
507 507 }
508 508
509 509 QSGNode *DeclarativeChart::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
510 510 {
511 511 DeclarativeChartNode *node = static_cast<DeclarativeChartNode *>(oldNode);
512 512
513 513 if (!node) {
514 514 node = new DeclarativeChartNode(window());
515 515 connect(window(), &QQuickWindow::beforeRendering,
516 516 node->glRenderNode(), &DeclarativeRenderNode::render);
517 517 }
518 518
519 519 const QRectF &bRect = boundingRect();
520 520
521 521 // Update GL data
522 522 if (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty()) {
523 523 const QRectF &plotArea = m_chart->plotArea();
524 524 const QSizeF &chartAreaSize = m_chart->size();
525 525
526 526 // We can't use chart's plot area directly, as graphicscene has some internal minimum size
527 527 const qreal normalizedX = plotArea.x() / chartAreaSize.width();
528 528 const qreal normalizedY = plotArea.y() / chartAreaSize.height();
529 529 const qreal normalizedWidth = plotArea.width() / chartAreaSize.width();
530 530 const qreal normalizedHeight = plotArea.height() / chartAreaSize.height();
531 531
532 532 QRectF adjustedPlotArea(normalizedX * bRect.width(),
533 533 normalizedY * bRect.height(),
534 534 normalizedWidth * bRect.width(),
535 535 normalizedHeight * bRect.height());
536 536
537 537 const QSize &adjustedPlotSize = adjustedPlotArea.size().toSize();
538 538 if (adjustedPlotSize != node->glRenderNode()->textureSize())
539 539 node->glRenderNode()->setTextureSize(adjustedPlotSize);
540 540
541 541 node->glRenderNode()->setRect(adjustedPlotArea);
542 542 node->glRenderNode()->setSeriesData(m_glXYDataManager->mapDirty(),
543 543 m_glXYDataManager->dataMap());
544 544
545 545 // Clear dirty flags from original xy data
546 546 m_glXYDataManager->clearAllDirty();
547 547 }
548 548
549 549 // Copy chart (if dirty) to chart node
550 550 if (m_sceneImageDirty) {
551 551 node->createTextureFromImage(*m_sceneImage);
552 552 m_sceneImageDirty = false;
553 553 }
554 554
555 555 node->setRect(bRect);
556 556
557 557 return node;
558 558 }
559 559
560 560 void DeclarativeChart::sceneChanged(QList<QRectF> region)
561 561 {
562 562 const int count = region.size();
563 563 const qreal limitSize = 0.01;
564 564 if (count && !m_updatePending) {
565 565 qreal totalSize = 0.0;
566 566 for (int i = 0; i < count; i++) {
567 567 const QRectF &reg = region.at(i);
568 568 totalSize += (reg.height() * reg.width());
569 569 if (totalSize >= limitSize)
570 570 break;
571 571 }
572 572 // Ignore region updates that change less than small fraction of a pixel, as there is
573 573 // little point regenerating the image in these cases. These are typically cases
574 574 // where OpenGL series are drawn to otherwise static chart.
575 575 if (totalSize >= limitSize) {
576 576 m_updatePending = true;
577 577 // Do async render to avoid some unnecessary renders.
578 578 emit needRender();
579 579 } else {
580 580 // We do want to call update to trigger possible gl series updates.
581 581 update();
582 582 }
583 583 }
584 584 }
585 585
586 586 void DeclarativeChart::renderScene()
587 587 {
588 588 m_updatePending = false;
589 589 m_sceneImageDirty = true;
590 590 QSize chartSize = m_chart->size().toSize();
591 591 if (!m_sceneImage || chartSize != m_sceneImage->size()) {
592 592 delete m_sceneImage;
593 m_sceneImage = new QImage(chartSize, QImage::Format_ARGB32);
593 qreal dpr = window() ? window()->devicePixelRatio() : 1.0;
594 m_sceneImage = new QImage(chartSize * dpr, QImage::Format_ARGB32);
595 m_sceneImage->setDevicePixelRatio(dpr);
594 596 m_sceneImageNeedsClear = true;
595 597 }
596 598
597 599 if (m_sceneImageNeedsClear) {
598 600 m_sceneImage->fill(Qt::transparent);
599 601 // Don't clear the flag if chart background has any transparent element to it
600 602 if (m_chart->backgroundBrush().color().alpha() == 0xff && !m_chart->isDropShadowEnabled())
601 603 m_sceneImageNeedsClear = false;
602 604 }
603 605 QPainter painter(m_sceneImage);
604 606 if (antialiasing()) {
605 607 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
606 608 | QPainter::SmoothPixmapTransform);
607 609 }
608 610 QRect renderRect(QPoint(0, 0), chartSize);
609 611 m_scene->render(&painter, renderRect, renderRect);
610 612 update();
611 613 }
612 614
613 615 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
614 616 {
615 617 m_mousePressScenePoint = event->pos();
616 618 m_mousePressScreenPoint = event->globalPos();
617 619 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
618 620 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
619 621 m_mousePressButton = event->button();
620 622 m_mousePressButtons = event->buttons();
621 623
622 624 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
623 625 mouseEvent.setWidget(0);
624 626 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
625 627 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
626 628 mouseEvent.setScenePos(m_mousePressScenePoint);
627 629 mouseEvent.setScreenPos(m_mousePressScreenPoint);
628 630 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
629 631 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
630 632 mouseEvent.setButtons(m_mousePressButtons);
631 633 mouseEvent.setButton(m_mousePressButton);
632 634 mouseEvent.setModifiers(event->modifiers());
633 635 mouseEvent.setAccepted(false);
634 636
635 637 QApplication::sendEvent(m_scene, &mouseEvent);
636 638 }
637 639
638 640 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
639 641 {
640 642 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
641 643 mouseEvent.setWidget(0);
642 644 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
643 645 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
644 646 mouseEvent.setScenePos(event->pos());
645 647 mouseEvent.setScreenPos(event->globalPos());
646 648 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
647 649 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
648 650 mouseEvent.setButtons(event->buttons());
649 651 mouseEvent.setButton(event->button());
650 652 mouseEvent.setModifiers(event->modifiers());
651 653 mouseEvent.setAccepted(false);
652 654
653 655 QApplication::sendEvent(m_scene, &mouseEvent);
654 656
655 657 m_mousePressButtons = event->buttons();
656 658 m_mousePressButton = Qt::NoButton;
657 659 }
658 660
659 661 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
660 662 {
661 663 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
662 664 // QGraphicsScene generates hover events from mouse move events, so we don't need
663 665 // to pass hover events there.
664 666 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
665 667 mouseEvent.setWidget(0);
666 668 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
667 669 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
668 670 mouseEvent.setScenePos(event->pos());
669 671 // Hover events do not have global pos in them, and the screen position doesn't seem to
670 672 // matter anyway in this use case, so just pass event pos instead of trying to
671 673 // calculate the real screen position.
672 674 mouseEvent.setScreenPos(event->pos());
673 675 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
674 676 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
675 677 mouseEvent.setButtons(m_mousePressButtons);
676 678 mouseEvent.setButton(m_mousePressButton);
677 679 mouseEvent.setModifiers(event->modifiers());
678 680 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
679 681 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
680 682 mouseEvent.setAccepted(false);
681 683
682 684 QApplication::sendEvent(m_scene, &mouseEvent);
683 685 }
684 686
685 687 void DeclarativeChart::mouseDoubleClickEvent(QMouseEvent *event)
686 688 {
687 689 m_mousePressScenePoint = event->pos();
688 690 m_mousePressScreenPoint = event->globalPos();
689 691 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
690 692 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
691 693 m_mousePressButton = event->button();
692 694 m_mousePressButtons = event->buttons();
693 695
694 696 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
695 697 mouseEvent.setWidget(0);
696 698 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
697 699 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
698 700 mouseEvent.setScenePos(m_mousePressScenePoint);
699 701 mouseEvent.setScreenPos(m_mousePressScreenPoint);
700 702 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
701 703 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
702 704 mouseEvent.setButtons(m_mousePressButtons);
703 705 mouseEvent.setButton(m_mousePressButton);
704 706 mouseEvent.setModifiers(event->modifiers());
705 707 mouseEvent.setAccepted(false);
706 708
707 709 QApplication::sendEvent(m_scene, &mouseEvent);
708 710 }
709 711
710 712 void DeclarativeChart::handleAntialiasingChanged(bool enable)
711 713 {
712 714 setAntialiasing(enable);
713 715 }
714 716
715 717 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
716 718 {
717 719 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
718 720 if (chartTheme != m_chart->theme())
719 721 m_chart->setTheme(chartTheme);
720 722 }
721 723
722 724 DeclarativeChart::Theme DeclarativeChart::theme()
723 725 {
724 726 return (DeclarativeChart::Theme) m_chart->theme();
725 727 }
726 728
727 729 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
728 730 {
729 731 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
730 732 if (animationOptions != m_chart->animationOptions())
731 733 m_chart->setAnimationOptions(animationOptions);
732 734 }
733 735
734 736 DeclarativeChart::Animation DeclarativeChart::animationOptions()
735 737 {
736 738 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
737 739 return DeclarativeChart::AllAnimations;
738 740 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
739 741 return DeclarativeChart::GridAxisAnimations;
740 742 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
741 743 return DeclarativeChart::SeriesAnimations;
742 744 else
743 745 return DeclarativeChart::NoAnimation;
744 746 }
745 747
746 748 void DeclarativeChart::setAnimationDuration(int msecs)
747 749 {
748 750 if (msecs != m_chart->animationDuration()) {
749 751 m_chart->setAnimationDuration(msecs);
750 752 emit animationDurationChanged(msecs);
751 753 }
752 754 }
753 755
754 756 int DeclarativeChart::animationDuration() const
755 757 {
756 758 return m_chart->animationDuration();
757 759 }
758 760
759 761 void DeclarativeChart::setAnimationEasingCurve(const QEasingCurve &curve)
760 762 {
761 763 if (curve != m_chart->animationEasingCurve()) {
762 764 m_chart->setAnimationEasingCurve(curve);
763 765 emit animationEasingCurveChanged(curve);
764 766 }
765 767 }
766 768
767 769 QEasingCurve DeclarativeChart::animationEasingCurve() const
768 770 {
769 771 return m_chart->animationEasingCurve();
770 772 }
771 773
772 774 void DeclarativeChart::setTitle(QString title)
773 775 {
774 776 if (title != m_chart->title())
775 777 m_chart->setTitle(title);
776 778 }
777 779 QString DeclarativeChart::title()
778 780 {
779 781 return m_chart->title();
780 782 }
781 783
782 784 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
783 785 {
784 786 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
785 787 if (axes.count())
786 788 return axes[0];
787 789 return 0;
788 790 }
789 791
790 792 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
791 793 {
792 794 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
793 795 if (axes.count())
794 796 return axes[0];
795 797 return 0;
796 798 }
797 799
798 800 QLegend *DeclarativeChart::legend()
799 801 {
800 802 return m_chart->legend();
801 803 }
802 804
803 805 void DeclarativeChart::setTitleColor(QColor color)
804 806 {
805 807 QBrush b = m_chart->titleBrush();
806 808 if (color != b.color()) {
807 809 b.setColor(color);
808 810 m_chart->setTitleBrush(b);
809 811 emit titleColorChanged(color);
810 812 }
811 813 }
812 814
813 815 QFont DeclarativeChart::titleFont() const
814 816 {
815 817 return m_chart->titleFont();
816 818 }
817 819
818 820 void DeclarativeChart::setTitleFont(const QFont &font)
819 821 {
820 822 m_chart->setTitleFont(font);
821 823 }
822 824
823 825 QColor DeclarativeChart::titleColor()
824 826 {
825 827 return m_chart->titleBrush().color();
826 828 }
827 829
828 830 void DeclarativeChart::setBackgroundColor(QColor color)
829 831 {
830 832 QBrush b = m_chart->backgroundBrush();
831 833 if (b.style() != Qt::SolidPattern || color != b.color()) {
832 834 if (color.alpha() < 0xff)
833 835 m_sceneImageNeedsClear = true;
834 836 b.setStyle(Qt::SolidPattern);
835 837 b.setColor(color);
836 838 m_chart->setBackgroundBrush(b);
837 839 emit backgroundColorChanged();
838 840 }
839 841 }
840 842
841 843 QColor DeclarativeChart::backgroundColor()
842 844 {
843 845 return m_chart->backgroundBrush().color();
844 846 }
845 847
846 848 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
847 849 {
848 850 QBrush b = m_chart->plotAreaBackgroundBrush();
849 851 if (b.style() != Qt::SolidPattern || color != b.color()) {
850 852 b.setStyle(Qt::SolidPattern);
851 853 b.setColor(color);
852 854 m_chart->setPlotAreaBackgroundBrush(b);
853 855 m_chart->setPlotAreaBackgroundVisible(true);
854 856 emit plotAreaColorChanged();
855 857 }
856 858 }
857 859
858 860 QColor QtCharts::DeclarativeChart::plotAreaColor()
859 861 {
860 862 return m_chart->plotAreaBackgroundBrush().color();
861 863 }
862 864
863 865 void DeclarativeChart::setLocalizeNumbers(bool localize)
864 866 {
865 867 if (m_chart->localizeNumbers() != localize) {
866 868 m_chart->setLocalizeNumbers(localize);
867 869 emit localizeNumbersChanged();
868 870 }
869 871 }
870 872
871 873 bool DeclarativeChart::localizeNumbers() const
872 874 {
873 875 return m_chart->localizeNumbers();
874 876 }
875 877
876 878 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
877 879 {
878 880 if (m_chart->locale() != locale) {
879 881 m_chart->setLocale(locale);
880 882 emit localeChanged();
881 883 }
882 884 }
883 885
884 886 QLocale QtCharts::DeclarativeChart::locale() const
885 887 {
886 888 return m_chart->locale();
887 889 }
888 890
889 891 int DeclarativeChart::count()
890 892 {
891 893 return m_chart->series().count();
892 894 }
893 895
894 896 void DeclarativeChart::setDropShadowEnabled(bool enabled)
895 897 {
896 898 if (enabled != m_chart->isDropShadowEnabled()) {
897 899 m_sceneImageNeedsClear = true;
898 900 m_chart->setDropShadowEnabled(enabled);
899 901 dropShadowEnabledChanged(enabled);
900 902 }
901 903 }
902 904
903 905 bool DeclarativeChart::dropShadowEnabled()
904 906 {
905 907 return m_chart->isDropShadowEnabled();
906 908 }
907 909
908 910 qreal DeclarativeChart::backgroundRoundness() const
909 911 {
910 912 return m_chart->backgroundRoundness();
911 913 }
912 914
913 915 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
914 916 {
915 917 if (m_chart->backgroundRoundness() != diameter) {
916 918 m_sceneImageNeedsClear = true;
917 919 m_chart->setBackgroundRoundness(diameter);
918 920 emit backgroundRoundnessChanged(diameter);
919 921 }
920 922 }
921 923
922 924 void DeclarativeChart::zoom(qreal factor)
923 925 {
924 926 m_chart->zoom(factor);
925 927 }
926 928
927 929 void DeclarativeChart::zoomIn()
928 930 {
929 931 m_chart->zoomIn();
930 932 }
931 933
932 934 void DeclarativeChart::zoomIn(const QRectF &rectangle)
933 935 {
934 936 m_chart->zoomIn(rectangle);
935 937 }
936 938
937 939 void DeclarativeChart::zoomOut()
938 940 {
939 941 m_chart->zoomOut();
940 942 }
941 943
942 944 void DeclarativeChart::zoomReset()
943 945 {
944 946 m_chart->zoomReset();
945 947 }
946 948
947 949 bool DeclarativeChart::isZoomed()
948 950 {
949 951 return m_chart->isZoomed();
950 952 }
951 953
952 954 void DeclarativeChart::scrollLeft(qreal pixels)
953 955 {
954 956 m_chart->scroll(-pixels, 0);
955 957 }
956 958
957 959 void DeclarativeChart::scrollRight(qreal pixels)
958 960 {
959 961 m_chart->scroll(pixels, 0);
960 962 }
961 963
962 964 void DeclarativeChart::scrollUp(qreal pixels)
963 965 {
964 966 m_chart->scroll(0, pixels);
965 967 }
966 968
967 969 void DeclarativeChart::scrollDown(qreal pixels)
968 970 {
969 971 m_chart->scroll(0, -pixels);
970 972 }
971 973
972 974 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
973 975 {
974 976 return QQmlListProperty<QAbstractAxis>(this, 0,
975 977 &DeclarativeChart::axesAppendFunc,
976 978 &DeclarativeChart::axesCountFunc,
977 979 &DeclarativeChart::axesAtFunc,
978 980 &DeclarativeChart::axesClearFunc);
979 981 }
980 982
981 983 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
982 984 {
983 985 // Empty implementation
984 986 Q_UNUSED(list);
985 987 Q_UNUSED(element);
986 988 }
987 989
988 990 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
989 991 {
990 992 if (qobject_cast<DeclarativeChart *>(list->object)) {
991 993 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
992 994 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
993 995 }
994 996 return 0;
995 997 }
996 998
997 999 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
998 1000 {
999 1001 if (qobject_cast<DeclarativeChart *>(list->object)) {
1000 1002 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
1001 1003 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
1002 1004 return axes.at(index);
1003 1005 }
1004 1006 return 0;
1005 1007 }
1006 1008
1007 1009 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
1008 1010 {
1009 1011 // Empty implementation
1010 1012 Q_UNUSED(list);
1011 1013 }
1012 1014
1013 1015
1014 1016 QAbstractSeries *DeclarativeChart::series(int index)
1015 1017 {
1016 1018 if (index < m_chart->series().count()) {
1017 1019 return m_chart->series().at(index);
1018 1020 }
1019 1021 return 0;
1020 1022 }
1021 1023
1022 1024 QAbstractSeries *DeclarativeChart::series(QString seriesName)
1023 1025 {
1024 1026 foreach (QAbstractSeries *series, m_chart->series()) {
1025 1027 if (series->name() == seriesName)
1026 1028 return series;
1027 1029 }
1028 1030 return 0;
1029 1031 }
1030 1032
1031 1033 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
1032 1034 {
1033 1035 QAbstractSeries *series = 0;
1034 1036
1035 1037 switch (type) {
1036 1038 case DeclarativeChart::SeriesTypeLine:
1037 1039 series = new DeclarativeLineSeries();
1038 1040 break;
1039 1041 case DeclarativeChart::SeriesTypeArea: {
1040 1042 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
1041 1043 DeclarativeLineSeries *line = new DeclarativeLineSeries();
1042 1044 line->setParent(area);
1043 1045 area->setUpperSeries(line);
1044 1046 series = area;
1045 1047 break;
1046 1048 }
1047 1049 case DeclarativeChart::SeriesTypeStackedBar:
1048 1050 series = new DeclarativeStackedBarSeries();
1049 1051 break;
1050 1052 case DeclarativeChart::SeriesTypePercentBar:
1051 1053 series = new DeclarativePercentBarSeries();
1052 1054 break;
1053 1055 case DeclarativeChart::SeriesTypeBar:
1054 1056 series = new DeclarativeBarSeries();
1055 1057 break;
1056 1058 case DeclarativeChart::SeriesTypeHorizontalBar:
1057 1059 series = new DeclarativeHorizontalBarSeries();
1058 1060 break;
1059 1061 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
1060 1062 series = new DeclarativeHorizontalPercentBarSeries();
1061 1063 break;
1062 1064 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
1063 1065 series = new DeclarativeHorizontalStackedBarSeries();
1064 1066 break;
1065 1067 case DeclarativeChart::SeriesTypeBoxPlot:
1066 1068 series = new DeclarativeBoxPlotSeries();
1067 1069 break;
1068 1070 case DeclarativeChart::SeriesTypePie:
1069 1071 series = new DeclarativePieSeries();
1070 1072 break;
1071 1073 case DeclarativeChart::SeriesTypeScatter:
1072 1074 series = new DeclarativeScatterSeries();
1073 1075 break;
1074 1076 case DeclarativeChart::SeriesTypeSpline:
1075 1077 series = new DeclarativeSplineSeries();
1076 1078 break;
1077 1079 default:
1078 1080 qWarning() << "Illegal series type";
1079 1081 }
1080 1082
1081 1083 if (series) {
1082 1084 // Connect to axis changed signals (unless this is a pie series)
1083 1085 if (!qobject_cast<DeclarativePieSeries *>(series)) {
1084 1086 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1085 1087 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1086 1088 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
1087 1089 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
1088 1090 }
1089 1091
1090 1092 series->setName(name);
1091 1093 m_chart->addSeries(series);
1092 1094
1093 1095 if (!axisX || !axisY)
1094 1096 initializeAxes(series);
1095 1097
1096 1098 if (axisX)
1097 1099 setAxisX(axisX, series);
1098 1100 if (axisY)
1099 1101 setAxisY(axisY, series);
1100 1102 }
1101 1103
1102 1104 return series;
1103 1105 }
1104 1106
1105 1107 void DeclarativeChart::removeSeries(QAbstractSeries *series)
1106 1108 {
1107 1109 if (series)
1108 1110 m_chart->removeSeries(series);
1109 1111 else
1110 1112 qWarning("removeSeries: cannot remove null");
1111 1113 }
1112 1114
1113 1115 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
1114 1116 {
1115 1117 if (axis && series)
1116 1118 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
1117 1119 }
1118 1120
1119 1121 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
1120 1122 {
1121 1123 if (axis && series)
1122 1124 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
1123 1125 }
1124 1126
1125 1127 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
1126 1128 {
1127 1129 if (!series) {
1128 1130 qWarning() << "No axis type defined for null series";
1129 1131 return 0;
1130 1132 }
1131 1133
1132 1134 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
1133 1135 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
1134 1136 return existingAxis;
1135 1137 }
1136 1138
1137 1139 switch (series->d_ptr->defaultAxisType(orientation)) {
1138 1140 case QAbstractAxis::AxisTypeValue:
1139 1141 return new QValueAxis(this);
1140 1142 case QAbstractAxis::AxisTypeBarCategory:
1141 1143 return new QBarCategoryAxis(this);
1142 1144 case QAbstractAxis::AxisTypeCategory:
1143 1145 return new QCategoryAxis(this);
1144 1146 #ifndef QT_ON_ARM
1145 1147 case QAbstractAxis::AxisTypeDateTime:
1146 1148 return new QDateTimeAxis(this);
1147 1149 #endif
1148 1150 case QAbstractAxis::AxisTypeLogValue:
1149 1151 return new QLogValueAxis(this);
1150 1152 default:
1151 1153 // assume AxisTypeNoAxis
1152 1154 return 0;
1153 1155 }
1154 1156 }
1155 1157
1156 1158 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1157 1159 {
1158 1160 if (qobject_cast<DeclarativeLineSeries *>(series))
1159 1161 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1160 1162 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1161 1163 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1162 1164 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1163 1165 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1164 1166 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1165 1167 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1166 1168 else if (qobject_cast<DeclarativeBarSeries *>(series))
1167 1169 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1168 1170 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1169 1171 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1170 1172 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1171 1173 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1172 1174 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1173 1175 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1174 1176 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1175 1177 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1176 1178 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1177 1179 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1178 1180 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1179 1181 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1180 1182 // else: do nothing
1181 1183 }
1182 1184
1183 1185 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1184 1186 {
1185 1187 qreal min;
1186 1188 qreal max;
1187 1189 // Initialize axis X
1188 1190 if (axes->axisX()) {
1189 1191 axes->emitAxisXChanged();
1190 1192 } else if (axes->axisXTop()) {
1191 1193 axes->emitAxisXTopChanged();
1192 1194 } else {
1193 1195 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1194 1196 findMinMaxForSeries(series, Qt::Horizontal, min, max);
1195 1197 axes->axisX()->setRange(min, max);
1196 1198 }
1197 1199
1198 1200 // Initialize axis Y
1199 1201 if (axes->axisY()) {
1200 1202 axes->emitAxisYChanged();
1201 1203 } else if (axes->axisYRight()) {
1202 1204 axes->emitAxisYRightChanged();
1203 1205 } else {
1204 1206 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1205 1207 findMinMaxForSeries(series, Qt::Vertical, min, max);
1206 1208 axes->axisY()->setRange(min, max);
1207 1209 }
1208 1210 }
1209 1211
1210 1212 void DeclarativeChart::findMinMaxForSeries(QAbstractSeries *series, Qt::Orientations orientation,
1211 1213 qreal &min, qreal &max)
1212 1214 {
1213 1215 if (!series) {
1214 1216 min = 0.5;
1215 1217 max = 0.5;
1216 1218 } else {
1217 1219 AbstractDomain *domain = series->d_ptr->domain();
1218 1220 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
1219 1221 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
1220 1222
1221 1223 if (min == max) {
1222 1224 min -= 0.5;
1223 1225 max += 0.5;
1224 1226 }
1225 1227 }
1226 1228 }
1227 1229
1228 1230 QPointF DeclarativeChart::mapToValue(const QPointF &position, QAbstractSeries *series)
1229 1231 {
1230 1232 return m_chart->mapToValue(position, series);
1231 1233 }
1232 1234
1233 1235 QPointF DeclarativeChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
1234 1236 {
1235 1237 return m_chart->mapToPosition(value, series);
1236 1238 }
1237 1239
1238 1240 #include "moc_declarativechart.cpp"
1239 1241
1240 1242 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now