##// END OF EJS Templates
Improves spline interpolation...
Michal Klocek -
r622:960bcf5125b7
parent child
Show More
@@ -0,0 +1,127
1 #include "splineanimation_p.h"
2 #include "splinechartitem_p.h"
3
4 Q_DECLARE_METATYPE(QVector<QPointF>)
5 Q_DECLARE_METATYPE(SplineVector)
6
7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8
9 SplineAnimation::SplineAnimation(SplineChartItem* item):ChartAnimation(item),
10 m_item(item),
11 m_dirty(true)
12 {
13 }
14
15 SplineAnimation::~SplineAnimation()
16 {
17 }
18
19 void SplineAnimation::setValues(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,QVector<QPointF>& oldControlPoints,QVector<QPointF>& newControlPoints,int index)
20 {
21 int x = oldPoints.count();
22 int y = newPoints.count();
23
24 Q_ASSERT(newPoints.count()*2-2 == newControlPoints.count());
25
26 if(x!=y && abs(x-y)!=1) {
27 m_oldSpline.first= newPoints;
28 m_oldSpline.second= newControlPoints;
29 oldPoints.resize(newPoints.size());
30 oldControlPoints.resize(newControlPoints.size());
31 SplineVector oldPair;
32 oldPair.first=oldPoints;
33 oldPair.second=oldControlPoints;
34 SplineVector newPair;
35 newPair.first=newPoints;
36 newPair.second=newControlPoints;
37 setKeyValueAt(0.0, qVariantFromValue(oldPair));
38 setKeyValueAt(1.0, qVariantFromValue(newPair));
39 m_dirty=false;
40 }
41 else {
42 if(m_dirty) {
43 m_oldSpline.first = oldPoints;
44 m_oldSpline.second = oldControlPoints;
45 m_dirty=false;
46 }
47 oldPoints = newPoints;
48 oldControlPoints = newControlPoints;
49 if (y<x) {
50 m_oldSpline.first.remove(index); //remove
51 m_oldSpline.second.remove(index*2);
52 m_oldSpline.second.remove(index*2);
53 }
54 if (y>x) {
55 m_oldSpline.first.insert(index,x>0?m_oldSpline.first[index-1]:newPoints[index]); //add
56 m_oldSpline.second.insert((index-1)*2,x>1?m_oldSpline.second[(index-2)*2]:newControlPoints[(index-1)*2]); //add
57 m_oldSpline.second.insert((index-1)*2+1,x>1?m_oldSpline.second[(index-2)*2+1]:newControlPoints[(index-1)*2+1]); //add
58 }
59 SplineVector newPair;
60 newPair.first=newPoints;
61 newPair.second=newControlPoints;
62 setKeyValueAt(0.0, qVariantFromValue(m_oldSpline));
63 setKeyValueAt(1.0, qVariantFromValue(newPair));
64
65 }
66 }
67
68 QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant & end, qreal progress ) const
69 {
70
71 SplineVector startPair = qVariantValue< SplineVector >(start);
72 SplineVector endPair = qVariantValue< SplineVector >(end);
73 SplineVector result;
74
75
76 switch(m_type) {
77
78 case MoveDownAnimation: {
79
80 if(startPair.first.count() != endPair.first.count()) break;
81 Q_ASSERT(startPair.first.count()*2-2 == startPair.second.count());
82 Q_ASSERT(endPair.first.count()*2-2 == endPair.second.count());
83 for(int i =0;i< endPair.first.count();i++) {
84 qreal x = startPair.first[i].x() + ((endPair.first[i].x()- startPair.first[i].x()) * progress);
85 qreal y = startPair.first[i].y() + ((endPair.first[i].y()- startPair.first[i].y()) * progress);
86 result.first << QPointF(x,y);
87 if(i +1 >= endPair.first.count()) continue;
88 x = startPair.second[i*2].x() + ((endPair.second[i*2].x()- startPair.second[i*2].x()) * progress);
89 y = startPair.second[i*2].y() + ((endPair.second[i*2].y()- startPair.second[i*2].y()) * progress);
90 result.second << QPoint(x,y);
91 x = startPair.second[i*2+1].x() + ((endPair.second[i*2+1].x()- startPair.second[i*2+1].x()) * progress);
92 y = startPair.second[i*2+1].y() + ((endPair.second[i*2+1].y()- startPair.second[i*2+1].y()) * progress);
93 result.second << QPoint(x,y);
94 }
95
96 }
97 break;
98 case LineDrawAnimation:{
99 Q_ASSERT(endPair.first.count()*2-2 == endPair.second.count());
100 int count = endPair.first.count()* qBound(0.0, progress, 1.0);
101 for(int i =0;i<count;i++) {
102 result.first << endPair.first[i];
103 if(i+1==count) break;
104 result.second << endPair.second[2*i];
105 result.second << endPair.second[2*i+1];
106 }
107 }
108 break;
109 default:
110 qWarning()<<"Unknow type of animation";
111 break;
112 }
113
114 return qVariantFromValue(result);
115 }
116
117 void SplineAnimation::updateCurrentValue (const QVariant & value )
118 {
119 if(state()!=QAbstractAnimation::Stopped){ //workaround
120 m_dirty=true;
121 QPair<QVector<QPointF >, QVector<QPointF > > pair = qVariantValue< QPair< QVector<QPointF>, QVector<QPointF> > >(value);
122 m_item->setLayout(pair.first,pair.second);
123 }
124 }
125
126
127 QTCOMMERCIALCHART_END_NAMESPACE
@@ -0,0 +1,33
1 #ifndef SPLINEANIMATION_P_H_
2 #define SPLINEANIMATION_P_H_
3 #include "chartanimation_p.h"
4 #include <QPointF>
5
6 typedef QPair<QVector<QPointF >, QVector<QPointF > > SplineVector;
7
8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9
10
11 class SplineChartItem;
12
13 class SplineAnimation : public ChartAnimation
14 {
15 public:
16
17 SplineAnimation(SplineChartItem* item);
18 ~SplineAnimation();
19 void setValues(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,QVector<QPointF>& oldContorlPoints,QVector<QPointF>& newControlPoints,int index);
20
21 protected:
22 QVariant interpolated(const QVariant &start, const QVariant & end, qreal progress ) const;
23 void updateCurrentValue (const QVariant & value );
24
25 private:
26 SplineVector m_oldSpline;
27 SplineChartItem* m_item;
28 bool m_dirty;
29 };
30
31 QTCOMMERCIALCHART_END_NAMESPACE
32
33 #endif
@@ -1,53 +1,58
1 1 #include "chartview.h"
2 2 #include <QSplineSeries>
3 3 #include <QTime>
4 4
5 5 ChartView::ChartView(QWidget* parent):QChartView(parent),
6 6 m_step(1),
7 7 m_x(0),
8 8 m_y(1)
9 9 {
10 10 QTime now = QTime::currentTime();
11 11 qsrand((uint)now.msec());
12 12 setChartTitle("Three random line charts");
13 13
14 14 QObject::connect(&m_timer,SIGNAL(timeout()),this,SLOT(handleTimeout()));
15 m_timer.setInterval(1000);
15 m_timer.setInterval(3000);
16 16
17 17 m_series0 = new QLineSeries(this);
18 18 QPen blue(Qt::blue);
19 19 blue.setWidth(3);
20 20 m_series0->setPen(blue);
21 21
22 22
23 23 m_series1 = new QSplineSeries(this);
24 24 QPen green(Qt::green);
25 25 green.setWidth(3);
26 26 m_series1->setPen(green);
27 27
28 28
29 29 m_series0->add(m_x,m_y);
30 30 m_series1->add(m_x,m_y);
31 31
32 32 setChartTitle("Simple EKG exmaple");
33 33 addSeries(m_series0);
34 34 addSeries(m_series1);
35 35 axisY()->setRange(-5,5);
36 36 axisX()->setRange(-9,1);
37 37 axisX()->setTicksCount(11);
38 38 m_timer.start();
39 39 }
40 40
41 41 ChartView::~ChartView()
42 42 {
43 43
44 44 }
45 45
46 46 void ChartView::handleTimeout()
47 47 {
48 48 m_x+=m_step;
49 49 m_y = qrand() % 5 - 2.5;
50 50 m_series0->add(m_x,m_y);
51 51 m_series1->add(m_x,m_y);
52 if(m_x>=10)
53 {
54 m_series0->remove(m_x-10);
55 m_series1->remove(m_x-10);
56 }
52 57 scrollRight();
53 58 }
@@ -1,17 +1,20
1 1 INCLUDEPATH += $$PWD
2 2 DEPENDPATH += $$PWD
3 3
4 4 SOURCES += \
5 5 $$PWD/axisanimation.cpp \
6 6 $$PWD/chartanimator.cpp \
7 7 $$PWD/xyanimation.cpp \
8 8 $$PWD/pieanimation.cpp \
9 $$PWD/piesliceanimation.cpp
9 $$PWD/piesliceanimation.cpp \
10 $$PWD/splineanimation.cpp
11
10 12
11 13 PRIVATE_HEADERS += \
12 14 $$PWD/axisanimation_p.h \
13 15 $$PWD/chartanimator_p.h \
14 16 $$PWD/chartanimation_p.h \
15 17 $$PWD/xyanimation_p.h \
16 18 $$PWD/pieanimation_p.h \
17 $$PWD/piesliceanimation_p.h
19 $$PWD/piesliceanimation_p.h \
20 $$PWD/splineanimation_p.h
@@ -1,19 +1,26
1 1 #ifndef CHARTANIMATION_H_
2 2 #define CHARTANIMATION_H_
3 3
4 4 #include "qchartglobal.h"
5 5 #include <QVariantAnimation>
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 class ChartAnimation: public QVariantAnimation
10 10 {
11 11 public:
12 ChartAnimation(QObject* parent=0):QVariantAnimation(parent){};
12 enum Animation { LineDrawAnimation, MoveDownAnimation, MoveUpAnimation };
13 ChartAnimation(QObject* parent=0):QVariantAnimation(parent),m_type(MoveDownAnimation){};
14 void setAnimationType(Animation type){
15 m_type=type;
16 }
17 protected:
18 Animation m_type;
19
13 20 };
14 21
15 22 QTCOMMERCIALCHART_END_NAMESPACE
16 23
17 24
18 25
19 26 #endif /* AXISITEM_H_ */
@@ -1,221 +1,261
1 1 #include "chartanimator_p.h"
2 2 #include "axisanimation_p.h"
3 3 #include "xyanimation_p.h"
4 #include "splineanimation_p.h"
4 5 #include "xychartitem_p.h"
5 6 #include "pieanimation_p.h"
6 7 #include "areachartitem_p.h"
8 #include "splinechartitem_p.h"
9 #include "scatterchartitem_p.h"
7 10 #include <QTimer>
8 11
9 12 Q_DECLARE_METATYPE(QVector<QPointF>)
10 13 Q_DECLARE_METATYPE(QVector<qreal>)
11 14
12 15 QTCOMMERCIALCHART_BEGIN_NAMESPACE
13 16
14 17 const static int duration = 1000;
15 18
16 19 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent)
17 20 {
18 21 }
19 22
20 23 ChartAnimator::~ChartAnimator()
21 24 {
22 25 }
23 26
24 27 void ChartAnimator::addAnimation(AxisItem* item)
25 28 {
26 29 ChartAnimation* animation = m_animations.value(item);
27 30
28 31 if(!animation) {
29 32 animation = new AxisAnimation(item);
30 33 m_animations.insert(item,animation);
31 34 }
32 35
33 36 item->setAnimator(this);
34 37 }
35 38
36 void ChartAnimator::addAnimation(XYChartItem* item)
39 void ChartAnimator::addAnimation(SplineChartItem* item)
40 {
41 ChartAnimation* animation = m_animations.value(item);
42
43 if(!animation) {
44 animation = new SplineAnimation(item);
45 m_animations.insert(item,animation);
46 }
47
48 item->setAnimator(this);
49 }
50
51 void ChartAnimator::addAnimation(ScatterChartItem* item)
52 {
53 ChartAnimation* animation = m_animations.value(item);
54
55 if(!animation) {
56 animation = new XYAnimation(item);
57 m_animations.insert(item,animation);
58 }
59
60 item->setAnimator(this);
61 }
62
63 void ChartAnimator::addAnimation(LineChartItem* item)
37 64 {
38 65 ChartAnimation* animation = m_animations.value(item);
39 66
40 67 if(!animation) {
41 68 animation = new XYAnimation(item);
42 69 m_animations.insert(item,animation);
43 70 }
44 71
45 72 item->setAnimator(this);
46 73 }
47 74
48 75 void ChartAnimator::addAnimation(PieChartItem* item)
49 76 {
50 77 ChartAnimation* animation = m_animations.value(item);
51 78
52 79 if(!animation) {
53 80 animation = new PieAnimation(item);
54 81 m_animations.insert(item,animation);
55 82 }
56 83
57 84 item->setAnimator(this);
58 85 }
59 86
60 87 void ChartAnimator::removeAnimation(ChartItem* item)
61 88 {
62 89 item->setAnimator(0);
63 90 m_animations.remove(item);
64 91 }
65 92
66 93 void ChartAnimator::applyLayout(AxisItem* item , QVector<qreal>& newLayout)
67 94 {
68 95 AxisAnimation* animation = static_cast<AxisAnimation*>(m_animations.value(item));
69 96
70 97 Q_ASSERT(animation);
71 98
72 99 QVector<qreal> oldLayout = item->layout();
73 100
74 101 if(newLayout.count()==0) return;
75 102
76 103 switch(m_state)
77 104 {
78 105 case ZoomOutState: {
79 106 QRectF rect = item->geometry();
80 107 oldLayout.resize(newLayout.count());
81 108
82 109 for(int i=0,j=oldLayout.count()-1;i<(oldLayout.count()+1)/2;i++,j--)
83 110 {
84 111 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.bottom();
85 112 oldLayout[j]= item->axisType()==AxisItem::X_AXIS?rect.right():rect.top();
86 113 }
87 114 }
88 115 break;
89 116 case ZoomInState: {
90 117 int index = qMin(oldLayout.count()*(item->axisType()==AxisItem::X_AXIS?m_point.x():(1 -m_point.y())),newLayout.count()-1.0);
91 118 oldLayout.resize(newLayout.count());
92 119
93 120 for(int i=0;i<oldLayout.count();i++)
94 121 {
95 122 oldLayout[i]= oldLayout[index];
96 123 }
97 124 }
98 125 break;
99 126 case ScrollDownState:
100 127 case ScrollRightState: {
101 128 oldLayout.resize(newLayout.count());
102 129
103 130 for(int i=0, j=i+1;i<oldLayout.count()-1;i++,j++)
104 131 {
105 132 oldLayout[i]= oldLayout[j];
106 133 }
107 134 }
108 135 break;
109 136 case ScrollUpState:
110 137 case ScrollLeftState: {
111 138 oldLayout.resize(newLayout.count());
112 139
113 140 for(int i=oldLayout.count()-1, j=i-1;i>0;i--,j--)
114 141 {
115 142 oldLayout[i]= oldLayout[j];
116 143 }
117 144 }
118 145 break;
119 146 default: {
120 147 oldLayout.resize(newLayout.count());
121 148 QRectF rect = item->geometry();
122 149 for(int i=0, j=oldLayout.count()-1;i<oldLayout.count();i++,j--)
123 150 {
124 151 oldLayout[i]= item->axisType()==AxisItem::X_AXIS?rect.left():rect.top();
125 152 }
126 153 }
127 154 break;
128 155 }
129 156
130 157
131 158 if(animation->state()!=QAbstractAnimation::Stopped) {
132 159 animation->stop();
133 160 }
134 161
135 162 animation->setDuration(duration);
136 163 animation->setEasingCurve(QEasingCurve::OutQuart);
137 164 QVariantAnimation::KeyValues value;
138 165 animation->setKeyValues(value); //workaround for wrong interpolation call
139 166 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
140 167 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
141 168
142 169 QTimer::singleShot(0,animation,SLOT(start()));
143 170 }
144 171
145 void ChartAnimator::applyLayout(XYChartItem* item, QVector<QPointF>& newPoints)
172 void ChartAnimator::updateLayout(SplineChartItem* item, QVector<QPointF>& oldPoints ,QVector<QPointF>& newPoints, QVector<QPointF>& oldControlPoints, QVector<QPointF>& newControlPoints,int index)
146 173 {
147
148 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
174 SplineAnimation* animation = static_cast<SplineAnimation*>(m_animations.value(item));
149 175
150 176 Q_ASSERT(animation);
151 177
152 QVector<QPointF> oldPoints = item->points();
153
154 if(newPoints.count()==0) return;
178 if(newPoints.count()<2 || newControlPoints.count()<2) return;
155 179
156 180 bool empty = oldPoints.count()==0;
157 oldPoints.resize(newPoints.size());
181
158 182
159 183 if(animation->state()!=QAbstractAnimation::Stopped) {
160 animation->stop();
184 animation->stop();
161 185 }
162 186
163 187 animation->setDuration(duration);
164 188 if(!empty)
165 animation->setAnimationType(XYAnimation::MoveDownAnimation);
189 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
166 190 else
167 animation->setAnimationType(XYAnimation::LineDrawAnimation);
191 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
192
168 193 animation->setEasingCurve(QEasingCurve::OutQuart);
169 animation->setValues(oldPoints,newPoints);
194 animation->setValues(oldPoints,newPoints,oldControlPoints,newControlPoints,index);
195
170 196 QTimer::singleShot(0,animation,SLOT(start()));
171 197 }
172 198
173 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& newPoints)
199
200 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& oldPoints , QVector<QPointF>& newPoints, int index)
174 201 {
175 202 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
176 203
177 204 Q_ASSERT(animation);
178 205
206 if(newPoints.count()==0) return;
207
208 bool empty = oldPoints.count()==0;
209
210
211 if(animation->state()!=QAbstractAnimation::Stopped) {
212 animation->stop();
213 }
214
179 215 animation->setDuration(duration);
180 animation->setAnimationType(XYAnimation::MoveDownAnimation);
216 if(!empty)
217 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
218 else
219 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
220
181 221 animation->setEasingCurve(QEasingCurve::OutQuart);
182 animation->updateValues(newPoints);
222 animation->setValues(oldPoints,newPoints,index);
183 223
184 224 QTimer::singleShot(0,animation,SLOT(start()));
185 225 }
186 226
187 227 void ChartAnimator::addAnimation(PieChartItem* item, QPieSlice *slice, PieSliceLayout &layout)
188 228 {
189 229 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
190 230 Q_ASSERT(animation);
191 231 animation->addSlice(slice, layout);
192 232 }
193 233
194 234 void ChartAnimator::removeAnimation(PieChartItem* item, QPieSlice *slice)
195 235 {
196 236 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
197 237 Q_ASSERT(animation);
198 238 animation->removeSlice(slice);
199 239 }
200 240
201 241 void ChartAnimator::updateLayout(PieChartItem* item, QVector<PieSliceLayout> &layout)
202 242 {
203 243 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
204 244 Q_ASSERT(animation);
205 245 animation->updateValues(layout);
206 246 }
207 247
208 248 void ChartAnimator::updateLayout(PieChartItem* item, PieSliceLayout &layout)
209 249 {
210 250 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
211 251 Q_ASSERT(animation);
212 252 animation->updateValue(layout);
213 253 }
214 254
215 255 void ChartAnimator::setState(State state,const QPointF& point)
216 256 {
217 257 m_state=state;
218 258 m_point=point;
219 259 }
220 260
221 261 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,50 +1,53
1 1 #ifndef CHARTANIMATOR_P_H_
2 2 #define CHARTANIMATOR_P_H_
3 3 #include "qchartglobal.h"
4 4 #include "chartanimation_p.h"
5 5 #include "piechartitem_p.h"
6 6 #include <QPointF>
7 7
8 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 9
10 10 class ChartItem;
11 class XYChartItem;
12 11 class AxisItem;
13 12 class AreaChartItem;
14
13 class SplineChartItem;
14 class ScatterChartItem;
15 class LineChartItem;
16 class XYChartItem;
15 17
16 18 class ChartAnimator : public QObject {
17 19
18 20 public:
19 21 //TODO: this should be flags in case of two state at the time
20 22 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState,ScrollRightState,ZoomInState,ZoomOutState};
21 23 ChartAnimator(QObject *parent = 0);
22 24 virtual ~ChartAnimator();
23 25
24 26 void addAnimation(AxisItem* item);
25 void addAnimation(XYChartItem* item);
26 27 void addAnimation(PieChartItem* item);
27
28 void addAnimation(ScatterChartItem* item);
29 void addAnimation(LineChartItem* item);
30 void addAnimation(SplineChartItem* item);
28 31 void removeAnimation(ChartItem* item);
29 32
30 33 void animationStarted();
31 void applyLayout(XYChartItem* item, QVector<QPointF>& layout);
32 void updateLayout(XYChartItem* item, QVector<QPointF>& layout);
34 void updateLayout(XYChartItem* item, QVector<QPointF>& oldLayout,QVector<QPointF>& newLayout,int index);
35 void updateLayout(SplineChartItem* item, QVector<QPointF>& oldPoints , QVector<QPointF>& newPoints, QVector<QPointF>& oldControlPoints, QVector<QPointF>& newContorlPoints,int index);
33 36 void applyLayout(AxisItem* item, QVector<qreal>& layout);
34 37
35 38 void addAnimation(PieChartItem* item, QPieSlice *slice, PieSliceLayout &layout);
36 39 void removeAnimation(PieChartItem* item, QPieSlice *slice);
37 40 void updateLayout(PieChartItem* item, QVector<PieSliceLayout> &layout);
38 41 void updateLayout(PieChartItem* item, PieSliceLayout &layout);
39 42
40 43 void setState(State state,const QPointF& point = QPointF());
41 44
42 45 private:
43 46 QMap<ChartItem*,ChartAnimation*> m_animations;
44 47 State m_state;
45 48 QPointF m_point;
46 49 };
47 50
48 51 QTCOMMERCIALCHART_END_NAMESPACE
49 52
50 53 #endif
@@ -1,97 +1,88
1 1 #include "xyanimation_p.h"
2 2 #include "xychartitem_p.h"
3 3
4 4 Q_DECLARE_METATYPE(QVector<QPointF>)
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 XYAnimation::XYAnimation(XYChartItem *item):ChartAnimation(item),
9 9 m_item(item),
10 m_type(MoveDownAnimation),
11 10 m_dirty(false)
12 11 {
13 12 }
14 13
15 14 XYAnimation::~XYAnimation()
16 15 {
17 16 }
18 17
19 void XYAnimation::setAnimationType(Animation type)
18 void XYAnimation::setValues(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,int index)
20 19 {
21 m_type=type;
22 }
23
24 void XYAnimation::setValues(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints)
25 {
26 setKeyValueAt(0.0, qVariantFromValue(oldPoints));
27 setKeyValueAt(1.0, qVariantFromValue(newPoints));
28 m_points = newPoints;
29 m_dirty=false;
30 }
31 20
32 void XYAnimation::updateValues(QVector<QPointF>& newPoints)
33 {
34 if(state()!=QAbstractAnimation::Stopped) {
35 stop();
36 m_dirty=true;
37 }
21 int x = oldPoints.count();
22 int y = newPoints.count();
38 23
39 if(m_dirty) {
40 m_points=newPoints;
24 if(x!=y && abs(x-y)!=1) {
25 m_oldPoints = newPoints;
26 oldPoints.resize(newPoints.size());
27 setKeyValueAt(0.0, qVariantFromValue(oldPoints));
28 setKeyValueAt(1.0, qVariantFromValue(newPoints));
41 29 m_dirty=false;
42 30 }
43
44 setKeyValueAt(0.0, qVariantFromValue(m_points));
45 setKeyValueAt(1.0, qVariantFromValue(newPoints));
31 else {
32 if(m_dirty) {
33 m_oldPoints = oldPoints;
34 m_dirty=false;
35 }
36 oldPoints = newPoints;
37 if (y<x) (m_oldPoints.remove(index)); //remove
38 if (y>x) (m_oldPoints.insert(index,x>0?m_oldPoints[index-1]:newPoints[index])); //add
39 setKeyValueAt(0.0, qVariantFromValue(m_oldPoints));
40 setKeyValueAt(1.0, qVariantFromValue(newPoints));
41 Q_ASSERT(m_oldPoints.count() == newPoints.count());
42 }
46 43 }
47 44
48 45 QVariant XYAnimation::interpolated(const QVariant &start, const QVariant & end, qreal progress ) const
49 46 {
50 47 QVector<QPointF> startVector = qVariantValue<QVector<QPointF> >(start);
51 48 QVector<QPointF> endVector = qVariantValue<QVector<QPointF> >(end);
52 49 QVector<QPointF> result;
53 50
54 51 switch(m_type) {
55 52
56 53 case MoveDownAnimation: {
57 54
58 55 if(startVector.count() != endVector.count()) break;
59 56
60 57 for(int i =0;i< startVector.count();i++) {
61 58 qreal x = startVector[i].x() + ((endVector[i].x()- startVector[i].x()) * progress);
62 59 qreal y = startVector[i].y() + ((endVector[i].y()- startVector[i].y()) * progress);
63 60 result << QPointF(x,y);
64 61 }
65 62
66 63 }
67 64 break;
68 65 case LineDrawAnimation:{
69 66 for(int i =0;i< endVector.count()* qBound(0.0, progress, 1.0);i++) {
70 67 result << endVector[i];
71 68 }
72 69 }
73 70 break;
74 71 default:
75 72 qWarning()<<"Unknow type of animation";
76 73 break;
77 74 }
78 75
79 76 return qVariantFromValue(result);
80 77 }
81 78
82 79 void XYAnimation::updateCurrentValue (const QVariant & value )
83 80 {
84 81 if(state()!=QAbstractAnimation::Stopped){ //workaround
82 m_dirty=true;
85 83 QVector<QPointF> vector = qVariantValue<QVector<QPointF> >(value);
86 84 m_item->setLayout(vector);
87 85 }
88 86 }
89 87
90 void XYAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
91 {
92 Q_UNUSED(oldState)
93 if (newState==QAbstractAnimation::Running) m_dirty=true;
94 QVariantAnimation::updateState(newState,oldState);
95 }
96
97 88 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,34 +1,30
1 1 #ifndef XYCHARTANIMATION_P_H_
2 2 #define XYCHARTANIMATION_P_H_
3 3 #include "chartanimation_p.h"
4 4 #include <QPointF>
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 class XYChartItem;
9 9
10 10 class XYAnimation : public ChartAnimation
11 11 {
12 12 public:
13 13 enum Animation { LineDrawAnimation, MoveDownAnimation, MoveUpAnimation };
14 14 XYAnimation(XYChartItem *item);
15 15 ~XYAnimation();
16 void setAnimationType(Animation type);
17 void setValues(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints);
18 void updateValues(QVector<QPointF>& newPoints);
16 void setValues(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,int index);
19 17
20 18 protected:
21 19 QVariant interpolated(const QVariant &start, const QVariant & end, qreal progress ) const;
22 20 void updateCurrentValue (const QVariant & value );
23 void updateState ( QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
24 21
25 22 private:
26 23 XYChartItem *m_item;
27 Animation m_type;
28 QVector<QPointF> m_points;
24 QVector<QPointF> m_oldPoints;
29 25 bool m_dirty;
30 26 };
31 27
32 28 QTCOMMERCIALCHART_END_NAMESPACE
33 29
34 30 #endif
@@ -1,82 +1,83
1 1 #include "linechartitem_p.h"
2 2 #include "qlineseries.h"
3 3 #include "chartpresenter_p.h"
4 4 #include <QPainter>
5 5
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 //TODO: optimize : remove points which are not visible
10 10
11 11 LineChartItem::LineChartItem(QLineSeries* series,QGraphicsItem *parent):XYChartItem(series,parent),
12 12 m_series(series),
13 13 m_pointsVisible(false)
14 14 {
15 15 setZValue(ChartPresenter::LineChartZValue);
16 16 QObject::connect(series,SIGNAL(updated()),this,SLOT(handleUpdated()));
17 17 handleUpdated();
18 18 }
19 19
20 20 QRectF LineChartItem::boundingRect() const
21 21 {
22 22 return m_rect;
23 23 }
24 24
25 25 QPainterPath LineChartItem::shape() const
26 26 {
27 27 return m_path;
28 28 }
29 29
30 30 void LineChartItem::setLayout(QVector<QPointF>& points)
31 31 {
32 32 if(points.size()==0)
33 33 {
34 34 XYChartItem::setLayout(points);
35 35 return;
36 36 }
37 37
38 38 QList<QGraphicsItem*> items = m_items.childItems();
39 39
40 40 QPainterPath linePath(points.at(0));
41 41
42 42 for(int i=1; i< points.size();i++) {
43 43 linePath.lineTo(points.at(i));
44 44 }
45 45
46 46 prepareGeometryChange();
47 47 m_path = linePath;
48 48 m_rect = linePath.boundingRect();
49 49
50 50 XYChartItem::setLayout(points);
51
51 52 }
52 53
53 54 void LineChartItem::handleUpdated()
54 55 {
55 56 m_pointsVisible = m_series->pointsVisible();
56 57 m_linePen = m_series->pen();
57 58 m_pointPen = m_series->pen();
58 59 m_pointPen.setWidthF(2*m_pointPen.width());
59 60 update();
60 61 }
61 62
62 63 //painter
63 64
64 65 void LineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
65 66 {
66 67 Q_UNUSED(widget)
67 68 Q_UNUSED(option)
68 69
69 70 painter->save();
70 71 painter->setPen(m_linePen);
71 72 painter->setClipRect(clipRect());
72 73 painter->drawPath(m_path);
73 74 if(m_pointsVisible){
74 75 painter->setPen(m_pointPen);
75 76 painter->drawPoints(points());
76 77 }
77 78 painter->restore();
78 79 }
79 80
80 81 #include "moc_linechartitem_p.cpp"
81 82
82 83 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,90 +1,116
1 1 #include "splinechartitem_p.h"
2 2 #include "chartpresenter_p.h"
3 #include "chartanimator_p.h"
3 4 #include <QPainter>
4 5
5 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
6 7
7 8 SplineChartItem::SplineChartItem(QSplineSeries* series, QGraphicsItem *parent) :
8 9 XYChartItem(series, parent),
9 10 m_series(series),
10 11 m_pointsVisible(false)
11 12 {
12 13 setZValue(ChartPresenter::LineChartZValue);
13 14 QObject::connect(series,SIGNAL(updated()),this,SLOT(handleUpdated()));
14 15 handleUpdated();
15 16 }
16 17
17 18 QRectF SplineChartItem::boundingRect() const
18 19 {
19 20 return m_rect;
20 21 }
21 22
22 23 QPainterPath SplineChartItem::shape() const
23 24 {
24 25 return m_path;
25 26 }
26 27
28 void SplineChartItem::updateLayout(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,int index)
29 {
30 QVector<QPointF> controlPoints;
31
32 controlPoints.resize(newPoints.count()*2-2);
33
34 for (int i = 0; i < newPoints.size() - 1; i++)
35 {
36 controlPoints[2*i] = calculateGeometryControlPoint(2 * i);
37 controlPoints[2 * i + 1] = calculateGeometryControlPoint(2 * i + 1);
38 }
39
40 if(controlPoints.count()<2) {
41 setLayout(newPoints,controlPoints);
42 return;
43 }
44
45 if(m_animator){
46 m_animator->updateLayout(this,oldPoints,newPoints,m_controlPoints,controlPoints,index);
47 }else{
48 setLayout(newPoints,controlPoints);
49 }
50 }
51
27 52 QPointF SplineChartItem::calculateGeometryControlPoint(int index) const
28 53 {
29 54 return XYChartItem::calculateGeometryPoint(m_series->controlPoint(index));
30 55 }
31 56
32 void SplineChartItem::setLayout(QVector<QPointF>& points)
57 void SplineChartItem::setLayout(QVector<QPointF>& points,QVector<QPointF>& controlPoints)
33 58 {
34
35 if(points.size()==0)
59 if(points.size()<2 || controlPoints.size()<2)
36 60 {
37 61 XYChartItem::setLayout(points);
62 m_controlPoints=controlPoints;
38 63 return;
39 64 }
40 65
41 QPainterPath splinePath;
42 const QPointF& point = points.at(0);
43 splinePath.moveTo(point);
66 Q_ASSERT(points.count()*2-2 == controlPoints.count());
67
68 QPainterPath splinePath(points.at(0));
44 69
45 70 for (int i = 0; i < points.size() - 1; i++)
46 71 {
47 72 const QPointF& point = points.at(i + 1);
48 splinePath.cubicTo(calculateGeometryControlPoint(2 * i), calculateGeometryControlPoint(2 * i + 1), point);
73 splinePath.cubicTo(controlPoints[2*i],controlPoints[2 * i + 1],point);
49 74 }
50 75
51 76 prepareGeometryChange();
52 77 m_path = splinePath;
53 78 m_rect = splinePath.boundingRect();
54 79 XYChartItem::setLayout(points);
80 m_controlPoints=controlPoints;
55 81 }
56 82
57 83 //handlers
58 84
59 85 void SplineChartItem::handleUpdated()
60 86 {
61 87 m_pointsVisible = m_series->pointsVisible();
62 88 m_linePen = m_series->pen();
63 89 m_pointPen = m_series->pen();
64 90 m_pointPen.setWidthF(2*m_pointPen.width());
65 91 update();
66 92 }
67 93
68 94 //painter
69 95
70 96 void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
71 97 {
72 98 Q_UNUSED(widget)
73 99 Q_UNUSED(option)
74 100
75 101 painter->save();
76 102 painter->setClipRect(clipRect());
77 103 painter->setPen(m_linePen);
78 104 painter->drawPath(m_path);
79 105 if(m_pointsVisible){
80 106 painter->setPen(m_pointPen);
81 107 painter->drawPoints(points());
82 108 }
83 109 painter->restore();
84 110 }
85 111
86 112
87 113
88 114 #include "moc_splinechartitem_p.cpp"
89 115
90 116 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,42 +1,46
1 1 #ifndef SPLINECHARTITEM_P_H
2 2 #define SPLINECHARTITEM_P_H
3 3
4 4 #include "qsplineseries.h"
5 5 #include "xychartitem_p.h"
6 6 #include <QGraphicsItem>
7 7
8
8 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 10
10 11 class SplineChartItem : public XYChartItem
11 12 {
12 13 Q_OBJECT
13 14 public:
14 15 SplineChartItem(QSplineSeries* series, QGraphicsItem *parent = 0);
15 16
16 17 //from QGraphicsItem
17 18 QRectF boundingRect() const;
18 19 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
19 20 QPainterPath shape() const;
20 21
21 22 public slots:
22 23 void handleUpdated();
23 24
24 25 protected:
25 void setLayout(QVector<QPointF>& points);
26 void setLayout(QVector<QPointF>& points,QVector<QPointF>& controlPoints);
27 void updateLayout(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,int index);
26 28
27 29 private:
28 30 QPointF calculateGeometryControlPoint(int index) const;
29 31
30 32 private:
31 33 QSplineSeries* m_series;
32 34 QPainterPath m_path;
33 35 QRectF m_rect;
34 36 QPen m_linePen;
35 37 QPen m_pointPen;
36 38 bool m_pointsVisible;
39 QVector<QPointF> m_controlPoints;
37 40
41 friend class SplineAnimation;
38 42 };
39 43
40 44 QTCOMMERCIALCHART_END_NAMESPACE
41 45
42 46 #endif // SPLINECHARTITEM_P_H
@@ -1,318 +1,333
1 1 #include "qxyseries.h"
2 2
3 3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4 4
5 5 /*!
6 6 \class QXYSeries
7 7 \brief The QXYSeries class is a base class for line, spline and scatter series.
8 8 */
9 9
10 10 /*!
11 11 \fn QPen QXYSeries::pen() const
12 12 \brief Returns pen used to draw points for series.
13 13 \sa setPen()
14 14 */
15 15
16 16 /*!
17 17 \fn QBrush QXYSeries::brush() const
18 18 \brief Returns brush used to draw points for series.
19 19 \sa setBrush()
20 20 */
21 21
22 22 /*!
23 23 \fn void QXYSeries::clicked(const QPointF& point)
24 24 \brief Signal is emitted when user clicks the \a point on chart.
25 25 */
26 26
27 27 /*!
28 28 \fn void QXYSeries::pointReplaced(int index)
29 29 \brief \internal \a index
30 30 */
31 31
32 32 /*!
33 33 \fn void QXYSeries::pointAdded(int index)
34 34 \brief \internal \a index
35 35 */
36 36
37 37 /*!
38 38 \fn void QXYSeries::pointRemoved(int index)
39 39 \brief \internal \a index
40 40 */
41 41
42 42 /*!
43 43 \fn void QXYSeries::updated()
44 44 \brief \internal
45 45 */
46 46
47 47 /*!
48 48 Constructs empty series object which is a child of \a parent.
49 49 When series object is added to QChartView or QChart instance ownerships is transfered.
50 50 */
51 51 QXYSeries::QXYSeries(QObject* parent):QSeries(parent)
52 52 {
53 53 m_mapX = -1;
54 54 m_mapY = -1;
55 55 m_mapOrientation = Qt::Vertical;
56 56 // m_mapYOrientation = Qt::Vertical;
57 57 }
58 58 /*!
59 59 Destroys the object. Series added to QChartView or QChart instances are owned by those,
60 60 and are deleted when mentioned object are destroyed.
61 61 */
62 62 QXYSeries::~QXYSeries()
63 63 {
64 64 }
65 65
66 66 /*!
67 67 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
68 68 */
69 69 void QXYSeries::add(qreal x,qreal y)
70 70 {
71 71 Q_ASSERT(m_x.size() == m_y.size());
72 72 m_x<<x;
73 73 m_y<<y;
74 74 emit pointAdded(m_x.size()-1);
75 75 }
76 76
77 77 /*!
78 78 This is an overloaded function.
79 79 Adds data \a point to the series. Points are connected with lines on the chart.
80 80 */
81 81 void QXYSeries::add(const QPointF& point)
82 82 {
83 83 add(point.x(),point.y());
84 84 }
85 85
86 86 /*!
87 87 This is an overloaded function.
88 88 Adds list of data \a points to the series. Points are connected with lines on the chart.
89 89 */
90 90 void QXYSeries::add(const QList<QPointF> points)
91 91 {
92 92 foreach(const QPointF& point , points) {
93 93 add(point.x(),point.y());
94 94 }
95 95 }
96 96
97 97 /*!
98 98 Modifies \a y value for given \a x a value.
99 99 */
100 100 void QXYSeries::replace(qreal x,qreal y)
101 101 {
102 102 int index = m_x.indexOf(x);
103 103 m_x[index]=x;
104 104 m_y[index]=y;
105 105 emit pointReplaced(index);
106 106 }
107 107
108 108 /*!
109 109 This is an overloaded function.
110 110 Replaces current y value of for given \a point x value with \a point y value.
111 111 */
112 112 void QXYSeries::replace(const QPointF& point)
113 113 {
114 114 replace(point.x(),point.y());
115 115 }
116 116
117 117 /*!
118 Removes first \a x value and related y value.
119 */
120 void QXYSeries::remove(qreal x)
121 {
122 int index = m_x.indexOf(x);
123
124 if(index==-1) return;
125
126 m_x.remove(index);
127 m_y.remove(index);
128
129 emit pointRemoved(index);
130 }
131
132 /*!
118 133 Removes current \a x and \a y value.
119 134 */
120 135 void QXYSeries::remove(qreal x,qreal y)
121 136 {
122 137 int index =-1;
123 138 do{
124 139 index = m_x.indexOf(x,index+1);
125 140 }while(index !=-1 && m_y.at(index)!=y);
126 141
127 142 if(index==-1) return;
128 143
129 144 m_x.remove(index);
130 145 m_y.remove(index);
131 146 emit pointRemoved(index);
132 147 }
133 148
134 149 /*!
135 150 Removes current \a point x value. Note \a point y value is ignored.
136 151 */
137 152 void QXYSeries::remove(const QPointF& point)
138 153 {
139 154 remove(point.x(),point.y());
140 155 }
141 156
142 157 /*!
143 158 Removes all data points from the series.
144 159 */
145 160 void QXYSeries::removeAll()
146 161 {
147 162 m_x.clear();
148 163 m_y.clear();
149 164 }
150 165
151 166 /*!
152 167 \internal \a pos
153 168 */
154 169 qreal QXYSeries::x(int pos) const
155 170 {
156 171 if (m_model)
157 172 if (m_mapOrientation == Qt::Vertical)
158 173 // consecutive data is read from model's column
159 174 return m_model->data(m_model->index(pos, m_mapX), Qt::DisplayRole).toDouble();
160 175 else
161 176 // consecutive data is read from model's row
162 177 return m_model->data(m_model->index(m_mapX, pos), Qt::DisplayRole).toDouble();
163 178 else
164 179 // model is not specified, return the data from series' internal data store
165 180 return m_x.at(pos);
166 181 }
167 182
168 183 /*!
169 184 \internal \a pos
170 185 */
171 186 qreal QXYSeries::y(int pos) const
172 187 {
173 188 if (m_model)
174 189 if (m_mapOrientation == Qt::Vertical)
175 190 // consecutive data is read from model's column
176 191 return m_model->data(m_model->index(pos, m_mapY), Qt::DisplayRole).toDouble();
177 192 else
178 193 // consecutive data is read from model's row
179 194 return m_model->data(m_model->index(m_mapY, pos), Qt::DisplayRole).toDouble();
180 195 else
181 196 // model is not specified, return the data from series' internal data store
182 197 return m_y.at(pos);
183 198 }
184 199
185 200 /*!
186 201 Returns number of data points within series.
187 202 */
188 203 int QXYSeries::count() const
189 204 {
190 205 Q_ASSERT(m_x.size() == m_y.size());
191 206
192 207 if (m_model) {
193 208 if (m_mapOrientation == Qt::Vertical)
194 209 // data is in a column, so return the number of items in single column
195 210 return m_model->rowCount();
196 211 else
197 212 // data is in a row, so return the number of items in single row
198 213 return m_model->columnCount();
199 214 }
200 215
201 216 // model is not specified, return the number of points in the series internal data store
202 217 return m_x.size();
203 218 }
204 219
205 220 /*!
206 221 Returns the data points of the series.
207 222 */
208 223 QList<QPointF> QXYSeries::data()
209 224 {
210 225 QList<QPointF> data;
211 226 for (int i(0); i < m_x.count() && i < m_y.count(); i++)
212 227 data.append(QPointF(m_x.at(i), m_y.at(i)));
213 228 return data;
214 229 }
215 230
216 231
217 232 /*!
218 233 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
219 234 pen from chart theme is used.
220 235 \sa QChart::setChartTheme()
221 236 */
222 237 void QXYSeries::setPen(const QPen& pen)
223 238 {
224 239 if(pen!=m_pen){
225 240 m_pen=pen;
226 241 emit updated();
227 242 }
228 243 }
229 244
230 245 /*!
231 246 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
232 247 from chart theme setting is used.
233 248 \sa QChart::setChartTheme()
234 249 */
235 250
236 251 void QXYSeries::setBrush(const QBrush& brush)
237 252 {
238 253 if(brush!=m_brush){
239 254 m_brush=brush;
240 255 emit updated();
241 256 }
242 257 }
243 258
244 259
245 260 /*!
246 261 Stream operator for adding a data \a point to the series.
247 262 \sa add()
248 263 */
249 264
250 265 QXYSeries& QXYSeries::operator<< (const QPointF &point)
251 266 {
252 267 add(point);
253 268 return *this;
254 269 }
255 270
256 271
257 272 /*!
258 273 Stream operator for adding a list of \a points to the series.
259 274 \sa add()
260 275 */
261 276
262 277 QXYSeries& QXYSeries::operator<< (const QList<QPointF> points)
263 278 {
264 279 add(points);
265 280 return *this;
266 281 }
267 282
268 283
269 284 void QXYSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
270 285 {
271 286 Q_UNUSED(bottomRight)
272 287
273 288 if (m_mapOrientation == Qt::Vertical)
274 289 emit pointReplaced(topLeft.row());
275 290 else
276 291 emit pointReplaced(topLeft.column());
277 292 }
278 293
279 294 void QXYSeries::modelDataAdded(QModelIndex parent, int start, int end)
280 295 {
281 296 Q_UNUSED(parent)
282 297 Q_UNUSED(end)
283 298 emit pointAdded(start);
284 299 }
285 300
286 301 void QXYSeries::modelDataRemoved(QModelIndex parent, int start, int end)
287 302 {
288 303 Q_UNUSED(parent)
289 304 Q_UNUSED(end)
290 305 emit pointRemoved(start);
291 306 }
292 307
293 308 bool QXYSeries::setModel(QAbstractItemModel* model) {
294 309 m_model = model;
295 310 // for (int i = 0; i < m_model->rowCount(); i++)
296 311 // emit pointAdded(i);
297 312 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
298 313 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
299 314 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
300 315 return true;
301 316 }
302 317
303 318 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
304 319 {
305 320 m_mapX = modelX;
306 321 m_mapY = modelY;
307 322 m_mapOrientation = orientation;
308 323 }
309 324
310 325 //void QXYSeries::setModelMappingY(int modelLineIndex, Qt::Orientation orientation)
311 326 //{
312 327 // m_mapY = modelLineIndex;
313 328 // m_mapYOrientation = orientation;
314 329 //}
315 330
316 331 #include "moc_qxyseries.cpp"
317 332
318 333 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,76 +1,77
1 1 #ifndef QXYSERIES_H_
2 2 #define QXYSERIES_H_
3 3
4 4 #include "qchartglobal.h"
5 5 #include "qseries.h"
6 6 #include <QDebug>
7 7 #include <QPen>
8 8 #include <QBrush>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class QTCOMMERCIALCHART_EXPORT QXYSeries : public QSeries
13 13 {
14 14 Q_OBJECT
15 15 protected:
16 16 QXYSeries(QObject* parent=0);
17 17 virtual ~QXYSeries();
18 18
19 19 public:
20 20 void add(qreal x, qreal y);
21 21 void add(const QPointF& point);
22 22 void add(const QList<QPointF> points);
23 23 void replace(qreal x,qreal y);
24 24 void replace(const QPointF& point);
25 void remove(qreal x);
25 26 void remove(qreal x, qreal y);
26 27 void remove(const QPointF& point);
27 28 void removeAll();
28 29
29 30 int count() const;
30 31 qreal x(int pos) const;
31 32 qreal y(int pos) const;
32 33 QList<QPointF> data();
33 34
34 35 QXYSeries& operator << (const QPointF &point);
35 36 QXYSeries& operator << (const QList<QPointF> points);
36 37
37 38 void setPen(const QPen& pen);
38 39 QPen pen() const {return m_pen;}
39 40 void setBrush(const QBrush& pen);
40 41 QBrush brush() const {return m_brush;}
41 42
42 43 bool setModel(QAbstractItemModel* model);
43 44 QAbstractItemModel* model() {return m_model;}
44 45
45 46 virtual void setModelMapping(int modelX, int modelY, Qt::Orientation orientation = Qt::Vertical);
46 47 // void setModelMappingY(int modelLineIndex, Qt::Orientation orientation = Qt::Vertical);
47 48
48 49 private slots:
49 50 void modelUpdated(QModelIndex topLeft, QModelIndex bottomRight);
50 51 void modelDataAdded(QModelIndex parent, int start, int end);
51 52 void modelDataRemoved(QModelIndex parent, int start, int end);
52 53
53 54 signals:
54 55 void clicked(const QPointF& point);
55 56 void updated();
56 57 void pointReplaced(int index);
57 58 void pointRemoved(int index);
58 59 void pointAdded(int index);
59 60
60 61 protected:
61 62 QVector<qreal> m_x;
62 63 QVector<qreal> m_y;
63 64
64 65 QPen m_pen;
65 66 QBrush m_brush;
66 67
67 68 // QAbstractItemModel* m_model;
68 69 int m_mapX;
69 70 Qt::Orientation m_mapOrientation;
70 71 int m_mapY;
71 72 // Qt::Orientation m_mapYOrientation;
72 73 };
73 74
74 75 QTCOMMERCIALCHART_END_NAMESPACE
75 76
76 77 #endif
@@ -1,161 +1,157
1 1 #include "xychartitem_p.h"
2 2 #include "qxyseries.h"
3 3 #include "chartpresenter_p.h"
4 4 #include "chartanimator_p.h"
5 5 #include <QPainter>
6 6 #include <QGraphicsSceneMouseEvent>
7 7
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 //TODO: optimize : remove points which are not visible
12 12
13 13 XYChartItem::XYChartItem(QXYSeries* series, QGraphicsItem *parent):ChartItem(parent),
14 14 m_minX(0),
15 15 m_maxX(0),
16 16 m_minY(0),
17 17 m_maxY(0),
18 18 m_series(series)
19 19 {
20 20 QObject::connect(series,SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
21 21 QObject::connect(series,SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
22 22 QObject::connect(series,SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
23 23 QObject::connect(this,SIGNAL(clicked(const QPointF&)),series,SIGNAL(clicked(const QPointF&)));
24 24 }
25 25
26 26 QPointF XYChartItem::calculateGeometryPoint(const QPointF& point) const
27 27 {
28 28 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
29 29 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
30 30 qreal x = (point.x() - m_minX)* deltaX;
31 31 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
32 32 return QPointF(x,y);
33 33 }
34 34
35 35
36 36 QPointF XYChartItem::calculateGeometryPoint(int index) const
37 37 {
38 38 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
39 39 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
40 40 qreal x = (m_series->x(index) - m_minX)* deltaX;
41 41 qreal y = (m_series->y(index) - m_minY)*-deltaY + m_size.height();
42 42 return QPointF(x,y);
43 43 }
44 44
45 45 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
46 46 {
47 47 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
48 48 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
49 49
50 50 QVector<QPointF> points;
51 51 points.reserve(m_series->count());
52 52 for (int i = 0; i < m_series->count(); ++i) {
53 53 qreal x = (m_series->x(i) - m_minX)* deltaX;
54 54 qreal y = (m_series->y(i) - m_minY)*-deltaY + m_size.height();
55 55 points << QPointF(x,y);
56 56 }
57 57 return points;
58 58 }
59 59
60 60 QPointF XYChartItem::calculateDomainPoint(const QPointF& point) const
61 61 {
62 62 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
63 63 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
64 64 qreal x = point.x()/deltaX +m_minX;
65 65 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
66 66 return QPointF(x,y);
67 67 }
68 68
69 void XYChartItem::applyLayout(QVector<QPointF>& points)
69 void XYChartItem::updateLayout(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,int index)
70 70 {
71 71 if(m_animator){
72 m_animator->applyLayout(this,points);
72 m_animator->updateLayout(this,oldPoints,newPoints,index);
73 }else{
74 setLayout(newPoints);
73 75 }
74 else setLayout(points);
75
76 }
77
78 void XYChartItem::updateLayout(QVector<QPointF>& points)
79 {
80 setLayout(points);
81 76 }
82 77
83 78 void XYChartItem::setLayout(QVector<QPointF>& points)
84 79 {
85 80 m_points = points;
81 update();
86 82 }
87 83
88 84 //handlers
89 85
90 86 void XYChartItem::handlePointAdded(int index)
91 87 {
92 88 Q_ASSERT(index<m_series->count());
93 89 Q_ASSERT(index>=0);
94
90 qDebug()<<__FUNCTION__<<index;
95 91 QPointF point = calculateGeometryPoint(index);
96 92 QVector<QPointF> points = m_points;
97 points.insert(index-1,point);
98 updateLayout(points);
93 points.insert(index,point);
94 updateLayout(m_points,points,index);
99 95 update();
100 96 }
101 97 void XYChartItem::handlePointRemoved(int index)
102 98 {
103 99 Q_ASSERT(index<m_series->count() + 1);
104 100 Q_ASSERT(index>=0);
105 101 QVector<QPointF> points = m_points;
106 102 points.remove(index);
107 updateLayout(points);
103 updateLayout(m_points,points,index);
108 104 update();
109 105 }
110 106
111 107 void XYChartItem::handlePointReplaced(int index)
112 108 {
113 109 Q_ASSERT(index<m_series->count());
114 110 Q_ASSERT(index>=0);
115 111 QPointF point = calculateGeometryPoint(index);
116 112 QVector<QPointF> points = m_points;
117 113 points.replace(index,point);
118 updateLayout(points);
114 updateLayout(m_points,points,index);
119 115 update();
120 116 }
121 117
122 118 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
123 119 {
124 120 m_minX=minX;
125 121 m_maxX=maxX;
126 122 m_minY=minY;
127 123 m_maxY=maxY;
128 124
129 125 if(isEmpty()) return;
130 126 QVector<QPointF> points = calculateGeometryPoints();
131 applyLayout(points);
127 updateLayout(m_points,points);
132 128 update();
133 129 }
134 130
135 131 void XYChartItem::handleGeometryChanged(const QRectF& rect)
136 132 {
137 133 Q_ASSERT(rect.isValid());
138 134 m_size=rect.size();
139 135 m_clipRect=rect.translated(-rect.topLeft());
140 136 setPos(rect.topLeft());
141 137
142 138 if(isEmpty()) return;
143 139 QVector<QPointF> points = calculateGeometryPoints();
144 applyLayout(points);
140 updateLayout(m_points,points);
145 141 update();
146 142 }
147 143
148 144
149 145 bool XYChartItem::isEmpty()
150 146 {
151 147 return !m_clipRect.isValid() || m_maxX - m_minX == 0 || m_maxY - m_minY ==0 ;
152 148 }
153 149
154 150 void XYChartItem::mousePressEvent( QGraphicsSceneMouseEvent * event )
155 151 {
156 152 emit clicked(calculateDomainPoint(event->pos()));
157 153 }
158 154
159 155 #include "moc_xychartitem_p.cpp"
160 156
161 157 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,63 +1,62
1 1 #ifndef XYCHARTITEM_H
2 2 #define XYCHARTITEM_H
3 3
4 4 #include "qchartglobal.h"
5 5 #include "chartitem_p.h"
6 6 #include <QPen>
7 7
8 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 9
10 10 class ChartPresenter;
11 11 class QXYSeries;
12 12
13 13 class XYChartItem : public QObject , public ChartItem
14 14 {
15 15 Q_OBJECT
16 16 public:
17 17 explicit XYChartItem(QXYSeries* series, QGraphicsItem *parent = 0);
18 18 ~ XYChartItem(){};
19 19
20 20 QVector<QPointF> points() const {return m_points;}
21 21 QRectF clipRect() const { return m_clipRect;}
22 22
23 23 public slots:
24 24 void handlePointAdded(int index);
25 25 void handlePointRemoved(int index);
26 26 void handlePointReplaced(int index);
27 27 void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY);
28 28 void handleGeometryChanged(const QRectF& size);
29 29
30 30 signals:
31 31 void clicked(const QPointF& point);
32 32
33 33 protected:
34 34 virtual void setLayout(QVector<QPointF>& points);
35 virtual void updateLayout(QVector<QPointF>& oldPoints,QVector<QPointF>& newPoints,int index = 0);
35 36 QPointF calculateGeometryPoint(const QPointF& point) const;
36 37 QPointF calculateGeometryPoint(int index) const;
37 38 QPointF calculateDomainPoint(const QPointF& point) const;
38 39 QVector<QPointF> calculateGeometryPoints() const;
39 40 void mousePressEvent( QGraphicsSceneMouseEvent * event );
40 41
41 42 private:
42 void applyLayout(QVector<QPointF>& points);
43 void updateLayout(QVector<QPointF>& points);
44 43 inline bool isEmpty();
45 44
46 45 private:
47 46 qreal m_minX;
48 47 qreal m_maxX;
49 48 qreal m_minY;
50 49 qreal m_maxY;
51 50 QXYSeries* m_series;
52 51 QSizeF m_size;
53 52 QRectF m_clipRect;
54 53 QVector<QPointF> m_points;
55 54
56 55 friend class XYAnimation;
57 56 friend class AreaChartItem;
58 57
59 58 };
60 59
61 60 QTCOMMERCIALCHART_END_NAMESPACE
62 61
63 62 #endif
General Comments 0
You need to be logged in to leave comments. Login now