##// END OF EJS Templates
barseries scaledomain fix
sauimone -
r1376:7989ebf68fe8
parent child
Show More
@@ -1,644 +1,644
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 "qbarseries.h"
22 22 #include "qbarseries_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 "chartanimator_p.h"
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 /*!
34 34 \class QBarSeries
35 35 \brief part of QtCommercial chart API.
36 36 \mainclass
37 37
38 38 QBarSeries represents a series of data shown as bars. The purpose of this class is to draw bars to
39 39 the position defined by data. Single bar is defined by QPointF, where x value is the x-coordinate of the bar
40 40 and y-value is the height of the bar. The category names are ignored with this series and x-axis
41 41 shows the x-values.
42 42
43 43 See the \l {BarChart Example} {bar chart example} to learn how to create a simple bar chart.
44 44 \image examples_barchart.png
45 45
46 46 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
47 47 */
48 48
49 49 /*!
50 50 \property QBarSeries::barMargin
51 51 \brief Defines the margin around bars.
52 52
53 53 Value is from 0 to 1 and represents
54 54 percentage of margin compared to bars
55 55 */
56 56
57 57 /*!
58 58 \property QBarSeries::count
59 59 \brief Holds the number of sets in series.
60 60 */
61 61
62 62 /*!
63 63 \property QBarSeries::labelsVisible
64 64 \brief Defines the visibility of the labels in series
65 65 */
66 66
67 67 /*!
68 68 \fn void QBarSeries::clicked(QBarSet *barset, int index)
69 69
70 70 The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset.
71 71 Clicked bar inside set is indexed by \a index
72 72 */
73 73
74 74 /*!
75 75 \fn void QBarSeries::hovered(QBarSet* barset, bool status)
76 76
77 77 The signal is emitted if mouse is hovered on top of series.
78 78 Parameter \a barset is the pointer of barset, where hover happened.
79 79 Parameter \a status is true, if mouse entered on top of series, false if mouse left from top of series.
80 80 */
81 81
82 82 /*!
83 83 \fn void QBarSeries::visibleChanged()
84 84 */
85 85
86 86 /*!
87 87 \fn void QBarSeries::labelsVisibleChanged()
88 88
89 89 This signal is emitted when labels visibility have changed.
90 90
91 91 \sa isLabelsVisible(), setLabelsVisible()
92 92 */
93 93
94 94 /*!
95 95 \fn void QBarSeries::barsetsAdded(QList<QBarSet*> sets)
96 96
97 97 This signal is emitted when \a sets have been added to the series.
98 98
99 99 \sa append(), insert()
100 100 */
101 101
102 102 /*!
103 103 \fn void QBarSeries::barsetsRemoved(QList<QBarSet*> sets)
104 104
105 105 This signal is emitted when \a sets have been removed from the series.
106 106
107 107 \sa remove()
108 108 */
109 109
110 110 /*!
111 111 Constructs empty QBarSeries.
112 112 QBarSeries is QObject which is a child of a \a parent.
113 113 */
114 114 QBarSeries::QBarSeries(QObject *parent) :
115 115 QAbstractSeries(*new QBarSeriesPrivate(this),parent)
116 116 {
117 117 }
118 118
119 119 /*!
120 120 Destructs barseries and owned barsets.
121 121 */
122 122 QBarSeries::~QBarSeries()
123 123 {
124 124 Q_D(QBarSeries);
125 125 if(d->m_dataset){
126 126 d->m_dataset->removeSeries(this);
127 127 }
128 128 }
129 129
130 130 /*!
131 131 \internal
132 132 */
133 133 QBarSeries::QBarSeries(QBarSeriesPrivate &d, QObject *parent) :
134 134 QAbstractSeries(d,parent)
135 135 {
136 136 }
137 137
138 138 /*!
139 139 Returns the type of series. Derived classes override this.
140 140 */
141 141 QAbstractSeries::SeriesType QBarSeries::type() const
142 142 {
143 143 return QAbstractSeries::SeriesTypeBar;
144 144 }
145 145
146 146 /*!
147 147 Sets the margin around bars. Parameter \a margin is from 0 to 1 and represents
148 148 percentage of margin compared to bars
149 149 */
150 150 void QBarSeries::setBarMargin(qreal margin)
151 151 {
152 152 Q_D(QBarSeries);
153 153 d->setBarMargin(margin);
154 154 }
155 155
156 156 /*!
157 157 Returns the margin around bars
158 158 */
159 159 qreal QBarSeries::barMargin() const
160 160 {
161 161 Q_D(const QBarSeries);
162 162 return d->barMargin();
163 163 }
164 164
165 165 /*!
166 166 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.
167 167 Returns true, if appending succeeded.
168 168
169 169 */
170 170 bool QBarSeries::append(QBarSet *set)
171 171 {
172 172 Q_D(QBarSeries);
173 173 bool success = d->append(set);
174 174 if (success) {
175 175 QList<QBarSet*> sets;
176 176 sets.append(set);
177 177 emit barsetsAdded(sets);
178 178 }
179 179 return success;
180 180 }
181 181
182 182 /*!
183 183 Removes a set of bars from series. Releases ownership of \a set. Doesn't delete \a set.
184 184 Returns true, if set was removed.
185 185 */
186 186 bool QBarSeries::remove(QBarSet *set)
187 187 {
188 188 Q_D(QBarSeries);
189 189 bool success = d->remove(set);
190 190 if (success) {
191 191 QList<QBarSet*> sets;
192 192 sets.append(set);
193 193 emit barsetsRemoved(sets);
194 194 }
195 195 return success;
196 196 }
197 197
198 198 /*!
199 199 Adds a list of barsets to series. Takes ownership of \a sets.
200 200 Returns true, if all sets were appended succesfully. If any of the sets is null or is already appended to series,
201 201 nothing is appended and function returns false. If any of the sets is in list more than once, nothing is appended
202 202 and function returns false.
203 203 */
204 204 bool QBarSeries::append(QList<QBarSet* > sets)
205 205 {
206 206 Q_D(QBarSeries);
207 207 bool success = d->append(sets);
208 208 if (success) {
209 209 emit barsetsAdded(sets);
210 210 }
211 211 return success;
212 212 }
213 213
214 214 /*!
215 215 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.
216 216 Returns true, if inserting succeeded.
217 217
218 218 */
219 219 bool QBarSeries::insert(int index, QBarSet *set)
220 220 {
221 221 Q_D(QBarSeries);
222 222 bool success = d->insert(index, set);
223 223 if (success) {
224 224 QList<QBarSet*> sets;
225 225 sets.append(set);
226 226 emit barsetsAdded(sets);
227 227 }
228 228 return success;
229 229 }
230 230
231 231 /*!
232 232 Removes all of the bar sets from the series
233 233 */
234 234 void QBarSeries::clear()
235 235 {
236 236 Q_D(QBarSeries);
237 237 QList<QBarSet *> sets = barSets();
238 238 bool success = d->remove(sets);
239 239 if (success) {
240 240 emit barsetsRemoved(sets);
241 241 }
242 242 }
243 243
244 244 /*!
245 245 Returns number of sets in series.
246 246 */
247 247 int QBarSeries::barsetCount() const
248 248 {
249 249 Q_D(const QBarSeries);
250 250 return d->m_barSets.count();
251 251 }
252 252
253 253 /*!
254 254 Returns a list of sets in series. Keeps ownership of sets.
255 255 */
256 256 QList<QBarSet*> QBarSeries::barSets() const
257 257 {
258 258 Q_D(const QBarSeries);
259 259 return d->m_barSets;
260 260 }
261 261
262 262 /*!
263 263 Sets the visibility of labels in series to \a visible
264 264 */
265 265 void QBarSeries::setLabelsVisible(bool visible)
266 266 {
267 267 Q_D(QBarSeries);
268 268 if (d->m_labelsVisible != visible) {
269 269 d->setLabelsVisible(visible);
270 270 emit labelsVisibleChanged();
271 271 }
272 272 }
273 273
274 274 /*!
275 275 Returns the visibility of labels
276 276 */
277 277 bool QBarSeries::isLabelsVisible() const
278 278 {
279 279 Q_D(const QBarSeries);
280 280 return d->m_labelsVisible;
281 281 }
282 282
283 283 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
284 284
285 285 QBarSeriesPrivate::QBarSeriesPrivate(QBarSeries *q) :
286 286 QAbstractSeriesPrivate(q),
287 287 m_barMargin(0.5), // Default value is 50% of category width
288 288 m_labelsVisible(false),
289 289 m_visible(true)
290 290 {
291 291 }
292 292
293 293 void QBarSeriesPrivate::setCategories(QStringList categories)
294 294 {
295 295 m_categories = categories;
296 296 }
297 297
298 298 void QBarSeriesPrivate::insertCategory(int index, const QString category)
299 299 {
300 300 m_categories.insert(index, category);
301 301 emit categoriesUpdated();
302 302 }
303 303
304 304 void QBarSeriesPrivate::removeCategory(int index)
305 305 {
306 306 m_categories.removeAt(index);
307 307 emit categoriesUpdated();
308 308 }
309 309
310 310 int QBarSeriesPrivate::categoryCount() const
311 311 {
312 312 if (m_categories.count() > 0) {
313 313 return m_categories.count();
314 314 }
315 315
316 316 // No categories defined. return count of longest set.
317 317 int count = 0;
318 318 for (int i=0; i<m_barSets.count(); i++) {
319 319 if (m_barSets.at(i)->count() > count) {
320 320 count = m_barSets.at(i)->count();
321 321 }
322 322 }
323 323
324 324 return count;
325 325 }
326 326
327 327 QStringList QBarSeriesPrivate::categories() const
328 328 {
329 329 if (m_categories.count() > 0) {
330 330 return m_categories;
331 331 }
332 332
333 333 // No categories defined. retun list of indices.
334 334 QStringList categories;
335 335
336 336 int count = categoryCount();
337 337 for (int i = 0; i < count; i++) {
338 338 categories.append(QString::number(i));
339 339 }
340 340 return categories;
341 341 }
342 342
343 343 void QBarSeriesPrivate::setBarMargin(qreal margin)
344 344 {
345 345 if (margin > 1.0) {
346 346 margin = 1.0;
347 347 } else if (margin < 0.0) {
348 348 margin = 0.0;
349 349 }
350 350
351 351 m_barMargin = margin;
352 352 emit updatedBars();
353 353 }
354 354
355 355 qreal QBarSeriesPrivate::barMargin() const
356 356 {
357 357 return m_barMargin;
358 358 }
359 359
360 360 QBarSet* QBarSeriesPrivate::barsetAt(int index)
361 361 {
362 362 return m_barSets.at(index);
363 363 }
364 364
365 365 void QBarSeriesPrivate::setVisible(bool visible)
366 366 {
367 367 m_visible = visible;
368 368 emit updatedBars();
369 369 }
370 370
371 371 void QBarSeriesPrivate::setLabelsVisible(bool visible)
372 372 {
373 373 m_labelsVisible = visible;
374 374 emit labelsVisibleChanged(visible);
375 375 }
376 376
377 377 QString QBarSeriesPrivate::categoryName(int category)
378 378 {
379 379 if ((category >= 0) && (category < m_categories.count())) {
380 380 return m_categories.at(category);
381 381 }
382 382
383 383 return QString::number(category);
384 384 }
385 385
386 386 qreal QBarSeriesPrivate::min()
387 387 {
388 388 if (m_barSets.count() <= 0) {
389 389 return 0;
390 390 }
391 391 qreal min = INT_MAX;
392 392
393 393 for (int i = 0; i < m_barSets.count(); i++) {
394 394 int categoryCount = m_barSets.at(i)->count();
395 395 for (int j = 0; j < categoryCount; j++) {
396 396 qreal temp = m_barSets.at(i)->at(j).y();
397 397 if (temp < min)
398 398 min = temp;
399 399 }
400 400 }
401 401 return min;
402 402 }
403 403
404 404 qreal QBarSeriesPrivate::max()
405 405 {
406 406 if (m_barSets.count() <= 0) {
407 407 return 0;
408 408 }
409 409 qreal max = INT_MIN;
410 410
411 411 for (int i = 0; i < m_barSets.count(); i++) {
412 412 int categoryCount = m_barSets.at(i)->count();
413 413 for (int j = 0; j < categoryCount; j++) {
414 414 qreal temp = m_barSets.at(i)->at(j).y();
415 415 if (temp > max)
416 416 max = temp;
417 417 }
418 418 }
419 419
420 420 return max;
421 421 }
422 422
423 423 qreal QBarSeriesPrivate::valueAt(int set, int category)
424 424 {
425 425 if ((set < 0) || (set >= m_barSets.count())) {
426 426 // No set, no value.
427 427 return 0;
428 428 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
429 429 // No category, no value.
430 430 return 0;
431 431 }
432 432
433 433 return m_barSets.at(set)->at(category).y();
434 434 }
435 435
436 436 qreal QBarSeriesPrivate::percentageAt(int set, int category)
437 437 {
438 438 if ((set < 0) || (set >= m_barSets.count())) {
439 439 // No set, no value.
440 440 return 0;
441 441 } else if ((category < 0) || (category >= m_barSets.at(set)->count())) {
442 442 // No category, no value.
443 443 return 0;
444 444 }
445 445
446 446 qreal value = m_barSets.at(set)->at(category).y();
447 447 qreal sum = categorySum(category);
448 448 if ( qFuzzyIsNull(sum) ) {
449 449 return 0;
450 450 }
451 451
452 452 return value / sum;
453 453 }
454 454
455 455 qreal QBarSeriesPrivate::categorySum(int category)
456 456 {
457 457 qreal sum(0);
458 458 int count = m_barSets.count(); // Count sets
459 459 for (int set = 0; set < count; set++) {
460 460 if (category < m_barSets.at(set)->count())
461 461 sum += m_barSets.at(set)->at(category).y();
462 462 }
463 463 return sum;
464 464 }
465 465
466 466 qreal QBarSeriesPrivate::absoluteCategorySum(int category)
467 467 {
468 468 qreal sum(0);
469 469 int count = m_barSets.count(); // Count sets
470 470 for (int set = 0; set < count; set++) {
471 471 if (category < m_barSets.at(set)->count())
472 472 sum += qAbs(m_barSets.at(set)->at(category).y());
473 473 }
474 474 return sum;
475 475 }
476 476
477 477 qreal QBarSeriesPrivate::maxCategorySum()
478 478 {
479 479 qreal max = INT_MIN;
480 480 int count = categoryCount();
481 481 for (int i = 0; i < count; i++) {
482 482 qreal sum = categorySum(i);
483 483 if (sum > max)
484 484 max = sum;
485 485 }
486 486 return max;
487 487 }
488 488
489 489 void QBarSeriesPrivate::scaleDomain(Domain& domain)
490 490 {
491 491 qreal minX(domain.minX());
492 492 qreal minY(domain.minY());
493 493 qreal maxX(domain.maxX());
494 494 qreal maxY(domain.maxY());
495 495 int tickXCount(domain.tickXCount());
496 496 int tickYCount(domain.tickYCount());
497 497
498 498 qreal x = categoryCount();
499 499 qreal y = max();
500 500 minX = qMin(minX, x) - 0.5;
501 501 minY = qMin(minY, y);
502 maxX = qMax(maxX, x) - 0.5;
502 maxX = qMax(maxX, x) + 0.5;
503 503 maxY = qMax(maxY, y);
504 504 tickXCount = x+1;
505 505
506 506 domain.setRange(minX,maxX,minY,maxY,tickXCount,tickYCount);
507 507 }
508 508
509 509 Chart* QBarSeriesPrivate::createGraphics(ChartPresenter* presenter)
510 510 {
511 511 Q_Q(QBarSeries);
512 512
513 513 BarChartItem* bar = new BarChartItem(q,presenter);
514 514 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
515 515 presenter->animator()->addAnimation(bar);
516 516 }
517 517 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
518 518 return bar;
519 519
520 520 }
521 521
522 522 QList<LegendMarker*> QBarSeriesPrivate::createLegendMarker(QLegend* legend)
523 523 {
524 524 Q_Q(QBarSeries);
525 525 QList<LegendMarker*> markers;
526 526 foreach(QBarSet* set, q->barSets()) {
527 527 BarLegendMarker* marker = new BarLegendMarker(q,set,legend);
528 528 markers << marker;
529 529 }
530 530
531 531 return markers;
532 532 }
533 533
534 534 bool QBarSeriesPrivate::append(QBarSet *set)
535 535 {
536 536 Q_Q(QBarSeries);
537 537 if ((m_barSets.contains(set)) || (set == 0)) {
538 538 // Fail if set is already in list or set is null.
539 539 return false;
540 540 }
541 541 m_barSets.append(set);
542 542 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
543 543 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
544 544 if (m_dataset) {
545 545 m_dataset->updateSeries(q); // this notifies legend
546 546 }
547 547 emit restructuredBars(); // this notifies barchartitem
548 548 return true;
549 549 }
550 550
551 551 bool QBarSeriesPrivate::remove(QBarSet *set)
552 552 {
553 553 Q_Q(QBarSeries);
554 554 if (!m_barSets.contains(set)) {
555 555 // Fail if set is not in list
556 556 return false;
557 557 }
558 558 m_barSets.removeOne(set);
559 559 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
560 560 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
561 561 if (m_dataset) {
562 562 m_dataset->updateSeries(q); // this notifies legend
563 563 }
564 564 emit restructuredBars(); // this notifies barchartitem
565 565 return true;
566 566 }
567 567
568 568 bool QBarSeriesPrivate::append(QList<QBarSet* > sets)
569 569 {
570 570 Q_Q(QBarSeries);
571 571 foreach (QBarSet* set, sets) {
572 572 if ((set == 0) || (m_barSets.contains(set))) {
573 573 // Fail if any of the sets is null or is already appended.
574 574 return false;
575 575 }
576 576 if (sets.count(set) != 1) {
577 577 // Also fail if same set is more than once in given list.
578 578 return false;
579 579 }
580 580 }
581 581
582 582 foreach (QBarSet* set, sets) {
583 583 m_barSets.append(set);
584 584 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
585 585 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
586 586 }
587 587 if (m_dataset) {
588 588 m_dataset->updateSeries(q); // this notifies legend
589 589 }
590 590 emit restructuredBars(); // this notifies barchartitem
591 591 return true;
592 592 }
593 593
594 594 bool QBarSeriesPrivate::remove(QList<QBarSet* > sets)
595 595 {
596 596 Q_Q(QBarSeries);
597 597 if (sets.count() == 0) {
598 598 return false;
599 599 }
600 600 foreach (QBarSet* set, sets) {
601 601 if ((set == 0) || (!m_barSets.contains(set))) {
602 602 // Fail if any of the sets is null or is not in series
603 603 return false;
604 604 }
605 605 if (sets.count(set) != 1) {
606 606 // Also fail if same set is more than once in given list.
607 607 return false;
608 608 }
609 609 }
610 610
611 611 foreach (QBarSet* set, sets) {
612 612 m_barSets.removeOne(set);
613 613 QObject::disconnect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
614 614 QObject::disconnect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
615 615 }
616 616
617 617 if (m_dataset) {
618 618 m_dataset->updateSeries(q); // this notifies legend
619 619 }
620 620 emit restructuredBars(); // this notifies barchartitem
621 621 return true;
622 622 }
623 623
624 624 bool QBarSeriesPrivate::insert(int index, QBarSet *set)
625 625 {
626 626 Q_Q(QBarSeries);
627 627 if ((m_barSets.contains(set)) || (set == 0)) {
628 628 // Fail if set is already in list or set is null.
629 629 return false;
630 630 }
631 631 m_barSets.insert(index, set);
632 632 QObject::connect(set->d_ptr.data(), SIGNAL(updatedBars()), this, SIGNAL(updatedBars()));
633 633 QObject::connect(set->d_ptr.data(), SIGNAL(restructuredBars()), this, SIGNAL(restructuredBars()));
634 634 if (m_dataset) {
635 635 m_dataset->updateSeries(q); // this notifies legend
636 636 }
637 637 emit restructuredBars(); // this notifies barchartitem
638 638 return true;
639 639 }
640 640
641 641 #include "moc_qbarseries.cpp"
642 642 #include "moc_qbarseries_p.cpp"
643 643
644 644 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now