##// END OF EJS Templates
Merge remote-tracking branch 'origin/5.6.0' into 5.6...
Frederik Gladhorn -
r2874:b2259e94e953 merge
parent child
Show More
@@ -1,1242 +1,1244
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 if (node->glRenderNode()) {
515 516 connect(window(), &QQuickWindow::beforeRendering,
516 517 node->glRenderNode(), &DeclarativeRenderNode::render);
517 518 }
519 }
518 520
519 521 const QRectF &bRect = boundingRect();
520 522
521 523 // Update GL data
522 if (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty()) {
524 if (node->glRenderNode() && (m_glXYDataManager->dataMap().size() || m_glXYDataManager->mapDirty())) {
523 525 const QRectF &plotArea = m_chart->plotArea();
524 526 const QSizeF &chartAreaSize = m_chart->size();
525 527
526 528 // We can't use chart's plot area directly, as graphicscene has some internal minimum size
527 529 const qreal normalizedX = plotArea.x() / chartAreaSize.width();
528 530 const qreal normalizedY = plotArea.y() / chartAreaSize.height();
529 531 const qreal normalizedWidth = plotArea.width() / chartAreaSize.width();
530 532 const qreal normalizedHeight = plotArea.height() / chartAreaSize.height();
531 533
532 534 QRectF adjustedPlotArea(normalizedX * bRect.width(),
533 535 normalizedY * bRect.height(),
534 536 normalizedWidth * bRect.width(),
535 537 normalizedHeight * bRect.height());
536 538
537 539 const QSize &adjustedPlotSize = adjustedPlotArea.size().toSize();
538 540 if (adjustedPlotSize != node->glRenderNode()->textureSize())
539 541 node->glRenderNode()->setTextureSize(adjustedPlotSize);
540 542
541 543 node->glRenderNode()->setRect(adjustedPlotArea);
542 544 node->glRenderNode()->setSeriesData(m_glXYDataManager->mapDirty(),
543 545 m_glXYDataManager->dataMap());
544 546
545 547 // Clear dirty flags from original xy data
546 548 m_glXYDataManager->clearAllDirty();
547 549 }
548 550
549 551 // Copy chart (if dirty) to chart node
550 552 if (m_sceneImageDirty) {
551 553 node->createTextureFromImage(*m_sceneImage);
552 554 m_sceneImageDirty = false;
553 555 }
554 556
555 557 node->setRect(bRect);
556 558
557 559 return node;
558 560 }
559 561
560 562 void DeclarativeChart::sceneChanged(QList<QRectF> region)
561 563 {
562 564 const int count = region.size();
563 565 const qreal limitSize = 0.01;
564 566 if (count && !m_updatePending) {
565 567 qreal totalSize = 0.0;
566 568 for (int i = 0; i < count; i++) {
567 569 const QRectF &reg = region.at(i);
568 570 totalSize += (reg.height() * reg.width());
569 571 if (totalSize >= limitSize)
570 572 break;
571 573 }
572 574 // Ignore region updates that change less than small fraction of a pixel, as there is
573 575 // little point regenerating the image in these cases. These are typically cases
574 576 // where OpenGL series are drawn to otherwise static chart.
575 577 if (totalSize >= limitSize) {
576 578 m_updatePending = true;
577 579 // Do async render to avoid some unnecessary renders.
578 580 emit needRender();
579 581 } else {
580 582 // We do want to call update to trigger possible gl series updates.
581 583 update();
582 584 }
583 585 }
584 586 }
585 587
586 588 void DeclarativeChart::renderScene()
587 589 {
588 590 m_updatePending = false;
589 591 m_sceneImageDirty = true;
590 592 QSize chartSize = m_chart->size().toSize();
591 593 if (!m_sceneImage || chartSize != m_sceneImage->size()) {
592 594 delete m_sceneImage;
593 595 qreal dpr = window() ? window()->devicePixelRatio() : 1.0;
594 596 m_sceneImage = new QImage(chartSize * dpr, QImage::Format_ARGB32);
595 597 m_sceneImage->setDevicePixelRatio(dpr);
596 598 m_sceneImageNeedsClear = true;
597 599 }
598 600
599 601 if (m_sceneImageNeedsClear) {
600 602 m_sceneImage->fill(Qt::transparent);
601 603 // Don't clear the flag if chart background has any transparent element to it
602 604 if (m_chart->backgroundBrush().color().alpha() == 0xff && !m_chart->isDropShadowEnabled())
603 605 m_sceneImageNeedsClear = false;
604 606 }
605 607 QPainter painter(m_sceneImage);
606 608 if (antialiasing()) {
607 609 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
608 610 | QPainter::SmoothPixmapTransform);
609 611 }
610 612 QRect renderRect(QPoint(0, 0), chartSize);
611 613 m_scene->render(&painter, renderRect, renderRect);
612 614 update();
613 615 }
614 616
615 617 void DeclarativeChart::mousePressEvent(QMouseEvent *event)
616 618 {
617 619 m_mousePressScenePoint = event->pos();
618 620 m_mousePressScreenPoint = event->globalPos();
619 621 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
620 622 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
621 623 m_mousePressButton = event->button();
622 624 m_mousePressButtons = event->buttons();
623 625
624 626 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
625 627 mouseEvent.setWidget(0);
626 628 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
627 629 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
628 630 mouseEvent.setScenePos(m_mousePressScenePoint);
629 631 mouseEvent.setScreenPos(m_mousePressScreenPoint);
630 632 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
631 633 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
632 634 mouseEvent.setButtons(m_mousePressButtons);
633 635 mouseEvent.setButton(m_mousePressButton);
634 636 mouseEvent.setModifiers(event->modifiers());
635 637 mouseEvent.setAccepted(false);
636 638
637 639 QApplication::sendEvent(m_scene, &mouseEvent);
638 640 }
639 641
640 642 void DeclarativeChart::mouseReleaseEvent(QMouseEvent *event)
641 643 {
642 644 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
643 645 mouseEvent.setWidget(0);
644 646 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
645 647 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
646 648 mouseEvent.setScenePos(event->pos());
647 649 mouseEvent.setScreenPos(event->globalPos());
648 650 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
649 651 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
650 652 mouseEvent.setButtons(event->buttons());
651 653 mouseEvent.setButton(event->button());
652 654 mouseEvent.setModifiers(event->modifiers());
653 655 mouseEvent.setAccepted(false);
654 656
655 657 QApplication::sendEvent(m_scene, &mouseEvent);
656 658
657 659 m_mousePressButtons = event->buttons();
658 660 m_mousePressButton = Qt::NoButton;
659 661 }
660 662
661 663 void DeclarativeChart::hoverMoveEvent(QHoverEvent *event)
662 664 {
663 665 // Convert hover move to mouse move, since we don't seem to get actual mouse move events.
664 666 // QGraphicsScene generates hover events from mouse move events, so we don't need
665 667 // to pass hover events there.
666 668 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
667 669 mouseEvent.setWidget(0);
668 670 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
669 671 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
670 672 mouseEvent.setScenePos(event->pos());
671 673 // Hover events do not have global pos in them, and the screen position doesn't seem to
672 674 // matter anyway in this use case, so just pass event pos instead of trying to
673 675 // calculate the real screen position.
674 676 mouseEvent.setScreenPos(event->pos());
675 677 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
676 678 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
677 679 mouseEvent.setButtons(m_mousePressButtons);
678 680 mouseEvent.setButton(m_mousePressButton);
679 681 mouseEvent.setModifiers(event->modifiers());
680 682 m_lastMouseMoveScenePoint = mouseEvent.scenePos();
681 683 m_lastMouseMoveScreenPoint = mouseEvent.screenPos();
682 684 mouseEvent.setAccepted(false);
683 685
684 686 QApplication::sendEvent(m_scene, &mouseEvent);
685 687 }
686 688
687 689 void DeclarativeChart::mouseDoubleClickEvent(QMouseEvent *event)
688 690 {
689 691 m_mousePressScenePoint = event->pos();
690 692 m_mousePressScreenPoint = event->globalPos();
691 693 m_lastMouseMoveScenePoint = m_mousePressScenePoint;
692 694 m_lastMouseMoveScreenPoint = m_mousePressScreenPoint;
693 695 m_mousePressButton = event->button();
694 696 m_mousePressButtons = event->buttons();
695 697
696 698 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
697 699 mouseEvent.setWidget(0);
698 700 mouseEvent.setButtonDownScenePos(m_mousePressButton, m_mousePressScenePoint);
699 701 mouseEvent.setButtonDownScreenPos(m_mousePressButton, m_mousePressScreenPoint);
700 702 mouseEvent.setScenePos(m_mousePressScenePoint);
701 703 mouseEvent.setScreenPos(m_mousePressScreenPoint);
702 704 mouseEvent.setLastScenePos(m_lastMouseMoveScenePoint);
703 705 mouseEvent.setLastScreenPos(m_lastMouseMoveScreenPoint);
704 706 mouseEvent.setButtons(m_mousePressButtons);
705 707 mouseEvent.setButton(m_mousePressButton);
706 708 mouseEvent.setModifiers(event->modifiers());
707 709 mouseEvent.setAccepted(false);
708 710
709 711 QApplication::sendEvent(m_scene, &mouseEvent);
710 712 }
711 713
712 714 void DeclarativeChart::handleAntialiasingChanged(bool enable)
713 715 {
714 716 setAntialiasing(enable);
715 717 }
716 718
717 719 void DeclarativeChart::setTheme(DeclarativeChart::Theme theme)
718 720 {
719 721 QChart::ChartTheme chartTheme = (QChart::ChartTheme) theme;
720 722 if (chartTheme != m_chart->theme())
721 723 m_chart->setTheme(chartTheme);
722 724 }
723 725
724 726 DeclarativeChart::Theme DeclarativeChart::theme()
725 727 {
726 728 return (DeclarativeChart::Theme) m_chart->theme();
727 729 }
728 730
729 731 void DeclarativeChart::setAnimationOptions(DeclarativeChart::Animation animations)
730 732 {
731 733 QChart::AnimationOption animationOptions = (QChart::AnimationOption) animations;
732 734 if (animationOptions != m_chart->animationOptions())
733 735 m_chart->setAnimationOptions(animationOptions);
734 736 }
735 737
736 738 DeclarativeChart::Animation DeclarativeChart::animationOptions()
737 739 {
738 740 if (m_chart->animationOptions().testFlag(QChart::AllAnimations))
739 741 return DeclarativeChart::AllAnimations;
740 742 else if (m_chart->animationOptions().testFlag(QChart::GridAxisAnimations))
741 743 return DeclarativeChart::GridAxisAnimations;
742 744 else if (m_chart->animationOptions().testFlag(QChart::SeriesAnimations))
743 745 return DeclarativeChart::SeriesAnimations;
744 746 else
745 747 return DeclarativeChart::NoAnimation;
746 748 }
747 749
748 750 void DeclarativeChart::setAnimationDuration(int msecs)
749 751 {
750 752 if (msecs != m_chart->animationDuration()) {
751 753 m_chart->setAnimationDuration(msecs);
752 754 emit animationDurationChanged(msecs);
753 755 }
754 756 }
755 757
756 758 int DeclarativeChart::animationDuration() const
757 759 {
758 760 return m_chart->animationDuration();
759 761 }
760 762
761 763 void DeclarativeChart::setAnimationEasingCurve(const QEasingCurve &curve)
762 764 {
763 765 if (curve != m_chart->animationEasingCurve()) {
764 766 m_chart->setAnimationEasingCurve(curve);
765 767 emit animationEasingCurveChanged(curve);
766 768 }
767 769 }
768 770
769 771 QEasingCurve DeclarativeChart::animationEasingCurve() const
770 772 {
771 773 return m_chart->animationEasingCurve();
772 774 }
773 775
774 776 void DeclarativeChart::setTitle(QString title)
775 777 {
776 778 if (title != m_chart->title())
777 779 m_chart->setTitle(title);
778 780 }
779 781 QString DeclarativeChart::title()
780 782 {
781 783 return m_chart->title();
782 784 }
783 785
784 786 QAbstractAxis *DeclarativeChart::axisX(QAbstractSeries *series)
785 787 {
786 788 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Horizontal, series);
787 789 if (axes.count())
788 790 return axes[0];
789 791 return 0;
790 792 }
791 793
792 794 QAbstractAxis *DeclarativeChart::axisY(QAbstractSeries *series)
793 795 {
794 796 QList<QAbstractAxis *> axes = m_chart->axes(Qt::Vertical, series);
795 797 if (axes.count())
796 798 return axes[0];
797 799 return 0;
798 800 }
799 801
800 802 QLegend *DeclarativeChart::legend()
801 803 {
802 804 return m_chart->legend();
803 805 }
804 806
805 807 void DeclarativeChart::setTitleColor(QColor color)
806 808 {
807 809 QBrush b = m_chart->titleBrush();
808 810 if (color != b.color()) {
809 811 b.setColor(color);
810 812 m_chart->setTitleBrush(b);
811 813 emit titleColorChanged(color);
812 814 }
813 815 }
814 816
815 817 QFont DeclarativeChart::titleFont() const
816 818 {
817 819 return m_chart->titleFont();
818 820 }
819 821
820 822 void DeclarativeChart::setTitleFont(const QFont &font)
821 823 {
822 824 m_chart->setTitleFont(font);
823 825 }
824 826
825 827 QColor DeclarativeChart::titleColor()
826 828 {
827 829 return m_chart->titleBrush().color();
828 830 }
829 831
830 832 void DeclarativeChart::setBackgroundColor(QColor color)
831 833 {
832 834 QBrush b = m_chart->backgroundBrush();
833 835 if (b.style() != Qt::SolidPattern || color != b.color()) {
834 836 if (color.alpha() < 0xff)
835 837 m_sceneImageNeedsClear = true;
836 838 b.setStyle(Qt::SolidPattern);
837 839 b.setColor(color);
838 840 m_chart->setBackgroundBrush(b);
839 841 emit backgroundColorChanged();
840 842 }
841 843 }
842 844
843 845 QColor DeclarativeChart::backgroundColor()
844 846 {
845 847 return m_chart->backgroundBrush().color();
846 848 }
847 849
848 850 void QtCharts::DeclarativeChart::setPlotAreaColor(QColor color)
849 851 {
850 852 QBrush b = m_chart->plotAreaBackgroundBrush();
851 853 if (b.style() != Qt::SolidPattern || color != b.color()) {
852 854 b.setStyle(Qt::SolidPattern);
853 855 b.setColor(color);
854 856 m_chart->setPlotAreaBackgroundBrush(b);
855 857 m_chart->setPlotAreaBackgroundVisible(true);
856 858 emit plotAreaColorChanged();
857 859 }
858 860 }
859 861
860 862 QColor QtCharts::DeclarativeChart::plotAreaColor()
861 863 {
862 864 return m_chart->plotAreaBackgroundBrush().color();
863 865 }
864 866
865 867 void DeclarativeChart::setLocalizeNumbers(bool localize)
866 868 {
867 869 if (m_chart->localizeNumbers() != localize) {
868 870 m_chart->setLocalizeNumbers(localize);
869 871 emit localizeNumbersChanged();
870 872 }
871 873 }
872 874
873 875 bool DeclarativeChart::localizeNumbers() const
874 876 {
875 877 return m_chart->localizeNumbers();
876 878 }
877 879
878 880 void QtCharts::DeclarativeChart::setLocale(const QLocale &locale)
879 881 {
880 882 if (m_chart->locale() != locale) {
881 883 m_chart->setLocale(locale);
882 884 emit localeChanged();
883 885 }
884 886 }
885 887
886 888 QLocale QtCharts::DeclarativeChart::locale() const
887 889 {
888 890 return m_chart->locale();
889 891 }
890 892
891 893 int DeclarativeChart::count()
892 894 {
893 895 return m_chart->series().count();
894 896 }
895 897
896 898 void DeclarativeChart::setDropShadowEnabled(bool enabled)
897 899 {
898 900 if (enabled != m_chart->isDropShadowEnabled()) {
899 901 m_sceneImageNeedsClear = true;
900 902 m_chart->setDropShadowEnabled(enabled);
901 903 dropShadowEnabledChanged(enabled);
902 904 }
903 905 }
904 906
905 907 bool DeclarativeChart::dropShadowEnabled()
906 908 {
907 909 return m_chart->isDropShadowEnabled();
908 910 }
909 911
910 912 qreal DeclarativeChart::backgroundRoundness() const
911 913 {
912 914 return m_chart->backgroundRoundness();
913 915 }
914 916
915 917 void DeclarativeChart::setBackgroundRoundness(qreal diameter)
916 918 {
917 919 if (m_chart->backgroundRoundness() != diameter) {
918 920 m_sceneImageNeedsClear = true;
919 921 m_chart->setBackgroundRoundness(diameter);
920 922 emit backgroundRoundnessChanged(diameter);
921 923 }
922 924 }
923 925
924 926 void DeclarativeChart::zoom(qreal factor)
925 927 {
926 928 m_chart->zoom(factor);
927 929 }
928 930
929 931 void DeclarativeChart::zoomIn()
930 932 {
931 933 m_chart->zoomIn();
932 934 }
933 935
934 936 void DeclarativeChart::zoomIn(const QRectF &rectangle)
935 937 {
936 938 m_chart->zoomIn(rectangle);
937 939 }
938 940
939 941 void DeclarativeChart::zoomOut()
940 942 {
941 943 m_chart->zoomOut();
942 944 }
943 945
944 946 void DeclarativeChart::zoomReset()
945 947 {
946 948 m_chart->zoomReset();
947 949 }
948 950
949 951 bool DeclarativeChart::isZoomed()
950 952 {
951 953 return m_chart->isZoomed();
952 954 }
953 955
954 956 void DeclarativeChart::scrollLeft(qreal pixels)
955 957 {
956 958 m_chart->scroll(-pixels, 0);
957 959 }
958 960
959 961 void DeclarativeChart::scrollRight(qreal pixels)
960 962 {
961 963 m_chart->scroll(pixels, 0);
962 964 }
963 965
964 966 void DeclarativeChart::scrollUp(qreal pixels)
965 967 {
966 968 m_chart->scroll(0, pixels);
967 969 }
968 970
969 971 void DeclarativeChart::scrollDown(qreal pixels)
970 972 {
971 973 m_chart->scroll(0, -pixels);
972 974 }
973 975
974 976 QQmlListProperty<QAbstractAxis> DeclarativeChart::axes()
975 977 {
976 978 return QQmlListProperty<QAbstractAxis>(this, 0,
977 979 &DeclarativeChart::axesAppendFunc,
978 980 &DeclarativeChart::axesCountFunc,
979 981 &DeclarativeChart::axesAtFunc,
980 982 &DeclarativeChart::axesClearFunc);
981 983 }
982 984
983 985 void DeclarativeChart::axesAppendFunc(QQmlListProperty<QAbstractAxis> *list, QAbstractAxis *element)
984 986 {
985 987 // Empty implementation
986 988 Q_UNUSED(list);
987 989 Q_UNUSED(element);
988 990 }
989 991
990 992 int DeclarativeChart::axesCountFunc(QQmlListProperty<QAbstractAxis> *list)
991 993 {
992 994 if (qobject_cast<DeclarativeChart *>(list->object)) {
993 995 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
994 996 return chart->m_chart->axes(Qt::Horizontal | Qt::Vertical).count();
995 997 }
996 998 return 0;
997 999 }
998 1000
999 1001 QAbstractAxis *DeclarativeChart::axesAtFunc(QQmlListProperty<QAbstractAxis> *list, int index)
1000 1002 {
1001 1003 if (qobject_cast<DeclarativeChart *>(list->object)) {
1002 1004 DeclarativeChart *chart = qobject_cast<DeclarativeChart *>(list->object);
1003 1005 QList<QAbstractAxis *> axes = chart->m_chart->axes(Qt::Horizontal | Qt::Vertical, chart->m_chart->series()[0]);
1004 1006 return axes.at(index);
1005 1007 }
1006 1008 return 0;
1007 1009 }
1008 1010
1009 1011 void DeclarativeChart::axesClearFunc(QQmlListProperty<QAbstractAxis> *list)
1010 1012 {
1011 1013 // Empty implementation
1012 1014 Q_UNUSED(list);
1013 1015 }
1014 1016
1015 1017
1016 1018 QAbstractSeries *DeclarativeChart::series(int index)
1017 1019 {
1018 1020 if (index < m_chart->series().count()) {
1019 1021 return m_chart->series().at(index);
1020 1022 }
1021 1023 return 0;
1022 1024 }
1023 1025
1024 1026 QAbstractSeries *DeclarativeChart::series(QString seriesName)
1025 1027 {
1026 1028 foreach (QAbstractSeries *series, m_chart->series()) {
1027 1029 if (series->name() == seriesName)
1028 1030 return series;
1029 1031 }
1030 1032 return 0;
1031 1033 }
1032 1034
1033 1035 QAbstractSeries *DeclarativeChart::createSeries(int type, QString name, QAbstractAxis *axisX, QAbstractAxis *axisY)
1034 1036 {
1035 1037 QAbstractSeries *series = 0;
1036 1038
1037 1039 switch (type) {
1038 1040 case DeclarativeChart::SeriesTypeLine:
1039 1041 series = new DeclarativeLineSeries();
1040 1042 break;
1041 1043 case DeclarativeChart::SeriesTypeArea: {
1042 1044 DeclarativeAreaSeries *area = new DeclarativeAreaSeries();
1043 1045 DeclarativeLineSeries *line = new DeclarativeLineSeries();
1044 1046 line->setParent(area);
1045 1047 area->setUpperSeries(line);
1046 1048 series = area;
1047 1049 break;
1048 1050 }
1049 1051 case DeclarativeChart::SeriesTypeStackedBar:
1050 1052 series = new DeclarativeStackedBarSeries();
1051 1053 break;
1052 1054 case DeclarativeChart::SeriesTypePercentBar:
1053 1055 series = new DeclarativePercentBarSeries();
1054 1056 break;
1055 1057 case DeclarativeChart::SeriesTypeBar:
1056 1058 series = new DeclarativeBarSeries();
1057 1059 break;
1058 1060 case DeclarativeChart::SeriesTypeHorizontalBar:
1059 1061 series = new DeclarativeHorizontalBarSeries();
1060 1062 break;
1061 1063 case DeclarativeChart::SeriesTypeHorizontalPercentBar:
1062 1064 series = new DeclarativeHorizontalPercentBarSeries();
1063 1065 break;
1064 1066 case DeclarativeChart::SeriesTypeHorizontalStackedBar:
1065 1067 series = new DeclarativeHorizontalStackedBarSeries();
1066 1068 break;
1067 1069 case DeclarativeChart::SeriesTypeBoxPlot:
1068 1070 series = new DeclarativeBoxPlotSeries();
1069 1071 break;
1070 1072 case DeclarativeChart::SeriesTypePie:
1071 1073 series = new DeclarativePieSeries();
1072 1074 break;
1073 1075 case DeclarativeChart::SeriesTypeScatter:
1074 1076 series = new DeclarativeScatterSeries();
1075 1077 break;
1076 1078 case DeclarativeChart::SeriesTypeSpline:
1077 1079 series = new DeclarativeSplineSeries();
1078 1080 break;
1079 1081 default:
1080 1082 qWarning() << "Illegal series type";
1081 1083 }
1082 1084
1083 1085 if (series) {
1084 1086 // Connect to axis changed signals (unless this is a pie series)
1085 1087 if (!qobject_cast<DeclarativePieSeries *>(series)) {
1086 1088 connect(series, SIGNAL(axisXChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1087 1089 connect(series, SIGNAL(axisXTopChanged(QAbstractAxis*)), this, SLOT(handleAxisXSet(QAbstractAxis*)));
1088 1090 connect(series, SIGNAL(axisYChanged(QAbstractAxis*)), this, SLOT(handleAxisYSet(QAbstractAxis*)));
1089 1091 connect(series, SIGNAL(axisYRightChanged(QAbstractAxis*)), this, SLOT(handleAxisYRightSet(QAbstractAxis*)));
1090 1092 }
1091 1093
1092 1094 series->setName(name);
1093 1095 m_chart->addSeries(series);
1094 1096
1095 1097 if (!axisX || !axisY)
1096 1098 initializeAxes(series);
1097 1099
1098 1100 if (axisX)
1099 1101 setAxisX(axisX, series);
1100 1102 if (axisY)
1101 1103 setAxisY(axisY, series);
1102 1104 }
1103 1105
1104 1106 return series;
1105 1107 }
1106 1108
1107 1109 void DeclarativeChart::removeSeries(QAbstractSeries *series)
1108 1110 {
1109 1111 if (series)
1110 1112 m_chart->removeSeries(series);
1111 1113 else
1112 1114 qWarning("removeSeries: cannot remove null");
1113 1115 }
1114 1116
1115 1117 void DeclarativeChart::setAxisX(QAbstractAxis *axis, QAbstractSeries *series)
1116 1118 {
1117 1119 if (axis && series)
1118 1120 seriesAxisAttachHelper(series, axis, Qt::Horizontal, Qt::AlignBottom);
1119 1121 }
1120 1122
1121 1123 void DeclarativeChart::setAxisY(QAbstractAxis *axis, QAbstractSeries *series)
1122 1124 {
1123 1125 if (axis && series)
1124 1126 seriesAxisAttachHelper(series, axis, Qt::Vertical, Qt::AlignLeft);
1125 1127 }
1126 1128
1127 1129 QAbstractAxis *DeclarativeChart::defaultAxis(Qt::Orientation orientation, QAbstractSeries *series)
1128 1130 {
1129 1131 if (!series) {
1130 1132 qWarning() << "No axis type defined for null series";
1131 1133 return 0;
1132 1134 }
1133 1135
1134 1136 foreach (QAbstractAxis *existingAxis, m_chart->axes(orientation)) {
1135 1137 if (existingAxis->type() == series->d_ptr->defaultAxisType(orientation))
1136 1138 return existingAxis;
1137 1139 }
1138 1140
1139 1141 switch (series->d_ptr->defaultAxisType(orientation)) {
1140 1142 case QAbstractAxis::AxisTypeValue:
1141 1143 return new QValueAxis(this);
1142 1144 case QAbstractAxis::AxisTypeBarCategory:
1143 1145 return new QBarCategoryAxis(this);
1144 1146 case QAbstractAxis::AxisTypeCategory:
1145 1147 return new QCategoryAxis(this);
1146 1148 #ifndef QT_ON_ARM
1147 1149 case QAbstractAxis::AxisTypeDateTime:
1148 1150 return new QDateTimeAxis(this);
1149 1151 #endif
1150 1152 case QAbstractAxis::AxisTypeLogValue:
1151 1153 return new QLogValueAxis(this);
1152 1154 default:
1153 1155 // assume AxisTypeNoAxis
1154 1156 return 0;
1155 1157 }
1156 1158 }
1157 1159
1158 1160 void DeclarativeChart::initializeAxes(QAbstractSeries *series)
1159 1161 {
1160 1162 if (qobject_cast<DeclarativeLineSeries *>(series))
1161 1163 doInitializeAxes(series, qobject_cast<DeclarativeLineSeries *>(series)->m_axes);
1162 1164 else if (qobject_cast<DeclarativeScatterSeries *>(series))
1163 1165 doInitializeAxes(series, qobject_cast<DeclarativeScatterSeries *>(series)->m_axes);
1164 1166 else if (qobject_cast<DeclarativeSplineSeries *>(series))
1165 1167 doInitializeAxes(series, qobject_cast<DeclarativeSplineSeries *>(series)->m_axes);
1166 1168 else if (qobject_cast<DeclarativeAreaSeries *>(series))
1167 1169 doInitializeAxes(series, qobject_cast<DeclarativeAreaSeries *>(series)->m_axes);
1168 1170 else if (qobject_cast<DeclarativeBarSeries *>(series))
1169 1171 doInitializeAxes(series, qobject_cast<DeclarativeBarSeries *>(series)->m_axes);
1170 1172 else if (qobject_cast<DeclarativeStackedBarSeries *>(series))
1171 1173 doInitializeAxes(series, qobject_cast<DeclarativeStackedBarSeries *>(series)->m_axes);
1172 1174 else if (qobject_cast<DeclarativePercentBarSeries *>(series))
1173 1175 doInitializeAxes(series, qobject_cast<DeclarativePercentBarSeries *>(series)->m_axes);
1174 1176 else if (qobject_cast<DeclarativeHorizontalBarSeries *>(series))
1175 1177 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalBarSeries *>(series)->m_axes);
1176 1178 else if (qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series))
1177 1179 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalStackedBarSeries *>(series)->m_axes);
1178 1180 else if (qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series))
1179 1181 doInitializeAxes(series, qobject_cast<DeclarativeHorizontalPercentBarSeries *>(series)->m_axes);
1180 1182 else if (qobject_cast<DeclarativeBoxPlotSeries *>(series))
1181 1183 doInitializeAxes(series, qobject_cast<DeclarativeBoxPlotSeries *>(series)->m_axes);
1182 1184 // else: do nothing
1183 1185 }
1184 1186
1185 1187 void DeclarativeChart::doInitializeAxes(QAbstractSeries *series, DeclarativeAxes *axes)
1186 1188 {
1187 1189 qreal min;
1188 1190 qreal max;
1189 1191 // Initialize axis X
1190 1192 if (axes->axisX()) {
1191 1193 axes->emitAxisXChanged();
1192 1194 } else if (axes->axisXTop()) {
1193 1195 axes->emitAxisXTopChanged();
1194 1196 } else {
1195 1197 axes->setAxisX(defaultAxis(Qt::Horizontal, series));
1196 1198 findMinMaxForSeries(series, Qt::Horizontal, min, max);
1197 1199 axes->axisX()->setRange(min, max);
1198 1200 }
1199 1201
1200 1202 // Initialize axis Y
1201 1203 if (axes->axisY()) {
1202 1204 axes->emitAxisYChanged();
1203 1205 } else if (axes->axisYRight()) {
1204 1206 axes->emitAxisYRightChanged();
1205 1207 } else {
1206 1208 axes->setAxisY(defaultAxis(Qt::Vertical, series));
1207 1209 findMinMaxForSeries(series, Qt::Vertical, min, max);
1208 1210 axes->axisY()->setRange(min, max);
1209 1211 }
1210 1212 }
1211 1213
1212 1214 void DeclarativeChart::findMinMaxForSeries(QAbstractSeries *series, Qt::Orientations orientation,
1213 1215 qreal &min, qreal &max)
1214 1216 {
1215 1217 if (!series) {
1216 1218 min = 0.5;
1217 1219 max = 0.5;
1218 1220 } else {
1219 1221 AbstractDomain *domain = series->d_ptr->domain();
1220 1222 min = (orientation == Qt::Vertical) ? domain->minY() : domain->minX();
1221 1223 max = (orientation == Qt::Vertical) ? domain->maxY() : domain->maxX();
1222 1224
1223 1225 if (min == max) {
1224 1226 min -= 0.5;
1225 1227 max += 0.5;
1226 1228 }
1227 1229 }
1228 1230 }
1229 1231
1230 1232 QPointF DeclarativeChart::mapToValue(const QPointF &position, QAbstractSeries *series)
1231 1233 {
1232 1234 return m_chart->mapToValue(position, series);
1233 1235 }
1234 1236
1235 1237 QPointF DeclarativeChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
1236 1238 {
1237 1239 return m_chart->mapToPosition(value, series);
1238 1240 }
1239 1241
1240 1242 #include "moc_declarativechart.cpp"
1241 1243
1242 1244 QT_CHARTS_END_NAMESPACE
@@ -1,81 +1,81
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 "declarativechartnode.h"
23 23 #include "declarativerendernode.h"
24 24 #include <QtGui/QOpenGLContext>
25 25 #include <QtGui/QOpenGLFunctions>
26 26 #include <QtGui/QOpenGLFramebufferObjectFormat>
27 27 #include <QtGui/QOpenGLFramebufferObject>
28 28 #include <QOpenGLShaderProgram>
29 29 #include <QtGui/QOpenGLBuffer>
30 30
31 31 QT_CHARTS_BEGIN_NAMESPACE
32 32
33 33 // This node handles displaying of the chart itself
34 34 DeclarativeChartNode::DeclarativeChartNode(QQuickWindow *window) :
35 35 QSGSimpleTextureNode(),
36 36 m_texture(0),
37 37 m_window(window),
38 38 m_textureOptions(0),
39 39 m_textureSize(1, 1),
40 40 m_glRenderNode(0)
41 41 {
42 initializeOpenGLFunctions();
43
44 42 // Our texture node must have a texture, so use a default one pixel texture
45 GLuint defaultTexture = 0;
46 glGenTextures(1, &defaultTexture);
47 glBindTexture(GL_TEXTURE_2D, defaultTexture);
48 uchar buf[4] = { 0, 0, 0, 0 };
49 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &buf);
50
43 QImage dummyImage(QSize(1, 1), QImage::Format_ARGB32);
44 uchar *imageData = dummyImage.bits();
45 imageData[0] = 0;
46 imageData[1] = 0;
47 imageData[2] = 0;
48 imageData[3] = 0;
51 49 QQuickWindow::CreateTextureOptions defaultTextureOptions = QQuickWindow::CreateTextureOptions(
52 50 QQuickWindow::TextureHasAlphaChannel | QQuickWindow::TextureOwnsGLTexture);
53 m_texture = m_window->createTextureFromId(defaultTexture, QSize(1, 1), defaultTextureOptions);
51 m_texture = m_window->createTextureFromImage(dummyImage, defaultTextureOptions);
54 52
55 53 setTexture(m_texture);
56 54 setFiltering(QSGTexture::Linear);
57 55
56 if (QOpenGLContext::currentContext()) {
58 57 // Create child node for rendering GL graphics
59 58 m_glRenderNode = new DeclarativeRenderNode(m_window);
60 59 m_glRenderNode->setFlag(OwnedByParent);
61 60 appendChildNode(m_glRenderNode);
62 61 m_glRenderNode->setRect(0, 0, 0, 0); // Hide child node by default
63 62 }
63 }
64 64
65 65 DeclarativeChartNode::~DeclarativeChartNode()
66 66 {
67 67 delete m_texture;
68 68 }
69 69
70 70 // Must be called on render thread and in context
71 71 void DeclarativeChartNode::createTextureFromImage(const QImage &chartImage)
72 72 {
73 73 if (chartImage.size() != m_textureSize)
74 74 m_textureSize = chartImage.size();
75 75
76 76 delete m_texture;
77 77 m_texture = m_window->createTextureFromImage(chartImage, m_textureOptions);
78 78 setTexture(m_texture);
79 79 }
80 80
81 81 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now