##// END OF EJS Templates
Added two model related tests to pieseries
Marek Rosa -
r1180:1a2d53d6021f
parent child
Show More
@@ -1,81 +1,82
1 #include "qpiemodelmapper.h"
1 #include "qpiemodelmapper.h"
2
2
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4
4
5 QPieModelMapper::QPieModelMapper(QObject *parent) :
5 QPieModelMapper::QPieModelMapper(QObject *parent) :
6 QObject(parent),
6 QObject(parent),
7 m_first(0),
7 m_first(0),
8 m_count(-1),
8 m_count(-1),
9 m_orientation(Qt::Vertical),
9 m_orientation(Qt::Vertical),
10 m_mapValues(-1),
10 m_mapValues(-1),
11 m_mapLabels(-1)
11 m_mapLabels(-1)
12 {
12 {
13 }
13 }
14
14
15 int QPieModelMapper::first() const
15 int QPieModelMapper::first() const
16 {
16 {
17 return m_first;
17 return m_first;
18 }
18 }
19
19
20 void QPieModelMapper::setFirst(int first)
20 void QPieModelMapper::setFirst(int first)
21 {
21 {
22 m_first = qMax(first, 0);
22 m_first = qMax(first, 0);
23 emit updated();
23 emit updated();
24 }
24 }
25
25
26 int QPieModelMapper::count() const
26 int QPieModelMapper::count() const
27 {
27 {
28 return m_count;
28 return m_count;
29 }
29 }
30
30
31 void QPieModelMapper::setCount(int count)
31 void QPieModelMapper::setCount(int count)
32 {
32 {
33 m_count = qMax(count, -1);
33 m_count = qMax(count, -1);
34 emit updated();
34 emit updated();
35 }
35 }
36
36
37 Qt::Orientation QPieModelMapper::orientation() const
37 Qt::Orientation QPieModelMapper::orientation() const
38 {
38 {
39 return m_orientation;
39 return m_orientation;
40 }
40 }
41
41
42 void QPieModelMapper::setOrientation(Qt::Orientation orientation)
42 void QPieModelMapper::setOrientation(Qt::Orientation orientation)
43 {
43 {
44 m_orientation = orientation;
44 m_orientation = orientation;
45 emit updated();
45 emit updated();
46 }
46 }
47
47
48 int QPieModelMapper::mapValues() const
48 int QPieModelMapper::mapValues() const
49 {
49 {
50 return m_mapValues;
50 return m_mapValues;
51 }
51 }
52
52
53 void QPieModelMapper::setMapValues(int mapValues)
53 void QPieModelMapper::setMapValues(int mapValues)
54 {
54 {
55 m_mapValues = mapValues;
55 m_mapValues = mapValues;
56 emit updated();
56 emit updated();
57 }
57 }
58
58
59 int QPieModelMapper::mapLabels() const
59 int QPieModelMapper::mapLabels() const
60 {
60 {
61 return m_mapLabels;
61 return m_mapLabels;
62 }
62 }
63
63
64 void QPieModelMapper::setMapLabels(int mapLabels)
64 void QPieModelMapper::setMapLabels(int mapLabels)
65 {
65 {
66 m_mapLabels = mapLabels;
66 m_mapLabels = mapLabels;
67 emit updated();
67 emit updated();
68 }
68 }
69
69
70 void QPieModelMapper::reset()
70 void QPieModelMapper::reset()
71 {
71 {
72 m_first = 0;
72 m_first = 0;
73 m_count = -1;
73 m_count = -1;
74 m_orientation = Qt::Vertical;
74 m_orientation = Qt::Vertical;
75 m_mapValues = -1;
75 m_mapValues = -1;
76 m_mapLabels = -1;
76 m_mapLabels = -1;
77 emit updated();
77 }
78 }
78
79
79 #include "moc_qpiemodelmapper.cpp"
80 #include "moc_qpiemodelmapper.cpp"
80
81
81 QTCOMMERCIALCHART_END_NAMESPACE
82 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,811 +1,815
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qpieseries.h"
21 #include "qpieseries.h"
22 #include "qpieseries_p.h"
22 #include "qpieseries_p.h"
23 #include "qpieslice.h"
23 #include "qpieslice.h"
24 #include "pieslicedata_p.h"
24 #include "pieslicedata_p.h"
25 #include "chartdataset_p.h"
25 #include "chartdataset_p.h"
26 #include "charttheme_p.h"
26 #include "charttheme_p.h"
27 #include "chartanimator_p.h"
27 #include "chartanimator_p.h"
28 #include "legendmarker_p.h"
28 #include "legendmarker_p.h"
29 #include <QAbstractItemModel>
29 #include <QAbstractItemModel>
30 #include "qpiemodelmapper.h"
30 #include "qpiemodelmapper.h"
31
31
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33
33
34 /*!
34 /*!
35 \class QPieSeries
35 \class QPieSeries
36 \brief Pie series API for QtCommercial Charts
36 \brief Pie series API for QtCommercial Charts
37
37
38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
40 The actual slice size is determined by that relative value.
40 The actual slice size is determined by that relative value.
41
41
42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
43 These relate to the actual chart rectangle.
43 These relate to the actual chart rectangle.
44
44
45 By default the pie is defined as a full pie but it can also be a partial pie.
45 By default the pie is defined as a full pie but it can also be a partial pie.
46 This can be done by setting a starting angle and angle span to the series.
46 This can be done by setting a starting angle and angle span to the series.
47 Full pie is 360 degrees where 0 is at 12 a'clock.
47 Full pie is 360 degrees where 0 is at 12 a'clock.
48
48
49 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
49 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
50 \image examples_piechart.png
50 \image examples_piechart.png
51 */
51 */
52
52
53 /*!
53 /*!
54 \property QPieSeries::horizontalPosition
54 \property QPieSeries::horizontalPosition
55 \brief Defines the horizontal position of the pie.
55 \brief Defines the horizontal position of the pie.
56
56
57 The value is a relative value to the chart rectangle where:
57 The value is a relative value to the chart rectangle where:
58
58
59 \list
59 \list
60 \o 0.0 is the absolute left.
60 \o 0.0 is the absolute left.
61 \o 1.0 is the absolute right.
61 \o 1.0 is the absolute right.
62 \endlist
62 \endlist
63
63
64 Default value is 0.5 (center).
64 Default value is 0.5 (center).
65 */
65 */
66
66
67 /*!
67 /*!
68 \property QPieSeries::verticalPosition
68 \property QPieSeries::verticalPosition
69 \brief Defines the vertical position of the pie.
69 \brief Defines the vertical position of the pie.
70
70
71 The value is a relative value to the chart rectangle where:
71 The value is a relative value to the chart rectangle where:
72
72
73 \list
73 \list
74 \o 0.0 is the absolute top.
74 \o 0.0 is the absolute top.
75 \o 1.0 is the absolute bottom.
75 \o 1.0 is the absolute bottom.
76 \endlist
76 \endlist
77
77
78 Default value is 0.5 (center).
78 Default value is 0.5 (center).
79 */
79 */
80
80
81 /*!
81 /*!
82 \property QPieSeries::size
82 \property QPieSeries::size
83 \brief Defines the pie size.
83 \brief Defines the pie size.
84
84
85 The value is a relative value to the chart rectangle where:
85 The value is a relative value to the chart rectangle where:
86
86
87 \list
87 \list
88 \o 0.0 is the minimum size (pie not drawn).
88 \o 0.0 is the minimum size (pie not drawn).
89 \o 1.0 is the maximum size that can fit the chart.
89 \o 1.0 is the maximum size that can fit the chart.
90 \endlist
90 \endlist
91
91
92 Default value is 0.7.
92 Default value is 0.7.
93 */
93 */
94
94
95 /*!
95 /*!
96 \property QPieSeries::startAngle
96 \property QPieSeries::startAngle
97 \brief Defines the starting angle of the pie.
97 \brief Defines the starting angle of the pie.
98
98
99 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
99 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
100
100
101 Default is value is 0.
101 Default is value is 0.
102 */
102 */
103
103
104 /*!
104 /*!
105 \property QPieSeries::endAngle
105 \property QPieSeries::endAngle
106 \brief Defines the ending angle of the pie.
106 \brief Defines the ending angle of the pie.
107
107
108 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
108 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
109
109
110 Default is value is 360.
110 Default is value is 360.
111 */
111 */
112
112
113
113
114 /*!
114 /*!
115 Constructs a series object which is a child of \a parent.
115 Constructs a series object which is a child of \a parent.
116 */
116 */
117 QPieSeries::QPieSeries(QObject *parent) :
117 QPieSeries::QPieSeries(QObject *parent) :
118 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
118 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
119 {
119 {
120
120
121 }
121 }
122
122
123 /*!
123 /*!
124 Destroys the series and its slices.
124 Destroys the series and its slices.
125 */
125 */
126 QPieSeries::~QPieSeries()
126 QPieSeries::~QPieSeries()
127 {
127 {
128 // NOTE: d_prt destroyed by QObject
128 // NOTE: d_prt destroyed by QObject
129 }
129 }
130
130
131 /*!
131 /*!
132 Returns QChartSeries::SeriesTypePie.
132 Returns QChartSeries::SeriesTypePie.
133 */
133 */
134 QAbstractSeries::SeriesType QPieSeries::type() const
134 QAbstractSeries::SeriesType QPieSeries::type() const
135 {
135 {
136 return QAbstractSeries::SeriesTypePie;
136 return QAbstractSeries::SeriesTypePie;
137 }
137 }
138
138
139 /*!
139 /*!
140 Appends an array of \a slices to the series.
140 Appends an array of \a slices to the series.
141 Slice ownership is passed to the series.
141 Slice ownership is passed to the series.
142 */
142 */
143 bool QPieSeries::append(QList<QPieSlice*> slices)
143 bool QPieSeries::append(QList<QPieSlice*> slices)
144 {
144 {
145 Q_D(QPieSeries);
145 Q_D(QPieSeries);
146
146
147 if (slices.count() == 0)
147 if (slices.count() == 0)
148 return false;
148 return false;
149
149
150 foreach (QPieSlice* s, slices) {
150 foreach (QPieSlice* s, slices) {
151 if (!s || d->m_slices.contains(s))
151 if (!s || d->m_slices.contains(s))
152 return false;
152 return false;
153 }
153 }
154
154
155 foreach (QPieSlice* s, slices) {
155 foreach (QPieSlice* s, slices) {
156 s->setParent(this);
156 s->setParent(this);
157 d->m_slices << s;
157 d->m_slices << s;
158 }
158 }
159
159
160 d->updateDerivativeData();
160 d->updateDerivativeData();
161
161
162 foreach (QPieSlice* s, slices) {
162 foreach (QPieSlice* s, slices) {
163 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
163 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
164 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
164 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
165 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
165 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
166 }
166 }
167
167
168 emit d->added(slices);
168 emit d->added(slices);
169
169
170 return true;
170 return true;
171 }
171 }
172
172
173 /*!
173 /*!
174 Appends a single \a slice to the series.
174 Appends a single \a slice to the series.
175 Slice ownership is passed to the series.
175 Slice ownership is passed to the series.
176 */
176 */
177 bool QPieSeries::append(QPieSlice* slice)
177 bool QPieSeries::append(QPieSlice* slice)
178 {
178 {
179 return append(QList<QPieSlice*>() << slice);
179 return append(QList<QPieSlice*>() << slice);
180 }
180 }
181
181
182 /*!
182 /*!
183 Appends a single \a slice to the series and returns a reference to the series.
183 Appends a single \a slice to the series and returns a reference to the series.
184 Slice ownership is passed to the series.
184 Slice ownership is passed to the series.
185 */
185 */
186 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
186 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
187 {
187 {
188 append(slice);
188 append(slice);
189 return *this;
189 return *this;
190 }
190 }
191
191
192
192
193 /*!
193 /*!
194 Appends a single slice to the series with give \a value and \a name.
194 Appends a single slice to the series with give \a value and \a name.
195 Slice ownership is passed to the series.
195 Slice ownership is passed to the series.
196 */
196 */
197 QPieSlice* QPieSeries::append(qreal value, QString name)
197 QPieSlice* QPieSeries::append(qreal value, QString name)
198 {
198 {
199 QPieSlice* slice = new QPieSlice(value, name);
199 QPieSlice* slice = new QPieSlice(value, name);
200 append(slice);
200 append(slice);
201 return slice;
201 return slice;
202 }
202 }
203
203
204 /*!
204 /*!
205 Inserts a single \a slice to the series before the slice at \a index position.
205 Inserts a single \a slice to the series before the slice at \a index position.
206 Slice ownership is passed to the series.
206 Slice ownership is passed to the series.
207 */
207 */
208 bool QPieSeries::insert(int index, QPieSlice* slice)
208 bool QPieSeries::insert(int index, QPieSlice* slice)
209 {
209 {
210 Q_D(QPieSeries);
210 Q_D(QPieSeries);
211
211
212 if (index < 0 || index > d->m_slices.count())
212 if (index < 0 || index > d->m_slices.count())
213 return false;
213 return false;
214
214
215 if (!slice || d->m_slices.contains(slice))
215 if (!slice || d->m_slices.contains(slice))
216 return false;
216 return false;
217
217
218 slice->setParent(this);
218 slice->setParent(this);
219 d->m_slices.insert(index, slice);
219 d->m_slices.insert(index, slice);
220
220
221 d->updateDerivativeData();
221 d->updateDerivativeData();
222
222
223 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
223 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
224 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
224 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
225 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
225 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
226
226
227 emit d->added(QList<QPieSlice*>() << slice);
227 emit d->added(QList<QPieSlice*>() << slice);
228
228
229 return true;
229 return true;
230 }
230 }
231
231
232 /*!
232 /*!
233 Removes a single \a slice from the series and deletes the slice.
233 Removes a single \a slice from the series and deletes the slice.
234
234
235 Do not reference the pointer after this call.
235 Do not reference the pointer after this call.
236 */
236 */
237 bool QPieSeries::remove(QPieSlice* slice)
237 bool QPieSeries::remove(QPieSlice* slice)
238 {
238 {
239 Q_D(QPieSeries);
239 Q_D(QPieSeries);
240
240
241 if (!d->m_slices.removeOne(slice))
241 if (!d->m_slices.removeOne(slice))
242 return false;
242 return false;
243
243
244 d->updateDerivativeData();
244 d->updateDerivativeData();
245
245
246 emit d->removed(QList<QPieSlice*>() << slice);
246 emit d->removed(QList<QPieSlice*>() << slice);
247
247
248 delete slice;
248 delete slice;
249 slice = 0;
249 slice = 0;
250
250
251 return true;
251 return true;
252 }
252 }
253
253
254 /*!
254 /*!
255 Clears all slices from the series.
255 Clears all slices from the series.
256 */
256 */
257 void QPieSeries::clear()
257 void QPieSeries::clear()
258 {
258 {
259 Q_D(QPieSeries);
259 Q_D(QPieSeries);
260 if (d->m_slices.count() == 0)
260 if (d->m_slices.count() == 0)
261 return;
261 return;
262
262
263 QList<QPieSlice*> slices = d->m_slices;
263 QList<QPieSlice*> slices = d->m_slices;
264 foreach (QPieSlice* s, d->m_slices) {
264 foreach (QPieSlice* s, d->m_slices) {
265 d->m_slices.removeOne(s);
265 d->m_slices.removeOne(s);
266 delete s;
266 delete s;
267 }
267 }
268
268
269 d->updateDerivativeData();
269 d->updateDerivativeData();
270
270
271 emit d->removed(slices);
271 emit d->removed(slices);
272 }
272 }
273
273
274 /*!
274 /*!
275 returns the number of the slices in this series.
275 returns the number of the slices in this series.
276 */
276 */
277 int QPieSeries::count() const
277 int QPieSeries::count() const
278 {
278 {
279 Q_D(const QPieSeries);
279 Q_D(const QPieSeries);
280 return d->m_slices.count();
280 return d->m_slices.count();
281 }
281 }
282
282
283 /*!
283 /*!
284 Returns true is the series is empty.
284 Returns true is the series is empty.
285 */
285 */
286 bool QPieSeries::isEmpty() const
286 bool QPieSeries::isEmpty() const
287 {
287 {
288 Q_D(const QPieSeries);
288 Q_D(const QPieSeries);
289 return d->m_slices.isEmpty();
289 return d->m_slices.isEmpty();
290 }
290 }
291
291
292 /*!
292 /*!
293 Returns a list of slices that belong to this series.
293 Returns a list of slices that belong to this series.
294 */
294 */
295 QList<QPieSlice*> QPieSeries::slices() const
295 QList<QPieSlice*> QPieSeries::slices() const
296 {
296 {
297 Q_D(const QPieSeries);
297 Q_D(const QPieSeries);
298 return d->m_slices;
298 return d->m_slices;
299 }
299 }
300
300
301 void QPieSeries::setHorizontalPosition(qreal relativePosition)
301 void QPieSeries::setHorizontalPosition(qreal relativePosition)
302 {
302 {
303 Q_D(QPieSeries);
303 Q_D(QPieSeries);
304 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
304 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
305 emit d->piePositionChanged();
305 emit d->piePositionChanged();
306 }
306 }
307
307
308 void QPieSeries::setVerticalPosition(qreal relativePosition)
308 void QPieSeries::setVerticalPosition(qreal relativePosition)
309 {
309 {
310 Q_D(QPieSeries);
310 Q_D(QPieSeries);
311 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
311 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
312 emit d->piePositionChanged();
312 emit d->piePositionChanged();
313 }
313 }
314
314
315 qreal QPieSeries::horizontalPosition() const
315 qreal QPieSeries::horizontalPosition() const
316 {
316 {
317 Q_D(const QPieSeries);
317 Q_D(const QPieSeries);
318 return d->m_pieRelativeHorPos;
318 return d->m_pieRelativeHorPos;
319 }
319 }
320
320
321 qreal QPieSeries::verticalPosition() const
321 qreal QPieSeries::verticalPosition() const
322 {
322 {
323 Q_D(const QPieSeries);
323 Q_D(const QPieSeries);
324 return d->m_pieRelativeVerPos;
324 return d->m_pieRelativeVerPos;
325 }
325 }
326
326
327 void QPieSeries::setPieSize(qreal relativeSize)
327 void QPieSeries::setPieSize(qreal relativeSize)
328 {
328 {
329 Q_D(QPieSeries);
329 Q_D(QPieSeries);
330 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
330 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
331 emit d->pieSizeChanged();
331 emit d->pieSizeChanged();
332 }
332 }
333
333
334 qreal QPieSeries::pieSize() const
334 qreal QPieSeries::pieSize() const
335 {
335 {
336 Q_D(const QPieSeries);
336 Q_D(const QPieSeries);
337 return d->m_pieRelativeSize;
337 return d->m_pieRelativeSize;
338 }
338 }
339
339
340
340
341 void QPieSeries::setPieStartAngle(qreal angle)
341 void QPieSeries::setPieStartAngle(qreal angle)
342 {
342 {
343 Q_D(QPieSeries);
343 Q_D(QPieSeries);
344 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
344 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
345 d->updateDerivativeData();
345 d->updateDerivativeData();
346 }
346 }
347
347
348 qreal QPieSeries::pieStartAngle() const
348 qreal QPieSeries::pieStartAngle() const
349 {
349 {
350 Q_D(const QPieSeries);
350 Q_D(const QPieSeries);
351 return d->m_pieStartAngle;
351 return d->m_pieStartAngle;
352 }
352 }
353
353
354 /*!
354 /*!
355 Sets the end angle of the pie.
355 Sets the end angle of the pie.
356
356
357 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
357 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
358
358
359 \a angle must be greater than start angle.
359 \a angle must be greater than start angle.
360
360
361 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
361 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
362 */
362 */
363 void QPieSeries::setPieEndAngle(qreal angle)
363 void QPieSeries::setPieEndAngle(qreal angle)
364 {
364 {
365 Q_D(QPieSeries);
365 Q_D(QPieSeries);
366
366
367 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
367 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
368 d->updateDerivativeData();
368 d->updateDerivativeData();
369 }
369 }
370
370
371 /*!
371 /*!
372 Returns the end angle of the pie.
372 Returns the end angle of the pie.
373
373
374 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
374 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
375
375
376 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
376 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
377 */
377 */
378 qreal QPieSeries::pieEndAngle() const
378 qreal QPieSeries::pieEndAngle() const
379 {
379 {
380 Q_D(const QPieSeries);
380 Q_D(const QPieSeries);
381 return d->m_pieEndAngle;
381 return d->m_pieEndAngle;
382 }
382 }
383
383
384 /*!
384 /*!
385 Sets the all the slice labels \a visible or invisible.
385 Sets the all the slice labels \a visible or invisible.
386
386
387 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
387 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
388 */
388 */
389 void QPieSeries::setLabelsVisible(bool visible)
389 void QPieSeries::setLabelsVisible(bool visible)
390 {
390 {
391 Q_D(QPieSeries);
391 Q_D(QPieSeries);
392 foreach (QPieSlice* s, d->m_slices)
392 foreach (QPieSlice* s, d->m_slices)
393 s->setLabelVisible(visible);
393 s->setLabelVisible(visible);
394 }
394 }
395
395
396 /*!
396 /*!
397 Returns the sum of all slice values in this series.
397 Returns the sum of all slice values in this series.
398
398
399 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
399 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
400 */
400 */
401 qreal QPieSeries::sum() const
401 qreal QPieSeries::sum() const
402 {
402 {
403 Q_D(const QPieSeries);
403 Q_D(const QPieSeries);
404 return d->m_sum;
404 return d->m_sum;
405 }
405 }
406
406
407 /*!
407 /*!
408 \fn void QPieSeries::clicked(QPieSlice* slice)
408 \fn void QPieSeries::clicked(QPieSlice* slice)
409
409
410 This signal is emitted when a \a slice has been clicked.
410 This signal is emitted when a \a slice has been clicked.
411
411
412 \sa QPieSlice::clicked()
412 \sa QPieSlice::clicked()
413 */
413 */
414
414
415 /*!
415 /*!
416 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
416 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
417
417
418 This signal is emitted when user has hovered over or away from the \a slice.
418 This signal is emitted when user has hovered over or away from the \a slice.
419
419
420 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
420 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
421
421
422 \sa QPieSlice::hovered()
422 \sa QPieSlice::hovered()
423 */
423 */
424
424
425 /*!
425 /*!
426 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
426 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
427 Sets the \a model to be used as a data source
427 Sets the \a model to be used as a data source
428 */
428 */
429 void QPieSeries::setModel(QAbstractItemModel* model)
429 void QPieSeries::setModel(QAbstractItemModel* model)
430 {
430 {
431 Q_D(QPieSeries);
431 Q_D(QPieSeries);
432 // disconnect signals from old model
432 // disconnect signals from old model
433 if(d->m_model)
433 if(d->m_model)
434 {
434 {
435 disconnect(d->m_model, 0, this, 0);
435 disconnect(d->m_model, 0, this, 0);
436 }
436 }
437
437
438 // set new model
438 // set new model
439 if(model)
439 if(model)
440 {
440 {
441 d->m_model = model;
441 d->m_model = model;
442 // connect signals from the model
442 // connect signals from the model
443 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
443 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
444 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
444 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelRowsAdded(QModelIndex,int,int)));
445 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
445 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelRowsRemoved(QModelIndex,int,int)));
446 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
446 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelColumnsAdded(QModelIndex,int,int)));
447 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
447 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelColumnsRemoved(QModelIndex,int,int)));
448
448
449 if (d->m_mapper)
449 if (d->m_mapper)
450 d->initializePieFromModel();
450 d->initializePieFromModel();
451 }
451 }
452 else
452 else
453 {
453 {
454 d->m_model = 0;
454 d->m_model = 0;
455 }
455 }
456 }
456 }
457
457
458 void QPieSeries::setModelMapper(QPieModelMapper *mapper)
458 void QPieSeries::setModelMapper(QPieModelMapper *mapper)
459 {
459 {
460 Q_D(QPieSeries);
460 Q_D(QPieSeries);
461 // disconnect signals from old mapper
461 // disconnect signals from old mapper
462 if (d->m_mapper) {
462 if (d->m_mapper) {
463 QObject::disconnect(d->m_mapper, 0, this, 0);
463 QObject::disconnect(d->m_mapper, 0, this, 0);
464 }
464 }
465
465
466 if (mapper) {
466 if (mapper) {
467 d->m_mapper = mapper;
467 d->m_mapper = mapper;
468 // connect the signal from the mapper
468 // connect the signal from the mapper
469 connect(d->m_mapper, SIGNAL(updated()), d, SLOT(initializePieFromModel()));
469 connect(d->m_mapper, SIGNAL(updated()), d, SLOT(initializePieFromModel()));
470
470
471 if (d->m_model)
471 if (d->m_model)
472 d->initializePieFromModel();
472 d->initializePieFromModel();
473 } else {
473 } else {
474 d->m_mapper = 0;
474 d->m_mapper = 0;
475 }
475 }
476 }
476 }
477
477
478 QPieModelMapper* QPieSeries::modelMapper() const
478 QPieModelMapper* QPieSeries::modelMapper() const
479 {
479 {
480 Q_D(const QPieSeries);
480 Q_D(const QPieSeries);
481 return d->m_mapper;
481 return d->m_mapper;
482 }
482 }
483
483
484 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
484 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
485
485
486
486
487 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
487 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
488 QAbstractSeriesPrivate(parent),
488 QAbstractSeriesPrivate(parent),
489 m_pieRelativeHorPos(0.5),
489 m_pieRelativeHorPos(0.5),
490 m_pieRelativeVerPos(0.5),
490 m_pieRelativeVerPos(0.5),
491 m_pieRelativeSize(0.7),
491 m_pieRelativeSize(0.7),
492 m_pieStartAngle(0),
492 m_pieStartAngle(0),
493 m_pieEndAngle(360),
493 m_pieEndAngle(360),
494 m_sum(0),
494 m_sum(0),
495 m_mapper(0)
495 m_mapper(0)
496 {
496 {
497
497
498 }
498 }
499
499
500 QPieSeriesPrivate::~QPieSeriesPrivate()
500 QPieSeriesPrivate::~QPieSeriesPrivate()
501 {
501 {
502
502
503 }
503 }
504
504
505 void QPieSeriesPrivate::updateDerivativeData()
505 void QPieSeriesPrivate::updateDerivativeData()
506 {
506 {
507 m_sum = 0;
507 m_sum = 0;
508
508
509 // nothing to do?
509 // nothing to do?
510 if (m_slices.count() == 0)
510 if (m_slices.count() == 0)
511 return;
511 return;
512
512
513 // calculate sum of all slices
513 // calculate sum of all slices
514 foreach (QPieSlice* s, m_slices)
514 foreach (QPieSlice* s, m_slices)
515 m_sum += s->value();
515 m_sum += s->value();
516
516
517 // nothing to show..
517 // nothing to show..
518 if (qFuzzyIsNull(m_sum))
518 if (qFuzzyIsNull(m_sum))
519 return;
519 return;
520
520
521 // update slice attributes
521 // update slice attributes
522 qreal sliceAngle = m_pieStartAngle;
522 qreal sliceAngle = m_pieStartAngle;
523 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
523 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
524 QVector<QPieSlice*> changed;
524 QVector<QPieSlice*> changed;
525 foreach (QPieSlice* s, m_slices) {
525 foreach (QPieSlice* s, m_slices) {
526
526
527 PieSliceData data = PieSliceData::data(s);
527 PieSliceData data = PieSliceData::data(s);
528 data.m_percentage = s->value() / m_sum;
528 data.m_percentage = s->value() / m_sum;
529 data.m_angleSpan = pieSpan * data.m_percentage;
529 data.m_angleSpan = pieSpan * data.m_percentage;
530 data.m_startAngle = sliceAngle;
530 data.m_startAngle = sliceAngle;
531 sliceAngle += data.m_angleSpan;
531 sliceAngle += data.m_angleSpan;
532
532
533 if (PieSliceData::data(s) != data) {
533 if (PieSliceData::data(s) != data) {
534 PieSliceData::data(s) = data;
534 PieSliceData::data(s) = data;
535 changed << s;
535 changed << s;
536 }
536 }
537 }
537 }
538
538
539 // emit signals
539 // emit signals
540 foreach (QPieSlice* s, changed)
540 foreach (QPieSlice* s, changed)
541 PieSliceData::data(s).emitChangedSignal(s);
541 PieSliceData::data(s).emitChangedSignal(s);
542 }
542 }
543
543
544 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
544 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
545 {
545 {
546 return series.d_func();
546 return series.d_func();
547 }
547 }
548
548
549 void QPieSeriesPrivate::sliceChanged()
549 void QPieSeriesPrivate::sliceChanged()
550 {
550 {
551 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
551 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
552 updateDerivativeData();
552 updateDerivativeData();
553 }
553 }
554
554
555 void QPieSeriesPrivate::sliceClicked()
555 void QPieSeriesPrivate::sliceClicked()
556 {
556 {
557 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
557 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
558 Q_ASSERT(m_slices.contains(slice));
558 Q_ASSERT(m_slices.contains(slice));
559 Q_Q(QPieSeries);
559 Q_Q(QPieSeries);
560 emit q->clicked(slice);
560 emit q->clicked(slice);
561 }
561 }
562
562
563 void QPieSeriesPrivate::sliceHovered(bool state)
563 void QPieSeriesPrivate::sliceHovered(bool state)
564 {
564 {
565 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
565 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
566 Q_ASSERT(m_slices.contains(slice));
566 Q_ASSERT(m_slices.contains(slice));
567 Q_Q(QPieSeries);
567 Q_Q(QPieSeries);
568 emit q->hovered(slice, state);
568 emit q->hovered(slice, state);
569 }
569 }
570
570
571 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
571 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
572 {
572 {
573 if (m_mapper) {
573 if (m_mapper) {
574 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
574 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
575 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
575 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
576 if (m_mapper->orientation() == Qt::Vertical)
576 if (m_mapper->orientation() == Qt::Vertical)
577 {
577 {
578 if ( topLeft.row() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.row() < m_mapper->first() + m_mapper->count())) {
578 if ( topLeft.row() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.row() < m_mapper->first() + m_mapper->count())) {
579 if (topLeft.column() == m_mapper->mapValues())
579 if (topLeft.column() == m_mapper->mapValues())
580 m_slices.at(topLeft.row() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
580 m_slices.at(topLeft.row() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
581 if (topLeft.column() == m_mapper->mapLabels())
581 if (topLeft.column() == m_mapper->mapLabels())
582 m_slices.at(topLeft.row() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
582 m_slices.at(topLeft.row() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
583 }
583 }
584 }
584 }
585 else
585 else
586 {
586 {
587 if (topLeft.column() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.column() < m_mapper->first() + m_mapper->count())) {
587 if (topLeft.column() >= m_mapper->first() && (m_mapper->count() == - 1 || topLeft.column() < m_mapper->first() + m_mapper->count())) {
588 if (topLeft.row() == m_mapper->mapValues())
588 if (topLeft.row() == m_mapper->mapValues())
589 m_slices.at(topLeft.column() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
589 m_slices.at(topLeft.column() - m_mapper->first())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
590 if (topLeft.row() == m_mapper->mapLabels())
590 if (topLeft.row() == m_mapper->mapLabels())
591 m_slices.at(topLeft.column() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
591 m_slices.at(topLeft.column() - m_mapper->first())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
592 }
592 }
593 }
593 }
594 }
594 }
595 }
595 }
596 }
596 }
597 }
597 }
598
598
599
599
600 void QPieSeriesPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
600 void QPieSeriesPrivate::modelRowsAdded(QModelIndex parent, int start, int end)
601 {
601 {
602 Q_UNUSED(parent);
602 Q_UNUSED(parent);
603 if (m_mapper) {
603 if (m_mapper) {
604 if (m_mapper->orientation() == Qt::Vertical)
604 if (m_mapper->orientation() == Qt::Vertical)
605 insertData(start, end);
605 insertData(start, end);
606 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
606 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
607 initializePieFromModel();
607 initializePieFromModel();
608 }
608 }
609 }
609 }
610
610
611 void QPieSeriesPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
611 void QPieSeriesPrivate::modelRowsRemoved(QModelIndex parent, int start, int end)
612 {
612 {
613 Q_UNUSED(parent);
613 Q_UNUSED(parent);
614 if (m_mapper) {
614 if (m_mapper) {
615 if (m_mapper->orientation() == Qt::Vertical)
615 if (m_mapper->orientation() == Qt::Vertical)
616 removeData(start, end);
616 removeData(start, end);
617 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
617 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
618 initializePieFromModel();
618 initializePieFromModel();
619 }
619 }
620 }
620 }
621
621
622 void QPieSeriesPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
622 void QPieSeriesPrivate::modelColumnsAdded(QModelIndex parent, int start, int end)
623 {
623 {
624 Q_UNUSED(parent);
624 Q_UNUSED(parent);
625 if (m_mapper) {
625 if (m_mapper) {
626 if (m_mapper->orientation() == Qt::Horizontal)
626 if (m_mapper->orientation() == Qt::Horizontal)
627 insertData(start, end);
627 insertData(start, end);
628 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
628 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
629 initializePieFromModel();
629 initializePieFromModel();
630 }
630 }
631 }
631 }
632
632
633 void QPieSeriesPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
633 void QPieSeriesPrivate::modelColumnsRemoved(QModelIndex parent, int start, int end)
634 {
634 {
635 Q_UNUSED(parent);
635 Q_UNUSED(parent);
636 if (m_mapper) {
636 if (m_mapper) {
637 if (m_mapper->orientation() == Qt::Horizontal)
637 if (m_mapper->orientation() == Qt::Horizontal)
638 removeData(start, end);
638 removeData(start, end);
639 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
639 else if (start <= m_mapper->mapValues() || start <= m_mapper->mapLabels()) // if the changes affect the map - reinitialize the pie
640 initializePieFromModel();
640 initializePieFromModel();
641 }
641 }
642 }
642 }
643
643
644 void QPieSeriesPrivate::insertData(int start, int end)
644 void QPieSeriesPrivate::insertData(int start, int end)
645 {
645 {
646 Q_Q(QPieSeries);
646 Q_Q(QPieSeries);
647 if (m_mapper) {
647 if (m_mapper) {
648 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
648 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
649 return;
649 return;
650 } else {
650 } else {
651 int addedCount = end - start + 1;
651 int addedCount = end - start + 1;
652 if (m_mapper->count() != -1 && addedCount > m_mapper->count())
652 if (m_mapper->count() != -1 && addedCount > m_mapper->count())
653 addedCount = m_mapper->count();
653 addedCount = m_mapper->count();
654 int first = qMax(start, m_mapper->first());
654 int first = qMax(start, m_mapper->first());
655 int last = qMin(first + addedCount - 1, m_mapper->orientation() == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
655 int last = qMin(first + addedCount - 1, m_mapper->orientation() == Qt::Vertical ? m_model->rowCount() - 1 : m_model->columnCount() - 1);
656 for (int i = first; i <= last; i++) {
656 for (int i = first; i <= last; i++) {
657 QPieSlice *slice = new QPieSlice;
657 QPieSlice *slice = new QPieSlice;
658 if (m_mapper->orientation() == Qt::Vertical) {
658 if (m_mapper->orientation() == Qt::Vertical) {
659 slice->setValue(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble());
659 slice->setValue(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble());
660 slice->setLabel(m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
660 slice->setLabel(m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
661 } else {
661 } else {
662 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble());
662 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble());
663 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
663 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
664 }
664 }
665 slice->setLabelVisible();
665 slice->setLabelVisible();
666 q->insert(i - m_mapper->first(), slice);
666 q->insert(i - m_mapper->first(), slice);
667 }
667 }
668 if (m_mapper->count() != -1 && m_slices.size() > m_mapper->count())
668 if (m_mapper->count() != -1 && m_slices.size() > m_mapper->count())
669 for (int i = m_slices.size() - 1; i >= m_mapper->count(); i--)
669 for (int i = m_slices.size() - 1; i >= m_mapper->count(); i--)
670 q->remove(q->slices().at(i));
670 q->remove(q->slices().at(i));
671 }
671 }
672 }
672 }
673 }
673 }
674
674
675 void QPieSeriesPrivate::removeData(int start, int end)
675 void QPieSeriesPrivate::removeData(int start, int end)
676 {
676 {
677 Q_Q(QPieSeries);
677 Q_Q(QPieSeries);
678 if (m_mapper) {
678 if (m_mapper) {
679 int removedCount = end - start + 1;
679 int removedCount = end - start + 1;
680 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
680 if (m_mapper->count() != -1 && start >= m_mapper->first() + m_mapper->count()) {
681 return;
681 return;
682 } else {
682 } else {
683 int toRemove = qMin(m_slices.size(), removedCount); // first find how many items can actually be removed
683 int toRemove = qMin(m_slices.size(), removedCount); // first find how many items can actually be removed
684 int first = qMax(start, m_mapper->first()); // get the index of the first item that will be removed.
684 int first = qMax(start, m_mapper->first()); // get the index of the first item that will be removed.
685 int last = qMin(first + toRemove - 1, m_slices.size() + m_mapper->first() - 1); // get the index of the last item that will be removed.
685 int last = qMin(first + toRemove - 1, m_slices.size() + m_mapper->first() - 1); // get the index of the last item that will be removed.
686 for (int i = last; i >= first; i--)
686 for (int i = last; i >= first; i--)
687 q->remove(q->slices().at(i - m_mapper->first()));
687 q->remove(q->slices().at(i - m_mapper->first()));
688
688
689 if (m_mapper->count() != -1) {
689 if (m_mapper->count() != -1) {
690 int itemsAvailable; // check how many are available to be added
690 int itemsAvailable; // check how many are available to be added
691 if (m_mapper->orientation() == Qt::Vertical)
691 if (m_mapper->orientation() == Qt::Vertical)
692 itemsAvailable = m_model->rowCount() - m_mapper->first() - m_slices.size();
692 itemsAvailable = m_model->rowCount() - m_mapper->first() - m_slices.size();
693 else
693 else
694 itemsAvailable = m_model->columnCount() - m_mapper->first() - m_slices.size();
694 itemsAvailable = m_model->columnCount() - m_mapper->first() - m_slices.size();
695 int toBeAdded = qMin(itemsAvailable, m_mapper->count() - m_slices.size()); // add not more items than there is space left to be filled.
695 int toBeAdded = qMin(itemsAvailable, m_mapper->count() - m_slices.size()); // add not more items than there is space left to be filled.
696 int currentSize = m_slices.size();
696 int currentSize = m_slices.size();
697 if (toBeAdded > 0)
697 if (toBeAdded > 0)
698 for (int i = m_slices.size(); i < currentSize + toBeAdded; i++) {
698 for (int i = m_slices.size(); i < currentSize + toBeAdded; i++) {
699 QPieSlice *slice = new QPieSlice;
699 QPieSlice *slice = new QPieSlice;
700 if (m_mapper->orientation() == Qt::Vertical) {
700 if (m_mapper->orientation() == Qt::Vertical) {
701 slice->setValue(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapValues()), Qt::DisplayRole).toDouble());
701 slice->setValue(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapValues()), Qt::DisplayRole).toDouble());
702 slice->setLabel(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapLabels()), Qt::DisplayRole).toString());
702 slice->setLabel(m_model->data(m_model->index(i + m_mapper->first(), m_mapper->mapLabels()), Qt::DisplayRole).toString());
703 } else {
703 } else {
704 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i + m_mapper->first()), Qt::DisplayRole).toDouble());
704 slice->setValue(m_model->data(m_model->index(m_mapper->mapValues(), i + m_mapper->first()), Qt::DisplayRole).toDouble());
705 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i + m_mapper->first()), Qt::DisplayRole).toString());
705 slice->setLabel(m_model->data(m_model->index(m_mapper->mapLabels(), i + m_mapper->first()), Qt::DisplayRole).toString());
706 }
706 }
707 slice->setLabelVisible();
707 slice->setLabelVisible();
708 q->insert(i, slice);
708 q->insert(i, slice);
709 }
709 }
710 }
710 }
711 }
711 }
712 }
712 }
713 }
713 }
714
714
715 void QPieSeriesPrivate::initializePieFromModel()
715 void QPieSeriesPrivate::initializePieFromModel()
716 {
716 {
717 Q_Q(QPieSeries);
717 Q_Q(QPieSeries);
718
718
719 if (m_model == 0 || m_mapper == 0)
719 if (m_model == 0 || m_mapper == 0)
720 return;
720 return;
721
721
722 // clear current content
722 // clear current content
723 q->clear();
723 q->clear();
724
724
725 // check if mappings are set
726 if (m_mapper->mapValues() == -1 || m_mapper->mapLabels() == -1)
727 return;
728
725 // create the initial slices set
729 // create the initial slices set
726 if (m_mapper->orientation() == Qt::Vertical) {
730 if (m_mapper->orientation() == Qt::Vertical) {
727 if (m_mapper->mapValues() >= m_model->columnCount() || m_mapper->mapLabels() >= m_model->columnCount())
731 if (m_mapper->mapValues() >= m_model->columnCount() || m_mapper->mapLabels() >= m_model->columnCount())
728 return; // mapped columns are not existing
732 return; // mapped columns are not existing
729
733
730 int sliceCount = 0;
734 int sliceCount = 0;
731 if(m_mapper->count() == -1)
735 if(m_mapper->count() == -1)
732 sliceCount = m_model->rowCount() - m_mapper->first();
736 sliceCount = m_model->rowCount() - m_mapper->first();
733 else
737 else
734 sliceCount = qMin(m_mapper->count(), m_model->rowCount() - m_mapper->first());
738 sliceCount = qMin(m_mapper->count(), m_model->rowCount() - m_mapper->first());
735 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
739 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
736 q->append(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
740 q->append(m_model->data(m_model->index(i, m_mapper->mapValues()), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(i, m_mapper->mapLabels()), Qt::DisplayRole).toString());
737 } else {
741 } else {
738 if (m_mapper->mapValues() >= m_model->rowCount() || m_mapper->mapLabels() >= m_model->rowCount())
742 if (m_mapper->mapValues() >= m_model->rowCount() || m_mapper->mapLabels() >= m_model->rowCount())
739 return; // mapped columns are not existing
743 return; // mapped columns are not existing
740
744
741 int sliceCount = 0;
745 int sliceCount = 0;
742 if(m_mapper->count() == -1)
746 if(m_mapper->count() == -1)
743 sliceCount = m_model->columnCount() - m_mapper->first();
747 sliceCount = m_model->columnCount() - m_mapper->first();
744 else
748 else
745 sliceCount = qMin(m_mapper->count(), m_model->columnCount() - m_mapper->first());
749 sliceCount = qMin(m_mapper->count(), m_model->columnCount() - m_mapper->first());
746 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
750 for (int i = m_mapper->first(); i < m_mapper->first() + sliceCount; i++)
747 q->append(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
751 q->append(m_model->data(m_model->index(m_mapper->mapValues(), i), Qt::DisplayRole).toDouble(), m_model->data(m_model->index(m_mapper->mapLabels(), i), Qt::DisplayRole).toString());
748 }
752 }
749 q->setLabelsVisible(true);
753 q->setLabelsVisible(true);
750 }
754 }
751
755
752 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
756 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
753 {
757 {
754 // Remove rounding errors
758 // Remove rounding errors
755 qreal roundedValue = newValue;
759 qreal roundedValue = newValue;
756 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
760 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
757 roundedValue = 0.0;
761 roundedValue = 0.0;
758 else if (qFuzzyCompare(newValue, max))
762 else if (qFuzzyCompare(newValue, max))
759 roundedValue = max;
763 roundedValue = max;
760 else if (qFuzzyCompare(newValue, min))
764 else if (qFuzzyCompare(newValue, min))
761 roundedValue = min;
765 roundedValue = min;
762
766
763 // Check if the position is valid after removing the rounding errors
767 // Check if the position is valid after removing the rounding errors
764 if (roundedValue < min || roundedValue > max) {
768 if (roundedValue < min || roundedValue > max) {
765 qWarning("QPieSeries: Illegal value");
769 qWarning("QPieSeries: Illegal value");
766 return false;
770 return false;
767 }
771 }
768
772
769 if (!qFuzzyIsNull(value - roundedValue)) {
773 if (!qFuzzyIsNull(value - roundedValue)) {
770 value = roundedValue;
774 value = roundedValue;
771 return true;
775 return true;
772 }
776 }
773
777
774 // The change was so small it is considered a rounding error
778 // The change was so small it is considered a rounding error
775 return false;
779 return false;
776 }
780 }
777
781
778 void QPieSeriesPrivate::scaleDomain(Domain& domain)
782 void QPieSeriesPrivate::scaleDomain(Domain& domain)
779 {
783 {
780 Q_UNUSED(domain);
784 Q_UNUSED(domain);
781 #ifndef QT_NO_DEBUG
785 #ifndef QT_NO_DEBUG
782 qWarning() << __FILE__<<__FUNCTION__<<"not implemented";
786 qWarning() << __FILE__<<__FUNCTION__<<"not implemented";
783 #endif
787 #endif
784 }
788 }
785
789
786 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
790 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
787 {
791 {
788 Q_Q(QPieSeries);
792 Q_Q(QPieSeries);
789 PieChartItem* pie = new PieChartItem(q,presenter);
793 PieChartItem* pie = new PieChartItem(q,presenter);
790 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
794 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
791 presenter->animator()->addAnimation(pie);
795 presenter->animator()->addAnimation(pie);
792 }
796 }
793 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
797 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
794 return pie;
798 return pie;
795 }
799 }
796
800
797 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
801 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
798 {
802 {
799 Q_Q(QPieSeries);
803 Q_Q(QPieSeries);
800 QList<LegendMarker*> markers;
804 QList<LegendMarker*> markers;
801 foreach(QPieSlice* slice, q->slices()) {
805 foreach(QPieSlice* slice, q->slices()) {
802 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
806 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
803 markers << marker;
807 markers << marker;
804 }
808 }
805 return markers;
809 return markers;
806 }
810 }
807
811
808 #include "moc_qpieseries.cpp"
812 #include "moc_qpieseries.cpp"
809 #include "moc_qpieseries_p.cpp"
813 #include "moc_qpieseries_p.cpp"
810
814
811 QTCOMMERCIALCHART_END_NAMESPACE
815 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,326 +1,398
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include <QtTest/QtTest>
21 #include <QtTest/QtTest>
22 #include <qchartview.h>
22 #include <qchartview.h>
23 #include <qchart.h>
23 #include <qchart.h>
24 #include <qpieseries.h>
24 #include <qpieseries.h>
25 #include <qpieslice.h>
25 #include <qpieslice.h>
26 #include <qpiemodelmapper.h>
27 #include <QStandardItemModel>
26 #include <tst_definitions.h>
28 #include <tst_definitions.h>
27
29
28 QTCOMMERCIALCHART_USE_NAMESPACE
30 QTCOMMERCIALCHART_USE_NAMESPACE
29
31
30 Q_DECLARE_METATYPE(QPieSlice*)
32 Q_DECLARE_METATYPE(QPieSlice*)
31
33
32 class tst_qpieseries : public QObject
34 class tst_qpieseries : public QObject
33 {
35 {
34 Q_OBJECT
36 Q_OBJECT
35
37
36 public slots:
38 public slots:
37 void initTestCase();
39 void initTestCase();
38 void cleanupTestCase();
40 void cleanupTestCase();
39 void init();
41 void init();
40 void cleanup();
42 void cleanup();
41
43
42 private slots:
44 private slots:
43 void construction();
45 void construction();
44 void append();
46 void append();
45 void insert();
47 void insert();
46 void remove();
48 void remove();
47 void calculatedValues();
49 void calculatedValues();
48 void clickedSignal();
50 void clickedSignal();
49 void hoverSignal();
51 void hoverSignal();
52 void model();
53 void modelCustomMap();
50
54
51 private:
55 private:
52 void verifyCalculatedData(const QPieSeries &series, bool *ok);
56 void verifyCalculatedData(const QPieSeries &series, bool *ok);
53
57
54 private:
58 private:
55
59
56 };
60 };
57
61
58 void tst_qpieseries::initTestCase()
62 void tst_qpieseries::initTestCase()
59 {
63 {
60 qRegisterMetaType<QPieSlice*>("QPieSlice*");
64 qRegisterMetaType<QPieSlice*>("QPieSlice*");
61 }
65 }
62
66
63 void tst_qpieseries::cleanupTestCase()
67 void tst_qpieseries::cleanupTestCase()
64 {
68 {
65 }
69 }
66
70
67 void tst_qpieseries::init()
71 void tst_qpieseries::init()
68 {
72 {
69
73
70 }
74 }
71
75
72 void tst_qpieseries::cleanup()
76 void tst_qpieseries::cleanup()
73 {
77 {
74
78
75 }
79 }
76
80
77 void tst_qpieseries::construction()
81 void tst_qpieseries::construction()
78 {
82 {
79 // verify default values
83 // verify default values
80 QPieSeries s;
84 QPieSeries s;
81 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
85 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
82 QVERIFY(s.count() == 0);
86 QVERIFY(s.count() == 0);
83 QVERIFY(s.isEmpty());
87 QVERIFY(s.isEmpty());
84 QCOMPARE(s.sum(), 0.0);
88 QCOMPARE(s.sum(), 0.0);
85 QCOMPARE(s.horizontalPosition(), 0.5);
89 QCOMPARE(s.horizontalPosition(), 0.5);
86 QCOMPARE(s.verticalPosition(), 0.5);
90 QCOMPARE(s.verticalPosition(), 0.5);
87 QCOMPARE(s.pieSize(), 0.7);
91 QCOMPARE(s.pieSize(), 0.7);
88 QCOMPARE(s.pieStartAngle(), 0.0);
92 QCOMPARE(s.pieStartAngle(), 0.0);
89 QCOMPARE(s.pieEndAngle(), 360.0);
93 QCOMPARE(s.pieEndAngle(), 360.0);
90 }
94 }
91
95
92 void tst_qpieseries::append()
96 void tst_qpieseries::append()
93 {
97 {
94 QPieSeries s;
98 QPieSeries s;
95
99
96 // append pointer
100 // append pointer
97 QPieSlice *slice1 = 0;
101 QPieSlice *slice1 = 0;
98 QVERIFY(!s.append(slice1));
102 QVERIFY(!s.append(slice1));
99 slice1 = new QPieSlice(1, "slice 1");
103 slice1 = new QPieSlice(1, "slice 1");
100 QVERIFY(s.append(slice1));
104 QVERIFY(s.append(slice1));
101 QVERIFY(!s.append(slice1));
105 QVERIFY(!s.append(slice1));
102 QCOMPARE(s.count(), 1);
106 QCOMPARE(s.count(), 1);
103
107
104 // append pointer list
108 // append pointer list
105 QList<QPieSlice *> list;
109 QList<QPieSlice *> list;
106 QVERIFY(!s.append(list));
110 QVERIFY(!s.append(list));
107 list << (QPieSlice *) 0;
111 list << (QPieSlice *) 0;
108 QVERIFY(!s.append(list));
112 QVERIFY(!s.append(list));
109 list.clear();
113 list.clear();
110 list << new QPieSlice(2, "slice 2");
114 list << new QPieSlice(2, "slice 2");
111 list << new QPieSlice(3, "slice 3");
115 list << new QPieSlice(3, "slice 3");
112 QVERIFY(s.append(list));
116 QVERIFY(s.append(list));
113 QVERIFY(!s.append(list));
117 QVERIFY(!s.append(list));
114 QCOMPARE(s.count(), 3);
118 QCOMPARE(s.count(), 3);
115
119
116 // append operator
120 // append operator
117 s << new QPieSlice(4, "slice 4");
121 s << new QPieSlice(4, "slice 4");
118 s << slice1; // fails because already added
122 s << slice1; // fails because already added
119 QCOMPARE(s.count(), 4);
123 QCOMPARE(s.count(), 4);
120
124
121 // append with params
125 // append with params
122 QPieSlice *slice5 = s.append(5, "slice 5");
126 QPieSlice *slice5 = s.append(5, "slice 5");
123 QVERIFY(slice5 != 0);
127 QVERIFY(slice5 != 0);
124 QCOMPARE(slice5->value(), 5.0);
128 QCOMPARE(slice5->value(), 5.0);
125 QCOMPARE(slice5->label(), QString("slice 5"));
129 QCOMPARE(slice5->label(), QString("slice 5"));
126 QCOMPARE(s.count(), 5);
130 QCOMPARE(s.count(), 5);
127
131
128 // check slices
132 // check slices
129 QVERIFY(!s.isEmpty());
133 QVERIFY(!s.isEmpty());
130 for (int i=0; i<s.count(); i++) {
134 for (int i=0; i<s.count(); i++) {
131 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
135 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
132 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
136 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
133 }
137 }
134 }
138 }
135
139
136 void tst_qpieseries::insert()
140 void tst_qpieseries::insert()
137 {
141 {
138 QPieSeries s;
142 QPieSeries s;
139
143
140 // insert one slice
144 // insert one slice
141 QPieSlice *slice1 = 0;
145 QPieSlice *slice1 = 0;
142 QVERIFY(!s.insert(0, slice1));
146 QVERIFY(!s.insert(0, slice1));
143 slice1 = new QPieSlice(1, "slice 1");
147 slice1 = new QPieSlice(1, "slice 1");
144 QVERIFY(!s.insert(-1, slice1));
148 QVERIFY(!s.insert(-1, slice1));
145 QVERIFY(!s.insert(5, slice1));
149 QVERIFY(!s.insert(5, slice1));
146 QVERIFY(s.insert(0, slice1));
150 QVERIFY(s.insert(0, slice1));
147 QVERIFY(!s.insert(0, slice1));
151 QVERIFY(!s.insert(0, slice1));
148 QCOMPARE(s.count(), 1);
152 QCOMPARE(s.count(), 1);
149
153
150 // add some more slices
154 // add some more slices
151 s.append(2, "slice 2");
155 s.append(2, "slice 2");
152 s.append(4, "slice 4");
156 s.append(4, "slice 4");
153 QCOMPARE(s.count(), 3);
157 QCOMPARE(s.count(), 3);
154
158
155 // insert between slices
159 // insert between slices
156 s.insert(2, new QPieSlice(3, "slice 3"));
160 s.insert(2, new QPieSlice(3, "slice 3"));
157 QCOMPARE(s.count(), 4);
161 QCOMPARE(s.count(), 4);
158
162
159 // check slices
163 // check slices
160 for (int i=0; i<s.count(); i++) {
164 for (int i=0; i<s.count(); i++) {
161 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
165 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
162 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
166 QCOMPARE(s.slices().at(i)->label(), QString("slice ") + QString::number(i+1));
163 }
167 }
164 }
168 }
165
169
166 void tst_qpieseries::remove()
170 void tst_qpieseries::remove()
167 {
171 {
168 QPieSeries s;
172 QPieSeries s;
169
173
170 // add some slices
174 // add some slices
171 QPieSlice *slice1 = s.append(1, "slice 1");
175 QPieSlice *slice1 = s.append(1, "slice 1");
172 QPieSlice *slice2 = s.append(2, "slice 2");
176 QPieSlice *slice2 = s.append(2, "slice 2");
173 QPieSlice *slice3 = s.append(3, "slice 3");
177 QPieSlice *slice3 = s.append(3, "slice 3");
174 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
178 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
175 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
179 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
176 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
180 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
177 QCOMPARE(s.count(), 3);
181 QCOMPARE(s.count(), 3);
178
182
179 // null pointer remove
183 // null pointer remove
180 QVERIFY(!s.remove(0));
184 QVERIFY(!s.remove(0));
181
185
182 // remove first
186 // remove first
183 QVERIFY(s.remove(slice1));
187 QVERIFY(s.remove(slice1));
184 QVERIFY(!s.remove(slice1));
188 QVERIFY(!s.remove(slice1));
185 QCOMPARE(s.count(), 2);
189 QCOMPARE(s.count(), 2);
186 QCOMPARE(s.slices().at(0)->label(), slice2->label());
190 QCOMPARE(s.slices().at(0)->label(), slice2->label());
187
191
188 // remove all
192 // remove all
189 s.clear();
193 s.clear();
190 QVERIFY(s.isEmpty());
194 QVERIFY(s.isEmpty());
191 QVERIFY(s.slices().isEmpty());
195 QVERIFY(s.slices().isEmpty());
192 QCOMPARE(s.count(), 0);
196 QCOMPARE(s.count(), 0);
193
197
194 // check that slices were actually destroyed
198 // check that slices were actually destroyed
195 TRY_COMPARE(spy1.count(), 1);
199 TRY_COMPARE(spy1.count(), 1);
196 TRY_COMPARE(spy2.count(), 1);
200 TRY_COMPARE(spy2.count(), 1);
197 TRY_COMPARE(spy3.count(), 1);
201 TRY_COMPARE(spy3.count(), 1);
198 }
202 }
199
203
200 void tst_qpieseries::calculatedValues()
204 void tst_qpieseries::calculatedValues()
201 {
205 {
202 bool ok;
206 bool ok;
203 QPieSeries s;
207 QPieSeries s;
204
208
205 // add a slice
209 // add a slice
206 QPieSlice *slice1 = s.append(1, "slice 1");
210 QPieSlice *slice1 = s.append(1, "slice 1");
207 verifyCalculatedData(s, &ok);
211 verifyCalculatedData(s, &ok);
208 if (!ok)
212 if (!ok)
209 return;
213 return;
210
214
211 // add some more slices
215 // add some more slices
212 QList<QPieSlice *> list;
216 QList<QPieSlice *> list;
213 list << new QPieSlice(2, "slice 2");
217 list << new QPieSlice(2, "slice 2");
214 list << new QPieSlice(3, "slice 3");
218 list << new QPieSlice(3, "slice 3");
215 s.append(list);
219 s.append(list);
216 verifyCalculatedData(s, &ok);
220 verifyCalculatedData(s, &ok);
217 if (!ok)
221 if (!ok)
218 return;
222 return;
219
223
220 // remove a slice
224 // remove a slice
221 s.remove(slice1);
225 s.remove(slice1);
222 verifyCalculatedData(s, &ok);
226 verifyCalculatedData(s, &ok);
223 if (!ok)
227 if (!ok)
224 return;
228 return;
225
229
226 // insert a slice
230 // insert a slice
227 s.insert(0, new QPieSlice(1, "Slice 4"));
231 s.insert(0, new QPieSlice(1, "Slice 4"));
228 verifyCalculatedData(s, &ok);
232 verifyCalculatedData(s, &ok);
229 if (!ok)
233 if (!ok)
230 return;
234 return;
231
235
232 // clear all
236 // clear all
233 s.clear();
237 s.clear();
234 verifyCalculatedData(s, &ok);
238 verifyCalculatedData(s, &ok);
235 }
239 }
236
240
237 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
241 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
238 {
242 {
239 *ok = false;
243 *ok = false;
240
244
241 qreal sum = 0;
245 qreal sum = 0;
242 foreach (const QPieSlice *slice, series.slices())
246 foreach (const QPieSlice *slice, series.slices())
243 sum += slice->value();
247 sum += slice->value();
244 QCOMPARE(series.sum(), sum);
248 QCOMPARE(series.sum(), sum);
245
249
246 qreal startAngle = series.pieStartAngle();
250 qreal startAngle = series.pieStartAngle();
247 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
251 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
248 foreach (const QPieSlice *slice, series.slices()) {
252 foreach (const QPieSlice *slice, series.slices()) {
249 qreal ratio = slice->value() / sum;
253 qreal ratio = slice->value() / sum;
250 qreal sliceSpan = pieAngleSpan * ratio;
254 qreal sliceSpan = pieAngleSpan * ratio;
251 QCOMPARE(slice->startAngle(), startAngle);
255 QCOMPARE(slice->startAngle(), startAngle);
252 QCOMPARE(slice->endAngle(), startAngle + sliceSpan);
256 QCOMPARE(slice->endAngle(), startAngle + sliceSpan);
253 QCOMPARE(slice->percentage(), ratio);
257 QCOMPARE(slice->percentage(), ratio);
254 startAngle += sliceSpan;
258 startAngle += sliceSpan;
255 }
259 }
256
260
257 if (!series.isEmpty())
261 if (!series.isEmpty())
258 QCOMPARE(series.slices().last()->endAngle(), series.pieEndAngle());
262 QCOMPARE(series.slices().last()->endAngle(), series.pieEndAngle());
259
263
260 *ok = true;
264 *ok = true;
261 }
265 }
262
266
263
267
264 void tst_qpieseries::clickedSignal()
268 void tst_qpieseries::clickedSignal()
265 {
269 {
266 // create a pie series
270 // create a pie series
267 QPieSeries *series = new QPieSeries();
271 QPieSeries *series = new QPieSeries();
268 series->setPieSize(1.0);
272 series->setPieSize(1.0);
269 QPieSlice *s1 = series->append(1, "slice 1");
273 QPieSlice *s1 = series->append(1, "slice 1");
270 series->append(2, "slice 2");
274 series->append(2, "slice 2");
271 series->append(3, "slice 3");
275 series->append(3, "slice 3");
272 QSignalSpy clickSpy1(series, SIGNAL(clicked(QPieSlice*)));
276 QSignalSpy clickSpy1(series, SIGNAL(clicked(QPieSlice*)));
273
277
274 // add series to the chart
278 // add series to the chart
275 QChartView view(new QChart());
279 QChartView view(new QChart());
276 view.resize(200, 200);
280 view.resize(200, 200);
277 view.chart()->addSeries(series);
281 view.chart()->addSeries(series);
278 view.show();
282 view.show();
279 QTest::qWaitForWindowShown(&view);
283 QTest::qWaitForWindowShown(&view);
280
284
281 // simulate clicks
285 // simulate clicks
282 // pie rectangle: QRectF(60,60 121x121)
286 // pie rectangle: QRectF(60,60 121x121)
283 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(139, 85)); // inside slice 1
287 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(139, 85)); // inside slice 1
284 TRY_COMPARE(clickSpy1.count(), 1);
288 TRY_COMPARE(clickSpy1.count(), 1);
285 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy1.at(0).at(0)), s1);
289 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy1.at(0).at(0)), s1);
286 }
290 }
287
291
288 void tst_qpieseries::hoverSignal()
292 void tst_qpieseries::hoverSignal()
289 {
293 {
290 // create a pie series
294 // create a pie series
291 QPieSeries *series = new QPieSeries();
295 QPieSeries *series = new QPieSeries();
292 series->setPieSize(1.0);
296 series->setPieSize(1.0);
293 QPieSlice *s1 = series->append(1, "slice 1");
297 QPieSlice *s1 = series->append(1, "slice 1");
294 series->append(2, "slice 2");
298 series->append(2, "slice 2");
295 series->append(3, "slice 3");
299 series->append(3, "slice 3");
296
300
297 // add series to the chart
301 // add series to the chart
298 QChartView view(new QChart());
302 QChartView view(new QChart());
299 view.resize(200, 200);
303 view.resize(200, 200);
300 view.chart()->addSeries(series);
304 view.chart()->addSeries(series);
301 view.show();
305 view.show();
302 QTest::qWaitForWindowShown(&view);
306 QTest::qWaitForWindowShown(&view);
303
307
304 // first move to right top corner
308 // first move to right top corner
305 QTest::mouseMove(view.viewport(), QPoint(200, 0));
309 QTest::mouseMove(view.viewport(), QPoint(200, 0));
306 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
310 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
307
311
308 // move inside the slice
312 // move inside the slice
309 // pie rectangle: QRectF(60,60 121x121)
313 // pie rectangle: QRectF(60,60 121x121)
310 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
314 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
311 QTest::mouseMove(view.viewport(), QPoint(139, 85));
315 QTest::mouseMove(view.viewport(), QPoint(139, 85));
312 TRY_COMPARE(hoverSpy.count(), 1);
316 TRY_COMPARE(hoverSpy.count(), 1);
313 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
317 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
314 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
318 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
315
319
316 // move outside the slice
320 // move outside the slice
317 QTest::mouseMove(view.viewport(), QPoint(200, 0));
321 QTest::mouseMove(view.viewport(), QPoint(200, 0));
318 TRY_COMPARE(hoverSpy.count(), 2);
322 TRY_COMPARE(hoverSpy.count(), 2);
319 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
323 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
320 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
324 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
321 }
325 }
322
326
327 void tst_qpieseries::model()
328 {
329 QPieSeries *series = new QPieSeries;
330 QStandardItemModel *stdModel = new QStandardItemModel(0, 2);
331 series->setModel(stdModel);
332 QVERIFY2((series->model()) == stdModel, "Model should be stdModel");
333
334 int rowCount = 3;
335 for (int row = 0; row < rowCount; ++row) {
336 for (int column = 0; column < 2; column++) {
337 QStandardItem *item = new QStandardItem(row * column);
338 stdModel->setItem(row, column, item);
339 }
340 }
341
342 // data has been added to the model, but mapper is not set the number of slices should still be 0
343 QVERIFY2(series->slices().count() == 0, "Mapper has not been set, so the number of slices should be 0");
344
345 // set the mapper
346 QPieModelMapper *mapper = new QPieModelMapper;
347 mapper->setMapValues(0);
348 mapper->setMapLabels(0);
349 series->setModelMapper(mapper); // this should cause the Pie to get initialized from the model, since there is now both the model and the mapper defined
350 QCOMPARE(series->slices().count(), rowCount);
351
352 // reset the mappings
353 mapper->reset();
354 QCOMPARE(series->slices().count(), 0); // Mappings have been reset and are invalid, so the number of slices should be 0
355
356 // unset the model and the mapper
357 series->setModel(0);
358 series->setModelMapper(0);
359 QVERIFY(series->model() == 0); // Model should be unset
360 QVERIFY(series->modelMapper() == 0); // Model mapper should be unset
361 }
362
363 void tst_qpieseries::modelCustomMap()
364 {
365 int rowCount = 12;
366 QStandardItemModel *stdModel = new QStandardItemModel(0, 2);
367 for (int row = 0; row < rowCount; ++row) {
368 for (int column = 0; column < 2; column++) {
369 QStandardItem *item = new QStandardItem(row * column);
370 stdModel->setItem(row, column, item);
371 }
372 }
373
374 QPieSeries *series = new QPieSeries;
375 series->setModel(stdModel);
376
377 QPieModelMapper *mapper = new QPieModelMapper;
378 mapper->setMapValues(0);
379 mapper->setMapLabels(0);
380 series->setModelMapper(mapper);
381 QCOMPARE(series->slices().count(), rowCount);
382
383 // lets customize the mapping
384 int first = 3;
385 mapper->setFirst(first);
386 QCOMPARE(series->slices().count(), rowCount - first);
387 int count = 7;
388 mapper->setCount(count);
389 QCOMPARE(series->slices().count(), count);
390 first = 9;
391 mapper->setFirst(first);
392 QCOMPARE(series->slices().count(), qMin(count, rowCount - first));
393 }
394
323 QTEST_MAIN(tst_qpieseries)
395 QTEST_MAIN(tst_qpieseries)
324
396
325 #include "tst_qpieseries.moc"
397 #include "tst_qpieseries.moc"
326
398
General Comments 0
You need to be logged in to leave comments. Login now