##// END OF EJS Templates
Fix resetting animation options mid-animation....
Miikka Heikkinen -
r2555:8f0e18a7e02c
parent child
Show More
@@ -0,0 +1,46
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
14 **
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
18 **
19 ****************************************************************************/
20
21 #include "chartanimation_p.h"
22
23 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24
25 ChartAnimation::ChartAnimation(QObject *parent) :
26 QVariantAnimation(parent),
27 m_destructing(false)
28 {
29 }
30
31 void ChartAnimation::stopAndDestroyLater()
32 {
33 m_destructing = true;
34 stop();
35 deleteLater();
36 }
37
38 void ChartAnimation::startChartAnimation()
39 {
40 if (!m_destructing)
41 start();
42 }
43
44 QTCOMMERCIALCHART_END_NAMESPACE
45
46
@@ -1,25 +1,26
1 1 INCLUDEPATH += $$PWD
2 2 DEPENDPATH += $$PWD
3 3
4 4 SOURCES += \
5 5 $$PWD/axisanimation.cpp \
6 6 $$PWD/xyanimation.cpp \
7 7 $$PWD/pieanimation.cpp \
8 8 $$PWD/piesliceanimation.cpp \
9 9 $$PWD/splineanimation.cpp \
10 10 $$PWD/baranimation.cpp \
11 11 $$PWD/scatteranimation.cpp \
12 12 $$PWD/boxplotanimation.cpp \
13 $$PWD/boxwhiskersanimation.cpp
13 $$PWD/boxwhiskersanimation.cpp \
14 $$PWD/chartanimation.cpp
14 15
15 16 PRIVATE_HEADERS += \
16 17 $$PWD/axisanimation_p.h \
17 18 $$PWD/chartanimation_p.h \
18 19 $$PWD/xyanimation_p.h \
19 20 $$PWD/pieanimation_p.h \
20 21 $$PWD/piesliceanimation_p.h \
21 22 $$PWD/splineanimation_p.h \
22 23 $$PWD/baranimation_p.h \
23 24 $$PWD/scatteranimation_p.h \
24 25 $$PWD/boxplotanimation_p.h \
25 26 $$PWD/boxwhiskersanimation_p.h
@@ -1,49 +1,57
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef CHARTANIMATION_H
31 31 #define CHARTANIMATION_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include <QVariantAnimation>
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37
38 38 const static int ChartAnimationDuration = 1000;
39 39
40 40 class ChartAnimation: public QVariantAnimation
41 41 {
42 42 Q_OBJECT
43 43 public:
44 ChartAnimation(QObject *parent = 0): QVariantAnimation(parent) {};
44 ChartAnimation(QObject *parent = 0);
45
46 void stopAndDestroyLater();
47
48 public Q_SLOTS:
49 void startChartAnimation();
50
51 protected:
52 bool m_destructing;
45 53 };
46 54
47 55 QTCOMMERCIALCHART_END_NAMESPACE
48 56
49 57 #endif /* CHARTANIMATION_H */
@@ -1,459 +1,465
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qareaseries.h"
22 22 #include "qareaseries_p.h"
23 23 #include "qlineseries.h"
24 24 #include "areachartitem_p.h"
25 25 #include "abstractdomain_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include "charttheme_p.h"
28 28 #include "qvalueaxis.h"
29 29 #include "qarealegendmarker.h"
30 30 #include "qchart_p.h"
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 /*!
35 35 \class QAreaSeries
36 36 \brief The QAreaSeries class is used for making area charts.
37 37
38 38 \mainclass
39 39
40 40 An area chart is used to show quantitative data. It is based on line chart, in the way that area between axis and the line
41 41 is emphasized with color. Since the area chart is based on line chart, QAreaSeries constructor needs QLineSeries instance,
42 42 which defines "upper" boundary of the area. "Lower" boundary is defined by default by axis X. Instead of axis X "lower" boundary can be specified by other line.
43 43 In that case QAreaSeries should be initiated with two QLineSeries instances. Please note terms "upper" and "lower" boundary can be misleading in cases
44 44 where "lower" boundary had bigger values than the "upper" one, however the main point that area between these two boundary lines will be filled.
45 45
46 46 See the \l {AreaChart Example} {area chart example} to learn how to create a simple area chart.
47 47 \image examples_areachart.png
48 48 */
49 49 /*!
50 50 \qmlclass AreaSeries QAreaSeries
51 51
52 52 The following QML shows how to create a simple area chart:
53 53 \snippet ../demos/qmlchart/qml/qmlchart/View4.qml 1
54 54 \beginfloatleft
55 55 \image demos_qmlchart4.png
56 56 \endfloat
57 57 \clearfloat
58 58 */
59 59
60 60 /*!
61 61 \property QAreaSeries::upperSeries
62 62 \brief The upper one of the two line series used to define area series boundaries.
63 63 */
64 64 /*!
65 65 \qmlproperty LineSeries AreaSeries::upperSeries
66 66 The upper one of the two line series used to define area series boundaries.
67 67 */
68 68
69 69 /*!
70 70 \property QAreaSeries::lowerSeries
71 71 The lower one of the two line series used to define are series boundaries. Note if
72 72 QAreaSeries was constructed without a\ lowerSeries this is null.
73 73 */
74 74 /*!
75 75 \qmlproperty LineSeries AreaSeries::lowerSeries
76 76 The lower one of the two line series used to define are series boundaries. Note if
77 77 AreaSeries was constructed without a\ lowerSeries this is null.
78 78 */
79 79
80 80 /*!
81 81 \property QAreaSeries::color
82 82 Fill (brush) color of the series. This is a convenience property for modifying the color of brush.
83 83 \sa QAreaSeries::brush()
84 84 */
85 85 /*!
86 86 \qmlproperty color AreaSeries::color
87 87 Fill (brush) color of the series.
88 88 */
89 89
90 90 /*!
91 91 \property QAreaSeries::borderColor
92 92 Line (pen) color of the series. This is a convenience property for modifying the color of pen.
93 93 \sa QAreaSeries::pen()
94 94 */
95 95 /*!
96 96 \qmlproperty color AreaSeries::borderColor
97 97 Line (pen) color of the series.
98 98 */
99 99
100 100 /*!
101 101 \qmlproperty real AreaSeries::borderWidth
102 102 The width of the border line. By default the width is 2.0.
103 103 */
104 104
105 105 /*!
106 106 \fn QPen QAreaSeries::pen() const
107 107 \brief Returns the pen used to draw line for this series.
108 108 \sa setPen()
109 109 */
110 110
111 111 /*!
112 112 \fn QPen QAreaSeries::brush() const
113 113 \brief Returns the brush used to draw line for this series.
114 114 \sa setBrush()
115 115 */
116 116
117 117 /*!
118 118 \fn void QAreaSeries::colorChanged(QColor color)
119 119 \brief Signal is emitted when the fill (brush) color has changed to \a color.
120 120 */
121 121 /*!
122 122 \qmlsignal AreaSeries::onColorChanged(color color)
123 123 Signal is emitted when the fill (brush) color has changed to \a color.
124 124 */
125 125
126 126 /*!
127 127 \fn void QAreaSeries::borderColorChanged(QColor color)
128 128 \brief Signal is emitted when the line (pen) color has changed to \a color.
129 129 */
130 130 /*!
131 131 \qmlsignal AreaSeries::onBorderColorChanged(color color)
132 132 Signal is emitted when the line (pen) color has changed to \a color.
133 133 */
134 134
135 135 /*!
136 136 \fn void QAreaSeries::clicked(const QPointF& point)
137 137 \brief Signal is emitted when user clicks the \a point on area chart.
138 138 */
139 139 /*!
140 140 \qmlsignal AreaSeries::onClicked(QPointF point)
141 141 Signal is emitted when user clicks the \a point on area chart.
142 142 */
143 143
144 144 /*!
145 145 \fn void QAreaSeries::hovered(const QPointF &point, bool state)
146 146 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
147 147 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
148 148 the series.
149 149 */
150 150 /*!
151 151 \qmlsignal AreaSeries::onHovered(point point, bool state)
152 152 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
153 153 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
154 154 the series.
155 155 */
156 156
157 157 /*!
158 158 \fn void QAreaSeries::selected()
159 159 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
160 160 implemented by the user of QAreaSeries API.
161 161 */
162 162 /*!
163 163 \qmlsignal AreaSeries::onSelected()
164 164 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
165 165 implemented by the user of AreaSeries API.
166 166 */
167 167
168 168 /*!
169 169 \fn void QAreaSeriesPrivate::updated()
170 170 \brief \internal
171 171 */
172 172
173 173 /*!
174 174 Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a
175 175 upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead.
176 176 When series object is added to QChartView or QChart instance ownerships is transferred.
177 177 */
178 178 QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries)
179 179 : QAbstractSeries(*new QAreaSeriesPrivate(upperSeries, lowerSeries, this), upperSeries)
180 180 {
181 181 }
182 182
183 183 /*!
184 184 Constructs area series object without upper or lower series with \a parent object.
185 185 */
186 186 QAreaSeries::QAreaSeries(QObject *parent)
187 187 : QAbstractSeries(*new QAreaSeriesPrivate(0, 0, this), parent)
188 188 {
189 189 }
190 190
191 191 /*!
192 192 Destroys the object.
193 193 */
194 194 QAreaSeries::~QAreaSeries()
195 195 {
196 196 Q_D(QAreaSeries);
197 197 if (d->m_chart)
198 198 d->m_chart->removeSeries(this);
199 199 }
200 200
201 201 /*!
202 202 Returns QAbstractSeries::SeriesTypeArea.
203 203 */
204 204 QAbstractSeries::SeriesType QAreaSeries::type() const
205 205 {
206 206 return QAbstractSeries::SeriesTypeArea;
207 207 }
208 208
209 209 /*!
210 210 Sets the \a series that is to be used as the area chart upper series.
211 211 */
212 212 void QAreaSeries::setUpperSeries(QLineSeries *series)
213 213 {
214 214 Q_D(QAreaSeries);
215 215 if (d->m_upperSeries != series)
216 216 d->m_upperSeries = series;
217 217 }
218 218
219 219 QLineSeries *QAreaSeries::upperSeries() const
220 220 {
221 221 Q_D(const QAreaSeries);
222 222 return d->m_upperSeries;
223 223 }
224 224
225 225 /*!
226 226 Sets the \a series that is to be used as the area chart lower series.
227 227 */
228 228 void QAreaSeries::setLowerSeries(QLineSeries *series)
229 229 {
230 230 Q_D(QAreaSeries);
231 231 d->m_lowerSeries = series;
232 232 }
233 233
234 234 QLineSeries *QAreaSeries::lowerSeries() const
235 235 {
236 236 Q_D(const QAreaSeries);
237 237 return d->m_lowerSeries;
238 238 }
239 239
240 240 /*!
241 241 Sets \a pen used for drawing area outline.
242 242 */
243 243 void QAreaSeries::setPen(const QPen &pen)
244 244 {
245 245 Q_D(QAreaSeries);
246 246 if (d->m_pen != pen) {
247 247 d->m_pen = pen;
248 248 emit d->updated();
249 249 }
250 250 }
251 251
252 252 QPen QAreaSeries::pen() const
253 253 {
254 254 Q_D(const QAreaSeries);
255 255 if (d->m_pen == QChartPrivate::defaultPen())
256 256 return QPen();
257 257 else
258 258 return d->m_pen;
259 259 }
260 260
261 261 /*!
262 262 Sets \a brush used for filling the area.
263 263 */
264 264 void QAreaSeries::setBrush(const QBrush &brush)
265 265 {
266 266 Q_D(QAreaSeries);
267 267 if (d->m_brush != brush) {
268 268 bool emitColorChanged = brush.color() != d->m_brush.color();
269 269 d->m_brush = brush;
270 270 emit d->updated();
271 271 if (emitColorChanged)
272 272 emit colorChanged(brush.color());
273 273 }
274 274 }
275 275
276 276 QBrush QAreaSeries::brush() const
277 277 {
278 278 Q_D(const QAreaSeries);
279 279 if (d->m_brush == QChartPrivate::defaultBrush())
280 280 return QBrush();
281 281 else
282 282 return d->m_brush;
283 283 }
284 284
285 285 void QAreaSeries::setColor(const QColor &color)
286 286 {
287 287 QBrush b = brush();
288 288 if (b == QBrush())
289 289 b.setStyle(Qt::SolidPattern);
290 290 b.setColor(color);
291 291 setBrush(b);
292 292 }
293 293
294 294 QColor QAreaSeries::color() const
295 295 {
296 296 return brush().color();
297 297 }
298 298
299 299 void QAreaSeries::setBorderColor(const QColor &color)
300 300 {
301 301 QPen p = pen();
302 302 if (p.color() != color) {
303 303 p.setColor(color);
304 304 setPen(p);
305 305 emit borderColorChanged(color);
306 306 }
307 307 }
308 308
309 309 QColor QAreaSeries::borderColor() const
310 310 {
311 311 return pen().color();
312 312 }
313 313
314 314 /*!
315 315 Sets if data points are \a visible and should be drawn on line.
316 316 */
317 317 void QAreaSeries::setPointsVisible(bool visible)
318 318 {
319 319 Q_D(QAreaSeries);
320 320 if (d->m_pointsVisible != visible) {
321 321 d->m_pointsVisible = visible;
322 322 emit d->updated();
323 323 }
324 324 }
325 325
326 326 /*!
327 327 Returns if the points are drawn for this series.
328 328 \sa setPointsVisible()
329 329 */
330 330 bool QAreaSeries::pointsVisible() const
331 331 {
332 332 Q_D(const QAreaSeries);
333 333 return d->m_pointsVisible;
334 334 }
335 335
336 336 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
337 337
338 338 QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries, QAreaSeries *q)
339 339 : QAbstractSeriesPrivate(q),
340 340 m_brush(QChartPrivate::defaultBrush()),
341 341 m_pen(QChartPrivate::defaultPen()),
342 342 m_upperSeries(upperSeries),
343 343 m_lowerSeries(lowerSeries),
344 344 m_pointsVisible(false)
345 345 {
346 346 }
347 347
348 348 void QAreaSeriesPrivate::initializeDomain()
349 349 {
350 350 Q_Q(QAreaSeries);
351 351
352 352 qreal minX(domain()->minX());
353 353 qreal minY(domain()->minY());
354 354 qreal maxX(domain()->maxX());
355 355 qreal maxY(domain()->maxY());
356 356
357 357 QLineSeries *upperSeries = q->upperSeries();
358 358 QLineSeries *lowerSeries = q->lowerSeries();
359 359
360 360 const QList<QPointF>& points = upperSeries->points();
361 361
362 362 for (int i = 0; i < points.count(); i++) {
363 363 qreal x = points[i].x();
364 364 qreal y = points[i].y();
365 365 minX = qMin(minX, x);
366 366 minY = qMin(minY, y);
367 367 maxX = qMax(maxX, x);
368 368 maxY = qMax(maxY, y);
369 369 }
370 370 if (lowerSeries) {
371 371
372 372 const QList<QPointF>& points = lowerSeries->points();
373 373
374 374 for (int i = 0; i < points.count(); i++) {
375 375 qreal x = points[i].x();
376 376 qreal y = points[i].y();
377 377 minX = qMin(minX, x);
378 378 minY = qMin(minY, y);
379 379 maxX = qMax(maxX, x);
380 380 maxY = qMax(maxY, y);
381 381 }
382 382 }
383 383
384 384 domain()->setRange(minX, maxX, minY, maxY);
385 385 }
386 386
387 387 void QAreaSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
388 388 {
389 389 Q_Q(QAreaSeries);
390 390 AreaChartItem *area = new AreaChartItem(q,parent);
391 391 m_item.reset(area);
392 392 QAbstractSeriesPrivate::initializeGraphics(parent);
393 393 }
394 394 void QAreaSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
395 395 {
396 396 Q_Q(QAreaSeries);
397 397 AreaChartItem *area = static_cast<AreaChartItem *>(m_item.data());
398
399 if (area->upperLineItem()->animation())
400 area->upperLineItem()->animation()->stopAndDestroyLater();
401 if (q->lowerSeries() && area->lowerLineItem()->animation())
402 area->lowerLineItem()->animation()->stopAndDestroyLater();
403
398 404 if (options.testFlag(QChart::SeriesAnimations)) {
399 405 area->upperLineItem()->setAnimation(new XYAnimation(area->upperLineItem()));
400 406 if (q->lowerSeries())
401 area->lowerLineItem()->setAnimation(new XYAnimation(area->lowerLineItem()));
402 }else{
407 area->lowerLineItem()->setAnimation(new XYAnimation(area->lowerLineItem()));
408 } else {
403 409 area->upperLineItem()->setAnimation(0);
404 410 if (q->lowerSeries())
405 411 area->lowerLineItem()->setAnimation(0);
406 412 }
407 413 QAbstractSeriesPrivate::initializeAnimations(options);
408 414 }
409 415
410 416 QList<QLegendMarker*> QAreaSeriesPrivate::createLegendMarkers(QLegend* legend)
411 417 {
412 418 Q_Q(QAreaSeries);
413 419 QList<QLegendMarker*> list;
414 420 return list << new QAreaLegendMarker(q,legend);
415 421 }
416 422
417 423
418 424 void QAreaSeriesPrivate::initializeAxes()
419 425 {
420 426
421 427 }
422 428
423 429 QAbstractAxis::AxisType QAreaSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
424 430 {
425 431 Q_UNUSED(orientation);
426 432 return QAbstractAxis::AxisTypeValue;
427 433 }
428 434
429 435 QAbstractAxis* QAreaSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
430 436 {
431 437 Q_UNUSED(orientation);
432 438 return 0;
433 439 }
434 440
435 441 void QAreaSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
436 442 {
437 443 Q_Q(QAreaSeries);
438 444
439 445 const QList<QGradient> gradients = theme->seriesGradients();
440 446 const QList<QColor> colors = theme->seriesColors();
441 447
442 448 if (forced || QChartPrivate::defaultPen() == m_pen) {
443 449 QPen pen;
444 450 pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0));
445 451 pen.setWidthF(2);
446 452 q->setPen(pen);
447 453 }
448 454
449 455 if (forced || QChartPrivate::defaultBrush() == m_brush) {
450 456 QBrush brush(colors.at(index % colors.size()));
451 457 q->setBrush(brush);
452 458 }
453 459 }
454 460
455 461
456 462 #include "moc_qareaseries.cpp"
457 463 #include "moc_qareaseries_p.cpp"
458 464
459 465 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,1012 +1,1014
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qabstractaxis.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "chartdataset_p.h"
24 24 #include "charttheme_p.h"
25 25 #include "qchart_p.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 /*!
30 30 \class QAbstractAxis
31 31 \brief The QAbstractAxis class is used for manipulating chart's axis.
32 32 \mainclass
33 33
34 34 Each series can be bound to one or more horizontal and vertical axes, but mixing axis types
35 35 that would result in different domains is not supported, such as specifying
36 36 QValueAxis and QLogValueAxis on the same orientation.
37 37
38 38 Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
39 39 and shades can be individually controlled.
40 40 */
41 41
42 42 /*!
43 43 \qmlclass AbstractAxis QAbstractAxis
44 44 \brief The AbstractAxis is a base element used for specialized axis elements.
45 45
46 46 Each series can be bound to only one horizontal and vertical axis.
47 47
48 48 Properties and visibility of various axis elements such as axis line, title, labels, grid lines,
49 49 and shades can be individually controlled.
50 50 */
51 51
52 52 /*!
53 53 \enum QAbstractAxis::AxisType
54 54
55 55 The type of the series object.
56 56
57 57 \value AxisTypeNoAxis
58 58 \value AxisTypeValue
59 59 \value AxisTypeBarCategory
60 60 \value AxisTypeCategory
61 61 \value AxisTypeDateTime
62 62 \value AxisTypeLogValue
63 63 */
64 64
65 65 /*!
66 66 *\fn void QAbstractAxis::type() const
67 67 Returns the type of the axis
68 68 */
69 69
70 70 /*!
71 71 \property QAbstractAxis::lineVisible
72 72 The visibility of the axis line
73 73 */
74 74 /*!
75 75 \qmlproperty bool AbstractAxis::lineVisible
76 76 The visibility of the axis line
77 77 */
78 78
79 79 /*!
80 80 \property QAbstractAxis::linePen
81 81 The pen of the line.
82 82 */
83 83
84 84 /*!
85 85 \property QAbstractAxis::labelsVisible
86 86 Defines if axis labels are visible.
87 87 */
88 88 /*!
89 89 \qmlproperty bool AbstractAxis::labelsVisible
90 90 Defines if axis labels are visible.
91 91 */
92 92
93 93 /*!
94 94 \property QAbstractAxis::labelsPen
95 95 \deprecated
96 96 The pen of the labels.
97 97 */
98 98
99 99 /*!
100 100 \property QAbstractAxis::labelsBrush
101 101 The brush of the labels. Only the color of the brush is relevant.
102 102 */
103 103
104 104 /*!
105 105 \property QAbstractAxis::visible
106 106 The visibility of the axis.
107 107 */
108 108 /*!
109 109 \qmlproperty bool AbstractAxis::visible
110 110 The visibility of the axis.
111 111 */
112 112
113 113 /*!
114 114 \property QAbstractAxis::gridVisible
115 115 The visibility of the grid lines.
116 116 */
117 117 /*!
118 118 \qmlproperty bool AbstractAxis::gridVisible
119 119 The visibility of the grid lines.
120 120 */
121 121
122 122 /*!
123 123 \property QAbstractAxis::color
124 124 The color of the axis and ticks.
125 125 */
126 126 /*!
127 127 \qmlproperty color AbstractAxis::color
128 128 The color of the axis and ticks.
129 129 */
130 130
131 131 /*!
132 132 \property QAbstractAxis::gridLinePen
133 133 The pen of the grid line.
134 134 */
135 135
136 136 /*!
137 137 \property QAbstractAxis::labelsFont
138 138 The font of the axis labels.
139 139 */
140 140
141 141 /*!
142 142 \qmlproperty Font AbstractAxis::labelsFont
143 143 The font of the axis labels.
144 144
145 145 See the \l {Font} {QML Font Element} for detailed documentation.
146 146 */
147 147
148 148 /*!
149 149 \property QAbstractAxis::labelsColor
150 150 The color of the axis labels.
151 151 */
152 152 /*!
153 153 \qmlproperty color AbstractAxis::labelsColor
154 154 The color of the axis labels.
155 155 */
156 156
157 157 /*!
158 158 \property QAbstractAxis::labelsAngle
159 159 The angle of the axis labels in degrees.
160 160 */
161 161 /*!
162 162 \qmlproperty int AbstractAxis::labelsAngle
163 163 The angle of the axis labels in degrees.
164 164 */
165 165
166 166 /*!
167 167 \property QAbstractAxis::shadesVisible
168 168 The visibility of the axis shades.
169 169 */
170 170 /*!
171 171 \qmlproperty bool AbstractAxis::shadesVisible
172 172 The visibility of the axis shades.
173 173 */
174 174
175 175 /*!
176 176 \property QAbstractAxis::shadesColor
177 177 The fill (brush) color of the axis shades.
178 178 */
179 179 /*!
180 180 \qmlproperty color AbstractAxis::shadesColor
181 181 The fill (brush) color of the axis shades.
182 182 */
183 183
184 184 /*!
185 185 \property QAbstractAxis::shadesBorderColor
186 186 The border (pen) color of the axis shades.
187 187 */
188 188 /*!
189 189 \qmlproperty color AbstractAxis::shadesBorderColor
190 190 The border (pen) color of the axis shades.
191 191 */
192 192
193 193 /*!
194 194 \property QAbstractAxis::shadesPen
195 195 The pen of the axis shades (area between grid lines).
196 196 */
197 197
198 198 /*!
199 199 \property QAbstractAxis::shadesBrush
200 200 The brush of the axis shades (area between grid lines).
201 201 */
202 202
203 203 /*!
204 204 \property QAbstractAxis::titleVisible
205 205 The visibility of the axis title. By default the value is true.
206 206 */
207 207 /*!
208 208 \qmlproperty bool AbstractAxis::titleVisible
209 209 The visibility of the axis title. By default the value is true.
210 210 */
211 211
212 212 /*!
213 213 \property QAbstractAxis::titleText
214 214 The title of the axis. Empty by default. Axis titles support html formatting.
215 215 */
216 216 /*!
217 217 \qmlproperty String AbstractAxis::titleText
218 218 The title of the axis. Empty by default. Axis titles support html formatting.
219 219 */
220 220
221 221 /*!
222 222 \property QAbstractAxis::titlePen
223 223 \deprecated
224 224 The pen of the title text.
225 225 */
226 226
227 227 /*!
228 228 \property QAbstractAxis::titleBrush
229 229 The brush of the title text. Only the color of the brush is relevant.
230 230 */
231 231
232 232 /*!
233 233 \property QAbstractAxis::titleFont
234 234 The font of the title of the axis.
235 235 */
236 236 /*!
237 237 \qmlproperty Font AbstractAxis::titleFont
238 238 The font of the title of the axis.
239 239 */
240 240
241 241 /*!
242 242 \property QAbstractAxis::orientation
243 243 The orientation of the axis. Fixed to either Qt::Horizontal or Qt::Vertical when you add the axis to a chart.
244 244 */
245 245 /*!
246 246 \qmlproperty Qt.Orientation AbstractAxis::orientation
247 247 The orientation of the axis. Fixed to either Qt.Horizontal or Qt.Vertical when the axis is set to a series.
248 248 */
249 249
250 250 /*!
251 251 \property QAbstractAxis::alignment
252 252 The alignment of the axis. Can be Qt::AlignLeft, Qt::AlignRight, Qt::AlignBottom, or Qt::AlignTop.
253 253 */
254 254 /*!
255 255 \qmlproperty alignment AbstractAxis::alignment
256 256 The alignment of the axis. Can be Qt.AlignLeft, Qt.AlignRight, Qt.AlignBottom, or Qt.AlignTop.
257 257 */
258 258
259 259 /*!
260 260 \fn void QAbstractAxis::visibleChanged(bool visible)
261 261 Visibility of the axis has changed to \a visible.
262 262 */
263 263 /*!
264 264 \qmlsignal AbstractAxis::onVisibleChanged(bool visible)
265 265 Visibility of the axis has changed to \a visible.
266 266 */
267 267
268 268 /*!
269 269 \fn void QAbstractAxis::linePenChanged(const QPen& pen)
270 270 The pen of the line of the axis has changed to \a pen.
271 271 */
272 272
273 273 /*!
274 274 \fn void QAbstractAxis::lineVisibleChanged(bool visible)
275 275 Visibility of the axis line has changed to \a visible.
276 276 */
277 277 /*!
278 278 \qmlsignal AbstractAxis::onLineVisibleChanged(bool visible)
279 279 Visibility of the axis line has changed to \a visible.
280 280 */
281 281
282 282 /*!
283 283 \fn void QAbstractAxis::labelsVisibleChanged(bool visible)
284 284 Visibility of the labels of the axis has changed to \a visible.
285 285 */
286 286 /*!
287 287 \qmlsignal AbstractAxis::onLabelsVisibleChanged(bool visible)
288 288 Visibility of the labels of the axis has changed to \a visible.
289 289 */
290 290
291 291 /*!
292 292 \fn void QAbstractAxis::labelsFontChanged(const QFont& font)
293 293 The font of the axis labels has changed to \a font.
294 294 */
295 295 /*!
296 296 \qmlsignal AbstractAxis::onLabelsFontChanged(Font font)
297 297 The font of the axis labels has changed to \a font.
298 298 */
299 299
300 300 /*!
301 301 \fn void QAbstractAxis::labelsPenChanged(const QPen& pen)
302 302 \deprecated
303 303 The pen of the axis labels has changed to \a pen.
304 304 */
305 305
306 306 /*!
307 307 \fn void QAbstractAxis::labelsBrushChanged(const QBrush& brush)
308 308 The brush of the axis labels has changed to \a brush.
309 309 */
310 310
311 311 /*!
312 312 \fn void QAbstractAxis::labelsAngleChanged(int angle)
313 313 The angle of the axis labels has changed to \a angle.
314 314 */
315 315 /*!
316 316 \qmlsignal AbstractAxis::onLabelsAngleChanged(int angle)
317 317 The angle of the axis labels has changed to \a angle.
318 318 */
319 319
320 320 /*!
321 321 \fn void QAbstractAxis::gridVisibleChanged(bool visible)
322 322 Visibility of the grid lines of the axis has changed to \a visible.
323 323 */
324 324 /*!
325 325 \qmlsignal AbstractAxis::onGridVisibleChanged(bool visible)
326 326 Visibility of the grid lines of the axis has changed to \a visible.
327 327 */
328 328
329 329 /*!
330 330 \fn void QAbstractAxis::gridLinePenChanged(const QPen& pen)
331 331 The pen of the grid line has changed to \a pen.
332 332 */
333 333
334 334 /*!
335 335 \fn void QAbstractAxis::colorChanged(QColor color)
336 336 Emitted if the \a color of the axis is changed.
337 337 */
338 338 /*!
339 339 \qmlsignal AbstractAxis::onColorChanged(QColor color)
340 340 Emitted if the \a color of the axis is changed.
341 341 */
342 342
343 343 /*!
344 344 \fn void QAbstractAxis::labelsColorChanged(QColor color)
345 345 Emitted if the \a color of the axis labels is changed.
346 346 */
347 347 /*!
348 348 \qmlsignal AbstractAxis::onLabelsColorChanged(QColor color)
349 349 Emitted if the \a color of the axis labels is changed.
350 350 */
351 351
352 352 /*!
353 353 \fn void QAbstractAxis::titleVisibleChanged(bool visible)
354 354 Visibility of the title text of the axis has changed to \a visible.
355 355 */
356 356 /*!
357 357 \qmlsignal AbstractAxis::onTitleVisibleChanged(bool visible)
358 358 Visibility of the title text of the axis has changed to \a visible.
359 359 */
360 360
361 361 /*!
362 362 \fn void QAbstractAxis::titleTextChanged(const QString& text)
363 363 The text of the axis title has changed to \a text.
364 364 */
365 365 /*!
366 366 \qmlsignal AbstractAxis::onTitleTextChanged(String text)
367 367 The text of the axis title has changed to \a text.
368 368 */
369 369
370 370 /*!
371 371 \fn void QAbstractAxis::titlePenChanged(const QPen& pen)
372 372 \deprecated
373 373 The pen of the axis shades has changed to \a pen.
374 374 */
375 375
376 376 /*!
377 377 \fn void QAbstractAxis::titleBrushChanged(const QBrush& brush)
378 378 The brush of the axis title has changed to \a brush.
379 379 */
380 380
381 381 /*!
382 382 \fn void QAbstractAxis::titleFontChanged(const QFont& font)
383 383 The font of the axis title has changed to \a font.
384 384 */
385 385 /*!
386 386 \qmlsignal AbstractAxis::onTitleFontChanged(Font font)
387 387 The font of the axis title has changed to \a font.
388 388 */
389 389
390 390 /*!
391 391 \fn void QAbstractAxis::shadesVisibleChanged(bool)
392 392 Emitted if the visibility of the axis shades is changed to \a visible.
393 393 */
394 394 /*!
395 395 \qmlsignal AbstractAxis::onShadesVisibleChanged(bool visible)
396 396 Emitted if the visibility of the axis shades is changed to \a visible.
397 397 */
398 398
399 399 /*!
400 400 \fn void QAbstractAxis::shadesColorChanged(QColor color)
401 401 Emitted if the \a color of the axis shades is changed.
402 402 */
403 403 /*!
404 404 \qmlsignal AbstractAxis::onShadesColorChanged(QColor color)
405 405 Emitted if the \a color of the axis shades is changed.
406 406 */
407 407
408 408 /*!
409 409 \fn void QAbstractAxis::shadesBorderColorChanged(QColor)
410 410 Emitted if the border \a color of the axis shades is changed.
411 411 */
412 412 /*!
413 413 \qmlsignal AbstractAxis::onBorderColorChanged(QColor color)
414 414 Emitted if the border \a color of the axis shades is changed.
415 415 */
416 416
417 417 /*!
418 418 \fn void QAbstractAxis::shadesBrushChanged(const QBrush& brush)
419 419 The brush of the axis shades has changed to \a brush.
420 420 */
421 421
422 422 /*!
423 423 \fn void QAbstractAxis::shadesPenChanged(const QPen& pen)
424 424 The pen of the axis shades has changed to \a pen.
425 425 */
426 426
427 427 /*!
428 428 \internal
429 429 Constructs new axis object which is a child of \a parent. Ownership is taken by
430 430 QChart when axis added.
431 431 */
432 432
433 433 QAbstractAxis::QAbstractAxis(QAbstractAxisPrivate &d, QObject *parent)
434 434 : QObject(parent),
435 435 d_ptr(&d)
436 436 {
437 437 }
438 438
439 439 /*!
440 440 Destructor of the axis object. When axis is added to chart, chart object takes ownership.
441 441 */
442 442
443 443 QAbstractAxis::~QAbstractAxis()
444 444 {
445 445 if (d_ptr->m_chart)
446 446 qFatal("Still binded axis detected !");
447 447 }
448 448
449 449 /*!
450 450 Sets \a pen used to draw axis line and ticks.
451 451 */
452 452 void QAbstractAxis::setLinePen(const QPen &pen)
453 453 {
454 454 if (d_ptr->m_axisPen != pen) {
455 455 d_ptr->m_axisPen = pen;
456 456 emit linePenChanged(pen);
457 457 }
458 458 }
459 459
460 460 /*!
461 461 Returns pen used to draw axis and ticks.
462 462 */
463 463 QPen QAbstractAxis::linePen() const
464 464 {
465 465 if (d_ptr->m_axisPen == QChartPrivate::defaultPen())
466 466 return QPen();
467 467 else
468 468 return d_ptr->m_axisPen;
469 469 }
470 470
471 471 //TODO: remove me 2.0
472 472 void QAbstractAxis::setLinePenColor(QColor color)
473 473 {
474 474 QPen p = d_ptr->m_axisPen;
475 475 if (p.color() != color) {
476 476 p.setColor(color);
477 477 setLinePen(p);
478 478 emit colorChanged(color);
479 479 }
480 480 }
481 481
482 482 QColor QAbstractAxis::linePenColor() const
483 483 {
484 484 return linePen().color();
485 485 }
486 486
487 487 /*!
488 488 Sets if axis and ticks are \a visible.
489 489 */
490 490 void QAbstractAxis::setLineVisible(bool visible)
491 491 {
492 492 if (d_ptr->m_arrowVisible != visible) {
493 493 d_ptr->m_arrowVisible = visible;
494 494 emit lineVisibleChanged(visible);
495 495 }
496 496 }
497 497
498 498 bool QAbstractAxis::isLineVisible() const
499 499 {
500 500 return d_ptr->m_arrowVisible;
501 501 }
502 502
503 503 void QAbstractAxis::setGridLineVisible(bool visible)
504 504 {
505 505 if (d_ptr->m_gridLineVisible != visible) {
506 506 d_ptr->m_gridLineVisible = visible;
507 507 emit gridVisibleChanged(visible);
508 508 }
509 509 }
510 510
511 511 bool QAbstractAxis::isGridLineVisible() const
512 512 {
513 513 return d_ptr->m_gridLineVisible;
514 514 }
515 515
516 516 /*!
517 517 Sets \a pen used to draw grid line.
518 518 */
519 519 void QAbstractAxis::setGridLinePen(const QPen &pen)
520 520 {
521 521 if (d_ptr->m_gridLinePen != pen) {
522 522 d_ptr->m_gridLinePen = pen;
523 523 emit gridLinePenChanged(pen);
524 524 }
525 525 }
526 526
527 527 /*!
528 528 Returns pen used to draw grid.
529 529 */
530 530 QPen QAbstractAxis::gridLinePen() const
531 531 {
532 532 if (d_ptr->m_gridLinePen == QChartPrivate::defaultPen())
533 533 return QPen();
534 534 else
535 535 return d_ptr->m_gridLinePen;
536 536 }
537 537
538 538 void QAbstractAxis::setLabelsVisible(bool visible)
539 539 {
540 540 if (d_ptr->m_labelsVisible != visible) {
541 541 d_ptr->m_labelsVisible = visible;
542 542 emit labelsVisibleChanged(visible);
543 543 }
544 544 }
545 545
546 546 bool QAbstractAxis::labelsVisible() const
547 547 {
548 548 return d_ptr->m_labelsVisible;
549 549 }
550 550
551 551 void QAbstractAxis::setLabelsPen(const QPen &pen)
552 552 {
553 553 if (d_ptr->m_labelsPen != pen) {
554 554 d_ptr->m_labelsPen = pen;
555 555 emit labelsPenChanged(pen);
556 556 }
557 557 }
558 558
559 559 QPen QAbstractAxis::labelsPen() const
560 560 {
561 561 if (d_ptr->m_labelsPen == QChartPrivate::defaultPen())
562 562 return QPen();
563 563 else
564 564 return d_ptr->m_labelsPen;
565 565 }
566 566
567 567 /*!
568 568 Sets \a brush used to draw labels.
569 569 */
570 570 void QAbstractAxis::setLabelsBrush(const QBrush &brush)
571 571 {
572 572 if (d_ptr->m_labelsBrush != brush) {
573 573 d_ptr->m_labelsBrush = brush;
574 574 emit labelsBrushChanged(brush);
575 575 }
576 576 }
577 577
578 578 /*!
579 579 Returns brush used to draw labels.
580 580 */
581 581 QBrush QAbstractAxis::labelsBrush() const
582 582 {
583 583 if (d_ptr->m_labelsBrush == QChartPrivate::defaultBrush())
584 584 return QBrush();
585 585 else
586 586 return d_ptr->m_labelsBrush;
587 587 }
588 588
589 589 /*!
590 590 Sets \a font used to draw labels.
591 591 */
592 592 void QAbstractAxis::setLabelsFont(const QFont &font)
593 593 {
594 594 if (d_ptr->m_labelsFont != font) {
595 595 d_ptr->m_labelsFont = font;
596 596 emit labelsFontChanged(font);
597 597 }
598 598 }
599 599
600 600 /*!
601 601 Returns font used to draw labels.
602 602 */
603 603 QFont QAbstractAxis::labelsFont() const
604 604 {
605 605 if (d_ptr->m_labelsFont == QChartPrivate::defaultFont())
606 606 return QFont();
607 607 else
608 608 return d_ptr->m_labelsFont;
609 609 }
610 610
611 611 void QAbstractAxis::setLabelsAngle(int angle)
612 612 {
613 613 if (d_ptr->m_labelsAngle != angle) {
614 614 d_ptr->m_labelsAngle = angle;
615 615 emit labelsAngleChanged(angle);
616 616 }
617 617 }
618 618
619 619 int QAbstractAxis::labelsAngle() const
620 620 {
621 621 return d_ptr->m_labelsAngle;
622 622 }
623 623 //TODO: remove me 2.0
624 624 void QAbstractAxis::setLabelsColor(QColor color)
625 625 {
626 626 QBrush b = d_ptr->m_labelsBrush;
627 627 if (b.color() != color) {
628 628 b.setColor(color);
629 629 setLabelsBrush(b);
630 630 emit labelsColorChanged(color);
631 631 }
632 632 }
633 633
634 634 QColor QAbstractAxis::labelsColor() const
635 635 {
636 636 return labelsBrush().color();
637 637 }
638 638
639 639 void QAbstractAxis::setTitleVisible(bool visible)
640 640 {
641 641 if (d_ptr->m_titleVisible != visible) {
642 642 d_ptr->m_titleVisible = visible;
643 643 emit titleVisibleChanged(visible);
644 644 }
645 645 }
646 646
647 647 bool QAbstractAxis::isTitleVisible() const
648 648 {
649 649 return d_ptr->m_titleVisible;
650 650 }
651 651
652 652 void QAbstractAxis::setTitlePen(const QPen &pen)
653 653 {
654 654 if (d_ptr->m_titlePen != pen) {
655 655 d_ptr->m_titlePen = pen;
656 656 emit titlePenChanged(pen);
657 657 }
658 658 }
659 659
660 660 QPen QAbstractAxis::titlePen() const
661 661 {
662 662 if (d_ptr->m_titlePen == QChartPrivate::defaultPen())
663 663 return QPen();
664 664 else
665 665 return d_ptr->m_titlePen;
666 666 }
667 667
668 668 /*!
669 669 Sets \a brush used to draw title.
670 670 */
671 671 void QAbstractAxis::setTitleBrush(const QBrush &brush)
672 672 {
673 673 if (d_ptr->m_titleBrush != brush) {
674 674 d_ptr->m_titleBrush = brush;
675 675 emit titleBrushChanged(brush);
676 676 }
677 677 }
678 678
679 679 /*!
680 680 Returns brush used to draw title.
681 681 */
682 682 QBrush QAbstractAxis::titleBrush() const
683 683 {
684 684 if (d_ptr->m_titleBrush == QChartPrivate::defaultBrush())
685 685 return QBrush();
686 686 else
687 687 return d_ptr->m_titleBrush;
688 688 }
689 689
690 690 /*!
691 691 Sets \a font used to draw title.
692 692 */
693 693 void QAbstractAxis::setTitleFont(const QFont &font)
694 694 {
695 695 if (d_ptr->m_titleFont != font) {
696 696 d_ptr->m_titleFont = font;
697 697 emit titleFontChanged(font);
698 698 }
699 699 }
700 700
701 701 /*!
702 702 Returns font used to draw title.
703 703 */
704 704 QFont QAbstractAxis::titleFont() const
705 705 {
706 706 if (d_ptr->m_titleFont == QChartPrivate::defaultFont())
707 707 return QFont();
708 708 else
709 709 return d_ptr->m_titleFont;
710 710 }
711 711
712 712 void QAbstractAxis::setTitleText(const QString &title)
713 713 {
714 714 if (d_ptr->m_title != title) {
715 715 d_ptr->m_title = title;
716 716 emit titleTextChanged(title);
717 717 }
718 718 }
719 719
720 720 QString QAbstractAxis::titleText() const
721 721 {
722 722 return d_ptr->m_title;
723 723 }
724 724
725 725
726 726 void QAbstractAxis::setShadesVisible(bool visible)
727 727 {
728 728 if (d_ptr->m_shadesVisible != visible) {
729 729 d_ptr->m_shadesVisible = visible;
730 730 emit shadesVisibleChanged(visible);
731 731 }
732 732 }
733 733
734 734 bool QAbstractAxis::shadesVisible() const
735 735 {
736 736 return d_ptr->m_shadesVisible;
737 737 }
738 738
739 739 /*!
740 740 Sets \a pen used to draw shades.
741 741 */
742 742 void QAbstractAxis::setShadesPen(const QPen &pen)
743 743 {
744 744 if (d_ptr->m_shadesPen != pen) {
745 745 d_ptr->m_shadesPen = pen;
746 746 emit shadesPenChanged(pen);
747 747 }
748 748 }
749 749
750 750 /*!
751 751 Returns pen used to draw shades.
752 752 */
753 753 QPen QAbstractAxis::shadesPen() const
754 754 {
755 755 if (d_ptr->m_shadesPen == QChartPrivate::defaultPen())
756 756 return QPen();
757 757 else
758 758 return d_ptr->m_shadesPen;
759 759 }
760 760
761 761 /*!
762 762 Sets \a brush used to draw shades.
763 763 */
764 764 void QAbstractAxis::setShadesBrush(const QBrush &brush)
765 765 {
766 766 if (d_ptr->m_shadesBrush != brush) {
767 767 d_ptr->m_shadesBrush = brush;
768 768 emit shadesBrushChanged(brush);
769 769 }
770 770 }
771 771
772 772 /*!
773 773 Returns brush used to draw shades.
774 774 */
775 775 QBrush QAbstractAxis::shadesBrush() const
776 776 {
777 777 if (d_ptr->m_shadesBrush == QChartPrivate::defaultBrush())
778 778 return QBrush(Qt::SolidPattern);
779 779 else
780 780 return d_ptr->m_shadesBrush;
781 781 }
782 782
783 783 void QAbstractAxis::setShadesColor(QColor color)
784 784 {
785 785 QBrush b = d_ptr->m_shadesBrush;
786 786 if (b.color() != color) {
787 787 b.setColor(color);
788 788 setShadesBrush(b);
789 789 emit shadesColorChanged(color);
790 790 }
791 791 }
792 792
793 793 QColor QAbstractAxis::shadesColor() const
794 794 {
795 795 return shadesBrush().color();
796 796 }
797 797
798 798 void QAbstractAxis::setShadesBorderColor(QColor color)
799 799 {
800 800 QPen p = d_ptr->m_shadesPen;
801 801 if (p.color() != color) {
802 802 p.setColor(color);
803 803 setShadesPen(p);
804 804 emit shadesColorChanged(color);
805 805 }
806 806 }
807 807
808 808 QColor QAbstractAxis::shadesBorderColor() const
809 809 {
810 810 return shadesPen().color();
811 811 }
812 812
813 813
814 814 bool QAbstractAxis::isVisible() const
815 815 {
816 816 return d_ptr->m_visible;
817 817 }
818 818
819 819 /*!
820 820 Sets axis, shades, labels and grid lines to be visible.
821 821 */
822 822 void QAbstractAxis::setVisible(bool visible)
823 823 {
824 824 if (d_ptr->m_visible != visible) {
825 825 d_ptr->m_visible = visible;
826 826 emit visibleChanged(visible);
827 827 }
828 828 }
829 829
830 830
831 831 /*!
832 832 Sets axis, shades, labels and grid lines to be visible.
833 833 */
834 834 void QAbstractAxis::show()
835 835 {
836 836 setVisible(true);
837 837 }
838 838
839 839 /*!
840 840 Sets axis, shades, labels and grid lines to not be visible.
841 841 */
842 842 void QAbstractAxis::hide()
843 843 {
844 844 setVisible(false);
845 845 }
846 846
847 847 /*!
848 848 Sets the minimum value shown on the axis.
849 849 Depending on the actual axis type the \a min parameter is converted to appropriate type.
850 850 If the conversion is impossible then the function call does nothing
851 851 */
852 852 void QAbstractAxis::setMin(const QVariant &min)
853 853 {
854 854 d_ptr->setMin(min);
855 855 }
856 856
857 857 /*!
858 858 Sets the maximum value shown on the axis.
859 859 Depending on the actual axis type the \a max parameter is converted to appropriate type.
860 860 If the conversion is impossible then the function call does nothing
861 861 */
862 862 void QAbstractAxis::setMax(const QVariant &max)
863 863 {
864 864 d_ptr->setMax(max);
865 865 }
866 866
867 867 /*!
868 868 Sets the range shown on the axis.
869 869 Depending on the actual axis type the \a min and \a max parameters are converted to appropriate types.
870 870 If the conversion is impossible then the function call does nothing.
871 871 */
872 872 void QAbstractAxis::setRange(const QVariant &min, const QVariant &max)
873 873 {
874 874 d_ptr->setRange(min, max);
875 875 }
876 876
877 877
878 878 /*!
879 879 Returns the orientation in which the axis is being used (Vertical or Horizontal)
880 880 */
881 881 // NOTE: should have const but it breaks BC:
882 882 // http://techbase.kde.org/Policies/Binary_Compatibility_Examples#Change_the_CV-qualifiers_of_a_member_function
883 883 Qt::Orientation QAbstractAxis::orientation()
884 884 {
885 885 return d_ptr->orientation();
886 886 }
887 887
888 888 Qt::Alignment QAbstractAxis::alignment() const
889 889 {
890 890 return d_ptr->alignment();
891 891 }
892 892
893 893 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
894 894
895 895 QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q)
896 896 : q_ptr(q),
897 897 m_chart(0),
898 898 m_alignment(0),
899 899 m_orientation(Qt::Orientation(0)),
900 900 m_visible(true),
901 901 m_arrowVisible(true),
902 902 m_axisPen(QChartPrivate::defaultPen()),
903 903 m_axisBrush(QChartPrivate::defaultBrush()),
904 904 m_gridLineVisible(true),
905 905 m_gridLinePen(QChartPrivate::defaultPen()),
906 906 m_labelsVisible(true),
907 907 m_labelsPen(QChartPrivate::defaultPen()),
908 908 m_labelsBrush(QChartPrivate::defaultBrush()),
909 909 m_labelsFont(QChartPrivate::defaultFont()),
910 910 m_labelsAngle(0),
911 911 m_titleVisible(true),
912 912 m_titlePen(QChartPrivate::defaultPen()),
913 913 m_titleBrush(QChartPrivate::defaultBrush()),
914 914 m_titleFont(QChartPrivate::defaultFont()),
915 915 m_shadesVisible(false),
916 916 m_shadesPen(QChartPrivate::defaultPen()),
917 917 m_shadesBrush(QChartPrivate::defaultBrush()),
918 918 m_shadesOpacity(1.0),
919 919 m_dirty(false)
920 920 {
921 921 }
922 922
923 923 QAbstractAxisPrivate::~QAbstractAxisPrivate()
924 924 {
925 925 }
926 926
927 927 void QAbstractAxisPrivate::setAlignment( Qt::Alignment alignment)
928 928 {
929 929 switch(alignment) {
930 930 case Qt::AlignTop:
931 931 case Qt::AlignBottom:
932 932 m_orientation = Qt::Horizontal;
933 933 break;
934 934 case Qt::AlignLeft:
935 935 case Qt::AlignRight:
936 936 m_orientation = Qt::Vertical;
937 937 break;
938 938 default:
939 939 qWarning()<<"No alignment specified !";
940 940 break;
941 941 };
942 942 m_alignment=alignment;
943 943 }
944 944
945 945 void QAbstractAxisPrivate::initializeTheme(ChartTheme* theme, bool forced)
946 946 {
947 947 //TODO: introduce axis brush
948 948 if (forced || QChartPrivate::defaultPen() == m_axisPen)
949 949 q_ptr->setLinePen(theme->axisLinePen());
950 950
951 951 if (forced || QChartPrivate::defaultPen() == m_gridLinePen)
952 952 q_ptr->setGridLinePen(theme->girdLinePen());
953 953
954 954 if (forced || QChartPrivate::defaultBrush() == m_labelsBrush)
955 955 q_ptr->setLabelsBrush(theme->labelBrush());
956 956 if (forced || QChartPrivate::defaultPen() == m_labelsPen)
957 957 q_ptr->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
958 958 if (forced || QChartPrivate::defaultFont() == m_labelsFont)
959 959 q_ptr->setLabelsFont(theme->labelFont());
960 960
961 961 if (forced || QChartPrivate::defaultBrush() == m_titleBrush)
962 962 q_ptr->setTitleBrush(theme->labelBrush());
963 963 if (forced || QChartPrivate::defaultPen() == m_titlePen)
964 964 q_ptr->setTitlePen(Qt::NoPen); // NoPen for performance reasons
965 965 if (forced || QChartPrivate::defaultFont() == m_titleFont) {
966 966 QFont font(m_labelsFont);
967 967 font.setBold(true);
968 968 q_ptr->setTitleFont(font);
969 969 }
970 970
971 971 if (forced || QChartPrivate::defaultBrush() == m_shadesBrush)
972 972 q_ptr->setShadesBrush(theme->backgroundShadesBrush());
973 973 if (forced || QChartPrivate::defaultPen() == m_shadesPen)
974 974 q_ptr->setShadesPen(theme->backgroundShadesPen());
975 975
976 976 bool axisX = m_orientation == Qt::Horizontal;
977 977 if (forced && (theme->backgroundShades() == ChartTheme::BackgroundShadesBoth
978 978 || (theme->backgroundShades() == ChartTheme::BackgroundShadesVertical && axisX)
979 979 || (theme->backgroundShades() == ChartTheme::BackgroundShadesHorizontal && !axisX))) {
980 980 q_ptr->setShadesVisible(true);
981 981 } else if (forced) {
982 982 q_ptr->setShadesVisible(false);
983 983 }
984 984 }
985 985
986 986 void QAbstractAxisPrivate::handleRangeChanged(qreal min, qreal max)
987 987 {
988 988 setRange(min,max);
989 989 }
990 990
991 991 void QAbstractAxisPrivate::initializeGraphics(QGraphicsItem* parent)
992 992 {
993 993 Q_UNUSED(parent);
994 994 }
995 995
996 996 void QAbstractAxisPrivate::initializeAnimations(QChart::AnimationOptions options)
997 997 {
998 998 ChartAxisElement *axis = m_item.data();
999 999 Q_ASSERT(axis);
1000 if (options.testFlag(QChart::GridAxisAnimations)) {
1000 if (axis->animation())
1001 axis->animation()->stopAndDestroyLater();
1002
1003 if (options.testFlag(QChart::GridAxisAnimations))
1001 1004 axis->setAnimation(new AxisAnimation(axis));
1002 } else {
1005 else
1003 1006 axis->setAnimation(0);
1004 }
1005 1007 }
1006 1008
1007 1009
1008 1010
1009 1011 #include "moc_qabstractaxis.cpp"
1010 1012 #include "moc_qabstractaxis_p.cpp"
1011 1013
1012 1014 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,901 +1,903
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qabstractbarseries.h"
22 22 #include "qabstractbarseries_p.h"
23 23 #include "qbarset.h"
24 24 #include "qbarset_p.h"
25 25 #include "abstractdomain_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include "charttheme_p.h"
28 28 #include "qvalueaxis.h"
29 29 #include "qbarcategoryaxis.h"
30 30 #include "qbarlegendmarker.h"
31 31 #include "baranimation_p.h"
32 32 #include "abstractbarchartitem_p.h"
33 33 #include "qchart_p.h"
34 34
35 35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 36
37 37 /*!
38 38 \class QAbstractBarSeries
39 39 \brief Series for creating a bar chart.
40 40 \mainclass
41 41
42 42 QAbstractBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars to
43 43 the position defined by data. Single bar is defined by QPointF, where x value is the x-coordinate of the bar
44 44 and y-value is the height of the bar. The category names are ignored with this series and x-axis
45 45 shows the x-values.
46 46
47 47 See the \l {BarChart Example} {bar chart example} to learn how to create a simple bar chart.
48 48 \image examples_barchart.png
49 49
50 50 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
51 51 */
52 52 /*!
53 53 \qmlclass AbstractBarSeries QAbstractBarSeries
54 54 \inherits QAbstractSeries
55 55
56 56 The following QML shows how to create a simple bar chart:
57 57 \snippet ../demos/qmlchart/qml/qmlchart/View6.qml 1
58 58
59 59 \beginfloatleft
60 60 \image demos_qmlchart6.png
61 61 \endfloat
62 62 \clearfloat
63 63 */
64 64
65 65 /*!
66 66 \qmlproperty AbstractAxis AbstractBarSeries::axisX
67 67 The x axis used for the series. If you leave both axisX and axisXTop undefined, a BarCategoriesAxis is created for
68 68 the series.
69 69 \sa axisXTop
70 70 */
71 71
72 72 /*!
73 73 \qmlproperty AbstractAxis AbstractBarSeries::axisY
74 74 The y axis used for the series. If you leave both axisY and axisYRight undefined, a ValueAxis is created for
75 75 the series.
76 76 \sa axisYRight
77 77 */
78 78
79 79 /*!
80 80 \qmlproperty AbstractAxis AbstractBarSeries::axisXTop
81 81 The x axis used for the series, drawn on top of the chart view. Note that you can only provide either axisX or
82 82 axisXTop, but not both.
83 83 \sa axisX
84 84 */
85 85
86 86 /*!
87 87 \qmlproperty AbstractAxis AbstractBarSeries::axisYRight
88 88 The y axis used for the series, drawn to the right on the chart view. Note that you can only provide either axisY
89 89 or axisYRight, but not both.
90 90 \sa axisY
91 91 */
92 92
93 93 /*!
94 94 \property QAbstractBarSeries::barWidth
95 95 The width of the bars of the series. The unit of \a width is the unit of x-axis. The minimum width for bars
96 96 is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
97 97 is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
98 98 Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
99 99 \sa QBarSeries
100 100 */
101 101 /*!
102 102 \qmlproperty real AbstractBarSeries::barWidth
103 103 The width of the bars of the series. The unit of width is the unit of x-axis. The minimum width for bars
104 104 is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
105 105 is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
106 106 Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
107 107 */
108 108
109 109 /*!
110 110 \property QAbstractBarSeries::count
111 111 Holds the number of sets in series.
112 112 */
113 113 /*!
114 114 \qmlproperty int AbstractBarSeries::count
115 115 Holds the number of sets in series.
116 116 */
117 117
118 118 /*!
119 119 \property QAbstractBarSeries::labelsVisible
120 120 Defines the visibility of the labels in series
121 121 */
122 122 /*!
123 123 \qmlproperty bool AbstractBarSeries::labelsVisible
124 124 Defines the visibility of the labels in series
125 125 */
126 126
127 127 /*!
128 128 \fn void QAbstractBarSeries::clicked(int index, QBarSet *barset)
129 129 The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset.
130 130 Clicked bar inside set is indexed by \a index
131 131 */
132 132 /*!
133 133 \qmlsignal AbstractBarSeries::onClicked(int index, BarSet barset)
134 134 The signal is emitted if the user clicks with a mouse on top of BarSet.
135 135 Clicked bar inside set is indexed by \a index
136 136 */
137 137
138 138 /*!
139 139 \fn void QAbstractBarSeries::hovered(bool status, QBarSet* barset)
140 140
141 141 The signal is emitted if mouse is hovered on top of series.
142 142 Parameter \a barset is the pointer of barset, where hover happened.
143 143 Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
144 144 */
145 145 /*!
146 146 \qmlsignal AbstractBarSeries::onHovered(bool status, BarSet barset)
147 147
148 148 The signal is emitted if mouse is hovered on top of series.
149 149 Parameter \a barset is the pointer of barset, where hover happened.
150 150 Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
151 151 */
152 152
153 153 /*!
154 154 \fn void QAbstractBarSeries::countChanged()
155 155 This signal is emitted when barset count has been changed, for example by append or remove.
156 156 */
157 157 /*!
158 158 \qmlsignal AbstractBarSeries::onCountChanged()
159 159 This signal is emitted when barset count has been changed, for example by append or remove.
160 160 */
161 161
162 162 /*!
163 163 \fn void QAbstractBarSeries::labelsVisibleChanged()
164 164 This signal is emitted when labels visibility have changed.
165 165 \sa isLabelsVisible(), setLabelsVisible()
166 166 */
167 167
168 168 /*!
169 169 \fn void QAbstractBarSeries::barsetsAdded(QList<QBarSet*> sets)
170 170 This signal is emitted when \a sets have been added to the series.
171 171 \sa append(), insert()
172 172 */
173 173 /*!
174 174 \qmlsignal AbstractBarSeries::onBarsetsAdded(BarSet barset)
175 175 Emitted when \a barset has been added to the series.
176 176 */
177 177
178 178 /*!
179 179 \fn void QAbstractBarSeries::barsetsRemoved(QList<QBarSet*> sets)
180 180 This signal is emitted when \a sets have been removed from the series.
181 181 \sa remove()
182 182 */
183 183 /*!
184 184 \qmlsignal AbstractBarSeries::onBarsetsRemoved(BarSet barset)
185 185 Emitted when \a barset has been removed from the series.
186 186 */
187 187
188 188 /*!
189 189 \qmlmethod BarSet AbstractBarSeries::at(int index)
190 190 Returns bar set at \a index. Returns null if the index is not valid.
191 191 */
192 192
193 193 /*!
194 194 \qmlmethod BarSet AbstractBarSeries::append(string label, VariantList values)
195 195 Adds a new bar set with \a label and \a values to \a index. Values is a list of reals.
196 196 For example:
197 197 \code
198 198 myBarSeries.append("set 1", [0, 0.2, 0.2, 0.5, 0.4, 1.5, 0.9]);
199 199 \endcode
200 200 */
201 201
202 202 /*!
203 203 \qmlmethod BarSet AbstractBarSeries::insert(int index, string label, VariantList values)
204 204 Inserts a new bar set with \a label and \a values to \a index. Values can be a list of reals or a list of XYPoints.
205 205 If index is zero or smaller, the new barset is prepended. If the index is count or bigger, the new barset is
206 206 appended.
207 207 \sa AbstractBarSeries::append()
208 208 */
209 209
210 210 /*!
211 211 \qmlmethod bool AbstractBarSeries::remove(BarSet barset)
212 212 Removes the barset from the series. Returns true if successful, false otherwise.
213 213 */
214 214
215 215 /*!
216 216 \qmlmethod AbstractBarSeries::clear()
217 217 Removes all barsets from the series.
218 218 */
219 219
220 220 /*!
221 221 Destructs abstractbarseries and owned barsets.
222 222 */
223 223 QAbstractBarSeries::~QAbstractBarSeries()
224 224 {
225 225
226 226 }
227 227
228 228 /*!
229 229 \internal
230 230 */
231 231 QAbstractBarSeries::QAbstractBarSeries(QAbstractBarSeriesPrivate &o, QObject *parent)
232 232 : QAbstractSeries(o, parent)
233 233 {
234 234 Q_D(QAbstractSeries);
235 235 QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged()));
236 236 }
237 237
238 238 /*!
239 239 Sets the width of the bars of the series. The unit of \a width is the unit of x-axis. The minimum width for bars
240 240 is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
241 241 is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
242 242 Note that with \link QBarSeries \endlink this value means the width of one group of bars instead of just one bar.
243 243 */
244 244 void QAbstractBarSeries::setBarWidth(qreal width)
245 245 {
246 246 Q_D(QAbstractBarSeries);
247 247 d->setBarWidth(width);
248 248 }
249 249
250 250 /*!
251 251 Returns the width of the bars of the series.
252 252 \sa setBarWidth()
253 253 */
254 254 qreal QAbstractBarSeries::barWidth() const
255 255 {
256 256 Q_D(const QAbstractBarSeries);
257 257 return d->barWidth();
258 258 }
259 259
260 260 /*!
261 261 Adds a set of bars to series. Takes ownership of \a set. If the set is null or is already in series, it won't be appended.
262 262 Returns true, if appending succeeded.
263 263 */
264 264 bool QAbstractBarSeries::append(QBarSet *set)
265 265 {
266 266 Q_D(QAbstractBarSeries);
267 267 bool success = d->append(set);
268 268 if (success) {
269 269 QList<QBarSet *> sets;
270 270 sets.append(set);
271 271 set->setParent(this);
272 272 emit barsetsAdded(sets);
273 273 emit countChanged();
274 274 }
275 275 return success;
276 276 }
277 277
278 278 /*!
279 279 Removes barset from series. Releases ownership of \a set. Deletes the set, if remove
280 280 was successful.
281 281 Returns true, if set was removed.
282 282 */
283 283 bool QAbstractBarSeries::remove(QBarSet *set)
284 284 {
285 285 Q_D(QAbstractBarSeries);
286 286 bool success = d->remove(set);
287 287 if (success) {
288 288 QList<QBarSet *> sets;
289 289 sets.append(set);
290 290 set->setParent(0);
291 291 emit barsetsRemoved(sets);
292 292 emit countChanged();
293 293 delete set;
294 294 set = 0;
295 295 }
296 296 return success;
297 297 }
298 298
299 299 /*!
300 300 Takes a single \a set from the series. Does not delete the barset object.
301 301
302 302 NOTE: The series remains as the barset's parent object. You must set the
303 303 parent object to take full ownership.
304 304
305 305 Returns true if take was successful.
306 306 */
307 307 bool QAbstractBarSeries::take(QBarSet *set)
308 308 {
309 309 Q_D(QAbstractBarSeries);
310 310 bool success = d->remove(set);
311 311 if (success) {
312 312 QList<QBarSet *> sets;
313 313 sets.append(set);
314 314 emit barsetsRemoved(sets);
315 315 emit countChanged();
316 316 }
317 317 return success;
318 318 }
319 319
320 320 /*!
321 321 Adds a list of barsets to series. Takes ownership of \a sets.
322 322 Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
323 323 nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
324 324 and function returns false.
325 325 */
326 326 bool QAbstractBarSeries::append(QList<QBarSet *> sets)
327 327 {
328 328 Q_D(QAbstractBarSeries);
329 329 bool success = d->append(sets);
330 330 if (success) {
331 331 emit barsetsAdded(sets);
332 332 emit countChanged();
333 333 }
334 334 return success;
335 335 }
336 336
337 337 /*!
338 338 Insert a set of bars to series at \a index postion. Takes ownership of \a set. If the set is null or is already in series, it won't be appended.
339 339 Returns true, if inserting succeeded.
340 340
341 341 */
342 342 bool QAbstractBarSeries::insert(int index, QBarSet *set)
343 343 {
344 344 Q_D(QAbstractBarSeries);
345 345 bool success = d->insert(index, set);
346 346 if (success) {
347 347 QList<QBarSet *> sets;
348 348 sets.append(set);
349 349 emit barsetsAdded(sets);
350 350 emit countChanged();
351 351 }
352 352 return success;
353 353 }
354 354
355 355 /*!
356 356 Removes all barsets from the series. Deletes removed sets.
357 357 */
358 358 void QAbstractBarSeries::clear()
359 359 {
360 360 Q_D(QAbstractBarSeries);
361 361 QList<QBarSet *> sets = barSets();
362 362 bool success = d->remove(sets);
363 363 if (success) {
364 364 emit barsetsRemoved(sets);
365 365 emit countChanged();
366 366 foreach (QBarSet *set, sets)
367 367 delete set;
368 368 }
369 369 }
370 370
371 371 /*!
372 372 Returns number of sets in series.
373 373 */
374 374 int QAbstractBarSeries::count() const
375 375 {
376 376 Q_D(const QAbstractBarSeries);
377 377 return d->m_barSets.count();
378 378 }
379 379
380 380 /*!
381 381 Returns a list of sets in series. Keeps ownership of sets.
382 382 */
383 383 QList<QBarSet *> QAbstractBarSeries::barSets() const
384 384 {
385 385 Q_D(const QAbstractBarSeries);
386 386 return d->m_barSets;
387 387 }
388 388
389 389 /*!
390 390 Sets the visibility of labels in series to \a visible
391 391 */
392 392 void QAbstractBarSeries::setLabelsVisible(bool visible)
393 393 {
394 394 Q_D(QAbstractBarSeries);
395 395 if (d->m_labelsVisible != visible) {
396 396 d->setLabelsVisible(visible);
397 397 emit labelsVisibleChanged();
398 398 }
399 399 }
400 400
401 401 /*!
402 402 Returns the visibility of labels
403 403 */
404 404 bool QAbstractBarSeries::isLabelsVisible() const
405 405 {
406 406 Q_D(const QAbstractBarSeries);
407 407 return d->m_labelsVisible;
408 408 }
409 409
410 410 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
411 411
412 412 QAbstractBarSeriesPrivate::QAbstractBarSeriesPrivate(QAbstractBarSeries *q) :
413 413 QAbstractSeriesPrivate(q),
414 414 m_barWidth(0.5), // Default value is 50% of category width
415 415 m_labelsVisible(false),
416 416 m_visible(true)
417 417 {
418 418 }
419 419
420 420 int QAbstractBarSeriesPrivate::categoryCount() const
421 421 {
422 422 // No categories defined. return count of longest set.
423 423 int count = 0;
424 424 for (int i = 0; i < m_barSets.count(); i++) {
425 425 if (m_barSets.at(i)->count() > count)
426 426 count = m_barSets.at(i)->count();
427 427 }
428 428
429 429 return count;
430 430 }
431 431
432 432 void QAbstractBarSeriesPrivate::setBarWidth(qreal width)
433 433 {
434 434 if (width < 0.0)
435 435 width = 0.0;
436 436 m_barWidth = width;
437 437 emit updatedLayout();
438 438 }
439 439
440 440 qreal QAbstractBarSeriesPrivate::barWidth() const
441 441 {
442 442 return m_barWidth;
443 443 }
444 444
445 445 QBarSet *QAbstractBarSeriesPrivate::barsetAt(int index)
446 446 {
447 447 return m_barSets.at(index);
448 448 }
449 449
450 450 void QAbstractBarSeriesPrivate::setVisible(bool visible)
451 451 {
452 452 m_visible = visible;
453 453 emit visibleChanged();
454 454 }
455 455
456 456 void QAbstractBarSeriesPrivate::setLabelsVisible(bool visible)
457 457 {
458 458 m_labelsVisible = visible;
459 459 emit labelsVisibleChanged(visible);
460 460 }
461 461
462 462 qreal QAbstractBarSeriesPrivate::min()
463 463 {
464 464 if (m_barSets.count() <= 0)
465 465 return 0;
466 466
467 467 qreal min = INT_MAX;
468 468
469 469 for (int i = 0; i < m_barSets.count(); i++) {
470 470 int categoryCount = m_barSets.at(i)->count();
471 471 for (int j = 0; j < categoryCount; j++) {
472 472 qreal temp = m_barSets.at(i)->at(j);
473 473 if (temp < min)
474 474 min = temp;
475 475 }
476 476 }
477 477 return min;
478 478 }
479 479
480 480 qreal QAbstractBarSeriesPrivate::max()
481 481 {
482 482 if (m_barSets.count() <= 0)
483 483 return 0;
484 484
485 485 qreal max = INT_MIN;
486 486
487 487 for (int i = 0; i < m_barSets.count(); i++) {
488 488 int categoryCount = m_barSets.at(i)->count();
489 489 for (int j = 0; j < categoryCount; j++) {
490 490 qreal temp = m_barSets.at(i)->at(j);
491 491 if (temp > max)
492 492 max = temp;
493 493 }
494 494 }
495 495
496 496 return max;
497 497 }
498 498
499 499 qreal QAbstractBarSeriesPrivate::valueAt(int set, int category)
500 500 {
501 501 if ((set < 0) || (set >= m_barSets.count()))
502 502 return 0; // No set, no value.
503 503 else if ((category < 0) || (category >= m_barSets.at(set)->count()))
504 504 return 0; // No category, no value.
505 505
506 506 return m_barSets.at(set)->at(category);
507 507 }
508 508
509 509 qreal QAbstractBarSeriesPrivate::percentageAt(int set, int category)
510 510 {
511 511 if ((set < 0) || (set >= m_barSets.count()))
512 512 return 0; // No set, no value.
513 513 else if ((category < 0) || (category >= m_barSets.at(set)->count()))
514 514 return 0; // No category, no value.
515 515
516 516 qreal value = m_barSets.at(set)->at(category);
517 517 qreal sum = categorySum(category);
518 518 if (qFuzzyCompare(sum, 0))
519 519 return 0;
520 520
521 521 return value / sum;
522 522 }
523 523
524 524 qreal QAbstractBarSeriesPrivate::categorySum(int category)
525 525 {
526 526 qreal sum(0);
527 527 int count = m_barSets.count(); // Count sets
528 528 for (int set = 0; set < count; set++) {
529 529 if (category < m_barSets.at(set)->count())
530 530 sum += m_barSets.at(set)->at(category);
531 531 }
532 532 return sum;
533 533 }
534 534
535 535 qreal QAbstractBarSeriesPrivate::absoluteCategorySum(int category)
536 536 {
537 537 qreal sum(0);
538 538 int count = m_barSets.count(); // Count sets
539 539 for (int set = 0; set < count; set++) {
540 540 if (category < m_barSets.at(set)->count())
541 541 sum += qAbs(m_barSets.at(set)->at(category));
542 542 }
543 543 return sum;
544 544 }
545 545
546 546 qreal QAbstractBarSeriesPrivate::maxCategorySum()
547 547 {
548 548 qreal max = INT_MIN;
549 549 int count = categoryCount();
550 550 for (int i = 0; i < count; i++) {
551 551 qreal sum = categorySum(i);
552 552 if (sum > max)
553 553 max = sum;
554 554 }
555 555 return max;
556 556 }
557 557
558 558 qreal QAbstractBarSeriesPrivate::minX()
559 559 {
560 560 if (m_barSets.count() <= 0)
561 561 return 0;
562 562
563 563 qreal min = INT_MAX;
564 564
565 565 for (int i = 0; i < m_barSets.count(); i++) {
566 566 int categoryCount = m_barSets.at(i)->count();
567 567 for (int j = 0; j < categoryCount; j++) {
568 568 qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
569 569 if (temp < min)
570 570 min = temp;
571 571 }
572 572 }
573 573 return min;
574 574 }
575 575
576 576 qreal QAbstractBarSeriesPrivate::maxX()
577 577 {
578 578 if (m_barSets.count() <= 0)
579 579 return 0;
580 580
581 581 qreal max = INT_MIN;
582 582
583 583 for (int i = 0; i < m_barSets.count(); i++) {
584 584 int categoryCount = m_barSets.at(i)->count();
585 585 for (int j = 0; j < categoryCount; j++) {
586 586 qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
587 587 if (temp > max)
588 588 max = temp;
589 589 }
590 590 }
591 591
592 592 return max;
593 593 }
594 594
595 595 qreal QAbstractBarSeriesPrivate::categoryTop(int category)
596 596 {
597 597 // Returns top (sum of all positive values) of category.
598 598 // Returns 0, if all values are negative
599 599 qreal top(0);
600 600 int count = m_barSets.count();
601 601 for (int set = 0; set < count; set++) {
602 602 if (category < m_barSets.at(set)->count()) {
603 603 qreal temp = m_barSets.at(set)->at(category);
604 604 if (temp > 0) {
605 605 top += temp;
606 606 }
607 607 }
608 608 }
609 609 return top;
610 610 }
611 611
612 612 qreal QAbstractBarSeriesPrivate::categoryBottom(int category)
613 613 {
614 614 // Returns bottom (sum of all negative values) of category
615 615 // Returns 0, if all values are positive
616 616 qreal bottom(0);
617 617 int count = m_barSets.count();
618 618 for (int set = 0; set < count; set++) {
619 619 if (category < m_barSets.at(set)->count()) {
620 620 qreal temp = m_barSets.at(set)->at(category);
621 621 if (temp < 0) {
622 622 bottom += temp;
623 623 }
624 624 }
625 625 }
626 626 return bottom;
627 627 }
628 628
629 629 qreal QAbstractBarSeriesPrivate::top()
630 630 {
631 631 // Returns top of all categories
632 632 qreal top(0);
633 633 int count = categoryCount();
634 634 for (int i = 0; i < count; i++) {
635 635 qreal temp = categoryTop(i);
636 636 if (temp > top)
637 637 top = temp;
638 638 }
639 639 return top;
640 640 }
641 641
642 642 qreal QAbstractBarSeriesPrivate::bottom()
643 643 {
644 644 // Returns bottom of all categories
645 645 qreal bottom(0);
646 646 int count = categoryCount();
647 647 for (int i = 0; i < count; i++) {
648 648 qreal temp = categoryBottom(i);
649 649 if (temp < bottom)
650 650 bottom = temp;
651 651 }
652 652 return bottom;
653 653 }
654 654
655 655
656 656 void QAbstractBarSeriesPrivate::initializeDomain()
657 657 {
658 658 qreal minX(domain()->minX());
659 659 qreal minY(domain()->minY());
660 660 qreal maxX(domain()->maxX());
661 661 qreal maxY(domain()->maxY());
662 662
663 663 qreal seriesMinX = this->minX();
664 664 qreal seriesMaxX = this->maxX();
665 665 qreal y = max();
666 666 minX = qMin(minX, seriesMinX - (qreal)0.5);
667 667 minY = qMin(minY, y);
668 668 maxX = qMax(maxX, seriesMaxX + (qreal)0.5);
669 669 maxY = qMax(maxY, y);
670 670
671 671 domain()->setRange(minX, maxX, minY, maxY);
672 672 }
673 673
674 674 QList<QLegendMarker*> QAbstractBarSeriesPrivate::createLegendMarkers(QLegend* legend)
675 675 {
676 676 Q_Q(QAbstractBarSeries);
677 677 QList<QLegendMarker*> markers;
678 678
679 679 foreach(QBarSet* set, q->barSets()) {
680 680 QBarLegendMarker* marker = new QBarLegendMarker(q,set,legend);
681 681 markers << marker;
682 682 }
683 683 return markers;
684 684 }
685 685
686 686
687 687 bool QAbstractBarSeriesPrivate::append(QBarSet *set)
688 688 {
689 689 if ((m_barSets.contains(set)) || (set == 0))
690 690 return false; // Fail if set is already in list or set is null.
691 691
692 692 m_barSets.append(set);
693 693 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
694 694 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
695 695 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
696 696
697 697 emit restructuredBars(); // this notifies barchartitem
698 698 return true;
699 699 }
700 700
701 701 bool QAbstractBarSeriesPrivate::remove(QBarSet *set)
702 702 {
703 703 if (!m_barSets.contains(set))
704 704 return false; // Fail if set is not in list
705 705
706 706 m_barSets.removeOne(set);
707 707 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
708 708 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
709 709 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
710 710
711 711 emit restructuredBars(); // this notifies barchartitem
712 712 return true;
713 713 }
714 714
715 715 bool QAbstractBarSeriesPrivate::append(QList<QBarSet * > sets)
716 716 {
717 717 foreach (QBarSet *set, sets) {
718 718 if ((set == 0) || (m_barSets.contains(set)))
719 719 return false; // Fail if any of the sets is null or is already appended.
720 720 if (sets.count(set) != 1)
721 721 return false; // Also fail if same set is more than once in given list.
722 722 }
723 723
724 724 foreach (QBarSet *set, sets) {
725 725 m_barSets.append(set);
726 726 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
727 727 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
728 728 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
729 729 }
730 730
731 731 emit restructuredBars(); // this notifies barchartitem
732 732 return true;
733 733 }
734 734
735 735 bool QAbstractBarSeriesPrivate::remove(QList<QBarSet * > sets)
736 736 {
737 737 if (sets.count() == 0)
738 738 return false;
739 739
740 740 foreach (QBarSet *set, sets) {
741 741 if ((set == 0) || (!m_barSets.contains(set)))
742 742 return false; // Fail if any of the sets is null or is not in series
743 743 if (sets.count(set) != 1)
744 744 return false; // Also fail if same set is more than once in given list.
745 745 }
746 746
747 747 foreach (QBarSet *set, sets) {
748 748 m_barSets.removeOne(set);
749 749 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
750 750 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
751 751 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
752 752 }
753 753
754 754 emit restructuredBars(); // this notifies barchartitem
755 755
756 756 return true;
757 757 }
758 758
759 759 bool QAbstractBarSeriesPrivate::insert(int index, QBarSet *set)
760 760 {
761 761 if ((m_barSets.contains(set)) || (set == 0))
762 762 return false; // Fail if set is already in list or set is null.
763 763
764 764 m_barSets.insert(index, set);
765 765 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
766 766 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
767 767 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
768 768
769 769 emit restructuredBars(); // this notifies barchartitem
770 770 return true;
771 771 }
772 772
773 773 void QAbstractBarSeriesPrivate::initializeAxes()
774 774 {
775 775 Q_Q(QAbstractBarSeries);
776 776
777 777 foreach(QAbstractAxis* axis, m_axes) {
778 778
779 779 if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
780 780 switch (q->type()) {
781 781 case QAbstractSeries::SeriesTypeHorizontalBar:
782 782 case QAbstractSeries::SeriesTypeHorizontalPercentBar:
783 783 case QAbstractSeries::SeriesTypeHorizontalStackedBar:
784 784 if (axis->orientation() == Qt::Vertical)
785 785 populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
786 786 break;
787 787 case QAbstractSeries::SeriesTypeBar:
788 788 case QAbstractSeries::SeriesTypePercentBar:
789 789 case QAbstractSeries::SeriesTypeStackedBar:
790 790 case QAbstractSeries::SeriesTypeBoxPlot:
791 791 if (axis->orientation() == Qt::Horizontal)
792 792 populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
793 793 break;
794 794 default:
795 795 qWarning() << "Unexpected series type";
796 796 break;
797 797 }
798 798 }
799 799 }
800 800 }
801 801
802 802 QAbstractAxis::AxisType QAbstractBarSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
803 803 {
804 804 Q_Q(const QAbstractBarSeries);
805 805
806 806 switch (q->type()) {
807 807 case QAbstractSeries::SeriesTypeHorizontalBar:
808 808 case QAbstractSeries::SeriesTypeHorizontalPercentBar:
809 809 case QAbstractSeries::SeriesTypeHorizontalStackedBar:
810 810 if (orientation == Qt::Vertical)
811 811 return QAbstractAxis::AxisTypeBarCategory;
812 812 break;
813 813 case QAbstractSeries::SeriesTypeBar:
814 814 case QAbstractSeries::SeriesTypePercentBar:
815 815 case QAbstractSeries::SeriesTypeStackedBar:
816 816 case QAbstractSeries::SeriesTypeBoxPlot:
817 817 if (orientation == Qt::Horizontal)
818 818 return QAbstractAxis::AxisTypeBarCategory;
819 819 break;
820 820 default:
821 821 qWarning() << "Unexpected series type";
822 822 break;
823 823 }
824 824 return QAbstractAxis::AxisTypeValue;
825 825
826 826 }
827 827
828 828 void QAbstractBarSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
829 829 {
830 830 QStringList categories;
831 831 if (axis->categories().isEmpty()) {
832 832 for (int i(1); i < categoryCount() + 1; i++)
833 833 categories << QString::number(i);
834 834 axis->append(categories);
835 835 }
836 836 }
837 837
838 838 QAbstractAxis* QAbstractBarSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
839 839 {
840 840 Q_UNUSED(orientation);
841 841 return 0;
842 842 }
843 843
844 844 void QAbstractBarSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
845 845 {
846 846 const QList<QGradient> gradients = theme->seriesGradients();
847 847
848 848 qreal takeAtPos = 0.5;
849 849 qreal step = 0.2;
850 850 if (m_barSets.count() > 1) {
851 851 step = 1.0 / (qreal) m_barSets.count();
852 852 if (m_barSets.count() % gradients.count())
853 853 step *= gradients.count();
854 854 else
855 855 step *= (gradients.count() - 1);
856 856 }
857 857
858 858 for (int i(0); i < m_barSets.count(); i++) {
859 859 int colorIndex = (index + i) % gradients.count();
860 860 if (i > 0 && i %gradients.count() == 0) {
861 861 // There is no dedicated base color for each sets, generate more colors
862 862 takeAtPos += step;
863 863 if (takeAtPos == 1.0)
864 864 takeAtPos += step;
865 865 takeAtPos -= (int) takeAtPos;
866 866 }
867 867 if (forced || QChartPrivate::defaultBrush() == m_barSets.at(i)->d_ptr->m_brush)
868 868 m_barSets.at(i)->setBrush(ChartThemeManager::colorAt(gradients.at(colorIndex), takeAtPos));
869 869
870 870 // Pick label color from the opposite end of the gradient.
871 871 // 0.3 as a boundary seems to work well.
872 872 if (forced || QChartPrivate::defaultBrush() == m_barSets.at(i)->d_ptr->m_labelBrush) {
873 873 if (takeAtPos < 0.3)
874 874 m_barSets.at(i)->setLabelBrush(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 1));
875 875 else
876 876 m_barSets.at(i)->setLabelBrush(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0));
877 877 }
878 878
879 879 if (forced || QChartPrivate::defaultPen() == m_barSets.at(i)->d_ptr->m_pen) {
880 880 QColor c = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
881 881 m_barSets.at(i)->setPen(c);
882 882 }
883 883 }
884 884 }
885 885
886 886 void QAbstractBarSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
887 887 {
888 888 AbstractBarChartItem *bar = static_cast<AbstractBarChartItem *>(m_item.data());
889 889 Q_ASSERT(bar);
890 if (options.testFlag(QChart::SeriesAnimations)) {
890 if (bar->animation())
891 bar->animation()->stopAndDestroyLater();
892
893 if (options.testFlag(QChart::SeriesAnimations))
891 894 bar->setAnimation(new BarAnimation(bar));
892 }else{
895 else
893 896 bar->setAnimation(0);
894 }
895 897 QAbstractSeriesPrivate::initializeAnimations(options);
896 898 }
897 899
898 900 #include "moc_qabstractbarseries.cpp"
899 901 #include "moc_qabstractbarseries_p.cpp"
900 902
901 903 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,680 +1,683
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qboxplotseries.h"
22 22 #include "qboxplotseries_p.h"
23 23 #include "qboxplotlegendmarker.h"
24 24 #include "qbarcategoryaxis.h"
25 25 #include "boxplotchartitem_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include "charttheme_p.h"
28 28 #include "qvalueaxis.h"
29 29 #include "charttheme_p.h"
30 30 #include "boxplotanimation_p.h"
31 31 #include "qchart_p.h"
32 32 #include "qboxset.h"
33 33 #include "qboxset_p.h"
34 34
35 35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 36
37 37 /*!
38 38 \class QBoxPlotSeries
39 39 \brief Series for creating box-and-whiskers chart
40 40 \mainclass
41 41
42 42 QBoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
43 43 a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
44 44 QBoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
45 45
46 46 See the \l {Box and Whiskers Example} {box-and-whiskers chart example} to learn how to create a box-and-whiskers chart.
47 47 \image examples_boxplotchart.png
48 48
49 49 \sa QBoxSet
50 50 */
51 51
52 52 /*!
53 53 \qmlclass BoxPlotSeries QBoxPlotSeries
54 54 \inherits QAbstractSeries
55 55
56 56 BoxPlotSeries represents a series of data shown as box-and-whisker bars. The purpose of this class is to act as
57 57 a container for single box-and-whisker items. Each item is drawn to own slot. If chart includes multiple instances of
58 58 BoxPlotSeries then box-and-whiskers items with the same index are drawn to same slot.
59 59
60 60 The following QML shows how to create a simple box-and-whiskers chart:
61 61 \code
62 62 import QtQuick 1.0
63 63 import QtCommercial.Chart 1.1
64 64
65 65 ChartView {
66 66 title: "Box Plot series"
67 67 width: 400
68 68 height: 300
69 69 theme: ChartView.ChartThemeBrownSand
70 70 legend.alignment: Qt.AlignBottom
71 71
72 72 BoxPlotSeries {
73 73 id: plotSeries
74 74 name: "Income"
75 75 BoxSet { label: "Jan"; values: [3, 4, 5.1, 6.2, 8.5] }
76 76 BoxSet { label: "Feb"; values: [5, 6, 7.5, 8.6, 11.8] }
77 77 BoxSet { label: "Mar"; values: [3.2, 5, 5.7, 8, 9.2] }
78 78 BoxSet { label: "Apr"; values: [3.8, 5, 6.4, 7, 8] }
79 79 BoxSet { label: "May"; values: [4, 5, 5.2, 6, 7] }
80 80 }
81 81 }
82 82 \endcode
83 83
84 84 \beginfloatleft
85 85 \image examples_qmlboxplot.png
86 86 \endfloat
87 87 \clearfloat
88 88 */
89 89
90 90 /*!
91 91 \fn QBoxPlotSeries::boxsetsAdded(QList<QBoxSet *> sets)
92 92 \brief Signal is emitted when a new \a sets of box-and-whiskers data is added to the series.
93 93 */
94 94
95 95 /*!
96 96 \fn QBoxPlotSeries::boxsetsRemoved(QList<QBoxSet *> sets)
97 97 \brief Signal is emitted when \a sets of box-and-whiskers data is removed from the series.
98 98 */
99 99
100 100 /*!
101 101 \fn QBoxPlotSeries::clicked(QBoxSet *boxset)
102 102 \brief Signal is emitted when the user clicks the \a boxset on the chart.
103 103 */
104 104
105 105 /*!
106 106 \fn QBoxPlotSeries::hovered(bool status, QBoxSet *boxset)
107 107 \brief Signal is emitted when there is change in hover \a status over \a boxset.
108 108 */
109 109
110 110 /*!
111 111 \fn QBoxPlotSeries::countChanged()
112 112 \brief Signal is emitted when there is change in count of box-and-whiskers items in the series.
113 113 */
114 114 /*!
115 115 \fn virtual SeriesType QBoxPlotSeries::type() const
116 116 \brief Returns type of series.
117 117 \sa QAbstractSeries, SeriesType
118 118 */
119 119 /*!
120 120 \qmlmethod BoxPlotSeries::append(const QString label, QVariantList values)
121 121 Appends a new box-and-whiskers set with \a label and \a values to the series.
122 122 */
123 123 /*!
124 124 \qmlmethod BoxPlotSeries::append(BoxSet *box)
125 125 Appends the \a box to the series.
126 126 */
127 127 /*!
128 128 \qmlmethod BoxPlotSeries::insert(int index, const QString label, QVariantList values)
129 129 Inserts a new box-and-whiskers set with \a label and \a values at the \a index position.
130 130 */
131 131 /*!
132 132 \qmlmethod BoxPlotSeries::remove(QBoxSet *boxset)
133 133 Removes the \a boxset from the series.
134 134 */
135 135 /*!
136 136 \qmlmethod BoxPlotSeries::clear()
137 137 Removes all boxsets from the series. Deletes removed sets.
138 138 */
139 139
140 140 /*!
141 141 \qmlsignal BoxPlotSeries::onClicked(BoxSet boxset);
142 142 Signal is emitted when the user clicks the \a boxset on the chart.
143 143 */
144 144 /*!
145 145 \qmlsignal BoxPlotSeries::onHovered(bool status, BoxSet boxset);
146 146 Signal is emitted when there is change in hover \a status over \a boxset.
147 147 */
148 148 /*!
149 149 \qmlsignal BoxPlotSeries::onCountChanged();
150 150 Signal is emitted when there is change in count of box-and-whiskers items in the series.
151 151 */
152 152 /*!
153 153 \qmlsignal BoxPlotSeries::onBoxsetsAdded()
154 154 Signal is emitted when new box-and-whiskers sets are added to the series.
155 155 */
156 156 /*!
157 157 \qmlsignal BoxPlotSeries::boxsetsRemoved()
158 158 Signal is emitted when new box-and-whiskers sets are removed from the series.
159 159 */
160 160
161 161 /*!
162 162 Constructs empty QBoxPlotSeries.
163 163 QBoxPlotSeries is QObject which is a child of a \a parent.
164 164 */
165 165 QBoxPlotSeries::QBoxPlotSeries(QObject *parent)
166 166 : QAbstractSeries(*new QBoxPlotSeriesPrivate(this), parent)
167 167 {
168 168 }
169 169
170 170 /*!
171 171 Destructor. Removes series from chart.
172 172 */
173 173 QBoxPlotSeries::~QBoxPlotSeries()
174 174 {
175 175 Q_D(QBoxPlotSeries);
176 176 if (d->m_chart)
177 177 d->m_chart->removeSeries(this);
178 178 }
179 179
180 180 /*!
181 181 Adds a single box and whiskers set to series. Takes ownership of the \a set. If the set is null or is already in series, it won't be appended.
182 182 Returns true, if appending succeeded.
183 183 */
184 184 bool QBoxPlotSeries::append(QBoxSet *set)
185 185 {
186 186 Q_D(QBoxPlotSeries);
187 187
188 188 bool success = d->append(set);
189 189 if (success) {
190 190 QList<QBoxSet *> sets;
191 191 sets.append(set);
192 192 set->setParent(this);
193 193 emit boxsetsAdded(sets);
194 194 emit countChanged();
195 195 }
196 196 return success;
197 197 }
198 198
199 199 /*!
200 200 Removes boxset from the series. Deletes the \a set and returns true if successful.
201 201 */
202 202 bool QBoxPlotSeries::remove(QBoxSet *set)
203 203 {
204 204 Q_D(QBoxPlotSeries);
205 205 bool success = d->remove(set);
206 206 if (success) {
207 207 QList<QBoxSet *> sets;
208 208 sets.append(set);
209 209 set->setParent(0);
210 210 emit boxsetsRemoved(sets);
211 211 emit countChanged();
212 212 delete set;
213 213 set = 0;
214 214 }
215 215 return success;
216 216 }
217 217
218 218 /*!
219 219 Takes a single \a set from the series. Does not delete the boxset object.
220 220
221 221 NOTE: The series remains as the boxset's parent object. You must set the
222 222 parent object to take full ownership.
223 223
224 224 Returns true if take was successful.
225 225 */
226 226 bool QBoxPlotSeries::take(QBoxSet *set)
227 227 {
228 228 Q_D(QBoxPlotSeries);
229 229
230 230 bool success = d->remove(set);
231 231 if (success) {
232 232 QList<QBoxSet *> sets;
233 233 sets.append(set);
234 234 emit boxsetsRemoved(sets);
235 235 emit countChanged();
236 236 }
237 237 return success;
238 238 }
239 239
240 240 /*!
241 241 Adds a list of boxsets to series. Takes ownership of the \a sets.
242 242 Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
243 243 nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
244 244 and function returns false.
245 245 */
246 246 bool QBoxPlotSeries::append(QList<QBoxSet *> sets)
247 247 {
248 248 Q_D(QBoxPlotSeries);
249 249 bool success = d->append(sets);
250 250 if (success) {
251 251 emit boxsetsAdded(sets);
252 252 emit countChanged();
253 253 }
254 254 return success;
255 255 }
256 256
257 257 /*!
258 258 Insert a box-and-whiskers set to the series at \a index postion. Takes ownership of the \a set. If the set is null or
259 259 is already in series, it won't be appended. Returns true, if inserting succeeded.
260 260
261 261 */
262 262 bool QBoxPlotSeries::insert(int index, QBoxSet *set)
263 263 {
264 264 Q_D(QBoxPlotSeries);
265 265 bool success = d->insert(index, set);
266 266 if (success) {
267 267 QList<QBoxSet *> sets;
268 268 sets.append(set);
269 269 emit boxsetsAdded(sets);
270 270 emit countChanged();
271 271 }
272 272 return success;
273 273 }
274 274
275 275 /*!
276 276 Removes all boxsets from the series. Deletes removed sets.
277 277 */
278 278 void QBoxPlotSeries::clear()
279 279 {
280 280 Q_D(QBoxPlotSeries);
281 281 QList<QBoxSet *> sets = boxSets();
282 282 bool success = d->remove(sets);
283 283 if (success) {
284 284 emit boxsetsRemoved(sets);
285 285 emit countChanged();
286 286 foreach (QBoxSet *set, sets)
287 287 delete set;
288 288 }
289 289 }
290 290
291 291 /*!
292 292 Returns number of sets in series.
293 293 */
294 294 int QBoxPlotSeries::count() const
295 295 {
296 296 Q_D(const QBoxPlotSeries);
297 297 return d->m_boxSets.count();
298 298 }
299 299
300 300 /*!
301 301 Returns a list of sets in series. Keeps ownership of sets.
302 302 */
303 303 QList<QBoxSet *> QBoxPlotSeries::boxSets() const
304 304 {
305 305 Q_D(const QBoxPlotSeries);
306 306 return d->m_boxSets;
307 307 }
308 308
309 309 /*
310 310 Returns QAbstractSeries::SeriesTypeBoxPlot.
311 311 */
312 312 QAbstractSeries::SeriesType QBoxPlotSeries::type() const
313 313 {
314 314 return QAbstractSeries::SeriesTypeBoxPlot;
315 315 }
316 316
317 317 /*!
318 318 Sets brush for the series. Box-and-whiskers items are drawn using \a brush
319 319 */
320 320 void QBoxPlotSeries::setBrush(const QBrush &brush)
321 321 {
322 322 Q_D(QBoxPlotSeries);
323 323
324 324 if (d->m_brush != brush) {
325 325 d->m_brush = brush;
326 326 emit d->updated();
327 327 }
328 328 }
329 329
330 330 /*!
331 331 Returns brush of the series.
332 332 */
333 333 QBrush QBoxPlotSeries::brush() const
334 334 {
335 335 Q_D(const QBoxPlotSeries);
336 336
337 337 return d->m_brush;
338 338 }
339 339
340 340 /*!
341 341 Sets pen for the series. Box-and-whiskers items are drawn using \a pen
342 342 */
343 343 void QBoxPlotSeries::setPen(const QPen &pen)
344 344 {
345 345 Q_D(QBoxPlotSeries);
346 346
347 347 if (d->m_pen != pen) {
348 348 d->m_pen = pen;
349 349 emit d->updated();
350 350 }
351 351 }
352 352
353 353 /*!
354 354 Returns the pen of this series.
355 355 */
356 356 QPen QBoxPlotSeries::pen() const
357 357 {
358 358 Q_D(const QBoxPlotSeries);
359 359
360 360 return d->m_pen;
361 361 }
362 362
363 363 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
364 364
365 365 QBoxPlotSeriesPrivate::QBoxPlotSeriesPrivate(QBoxPlotSeries *q)
366 366 : QAbstractSeriesPrivate(q),
367 367 m_pen(QChartPrivate::defaultPen()),
368 368 m_brush(QChartPrivate::defaultBrush())
369 369 {
370 370 }
371 371
372 372 QBoxPlotSeriesPrivate::~QBoxPlotSeriesPrivate()
373 373 {
374 374 disconnect(this, 0, 0, 0);
375 375 }
376 376
377 377 void QBoxPlotSeriesPrivate::initializeDomain()
378 378 {
379 379 qreal minX(domain()->minX());
380 380 qreal minY(domain()->minY());
381 381 qreal maxX(domain()->maxX());
382 382 qreal maxY(domain()->maxY());
383 383
384 384 qreal x = m_boxSets.count();
385 385 minX = qMin(minX, qreal(-0.5));
386 386 minY = qMin(minY, min());
387 387 maxX = qMax(maxX, x - qreal(0.5));
388 388 maxY = qMax(maxY, max());
389 389
390 390 domain()->setRange(minX, maxX, minY, maxY);
391 391 }
392 392
393 393 void QBoxPlotSeriesPrivate::initializeAxes()
394 394 {
395 395 foreach (QAbstractAxis* axis, m_axes) {
396 396 if (axis->type() == QAbstractAxis::AxisTypeBarCategory) {
397 397 if (axis->orientation() == Qt::Horizontal)
398 398 populateCategories(qobject_cast<QBarCategoryAxis *>(axis));
399 399 }
400 400 }
401 401 }
402 402
403 403 QAbstractAxis::AxisType QBoxPlotSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
404 404 {
405 405 if (orientation == Qt::Horizontal)
406 406 return QAbstractAxis::AxisTypeBarCategory;
407 407
408 408 return QAbstractAxis::AxisTypeValue;
409 409 }
410 410
411 411 QAbstractAxis* QBoxPlotSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
412 412 {
413 413 Q_UNUSED(orientation);
414 414
415 415 return 0;
416 416 }
417 417
418 418 void QBoxPlotSeriesPrivate::populateCategories(QBarCategoryAxis *axis)
419 419 {
420 420 QStringList categories;
421 421 if (axis->categories().isEmpty()) {
422 422 for (int i(1); i < m_boxSets.count() + 1; i++) {
423 423 QBoxSet *set = m_boxSets.at(i - 1);
424 424 if (set->label().isEmpty())
425 425 categories << QString::number(i);
426 426 else
427 427 categories << set->label();
428 428 }
429 429 axis->append(categories);
430 430 }
431 431 }
432 432
433 433 void QBoxPlotSeriesPrivate::initializeGraphics(QGraphicsItem *parent)
434 434 {
435 435 Q_Q(QBoxPlotSeries);
436 436
437 437 BoxPlotChartItem *boxPlot = new BoxPlotChartItem(q, parent);
438 438 m_item.reset(boxPlot);
439 439 QAbstractSeriesPrivate::initializeGraphics(parent);
440 440
441 441 if (m_chart) {
442 442 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), this, SLOT(handleSeriesChange(QAbstractSeries*)) );
443 443 connect(m_chart->d_ptr->m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), this, SLOT(handleSeriesRemove(QAbstractSeries*)) );
444 444
445 445 QList<QAbstractSeries *> serieses = m_chart->series();
446 446
447 447 // Tries to find this series from the Chart's list of series and deduce the index
448 448 int index = 0;
449 449 foreach (QAbstractSeries *s, serieses) {
450 450 if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
451 451 if (q == static_cast<QBoxPlotSeries *>(s)) {
452 452 boxPlot->m_seriesIndex = index;
453 453 m_index = index;
454 454 }
455 455 index++;
456 456 }
457 457 }
458 458 boxPlot->m_seriesCount = index;
459 459 }
460 460
461 461 // Make BoxPlotChartItem to instantiate box & whisker items
462 462 boxPlot->handleDataStructureChanged();
463 463 }
464 464
465 465 void QBoxPlotSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
466 466 {
467 467 Q_Q(QBoxPlotSeries);
468 468
469 469 const QList<QGradient> gradients = theme->seriesGradients();
470 470
471 471 if (forced || QChartPrivate::defaultBrush() == m_brush) {
472 472 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.5);
473 473 q->setBrush(brushColor);
474 474 }
475 475
476 476 if (forced || QChartPrivate::defaultPen() == m_pen) {
477 477 QPen pen = theme->outlinePen();
478 478 pen.setCosmetic(true);
479 479 q->setPen(pen);
480 480 }
481 481 }
482 482
483 483 void QBoxPlotSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
484 484 {
485 485 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
486 486 Q_ASSERT(item);
487 if (item->animation())
488 item->animation()->stopAndDestroyLater();
489
487 490 if (options.testFlag(QChart::SeriesAnimations))
488 491 item->setAnimation(new BoxPlotAnimation(item));
489 492 else
490 item->setAnimation((BoxPlotAnimation *)0);
493 item->setAnimation(0);
491 494 QAbstractSeriesPrivate::initializeAnimations(options);
492 495 }
493 496
494 497 QList<QLegendMarker*> QBoxPlotSeriesPrivate::createLegendMarkers(QLegend *legend)
495 498 {
496 499 Q_Q(QBoxPlotSeries);
497 500 QList<QLegendMarker *> list;
498 501 return list << new QBoxPlotLegendMarker(q, legend);
499 502 }
500 503
501 504 void QBoxPlotSeriesPrivate::handleSeriesRemove(QAbstractSeries *series)
502 505 {
503 506 Q_Q(QBoxPlotSeries);
504 507
505 508 QBoxPlotSeries *removedSeries = static_cast<QBoxPlotSeries *>(series);
506 509 QObject::disconnect(m_chart->d_ptr->m_dataset, 0, removedSeries->d_func(), 0);
507 510
508 511 // Test if series removed is me, then don't do anything
509 512 if (q != removedSeries) {
510 513 BoxPlotChartItem *item = static_cast<BoxPlotChartItem *>(m_item.data());
511 514 if (item) {
512 515 item->m_seriesCount = item->m_seriesCount - 1;
513 516 if (removedSeries->d_func()->m_index < m_index) {
514 517 m_index--;
515 518 item->m_seriesIndex = m_index;
516 519 }
517 520
518 521 item->handleDataStructureChanged();
519 522 }
520 523 }
521 524 }
522 525
523 526 void QBoxPlotSeriesPrivate::handleSeriesChange(QAbstractSeries *series)
524 527 {
525 528 Q_UNUSED(series);
526 529
527 530 Q_Q(QBoxPlotSeries);
528 531
529 532 BoxPlotChartItem *boxPlot = static_cast<BoxPlotChartItem *>(m_item.data());
530 533
531 534 if (m_chart) {
532 535 QList<QAbstractSeries *> serieses = m_chart->series();
533 536
534 537 // Tries to find this series from the Chart's list of series and deduce the index
535 538 int index = 0;
536 539 foreach (QAbstractSeries *s, serieses) {
537 540 if (s->type() == QAbstractSeries::SeriesTypeBoxPlot) {
538 541 if (q == static_cast<QBoxPlotSeries *>(s)) {
539 542 boxPlot->m_seriesIndex = index;
540 543 m_index = index;
541 544 }
542 545 index++;
543 546 }
544 547 }
545 548 boxPlot->m_seriesCount = index;
546 549 }
547 550
548 551 boxPlot->handleDataStructureChanged();
549 552 }
550 553
551 554 bool QBoxPlotSeriesPrivate::append(QBoxSet *set)
552 555 {
553 556 if ((m_boxSets.contains(set)) || (set == 0))
554 557 return false; // Fail if set is already in list or set is null.
555 558
556 559 m_boxSets.append(set);
557 560 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
558 561 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
559 562 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
560 563
561 564 emit restructuredBoxes(); // this notifies boxplotchartitem
562 565 return true;
563 566 }
564 567
565 568 bool QBoxPlotSeriesPrivate::remove(QBoxSet *set)
566 569 {
567 570 if (!m_boxSets.contains(set))
568 571 return false; // Fail if set is not in list
569 572
570 573 m_boxSets.removeOne(set);
571 574 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
572 575 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
573 576 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
574 577
575 578 emit restructuredBoxes(); // this notifies boxplotchartitem
576 579 return true;
577 580 }
578 581
579 582 bool QBoxPlotSeriesPrivate::append(QList<QBoxSet *> sets)
580 583 {
581 584 foreach (QBoxSet *set, sets) {
582 585 if ((set == 0) || (m_boxSets.contains(set)))
583 586 return false; // Fail if any of the sets is null or is already appended.
584 587 if (sets.count(set) != 1)
585 588 return false; // Also fail if same set is more than once in given list.
586 589 }
587 590
588 591 foreach (QBoxSet *set, sets) {
589 592 m_boxSets.append(set);
590 593 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
591 594 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
592 595 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
593 596 }
594 597
595 598 emit restructuredBoxes(); // this notifies boxplotchartitem
596 599 return true;
597 600 }
598 601
599 602 bool QBoxPlotSeriesPrivate::remove(QList<QBoxSet *> sets)
600 603 {
601 604 if (sets.count() == 0)
602 605 return false;
603 606
604 607 foreach (QBoxSet *set, sets) {
605 608 if ((set == 0) || (!m_boxSets.contains(set)))
606 609 return false; // Fail if any of the sets is null or is not in series
607 610 if (sets.count(set) != 1)
608 611 return false; // Also fail if same set is more than once in given list.
609 612 }
610 613
611 614 foreach (QBoxSet *set, sets) {
612 615 m_boxSets.removeOne(set);
613 616 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
614 617 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
615 618 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
616 619 }
617 620
618 621 emit restructuredBoxes(); // this notifies boxplotchartitem
619 622
620 623 return true;
621 624 }
622 625
623 626 bool QBoxPlotSeriesPrivate::insert(int index, QBoxSet *set)
624 627 {
625 628 if ((m_boxSets.contains(set)) || (set == 0))
626 629 return false; // Fail if set is already in list or set is null.
627 630
628 631 m_boxSets.insert(index, set);
629 632 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
630 633 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBox()), this, SIGNAL(updatedBoxes()));
631 634 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBox()), this, SIGNAL(restructuredBoxes()));
632 635
633 636 emit restructuredBoxes(); // this notifies boxplotchartitem
634 637 return true;
635 638 }
636 639
637 640 QBoxSet *QBoxPlotSeriesPrivate::boxSetAt(int index)
638 641 {
639 642 return m_boxSets.at(index);
640 643 }
641 644
642 645 qreal QBoxPlotSeriesPrivate::min()
643 646 {
644 647 if (m_boxSets.count() <= 0)
645 648 return 0;
646 649
647 650 qreal min = m_boxSets.at(0)->at(0);
648 651
649 652 foreach (QBoxSet *set, m_boxSets) {
650 653 for (int i = 0; i < 5; i++) {
651 654 if (set->at(i) < min)
652 655 min = set->at(i);
653 656 }
654 657 }
655 658
656 659 return min;
657 660 }
658 661
659 662 qreal QBoxPlotSeriesPrivate::max()
660 663 {
661 664 if (m_boxSets.count() <= 0)
662 665 return 0;
663 666
664 667 qreal max = m_boxSets.at(0)->at(0);
665 668
666 669 foreach (QBoxSet *set, m_boxSets) {
667 670 for (int i = 0; i < 5; i++) {
668 671 if (set->at(i) > max)
669 672 max = set->at(i);
670 673 }
671 674 }
672 675
673 676 return max;
674 677 }
675 678
676 679 #include "moc_qboxplotseries.cpp"
677 680 #include "moc_qboxplotseries_p.cpp"
678 681
679 682 QTCOMMERCIALCHART_END_NAMESPACE
680 683
@@ -1,486 +1,478
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20 #include "chartpresenter_p.h"
21 21 #include "qchart.h"
22 22 #include "chartitem_p.h"
23 23 #include "qchart_p.h"
24 24 #include "qabstractaxis.h"
25 25 #include "qabstractaxis_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include "chartanimation_p.h"
28 28 #include "qabstractseries_p.h"
29 29 #include "qareaseries.h"
30 30 #include "chartaxiselement_p.h"
31 31 #include "chartbackground_p.h"
32 32 #include "cartesianchartlayout_p.h"
33 33 #include "polarchartlayout_p.h"
34 34 #include "charttitle_p.h"
35 35 #include <QTimer>
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
40 40 : QObject(chart),
41 41 m_chart(chart),
42 42 m_options(QChart::NoAnimation),
43 43 m_state(ShowState),
44 44 m_background(0),
45 45 m_plotAreaBackground(0),
46 46 m_title(0)
47 47 {
48 48 if (type == QChart::ChartTypeCartesian)
49 49 m_layout = new CartesianChartLayout(this);
50 50 else if (type == QChart::ChartTypePolar)
51 51 m_layout = new PolarChartLayout(this);
52 52 Q_ASSERT(m_layout);
53 53 }
54 54
55 55 ChartPresenter::~ChartPresenter()
56 56 {
57 57
58 58 }
59 59
60 60 void ChartPresenter::setGeometry(const QRectF rect)
61 61 {
62 62 if (m_rect != rect) {
63 63 m_rect = rect;
64 64 foreach (ChartItem *chart, m_chartItems) {
65 65 chart->domain()->setSize(rect.size());
66 66 chart->setPos(rect.topLeft());
67 67 }
68 68 }
69 69 }
70 70
71 71 QRectF ChartPresenter::geometry() const
72 72 {
73 73 return m_rect;
74 74 }
75 75
76 76 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
77 77 {
78 78 axis->d_ptr->initializeGraphics(rootItem());
79 79 axis->d_ptr->initializeAnimations(m_options);
80 80 ChartAxisElement *item = axis->d_ptr->axisItem();
81 81 item->setPresenter(this);
82 82 item->setThemeManager(m_chart->d_ptr->m_themeManager);
83 83 m_axisItems<<item;
84 84 m_axes<<axis;
85 85 m_layout->invalidate();
86 86 }
87 87
88 88 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
89 89 {
90 90 ChartAxisElement *item = axis->d_ptr->m_item.take();
91 91 item->hide();
92 92 item->disconnect();
93 93 item->deleteLater();
94 94 m_axisItems.removeAll(item);
95 95 m_axes.removeAll(axis);
96 96 m_layout->invalidate();
97 97 }
98 98
99 99
100 100 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
101 101 {
102 102 series->d_ptr->initializeGraphics(rootItem());
103 103 series->d_ptr->initializeAnimations(m_options);
104 104 ChartItem *chart = series->d_ptr->chartItem();
105 105 chart->setPresenter(this);
106 106 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
107 107 chart->domain()->setSize(m_rect.size());
108 108 chart->setPos(m_rect.topLeft());
109 109 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
110 110 m_chartItems<<chart;
111 111 m_series<<series;
112 112 m_layout->invalidate();
113 113 }
114 114
115 115 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
116 116 {
117 117 ChartItem *chart = series->d_ptr->m_item.take();
118 118 chart->hide();
119 119 chart->disconnect();
120 120 chart->deleteLater();
121 121 m_chartItems.removeAll(chart);
122 122 m_series.removeAll(series);
123 123 m_layout->invalidate();
124 124 }
125 125
126 126 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
127 127 {
128 128 if (m_options != options) {
129 QChart::AnimationOptions oldOptions = m_options;
129 130 m_options = options;
130
131 foreach(QAbstractSeries* series, m_series){
132 series->d_ptr->initializeAnimations(m_options);
131 if (options.testFlag(QChart::SeriesAnimations) != oldOptions.testFlag(QChart::SeriesAnimations)) {
132 foreach (QAbstractSeries *series, m_series)
133 series->d_ptr->initializeAnimations(m_options);
133 134 }
134 foreach(QAbstractAxis* axis, m_axes){
135 axis->d_ptr->initializeAnimations(m_options);
135 if (options.testFlag(QChart::GridAxisAnimations) != oldOptions.testFlag(QChart::GridAxisAnimations)) {
136 foreach (QAbstractAxis *axis, m_axes)
137 axis->d_ptr->initializeAnimations(m_options);
136 138 }
139 m_layout->invalidate(); // So that existing animations don't just stop halfway
137 140 }
138 141 }
139 142
140 143 void ChartPresenter::setState(State state,QPointF point)
141 144 {
142 145 m_state=state;
143 146 m_statePoint=point;
144 147 }
145 148
146 149 QChart::AnimationOptions ChartPresenter::animationOptions() const
147 150 {
148 151 return m_options;
149 152 }
150 153
151 154 void ChartPresenter::createBackgroundItem()
152 155 {
153 156 if (!m_background) {
154 157 m_background = new ChartBackground(rootItem());
155 158 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
156 159 m_background->setBrush(QChartPrivate::defaultBrush());
157 160 m_background->setZValue(ChartPresenter::BackgroundZValue);
158 161 }
159 162 }
160 163
161 164 void ChartPresenter::createPlotAreaBackgroundItem()
162 165 {
163 166 if (!m_plotAreaBackground) {
164 167 if (m_chart->chartType() == QChart::ChartTypeCartesian)
165 168 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
166 169 else
167 170 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
168 171 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
169 172 // antialising artifacts with axis lines for some reason.
170 173 m_plotAreaBackground->setPen(QPen(Qt::transparent));
171 174 m_plotAreaBackground->setBrush(Qt::NoBrush);
172 175 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
173 176 m_plotAreaBackground->setVisible(false);
174 177 }
175 178 }
176 179
177 180 void ChartPresenter::createTitleItem()
178 181 {
179 182 if (!m_title) {
180 183 m_title = new ChartTitle(rootItem());
181 184 m_title->setZValue(ChartPresenter::BackgroundZValue);
182 185 }
183 186 }
184 187
185
186 void ChartPresenter::handleAnimationFinished()
187 {
188 m_animations.removeAll(qobject_cast<ChartAnimation *>(sender()));
189 if (m_animations.empty())
190 emit animationsFinished();
191 }
192
193 188 void ChartPresenter::startAnimation(ChartAnimation *animation)
194 189 {
195 if (animation->state() != QAbstractAnimation::Stopped) animation->stop();
196 QObject::connect(animation, SIGNAL(finished()), this, SLOT(handleAnimationFinished()), Qt::UniqueConnection);
197 if (!m_animations.isEmpty())
198 m_animations.append(animation);
199 QTimer::singleShot(0, animation, SLOT(start()));
190 animation->stop();
191 QTimer::singleShot(0, animation, SLOT(startChartAnimation()));
200 192 }
201 193
202 194 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
203 195 {
204 196 createBackgroundItem();
205 197 m_background->setBrush(brush);
206 198 m_layout->invalidate();
207 199 }
208 200
209 201 QBrush ChartPresenter::backgroundBrush() const
210 202 {
211 203 if (!m_background)
212 204 return QBrush();
213 205 return m_background->brush();
214 206 }
215 207
216 208 void ChartPresenter::setBackgroundPen(const QPen &pen)
217 209 {
218 210 createBackgroundItem();
219 211 m_background->setPen(pen);
220 212 m_layout->invalidate();
221 213 }
222 214
223 215 QPen ChartPresenter::backgroundPen() const
224 216 {
225 217 if (!m_background)
226 218 return QPen();
227 219 return m_background->pen();
228 220 }
229 221
230 222 void ChartPresenter::setBackgroundRoundness(qreal diameter)
231 223 {
232 224 createBackgroundItem();
233 225 m_background->setDiameter(diameter);
234 226 m_layout->invalidate();
235 227 }
236 228
237 229 qreal ChartPresenter::backgroundRoundness() const
238 230 {
239 231 if (!m_background)
240 232 return 0;
241 233 return m_background->diameter();
242 234 }
243 235
244 236 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
245 237 {
246 238 createPlotAreaBackgroundItem();
247 239 m_plotAreaBackground->setBrush(brush);
248 240 m_layout->invalidate();
249 241 }
250 242
251 243 QBrush ChartPresenter::plotAreaBackgroundBrush() const
252 244 {
253 245 if (!m_plotAreaBackground)
254 246 return QBrush();
255 247 return m_plotAreaBackground->brush();
256 248 }
257 249
258 250 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
259 251 {
260 252 createPlotAreaBackgroundItem();
261 253 m_plotAreaBackground->setPen(pen);
262 254 m_layout->invalidate();
263 255 }
264 256
265 257 QPen ChartPresenter::plotAreaBackgroundPen() const
266 258 {
267 259 if (!m_plotAreaBackground)
268 260 return QPen();
269 261 return m_plotAreaBackground->pen();
270 262 }
271 263
272 264 void ChartPresenter::setTitle(const QString &title)
273 265 {
274 266 createTitleItem();
275 267 m_title->setText(title);
276 268 m_layout->invalidate();
277 269 }
278 270
279 271 QString ChartPresenter::title() const
280 272 {
281 273 if (!m_title)
282 274 return QString();
283 275 return m_title->text();
284 276 }
285 277
286 278 void ChartPresenter::setTitleFont(const QFont &font)
287 279 {
288 280 createTitleItem();
289 281 m_title->setFont(font);
290 282 m_layout->invalidate();
291 283 }
292 284
293 285 QFont ChartPresenter::titleFont() const
294 286 {
295 287 if (!m_title)
296 288 return QFont();
297 289 return m_title->font();
298 290 }
299 291
300 292 void ChartPresenter::setTitleBrush(const QBrush &brush)
301 293 {
302 294 createTitleItem();
303 295 m_title->setDefaultTextColor(brush.color());
304 296 m_layout->invalidate();
305 297 }
306 298
307 299 QBrush ChartPresenter::titleBrush() const
308 300 {
309 301 if (!m_title)
310 302 return QBrush();
311 303 return QBrush(m_title->defaultTextColor());
312 304 }
313 305
314 306 void ChartPresenter::setBackgroundVisible(bool visible)
315 307 {
316 308 createBackgroundItem();
317 309 m_background->setVisible(visible);
318 310 }
319 311
320 312
321 313 bool ChartPresenter::isBackgroundVisible() const
322 314 {
323 315 if (!m_background)
324 316 return false;
325 317 return m_background->isVisible();
326 318 }
327 319
328 320 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
329 321 {
330 322 createPlotAreaBackgroundItem();
331 323 m_plotAreaBackground->setVisible(visible);
332 324 }
333 325
334 326 bool ChartPresenter::isPlotAreaBackgroundVisible() const
335 327 {
336 328 if (!m_plotAreaBackground)
337 329 return false;
338 330 return m_plotAreaBackground->isVisible();
339 331 }
340 332
341 333 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
342 334 {
343 335 createBackgroundItem();
344 336 m_background->setDropShadowEnabled(enabled);
345 337 }
346 338
347 339 bool ChartPresenter::isBackgroundDropShadowEnabled() const
348 340 {
349 341 if (!m_background)
350 342 return false;
351 343 return m_background->isDropShadowEnabled();
352 344 }
353 345
354 346
355 347 AbstractChartLayout *ChartPresenter::layout()
356 348 {
357 349 return m_layout;
358 350 }
359 351
360 352 QLegend *ChartPresenter::legend()
361 353 {
362 354 return m_chart->legend();
363 355 }
364 356
365 357 void ChartPresenter::setVisible(bool visible)
366 358 {
367 359 m_chart->setVisible(visible);
368 360 }
369 361
370 362 ChartBackground *ChartPresenter::backgroundElement()
371 363 {
372 364 return m_background;
373 365 }
374 366
375 367 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
376 368 {
377 369 return m_plotAreaBackground;
378 370 }
379 371
380 372 QList<ChartAxisElement *> ChartPresenter::axisItems() const
381 373 {
382 374 return m_axisItems;
383 375 }
384 376
385 377 QList<ChartItem *> ChartPresenter::chartItems() const
386 378 {
387 379 return m_chartItems;
388 380 }
389 381
390 382 ChartTitle *ChartPresenter::titleElement()
391 383 {
392 384 return m_title;
393 385 }
394 386
395 387 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
396 388 {
397 389 static QGraphicsTextItem dummyTextItem;
398 390
399 391 dummyTextItem.setFont(font);
400 392 dummyTextItem.setHtml(text);
401 393 QRectF boundingRect = dummyTextItem.boundingRect();
402 394
403 395 // Take rotation into account
404 396 if (angle) {
405 397 QTransform transform;
406 398 transform.rotate(angle);
407 399 boundingRect = transform.mapRect(boundingRect);
408 400 }
409 401
410 402 return boundingRect;
411 403 }
412 404
413 405 // boundingRect parameter returns the rotated bounding rect of the text
414 406 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
415 407 qreal maxSize, Qt::Orientation constraintOrientation,
416 408 QRectF &boundingRect)
417 409 {
418 410 QString truncatedString(text);
419 411 boundingRect = textBoundingRect(font, truncatedString, angle);
420 412 qreal checkDimension = ((constraintOrientation == Qt::Horizontal)
421 413 ? boundingRect.width() : boundingRect.height());
422 414 if (checkDimension > maxSize) {
423 415 // It can be assumed that almost any amount of string manipulation is faster
424 416 // than calculating one bounding rectangle, so first prepare a list of truncated strings
425 417 // to try.
426 418 static const char *truncateMatchString = "&#?[0-9a-zA-Z]*;$";
427 419 static QRegExp truncateMatcher(truncateMatchString);
428 420
429 421 QVector<QString> testStrings(text.length());
430 422 int count(0);
431 423 static QLatin1Char closeTag('>');
432 424 static QLatin1Char openTag('<');
433 425 static QLatin1Char semiColon(';');
434 426 static QLatin1String ellipsis("...");
435 427 while (truncatedString.length() > 1) {
436 428 int chopIndex(-1);
437 429 int chopCount(1);
438 430 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
439 431
440 432 if (lastChar == closeTag)
441 433 chopIndex = truncatedString.lastIndexOf(openTag);
442 434 else if (lastChar == semiColon)
443 435 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
444 436
445 437 if (chopIndex != -1)
446 438 chopCount = truncatedString.length() - chopIndex;
447 439 truncatedString.chop(chopCount);
448 440 testStrings[count] = truncatedString + ellipsis;
449 441 count++;
450 442 }
451 443
452 444 // Binary search for best fit
453 445 int minIndex(0);
454 446 int maxIndex(count - 1);
455 447 int bestIndex(count);
456 448 QRectF checkRect;
457 449 while (maxIndex >= minIndex) {
458 450 int mid = (maxIndex + minIndex) / 2;
459 451 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
460 452 checkDimension = ((constraintOrientation == Qt::Horizontal)
461 453 ? checkRect.width() : checkRect.height());
462 454 if (checkDimension > maxSize) {
463 455 // Checked index too large, all under this are also too large
464 456 minIndex = mid + 1;
465 457 } else {
466 458 // Checked index fits, all over this also fit
467 459 maxIndex = mid - 1;
468 460 bestIndex = mid;
469 461 boundingRect = checkRect;
470 462 }
471 463 }
472 464 // Default to "..." if nothing fits
473 465 if (bestIndex == count) {
474 466 boundingRect = textBoundingRect(font, ellipsis, angle);
475 467 truncatedString = ellipsis;
476 468 } else {
477 469 truncatedString = testStrings.at(bestIndex);
478 470 }
479 471 }
480 472
481 473 return truncatedString;
482 474 }
483 475
484 476 #include "moc_chartpresenter_p.cpp"
485 477
486 478 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,187 +1,180
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef CHARTPRESENTER_H
31 31 #define CHARTPRESENTER_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include "qchart.h" //because of QChart::ChartThemeId
35 35 #include <QRectF>
36 36 #include <QMargins>
37 37
38 38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 39
40 40 class ChartItem;
41 41 class AxisItem;
42 42 class QAbstractSeries;
43 43 class ChartDataSet;
44 44 class AbstractDomain;
45 45 class ChartAxisElement;
46 46 class ChartAnimator;
47 47 class ChartBackground;
48 48 class ChartTitle;
49 49 class ChartAnimation;
50 50 class AbstractChartLayout;
51 51
52 52 class ChartPresenter: public QObject
53 53 {
54 54 Q_OBJECT
55 55 public:
56 56 enum ZValues {
57 57 BackgroundZValue = -1,
58 58 PlotAreaZValue,
59 59 ShadesZValue,
60 60 GridZValue,
61 61 AxisZValue,
62 62 SeriesZValue,
63 63 LineChartZValue = SeriesZValue,
64 64 SplineChartZValue = SeriesZValue,
65 65 BarSeriesZValue = SeriesZValue,
66 66 ScatterSeriesZValue = SeriesZValue,
67 67 PieSeriesZValue = SeriesZValue,
68 68 BoxPlotSeriesZValue = SeriesZValue,
69 69 LegendZValue,
70 70 TopMostZValue
71 71 };
72 72
73 73 enum State {
74 74 ShowState,
75 75 ScrollUpState,
76 76 ScrollDownState,
77 77 ScrollLeftState,
78 78 ScrollRightState,
79 79 ZoomInState,
80 80 ZoomOutState
81 81 };
82 82
83 83 ChartPresenter(QChart *chart, QChart::ChartType type);
84 84 virtual ~ChartPresenter();
85 85
86 86
87 87 void setGeometry(QRectF rect);
88 88 QRectF geometry() const;
89 89
90 90 QGraphicsItem *rootItem(){ return m_chart; }
91 91 ChartBackground *backgroundElement();
92 92 QAbstractGraphicsShapeItem *plotAreaElement();
93 93 ChartTitle *titleElement();
94 94 QList<ChartAxisElement *> axisItems() const;
95 95 QList<ChartItem *> chartItems() const;
96 96
97 97 QLegend *legend();
98 98
99 99 void setBackgroundBrush(const QBrush &brush);
100 100 QBrush backgroundBrush() const;
101 101
102 102 void setBackgroundPen(const QPen &pen);
103 103 QPen backgroundPen() const;
104 104
105 105 void setBackgroundRoundness(qreal diameter);
106 106 qreal backgroundRoundness() const;
107 107
108 108 void setPlotAreaBackgroundBrush(const QBrush &brush);
109 109 QBrush plotAreaBackgroundBrush() const;
110 110
111 111 void setPlotAreaBackgroundPen(const QPen &pen);
112 112 QPen plotAreaBackgroundPen() const;
113 113
114 114 void setTitle(const QString &title);
115 115 QString title() const;
116 116
117 117 void setTitleFont(const QFont &font);
118 118 QFont titleFont() const;
119 119
120 120 void setTitleBrush(const QBrush &brush);
121 121 QBrush titleBrush() const;
122 122
123 123 void setBackgroundVisible(bool visible);
124 124 bool isBackgroundVisible() const;
125 125
126 126 void setPlotAreaBackgroundVisible(bool visible);
127 127 bool isPlotAreaBackgroundVisible() const;
128 128
129 129 void setBackgroundDropShadowEnabled(bool enabled);
130 130 bool isBackgroundDropShadowEnabled() const;
131 131
132 132 void setVisible(bool visible);
133 133
134 134 void setAnimationOptions(QChart::AnimationOptions options);
135 135 QChart::AnimationOptions animationOptions() const;
136 136
137 137 void startAnimation(ChartAnimation *animation);
138 138
139 139 //TODO refactor
140 140 void setState(State state,QPointF point);
141 141 State state() const { return m_state; }
142 142 QPointF statePoint() const { return m_statePoint; }
143 143 AbstractChartLayout *layout();
144 144
145 145 QChart::ChartType chartType() const { return m_chart->chartType(); }
146 146 QChart *chart() { return m_chart; }
147 147
148 148 static QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0);
149 149 static QString truncatedText(const QFont &font, const QString &text, qreal angle, qreal maxSize,
150 150 Qt::Orientation constraintOrientation, QRectF &boundingRect);
151 151 private:
152 152 void createBackgroundItem();
153 153 void createPlotAreaBackgroundItem();
154 154 void createTitleItem();
155 155
156 156 public Q_SLOTS:
157 157 void handleSeriesAdded(QAbstractSeries *series);
158 158 void handleSeriesRemoved(QAbstractSeries *series);
159 159 void handleAxisAdded(QAbstractAxis *axis);
160 160 void handleAxisRemoved(QAbstractAxis *axis);
161 161
162 private Q_SLOTS:
163 void handleAnimationFinished();
164
165 Q_SIGNALS:
166 void animationsFinished();
167
168 162 private:
169 163 QChart *m_chart;
170 164 QList<ChartItem *> m_chartItems;
171 165 QList<ChartAxisElement *> m_axisItems;
172 166 QList<QAbstractSeries *> m_series;
173 167 QList<QAbstractAxis *> m_axes;
174 168 QChart::AnimationOptions m_options;
175 169 State m_state;
176 170 QPointF m_statePoint;
177 QList<ChartAnimation *> m_animations;
178 171 AbstractChartLayout *m_layout;
179 172 ChartBackground *m_background;
180 173 QAbstractGraphicsShapeItem *m_plotAreaBackground;
181 174 ChartTitle *m_title;
182 175 QRectF m_rect;
183 176 };
184 177
185 178 QTCOMMERCIALCHART_END_NAMESPACE
186 179
187 180 #endif /* CHARTPRESENTER_H */
@@ -1,937 +1,939
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qpieseries.h"
22 22 #include "qpieseries_p.h"
23 23 #include "qpieslice.h"
24 24 #include "qpieslice_p.h"
25 25 #include "pieslicedata_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include "charttheme_p.h"
28 28 #include "qabstractaxis.h"
29 29 #include "pieanimation_p.h"
30 30 #include "charthelpers_p.h"
31 31
32 32 #include "qpielegendmarker.h"
33 33
34 34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 35
36 36 /*!
37 37 \class QPieSeries
38 38 \brief Pie series API for QtCommercial Charts.
39 39
40 40 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
41 41 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
42 42 The actual slice size is determined by that relative value.
43 43
44 44 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0.
45 45 These relate to the actual chart rectangle.
46 46
47 47 By default the pie is defined as a full pie but it can also be a partial pie.
48 48 This can be done by setting a starting angle and angle span to the series.
49 49 Full pie is 360 degrees where 0 is at 12 a'clock.
50 50
51 51 See the \l {PieChart Example} {pie chart example} or \l {DonutChart Example} {donut chart example} to learn how to use QPieSeries.
52 52 \table 100%
53 53 \row
54 54 \o \image examples_piechart.png
55 55 \o \image examples_donutchart.png
56 56 \endtable
57 57 */
58 58 /*!
59 59 \qmlclass PieSeries QPieSeries
60 60 \inherits AbstractSeries
61 61
62 62 The following QML shows how to create a simple pie chart.
63 63
64 64 \snippet ../demos/qmlchart/qml/qmlchart/View1.qml 1
65 65
66 66 \beginfloatleft
67 67 \image demos_qmlchart1.png
68 68 \endfloat
69 69 \clearfloat
70 70 */
71 71
72 72 /*!
73 73 \property QPieSeries::horizontalPosition
74 74 \brief Defines the horizontal position of the pie.
75 75
76 76 The value is a relative value to the chart rectangle where:
77 77
78 78 \list
79 79 \o 0.0 is the absolute left.
80 80 \o 1.0 is the absolute right.
81 81 \endlist
82 82 Default value is 0.5 (center).
83 83 \sa verticalPosition
84 84 */
85 85
86 86 /*!
87 87 \qmlproperty real PieSeries::horizontalPosition
88 88
89 89 Defines the horizontal position of the pie.
90 90
91 91 The value is a relative value to the chart rectangle where:
92 92
93 93 \list
94 94 \o 0.0 is the absolute left.
95 95 \o 1.0 is the absolute right.
96 96 \endlist
97 97 Default value is 0.5 (center).
98 98 \sa verticalPosition
99 99 */
100 100
101 101 /*!
102 102 \property QPieSeries::verticalPosition
103 103 \brief Defines the vertical position of the pie.
104 104
105 105 The value is a relative value to the chart rectangle where:
106 106
107 107 \list
108 108 \o 0.0 is the absolute top.
109 109 \o 1.0 is the absolute bottom.
110 110 \endlist
111 111 Default value is 0.5 (center).
112 112 \sa horizontalPosition
113 113 */
114 114
115 115 /*!
116 116 \qmlproperty real PieSeries::verticalPosition
117 117
118 118 Defines the vertical position of the pie.
119 119
120 120 The value is a relative value to the chart rectangle where:
121 121
122 122 \list
123 123 \o 0.0 is the absolute top.
124 124 \o 1.0 is the absolute bottom.
125 125 \endlist
126 126 Default value is 0.5 (center).
127 127 \sa horizontalPosition
128 128 */
129 129
130 130 /*!
131 131 \property QPieSeries::size
132 132 \brief Defines the pie size.
133 133
134 134 The value is a relative value to the chart rectangle where:
135 135
136 136 \list
137 137 \o 0.0 is the minimum size (pie not drawn).
138 138 \o 1.0 is the maximum size that can fit the chart.
139 139 \endlist
140 140
141 141 When setting this property the holeSize property is adjusted if necessary, to ensure that the hole size is not greater than the outer size.
142 142
143 143 Default value is 0.7.
144 144 */
145 145
146 146 /*!
147 147 \qmlproperty real PieSeries::size
148 148
149 149 Defines the pie size.
150 150
151 151 The value is a relative value to the chart rectangle where:
152 152
153 153 \list
154 154 \o 0.0 is the minimum size (pie not drawn).
155 155 \o 1.0 is the maximum size that can fit the chart.
156 156 \endlist
157 157
158 158 Default value is 0.7.
159 159 */
160 160
161 161 /*!
162 162 \property QPieSeries::holeSize
163 163 \brief Defines the donut hole size.
164 164
165 165 The value is a relative value to the chart rectangle where:
166 166
167 167 \list
168 168 \o 0.0 is the minimum size (full pie drawn, without any hole inside).
169 169 \o 1.0 is the maximum size that can fit the chart. (donut has no width)
170 170 \endlist
171 171
172 172 The value is never greater then size property.
173 173 Default value is 0.0.
174 174 */
175 175
176 176 /*!
177 177 \qmlproperty real PieSeries::holeSize
178 178
179 179 Defines the donut hole size.
180 180
181 181 The value is a relative value to the chart rectangle where:
182 182
183 183 \list
184 184 \o 0.0 is the minimum size (full pie drawn, without any hole inside).
185 185 \o 1.0 is the maximum size that can fit the chart. (donut has no width)
186 186 \endlist
187 187
188 188 When setting this property the size property is adjusted if necessary, to ensure that the inner size is not greater than the outer size.
189 189
190 190 Default value is 0.0.
191 191 */
192 192
193 193 /*!
194 194 \property QPieSeries::startAngle
195 195 \brief Defines the starting angle of the pie.
196 196
197 197 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
198 198
199 199 Default is value is 0.
200 200 */
201 201
202 202 /*!
203 203 \qmlproperty real PieSeries::startAngle
204 204
205 205 Defines the starting angle of the pie.
206 206
207 207 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
208 208
209 209 Default is value is 0.
210 210 */
211 211
212 212 /*!
213 213 \property QPieSeries::endAngle
214 214 \brief Defines the ending angle of the pie.
215 215
216 216 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
217 217
218 218 Default is value is 360.
219 219 */
220 220
221 221 /*!
222 222 \qmlproperty real PieSeries::endAngle
223 223
224 224 Defines the ending angle of the pie.
225 225
226 226 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
227 227
228 228 Default is value is 360.
229 229 */
230 230
231 231 /*!
232 232 \property QPieSeries::count
233 233
234 234 Number of slices in the series.
235 235 */
236 236
237 237 /*!
238 238 \qmlproperty int PieSeries::count
239 239
240 240 Number of slices in the series.
241 241 */
242 242
243 243 /*!
244 244 \fn void QPieSeries::countChanged()
245 245 Emitted when the slice count has changed.
246 246 \sa count
247 247 */
248 248 /*!
249 249 \qmlsignal PieSeries::onCountChanged()
250 250 Emitted when the slice count has changed.
251 251 */
252 252
253 253 /*!
254 254 \property QPieSeries::sum
255 255
256 256 Sum of all slices.
257 257
258 258 The series keeps track of the sum of all slices it holds.
259 259 */
260 260
261 261 /*!
262 262 \qmlproperty real PieSeries::sum
263 263
264 264 Sum of all slices.
265 265
266 266 The series keeps track of the sum of all slices it holds.
267 267 */
268 268
269 269 /*!
270 270 \fn void QPieSeries::sumChanged()
271 271 Emitted when the sum of all slices has changed.
272 272 \sa sum
273 273 */
274 274 /*!
275 275 \qmlsignal PieSeries::onSumChanged()
276 276 Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you
277 277 change value of a slice.
278 278 */
279 279
280 280 /*!
281 281 \fn void QPieSeries::added(QList<QPieSlice*> slices)
282 282
283 283 This signal is emitted when \a slices have been added to the series.
284 284
285 285 \sa append(), insert()
286 286 */
287 287 /*!
288 288 \qmlsignal PieSeries::onAdded(PieSlice slice)
289 289 Emitted when \a slice has been added to the series.
290 290 */
291 291
292 292 /*!
293 293 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
294 294 This signal is emitted when \a slices have been removed from the series.
295 295 \sa remove()
296 296 */
297 297 /*!
298 298 \qmlsignal PieSeries::onRemoved(PieSlice slice)
299 299 Emitted when \a slice has been removed from the series.
300 300 */
301 301
302 302 /*!
303 303 \fn void QPieSeries::clicked(QPieSlice* slice)
304 304 This signal is emitted when a \a slice has been clicked.
305 305 \sa QPieSlice::clicked()
306 306 */
307 307 /*!
308 308 \qmlsignal PieSeries::onClicked(PieSlice slice)
309 309 This signal is emitted when a \a slice has been clicked.
310 310 */
311 311
312 312 /*!
313 313 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
314 314 This signal is emitted when user has hovered over or away from the \a slice.
315 315 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
316 316 \sa QPieSlice::hovered()
317 317 */
318 318 /*!
319 319 \qmlsignal PieSeries::onHovered(PieSlice slice, bool state)
320 320 This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered
321 321 over the slice and false when hover has moved away from the slice.
322 322 */
323 323
324 324 /*!
325 325 \qmlmethod PieSlice PieSeries::at(int index)
326 326 Returns slice at \a index. Returns null if the index is not valid.
327 327 */
328 328
329 329 /*!
330 330 \qmlmethod PieSlice PieSeries::find(string label)
331 331 Returns the first slice with \a label. Returns null if the index is not valid.
332 332 */
333 333
334 334 /*!
335 335 \qmlmethod PieSlice PieSeries::append(string label, real value)
336 336 Adds a new slice with \a label and \a value to the pie.
337 337 */
338 338
339 339 /*!
340 340 \qmlmethod bool PieSeries::remove(PieSlice slice)
341 341 Removes the \a slice from the pie. Returns true if the removal was successful, false otherwise.
342 342 */
343 343
344 344 /*!
345 345 \qmlmethod PieSeries::clear()
346 346 Removes all slices from the pie.
347 347 */
348 348
349 349 /*!
350 350 Constructs a series object which is a child of \a parent.
351 351 */
352 352 QPieSeries::QPieSeries(QObject *parent)
353 353 : QAbstractSeries(*new QPieSeriesPrivate(this), parent)
354 354 {
355 355 Q_D(QPieSeries);
356 356 QObject::connect(this, SIGNAL(countChanged()), d, SIGNAL(countChanged()));
357 357 }
358 358
359 359 /*!
360 360 Destroys the series and its slices.
361 361 */
362 362 QPieSeries::~QPieSeries()
363 363 {
364 364 // NOTE: d_prt destroyed by QObject
365 365 clear();
366 366 }
367 367
368 368 /*!
369 369 Returns QAbstractSeries::SeriesTypePie.
370 370 */
371 371 QAbstractSeries::SeriesType QPieSeries::type() const
372 372 {
373 373 return QAbstractSeries::SeriesTypePie;
374 374 }
375 375
376 376 /*!
377 377 Appends a single \a slice to the series.
378 378 Slice ownership is passed to the series.
379 379
380 380 Returns true if append was succesfull.
381 381 */
382 382 bool QPieSeries::append(QPieSlice *slice)
383 383 {
384 384 return append(QList<QPieSlice *>() << slice);
385 385 }
386 386
387 387 /*!
388 388 Appends an array of \a slices to the series.
389 389 Slice ownership is passed to the series.
390 390
391 391 Returns true if append was successful.
392 392 */
393 393 bool QPieSeries::append(QList<QPieSlice *> slices)
394 394 {
395 395 Q_D(QPieSeries);
396 396
397 397 if (slices.count() == 0)
398 398 return false;
399 399
400 400 foreach (QPieSlice *s, slices) {
401 401 if (!s || d->m_slices.contains(s))
402 402 return false;
403 403 if (s->series()) // already added to some series
404 404 return false;
405 405 if (!isValidValue(s->value()))
406 406 return false;
407 407 }
408 408
409 409 foreach (QPieSlice *s, slices) {
410 410 s->setParent(this);
411 411 QPieSlicePrivate::fromSlice(s)->m_series = this;
412 412 d->m_slices << s;
413 413 }
414 414
415 415 d->updateDerivativeData();
416 416
417 417 foreach(QPieSlice * s, slices) {
418 418 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
419 419 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
420 420 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
421 421 }
422 422
423 423 emit added(slices);
424 424 emit countChanged();
425 425
426 426 return true;
427 427 }
428 428
429 429 /*!
430 430 Appends a single \a slice to the series and returns a reference to the series.
431 431 Slice ownership is passed to the series.
432 432 */
433 433 QPieSeries &QPieSeries::operator << (QPieSlice *slice)
434 434 {
435 435 append(slice);
436 436 return *this;
437 437 }
438 438
439 439
440 440 /*!
441 441 Appends a single slice to the series with give \a value and \a label.
442 442 Slice ownership is passed to the series.
443 443 Returns NULL if value is NaN, Inf or -Inf and no slice is added to the series.
444 444 */
445 445 QPieSlice *QPieSeries::append(QString label, qreal value)
446 446 {
447 447 if (isValidValue(value)) {
448 448 QPieSlice *slice = new QPieSlice(label, value);
449 449 append(slice);
450 450 return slice;
451 451 } else {
452 452 return 0;
453 453 }
454 454 }
455 455
456 456 /*!
457 457 Inserts a single \a slice to the series before the slice at \a index position.
458 458 Slice ownership is passed to the series.
459 459
460 460 Returns true if insert was successful.
461 461 */
462 462 bool QPieSeries::insert(int index, QPieSlice *slice)
463 463 {
464 464 Q_D(QPieSeries);
465 465
466 466 if (index < 0 || index > d->m_slices.count())
467 467 return false;
468 468
469 469 if (!slice || d->m_slices.contains(slice))
470 470 return false;
471 471
472 472 if (slice->series()) // already added to some series
473 473 return false;
474 474
475 475 if (!isValidValue(slice->value()))
476 476 return false;
477 477
478 478 slice->setParent(this);
479 479 QPieSlicePrivate::fromSlice(slice)->m_series = this;
480 480 d->m_slices.insert(index, slice);
481 481
482 482 d->updateDerivativeData();
483 483
484 484 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
485 485 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
486 486 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
487 487
488 488 emit added(QList<QPieSlice *>() << slice);
489 489 emit countChanged();
490 490
491 491 return true;
492 492 }
493 493
494 494 /*!
495 495 Removes a single \a slice from the series and deletes the slice.
496 496
497 497 Do not reference the pointer after this call.
498 498
499 499 Returns true if remove was successful.
500 500 */
501 501 bool QPieSeries::remove(QPieSlice *slice)
502 502 {
503 503 Q_D(QPieSeries);
504 504
505 505 if (!d->m_slices.removeOne(slice))
506 506 return false;
507 507
508 508 d->updateDerivativeData();
509 509
510 510 emit removed(QList<QPieSlice *>() << slice);
511 511 emit countChanged();
512 512
513 513 delete slice;
514 514 slice = 0;
515 515
516 516 return true;
517 517 }
518 518
519 519 /*!
520 520 Takes a single \a slice from the series. Does not destroy the slice object.
521 521
522 522 \note The series remains as the slice's parent object. You must set the
523 523 parent object to take full ownership.
524 524
525 525 Returns true if take was successful.
526 526 */
527 527 bool QPieSeries::take(QPieSlice *slice)
528 528 {
529 529 Q_D(QPieSeries);
530 530
531 531 if (!d->m_slices.removeOne(slice))
532 532 return false;
533 533
534 534 QPieSlicePrivate::fromSlice(slice)->m_series = 0;
535 535 slice->disconnect(d);
536 536
537 537 d->updateDerivativeData();
538 538
539 539 emit removed(QList<QPieSlice *>() << slice);
540 540 emit countChanged();
541 541
542 542 return true;
543 543 }
544 544
545 545 /*!
546 546 Clears all slices from the series.
547 547 */
548 548 void QPieSeries::clear()
549 549 {
550 550 Q_D(QPieSeries);
551 551 if (d->m_slices.count() == 0)
552 552 return;
553 553
554 554 QList<QPieSlice *> slices = d->m_slices;
555 555 foreach (QPieSlice *s, d->m_slices)
556 556 d->m_slices.removeOne(s);
557 557
558 558 d->updateDerivativeData();
559 559
560 560 emit removed(slices);
561 561 emit countChanged();
562 562
563 563 foreach (QPieSlice *s, slices)
564 564 delete s;
565 565 }
566 566
567 567 /*!
568 568 Returns a list of slices that belong to this series.
569 569 */
570 570 QList<QPieSlice *> QPieSeries::slices() const
571 571 {
572 572 Q_D(const QPieSeries);
573 573 return d->m_slices;
574 574 }
575 575
576 576 /*!
577 577 returns the number of the slices in this series.
578 578 */
579 579 int QPieSeries::count() const
580 580 {
581 581 Q_D(const QPieSeries);
582 582 return d->m_slices.count();
583 583 }
584 584
585 585 /*!
586 586 Returns true is the series is empty.
587 587 */
588 588 bool QPieSeries::isEmpty() const
589 589 {
590 590 Q_D(const QPieSeries);
591 591 return d->m_slices.isEmpty();
592 592 }
593 593
594 594 /*!
595 595 Returns the sum of all slice values in this series.
596 596
597 597 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
598 598 */
599 599 qreal QPieSeries::sum() const
600 600 {
601 601 Q_D(const QPieSeries);
602 602 return d->m_sum;
603 603 }
604 604
605 605 void QPieSeries::setHoleSize(qreal holeSize)
606 606 {
607 607 Q_D(QPieSeries);
608 608 holeSize = qBound((qreal)0.0, holeSize, (qreal)1.0);
609 609 d->setSizes(holeSize, qMax(d->m_pieRelativeSize, holeSize));
610 610 }
611 611
612 612 qreal QPieSeries::holeSize() const
613 613 {
614 614 Q_D(const QPieSeries);
615 615 return d->m_holeRelativeSize;
616 616 }
617 617
618 618 void QPieSeries::setHorizontalPosition(qreal relativePosition)
619 619 {
620 620 Q_D(QPieSeries);
621 621
622 622 if (relativePosition < 0.0)
623 623 relativePosition = 0.0;
624 624 if (relativePosition > 1.0)
625 625 relativePosition = 1.0;
626 626
627 627 if (!qFuzzyCompare(d->m_pieRelativeHorPos, relativePosition)) {
628 628 d->m_pieRelativeHorPos = relativePosition;
629 629 emit d->horizontalPositionChanged();
630 630 }
631 631 }
632 632
633 633 qreal QPieSeries::horizontalPosition() const
634 634 {
635 635 Q_D(const QPieSeries);
636 636 return d->m_pieRelativeHorPos;
637 637 }
638 638
639 639 void QPieSeries::setVerticalPosition(qreal relativePosition)
640 640 {
641 641 Q_D(QPieSeries);
642 642
643 643 if (relativePosition < 0.0)
644 644 relativePosition = 0.0;
645 645 if (relativePosition > 1.0)
646 646 relativePosition = 1.0;
647 647
648 648 if (!qFuzzyCompare(d->m_pieRelativeVerPos, relativePosition)) {
649 649 d->m_pieRelativeVerPos = relativePosition;
650 650 emit d->verticalPositionChanged();
651 651 }
652 652 }
653 653
654 654 qreal QPieSeries::verticalPosition() const
655 655 {
656 656 Q_D(const QPieSeries);
657 657 return d->m_pieRelativeVerPos;
658 658 }
659 659
660 660 void QPieSeries::setPieSize(qreal relativeSize)
661 661 {
662 662 Q_D(QPieSeries);
663 663 relativeSize = qBound((qreal)0.0, relativeSize, (qreal)1.0);
664 664 d->setSizes(qMin(d->m_holeRelativeSize, relativeSize), relativeSize);
665 665
666 666 }
667 667
668 668 qreal QPieSeries::pieSize() const
669 669 {
670 670 Q_D(const QPieSeries);
671 671 return d->m_pieRelativeSize;
672 672 }
673 673
674 674
675 675 void QPieSeries::setPieStartAngle(qreal angle)
676 676 {
677 677 Q_D(QPieSeries);
678 678 if (qFuzzyCompare(d->m_pieStartAngle, angle))
679 679 return;
680 680 d->m_pieStartAngle = angle;
681 681 d->updateDerivativeData();
682 682 emit d->pieStartAngleChanged();
683 683 }
684 684
685 685 qreal QPieSeries::pieStartAngle() const
686 686 {
687 687 Q_D(const QPieSeries);
688 688 return d->m_pieStartAngle;
689 689 }
690 690
691 691 /*!
692 692 Sets the end angle of the pie.
693 693
694 694 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
695 695
696 696 \a angle must be greater than start angle.
697 697
698 698 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
699 699 */
700 700 void QPieSeries::setPieEndAngle(qreal angle)
701 701 {
702 702 Q_D(QPieSeries);
703 703 if (qFuzzyCompare(d->m_pieEndAngle, angle))
704 704 return;
705 705 d->m_pieEndAngle = angle;
706 706 d->updateDerivativeData();
707 707 emit d->pieEndAngleChanged();
708 708 }
709 709
710 710 /*!
711 711 Returns the end angle of the pie.
712 712
713 713 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
714 714
715 715 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
716 716 */
717 717 qreal QPieSeries::pieEndAngle() const
718 718 {
719 719 Q_D(const QPieSeries);
720 720 return d->m_pieEndAngle;
721 721 }
722 722
723 723 /*!
724 724 Sets the all the slice labels \a visible or invisible.
725 725
726 726 Note that this affects only the current slices in the series.
727 727 If user adds a new slice the default label visibility is false.
728 728
729 729 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
730 730 */
731 731 void QPieSeries::setLabelsVisible(bool visible)
732 732 {
733 733 Q_D(QPieSeries);
734 734 foreach (QPieSlice *s, d->m_slices)
735 735 s->setLabelVisible(visible);
736 736 }
737 737
738 738 /*!
739 739 Sets the all the slice labels \a position
740 740
741 741 Note that this affects only the current slices in the series.
742 742 If user adds a new slice the default label position is LabelOutside
743 743
744 744 \sa QPieSlice::labelPosition(), QPieSlice::setLabelPosition()
745 745 */
746 746 void QPieSeries::setLabelsPosition(QPieSlice::LabelPosition position)
747 747 {
748 748 Q_D(QPieSeries);
749 749 foreach (QPieSlice *s, d->m_slices)
750 750 s->setLabelPosition(position);
751 751 }
752 752
753 753 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
754 754
755 755
756 756 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
757 757 QAbstractSeriesPrivate(parent),
758 758 m_pieRelativeHorPos(0.5),
759 759 m_pieRelativeVerPos(0.5),
760 760 m_pieRelativeSize(0.7),
761 761 m_pieStartAngle(0),
762 762 m_pieEndAngle(360),
763 763 m_sum(0),
764 764 m_holeRelativeSize(0.0)
765 765 {
766 766 }
767 767
768 768 QPieSeriesPrivate::~QPieSeriesPrivate()
769 769 {
770 770 }
771 771
772 772 void QPieSeriesPrivate::updateDerivativeData()
773 773 {
774 774 // calculate sum of all slices
775 775 qreal sum = 0;
776 776 foreach (QPieSlice *s, m_slices)
777 777 sum += s->value();
778 778
779 779 if (!qFuzzyCompare(m_sum, sum)) {
780 780 m_sum = sum;
781 781 emit q_func()->sumChanged();
782 782 }
783 783
784 784 // nothing to show..
785 785 if (qFuzzyCompare(m_sum, 0))
786 786 return;
787 787
788 788 // update slice attributes
789 789 qreal sliceAngle = m_pieStartAngle;
790 790 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
791 791 QVector<QPieSlice *> changed;
792 792 foreach (QPieSlice *s, m_slices) {
793 793 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
794 794 d->setPercentage(s->value() / m_sum);
795 795 d->setStartAngle(sliceAngle);
796 796 d->setAngleSpan(pieSpan * s->percentage());
797 797 sliceAngle += s->angleSpan();
798 798 }
799 799
800 800
801 801 emit calculatedDataChanged();
802 802 }
803 803
804 804 void QPieSeriesPrivate::setSizes(qreal innerSize, qreal outerSize)
805 805 {
806 806 bool changed = false;
807 807
808 808 if (!qFuzzyCompare(m_holeRelativeSize, innerSize)) {
809 809 m_holeRelativeSize = innerSize;
810 810 changed = true;
811 811 }
812 812
813 813 if (!qFuzzyCompare(m_pieRelativeSize, outerSize)) {
814 814 m_pieRelativeSize = outerSize;
815 815 changed = true;
816 816 }
817 817
818 818 if (changed)
819 819 emit pieSizeChanged();
820 820 }
821 821
822 822 QPieSeriesPrivate *QPieSeriesPrivate::fromSeries(QPieSeries *series)
823 823 {
824 824 return series->d_func();
825 825 }
826 826
827 827 void QPieSeriesPrivate::sliceValueChanged()
828 828 {
829 829 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
830 830 updateDerivativeData();
831 831 }
832 832
833 833 void QPieSeriesPrivate::sliceClicked()
834 834 {
835 835 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
836 836 Q_ASSERT(m_slices.contains(slice));
837 837 Q_Q(QPieSeries);
838 838 emit q->clicked(slice);
839 839 }
840 840
841 841 void QPieSeriesPrivate::sliceHovered(bool state)
842 842 {
843 843 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
844 844 Q_ASSERT(m_slices.contains(slice));
845 845 Q_Q(QPieSeries);
846 846 emit q->hovered(slice, state);
847 847 }
848 848
849 849 void QPieSeriesPrivate::initializeDomain()
850 850 {
851 851 // does not apply to pie
852 852 }
853 853
854 854 void QPieSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
855 855 {
856 856 Q_Q(QPieSeries);
857 857 PieChartItem *pie = new PieChartItem(q,parent);
858 858 m_item.reset(pie);
859 859 QAbstractSeriesPrivate::initializeGraphics(parent);
860 860 }
861 861
862 862 void QPieSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
863 863 {
864 864 PieChartItem *item = static_cast<PieChartItem *>(m_item.data());
865 865 Q_ASSERT(item);
866 if (options.testFlag(QChart::SeriesAnimations)) {
866 if (item->animation())
867 item->animation()->stopAndDestroyLater();
868
869 if (options.testFlag(QChart::SeriesAnimations))
867 870 item->setAnimation(new PieAnimation(item));
868 }else{
871 else
869 872 item->setAnimation(0);
870 }
871 873 QAbstractSeriesPrivate::initializeAnimations(options);
872 874 }
873 875
874 876 QList<QLegendMarker*> QPieSeriesPrivate::createLegendMarkers(QLegend* legend)
875 877 {
876 878 Q_Q(QPieSeries);
877 879 QList<QLegendMarker*> markers;
878 880 foreach(QPieSlice* slice, q->slices()) {
879 881 QPieLegendMarker* marker = new QPieLegendMarker(q,slice,legend);
880 882 markers << marker;
881 883 }
882 884 return markers;
883 885 }
884 886
885 887 void QPieSeriesPrivate::initializeAxes()
886 888 {
887 889
888 890 }
889 891
890 892 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
891 893 {
892 894 Q_UNUSED(orientation);
893 895 return QAbstractAxis::AxisTypeNoAxis;
894 896 }
895 897
896 898 QAbstractAxis* QPieSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
897 899 {
898 900 Q_UNUSED(orientation);
899 901 return 0;
900 902 }
901 903
902 904 void QPieSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
903 905 {
904 906 //Q_Q(QPieSeries);
905 907 //const QList<QColor>& colors = theme->seriesColors();
906 908 const QList<QGradient>& gradients = theme->seriesGradients();
907 909
908 910 for (int i(0); i < m_slices.count(); i++) {
909 911
910 912 QColor penColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
911 913
912 914 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
913 915 qreal pos = (qreal)(i + 1) / (qreal) m_slices.count();
914 916 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), pos);
915 917
916 918 QPieSlice *s = m_slices.at(i);
917 919 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
918 920
919 921 if (forced || d->m_data.m_slicePen.isThemed())
920 922 d->setPen(penColor, true);
921 923
922 924 if (forced || d->m_data.m_sliceBrush.isThemed())
923 925 d->setBrush(brushColor, true);
924 926
925 927 if (forced || d->m_data.m_labelBrush.isThemed())
926 928 d->setLabelBrush(theme->labelBrush().color(), true);
927 929
928 930 if (forced || d->m_data.m_labelFont.isThemed())
929 931 d->setLabelFont(theme->labelFont(), true);
930 932 }
931 933 }
932 934
933 935
934 936 #include "moc_qpieseries.cpp"
935 937 #include "moc_qpieseries_p.cpp"
936 938
937 939 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,301 +1,304
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qscatterseries.h"
22 22 #include "qscatterseries_p.h"
23 23 #include "scatterchartitem_p.h"
24 24 #include "chartdataset_p.h"
25 25 #include "charttheme_p.h"
26 26 #include "scatteranimation_p.h"
27 27 #include "qchart_p.h"
28 28
29 29 /*!
30 30 \class QScatterSeries
31 31 \brief The QScatterSeries class is used for making scatter charts.
32 32
33 33 \mainclass
34 34
35 35 The scatter data is displayed as a collection of points on the chart. Each point determines the position on the horizontal axis
36 36 and the vertical axis.
37 37
38 38 \image examples_scatterchart.png
39 39
40 40 Creating basic scatter chart is simple:
41 41 \code
42 42 QScatterSeries* series = new QScatterSeries();
43 43 series->append(0, 6);
44 44 series->append(2, 4);
45 45 ...
46 46 chart->addSeries(series);
47 47 \endcode
48 48 */
49 49 /*!
50 50 \qmlclass ScatterSeries QScatterSeries
51 51 \inherits XYSeries
52 52
53 53 The following QML shows how to create a chart with two simple scatter series:
54 54 \snippet ../demos/qmlchart/qml/qmlchart/View5.qml 1
55 55
56 56 \beginfloatleft
57 57 \image demos_qmlchart5.png
58 58 \endfloat
59 59 \clearfloat
60 60 */
61 61
62 62 /*!
63 63 \enum QScatterSeries::MarkerShape
64 64
65 65 This enum describes the shape used when rendering marker items.
66 66
67 67 \value MarkerShapeCircle
68 68 \value MarkerShapeRectangle
69 69 */
70 70
71 71 /*!
72 72 \property QScatterSeries::color
73 73 Fill (brush) color of the series. This is a convenience property for modifying the color of brush.
74 74 \sa QScatterSeries::brush()
75 75 */
76 76
77 77 /*!
78 78 \property QScatterSeries::borderColor
79 79 Line (pen) color of the series. This is a convenience property for modifying the color of pen.
80 80 \sa QScatterSeries::pen()
81 81 */
82 82 /*!
83 83 \qmlproperty color ScatterSeries::borderColor
84 84 Border (pen) color of the series.
85 85 */
86 86
87 87 /*!
88 88 \qmlproperty real ScatterSeries::borderWidth
89 89 The width of the border line. By default the width is 2.0.
90 90 */
91 91
92 92 /*!
93 93 \property QScatterSeries::markerShape
94 94 Defines the shape of the marker used to draw the points in the series. The default shape is MarkerShapeCircle.
95 95 */
96 96 /*!
97 97 \qmlproperty MarkerShape ScatterSeries::markerShape
98 98 Defines the shape of the marker used to draw the points in the series. One of ScatterSeries
99 99 ScatterSeries.MarkerShapeCircle or ScatterSeries.MarkerShapeRectangle.
100 100 The default shape is ScatterSeries.MarkerShapeCircle.
101 101 */
102 102
103 103 /*!
104 104 \property QScatterSeries::markerSize
105 105 Defines the size of the marker used to draw the points in the series. The default size is 15.0.
106 106 */
107 107 /*!
108 108 \qmlproperty real ScatterSeries::markerSize
109 109 Defines the size of the marker used to draw the points in the series. The default size is 15.0.
110 110 */
111 111
112 112 /*!
113 113 \fn void QScatterSeries::colorChanged(QColor color)
114 114 Signal is emitted when the fill (brush) color has changed to \a color.
115 115 */
116 116
117 117 /*!
118 118 \fn void QScatterSeries::borderColorChanged(QColor color)
119 119 Signal is emitted when the line (pen) color has changed to \a color.
120 120 */
121 121 /*!
122 122 \qmlsignal ScatterSeries::borderColorChanged(color color)
123 123 Signal is emitted when the line (pen) color has changed to \a color.
124 124 */
125 125
126 126 /*!
127 127 \fn QAbstractSeries::SeriesType QScatterSeries::type() const
128 128 Returns QAbstractSeries::SeriesTypeScatter.
129 129 \sa QAbstractSeries, SeriesType
130 130 */
131 131
132 132 QTCOMMERCIALCHART_BEGIN_NAMESPACE
133 133
134 134 /*!
135 135 Constructs a series object which is a child of \a parent.
136 136 */
137 137 QScatterSeries::QScatterSeries(QObject *parent)
138 138 : QXYSeries(*new QScatterSeriesPrivate(this), parent)
139 139 {
140 140 }
141 141
142 142 /*!
143 143 Destroys the object. Note that adding series to QChart transfers the ownership to the chart.
144 144 */
145 145 QScatterSeries::~QScatterSeries()
146 146 {
147 147 Q_D(QScatterSeries);
148 148 if (d->m_chart)
149 149 d->m_chart->removeSeries(this);
150 150 }
151 151
152 152 QAbstractSeries::SeriesType QScatterSeries::type() const
153 153 {
154 154 return QAbstractSeries::SeriesTypeScatter;
155 155 }
156 156
157 157 /*!
158 158 Sets \a pen used for drawing points' border on the chart. If the pen is not defined, the
159 159 pen from chart theme is used.
160 160 \sa QChart::setTheme()
161 161 */
162 162 void QScatterSeries::setPen(const QPen &pen)
163 163 {
164 164 Q_D(QXYSeries);
165 165 if (d->m_pen != pen) {
166 166 bool emitColorChanged = d->m_pen.color() != pen.color();
167 167 d->m_pen = pen;
168 168 emit d->updated();
169 169 if (emitColorChanged)
170 170 emit borderColorChanged(pen.color());
171 171 }
172 172 }
173 173
174 174 /*!
175 175 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
176 176 from chart theme setting is used.
177 177 \sa QChart::setTheme()
178 178 */
179 179 void QScatterSeries::setBrush(const QBrush &brush)
180 180 {
181 181 Q_D(QScatterSeries);
182 182 if (d->m_brush != brush) {
183 183 bool emitColorChanged = d->m_brush.color() != brush.color();
184 184 d->m_brush = brush;
185 185 emit d->updated();
186 186 if (emitColorChanged)
187 187 emit colorChanged(brush.color());
188 188 }
189 189 }
190 190
191 191 void QScatterSeries::setColor(const QColor &color)
192 192 {
193 193 QBrush b = brush();
194 194 if (b == QBrush())
195 195 b.setStyle(Qt::SolidPattern);
196 196 b.setColor(color);
197 197 setBrush(b);
198 198 }
199 199
200 200 QColor QScatterSeries::color() const
201 201 {
202 202 return brush().color();
203 203 }
204 204
205 205 void QScatterSeries::setBorderColor(const QColor &color)
206 206 {
207 207 QPen p = pen();
208 208 if (p.color() != color) {
209 209 p.setColor(color);
210 210 setPen(p);
211 211 }
212 212 }
213 213
214 214 QColor QScatterSeries::borderColor() const
215 215 {
216 216 return pen().color();
217 217 }
218 218
219 219 QScatterSeries::MarkerShape QScatterSeries::markerShape() const
220 220 {
221 221 Q_D(const QScatterSeries);
222 222 return d->m_shape;
223 223 }
224 224
225 225 void QScatterSeries::setMarkerShape(MarkerShape shape)
226 226 {
227 227 Q_D(QScatterSeries);
228 228 if (d->m_shape != shape) {
229 229 d->m_shape = shape;
230 230 emit d->updated();
231 231 }
232 232 }
233 233
234 234 qreal QScatterSeries::markerSize() const
235 235 {
236 236 Q_D(const QScatterSeries);
237 237 return d->m_size;
238 238 }
239 239
240 240 void QScatterSeries::setMarkerSize(qreal size)
241 241 {
242 242 Q_D(QScatterSeries);
243 243
244 244 if (!qFuzzyCompare(d->m_size, size)) {
245 245 d->m_size = size;
246 246 emit d->updated();
247 247 }
248 248 }
249 249
250 250 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
251 251
252 252 QScatterSeriesPrivate::QScatterSeriesPrivate(QScatterSeries *q)
253 253 : QXYSeriesPrivate(q),
254 254 m_shape(QScatterSeries::MarkerShapeCircle),
255 255 m_size(15.0)
256 256 {
257 257 }
258 258
259 259 void QScatterSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
260 260 {
261 261 Q_Q(QScatterSeries);
262 262 ScatterChartItem *scatter = new ScatterChartItem(q,parent);
263 263 m_item.reset(scatter);
264 264 QAbstractSeriesPrivate::initializeGraphics(parent);
265 265 }
266 266
267 267 void QScatterSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
268 268 {
269 269 Q_Q(QScatterSeries);
270 270 const QList<QColor> colors = theme->seriesColors();
271 271 const QList<QGradient> gradients = theme->seriesGradients();
272 272
273 273 if (forced || QChartPrivate::defaultPen() == m_pen) {
274 274 QPen pen;
275 275 pen.setColor(ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0));
276 276 pen.setWidthF(2);
277 277 q->setPen(pen);
278 278 }
279 279
280 280 if (forced || QChartPrivate::defaultBrush() == m_brush) {
281 281 QBrush brush(colors.at(index % colors.size()));
282 282 q->setBrush(brush);
283 283 }
284 284 }
285 285
286 286 void QScatterSeriesPrivate::initializeAnimations(QChart::AnimationOptions options)
287 287 {
288 288 ScatterChartItem *item = static_cast<ScatterChartItem *>(m_item.data());
289 289 Q_ASSERT(item);
290 290
291 if (item->animation())
292 item->animation()->stopAndDestroyLater();
293
291 294 if (options.testFlag(QChart::SeriesAnimations))
292 295 item->setAnimation(new ScatterAnimation(item));
293 296 else
294 297 item->setAnimation(0);
295 298
296 299 QAbstractSeriesPrivate::initializeAnimations(options);
297 300 }
298 301
299 302 #include "moc_qscatterseries.cpp"
300 303
301 304 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,153 +1,155
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qsplineseries.h"
22 22 #include "qsplineseries_p.h"
23 23 #include "splinechartitem_p.h"
24 24 #include "chartdataset_p.h"
25 25 #include "charttheme_p.h"
26 26 #include "splineanimation_p.h"
27 27 #include "qchart_p.h"
28 28
29 29 /*!
30 30 \class QSplineSeries
31 31 \brief Series type used to store data needed to draw a spline.
32 32
33 33 QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
34 34 Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn.
35 35
36 36 \image examples_splinechart.png
37 37
38 38 Creating basic spline chart is simple:
39 39 \code
40 40 QSplineSeries* series = new QSplineSeries();
41 41 series->append(0, 6);
42 42 series->append(2, 4);
43 43 ...
44 44 chart->addSeries(series);
45 45 \endcode
46 46 */
47 47
48 48 /*!
49 49 \qmlclass SplineSeries QSplineSeries
50 50 \inherits XYSeries
51 51
52 52 The following QML shows how to create a simple spline chart:
53 53 \snippet ../demos/qmlchart/qml/qmlchart/View3.qml 1
54 54 \beginfloatleft
55 55 \image demos_qmlchart3.png
56 56 \endfloat
57 57 \clearfloat
58 58 */
59 59
60 60 /*!
61 61 \fn QSeriesType QSplineSeries::type() const
62 62 Returns the type of the series
63 63 */
64 64
65 65 /*!
66 66 \qmlproperty real SplineSeries::width
67 67 The width of the line. By default the width is 2.0.
68 68 */
69 69
70 70 /*!
71 71 \qmlproperty Qt::PenStyle SplineSeries::style
72 72 Controls the style of the line. Set to one of Qt.NoPen, Qt.SolidLine, Qt.DashLine, Qt.DotLine,
73 73 Qt.DashDotLine or Qt.DashDotDotLine. Using Qt.CustomDashLine is not supported in the QML API.
74 74 By default the style is Qt.SolidLine.
75 75 */
76 76
77 77 /*!
78 78 \qmlproperty Qt::PenCapStyle SplineSeries::capStyle
79 79 Controls the cap style of the line. Set to one of Qt.FlatCap, Qt.SquareCap or Qt.RoundCap. By
80 80 default the cap style is Qt.SquareCap.
81 81 */
82 82
83 83 QTCOMMERCIALCHART_BEGIN_NAMESPACE
84 84
85 85 /*!
86 86 Constructs empty series object which is a child of \a parent.
87 87 When series object is added to a QChart instance then the ownerships is transferred.
88 88 */
89 89
90 90 QSplineSeries::QSplineSeries(QObject *parent)
91 91 : QLineSeries(*new QSplineSeriesPrivate(this), parent)
92 92 {
93 93 }
94 94
95 95 /*!
96 96 Destroys the object.
97 97 */
98 98 QSplineSeries::~QSplineSeries()
99 99 {
100 100 Q_D(QSplineSeries);
101 101 if (d->m_chart)
102 102 d->m_chart->removeSeries(this);
103 103 }
104 104
105 105 QAbstractSeries::SeriesType QSplineSeries::type() const
106 106 {
107 107 return QAbstractSeries::SeriesTypeSpline;
108 108 }
109 109
110 110 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
111 111
112 112 QSplineSeriesPrivate::QSplineSeriesPrivate(QSplineSeries *q)
113 113 : QLineSeriesPrivate(q)
114 114 {
115 115 }
116 116
117 117 void QSplineSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
118 118 {
119 119 Q_Q(QSplineSeries);
120 120 SplineChartItem *spline = new SplineChartItem(q,parent);
121 121 m_item.reset(spline);
122 122 QAbstractSeriesPrivate::initializeGraphics(parent);
123 123 }
124 124
125 125 void QSplineSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
126 126 {
127 127 Q_Q(QSplineSeries);
128 128 const QList<QColor> colors = theme->seriesColors();
129 129
130 130 if (forced || QChartPrivate::defaultPen() == m_pen) {
131 131 QPen pen;
132 132 pen.setColor(colors.at(index % colors.size()));
133 133 pen.setWidthF(2);
134 134 q->setPen(pen);
135 135 }
136 136 }
137 137
138 138 void QSplineSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
139 139 {
140 140 SplineChartItem *item = static_cast<SplineChartItem *>(m_item.data());
141 141 Q_ASSERT(item);
142 if (options.testFlag(QChart::SeriesAnimations)) {
142 if (item->animation())
143 item->animation()->stopAndDestroyLater();
144
145 if (options.testFlag(QChart::SeriesAnimations))
143 146 item->setAnimation(new SplineAnimation(item));
144 }else{
147 else
145 148 item->setAnimation(0);
146 }
147 149 QAbstractSeriesPrivate::initializeAnimations(options);
148 150 }
149 151
150 152 #include "moc_qsplineseries.cpp"
151 153 #include "moc_qsplineseries_p.cpp"
152 154
153 155 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,596 +1,598
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qxyseries.h"
22 22 #include "qxyseries_p.h"
23 23 #include "abstractdomain_p.h"
24 24 #include "qvalueaxis.h"
25 25 #include "xychart_p.h"
26 26 #include "qxylegendmarker.h"
27 27 #include "charthelpers_p.h"
28 28 #include "qchart_p.h"
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31
32 32 /*!
33 33 \class QXYSeries
34 34 \brief The QXYSeries class is a base class for line, spline and scatter series.
35 35 */
36 36 /*!
37 37 \qmlclass XYSeries
38 38 \inherits AbstractSeries
39 39 The XYSeries class is a base class for line, spline and scatter series.
40 40
41 41 The class cannot be instantiated directly.
42 42 */
43 43
44 44 /*!
45 45 \qmlproperty AbstractAxis XYSeries::axisX
46 46 The x axis used for the series. If you leave both axisX and axisXTop undefined, a ValueAxis is created for
47 47 the series.
48 48 \sa axisXTop
49 49 */
50 50
51 51 /*!
52 52 \qmlproperty AbstractAxis XYSeries::axisY
53 53 The y axis used for the series. If you leave both axisY and axisYRight undefined, a ValueAxis is created for
54 54 the series.
55 55 \sa axisYRight
56 56 */
57 57
58 58 /*!
59 59 \qmlproperty AbstractAxis XYSeries::axisXTop
60 60 The x axis used for the series, drawn on top of the chart view. Note that you can only provide either axisX or
61 61 axisXTop, but not both.
62 62 \sa axisX
63 63 */
64 64
65 65 /*!
66 66 \qmlproperty AbstractAxis XYSeries::axisYRight
67 67 The y axis used for the series, drawn to the right on the chart view. Note that you can only provide either axisY
68 68 or axisYRight, but not both.
69 69 \sa axisY
70 70 */
71 71
72 72 /*!
73 73 \qmlproperty AbstractAxis XYSeries::axisAngular
74 74 The angular axis used for the series, drawn around the polar chart view.
75 75 \sa axisX
76 76 */
77 77
78 78 /*!
79 79 \qmlproperty AbstractAxis XYSeries::axisRadial
80 80 The radial axis used for the series, drawn inside the polar chart view.
81 81 \sa axisY
82 82 */
83 83
84 84 /*!
85 85 \property QXYSeries::pointsVisible
86 86 Controls if the data points are visible and should be drawn.
87 87 */
88 88 /*!
89 89 \qmlproperty bool XYSeries::pointsVisible
90 90 Controls if the data points are visible and should be drawn.
91 91 */
92 92
93 93 /*!
94 94 \fn QPen QXYSeries::pen() const
95 95 \brief Returns pen used to draw points for series.
96 96 \sa setPen()
97 97 */
98 98
99 99 /*!
100 100 \fn QBrush QXYSeries::brush() const
101 101 \brief Returns brush used to draw points for series.
102 102 \sa setBrush()
103 103 */
104 104
105 105 /*!
106 106 \property QXYSeries::color
107 107 The color of the series. This is line (pen) color in case of QLineSeries or QSplineSeries and
108 108 fill (brush) color in case of QScatterSeries or QAreaSeries.
109 109 \sa QXYSeries::pen(), QXYSeries::brush()
110 110 */
111 111 /*!
112 112 \qmlproperty color XYSeries::color
113 113 The color of the series. This is line (pen) color in case of LineSeries or SplineSeries and
114 114 fill (brush) color in case of ScatterSeries or AreaSeries.
115 115 */
116 116
117 117 /*!
118 118 \fn void QXYSeries::clicked(const QPointF& point)
119 119 \brief Signal is emitted when user clicks the \a point on chart.
120 120 */
121 121 /*!
122 122 \qmlsignal XYSeries::onClicked(QPointF point)
123 123 Signal is emitted when user clicks the \a point on chart. For example:
124 124 \code
125 125 LineSeries {
126 126 XYPoint { x: 0; y: 0 }
127 127 XYPoint { x: 1.1; y: 2.1 }
128 128 onClicked: console.log("onClicked: " + point.x + ", " + point.y);
129 129 }
130 130 \endcode
131 131 */
132 132
133 133 /*!
134 134 \fn void QXYSeries::hovered(const QPointF &point, bool state)
135 135 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
136 136 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
137 137 the series.
138 138 */
139 139 /*!
140 140 \qmlsignal XYSeries::onHovered(point point, bool state)
141 141 This signal is emitted when user has hovered over or away from the series. \a point shows the origin (coordinate)
142 142 of the hover event. \a state is true when user has hovered over the series and false when hover has moved away from
143 143 the series.
144 144 */
145 145
146 146 /*!
147 147 \fn void QXYSeries::pointReplaced(int index)
148 148 Signal is emitted when a point has been replaced at \a index.
149 149 \sa replace()
150 150 */
151 151 /*!
152 152 \qmlsignal XYSeries::onPointReplaced(int index)
153 153 Signal is emitted when a point has been replaced at \a index.
154 154 */
155 155
156 156 /*!
157 157 \fn void QXYSeries::pointsReplaced()
158 158 Signal is emitted when all points have been replaced with other points.
159 159 \sa replace()
160 160 */
161 161 /*!
162 162 \qmlsignal XYSeries::onPointsReplaced()
163 163 */
164 164
165 165 /*!
166 166 \fn void QXYSeries::pointAdded(int index)
167 167 Signal is emitted when a point has been added at \a index.
168 168 \sa append(), insert()
169 169 */
170 170 /*!
171 171 \qmlsignal XYSeries::onPointAdded(int index)
172 172 Signal is emitted when a point has been added at \a index.
173 173 */
174 174
175 175 /*!
176 176 \fn void QXYSeries::pointRemoved(int index)
177 177 Signal is emitted when a point has been removed from \a index.
178 178 \sa remove()
179 179 */
180 180 /*!
181 181 \qmlsignal XYSeries::onPointRemoved(int index)
182 182 Signal is emitted when a point has been removed from \a index.
183 183 */
184 184
185 185 /*!
186 186 \fn void QXYSeries::colorChanged(QColor color)
187 187 \brief Signal is emitted when the line (pen) color has changed to \a color.
188 188 */
189 189 /*!
190 190 \qmlsignal XYSeries::onColorChanged(color color)
191 191 Signal is emitted when the line (pen) color has changed to \a color.
192 192 */
193 193
194 194 /*!
195 195 \fn void QXYSeriesPrivate::updated()
196 196 \brief \internal
197 197 */
198 198
199 199 /*!
200 200 \qmlmethod XYSeries::append(real x, real y)
201 201 Append point (\a x, \a y) to the series
202 202 */
203 203
204 204 /*!
205 205 \qmlmethod XYSeries::replace(real oldX, real oldY, real newX, real newY)
206 206 Replaces point (\a oldX, \a oldY) with point (\a newX, \a newY). Does nothing, if point (oldX, oldY) does not
207 207 exist.
208 208 */
209 209
210 210 /*!
211 211 \qmlmethod XYSeries::remove(real x, real y)
212 212 Removes point (\a x, \a y) from the series. Does nothing, if point (x, y) does not exist.
213 213 */
214 214
215 215 /*!
216 216 \qmlmethod XYSeries::insert(int index, real x, real y)
217 217 Inserts point (\a x, \a y) to the \a index. If index is 0 or smaller than 0 the point is prepended to the list of
218 218 points. If index is the same as or bigger than count, the point is appended to the list of points.
219 219 */
220 220
221 221 /*!
222 222 \qmlmethod QPointF XYSeries::at(int index)
223 223 Returns point at \a index. Returns (0, 0) if the index is not valid.
224 224 */
225 225
226 226 /*!
227 227 \internal
228 228
229 229 Constructs empty series object which is a child of \a parent.
230 230 When series object is added to QChart instance ownerships is transferred.
231 231 */
232 232 QXYSeries::QXYSeries(QXYSeriesPrivate &d, QObject *parent)
233 233 : QAbstractSeries(d, parent)
234 234 {
235 235 }
236 236
237 237 /*!
238 238 Destroys the object. Series added to QChart instances are owned by those,
239 239 and are destroyed when QChart instances are destroyed.
240 240 */
241 241 QXYSeries::~QXYSeries()
242 242 {
243 243 }
244 244
245 245 /*!
246 246 Adds data point (\a x, \a y) to the series.
247 247 */
248 248 void QXYSeries::append(qreal x, qreal y)
249 249 {
250 250 append(QPointF(x, y));
251 251 }
252 252
253 253 /*!
254 254 This is an overloaded function.
255 255 Adds data \a point to the series.
256 256 */
257 257 void QXYSeries::append(const QPointF &point)
258 258 {
259 259 Q_D(QXYSeries);
260 260
261 261 if (isValidValue(point)) {
262 262 d->m_points << point;
263 263 emit pointAdded(d->m_points.count() - 1);
264 264 }
265 265 }
266 266
267 267 /*!
268 268 This is an overloaded function.
269 269 Adds list of data \a points to the series.
270 270 */
271 271 void QXYSeries::append(const QList<QPointF> &points)
272 272 {
273 273 foreach (const QPointF &point , points)
274 274 append(point);
275 275 }
276 276
277 277 /*!
278 278 Replaces data point (\a oldX, \a oldY) with data point (\a newX, \a newY).
279 279 \sa QXYSeries::pointReplaced()
280 280 */
281 281 void QXYSeries::replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
282 282 {
283 283 replace(QPointF(oldX, oldY), QPointF(newX, newY));
284 284 }
285 285
286 286 /*!
287 287 Replaces \a oldPoint with \a newPoint.
288 288 \sa QXYSeries::pointReplaced()
289 289 */
290 290 void QXYSeries::replace(const QPointF &oldPoint, const QPointF &newPoint)
291 291 {
292 292 Q_D(QXYSeries);
293 293 int index = d->m_points.indexOf(oldPoint);
294 294 if (index == -1)
295 295 return;
296 296 replace(index, newPoint);
297 297 }
298 298
299 299 /*!
300 300 Replaces the point at \a index with data point (\a newX, \a newY).
301 301 \sa QXYSeries::pointReplaced()
302 302 */
303 303 void QXYSeries::replace(int index, qreal newX, qreal newY)
304 304 {
305 305 replace(index, QPointF(newX, newY));
306 306 }
307 307
308 308 /*!
309 309 Replaces the point at \a index with \a newPoint.
310 310 \sa QXYSeries::pointReplaced()
311 311 */
312 312 void QXYSeries::replace(int index, const QPointF &newPoint)
313 313 {
314 314 Q_D(QXYSeries);
315 315 if (isValidValue(newPoint)) {
316 316 d->m_points[index] = newPoint;
317 317 emit pointReplaced(index);
318 318 }
319 319 }
320 320
321 321 /*!
322 322 Replaces the current points with \a points.
323 323 \note This is much faster than replacing data points one by one,
324 324 or first clearing all data, and then appending the new data. Emits QXYSeries::pointsReplaced()
325 325 when the points have been replaced.
326 326 \sa QXYSeries::pointsReplaced()
327 327 */
328 328 void QXYSeries::replace(QList<QPointF> points)
329 329 {
330 330 Q_D(QXYSeries);
331 331 d->m_points = points.toVector();
332 332 emit pointsReplaced();
333 333 }
334 334
335 335 /*!
336 336 Removes the point (\a x, \a y) from the series.
337 337 */
338 338 void QXYSeries::remove(qreal x, qreal y)
339 339 {
340 340 remove(QPointF(x, y));
341 341 }
342 342
343 343 /*!
344 344 Removes the \a point from the series.
345 345 */
346 346 void QXYSeries::remove(const QPointF &point)
347 347 {
348 348 Q_D(QXYSeries);
349 349 int index = d->m_points.indexOf(point);
350 350 if (index == -1)
351 351 return;
352 352 remove(index);
353 353 }
354 354
355 355 /*!
356 356 Removes the point at \a index from the series.
357 357 */
358 358 void QXYSeries::remove(int index)
359 359 {
360 360 Q_D(QXYSeries);
361 361 d->m_points.remove(index);
362 362 emit pointRemoved(index);
363 363 }
364 364
365 365 /*!
366 366 Inserts a \a point in the series at \a index position.
367 367 */
368 368 void QXYSeries::insert(int index, const QPointF &point)
369 369 {
370 370 Q_D(QXYSeries);
371 371 if (isValidValue(point)) {
372 372 d->m_points.insert(index, point);
373 373 emit pointAdded(index);
374 374 }
375 375 }
376 376
377 377 /*!
378 378 Removes all points from the series.
379 379 */
380 380 void QXYSeries::clear()
381 381 {
382 382 Q_D(QXYSeries);
383 383 for (int i = d->m_points.size() - 1; i >= 0; i--)
384 384 remove(d->m_points.at(i));
385 385 }
386 386
387 387 /*!
388 388 Returns list of points in the series.
389 389 */
390 390 QList<QPointF> QXYSeries::points() const
391 391 {
392 392 Q_D(const QXYSeries);
393 393 return d->m_points.toList();
394 394 }
395 395
396 396 /*!
397 397 Returns point at \a index in internal points vector.
398 398 */
399 399 const QPointF &QXYSeries::at(int index) const
400 400 {
401 401 Q_D(const QXYSeries);
402 402 return d->m_points.at(index);
403 403 }
404 404
405 405 /*!
406 406 Returns number of data points within series.
407 407 */
408 408 int QXYSeries::count() const
409 409 {
410 410 Q_D(const QXYSeries);
411 411 return d->m_points.count();
412 412 }
413 413
414 414
415 415 /*!
416 416 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
417 417 pen from chart theme is used.
418 418 \sa QChart::setTheme()
419 419 */
420 420 void QXYSeries::setPen(const QPen &pen)
421 421 {
422 422 Q_D(QXYSeries);
423 423 if (d->m_pen != pen) {
424 424 bool emitColorChanged = d->m_pen.color() != pen.color();
425 425 d->m_pen = pen;
426 426 emit d->updated();
427 427 if (emitColorChanged)
428 428 emit colorChanged(pen.color());
429 429 }
430 430 }
431 431
432 432 QPen QXYSeries::pen() const
433 433 {
434 434 Q_D(const QXYSeries);
435 435 if (d->m_pen == QChartPrivate::defaultPen())
436 436 return QPen();
437 437 else
438 438 return d->m_pen;
439 439 }
440 440
441 441 /*!
442 442 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
443 443 from chart theme setting is used.
444 444 \sa QChart::setTheme()
445 445 */
446 446 void QXYSeries::setBrush(const QBrush &brush)
447 447 {
448 448 Q_D(QXYSeries);
449 449 if (d->m_brush != brush) {
450 450 d->m_brush = brush;
451 451 emit d->updated();
452 452 }
453 453 }
454 454
455 455 QBrush QXYSeries::brush() const
456 456 {
457 457 Q_D(const QXYSeries);
458 458 if (d->m_brush == QChartPrivate::defaultBrush())
459 459 return QBrush();
460 460 else
461 461 return d->m_brush;
462 462 }
463 463
464 464 void QXYSeries::setColor(const QColor &color)
465 465 {
466 466 QPen p = pen();
467 467 if (p.color() != color) {
468 468 p.setColor(color);
469 469 setPen(p);
470 470 }
471 471 }
472 472
473 473 QColor QXYSeries::color() const
474 474 {
475 475 return pen().color();
476 476 }
477 477
478 478 void QXYSeries::setPointsVisible(bool visible)
479 479 {
480 480 Q_D(QXYSeries);
481 481 if (d->m_pointsVisible != visible) {
482 482 d->m_pointsVisible = visible;
483 483 emit d->updated();
484 484 }
485 485 }
486 486
487 487 bool QXYSeries::pointsVisible() const
488 488 {
489 489 Q_D(const QXYSeries);
490 490 return d->m_pointsVisible;
491 491 }
492 492
493 493
494 494 /*!
495 495 Stream operator for adding a data \a point to the series.
496 496 \sa append()
497 497 */
498 498 QXYSeries &QXYSeries::operator<< (const QPointF &point)
499 499 {
500 500 append(point);
501 501 return *this;
502 502 }
503 503
504 504
505 505 /*!
506 506 Stream operator for adding a list of \a points to the series.
507 507 \sa append()
508 508 */
509 509
510 510 QXYSeries &QXYSeries::operator<< (const QList<QPointF>& points)
511 511 {
512 512 append(points);
513 513 return *this;
514 514 }
515 515
516 516 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
517 517
518 518
519 519 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q)
520 520 : QAbstractSeriesPrivate(q),
521 521 m_pen(QChartPrivate::defaultPen()),
522 522 m_brush(QChartPrivate::defaultBrush()),
523 523 m_pointsVisible(false)
524 524 {
525 525 }
526 526
527 527 void QXYSeriesPrivate::initializeDomain()
528 528 {
529 529 qreal minX(0);
530 530 qreal minY(0);
531 531 qreal maxX(1);
532 532 qreal maxY(1);
533 533
534 534 Q_Q(QXYSeries);
535 535
536 536 const QList<QPointF>& points = q->points();
537 537
538 538 if (!points.isEmpty()) {
539 539 minX = points[0].x();
540 540 minY = points[0].y();
541 541 maxX = minX;
542 542 maxY = minY;
543 543
544 544 for (int i = 0; i < points.count(); i++) {
545 545 qreal x = points[i].x();
546 546 qreal y = points[i].y();
547 547 minX = qMin(minX, x);
548 548 minY = qMin(minY, y);
549 549 maxX = qMax(maxX, x);
550 550 maxY = qMax(maxY, y);
551 551 }
552 552 }
553 553
554 554 domain()->setRange(minX, maxX, minY, maxY);
555 555 }
556 556
557 557 QList<QLegendMarker*> QXYSeriesPrivate::createLegendMarkers(QLegend* legend)
558 558 {
559 559 Q_Q(QXYSeries);
560 560 QList<QLegendMarker*> list;
561 561 return list << new QXYLegendMarker(q,legend);
562 562 }
563 563
564 564 void QXYSeriesPrivate::initializeAxes()
565 565 {
566 566
567 567 }
568 568
569 569 QAbstractAxis::AxisType QXYSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
570 570 {
571 571 Q_UNUSED(orientation);
572 572 return QAbstractAxis::AxisTypeValue;
573 573 }
574 574
575 575 QAbstractAxis* QXYSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
576 576 {
577 577 Q_UNUSED(orientation);
578 578 return 0;
579 579 }
580 580
581 581 void QXYSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
582 582 {
583 583 XYChart *item = static_cast<XYChart *>(m_item.data());
584 584 Q_ASSERT(item);
585 if (options.testFlag(QChart::SeriesAnimations)) {
585 if (item->animation())
586 item->animation()->stopAndDestroyLater();
587
588 if (options.testFlag(QChart::SeriesAnimations))
586 589 item->setAnimation(new XYAnimation(item));
587 }else{
590 else
588 591 item->setAnimation(0);
589 }
590 592 QAbstractSeriesPrivate::initializeAnimations(options);
591 593 }
592 594
593 595 #include "moc_qxyseries.cpp"
594 596 #include "moc_qxyseries_p.cpp"
595 597
596 598 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now