##// END OF EJS Templates
pie: add everything as a property in series...
Jani Honkonen -
r1255:419a2509ab1e
parent child
Show More
@@ -1,194 +1,194
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 "piechartitem_p.h"
22 22 #include "piesliceitem_p.h"
23 23 #include "qpieslice.h"
24 24 #include "qpieseries.h"
25 25 #include "qpieseries_p.h"
26 26 #include "chartpresenter_p.h"
27 27 #include "chartdataset_p.h"
28 28 #include "chartanimator_p.h"
29 29 #include <QPainter>
30 30 #include <QTimer>
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
35 35 :ChartItem(presenter),
36 36 m_series(series)
37 37 {
38 38 Q_ASSERT(series);
39 39
40 40 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
41 41 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
42 QPieSeriesPrivate *d = QPieSeriesPrivate::seriesData(*series);
43 connect(d, SIGNAL(piePositionChanged()), this, SLOT(updateLayout()));
44 connect(d, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
42 connect(series, SIGNAL(horizontalPositionChanged()), this, SLOT(updateLayout()));
43 connect(series, SIGNAL(verticalPositionChanged()), this, SLOT(updateLayout()));
44 connect(series, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
45 45
46 46 // Note: the following does not affect as long as the item does not have anything to paint
47 47 setZValue(ChartPresenter::PieSeriesZValue);
48 48
49 49 // Note: will not create slice items until we have a proper rectangle to draw on.
50 50 }
51 51
52 52 PieChartItem::~PieChartItem()
53 53 {
54 54 // slices deleted automatically through QGraphicsItem
55 55 }
56 56
57 57 void PieChartItem::handleGeometryChanged(const QRectF& rect)
58 58 {
59 59 prepareGeometryChange();
60 60 m_rect = rect;
61 61 updateLayout();
62 62
63 63 // This is for delayed initialization of the slice items during startup.
64 64 // It ensures that startup animation originates from the correct position.
65 65 if (m_sliceItems.isEmpty())
66 66 handleSlicesAdded(m_series->slices());
67 67 }
68 68
69 69 void PieChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
70 70 {
71 71 Q_UNUSED(minX);
72 72 Q_UNUSED(maxX);
73 73 Q_UNUSED(minY);
74 74 Q_UNUSED(maxY);
75 75 // does not apply to pie
76 76 }
77 77
78 78 void PieChartItem::rangeXChanged(qreal min, qreal max, int tickXCount)
79 79 {
80 80 Q_UNUSED(min);
81 81 Q_UNUSED(max);
82 82 Q_UNUSED(tickXCount);
83 83 // does not apply to pie
84 84 }
85 85
86 86 void PieChartItem::rangeYChanged(qreal min, qreal max, int tickYCount)
87 87 {
88 88 Q_UNUSED(min);
89 89 Q_UNUSED(max);
90 90 Q_UNUSED(tickYCount);
91 91 // does not apply to pie
92 92 }
93 93
94 94 void PieChartItem::updateLayout()
95 95 {
96 96 // find pie center coordinates
97 97 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
98 98 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
99 99
100 100 // find maximum radius for pie
101 101 m_pieRadius = m_rect.height() / 2;
102 102 if (m_rect.width() < m_rect.height())
103 103 m_pieRadius = m_rect.width() / 2;
104 104
105 105 // apply size factor
106 106 m_pieRadius *= m_series->pieSize();
107 107
108 108 // set layouts for existing slice items
109 109 foreach (QPieSlice* slice, m_series->slices()) {
110 110 PieSliceItem *sliceItem = m_sliceItems.value(slice);
111 111 if (sliceItem) {
112 112 PieSliceData sliceData = updateSliceGeometry(slice);
113 113 if (animator())
114 114 animator()->updateAnimation(this, sliceItem, sliceData);
115 115 else
116 116 sliceItem->setLayout(sliceData);
117 117 }
118 118 }
119 119
120 120 update();
121 121 }
122 122
123 123 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
124 124 {
125 125 // delay creating slice items until there is a proper rectangle
126 126 if (!m_rect.isValid() && m_sliceItems.isEmpty())
127 127 return;
128 128
129 129 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
130 130
131 131 bool startupAnimation = m_sliceItems.isEmpty();
132 132
133 133 foreach (QPieSlice *slice, slices) {
134 134 PieSliceItem* sliceItem = new PieSliceItem(this);
135 135 m_sliceItems.insert(slice, sliceItem);
136 136
137 137 // note: do need to connect to slice valueChanged(). calculatedDataChanged() is enough.
138 138 // to update the slice.
139 139 connect(slice, SIGNAL(calculatedDataChanged()), this, SLOT(handleSliceChanged()));
140 140 connect(slice, SIGNAL(labelChanged()), this, SLOT(handleSliceChanged()));
141 141 connect(slice, SIGNAL(appearanceChanged()), this, SLOT(handleSliceChanged()));
142 142 connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked()));
143 143 connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool)));
144 144
145 145 PieSliceData sliceData = updateSliceGeometry(slice);
146 146 if (animator())
147 147 animator()->addAnimation(this, sliceItem, sliceData, startupAnimation);
148 148 else
149 149 sliceItem->setLayout(sliceData);
150 150 }
151 151 }
152 152
153 153 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
154 154 {
155 155 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
156 156
157 157 foreach (QPieSlice *slice, slices) {
158 158 PieSliceItem *sliceItem = m_sliceItems.value(slice);
159 159 Q_ASSERT(sliceItem);
160 160 m_sliceItems.remove(slice);
161 161
162 162 if (animator())
163 163 animator()->removeAnimation(this, sliceItem); // animator deletes the PieSliceItem
164 164 else
165 165 delete sliceItem;
166 166 }
167 167 }
168 168
169 169 void PieChartItem::handleSliceChanged()
170 170 {
171 171 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
172 172 Q_ASSERT(m_sliceItems.contains(slice));
173 173
174 174 PieSliceItem *sliceItem = m_sliceItems.value(slice);
175 175 PieSliceData sliceData = updateSliceGeometry(slice);
176 176 if (animator())
177 177 animator()->updateAnimation(this, sliceItem, sliceData);
178 178 else
179 179 sliceItem->setLayout(sliceData);
180 180
181 181 update();
182 182 }
183 183
184 184 PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice)
185 185 {
186 186 PieSliceData &sliceData = PieSliceData::fromSlice(slice);
187 187 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
188 188 sliceData.m_radius = m_pieRadius;
189 189 return sliceData;
190 190 }
191 191
192 192 #include "moc_piechartitem_p.cpp"
193 193
194 194 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,606 +1,610
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
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31
32 32 /*!
33 33 \class QPieSeries
34 34 \brief Pie series API for QtCommercial Charts
35 35
36 36 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
37 37 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
38 38 The actual slice size is determined by that relative value.
39 39
40 40 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
41 41 These relate to the actual chart rectangle.
42 42
43 43 By default the pie is defined as a full pie but it can also be a partial pie.
44 44 This can be done by setting a starting angle and angle span to the series.
45 45 Full pie is 360 degrees where 0 is at 12 a'clock.
46 46
47 47 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
48 48 \image examples_piechart.png
49 49 */
50 50
51 51 /*!
52 52 \property QPieSeries::horizontalPosition
53 53 \brief Defines the horizontal position of the pie.
54 54
55 55 The value is a relative value to the chart rectangle where:
56 56
57 57 \list
58 58 \o 0.0 is the absolute left.
59 59 \o 1.0 is the absolute right.
60 60 \endlist
61 61
62 62 Default value is 0.5 (center).
63 63 */
64 64
65 65 /*!
66 66 \property QPieSeries::verticalPosition
67 67 \brief Defines the vertical position of the pie.
68 68
69 69 The value is a relative value to the chart rectangle where:
70 70
71 71 \list
72 72 \o 0.0 is the absolute top.
73 73 \o 1.0 is the absolute bottom.
74 74 \endlist
75 75
76 76 Default value is 0.5 (center).
77 77 */
78 78
79 79 /*!
80 80 \property QPieSeries::size
81 81 \brief Defines the pie size.
82 82
83 83 The value is a relative value to the chart rectangle where:
84 84
85 85 \list
86 86 \o 0.0 is the minimum size (pie not drawn).
87 87 \o 1.0 is the maximum size that can fit the chart.
88 88 \endlist
89 89
90 90 Default value is 0.7.
91 91 */
92 92
93 93 /*!
94 94 \property QPieSeries::startAngle
95 95 \brief Defines the starting angle of the pie.
96 96
97 97 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
98 98
99 99 Default is value is 0.
100 100 */
101 101
102 102 /*!
103 103 \property QPieSeries::endAngle
104 104 \brief Defines the ending angle of the pie.
105 105
106 106 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
107 107
108 108 Default is value is 360.
109 109 */
110 110
111 111 /*!
112 112 \property QPieSeries::count
113 113 \brief Number of slices in the series.
114 114
115 115 */
116 116
117 117 /*!
118 118 \property QPieSeries::sum
119 119 \brief Sum of all slices.
120 120
121 121 The series keeps track of the sum of all slices it holds.
122 122 */
123 123
124 124
125 125 /*!
126 126 Constructs a series object which is a child of \a parent.
127 127 */
128 128 QPieSeries::QPieSeries(QObject *parent) :
129 129 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
130 130 {
131 131
132 132 }
133 133
134 134 /*!
135 135 Destroys the series and its slices.
136 136 */
137 137 QPieSeries::~QPieSeries()
138 138 {
139 139 // NOTE: d_prt destroyed by QObject
140 140 }
141 141
142 142 /*!
143 143 Returns QChartSeries::SeriesTypePie.
144 144 */
145 145 QAbstractSeries::SeriesType QPieSeries::type() const
146 146 {
147 147 return QAbstractSeries::SeriesTypePie;
148 148 }
149 149
150 150 /*!
151 151 Appends an array of \a slices to the series.
152 152 Slice ownership is passed to the series.
153 153
154 154 Returns true if append was successfull.
155 155 */
156 156 bool QPieSeries::append(QList<QPieSlice*> slices)
157 157 {
158 158 Q_D(QPieSeries);
159 159
160 160 if (slices.count() == 0)
161 161 return false;
162 162
163 163 foreach (QPieSlice* s, slices) {
164 164 if (!s || d->m_slices.contains(s))
165 165 return false;
166 166 }
167 167
168 168 foreach (QPieSlice* s, slices) {
169 169 s->setParent(this);
170 170 d->m_slices << s;
171 171 }
172 172
173 173 d->updateDerivativeData();
174 174
175 175 foreach (QPieSlice* s, slices) {
176 176 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceChanged()));
177 177 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
178 178 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
179 179 }
180 180
181 181 emit added(slices);
182 emit countChanged();
182 183
183 184 return true;
184 185 }
185 186
186 187 /*!
187 188 Appends a single \a slice to the series.
188 189 Slice ownership is passed to the series.
189 190
190 191 Returns true if append was succesfull.
191 192 */
192 193 bool QPieSeries::append(QPieSlice* slice)
193 194 {
194 195 return append(QList<QPieSlice*>() << slice);
195 196 }
196 197
197 198 /*!
198 199 Appends a single \a slice to the series and returns a reference to the series.
199 200 Slice ownership is passed to the series.
200 201 */
201 202 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
202 203 {
203 204 append(slice);
204 205 return *this;
205 206 }
206 207
207 208
208 209 /*!
209 210 Appends a single slice to the series with give \a value and \a label.
210 211 Slice ownership is passed to the series.
211 212 */
212 213 QPieSlice* QPieSeries::append(QString label, qreal value)
213 214 {
214 215 QPieSlice* slice = new QPieSlice(label, value);
215 216 append(slice);
216 217 return slice;
217 218 }
218 219
219 220 /*!
220 221 Inserts a single \a slice to the series before the slice at \a index position.
221 222 Slice ownership is passed to the series.
222 223
223 224 Returns true if insert was successfull.
224 225 */
225 226 bool QPieSeries::insert(int index, QPieSlice* slice)
226 227 {
227 228 Q_D(QPieSeries);
228 229
229 230 if (index < 0 || index > d->m_slices.count())
230 231 return false;
231 232
232 233 if (!slice || d->m_slices.contains(slice))
233 234 return false;
234 235
235 236 slice->setParent(this);
236 237 d->m_slices.insert(index, slice);
237 238
238 239 d->updateDerivativeData();
239 240
240 241 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceChanged()));
241 242 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
242 243 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
243 244
244 245 emit added(QList<QPieSlice*>() << slice);
246 emit countChanged();
245 247
246 248 return true;
247 249 }
248 250
249 251 /*!
250 252 Removes a single \a slice from the series and deletes the slice.
251 253
252 254 Do not reference the pointer after this call.
253 255
254 256 Returns true if remove was successfull.
255 257 */
256 258 bool QPieSeries::remove(QPieSlice* slice)
257 259 {
258 260 Q_D(QPieSeries);
259 261
260 262 if (!d->m_slices.removeOne(slice))
261 263 return false;
262 264
263 265 d->updateDerivativeData();
264 266
265 267 emit removed(QList<QPieSlice*>() << slice);
268 emit countChanged();
266 269
267 270 delete slice;
268 271 slice = 0;
269 272
270 273 return true;
271 274 }
272 275
273 276 /*!
274 277 Clears all slices from the series.
275 278 */
276 279 void QPieSeries::clear()
277 280 {
278 281 Q_D(QPieSeries);
279 282 if (d->m_slices.count() == 0)
280 283 return;
281 284
282 285 QList<QPieSlice*> slices = d->m_slices;
283 286 foreach (QPieSlice* s, d->m_slices) {
284 287 d->m_slices.removeOne(s);
285 288 delete s;
286 289 }
287 290
288 291 d->updateDerivativeData();
289 292
290 293 emit removed(slices);
294 emit countChanged();
291 295 }
292 296
293 297 /*!
294 298 returns the number of the slices in this series.
295 299 */
296 300 int QPieSeries::count() const
297 301 {
298 302 Q_D(const QPieSeries);
299 303 return d->m_slices.count();
300 304 }
301 305
302 306 /*!
303 307 Returns true is the series is empty.
304 308 */
305 309 bool QPieSeries::isEmpty() const
306 310 {
307 311 Q_D(const QPieSeries);
308 312 return d->m_slices.isEmpty();
309 313 }
310 314
311 315 /*!
312 316 Returns a list of slices that belong to this series.
313 317 */
314 318 QList<QPieSlice*> QPieSeries::slices() const
315 319 {
316 320 Q_D(const QPieSeries);
317 321 return d->m_slices;
318 322 }
319 323
320 324 void QPieSeries::setHorizontalPosition(qreal relativePosition)
321 325 {
322 326 Q_D(QPieSeries);
323 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
324 emit d->piePositionChanged();
327
328 if (relativePosition < 0.0)
329 relativePosition = 0.0;
330 if (relativePosition > 1.0)
331 relativePosition = 1.0;
332
333 if (!qFuzzyIsNull(d->m_pieRelativeHorPos - relativePosition)) {
334 d->m_pieRelativeHorPos = relativePosition;
335 emit horizontalPositionChanged();
336 }
325 337 }
326 338
327 339 void QPieSeries::setVerticalPosition(qreal relativePosition)
328 340 {
329 341 Q_D(QPieSeries);
330 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
331 emit d->piePositionChanged();
342
343 if (relativePosition < 0.0)
344 relativePosition = 0.0;
345 if (relativePosition > 1.0)
346 relativePosition = 1.0;
347
348 if (!qFuzzyIsNull(d->m_pieRelativeVerPos - relativePosition)) {
349 d->m_pieRelativeVerPos = relativePosition;
350 emit verticalPositionChanged();
351 }
332 352 }
333 353
334 354 qreal QPieSeries::horizontalPosition() const
335 355 {
336 356 Q_D(const QPieSeries);
337 357 return d->m_pieRelativeHorPos;
338 358 }
339 359
340 360 qreal QPieSeries::verticalPosition() const
341 361 {
342 362 Q_D(const QPieSeries);
343 363 return d->m_pieRelativeVerPos;
344 364 }
345 365
346 366 void QPieSeries::setPieSize(qreal relativeSize)
347 367 {
348 368 Q_D(QPieSeries);
349 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
350 emit d->pieSizeChanged();
369
370 if (relativeSize < 0.0)
371 relativeSize = 0.0;
372 if (relativeSize > 1.0)
373 relativeSize = 1.0;
374
375 if (!qFuzzyIsNull(d->m_pieRelativeSize - relativeSize)) {
376 d->m_pieRelativeSize = relativeSize;
377 emit pieSizeChanged();
378 }
351 379 }
352 380
353 381 qreal QPieSeries::pieSize() const
354 382 {
355 383 Q_D(const QPieSeries);
356 384 return d->m_pieRelativeSize;
357 385 }
358 386
359 387
360 388 void QPieSeries::setPieStartAngle(qreal angle)
361 389 {
362 390 Q_D(QPieSeries);
363 391 if (qFuzzyIsNull(d->m_pieStartAngle - angle))
364 392 return;
365 393 d->m_pieStartAngle = angle;
366 394 d->updateDerivativeData();
395 emit pieStartAngleChanged();
367 396 }
368 397
369 398 qreal QPieSeries::pieStartAngle() const
370 399 {
371 400 Q_D(const QPieSeries);
372 401 return d->m_pieStartAngle;
373 402 }
374 403
375 404 /*!
376 405 Sets the end angle of the pie.
377 406
378 407 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
379 408
380 409 \a angle must be greater than start angle.
381 410
382 411 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
383 412 */
384 413 void QPieSeries::setPieEndAngle(qreal angle)
385 414 {
386 415 Q_D(QPieSeries);
387 416 if (qFuzzyIsNull(d->m_pieEndAngle - angle))
388 417 return;
389 418 d->m_pieEndAngle = angle;
390 419 d->updateDerivativeData();
420 emit pieEndAngleChanged();
391 421 }
392 422
393 423 /*!
394 424 Returns the end angle of the pie.
395 425
396 426 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
397 427
398 428 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
399 429 */
400 430 qreal QPieSeries::pieEndAngle() const
401 431 {
402 432 Q_D(const QPieSeries);
403 433 return d->m_pieEndAngle;
404 434 }
405 435
406 436 /*!
407 437 Sets the all the slice labels \a visible or invisible.
408 438
409 439 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
410 440 */
411 441 void QPieSeries::setLabelsVisible(bool visible)
412 442 {
413 443 Q_D(QPieSeries);
414 444 foreach (QPieSlice* s, d->m_slices)
415 445 s->setLabelVisible(visible);
416 446 }
417 447
418 448 /*!
419 449 Returns the sum of all slice values in this series.
420 450
421 451 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
422 452 */
423 453 qreal QPieSeries::sum() const
424 454 {
425 455 Q_D(const QPieSeries);
426 456 return d->m_sum;
427 457 }
428 458
429 459 /*!
430 460 \fn void QPieSeries::added(QList<QPieSlice*> slices)
431 461
432 462 This signal is emitted when \a slices have been added to the series.
433 463
434 464 \sa append(), insert()
435 465 */
436 466
437 467 /*!
438 468 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
439 469
440 470 This signal is emitted when \a slices have been removed from the series.
441 471
442 472 \sa remove()
443 473 */
444 474
445 475 /*!
446 476 \fn void QPieSeries::clicked(QPieSlice* slice)
447 477
448 478 This signal is emitted when a \a slice has been clicked.
449 479
450 480 \sa QPieSlice::clicked()
451 481 */
452 482
453 483 /*!
454 484 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
455 485
456 486 This signal is emitted when user has hovered over or away from the \a slice.
457 487
458 488 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
459 489
460 490 \sa QPieSlice::hovered()
461 491 */
462 492
463 493
464 494
465 495 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
466 496
467 497
468 498 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
469 499 QAbstractSeriesPrivate(parent),
470 500 m_pieRelativeHorPos(0.5),
471 501 m_pieRelativeVerPos(0.5),
472 502 m_pieRelativeSize(0.7),
473 503 m_pieStartAngle(0),
474 504 m_pieEndAngle(360),
475 505 m_sum(0)
476 506 {
477 507 }
478 508
479 509 QPieSeriesPrivate::~QPieSeriesPrivate()
480 510 {
481 511 }
482 512
483 513 void QPieSeriesPrivate::updateDerivativeData()
484 514 {
485 m_sum = 0;
486
487 // nothing to do?
488 if (m_slices.count() == 0)
489 return;
490
491 515 // calculate sum of all slices
516 qreal sum = 0;
492 517 foreach (QPieSlice* s, m_slices)
493 m_sum += s->value();
518 sum += s->value();
519
520 if (!qFuzzyIsNull(m_sum - sum)) {
521 m_sum = sum;
522 emit q_func()->sumChanged();
523 }
494 524
495 525 // nothing to show..
496 526 if (qFuzzyIsNull(m_sum))
497 527 return;
498 528
499 529 // update slice attributes
500 530 qreal sliceAngle = m_pieStartAngle;
501 531 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
502 532 QVector<QPieSlice*> changed;
503 533 foreach (QPieSlice* s, m_slices) {
504 534
505 535 PieSliceData data = PieSliceData::fromSlice(s);
506 536 data.m_percentage = s->value() / m_sum;
507 537 data.m_angleSpan = pieSpan * data.m_percentage;
508 538 data.m_startAngle = sliceAngle;
509 539 sliceAngle += data.m_angleSpan;
510 540
511 541 if (PieSliceData::fromSlice(s) != data) {
512 542 PieSliceData::fromSlice(s) = data;
513 543 changed << s;
514 544 }
515 545 }
516 546
517 547 // emit signals
518 548 foreach (QPieSlice* s, changed)
519 549 PieSliceData::emitCalculatedDataChanged(s);
520 550 }
521 551
522 552 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
523 553 {
524 554 return series.d_func();
525 555 }
526 556
527 557 void QPieSeriesPrivate::sliceChanged()
528 558 {
529 559 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
530 560 updateDerivativeData();
531 561 }
532 562
533 563 void QPieSeriesPrivate::sliceClicked()
534 564 {
535 565 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
536 566 Q_ASSERT(m_slices.contains(slice));
537 567 Q_Q(QPieSeries);
538 568 emit q->clicked(slice);
539 569 }
540 570
541 571 void QPieSeriesPrivate::sliceHovered(bool state)
542 572 {
543 573 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
544 574 Q_ASSERT(m_slices.contains(slice));
545 575 Q_Q(QPieSeries);
546 576 emit q->hovered(slice, state);
547 577 }
548 578
549 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
550 {
551 // Remove rounding errors
552 qreal roundedValue = newValue;
553 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
554 roundedValue = 0.0;
555 else if (qFuzzyCompare(newValue, max))
556 roundedValue = max;
557 else if (qFuzzyCompare(newValue, min))
558 roundedValue = min;
559
560 // Check if the position is valid after removing the rounding errors
561 if (roundedValue < min || roundedValue > max) {
562 qWarning("QPieSeries: Illegal value");
563 return false;
564 }
565
566 if (!qFuzzyIsNull(value - roundedValue)) {
567 value = roundedValue;
568 return true;
569 }
570
571 // The change was so small it is considered a rounding error
572 return false;
573 }
574
575 579 void QPieSeriesPrivate::scaleDomain(Domain& domain)
576 580 {
577 581 Q_UNUSED(domain);
578 582 // does not apply to pie
579 583 }
580 584
581 585 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
582 586 {
583 587 Q_Q(QPieSeries);
584 588 PieChartItem* pie = new PieChartItem(q,presenter);
585 589 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
586 590 presenter->animator()->addAnimation(pie);
587 591 }
588 592 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
589 593 return pie;
590 594 }
591 595
592 596 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
593 597 {
594 598 Q_Q(QPieSeries);
595 599 QList<LegendMarker*> markers;
596 600 foreach(QPieSlice* slice, q->slices()) {
597 601 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
598 602 markers << marker;
599 603 }
600 604 return markers;
601 605 }
602 606
603 607 #include "moc_qpieseries.cpp"
604 608 #include "moc_qpieseries_p.cpp"
605 609
606 610 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,89 +1,101
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 #ifndef PIESERIES_H
22 22 #define PIESERIES_H
23 23
24 24 #include <qabstractseries.h>
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27 class QPieSeriesPrivate;
28 28 class QPieSlice;
29 29
30 30 class QTCOMMERCIALCHART_EXPORT QPieSeries : public QAbstractSeries
31 31 {
32 32 Q_OBJECT
33 Q_PROPERTY(qreal horizontalPosition READ horizontalPosition WRITE setHorizontalPosition)
34 Q_PROPERTY(qreal verticalPosition READ verticalPosition WRITE setVerticalPosition)
35 Q_PROPERTY(qreal size READ pieSize WRITE setPieSize)
36 Q_PROPERTY(qreal startAngle READ pieStartAngle WRITE setPieStartAngle)
37 Q_PROPERTY(qreal endAngle READ pieEndAngle WRITE setPieEndAngle)
38 Q_PROPERTY(int count READ count)
39 Q_PROPERTY(qreal sum READ sum)
33 Q_PROPERTY(qreal horizontalPosition READ horizontalPosition WRITE setHorizontalPosition NOTIFY horizontalPositionChanged)
34 Q_PROPERTY(qreal verticalPosition READ verticalPosition WRITE setVerticalPosition NOTIFY verticalPositionChanged)
35 Q_PROPERTY(qreal size READ pieSize WRITE setPieSize NOTIFY pieSizeChanged)
36 Q_PROPERTY(qreal startAngle READ pieStartAngle WRITE setPieStartAngle NOTIFY pieStartAngleChanged)
37 Q_PROPERTY(qreal endAngle READ pieEndAngle WRITE setPieEndAngle NOTIFY pieEndAngleChanged)
38 Q_PROPERTY(int count READ count NOTIFY countChanged)
39 Q_PROPERTY(qreal sum READ sum NOTIFY sumChanged)
40 40
41 41 public:
42 42 explicit QPieSeries(QObject *parent = 0);
43 43 virtual ~QPieSeries();
44 44
45 45 QAbstractSeries::SeriesType type() const;
46 46
47 47 bool append(QPieSlice* slice);
48 48 bool append(QList<QPieSlice*> slices);
49 49 QPieSeries& operator << (QPieSlice* slice);
50 50 QPieSlice* append(QString label, qreal value);
51
51 52 bool insert(int index, QPieSlice* slice);
53
52 54 bool remove(QPieSlice* slice);
53 55 void clear();
54 56
55 57 QList<QPieSlice*> slices() const;
56 58 int count() const;
59
57 60 bool isEmpty() const;
58 61
59 62 qreal sum() const;
60 63
61 64 void setHorizontalPosition(qreal relativePosition);
62 65 qreal horizontalPosition() const;
66
63 67 void setVerticalPosition(qreal relativePosition);
64 68 qreal verticalPosition() const;
65 69
66 70 void setPieSize(qreal relativeSize);
67 71 qreal pieSize() const;
68 72
69 73 void setPieStartAngle(qreal startAngle);
70 74 qreal pieStartAngle() const;
75
71 76 void setPieEndAngle(qreal endAngle);
72 77 qreal pieEndAngle() const;
73 78
74 79 void setLabelsVisible(bool visible = true);
75 80
76 81 Q_SIGNALS:
77 82 void added(QList<QPieSlice*> slices);
78 83 void removed(QList<QPieSlice*> slices);
79 84 void clicked(QPieSlice* slice);
80 85 void hovered(QPieSlice* slice, bool state);
86 void countChanged();
87 void sumChanged();
88 void pieSizeChanged();
89 void pieStartAngleChanged();
90 void pieEndAngleChanged();
91 void horizontalPositionChanged();
92 void verticalPositionChanged();
81 93
82 94 private:
83 95 Q_DECLARE_PRIVATE(QPieSeries)
84 96 Q_DISABLE_COPY(QPieSeries)
85 97 };
86 98
87 99 QTCOMMERCIALCHART_END_NAMESPACE
88 100
89 101 #endif // PIESERIES_H
@@ -1,72 +1,67
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 #ifndef QPIESERIES_P_H
22 22 #define QPIESERIES_P_H
23 23
24 24 #include "qpieseries.h"
25 25 #include "qabstractseries_p.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28 class QLegendPrivate;
29 29
30 30 class QPieSeriesPrivate : public QAbstractSeriesPrivate
31 31 {
32 32 Q_OBJECT
33 33
34 34 public:
35 35 QPieSeriesPrivate(QPieSeries *parent);
36 36 ~QPieSeriesPrivate();
37 37
38 38 void scaleDomain(Domain& domain);
39 39 Chart* createGraphics(ChartPresenter *presenter);
40 40 QList<LegendMarker*> createLegendMarker(QLegend *legend);
41 41
42 42 void updateDerivativeData();
43 43
44 44 static QPieSeriesPrivate* seriesData(QPieSeries &series);
45 45
46 Q_SIGNALS:
47 void piePositionChanged();
48 void pieSizeChanged();
49
50 46 public Q_SLOTS:
51 47 void sliceChanged();
52 48 void sliceClicked();
53 49 void sliceHovered(bool state);
54 bool setRealValue(qreal &value, qreal newValue, qreal max, qreal min = 0.0);
55 50
56 51 public:
57 52 QList<QPieSlice*> m_slices;
58 53 qreal m_pieRelativeHorPos;
59 54 qreal m_pieRelativeVerPos;
60 55 qreal m_pieRelativeSize;
61 56 qreal m_pieStartAngle;
62 57 qreal m_pieEndAngle;
63 58 qreal m_sum;
64 59
65 60 private:
66 61 friend class QLegendPrivate;
67 62 Q_DECLARE_PUBLIC(QPieSeries)
68 63 };
69 64
70 65 QTCOMMERCIALCHART_END_NAMESPACE
71 66
72 67 #endif // QPIESERIES_P_H
@@ -1,402 +1,457
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 <QtTest/QtTest>
22 22 #include <qchartview.h>
23 23 #include <qchart.h>
24 24 #include <qpieseries.h>
25 25 #include <qpieslice.h>
26 26 #include <qpiemodelmapper.h>
27 27 #include <QStandardItemModel>
28 28 #include <tst_definitions.h>
29 29
30 30 QTCOMMERCIALCHART_USE_NAMESPACE
31 31
32 32 Q_DECLARE_METATYPE(QPieSlice*)
33 33
34 34 class tst_qpieseries : public QObject
35 35 {
36 36 Q_OBJECT
37 37
38 38 public slots:
39 39 void initTestCase();
40 40 void cleanupTestCase();
41 41 void init();
42 42 void cleanup();
43 43
44 44 private slots:
45 void construction();
45 void properties();
46 46 void append();
47 47 void insert();
48 48 void remove();
49 49 void calculatedValues();
50 50 void clickedSignal();
51 51 void hoverSignal();
52 52
53 53 private:
54 54 void verifyCalculatedData(const QPieSeries &series, bool *ok);
55 55
56 56 private:
57 57
58 58 };
59 59
60 60 void tst_qpieseries::initTestCase()
61 61 {
62 62 qRegisterMetaType<QPieSlice*>("QPieSlice*");
63 63 }
64 64
65 65 void tst_qpieseries::cleanupTestCase()
66 66 {
67 67 }
68 68
69 69 void tst_qpieseries::init()
70 70 {
71 71
72 72 }
73 73
74 74 void tst_qpieseries::cleanup()
75 75 {
76 76
77 77 }
78 78
79 void tst_qpieseries::construction()
79 void tst_qpieseries::properties()
80 80 {
81 // verify default values
82 81 QPieSeries s;
82
83 QSignalSpy countSpy(&s, SIGNAL(countChanged()));
84 QSignalSpy sumSpy(&s, SIGNAL(sumChanged()));
85 QSignalSpy sizeSpy(&s, SIGNAL(pieSizeChanged()));
86 QSignalSpy startAngleSpy(&s, SIGNAL(pieStartAngleChanged()));
87 QSignalSpy endAngleSpy(&s, SIGNAL(pieEndAngleChanged()));
88 QSignalSpy horPosSpy(&s, SIGNAL(horizontalPositionChanged()));
89 QSignalSpy verPosSpy(&s, SIGNAL(verticalPositionChanged()));
90
83 91 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
84 92 QVERIFY(s.count() == 0);
85 93 QVERIFY(s.isEmpty());
86 94 QCOMPARE(s.sum(), 0.0);
87 95 QCOMPARE(s.horizontalPosition(), 0.5);
88 96 QCOMPARE(s.verticalPosition(), 0.5);
89 97 QCOMPARE(s.pieSize(), 0.7);
90 98 QCOMPARE(s.pieStartAngle(), 0.0);
91 99 QCOMPARE(s.pieEndAngle(), 360.0);
100
101 s.append("s1", 1);
102 s.append("s2", 1);
103 s.append("s3", 1);
104 s.insert(1, new QPieSlice("s4", 1));
105 s.remove(s.slices().first());
106 QCOMPARE(s.count(), 3);
107 QCOMPARE(s.sum(), 3.0);
108 s.clear();
109 QCOMPARE(s.count(), 0);
110 QCOMPARE(s.sum(), 0.0);
111 QCOMPARE(countSpy.count(), 6);
112 QCOMPARE(sumSpy.count(), 6);
113
114 s.setPieSize(-1.0);
115 QCOMPARE(s.pieSize(), 0.0);
116 s.setPieSize(0.0);
117 s.setPieSize(0.9);
118 s.setPieSize(2.0);
119 QCOMPARE(s.pieSize(), 1.0);
120 QCOMPARE(sizeSpy.count(), 3);
121
122 s.setPieStartAngle(0);
123 s.setPieStartAngle(-180);
124 s.setPieStartAngle(180);
125 QCOMPARE(startAngleSpy.count(), 2);
126
127 s.setPieEndAngle(360);
128 s.setPieEndAngle(-180);
129 s.setPieEndAngle(180);
130 QCOMPARE(endAngleSpy.count(), 2);
131
132 s.setHorizontalPosition(0.5);
133 s.setHorizontalPosition(-1.0);
134 QCOMPARE(s.horizontalPosition(), 0.0);
135 s.setHorizontalPosition(1.0);
136 s.setHorizontalPosition(2.0);
137 QCOMPARE(s.horizontalPosition(), 1.0);
138 QCOMPARE(horPosSpy.count(), 2);
139
140 s.setVerticalPosition(0.5);
141 s.setVerticalPosition(-1.0);
142 QCOMPARE(s.verticalPosition(), 0.0);
143 s.setVerticalPosition(1.0);
144 s.setVerticalPosition(2.0);
145 QCOMPARE(s.verticalPosition(), 1.0);
146 QCOMPARE(verPosSpy.count(), 2);
92 147 }
93 148
94 149 void tst_qpieseries::append()
95 150 {
96 151 QPieSeries s;
97 152
98 153 // append pointer
99 154 QPieSlice *slice1 = 0;
100 155 QVERIFY(!s.append(slice1));
101 156 slice1 = new QPieSlice("slice 1", 1);
102 157 QVERIFY(s.append(slice1));
103 158 QVERIFY(!s.append(slice1));
104 159 QCOMPARE(s.count(), 1);
105 160
106 161 // append pointer list
107 162 QList<QPieSlice *> list;
108 163 QVERIFY(!s.append(list));
109 164 list << (QPieSlice *) 0;
110 165 QVERIFY(!s.append(list));
111 166 list.clear();
112 167 list << new QPieSlice("slice 2", 2);
113 168 list << new QPieSlice("slice 3", 3);
114 169 QVERIFY(s.append(list));
115 170 QVERIFY(!s.append(list));
116 171 QCOMPARE(s.count(), 3);
117 172
118 173 // append operator
119 174 s << new QPieSlice("slice 4", 4);
120 175 s << slice1; // fails because already added
121 176 QCOMPARE(s.count(), 4);
122 177
123 178 // append with params
124 179 QPieSlice *slice5 = s.append("slice 5", 5);
125 180 QVERIFY(slice5 != 0);
126 181 QCOMPARE(slice5->value(), 5.0);
127 182 QCOMPARE(slice5->label(), QString("slice 5"));
128 183 QCOMPARE(s.count(), 5);
129 184
130 185 // check slices
131 186 QVERIFY(!s.isEmpty());
132 187 for (int i=0; i<s.count(); i++) {
133 188 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
134 189 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
135 190 }
136 191 }
137 192
138 193 void tst_qpieseries::insert()
139 194 {
140 195 QPieSeries s;
141 196
142 197 // insert one slice
143 198 QPieSlice *slice1 = 0;
144 199 QVERIFY(!s.insert(0, slice1));
145 200 slice1 = new QPieSlice("slice 1", 1);
146 201 QVERIFY(!s.insert(-1, slice1));
147 202 QVERIFY(!s.insert(5, slice1));
148 203 QVERIFY(s.insert(0, slice1));
149 204 QVERIFY(!s.insert(0, slice1));
150 205 QCOMPARE(s.count(), 1);
151 206
152 207 // add some more slices
153 208 s.append("slice 2", 2);
154 209 s.append("slice 4", 4);
155 210 QCOMPARE(s.count(), 3);
156 211
157 212 // insert between slices
158 213 s.insert(2, new QPieSlice("slice 3", 3));
159 214 QCOMPARE(s.count(), 4);
160 215
161 216 // check slices
162 217 for (int i=0; i<s.count(); i++) {
163 218 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
164 219 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
165 220 }
166 221 }
167 222
168 223 void tst_qpieseries::remove()
169 224 {
170 225 QPieSeries s;
171 226
172 227 // add some slices
173 228 QPieSlice *slice1 = s.append("slice 1", 1);
174 229 QPieSlice *slice2 = s.append("slice 2", 2);
175 230 QPieSlice *slice3 = s.append("slice 3", 3);
176 231 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
177 232 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
178 233 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
179 234 QCOMPARE(s.count(), 3);
180 235
181 236 // null pointer remove
182 237 QVERIFY(!s.remove(0));
183 238
184 239 // remove first
185 240 QVERIFY(s.remove(slice1));
186 241 QVERIFY(!s.remove(slice1));
187 242 QCOMPARE(s.count(), 2);
188 243 QCOMPARE(s.slices().at(0)->label(), slice2->label());
189 244
190 245 // remove all
191 246 s.clear();
192 247 QVERIFY(s.isEmpty());
193 248 QVERIFY(s.slices().isEmpty());
194 249 QCOMPARE(s.count(), 0);
195 250
196 251 // check that slices were actually destroyed
197 252 TRY_COMPARE(spy1.count(), 1);
198 253 TRY_COMPARE(spy2.count(), 1);
199 254 TRY_COMPARE(spy3.count(), 1);
200 255 }
201 256
202 257 void tst_qpieseries::calculatedValues()
203 258 {
204 259 bool ok;
205 260 QPieSeries s;
206 261
207 262 QPieSlice *slice1 = new QPieSlice("slice 1", 1);
208 263 QSignalSpy calculatedDataSpy(slice1, SIGNAL(calculatedDataChanged()));
209 264
210 265 // add a slice
211 266 s.append(slice1);
212 267 verifyCalculatedData(s, &ok);
213 268 if (!ok)
214 269 return;
215 270 QCOMPARE(calculatedDataSpy.count(), 1);
216 271
217 272 // add some more slices
218 273 QList<QPieSlice *> list;
219 274 list << new QPieSlice("slice 2", 2);
220 275 list << new QPieSlice("slice 3", 3);
221 276 s.append(list);
222 277 verifyCalculatedData(s, &ok);
223 278 if (!ok)
224 279 return;
225 280 QCOMPARE(calculatedDataSpy.count(), 2);
226 281
227 282 // remove a slice
228 283 s.remove(list.first()); // remove slice 2
229 284 verifyCalculatedData(s, &ok);
230 285 if (!ok)
231 286 return;
232 287 QCOMPARE(calculatedDataSpy.count(), 3);
233 288
234 289 // insert a slice
235 290 s.insert(0, new QPieSlice("Slice 4", 4));
236 291 verifyCalculatedData(s, &ok);
237 292 if (!ok)
238 293 return;
239 294 QCOMPARE(calculatedDataSpy.count(), 4);
240 295
241 296 // modify pie angles
242 297 s.setPieStartAngle(-90);
243 298 s.setPieEndAngle(90);
244 299 verifyCalculatedData(s, &ok);
245 300 if (!ok)
246 301 return;
247 302 QCOMPARE(calculatedDataSpy.count(), 6);
248 303
249 304 // clear all
250 305 s.clear();
251 306 verifyCalculatedData(s, &ok);
252 307 }
253 308
254 309 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
255 310 {
256 311 *ok = false;
257 312
258 313 qreal sum = 0;
259 314 foreach (const QPieSlice *slice, series.slices())
260 315 sum += slice->value();
261 316 QCOMPARE(series.sum(), sum);
262 317
263 318 qreal startAngle = series.pieStartAngle();
264 319 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
265 320 foreach (const QPieSlice *slice, series.slices()) {
266 321 qreal ratio = slice->value() / sum;
267 322 qreal sliceSpan = pieAngleSpan * ratio;
268 323 QCOMPARE(slice->startAngle(), startAngle);
269 324 QCOMPARE(slice->endAngle(), startAngle + sliceSpan);
270 325 QCOMPARE(slice->percentage(), ratio);
271 326 startAngle += sliceSpan;
272 327 }
273 328
274 329 if (!series.isEmpty())
275 330 QCOMPARE(series.slices().last()->endAngle(), series.pieEndAngle());
276 331
277 332 *ok = true;
278 333 }
279 334
280 335
281 336 void tst_qpieseries::clickedSignal()
282 337 {
283 338 // create a pie series
284 339 QPieSeries *series = new QPieSeries();
285 340 QPieSlice *s1 = series->append("slice 1", 1);
286 341 QPieSlice *s2 = series->append("slice 2", 1);
287 342 QPieSlice *s3 = series->append("slice 3", 1);
288 343 QPieSlice *s4 = series->append("slice 4", 1);
289 344 QSignalSpy clickSpy(series, SIGNAL(clicked(QPieSlice*)));
290 345
291 346 // add series to the chart
292 347 QChartView view(new QChart());
293 348 view.chart()->legend()->setVisible(false);
294 349 view.resize(200, 200);
295 350 view.chart()->addSeries(series);
296 351 view.show();
297 352 QTest::qWaitForWindowShown(&view);
298 353
299 354 // if you devide the chart in four equal tiles these
300 355 // are the center points of those tiles
301 356 QPoint p1(90.25, 90);
302 357 QPoint p2(150, 90);
303 358 QPoint p3(90, 150);
304 359 QPoint p4(150, 150);
305 360
306 361 QPoint center(120, 120);
307 362
308 363 series->setPieSize(1.0);
309 364 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
310 365 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
311 366 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
312 367 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
313 368 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
314 369 TRY_COMPARE(clickSpy.count(), 5); // all hit
315 370 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(0).at(0)), s4);
316 371 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(1).at(0)), s1);
317 372 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(2).at(0)), s3);
318 373 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(3).at(0)), s2);
319 374 clickSpy.clear();
320 375
321 376 series->setPieSize(0.5);
322 377 series->setVerticalPosition(0.25);
323 378 series->setHorizontalPosition(0.25);
324 379 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1); // hits
325 380 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
326 381 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
327 382 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
328 383 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
329 384 TRY_COMPARE(clickSpy.count(), 1);
330 385 clickSpy.clear();
331 386
332 387 series->setVerticalPosition(0.25);
333 388 series->setHorizontalPosition(0.75);
334 389 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
335 390 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2); // hits
336 391 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
337 392 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
338 393 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
339 394 TRY_COMPARE(clickSpy.count(), 1);
340 395 clickSpy.clear();
341 396
342 397 series->setVerticalPosition(0.75);
343 398 series->setHorizontalPosition(0.25);
344 399 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
345 400 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
346 401 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3); // hits
347 402 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
348 403 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
349 404 TRY_COMPARE(clickSpy.count(), 1);
350 405 clickSpy.clear();
351 406
352 407 series->setVerticalPosition(0.75);
353 408 series->setHorizontalPosition(0.75);
354 409 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
355 410 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
356 411 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
357 412 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4); // hits
358 413 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
359 414 TRY_COMPARE(clickSpy.count(), 1);
360 415 clickSpy.clear();
361 416 }
362 417
363 418 void tst_qpieseries::hoverSignal()
364 419 {
365 420 // create a pie series
366 421 QPieSeries *series = new QPieSeries();
367 422 series->setPieSize(1.0);
368 423 QPieSlice *s1 = series->append("slice 1", 1);
369 424 series->append("slice 2", 2);
370 425 series->append("slice 3", 3);
371 426
372 427 // add series to the chart
373 428 QChartView view(new QChart());
374 429 view.chart()->legend()->setVisible(false);
375 430 view.resize(200, 200);
376 431 view.chart()->addSeries(series);
377 432 view.show();
378 433 QTest::qWaitForWindowShown(&view);
379 434
380 435 // first move to right top corner
381 436 QTest::mouseMove(view.viewport(), QPoint(200, 0));
382 437 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
383 438
384 439 // move inside the slice
385 440 // pie rectangle: QRectF(60,60 121x121)
386 441 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
387 442 QTest::mouseMove(view.viewport(), QPoint(139, 85));
388 443 TRY_COMPARE(hoverSpy.count(), 1);
389 444 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
390 445 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
391 446
392 447 // move outside the slice
393 448 QTest::mouseMove(view.viewport(), QPoint(200, 0));
394 449 TRY_COMPARE(hoverSpy.count(), 2);
395 450 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
396 451 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
397 452 }
398 453
399 454 QTEST_MAIN(tst_qpieseries)
400 455
401 456 #include "tst_qpieseries.moc"
402 457
General Comments 0
You need to be logged in to leave comments. Login now