##// END OF EJS Templates
Fixes to model support
Marek Rosa -
r1060:9efd7b220dc4
parent child
Show More
@@ -1,863 +1,870
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 "pieslicedata_p.h"
25 25 #include "chartdataset_p.h"
26 26 #include "charttheme_p.h"
27 27 #include "chartanimator_p.h"
28 28 #include "legendmarker_p.h"
29 29 #include <QAbstractItemModel>
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 /*!
34 34 \class QPieSeries
35 35 \brief Pie series API for QtCommercial Charts
36 36
37 37 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
38 38 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
39 39 The actual slice size is determined by that relative value.
40 40
41 41 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
42 42 These relate to the actual chart rectangle.
43 43
44 44 By default the pie is defined as a full pie but it can also be a partial pie.
45 45 This can be done by setting a starting angle and angle span to the series.
46 46 Full pie is 360 degrees where 0 is at 12 a'clock.
47 47
48 48 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
49 49 \image examples_piechart.png
50 50 */
51 51
52 52 /*!
53 53 \property QPieSeries::horizontalPosition
54 54 \brief Defines the horizontal position of the pie.
55 55
56 56 The value is a relative value to the chart rectangle where:
57 57
58 58 \list
59 59 \o 0.0 is the absolute left.
60 60 \o 1.0 is the absolute right.
61 61 \endlist
62 62
63 63 Default value is 0.5 (center).
64 64 */
65 65
66 66 /*!
67 67 \property QPieSeries::verticalPosition
68 68 \brief Defines the vertical position of the pie.
69 69
70 70 The value is a relative value to the chart rectangle where:
71 71
72 72 \list
73 73 \o 0.0 is the absolute top.
74 74 \o 1.0 is the absolute bottom.
75 75 \endlist
76 76
77 77 Default value is 0.5 (center).
78 78 */
79 79
80 80 /*!
81 81 \property QPieSeries::size
82 82 \brief Defines the pie size.
83 83
84 84 The value is a relative value to the chart rectangle where:
85 85
86 86 \list
87 87 \o 0.0 is the minimum size (pie not drawn).
88 88 \o 1.0 is the maximum size that can fit the chart.
89 89 \endlist
90 90
91 91 Default value is 0.7.
92 92 */
93 93
94 94 /*!
95 95 \property QPieSeries::startAngle
96 96 \brief Defines the starting angle of the pie.
97 97
98 98 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
99 99
100 100 Default is value is 0.
101 101 */
102 102
103 103 /*!
104 104 \property QPieSeries::endAngle
105 105 \brief Defines the ending angle of the pie.
106 106
107 107 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
108 108
109 109 Default is value is 360.
110 110 */
111 111
112 112
113 113 /*!
114 114 Constructs a series object which is a child of \a parent.
115 115 */
116 116 QPieSeries::QPieSeries(QObject *parent) :
117 117 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
118 118 {
119 119
120 120 }
121 121
122 122 /*!
123 123 Destroys the series and its slices.
124 124 */
125 125 QPieSeries::~QPieSeries()
126 126 {
127 127 // NOTE: d_prt destroyed by QObject
128 128 }
129 129
130 130 /*!
131 131 Returns QChartSeries::SeriesTypePie.
132 132 */
133 133 QAbstractSeries::QSeriesType QPieSeries::type() const
134 134 {
135 135 return QAbstractSeries::SeriesTypePie;
136 136 }
137 137
138 138 /*!
139 139 Appends an array of \a slices to the series.
140 140 Slice ownership is passed to the series.
141 141 */
142 142 void QPieSeries::append(QList<QPieSlice*> slices)
143 143 {
144 144 Q_D(QPieSeries);
145 145
146 146 foreach (QPieSlice* s, slices) {
147 147 s->setParent(this);
148 148 d->m_slices << s;
149 149 }
150 150
151 151 d->updateDerivativeData();
152 152
153 153 foreach (QPieSlice* s, slices) {
154 154 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
155 155 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
156 156 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
157 157 }
158 158
159 159 emit d->added(slices);
160 160 }
161 161
162 162 /*!
163 163 Appends a single \a slice to the series.
164 164 Slice ownership is passed to the series.
165 165 */
166 166 void QPieSeries::append(QPieSlice* slice)
167 167 {
168 168 append(QList<QPieSlice*>() << slice);
169 169 }
170 170
171 171 /*!
172 172 Appends a single \a slice to the series and returns a reference to the series.
173 173 Slice ownership is passed to the series.
174 174 */
175 175 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
176 176 {
177 177 append(slice);
178 178 return *this;
179 179 }
180 180
181 181
182 182 /*!
183 183 Appends a single slice to the series with give \a value and \a name.
184 184 Slice ownership is passed to the series.
185 185 */
186 186 QPieSlice* QPieSeries::append(qreal value, QString name)
187 187 {
188 188 QPieSlice* slice = new QPieSlice(value, name);
189 189 append(slice);
190 190 return slice;
191 191 }
192 192
193 193 /*!
194 194 Inserts a single \a slice to the series before the slice at \a index position.
195 195 Slice ownership is passed to the series.
196 196 */
197 197 void QPieSeries::insert(int index, QPieSlice* slice)
198 198 {
199 199 Q_D(QPieSeries);
200 200 Q_ASSERT(index <= d->m_slices.count());
201 201 slice->setParent(this);
202 202 d->m_slices.insert(index, slice);
203 203
204 204 d->updateDerivativeData();
205 205
206 206 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
207 207 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
208 208 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
209 209
210 210 emit d->added(QList<QPieSlice*>() << slice);
211 211 }
212 212
213 213 /*!
214 214 Removes a single \a slice from the series and deletes the slice.
215 215
216 216 Do not reference the pointer after this call.
217 217 */
218 218 void QPieSeries::remove(QPieSlice* slice)
219 219 {
220 220 Q_D(QPieSeries);
221 221 if (!d->m_slices.removeOne(slice)) {
222 222 Q_ASSERT(0); // TODO: how should this be reported?
223 223 return;
224 224 }
225 225
226 226 d->updateDerivativeData();
227 227
228 228 emit d->removed(QList<QPieSlice*>() << slice);
229 229
230 230 delete slice;
231 231 slice = 0;
232 232 }
233 233
234 234 /*!
235 235 Clears all slices from the series.
236 236 */
237 237 void QPieSeries::clear()
238 238 {
239 239 Q_D(QPieSeries);
240 240 if (d->m_slices.count() == 0)
241 241 return;
242 242
243 243 QList<QPieSlice*> slices = d->m_slices;
244 244 foreach (QPieSlice* s, d->m_slices) {
245 245 d->m_slices.removeOne(s);
246 246 delete s;
247 247 }
248 248
249 249 d->updateDerivativeData();
250 250
251 251 emit d->removed(slices);
252 252 }
253 253
254 254 /*!
255 255 returns the number of the slices in this series.
256 256 */
257 257 int QPieSeries::count() const
258 258 {
259 259 Q_D(const QPieSeries);
260 260 return d->m_slices.count();
261 261 }
262 262
263 263 /*!
264 264 Returns true is the series is empty.
265 265 */
266 266 bool QPieSeries::isEmpty() const
267 267 {
268 268 Q_D(const QPieSeries);
269 269 return d->m_slices.isEmpty();
270 270 }
271 271
272 272 /*!
273 273 Returns a list of slices that belong to this series.
274 274 */
275 275 QList<QPieSlice*> QPieSeries::slices() const
276 276 {
277 277 Q_D(const QPieSeries);
278 278 return d->m_slices;
279 279 }
280 280
281 281 void QPieSeries::setHorizontalPosition(qreal relativePosition)
282 282 {
283 283 Q_D(QPieSeries);
284 284 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
285 285 emit d->piePositionChanged();
286 286 }
287 287
288 288 void QPieSeries::setVerticalPosition(qreal relativePosition)
289 289 {
290 290 Q_D(QPieSeries);
291 291 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
292 292 emit d->piePositionChanged();
293 293 }
294 294
295 295 qreal QPieSeries::horizontalPosition() const
296 296 {
297 297 Q_D(const QPieSeries);
298 298 return d->m_pieRelativeHorPos;
299 299 }
300 300
301 301 qreal QPieSeries::verticalPosition() const
302 302 {
303 303 Q_D(const QPieSeries);
304 304 return d->m_pieRelativeVerPos;
305 305 }
306 306
307 307 void QPieSeries::setPieSize(qreal relativeSize)
308 308 {
309 309 Q_D(QPieSeries);
310 310 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
311 311 emit d->pieSizeChanged();
312 312 }
313 313
314 314 qreal QPieSeries::pieSize() const
315 315 {
316 316 Q_D(const QPieSeries);
317 317 return d->m_pieRelativeSize;
318 318 }
319 319
320 320
321 321 void QPieSeries::setPieStartAngle(qreal angle)
322 322 {
323 323 Q_D(QPieSeries);
324 324 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
325 325 d->updateDerivativeData();
326 326 }
327 327
328 328 qreal QPieSeries::pieStartAngle() const
329 329 {
330 330 Q_D(const QPieSeries);
331 331 return d->m_pieStartAngle;
332 332 }
333 333
334 334 /*!
335 335 Sets the end angle of the pie.
336 336
337 337 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
338 338
339 339 \a angle must be greater than start angle.
340 340
341 341 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
342 342 */
343 343 void QPieSeries::setPieEndAngle(qreal angle)
344 344 {
345 345 Q_D(QPieSeries);
346 346
347 347 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
348 348 d->updateDerivativeData();
349 349 }
350 350
351 351 /*!
352 352 Returns the end angle of the pie.
353 353
354 354 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
355 355
356 356 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
357 357 */
358 358 qreal QPieSeries::pieEndAngle() const
359 359 {
360 360 Q_D(const QPieSeries);
361 361 return d->m_pieEndAngle;
362 362 }
363 363
364 364 /*!
365 365 Sets the all the slice labels \a visible or invisible.
366 366
367 367 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
368 368 */
369 369 void QPieSeries::setLabelsVisible(bool visible)
370 370 {
371 371 Q_D(QPieSeries);
372 372 foreach (QPieSlice* s, d->m_slices)
373 373 s->setLabelVisible(visible);
374 374 }
375 375
376 376 /*!
377 377 Returns the sum of all slice values in this series.
378 378
379 379 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
380 380 */
381 381 qreal QPieSeries::sum() const
382 382 {
383 383 Q_D(const QPieSeries);
384 384 return d->m_sum;
385 385 }
386 386
387 387 /*!
388 388 \fn void QPieSeries::clicked(QPieSlice* slice)
389 389
390 390 This signal is emitted when a \a slice has been clicked.
391 391
392 392 \sa QPieSlice::clicked()
393 393 */
394 394
395 395 /*!
396 396 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
397 397
398 398 This signal is emitted when user has hovered over or away from the \a slice.
399 399
400 400 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
401 401
402 402 \sa QPieSlice::hovered()
403 403 */
404 404
405 405 /*!
406 406 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
407 407 Sets the \a model to be used as a data source
408 408 */
409 409 bool QPieSeries::setModel(QAbstractItemModel* model)
410 410 {
411 411 Q_D(QPieSeries);
412 412 // disconnect signals from old model
413 413 if(d->m_model)
414 414 {
415 415 disconnect(d->m_model, 0, this, 0);
416 416 d->m_mapValues = -1;
417 417 d->m_mapLabels = -1;
418 418 d->m_mapOrientation = Qt::Vertical;
419 419 }
420 420
421 421 // set new model
422 422 if(model)
423 423 {
424 424 d->m_model = model;
425 425 return true;
426 426 }
427 427 else
428 428 {
429 429 d->m_model = 0;
430 430 return false;
431 431 }
432 432 }
433 433
434 434 /*!
435 435 \fn bool QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
436 436 Sets column/row specified by \a modelValuesLine to be used as a list of pie slice values for the pie.
437 437 Parameter \a modelValuesLine indicates the column/row where the values for the pie slices are located in the model.
438 438 Parameter \a modelLabelsLine indicates the column/row where the labels for the pie slices are located in the model.
439 439 The \a orientation parameter specifies whether the data is in columns or in rows.
440 440 */
441 441 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
442 442 {
443 443 Q_D(QPieSeries);
444 444
445 445 if (d->m_model == 0)
446 446 return;
447 447
448 448 d->m_mapValues = modelValuesLine;
449 449 d->m_mapLabels = modelLabelsLine;
450 450 d->m_mapOrientation = orientation;
451 451
452 452 d->initializePieFromModel();
453 453 // // connect the signals
454 454 // connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
455 455
456 456
457 457 // // create the initial slices set
458 458 // if (d->m_mapOrientation == Qt::Vertical) {
459 459 // for (int i = 0; i < d->m_model->rowCount(); i++)
460 460 // append(d->m_model->data(d->m_model->index(i, d->m_mapValues), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(i, d->m_mapLabels), Qt::DisplayRole).toString());
461 461 // } else {
462 462 // for (int i = 0; i < d->m_model->columnCount(); i++)
463 463 // append(d->m_model->data(d->m_model->index(d->m_mapValues, i), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(d->m_mapLabels, i), Qt::DisplayRole).toString());
464 464 // }
465 465 }
466 466
467 467 void QPieSeries::setModelMappingRange(int first, int count)
468 468 {
469 469 Q_D(QPieSeries);
470 470 d->m_mapFirst = first;
471 471 d->m_mapCount = count;
472 472 }
473 473
474 474 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
475 475
476 476
477 477 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
478 478 QAbstractSeriesPrivate(parent),
479 479 m_pieRelativeHorPos(0.5),
480 480 m_pieRelativeVerPos(0.5),
481 481 m_pieRelativeSize(0.7),
482 482 m_pieStartAngle(0),
483 483 m_pieEndAngle(360),
484 484 m_sum(0),
485 485 m_mapValues(0),
486 486 m_mapLabels(0)
487 487 {
488 488
489 489 }
490 490
491 491 QPieSeriesPrivate::~QPieSeriesPrivate()
492 492 {
493 493
494 494 }
495 495
496 496 void QPieSeriesPrivate::updateDerivativeData()
497 497 {
498 498 m_sum = 0;
499 499
500 500 // nothing to do?
501 501 if (m_slices.count() == 0)
502 502 return;
503 503
504 504 // calculate sum of all slices
505 505 foreach (QPieSlice* s, m_slices)
506 506 m_sum += s->value();
507 507
508 508 // nothing to show..
509 509 if (qFuzzyIsNull(m_sum))
510 510 return;
511 511
512 512 // update slice attributes
513 513 qreal sliceAngle = m_pieStartAngle;
514 514 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
515 515 QVector<QPieSlice*> changed;
516 516 foreach (QPieSlice* s, m_slices) {
517 517
518 518 PieSliceData data = PieSliceData::data(s);
519 519 data.m_percentage = s->value() / m_sum;
520 520 data.m_angleSpan = pieSpan * data.m_percentage;
521 521 data.m_startAngle = sliceAngle;
522 522 sliceAngle += data.m_angleSpan;
523 523
524 524 if (PieSliceData::data(s) != data) {
525 525 PieSliceData::data(s) = data;
526 526 changed << s;
527 527 }
528 528 }
529 529
530 530 // emit signals
531 531 foreach (QPieSlice* s, changed)
532 532 PieSliceData::data(s).emitChangedSignal(s);
533 533 }
534 534
535 535 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
536 536 {
537 537 return series.d_func();
538 538 }
539 539
540 540 void QPieSeriesPrivate::sliceChanged()
541 541 {
542 542 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
543 543 updateDerivativeData();
544 544 }
545 545
546 546 void QPieSeriesPrivate::sliceClicked()
547 547 {
548 548 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
549 549 Q_ASSERT(m_slices.contains(slice));
550 550 Q_Q(QPieSeries);
551 551 emit q->clicked(slice);
552 552 }
553 553
554 554 void QPieSeriesPrivate::sliceHovered(bool state)
555 555 {
556 556 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
557 557 Q_ASSERT(m_slices.contains(slice));
558 558 Q_Q(QPieSeries);
559 559 emit q->hovered(slice, state);
560 560 }
561 561
562 562 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
563 563 {
564 564 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
565 565 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
566 566 if (m_mapOrientation == Qt::Vertical)
567 567 {
568 568 if ( topLeft.row() >= m_mapFirst && (m_mapCount == - 1 || topLeft.row() < m_mapFirst + m_mapCount)) {
569 569 if (topLeft.column() == m_mapValues)
570 570 m_slices.at(topLeft.row() - m_mapFirst)->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
571 571 if (topLeft.column() == m_mapLabels)
572 572 m_slices.at(topLeft.row() - m_mapFirst)->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
573 573 }
574 574 }
575 575 else
576 576 {
577 577 if (topLeft.column() >= m_mapFirst && (m_mapCount == - 1 || topLeft.column() < m_mapFirst + m_mapCount)) {
578 578 if (topLeft.row() == m_mapValues)
579 579 m_slices.at(topLeft.column() - m_mapFirst)->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
580 580 if (topLeft.row() == m_mapLabels)
581 581 m_slices.at(topLeft.column() - m_mapFirst)->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
582 582 }
583 583 }
584 584 }
585 585 }
586 586 }
587 587
588 588
589 589 void QPieSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
590 590 {
591 591 Q_UNUSED(parent);
592 592 Q_Q(QPieSeries);
593 593 // series uses model as a data sourceupda
594 int addedCount = end - start + 1;
595 594 if (m_mapCount != -1 && start >= m_mapFirst + m_mapCount) {
596 595 return;
597 596 } else {
597 int addedCount = end - start + 1;
598 if (m_mapCount != -1 && addedCount > m_mapCount)
599 addedCount = m_mapCount;
598 600 int first = qMax(start, m_mapFirst);
599 int last = qMin(first + addedCount - 1, end);
601 int last = qMin(first + addedCount - 1, m_mapOrientation == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
600 602 for (int i = first; i <= last; i++) {
601 603 QPieSlice *slice = new QPieSlice;
602 604 if (m_mapOrientation == Qt::Vertical) {
603 605 slice->setValue(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble());
604 606 slice->setLabel(m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
605 607 } else {
606 608 slice->setValue(m_model->data(m_model->index(m_mapValues, i), Qt::DisplayRole).toDouble());
607 609 slice->setLabel(m_model->data(m_model->index(m_mapLabels, i), Qt::DisplayRole).toString());
608 610 }
609 611 slice->setLabelVisible();
610 612 q->insert(i - m_mapFirst, slice);
611 613 }
612 614 if (m_mapCount != -1 && m_slices.size() > m_mapCount)
613 615 for (int i = m_slices.size() - 1; i >= m_mapCount; i--)
614 616 q->remove(q->slices().at(i));
615 617 }
616 618
617 619 // // adding items to unlimited map
618 620 // else if (m_mapCount == -1 && start >= m_mapFirst) {
619 621 // for (int i = start; i <= end; i++) {
620 622 // QPieSlice *slice = new QPieSlice;
621 623 // slice->setValue(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble());
622 624 // slice->setLabel(m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
623 625 // slice->setLabelVisible(true);
624 626 // q->insert(i - m_mapFirst, slice);
625 627 // // handlePointAdded(i - first);
626 628 // }
627 629 // } else if (m_mapCount == - 1 && start < m_mapFirst) {
628 630 // // not all newly added items
629 631 // for (int i = m_mapFirst; i < m_mapFirst + addedCount; i++) {
630 632 // QPieSlice *slice = new QPieSlice;
631 633 // slice->setValue(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble());
632 634 // slice->setLabel(m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
633 635 // slice->setLabelVisible(true);
634 636 // q->insert(i - m_mapFirst, slice);
635 637 // // handlePointAdded(i - first);
636 638 // }
637 639 // }
638 640
639 641 // // adding items to limited map
640 642 // else if (start >= m_mapFirst) {
641 643 // // remove the items that will no longer fit into the map
642 644 // // int toRemove = addedCount - (count - points().size());
643 645 // for (int i = start; i <= end; i++) {
644 646 // QPieSlice *slice = new QPieSlice;
645 647 // slice->setValue(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble());
646 648 // slice->setLabel(m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
647 649 // slice->setLabelVisible(true);
648 650 // q->insert(i - m_mapFirst, slice);
649 651 // }
650 652 // if (m_slices.size() > m_mapCount)
651 653 // for (int i = m_slices.size() - 1; i >= m_mapCount; i--)
652 654 // q->remove(q->slices().at(i));
653 655 // // handlePointRemoved(i);
654 656 // // update();
655 657 // } else {
656 658 // //
657 659 // for (int i = m_mapFirst; i < m_mapFirst + addedCount; i++) {
658 660 // QPieSlice *slice = new QPieSlice;
659 661 // slice->setValue(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble());
660 662 // slice->setLabel(m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
661 663 // slice->setLabelVisible(true);
662 664 // q->insert(i - m_mapFirst, slice);
663 665 // // handlePointAdded(i - first);
664 666 // }
665 667 // if (m_slices.size() > m_mapCount)
666 668 // for (int i = m_slices.size() - 1; i >= m_mapCount; i--)
667 669 // q->remove(q->slices().at(i));
668 670 // // handlePointRemoved(i);
669 671 // }
670 672 }
671 673
672 674 void QPieSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
673 675 {
674 676 Q_UNUSED(parent);
675 677 Q_Q(QPieSeries);
676 678 int removedCount = end - start + 1;
677 679 if (m_mapCount != -1 && start >= m_mapFirst + m_mapCount) {
678 680 return;
679 681 }
680 682
681 683 // else if (m_mapCount == -1) {
684 // // first find how many items can actually be removed
685 // int toRemove = qMin(m_slices.size(), removedCount);
686 // // get the index of the first item that will be removed.
682 687 // int first = qMax(start, m_mapFirst);
683 // int last = qMax(end, m_mapFirst + removedCount - 1);
684 // for (int i = last; i >= first; i--)
688 // // get the index of the last item that will be removed.
689 // int last = first + toRemove;
690 // for (int i = last - 1; i >= first; i--)
685 691 // q->remove(q->slices().at(i - m_mapFirst));
686 692 // }
687 693 // else {
688 694 // int toRemove = qMin(m_slices.size() - 1, removedCount);
689 695 // int first = qMax(start, m_mapFirst);
690 696 // int last = qMax(end, m_mapFirst + toRemove - 1);
691 697
692 698 // }
693 699
694 700 // removing items from unlimited map
695 701 else if (m_mapCount == -1 && start >= m_mapFirst) {
696 702 for (int i = end; i >= start; i--)
697 703 q->remove(q->slices().at(i - m_mapFirst));
698 704 // handlePointRemoved(i - m_mapFirst);
699 705 } else if (m_mapCount == - 1 && start < m_mapFirst) {
700 706 // not all removed items
701 for (int i = m_mapFirst + removedCount - 1; i >= m_mapFirst; i--)
707 int lastExisting = qMin(m_mapFirst + m_slices.size() - 1, m_mapFirst + removedCount - 1);
708 for (int i = lastExisting; i >= m_mapFirst; i--)
702 709 q->remove(q->slices().at(i - m_mapFirst));
703 710 // handlePointRemoved(i - m_mapFirst);
704 711 }
705 712
706 713 // removing items from limited map
707 714 else if (start >= m_mapFirst) {
708 715 //
709 716 // int sizeAfter = m_slices.size();
710 717 int lastExisting = qMin(m_mapFirst + m_slices.size() - 1, end);
711 718 for (int i = lastExisting; i >= start; i--) {
712 719 q->remove(q->slices().at(i - m_mapFirst));
713 720 // sizeAfter--;
714 721 // handlePointRemoved(i - m_mapFirst);
715 722 }
716 723
717 724 // the map is limited, so after removing the items some new items may have fall within the mapped area
718 725 int itemsAvailable;
719 726 if (m_mapOrientation == Qt::Vertical)
720 727 itemsAvailable = m_model->rowCount() - m_mapFirst - m_slices.size();
721 728 else
722 729 itemsAvailable = m_model->columnCount() - m_mapFirst - m_slices.size();
723 730 int toBeAdded = qMin(itemsAvailable, m_mapCount - m_slices.size());
724 731 int currentSize = m_slices.size();
725 732 if (itemsAvailable > 0)
726 733 for (int i = m_slices.size() + m_mapFirst; i < currentSize + toBeAdded + m_mapFirst; i++) {
727 734 // handlePointAdded(i);
728 735 QPieSlice *slice = new QPieSlice;
729 736 slice->setValue(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble());
730 737 slice->setLabel(m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
731 738 slice->setLabelVisible(true);
732 739 q->insert(i - m_mapFirst, slice);
733 740 }
734 741
735 742 // for (int i = lastExisting; i >= start; i--) {
736 743 // q->remove(q->slices().at(i - m_mapFirst));
737 744 //// sizeAfter--;
738 745 //// handlePointRemoved(i - m_mapFirst);
739 746 // }
740 747 } else {
741 748 // first remove item lays before the mapped area
742 749 int toRemove = qMin(m_slices.size(), removedCount);
743 750 for (int i = m_mapFirst; i < m_mapFirst + toRemove; i++)
744 751 q->remove(q->slices().at(0));
745 752 // handlePointRemoved(0);
746 753
747 754 // the map is limited, so after removing the items some new items may have fall into the map
748 755 int itemsAvailable;
749 756 if (m_mapOrientation == Qt::Vertical)
750 757 itemsAvailable = m_model->rowCount() - m_mapFirst - m_slices.size();
751 758 else
752 759 itemsAvailable = m_model->columnCount() - m_mapFirst - m_slices.size();
753 760 int toBeAdded = qMin(itemsAvailable, m_mapCount - m_slices.size());
754 761 int currentSize = m_slices.size();
755 762 if (itemsAvailable > 0)
756 763 for (int i = m_slices.size(); i < currentSize + toBeAdded; i++) {
757 764 QPieSlice *slice = new QPieSlice;
758 765 slice->setValue(m_model->data(m_model->index(i + m_mapFirst, m_mapValues), Qt::DisplayRole).toDouble());
759 766 slice->setLabel(m_model->data(m_model->index(i + m_mapFirst, m_mapLabels), Qt::DisplayRole).toString());
760 767 slice->setLabelVisible(true);
761 768 q->insert(i, slice);
762 769 // handlePointAdded(i);
763 770 }
764 771 }
765 772
766 773 }
767 774
768 775 void QPieSeriesPrivate::initializePieFromModel()
769 776 {
770 777 Q_Q(QPieSeries);
771 778 // clear current content
772 779 q->clear();
773 780
774 781 // connect the signals
775 782 connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
776 783 if (m_mapOrientation == Qt::Vertical) {
777 784 connect(m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
778 785 connect(m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
779 786 } else {
780 787 connect(m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
781 788 connect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
782 789 }
783 790
784 791 // create the initial slices set
785 792 if (m_mapOrientation == Qt::Vertical) {
786 793 int sliceCount = 0;
787 794 if(m_mapCount == -1)
788 795 sliceCount = m_model->rowCount() - m_mapFirst;
789 796 else
790 797 sliceCount = qMin(m_mapCount, m_model->rowCount() - m_mapFirst);
791 798 for (int i = m_mapFirst; i < m_mapFirst + sliceCount; i++)
792 799 q->append(m_model->data(m_model->index(i, m_mapValues), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, m_mapLabels), Qt::DisplayRole).toString());
793 800 } else {
794 801 int sliceCount = 0;
795 802 if(m_mapCount == -1)
796 803 sliceCount = m_model->columnCount() - m_mapFirst;
797 804 else
798 805 sliceCount = qMin(m_mapCount, m_model->columnCount() - m_mapFirst);
799 806 for (int i = m_mapFirst; i < m_mapFirst + sliceCount; i++)
800 807 q->append(m_model->data(m_model->index(m_mapValues, i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(m_mapLabels, i), Qt::DisplayRole).toString());
801 808 }
802 809 }
803 810
804 811 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
805 812 {
806 813 // Remove rounding errors
807 814 qreal roundedValue = newValue;
808 815 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
809 816 roundedValue = 0.0;
810 817 else if (qFuzzyCompare(newValue, max))
811 818 roundedValue = max;
812 819 else if (qFuzzyCompare(newValue, min))
813 820 roundedValue = min;
814 821
815 822 // Check if the position is valid after removing the rounding errors
816 823 if (roundedValue < min || roundedValue > max) {
817 824 qWarning("QPieSeries: Illegal value");
818 825 return false;
819 826 }
820 827
821 828 if (!qFuzzyIsNull(value - roundedValue)) {
822 829 value = roundedValue;
823 830 return true;
824 831 }
825 832
826 833 // The change was so small it is considered a rounding error
827 834 return false;
828 835 }
829 836
830 837 void QPieSeriesPrivate::scaleDomain(Domain& domain)
831 838 {
832 839 Q_UNUSED(domain);
833 840 #ifndef QT_NO_DEBUG
834 841 qWarning() << __FILE__<<__FUNCTION__<<"not implemented";
835 842 #endif
836 843 }
837 844
838 845 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
839 846 {
840 847 Q_Q(QPieSeries);
841 848 PieChartItem* pie = new PieChartItem(q,presenter);
842 849 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
843 850 presenter->animator()->addAnimation(pie);
844 851 }
845 852 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
846 853 return pie;
847 854 }
848 855
849 856 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
850 857 {
851 858 Q_Q(QPieSeries);
852 859 QList<LegendMarker*> markers;
853 860 foreach(QPieSlice* slice, q->slices()) {
854 861 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
855 862 markers << marker;
856 863 }
857 864 return markers;
858 865 }
859 866
860 867 #include "moc_qpieseries.cpp"
861 868 #include "moc_qpieseries_p.cpp"
862 869
863 870 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,457 +1,458
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 "qxyseries.h"
22 22 #include "qxyseries_p.h"
23 23 #include "domain_p.h"
24 24 #include "legendmarker_p.h"
25 25 #include <QAbstractItemModel>
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 /*!
30 30 \class QXYSeries
31 31 \brief The QXYSeries class is a base class for line, spline and scatter series.
32 32 */
33 33
34 34 /*!
35 35 \fn QPen QXYSeries::pen() const
36 36 \brief Returns pen used to draw points for series.
37 37 \sa setPen()
38 38 */
39 39
40 40 /*!
41 41 \fn QBrush QXYSeries::brush() const
42 42 \brief Returns brush used to draw points for series.
43 43 \sa setBrush()
44 44 */
45 45
46 46 /*!
47 47 \fn void QXYSeries::clicked(const QPointF& point)
48 48 \brief Signal is emitted when user clicks the \a point on chart.
49 49 */
50 50
51 51 /*!
52 52 \fn void QXYSeries::selected()
53 53
54 54 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
55 55 implemented by the user of QXYSeries API.
56 56 */
57 57
58 58 /*!
59 59 \fn void QXYSeriesPrivate::pointReplaced(int index)
60 60 \brief \internal \a index
61 61 */
62 62
63 63 /*!
64 64 \fn void QXYSeriesPrivate::pointAdded(int index)
65 65 \brief \internal \a index
66 66 */
67 67
68 68 /*!
69 69 \fn void QXYSeriesPrivate::pointRemoved(int index)
70 70 \brief \internal \a index
71 71 */
72 72
73 73 /*!
74 74 \fn void QXYSeriesPrivate::updated()
75 75 \brief \internal
76 76 */
77 77
78 78 /*!
79 79 \internal
80 80
81 81 Constructs empty series object which is a child of \a parent.
82 82 When series object is added to QChartView or QChart instance ownerships is transferred.
83 83 */
84 84 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent) : QAbstractSeries(d, parent)
85 85 {
86 86
87 87 }
88 88 /*!
89 89 Destroys the object. Series added to QChartView or QChart instances are owned by those,
90 90 and are deleted when mentioned object are destroyed.
91 91 */
92 92 QXYSeries::~QXYSeries()
93 93 {
94 94 }
95 95
96 96 /*!
97 97 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
98 98 */
99 99 void QXYSeries::append(qreal x,qreal y)
100 100 {
101 101 append(QPointF(x,y));
102 102 }
103 103
104 104 /*!
105 105 This is an overloaded function.
106 106 Adds data \a point to the series. Points are connected with lines on the chart.
107 107 */
108 108 void QXYSeries::append(const QPointF &point)
109 109 {
110 110 Q_D(QXYSeries);
111 111 d->m_points<<point;
112 112 emit d->pointAdded(d->m_points.count()-1);
113 113 }
114 114
115 115 /*!
116 116 This is an overloaded function.
117 117 Adds list of data \a points to the series. Points are connected with lines on the chart.
118 118 */
119 119 void QXYSeries::append(const QList<QPointF> &points)
120 120 {
121 121 foreach(const QPointF& point , points) {
122 122 append(point);
123 123 }
124 124 }
125 125
126 126
127 127 void QXYSeries::replace(qreal oldX,qreal oldY,qreal newX,qreal newY)
128 128 {
129 129 replace(QPointF(oldX,oldY),QPointF(newX,newY));
130 130 }
131 131
132 132 void QXYSeries::replace(const QPointF &oldPoint,const QPointF &newPoint)
133 133 {
134 134 Q_D(QXYSeries);
135 135 int index = d->m_points.indexOf(oldPoint);
136 136 if(index==1) return;
137 137 d->m_points[index] = newPoint;
138 138 emit d->pointReplaced(index);
139 139 }
140 140
141 141 /*!
142 142 Removes current \a x and \a y value.
143 143 */
144 144 void QXYSeries::remove(qreal x,qreal y)
145 145 {
146 146 remove(QPointF(x,y));
147 147 }
148 148
149 149 /*!
150 150 Removes current \a point x value. Note \a point y value is ignored.
151 151 */
152 152 void QXYSeries::remove(const QPointF &point)
153 153 {
154 154 Q_D(QXYSeries);
155 155 int index = d->m_points.indexOf(point);
156 156 if(index==1) return;
157 157 d->m_points.remove(index);
158 158 emit d->pointRemoved(index);
159 159 }
160 160
161 161 /*!
162 162 Removes all data points from the series.
163 163 */
164 164 void QXYSeries::removeAll()
165 165 {
166 166 Q_D(QXYSeries);
167 167 foreach(const QPointF& point, d->m_points) {
168 168 remove(point);
169 169 }
170 170 }
171 171
172 172 /*!
173 173 \internal \a pos
174 174 */
175 175 QList<QPointF> QXYSeries::points() const
176 176 {
177 // Q_ASSERT(false);
177 178 Q_D(const QXYSeries);
178 179 if (d->m_model) {
179 180 QList<QPointF> result;
180 181 if (d->m_mapOrientation == Qt::Vertical){
181 182 // consecutive data is read from model's column
182 183
183 184 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
184 185 qreal x = d->m_model->data(d->m_model->index(i, d->m_mapX), Qt::DisplayRole).toReal();
185 186 qreal y = d->m_model->data(d->m_model->index(i, d->m_mapY), Qt::DisplayRole).toReal();
186 187 result << QPointF(x,y);
187 188 }
188 189 return result;
189 190 }
190 191 else{
191 192 // consecutive data is read from model's row
192 193 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
193 194 qreal x = d->m_model->data(d->m_model->index(d->m_mapX, i), Qt::DisplayRole).toReal();
194 195 qreal y = d->m_model->data(d->m_model->index(d->m_mapY, i), Qt::DisplayRole).toReal();
195 196 result << QPointF(x,y);
196 197 }
197 198 return result;
198 199 }
199 200 } else {
200 201 // model is not specified, return the data from series' internal data store
201 202 return d->m_points.toList();
202 203 }
203 204 }
204 205
205 206 /*!
206 207 Returns number of data points within series.
207 208 */
208 209 int QXYSeries::count() const
209 210 {
210 211 Q_D(const QXYSeries);
211 212
212 213 if (d->m_model) {
213 214 if (d->m_mapOrientation == Qt::Vertical) {
214 215 // data is in a column. Return the number of mapped items if the model's column have enough items
215 216 // or the number of items that can be mapped
216 217 if (d->m_mapCount != -1)
217 218 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
218 219 else
219 220 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
220 221 } else {
221 222 // data is in a row. Return the number of mapped items if the model's row have enough items
222 223 // or the number of items that can be mapped
223 224 if (d->m_mapCount != -1)
224 225 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
225 226 else
226 227 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
227 228 }
228 229 }
229 230
230 231 // model is not specified, return the number of points in the series internal data store
231 232 return d->m_points.count();
232 233 }
233 234
234 235
235 236 /*!
236 237 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
237 238 pen from chart theme is used.
238 239 \sa QChart::setTheme()
239 240 */
240 241 void QXYSeries::setPen(const QPen &pen)
241 242 {
242 243 Q_D(QXYSeries);
243 244 if (d->m_pen!=pen) {
244 245 d->m_pen = pen;
245 246 emit d->updated();
246 247 }
247 248 }
248 249
249 250 QPen QXYSeries::pen() const
250 251 {
251 252 Q_D(const QXYSeries);
252 253 return d->m_pen;
253 254 }
254 255
255 256 /*!
256 257 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
257 258 from chart theme setting is used.
258 259 \sa QChart::setTheme()
259 260 */
260 261 void QXYSeries::setBrush(const QBrush &brush)
261 262 {
262 263 Q_D(QXYSeries);
263 264 if (d->m_brush!=brush) {
264 265 d->m_brush = brush;
265 266 emit d->updated();
266 267 }
267 268 }
268 269
269 270 QBrush QXYSeries::brush() const
270 271 {
271 272 Q_D(const QXYSeries);
272 273 return d->m_brush;
273 274 }
274 275
275 276
276 277 /*!
277 278 Sets if data points are \a visible and should be drawn on line.
278 279 */
279 280 void QXYSeries::setPointsVisible(bool visible)
280 281 {
281 282 Q_D(QXYSeries);
282 283 if (d->m_pointsVisible != visible){
283 284 d->m_pointsVisible = visible;
284 285 emit d->updated();
285 286 }
286 287 }
287 288
288 289 /*!
289 290 Returns true if drawing the data points of the series is enabled.
290 291 */
291 292 bool QXYSeries::pointsVisible() const
292 293 {
293 294 Q_D(const QXYSeries);
294 295 return d->m_pointsVisible;
295 296 }
296 297
297 298
298 299 /*!
299 300 Stream operator for adding a data \a point to the series.
300 301 \sa append()
301 302 */
302 303 QXYSeries& QXYSeries::operator<< (const QPointF &point)
303 304 {
304 305 append(point);
305 306 return *this;
306 307 }
307 308
308 309
309 310 /*!
310 311 Stream operator for adding a list of \a points to the series.
311 312 \sa append()
312 313 */
313 314
314 315 QXYSeries& QXYSeries::operator<< (const QList<QPointF>& points)
315 316 {
316 317 append(points);
317 318 return *this;
318 319 }
319 320
320 321 /*!
321 322 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
322 323 Sets the \a model to be used as a data source
323 324 \sa setModelMapping()
324 325 */
325 326 bool QXYSeries::setModel(QAbstractItemModel *model)
326 327 {
327 328 Q_D(QXYSeries);
328 329 // disconnect signals from old model
329 330 if (d->m_model) {
330 331 QObject::disconnect(d->m_model, 0, this, 0);
331 332 d->m_mapX = -1;
332 333 d->m_mapY = -1;
333 334 d->m_mapOrientation = Qt::Vertical;
334 335 }
335 336
336 337 // set new model
337 338 if (model) {
338 339 d->m_model = model;
339 340 return true;
340 341 } else {
341 342 d->m_model = 0;
342 343 return false;
343 344 }
344 345 }
345 346
346 347 /*!
347 348 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
348 349 as a data source for y coordinate. The \a orientation parameter specifies whether the data
349 350 is in columns or in rows.
350 351 \sa setModel()
351 352 */
352 353 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
353 354 {
354 355 Q_D(QXYSeries);
355 356 if (d->m_model == 0)
356 357 return;
357 358 d->m_mapX = modelX;
358 359 d->m_mapY = modelY;
359 360 d->m_mapOrientation = orientation;
360 361
361 362 // connect the signals from the model
362 363 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
363 364 if (d->m_mapOrientation == Qt::Vertical) {
364 365 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
365 366 connect(d->m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
366 367 } else {
367 368 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
368 369 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
369 370 }
370 371 }
371 372
372 373 void QXYSeries::setModelMappingRange(int first, int count)
373 374 {
374 375 Q_D(QXYSeries);
375 376 d->m_mapFirst = first;
376 377 d->m_mapCount = count;
377 378 }
378 379
379 380 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
380 381
381 382
382 383 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q) : QAbstractSeriesPrivate(q),
383 384 m_mapX(-1),
384 385 m_mapY(-1),
385 386 m_pointsVisible(false)
386 387 {
387 388 }
388 389
389 390 void QXYSeriesPrivate::scaleDomain(Domain& domain)
390 391 {
391 392 qreal minX(domain.minX());
392 393 qreal minY(domain.minY());
393 394 qreal maxX(domain.maxX());
394 395 qreal maxY(domain.maxY());
395 396 int tickXCount(domain.tickXCount());
396 397 int tickYCount(domain.tickYCount());
397 398
398 399 Q_Q(QXYSeries);
399 400
400 401 const QList<QPointF>& points = q->points();
401 402 for (int i = 0; i < points.count(); i++)
402 403 {
403 404 qreal x = points[i].x();
404 405 qreal y = points[i].y();
405 406 minX = qMin(minX, x);
406 407 minY = qMin(minY, y);
407 408 maxX = qMax(maxX, x);
408 409 maxY = qMax(maxY, y);
409 410 }
410 411
411 412 domain.setRangeX(minX,maxX,tickXCount);
412 413 domain.setRangeY(minY,maxY,tickYCount);
413 414 }
414 415
415 416 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
416 417 {
417 418 Q_Q(QXYSeries);
418 419 QList<LegendMarker*> list;
419 420 return list << new XYLegendMarker(q,legend);
420 421 }
421 422
422 423 void QXYSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
423 424 {
424 425 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
425 426 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
426 427 if (m_mapOrientation == Qt::Vertical) {
427 428 if ((column == m_mapX || column == m_mapY) // modified item is in a mapped column
428 429 && row >= m_mapFirst // modfied item in not before first item
429 430 && (m_mapCount == -1 || row < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
430 431 emit pointReplaced(row - m_mapFirst);
431 432 } else {
432 433 if ((row == m_mapX || row == m_mapY) // modified item is in a mapped row
433 434 && column >= m_mapFirst // modfied item in not before first item
434 435 && (m_mapCount == -1 || column < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
435 436 emit pointReplaced(column - m_mapFirst);
436 437 }
437 438 }
438 439 }
439 440 }
440 441
441 442
442 443 void QXYSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
443 444 {
444 445 Q_UNUSED(parent);
445 446 emit pointsAdded(start, end);
446 447 }
447 448
448 449 void QXYSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
449 450 {
450 451 Q_UNUSED(parent);
451 452 emit pointsRemoved(start, end);
452 453 }
453 454
454 455 #include "moc_qxyseries.cpp"
455 456 #include "moc_qxyseries_p.cpp"
456 457
457 458 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,308 +1,325
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 "xychartitem_p.h"
22 22 #include "qxyseries.h"
23 23 #include "qxyseries_p.h"
24 24 #include "chartpresenter_p.h"
25 25 #include "chartanimator_p.h"
26 26 #include <QPainter>
27 27 #include <QGraphicsSceneMouseEvent>
28 28 #include <QAbstractItemModel>
29 29
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 //TODO: optimize : remove points which are not visible
34 34
35 35 XYChartItem::XYChartItem(QXYSeries *series, ChartPresenter *presenter):ChartItem(presenter),
36 36 m_minX(0),
37 37 m_maxX(0),
38 38 m_minY(0),
39 39 m_maxY(0),
40 40 m_series(series)
41 41 {
42 42 connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
43 43 connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
44 44 connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
45 45 connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
46 46 connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
47 47 connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
48 48 }
49 49
50 50 QPointF XYChartItem::calculateGeometryPoint(const QPointF &point) const
51 51 {
52 52 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
53 53 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
54 54 qreal x = (point.x() - m_minX)* deltaX;
55 55 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
56 56 return QPointF(x,y);
57 57 }
58 58
59 59
60 60 QPointF XYChartItem::calculateGeometryPoint(int index) const
61 61 {
62 62 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
63 63 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
64 64 const QList<QPointF>& vector = m_series->points();
65 65 qreal x = (vector[index].x() - m_minX)* deltaX;
66 66 qreal y = (vector[index].y() - m_minY)*-deltaY + m_size.height();
67 67 return QPointF(x,y);
68 68 }
69 69
70 70 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
71 71 {
72 72 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
73 73 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
74 74
75 75 QVector<QPointF> result;
76 76 result.resize(m_series->count());
77 77 const QList<QPointF>& vector = m_series->points();
78 78 for (int i = 0; i < m_series->count(); ++i) {
79 79 qreal x = (vector[i].x() - m_minX)* deltaX;
80 80 qreal y = (vector[i].y() - m_minY)*-deltaY + m_size.height();
81 81 result[i].setX(x);
82 82 result[i].setY(y);
83 83 }
84 84 return result;
85 85 }
86 86
87 87 QPointF XYChartItem::calculateDomainPoint(const QPointF &point) const
88 88 {
89 89 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
90 90 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
91 91 qreal x = point.x()/deltaX +m_minX;
92 92 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
93 93 return QPointF(x,y);
94 94 }
95 95
96 96 void XYChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
97 97 {
98 98 if (animator()) {
99 99 animator()->updateLayout(this,oldPoints,newPoints,index);
100 100 } else {
101 101 setLayout(newPoints);
102 102 }
103 103 }
104 104
105 105 void XYChartItem::setLayout(QVector<QPointF> &points)
106 106 {
107 107 m_points = points;
108 108 update();
109 109 }
110 110
111 111 //handlers
112 112
113 113 void XYChartItem::handlePointAdded(int index)
114 114 {
115 115 if (m_series->model() == 0) {
116 116 Q_ASSERT(index<m_series->count());
117 117 Q_ASSERT(index>=0);
118 118 }
119 119 QVector<QPointF> points = m_points;
120 120 QPointF point;
121 121 point = calculateGeometryPoint(index);
122 122 points.insert(index, point);
123 123 updateLayout(m_points, points, index);
124 124 update();
125 125 }
126 126
127 127 void XYChartItem::handlePointsAdded(int start, int end)
128 128 {
129 129 if (m_series->model() == 0) {
130 130 for (int i = start; i <= end; i++)
131 131 handlePointAdded(i);
132 } else if (m_series->mapCount() != -1 && start >= m_series->mapFirst() + m_series->mapCount()) {
133 return;
132 134 } else {
133 // series uses model as a data source
134 int first = m_series->mapFirst();
135 int count = m_series->mapCount();
136 135 int addedCount = end - start + 1;
137 if (count != -1 && start >= first + count) {
138 return;
136 if (m_series->mapCount() != -1 && addedCount > m_series->mapCount())
137 addedCount = m_series->mapCount();
138 int first = qMax(start, m_series->mapFirst());
139 int last = qMin(first + addedCount - 1, m_series->mapOrientation() == Qt::Vertical ? m_series->model()->rowCount() - 1 : m_series->model()->columnCount() - 1);
140 for (int i = first; i <= last; i++) {
141 handlePointAdded(i - m_series->mapFirst());
139 142 }
140
141 // adding items to unlimited map
142 else if (count == -1 && start >= first) {
143 for (int i = start; i <= end; i++)
144 handlePointAdded(i - first);
145 } else if (count == - 1 && start < first) {
146 // not all newly added items
147 for (int i = first; i < first + addedCount; i++)
148 handlePointAdded(i - first);
143 if (m_series->mapCount() != -1 && m_points.size() > m_series->mapCount())
144 for (int i = m_points.size() - 1; i >= m_series->mapCount(); i--)
145 handlePointRemoved(i);
149 146 }
150 // commented out code below does the same thing, but its more confusing.
151 // } else if (count == -1) {
152 // int begin = qMax(start, first);
153 // for (int i = begin; i < begin + (end - start + 1); i++)
154 // handlePointAdded(i - first);
147
148 // else {
149 // // series uses model as a data source
150 // int first = m_series->mapFirst();
151 // int count = m_series->mapCount();
152 // int addedCount = end - start + 1;
153 // if (count != -1 && start >= first + count) {
154 // return;
155 155 // }
156 156
157 // adding items to limited map
158 else if (start >= first) {
159 // remove the items that will no longer fit into the map
160 // int toRemove = addedCount - (count - points().size());
161 for (int i = start; i <= end; i++) {
162 handlePointAdded(i - first);
163 }
164 if (m_points.size() > count)
165 for (int i = m_points.size() - 1; i >= count; i--)
166 handlePointRemoved(i);
167 // update();
168 } else {
169 //
170 for (int i = first; i < first + addedCount; i++) {
171 handlePointAdded(i - first);
172 }
173 if (m_points.size() > count)
174 for (int i = m_points.size() - 1; i >= count; i--)
175 handlePointRemoved(i);
176 }
177 }
157 // // adding items to unlimited map
158 // else if (count == -1 && start >= first) {
159 // for (int i = start; i <= end; i++)
160 // handlePointAdded(i - first);
161 // } else if (count == - 1 && start < first) {
162 // // not all newly added items
163 // for (int i = first; i < first + addedCount; i++)
164 // handlePointAdded(i - first);
165 // }
166 // // commented out code below does the same thing, but its more confusing.
167 // // } else if (count == -1) {
168 // // int begin = qMax(start, first);
169 // // for (int i = begin; i < begin + (end - start + 1); i++)
170 // // handlePointAdded(i - first);
171 // // }
172
173 // // adding items to limited map
174 // else if (start >= first) {
175 // // remove the items that will no longer fit into the map
176 // // int toRemove = addedCount - (count - points().size());
177 // for (int i = start; i <= end; i++) {
178 // handlePointAdded(i - first);
179 // }
180 // if (m_points.size() > count)
181 // for (int i = m_points.size() - 1; i >= count; i--)
182 // handlePointRemoved(i);
183 // // update();
184 // } else {
185 // //
186 // for (int i = first; i < first + addedCount; i++) {
187 // handlePointAdded(i - first);
188 // }
189 // if (m_points.size() > count)
190 // for (int i = m_points.size() - 1; i >= count; i--)
191 // handlePointRemoved(i);
192 // }
193 // }
178 194 }
179 195
180 196 void XYChartItem::handlePointRemoved(int index)
181 197 {
182 198 if (m_series->model() == 0) {
183 199 Q_ASSERT(index<m_series->count() + 1);
184 200 Q_ASSERT(index>=0);
185 201 }
186 202 QVector<QPointF> points = m_points;
187 203 points.remove(index);
188 204 updateLayout(m_points, points, index);
189 205 update();
190 206 }
191 207
192 208 void XYChartItem::handlePointsRemoved(int start, int end)
193 209 {
194 210 Q_UNUSED(start)
195 211 Q_UNUSED(end)
196 212 if (m_series->model() == 0) {
197 213 for (int i = end; i >= start; i--)
198 214 handlePointRemoved(i);
199 215 } else {
200 216 // series uses model as a data source
201 217 int first = m_series->mapFirst();
202 218 int count = m_series->mapCount();
203 219 int removedCount = end - start + 1;
204 220 if (count != -1 && start >= first + count) {
205 221 return;
206 222 }
207 223
208 224 // removing items from unlimited map
209 225 else if (count == -1 && start >= first) {
210 226 for (int i = end; i >= start; i--)
211 227 handlePointRemoved(i - first);
212 228 } else if (count == - 1 && start < first) {
213 229 // not all removed items
214 for (int i = first + removedCount - 1; i >= first; i--)
230 int lastExisting = qMin(first + m_points.size() - 1, first + removedCount - 1);
231 for (int i = lastExisting; i >= first; i--)
215 232 handlePointRemoved(i - first);
216 233 }
217 234
218 235 // removing items from limited map
219 236 else if (start >= first) {
220 237 //
221 238 int lastExisting = qMin(first + m_points.size() - 1, end);
222 239 for (int i = lastExisting; i >= start; i--) {
223 240 handlePointRemoved(i - first);
224 241 }
225 242
226 243 // the map is limited, so after removing the items some new items may have fall within the mapped area
227 244 int itemsAvailable;
228 245 if (m_series->mapOrientation() == Qt::Vertical)
229 246 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
230 247 else
231 248 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
232 249 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
233 250 int currentSize = m_points.size();
234 251 if (itemsAvailable > 0)
235 252 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
236 253 handlePointAdded(i);
237 254 } else {
238 255 // first removed item lays before the mapped area
239 256 int toRemove = qMin(m_points.size() - 1, removedCount);
240 257 for (int i = first; i < first + toRemove; i++)
241 258 handlePointRemoved(0);
242 259
243 260 // the map is limited, so after removing the items some new items may have fall into the map
244 261 int itemsAvailable;
245 262 if (m_series->mapOrientation() == Qt::Vertical)
246 263 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
247 264 else
248 265 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
249 266 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
250 267 int currentSize = m_points.size();
251 268 if (itemsAvailable > 0)
252 269 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
253 270 handlePointAdded(i);
254 271 }
255 272 }
256 273
257 274 }
258 275
259 276 void XYChartItem::handlePointReplaced(int index)
260 277 {
261 278 Q_ASSERT(index<m_series->count());
262 279 Q_ASSERT(index>=0);
263 280 QPointF point = calculateGeometryPoint(index);
264 281 QVector<QPointF> points = m_points;
265 282 points.replace(index,point);
266 283 updateLayout(m_points,points,index);
267 284 update();
268 285 }
269 286
270 287 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
271 288 {
272 289 m_minX=minX;
273 290 m_maxX=maxX;
274 291 m_minY=minY;
275 292 m_maxY=maxY;
276 293 if (isEmpty()) return;
277 294 QVector<QPointF> points = calculateGeometryPoints();
278 295 updateLayout(m_points,points);
279 296 update();
280 297 }
281 298
282 299 void XYChartItem::handleGeometryChanged(const QRectF &rect)
283 300 {
284 301 Q_ASSERT(rect.isValid());
285 302 m_size=rect.size();
286 303 m_clipRect=rect.translated(-rect.topLeft());
287 304 setPos(rect.topLeft());
288 305
289 306 if (isEmpty()) return;
290 307 QVector<QPointF> points = calculateGeometryPoints();
291 308 updateLayout(m_points,points);
292 309 update();
293 310 }
294 311
295 312
296 313 bool XYChartItem::isEmpty()
297 314 {
298 315 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY);
299 316 }
300 317
301 318 void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
302 319 {
303 320 emit clicked(calculateDomainPoint(event->pos()));
304 321 }
305 322
306 323 #include "moc_xychartitem_p.cpp"
307 324
308 325 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,375 +1,375
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 "tablewidget.h"
22 22 #include <QGridLayout>
23 23 #include <QTableView>
24 24 #include <QChart>
25 25 #include <QStyledItemDelegate>
26 26 #include <QLineSeries>
27 27 #include <QSplineSeries>
28 28 #include <QScatterSeries>
29 29 #include "customtablemodel.h"
30 30 #include <QPieSeries>
31 31 #include <QPieSlice>
32 32 #include <QAreaSeries>
33 33 #include <QBarSeries>
34 34 #include <QBarSet>
35 35 #include <QPushButton>
36 36 #include <QRadioButton>
37 37 #include <QLabel>
38 38 #include <QSpinBox>
39 39 #include <QTime>
40 40
41 41 TableWidget::TableWidget(QWidget *parent)
42 42 : QWidget(parent),specialPie(0)
43 43 {
44 44 setGeometry(1900, 100, 1000, 600);
45 45 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
46 46 // create simple model for storing data
47 47 // user's table data model
48 48 m_model = new CustomTableModel;
49 49 m_tableView = new QTableView;
50 50 m_tableView->setModel(m_model);
51 51 m_tableView->setMinimumHeight(300);
52 52 // tableView->setMinimumSize(340, 480);
53 53 // tableView->setItemDelegate(new QStyledItemDelegate);
54 54 m_chart = new QChart;
55 55 m_chart->legend()->setVisible(true);
56 m_chart->setAnimationOptions(QChart::SeriesAnimations);
56 // m_chart->setAnimationOptions(QChart::SeriesAnimations);
57 57 m_chartView = new QChartView(m_chart);
58 58 m_chartView->setRenderHint(QPainter::Antialiasing);
59 59 m_chartView->setMinimumSize(640, 480);
60 60
61 61 // add, remove data buttons
62 62 QPushButton* addRowAboveButton = new QPushButton("Add row above");
63 63 connect(addRowAboveButton, SIGNAL(clicked()), this, SLOT(addRowAbove()));
64 64
65 65 QPushButton* addRowBelowButton = new QPushButton("Add row below");
66 66 connect(addRowBelowButton, SIGNAL(clicked()), this, SLOT(addRowBelow()));
67 67
68 68 QPushButton* removeRowButton = new QPushButton("Remove row");
69 69 connect(removeRowButton, SIGNAL(clicked()), this, SLOT(removeRow()));
70 70
71 71 QPushButton* specialPieButton = new QPushButton("Test pie");
72 72 connect(specialPieButton, SIGNAL(clicked()), this, SLOT(testPie()));
73 73
74 74
75 75 QLabel *spinBoxLabel = new QLabel("Rows affected:");
76 76
77 77 // spin box for setting number of affected items (add, remove)
78 78 m_linesCountSpinBox = new QSpinBox;
79 79 m_linesCountSpinBox->setRange(1, 10);
80 80 m_linesCountSpinBox->setValue(1);
81 81
82 82 // buttons layout
83 83 QVBoxLayout* buttonsLayout = new QVBoxLayout;
84 84 buttonsLayout->addWidget(spinBoxLabel);
85 85 buttonsLayout->addWidget(m_linesCountSpinBox);
86 86 buttonsLayout->addWidget(addRowAboveButton);
87 87 buttonsLayout->addWidget(addRowBelowButton);
88 88 buttonsLayout->addWidget(removeRowButton);
89 89 buttonsLayout->addWidget(specialPieButton);
90 90 buttonsLayout->addStretch();
91 91
92 92 // chart type radio buttons
93 93 m_lineRadioButton = new QRadioButton("Line");
94 94 m_splineRadioButton = new QRadioButton("Spline");
95 95 m_scatterRadioButton = new QRadioButton("Scatter");
96 96 m_pieRadioButton = new QRadioButton("Pie");
97 97 m_areaRadioButton = new QRadioButton("Area");
98 98 m_barRadioButton = new QRadioButton("Bar");
99 99
100 100 connect(m_lineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
101 101 connect(m_splineRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
102 102 connect(m_scatterRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
103 103 connect(m_pieRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
104 104 connect(m_areaRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
105 105 connect(m_barRadioButton, SIGNAL(toggled(bool)), this, SLOT(updateChartType(bool)));
106 106 m_lineRadioButton->setChecked(true);
107 107
108 108 // radio buttons layout
109 109 QVBoxLayout* radioLayout = new QVBoxLayout;
110 110 radioLayout->addWidget(m_lineRadioButton);
111 111 radioLayout->addWidget(m_splineRadioButton);
112 112 radioLayout->addWidget(m_scatterRadioButton);
113 113 radioLayout->addWidget(m_pieRadioButton);
114 114 radioLayout->addWidget(m_areaRadioButton);
115 115 radioLayout->addWidget(m_barRadioButton);
116 116 radioLayout->addStretch();
117 117
118 118 // create main layout
119 119 QGridLayout* mainLayout = new QGridLayout;
120 120 mainLayout->addLayout(buttonsLayout, 1, 1);
121 121 mainLayout->addLayout(radioLayout, 2, 1);
122 122 mainLayout->addWidget(m_tableView, 1, 0);
123 123 mainLayout->addWidget(m_chartView, 2, 0);
124 124 setLayout(mainLayout);
125 125 m_lineRadioButton->setFocus();
126 126 }
127 127
128 128 void TableWidget::addRowAbove()
129 129 {
130 130 m_model->insertRows(m_tableView->currentIndex().row(), m_linesCountSpinBox->value());
131 131
132 132 }
133 133
134 134 void TableWidget::addRowBelow()
135 135 {
136 136 m_model->insertRows(m_tableView->currentIndex().row() + 1, m_linesCountSpinBox->value());
137 137
138 138 }
139 139
140 140 void TableWidget::removeRow()
141 141 {
142 142 m_model->removeRows(m_tableView->currentIndex().row(), qMin(m_model->rowCount() - m_tableView->currentIndex().row(), m_linesCountSpinBox->value()));
143 143 }
144 144
145 145 void TableWidget::updateChartType(bool toggle)
146 146 {
147 147 // this if is needed, so that the function is only called once.
148 148 // For the radioButton that was enabled.
149 149 if (toggle) {
150 150 specialPie = 0;
151 151 m_chart->removeAllSeries();
152 152 m_chart->axisX()->setNiceNumbersEnabled(false);
153 153 m_chart->axisY()->setNiceNumbersEnabled(false);
154 154
155 155 // renable axes of the chart (pie hides them)
156 156 // x axis
157 157 QAxis *axis = m_chart->axisX();
158 158 axis->setAxisVisible(true);
159 159 axis->setGridLineVisible(true);
160 160 axis->setLabelsVisible(true);
161 161
162 162 // y axis
163 163 axis = m_chart->axisY();
164 164 axis->setAxisVisible(true);
165 165 axis->setGridLineVisible(true);
166 166 axis->setLabelsVisible(true);
167 167
168 168 m_model->clearMapping();
169 169
170 170 QString seriesColorHex = "#000000";
171 171 QPen pen;
172 172 pen.setWidth(2);
173 173
174 174 if (m_lineRadioButton->isChecked())
175 175 {
176 176 // series 1
177 177 m_series = new QLineSeries;
178 178 m_series->setModel(m_model);
179 179 m_series->setModelMapping(0,1, Qt::Vertical);
180 180 m_series->setModelMappingRange(4, 4);
181 181 m_chart->addSeries(m_series);
182 182 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
183 183 m_model->addMapping(seriesColorHex, QRect(0, 4, 2, 4));
184 184
185 185 // series 2
186 186 m_series = new QLineSeries;
187 187 m_series->setModel(m_model);
188 188 m_series->setModelMapping(2,3, Qt::Vertical);
189 189 m_chart->addSeries(m_series);
190 190 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
191 191 m_model->addMapping(seriesColorHex, QRect(2, 0, 2, 1000));
192 192
193 193 // series 3
194 194 m_series = new QLineSeries;
195 195 m_series->setModel(m_model);
196 196 m_series->setModelMapping(4,5, Qt::Vertical);
197 197 m_series->setModelMappingRange(2, -1);
198 198 m_chart->addSeries(m_series);
199 199 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
200 200 m_model->addMapping(seriesColorHex, QRect(4, 2, 2, 1000));
201 201 }
202 202 else if (m_splineRadioButton->isChecked())
203 203 {
204 204 // series 1
205 205 m_series = new QSplineSeries;
206 206 m_series->setModel(m_model);
207 207 m_series->setModelMapping(0,1, Qt::Vertical);
208 208 // m_series->setModelMappingRange(1, 4);
209 209 // series->setModelMapping(0,1, Qt::Horizontal);
210 210 m_chart->addSeries(m_series);
211 211 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
212 212 m_model->addMapping(seriesColorHex, QRect(0, 1, 2, 4));
213 213
214 214 // series 2
215 215 m_series = new QSplineSeries;
216 216 m_series->setModel(m_model);
217 217 m_series->setModelMapping(2,3, Qt::Vertical);
218 218 // m_series->setModelMappingRange(0, 0);
219 219 // series->setModelMapping(2,3, Qt::Horizontal);
220 220 m_chart->addSeries(m_series);
221 221 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
222 222 m_model->addMapping(seriesColorHex, QRect(2, 0, 2, 1000));
223 223
224 224 // series 3
225 225 m_series = new QSplineSeries;
226 226 m_series->setModel(m_model);
227 227 m_series->setModelMapping(4,5, Qt::Vertical);
228 228 // m_series->setModelMappingRange(2, 0);
229 229 // series->setModelMapping(4,5, Qt::Horizontal);
230 230 m_chart->addSeries(m_series);
231 231 seriesColorHex = "#" + QString::number(m_series->pen().color().rgb(), 16).right(6).toUpper();
232 232 m_model->addMapping(seriesColorHex, QRect(4, 2, 2, 1000));
233 233 }
234 234 else if (m_scatterRadioButton->isChecked())
235 235 {
236 236 // series 1
237 237 m_series = new QScatterSeries;
238 238 m_series->setModel(m_model);
239 239 m_series->setModelMapping(0,1, Qt::Vertical);
240 240 // m_series->setModelMappingRange(2, 0);
241 241 // series->setModelMapping(0,1, Qt::Horizontal);
242 242 m_chart->addSeries(m_series);
243 243
244 244 seriesColorHex = "#" + QString::number(m_series->brush().color().rgb(), 16).right(6).toUpper();
245 245 m_model->addMapping(seriesColorHex, QRect(0, 2, 2, 1000));
246 246
247 247 // series 2
248 248 m_series = new QScatterSeries;
249 249 m_series->setModel(m_model);
250 250 m_series->setModelMapping(2,3, Qt::Vertical);
251 251 // m_series->setModelMappingRange(1, 6);
252 252 // series->setModelMapping(2,3, Qt::Horizontal);
253 253 m_chart->addSeries(m_series);
254 254
255 255 seriesColorHex = "#" + QString::number(m_series->brush().color().rgb(), 16).right(6).toUpper();
256 256 m_model->addMapping(seriesColorHex, QRect(2, 1, 2, 6));
257 257
258 258 // series 3
259 259 m_series = new QScatterSeries;
260 260 m_series->setModel(m_model);
261 261 m_series->setModelMapping(4,5, Qt::Vertical);
262 262 // series->setModelMapping(4,5, Qt::Horizontal);
263 263 m_chart->addSeries(m_series);
264 264 seriesColorHex = "#" + QString::number(m_series->brush().color().rgb(), 16).right(6).toUpper();
265 265 m_model->addMapping(seriesColorHex, QRect(4, 0, 2, 1000));
266 266 }
267 267 else if (m_pieRadioButton->isChecked())
268 268 {
269 269 // pie 1
270 270 QPieSeries* pieSeries = new QPieSeries;
271 271 pieSeries->setModel(m_model);
272 272 pieSeries->setModelMappingRange(3, 3);
273 273 pieSeries->setModelMapping(0,0, Qt::Vertical);
274 274 pieSeries->setLabelsVisible(true);
275 275 pieSeries->setPieSize(0.35);
276 276 pieSeries->setHorizontalPosition(0.2);
277 277 pieSeries->setVerticalPosition(0.3);
278 278
279 279 m_chart->addSeries(pieSeries);
280 280 seriesColorHex = "#" + QString::number(pieSeries->slices().at(pieSeries->slices().count()/2)->brush().color().rgb(), 16).right(6).toUpper();
281 281 m_model->addMapping(seriesColorHex, QRect(0, 3, 1, 3));
282 282
283 283 // pie 2
284 284 pieSeries = new QPieSeries;
285 285 pieSeries->setModel(m_model);
286 286 pieSeries->setModelMappingRange(2, -1);
287 287 pieSeries->setModelMapping(1,1, Qt::Vertical);
288 288 pieSeries->setLabelsVisible(true);
289 289 pieSeries->setPieSize(0.35);
290 290 pieSeries->setHorizontalPosition(0.8);
291 291 pieSeries->setVerticalPosition(0.3);
292 292 m_chart->addSeries(pieSeries);
293 293 seriesColorHex = "#" + QString::number(pieSeries->slices().at(pieSeries->slices().count()/2)->brush().color().rgb(), 16).right(6).toUpper();
294 294 m_model->addMapping(seriesColorHex, QRect(1, 2, 1, 1000));
295 295
296 296 // pie 3
297 297 pieSeries = new QPieSeries;
298 298 pieSeries->setModel(m_model);
299 299 pieSeries->setModelMapping(2,2, Qt::Vertical);
300 300 pieSeries->setLabelsVisible(true);
301 301 pieSeries->setPieSize(0.35);
302 302 pieSeries->setHorizontalPosition(0.2);
303 303 pieSeries->setVerticalPosition(0.75);
304 304 m_chart->addSeries(pieSeries);
305 305 seriesColorHex = "#" + QString::number(pieSeries->slices().at(pieSeries->slices().count()/2)->brush().color().rgb(), 16).right(6).toUpper();
306 306 m_model->addMapping(seriesColorHex, QRect(2, 0, 1, 1000));
307 307
308 308 // special pie
309 309 specialPie = new QPieSeries;
310 310 specialPie->append(17, "1");
311 311 specialPie->append(45, "2");
312 312 specialPie->append(77, "3");
313 313 specialPie->append(37, "4");
314 314 specialPie->append(27, "5");
315 315 specialPie->append(47, "6");
316 316 specialPie->setPieSize(0.35);
317 317 specialPie->setHorizontalPosition(0.8);
318 318 specialPie->setVerticalPosition(0.75);
319 319 specialPie->setLabelsVisible(true);
320 320 m_chart->addSeries(specialPie);
321 321 }
322 322 else if (m_areaRadioButton->isChecked())
323 323 {
324 324 QLineSeries* upperLineSeries = new QLineSeries;
325 325 upperLineSeries->setModel(m_model);
326 326 upperLineSeries->setModelMapping(0, 1, Qt::Vertical);
327 327 // upperLineSeries->setModelMappingRange(1, 5);
328 328 QLineSeries* lowerLineSeries = new QLineSeries;
329 329 lowerLineSeries->setModel(m_model);
330 330 lowerLineSeries->setModelMapping(2, 3, Qt::Vertical);
331 331 QAreaSeries* areaSeries = new QAreaSeries(upperLineSeries, lowerLineSeries);
332 332 m_chart->addSeries(areaSeries);
333 333 seriesColorHex = "#" + QString::number(areaSeries->brush().color().rgb(), 16).right(6).toUpper();
334 334 m_model->addMapping(seriesColorHex, QRect(0, 1, 2, 5));
335 335 m_model->addMapping(seriesColorHex, QRect(2, 0, 2, 1000));
336 336 }
337 337 else if (m_barRadioButton->isChecked())
338 338 {
339 339 QBarSeries* barSeries = new QBarSeries(QStringList());
340 340 barSeries->setModel(m_model);
341 341 // barSeries->setModelMappingRange(2, 5);
342 342 barSeries->setModelMapping(5, 2, 4, Qt::Vertical);
343 343 m_chart->addSeries(barSeries);
344 344 QList<QBarSet*> barsets = barSeries->barSets();
345 345 for (int i = 0; i < barsets.count(); i++) {
346 346 seriesColorHex = "#" + QString::number(barsets.at(i)->brush().color().rgb(), 16).right(6).toUpper();
347 347 m_model->addMapping(seriesColorHex, QRect(2 + i, 0, 1, 1000));
348 348 }
349 349 }
350 350
351 351
352 352 if (!m_barRadioButton->isChecked())
353 353 m_chart->axisX()->setRange(0, 500);
354 354 // m_chart->axisY()->setRange(0, 120);
355 355 m_chart->legend()->setVisible(true);
356 356
357 357 // repaint table view colors
358 358 m_tableView->repaint();
359 359 m_tableView->setFocus();
360 360 }
361 361 }
362 362
363 363 void TableWidget::testPie()
364 364 {
365 365 if (specialPie) {
366 366 specialPie->remove(specialPie->slices().at(2));
367 367 // specialPie->insert(4, new QPieSlice(45, "Hello"));//specialPie->slices.at(2));
368 368 specialPie->append(4, "heloo");
369 369 }
370 370 }
371 371
372 372 TableWidget::~TableWidget()
373 373 {
374 374
375 375 }
General Comments 0
You need to be logged in to leave comments. Login now