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