##// END OF EJS Templates
pie: added everything as a property in QPieSlice...
Jani Honkonen -
r1274:9c11726517fa
parent child
Show More
@@ -0,0 +1,43
1 #ifndef QPIESLICE_P_H
2 #define QPIESLICE_P_H
3
4 #include <QObject>
5 #include "qpieslice.h"
6 #include "pieslicedata_p.h"
7
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9
10 class QPieSlicePrivate : public QObject
11 {
12 Q_OBJECT
13
14 public:
15 QPieSlicePrivate(QPieSlice *parent);
16 ~QPieSlicePrivate();
17
18 static QPieSlicePrivate* fromSlice(QPieSlice *slice);
19
20 void setPen(const QPen &pen, bool themed);
21 void setBrush(const QBrush &brush, bool themed);
22 void setLabelPen(const QPen &pen, bool themed);
23 void setLabelFont(const QFont &font, bool themed);
24
25 void setPercentage(qreal percentage);
26 void setStartAngle(qreal angle);
27 void setAngleSpan(qreal span);
28
29 private:
30 PieSliceData m_data;
31
32 private:
33 friend class QPieSeriesPrivate;
34 friend class ChartTheme;
35 friend class PieChartItem;
36
37 QPieSlice * const q_ptr;
38 Q_DECLARE_PUBLIC(QPieSlice)
39 };
40
41 QTCOMMERCIALCHART_END_NAMESPACE
42
43 #endif // QPIESLICE_P_H
@@ -1,63 +1,63
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 "drilldownslice.h"
21 #include "drilldownslice.h"
22
22
23 QTCOMMERCIALCHART_USE_NAMESPACE
23 QTCOMMERCIALCHART_USE_NAMESPACE
24
24
25 DrilldownSlice::DrilldownSlice(qreal value, QString prefix, QAbstractSeries* drilldownSeries)
25 DrilldownSlice::DrilldownSlice(qreal value, QString prefix, QAbstractSeries* drilldownSeries)
26 :m_drilldownSeries(drilldownSeries),
26 :m_drilldownSeries(drilldownSeries),
27 m_prefix(prefix)
27 m_prefix(prefix)
28 {
28 {
29 setValue(value);
29 setValue(value);
30 updateLabel();
30 updateLabel();
31 setLabelFont(QFont("Arial", 8));
31 setLabelFont(QFont("Arial", 8));
32 connect(this, SIGNAL(calculatedDataChanged()), this, SLOT(updateLabel()));
32 connect(this, SIGNAL(percentageChanged()), this, SLOT(updateLabel()));
33 connect(this, SIGNAL(hovered(bool)), this, SLOT(showHighlight(bool)));
33 connect(this, SIGNAL(hovered(bool)), this, SLOT(showHighlight(bool)));
34 }
34 }
35
35
36 DrilldownSlice::~DrilldownSlice()
36 DrilldownSlice::~DrilldownSlice()
37 {
37 {
38
38
39 }
39 }
40
40
41 QAbstractSeries* DrilldownSlice::drilldownSeries() const
41 QAbstractSeries* DrilldownSlice::drilldownSeries() const
42 {
42 {
43 return m_drilldownSeries;
43 return m_drilldownSeries;
44 }
44 }
45
45
46 void DrilldownSlice::updateLabel()
46 void DrilldownSlice::updateLabel()
47 {
47 {
48 QString label = m_prefix;
48 QString label = m_prefix;
49 label += " $";
49 label += " $";
50 label += QString::number(this->value());
50 label += QString::number(this->value());
51 label += ", ";
51 label += ", ";
52 label += QString::number(this->percentage()*100, 'f', 1);
52 label += QString::number(this->percentage()*100, 'f', 1);
53 label += "%";
53 label += "%";
54 setLabel(label);
54 setLabel(label);
55 }
55 }
56
56
57 void DrilldownSlice::showHighlight(bool show)
57 void DrilldownSlice::showHighlight(bool show)
58 {
58 {
59 setLabelVisible(show);
59 setLabelVisible(show);
60 setExploded(show);
60 setExploded(show);
61 }
61 }
62
62
63 #include "moc_drilldownslice.cpp"
63 #include "moc_drilldownslice.cpp"
@@ -1,397 +1,385
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 "charttheme_p.h"
21 #include "charttheme_p.h"
22 #include "qchart.h"
22 #include "qchart.h"
23 #include "qchart_p.h"
23 #include "qchart_p.h"
24 #include "qchartview.h"
24 #include "qchartview.h"
25 #include "qlegend.h"
25 #include "qlegend.h"
26 #include "qaxis.h"
26 #include "qaxis.h"
27 #include <QTime>
27 #include <QTime>
28
28
29 //series
29 //series
30 #include "qbarset.h"
30 #include "qbarset.h"
31 #include "qbarseries.h"
31 #include "qbarseries.h"
32 #include "qstackedbarseries.h"
32 #include "qstackedbarseries.h"
33 #include "qpercentbarseries.h"
33 #include "qpercentbarseries.h"
34 #include "qlineseries.h"
34 #include "qlineseries.h"
35 #include "qareaseries.h"
35 #include "qareaseries.h"
36 #include "qscatterseries.h"
36 #include "qscatterseries.h"
37 #include "qpieseries.h"
37 #include "qpieseries.h"
38 #include "qpieslice.h"
38 #include "qpieslice.h"
39 #include "qpieslice_p.h"
39 #include "qsplineseries.h"
40 #include "qsplineseries.h"
40
41
41 //items
42 //items
42 #include "chartaxis_p.h"
43 #include "chartaxis_p.h"
43 #include "barchartitem_p.h"
44 #include "barchartitem_p.h"
44 #include "stackedbarchartitem_p.h"
45 #include "stackedbarchartitem_p.h"
45 #include "percentbarchartitem_p.h"
46 #include "percentbarchartitem_p.h"
46 #include "linechartitem_p.h"
47 #include "linechartitem_p.h"
47 #include "areachartitem_p.h"
48 #include "areachartitem_p.h"
48 #include "scatterchartitem_p.h"
49 #include "scatterchartitem_p.h"
49 #include "piechartitem_p.h"
50 #include "piechartitem_p.h"
50 #include "splinechartitem_p.h"
51 #include "splinechartitem_p.h"
51
52
52 //themes
53 //themes
53 #include "chartthemesystem_p.h"
54 #include "chartthemesystem_p.h"
54 #include "chartthemelight_p.h"
55 #include "chartthemelight_p.h"
55 #include "chartthemebluecerulean_p.h"
56 #include "chartthemebluecerulean_p.h"
56 #include "chartthemedark_p.h"
57 #include "chartthemedark_p.h"
57 #include "chartthemebrownsand_p.h"
58 #include "chartthemebrownsand_p.h"
58 #include "chartthemebluencs_p.h"
59 #include "chartthemebluencs_p.h"
59 #include "chartthemehighcontrast_p.h"
60 #include "chartthemehighcontrast_p.h"
60 #include "chartthemeblueicy_p.h"
61 #include "chartthemeblueicy_p.h"
61
62
62 QTCOMMERCIALCHART_BEGIN_NAMESPACE
63 QTCOMMERCIALCHART_BEGIN_NAMESPACE
63
64
64 ChartTheme::ChartTheme(QChart::ChartTheme id) :
65 ChartTheme::ChartTheme(QChart::ChartTheme id) :
65 m_masterFont(QFont("arial", 14)),
66 m_masterFont(QFont("arial", 14)),
66 m_labelFont(QFont("arial", 10)),
67 m_labelFont(QFont("arial", 10)),
67 m_titleBrush(QColor(QRgb(0x000000))),
68 m_titleBrush(QColor(QRgb(0x000000))),
68 m_axisLinePen(QPen(QRgb(0x000000))),
69 m_axisLinePen(QPen(QRgb(0x000000))),
69 m_axisLabelBrush(QColor(QRgb(0x000000))),
70 m_axisLabelBrush(QColor(QRgb(0x000000))),
70 m_backgroundShadesPen(Qt::NoPen),
71 m_backgroundShadesPen(Qt::NoPen),
71 m_backgroundShadesBrush(Qt::NoBrush),
72 m_backgroundShadesBrush(Qt::NoBrush),
72 m_backgroundShades(BackgroundShadesNone),
73 m_backgroundShades(BackgroundShadesNone),
73 m_backgroundDropShadowEnabled(false),
74 m_backgroundDropShadowEnabled(false),
74 m_gridLinePen(QPen(QRgb(0x000000))),
75 m_gridLinePen(QPen(QRgb(0x000000))),
75 m_force(false)
76 m_force(false)
76 {
77 {
77 m_id = id;
78 m_id = id;
78 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
79 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
79 }
80 }
80
81
81
82
82 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
83 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
83 {
84 {
84 switch(theme) {
85 switch(theme) {
85 case QChart::ChartThemeLight:
86 case QChart::ChartThemeLight:
86 return new ChartThemeLight();
87 return new ChartThemeLight();
87 case QChart::ChartThemeBlueCerulean:
88 case QChart::ChartThemeBlueCerulean:
88 return new ChartThemeBlueCerulean();
89 return new ChartThemeBlueCerulean();
89 case QChart::ChartThemeDark:
90 case QChart::ChartThemeDark:
90 return new ChartThemeDark();
91 return new ChartThemeDark();
91 case QChart::ChartThemeBrownSand:
92 case QChart::ChartThemeBrownSand:
92 return new ChartThemeBrownSand();
93 return new ChartThemeBrownSand();
93 case QChart::ChartThemeBlueNcs:
94 case QChart::ChartThemeBlueNcs:
94 return new ChartThemeBlueNcs();
95 return new ChartThemeBlueNcs();
95 case QChart::ChartThemeHighContrast:
96 case QChart::ChartThemeHighContrast:
96 return new ChartThemeHighContrast();
97 return new ChartThemeHighContrast();
97 case QChart::ChartThemeBlueIcy:
98 case QChart::ChartThemeBlueIcy:
98 return new ChartThemeBlueIcy();
99 return new ChartThemeBlueIcy();
99 default:
100 default:
100 return new ChartThemeSystem();
101 return new ChartThemeSystem();
101 }
102 }
102 }
103 }
103
104
104 void ChartTheme::decorate(QChart *chart)
105 void ChartTheme::decorate(QChart *chart)
105 {
106 {
106 QBrush brush;
107 QBrush brush;
107
108
108 if(brush == chart->backgroundBrush() || m_force)
109 if(brush == chart->backgroundBrush() || m_force)
109 chart->setBackgroundBrush(m_chartBackgroundGradient);
110 chart->setBackgroundBrush(m_chartBackgroundGradient);
110 chart->setTitleFont(m_masterFont);
111 chart->setTitleFont(m_masterFont);
111 chart->setTitleBrush(m_titleBrush);
112 chart->setTitleBrush(m_titleBrush);
112 chart->setBackgroundDropShadowEnabled(m_backgroundDropShadowEnabled);
113 chart->setBackgroundDropShadowEnabled(m_backgroundDropShadowEnabled);
113 }
114 }
114
115
115 void ChartTheme::decorate(QLegend *legend)
116 void ChartTheme::decorate(QLegend *legend)
116 {
117 {
117 QPen pen;
118 QPen pen;
118 QBrush brush;
119 QBrush brush;
119
120
120 if (pen == legend->pen() || m_force){
121 if (pen == legend->pen() || m_force){
121 legend->setPen(Qt::NoPen);
122 legend->setPen(Qt::NoPen);
122 }
123 }
123
124
124 if (brush == legend->brush() || m_force) {
125 if (brush == legend->brush() || m_force) {
125 legend->setBrush(m_chartBackgroundGradient);
126 legend->setBrush(m_chartBackgroundGradient);
126 }
127 }
127 }
128 }
128
129
129 void ChartTheme::decorate(QAreaSeries *series, int index)
130 void ChartTheme::decorate(QAreaSeries *series, int index)
130 {
131 {
131 QPen pen;
132 QPen pen;
132 QBrush brush;
133 QBrush brush;
133
134
134 if (pen == series->pen() || m_force){
135 if (pen == series->pen() || m_force){
135 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
136 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
136 pen.setWidthF(2);
137 pen.setWidthF(2);
137 series->setPen(pen);
138 series->setPen(pen);
138 }
139 }
139
140
140 if (brush == series->brush() || m_force) {
141 if (brush == series->brush() || m_force) {
141 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
142 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
142 series->setBrush(brush);
143 series->setBrush(brush);
143 }
144 }
144 }
145 }
145
146
146
147
147 void ChartTheme::decorate(QLineSeries *series,int index)
148 void ChartTheme::decorate(QLineSeries *series,int index)
148 {
149 {
149 QPen pen;
150 QPen pen;
150 if(pen == series->pen() || m_force ){
151 if(pen == series->pen() || m_force ){
151 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
152 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
152 pen.setWidthF(2);
153 pen.setWidthF(2);
153 series->setPen(pen);
154 series->setPen(pen);
154 }
155 }
155 }
156 }
156
157
157 void ChartTheme::decorate(QBarSeries *series, int index)
158 void ChartTheme::decorate(QBarSeries *series, int index)
158 {
159 {
159 QBrush brush;
160 QBrush brush;
160 QPen pen;
161 QPen pen;
161 QList<QBarSet *> sets = series->barSets();
162 QList<QBarSet *> sets = series->barSets();
162
163
163 qreal takeAtPos = 0.5;
164 qreal takeAtPos = 0.5;
164 qreal step = 0.2;
165 qreal step = 0.2;
165 if (sets.count() > 1 ) {
166 if (sets.count() > 1 ) {
166 step = 1.0 / (qreal) sets.count();
167 step = 1.0 / (qreal) sets.count();
167 if (sets.count() % m_seriesGradients.count())
168 if (sets.count() % m_seriesGradients.count())
168 step *= m_seriesGradients.count();
169 step *= m_seriesGradients.count();
169 else
170 else
170 step *= (m_seriesGradients.count() - 1);
171 step *= (m_seriesGradients.count() - 1);
171 }
172 }
172
173
173 for (int i(0); i < sets.count(); i++) {
174 for (int i(0); i < sets.count(); i++) {
174 int colorIndex = (index + i) % m_seriesGradients.count();
175 int colorIndex = (index + i) % m_seriesGradients.count();
175 if (i > 0 && i % m_seriesGradients.count() == 0) {
176 if (i > 0 && i % m_seriesGradients.count() == 0) {
176 // There is no dedicated base color for each sets, generate more colors
177 // There is no dedicated base color for each sets, generate more colors
177 takeAtPos += step;
178 takeAtPos += step;
178 if (takeAtPos == 1.0)
179 if (takeAtPos == 1.0)
179 takeAtPos += step;
180 takeAtPos += step;
180 takeAtPos -= (int) takeAtPos;
181 takeAtPos -= (int) takeAtPos;
181 }
182 }
182 if (brush == sets.at(i)->brush() || m_force )
183 if (brush == sets.at(i)->brush() || m_force )
183 sets.at(i)->setBrush(colorAt(m_seriesGradients.at(colorIndex), takeAtPos));
184 sets.at(i)->setBrush(colorAt(m_seriesGradients.at(colorIndex), takeAtPos));
184
185
185 // Pick label color from the opposite end of the gradient.
186 // Pick label color from the opposite end of the gradient.
186 // 0.3 as a boundary seems to work well.
187 // 0.3 as a boundary seems to work well.
187 if (takeAtPos < 0.3)
188 if (takeAtPos < 0.3)
188 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
189 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
189 else
190 else
190 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
191 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
191
192
192 if (pen == sets.at(i)->pen() || m_force) {
193 if (pen == sets.at(i)->pen() || m_force) {
193 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
194 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
194 sets.at(i)->setPen(c);
195 sets.at(i)->setPen(c);
195 }
196 }
196 }
197 }
197 }
198 }
198
199
199 void ChartTheme::decorate(QScatterSeries *series, int index)
200 void ChartTheme::decorate(QScatterSeries *series, int index)
200 {
201 {
201 QPen pen;
202 QPen pen;
202 QBrush brush;
203 QBrush brush;
203
204
204 if (pen == series->pen() || m_force) {
205 if (pen == series->pen() || m_force) {
205 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
206 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
206 pen.setWidthF(2);
207 pen.setWidthF(2);
207 series->setPen(pen);
208 series->setPen(pen);
208 }
209 }
209
210
210 if (brush == series->brush() || m_force) {
211 if (brush == series->brush() || m_force) {
211 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
212 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
212 series->setBrush(brush);
213 series->setBrush(brush);
213 }
214 }
214 }
215 }
215
216
216 void ChartTheme::decorate(QPieSeries *series, int index)
217 void ChartTheme::decorate(QPieSeries *series, int index)
217 {
218 {
218
219
219 for (int i(0); i < series->slices().count(); i++) {
220 for (int i(0); i < series->slices().count(); i++) {
220
221
221 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
222 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
222
223
223 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
224 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
224 qreal pos = (qreal) (i + 1) / (qreal) series->count();
225 qreal pos = (qreal) (i + 1) / (qreal) series->count();
225 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
226 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
226
227
227 QPieSlice *s = series->slices().at(i);
228 QPieSlice *s = series->slices().at(i);
228 PieSliceData data = PieSliceData::fromSlice(s);
229 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
229
230
230 if (data.m_slicePen.isThemed() || m_force) {
231 if (d->m_data.m_slicePen.isThemed() || m_force)
231 data.m_slicePen = penColor;
232 d->setPen(penColor, true);
232 data.m_slicePen.setThemed(true);
233 }
234
235 if (data.m_sliceBrush.isThemed() || m_force) {
236 data.m_sliceBrush = brushColor;
237 data.m_sliceBrush.setThemed(true);
238 }
239
233
240 if (data.m_labelPen.isThemed() || m_force) {
234 if (d->m_data.m_sliceBrush.isThemed() || m_force)
241 data.m_labelPen = QPen(m_titleBrush.color());
235 d->setBrush(brushColor, true);
242 data.m_labelPen.setThemed(true);
243 }
244
236
245 if (data.m_labelFont.isThemed() || m_force) {
237 if (d->m_data.m_labelPen.isThemed() || m_force)
246 data.m_labelFont = m_labelFont;
238 d->setLabelPen(QPen(m_titleBrush.color()), true);
247 data.m_labelFont.setThemed(true);
248 }
249
239
250 if (PieSliceData::fromSlice(s) != data) {
240 if (d->m_data.m_labelFont.isThemed() || m_force)
251 PieSliceData::fromSlice(s) = data;
241 d->setLabelFont(m_labelFont, true);
252 emit PieSliceData::emitAppearanceChanged(s);
253 }
254 }
242 }
255 }
243 }
256
244
257 void ChartTheme::decorate(QSplineSeries *series, int index)
245 void ChartTheme::decorate(QSplineSeries *series, int index)
258 {
246 {
259 QPen pen;
247 QPen pen;
260 if(pen == series->pen() || m_force){
248 if(pen == series->pen() || m_force){
261 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
249 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
262 pen.setWidthF(2);
250 pen.setWidthF(2);
263 series->setPen(pen);
251 series->setPen(pen);
264 }
252 }
265 }
253 }
266
254
267 void ChartTheme::decorate(QAxis *axis,bool axisX)
255 void ChartTheme::decorate(QAxis *axis,bool axisX)
268 {
256 {
269 QPen pen;
257 QPen pen;
270 QBrush brush;
258 QBrush brush;
271 QFont font;
259 QFont font;
272
260
273 if (axis->isAxisVisible()) {
261 if (axis->isAxisVisible()) {
274
262
275 if(brush == axis->labelsBrush() || m_force){
263 if(brush == axis->labelsBrush() || m_force){
276 axis->setLabelsBrush(m_axisLabelBrush);
264 axis->setLabelsBrush(m_axisLabelBrush);
277 }
265 }
278 if(pen == axis->labelsPen() || m_force){
266 if(pen == axis->labelsPen() || m_force){
279 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
267 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
280 }
268 }
281
269
282
270
283 if (axis->shadesVisible() || m_force) {
271 if (axis->shadesVisible() || m_force) {
284
272
285 if(brush == axis->shadesBrush() || m_force){
273 if(brush == axis->shadesBrush() || m_force){
286 axis->setShadesBrush(m_backgroundShadesBrush);
274 axis->setShadesBrush(m_backgroundShadesBrush);
287 }
275 }
288
276
289 if(pen == axis->shadesPen() || m_force){
277 if(pen == axis->shadesPen() || m_force){
290 axis->setShadesPen(m_backgroundShadesPen);
278 axis->setShadesPen(m_backgroundShadesPen);
291 }
279 }
292
280
293 if( m_force && (m_backgroundShades == BackgroundShadesBoth
281 if( m_force && (m_backgroundShades == BackgroundShadesBoth
294 || (m_backgroundShades == BackgroundShadesVertical && axisX)
282 || (m_backgroundShades == BackgroundShadesVertical && axisX)
295 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))){
283 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))){
296 axis->setShadesVisible(true);
284 axis->setShadesVisible(true);
297
285
298 }
286 }
299 }
287 }
300
288
301 if(pen == axis->axisPen() || m_force){
289 if(pen == axis->axisPen() || m_force){
302 axis->setAxisPen(m_axisLinePen);
290 axis->setAxisPen(m_axisLinePen);
303 }
291 }
304
292
305 if(pen == axis->gridLinePen() || m_force){
293 if(pen == axis->gridLinePen() || m_force){
306 axis->setGridLinePen(m_gridLinePen);
294 axis->setGridLinePen(m_gridLinePen);
307 }
295 }
308
296
309 if(font == axis->labelsFont() || m_force){
297 if(font == axis->labelsFont() || m_force){
310 axis->setLabelsFont(m_labelFont);
298 axis->setLabelsFont(m_labelFont);
311 }
299 }
312 }
300 }
313 }
301 }
314
302
315 void ChartTheme::generateSeriesGradients()
303 void ChartTheme::generateSeriesGradients()
316 {
304 {
317 // Generate gradients in HSV color space
305 // Generate gradients in HSV color space
318 foreach (const QColor& color, m_seriesColors) {
306 foreach (const QColor& color, m_seriesColors) {
319 QLinearGradient g;
307 QLinearGradient g;
320 qreal h = color.hsvHueF();
308 qreal h = color.hsvHueF();
321 qreal s = color.hsvSaturationF();
309 qreal s = color.hsvSaturationF();
322
310
323 // TODO: tune the algorithm to give nice results with most base colors defined in
311 // TODO: tune the algorithm to give nice results with most base colors defined in
324 // most themes. The rest of the gradients we can define manually in theme specific
312 // most themes. The rest of the gradients we can define manually in theme specific
325 // implementation.
313 // implementation.
326 QColor start = color;
314 QColor start = color;
327 start.setHsvF(h, 0.0, 1.0);
315 start.setHsvF(h, 0.0, 1.0);
328 g.setColorAt(0.0, start);
316 g.setColorAt(0.0, start);
329
317
330 g.setColorAt(0.5, color);
318 g.setColorAt(0.5, color);
331
319
332 QColor end = color;
320 QColor end = color;
333 end.setHsvF(h, s, 0.25);
321 end.setHsvF(h, s, 0.25);
334 g.setColorAt(1.0, end);
322 g.setColorAt(1.0, end);
335
323
336 m_seriesGradients << g;
324 m_seriesGradients << g;
337 }
325 }
338 }
326 }
339
327
340
328
341 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
329 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
342 {
330 {
343 Q_ASSERT(pos >= 0.0 && pos <= 1.0);
331 Q_ASSERT(pos >= 0.0 && pos <= 1.0);
344 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
332 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
345 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
333 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
346 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
334 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
347 QColor c;
335 QColor c;
348 c.setRgbF(r, g, b);
336 c.setRgbF(r, g, b);
349 return c;
337 return c;
350 }
338 }
351
339
352 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
340 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
353 {
341 {
354 Q_ASSERT(pos >= 0 && pos <= 1.0);
342 Q_ASSERT(pos >= 0 && pos <= 1.0);
355
343
356 QGradientStops stops = gradient.stops();
344 QGradientStops stops = gradient.stops();
357 int count = stops.count();
345 int count = stops.count();
358
346
359 // find previous stop relative to position
347 // find previous stop relative to position
360 QGradientStop prev = stops.first();
348 QGradientStop prev = stops.first();
361 for (int i = 0; i < count; i++) {
349 for (int i = 0; i < count; i++) {
362 QGradientStop stop = stops.at(i);
350 QGradientStop stop = stops.at(i);
363 if (pos > stop.first)
351 if (pos > stop.first)
364 prev = stop;
352 prev = stop;
365
353
366 // given position is actually a stop position?
354 // given position is actually a stop position?
367 if (pos == stop.first) {
355 if (pos == stop.first) {
368 //qDebug() << "stop color" << pos;
356 //qDebug() << "stop color" << pos;
369 return stop.second;
357 return stop.second;
370 }
358 }
371 }
359 }
372
360
373 // find next stop relative to position
361 // find next stop relative to position
374 QGradientStop next = stops.last();
362 QGradientStop next = stops.last();
375 for (int i = count - 1; i >= 0; i--) {
363 for (int i = count - 1; i >= 0; i--) {
376 QGradientStop stop = stops.at(i);
364 QGradientStop stop = stops.at(i);
377 if (pos < stop.first)
365 if (pos < stop.first)
378 next = stop;
366 next = stop;
379 }
367 }
380
368
381 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
369 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
382
370
383 qreal range = next.first - prev.first;
371 qreal range = next.first - prev.first;
384 qreal posDelta = pos - prev.first;
372 qreal posDelta = pos - prev.first;
385 qreal relativePos = posDelta / range;
373 qreal relativePos = posDelta / range;
386
374
387 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
375 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
388
376
389 return colorAt(prev.second, next.second, relativePos);
377 return colorAt(prev.second, next.second, relativePos);
390 }
378 }
391
379
392 void ChartTheme::setForced(bool enabled)
380 void ChartTheme::setForced(bool enabled)
393 {
381 {
394 m_force=enabled;
382 m_force=enabled;
395 }
383 }
396
384
397 QTCOMMERCIALCHART_END_NAMESPACE
385 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,195 +1,195
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 "legendmarker_p.h"
21 #include "legendmarker_p.h"
22 #include "qxyseries.h"
22 #include "qxyseries.h"
23 #include "qxyseries_p.h"
23 #include "qxyseries_p.h"
24 #include "qlegend.h"
24 #include "qlegend.h"
25 #include "qbarseries.h"
25 #include "qbarseries.h"
26 #include "qpieseries.h"
26 #include "qpieseries.h"
27 #include "qpieslice.h"
27 #include "qpieslice.h"
28 #include "qbarset.h"
28 #include "qbarset.h"
29 #include "qbarset_p.h"
29 #include "qbarset_p.h"
30 #include "qareaseries.h"
30 #include "qareaseries.h"
31 #include "qareaseries_p.h"
31 #include "qareaseries_p.h"
32 #include <QPainter>
32 #include <QPainter>
33 #include <QGraphicsSceneEvent>
33 #include <QGraphicsSceneEvent>
34 #include <QGraphicsSimpleTextItem>
34 #include <QGraphicsSimpleTextItem>
35 #include <QDebug>
35 #include <QDebug>
36
36
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38
38
39 LegendMarker::LegendMarker(QAbstractSeries *series, QLegend *legend) : QGraphicsObject(legend),
39 LegendMarker::LegendMarker(QAbstractSeries *series, QLegend *legend) : QGraphicsObject(legend),
40 m_series(series),
40 m_series(series),
41 m_markerRect(0,0,10.0,10.0),
41 m_markerRect(0,0,10.0,10.0),
42 m_boundingRect(0,0,0,0),
42 m_boundingRect(0,0,0,0),
43 m_legend(legend),
43 m_legend(legend),
44 m_textItem(new QGraphicsSimpleTextItem(this)),
44 m_textItem(new QGraphicsSimpleTextItem(this)),
45 m_rectItem(new QGraphicsRectItem(this))
45 m_rectItem(new QGraphicsRectItem(this))
46 {
46 {
47 //setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
47 //setAcceptedMouseButtons(Qt::LeftButton|Qt::RightButton);
48 m_rectItem->setRect(m_markerRect);
48 m_rectItem->setRect(m_markerRect);
49 updateLayout();
49 updateLayout();
50 }
50 }
51
51
52 void LegendMarker::setPen(const QPen &pen)
52 void LegendMarker::setPen(const QPen &pen)
53 {
53 {
54 m_textItem->setPen(pen);
54 m_textItem->setPen(pen);
55 updateLayout();
55 updateLayout();
56 }
56 }
57
57
58 QPen LegendMarker::pen() const
58 QPen LegendMarker::pen() const
59 {
59 {
60 return m_textItem->pen();
60 return m_textItem->pen();
61 }
61 }
62
62
63 void LegendMarker::setBrush(const QBrush &brush)
63 void LegendMarker::setBrush(const QBrush &brush)
64 {
64 {
65 m_rectItem->setBrush(brush);
65 m_rectItem->setBrush(brush);
66 }
66 }
67
67
68 QBrush LegendMarker::brush() const
68 QBrush LegendMarker::brush() const
69 {
69 {
70 return m_rectItem->brush();
70 return m_rectItem->brush();
71 }
71 }
72
72
73 void LegendMarker::setLabel(const QString name)
73 void LegendMarker::setLabel(const QString name)
74 {
74 {
75 m_textItem->setText(name);
75 m_textItem->setText(name);
76 updateLayout();
76 updateLayout();
77 }
77 }
78
78
79 void LegendMarker::setSize(const QSize& size)
79 void LegendMarker::setSize(const QSize& size)
80 {
80 {
81 m_markerRect = QRectF(0,0,size.width(),size.height());
81 m_markerRect = QRectF(0,0,size.width(),size.height());
82 }
82 }
83
83
84 QString LegendMarker::label() const
84 QString LegendMarker::label() const
85 {
85 {
86 return m_textItem->text();
86 return m_textItem->text();
87 }
87 }
88
88
89 void LegendMarker::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
89 void LegendMarker::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
90 {
90 {
91 Q_UNUSED(option)
91 Q_UNUSED(option)
92 Q_UNUSED(widget)
92 Q_UNUSED(widget)
93 Q_UNUSED(painter)
93 Q_UNUSED(painter)
94 }
94 }
95
95
96 QRectF LegendMarker::boundingRect() const
96 QRectF LegendMarker::boundingRect() const
97 {
97 {
98 return m_boundingRect;
98 return m_boundingRect;
99 }
99 }
100
100
101 void LegendMarker::updateLayout()
101 void LegendMarker::updateLayout()
102 {
102 {
103
103
104 static const qreal margin = 2;
104 static const qreal margin = 2;
105 static const qreal space = 4;
105 static const qreal space = 4;
106
106
107 const QRectF& textRect = m_textItem->boundingRect();
107 const QRectF& textRect = m_textItem->boundingRect();
108 prepareGeometryChange();
108 prepareGeometryChange();
109 m_boundingRect = QRectF(0,0,m_markerRect.width() + 2*margin + space + textRect.width(),qMax(m_markerRect.height()+2*margin,textRect.height()+2*margin));
109 m_boundingRect = QRectF(0,0,m_markerRect.width() + 2*margin + space + textRect.width(),qMax(m_markerRect.height()+2*margin,textRect.height()+2*margin));
110 m_textItem->setPos(m_markerRect.width() + space + margin,m_boundingRect.height()/2 - textRect.height()/2);
110 m_textItem->setPos(m_markerRect.width() + space + margin,m_boundingRect.height()/2 - textRect.height()/2);
111 m_rectItem->setPos(margin,m_boundingRect.height()/2 - m_markerRect.height()/2);
111 m_rectItem->setPos(margin,m_boundingRect.height()/2 - m_markerRect.height()/2);
112
112
113 }
113 }
114
114
115 void LegendMarker::mousePressEvent(QGraphicsSceneMouseEvent *event)
115 void LegendMarker::mousePressEvent(QGraphicsSceneMouseEvent *event)
116 {
116 {
117 QGraphicsObject::mousePressEvent(event);
117 QGraphicsObject::mousePressEvent(event);
118 qDebug()<<"Not implemented"; //TODO: selected signal removed for now
118 qDebug()<<"Not implemented"; //TODO: selected signal removed for now
119 }
119 }
120
120
121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
122
122
123 AreaLegendMarker::AreaLegendMarker(QAreaSeries *series,QLegend *legend) : LegendMarker(series,legend),
123 AreaLegendMarker::AreaLegendMarker(QAreaSeries *series,QLegend *legend) : LegendMarker(series,legend),
124 m_series(series)
124 m_series(series)
125 {
125 {
126 //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
126 //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
127 QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated()));
127 QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated()));
128 updated();
128 updated();
129 }
129 }
130
130
131 void AreaLegendMarker::updated()
131 void AreaLegendMarker::updated()
132 {
132 {
133 setBrush(m_series->brush());
133 setBrush(m_series->brush());
134 setLabel(m_series->name());
134 setLabel(m_series->name());
135 }
135 }
136
136
137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
138
138
139 BarLegendMarker::BarLegendMarker(QBarSeries *barseries,QBarSet *barset, QLegend *legend) : LegendMarker(barseries,legend),
139 BarLegendMarker::BarLegendMarker(QBarSeries *barseries,QBarSet *barset, QLegend *legend) : LegendMarker(barseries,legend),
140 m_barset(barset)
140 m_barset(barset)
141 {
141 {
142 //QObject::connect(this, SIGNAL(selected()),barset->d_ptr.data(), SIGNAL(selected()));
142 //QObject::connect(this, SIGNAL(selected()),barset->d_ptr.data(), SIGNAL(selected()));
143 QObject::connect(barset->d_ptr.data(), SIGNAL(updatedBars()), this, SLOT(updated()));
143 QObject::connect(barset->d_ptr.data(), SIGNAL(updatedBars()), this, SLOT(updated()));
144 updated();
144 updated();
145 }
145 }
146
146
147 void BarLegendMarker::updated()
147 void BarLegendMarker::updated()
148 {
148 {
149 setBrush(m_barset->brush());
149 setBrush(m_barset->brush());
150 setLabel(m_barset->name());
150 setLabel(m_barset->name());
151 }
151 }
152
152
153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
154
154
155 PieLegendMarker::PieLegendMarker(QPieSeries* series,QPieSlice *pieslice, QLegend *legend) : LegendMarker(series,legend),
155 PieLegendMarker::PieLegendMarker(QPieSeries* series,QPieSlice *pieslice, QLegend *legend) : LegendMarker(series,legend),
156 m_pieslice(pieslice)
156 m_pieslice(pieslice)
157 {
157 {
158 QObject::connect(pieslice, SIGNAL(labelChanged()), this, SLOT(updated()));
158 QObject::connect(pieslice, SIGNAL(labelChanged()), this, SLOT(updated()));
159 QObject::connect(pieslice, SIGNAL(appearanceChanged()), this, SLOT(updated()));
159 QObject::connect(pieslice, SIGNAL(brushChanged()), this, SLOT(updated()));
160 updated();
160 updated();
161 }
161 }
162
162
163 void PieLegendMarker::updated()
163 void PieLegendMarker::updated()
164 {
164 {
165 setBrush(m_pieslice->brush());
165 setBrush(m_pieslice->brush());
166 setLabel(m_pieslice->label());
166 setLabel(m_pieslice->label());
167 }
167 }
168
168
169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
170
170
171 XYLegendMarker::XYLegendMarker(QXYSeries *series, QLegend *legend) : LegendMarker(series,legend),
171 XYLegendMarker::XYLegendMarker(QXYSeries *series, QLegend *legend) : LegendMarker(series,legend),
172 m_series(series)
172 m_series(series)
173 {
173 {
174 //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
174 //QObject::connect(this, SIGNAL(selected()), series, SIGNAL(selected()));
175 QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated()));
175 QObject::connect(series->d_func(),SIGNAL(updated()), this, SLOT(updated()));
176 updated();
176 updated();
177 }
177 }
178
178
179 void XYLegendMarker::updated()
179 void XYLegendMarker::updated()
180 {
180 {
181 setLabel(m_series->name());
181 setLabel(m_series->name());
182
182
183 if(m_series->type()== QAbstractSeries::SeriesTypeScatter)
183 if(m_series->type()== QAbstractSeries::SeriesTypeScatter)
184 {
184 {
185 setBrush(m_series->brush());
185 setBrush(m_series->brush());
186
186
187 }
187 }
188 else {
188 else {
189 setBrush(QBrush(m_series->pen().color()));
189 setBrush(QBrush(m_series->pen().color()));
190 }
190 }
191 }
191 }
192
192
193 #include "moc_legendmarker_p.cpp"
193 #include "moc_legendmarker_p.cpp"
194
194
195 QTCOMMERCIALCHART_END_NAMESPACE
195 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,25 +1,27
1 INCLUDEPATH += $$PWD
1 INCLUDEPATH += $$PWD
2 DEPENDPATH += $$PWD
2 DEPENDPATH += $$PWD
3
3
4 SOURCES += \
4 SOURCES += \
5 $$PWD/qpieseries.cpp \
5 $$PWD/qpieseries.cpp \
6 $$PWD/piesliceitem.cpp \
6 $$PWD/piesliceitem.cpp \
7 $$PWD/piechartitem.cpp \
7 $$PWD/piechartitem.cpp \
8 $$PWD/qpieslice.cpp \
8 $$PWD/qpieslice.cpp \
9 $$PWD/qpiemodelmapper.cpp \
9 $$PWD/qpiemodelmapper.cpp \
10 $$PWD/qvpiemodelmapper.cpp \
10 $$PWD/qvpiemodelmapper.cpp \
11 $$PWD/qhpiemodelmapper.cpp
11 $$PWD/qhpiemodelmapper.cpp
12
12
13 PRIVATE_HEADERS += \
13 PRIVATE_HEADERS += \
14 $$PWD/pieslicedata_p.h \
14 $$PWD/pieslicedata_p.h \
15 $$PWD/piechartitem_p.h \
15 $$PWD/piechartitem_p.h \
16 $$PWD/piesliceitem_p.h \
16 $$PWD/piesliceitem_p.h \
17 $$PWD/qpieslice_p.h \
17 $$PWD/qpieseries_p.h \
18 $$PWD/qpieseries_p.h \
18 $$PWD/qpiemodelmapper_p.h
19 $$PWD/qpiemodelmapper_p.h
19
20
20 PUBLIC_HEADERS += \
21 PUBLIC_HEADERS += \
21 $$PWD/qpieseries.h \
22 $$PWD/qpieseries.h \
22 $$PWD/qpieslice.h \
23 $$PWD/qpieslice.h \
23 $$PWD/qpiemodelmapper.h \
24 $$PWD/qpiemodelmapper.h \
24 $$PWD/qvpiemodelmapper.h \
25 $$PWD/qvpiemodelmapper.h \
25 $$PWD/qhpiemodelmapper.h
26 $$PWD/qhpiemodelmapper.h
27
@@ -1,194 +1,203
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 "qpieslice_p.h"
24 #include "qpieseries.h"
25 #include "qpieseries.h"
25 #include "qpieseries_p.h"
26 #include "qpieseries_p.h"
26 #include "chartpresenter_p.h"
27 #include "chartpresenter_p.h"
27 #include "chartdataset_p.h"
28 #include "chartdataset_p.h"
28 #include "chartanimator_p.h"
29 #include "chartanimator_p.h"
29 #include <QPainter>
30 #include <QPainter>
30 #include <QTimer>
31 #include <QTimer>
31
32
32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33
34
34 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
35 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter* presenter)
35 :ChartItem(presenter),
36 :ChartItem(presenter),
36 m_series(series)
37 m_series(series)
37 {
38 {
38 Q_ASSERT(series);
39 Q_ASSERT(series);
39
40
40 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
41 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
41 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
42 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
42 connect(series, SIGNAL(horizontalPositionChanged()), this, SLOT(updateLayout()));
43 connect(series, SIGNAL(horizontalPositionChanged()), this, SLOT(updateLayout()));
43 connect(series, SIGNAL(verticalPositionChanged()), this, SLOT(updateLayout()));
44 connect(series, SIGNAL(verticalPositionChanged()), this, SLOT(updateLayout()));
44 connect(series, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
45 connect(series, SIGNAL(pieSizeChanged()), this, SLOT(updateLayout()));
46 connect(QPieSeriesPrivate::fromSeries(series), SIGNAL(calculatedDataChanged()), this, SLOT(updateLayout()));
45
47
46 // Note: the following does not affect as long as the item does not have anything to paint
48 // Note: the following does not affect as long as the item does not have anything to paint
47 setZValue(ChartPresenter::PieSeriesZValue);
49 setZValue(ChartPresenter::PieSeriesZValue);
48
50
49 // Note: will not create slice items until we have a proper rectangle to draw on.
51 // Note: will not create slice items until we have a proper rectangle to draw on.
50 }
52 }
51
53
52 PieChartItem::~PieChartItem()
54 PieChartItem::~PieChartItem()
53 {
55 {
54 // slices deleted automatically through QGraphicsItem
56 // slices deleted automatically through QGraphicsItem
55 }
57 }
56
58
57 void PieChartItem::handleGeometryChanged(const QRectF& rect)
59 void PieChartItem::handleGeometryChanged(const QRectF& rect)
58 {
60 {
59 prepareGeometryChange();
61 prepareGeometryChange();
60 m_rect = rect;
62 m_rect = rect;
61 updateLayout();
63 updateLayout();
62
64
63 // This is for delayed initialization of the slice items during startup.
65 // This is for delayed initialization of the slice items during startup.
64 // It ensures that startup animation originates from the correct position.
66 // It ensures that startup animation originates from the correct position.
65 if (m_sliceItems.isEmpty())
67 if (m_sliceItems.isEmpty())
66 handleSlicesAdded(m_series->slices());
68 handleSlicesAdded(m_series->slices());
67 }
69 }
68
70
69 void PieChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
71 void PieChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
70 {
72 {
71 Q_UNUSED(minX);
73 Q_UNUSED(minX);
72 Q_UNUSED(maxX);
74 Q_UNUSED(maxX);
73 Q_UNUSED(minY);
75 Q_UNUSED(minY);
74 Q_UNUSED(maxY);
76 Q_UNUSED(maxY);
75 // does not apply to pie
77 // does not apply to pie
76 }
78 }
77
79
78 void PieChartItem::rangeXChanged(qreal min, qreal max, int tickXCount)
80 void PieChartItem::rangeXChanged(qreal min, qreal max, int tickXCount)
79 {
81 {
80 Q_UNUSED(min);
82 Q_UNUSED(min);
81 Q_UNUSED(max);
83 Q_UNUSED(max);
82 Q_UNUSED(tickXCount);
84 Q_UNUSED(tickXCount);
83 // does not apply to pie
85 // does not apply to pie
84 }
86 }
85
87
86 void PieChartItem::rangeYChanged(qreal min, qreal max, int tickYCount)
88 void PieChartItem::rangeYChanged(qreal min, qreal max, int tickYCount)
87 {
89 {
88 Q_UNUSED(min);
90 Q_UNUSED(min);
89 Q_UNUSED(max);
91 Q_UNUSED(max);
90 Q_UNUSED(tickYCount);
92 Q_UNUSED(tickYCount);
91 // does not apply to pie
93 // does not apply to pie
92 }
94 }
93
95
94 void PieChartItem::updateLayout()
96 void PieChartItem::updateLayout()
95 {
97 {
96 // find pie center coordinates
98 // find pie center coordinates
97 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->horizontalPosition()));
99 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()));
100 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->verticalPosition()));
99
101
100 // find maximum radius for pie
102 // find maximum radius for pie
101 m_pieRadius = m_rect.height() / 2;
103 m_pieRadius = m_rect.height() / 2;
102 if (m_rect.width() < m_rect.height())
104 if (m_rect.width() < m_rect.height())
103 m_pieRadius = m_rect.width() / 2;
105 m_pieRadius = m_rect.width() / 2;
104
106
105 // apply size factor
107 // apply size factor
106 m_pieRadius *= m_series->pieSize();
108 m_pieRadius *= m_series->pieSize();
107
109
108 // set layouts for existing slice items
110 // set layouts for existing slice items
109 foreach (QPieSlice* slice, m_series->slices()) {
111 foreach (QPieSlice* slice, m_series->slices()) {
110 PieSliceItem *sliceItem = m_sliceItems.value(slice);
112 PieSliceItem *sliceItem = m_sliceItems.value(slice);
111 if (sliceItem) {
113 if (sliceItem) {
112 PieSliceData sliceData = updateSliceGeometry(slice);
114 PieSliceData sliceData = updateSliceGeometry(slice);
113 if (animator())
115 if (animator())
114 animator()->updateAnimation(this, sliceItem, sliceData);
116 animator()->updateAnimation(this, sliceItem, sliceData);
115 else
117 else
116 sliceItem->setLayout(sliceData);
118 sliceItem->setLayout(sliceData);
117 }
119 }
118 }
120 }
119
121
120 update();
122 update();
121 }
123 }
122
124
123 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
125 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
124 {
126 {
125 // delay creating slice items until there is a proper rectangle
127 // delay creating slice items until there is a proper rectangle
126 if (!m_rect.isValid() && m_sliceItems.isEmpty())
128 if (!m_rect.isValid() && m_sliceItems.isEmpty())
127 return;
129 return;
128
130
129 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
131 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
130
132
131 bool startupAnimation = m_sliceItems.isEmpty();
133 bool startupAnimation = m_sliceItems.isEmpty();
132
134
133 foreach (QPieSlice *slice, slices) {
135 foreach (QPieSlice *slice, slices) {
134 PieSliceItem* sliceItem = new PieSliceItem(this);
136 PieSliceItem* sliceItem = new PieSliceItem(this);
135 m_sliceItems.insert(slice, sliceItem);
137 m_sliceItems.insert(slice, sliceItem);
136
138
137 // note: do need to connect to slice valueChanged(). calculatedDataChanged() is enough.
139 // Note: do need to connect to slice valueChanged() etc.
138 // to update the slice.
140 // This is handled through calculatedDataChanged signal.
139 connect(slice, SIGNAL(calculatedDataChanged()), this, SLOT(handleSliceChanged()));
140 connect(slice, SIGNAL(labelChanged()), this, SLOT(handleSliceChanged()));
141 connect(slice, SIGNAL(labelChanged()), this, SLOT(handleSliceChanged()));
141 connect(slice, SIGNAL(appearanceChanged()), this, SLOT(handleSliceChanged()));
142 connect(slice, SIGNAL(labelVisibleChanged()), this, SLOT(handleSliceChanged()));
143 connect(slice, SIGNAL(explodedChanged()), this, SLOT(handleSliceChanged()));
144 connect(slice, SIGNAL(penChanged()), this, SLOT(handleSliceChanged()));
145 connect(slice, SIGNAL(brushChanged()), this, SLOT(handleSliceChanged()));
146 connect(slice, SIGNAL(labelPenChanged()), this, SLOT(handleSliceChanged()));
147 connect(slice, SIGNAL(labelFontChanged()), this, SLOT(handleSliceChanged()));
148 connect(slice, SIGNAL(labelArmLengthFactorChanged()), this, SLOT(handleSliceChanged()));
149 connect(slice, SIGNAL(explodeDistanceFactorChanged()), this, SLOT(handleSliceChanged()));
150
142 connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked()));
151 connect(sliceItem, SIGNAL(clicked(Qt::MouseButtons)), slice, SIGNAL(clicked()));
143 connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool)));
152 connect(sliceItem, SIGNAL(hovered(bool)), slice, SIGNAL(hovered(bool)));
144
153
145 PieSliceData sliceData = updateSliceGeometry(slice);
154 PieSliceData sliceData = updateSliceGeometry(slice);
146 if (animator())
155 if (animator())
147 animator()->addAnimation(this, sliceItem, sliceData, startupAnimation);
156 animator()->addAnimation(this, sliceItem, sliceData, startupAnimation);
148 else
157 else
149 sliceItem->setLayout(sliceData);
158 sliceItem->setLayout(sliceData);
150 }
159 }
151 }
160 }
152
161
153 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
162 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
154 {
163 {
155 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
164 presenter()->chartTheme()->decorate(m_series, presenter()->dataSet()->seriesIndex(m_series));
156
165
157 foreach (QPieSlice *slice, slices) {
166 foreach (QPieSlice *slice, slices) {
158 PieSliceItem *sliceItem = m_sliceItems.value(slice);
167 PieSliceItem *sliceItem = m_sliceItems.value(slice);
159 Q_ASSERT(sliceItem);
168 Q_ASSERT(sliceItem);
160 m_sliceItems.remove(slice);
169 m_sliceItems.remove(slice);
161
170
162 if (animator())
171 if (animator())
163 animator()->removeAnimation(this, sliceItem); // animator deletes the PieSliceItem
172 animator()->removeAnimation(this, sliceItem); // animator deletes the PieSliceItem
164 else
173 else
165 delete sliceItem;
174 delete sliceItem;
166 }
175 }
167 }
176 }
168
177
169 void PieChartItem::handleSliceChanged()
178 void PieChartItem::handleSliceChanged()
170 {
179 {
171 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
180 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
172 Q_ASSERT(m_sliceItems.contains(slice));
181 Q_ASSERT(m_sliceItems.contains(slice));
173
182
174 PieSliceItem *sliceItem = m_sliceItems.value(slice);
183 PieSliceItem *sliceItem = m_sliceItems.value(slice);
175 PieSliceData sliceData = updateSliceGeometry(slice);
184 PieSliceData sliceData = updateSliceGeometry(slice);
176 if (animator())
185 if (animator())
177 animator()->updateAnimation(this, sliceItem, sliceData);
186 animator()->updateAnimation(this, sliceItem, sliceData);
178 else
187 else
179 sliceItem->setLayout(sliceData);
188 sliceItem->setLayout(sliceData);
180
189
181 update();
190 update();
182 }
191 }
183
192
184 PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice)
193 PieSliceData PieChartItem::updateSliceGeometry(QPieSlice *slice)
185 {
194 {
186 PieSliceData &sliceData = PieSliceData::fromSlice(slice);
195 PieSliceData &sliceData = QPieSlicePrivate::fromSlice(slice)->m_data;
187 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
196 sliceData.m_center = PieSliceItem::sliceCenter(m_pieCenter, m_pieRadius, slice);
188 sliceData.m_radius = m_pieRadius;
197 sliceData.m_radius = m_pieRadius;
189 return sliceData;
198 return sliceData;
190 }
199 }
191
200
192 #include "moc_piechartitem_p.cpp"
201 #include "moc_piechartitem_p.cpp"
193
202
194 QTCOMMERCIALCHART_END_NAMESPACE
203 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,148 +1,130
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 PIESLICEDATA_P_H
21 #ifndef PIESLICEDATA_P_H
22 #define PIESLICEDATA_P_H
22 #define PIESLICEDATA_P_H
23
23
24 #include "qchartglobal.h"
24 #include "qchartglobal.h"
25 #include "qpieslice.h"
25 #include "qpieslice.h"
26 #include <QPen>
26 #include <QPen>
27 #include <QBrush>
27 #include <QBrush>
28
28
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30
30
31 template <class T>
31 template <class T>
32 class Themed : public T
32 class Themed : public T
33 {
33 {
34 public:
34 public:
35 Themed():m_isThemed(true) {}
35 Themed():m_isThemed(true) {}
36
36
37 inline T &operator=(const T &other) { return T::operator =(other); }
37 inline T &operator=(const T &other) { return T::operator =(other); }
38
38
39 inline bool operator!=(const T &other) const { return T::operator !=(other); }
39 inline bool operator!=(const T &other) const { return T::operator !=(other); }
40 inline bool operator!=(const Themed &other) const
40 inline bool operator!=(const Themed &other) const
41 {
41 {
42 if (T::operator !=(other))
42 if (T::operator !=(other))
43 return true;
43 return true;
44
44
45 if (m_isThemed != other.m_isThemed)
45 if (m_isThemed != other.m_isThemed)
46 return true;
46 return true;
47
47
48 return false;
48 return false;
49 }
49 }
50
50
51 inline void setThemed(bool state) { m_isThemed = state; }
51 inline void setThemed(bool state) { m_isThemed = state; }
52 inline bool isThemed() const { return m_isThemed; }
52 inline bool isThemed() const { return m_isThemed; }
53
53
54 private:
54 private:
55 bool m_isThemed;
55 bool m_isThemed;
56 };
56 };
57
57
58 class PieSliceData
58 class PieSliceData
59 {
59 {
60 public:
60 public:
61 PieSliceData()
61 PieSliceData()
62 {
62 {
63 m_value = 0;
63 m_value = 0;
64
64
65 m_isExploded = false;
65 m_isExploded = false;
66 m_explodeDistanceFactor = 0.15;
66 m_explodeDistanceFactor = 0.15;
67
67
68 m_isLabelVisible = false;
68 m_isLabelVisible = false;
69 m_labelArmLengthFactor = 0.15;
69 m_labelArmLengthFactor = 0.15;
70
70
71 m_percentage = 0;
71 m_percentage = 0;
72 m_radius = 0;
72 m_radius = 0;
73 m_startAngle = 0;
73 m_startAngle = 0;
74 m_angleSpan = 0;
74 m_angleSpan = 0;
75 }
75 }
76
76
77 bool operator!=(const PieSliceData &other) const
77 bool operator!=(const PieSliceData &other) const
78 {
78 {
79 if (!qFuzzyIsNull(m_value - other.m_value))
79 if (!qFuzzyIsNull(m_value - other.m_value))
80 return true;
80 return true;
81
81
82 if (m_slicePen != other.m_slicePen ||
82 if (m_slicePen != other.m_slicePen ||
83 m_sliceBrush != other.m_sliceBrush)
83 m_sliceBrush != other.m_sliceBrush)
84 return true;
84 return true;
85
85
86 if (m_isExploded != other.m_isExploded ||
86 if (m_isExploded != other.m_isExploded ||
87 !qFuzzyIsNull(m_explodeDistanceFactor - other.m_explodeDistanceFactor))
87 !qFuzzyIsNull(m_explodeDistanceFactor - other.m_explodeDistanceFactor))
88 return true;
88 return true;
89
89
90 if (m_isLabelVisible != other.m_isLabelVisible ||
90 if (m_isLabelVisible != other.m_isLabelVisible ||
91 m_labelText != other.m_labelText ||
91 m_labelText != other.m_labelText ||
92 m_labelFont != other.m_labelFont ||
92 m_labelFont != other.m_labelFont ||
93 !qFuzzyIsNull(m_labelArmLengthFactor - other.m_labelArmLengthFactor) ||
93 !qFuzzyIsNull(m_labelArmLengthFactor - other.m_labelArmLengthFactor) ||
94 m_labelPen != other.m_labelPen)
94 m_labelPen != other.m_labelPen)
95 return true;
95 return true;
96
96
97 if (!qFuzzyIsNull(m_percentage - other.m_percentage) ||
97 if (!qFuzzyIsNull(m_percentage - other.m_percentage) ||
98 m_center != other.m_center ||
98 m_center != other.m_center ||
99 !qFuzzyIsNull(m_radius - other.m_radius) ||
99 !qFuzzyIsNull(m_radius - other.m_radius) ||
100 !qFuzzyIsNull(m_startAngle - other.m_startAngle) ||
100 !qFuzzyIsNull(m_startAngle - other.m_startAngle) ||
101 !qFuzzyIsNull(m_angleSpan - other.m_angleSpan))
101 !qFuzzyIsNull(m_angleSpan - other.m_angleSpan))
102 return true;
102 return true;
103
103
104 return false;
104 return false;
105 }
105 }
106
106
107 static void emitAppearanceChanged(QPieSlice *slice)
108 {
109 Q_ASSERT(slice);
110 emit slice->appearanceChanged();
111 }
112
113 static void emitCalculatedDataChanged(QPieSlice *slice)
114 {
115 Q_ASSERT(slice);
116 emit slice->calculatedDataChanged();
117 }
118
119 static PieSliceData &fromSlice(QPieSlice *slice)
120 {
121 Q_ASSERT(slice);
122 return *slice->d;
123 }
124
125 qreal m_value;
107 qreal m_value;
126
108
127 Themed<QPen> m_slicePen;
109 Themed<QPen> m_slicePen;
128 Themed<QBrush> m_sliceBrush;
110 Themed<QBrush> m_sliceBrush;
129
111
130 bool m_isExploded;
112 bool m_isExploded;
131 qreal m_explodeDistanceFactor;
113 qreal m_explodeDistanceFactor;
132
114
133 bool m_isLabelVisible;
115 bool m_isLabelVisible;
134 QString m_labelText;
116 QString m_labelText;
135 Themed<QFont> m_labelFont;
117 Themed<QFont> m_labelFont;
136 qreal m_labelArmLengthFactor;
118 qreal m_labelArmLengthFactor;
137 Themed<QPen> m_labelPen;
119 Themed<QPen> m_labelPen;
138
120
139 qreal m_percentage;
121 qreal m_percentage;
140 QPointF m_center;
122 QPointF m_center;
141 qreal m_radius;
123 qreal m_radius;
142 qreal m_startAngle;
124 qreal m_startAngle;
143 qreal m_angleSpan;
125 qreal m_angleSpan;
144 };
126 };
145
127
146 QTCOMMERCIALCHART_END_NAMESPACE
128 QTCOMMERCIALCHART_END_NAMESPACE
147
129
148 #endif // PIESLICEDATA_P_H
130 #endif // PIESLICEDATA_P_H
@@ -1,220 +1,220
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 "piesliceitem_p.h"
21 #include "piesliceitem_p.h"
22 #include "piechartitem_p.h"
22 #include "piechartitem_p.h"
23 #include "qpieseries.h"
23 #include "qpieseries.h"
24 #include "qpieslice.h"
24 #include "qpieslice.h"
25 #include "chartpresenter_p.h"
25 #include "chartpresenter_p.h"
26 #include <QPainter>
26 #include <QPainter>
27 #include <qmath.h>
27 #include <qmath.h>
28 #include <QGraphicsSceneEvent>
28 #include <QGraphicsSceneEvent>
29 #include <QTime>
29 #include <QTime>
30
30
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
32
33 #define PI 3.14159265 // TODO: is this defined in some header?
33 #define PI 3.14159265 // TODO: is this defined in some header?
34
34
35 QPointF offset(qreal angle, qreal length)
35 QPointF offset(qreal angle, qreal length)
36 {
36 {
37 qreal dx = qSin(angle*(PI/180)) * length;
37 qreal dx = qSin(angle*(PI/180)) * length;
38 qreal dy = qCos(angle*(PI/180)) * length;
38 qreal dy = qCos(angle*(PI/180)) * length;
39 return QPointF(dx, -dy);
39 return QPointF(dx, -dy);
40 }
40 }
41
41
42 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
42 PieSliceItem::PieSliceItem(QGraphicsItem* parent)
43 :QGraphicsObject(parent),
43 :QGraphicsObject(parent),
44 m_hovered(false)
44 m_hovered(false)
45 {
45 {
46 setAcceptHoverEvents(true);
46 setAcceptHoverEvents(true);
47 setAcceptedMouseButtons(Qt::MouseButtonMask);
47 setAcceptedMouseButtons(Qt::MouseButtonMask);
48 setZValue(ChartPresenter::PieSeriesZValue);
48 setZValue(ChartPresenter::PieSeriesZValue);
49 }
49 }
50
50
51 PieSliceItem::~PieSliceItem()
51 PieSliceItem::~PieSliceItem()
52 {
52 {
53 // If user is hovering over the slice and it gets destroyed we do
53 // If user is hovering over the slice and it gets destroyed we do
54 // not get a hover leave event. So we must emit the signal here.
54 // not get a hover leave event. So we must emit the signal here.
55 if (m_hovered)
55 if (m_hovered)
56 emit hovered(false);
56 emit hovered(false);
57 }
57 }
58
58
59 QRectF PieSliceItem::boundingRect() const
59 QRectF PieSliceItem::boundingRect() const
60 {
60 {
61 return m_boundingRect;
61 return m_boundingRect;
62 }
62 }
63
63
64 QPainterPath PieSliceItem::shape() const
64 QPainterPath PieSliceItem::shape() const
65 {
65 {
66 // Don't include the label and label arm.
66 // Don't include the label and label arm.
67 // This is used to detect a mouse clicks. We do not want clicks from label.
67 // This is used to detect a mouse clicks. We do not want clicks from label.
68 return m_slicePath;
68 return m_slicePath;
69 }
69 }
70
70
71 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
71 void PieSliceItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
72 {
72 {
73 painter->save();
73 painter->save();
74 painter->setClipRect(parentItem()->boundingRect());
74 painter->setClipRect(parentItem()->boundingRect());
75 painter->setPen(m_data.m_slicePen);
75 painter->setPen(m_data.m_slicePen);
76 painter->setBrush(m_data.m_sliceBrush);
76 painter->setBrush(m_data.m_sliceBrush);
77 painter->drawPath(m_slicePath);
77 painter->drawPath(m_slicePath);
78 painter->restore();
78 painter->restore();
79
79
80 if (m_data.m_isLabelVisible) {
80 if (m_data.m_isLabelVisible) {
81 painter->setClipRect(parentItem()->boundingRect());
81 painter->setClipRect(parentItem()->boundingRect());
82 painter->setPen(m_data.m_labelPen);
82 painter->setPen(m_data.m_labelPen);
83 painter->drawPath(m_labelArmPath);
83 painter->drawPath(m_labelArmPath);
84 // the pen color will affect the font color as well
84 // the pen color will affect the font color as well
85 painter->setFont(m_data.m_labelFont);
85 painter->setFont(m_data.m_labelFont);
86 painter->drawText(m_labelTextRect.bottomLeft(), m_data.m_labelText);
86 painter->drawText(m_labelTextRect.bottomLeft(), m_data.m_labelText);
87 }
87 }
88 }
88 }
89
89
90 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
90 void PieSliceItem::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
91 {
91 {
92 m_hovered = true;
92 m_hovered = true;
93 emit hovered(true);
93 emit hovered(true);
94 }
94 }
95
95
96 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
96 void PieSliceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
97 {
97 {
98 m_hovered = false;
98 m_hovered = false;
99 emit hovered(false);
99 emit hovered(false);
100 }
100 }
101
101
102 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
102 void PieSliceItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
103 {
103 {
104 emit clicked(event->buttons());
104 emit clicked(event->buttons());
105 }
105 }
106
106
107 void PieSliceItem::setLayout(const PieSliceData &sliceData)
107 void PieSliceItem::setLayout(const PieSliceData &sliceData)
108 {
108 {
109 m_data = sliceData;
109 m_data = sliceData;
110 updateGeometry();
110 updateGeometry();
111 update();
111 update();
112 }
112 }
113
113
114 void PieSliceItem::updateGeometry()
114 void PieSliceItem::updateGeometry()
115 {
115 {
116 if (m_data.m_radius <= 0)
116 if (m_data.m_radius <= 0)
117 return;
117 return;
118
118
119 prepareGeometryChange();
119 prepareGeometryChange();
120
120
121 // update slice path
121 // update slice path
122 qreal centerAngle;
122 qreal centerAngle;
123 QPointF armStart;
123 QPointF armStart;
124 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
124 m_slicePath = slicePath(m_data.m_center, m_data.m_radius, m_data.m_startAngle, m_data.m_angleSpan, &centerAngle, &armStart);
125
125
126 // update text rect
126 // update text rect
127 m_labelTextRect = labelTextRect(m_data.m_labelFont, m_data.m_labelText);
127 m_labelTextRect = labelTextRect(m_data.m_labelFont, m_data.m_labelText);
128
128
129 // update label arm path
129 // update label arm path
130 QPointF labelTextStart;
130 QPointF labelTextStart;
131 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
131 m_labelArmPath = labelArmPath(armStart, centerAngle, m_data.m_radius * m_data.m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
132
132
133 // update text position
133 // update text position
134 m_labelTextRect.moveBottomLeft(labelTextStart);
134 m_labelTextRect.moveBottomLeft(labelTextStart);
135
135
136 // update bounding rect
136 // update bounding rect
137 if (m_data.m_isLabelVisible)
137 if (m_data.m_isLabelVisible)
138 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
138 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
139 else
139 else
140 m_boundingRect = m_slicePath.boundingRect();
140 m_boundingRect = m_slicePath.boundingRect();
141 }
141 }
142
142
143 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
143 QPointF PieSliceItem::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
144 {
144 {
145 if (slice->isExploded()) {
145 if (slice->isExploded()) {
146 qreal centerAngle = slice->startAngle() + ((slice->endAngle() - slice->startAngle())/2);
146 qreal centerAngle = slice->startAngle() + (slice->angleSpan()/2);
147 qreal len = radius * slice->explodeDistanceFactor();
147 qreal len = radius * slice->explodeDistanceFactor();
148 qreal dx = qSin(centerAngle*(PI/180)) * len;
148 qreal dx = qSin(centerAngle*(PI/180)) * len;
149 qreal dy = -qCos(centerAngle*(PI/180)) * len;
149 qreal dy = -qCos(centerAngle*(PI/180)) * len;
150 point += QPointF(dx, dy);
150 point += QPointF(dx, dy);
151 }
151 }
152 return point;
152 return point;
153 }
153 }
154
154
155 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF* armStart)
155 QPainterPath PieSliceItem::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal *centerAngle, QPointF* armStart)
156 {
156 {
157 // calculate center angle
157 // calculate center angle
158 *centerAngle = startAngle + (angleSpan/2);
158 *centerAngle = startAngle + (angleSpan/2);
159
159
160 // calculate slice rectangle
160 // calculate slice rectangle
161 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
161 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
162
162
163 // slice path
163 // slice path
164 // TODO: draw the shape so that it might have a hole in the center
164 // TODO: draw the shape so that it might have a hole in the center
165 QPainterPath path;
165 QPainterPath path;
166 path.moveTo(rect.center());
166 path.moveTo(rect.center());
167 path.arcTo(rect, -startAngle + 90, -angleSpan);
167 path.arcTo(rect, -startAngle + 90, -angleSpan);
168 path.closeSubpath();
168 path.closeSubpath();
169
169
170 // calculate label arm start point
170 // calculate label arm start point
171 *armStart = center;
171 *armStart = center;
172 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
172 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
173
173
174 return path;
174 return path;
175 }
175 }
176
176
177 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
177 QPainterPath PieSliceItem::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF *textStart)
178 {
178 {
179 // prevent label arm pointing straight down because it will look bad
179 // prevent label arm pointing straight down because it will look bad
180 if (angle < 180 && angle > 170)
180 if (angle < 180 && angle > 170)
181 angle = 170;
181 angle = 170;
182 if (angle > 180 && angle < 190)
182 if (angle > 180 && angle < 190)
183 angle = 190;
183 angle = 190;
184
184
185 // line from slice to label
185 // line from slice to label
186 qreal dx = qSin(angle*(PI/180)) * length;
186 qreal dx = qSin(angle*(PI/180)) * length;
187 qreal dy = -qCos(angle*(PI/180)) * length;
187 qreal dy = -qCos(angle*(PI/180)) * length;
188 QPointF parm1 = start + QPointF(dx, dy);
188 QPointF parm1 = start + QPointF(dx, dy);
189
189
190 // line to underline the label
190 // line to underline the label
191 QPointF parm2 = parm1;
191 QPointF parm2 = parm1;
192 if (angle < 180) { // arm swings the other way on the left side
192 if (angle < 180) { // arm swings the other way on the left side
193 parm2 += QPointF(textWidth, 0);
193 parm2 += QPointF(textWidth, 0);
194 *textStart = parm1;
194 *textStart = parm1;
195 }
195 }
196 else {
196 else {
197 parm2 += QPointF(-textWidth,0);
197 parm2 += QPointF(-textWidth,0);
198 *textStart = parm2;
198 *textStart = parm2;
199 }
199 }
200
200
201 // elevate the text position a bit so that it does not hit the line
201 // elevate the text position a bit so that it does not hit the line
202 *textStart += QPointF(0, -3);
202 *textStart += QPointF(0, -3);
203
203
204 QPainterPath path;
204 QPainterPath path;
205 path.moveTo(start);
205 path.moveTo(start);
206 path.lineTo(parm1);
206 path.lineTo(parm1);
207 path.lineTo(parm2);
207 path.lineTo(parm2);
208
208
209 return path;
209 return path;
210 }
210 }
211
211
212 QRectF PieSliceItem::labelTextRect(QFont font, QString text)
212 QRectF PieSliceItem::labelTextRect(QFont font, QString text)
213 {
213 {
214 QFontMetricsF fm(font);
214 QFontMetricsF fm(font);
215 return fm.boundingRect(text);
215 return fm.boundingRect(text);
216 }
216 }
217
217
218 #include "moc_piesliceitem_p.cpp"
218 #include "moc_piesliceitem_p.cpp"
219
219
220 QTCOMMERCIALCHART_END_NAMESPACE
220 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,610 +1,604
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 "qpieslice_p.h"
24 #include "pieslicedata_p.h"
25 #include "pieslicedata_p.h"
25 #include "chartdataset_p.h"
26 #include "chartdataset_p.h"
26 #include "charttheme_p.h"
27 #include "charttheme_p.h"
27 #include "chartanimator_p.h"
28 #include "chartanimator_p.h"
28 #include "legendmarker_p.h"
29 #include "legendmarker_p.h"
29
30
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31
32
32 /*!
33 /*!
33 \class QPieSeries
34 \class QPieSeries
34 \brief Pie series API for QtCommercial Charts
35 \brief Pie series API for QtCommercial Charts
35
36
36 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
37 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.
38 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.
39 The actual slice size is determined by that relative value.
39
40
40 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
41 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.
42 These relate to the actual chart rectangle.
42
43
43 By default the pie is defined as a full pie but it can also be a partial pie.
44 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.
45 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.
46 Full pie is 360 degrees where 0 is at 12 a'clock.
46
47
47 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
48 See the \l {PieChart Example} {pie chart example} to learn how to create a simple pie chart.
48 \image examples_piechart.png
49 \image examples_piechart.png
49 */
50 */
50
51
51 /*!
52 /*!
52 \property QPieSeries::horizontalPosition
53 \property QPieSeries::horizontalPosition
53 \brief Defines the horizontal position of the pie.
54 \brief Defines the horizontal position of the pie.
54
55
55 The value is a relative value to the chart rectangle where:
56 The value is a relative value to the chart rectangle where:
56
57
57 \list
58 \list
58 \o 0.0 is the absolute left.
59 \o 0.0 is the absolute left.
59 \o 1.0 is the absolute right.
60 \o 1.0 is the absolute right.
60 \endlist
61 \endlist
61
62
62 Default value is 0.5 (center).
63 Default value is 0.5 (center).
63 */
64 */
64
65
65 /*!
66 /*!
66 \property QPieSeries::verticalPosition
67 \property QPieSeries::verticalPosition
67 \brief Defines the vertical position of the pie.
68 \brief Defines the vertical position of the pie.
68
69
69 The value is a relative value to the chart rectangle where:
70 The value is a relative value to the chart rectangle where:
70
71
71 \list
72 \list
72 \o 0.0 is the absolute top.
73 \o 0.0 is the absolute top.
73 \o 1.0 is the absolute bottom.
74 \o 1.0 is the absolute bottom.
74 \endlist
75 \endlist
75
76
76 Default value is 0.5 (center).
77 Default value is 0.5 (center).
77 */
78 */
78
79
79 /*!
80 /*!
80 \property QPieSeries::size
81 \property QPieSeries::size
81 \brief Defines the pie size.
82 \brief Defines the pie size.
82
83
83 The value is a relative value to the chart rectangle where:
84 The value is a relative value to the chart rectangle where:
84
85
85 \list
86 \list
86 \o 0.0 is the minimum size (pie not drawn).
87 \o 0.0 is the minimum size (pie not drawn).
87 \o 1.0 is the maximum size that can fit the chart.
88 \o 1.0 is the maximum size that can fit the chart.
88 \endlist
89 \endlist
89
90
90 Default value is 0.7.
91 Default value is 0.7.
91 */
92 */
92
93
93 /*!
94 /*!
94 \property QPieSeries::startAngle
95 \property QPieSeries::startAngle
95 \brief Defines the starting angle of the pie.
96 \brief Defines the starting angle of the pie.
96
97
97 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
98 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
98
99
99 Default is value is 0.
100 Default is value is 0.
100 */
101 */
101
102
102 /*!
103 /*!
103 \property QPieSeries::endAngle
104 \property QPieSeries::endAngle
104 \brief Defines the ending angle of the pie.
105 \brief Defines the ending angle of the pie.
105
106
106 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
107 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
107
108
108 Default is value is 360.
109 Default is value is 360.
109 */
110 */
110
111
111 /*!
112 /*!
112 \property QPieSeries::count
113 \property QPieSeries::count
113 \brief Number of slices in the series.
114 \brief Number of slices in the series.
114
115
115 */
116 */
116
117
117 /*!
118 /*!
118 \property QPieSeries::sum
119 \property QPieSeries::sum
119 \brief Sum of all slices.
120 \brief Sum of all slices.
120
121
121 The series keeps track of the sum of all slices it holds.
122 The series keeps track of the sum of all slices it holds.
122 */
123 */
123
124
124
125
125 /*!
126 /*!
126 Constructs a series object which is a child of \a parent.
127 Constructs a series object which is a child of \a parent.
127 */
128 */
128 QPieSeries::QPieSeries(QObject *parent) :
129 QPieSeries::QPieSeries(QObject *parent) :
129 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
130 QAbstractSeries(*new QPieSeriesPrivate(this),parent)
130 {
131 {
131
132
132 }
133 }
133
134
134 /*!
135 /*!
135 Destroys the series and its slices.
136 Destroys the series and its slices.
136 */
137 */
137 QPieSeries::~QPieSeries()
138 QPieSeries::~QPieSeries()
138 {
139 {
139 // NOTE: d_prt destroyed by QObject
140 // NOTE: d_prt destroyed by QObject
140 }
141 }
141
142
142 /*!
143 /*!
143 Returns QChartSeries::SeriesTypePie.
144 Returns QChartSeries::SeriesTypePie.
144 */
145 */
145 QAbstractSeries::SeriesType QPieSeries::type() const
146 QAbstractSeries::SeriesType QPieSeries::type() const
146 {
147 {
147 return QAbstractSeries::SeriesTypePie;
148 return QAbstractSeries::SeriesTypePie;
148 }
149 }
149
150
150 /*!
151 /*!
151 Appends an array of \a slices to the series.
152 Appends an array of \a slices to the series.
152 Slice ownership is passed to the series.
153 Slice ownership is passed to the series.
153
154
154 Returns true if append was successfull.
155 Returns true if append was successfull.
155 */
156 */
156 bool QPieSeries::append(QList<QPieSlice*> slices)
157 bool QPieSeries::append(QList<QPieSlice*> slices)
157 {
158 {
158 Q_D(QPieSeries);
159 Q_D(QPieSeries);
159
160
160 if (slices.count() == 0)
161 if (slices.count() == 0)
161 return false;
162 return false;
162
163
163 foreach (QPieSlice* s, slices) {
164 foreach (QPieSlice* s, slices) {
164 if (!s || d->m_slices.contains(s))
165 if (!s || d->m_slices.contains(s))
165 return false;
166 return false;
166 }
167 }
167
168
168 foreach (QPieSlice* s, slices) {
169 foreach (QPieSlice* s, slices) {
169 s->setParent(this);
170 s->setParent(this);
170 d->m_slices << s;
171 d->m_slices << s;
171 }
172 }
172
173
173 d->updateDerivativeData();
174 d->updateDerivativeData();
174
175
175 foreach (QPieSlice* s, slices) {
176 foreach (QPieSlice* s, slices) {
176 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceChanged()));
177 connect(s, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
177 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
178 connect(s, SIGNAL(clicked()), d, SLOT(sliceClicked()));
178 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
179 connect(s, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
179 }
180 }
180
181
181 emit added(slices);
182 emit added(slices);
182 emit countChanged();
183 emit countChanged();
183
184
184 return true;
185 return true;
185 }
186 }
186
187
187 /*!
188 /*!
188 Appends a single \a slice to the series.
189 Appends a single \a slice to the series.
189 Slice ownership is passed to the series.
190 Slice ownership is passed to the series.
190
191
191 Returns true if append was succesfull.
192 Returns true if append was succesfull.
192 */
193 */
193 bool QPieSeries::append(QPieSlice* slice)
194 bool QPieSeries::append(QPieSlice* slice)
194 {
195 {
195 return append(QList<QPieSlice*>() << slice);
196 return append(QList<QPieSlice*>() << slice);
196 }
197 }
197
198
198 /*!
199 /*!
199 Appends a single \a slice to the series and returns a reference to the series.
200 Appends a single \a slice to the series and returns a reference to the series.
200 Slice ownership is passed to the series.
201 Slice ownership is passed to the series.
201 */
202 */
202 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
203 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
203 {
204 {
204 append(slice);
205 append(slice);
205 return *this;
206 return *this;
206 }
207 }
207
208
208
209
209 /*!
210 /*!
210 Appends a single slice to the series with give \a value and \a label.
211 Appends a single slice to the series with give \a value and \a label.
211 Slice ownership is passed to the series.
212 Slice ownership is passed to the series.
212 */
213 */
213 QPieSlice* QPieSeries::append(QString label, qreal value)
214 QPieSlice* QPieSeries::append(QString label, qreal value)
214 {
215 {
215 QPieSlice* slice = new QPieSlice(label, value);
216 QPieSlice* slice = new QPieSlice(label, value);
216 append(slice);
217 append(slice);
217 return slice;
218 return slice;
218 }
219 }
219
220
220 /*!
221 /*!
221 Inserts a single \a slice to the series before the slice at \a index position.
222 Inserts a single \a slice to the series before the slice at \a index position.
222 Slice ownership is passed to the series.
223 Slice ownership is passed to the series.
223
224
224 Returns true if insert was successfull.
225 Returns true if insert was successfull.
225 */
226 */
226 bool QPieSeries::insert(int index, QPieSlice* slice)
227 bool QPieSeries::insert(int index, QPieSlice* slice)
227 {
228 {
228 Q_D(QPieSeries);
229 Q_D(QPieSeries);
229
230
230 if (index < 0 || index > d->m_slices.count())
231 if (index < 0 || index > d->m_slices.count())
231 return false;
232 return false;
232
233
233 if (!slice || d->m_slices.contains(slice))
234 if (!slice || d->m_slices.contains(slice))
234 return false;
235 return false;
235
236
236 slice->setParent(this);
237 slice->setParent(this);
237 d->m_slices.insert(index, slice);
238 d->m_slices.insert(index, slice);
238
239
239 d->updateDerivativeData();
240 d->updateDerivativeData();
240
241
241 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceChanged()));
242 connect(slice, SIGNAL(valueChanged()), d, SLOT(sliceValueChanged()));
242 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
243 connect(slice, SIGNAL(clicked()), d, SLOT(sliceClicked()));
243 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
244 connect(slice, SIGNAL(hovered(bool)), d, SLOT(sliceHovered(bool)));
244
245
245 emit added(QList<QPieSlice*>() << slice);
246 emit added(QList<QPieSlice*>() << slice);
246 emit countChanged();
247 emit countChanged();
247
248
248 return true;
249 return true;
249 }
250 }
250
251
251 /*!
252 /*!
252 Removes a single \a slice from the series and deletes the slice.
253 Removes a single \a slice from the series and deletes the slice.
253
254
254 Do not reference the pointer after this call.
255 Do not reference the pointer after this call.
255
256
256 Returns true if remove was successfull.
257 Returns true if remove was successfull.
257 */
258 */
258 bool QPieSeries::remove(QPieSlice* slice)
259 bool QPieSeries::remove(QPieSlice* slice)
259 {
260 {
260 Q_D(QPieSeries);
261 Q_D(QPieSeries);
261
262
262 if (!d->m_slices.removeOne(slice))
263 if (!d->m_slices.removeOne(slice))
263 return false;
264 return false;
264
265
265 d->updateDerivativeData();
266 d->updateDerivativeData();
266
267
267 emit removed(QList<QPieSlice*>() << slice);
268 emit removed(QList<QPieSlice*>() << slice);
268 emit countChanged();
269 emit countChanged();
269
270
270 delete slice;
271 delete slice;
271 slice = 0;
272 slice = 0;
272
273
273 return true;
274 return true;
274 }
275 }
275
276
276 /*!
277 /*!
277 Clears all slices from the series.
278 Clears all slices from the series.
278 */
279 */
279 void QPieSeries::clear()
280 void QPieSeries::clear()
280 {
281 {
281 Q_D(QPieSeries);
282 Q_D(QPieSeries);
282 if (d->m_slices.count() == 0)
283 if (d->m_slices.count() == 0)
283 return;
284 return;
284
285
285 QList<QPieSlice*> slices = d->m_slices;
286 QList<QPieSlice*> slices = d->m_slices;
286 foreach (QPieSlice* s, d->m_slices) {
287 foreach (QPieSlice* s, d->m_slices) {
287 d->m_slices.removeOne(s);
288 d->m_slices.removeOne(s);
288 delete s;
289 delete s;
289 }
290 }
290
291
291 d->updateDerivativeData();
292 d->updateDerivativeData();
292
293
293 emit removed(slices);
294 emit removed(slices);
294 emit countChanged();
295 emit countChanged();
295 }
296 }
296
297
297 /*!
298 /*!
298 returns the number of the slices in this series.
299 returns the number of the slices in this series.
299 */
300 */
300 int QPieSeries::count() const
301 int QPieSeries::count() const
301 {
302 {
302 Q_D(const QPieSeries);
303 Q_D(const QPieSeries);
303 return d->m_slices.count();
304 return d->m_slices.count();
304 }
305 }
305
306
306 /*!
307 /*!
307 Returns true is the series is empty.
308 Returns true is the series is empty.
308 */
309 */
309 bool QPieSeries::isEmpty() const
310 bool QPieSeries::isEmpty() const
310 {
311 {
311 Q_D(const QPieSeries);
312 Q_D(const QPieSeries);
312 return d->m_slices.isEmpty();
313 return d->m_slices.isEmpty();
313 }
314 }
314
315
315 /*!
316 /*!
316 Returns a list of slices that belong to this series.
317 Returns a list of slices that belong to this series.
317 */
318 */
318 QList<QPieSlice*> QPieSeries::slices() const
319 QList<QPieSlice*> QPieSeries::slices() const
319 {
320 {
320 Q_D(const QPieSeries);
321 Q_D(const QPieSeries);
321 return d->m_slices;
322 return d->m_slices;
322 }
323 }
323
324
324 void QPieSeries::setHorizontalPosition(qreal relativePosition)
325 void QPieSeries::setHorizontalPosition(qreal relativePosition)
325 {
326 {
326 Q_D(QPieSeries);
327 Q_D(QPieSeries);
327
328
328 if (relativePosition < 0.0)
329 if (relativePosition < 0.0)
329 relativePosition = 0.0;
330 relativePosition = 0.0;
330 if (relativePosition > 1.0)
331 if (relativePosition > 1.0)
331 relativePosition = 1.0;
332 relativePosition = 1.0;
332
333
333 if (!qFuzzyIsNull(d->m_pieRelativeHorPos - relativePosition)) {
334 if (!qFuzzyIsNull(d->m_pieRelativeHorPos - relativePosition)) {
334 d->m_pieRelativeHorPos = relativePosition;
335 d->m_pieRelativeHorPos = relativePosition;
335 emit horizontalPositionChanged();
336 emit horizontalPositionChanged();
336 }
337 }
337 }
338 }
338
339
339 void QPieSeries::setVerticalPosition(qreal relativePosition)
340 void QPieSeries::setVerticalPosition(qreal relativePosition)
340 {
341 {
341 Q_D(QPieSeries);
342 Q_D(QPieSeries);
342
343
343 if (relativePosition < 0.0)
344 if (relativePosition < 0.0)
344 relativePosition = 0.0;
345 relativePosition = 0.0;
345 if (relativePosition > 1.0)
346 if (relativePosition > 1.0)
346 relativePosition = 1.0;
347 relativePosition = 1.0;
347
348
348 if (!qFuzzyIsNull(d->m_pieRelativeVerPos - relativePosition)) {
349 if (!qFuzzyIsNull(d->m_pieRelativeVerPos - relativePosition)) {
349 d->m_pieRelativeVerPos = relativePosition;
350 d->m_pieRelativeVerPos = relativePosition;
350 emit verticalPositionChanged();
351 emit verticalPositionChanged();
351 }
352 }
352 }
353 }
353
354
354 qreal QPieSeries::horizontalPosition() const
355 qreal QPieSeries::horizontalPosition() const
355 {
356 {
356 Q_D(const QPieSeries);
357 Q_D(const QPieSeries);
357 return d->m_pieRelativeHorPos;
358 return d->m_pieRelativeHorPos;
358 }
359 }
359
360
360 qreal QPieSeries::verticalPosition() const
361 qreal QPieSeries::verticalPosition() const
361 {
362 {
362 Q_D(const QPieSeries);
363 Q_D(const QPieSeries);
363 return d->m_pieRelativeVerPos;
364 return d->m_pieRelativeVerPos;
364 }
365 }
365
366
366 void QPieSeries::setPieSize(qreal relativeSize)
367 void QPieSeries::setPieSize(qreal relativeSize)
367 {
368 {
368 Q_D(QPieSeries);
369 Q_D(QPieSeries);
369
370
370 if (relativeSize < 0.0)
371 if (relativeSize < 0.0)
371 relativeSize = 0.0;
372 relativeSize = 0.0;
372 if (relativeSize > 1.0)
373 if (relativeSize > 1.0)
373 relativeSize = 1.0;
374 relativeSize = 1.0;
374
375
375 if (!qFuzzyIsNull(d->m_pieRelativeSize - relativeSize)) {
376 if (!qFuzzyIsNull(d->m_pieRelativeSize - relativeSize)) {
376 d->m_pieRelativeSize = relativeSize;
377 d->m_pieRelativeSize = relativeSize;
377 emit pieSizeChanged();
378 emit pieSizeChanged();
378 }
379 }
379 }
380 }
380
381
381 qreal QPieSeries::pieSize() const
382 qreal QPieSeries::pieSize() const
382 {
383 {
383 Q_D(const QPieSeries);
384 Q_D(const QPieSeries);
384 return d->m_pieRelativeSize;
385 return d->m_pieRelativeSize;
385 }
386 }
386
387
387
388
388 void QPieSeries::setPieStartAngle(qreal angle)
389 void QPieSeries::setPieStartAngle(qreal angle)
389 {
390 {
390 Q_D(QPieSeries);
391 Q_D(QPieSeries);
391 if (qFuzzyIsNull(d->m_pieStartAngle - angle))
392 if (qFuzzyIsNull(d->m_pieStartAngle - angle))
392 return;
393 return;
393 d->m_pieStartAngle = angle;
394 d->m_pieStartAngle = angle;
394 d->updateDerivativeData();
395 d->updateDerivativeData();
395 emit pieStartAngleChanged();
396 emit pieStartAngleChanged();
396 }
397 }
397
398
398 qreal QPieSeries::pieStartAngle() const
399 qreal QPieSeries::pieStartAngle() const
399 {
400 {
400 Q_D(const QPieSeries);
401 Q_D(const QPieSeries);
401 return d->m_pieStartAngle;
402 return d->m_pieStartAngle;
402 }
403 }
403
404
404 /*!
405 /*!
405 Sets the end angle of the pie.
406 Sets the end angle of the pie.
406
407
407 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
408 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
408
409
409 \a angle must be greater than start angle.
410 \a angle must be greater than start angle.
410
411
411 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
412 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
412 */
413 */
413 void QPieSeries::setPieEndAngle(qreal angle)
414 void QPieSeries::setPieEndAngle(qreal angle)
414 {
415 {
415 Q_D(QPieSeries);
416 Q_D(QPieSeries);
416 if (qFuzzyIsNull(d->m_pieEndAngle - angle))
417 if (qFuzzyIsNull(d->m_pieEndAngle - angle))
417 return;
418 return;
418 d->m_pieEndAngle = angle;
419 d->m_pieEndAngle = angle;
419 d->updateDerivativeData();
420 d->updateDerivativeData();
420 emit pieEndAngleChanged();
421 emit pieEndAngleChanged();
421 }
422 }
422
423
423 /*!
424 /*!
424 Returns the end angle of the pie.
425 Returns the end angle of the pie.
425
426
426 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
427 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
427
428
428 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
429 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
429 */
430 */
430 qreal QPieSeries::pieEndAngle() const
431 qreal QPieSeries::pieEndAngle() const
431 {
432 {
432 Q_D(const QPieSeries);
433 Q_D(const QPieSeries);
433 return d->m_pieEndAngle;
434 return d->m_pieEndAngle;
434 }
435 }
435
436
436 /*!
437 /*!
437 Sets the all the slice labels \a visible or invisible.
438 Sets the all the slice labels \a visible or invisible.
438
439
439 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
440 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
440 */
441 */
441 void QPieSeries::setLabelsVisible(bool visible)
442 void QPieSeries::setLabelsVisible(bool visible)
442 {
443 {
443 Q_D(QPieSeries);
444 Q_D(QPieSeries);
444 foreach (QPieSlice* s, d->m_slices)
445 foreach (QPieSlice* s, d->m_slices)
445 s->setLabelVisible(visible);
446 s->setLabelVisible(visible);
446 }
447 }
447
448
448 /*!
449 /*!
449 Returns the sum of all slice values in this series.
450 Returns the sum of all slice values in this series.
450
451
451 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
452 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
452 */
453 */
453 qreal QPieSeries::sum() const
454 qreal QPieSeries::sum() const
454 {
455 {
455 Q_D(const QPieSeries);
456 Q_D(const QPieSeries);
456 return d->m_sum;
457 return d->m_sum;
457 }
458 }
458
459
459 /*!
460 /*!
460 \fn void QPieSeries::added(QList<QPieSlice*> slices)
461 \fn void QPieSeries::added(QList<QPieSlice*> slices)
461
462
462 This signal is emitted when \a slices have been added to the series.
463 This signal is emitted when \a slices have been added to the series.
463
464
464 \sa append(), insert()
465 \sa append(), insert()
465 */
466 */
466
467
467 /*!
468 /*!
468 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
469 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
469
470
470 This signal is emitted when \a slices have been removed from the series.
471 This signal is emitted when \a slices have been removed from the series.
471
472
472 \sa remove()
473 \sa remove()
473 */
474 */
474
475
475 /*!
476 /*!
476 \fn void QPieSeries::clicked(QPieSlice* slice)
477 \fn void QPieSeries::clicked(QPieSlice* slice)
477
478
478 This signal is emitted when a \a slice has been clicked.
479 This signal is emitted when a \a slice has been clicked.
479
480
480 \sa QPieSlice::clicked()
481 \sa QPieSlice::clicked()
481 */
482 */
482
483
483 /*!
484 /*!
484 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
485 \fn void QPieSeries::hovered(QPieSlice* slice, bool state)
485
486
486 This signal is emitted when user has hovered over or away from the \a slice.
487 This signal is emitted when user has hovered over or away from the \a slice.
487
488
488 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
489 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
489
490
490 \sa QPieSlice::hovered()
491 \sa QPieSlice::hovered()
491 */
492 */
492
493
493
494
494
495
495 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
496
497
497
498
498 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
499 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent) :
499 QAbstractSeriesPrivate(parent),
500 QAbstractSeriesPrivate(parent),
500 m_pieRelativeHorPos(0.5),
501 m_pieRelativeHorPos(0.5),
501 m_pieRelativeVerPos(0.5),
502 m_pieRelativeVerPos(0.5),
502 m_pieRelativeSize(0.7),
503 m_pieRelativeSize(0.7),
503 m_pieStartAngle(0),
504 m_pieStartAngle(0),
504 m_pieEndAngle(360),
505 m_pieEndAngle(360),
505 m_sum(0)
506 m_sum(0)
506 {
507 {
507 }
508 }
508
509
509 QPieSeriesPrivate::~QPieSeriesPrivate()
510 QPieSeriesPrivate::~QPieSeriesPrivate()
510 {
511 {
511 }
512 }
512
513
513 void QPieSeriesPrivate::updateDerivativeData()
514 void QPieSeriesPrivate::updateDerivativeData()
514 {
515 {
515 // calculate sum of all slices
516 // calculate sum of all slices
516 qreal sum = 0;
517 qreal sum = 0;
517 foreach (QPieSlice* s, m_slices)
518 foreach (QPieSlice* s, m_slices)
518 sum += s->value();
519 sum += s->value();
519
520
520 if (!qFuzzyIsNull(m_sum - sum)) {
521 if (!qFuzzyIsNull(m_sum - sum)) {
521 m_sum = sum;
522 m_sum = sum;
522 emit q_func()->sumChanged();
523 emit q_func()->sumChanged();
523 }
524 }
524
525
525 // nothing to show..
526 // nothing to show..
526 if (qFuzzyIsNull(m_sum))
527 if (qFuzzyIsNull(m_sum))
527 return;
528 return;
528
529
529 // update slice attributes
530 // update slice attributes
530 qreal sliceAngle = m_pieStartAngle;
531 qreal sliceAngle = m_pieStartAngle;
531 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
532 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
532 QVector<QPieSlice*> changed;
533 QVector<QPieSlice*> changed;
533 foreach (QPieSlice* s, m_slices) {
534 foreach (QPieSlice* s, m_slices) {
534
535 QPieSlicePrivate *d = QPieSlicePrivate::fromSlice(s);
535 PieSliceData data = PieSliceData::fromSlice(s);
536 d->setPercentage(s->value() / m_sum);
536 data.m_percentage = s->value() / m_sum;
537 d->setStartAngle(sliceAngle);
537 data.m_angleSpan = pieSpan * data.m_percentage;
538 d->setAngleSpan(pieSpan * s->percentage());
538 data.m_startAngle = sliceAngle;
539 sliceAngle += s->angleSpan();
539 sliceAngle += data.m_angleSpan;
540
541 if (PieSliceData::fromSlice(s) != data) {
542 PieSliceData::fromSlice(s) = data;
543 changed << s;
544 }
545 }
540 }
546
541
547 // emit signals
542
548 foreach (QPieSlice* s, changed)
543 emit calculatedDataChanged();
549 PieSliceData::emitCalculatedDataChanged(s);
550 }
544 }
551
545
552 QPieSeriesPrivate* QPieSeriesPrivate::seriesData(QPieSeries &series)
546 QPieSeriesPrivate* QPieSeriesPrivate::fromSeries(QPieSeries *series)
553 {
547 {
554 return series.d_func();
548 return series->d_func();
555 }
549 }
556
550
557 void QPieSeriesPrivate::sliceChanged()
551 void QPieSeriesPrivate::sliceValueChanged()
558 {
552 {
559 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
553 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
560 updateDerivativeData();
554 updateDerivativeData();
561 }
555 }
562
556
563 void QPieSeriesPrivate::sliceClicked()
557 void QPieSeriesPrivate::sliceClicked()
564 {
558 {
565 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
559 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
566 Q_ASSERT(m_slices.contains(slice));
560 Q_ASSERT(m_slices.contains(slice));
567 Q_Q(QPieSeries);
561 Q_Q(QPieSeries);
568 emit q->clicked(slice);
562 emit q->clicked(slice);
569 }
563 }
570
564
571 void QPieSeriesPrivate::sliceHovered(bool state)
565 void QPieSeriesPrivate::sliceHovered(bool state)
572 {
566 {
573 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
567 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
574 Q_ASSERT(m_slices.contains(slice));
568 Q_ASSERT(m_slices.contains(slice));
575 Q_Q(QPieSeries);
569 Q_Q(QPieSeries);
576 emit q->hovered(slice, state);
570 emit q->hovered(slice, state);
577 }
571 }
578
572
579 void QPieSeriesPrivate::scaleDomain(Domain& domain)
573 void QPieSeriesPrivate::scaleDomain(Domain& domain)
580 {
574 {
581 Q_UNUSED(domain);
575 Q_UNUSED(domain);
582 // does not apply to pie
576 // does not apply to pie
583 }
577 }
584
578
585 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
579 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
586 {
580 {
587 Q_Q(QPieSeries);
581 Q_Q(QPieSeries);
588 PieChartItem* pie = new PieChartItem(q,presenter);
582 PieChartItem* pie = new PieChartItem(q,presenter);
589 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
583 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
590 presenter->animator()->addAnimation(pie);
584 presenter->animator()->addAnimation(pie);
591 }
585 }
592 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
586 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
593 return pie;
587 return pie;
594 }
588 }
595
589
596 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
590 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
597 {
591 {
598 Q_Q(QPieSeries);
592 Q_Q(QPieSeries);
599 QList<LegendMarker*> markers;
593 QList<LegendMarker*> markers;
600 foreach(QPieSlice* slice, q->slices()) {
594 foreach(QPieSlice* slice, q->slices()) {
601 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
595 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
602 markers << marker;
596 markers << marker;
603 }
597 }
604 return markers;
598 return markers;
605 }
599 }
606
600
607 #include "moc_qpieseries.cpp"
601 #include "moc_qpieseries.cpp"
608 #include "moc_qpieseries_p.cpp"
602 #include "moc_qpieseries_p.cpp"
609
603
610 QTCOMMERCIALCHART_END_NAMESPACE
604 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,67 +1,70
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* fromSeries(QPieSeries *series);
45
46 signals:
47 void calculatedDataChanged();
45
48
46 public Q_SLOTS:
49 public Q_SLOTS:
47 void sliceChanged();
50 void sliceValueChanged();
48 void sliceClicked();
51 void sliceClicked();
49 void sliceHovered(bool state);
52 void sliceHovered(bool state);
50
53
51 public:
54 private:
52 QList<QPieSlice*> m_slices;
55 QList<QPieSlice*> m_slices;
53 qreal m_pieRelativeHorPos;
56 qreal m_pieRelativeHorPos;
54 qreal m_pieRelativeVerPos;
57 qreal m_pieRelativeVerPos;
55 qreal m_pieRelativeSize;
58 qreal m_pieRelativeSize;
56 qreal m_pieStartAngle;
59 qreal m_pieStartAngle;
57 qreal m_pieEndAngle;
60 qreal m_pieEndAngle;
58 qreal m_sum;
61 qreal m_sum;
59
62
60 private:
63 private:
61 friend class QLegendPrivate;
64 friend class QLegendPrivate;
62 Q_DECLARE_PUBLIC(QPieSeries)
65 Q_DECLARE_PUBLIC(QPieSeries)
63 };
66 };
64
67
65 QTCOMMERCIALCHART_END_NAMESPACE
68 QTCOMMERCIALCHART_END_NAMESPACE
66
69
67 #endif // QPIESERIES_P_H
70 #endif // QPIESERIES_P_H
@@ -1,436 +1,498
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 "qpieslice.h"
21 #include "qpieslice.h"
22 #include "pieslicedata_p.h"
22 #include "qpieslice_p.h"
23
23
24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25
25
26 /*!
26 /*!
27 \class QPieSlice
27 \class QPieSlice
28 \brief Defines a slice in pie series.
28 \brief Defines a slice in pie series.
29
29
30 This object defines the properties of a single slice in a QPieSeries.
30 This object defines the properties of a single slice in a QPieSeries.
31
31
32 In addition to the obvious value and label properties the user can also control
32 In addition to the obvious value and label properties the user can also control
33 the visual appearance of a slice. By modifying the visual appearance also means that
33 the visual appearance of a slice. By modifying the visual appearance also means that
34 the user is overriding the default appearance set by the theme. Even if the theme is
34 the user is overriding the default appearance set by the theme. Even if the theme is
35 changed users settings will persist.
35 changed users settings will persist.
36
36
37 To enable user interaction customization with the slices some basic signals
37 To enable user interaction customization with the slices some basic signals
38 are provided about clicking and hovering.
38 are provided about clicking and hovering.
39 */
39 */
40
40
41 /*!
41 /*!
42 \property QPieSlice::label
42 \property QPieSlice::label
43
43
44 Label of the slice.
44 Label of the slice.
45 */
45 */
46
46
47 /*!
47 /*!
48 \property QPieSlice::value
48 \property QPieSlice::value
49
49
50 Value of the slice.
50 Value of the slice.
51
51
52 \sa percentage(), QPieSeries::sum()
52 \sa percentage(), QPieSeries::sum()
53 */
53 */
54
54
55 /*!
55 /*!
56 Constructs an empty slice with a \a parent.
56 Constructs an empty slice with a \a parent.
57
57
58 \sa QPieSeries::append(), QPieSeries::insert()
58 \sa QPieSeries::append(), QPieSeries::insert()
59 */
59 */
60 QPieSlice::QPieSlice(QObject *parent)
60 QPieSlice::QPieSlice(QObject *parent)
61 :QObject(parent),
61 :QObject(parent),
62 d(new PieSliceData())
62 d_ptr(new QPieSlicePrivate(this))
63 {
63 {
64
64
65 }
65 }
66
66
67 /*!
67 /*!
68 Constructs an empty slice with given \a value, \a label and a \a parent.
68 Constructs an empty slice with given \a value, \a label and a \a parent.
69 \sa QPieSeries::append(), QPieSeries::insert()
69 \sa QPieSeries::append(), QPieSeries::insert()
70 */
70 */
71 QPieSlice::QPieSlice(QString label, qreal value, QObject *parent)
71 QPieSlice::QPieSlice(QString label, qreal value, QObject *parent)
72 :QObject(parent),
72 :QObject(parent),
73 d(new PieSliceData())
73 d_ptr(new QPieSlicePrivate(this))
74 {
74 {
75 d->m_value = value;
75 d_ptr->m_data.m_value = value;
76 d->m_labelText = label;
76 d_ptr->m_data.m_labelText = label;
77 }
77 }
78
78
79 /*!
79 /*!
80 Destroys the slice.
80 Destroys the slice.
81 User should not delete the slice if it has been added to the series.
81 User should not delete the slice if it has been added to the series.
82 */
82 */
83 QPieSlice::~QPieSlice()
83 QPieSlice::~QPieSlice()
84 {
84 {
85 delete d;
85
86 }
86 }
87
87
88 /*!
88 /*!
89 Gets the value of the slice.
89 Gets the value of the slice.
90 Note that all values in the series
90 Note that all values in the series
91 \sa setValue()
91 \sa setValue()
92 */
92 */
93 qreal QPieSlice::value() const
93 qreal QPieSlice::value() const
94 {
94 {
95 return d->m_value;
95 return d_ptr->m_data.m_value;
96 }
96 }
97
97
98 /*!
98 /*!
99 Gets the label of the slice.
99 Gets the label of the slice.
100 \sa setLabel()
100 \sa setLabel()
101 */
101 */
102 QString QPieSlice::label() const
102 QString QPieSlice::label() const
103 {
103 {
104 return d->m_labelText;
104 return d_ptr->m_data.m_labelText;
105 }
105 }
106
106
107 /*!
107 /*!
108 Returns true if label is set as visible.
108 Returns true if label is set as visible.
109 \sa setLabelVisible()
109 \sa setLabelVisible()
110 */
110 */
111 bool QPieSlice::isLabelVisible() const
111 bool QPieSlice::isLabelVisible() const
112 {
112 {
113 return d->m_isLabelVisible;
113 return d_ptr->m_data.m_isLabelVisible;
114 }
114 }
115
115
116 /*!
116 /*!
117 Returns true if slice is exloded from the pie.
117 Returns true if slice is exloded from the pie.
118 \sa setExploded(), explodeDistanceFactor(), setExplodeDistanceFactor()
118 \sa setExploded(), explodeDistanceFactor(), setExplodeDistanceFactor()
119 */
119 */
120 bool QPieSlice::isExploded() const
120 bool QPieSlice::isExploded() const
121 {
121 {
122 return d->m_isExploded;
122 return d_ptr->m_data.m_isExploded;
123 }
123 }
124
124
125 /*!
125 /*!
126 Returns the explode distance factor.
126 Returns the explode distance factor.
127
127
128 The factor is relative to pie radius. For example:
128 The factor is relative to pie radius. For example:
129 1.0 means the distance is the same as the radius.
129 1.0 means the distance is the same as the radius.
130 0.5 means the distance is half of the radius.
130 0.5 means the distance is half of the radius.
131
131
132 Default value is 0.15.
132 Default value is 0.15.
133
133
134 \sa setExplodeDistanceFactor(), isExploded(), setExploded()
134 \sa setExplodeDistanceFactor(), isExploded(), setExploded()
135 */
135 */
136 qreal QPieSlice::explodeDistanceFactor() const
136 qreal QPieSlice::explodeDistanceFactor() const
137 {
137 {
138 return d->m_explodeDistanceFactor;
138 return d_ptr->m_data.m_explodeDistanceFactor;
139 }
139 }
140
140
141 /*!
141 /*!
142 Returns the percentage of this slice compared to the sum of all slices in the same series.
142 Returns the percentage of this slice compared to the sum of all slices in the same series.
143 The returned value ranges from 0 to 1.0.
143 The returned value ranges from 0 to 1.0.
144
144
145 Updated internally after the slice is added to the series.
145 Updated internally after the slice is added to the series.
146
146
147 \sa QPieSeries::sum()
147 \sa QPieSeries::sum()
148 */
148 */
149 qreal QPieSlice::percentage() const
149 qreal QPieSlice::percentage() const
150 {
150 {
151 return d->m_percentage;
151 return d_ptr->m_data.m_percentage;
152 }
152 }
153
153
154 /*!
154 /*!
155 Returns the starting angle of this slice in the series it belongs to.
155 Returns the starting angle of this slice in the series it belongs to.
156
156
157 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
157 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
158
158
159 Updated internally after the slice is added to the series.
159 Updated internally after the slice is added to the series.
160 */
160 */
161 qreal QPieSlice::startAngle() const
161 qreal QPieSlice::startAngle() const
162 {
162 {
163 return d->m_startAngle;
163 return d_ptr->m_data.m_startAngle;
164 }
164 }
165
165
166 /*!
166 /*!
167 Returns the end angle of this slice in the series it belongs to.
167 Returns the end angle of this slice in the series it belongs to.
168
168
169 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
169 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
170
170
171 Updated internally after the slice is added to the series.
171 Updated internally after the slice is added to the series.
172 */
172 */
173 qreal QPieSlice::endAngle() const
173 qreal QPieSlice::angleSpan() const
174 {
174 {
175 return d->m_startAngle + d->m_angleSpan;
175 return d_ptr->m_data.m_angleSpan;
176 }
176 }
177
177
178 /*!
178 /*!
179 Returns the pen used to draw this slice.
179 Returns the pen used to draw this slice.
180 \sa setPen()
180 \sa setPen()
181 */
181 */
182 QPen QPieSlice::pen() const
182 QPen QPieSlice::pen() const
183 {
183 {
184 return d->m_slicePen;
184 return d_ptr->m_data.m_slicePen;
185 }
185 }
186
186
187 /*!
187 /*!
188 Returns the brush used to draw this slice.
188 Returns the brush used to draw this slice.
189 \sa setBrush()
189 \sa setBrush()
190 */
190 */
191 QBrush QPieSlice::brush() const
191 QBrush QPieSlice::brush() const
192 {
192 {
193 return d->m_sliceBrush;
193 return d_ptr->m_data.m_sliceBrush;
194 }
194 }
195
195
196 /*!
196 /*!
197 Returns the pen used to draw the label in this slice.
197 Returns the pen used to draw the label in this slice.
198 \sa setLabelPen()
198 \sa setLabelPen()
199 */
199 */
200 QPen QPieSlice::labelPen() const
200 QPen QPieSlice::labelPen() const
201 {
201 {
202 return d->m_labelPen;
202 return d_ptr->m_data.m_labelPen;
203 }
203 }
204
204
205 /*!
205 /*!
206 Returns the font used to draw label in this slice.
206 Returns the font used to draw label in this slice.
207 \sa setLabelFont()
207 \sa setLabelFont()
208 */
208 */
209 QFont QPieSlice::labelFont() const
209 QFont QPieSlice::labelFont() const
210 {
210 {
211 return d->m_labelFont;
211 return d_ptr->m_data.m_labelFont;
212 }
212 }
213
213
214 /*!
214 /*!
215 Gets the label arm length factor.
215 Gets the label arm length factor.
216
216
217 The factor is relative to pie radius. For example:
217 The factor is relative to pie radius. For example:
218 1.0 means the length is the same as the radius.
218 1.0 means the length is the same as the radius.
219 0.5 means the length is half of the radius.
219 0.5 means the length is half of the radius.
220
220
221 Default value is 0.15
221 Default value is 0.15
222
222
223 \sa setLabelArmLengthFactor()
223 \sa setLabelArmLengthFactor()
224 */
224 */
225 qreal QPieSlice::labelArmLengthFactor() const
225 qreal QPieSlice::labelArmLengthFactor() const
226 {
226 {
227 return d->m_labelArmLengthFactor;
227 return d_ptr->m_data.m_labelArmLengthFactor;
228 }
228 }
229
229
230 /*!
230 /*!
231 \fn void QPieSlice::labelChanged()
231 \fn void QPieSlice::labelChanged()
232
232
233 This signal is emitted when the slice label changes.
233 This signal is emitted when the slice label changes.
234
234
235 \sa setLabel()
235 \sa setLabel()
236 */
236 */
237
237
238 /*!
238 /*!
239 \fn void QPieSlice::valueChanged()
239 \fn void QPieSlice::valueChanged()
240
240
241 This signal is emitted when the slice value changes.
241 This signal is emitted when the slice value changes.
242
242
243 \sa setValue()
243 \sa setValue()
244 */
244 */
245
245
246 /*!
246 /*!
247 \fn void QPieSlice::appearanceChanged()
247 \fn void QPieSlice::appearanceChanged()
248
248
249 This signal is emitted when visual appearance of the slice changes.
249 This signal is emitted when visual appearance of the slice changes.
250
250
251 \sa setPen(), setBrush(), setLabelVisible(), setExploded()
251 \sa setPen(), setBrush(), setLabelVisible(), setExploded()
252 */
252 */
253
253
254 /*!
254 /*!
255 \fn void QPieSlice::calculatedDataChanged()
255 \fn void QPieSlice::calculatedDataChanged()
256
256
257 This signal is emitted when calculated data for this slice changes.
257 This signal is emitted when calculated data for this slice changes.
258
258
259 \sa percentage(), startAngle(), endAngle()
259 \sa percentage(), startAngle(), endAngle()
260 */
260 */
261
261
262 /*!
262 /*!
263 \fn void QPieSlice::clicked()
263 \fn void QPieSlice::clicked()
264
264
265 This signal is emitted when user has clicked the slice.
265 This signal is emitted when user has clicked the slice.
266
266
267 \sa QPieSeries::clicked()
267 \sa QPieSeries::clicked()
268 */
268 */
269
269
270 /*!
270 /*!
271 \fn void QPieSlice::hovered(bool state)
271 \fn void QPieSlice::hovered(bool state)
272
272
273 This signal is emitted when user has hovered over or away from the slice.
273 This signal is emitted when user has hovered over or away from the slice.
274
274
275 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
275 \a state is true when user has hovered over the slice and false when hover has moved away from the slice.
276
276
277 \sa QPieSeries::hovered()
277 \sa QPieSeries::hovered()
278 */
278 */
279
279
280 /*!
280 /*!
281 Sets the \a value of this slice.
281 Sets the \a value of this slice.
282 \sa value()
282 \sa value()
283 */
283 */
284 void QPieSlice::setValue(qreal value)
284 void QPieSlice::setValue(qreal value)
285 {
285 {
286 if (!qFuzzyIsNull(d->m_value - value)) {
286 if (!qFuzzyIsNull(d_ptr->m_data.m_value - value)) {
287 d->m_value = value;
287 d_ptr->m_data.m_value = value;
288 emit valueChanged();
288 emit valueChanged();
289 }
289 }
290 }
290 }
291
291
292 /*!
292 /*!
293 Sets the \a label of the slice.
293 Sets the \a label of the slice.
294 \sa label()
294 \sa label()
295 */
295 */
296 void QPieSlice::setLabel(QString label)
296 void QPieSlice::setLabel(QString label)
297 {
297 {
298 if (d->m_labelText != label) {
298 if (d_ptr->m_data.m_labelText != label) {
299 d->m_labelText = label;
299 d_ptr->m_data.m_labelText = label;
300 emit labelChanged();
300 emit labelChanged();
301 }
301 }
302 }
302 }
303
303
304 /*!
304 /*!
305 Sets the label \a visible in this slice.
305 Sets the label \a visible in this slice.
306 \sa isLabelVisible(), QPieSeries::setLabelsVisible()
306 \sa isLabelVisible(), QPieSeries::setLabelsVisible()
307 */
307 */
308 void QPieSlice::setLabelVisible(bool visible)
308 void QPieSlice::setLabelVisible(bool visible)
309 {
309 {
310 if (d->m_isLabelVisible != visible) {
310 if (d_ptr->m_data.m_isLabelVisible != visible) {
311 d->m_isLabelVisible = visible;
311 d_ptr->m_data.m_isLabelVisible = visible;
312 emit appearanceChanged();
312 emit labelVisibleChanged();
313 }
313 }
314 }
314 }
315
315
316 /*!
316 /*!
317 Sets this slices \a exploded state.
317 Sets this slices \a exploded state.
318
318
319 If the slice is exploded it is moved away from the pie center. The distance is defined by the explode distance factor.
319 If the slice is exploded it is moved away from the pie center. The distance is defined by the explode distance factor.
320
320
321 \sa isExploded(), explodeDistanceFactor(), setExplodeDistanceFactor()
321 \sa isExploded(), explodeDistanceFactor(), setExplodeDistanceFactor()
322 */
322 */
323 void QPieSlice::setExploded(bool exploded)
323 void QPieSlice::setExploded(bool exploded)
324 {
324 {
325 if (d->m_isExploded != exploded) {
325 if (d_ptr->m_data.m_isExploded != exploded) {
326 d->m_isExploded = exploded;
326 d_ptr->m_data.m_isExploded = exploded;
327 emit appearanceChanged();
327 emit explodedChanged();
328 }
328 }
329 }
329 }
330
330
331 /*!
331 /*!
332 Sets the explode distance \a factor.
332 Sets the explode distance \a factor.
333
333
334 The factor is relative to pie radius. For example:
334 The factor is relative to pie radius. For example:
335 1.0 means the distance is the same as the radius.
335 1.0 means the distance is the same as the radius.
336 0.5 means the distance is half of the radius.
336 0.5 means the distance is half of the radius.
337
337
338 Default value is 0.15
338 Default value is 0.15
339
339
340 \sa explodeDistanceFactor(), isExploded(), setExploded()
340 \sa explodeDistanceFactor(), isExploded(), setExploded()
341 */
341 */
342 void QPieSlice::setExplodeDistanceFactor(qreal factor)
342 void QPieSlice::setExplodeDistanceFactor(qreal factor)
343 {
343 {
344 if (!qFuzzyIsNull(d->m_explodeDistanceFactor - factor)) {
344 if (!qFuzzyIsNull(d_ptr->m_data.m_explodeDistanceFactor - factor)) {
345 d->m_explodeDistanceFactor = factor;
345 d_ptr->m_data.m_explodeDistanceFactor = factor;
346 emit appearanceChanged();
346 emit explodeDistanceFactorChanged();
347 }
347 }
348 }
348 }
349
349
350 /*!
350 /*!
351 Sets the \a pen used to draw this slice.
351 Sets the \a pen used to draw this slice.
352
352
353 Overrides the pen set by the theme.
353 Overrides the pen set by the theme.
354
354
355 \sa pen()
355 \sa pen()
356 */
356 */
357 void QPieSlice::setPen(const QPen &pen)
357 void QPieSlice::setPen(const QPen &pen)
358 {
358 {
359 if (d->m_slicePen != pen) {
359 d_ptr->setPen(pen, false);
360 d->m_slicePen = pen;
361 d->m_slicePen.setThemed(false);
362 emit appearanceChanged();
363 }
364 }
360 }
365
361
366 /*!
362 /*!
367 Sets the \a brush used to draw this slice.
363 Sets the \a brush used to draw this slice.
368
364
369 Overrides the brush set by the theme.
365 Overrides the brush set by the theme.
370
366
371 \sa brush()
367 \sa brush()
372 */
368 */
373 void QPieSlice::setBrush(const QBrush &brush)
369 void QPieSlice::setBrush(const QBrush &brush)
374 {
370 {
375 if (d->m_sliceBrush != brush) {
371 d_ptr->setBrush(brush, false);
376 d->m_sliceBrush = brush;
377 d->m_sliceBrush.setThemed(false);
378 emit appearanceChanged();
379 }
380 }
372 }
381
373
382 /*!
374 /*!
383 Sets the \a pen used to draw the label in this slice.
375 Sets the \a pen used to draw the label in this slice.
384
376
385 Overrides the pen set by the theme.
377 Overrides the pen set by the theme.
386
378
387 \sa labelPen()
379 \sa labelPen()
388 */
380 */
389 void QPieSlice::setLabelPen(const QPen &pen)
381 void QPieSlice::setLabelPen(const QPen &pen)
390 {
382 {
391 if (d->m_labelPen != pen) {
383 d_ptr->setLabelPen(pen, false);
392 d->m_labelPen = pen;
393 d->m_labelPen.setThemed(false);
394 emit appearanceChanged();
395 }
396 }
384 }
397
385
398 /*!
386 /*!
399 Sets the \a font used to draw the label in this slice.
387 Sets the \a font used to draw the label in this slice.
400
388
401 Overrides the font set by the theme.
389 Overrides the font set by the theme.
402
390
403 \sa labelFont()
391 \sa labelFont()
404 */
392 */
405 void QPieSlice::setLabelFont(const QFont &font)
393 void QPieSlice::setLabelFont(const QFont &font)
406 {
394 {
407 if (d->m_labelFont != font) {
395 d_ptr->setLabelFont(font, false);
408 d->m_labelFont = font;
409 d->m_labelFont.setThemed(false);
410 emit appearanceChanged();
411 }
412 }
396 }
413
397
414 /*!
398 /*!
415 Sets the label arm length \a factor.
399 Sets the label arm length \a factor.
416
400
417 The factor is relative to pie radius. For example:
401 The factor is relative to pie radius. For example:
418 1.0 means the length is the same as the radius.
402 1.0 means the length is the same as the radius.
419 0.5 means the length is half of the radius.
403 0.5 means the length is half of the radius.
420
404
421 Default value is 0.15
405 Default value is 0.15
422
406
423 \sa labelArmLengthFactor()
407 \sa labelArmLengthFactor()
424 */
408 */
425 void QPieSlice::setLabelArmLengthFactor(qreal factor)
409 void QPieSlice::setLabelArmLengthFactor(qreal factor)
426 {
410 {
427 if (!qFuzzyIsNull(d->m_labelArmLengthFactor - factor)) {
411 if (!qFuzzyIsNull(d_ptr->m_data.m_labelArmLengthFactor - factor)) {
428 d->m_labelArmLengthFactor = factor;
412 d_ptr->m_data.m_labelArmLengthFactor = factor;
429 emit appearanceChanged();
413 emit labelArmLengthFactorChanged();
414 }
415 }
416
417 QPieSlicePrivate::QPieSlicePrivate(QPieSlice *parent)
418 :QObject(parent),
419 q_ptr(parent)
420 {
421
422 }
423
424 QPieSlicePrivate::~QPieSlicePrivate()
425 {
426
427 }
428
429 QPieSlicePrivate *QPieSlicePrivate::fromSlice(QPieSlice *slice)
430 {
431 return slice->d_func();
432 }
433
434 void QPieSlicePrivate::setPen(const QPen &pen, bool themed)
435 {
436 if (m_data.m_slicePen != pen) {
437 m_data.m_slicePen = pen;
438 m_data.m_slicePen.setThemed(themed);
439 emit q_ptr->penChanged();
440 }
441 }
442
443 void QPieSlicePrivate::setBrush(const QBrush &brush, bool themed)
444 {
445 if (m_data.m_sliceBrush != brush) {
446 m_data.m_sliceBrush = brush;
447 m_data.m_sliceBrush.setThemed(themed);
448 emit q_ptr->brushChanged();
449 }
450 }
451
452 void QPieSlicePrivate::setLabelPen(const QPen &pen, bool themed)
453 {
454 if (m_data.m_labelPen != pen) {
455 m_data.m_labelPen = pen;
456 m_data.m_labelPen.setThemed(themed);
457 emit q_ptr->labelPenChanged();
458 }
459 }
460
461 void QPieSlicePrivate::setLabelFont(const QFont &font, bool themed)
462 {
463 if (m_data.m_labelFont != font) {
464 m_data.m_labelFont = font;
465 m_data.m_labelFont.setThemed(themed);
466 emit q_ptr->labelFontChanged();
467 }
468 }
469
470 void QPieSlicePrivate::setPercentage(qreal percentage)
471 {
472 if (!qFuzzyIsNull(m_data.m_percentage - percentage)) {
473 m_data.m_percentage = percentage;
474 emit q_ptr->percentageChanged();
475 }
476 }
477
478 void QPieSlicePrivate::setStartAngle(qreal angle)
479 {
480 if (!qFuzzyIsNull(m_data.m_startAngle - angle)) {
481 m_data.m_startAngle = angle;
482 emit q_ptr->startAngleChanged();
483 }
484 }
485
486 void QPieSlicePrivate::setAngleSpan(qreal span)
487 {
488 if (!qFuzzyIsNull(m_data.m_angleSpan - span)) {
489 m_data.m_angleSpan = span;
490 emit q_ptr->angleSpanChanged();
430 }
491 }
431 }
492 }
432
493
433 QTCOMMERCIALCHART_END_NAMESPACE
494 QTCOMMERCIALCHART_END_NAMESPACE
434
495
435 QTCOMMERCIALCHART_USE_NAMESPACE
496 QTCOMMERCIALCHART_USE_NAMESPACE
436 #include "moc_qpieslice.cpp"
497 #include "moc_qpieslice.cpp"
498 #include "moc_qpieslice_p.cpp"
@@ -1,101 +1,114
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 QPIESLICE_H
21 #ifndef QPIESLICE_H
22 #define QPIESLICE_H
22 #define QPIESLICE_H
23
23
24 #include <qchartglobal.h>
24 #include <qchartglobal.h>
25 #include <QObject>
25 #include <QObject>
26 #include <QPen>
26 #include <QPen>
27 #include <QBrush>
27 #include <QBrush>
28 #include <QFont>
28 #include <QFont>
29
29
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 class PieSliceData;
31 class QPieSlicePrivate;
32
32
33 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
33 class QTCOMMERCIALCHART_EXPORT QPieSlice : public QObject
34 {
34 {
35 Q_OBJECT
35 Q_OBJECT
36 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
36 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
37 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
37 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
38 Q_PROPERTY(bool labelVisible READ isLabelVisible WRITE setLabelVisible)
38 Q_PROPERTY(bool labelVisible READ isLabelVisible WRITE setLabelVisible NOTIFY labelVisibleChanged)
39 Q_PROPERTY(bool exploded READ isExploded WRITE setExploded)
39 Q_PROPERTY(bool exploded READ isExploded WRITE setExploded NOTIFY explodedChanged)
40 Q_PROPERTY(QPen pen READ pen WRITE setPen NOTIFY penChanged)
41 Q_PROPERTY(QBrush brush READ brush WRITE setBrush NOTIFY brushChanged)
42 Q_PROPERTY(QPen labelPen READ labelPen WRITE setLabelPen NOTIFY labelPenChanged)
43 Q_PROPERTY(QFont labelFont READ labelFont WRITE setLabelFont NOTIFY labelFontChanged)
40 Q_PROPERTY(qreal LabelArmLengthFactor READ labelArmLengthFactor WRITE setLabelArmLengthFactor)
44 Q_PROPERTY(qreal LabelArmLengthFactor READ labelArmLengthFactor WRITE setLabelArmLengthFactor)
41 Q_PROPERTY(qreal explodeDistanceFactor READ explodeDistanceFactor WRITE setExplodeDistanceFactor)
45 Q_PROPERTY(qreal explodeDistanceFactor READ explodeDistanceFactor WRITE setExplodeDistanceFactor)
42 Q_PROPERTY(qreal percentage READ percentage NOTIFY calculatedDataChanged)
46 Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
43 Q_PROPERTY(qreal startAngle READ startAngle NOTIFY calculatedDataChanged)
47 Q_PROPERTY(qreal startAngle READ startAngle NOTIFY startAngleChanged)
44 Q_PROPERTY(qreal endAngle READ endAngle NOTIFY calculatedDataChanged)
48 Q_PROPERTY(qreal angleSpan READ angleSpan NOTIFY angleSpanChanged)
45
49
46 public:
50 public:
47 explicit QPieSlice(QObject *parent = 0);
51 explicit QPieSlice(QObject *parent = 0);
48 QPieSlice(QString label, qreal value, QObject *parent = 0);
52 QPieSlice(QString label, qreal value, QObject *parent = 0);
49 virtual ~QPieSlice();
53 virtual ~QPieSlice();
50
54
51 void setLabel(QString label);
55 void setLabel(QString label);
52 QString label() const;
56 QString label() const;
53
57
54 void setValue(qreal value);
58 void setValue(qreal value);
55 qreal value() const;
59 qreal value() const;
56
60
61 void setLabelVisible(bool visible = true);
62 bool isLabelVisible() const;
63
64 void setExploded(bool exploded = true);
65 bool isExploded() const;
66
57 void setPen(const QPen &pen);
67 void setPen(const QPen &pen);
58 QPen pen() const;
68 QPen pen() const;
59
69
60 void setBrush(const QBrush &brush);
70 void setBrush(const QBrush &brush);
61 QBrush brush() const;
71 QBrush brush() const;
62
72
63 void setLabelVisible(bool visible = true);
64 bool isLabelVisible() const;
65
66 void setLabelArmLengthFactor(qreal factor);
67 qreal labelArmLengthFactor() const;
68
69 void setLabelPen(const QPen &pen);
73 void setLabelPen(const QPen &pen);
70 QPen labelPen() const;
74 QPen labelPen() const;
71
75
72 void setLabelFont(const QFont &font);
76 void setLabelFont(const QFont &font);
73 QFont labelFont() const;
77 QFont labelFont() const;
74
78
75 void setExploded(bool exploded = true);
79 void setLabelArmLengthFactor(qreal factor);
76 bool isExploded() const;
80 qreal labelArmLengthFactor() const;
77
81
78 void setExplodeDistanceFactor(qreal factor);
82 void setExplodeDistanceFactor(qreal factor);
79 qreal explodeDistanceFactor() const;
83 qreal explodeDistanceFactor() const;
80
84
81 qreal percentage() const;
85 qreal percentage() const;
82 qreal startAngle() const;
86 qreal startAngle() const;
83 qreal endAngle() const;
87 qreal angleSpan() const;
84
88
85 Q_SIGNALS:
89 Q_SIGNALS:
86 void labelChanged();
90 void labelChanged();
87 void valueChanged();
91 void valueChanged();
88 void appearanceChanged();
92 void labelVisibleChanged();
89 void calculatedDataChanged();
93 void explodedChanged();
94 void penChanged();
95 void brushChanged();
96 void labelPenChanged();
97 void labelFontChanged();
98 void labelArmLengthFactorChanged();
99 void explodeDistanceFactorChanged();
100 void percentageChanged();
101 void startAngleChanged();
102 void angleSpanChanged();
90 void clicked();
103 void clicked();
91 void hovered(bool state);
104 void hovered(bool state);
92
105
93 private:
106 private:
94 friend class PieSliceData;
107 QPieSlicePrivate * const d_ptr;
95 PieSliceData * const d;
108 Q_DECLARE_PRIVATE(QPieSlice)
96 Q_DISABLE_COPY(QPieSlice)
109 Q_DISABLE_COPY(QPieSlice)
97 };
110 };
98
111
99 QTCOMMERCIALCHART_END_NAMESPACE
112 QTCOMMERCIALCHART_END_NAMESPACE
100
113
101 #endif // QPIESLICE_H
114 #endif // QPIESLICE_H
@@ -1,457 +1,472
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 properties();
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::properties()
79 void tst_qpieseries::properties()
80 {
80 {
81 QPieSeries s;
81 QPieSeries s;
82
82
83 QSignalSpy countSpy(&s, SIGNAL(countChanged()));
83 QSignalSpy countSpy(&s, SIGNAL(countChanged()));
84 QSignalSpy sumSpy(&s, SIGNAL(sumChanged()));
84 QSignalSpy sumSpy(&s, SIGNAL(sumChanged()));
85 QSignalSpy sizeSpy(&s, SIGNAL(pieSizeChanged()));
85 QSignalSpy sizeSpy(&s, SIGNAL(pieSizeChanged()));
86 QSignalSpy startAngleSpy(&s, SIGNAL(pieStartAngleChanged()));
86 QSignalSpy startAngleSpy(&s, SIGNAL(pieStartAngleChanged()));
87 QSignalSpy endAngleSpy(&s, SIGNAL(pieEndAngleChanged()));
87 QSignalSpy endAngleSpy(&s, SIGNAL(pieEndAngleChanged()));
88 QSignalSpy horPosSpy(&s, SIGNAL(horizontalPositionChanged()));
88 QSignalSpy horPosSpy(&s, SIGNAL(horizontalPositionChanged()));
89 QSignalSpy verPosSpy(&s, SIGNAL(verticalPositionChanged()));
89 QSignalSpy verPosSpy(&s, SIGNAL(verticalPositionChanged()));
90
90
91 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
91 QVERIFY(s.type() == QAbstractSeries::SeriesTypePie);
92 QVERIFY(s.count() == 0);
92 QVERIFY(s.count() == 0);
93 QVERIFY(s.isEmpty());
93 QVERIFY(s.isEmpty());
94 QCOMPARE(s.sum(), 0.0);
94 QCOMPARE(s.sum(), 0.0);
95 QCOMPARE(s.horizontalPosition(), 0.5);
95 QCOMPARE(s.horizontalPosition(), 0.5);
96 QCOMPARE(s.verticalPosition(), 0.5);
96 QCOMPARE(s.verticalPosition(), 0.5);
97 QCOMPARE(s.pieSize(), 0.7);
97 QCOMPARE(s.pieSize(), 0.7);
98 QCOMPARE(s.pieStartAngle(), 0.0);
98 QCOMPARE(s.pieStartAngle(), 0.0);
99 QCOMPARE(s.pieEndAngle(), 360.0);
99 QCOMPARE(s.pieEndAngle(), 360.0);
100
100
101 s.append("s1", 1);
101 s.append("s1", 1);
102 s.append("s2", 1);
102 s.append("s2", 1);
103 s.append("s3", 1);
103 s.append("s3", 1);
104 s.insert(1, new QPieSlice("s4", 1));
104 s.insert(1, new QPieSlice("s4", 1));
105 s.remove(s.slices().first());
105 s.remove(s.slices().first());
106 QCOMPARE(s.count(), 3);
106 QCOMPARE(s.count(), 3);
107 QCOMPARE(s.sum(), 3.0);
107 QCOMPARE(s.sum(), 3.0);
108 s.clear();
108 s.clear();
109 QCOMPARE(s.count(), 0);
109 QCOMPARE(s.count(), 0);
110 QCOMPARE(s.sum(), 0.0);
110 QCOMPARE(s.sum(), 0.0);
111 QCOMPARE(countSpy.count(), 6);
111 QCOMPARE(countSpy.count(), 6);
112 QCOMPARE(sumSpy.count(), 6);
112 QCOMPARE(sumSpy.count(), 6);
113
113
114 s.setPieSize(-1.0);
114 s.setPieSize(-1.0);
115 QCOMPARE(s.pieSize(), 0.0);
115 QCOMPARE(s.pieSize(), 0.0);
116 s.setPieSize(0.0);
116 s.setPieSize(0.0);
117 s.setPieSize(0.9);
117 s.setPieSize(0.9);
118 s.setPieSize(2.0);
118 s.setPieSize(2.0);
119 QCOMPARE(s.pieSize(), 1.0);
119 QCOMPARE(s.pieSize(), 1.0);
120 QCOMPARE(sizeSpy.count(), 3);
120 QCOMPARE(sizeSpy.count(), 3);
121
121
122 s.setPieStartAngle(0);
122 s.setPieStartAngle(0);
123 s.setPieStartAngle(-180);
123 s.setPieStartAngle(-180);
124 s.setPieStartAngle(180);
124 s.setPieStartAngle(180);
125 QCOMPARE(startAngleSpy.count(), 2);
125 QCOMPARE(startAngleSpy.count(), 2);
126
126
127 s.setPieEndAngle(360);
127 s.setPieEndAngle(360);
128 s.setPieEndAngle(-180);
128 s.setPieEndAngle(-180);
129 s.setPieEndAngle(180);
129 s.setPieEndAngle(180);
130 QCOMPARE(endAngleSpy.count(), 2);
130 QCOMPARE(endAngleSpy.count(), 2);
131
131
132 s.setHorizontalPosition(0.5);
132 s.setHorizontalPosition(0.5);
133 s.setHorizontalPosition(-1.0);
133 s.setHorizontalPosition(-1.0);
134 QCOMPARE(s.horizontalPosition(), 0.0);
134 QCOMPARE(s.horizontalPosition(), 0.0);
135 s.setHorizontalPosition(1.0);
135 s.setHorizontalPosition(1.0);
136 s.setHorizontalPosition(2.0);
136 s.setHorizontalPosition(2.0);
137 QCOMPARE(s.horizontalPosition(), 1.0);
137 QCOMPARE(s.horizontalPosition(), 1.0);
138 QCOMPARE(horPosSpy.count(), 2);
138 QCOMPARE(horPosSpy.count(), 2);
139
139
140 s.setVerticalPosition(0.5);
140 s.setVerticalPosition(0.5);
141 s.setVerticalPosition(-1.0);
141 s.setVerticalPosition(-1.0);
142 QCOMPARE(s.verticalPosition(), 0.0);
142 QCOMPARE(s.verticalPosition(), 0.0);
143 s.setVerticalPosition(1.0);
143 s.setVerticalPosition(1.0);
144 s.setVerticalPosition(2.0);
144 s.setVerticalPosition(2.0);
145 QCOMPARE(s.verticalPosition(), 1.0);
145 QCOMPARE(s.verticalPosition(), 1.0);
146 QCOMPARE(verPosSpy.count(), 2);
146 QCOMPARE(verPosSpy.count(), 2);
147 }
147 }
148
148
149 void tst_qpieseries::append()
149 void tst_qpieseries::append()
150 {
150 {
151 QPieSeries s;
151 QPieSeries s;
152
152
153 // append pointer
153 // append pointer
154 QPieSlice *slice1 = 0;
154 QPieSlice *slice1 = 0;
155 QVERIFY(!s.append(slice1));
155 QVERIFY(!s.append(slice1));
156 slice1 = new QPieSlice("slice 1", 1);
156 slice1 = new QPieSlice("slice 1", 1);
157 QVERIFY(s.append(slice1));
157 QVERIFY(s.append(slice1));
158 QVERIFY(!s.append(slice1));
158 QVERIFY(!s.append(slice1));
159 QCOMPARE(s.count(), 1);
159 QCOMPARE(s.count(), 1);
160
160
161 // append pointer list
161 // append pointer list
162 QList<QPieSlice *> list;
162 QList<QPieSlice *> list;
163 QVERIFY(!s.append(list));
163 QVERIFY(!s.append(list));
164 list << (QPieSlice *) 0;
164 list << (QPieSlice *) 0;
165 QVERIFY(!s.append(list));
165 QVERIFY(!s.append(list));
166 list.clear();
166 list.clear();
167 list << new QPieSlice("slice 2", 2);
167 list << new QPieSlice("slice 2", 2);
168 list << new QPieSlice("slice 3", 3);
168 list << new QPieSlice("slice 3", 3);
169 QVERIFY(s.append(list));
169 QVERIFY(s.append(list));
170 QVERIFY(!s.append(list));
170 QVERIFY(!s.append(list));
171 QCOMPARE(s.count(), 3);
171 QCOMPARE(s.count(), 3);
172
172
173 // append operator
173 // append operator
174 s << new QPieSlice("slice 4", 4);
174 s << new QPieSlice("slice 4", 4);
175 s << slice1; // fails because already added
175 s << slice1; // fails because already added
176 QCOMPARE(s.count(), 4);
176 QCOMPARE(s.count(), 4);
177
177
178 // append with params
178 // append with params
179 QPieSlice *slice5 = s.append("slice 5", 5);
179 QPieSlice *slice5 = s.append("slice 5", 5);
180 QVERIFY(slice5 != 0);
180 QVERIFY(slice5 != 0);
181 QCOMPARE(slice5->value(), 5.0);
181 QCOMPARE(slice5->value(), 5.0);
182 QCOMPARE(slice5->label(), QString("slice 5"));
182 QCOMPARE(slice5->label(), QString("slice 5"));
183 QCOMPARE(s.count(), 5);
183 QCOMPARE(s.count(), 5);
184
184
185 // check slices
185 // check slices
186 QVERIFY(!s.isEmpty());
186 QVERIFY(!s.isEmpty());
187 for (int i=0; i<s.count(); i++) {
187 for (int i=0; i<s.count(); i++) {
188 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
188 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
189 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));
190 }
190 }
191 }
191 }
192
192
193 void tst_qpieseries::insert()
193 void tst_qpieseries::insert()
194 {
194 {
195 QPieSeries s;
195 QPieSeries s;
196
196
197 // insert one slice
197 // insert one slice
198 QPieSlice *slice1 = 0;
198 QPieSlice *slice1 = 0;
199 QVERIFY(!s.insert(0, slice1));
199 QVERIFY(!s.insert(0, slice1));
200 slice1 = new QPieSlice("slice 1", 1);
200 slice1 = new QPieSlice("slice 1", 1);
201 QVERIFY(!s.insert(-1, slice1));
201 QVERIFY(!s.insert(-1, slice1));
202 QVERIFY(!s.insert(5, slice1));
202 QVERIFY(!s.insert(5, slice1));
203 QVERIFY(s.insert(0, slice1));
203 QVERIFY(s.insert(0, slice1));
204 QVERIFY(!s.insert(0, slice1));
204 QVERIFY(!s.insert(0, slice1));
205 QCOMPARE(s.count(), 1);
205 QCOMPARE(s.count(), 1);
206
206
207 // add some more slices
207 // add some more slices
208 s.append("slice 2", 2);
208 s.append("slice 2", 2);
209 s.append("slice 4", 4);
209 s.append("slice 4", 4);
210 QCOMPARE(s.count(), 3);
210 QCOMPARE(s.count(), 3);
211
211
212 // insert between slices
212 // insert between slices
213 s.insert(2, new QPieSlice("slice 3", 3));
213 s.insert(2, new QPieSlice("slice 3", 3));
214 QCOMPARE(s.count(), 4);
214 QCOMPARE(s.count(), 4);
215
215
216 // check slices
216 // check slices
217 for (int i=0; i<s.count(); i++) {
217 for (int i=0; i<s.count(); i++) {
218 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
218 QCOMPARE(s.slices().at(i)->value(), (qreal) i+1);
219 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));
220 }
220 }
221 }
221 }
222
222
223 void tst_qpieseries::remove()
223 void tst_qpieseries::remove()
224 {
224 {
225 QPieSeries s;
225 QPieSeries s;
226
226
227 // add some slices
227 // add some slices
228 QPieSlice *slice1 = s.append("slice 1", 1);
228 QPieSlice *slice1 = s.append("slice 1", 1);
229 QPieSlice *slice2 = s.append("slice 2", 2);
229 QPieSlice *slice2 = s.append("slice 2", 2);
230 QPieSlice *slice3 = s.append("slice 3", 3);
230 QPieSlice *slice3 = s.append("slice 3", 3);
231 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
231 QSignalSpy spy1(slice1, SIGNAL(destroyed()));
232 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
232 QSignalSpy spy2(slice2, SIGNAL(destroyed()));
233 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
233 QSignalSpy spy3(slice3, SIGNAL(destroyed()));
234 QCOMPARE(s.count(), 3);
234 QCOMPARE(s.count(), 3);
235
235
236 // null pointer remove
236 // null pointer remove
237 QVERIFY(!s.remove(0));
237 QVERIFY(!s.remove(0));
238
238
239 // remove first
239 // remove first
240 QVERIFY(s.remove(slice1));
240 QVERIFY(s.remove(slice1));
241 QVERIFY(!s.remove(slice1));
241 QVERIFY(!s.remove(slice1));
242 QCOMPARE(s.count(), 2);
242 QCOMPARE(s.count(), 2);
243 QCOMPARE(s.slices().at(0)->label(), slice2->label());
243 QCOMPARE(s.slices().at(0)->label(), slice2->label());
244
244
245 // remove all
245 // remove all
246 s.clear();
246 s.clear();
247 QVERIFY(s.isEmpty());
247 QVERIFY(s.isEmpty());
248 QVERIFY(s.slices().isEmpty());
248 QVERIFY(s.slices().isEmpty());
249 QCOMPARE(s.count(), 0);
249 QCOMPARE(s.count(), 0);
250
250
251 // check that slices were actually destroyed
251 // check that slices were actually destroyed
252 TRY_COMPARE(spy1.count(), 1);
252 TRY_COMPARE(spy1.count(), 1);
253 TRY_COMPARE(spy2.count(), 1);
253 TRY_COMPARE(spy2.count(), 1);
254 TRY_COMPARE(spy3.count(), 1);
254 TRY_COMPARE(spy3.count(), 1);
255 }
255 }
256
256
257 void tst_qpieseries::calculatedValues()
257 void tst_qpieseries::calculatedValues()
258 {
258 {
259 bool ok;
259 bool ok;
260 QPieSeries s;
260 QPieSeries s;
261
261
262 QPieSlice *slice1 = new QPieSlice("slice 1", 1);
262 QPieSlice *slice1 = new QPieSlice("slice 1", 1);
263 QSignalSpy calculatedDataSpy(slice1, SIGNAL(calculatedDataChanged()));
263 QSignalSpy percentageSpy(slice1, SIGNAL(percentageChanged()));
264 QSignalSpy startAngleSpy(slice1, SIGNAL(startAngleChanged()));
265 QSignalSpy angleSpanSpy(slice1, SIGNAL(angleSpanChanged()));
264
266
265 // add a slice
267 // add a slice
266 s.append(slice1);
268 s.append(slice1);
267 verifyCalculatedData(s, &ok);
269 verifyCalculatedData(s, &ok);
268 if (!ok)
270 if (!ok)
269 return;
271 return;
270 QCOMPARE(calculatedDataSpy.count(), 1);
272 QCOMPARE(percentageSpy.count(), 1);
273 QCOMPARE(startAngleSpy.count(), 0);
274 QCOMPARE(angleSpanSpy.count(), 1);
271
275
272 // add some more slices
276 // add some more slices
273 QList<QPieSlice *> list;
277 QList<QPieSlice *> list;
274 list << new QPieSlice("slice 2", 2);
278 list << new QPieSlice("slice 2", 2);
275 list << new QPieSlice("slice 3", 3);
279 list << new QPieSlice("slice 3", 3);
276 s.append(list);
280 s.append(list);
277 verifyCalculatedData(s, &ok);
281 verifyCalculatedData(s, &ok);
278 if (!ok)
282 if (!ok)
279 return;
283 return;
280 QCOMPARE(calculatedDataSpy.count(), 2);
284 QCOMPARE(percentageSpy.count(), 2);
285 QCOMPARE(startAngleSpy.count(), 0);
286 QCOMPARE(angleSpanSpy.count(), 2);
281
287
282 // remove a slice
288 // remove a slice
283 s.remove(list.first()); // remove slice 2
289 s.remove(list.first()); // remove slice 2
284 verifyCalculatedData(s, &ok);
290 verifyCalculatedData(s, &ok);
285 if (!ok)
291 if (!ok)
286 return;
292 return;
287 QCOMPARE(calculatedDataSpy.count(), 3);
293 QCOMPARE(percentageSpy.count(), 3);
294 QCOMPARE(startAngleSpy.count(), 0);
295 QCOMPARE(angleSpanSpy.count(), 3);
288
296
289 // insert a slice
297 // insert a slice
290 s.insert(0, new QPieSlice("Slice 4", 4));
298 s.insert(0, new QPieSlice("Slice 4", 4));
291 verifyCalculatedData(s, &ok);
299 verifyCalculatedData(s, &ok);
292 if (!ok)
300 if (!ok)
293 return;
301 return;
294 QCOMPARE(calculatedDataSpy.count(), 4);
302 QCOMPARE(percentageSpy.count(), 4);
303 QCOMPARE(startAngleSpy.count(), 1);
304 QCOMPARE(angleSpanSpy.count(), 4);
295
305
296 // modify pie angles
306 // modify pie angles
297 s.setPieStartAngle(-90);
307 s.setPieStartAngle(-90);
298 s.setPieEndAngle(90);
308 s.setPieEndAngle(90);
299 verifyCalculatedData(s, &ok);
309 verifyCalculatedData(s, &ok);
300 if (!ok)
310 if (!ok)
301 return;
311 return;
302 QCOMPARE(calculatedDataSpy.count(), 6);
312 QCOMPARE(percentageSpy.count(), 4);
313 QCOMPARE(startAngleSpy.count(), 3);
314 QCOMPARE(angleSpanSpy.count(), 6);
303
315
304 // clear all
316 // clear all
305 s.clear();
317 s.clear();
306 verifyCalculatedData(s, &ok);
318 verifyCalculatedData(s, &ok);
319 QCOMPARE(percentageSpy.count(), 4);
320 QCOMPARE(startAngleSpy.count(), 3);
321 QCOMPARE(angleSpanSpy.count(), 6);
307 }
322 }
308
323
309 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
324 void tst_qpieseries::verifyCalculatedData(const QPieSeries &series, bool *ok)
310 {
325 {
311 *ok = false;
326 *ok = false;
312
327
313 qreal sum = 0;
328 qreal sum = 0;
314 foreach (const QPieSlice *slice, series.slices())
329 foreach (const QPieSlice *slice, series.slices())
315 sum += slice->value();
330 sum += slice->value();
316 QCOMPARE(series.sum(), sum);
331 QCOMPARE(series.sum(), sum);
317
332
318 qreal startAngle = series.pieStartAngle();
333 qreal startAngle = series.pieStartAngle();
319 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
334 qreal pieAngleSpan = series.pieEndAngle() - series.pieStartAngle();
320 foreach (const QPieSlice *slice, series.slices()) {
335 foreach (const QPieSlice *slice, series.slices()) {
321 qreal ratio = slice->value() / sum;
336 qreal ratio = slice->value() / sum;
322 qreal sliceSpan = pieAngleSpan * ratio;
337 qreal sliceSpan = pieAngleSpan * ratio;
323 QCOMPARE(slice->startAngle(), startAngle);
338 QCOMPARE(slice->startAngle(), startAngle);
324 QCOMPARE(slice->endAngle(), startAngle + sliceSpan);
339 QCOMPARE(slice->angleSpan(), sliceSpan);
325 QCOMPARE(slice->percentage(), ratio);
340 QCOMPARE(slice->percentage(), ratio);
326 startAngle += sliceSpan;
341 startAngle += sliceSpan;
327 }
342 }
328
343
329 if (!series.isEmpty())
344 if (!series.isEmpty())
330 QCOMPARE(series.slices().last()->endAngle(), series.pieEndAngle());
345 QCOMPARE(series.slices().last()->startAngle() + series.slices().last()->angleSpan(), series.pieEndAngle());
331
346
332 *ok = true;
347 *ok = true;
333 }
348 }
334
349
335
350
336 void tst_qpieseries::clickedSignal()
351 void tst_qpieseries::clickedSignal()
337 {
352 {
338 // create a pie series
353 // create a pie series
339 QPieSeries *series = new QPieSeries();
354 QPieSeries *series = new QPieSeries();
340 QPieSlice *s1 = series->append("slice 1", 1);
355 QPieSlice *s1 = series->append("slice 1", 1);
341 QPieSlice *s2 = series->append("slice 2", 1);
356 QPieSlice *s2 = series->append("slice 2", 1);
342 QPieSlice *s3 = series->append("slice 3", 1);
357 QPieSlice *s3 = series->append("slice 3", 1);
343 QPieSlice *s4 = series->append("slice 4", 1);
358 QPieSlice *s4 = series->append("slice 4", 1);
344 QSignalSpy clickSpy(series, SIGNAL(clicked(QPieSlice*)));
359 QSignalSpy clickSpy(series, SIGNAL(clicked(QPieSlice*)));
345
360
346 // add series to the chart
361 // add series to the chart
347 QChartView view(new QChart());
362 QChartView view(new QChart());
348 view.chart()->legend()->setVisible(false);
363 view.chart()->legend()->setVisible(false);
349 view.resize(200, 200);
364 view.resize(200, 200);
350 view.chart()->addSeries(series);
365 view.chart()->addSeries(series);
351 view.show();
366 view.show();
352 QTest::qWaitForWindowShown(&view);
367 QTest::qWaitForWindowShown(&view);
353
368
354 // if you devide the chart in four equal tiles these
369 // if you devide the chart in four equal tiles these
355 // are the center points of those tiles
370 // are the center points of those tiles
356 QPoint p1(90.25, 90);
371 QPoint p1(90.25, 90);
357 QPoint p2(150, 90);
372 QPoint p2(150, 90);
358 QPoint p3(90, 150);
373 QPoint p3(90, 150);
359 QPoint p4(150, 150);
374 QPoint p4(150, 150);
360
375
361 QPoint center(120, 120);
376 QPoint center(120, 120);
362
377
363 series->setPieSize(1.0);
378 series->setPieSize(1.0);
364 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
379 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
365 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
380 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
366 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
381 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
367 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
382 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
368 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
383 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
369 TRY_COMPARE(clickSpy.count(), 5); // all hit
384 TRY_COMPARE(clickSpy.count(), 5); // all hit
370 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(0).at(0)), s4);
385 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(0).at(0)), s4);
371 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(1).at(0)), s1);
386 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(1).at(0)), s1);
372 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(2).at(0)), s3);
387 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(2).at(0)), s3);
373 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(3).at(0)), s2);
388 QCOMPARE(qvariant_cast<QPieSlice*>(clickSpy.at(3).at(0)), s2);
374 clickSpy.clear();
389 clickSpy.clear();
375
390
376 series->setPieSize(0.5);
391 series->setPieSize(0.5);
377 series->setVerticalPosition(0.25);
392 series->setVerticalPosition(0.25);
378 series->setHorizontalPosition(0.25);
393 series->setHorizontalPosition(0.25);
379 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1); // hits
394 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1); // hits
380 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
395 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
381 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
396 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
382 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
397 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
383 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
398 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
384 TRY_COMPARE(clickSpy.count(), 1);
399 TRY_COMPARE(clickSpy.count(), 1);
385 clickSpy.clear();
400 clickSpy.clear();
386
401
387 series->setVerticalPosition(0.25);
402 series->setVerticalPosition(0.25);
388 series->setHorizontalPosition(0.75);
403 series->setHorizontalPosition(0.75);
389 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
404 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
390 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2); // hits
405 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2); // hits
391 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
406 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
392 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
407 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
393 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
408 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
394 TRY_COMPARE(clickSpy.count(), 1);
409 TRY_COMPARE(clickSpy.count(), 1);
395 clickSpy.clear();
410 clickSpy.clear();
396
411
397 series->setVerticalPosition(0.75);
412 series->setVerticalPosition(0.75);
398 series->setHorizontalPosition(0.25);
413 series->setHorizontalPosition(0.25);
399 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
414 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
400 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
415 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
401 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3); // hits
416 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3); // hits
402 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
417 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4);
403 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
418 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
404 TRY_COMPARE(clickSpy.count(), 1);
419 TRY_COMPARE(clickSpy.count(), 1);
405 clickSpy.clear();
420 clickSpy.clear();
406
421
407 series->setVerticalPosition(0.75);
422 series->setVerticalPosition(0.75);
408 series->setHorizontalPosition(0.75);
423 series->setHorizontalPosition(0.75);
409 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
424 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p1);
410 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
425 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p2);
411 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
426 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p3);
412 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4); // hits
427 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p4); // hits
413 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
428 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, center);
414 TRY_COMPARE(clickSpy.count(), 1);
429 TRY_COMPARE(clickSpy.count(), 1);
415 clickSpy.clear();
430 clickSpy.clear();
416 }
431 }
417
432
418 void tst_qpieseries::hoverSignal()
433 void tst_qpieseries::hoverSignal()
419 {
434 {
420 // create a pie series
435 // create a pie series
421 QPieSeries *series = new QPieSeries();
436 QPieSeries *series = new QPieSeries();
422 series->setPieSize(1.0);
437 series->setPieSize(1.0);
423 QPieSlice *s1 = series->append("slice 1", 1);
438 QPieSlice *s1 = series->append("slice 1", 1);
424 series->append("slice 2", 2);
439 series->append("slice 2", 2);
425 series->append("slice 3", 3);
440 series->append("slice 3", 3);
426
441
427 // add series to the chart
442 // add series to the chart
428 QChartView view(new QChart());
443 QChartView view(new QChart());
429 view.chart()->legend()->setVisible(false);
444 view.chart()->legend()->setVisible(false);
430 view.resize(200, 200);
445 view.resize(200, 200);
431 view.chart()->addSeries(series);
446 view.chart()->addSeries(series);
432 view.show();
447 view.show();
433 QTest::qWaitForWindowShown(&view);
448 QTest::qWaitForWindowShown(&view);
434
449
435 // first move to right top corner
450 // first move to right top corner
436 QTest::mouseMove(view.viewport(), QPoint(200, 0));
451 QTest::mouseMove(view.viewport(), QPoint(200, 0));
437 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
452 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
438
453
439 // move inside the slice
454 // move inside the slice
440 // pie rectangle: QRectF(60,60 121x121)
455 // pie rectangle: QRectF(60,60 121x121)
441 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
456 QSignalSpy hoverSpy(series, SIGNAL(hovered(QPieSlice*,bool)));
442 QTest::mouseMove(view.viewport(), QPoint(139, 85));
457 QTest::mouseMove(view.viewport(), QPoint(139, 85));
443 TRY_COMPARE(hoverSpy.count(), 1);
458 TRY_COMPARE(hoverSpy.count(), 1);
444 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
459 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(0).at(0)), s1);
445 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
460 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(1)), true);
446
461
447 // move outside the slice
462 // move outside the slice
448 QTest::mouseMove(view.viewport(), QPoint(200, 0));
463 QTest::mouseMove(view.viewport(), QPoint(200, 0));
449 TRY_COMPARE(hoverSpy.count(), 2);
464 TRY_COMPARE(hoverSpy.count(), 2);
450 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
465 QCOMPARE(qvariant_cast<QPieSlice*>(hoverSpy.at(1).at(0)), s1);
451 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
466 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(1)), false);
452 }
467 }
453
468
454 QTEST_MAIN(tst_qpieseries)
469 QTEST_MAIN(tst_qpieseries)
455
470
456 #include "tst_qpieseries.moc"
471 #include "tst_qpieseries.moc"
457
472
@@ -1,278 +1,291
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 <tst_definitions.h>
22 #include <tst_definitions.h>
23 #include <qchartview.h>
23 #include <qchartview.h>
24 #include <qchart.h>
24 #include <qchart.h>
25 #include <qpieslice.h>
25 #include <qpieslice.h>
26 #include <qpieseries.h>
26 #include <qpieseries.h>
27
27
28 QTCOMMERCIALCHART_USE_NAMESPACE
28 QTCOMMERCIALCHART_USE_NAMESPACE
29
29
30 class tst_qpieslice : public QObject
30 class tst_qpieslice : public QObject
31 {
31 {
32 Q_OBJECT
32 Q_OBJECT
33
33
34 public slots:
34 public slots:
35 void initTestCase();
35 void initTestCase();
36 void cleanupTestCase();
36 void cleanupTestCase();
37 void init();
37 void init();
38 void cleanup();
38 void cleanup();
39
39
40 private slots:
40 private slots:
41 void construction();
41 void construction();
42 void changedSignals();
42 void changedSignals();
43 void customize();
43 void customize();
44 void mouseClick();
44 void mouseClick();
45 void mouseHover();
45 void mouseHover();
46
46
47 private:
47 private:
48
48
49
49
50 private:
50 private:
51
51
52 };
52 };
53
53
54 void tst_qpieslice::initTestCase()
54 void tst_qpieslice::initTestCase()
55 {
55 {
56 }
56 }
57
57
58 void tst_qpieslice::cleanupTestCase()
58 void tst_qpieslice::cleanupTestCase()
59 {
59 {
60 }
60 }
61
61
62 void tst_qpieslice::init()
62 void tst_qpieslice::init()
63 {
63 {
64
64
65 }
65 }
66
66
67 void tst_qpieslice::cleanup()
67 void tst_qpieslice::cleanup()
68 {
68 {
69
69
70 }
70 }
71
71
72 void tst_qpieslice::construction()
72 void tst_qpieslice::construction()
73 {
73 {
74 // no params
74 // no params
75 QPieSlice slice1;
75 QPieSlice slice1;
76 QCOMPARE(slice1.value(), 0.0);
76 QCOMPARE(slice1.value(), 0.0);
77 QVERIFY(slice1.label().isEmpty());
77 QVERIFY(slice1.label().isEmpty());
78 QVERIFY(!slice1.isLabelVisible());
78 QVERIFY(!slice1.isLabelVisible());
79 QVERIFY(!slice1.isExploded());
79 QVERIFY(!slice1.isExploded());
80 QCOMPARE(slice1.pen(), QPen());
80 QCOMPARE(slice1.pen(), QPen());
81 QCOMPARE(slice1.brush(), QBrush());
81 QCOMPARE(slice1.brush(), QBrush());
82 QCOMPARE(slice1.labelPen(), QPen());
82 QCOMPARE(slice1.labelPen(), QPen());
83 QCOMPARE(slice1.labelFont(), QFont());
83 QCOMPARE(slice1.labelFont(), QFont());
84 QCOMPARE(slice1.labelArmLengthFactor(), 0.15); // default value
84 QCOMPARE(slice1.labelArmLengthFactor(), 0.15); // default value
85 QCOMPARE(slice1.explodeDistanceFactor(), 0.15); // default value
85 QCOMPARE(slice1.explodeDistanceFactor(), 0.15); // default value
86 QCOMPARE(slice1.percentage(), 0.0);
86 QCOMPARE(slice1.percentage(), 0.0);
87 QCOMPARE(slice1.startAngle(), 0.0);
87 QCOMPARE(slice1.startAngle(), 0.0);
88 QCOMPARE(slice1.endAngle(), 0.0);
88 QCOMPARE(slice1.angleSpan(), 0.0);
89
89
90 // value and label params
90 // value and label params
91 QPieSlice slice2("foobar", 1.0);
91 QPieSlice slice2("foobar", 1.0);
92 QCOMPARE(slice2.value(), 1.0);
92 QCOMPARE(slice2.value(), 1.0);
93 QCOMPARE(slice2.label(), QString("foobar"));
93 QCOMPARE(slice2.label(), QString("foobar"));
94 QVERIFY(!slice2.isLabelVisible());
94 QVERIFY(!slice2.isLabelVisible());
95 QVERIFY(!slice2.isExploded());
95 QVERIFY(!slice2.isExploded());
96 QCOMPARE(slice2.pen(), QPen());
96 QCOMPARE(slice2.pen(), QPen());
97 QCOMPARE(slice2.brush(), QBrush());
97 QCOMPARE(slice2.brush(), QBrush());
98 QCOMPARE(slice2.labelPen(), QPen());
98 QCOMPARE(slice2.labelPen(), QPen());
99 QCOMPARE(slice2.labelFont(), QFont());
99 QCOMPARE(slice2.labelFont(), QFont());
100 QCOMPARE(slice2.labelArmLengthFactor(), 0.15); // default value
100 QCOMPARE(slice2.labelArmLengthFactor(), 0.15); // default value
101 QCOMPARE(slice2.explodeDistanceFactor(), 0.15); // default value
101 QCOMPARE(slice2.explodeDistanceFactor(), 0.15); // default value
102 QCOMPARE(slice2.percentage(), 0.0);
102 QCOMPARE(slice2.percentage(), 0.0);
103 QCOMPARE(slice2.startAngle(), 0.0);
103 QCOMPARE(slice2.startAngle(), 0.0);
104 QCOMPARE(slice2.endAngle(), 0.0);
104 QCOMPARE(slice2.angleSpan(), 0.0);
105 }
105 }
106
106
107 void tst_qpieslice::changedSignals()
107 void tst_qpieslice::changedSignals()
108 {
108 {
109 QPieSlice slice;
109 QPieSlice slice;
110
110
111 QSignalSpy valueSpy(&slice, SIGNAL(valueChanged()));
111 QSignalSpy valueSpy(&slice, SIGNAL(valueChanged()));
112 QSignalSpy labelSpy(&slice, SIGNAL(labelChanged()));
112 QSignalSpy labelSpy(&slice, SIGNAL(labelChanged()));
113 QSignalSpy appearanceSpy(&slice, SIGNAL(appearanceChanged()));
113 QSignalSpy explodedSpy(&slice, SIGNAL(explodedChanged()));
114 // calculatedDataChanged signal is tested at tst_qpieseries::calculatedValues()
114 QSignalSpy penSpy(&slice, SIGNAL(penChanged()));
115 QSignalSpy brushSpy(&slice, SIGNAL(brushChanged()));
116 QSignalSpy labelPenSpy(&slice, SIGNAL(labelPenChanged()));
117 QSignalSpy labelFontSpy(&slice, SIGNAL(labelFontChanged()));
118 QSignalSpy labelArmLengthFactorSpy(&slice, SIGNAL(labelArmLengthFactorChanged()));
119 QSignalSpy explodeDistanceFactorSpy(&slice, SIGNAL(explodeDistanceFactorChanged()));
120
121 // percentageChanged(), startAngleChanged() and angleSpanChanged() signals tested at tst_qpieseries::calculatedValues()
115
122
116 // set everything twice to see we do not get unnecessary signals
123 // set everything twice to see we do not get unnecessary signals
117 slice.setValue(1);
124 slice.setValue(1);
118 slice.setValue(1);
125 slice.setValue(1);
119 slice.setLabel("foobar");
126 slice.setLabel("foobar");
120 slice.setLabel("foobar");
127 slice.setLabel("foobar");
121 slice.setLabelVisible();
128 slice.setLabelVisible();
122 slice.setLabelVisible();
129 slice.setLabelVisible();
123 slice.setExploded();
130 slice.setExploded();
124 slice.setExploded();
131 slice.setExploded();
125 slice.setPen(QPen(Qt::red));
132 slice.setPen(QPen(Qt::red));
126 slice.setPen(QPen(Qt::red));
133 slice.setPen(QPen(Qt::red));
127 slice.setBrush(QBrush(Qt::red));
134 slice.setBrush(QBrush(Qt::red));
128 slice.setBrush(QBrush(Qt::red));
135 slice.setBrush(QBrush(Qt::red));
129 slice.setLabelPen(QPen(Qt::green));
136 slice.setLabelPen(QPen(Qt::green));
130 slice.setLabelPen(QPen(Qt::green));
137 slice.setLabelPen(QPen(Qt::green));
131 slice.setLabelFont(QFont("Tahoma"));
138 slice.setLabelFont(QFont("Tahoma"));
132 slice.setLabelFont(QFont("Tahoma"));
139 slice.setLabelFont(QFont("Tahoma"));
133 slice.setLabelArmLengthFactor(0.1);
140 slice.setLabelArmLengthFactor(0.1);
134 slice.setLabelArmLengthFactor(0.1);
141 slice.setLabelArmLengthFactor(0.1);
135 slice.setExplodeDistanceFactor(0.1);
142 slice.setExplodeDistanceFactor(0.1);
136 slice.setExplodeDistanceFactor(0.1);
143 slice.setExplodeDistanceFactor(0.1);
137
144
138 TRY_COMPARE(valueSpy.count(), 1);
145 TRY_COMPARE(valueSpy.count(), 1);
139 TRY_COMPARE(labelSpy.count(), 1);
146 TRY_COMPARE(labelSpy.count(), 1);
140 TRY_COMPARE(appearanceSpy.count(), 8);
147 TRY_COMPARE(explodedSpy.count(), 1);
148 TRY_COMPARE(penSpy.count(), 1);
149 TRY_COMPARE(brushSpy.count(), 1);
150 TRY_COMPARE(labelPenSpy.count(), 1);
151 TRY_COMPARE(labelFontSpy.count(), 1);
152 TRY_COMPARE(labelArmLengthFactorSpy.count(), 1);
153 TRY_COMPARE(explodeDistanceFactorSpy.count(), 1);
141 }
154 }
142
155
143 void tst_qpieslice::customize()
156 void tst_qpieslice::customize()
144 {
157 {
145 // create a pie series
158 // create a pie series
146 QPieSeries *series = new QPieSeries();
159 QPieSeries *series = new QPieSeries();
147 QPieSlice *s1 = series->append("slice 1", 1);
160 QPieSlice *s1 = series->append("slice 1", 1);
148 QPieSlice *s2 = series->append("slice 2", 2);
161 QPieSlice *s2 = series->append("slice 2", 2);
149 series->append("slice 3", 3);
162 series->append("slice 3", 3);
150
163
151 // customize a slice
164 // customize a slice
152 QPen p1(Qt::red);
165 QPen p1(Qt::red);
153 s1->setPen(p1);
166 s1->setPen(p1);
154 QBrush b1(Qt::red);
167 QBrush b1(Qt::red);
155 s1->setBrush(b1);
168 s1->setBrush(b1);
156 s1->setLabelPen(p1);
169 s1->setLabelPen(p1);
157 QFont f1("Consolas");
170 QFont f1("Consolas");
158 s1->setLabelFont(f1);
171 s1->setLabelFont(f1);
159
172
160 // add series to the chart
173 // add series to the chart
161 QChartView view(new QChart());
174 QChartView view(new QChart());
162 view.resize(200, 200);
175 view.resize(200, 200);
163 view.chart()->addSeries(series);
176 view.chart()->addSeries(series);
164 view.show();
177 view.show();
165 QTest::qWaitForWindowShown(&view);
178 QTest::qWaitForWindowShown(&view);
166 //QTest::qWait(1000);
179 //QTest::qWait(1000);
167
180
168 // check that customizations persist
181 // check that customizations persist
169 QCOMPARE(s1->pen(), p1);
182 QCOMPARE(s1->pen(), p1);
170 QCOMPARE(s1->brush(), b1);
183 QCOMPARE(s1->brush(), b1);
171 QCOMPARE(s1->labelPen(), p1);
184 QCOMPARE(s1->labelPen(), p1);
172 QCOMPARE(s1->labelFont(), f1);
185 QCOMPARE(s1->labelFont(), f1);
173
186
174 // remove a slice
187 // remove a slice
175 series->remove(s2);
188 series->remove(s2);
176 QCOMPARE(s1->pen(), p1);
189 QCOMPARE(s1->pen(), p1);
177 QCOMPARE(s1->brush(), b1);
190 QCOMPARE(s1->brush(), b1);
178 QCOMPARE(s1->labelPen(), p1);
191 QCOMPARE(s1->labelPen(), p1);
179 QCOMPARE(s1->labelFont(), f1);
192 QCOMPARE(s1->labelFont(), f1);
180
193
181 // add a slice
194 // add a slice
182 series->append("slice 4", 4);
195 series->append("slice 4", 4);
183 QCOMPARE(s1->pen(), p1);
196 QCOMPARE(s1->pen(), p1);
184 QCOMPARE(s1->brush(), b1);
197 QCOMPARE(s1->brush(), b1);
185 QCOMPARE(s1->labelPen(), p1);
198 QCOMPARE(s1->labelPen(), p1);
186 QCOMPARE(s1->labelFont(), f1);
199 QCOMPARE(s1->labelFont(), f1);
187
200
188 // insert a slice
201 // insert a slice
189 series->insert(0, new QPieSlice("slice 5", 5));
202 series->insert(0, new QPieSlice("slice 5", 5));
190 QCOMPARE(s1->pen(), p1);
203 QCOMPARE(s1->pen(), p1);
191 QCOMPARE(s1->brush(), b1);
204 QCOMPARE(s1->brush(), b1);
192 QCOMPARE(s1->labelPen(), p1);
205 QCOMPARE(s1->labelPen(), p1);
193 QCOMPARE(s1->labelFont(), f1);
206 QCOMPARE(s1->labelFont(), f1);
194
207
195 // change theme
208 // change theme
196 // theme will overwrite customizations
209 // theme will overwrite customizations
197 view.chart()->setTheme(QChart::ChartThemeHighContrast);
210 view.chart()->setTheme(QChart::ChartThemeHighContrast);
198 QVERIFY(s1->pen() != p1);
211 QVERIFY(s1->pen() != p1);
199 QVERIFY(s1->brush() != b1);
212 QVERIFY(s1->brush() != b1);
200 QVERIFY(s1->labelPen() != p1);
213 QVERIFY(s1->labelPen() != p1);
201 QVERIFY(s1->labelFont() != f1);
214 QVERIFY(s1->labelFont() != f1);
202 }
215 }
203
216
204 void tst_qpieslice::mouseClick()
217 void tst_qpieslice::mouseClick()
205 {
218 {
206 // create a pie series
219 // create a pie series
207 QPieSeries *series = new QPieSeries();
220 QPieSeries *series = new QPieSeries();
208 series->setPieSize(1.0);
221 series->setPieSize(1.0);
209 QPieSlice *s1 = series->append("slice 1", 1);
222 QPieSlice *s1 = series->append("slice 1", 1);
210 QPieSlice *s2 = series->append("slice 2", 2);
223 QPieSlice *s2 = series->append("slice 2", 2);
211 QPieSlice *s3 = series->append("slice 3", 3);
224 QPieSlice *s3 = series->append("slice 3", 3);
212 QSignalSpy clickSpy1(s1, SIGNAL(clicked()));
225 QSignalSpy clickSpy1(s1, SIGNAL(clicked()));
213 QSignalSpy clickSpy2(s2, SIGNAL(clicked()));
226 QSignalSpy clickSpy2(s2, SIGNAL(clicked()));
214 QSignalSpy clickSpy3(s3, SIGNAL(clicked()));
227 QSignalSpy clickSpy3(s3, SIGNAL(clicked()));
215
228
216 // add series to the chart
229 // add series to the chart
217 QChartView view(new QChart());
230 QChartView view(new QChart());
218 view.chart()->legend()->setVisible(false);
231 view.chart()->legend()->setVisible(false);
219 view.resize(200, 200);
232 view.resize(200, 200);
220 view.chart()->addSeries(series);
233 view.chart()->addSeries(series);
221 view.show();
234 view.show();
222 QTest::qWaitForWindowShown(&view);
235 QTest::qWaitForWindowShown(&view);
223
236
224 // simulate clicks
237 // simulate clicks
225 // pie rectangle: QRectF(60,60 121x121)
238 // pie rectangle: QRectF(60,60 121x121)
226 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(139, 85)); // inside slice 1
239 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(139, 85)); // inside slice 1
227 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(146, 136)); // inside slice 2
240 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(146, 136)); // inside slice 2
228 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(91, 119)); // inside slice 3
241 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(91, 119)); // inside slice 3
229 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(70, 70)); // inside pie rectangle but not inside a slice
242 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(70, 70)); // inside pie rectangle but not inside a slice
230 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(170, 170)); // inside pie rectangle but not inside a slice
243 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, QPoint(170, 170)); // inside pie rectangle but not inside a slice
231 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
244 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
232 QCOMPARE(clickSpy1.count(), 1);
245 QCOMPARE(clickSpy1.count(), 1);
233 QCOMPARE(clickSpy2.count(), 1);
246 QCOMPARE(clickSpy2.count(), 1);
234 QCOMPARE(clickSpy3.count(), 1);
247 QCOMPARE(clickSpy3.count(), 1);
235 }
248 }
236
249
237 void tst_qpieslice::mouseHover()
250 void tst_qpieslice::mouseHover()
238 {
251 {
239 // create a pie series
252 // create a pie series
240 QPieSeries *series = new QPieSeries();
253 QPieSeries *series = new QPieSeries();
241 series->setPieSize(1.0);
254 series->setPieSize(1.0);
242 QPieSlice *s1 = series->append("slice 1", 1);
255 QPieSlice *s1 = series->append("slice 1", 1);
243 series->append("slice 2", 2);
256 series->append("slice 2", 2);
244 series->append("slice 3", 3);
257 series->append("slice 3", 3);
245
258
246 // add series to the chart
259 // add series to the chart
247 QChartView view(new QChart());
260 QChartView view(new QChart());
248 view.chart()->legend()->setVisible(false);
261 view.chart()->legend()->setVisible(false);
249 view.resize(200, 200);
262 view.resize(200, 200);
250 view.chart()->addSeries(series);
263 view.chart()->addSeries(series);
251 view.show();
264 view.show();
252 QTest::qWaitForWindowShown(&view);
265 QTest::qWaitForWindowShown(&view);
253
266
254 // first move to right top corner
267 // first move to right top corner
255 QTest::mouseMove(view.viewport(), QPoint(200, 0));
268 QTest::mouseMove(view.viewport(), QPoint(200, 0));
256 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
269 QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
257
270
258 // move inside slice rectangle but NOT the actual slice
271 // move inside slice rectangle but NOT the actual slice
259 // pie rectangle: QRectF(60,60 121x121)
272 // pie rectangle: QRectF(60,60 121x121)
260 QSignalSpy hoverSpy(s1, SIGNAL(hovered(bool)));
273 QSignalSpy hoverSpy(s1, SIGNAL(hovered(bool)));
261 QTest::mouseMove(view.viewport(), QPoint(170, 70));
274 QTest::mouseMove(view.viewport(), QPoint(170, 70));
262 TRY_COMPARE(hoverSpy.count(), 0);
275 TRY_COMPARE(hoverSpy.count(), 0);
263
276
264 // move inside the slice
277 // move inside the slice
265 QTest::mouseMove(view.viewport(), QPoint(139, 85));
278 QTest::mouseMove(view.viewport(), QPoint(139, 85));
266 TRY_COMPARE(hoverSpy.count(), 1);
279 TRY_COMPARE(hoverSpy.count(), 1);
267 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(0)), true);
280 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(0).at(0)), true);
268
281
269 // move outside the slice
282 // move outside the slice
270 QTest::mouseMove(view.viewport(), QPoint(200, 0));
283 QTest::mouseMove(view.viewport(), QPoint(200, 0));
271 TRY_COMPARE(hoverSpy.count(), 2);
284 TRY_COMPARE(hoverSpy.count(), 2);
272 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(0)), false);
285 QCOMPARE(qvariant_cast<bool>(hoverSpy.at(1).at(0)), false);
273 }
286 }
274
287
275 QTEST_MAIN(tst_qpieslice)
288 QTEST_MAIN(tst_qpieslice)
276
289
277 #include "tst_qpieslice.moc"
290 #include "tst_qpieslice.moc"
278
291
General Comments 0
You need to be logged in to leave comments. Login now