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