##// END OF EJS Templates
Fix add/remove animation for pie and apply colors from theme when adding/removing
Jani Honkonen -
r659:7d415c8db783
parent child
Show More
@@ -1,77 +1,107
1 1 #include "piesliceanimation_p.h"
2 2 #include "piechartitem_p.h"
3 3 #include "qpieslice.h"
4 4
5 5 Q_DECLARE_METATYPE(QtCommercialChart::PieSliceLayout)
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 qreal linearPos(qreal start, qreal end, qreal pos)
10 10 {
11 11 return start + ((end - start) * pos);
12 12 }
13 13
14 14 QPointF linearPos(QPointF start, QPointF end, qreal pos)
15 15 {
16 16 qreal x = linearPos(start.x(), end.x(), pos);
17 17 qreal y = linearPos(start.y(), end.y(), pos);
18 18 return QPointF(x, y);
19 19 }
20 20
21 QPen linearPos(QPen start, QPen end, qreal pos)
22 {
23 QColor c;
24 c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
25 c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
26 c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
27 end.setColor(c);
28 return end;
29 }
30
31 QBrush linearPos(QBrush start, QBrush end, qreal pos)
32 {
33 QColor c;
34 c.setRedF(linearPos(start.color().redF(), end.color().redF(), pos));
35 c.setGreenF(linearPos(start.color().greenF(), end.color().greenF(), pos));
36 c.setBlueF(linearPos(start.color().blueF(), end.color().blueF(), pos));
37 end.setColor(c);
38 return end;
39 }
40
21 41 PieSliceAnimation::PieSliceAnimation(PieChartItem *item, QPieSlice *slice)
22 42 :QVariantAnimation(item),
23 43 m_item(item),
24 44 m_slice(slice)
25 45 {
26 46 }
27 47
28 48 PieSliceAnimation::~PieSliceAnimation()
29 49 {
30 50 }
31 51
32 52 void PieSliceAnimation::setValue(const PieSliceLayout &startValue, const PieSliceLayout &endValue)
33 53 {
34 54 if (state() != QAbstractAnimation::Stopped)
35 55 stop();
36 56
57 m_currentValue = startValue;
58
37 59 setKeyValueAt(0.0, qVariantFromValue(startValue));
38 60 setKeyValueAt(1.0, qVariantFromValue(endValue));
39 61 }
40 62
41 63 void PieSliceAnimation::updateValue(const PieSliceLayout &endValue)
42 64 {
43 65 if (state() != QAbstractAnimation::Stopped)
44 66 stop();
45 67
46 setKeyValueAt(0.0, qVariantFromValue(currentSliceValue()));
68 setKeyValueAt(0.0, qVariantFromValue(m_currentValue));
47 69 setKeyValueAt(1.0, qVariantFromValue(endValue));
48 70 }
49 71
50 72 PieSliceLayout PieSliceAnimation::currentSliceValue()
51 73 {
52 return qVariantValue<PieSliceLayout>(currentValue());
74 // NOTE:
75 // We must use an internal current value because QVariantAnimation::currentValue() is updated
76 // before the animation is actually started. So if we get 2 updateValue() calls in a row the currentValue()
77 // will have the end value set from the first call and the second call will interpolate that instead of
78 // the original current value as it was before the first call.
79 return m_currentValue;
53 80 }
54 81
55 82 QVariant PieSliceAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress) const
56 83 {
57 84 PieSliceLayout startValue = qVariantValue<PieSliceLayout>(start);
58 85 PieSliceLayout endValue = qVariantValue<PieSliceLayout>(end);
59 86
60 87 PieSliceLayout result;
61 88 result = endValue;
62 89 result.m_center = linearPos(startValue.m_center, endValue.m_center, progress);
63 90 result.m_radius = linearPos(startValue.m_radius, endValue.m_radius, progress);
64 91 result.m_startAngle = linearPos(startValue.m_startAngle, endValue.m_startAngle, progress);
65 92 result.m_angleSpan = linearPos(startValue.m_angleSpan, endValue.m_angleSpan, progress);
93 result.m_pen = linearPos(startValue.m_pen, endValue.m_pen, progress);
94 result.m_brush = linearPos(startValue.m_brush, endValue.m_brush, progress);
66 95
67 96 return qVariantFromValue(result);
68 97 }
69 98
70 99 void PieSliceAnimation::updateCurrentValue(const QVariant &value)
71 100 {
72 PieSliceLayout layout = qVariantValue<PieSliceLayout>(value);
73 if (state() != QAbstractAnimation::Stopped) //workaround
74 m_item->setLayout(m_slice, layout);
101 if (state() != QAbstractAnimation::Stopped) { //workaround
102 m_currentValue = qVariantValue<PieSliceLayout>(value);
103 m_item->setLayout(m_slice, m_currentValue);
104 }
75 105 }
76 106
77 107 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,32 +1,33
1 1 #ifndef PIESLICEANIMATION_P_H_
2 2 #define PIESLICEANIMATION_P_H_
3 3
4 4 #include "piechartitem_p.h"
5 5 #include <QVariantAnimation>
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 class PieChartItem;
10 10 class QPieSlice;
11 11
12 12 class PieSliceAnimation : public QVariantAnimation
13 13 {
14 14 public:
15 15 PieSliceAnimation(PieChartItem *item, QPieSlice *slice);
16 16 ~PieSliceAnimation();
17 17 void setValue(const PieSliceLayout &startValue, const PieSliceLayout &endValue);
18 18 void updateValue(const PieSliceLayout &endValue);
19 19 PieSliceLayout currentSliceValue();
20 20
21 21 protected:
22 22 QVariant interpolated(const QVariant &start, const QVariant &end, qreal progress) const;
23 23 void updateCurrentValue(const QVariant &value);
24 24
25 25 private:
26 26 PieChartItem *m_item;
27 27 QPieSlice *m_slice;
28 PieSliceLayout m_currentValue;
28 29 };
29 30
30 31 QTCOMMERCIALCHART_END_NAMESPACE
31 32
32 33 #endif
@@ -1,391 +1,391
1 1 #include "qchart.h"
2 2 #include "qchartaxis.h"
3 3 #include "chartpresenter_p.h"
4 4 #include "chartdataset_p.h"
5 5 #include "charttheme_p.h"
6 6 #include "chartanimator_p.h"
7 7 //series
8 8 #include "qbarseries.h"
9 9 #include "qstackedbarseries.h"
10 10 #include "qpercentbarseries.h"
11 11 #include "qlineseries.h"
12 12 #include "qareaseries.h"
13 13 #include "qpieseries.h"
14 14 #include "qscatterseries.h"
15 15 #include "qsplineseries.h"
16 16 //items
17 17 #include "axisitem_p.h"
18 18 #include "areachartitem_p.h"
19 19 #include "barpresenter_p.h"
20 20 #include "stackedbarpresenter_p.h"
21 21 #include "percentbarpresenter_p.h"
22 22 #include "linechartitem_p.h"
23 23 #include "piechartitem_p.h"
24 24 #include "scatterchartitem_p.h"
25 25 #include "splinechartitem_p.h"
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
30 30 m_chart(chart),
31 31 m_animator(0),
32 32 m_dataset(dataset),
33 33 m_chartTheme(0),
34 34 m_zoomIndex(0),
35 35 m_rect(QRectF(QPoint(0,0),m_chart->size())),
36 36 m_options(QChart::NoAnimation),
37 37 m_themeForce(false)
38 38 {
39 39 createConnections();
40 40 setChartTheme(QChart::ChartThemeDefault,false);
41 41 }
42 42
43 43 ChartPresenter::~ChartPresenter()
44 44 {
45 45 delete m_chartTheme;
46 46 }
47 47
48 48 void ChartPresenter::createConnections()
49 49 {
50 50 QObject::connect(m_chart,SIGNAL(geometryChanged()),this,SLOT(handleGeometryChanged()));
51 51 QObject::connect(m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),this,SLOT(handleSeriesAdded(QSeries*,Domain*)));
52 52 QObject::connect(m_dataset,SIGNAL(seriesRemoved(QSeries*)),this,SLOT(handleSeriesRemoved(QSeries*)));
53 53 QObject::connect(m_dataset,SIGNAL(axisAdded(QChartAxis*,Domain*)),this,SLOT(handleAxisAdded(QChartAxis*,Domain*)));
54 54 QObject::connect(m_dataset,SIGNAL(axisRemoved(QChartAxis*)),this,SLOT(handleAxisRemoved(QChartAxis*)));
55 55 }
56 56
57 57
58 58 QRectF ChartPresenter::geometry() const
59 59 {
60 60 return m_rect;
61 61 }
62 62
63 63 void ChartPresenter::handleGeometryChanged()
64 64 {
65 65 QRectF rect(QPoint(0,0),m_chart->size());
66 66 rect.adjust(m_chart->padding(),m_chart->padding(), -m_chart->padding(), -m_chart->padding());
67 67
68 68 //rewrite zoom stack
69 69 for(int i=0;i<m_zoomStack.count();i++){
70 70 QRectF r = m_zoomStack[i];
71 71 qreal w = rect.width()/m_rect.width();
72 72 qreal h = rect.height()/m_rect.height();
73 73 QPointF tl = r.topLeft();
74 74 tl.setX(tl.x()*w);
75 75 tl.setY(tl.y()*h);
76 76 QPointF br = r.bottomRight();
77 77 br.setX(br.x()*w);
78 78 br.setY(br.y()*h);
79 79 r.setTopLeft(tl);
80 80 r.setBottomRight(br);
81 81 m_zoomStack[i]=r;
82 82 }
83 83
84 84 m_rect = rect;
85 85 Q_ASSERT(m_rect.isValid());
86 86 emit geometryChanged(m_rect);
87 87 }
88 88
89 89 void ChartPresenter::handleAxisAdded(QChartAxis* axis,Domain* domain)
90 90 {
91 91 AxisItem* item = new AxisItem(axis,this,axis==m_dataset->axisX()?AxisItem::X_AXIS : AxisItem::Y_AXIS,m_chart);
92 92
93 93 if(m_options.testFlag(QChart::GridAxisAnimations)){
94 94 m_animator->addAnimation(item);
95 95 }
96 96
97 97 if(axis==m_dataset->axisX()){
98 98 m_chartTheme->decorate(axis,true,m_themeForce);
99 99 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
100 100 //initialize
101 101 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
102 102
103 103 }
104 104 else{
105 105 m_chartTheme->decorate(axis,false,m_themeForce);
106 106 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
107 107 //initialize
108 108 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
109 109 }
110 110
111 111 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
112 112 //initialize
113 113 item->handleGeometryChanged(m_rect);
114 114 m_axisItems.insert(axis, item);
115 115 }
116 116
117 117 void ChartPresenter::handleAxisRemoved(QChartAxis* axis)
118 118 {
119 119 AxisItem* item = m_axisItems.take(axis);
120 120 Q_ASSERT(item);
121 121 if(m_animator) m_animator->removeAnimation(item);
122 122 delete item;
123 123 }
124 124
125 125
126 126 void ChartPresenter::handleSeriesAdded(QSeries* series,Domain* domain)
127 127 {
128 128 ChartItem *item = 0 ;
129 129
130 130 switch(series->type())
131 131 {
132 132 case QSeries::SeriesTypeLine: {
133 133
134 134 QLineSeries* lineSeries = static_cast<QLineSeries*>(series);
135 135 LineChartItem* line = new LineChartItem(lineSeries,m_chart);
136 136 if(m_options.testFlag(QChart::SeriesAnimations)) {
137 137 m_animator->addAnimation(line);
138 138 }
139 139 m_chartTheme->decorate(lineSeries, m_dataset->seriesIndex(series),m_themeForce);
140 140 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),line,SLOT(handleGeometryChanged(const QRectF&)));
141 141 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),line,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
142 142 item = line;
143 143 break;
144 144 }
145 145
146 146 case QSeries::SeriesTypeArea: {
147 147
148 148 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
149 149 AreaChartItem* area = new AreaChartItem(areaSeries,m_chart);
150 150 if(m_options.testFlag(QChart::SeriesAnimations)) {
151 151 m_animator->addAnimation(area->upperLineItem());
152 152 if(areaSeries->lowerSeries()) m_animator->addAnimation(area->lowerLineItem());
153 153 }
154 154 m_chartTheme->decorate(areaSeries, m_dataset->seriesIndex(series),m_themeForce);
155 155 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),area,SLOT(handleGeometryChanged(const QRectF&)));
156 156 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),area,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
157 157 item=area;
158 158 break;
159 159 }
160 160
161 161 case QSeries::SeriesTypeBar: {
162 162 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
163 163 BarPresenter* bar = new BarPresenter(barSeries,m_chart);
164 164 if(m_options.testFlag(QChart::SeriesAnimations)) {
165 165 // m_animator->addAnimation(bar);
166 166 }
167 167 m_chartTheme->decorate(barSeries, m_dataset->seriesIndex(barSeries),m_themeForce);
168 168 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
169 169 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
170 170 item=bar;
171 171 break;
172 172 }
173 173
174 174 case QSeries::SeriesTypeStackedBar: {
175 175 QStackedBarSeries* stackedBarSeries = static_cast<QStackedBarSeries*>(series);
176 176 StackedBarPresenter* bar = new StackedBarPresenter(stackedBarSeries,m_chart);
177 177 if(m_options.testFlag(QChart::SeriesAnimations)) {
178 178 // m_animator->addAnimation(bar);
179 179 }
180 180 m_chartTheme->decorate(stackedBarSeries, m_dataset->seriesIndex(stackedBarSeries),m_themeForce);
181 181 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
182 182 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
183 183 item=bar;
184 184 break;
185 185 }
186 186
187 187 case QSeries::SeriesTypePercentBar: {
188 188 QPercentBarSeries* percentBarSeries = static_cast<QPercentBarSeries*>(series);
189 189 PercentBarPresenter* bar = new PercentBarPresenter(percentBarSeries,m_chart);
190 190 if(m_options.testFlag(QChart::SeriesAnimations)) {
191 191 // m_animator->addAnimation(bar);
192 192 }
193 193 m_chartTheme->decorate(percentBarSeries, m_dataset->seriesIndex(percentBarSeries),m_themeForce);
194 194 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),bar,SLOT(handleGeometryChanged(const QRectF&)));
195 195 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),bar,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
196 196 item=bar;
197 197 break;
198 198 }
199 199
200 200 case QSeries::SeriesTypeScatter: {
201 201 QScatterSeries *scatterSeries = static_cast<QScatterSeries *>(series);
202 202 ScatterChartItem *scatter = new ScatterChartItem(scatterSeries, m_chart);
203 203 if(m_options.testFlag(QChart::SeriesAnimations)) {
204 204 m_animator->addAnimation(scatter);
205 205 }
206 206 m_chartTheme->decorate(scatterSeries, m_dataset->seriesIndex(series),m_themeForce);
207 207 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),scatter,SLOT(handleGeometryChanged(const QRectF&)));
208 208 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),scatter,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
209 209 item = scatter;
210 210 break;
211 211 }
212 212
213 213 case QSeries::SeriesTypePie: {
214 214 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
215 PieChartItem* pie = new PieChartItem(m_chart, pieSeries);
215 PieChartItem* pie = new PieChartItem(pieSeries, this, m_chart);
216 216 if(m_options.testFlag(QChart::SeriesAnimations)) {
217 217 m_animator->addAnimation(pie);
218 218 }
219 219 m_chartTheme->decorate(pieSeries, m_dataset->seriesIndex(series),m_themeForce);
220 220 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),pie,SLOT(handleGeometryChanged(const QRectF&)));
221 221 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),pie,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
222 222 // Hide all from background when there is only piechart
223 223 // TODO: refactor this ugly code... should be one setting for this
224 224 if (m_chartItems.count() == 0) {
225 225 m_chart->axisX()->hide();
226 226 m_chart->axisY()->hide();
227 227 }
228 228 item=pie;
229 229 break;
230 230 }
231 231
232 232 case QSeries::SeriesTypeSpline: {
233 233 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
234 234 SplineChartItem* spline = new SplineChartItem(splineSeries, m_chart);
235 235 if(m_options.testFlag(QChart::SeriesAnimations)) {
236 236 m_animator->addAnimation(spline);
237 237 }
238 238 m_chartTheme->decorate(splineSeries, m_dataset->seriesIndex(series),m_themeForce);
239 239 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),spline,SLOT(handleGeometryChanged(const QRectF&)));
240 240 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),spline,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
241 241 item=spline;
242 242 break;
243 243 }
244 244 default: {
245 245 qDebug()<< "Series type" << series->type() << "not implemented.";
246 246 break;
247 247 }
248 248 }
249 249
250 250 //initialize
251 251 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
252 252 if(m_rect.isValid()) item->handleGeometryChanged(m_rect);
253 253 m_chartItems.insert(series,item);
254 254 zoomReset();
255 255 }
256 256
257 257 void ChartPresenter::handleSeriesRemoved(QSeries* series)
258 258 {
259 259 ChartItem* item = m_chartItems.take(series);
260 260 Q_ASSERT(item);
261 261 if(m_animator) {
262 262 //small hack to handle area animations
263 263 if(series->type()==QSeries::SeriesTypeArea){
264 264 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
265 265 AreaChartItem* area = static_cast<AreaChartItem*>(item);
266 266 m_animator->removeAnimation(area->upperLineItem());
267 267 if(areaSeries->lowerSeries()) m_animator->removeAnimation(area->lowerLineItem());
268 268 }else
269 269 m_animator->removeAnimation(item);
270 270 }
271 271 delete item;
272 272 }
273 273
274 274 void ChartPresenter::setChartTheme(QChart::ChartTheme theme,bool force)
275 275 {
276 276 if(m_chartTheme && m_chartTheme->id() == theme) return;
277 277 delete m_chartTheme;
278 278 m_themeForce = force;
279 279 m_chartTheme = ChartTheme::createTheme(theme);
280 280 m_chartTheme->decorate(m_chart,m_themeForce);
281 281 m_chartTheme->decorate(m_chart->legend(),m_themeForce);
282 282 resetAllElements();
283 283 }
284 284
285 285 QChart::ChartTheme ChartPresenter::chartTheme()
286 286 {
287 287 return m_chartTheme->id();
288 288 }
289 289
290 290 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
291 291 {
292 292 if(m_options!=options) {
293 293
294 294 m_options=options;
295 295
296 296 if(m_options!=QChart::NoAnimation && !m_animator) {
297 297 m_animator= new ChartAnimator(this);
298 298
299 299 }
300 300 resetAllElements();
301 301 }
302 302
303 303 }
304 304
305 305 void ChartPresenter::resetAllElements()
306 306 {
307 307 QList<QChartAxis*> axisList = m_axisItems.uniqueKeys();
308 308 QList<QSeries*> seriesList = m_chartItems.uniqueKeys();
309 309
310 310 foreach(QChartAxis* axis, axisList) {
311 311 handleAxisRemoved(axis);
312 312 handleAxisAdded(axis,m_dataset->domain(axis));
313 313 }
314 314 foreach(QSeries* series, seriesList) {
315 315 handleSeriesRemoved(series);
316 316 handleSeriesAdded(series,m_dataset->domain(series));
317 317 }
318 318 }
319 319
320 320 void ChartPresenter::zoomIn()
321 321 {
322 322 QRectF rect = geometry();
323 323 rect.setWidth(rect.width()/2);
324 324 rect.setHeight(rect.height()/2);
325 325 rect.moveCenter(geometry().center());
326 326 zoomIn(rect);
327 327 }
328 328
329 329 void ChartPresenter::zoomIn(const QRectF& rect)
330 330 {
331 331 QRectF r = rect.normalized();
332 332 r.translate(-m_chart->padding(), -m_chart->padding());
333 333 if(m_animator) {
334 334
335 335 QPointF point(r.center().x()/geometry().width(),r.center().y()/geometry().height());
336 336 m_animator->setState(ChartAnimator::ZoomInState,point);
337 337 }
338 338 m_dataset->zoomInDomain(r,geometry().size());
339 339 m_zoomStack<<r;
340 340 m_zoomIndex++;
341 341 if(m_animator) {
342 342 m_animator->setState(ChartAnimator::ShowState);
343 343 }
344 344 }
345 345
346 346 void ChartPresenter::zoomOut()
347 347 {
348 348 if(m_zoomIndex==0) return;
349 349 if(m_animator)
350 350 {
351 351 m_animator->setState(ChartAnimator::ZoomOutState);
352 352 }
353 353 m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
354 354 m_zoomIndex--;
355 355 m_zoomStack.resize(m_zoomIndex);
356 356 if(m_animator){
357 357 m_animator->setState(ChartAnimator::ShowState);
358 358 }
359 359 }
360 360
361 361 void ChartPresenter::zoomReset()
362 362 {
363 363 m_zoomIndex=0;
364 364 m_zoomStack.resize(m_zoomIndex);
365 365 }
366 366
367 367 void ChartPresenter::scroll(int dx,int dy)
368 368 {
369 369 if(m_animator){
370 370 if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF());
371 371 if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF());
372 372 if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF());
373 373 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
374 374 }
375 375
376 376 m_dataset->scrollDomain(dx,dy,geometry().size());
377 377
378 378 if(m_animator){
379 379 m_animator->setState(ChartAnimator::ShowState);
380 380 }
381 381 }
382 382
383 383 QChart::AnimationOptions ChartPresenter::animationOptions() const
384 384 {
385 385 return m_options;
386 386 }
387 387
388 388
389 389 #include "moc_chartpresenter_p.cpp"
390 390
391 391 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,86 +1,90
1 1 #ifndef CHARTPRESENTER_H_
2 2 #define CHARTPRESENTER_H_
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qchart.h" //becouse of QChart::ChartThemeId //TODO
6 6 #include "qchartaxis.h"
7 7 #include <QRectF>
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class ChartItem;
12 12 class QSeries;
13 13 class ChartDataSet;
14 14 class Domain;
15 15 class AxisItem;
16 16 class ChartTheme;
17 17 class ChartAnimator;
18 18
19 19 class ChartPresenter: public QObject
20 20 {
21 21 Q_OBJECT
22 22 public:
23 23 enum ZValues {
24 24 BackgroundZValue = -1,
25 25 ShadesZValue,
26 26 GridZValue,
27 27 AxisZValue,
28 28 LineChartZValue,
29 29 BarSeriesZValue,
30 30 ScatterSeriesZValue,
31 31 PieSeriesZValue,
32 32 LegendZValue
33 33 };
34 34
35 35 ChartPresenter(QChart* chart,ChartDataSet *dataset);
36 36 virtual ~ChartPresenter();
37 37
38 38 void setMargin(int margin);
39 39 int margin() const;
40 40
41 41 QRectF geometry() const;
42 ChartAnimator* animator() const {return m_animator;};
42
43 ChartAnimator* animator() const {return m_animator;}
44 ChartTheme *theme() { return m_chartTheme; }
45 ChartDataSet *dataSet() { return m_dataset; }
43 46
44 47 void setChartTheme(QChart::ChartTheme theme,bool force = true);
45 48 QChart::ChartTheme chartTheme();
46 49
47 50 void setAnimationOptions(QChart::AnimationOptions options);
48 51 QChart::AnimationOptions animationOptions() const;
49 52
50 53 void zoomIn();
51 54 void zoomIn(const QRectF& rect);
52 55 void zoomOut();
53 56 void zoomReset();
54 57 void scroll(int dx,int dy);
58
55 59 private:
56 60 void createConnections();
57 61 void resetAllElements();
58 62
59 63 public slots:
60 64 void handleSeriesAdded(QSeries* series,Domain* domain);
61 65 void handleSeriesRemoved(QSeries* series);
62 66 void handleAxisAdded(QChartAxis* axis,Domain* domain);
63 67 void handleAxisRemoved(QChartAxis* axis);
64 68 void handleGeometryChanged();
65 69
66 70 signals:
67 71 void geometryChanged(const QRectF& rect);
68 72
69 73 private:
70 74 QChart* m_chart;
71 75 ChartAnimator* m_animator;
72 76 ChartDataSet* m_dataset;
73 77 ChartTheme *m_chartTheme;
74 78 int m_zoomIndex;
75 79 QMap<QSeries*,ChartItem*> m_chartItems;
76 80 QMap<QChartAxis*,AxisItem*> m_axisItems;
77 81 QVector<QRectF> m_zoomStack;
78 82 QRectF m_rect;
79 83 QChart::AnimationOptions m_options;
80 84 bool m_themeForce;
81 85
82 86 };
83 87
84 88 QTCOMMERCIALCHART_END_NAMESPACE
85 89
86 90 #endif /* CHARTPRESENTER_H_ */
@@ -1,190 +1,198
1 1 #include "piechartitem_p.h"
2 2 #include "pieslice_p.h"
3 3 #include "qpieslice.h"
4 4 #include "qpieseries.h"
5 5 #include "chartpresenter_p.h"
6 #include "chartdataset_p.h"
6 7 #include "chartanimator_p.h"
7 8 #include <QDebug>
8 9 #include <QPainter>
9 10 #include <QTimer>
10 11
11 12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12 13
13 PieChartItem::PieChartItem(QGraphicsItem *parent, QPieSeries *series)
14 PieChartItem::PieChartItem(QPieSeries *series, ChartPresenter *presenter, QGraphicsItem *parent)
14 15 :ChartItem(parent),
15 m_series(series)
16 m_series(series),
17 m_presenter(presenter)
16 18 {
17 19 Q_ASSERT(series);
18 20 connect(series, SIGNAL(added(QList<QPieSlice*>)), this, SLOT(handleSlicesAdded(QList<QPieSlice*>)));
19 21 connect(series, SIGNAL(removed(QList<QPieSlice*>)), this, SLOT(handleSlicesRemoved(QList<QPieSlice*>)));
20 22 connect(series, SIGNAL(piePositionChanged()), this, SLOT(handlePieLayoutChanged()));
21 23 connect(series, SIGNAL(pieSizeChanged()), this, SLOT(handlePieLayoutChanged()));
22 24
23 25 QTimer::singleShot(0, this, SLOT(initialize()));
24 26
25 27 // Note: the following does not affect as long as the item does not have anything to paint
26 28 setZValue(ChartPresenter::PieSeriesZValue);
27 29 }
28 30
29 31 PieChartItem::~PieChartItem()
30 32 {
31 33 // slices deleted automatically through QGraphicsItem
32 34 }
33 35
34 36 void PieChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
35 37 {
36 38 Q_UNUSED(painter)
37 39 // TODO: paint shadows for all components
38 40 // - get paths from items & merge & offset and draw with shadow color?
39 41 //painter->setBrush(QBrush(Qt::red));
40 42 //painter->drawRect(m_debugRect);
41 43 }
42 44
43 45 void PieChartItem::initialize()
44 46 {
45 47 handleSlicesAdded(m_series->m_slices);
46 48 }
47 49
48 50 void PieChartItem::handleSlicesAdded(QList<QPieSlice*> slices)
49 51 {
50 52 bool isEmpty = m_slices.isEmpty();
51 53
54 m_presenter->theme()->decorate(m_series, m_presenter->dataSet()->seriesIndex(m_series));
55
52 56 foreach (QPieSlice *s, slices) {
53 57 PieSlice* slice = new PieSlice(this);
54 58 m_slices.insert(s, slice);
55 59 connect(s, SIGNAL(changed()), this, SLOT(handleSliceChanged()));
56 60 connect(slice, SIGNAL(clicked()), s, SIGNAL(clicked()));
57 61 connect(slice, SIGNAL(hoverEnter()), s, SIGNAL(hoverEnter()));
58 62 connect(slice, SIGNAL(hoverLeave()), s, SIGNAL(hoverLeave()));
59 63
60 64 PieSliceLayout layout = calculateSliceLayout(s);
61 65
62 66 if (m_animator)
63 67 m_animator->addAnimation(this, s, layout, isEmpty);
64 68 else
65 69 setLayout(s, layout);
66 70 }
67 71 }
68 72
69 73 void PieChartItem::handleSlicesRemoved(QList<QPieSlice*> slices)
70 74 {
75 m_presenter->theme()->decorate(m_series, m_presenter->dataSet()->seriesIndex(m_series));
76
71 77 foreach (QPieSlice *s, slices) {
72 78 if (m_animator)
73 79 m_animator->removeAnimation(this, s);
74 80 else
75 81 destroySlice(s);
76 82 }
77 83 }
78 84
79 85 void PieChartItem::handlePieLayoutChanged()
80 86 {
81 87 PieLayout layout = calculateLayout();
82 88 applyLayout(layout);
83 89 update();
84 90 }
85 91
86 92 void PieChartItem::handleSliceChanged()
87 93 {
88 94 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
89 95 Q_ASSERT(m_slices.contains(slice));
90 96 PieSliceLayout layout = calculateSliceLayout(slice);
91 97 updateLayout(slice, layout);
92 98 update();
93 99 }
94 100
95 101 void PieChartItem::handleDomainChanged(qreal, qreal, qreal, qreal)
96 102 {
97 103 // TODO
98 104 }
99 105
100 106 void PieChartItem::handleGeometryChanged(const QRectF& rect)
101 107 {
102 108 prepareGeometryChange();
103 109 m_rect = rect;
104 110 handlePieLayoutChanged();
105 111 }
106 112
107 113 void PieChartItem::calculatePieLayout()
108 114 {
109 115 // find pie center coordinates
110 116 m_pieCenter.setX(m_rect.left() + (m_rect.width() * m_series->pieHorizontalPosition()));
111 117 m_pieCenter.setY(m_rect.top() + (m_rect.height() * m_series->pieVerticalPosition()));
112 118
113 119 // find maximum radius for pie
114 120 m_pieRadius = m_rect.height() / 2;
115 121 if (m_rect.width() < m_rect.height())
116 122 m_pieRadius = m_rect.width() / 2;
117 123
118 124 // apply size factor
119 125 m_pieRadius *= m_series->pieSize();
120 126 }
121 127
122 128 PieSliceLayout PieChartItem::calculateSliceLayout(QPieSlice *slice)
123 129 {
124 130 PieSliceLayout sliceLayout;
125 131 sliceLayout.m_center = PieSlice::sliceCenter(m_pieCenter, m_pieRadius, slice);
126 132 sliceLayout.m_radius = m_pieRadius;
127 133 sliceLayout.m_startAngle = slice->startAngle();
128 134 sliceLayout.m_angleSpan = slice->m_angleSpan;
135 sliceLayout.m_pen = slice->m_slicePen;
136 sliceLayout.m_brush = slice->m_sliceBrush;
129 137 return sliceLayout;
130 138 }
131 139
132 140 PieLayout PieChartItem::calculateLayout()
133 141 {
134 142 calculatePieLayout();
135 143 PieLayout layout;
136 144 foreach (QPieSlice* s, m_series->slices()) {
137 145 if (m_slices.contains(s)) // calculate layout only for those slices that are already visible
138 146 layout.insert(s, calculateSliceLayout(s));
139 147 }
140 148 return layout;
141 149 }
142 150
143 151 void PieChartItem::applyLayout(const PieLayout &layout)
144 152 {
145 153 if (m_animator)
146 154 m_animator->updateLayout(this, layout);
147 155 else
148 156 setLayout(layout);
149 157 }
150 158
151 159 void PieChartItem::updateLayout(QPieSlice *slice, const PieSliceLayout &layout)
152 160 {
153 161 if (m_animator)
154 162 m_animator->updateLayout(this, slice, layout);
155 163 else
156 164 setLayout(slice, layout);
157 165 }
158 166
159 167 void PieChartItem::setLayout(const PieLayout &layout)
160 168 {
161 169 foreach (QPieSlice *slice, layout.keys()) {
162 170 PieSlice *s = m_slices.value(slice);
163 171 Q_ASSERT(s);
164 172 s->setLayout(layout.value(slice));
165 173 s->updateData(slice);
166 174 s->updateGeometry();
167 175 s->update();
168 176 }
169 177 }
170 178
171 179 void PieChartItem::setLayout(QPieSlice *slice, const PieSliceLayout &layout)
172 180 {
173 181 // find slice
174 182 PieSlice *s = m_slices.value(slice);
175 183 Q_ASSERT(s);
176 184 s->setLayout(layout);
177 185 if (m_series->m_slices.contains(slice)) // Slice has been deleted if not found. Animations ongoing...
178 186 s->updateData(slice);
179 187 s->updateGeometry();
180 188 s->update();
181 189 }
182 190
183 191 void PieChartItem::destroySlice(QPieSlice *slice)
184 192 {
185 193 delete m_slices.take(slice);
186 194 }
187 195
188 196 #include "moc_piechartitem_p.cpp"
189 197
190 198 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,58 +1,59
1 1 #ifndef PIECHARTITEM_H
2 2 #define PIECHARTITEM_H
3 3
4 4 #include "qpieseries.h"
5 5 #include "chartitem_p.h"
6 6 #include "pieslice_p.h"
7 7
8 8 class QGraphicsItem;
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10 class QPieSlice;
11 class ChartPresenter;
11 12
12 13 typedef QHash<QPieSlice*, PieSliceLayout> PieLayout;
13 14
14 15 class PieChartItem : public QObject, public ChartItem
15 16 {
16 17 Q_OBJECT
17 18
18 19 public:
19 20 // TODO: use a generic data class instead of x and y
20 PieChartItem(QGraphicsItem *parent, QPieSeries *series);
21 PieChartItem(QPieSeries *series, ChartPresenter *presenter, QGraphicsItem *parent);
21 22 ~PieChartItem();
22 23
23 24 public: // from QGraphicsItem
24 25 QRectF boundingRect() const { return m_rect; }
25 26 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
26 27
27 28 public Q_SLOTS:
28 29 void initialize();
29 30 void handleSlicesAdded(QList<QPieSlice*> slices);
30 31 void handleSlicesRemoved(QList<QPieSlice*> slices);
31 32 void handlePieLayoutChanged();
32 33 void handleSliceChanged();
33 34 void handleDomainChanged(qreal, qreal, qreal, qreal);
34 35 void handleGeometryChanged(const QRectF& rect);
35 36
36 37 public:
37 38 void calculatePieLayout();
38 39 PieSliceLayout calculateSliceLayout(QPieSlice *slice);
39 40 PieLayout calculateLayout();
40 41 void applyLayout(const PieLayout &layout);
41 42 void updateLayout(QPieSlice *slice, const PieSliceLayout &layout);
42 43 void setLayout(const PieLayout &layout);
43 44 void setLayout(QPieSlice *slice, const PieSliceLayout &layout);
44 45 void destroySlice(QPieSlice *slice);
45 46
46 47 private:
47 48 friend class PieSlice;
48 49 QHash<QPieSlice*, PieSlice*> m_slices;
49 50 QPieSeries *m_series;
50 51 QRectF m_rect;
51 52 QPointF m_pieCenter;
52 53 qreal m_pieRadius;
53 QRectF m_debugRect;
54 ChartPresenter *m_presenter;
54 55 };
55 56
56 57 QTCOMMERCIALCHART_END_NAMESPACE
57 58
58 59 #endif // PIECHARTITEM_H
@@ -1,204 +1,202
1 1 #include "pieslice_p.h"
2 2 #include "piechartitem_p.h"
3 3 #include "qpieseries.h"
4 4 #include "qpieslice.h"
5 5 #include "chartpresenter_p.h"
6 6 #include <QPainter>
7 7 #include <QDebug>
8 8 #include <qmath.h>
9 9 #include <QGraphicsSceneEvent>
10 10 #include <QTime>
11 11
12 12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13 13
14 14 #define PI 3.14159265 // TODO: is this defined in some header?
15 15
16 16 QPointF offset(qreal angle, qreal length)
17 17 {
18 18 qreal dx = qSin(angle*(PI/180)) * length;
19 19 qreal dy = qCos(angle*(PI/180)) * length;
20 20 return QPointF(dx, -dy);
21 21 }
22 22
23 23 PieSlice::PieSlice(QGraphicsItem* parent)
24 24 :QGraphicsObject(parent),
25 25 m_isExploded(false),
26 26 m_explodeDistanceFactor(0),
27 27 m_labelVisible(false),
28 28 m_labelArmLengthFactor(0)
29 29 {
30 30 setAcceptHoverEvents(true);
31 31 setAcceptedMouseButtons(Qt::LeftButton);
32 32 setZValue(ChartPresenter::PieSeriesZValue);
33 33 }
34 34
35 35 PieSlice::~PieSlice()
36 36 {
37 37
38 38 }
39 39
40 40 QRectF PieSlice::boundingRect() const
41 41 {
42 42 return m_boundingRect;
43 43 }
44 44
45 45 QPainterPath PieSlice::shape() const
46 46 {
47 47 // Don't include the label and label arm.
48 48 // This is used to detect a mouse clicks. We do not want clicks from label.
49 49 return m_slicePath;
50 50 }
51 51
52 52 void PieSlice::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/)
53 53 {
54 54 painter->setClipRect(parentItem()->boundingRect());
55 55
56 56 painter->save();
57 painter->setPen(m_slicePen);
58 painter->setBrush(m_sliceBrush);
57 painter->setPen(m_layout.m_pen);
58 painter->setBrush(m_layout.m_brush);
59 59 painter->drawPath(m_slicePath);
60 60 painter->restore();
61 61
62 62 if (m_labelVisible) {
63 63 painter->save();
64 64 painter->setPen(m_labelArmPen);
65 65 painter->drawPath(m_labelArmPath);
66 66 painter->restore();
67 67
68 68 painter->setFont(m_labelFont);
69 69 painter->drawText(m_labelTextRect.bottomLeft(), m_labelText);
70 70 }
71 71 }
72 72
73 73 void PieSlice::hoverEnterEvent(QGraphicsSceneHoverEvent* /*event*/)
74 74 {
75 75 emit hoverEnter();
76 76 }
77 77
78 78 void PieSlice::hoverLeaveEvent(QGraphicsSceneHoverEvent* /*event*/)
79 79 {
80 80 emit hoverLeave();
81 81 }
82 82
83 83 void PieSlice::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/)
84 84 {
85 85 emit clicked();
86 86 }
87 87
88 88 void PieSlice::setLayout(PieSliceLayout layout)
89 89 {
90 90 m_layout = layout;
91 91 }
92 92
93 93 void PieSlice::updateGeometry()
94 94 {
95 95 if (m_layout.m_radius <= 0)
96 96 return;
97 97
98 98 prepareGeometryChange();
99 99
100 100 // update slice path
101 101 qreal centerAngle;
102 102 QPointF armStart;
103 103 m_slicePath = slicePath(m_layout.m_center, m_layout.m_radius, m_layout.m_startAngle, m_layout.m_angleSpan, &centerAngle, &armStart);
104 104
105 105 // update text rect
106 106 m_labelTextRect = labelTextRect(m_labelFont, m_labelText);
107 107
108 108 // update label arm path
109 109 QPointF labelTextStart;
110 110 m_labelArmPath = labelArmPath(armStart, centerAngle, m_layout.m_radius * m_labelArmLengthFactor, m_labelTextRect.width(), &labelTextStart);
111 111
112 112 // update text position
113 113 m_labelTextRect.moveBottomLeft(labelTextStart);
114 114
115 115 // update bounding rect
116 116 m_boundingRect = m_slicePath.boundingRect().united(m_labelArmPath.boundingRect()).united(m_labelTextRect);
117 117 }
118 118
119 119 void PieSlice::updateData(const QPieSlice* sliceData)
120 120 {
121 121 // TODO: compare what has changes to avoid unneccesary geometry updates
122 122
123 123 m_isExploded = sliceData->isExploded();
124 124 m_explodeDistanceFactor = sliceData->explodeDistanceFactor();
125 m_slicePen = sliceData->slicePen();
126 m_sliceBrush = sliceData->sliceBrush();
127 125
128 126 m_labelVisible = sliceData->isLabelVisible();
129 127 m_labelText = sliceData->label();
130 128 m_labelFont = sliceData->labelFont();
131 129 m_labelArmLengthFactor = sliceData->labelArmLengthFactor();
132 130 m_labelArmPen = sliceData->labelArmPen();
133 131 }
134 132
135 133 QPointF PieSlice::sliceCenter(QPointF point, qreal radius, QPieSlice *slice)
136 134 {
137 135 if (slice->isExploded()) {
138 136 qreal centerAngle = slice->startAngle() + (slice->m_angleSpan/2);
139 137 qreal len = radius * slice->explodeDistanceFactor();
140 138 qreal dx = qSin(centerAngle*(PI/180)) * len;
141 139 qreal dy = -qCos(centerAngle*(PI/180)) * len;
142 140 point += QPointF(dx, dy);
143 141 }
144 142 return point;
145 143 }
146 144
147 145 QPainterPath PieSlice::slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart)
148 146 {
149 147 // calculate center angle
150 148 *centerAngle = startAngle + (angleSpan/2);
151 149
152 150 // calculate slice rectangle
153 151 QRectF rect(center.x()-radius, center.y()-radius, radius*2, radius*2);
154 152
155 153 // slice path
156 154 // TODO: draw the shape so that it might have a hole in the center
157 155 QPainterPath path;
158 156 path.moveTo(rect.center());
159 157 path.arcTo(rect, -startAngle + 90, -angleSpan);
160 158 path.closeSubpath();
161 159
162 160 // calculate label arm start point
163 161 *armStart = center;
164 162 *armStart += offset(*centerAngle, radius + PIESLICE_LABEL_GAP);
165 163
166 164 return path;
167 165 }
168 166
169 167 QPainterPath PieSlice::labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart)
170 168 {
171 169 qreal dx = qSin(angle*(PI/180)) * length;
172 170 qreal dy = -qCos(angle*(PI/180)) * length;
173 171 QPointF parm1 = start + QPointF(dx, dy);
174 172
175 173 QPointF parm2 = parm1;
176 174 if (angle < 180) { // arm swings the other way on the left side
177 175 parm2 += QPointF(textWidth, 0);
178 176 *textStart = parm1;
179 177 }
180 178 else {
181 179 parm2 += QPointF(-textWidth,0);
182 180 *textStart = parm2;
183 181 }
184 182
185 183 // elevate the text position a bit so that it does not hit the line
186 184 *textStart += QPointF(0, -5);
187 185
188 186 QPainterPath path;
189 187 path.moveTo(start);
190 188 path.lineTo(parm1);
191 189 path.lineTo(parm2);
192 190
193 191 return path;
194 192 }
195 193
196 194 QRectF PieSlice::labelTextRect(QFont font, QString text)
197 195 {
198 196 QFontMetricsF fm(font);
199 197 return fm.boundingRect(text);
200 198 }
201 199
202 200 #include "moc_pieslice_p.cpp"
203 201
204 202 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,80 +1,80
1 1 #ifndef PIESLICE_H
2 2 #define PIESLICE_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "charttheme_p.h"
6 6 #include "qpieseries.h"
7 7 #include <QGraphicsItem>
8 8 #include <QRectF>
9 9 #include <QColor>
10 10 #include <QPen>
11 11
12 12 #define PIESLICE_LABEL_GAP 5
13 13
14 14 QTCOMMERCIALCHART_BEGIN_NAMESPACE
15 15 class PieChartItem;
16 16 class PieSliceLabel;
17 17 class QPieSlice;
18 18
19 19 class PieSliceLayout
20 20 {
21 21 public:
22 22 QPointF m_center;
23 23 qreal m_radius;
24 24 qreal m_startAngle;
25 25 qreal m_angleSpan;
26 QPen m_pen;
27 QBrush m_brush;
26 28 };
27 29
28 30 class PieSlice : public QGraphicsObject
29 31 {
30 32 Q_OBJECT
31 33
32 34 public:
33 35 PieSlice(QGraphicsItem* parent = 0);
34 36 ~PieSlice();
35 37
36 38 public: // from QGraphicsItem
37 39 QRectF boundingRect() const;
38 40 QPainterPath shape() const;
39 41 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
40 42 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
41 43 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
42 44 void mousePressEvent(QGraphicsSceneMouseEvent *event);
43 45
44 46 Q_SIGNALS:
45 47 void clicked();
46 48 void hoverEnter();
47 49 void hoverLeave();
48 50
49 51 public:
50 52 void setLayout(PieSliceLayout layout);
51 53 void updateGeometry();
52 54 void updateData(const QPieSlice *sliceData);
53 55 static QPointF sliceCenter(QPointF point, qreal radius, QPieSlice *slice);
54 56 static QPainterPath slicePath(QPointF center, qreal radius, qreal startAngle, qreal angleSpan, qreal* centerAngle, QPointF* armStart);
55 57 static QPainterPath labelArmPath(QPointF start, qreal angle, qreal length, qreal textWidth, QPointF* textStart);
56 58 static QRectF labelTextRect(QFont font, QString text);
57 59
58 60 private:
59 61 PieSliceLayout m_layout;
60 62 QRectF m_boundingRect;
61 63
62 64 QPainterPath m_slicePath;
63 65 bool m_isExploded;
64 66 qreal m_explodeDistanceFactor;
65 67 bool m_labelVisible;
66 QPen m_slicePen;
67 QBrush m_sliceBrush;
68 68
69 69 QPainterPath m_labelArmPath;
70 70 qreal m_labelArmLengthFactor;
71 71 QPen m_labelArmPen;
72 72
73 73 QRectF m_labelTextRect;
74 74 QFont m_labelFont;
75 75 QString m_labelText;
76 76 };
77 77
78 78 QTCOMMERCIALCHART_END_NAMESPACE
79 79
80 80 #endif // PIESLICE_H
General Comments 0
You need to be logged in to leave comments. Login now