##// END OF EJS Templates
legend private implemantation modified.
sauimone -
r2081:b2efc1272dac
parent child
Show More
@@ -1,870 +1,867
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "domain_p.h"
26 26 #include "legendmarker_p.h"
27 27 #include "chartdataset_p.h"
28 28 #include "charttheme_p.h"
29 29 #include "qvalueaxis.h"
30 30 #include "qbarcategoryaxis.h"
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 /*!
35 35 \class QAbstractBarSeries
36 36 \brief Series for creating a bar chart
37 37 \mainclass
38 38
39 39 QAbstractBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars to
40 40 the position defined by data. Single bar is defined by QPointF, where x value is the x-coordinate of the bar
41 41 and y-value is the height of the bar. The category names are ignored with this series and x-axis
42 42 shows the x-values.
43 43
44 44 See the \l {BarChart Example} {bar chart example} to learn how to create a simple bar chart.
45 45 \image examples_barchart.png
46 46
47 47 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
48 48 */
49 49 /*!
50 50 \qmlclass AbstractBarSeries QAbstractBarSeries
51 51 \inherits QAbstractSeries
52 52
53 53 The following QML shows how to create a simple bar chart:
54 54 \snippet ../demos/qmlchart/qml/qmlchart/View6.qml 1
55 55
56 56 \beginfloatleft
57 57 \image demos_qmlchart6.png
58 58 \endfloat
59 59 \clearfloat
60 60 */
61 61
62 62 /*!
63 63 \property QAbstractBarSeries::barWidth
64 64 The width of the bars of the series. The unit of \a width is the unit of x-axis. The minimum width for bars
65 65 is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
66 66 is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
67 67 Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
68 68 \sa QBarSeries
69 69 */
70 70 /*!
71 71 \qmlproperty real AbstractBarSeries::barWidth
72 72 The width of the bars of the series. The unit of width is the unit of x-axis. The minimum width for bars
73 73 is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
74 74 is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
75 75 Note that with QBarSeries this value means the width of one group of bars instead of just one bar.
76 76 */
77 77
78 78 /*!
79 79 \property QAbstractBarSeries::count
80 80 Holds the number of sets in series.
81 81 */
82 82 /*!
83 83 \qmlproperty int AbstractBarSeries::count
84 84 Holds the number of sets in series.
85 85 */
86 86
87 87 /*!
88 88 \property QAbstractBarSeries::labelsVisible
89 89 Defines the visibility of the labels in series
90 90 */
91 91 /*!
92 92 \qmlproperty bool AbstractBarSeries::labelsVisible
93 93 Defines the visibility of the labels in series
94 94 */
95 95
96 96 /*!
97 97 \fn void QAbstractBarSeries::clicked(int index, QBarSet *barset)
98 98 The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset.
99 99 Clicked bar inside set is indexed by \a index
100 100 */
101 101 /*!
102 102 \qmlsignal AbstractBarSeries::onClicked(int index, BarSet barset)
103 103 The signal is emitted if the user clicks with a mouse on top of BarSet.
104 104 Clicked bar inside set is indexed by \a index
105 105 */
106 106
107 107 /*!
108 108 \fn void QAbstractBarSeries::hovered(bool status, QBarSet* barset)
109 109
110 110 The signal is emitted if mouse is hovered on top of series.
111 111 Parameter \a barset is the pointer of barset, where hover happened.
112 112 Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
113 113 */
114 114 /*!
115 115 \qmlsignal AbstractBarSeries::onHovered(bool status, BarSet barset)
116 116
117 117 The signal is emitted if mouse is hovered on top of series.
118 118 Parameter \a barset is the pointer of barset, where hover happened.
119 119 Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
120 120 */
121 121
122 122 /*!
123 123 \fn void QAbstractBarSeries::countChanged()
124 124 This signal is emitted when barset count has been changed, for example by append or remove.
125 125 */
126 126 /*!
127 127 \qmlsignal AbstractBarSeries::onCountChanged()
128 128 This signal is emitted when barset count has been changed, for example by append or remove.
129 129 */
130 130
131 131 /*!
132 132 \fn void QAbstractBarSeries::labelsVisibleChanged()
133 133 This signal is emitted when labels visibility have changed.
134 134 \sa isLabelsVisible(), setLabelsVisible()
135 135 */
136 136
137 137 /*!
138 138 \fn void QAbstractBarSeries::barsetsAdded(QList<QBarSet*> sets)
139 139 This signal is emitted when \a sets have been added to the series.
140 140 \sa append(), insert()
141 141 */
142 142 /*!
143 143 \qmlsignal AbstractBarSeries::onAdded(BarSet barset)
144 144 Emitted when \a barset has been added to the series.
145 145 */
146 146
147 147 /*!
148 148 \fn void QAbstractBarSeries::barsetsRemoved(QList<QBarSet*> sets)
149 149 This signal is emitted when \a sets have been removed from the series.
150 150 \sa remove()
151 151 */
152 152 /*!
153 153 \qmlsignal AbstractBarSeries::onRemoved(BarSet barset)
154 154 Emitted when \a barset has been removed from the series.
155 155 */
156 156
157 157 /*!
158 158 \qmlmethod BarSet AbstractBarSeries::at(int index)
159 159 Returns bar set at \a index. Returns null if the index is not valid.
160 160 */
161 161
162 162 /*!
163 163 \qmlmethod BarSet AbstractBarSeries::append(string label, VariantList values)
164 164 Adds 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.
165 165 For example:
166 166 \code
167 167 myBarSeries.append("set 1", [0, 0.2, 0.2, 0.5, 0.4, 1.5, 0.9]);
168 168 myBarSeries.append("set 2", [Qt.point(0, 1), Qt.point(2, 2.5), Qt.point(3.5, 2.2)]);
169 169 \endcode
170 170 */
171 171
172 172 /*!
173 173 \qmlmethod BarSet AbstractBarSeries::insert(int index, string label, VariantList values)
174 174 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.
175 175 If index is zero or smaller, the new barset is prepended. If the index is count or bigger, the new barset is
176 176 appended.
177 177 \sa AbstractBarSeries::append()
178 178 */
179 179
180 180 /*!
181 181 \qmlmethod bool AbstractBarSeries::remove(BarSet barset)
182 182 Removes the barset from the series. Returns true if successful, false otherwise.
183 183 */
184 184
185 185 /*!
186 186 \qmlmethod AbstractBarSeries::clear()
187 187 Removes all barsets from the series.
188 188 */
189 189
190 190 /*!
191 191 Destructs abstractbarseries and owned barsets.
192 192 */
193 193 QAbstractBarSeries::~QAbstractBarSeries()
194 194 {
195 195
196 196 }
197 197
198 198 /*!
199 199 \internal
200 200 */
201 201 QAbstractBarSeries::QAbstractBarSeries(QAbstractBarSeriesPrivate &d, QObject *parent) :
202 202 QAbstractSeries(d,parent)
203 203 {
204 204 }
205 205
206 206 /*!
207 207 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
208 208 is zero and negative values are treated as zero. Setting the width to zero means that width of the bar on screen
209 209 is one pixel no matter what the scale of x-axis is. Bars wider than zero are scaled with x-axis.
210 210 Note that with \link QBarSeries \endlink this value means the width of one group of bars instead of just one bar.
211 211 */
212 212 void QAbstractBarSeries::setBarWidth(qreal width)
213 213 {
214 214 Q_D(QAbstractBarSeries);
215 215 d->setBarWidth(width);
216 216 }
217 217
218 218 /*!
219 219 Returns the width of the bars of the series.
220 220 \sa setBarWidth()
221 221 */
222 222 qreal QAbstractBarSeries::barWidth() const
223 223 {
224 224 Q_D(const QAbstractBarSeries);
225 225 return d->barWidth();
226 226 }
227 227
228 228 /*!
229 229 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.
230 230 Returns true, if appending succeeded.
231 231 */
232 232 bool QAbstractBarSeries::append(QBarSet *set)
233 233 {
234 234 Q_D(QAbstractBarSeries);
235 235 bool success = d->append(set);
236 236 if (success) {
237 237 QList<QBarSet*> sets;
238 238 sets.append(set);
239 239 set->setParent(this);
240 240 emit barsetsAdded(sets);
241 241 emit countChanged();
242 242 }
243 243 return success;
244 244 }
245 245
246 246 /*!
247 247 Removes barset from series. Releases ownership of \a set. Deletes the set, if remove
248 248 was successful.
249 249 Returns true, if set was removed.
250 250 */
251 251 bool QAbstractBarSeries::remove(QBarSet *set)
252 252 {
253 253 Q_D(QAbstractBarSeries);
254 254 bool success = d->remove(set);
255 255 if (success) {
256 256 QList<QBarSet*> sets;
257 257 sets.append(set);
258 258 set->setParent(0);
259 259 emit barsetsRemoved(sets);
260 260 emit countChanged();
261 261 delete set;
262 262 set = 0;
263 263 }
264 264 return success;
265 265 }
266 266
267 267 /*!
268 268 Takes a single \a set from the series. Does not delete the barset object.
269 269
270 270 NOTE: The series remains as the barset's parent object. You must set the
271 271 parent object to take full ownership.
272 272
273 273 Returns true if take was successful.
274 274 */
275 275 bool QAbstractBarSeries::take(QBarSet *set)
276 276 {
277 277 Q_D(QAbstractBarSeries);
278 278 bool success = d->remove(set);
279 279 if (success) {
280 280 QList<QBarSet*> sets;
281 281 sets.append(set);
282 282 emit barsetsRemoved(sets);
283 283 emit countChanged();
284 284 }
285 285 return success;
286 286 }
287 287
288 288 /*!
289 289 Adds a list of barsets to series. Takes ownership of \a sets.
290 290 Returns true, if all sets were appended successfully. If any of the sets is null or is already appended to series,
291 291 nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
292 292 and function returns false.
293 293 */
294 294 bool QAbstractBarSeries::append(QList<QBarSet* > sets)
295 295 {
296 296 Q_D(QAbstractBarSeries);
297 297 bool success = d->append(sets);
298 298 if (success) {
299 299 emit barsetsAdded(sets);
300 300 emit countChanged();
301 301 }
302 302 return success;
303 303 }
304 304
305 305 /*!
306 306 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.
307 307 Returns true, if inserting succeeded.
308 308
309 309 */
310 310 bool QAbstractBarSeries::insert(int index, QBarSet *set)
311 311 {
312 312 Q_D(QAbstractBarSeries);
313 313 bool success = d->insert(index, set);
314 314 if (success) {
315 315 QList<QBarSet*> sets;
316 316 sets.append(set);
317 317 emit barsetsAdded(sets);
318 318 emit countChanged();
319 319 }
320 320 return success;
321 321 }
322 322
323 323 /*!
324 324 Removes all barsets from the series. Deletes removed sets.
325 325 */
326 326 void QAbstractBarSeries::clear()
327 327 {
328 328 Q_D(QAbstractBarSeries);
329 329 QList<QBarSet *> sets = barSets();
330 330 bool success = d->remove(sets);
331 331 if (success) {
332 332 emit barsetsRemoved(sets);
333 333 emit countChanged();
334 334 foreach (QBarSet* set, sets) {
335 335 delete set;
336 336 }
337 337 }
338 338 }
339 339
340 340 /*!
341 341 Returns number of sets in series.
342 342 */
343 343 int QAbstractBarSeries::count() const
344 344 {
345 345 Q_D(const QAbstractBarSeries);
346 346 return d->m_barSets.count();
347 347 }
348 348
349 349 /*!
350 350 Returns a list of sets in series. Keeps ownership of sets.
351 351 */
352 352 QList<QBarSet*> QAbstractBarSeries::barSets() const
353 353 {
354 354 Q_D(const QAbstractBarSeries);
355 355 return d->m_barSets;
356 356 }
357 357
358 358 /*!
359 359 Sets the visibility of labels in series to \a visible
360 360 */
361 361 void QAbstractBarSeries::setLabelsVisible(bool visible)
362 362 {
363 363 Q_D(QAbstractBarSeries);
364 364 if (d->m_labelsVisible != visible) {
365 365 d->setLabelsVisible(visible);
366 366 emit labelsVisibleChanged();
367 367 }
368 368 }
369 369
370 370 /*!
371 371 Returns the visibility of labels
372 372 */
373 373 bool QAbstractBarSeries::isLabelsVisible() const
374 374 {
375 375 Q_D(const QAbstractBarSeries);
376 376 return d->m_labelsVisible;
377 377 }
378 378
379 379 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
380 380
381 381 QAbstractBarSeriesPrivate::QAbstractBarSeriesPrivate(QAbstractBarSeries *q) :
382 382 QAbstractSeriesPrivate(q),
383 383 m_barWidth(0.5), // Default value is 50% of category width
384 384 m_labelsVisible(false),
385 385 m_visible(true)
386 386 {
387 387 }
388 388
389 389 int QAbstractBarSeriesPrivate::categoryCount() const
390 390 {
391 391 // No categories defined. return count of longest set.
392 392 int count = 0;
393 393 for (int i=0; i<m_barSets.count(); i++) {
394 394 if (m_barSets.at(i)->count() > count) {
395 395 count = m_barSets.at(i)->count();
396 396 }
397 397 }
398 398
399 399 return count;
400 400 }
401 401
402 402 void QAbstractBarSeriesPrivate::setBarWidth(qreal width)
403 403 {
404 404 if (width < 0.0) {
405 405 width = 0.0;
406 406 }
407 407 m_barWidth = width;
408 408 emit updatedLayout();
409 409 }
410 410
411 411 qreal QAbstractBarSeriesPrivate::barWidth() const
412 412 {
413 413 return m_barWidth;
414 414 }
415 415
416 416 QBarSet* QAbstractBarSeriesPrivate::barsetAt(int index)
417 417 {
418 418 return m_barSets.at(index);
419 419 }
420 420
421 421 void QAbstractBarSeriesPrivate::setVisible(bool visible)
422 422 {
423 423 m_visible = visible;
424 424 emit visibleChanged();
425 425 }
426 426
427 427 void QAbstractBarSeriesPrivate::setLabelsVisible(bool visible)
428 428 {
429 429 m_labelsVisible = visible;
430 430 emit labelsVisibleChanged(visible);
431 431 }
432 432
433 433 qreal QAbstractBarSeriesPrivate::min()
434 434 {
435 435 if (m_barSets.count() <= 0) {
436 436 return 0;
437 437 }
438 438 qreal min = INT_MAX;
439 439
440 440 for (int i = 0; i < m_barSets.count(); i++) {
441 441 int categoryCount = m_barSets.at(i)->count();
442 442 for (int j = 0; j < categoryCount; j++) {
443 443 qreal temp = m_barSets.at(i)->at(j);
444 444 if (temp < min)
445 445 min = temp;
446 446 }
447 447 }
448 448 return min;
449 449 }
450 450
451 451 qreal QAbstractBarSeriesPrivate::max()
452 452 {
453 453 if (m_barSets.count() <= 0) {
454 454 return 0;
455 455 }
456 456 qreal max = INT_MIN;
457 457
458 458 for (int i = 0; i < m_barSets.count(); i++) {
459 459 int categoryCount = m_barSets.at(i)->count();
460 460 for (int j = 0; j < categoryCount; j++) {
461 461 qreal temp = m_barSets.at(i)->at(j);
462 462 if (temp > max)
463 463 max = temp;
464 464 }
465 465 }
466 466
467 467 return max;
468 468 }
469 469
470 470 qreal QAbstractBarSeriesPrivate::valueAt(int set, int category)
471 471 {
472 472 if ((set < 0) || (set >= m_barSets.count())) {
473 473 // No set, no value.
474 474 return 0;
475 475 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
476 476 // No category, no value.
477 477 return 0;
478 478 }
479 479
480 480 return m_barSets.at(set)->at(category);
481 481 }
482 482
483 483 qreal QAbstractBarSeriesPrivate::percentageAt(int set, int category)
484 484 {
485 485 if ((set < 0) || (set >= m_barSets.count())) {
486 486 // No set, no value.
487 487 return 0;
488 488 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
489 489 // No category, no value.
490 490 return 0;
491 491 }
492 492
493 493 qreal value = m_barSets.at(set)->at(category);
494 494 qreal sum = categorySum(category);
495 495 if ( qFuzzyIsNull(sum) ) {
496 496 return 0;
497 497 }
498 498
499 499 return value / sum;
500 500 }
501 501
502 502 qreal QAbstractBarSeriesPrivate::categorySum(int category)
503 503 {
504 504 qreal sum(0);
505 505 int count = m_barSets.count(); // Count sets
506 506 for (int set = 0; set < count; set++) {
507 507 if (category < m_barSets.at(set)->count())
508 508 sum += m_barSets.at(set)->at(category);
509 509 }
510 510 return sum;
511 511 }
512 512
513 513 qreal QAbstractBarSeriesPrivate::absoluteCategorySum(int category)
514 514 {
515 515 qreal sum(0);
516 516 int count = m_barSets.count(); // Count sets
517 517 for (int set = 0; set < count; set++) {
518 518 if (category < m_barSets.at(set)->count())
519 519 sum += qAbs(m_barSets.at(set)->at(category));
520 520 }
521 521 return sum;
522 522 }
523 523
524 524 qreal QAbstractBarSeriesPrivate::maxCategorySum()
525 525 {
526 526 qreal max = INT_MIN;
527 527 int count = categoryCount();
528 528 for (int i = 0; i < count; i++) {
529 529 qreal sum = categorySum(i);
530 530 if (sum > max)
531 531 max = sum;
532 532 }
533 533 return max;
534 534 }
535 535
536 536 qreal QAbstractBarSeriesPrivate::minX()
537 537 {
538 538 if (m_barSets.count() <= 0) {
539 539 return 0;
540 540 }
541 541 qreal min = INT_MAX;
542 542
543 543 for (int i = 0; i < m_barSets.count(); i++) {
544 544 int categoryCount = m_barSets.at(i)->count();
545 545 for (int j = 0; j < categoryCount; j++) {
546 546 qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
547 547 if (temp < min)
548 548 min = temp;
549 549 }
550 550 }
551 551 return min;
552 552 }
553 553
554 554 qreal QAbstractBarSeriesPrivate::maxX()
555 555 {
556 556 if (m_barSets.count() <= 0) {
557 557 return 0;
558 558 }
559 559 qreal max = INT_MIN;
560 560
561 561 for (int i = 0; i < m_barSets.count(); i++) {
562 562 int categoryCount = m_barSets.at(i)->count();
563 563 for (int j = 0; j < categoryCount; j++) {
564 564 qreal temp = m_barSets.at(i)->d_ptr.data()->m_values.at(j).x();
565 565 if (temp > max)
566 566 max = temp;
567 567 }
568 568 }
569 569
570 570 return max;
571 571 }
572 572
573 573 qreal QAbstractBarSeriesPrivate::categoryTop(int category)
574 574 {
575 575 // Returns top (sum of all positive values) of category.
576 576 // Returns 0, if all values are negative
577 577 qreal top(0);
578 578 int count = m_barSets.count();
579 579 for (int set = 0; set < count; set++) {
580 580 if (category < m_barSets.at(set)->count()) {
581 581 qreal temp = m_barSets.at(set)->at(category);
582 582 if (temp > 0) {
583 583 top += temp;
584 584 }
585 585 }
586 586 }
587 587 return top;
588 588 }
589 589
590 590 qreal QAbstractBarSeriesPrivate::categoryBottom(int category)
591 591 {
592 592 // Returns bottom (sum of all negative values) of category
593 593 // Returns 0, if all values are positive
594 594 qreal bottom(0);
595 595 int count = m_barSets.count();
596 596 for (int set = 0; set < count; set++) {
597 597 if (category < m_barSets.at(set)->count()) {
598 598 qreal temp = m_barSets.at(set)->at(category);
599 599 if (temp < 0) {
600 600 bottom += temp;
601 601 }
602 602 }
603 603 }
604 604 return bottom;
605 605 }
606 606
607 607 qreal QAbstractBarSeriesPrivate::top()
608 608 {
609 609 // Returns top of all categories
610 610 qreal top(0);
611 611 int count = categoryCount();
612 612 for (int i=0; i<count; i++) {
613 613 qreal temp = categoryTop(i);
614 614 if (temp > top) {
615 615 top = temp;
616 616 }
617 617 }
618 618 return top;
619 619 }
620 620
621 621 qreal QAbstractBarSeriesPrivate::bottom()
622 622 {
623 623 // Returns bottom of all categories
624 624 qreal bottom(0);
625 625 int count = categoryCount();
626 626 for (int i=0; i<count; i++) {
627 627 qreal temp = categoryBottom(i);
628 628 if (temp < bottom) {
629 629 bottom = temp;
630 630 }
631 631 }
632 632 return bottom;
633 633 }
634 634
635 635
636 636 void QAbstractBarSeriesPrivate::scaleDomain(Domain& domain)
637 637 {
638 638 qreal minX(domain.minX());
639 639 qreal minY(domain.minY());
640 640 qreal maxX(domain.maxX());
641 641 qreal maxY(domain.maxY());
642 642
643 643 qreal seriesMinX = this->minX();
644 644 qreal seriesMaxX = this->maxX();
645 645 qreal y = max();
646 646 minX = qMin(minX, seriesMinX - (qreal)0.5);
647 647 minY = qMin(minY, y);
648 648 maxX = qMax(maxX, seriesMaxX + (qreal)0.5);
649 649 maxY = qMax(maxY, y);
650 650
651 651 domain.setRange(minX,maxX,minY,maxY);
652 652 }
653 653
654 654 ChartElement* QAbstractBarSeriesPrivate::createGraphics(ChartPresenter* presenter)
655 655 {
656 656 Q_UNUSED(presenter);
657 657 qWarning() << "QAbstractBarSeriesPrivate::createGraphics called";
658 658 return 0;
659 659 }
660 660
661 661 QList<LegendMarker*> QAbstractBarSeriesPrivate::createLegendMarker(QLegend* legend)
662 662 {
663 663 Q_Q(QAbstractBarSeries);
664 664 QList<LegendMarker*> markers;
665 665 foreach(QBarSet* set, q->barSets()) {
666 666 BarLegendMarker* marker = new BarLegendMarker(q,set,legend);
667 667 markers << marker;
668 668 }
669 669
670 670 return markers;
671 671 }
672 672
673 673 bool QAbstractBarSeriesPrivate::append(QBarSet *set)
674 674 {
675 675 Q_Q(QAbstractBarSeries);
676 676 if ((m_barSets.contains(set)) || (set == 0)) {
677 677 // Fail if set is already in list or set is null.
678 678 return false;
679 679 }
680
680 681 m_barSets.append(set);
681 682 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
682 683 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
683 684 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
684 emit restructuredBars(); // this notifies barchartitem
685 if (m_dataset) {
686 m_dataset->updateSeries(q); // this notifies legend
687 }
685
686 emit restructuredBars(); // this notifies barchartitem
687 emit legendPropertiesUpdated(q); // this notifies legend
688 688 return true;
689 689 }
690 690
691 691 bool QAbstractBarSeriesPrivate::remove(QBarSet *set)
692 692 {
693 693 Q_Q(QAbstractBarSeries);
694 694 if (!m_barSets.contains(set)) {
695 695 // Fail if set is not in list
696 696 return false;
697 697 }
698
698 699 m_barSets.removeOne(set);
699 700 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
700 701 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
701 702 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
703
702 704 emit restructuredBars(); // this notifies barchartitem
703 if (m_dataset) {
704 m_dataset->updateSeries(q); // this notifies legend
705 }
705 emit legendPropertiesUpdated(q);
706 706 return true;
707 707 }
708 708
709 709 bool QAbstractBarSeriesPrivate::append(QList<QBarSet* > sets)
710 710 {
711 711 Q_Q(QAbstractBarSeries);
712 712 foreach (QBarSet* set, sets) {
713 713 if ((set == 0) || (m_barSets.contains(set))) {
714 714 // Fail if any of the sets is null or is already appended.
715 715 return false;
716 716 }
717 717 if (sets.count(set) != 1) {
718 718 // Also fail if same set is more than once in given list.
719 719 return false;
720 720 }
721 721 }
722 722
723 723 foreach (QBarSet* set, sets) {
724 724 m_barSets.append(set);
725 725 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
726 726 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
727 727 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
728 728 }
729
729 730 emit restructuredBars(); // this notifies barchartitem
730 if (m_dataset) {
731 m_dataset->updateSeries(q); // this notifies legend
732 }
731 emit legendPropertiesUpdated(q); // this notifies legend
733 732 return true;
734 733 }
735 734
736 735 bool QAbstractBarSeriesPrivate::remove(QList<QBarSet* > sets)
737 736 {
738 737 Q_Q(QAbstractBarSeries);
739 738 if (sets.count() == 0) {
740 739 return false;
741 740 }
742 741 foreach (QBarSet* set, sets) {
743 742 if ((set == 0) || (!m_barSets.contains(set))) {
744 743 // Fail if any of the sets is null or is not in series
745 744 return false;
746 745 }
747 746 if (sets.count(set) != 1) {
748 747 // Also fail if same set is more than once in given list.
749 748 return false;
750 749 }
751 750 }
752 751
753 752 foreach (QBarSet* set, sets) {
754 753 m_barSets.removeOne(set);
755 754 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
756 755 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
757 756 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
758 757 }
759 758
760 759 emit restructuredBars(); // this notifies barchartitem
761 if (m_dataset) {
762 m_dataset->updateSeries(q); // this notifies legend
763 }
760 emit legendPropertiesUpdated(q);
764 761 return true;
765 762 }
766 763
767 764 bool QAbstractBarSeriesPrivate::insert(int index, QBarSet *set)
768 765 {
769 766 Q_Q(QAbstractBarSeries);
770 767 if ((m_barSets.contains(set)) || (set == 0)) {
771 768 // Fail if set is already in list or set is null.
772 769 return false;
773 770 }
771
774 772 m_barSets.insert(index, set);
775 773 QObject::connect(set->d_ptr.data(), SIGNAL(updatedLayout()), this, SIGNAL(updatedLayout()));
776 774 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
777 775 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
776
778 777 emit restructuredBars(); // this notifies barchartitem
779 if (m_dataset) {
780 m_dataset->updateSeries(q); // this notifies legend
781 }
778 emit legendPropertiesUpdated(q);
782 779 return true;
783 780 }
784 781
785 782 void QAbstractBarSeriesPrivate::initializeAxis(QAbstractAxis* axis)
786 783 {
787 784 Q_Q(QAbstractBarSeries);
788 785
789 786 if(axis->type()==QAbstractAxis::AxisTypeBarCategory) {
790 787
791 788 switch(q->type()) {
792 789
793 790 case QAbstractSeries::SeriesTypeHorizontalBar:
794 791 case QAbstractSeries::SeriesTypeHorizontalPercentBar:
795 792 case QAbstractSeries::SeriesTypeHorizontalStackedBar: {
796 793
797 794 if(axis->orientation()==Qt::Vertical)
798 795 {
799 796 populateCategories(qobject_cast<QBarCategoryAxis*>(axis));
800 797 }
801 798 break;
802 799 }
803 800 case QAbstractSeries::SeriesTypeBar:
804 801 case QAbstractSeries::SeriesTypePercentBar:
805 802 case QAbstractSeries::SeriesTypeStackedBar: {
806 803
807 804 if(axis->orientation()==Qt::Horizontal)
808 805 {
809 806 populateCategories(qobject_cast<QBarCategoryAxis*>(axis));
810 807 }
811 808 break;
812 809 }
813 810 default:
814 811 qWarning()<<"Unexpected series type";
815 812 break;
816 813
817 814 }
818 815 }
819 816 }
820 817
821 818 QAbstractAxis::AxisType QAbstractBarSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
822 819 {
823 820 Q_Q(const QAbstractBarSeries);
824 821
825 822 switch(q->type()) {
826 823
827 824 case QAbstractSeries::SeriesTypeHorizontalBar:
828 825 case QAbstractSeries::SeriesTypeHorizontalPercentBar:
829 826 case QAbstractSeries::SeriesTypeHorizontalStackedBar: {
830 827
831 828 if(orientation==Qt::Vertical)
832 829 {
833 830 return QAbstractAxis::AxisTypeBarCategory;
834 831 }
835 832 break;
836 833 }
837 834 case QAbstractSeries::SeriesTypeBar:
838 835 case QAbstractSeries::SeriesTypePercentBar:
839 836 case QAbstractSeries::SeriesTypeStackedBar: {
840 837
841 838 if(orientation==Qt::Horizontal)
842 839 {
843 840 return QAbstractAxis::AxisTypeBarCategory;
844 841 }
845 842 break;
846 843 }
847 844 default:
848 845 qWarning()<<"Unexpected series type";
849 846 break;
850 847
851 848 }
852 849 return QAbstractAxis::AxisTypeValue;
853 850
854 851 }
855 852
856 853 void QAbstractBarSeriesPrivate::populateCategories(QBarCategoryAxis* axis)
857 854 {
858 855 QStringList categories;
859 856 if(axis->categories().isEmpty()) {
860 857 for (int i(1); i < categoryCount()+1; i++)
861 858 categories << QString::number(i);
862 859 axis->append(categories);
863 860 }
864 861 }
865 862
866 863 #include "moc_qabstractbarseries.cpp"
867 864 #include "moc_qabstractbarseries_p.cpp"
868 865
869 866
870 867 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,496 +1,496
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "chartdataset_p.h"
22 22 #include "qchart.h"
23 23 #include "qvalueaxis.h"
24 24 #include "qbarcategoryaxis.h"
25 25 #include "qvalueaxis_p.h"
26 26 #include "qcategoryaxis.h"
27 27 #include "qabstractseries_p.h"
28 28 #include "qabstractbarseries.h"
29 29 #include "qstackedbarseries.h"
30 30 #include "qpercentbarseries.h"
31 31 #include "qpieseries.h"
32 32
33 33 #ifndef QT_ON_ARM
34 34 #include "qdatetimeaxis.h"
35 35 #endif
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 ChartDataSet::ChartDataSet(QChart *parent):QObject(parent)
40 40 {
41 41
42 42 }
43 43
44 44 ChartDataSet::~ChartDataSet()
45 45 {
46 46 removeAllSeries();
47 47 }
48 48
49 49 void ChartDataSet::addSeries(QAbstractSeries* series)
50 50 {
51 51 Domain* domain = m_seriesDomainMap.value(series);
52 52
53 53 if(domain) {
54 54 qWarning() << "Can not add series. Series already on the chart";
55 55 return;
56 56 }
57 57
58 58 domain = new Domain(series);
59 59 m_seriesDomainMap.insert(series,domain);
60 60 series->d_ptr->scaleDomain(*domain);
61 61
62 62 createSeriesIndex(series);
63 63
64 64 series->setParent(this); // take ownership
65 65 series->d_ptr->m_chart = qobject_cast<QChart*>(parent());
66 66 series->d_ptr->m_dataset = this;
67 67
68 68 emit seriesAdded(series,domain);
69 69
70 70 }
71 71
72 72 void ChartDataSet::removeSeries(QAbstractSeries* series)
73 73 {
74 74
75 75 if(!m_seriesDomainMap.contains(series)) {
76 76 qWarning()<<"Can not remove series. Series not found on the chart.";
77 77 return;
78 78 }
79 79
80 80 emit seriesRemoved(series);
81 81
82 82 Domain* domain = m_seriesDomainMap.take(series);
83 83 delete domain;
84 84 domain = 0;
85 85
86 86 removeSeriesIndex(series);
87 87
88 88 series->setParent(0);
89 89 series->d_ptr->m_chart = 0;
90 90 series->d_ptr->m_dataset = 0;
91 91
92 92 removeAxes(series);
93 93 }
94 94
95 95
96 96
97 97 void ChartDataSet::createSeriesIndex(QAbstractSeries* series)
98 98 {
99 99 QMapIterator<int, QAbstractSeries*> i(m_indexSeriesMap);
100 100
101 101 int key=0;
102 102 while (i.hasNext()) {
103 103 i.next();
104 104 if(i.key()!=key) {
105 105 break;
106 106 }
107 107 key++;
108 108 }
109 109
110 110 m_indexSeriesMap.insert(key,series);
111 111 }
112 112
113 113 void ChartDataSet::removeSeriesIndex(QAbstractSeries* series)
114 114 {
115 115 int key = seriesIndex(series);
116 116 Q_ASSERT(key!=-1);
117 117 m_indexSeriesMap.remove(key);
118 118 }
119 119
120 120 void ChartDataSet::createDefaultAxes()
121 121 {
122 122 if (m_seriesDomainMap.isEmpty())
123 123 return;
124 124
125 125 QAbstractAxis::AxisTypes typeX(0);
126 126 QAbstractAxis::AxisTypes typeY(0);
127 127
128 128 // Remove possibly existing axes
129 129 QMapIterator<QAbstractSeries*, Domain*> i(m_seriesDomainMap);
130 130 while (i.hasNext()) {
131 131 i.next();
132 132 removeAxes(i.key());
133 133 }
134 134
135 135 i.toFront();
136 136
137 137 // Select the required axis x and axis y types based on the types of the current series
138 138 while (i.hasNext()) {
139 139 i.next();
140 140
141 141 QAbstractAxis* axisX = m_seriesAxisXMap.value(i.key());
142 142 QAbstractAxis* axisY = m_seriesAxisYMap.value(i.key());
143 143 if(axisX) typeX&=axisX->type();
144 144 else typeX|=i.key()->d_ptr->defaultAxisType(Qt::Horizontal);
145 145 if(axisY) typeY&=axisY->type();
146 146 else typeY|=i.key()->d_ptr->defaultAxisType(Qt::Vertical);
147 147 }
148 148
149 149 // Create the axes of the types selected
150 150 createAxes(typeX, Qt::Horizontal);
151 151 createAxes(typeY, Qt::Vertical);
152 152 }
153 153
154 154 void ChartDataSet::createAxes(QAbstractAxis::AxisTypes type, Qt::Orientation orientation)
155 155 {
156 156 QMapIterator<QAbstractSeries*, Domain*> i(m_seriesDomainMap);
157 157
158 158 // TODO: Add a descriptive comment of what happens here
159 159 if (type.testFlag(QAbstractAxis::AxisTypeValue) && type.testFlag(QAbstractAxis::AxisTypeBarCategory)) {
160 160 while (i.hasNext()) {
161 161 i.next();
162 162 QAbstractAxis* axis = createAxis(i.key()->d_ptr->defaultAxisType(orientation), orientation);
163 163 if (axis) {
164 164 initializeAxis(axis, i.key());
165 165 emit axisAdded(axis, i.value());
166 166 }
167 167 }
168 168 } else if (!type.testFlag(QAbstractAxis::AxisTypeNoAxis)) {
169 169 QAbstractAxis* axis = createAxis(QAbstractAxis::AxisType(int(type)), orientation);
170 170 i.toFront();
171 171 while (i.hasNext()) {
172 172 i.next();
173 173 initializeAxis(axis,i.key());
174 174 }
175 175 emit axisAdded(axis,i.value());
176 176 }
177 177 }
178 178
179 179 QAbstractAxis* ChartDataSet::createAxis(QAbstractAxis::AxisType type, Qt::Orientation orientation)
180 180 {
181 181 QAbstractAxis* axis = 0;
182 182
183 183 switch(type) {
184 184 case QAbstractAxis::AxisTypeValue:
185 185 axis = new QValueAxis(this);
186 186 break;
187 187 case QAbstractAxis::AxisTypeBarCategory:
188 188 axis = new QBarCategoryAxis(this);
189 189 break;
190 190 case QAbstractAxis::AxisTypeCategory:
191 191 axis = new QCategoryAxis(this);
192 192 break;
193 193 #ifndef Q_WS_QWS
194 194 case QAbstractAxis::AxisTypeDateTime:
195 195 axis = new QDateTimeAxis(this);
196 196 break;
197 197 #endif
198 198 default:
199 199 axis = 0;
200 200 break;
201 201 }
202 202
203 203 if(axis)
204 204 axis->d_ptr->setOrientation(orientation);
205 205
206 206 return axis;
207 207 }
208 208
209 209 void ChartDataSet::initializeAxis(QAbstractAxis* axis,QAbstractSeries* series)
210 210 {
211 211 Domain* domain = m_seriesDomainMap.value(series);
212 212 axis->d_ptr->m_dataset = this;
213 213 series->d_ptr->initializeAxis(axis);
214 214 axis->d_ptr->intializeDomain(domain);
215 215 if(axis->orientation()==Qt::Horizontal) {
216 216 QObject::connect(axis->d_ptr.data(),SIGNAL(updated()),domain,SLOT(handleAxisUpdated()));
217 217 QObject::connect(domain,SIGNAL(updated()),axis->d_ptr.data(),SLOT(handleDomainUpdated()));
218 218 m_seriesAxisXMap.insert(series,axis);
219 219 }
220 220 else {
221 221 QObject::connect(axis->d_ptr.data(),SIGNAL(updated()),domain,SLOT(handleAxisUpdated()));
222 222 QObject::connect(domain,SIGNAL(updated()),axis->d_ptr.data(),SLOT(handleDomainUpdated()));
223 223 m_seriesAxisYMap.insert(series,axis);
224 224 }
225 225 axis->d_ptr->emitUpdated();
226 226 }
227 227
228 228 void ChartDataSet::removeAxes(QAbstractSeries* series)
229 229 {
230 230 QAbstractAxis* axisX = m_seriesAxisXMap.take(series);
231 231
232 232 if(axisX) {
233 233 QList<QAbstractAxis*> axesX = m_seriesAxisXMap.values();
234 234 int x = axesX.indexOf(axisX);
235 235
236 236 if(x==-1) {
237 237 emit axisRemoved(axisX);
238 238 axisX->d_ptr->m_dataset=0;
239 239 axisX->deleteLater();
240 240 }
241 241 }
242 242
243 243 QAbstractAxis* axisY = m_seriesAxisYMap.take(series);
244 244
245 245 if(axisY) {
246 246 QList<QAbstractAxis*> axesY = m_seriesAxisYMap.values();
247 247
248 248 int y = axesY.indexOf(axisY);
249 249
250 250 if(y==-1) {
251 251 emit axisRemoved(axisY);
252 252 axisY->d_ptr->m_dataset=0;
253 253 axisY->deleteLater();
254 254 }
255 255 }
256 256 }
257 257
258 258 void ChartDataSet::removeAxis(QAbstractAxis* axis)
259 259 {
260 260 if(!axis->d_ptr->m_dataset) {
261 261 qWarning()<<"UnBound axis found !";
262 262 return;
263 263 }
264 264
265 265 QMap<QAbstractSeries*, QAbstractAxis*> *seriesAxisMap;
266 266
267 267 if(axis->orientation()==Qt::Vertical) {
268 268 seriesAxisMap= &m_seriesAxisYMap;
269 269 }
270 270 else {
271 271 seriesAxisMap= &m_seriesAxisXMap;
272 272 }
273 273
274 274 QMapIterator<QAbstractSeries*, QAbstractAxis*> i(*seriesAxisMap);
275 275
276 276 while (i.hasNext()) {
277 277 i.next();
278 278 if(i.value()==axis) {
279 279 removeSeries(i.key());
280 280 }
281 281 }
282 282 }
283 283
284 284 void ChartDataSet::removeAllSeries()
285 285 {
286 286 QList<QAbstractSeries*> series = m_seriesDomainMap.keys();
287 287 foreach(QAbstractSeries *s , series) {
288 288 removeSeries(s);
289 289 }
290 290
291 291 Q_ASSERT(m_seriesAxisXMap.count()==0);
292 292 Q_ASSERT(m_seriesAxisXMap.count()==0);
293 293 Q_ASSERT(m_seriesDomainMap.count()==0);
294 294
295 295 qDeleteAll(series);
296 296 }
297 297
298 298 void ChartDataSet::zoomInDomain(const QRectF& rect, const QSizeF& size)
299 299 {
300 300 //for performance reasons block, signals and scale "full" domain one by one. Gives twice less screen updates
301 301
302 302
303 303 blockAxisSignals(true);
304 304
305 305 QMapIterator<QAbstractSeries*, Domain*> i(m_seriesDomainMap);
306 306
307 307 while (i.hasNext()) {
308 308 i.next();
309 309 i.value()->zoomIn(rect,size);
310 310 }
311 311
312 312 blockAxisSignals(false);
313 313
314 314 }
315 315
316 316 void ChartDataSet::zoomOutDomain(const QRectF& rect, const QSizeF& size)
317 317 {
318 318 //for performance reasons block, signals and scale "full" domain one by one. Gives twice less screen updates
319 319
320 320 blockAxisSignals(true);
321 321
322 322 QMapIterator<QAbstractSeries*, Domain*> i(m_seriesDomainMap);
323 323
324 324 while (i.hasNext()) {
325 325 i.next();
326 326 i.value()->zoomOut(rect,size);
327 327 }
328 328
329 329 blockAxisSignals(false);
330 330 }
331 331
332 332 void ChartDataSet::blockAxisSignals(bool enabled)
333 333 {
334 334 QMapIterator<QAbstractSeries*, Domain*> i(m_seriesDomainMap);
335 335 while (i.hasNext()) {
336 336 i.next();
337 337 QAbstractAxis* axisX = m_seriesAxisXMap.value(i.key());
338 338 QAbstractAxis* axisY = m_seriesAxisYMap.value(i.key());
339 339 if(axisX) {
340 340 axisX->d_ptr->blockSignals(enabled);
341 341 if(!enabled) {
342 342 axisX->d_ptr->setDirty(false);
343 343 axisX->d_ptr->emitUpdated();
344 344 }
345 345 }
346 346 if(axisY) {
347 347 axisY->d_ptr->blockSignals(enabled);
348 348 if(!enabled) {
349 349 axisY->d_ptr->setDirty(false);
350 350 axisY->d_ptr->emitUpdated();
351 351 }
352 352 }
353 353 }
354 354 }
355 355
356 356 int ChartDataSet::seriesCount(QAbstractSeries::SeriesType type)
357 357 {
358 358 int count=0;
359 359 QMapIterator<QAbstractSeries*, Domain*> i(m_seriesDomainMap);
360 360 while (i.hasNext()) {
361 361 i.next();
362 362 if(i.key()->type()==type) count++;
363 363 }
364 364 return count;
365 365 }
366 366
367 367 int ChartDataSet::seriesIndex(QAbstractSeries *series)
368 368 {
369 369 QMapIterator<int, QAbstractSeries*> i(m_indexSeriesMap);
370 370 while (i.hasNext()) {
371 371 i.next();
372 372 if (i.value() == series)
373 373 return i.key();
374 374 }
375 375 return -1;
376 376 }
377 377
378 378 QAbstractAxis* ChartDataSet::axisX(QAbstractSeries *series) const
379 379 {
380 380 if(series == 0) {
381 381
382 382 QMapIterator<QAbstractSeries*, QAbstractAxis *> i(m_seriesAxisXMap);
383 383
384 384 while (i.hasNext()) {
385 385 i.next();
386 386 if(i.value()->isVisible()) return i.value();
387 387 }
388 388 return 0;
389 389 }
390 390 return m_seriesAxisXMap.value(series);
391 391 }
392 392
393 393 QAbstractAxis* ChartDataSet::axisY(QAbstractSeries *series) const
394 394 {
395 395 if(series == 0) {
396 396 QMapIterator<QAbstractSeries*, QAbstractAxis *> i(m_seriesAxisYMap);
397 397
398 398 while (i.hasNext()) {
399 399 i.next();
400 400 if(i.value()->isVisible()) return i.value();
401 401 }
402 402 return 0;
403 403 }
404 404 return m_seriesAxisYMap.value(series);
405 405 }
406 406
407 407 void ChartDataSet::setAxis(QAbstractSeries *series, QAbstractAxis *axis, Qt::Orientation orientation)
408 408 {
409 409 Q_ASSERT(axis);
410 410
411 411 if(!series) {
412 412 qWarning() << "Series not found on the chart.";
413 413 return;
414 414 }
415 415
416 416 Domain* domain = m_seriesDomainMap.value(series);
417 417
418 418 if(!domain) {
419 419 qWarning() << "Series not found on the chart.";
420 420 return;
421 421 }
422 422
423 423 if(orientation==Qt::Horizontal && axis->orientation()==Qt::Vertical) {
424 424 qWarning()<<"Axis already defined as axis Y";
425 425 return;
426 426 }
427 427
428 428 if(orientation==Qt::Vertical && axis->orientation()==Qt::Horizontal) {
429 429 qWarning()<<"Axis already defined as axis X";
430 430 return;
431 431 }
432 432
433 433 axis->d_ptr->setOrientation(orientation);
434 434
435 435 QMap<QAbstractSeries*, QAbstractAxis*> *seriesAxisMap;
436 436
437 437 if(orientation==Qt::Vertical) {
438 438 seriesAxisMap= &m_seriesAxisYMap;
439 439 }else{
440 440 seriesAxisMap= &m_seriesAxisXMap;
441 441 }
442 442
443 443 if (seriesAxisMap->value(series) == axis) {
444 444 qWarning() << "The axis already set for the series";
445 445 return;
446 446 }
447 447
448 448 QAbstractAxis *oldAxis = seriesAxisMap->take(series);
449 449 QList<QAbstractAxis*> axes = seriesAxisMap->values();
450 450 if(oldAxis) {
451 451 if(axes.indexOf(oldAxis)==-1) {
452 452 emit axisRemoved(oldAxis);
453 453 oldAxis->disconnect();
454 454 QObject::disconnect(domain,0,oldAxis,0);
455 455 oldAxis->d_ptr->m_dataset=0;
456 456 oldAxis->deleteLater();
457 457 }
458 458 }
459 459
460 460 if(axes.indexOf(axis)==-1) {
461 461 initializeAxis(axis,series);
462 462 emit axisAdded(axis,domain);
463 463 }else{
464 464 initializeAxis(axis,series);
465 465 }
466 466 }
467 467
468 468 Domain* ChartDataSet::domain(QAbstractSeries *series) const
469 469 {
470 470 return m_seriesDomainMap.value(series);
471 471 }
472 472
473 473 void ChartDataSet::scrollDomain(qreal dx,qreal dy,const QSizeF& size)
474 474 {
475 475 blockAxisSignals(true);
476 476 QMapIterator<QAbstractSeries*, Domain*> i(m_seriesDomainMap);
477 477 while (i.hasNext()) {
478 478 i.next();
479 479 i.value()->move(dx,dy,size);
480 480 }
481 481 blockAxisSignals(false);
482 482 }
483 483
484 484 QList<QAbstractSeries*> ChartDataSet::series() const
485 485 {
486 486 return m_seriesDomainMap.keys();
487 487 }
488
488 /*
489 489 void ChartDataSet::updateSeries(QAbstractSeries *series)
490 490 {
491 491 emit seriesUpdated(series);
492 492 }
493
493 */
494 494 #include "moc_chartdataset_p.cpp"
495 495
496 496 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,98 +1,98
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 CHARTDATASET_P_H
31 31 #define CHARTDATASET_P_H
32 32
33 33 #include "qabstractseries.h"
34 34 #include "domain_p.h"
35 35 #include "qabstractaxis_p.h"
36 36 #include <QVector>
37 37
38 38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 39
40 40 class QAbstractAxis;
41 41
42 42 class QTCOMMERCIALCHART_AUTOTEST_EXPORT ChartDataSet : public QObject
43 43 {
44 44 Q_OBJECT
45 45 public:
46 46 ChartDataSet(QChart* parent=0);
47 47 virtual ~ChartDataSet();
48 48
49 49 void addSeries(QAbstractSeries* series);
50 50 void removeSeries(QAbstractSeries* series);
51 51 void removeAllSeries();
52 void updateSeries(QAbstractSeries* series);
52 // void updateSeries(QAbstractSeries* series);
53 53
54 54 void zoomInDomain(const QRectF& rect, const QSizeF& size);
55 55 void zoomOutDomain(const QRectF& rect, const QSizeF& size);
56 56 void scrollDomain(qreal dx,qreal dy,const QSizeF& size);
57 57
58 58 int seriesCount(QAbstractSeries::SeriesType type);
59 59 int seriesIndex(QAbstractSeries *series);
60 60
61 61 QAbstractAxis* axisX(QAbstractSeries *series) const;
62 62 QAbstractAxis* axisY(QAbstractSeries *series) const;
63 63
64 64 void setAxis(QAbstractSeries *series, QAbstractAxis *axis, Qt::Orientation orientation);
65 65
66 66 QList<QAbstractSeries*> series() const;
67 67 Domain* domain(QAbstractSeries *series) const;
68 68
69 69 void removeAxis(QAbstractAxis* axis);
70 70 void createDefaultAxes();
71 71
72 72 Q_SIGNALS:
73 73 void seriesAdded(QAbstractSeries* series, Domain* domain);
74 74 void seriesRemoved(QAbstractSeries* series);
75 void seriesUpdated(QAbstractSeries* series);
75 // void seriesUpdated(QAbstractSeries* series);
76 76 void axisAdded(QAbstractAxis* axis,Domain* domain);
77 77 void axisRemoved(QAbstractAxis* axis);
78 78
79 79 private:
80 80 void calculateDomain(QAbstractSeries* series,Domain* domain);
81 81 void createAxes(QAbstractAxis::AxisTypes type,Qt::Orientation orientation);
82 82 QAbstractAxis* createAxis(QAbstractAxis::AxisType type,Qt::Orientation orientation);
83 83 void initializeAxis(QAbstractAxis* axis,QAbstractSeries* series);
84 84 void removeAxes(QAbstractSeries* series);
85 85 void blockAxisSignals(bool enabled);
86 86 void createSeriesIndex(QAbstractSeries* series);
87 87 void removeSeriesIndex(QAbstractSeries* series);
88 88
89 89 private:
90 90 QMap<QAbstractSeries*, QAbstractAxis*> m_seriesAxisXMap;
91 91 QMap<QAbstractSeries*, QAbstractAxis*> m_seriesAxisYMap;
92 92 QMap<QAbstractSeries*, Domain*> m_seriesDomainMap;
93 93 QMap<int, QAbstractSeries*> m_indexSeriesMap;
94 94 };
95 95
96 96 QTCOMMERCIALCHART_END_NAMESPACE
97 97
98 98 #endif /* CHARTENGINE_P_H */
@@ -1,540 +1,522
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "qlegend.h"
22 22 #include "qlegend_p.h"
23 23 #include "qabstractseries.h"
24 24 #include "qabstractseries_p.h"
25 25 #include "qchart_p.h"
26 26 #include "legendlayout_p.h"
27 27 #include "legendmarker_p.h"
28 28 #include "qxyseries.h"
29 29 #include "qlineseries.h"
30 30 #include "qareaseries.h"
31 31 #include "qscatterseries.h"
32 32 #include "qsplineseries.h"
33 33 #include "qabstractbarseries.h"
34 34 #include "qstackedbarseries.h"
35 35 #include "qpercentbarseries.h"
36 36 #include "qbarset.h"
37 37 #include "qpieseries.h"
38 38 #include "qpieseries_p.h"
39 39 #include "qpieslice.h"
40 40 #include "chartpresenter_p.h"
41 41 #include <QPainter>
42 42 #include <QPen>
43 43 #include <QTimer>
44 44 #include <QGraphicsLayout>
45 45 #include <QGraphicsSceneEvent>
46 46
47 47 QTCOMMERCIALCHART_BEGIN_NAMESPACE
48 48
49 49 /*!
50 50 \class QLegend
51 51 \brief Legend object
52 52 \mainclass
53 53
54 54 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
55 55 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
56 56 handle the drawing manually.
57 57 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
58 58
59 59 \image examples_percentbarchart_legend.png
60 60
61 61 \sa QChart
62 62 */
63 63 /*!
64 64 \qmlclass Legend QLegend
65 65 \brief Legend is part of QtCommercial Chart QML API.
66 66
67 67 Legend is a graphical object, whics displays legend of the chart. Legend state is updated by ChartView, when
68 68 series have been changed. Legend is used via ChartView class. For example:
69 69 \code
70 70 ChartView {
71 71 legend.visible: true
72 72 legend.alignment: Qt.AlignBottom
73 73 // Add a few series...
74 74 }
75 75 \endcode
76 76
77 77 \image examples_percentbarchart_legend.png
78 78 */
79 79
80 80 /*!
81 81 \property QLegend::alignment
82 82 \brief The alignment of the legend.
83 83
84 84 Legend paints on the defined position in the chart. The following alignments are supported:
85 85 Qt::AlignTop, Qt::AlignBottom, Qt::AlignLeft, Qt::AlignRight. If you set more than one flag the result is undefined.
86 86 */
87 87 /*!
88 88 \qmlproperty Qt.Alignment Legend::alignment
89 89 \brief The alignment of the legend.
90 90
91 91 Legend paints on the defined position in the chart. The following alignments are supported:
92 92 Qt.AlignTop, Qt.AlignBottom, Qt.AlignLeft, Qt.AlignRight. If you set more than one flag the result is undefined.
93 93 */
94 94
95 95 /*!
96 96 \property QLegend::backgroundVisible
97 97 Whether the legend background is visible or not.
98 98 */
99 99 /*!
100 100 \qmlproperty bool Legend::backgroundVisible
101 101 Whether the legend background is visible or not.
102 102 */
103 103
104 104 /*!
105 105 \property QLegend::color
106 106 The color of the legend, i.e. the background (brush) color. Note that if you change the color
107 107 of the legend, the style of the legend brush is set to Qt::SolidPattern.
108 108 */
109 109 /*!
110 110 \qmlproperty color Legend::color
111 111 The color of the legend, i.e. the background (brush) color.
112 112 */
113 113
114 114 /*!
115 115 \property QLegend::borderColor
116 116 The border color of the legend, i.e. the line color.
117 117 */
118 118 /*!
119 119 \qmlproperty color Legend::borderColor
120 120 The border color of the legend, i.e. the line color.
121 121 */
122 122
123 123 /*!
124 124 \property QLegend::font
125 125 The font of markers used by legend
126 126 */
127 127 /*!
128 128 \qmlproperty color Legend::font
129 129 The font of markers used by legend
130 130 */
131 131
132 132 /*!
133 133 \property QLegend::labelColor
134 134 The color of brush used to draw labels.
135 135 */
136 136 /*!
137 137 \qmlproperty color QLegend::labelColor
138 138 The color of brush used to draw labels.
139 139 */
140 140
141 141 /*!
142 142 \fn void QLegend::backgroundVisibleChanged(bool)
143 143 The visibility of the legend background changed to \a visible.
144 144 */
145 145
146 146 /*!
147 147 \fn void QLegend::colorChanged(QColor)
148 148 The color of the legend background changed to \a color.
149 149 */
150 150
151 151 /*!
152 152 \fn void QLegend::borderColorChanged(QColor)
153 153 The border color of the legend background changed to \a color.
154 154 */
155 155
156 156 /*!
157 157 \fn void QLegend::fontChanged(QFont)
158 158 The font of markers of the legend changed to \a font.
159 159 */
160 160
161 161 /*!
162 162 \fn void QLegend::labelColorChanged(QColor color)
163 163 This signal is emitted when the color of brush used to draw labels has changed to \a color.
164 164 */
165 165
166 166 /*!
167 167 Constructs the legend object and sets the parent to \a parent
168 168 */
169 169
170 170 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
171 171 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter,chart,this))
172 172 {
173 173 setZValue(ChartPresenter::LegendZValue);
174 174 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
175 175 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesAdded(QAbstractSeries*,Domain*)),d_ptr.data(),SLOT(handleSeriesAdded(QAbstractSeries*,Domain*)));
176 176 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesRemoved(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesRemoved(QAbstractSeries*)));
177 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesUpdated(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesUpdated(QAbstractSeries*)));
177 // QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesUpdated(QAbstractSeries*)),d_ptr.data(),SLOT(handleSeriesUpdated(QAbstractSeries*)));
178 178 setLayout(d_ptr->m_layout);
179 179 }
180 180
181 181 /*!
182 182 Destroys the legend object. Legend is always owned by a QChart, so an application should never call this.
183 183 */
184 184 QLegend::~QLegend()
185 185 {
186 186 }
187 187
188 188 /*!
189 189 \internal
190 190 */
191 191 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
192 192 {
193 193 Q_UNUSED(option)
194 194 Q_UNUSED(widget)
195 195
196 196 if(!d_ptr->m_backgroundVisible) return;
197 197
198 198 painter->setOpacity(opacity());
199 199 painter->setPen(d_ptr->m_pen);
200 200 painter->setBrush(d_ptr->m_brush);
201 201 painter->drawRoundRect(rect(),d_ptr->roundness(rect().width()),d_ptr->roundness(rect().height()));
202 202
203 203 }
204 204
205 205
206 206 /*!
207 207 Sets the \a brush of legend. Brush affects the background of legend.
208 208 */
209 209 void QLegend::setBrush(const QBrush &brush)
210 210 {
211 211 if (d_ptr->m_brush != brush) {
212 212 d_ptr->m_brush = brush;
213 213 update();
214 214 emit colorChanged(brush.color());
215 215 }
216 216 }
217 217
218 218 /*!
219 219 Returns the brush used by legend.
220 220 */
221 221 QBrush QLegend::brush() const
222 222 {
223 223 return d_ptr->m_brush;
224 224 }
225 225
226 226 void QLegend::setColor(QColor color)
227 227 {
228 228 QBrush b = d_ptr->m_brush;
229 229 if (b.style() != Qt::SolidPattern || b.color() != color) {
230 230 b.setStyle(Qt::SolidPattern);
231 231 b.setColor(color);
232 232 setBrush(b);
233 233 }
234 234 }
235 235
236 236 QColor QLegend::color()
237 237 {
238 238 return d_ptr->m_brush.color();
239 239 }
240 240
241 241 /*!
242 242 Sets the \a pen of legend. Pen affects the legend borders.
243 243 */
244 244 void QLegend::setPen(const QPen &pen)
245 245 {
246 246 if (d_ptr->m_pen != pen) {
247 247 d_ptr->m_pen = pen;
248 248 update();
249 249 emit borderColorChanged(pen.color());
250 250 }
251 251 }
252 252
253 253 /*!
254 254 Returns the pen used by legend
255 255 */
256 256
257 257 QPen QLegend::pen() const
258 258 {
259 259 return d_ptr->m_pen;
260 260 }
261 261
262 262 void QLegend::setFont(const QFont &font)
263 263 {
264 264 if (d_ptr->m_font != font) {
265 265 d_ptr->m_font = font;
266 266
267 267 foreach (LegendMarker *marker, d_ptr->markers()) {
268 268 marker->setFont(d_ptr->m_font);
269 269 }
270 270 layout()->invalidate();
271 271 emit fontChanged(font);
272 272 }
273 273 }
274 274
275 275 QFont QLegend::font() const
276 276 {
277 277 return d_ptr->m_font;
278 278 }
279 279
280 280 void QLegend::setBorderColor(QColor color)
281 281 {
282 282 QPen p = d_ptr->m_pen;
283 283 if (p.color() != color) {
284 284 p.setColor(color);
285 285 setPen(p);
286 286 }
287 287 }
288 288
289 289 QColor QLegend::borderColor()
290 290 {
291 291 return d_ptr->m_pen.color();
292 292 }
293 293
294 294 /*!
295 295 Set brush used to draw labels to \a brush.
296 296 */
297 297 void QLegend::setLabelBrush(const QBrush &brush)
298 298 {
299 299 if (d_ptr->m_labelBrush != brush) {
300 300 d_ptr->m_labelBrush = brush;
301 301 foreach (LegendMarker *marker, d_ptr->markers()) {
302 302 marker->setLabelBrush(d_ptr->m_labelBrush);
303 303 // Note: The pen of the marker rectangle could be exposed in the public QLegend API
304 304 // instead of mapping it from label brush color
305 305 marker->setPen(brush.color());
306 306 }
307 307 emit labelColorChanged(brush.color());
308 308 }
309 309 }
310 310
311 311 /*!
312 312 Brush used to draw labels.
313 313 */
314 314 QBrush QLegend::labelBrush() const
315 315 {
316 316 return d_ptr->m_labelBrush;
317 317 }
318 318
319 319 void QLegend::setLabelColor(QColor color)
320 320 {
321 321 QBrush b = d_ptr->m_labelBrush;
322 322 if (b.style() != Qt::SolidPattern || b.color() != color) {
323 323 b.setStyle(Qt::SolidPattern);
324 324 b.setColor(color);
325 325 setLabelBrush(b);
326 326 }
327 327 }
328 328
329 329 QColor QLegend::labelColor() const
330 330 {
331 331 return d_ptr->m_labelBrush.color();
332 332 }
333 333
334 334
335 335 void QLegend::setAlignment(Qt::Alignment alignment)
336 336 {
337 337 if(d_ptr->m_alignment!=alignment) {
338 338 d_ptr->m_alignment = alignment;
339 339 updateGeometry();
340 340 if(isAttachedToChart()){
341 341 d_ptr->m_presenter->layout()->invalidate();
342 342 }else{
343 343 layout()->invalidate();
344 344 }
345 345 }
346 346 }
347 347
348 348 Qt::Alignment QLegend::alignment() const
349 349 {
350 350 return d_ptr->m_alignment;
351 351 }
352 352
353 353 /*!
354 354 Detaches the legend from chart. Chart won't change layout of the legend.
355 355 */
356 356 void QLegend::detachFromChart()
357 357 {
358 358 d_ptr->m_attachedToChart = false;
359 359 d_ptr->m_layout->invalidate();
360 360 setParent(0);
361 361
362 362 }
363 363
364 364 /*!
365 365 Attaches the legend to chart. Chart may change layout of the legend.
366 366 */
367 367 void QLegend::attachToChart()
368 368 {
369 369 d_ptr->m_attachedToChart = true;
370 370 d_ptr->m_presenter->layout()->invalidate();
371 371 setParent(d_ptr->m_chart);
372 372 }
373 373
374 374 /*!
375 375 Returns true, if legend is attached to chart.
376 376 */
377 377 bool QLegend::isAttachedToChart()
378 378 {
379 379 return d_ptr->m_attachedToChart;
380 380 }
381 381
382 382 /*!
383 383 Sets the visibility of legend background to \a visible
384 384 */
385 385 void QLegend::setBackgroundVisible(bool visible)
386 386 {
387 387 if(d_ptr->m_backgroundVisible != visible) {
388 388 d_ptr->m_backgroundVisible = visible;
389 389 update();
390 390 emit backgroundVisibleChanged(visible);
391 391 }
392 392 }
393 393
394 394 /*!
395 395 Returns the visibility of legend background
396 396 */
397 397 bool QLegend::isBackgroundVisible() const
398 398 {
399 399 return d_ptr->m_backgroundVisible;
400 400 }
401 401
402 402 /*!
403 403 \internal \a event see QGraphicsWidget for details
404 404 */
405 405 void QLegend::hideEvent(QHideEvent *event)
406 406 {
407 407 d_ptr->m_presenter->layout()->invalidate();
408 408 QGraphicsWidget::hideEvent(event);
409 409 }
410 410
411 411 /*!
412 412 \internal \a event see QGraphicsWidget for details
413 413 */
414 414 void QLegend::showEvent(QShowEvent *event)
415 415 {
416 416 QGraphicsWidget::showEvent(event);
417 417 d_ptr->m_presenter->layout()->invalidate();
418 418 d_ptr->items()->setVisible(false);
419 419 //layout activation will show the items
420 420 }
421 421
422 422 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
423 423
424 424 QLegendPrivate::QLegendPrivate(ChartPresenter* presenter, QChart *chart, QLegend *q):
425 425 q_ptr(q),
426 426 m_presenter(presenter),
427 427 m_layout(new LegendLayout(q)),
428 428 m_chart(chart),
429 429 m_items(new QGraphicsItemGroup(q)),
430 430 m_alignment(Qt::AlignTop),
431 431 m_brush(QBrush()),
432 432 m_pen(QPen()),
433 433 m_labelBrush(QBrush()),
434 434 m_diameter(5),
435 435 m_attachedToChart(true),
436 436 m_backgroundVisible(false)
437 437 {
438 438
439 439 }
440 440
441 441 QLegendPrivate::~QLegendPrivate()
442 442 {
443 443
444 444 }
445 445
446 446 void QLegendPrivate::setOffset(qreal x, qreal y)
447 447 {
448 448 m_layout->setOffset(x,y);
449 449 }
450 450
451 451 QPointF QLegendPrivate::offset() const
452 452 {
453 453 return m_layout->offset();
454 454 }
455 455
456 456 int QLegendPrivate::roundness(qreal size)
457 457 {
458 458 return 100*m_diameter/int(size);
459 459 }
460 460
461 461 void QLegendPrivate::handleSeriesAdded(QAbstractSeries *series, Domain *domain)
462 462 {
463 463 Q_UNUSED(domain)
464 464
465 465 QList<LegendMarker*> markers = series->d_ptr->createLegendMarker(q_ptr);
466 466
467 foreach(LegendMarker* marker, markers) {
467 foreach (LegendMarker* marker, markers) {
468 468 marker->setFont(m_font);
469 469 marker->setLabelBrush(m_labelBrush);
470 470 marker->setVisible(series->isVisible());
471 471 m_items->addToGroup(marker);
472 472 m_markers<<marker;
473 473 }
474 474
475 475 QObject::connect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
476
477 if(series->type() == QAbstractSeries::SeriesTypePie) {
478 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
479 QObject::connect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
480 QObject::connect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
481 }
476 QObject::connect(series->d_ptr.data(), SIGNAL(legendPropertiesUpdated(QAbstractSeries*)), this, SLOT(handleLegendPropertiesUpdated(QAbstractSeries*)));
482 477
483 478 q_ptr->layout()->invalidate();
484 479 q_ptr->layout()->activate();
485 480 }
486 481
487 482 void QLegendPrivate::handleSeriesRemoved(QAbstractSeries *series)
488 483 {
489 484 foreach (LegendMarker *marker, m_markers) {
490 485 if (marker->series() == series) {
491 486 delete marker;
492 487 m_markers.removeAll(marker);
493 488 }
494 489 }
495 490
496 if(series->type() == QAbstractSeries::SeriesTypePie)
497 {
498 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
499 QObject::disconnect(pieSeries, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
500 QObject::disconnect(pieSeries, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleUpdatePieSeries()));
501 }
491 QObject::disconnect(series, SIGNAL(visibleChanged()), this, SLOT(handleSeriesVisibleChanged()));
492 QObject::disconnect(series->d_ptr.data(), SIGNAL(legendPropertiesUpdated(QAbstractSeries*)), this, SLOT(handleLegendPropertiesUpdated(QAbstractSeries*)));
502 493
503 494 q_ptr->layout()->invalidate();
504 495 }
505 496
506 void QLegendPrivate::handleSeriesUpdated(QAbstractSeries *series)
507 {
508 // TODO: find out which markers are are added or removed. Update them
509 // TODO: better implementation
510 handleSeriesRemoved(series);
511 Domain domain;
512 handleSeriesAdded(series, &domain);
513 }
514
515 void QLegendPrivate::handleUpdatePieSeries()
516 {
517 //TODO: reimplement to be optimal
518 QPieSeries* series = qobject_cast<QPieSeries *> (sender());
519 Q_ASSERT(series);
520 handleSeriesRemoved(series);
521 handleSeriesAdded(series, 0);
522 }
523
524 497 void QLegendPrivate::handleSeriesVisibleChanged()
525 498 {
526 499 QAbstractSeries* series = qobject_cast<QAbstractSeries *> (sender());
527 500
528 501 foreach (LegendMarker* marker, m_markers) {
529 502 if (marker->series() == series) {
530 503 marker->setVisible(series->isVisible());
531 504 }
532 505 }
533 506
534 507 q_ptr->layout()->invalidate();
535 508 }
536 509
510 void QLegendPrivate::handleLegendPropertiesUpdated(QAbstractSeries *series)
511 {
512 // Handle new or removed markers
513 // Handle changes of marker pen/brush/label. every property that legend is interested
514 handleSeriesRemoved(series);
515 Domain domain;
516 handleSeriesAdded(series, &domain);
517 }
518
537 519 #include "moc_qlegend.cpp"
538 520 #include "moc_qlegend_p.cpp"
539 521
540 522 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,88 +1,87
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 QLEGEND_P_H
31 31 #define QLEGEND_P_H
32 32
33 33 #include "qlegend.h"
34 34
35 35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 36
37 37 class QChart;
38 38 class ChartPresenter;
39 39 class QAbstractSeries;
40 40 class LegendLayout;
41 41 class LegendMarker;
42 42 class Domain;
43 43
44 44 class QLegendPrivate : public QObject
45 45 {
46 46 Q_OBJECT
47 47 public:
48 48 QLegendPrivate(ChartPresenter *presenter, QChart *chart, QLegend *q);
49 49 ~QLegendPrivate();
50 50
51 51 void setOffset(qreal x, qreal y);
52 52 QPointF offset() const;
53 53 int roundness(qreal size);
54 54
55 55 QList<LegendMarker*> markers() { return m_markers; }
56 56 QGraphicsItemGroup* items() { return m_items; }
57 57
58 58 public Q_SLOTS:
59 59 void handleSeriesAdded(QAbstractSeries *series, Domain *domain);
60 60 void handleSeriesRemoved(QAbstractSeries *series);
61 void handleSeriesUpdated(QAbstractSeries *series);
62 void handleUpdatePieSeries(); //TODO remove this function
63 61 void handleSeriesVisibleChanged();
62 void handleLegendPropertiesUpdated(QAbstractSeries *series);
64 63
65 64 private:
66 65 QLegend *q_ptr;
67 66 ChartPresenter *m_presenter;
68 67 LegendLayout *m_layout;
69 68 QChart* m_chart;
70 69 QGraphicsItemGroup* m_items;
71 70 QList<LegendMarker*> m_markers;
72 71 Qt::Alignment m_alignment;
73 72 QBrush m_brush;
74 73 QPen m_pen;
75 74 QFont m_font;
76 75 QBrush m_labelBrush;
77 76
78 77 qreal m_diameter;
79 78 bool m_attachedToChart;
80 79 bool m_backgroundVisible;
81 80
82 81 friend class QLegend;
83 82
84 83 };
85 84
86 85 QTCOMMERCIALCHART_END_NAMESPACE
87 86
88 87 #endif
@@ -1,875 +1,896
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 "legendmarker_p.h"
29 29 #include "qabstractaxis.h"
30 30 #include "pieanimation_p.h"
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 /*!
35 35 \class QPieSeries
36 36 \brief Pie series API for QtCommercial Charts
37 37
38 38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
39 39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
40 40 The actual slice size is determined by that relative value.
41 41
42 42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
43 43 These relate to the actual chart rectangle.
44 44
45 45 By default the pie is defined as a full pie but it can also be a partial pie.
46 46 This can be done by setting a starting angle and angle span to the series.
47 47 Full pie is 360 degrees where 0 is at 12 a'clock.
48 48
49 49 See the \l {PieChart Example} {pie chart example} or \l {DonutChart Example} {donut chart example} to learn how to use QPieSeries.
50 50 \table 100%
51 51 \row
52 52 \o \image examples_piechart.png
53 53 \o \image examples_donut.png
54 54 \endtable
55 55 */
56 56 /*!
57 57 \qmlclass PieSeries QPieSeries
58 58 \inherits AbstractSeries
59 59
60 60 The following QML shows how to create a simple pie chart.
61 61
62 62 \snippet ../demos/qmlchart/qml/qmlchart/View1.qml 1
63 63
64 64 \beginfloatleft
65 65 \image demos_qmlchart1.png
66 66 \endfloat
67 67 \clearfloat
68 68 */
69 69
70 70 /*!
71 71 \property QPieSeries::horizontalPosition
72 72 \brief Defines the horizontal position of the pie.
73 73
74 74 The value is a relative value to the chart rectangle where:
75 75
76 76 \list
77 77 \o 0.0 is the absolute left.
78 78 \o 1.0 is the absolute right.
79 79 \endlist
80 80 Default value is 0.5 (center).
81 81 \sa verticalPosition
82 82 */
83 83
84 84 /*!
85 85 \qmlproperty real PieSeries::horizontalPosition
86 86
87 87 Defines the horizontal position of the pie.
88 88
89 89 The value is a relative value to the chart rectangle where:
90 90
91 91 \list
92 92 \o 0.0 is the absolute left.
93 93 \o 1.0 is the absolute right.
94 94 \endlist
95 95 Default value is 0.5 (center).
96 96 \sa verticalPosition
97 97 */
98 98
99 99 /*!
100 100 \property QPieSeries::verticalPosition
101 101 \brief Defines the vertical position of the pie.
102 102
103 103 The value is a relative value to the chart rectangle where:
104 104
105 105 \list
106 106 \o 0.0 is the absolute top.
107 107 \o 1.0 is the absolute bottom.
108 108 \endlist
109 109 Default value is 0.5 (center).
110 110 \sa horizontalPosition
111 111 */
112 112
113 113 /*!
114 114 \qmlproperty real PieSeries::verticalPosition
115 115
116 116 Defines the vertical position of the pie.
117 117
118 118 The value is a relative value to the chart rectangle where:
119 119
120 120 \list
121 121 \o 0.0 is the absolute top.
122 122 \o 1.0 is the absolute bottom.
123 123 \endlist
124 124 Default value is 0.5 (center).
125 125 \sa horizontalPosition
126 126 */
127 127
128 128 /*!
129 129 \property QPieSeries::size
130 130 \brief Defines the pie size.
131 131
132 132 The value is a relative value to the chart rectangle where:
133 133
134 134 \list
135 135 \o 0.0 is the minimum size (pie not drawn).
136 136 \o 1.0 is the maximum size that can fit the chart.
137 137 \endlist
138 138
139 139 When setting this property the holeSize property is adjusted if necessary, to ensure that the hole size is not greater than the outer size.
140 140
141 141 Default value is 0.7.
142 142 */
143 143
144 144 /*!
145 145 \qmlproperty real PieSeries::size
146 146
147 147 Defines the pie size.
148 148
149 149 The value is a relative value to the chart rectangle where:
150 150
151 151 \list
152 152 \o 0.0 is the minimum size (pie not drawn).
153 153 \o 1.0 is the maximum size that can fit the chart.
154 154 \endlist
155 155
156 156 Default value is 0.7.
157 157 */
158 158
159 159 /*!
160 160 \property QPieSeries::holeSize
161 161 \brief Defines the donut hole size.
162 162
163 163 The value is a relative value to the chart rectangle where:
164 164
165 165 \list
166 166 \o 0.0 is the minimum size (full pie drawn, without any hole inside).
167 167 \o 1.0 is the maximum size that can fit the chart. (donut has no width)
168 168 \endlist
169 169
170 170 The value is never greater then size property.
171 171 Default value is 0.0.
172 172 */
173 173
174 174 /*!
175 175 \qmlproperty real PieSeries::holeSize
176 176
177 177 Defines the donut hole size.
178 178
179 179 The value is a relative value to the chart rectangle where:
180 180
181 181 \list
182 182 \o 0.0 is the minimum size (full pie drawn, without any hole inside).
183 183 \o 1.0 is the maximum size that can fit the chart. (donut has no width)
184 184 \endlist
185 185
186 186 When setting this property the size property is adjusted if necessary, to ensure that the inner size is not greater than the outer size.
187 187
188 188 Default value is 0.0.
189 189 */
190 190
191 191 /*!
192 192 \property QPieSeries::startAngle
193 193 \brief Defines the starting angle of the pie.
194 194
195 195 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
196 196
197 197 Default is value is 0.
198 198 */
199 199
200 200 /*!
201 201 \qmlproperty real PieSeries::startAngle
202 202
203 203 Defines the starting angle of the pie.
204 204
205 205 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
206 206
207 207 Default is value is 0.
208 208 */
209 209
210 210 /*!
211 211 \property QPieSeries::endAngle
212 212 \brief Defines the ending angle of the pie.
213 213
214 214 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
215 215
216 216 Default is value is 360.
217 217 */
218 218
219 219 /*!
220 220 \qmlproperty real PieSeries::endAngle
221 221
222 222 Defines the ending angle of the pie.
223 223
224 224 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
225 225
226 226 Default is value is 360.
227 227 */
228 228
229 229 /*!
230 230 \property QPieSeries::count
231 231
232 232 Number of slices in the series.
233 233 */
234 234
235 235 /*!
236 236 \qmlproperty int PieSeries::count
237 237
238 238 Number of slices in the series.
239 239 */
240 240
241 241 /*!
242 242 \fn void QPieSeries::countChanged()
243 243 Emitted when the slice count has changed.
244 244 \sa count
245 245 */
246 246 /*!
247 247 \qmlsignal PieSeries::onCountChanged()
248 248 Emitted when the slice count has changed.
249 249 */
250 250
251 251 /*!
252 252 \property QPieSeries::sum
253 253
254 254 Sum of all slices.
255 255
256 256 The series keeps track of the sum of all slices it holds.
257 257 */
258 258
259 259 /*!
260 260 \qmlproperty real PieSeries::sum
261 261
262 262 Sum of all slices.
263 263
264 264 The series keeps track of the sum of all slices it holds.
265 265 */
266 266
267 267 /*!
268 268 \fn void QPieSeries::sumChanged()
269 269 Emitted when the sum of all slices has changed.
270 270 \sa sum
271 271 */
272 272 /*!
273 273 \qmlsignal PieSeries::onSumChanged()
274 274 Emitted when the sum of all slices has changed. This may happen for example if you add or remove slices, or if you
275 275 change value of a slice.
276 276 */
277 277
278 278 /*!
279 279 \fn void QPieSeries::added(QList<QPieSlice*> slices)
280 280
281 281 This signal is emitted when \a slices have been added to the series.
282 282
283 283 \sa append(), insert()
284 284 */
285 285 /*!
286 286 \qmlsignal PieSeries::onAdded(PieSlice slice)
287 287 Emitted when \a slice has been added to the series.
288 288 */
289 289
290 290 /*!
291 291 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
292 292 This signal is emitted when \a slices have been removed from the series.
293 293 \sa remove()
294 294 */
295 295 /*!
296 296 \qmlsignal PieSeries::onRemoved(PieSlice slice)
297 297 Emitted when \a slice has been removed from the series.
298 298 */
299 299
300 300 /*!
301 301 \fn void QPieSeries::clicked(QPieSlice* slice)
302 302 This signal is emitted when a \a slice has been clicked.
303 303 \sa QPieSlice::clicked()
304 304 */
305 305 /*!
306 306 \qmlsignal PieSeries::onClicked(PieSlice slice)
307 307 This signal is emitted when a \a slice has been clicked.
308 308 */
309 309
310 310 /*!
311 311 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
312 312 This signal is emitted when user has hovered over or away from the \a slice.
313 313 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
314 314 \sa QPieSlice::hovered()
315 315 */
316 316 /*!
317 317 \qmlsignal PieSeries::onHovered(PieSlice slice, bool state)
318 318 This signal is emitted when user has hovered over or away from the \a slice. \a state is true when user has hovered
319 319 over the slice and false when hover has moved away from the slice.
320 320 */
321 321
322 322 /*!
323 323 \qmlmethod PieSlice PieSeries::at(int index)
324 324 Returns slice at \a index. Returns null if the index is not valid.
325 325 */
326 326
327 327 /*!
328 328 \qmlmethod PieSlice PieSeries::find(string label)
329 329 Returns the first slice with \a label. Returns null if the index is not valid.
330 330 */
331 331
332 332 /*!
333 333 \qmlmethod PieSlice PieSeries::append(string label, real value)
334 334 Adds a new slice with \a label and \a value to the pie.
335 335 */
336 336
337 337 /*!
338 338 \qmlmethod bool PieSeries::remove(PieSlice slice)
339 339 Removes the \a slice from the pie. Returns true if the removal was successful, false otherwise.
340 340 */
341 341
342 342 /*!
343 343 \qmlmethod PieSeries::clear()
344 344 Removes all slices from the pie.
345 345 */
346 346
347 347 /*!
348 348 Constructs a series object which is a child of \a parent.
349 349 */
350 350 QPieSeries::QPieSeries(QObject *parent) :
351 351 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
352 352 {
353 353
354 354 }
355 355
356 356 /*!
357 357 Destroys the series and its slices.
358 358 */
359 359 QPieSeries::~QPieSeries()
360 360 {
361 361 // NOTE: d_prt destroyed by QObject
362 362 }
363 363
364 364 /*!
365 365 Returns QChartSeries::SeriesTypePie.
366 366 */
367 367 QAbstractSeries::SeriesType QPieSeries::type() const
368 368 {
369 369 return QAbstractSeries::SeriesTypePie;
370 370 }
371 371
372 372 /*!
373 373 Appends a single \a slice to the series.
374 374 Slice ownership is passed to the series.
375 375
376 376 Returns true if append was succesfull.
377 377 */
378 378 bool QPieSeries::append(QPieSlice* slice)
379 379 {
380 380 return append(QList<QPieSlice*>() << slice);
381 381 }
382 382
383 383 /*!
384 384 Appends an array of \a slices to the series.
385 385 Slice ownership is passed to the series.
386 386
387 387 Returns true if append was successful.
388 388 */
389 389 bool QPieSeries::append(QList<QPieSlice*> slices)
390 390 {
391 391 Q_D(QPieSeries);
392 392
393 393 if (slices.count() == 0)
394 394 return false;
395 395
396 396 foreach (QPieSlice* s, slices) {
397 397 if (!s || d->m_slices.contains(s))
398 398 return false;
399 399 if (s->series()) // already added to some series
400 400 return false;
401 401 }
402 402
403 403 foreach (QPieSlice* s, slices) {
404 404 s->setParent(this);
405 405 QPieSlicePrivate::fromSlice(s)->m_series = this;
406 406 d->m_slices << s;
407 407 }
408 408
409 409 d->updateDerivativeData();
410 410
411 411 foreach (QPieSlice* s, slices) {
412 412 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
413 413 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
414 414 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
415
416 connect(s, SIGNAL(labelChanged()), d, SLOT(updateLegendProperties()));
417 connect(s, SIGNAL(penChanged()), d, SLOT(updateLegendProperties()));
418 connect(s, SIGNAL(brushChanged()), d, SLOT(updateLegendProperties()));
419 connect(s, SIGNAL(labelBrushChanged()), d, SLOT(updateLegendProperties()));
420 connect(s, SIGNAL(labelFontChanged()), d, SLOT(updateLegendProperties()));
421 connect(s, SIGNAL(labelFontChanged()), d, SLOT(updateLegendProperties()));
415 422 }
416 423
417 424 emit added(slices);
418 425 emit countChanged();
419 426
420 427 return true;
421 428 }
422 429
423 430 /*!
424 431 Appends a single \a slice to the series and returns a reference to the series.
425 432 Slice ownership is passed to the series.
426 433 */
427 434 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
428 435 {
429 436 append(slice);
430 437 return *this;
431 438 }
432 439
433 440
434 441 /*!
435 442 Appends a single slice to the series with give \a value and \a label.
436 443 Slice ownership is passed to the series.
437 444 */
438 445 QPieSlice* QPieSeries::append(QString label, qreal value)
439 446 {
440 447 QPieSlice* slice = new QPieSlice(label, value);
441 448 append(slice);
442 449 return slice;
443 450 }
444 451
445 452 /*!
446 453 Inserts a single \a slice to the series before the slice at \a index position.
447 454 Slice ownership is passed to the series.
448 455
449 456 Returns true if insert was successful.
450 457 */
451 458 bool QPieSeries::insert(int index, QPieSlice* slice)
452 459 {
453 460 Q_D(QPieSeries);
454 461
455 462 if (index < 0 || index > d->m_slices.count())
456 463 return false;
457 464
458 465 if (!slice || d->m_slices.contains(slice))
459 466 return false;
460 467
461 468 if (slice->series()) // already added to some series
462 469 return false;
463 470
464 471 slice->setParent(this);
465 472 QPieSlicePrivate::fromSlice(slice)->m_series = this;
466 473 d->m_slices.insert(index, slice);
467 474
468 475 d->updateDerivativeData();
469 476
470 477 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
471 478 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
472 479 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
473 480
481 connect(slice, SIGNAL(labelChanged()), d, SLOT(updateLegendProperties()));
482 connect(slice, SIGNAL(penChanged()), d, SLOT(updateLegendProperties()));
483 connect(slice, SIGNAL(brushChanged()), d, SLOT(updateLegendProperties()));
484 connect(slice, SIGNAL(labelBrushChanged()), d, SLOT(updateLegendProperties()));
485 connect(slice, SIGNAL(labelFontChanged()), d, SLOT(updateLegendProperties()));
486 connect(slice, SIGNAL(labelFontChanged()), d, SLOT(updateLegendProperties()));
487
474 488 emit added(QList<QPieSlice*>() << slice);
475 489 emit countChanged();
476 490
477 491 return true;
478 492 }
479 493
480 494 /*!
481 495 Removes a single \a slice from the series and deletes the slice.
482 496
483 497 Do not reference the pointer after this call.
484 498
485 499 Returns true if remove was successful.
486 500 */
487 501 bool QPieSeries::remove(QPieSlice* slice)
488 502 {
489 503 Q_D(QPieSeries);
490 504
491 505 if (!d->m_slices.removeOne(slice))
492 506 return false;
493 507
494 508 d->updateDerivativeData();
495 509
496 510 emit removed(QList<QPieSlice*>() << slice);
497 511 emit countChanged();
498 512
499 513 delete slice;
500 514 slice = 0;
501 515
502 516 return true;
503 517 }
504 518
505 519 /*!
506 520 Takes a single \a slice from the series. Does not destroy the slice object.
507 521
508 522 NOTE: The series remains as the slice's parent object. You must set the
509 523 parent object to take full ownership.
510 524
511 525 Returns true if take was successful.
512 526 */
513 527 bool QPieSeries::take(QPieSlice* slice)
514 528 {
515 529 Q_D(QPieSeries);
516 530
517 531 if (!d->m_slices.removeOne(slice))
518 532 return false;
519 533
520 534 QPieSlicePrivate::fromSlice(slice)->m_series = 0;
521 535
522 536 d->updateDerivativeData();
523 537
524 538 emit removed(QList<QPieSlice*>() << slice);
525 539 emit countChanged();
526 540
527 541 return true;
528 542 }
529 543
530 544 /*!
531 545 Clears all slices from the series.
532 546 */
533 547 void QPieSeries::clear()
534 548 {
535 549 Q_D(QPieSeries);
536 550 if (d->m_slices.count() == 0)
537 551 return;
538 552
539 553 QList<QPieSlice*> slices = d->m_slices;
540 554 foreach (QPieSlice* s, d->m_slices) {
541 555 d->m_slices.removeOne(s);
542 556 delete s;
543 557 }
544 558
545 559 d->updateDerivativeData();
546 560
547 561 emit removed(slices);
548 562 emit countChanged();
549 563 }
550 564
551 565 /*!
552 566 Returns a list of slices that belong to this series.
553 567 */
554 568 QList<QPieSlice*> QPieSeries::slices() const
555 569 {
556 570 Q_D(const QPieSeries);
557 571 return d->m_slices;
558 572 }
559 573
560 574 /*!
561 575 returns the number of the slices in this series.
562 576 */
563 577 int QPieSeries::count() const
564 578 {
565 579 Q_D(const QPieSeries);
566 580 return d->m_slices.count();
567 581 }
568 582
569 583 /*!
570 584 Returns true is the series is empty.
571 585 */
572 586 bool QPieSeries::isEmpty() const
573 587 {
574 588 Q_D(const QPieSeries);
575 589 return d->m_slices.isEmpty();
576 590 }
577 591
578 592 /*!
579 593 Returns the sum of all slice values in this series.
580 594
581 595 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
582 596 */
583 597 qreal QPieSeries::sum() const
584 598 {
585 599 Q_D(const QPieSeries);
586 600 return d->m_sum;
587 601 }
588 602
589 603 void QPieSeries::setHoleSize(qreal holeSize)
590 604 {
591 605 Q_D(QPieSeries);
592 606 holeSize = qBound((qreal)0.0, holeSize, (qreal)1.0);
593 607 d->setSizes(holeSize, qMax(d->m_pieRelativeSize, holeSize));
594 608 }
595 609
596 610 qreal QPieSeries::holeSize() const
597 611 {
598 612 Q_D(const QPieSeries);
599 613 return d->m_holeRelativeSize;
600 614 }
601 615
602 616 void QPieSeries::setHorizontalPosition(qreal relativePosition)
603 617 {
604 618 Q_D(QPieSeries);
605 619
606 620 if (relativePosition < 0.0)
607 621 relativePosition = 0.0;
608 622 if (relativePosition > 1.0)
609 623 relativePosition = 1.0;
610 624
611 625 if (!qFuzzyIsNull(d->m_pieRelativeHorPos - relativePosition)) {
612 626 d->m_pieRelativeHorPos = relativePosition;
613 627 emit d->horizontalPositionChanged();
614 628 }
615 629 }
616 630
617 631 qreal QPieSeries::horizontalPosition() const
618 632 {
619 633 Q_D(const QPieSeries);
620 634 return d->m_pieRelativeHorPos;
621 635 }
622 636
623 637 void QPieSeries::setVerticalPosition(qreal relativePosition)
624 638 {
625 639 Q_D(QPieSeries);
626 640
627 641 if (relativePosition < 0.0)
628 642 relativePosition = 0.0;
629 643 if (relativePosition > 1.0)
630 644 relativePosition = 1.0;
631 645
632 646 if (!qFuzzyIsNull(d->m_pieRelativeVerPos - relativePosition)) {
633 647 d->m_pieRelativeVerPos = relativePosition;
634 648 emit d->verticalPositionChanged();
635 649 }
636 650 }
637 651
638 652 qreal QPieSeries::verticalPosition() const
639 653 {
640 654 Q_D(const QPieSeries);
641 655 return d->m_pieRelativeVerPos;
642 656 }
643 657
644 658 void QPieSeries::setPieSize(qreal relativeSize)
645 659 {
646 660 Q_D(QPieSeries);
647 661 relativeSize = qBound((qreal)0.0, relativeSize, (qreal)1.0);
648 662 d->setSizes(qMin(d->m_holeRelativeSize, relativeSize), relativeSize);
649 663
650 664 }
651 665
652 666 qreal QPieSeries::pieSize() const
653 667 {
654 668 Q_D(const QPieSeries);
655 669 return d->m_pieRelativeSize;
656 670 }
657 671
658 672
659 673 void QPieSeries::setPieStartAngle(qreal angle)
660 674 {
661 675 Q_D(QPieSeries);
662 676 if (qFuzzyIsNull(d->m_pieStartAngle - angle))
663 677 return;
664 678 d->m_pieStartAngle = angle;
665 679 d->updateDerivativeData();
666 680 emit d->pieStartAngleChanged();
667 681 }
668 682
669 683 qreal QPieSeries::pieStartAngle() const
670 684 {
671 685 Q_D(const QPieSeries);
672 686 return d->m_pieStartAngle;
673 687 }
674 688
675 689 /*!
676 690 Sets the end angle of the pie.
677 691
678 692 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
679 693
680 694 \a angle must be greater than start angle.
681 695
682 696 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
683 697 */
684 698 void QPieSeries::setPieEndAngle(qreal angle)
685 699 {
686 700 Q_D(QPieSeries);
687 701 if (qFuzzyIsNull(d->m_pieEndAngle - angle))
688 702 return;
689 703 d->m_pieEndAngle = angle;
690 704 d->updateDerivativeData();
691 705 emit d->pieEndAngleChanged();
692 706 }
693 707
694 708 /*!
695 709 Returns the end angle of the pie.
696 710
697 711 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
698 712
699 713 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
700 714 */
701 715 qreal QPieSeries::pieEndAngle() const
702 716 {
703 717 Q_D(const QPieSeries);
704 718 return d->m_pieEndAngle;
705 719 }
706 720
707 721 /*!
708 722 Sets the all the slice labels \a visible or invisible.
709 723
710 724 Note that this affects only the current slices in the series.
711 725 If user adds a new slice the default label visibility is false.
712 726
713 727 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
714 728 */
715 729 void QPieSeries::setLabelsVisible(bool visible)
716 730 {
717 731 Q_D(QPieSeries);
718 732 foreach (QPieSlice* s, d->m_slices)
719 733 s->setLabelVisible(visible);
720 734 }
721 735
722 736 /*!
723 737 Sets the all the slice labels \a position
724 738
725 739 Note that this affects only the current slices in the series.
726 740 If user adds a new slice the default label position is LabelOutside
727 741
728 742 \sa QPieSlice::labelPosition(), QPieSlice::setLabelPosition()
729 743 */
730 744 void QPieSeries::setLabelsPosition(QPieSlice::LabelPosition position)
731 745 {
732 746 Q_D(QPieSeries);
733 747 foreach (QPieSlice* s, d->m_slices)
734 748 s->setLabelPosition(position);
735 749 }
736 750
737 751 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
738 752
739 753
740 754 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
741 755 QAbstractSeriesPrivate(parent),
742 756 m_pieRelativeHorPos(0.5),
743 757 m_pieRelativeVerPos(0.5),
744 758 m_pieRelativeSize(0.7),
745 759 m_pieStartAngle(0),
746 760 m_pieEndAngle(360),
747 761 m_sum(0),
748 762 m_holeRelativeSize(0.0)
749 763 {
750 764 }
751 765
752 766 QPieSeriesPrivate::~QPieSeriesPrivate()
753 767 {
754 768 }
755 769
756 770 void QPieSeriesPrivate::updateDerivativeData()
757 771 {
758 772 // calculate sum of all slices
759 773 qreal sum = 0;
760 774 foreach (QPieSlice* s, m_slices)
761 775 sum += s->value();
762 776
763 777 if (!qFuzzyIsNull(m_sum - sum)) {
764 778 m_sum = sum;
765 779 emit q_func()->sumChanged();
766 780 }
767 781
768 782 // nothing to show..
769 783 if (qFuzzyIsNull(m_sum))
770 784 return;
771 785
772 786 // update slice attributes
773 787 qreal sliceAngle = m_pieStartAngle;
774 788 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
775 789 QVector<QPieSlice*> changed;
776 790 foreach (QPieSlice* s, m_slices) {
777 791 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
778 792 d->setPercentage(s->value() / m_sum);
779 793 d->setStartAngle(sliceAngle);
780 794 d->setAngleSpan(pieSpan * s->percentage());
781 795 sliceAngle += s->angleSpan();
782 796 }
783 797
784 798
785 799 emit calculatedDataChanged();
786 800 }
787 801
788 802 void QPieSeriesPrivate::setSizes(qreal innerSize, qreal outerSize)
789 803 {
790 804 bool changed = false;
791 805
792 806 if (!qFuzzyIsNull(m_holeRelativeSize - innerSize)) {
793 807 m_holeRelativeSize = innerSize;
794 808 changed = true;
795 809 }
796 810
797 811 if (!qFuzzyIsNull(m_pieRelativeSize - outerSize)) {
798 812 m_pieRelativeSize = outerSize;
799 813 changed = true;
800 814 }
801 815
802 816 if (changed)
803 817 emit pieSizeChanged();
804 818 }
805 819
806 820 QPieSeriesPrivate* QPieSeriesPrivate::fromSeries(QPieSeries *series)
807 821 {
808 822 return series->d_func();
809 823 }
810 824
811 825 void QPieSeriesPrivate::sliceValueChanged()
812 826 {
813 827 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
814 828 updateDerivativeData();
815 829 }
816 830
817 831 void QPieSeriesPrivate::sliceClicked()
818 832 {
819 833 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
820 834 Q_ASSERT(m_slices.contains(slice));
821 835 Q_Q(QPieSeries);
822 836 emit q->clicked(slice);
823 837 }
824 838
825 839 void QPieSeriesPrivate::sliceHovered(bool state)
826 840 {
827 841 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
828 842 Q_ASSERT(m_slices.contains(slice));
829 843 Q_Q(QPieSeries);
830 844 emit q->hovered(slice, state);
831 845 }
832 846
847 void QPieSeriesPrivate::updateLegendProperties()
848 {
849 // This slot listens to all properties of slices, which may interest legend and signals it.
850 Q_Q(QPieSeries);
851 emit legendPropertiesUpdated(q);
852 }
853
833 854 void QPieSeriesPrivate::scaleDomain(Domain& domain)
834 855 {
835 856 Q_UNUSED(domain);
836 857 // does not apply to pie
837 858 }
838 859
839 860 ChartElement* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
840 861 {
841 862 Q_Q(QPieSeries);
842 863 PieChartItem* pie = new PieChartItem(q,presenter);
843 864 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
844 865 pie->setAnimation(new PieAnimation(pie));
845 866 }
846 867 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
847 868 return pie;
848 869 }
849 870
850 871 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
851 872 {
852 873 Q_Q(QPieSeries);
853 874 QList<LegendMarker*> markers;
854 875 foreach(QPieSlice* slice, q->slices()) {
855 876 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
856 877 markers << marker;
857 878 }
858 879 return markers;
859 880 }
860 881
861 882 void QPieSeriesPrivate::initializeAxis(QAbstractAxis* axis)
862 883 {
863 884 Q_UNUSED(axis);
864 885 }
865 886
866 887 QAbstractAxis::AxisType QPieSeriesPrivate::defaultAxisType(Qt::Orientation orientation) const
867 888 {
868 889 Q_UNUSED(orientation);
869 890 return QAbstractAxis::AxisTypeNoAxis;
870 891 }
871 892
872 893 #include "moc_qpieseries.cpp"
873 894 #include "moc_qpieseries_p.cpp"
874 895
875 896 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,88 +1,89
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 QPIESERIES_P_H
31 31 #define QPIESERIES_P_H
32 32
33 33 #include "qpieseries.h"
34 34 #include "qabstractseries_p.h"
35 35
36 36 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 37 class QLegendPrivate;
38 38
39 39 class QPieSeriesPrivate : public QAbstractSeriesPrivate
40 40 {
41 41 Q_OBJECT
42 42
43 43 public:
44 44 QPieSeriesPrivate(QPieSeries *parent);
45 45 ~QPieSeriesPrivate();
46 46
47 47 void scaleDomain(Domain& domain);
48 48 ChartElement* createGraphics(ChartPresenter *presenter);
49 49 QList<LegendMarker*> createLegendMarker(QLegend *legend);
50 50 void initializeAxis(QAbstractAxis* axis);
51 51 QAbstractAxis::AxisType defaultAxisType(Qt::Orientation orientation) const;
52 52
53 53 void updateDerivativeData();
54 54 void setSizes(qreal innerSize, qreal outerSize);
55 55
56 56 static QPieSeriesPrivate* fromSeries(QPieSeries *series);
57 57
58 58 signals:
59 59 void calculatedDataChanged();
60 60 void pieSizeChanged();
61 61 void pieStartAngleChanged();
62 62 void pieEndAngleChanged();
63 63 void horizontalPositionChanged();
64 64 void verticalPositionChanged();
65 65
66 66 public Q_SLOTS:
67 67 void sliceValueChanged();
68 68 void sliceClicked();
69 69 void sliceHovered(bool state);
70 void updateLegendProperties();
70 71
71 72 private:
72 73 QList<QPieSlice*> m_slices;
73 74 qreal m_pieRelativeHorPos;
74 75 qreal m_pieRelativeVerPos;
75 76 qreal m_pieRelativeSize;
76 77 qreal m_pieStartAngle;
77 78 qreal m_pieEndAngle;
78 79 qreal m_sum;
79 80 qreal m_holeRelativeSize;
80 81
81 82 private:
82 83 friend class QLegendPrivate;
83 84 Q_DECLARE_PUBLIC(QPieSeries)
84 85 };
85 86
86 87 QTCOMMERCIALCHART_END_NAMESPACE
87 88
88 89 #endif // QPIESERIES_P_H
@@ -1,72 +1,75
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 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 QABSTRACTSERIES_P_H
31 31 #define QABSTRACTSERIES_P_H
32 32
33 33 #include "qabstractseries.h"
34 34
35 35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 36
37 37 class Domain;
38 38 class ChartPresenter;
39 39 class ChartElement;
40 40 class LegendMarker;
41 41 class QLegend;
42 42 class ChartDataSet;
43 43 class QAbstractAxis;
44 44
45 45 class QAbstractSeriesPrivate : public QObject
46 46 {
47 47 Q_OBJECT
48 48 public:
49 49 QAbstractSeriesPrivate(QAbstractSeries *q);
50 50 ~QAbstractSeriesPrivate();
51 51
52 52 virtual void scaleDomain(Domain& domain) = 0;
53 53 virtual ChartElement* createGraphics(ChartPresenter* presenter) = 0;
54 54 virtual QList<LegendMarker*> createLegendMarker(QLegend* legend) = 0;
55 55 virtual void initializeAxis(QAbstractAxis* axis) = 0;
56 56 virtual QAbstractAxis::AxisType defaultAxisType(Qt::Orientation) const = 0;
57 57
58 Q_SIGNALS:
59 void legendPropertiesUpdated(QAbstractSeries* series);
60
58 61 protected:
59 62 QAbstractSeries *q_ptr;
60 63 QChart *m_chart;
61 64 ChartDataSet *m_dataset;
62 65 QString m_name;
63 66 bool m_visible;
64 67 qreal m_opacity;
65 68
66 69 friend class QAbstractSeries;
67 70 friend class ChartDataSet;
68 71 };
69 72
70 73 QTCOMMERCIALCHART_END_NAMESPACE
71 74
72 75 #endif
General Comments 0
You need to be logged in to leave comments. Login now