##// END OF EJS Templates
Fix crash when removing pie series from chart...
Miikka Heikkinen -
r2475:9e35a3a169ed
parent child
Show More
@@ -1,85 +1,86
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 PIECHARTITEM_H
31 31 #define PIECHARTITEM_H
32 32
33 33 #include "qpieseries.h"
34 34 #include "chartitem_p.h"
35 35 #include "piesliceitem_p.h"
36 #include <QPointer>
36 37
37 38 class QGraphicsItem;
38 39 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 40 class QPieSlice;
40 41 class ChartPresenter;
41 42 class PieAnimation;
42 43
43 44 class PieChartItem : public ChartItem
44 45 {
45 46 Q_OBJECT
46 47
47 48 public:
48 49 explicit PieChartItem(QPieSeries *series, QGraphicsItem* item = 0);
49 50 ~PieChartItem();
50 51
51 52 // from QGraphicsItem
52 53 QRectF boundingRect() const { return m_rect; }
53 54 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
54 55
55 56 public Q_SLOTS:
56 57 // from Chart
57 58 virtual void handleDomainUpdated();
58 59
59 60 void updateLayout();
60 61 void handleSlicesAdded(QList<QPieSlice *> slices);
61 62 void handleSlicesRemoved(QList<QPieSlice *> slices);
62 63 void handleSliceChanged();
63 64 void handleSeriesVisibleChanged();
64 65 void handleOpacityChanged();
65 66
66 67 void setAnimation(PieAnimation *animation);
67 68 ChartAnimation *animation() const;
68 69
69 70 private:
70 71 PieSliceData updateSliceGeometry(QPieSlice *slice);
71 72
72 73 private:
73 74 QHash<QPieSlice *, PieSliceItem *> m_sliceItems;
74 QPieSeries *m_series;
75 QPointer<QPieSeries> m_series;
75 76 QRectF m_rect;
76 77 QPointF m_pieCenter;
77 78 qreal m_pieRadius;
78 79 qreal m_holeSize;
79 80 PieAnimation *m_animation;
80 81
81 82 };
82 83
83 84 QTCOMMERCIALCHART_END_NAMESPACE
84 85
85 86 #endif // PIECHARTITEM_H
@@ -1,936 +1,937
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 clear();
365 366 }
366 367
367 368 /*!
368 369 Returns QChartSeries::SeriesTypePie.
369 370 */
370 371 QAbstractSeries::SeriesType QPieSeries::type() const
371 372 {
372 373 return QAbstractSeries::SeriesTypePie;
373 374 }
374 375
375 376 /*!
376 377 Appends a single \a slice to the series.
377 378 Slice ownership is passed to the series.
378 379
379 380 Returns true if append was succesfull.
380 381 */
381 382 bool QPieSeries::append(QPieSlice *slice)
382 383 {
383 384 return append(QList<QPieSlice *>() << slice);
384 385 }
385 386
386 387 /*!
387 388 Appends an array of \a slices to the series.
388 389 Slice ownership is passed to the series.
389 390
390 391 Returns true if append was successful.
391 392 */
392 393 bool QPieSeries::append(QList<QPieSlice *> slices)
393 394 {
394 395 Q_D(QPieSeries);
395 396
396 397 if (slices.count() == 0)
397 398 return false;
398 399
399 400 foreach (QPieSlice *s, slices) {
400 401 if (!s || d->m_slices.contains(s))
401 402 return false;
402 403 if (s->series()) // already added to some series
403 404 return false;
404 405 if (!isValidValue(s->value()))
405 406 return false;
406 407 }
407 408
408 409 foreach (QPieSlice *s, slices) {
409 410 s->setParent(this);
410 411 QPieSlicePrivate::fromSlice(s)->m_series = this;
411 412 d->m_slices << s;
412 413 }
413 414
414 415 d->updateDerivativeData();
415 416
416 417 foreach(QPieSlice * s, slices) {
417 418 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
418 419 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
419 420 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
420 421 }
421 422
422 423 emit added(slices);
423 424 emit countChanged();
424 425
425 426 return true;
426 427 }
427 428
428 429 /*!
429 430 Appends a single \a slice to the series and returns a reference to the series.
430 431 Slice ownership is passed to the series.
431 432 */
432 433 QPieSeries &QPieSeries::operator << (QPieSlice *slice)
433 434 {
434 435 append(slice);
435 436 return *this;
436 437 }
437 438
438 439
439 440 /*!
440 441 Appends a single slice to the series with give \a value and \a label.
441 442 Slice ownership is passed to the series.
442 443 Returns NULL if value is NaN, Inf or -Inf and no slice is added to the series.
443 444 */
444 445 QPieSlice *QPieSeries::append(QString label, qreal value)
445 446 {
446 447 if (isValidValue(value)) {
447 448 QPieSlice *slice = new QPieSlice(label, value);
448 449 append(slice);
449 450 return slice;
450 451 } else {
451 452 return 0;
452 453 }
453 454 }
454 455
455 456 /*!
456 457 Inserts a single \a slice to the series before the slice at \a index position.
457 458 Slice ownership is passed to the series.
458 459
459 460 Returns true if insert was successful.
460 461 */
461 462 bool QPieSeries::insert(int index, QPieSlice *slice)
462 463 {
463 464 Q_D(QPieSeries);
464 465
465 466 if (index < 0 || index > d->m_slices.count())
466 467 return false;
467 468
468 469 if (!slice || d->m_slices.contains(slice))
469 470 return false;
470 471
471 472 if (slice->series()) // already added to some series
472 473 return false;
473 474
474 475 if (!isValidValue(slice->value()))
475 476 return false;
476 477
477 478 slice->setParent(this);
478 479 QPieSlicePrivate::fromSlice(slice)->m_series = this;
479 480 d->m_slices.insert(index, slice);
480 481
481 482 d->updateDerivativeData();
482 483
483 484 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
484 485 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
485 486 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
486 487
487 488 emit added(QList<QPieSlice *>() << slice);
488 489 emit countChanged();
489 490
490 491 return true;
491 492 }
492 493
493 494 /*!
494 495 Removes a single \a slice from the series and deletes the slice.
495 496
496 497 Do not reference the pointer after this call.
497 498
498 499 Returns true if remove was successful.
499 500 */
500 501 bool QPieSeries::remove(QPieSlice *slice)
501 502 {
502 503 Q_D(QPieSeries);
503 504
504 505 if (!d->m_slices.removeOne(slice))
505 506 return false;
506 507
507 508 d->updateDerivativeData();
508 509
509 510 emit removed(QList<QPieSlice *>() << slice);
510 511 emit countChanged();
511 512
512 513 delete slice;
513 514 slice = 0;
514 515
515 516 return true;
516 517 }
517 518
518 519 /*!
519 520 Takes a single \a slice from the series. Does not destroy the slice object.
520 521
521 522 NOTE: The series remains as the slice's parent object. You must set the
522 523 parent object to take full ownership.
523 524
524 525 Returns true if take was successful.
525 526 */
526 527 bool QPieSeries::take(QPieSlice *slice)
527 528 {
528 529 Q_D(QPieSeries);
529 530
530 531 if (!d->m_slices.removeOne(slice))
531 532 return false;
532 533
533 534 QPieSlicePrivate::fromSlice(slice)->m_series = 0;
534 535 slice->disconnect(d);
535 536
536 537 d->updateDerivativeData();
537 538
538 539 emit removed(QList<QPieSlice *>() << slice);
539 540 emit countChanged();
540 541
541 542 return true;
542 543 }
543 544
544 545 /*!
545 546 Clears all slices from the series.
546 547 */
547 548 void QPieSeries::clear()
548 549 {
549 550 Q_D(QPieSeries);
550 551 if (d->m_slices.count() == 0)
551 552 return;
552 553
553 554 QList<QPieSlice *> slices = d->m_slices;
554 555 foreach (QPieSlice *s, d->m_slices)
555 556 d->m_slices.removeOne(s);
556 557
557 558 d->updateDerivativeData();
558 559
559 560 emit removed(slices);
560 561 emit countChanged();
561 562
562 563 foreach (QPieSlice *s, slices)
563 564 delete s;
564 565 }
565 566
566 567 /*!
567 568 Returns a list of slices that belong to this series.
568 569 */
569 570 QList<QPieSlice *> QPieSeries::slices() const
570 571 {
571 572 Q_D(const QPieSeries);
572 573 return d->m_slices;
573 574 }
574 575
575 576 /*!
576 577 returns the number of the slices in this series.
577 578 */
578 579 int QPieSeries::count() const
579 580 {
580 581 Q_D(const QPieSeries);
581 582 return d->m_slices.count();
582 583 }
583 584
584 585 /*!
585 586 Returns true is the series is empty.
586 587 */
587 588 bool QPieSeries::isEmpty() const
588 589 {
589 590 Q_D(const QPieSeries);
590 591 return d->m_slices.isEmpty();
591 592 }
592 593
593 594 /*!
594 595 Returns the sum of all slice values in this series.
595 596
596 597 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
597 598 */
598 599 qreal QPieSeries::sum() const
599 600 {
600 601 Q_D(const QPieSeries);
601 602 return d->m_sum;
602 603 }
603 604
604 605 void QPieSeries::setHoleSize(qreal holeSize)
605 606 {
606 607 Q_D(QPieSeries);
607 608 holeSize = qBound((qreal)0.0, holeSize, (qreal)1.0);
608 609 d->setSizes(holeSize, qMax(d->m_pieRelativeSize, holeSize));
609 610 }
610 611
611 612 qreal QPieSeries::holeSize() const
612 613 {
613 614 Q_D(const QPieSeries);
614 615 return d->m_holeRelativeSize;
615 616 }
616 617
617 618 void QPieSeries::setHorizontalPosition(qreal relativePosition)
618 619 {
619 620 Q_D(QPieSeries);
620 621
621 622 if (relativePosition < 0.0)
622 623 relativePosition = 0.0;
623 624 if (relativePosition > 1.0)
624 625 relativePosition = 1.0;
625 626
626 627 if (!qFuzzyCompare(d->m_pieRelativeHorPos, relativePosition)) {
627 628 d->m_pieRelativeHorPos = relativePosition;
628 629 emit d->horizontalPositionChanged();
629 630 }
630 631 }
631 632
632 633 qreal QPieSeries::horizontalPosition() const
633 634 {
634 635 Q_D(const QPieSeries);
635 636 return d->m_pieRelativeHorPos;
636 637 }
637 638
638 639 void QPieSeries::setVerticalPosition(qreal relativePosition)
639 640 {
640 641 Q_D(QPieSeries);
641 642
642 643 if (relativePosition < 0.0)
643 644 relativePosition = 0.0;
644 645 if (relativePosition > 1.0)
645 646 relativePosition = 1.0;
646 647
647 648 if (!qFuzzyCompare(d->m_pieRelativeVerPos, relativePosition)) {
648 649 d->m_pieRelativeVerPos = relativePosition;
649 650 emit d->verticalPositionChanged();
650 651 }
651 652 }
652 653
653 654 qreal QPieSeries::verticalPosition() const
654 655 {
655 656 Q_D(const QPieSeries);
656 657 return d->m_pieRelativeVerPos;
657 658 }
658 659
659 660 void QPieSeries::setPieSize(qreal relativeSize)
660 661 {
661 662 Q_D(QPieSeries);
662 663 relativeSize = qBound((qreal)0.0, relativeSize, (qreal)1.0);
663 664 d->setSizes(qMin(d->m_holeRelativeSize, relativeSize), relativeSize);
664 665
665 666 }
666 667
667 668 qreal QPieSeries::pieSize() const
668 669 {
669 670 Q_D(const QPieSeries);
670 671 return d->m_pieRelativeSize;
671 672 }
672 673
673 674
674 675 void QPieSeries::setPieStartAngle(qreal angle)
675 676 {
676 677 Q_D(QPieSeries);
677 678 if (qFuzzyCompare(d->m_pieStartAngle, angle))
678 679 return;
679 680 d->m_pieStartAngle = angle;
680 681 d->updateDerivativeData();
681 682 emit d->pieStartAngleChanged();
682 683 }
683 684
684 685 qreal QPieSeries::pieStartAngle() const
685 686 {
686 687 Q_D(const QPieSeries);
687 688 return d->m_pieStartAngle;
688 689 }
689 690
690 691 /*!
691 692 Sets the end angle of the pie.
692 693
693 694 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
694 695
695 696 \a angle must be greater than start angle.
696 697
697 698 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
698 699 */
699 700 void QPieSeries::setPieEndAngle(qreal angle)
700 701 {
701 702 Q_D(QPieSeries);
702 703 if (qFuzzyCompare(d->m_pieEndAngle, angle))
703 704 return;
704 705 d->m_pieEndAngle = angle;
705 706 d->updateDerivativeData();
706 707 emit d->pieEndAngleChanged();
707 708 }
708 709
709 710 /*!
710 711 Returns the end angle of the pie.
711 712
712 713 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
713 714
714 715 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
715 716 */
716 717 qreal QPieSeries::pieEndAngle() const
717 718 {
718 719 Q_D(const QPieSeries);
719 720 return d->m_pieEndAngle;
720 721 }
721 722
722 723 /*!
723 724 Sets the all the slice labels \a visible or invisible.
724 725
725 726 Note that this affects only the current slices in the series.
726 727 If user adds a new slice the default label visibility is false.
727 728
728 729 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
729 730 */
730 731 void QPieSeries::setLabelsVisible(bool visible)
731 732 {
732 733 Q_D(QPieSeries);
733 734 foreach (QPieSlice *s, d->m_slices)
734 735 s->setLabelVisible(visible);
735 736 }
736 737
737 738 /*!
738 739 Sets the all the slice labels \a position
739 740
740 741 Note that this affects only the current slices in the series.
741 742 If user adds a new slice the default label position is LabelOutside
742 743
743 744 \sa QPieSlice::labelPosition(), QPieSlice::setLabelPosition()
744 745 */
745 746 void QPieSeries::setLabelsPosition(QPieSlice::LabelPosition position)
746 747 {
747 748 Q_D(QPieSeries);
748 749 foreach (QPieSlice *s, d->m_slices)
749 750 s->setLabelPosition(position);
750 751 }
751 752
752 753 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
753 754
754 755
755 756 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
756 757 QAbstractSeriesPrivate(parent),
757 758 m_pieRelativeHorPos(0.5),
758 759 m_pieRelativeVerPos(0.5),
759 760 m_pieRelativeSize(0.7),
760 761 m_pieStartAngle(0),
761 762 m_pieEndAngle(360),
762 763 m_sum(0),
763 764 m_holeRelativeSize(0.0)
764 765 {
765 766 }
766 767
767 768 QPieSeriesPrivate::~QPieSeriesPrivate()
768 769 {
769 770 }
770 771
771 772 void QPieSeriesPrivate::updateDerivativeData()
772 773 {
773 774 // calculate sum of all slices
774 775 qreal sum = 0;
775 776 foreach (QPieSlice *s, m_slices)
776 777 sum += s->value();
777 778
778 779 if (!qFuzzyCompare(m_sum, sum)) {
779 780 m_sum = sum;
780 781 emit q_func()->sumChanged();
781 782 }
782 783
783 784 // nothing to show..
784 785 if (qFuzzyCompare(m_sum, 0))
785 786 return;
786 787
787 788 // update slice attributes
788 789 qreal sliceAngle = m_pieStartAngle;
789 790 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
790 791 QVector<QPieSlice *> changed;
791 792 foreach (QPieSlice *s, m_slices) {
792 793 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
793 794 d->setPercentage(s->value() / m_sum);
794 795 d->setStartAngle(sliceAngle);
795 796 d->setAngleSpan(pieSpan * s->percentage());
796 797 sliceAngle += s->angleSpan();
797 798 }
798 799
799 800
800 801 emit calculatedDataChanged();
801 802 }
802 803
803 804 void QPieSeriesPrivate::setSizes(qreal innerSize, qreal outerSize)
804 805 {
805 806 bool changed = false;
806 807
807 808 if (!qFuzzyCompare(m_holeRelativeSize, innerSize)) {
808 809 m_holeRelativeSize = innerSize;
809 810 changed = true;
810 811 }
811 812
812 813 if (!qFuzzyCompare(m_pieRelativeSize, outerSize)) {
813 814 m_pieRelativeSize = outerSize;
814 815 changed = true;
815 816 }
816 817
817 818 if (changed)
818 819 emit pieSizeChanged();
819 820 }
820 821
821 822 QPieSeriesPrivate *QPieSeriesPrivate::fromSeries(QPieSeries *series)
822 823 {
823 824 return series->d_func();
824 825 }
825 826
826 827 void QPieSeriesPrivate::sliceValueChanged()
827 828 {
828 829 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
829 830 updateDerivativeData();
830 831 }
831 832
832 833 void QPieSeriesPrivate::sliceClicked()
833 834 {
834 835 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
835 836 Q_ASSERT(m_slices.contains(slice));
836 837 Q_Q(QPieSeries);
837 838 emit q->clicked(slice);
838 839 }
839 840
840 841 void QPieSeriesPrivate::sliceHovered(bool state)
841 842 {
842 843 QPieSlice *slice = qobject_cast<QPieSlice *>(sender());
843 844 Q_ASSERT(m_slices.contains(slice));
844 845 Q_Q(QPieSeries);
845 846 emit q->hovered(slice, state);
846 847 }
847 848
848 849 void QPieSeriesPrivate::initializeDomain()
849 850 {
850 851 // does not apply to pie
851 852 }
852 853
853 854 void QPieSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
854 855 {
855 856 Q_Q(QPieSeries);
856 857 PieChartItem *pie = new PieChartItem(q,parent);
857 858 m_item.reset(pie);
858 859 QAbstractSeriesPrivate::initializeGraphics(parent);
859 860 }
860 861
861 862 void QPieSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
862 863 {
863 864 PieChartItem *item = static_cast<PieChartItem *>(m_item.data());
864 865 Q_ASSERT(item);
865 866 if (options.testFlag(QChart::SeriesAnimations)) {
866 867 item->setAnimation(new PieAnimation(item));
867 868 }else{
868 869 item->setAnimation(0);
869 870 }
870 871 QAbstractSeriesPrivate::initializeAnimations(options);
871 872 }
872 873
873 874 QList<QLegendMarker*> QPieSeriesPrivate::createLegendMarkers(QLegend* legend)
874 875 {
875 876 Q_Q(QPieSeries);
876 877 QList<QLegendMarker*> markers;
877 878 foreach(QPieSlice* slice, q->slices()) {
878 879 QPieLegendMarker* marker = new QPieLegendMarker(q,slice,legend);
879 880 markers << marker;
880 881 }
881 882 return markers;
882 883 }
883 884
884 885 void QPieSeriesPrivate::initializeAxes()
885 886 {
886 887
887 888 }
888 889
889 890 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
890 891 {
891 892 Q_UNUSED(orientation);
892 893 return QAbstractAxis::AxisTypeNoAxis;
893 894 }
894 895
895 896 QAbstractAxis* QPieSeriesPrivate::createDefaultAxis(Qt::Orientation orientation) const
896 897 {
897 898 Q_UNUSED(orientation);
898 899 return 0;
899 900 }
900 901
901 902 void QPieSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool forced)
902 903 {
903 904 //Q_Q(QPieSeries);
904 905 //const QList<QColor>& colors = theme->seriesColors();
905 906 const QList<QGradient>& gradients = theme->seriesGradients();
906 907
907 908 for (int i(0); i < m_slices.count(); i++) {
908 909
909 910 QColor penColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), 0.0);
910 911
911 912 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
912 913 qreal pos = (qreal)(i + 1) / (qreal) m_slices.count();
913 914 QColor brushColor = ChartThemeManager::colorAt(gradients.at(index % gradients.size()), pos);
914 915
915 916 QPieSlice *s = m_slices.at(i);
916 917 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
917 918
918 919 if (forced || d->m_data.m_slicePen.isThemed())
919 920 d->setPen(penColor, true);
920 921
921 922 if (forced || d->m_data.m_sliceBrush.isThemed())
922 923 d->setBrush(brushColor, true);
923 924
924 925 if (forced || d->m_data.m_labelBrush.isThemed())
925 926 d->setLabelBrush(theme->labelBrush().color(), true);
926 927
927 928 if (forced || d->m_data.m_labelFont.isThemed())
928 929 d->setLabelFont(theme->labelFont(), true);
929 930 }
930 931 }
931 932
932 933
933 934 #include "moc_qpieseries.cpp"
934 935 #include "moc_qpieseries_p.cpp"
935 936
936 937 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now