##// END OF EJS Templates
barchart animation mechanics working. still some todo
sauimone -
r681:223051b363f0
parent child
Show More
@@ -1,49 +1,55
1 1 #include "baranimation_p.h"
2 2 #include "barchartitem_p.h"
3 3 #include <QParallelAnimationGroup>
4 4 #include <QTimer>
5 5
6 Q_DECLARE_METATYPE(QVector<QSizeF>)
6 Q_DECLARE_METATYPE(QVector<QRectF>)
7 //Q_DECLARE_METATYPE(BarLayout) // TODO?
8
7 9
8 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
9 11
10 12 BarAnimation::BarAnimation(BarChartItem *item)
11 13 :ChartAnimation(item),
12 14 m_item(item)
13 15 {
14 16 }
15 17
16 18 BarAnimation::~BarAnimation()
17 19 {
18 20 }
19 21
20 void BarAnimation::updateValues(const BarLayout& /*layout*/)
22 void BarAnimation::updateValues(const QVector<QRectF>& layout)
21 23 {
22 // TODO:
23 qDebug() << "BarAnimation::updateValues";
24 // TODO?:
25 // qDebug() << "BarAnimation::updateValues" << layout.count();
24 26 }
25 27
26 28
27 29 QVariant BarAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
28 30 {
29 QVector<QSizeF> startVector = qVariantValue<QVector<QSizeF> > (from);
30 QVector<QSizeF> endVector = qVariantValue<QVector<QSizeF> > (to);
31 QVector<QSizeF> result;
31 QVector<QRectF> startVector = qVariantValue<QVector<QRectF> > (from);
32 QVector<QRectF> endVector = qVariantValue<QVector<QRectF> > (to);
33 QVector<QRectF> result;
32 34
33 35 Q_ASSERT(startVector.count() == endVector.count()) ;
34 36
35 37 for(int i =0 ;i< startVector.count();i++){
36 QSizeF value = startVector[i] + ((endVector[i]- endVector[i]) * progress);
37 result << value;
38 //QRectF value = startVector[i] + ((endVector[i] - startVector[i]) * progress);
39 QPointF topLeft = startVector[i].topLeft() + ((endVector[i].topLeft() - startVector[i].topLeft()) * progress);
40 QSizeF size = startVector[i].size() + ((endVector[i].size() - startVector[i].size()) * progress);
41 QRectF value(topLeft,size);
42 result << value;
38 43 }
39 44 return qVariantFromValue(result);
40 45 }
41 46
42 void BarAnimation::updateCurrentValue(const QVariant &)
47 void BarAnimation::updateCurrentValue(const QVariant &value)
43 48 {
44 // TODO?
49 QVector<QRectF> layout = qVariantValue<QVector<QRectF> >(value);
50 m_item->setLayout(layout);
45 51 }
46 52
47 53 #include "moc_baranimation_p.cpp"
48 54
49 55 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,36 +1,36
1 1 #ifndef BARANIMATION_P_H_
2 2 #define BARANIMATION_P_H_
3 3
4 4 #include "chartanimation_p.h"
5 5 #include "barchartitem_p.h"
6 6
7 7 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 8
9 9 class BarChartItem;
10 10 class QBarSet;
11 11 class BarSetAnimation;
12 12
13 13 class BarAnimation : public ChartAnimation
14 14 {
15 15 Q_OBJECT
16 16
17 17 public:
18 18 BarAnimation(BarChartItem *item);
19 19 ~BarAnimation();
20 20
21 void updateValues(const BarLayout& layout);
21 void updateValues(const QVector<QRectF>& layout);
22 22
23 23 public: // from QVariantAnimation
24 24 virtual QVariant interpolated (const QVariant & from, const QVariant & to, qreal progress ) const;
25 25 virtual void updateCurrentValue (const QVariant & value );
26 26
27 27 public Q_SLOTS:
28 28
29 29 private:
30 30 BarChartItem *m_item;
31 31 QHash<QBarSet*, BarSetAnimation*> m_animations;
32 32 };
33 33
34 34 QTCOMMERCIALCHART_END_NAMESPACE
35 35
36 36 #endif
@@ -1,285 +1,290
1 1 #include "chartanimator_p.h"
2 2 #include "axisanimation_p.h"
3 3 #include "xyanimation_p.h"
4 4 #include "splineanimation_p.h"
5 5 #include "xychartitem_p.h"
6 6 #include "pieanimation_p.h"
7 7 #include "baranimation_p.h"
8 8 #include "barchartitem_p.h"
9 9 #include "areachartitem_p.h"
10 10 #include "splinechartitem_p.h"
11 11 #include "scatterchartitem_p.h"
12 12 #include <QTimer>
13 13
14 14 Q_DECLARE_METATYPE(QVector<QPointF>)
15 15 Q_DECLARE_METATYPE(QVector<qreal>)
16 Q_DECLARE_METATYPE(QVector<QRectF>)
16 17
17 18 QTCOMMERCIALCHART_BEGIN_NAMESPACE
18 19
19 20 const static int duration = 1000;
20 21
21 22 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent)
22 23 {
23 24 }
24 25
25 26 ChartAnimator::~ChartAnimator()
26 27 {
27 28 }
28 29
29 30 void ChartAnimator::addAnimation(Axis* item)
30 31 {
31 32 ChartAnimation* animation = m_animations.value(item);
32 33
33 34 if(!animation) {
34 35 animation = new AxisAnimation(item);
35 36 m_animations.insert(item,animation);
36 37 }
37 38
38 39 item->setAnimator(this);
39 40 }
40 41
41 42 void ChartAnimator::addAnimation(SplineChartItem* item)
42 43 {
43 44 ChartAnimation* animation = m_animations.value(item);
44 45
45 46 if(!animation) {
46 47 animation = new SplineAnimation(item);
47 48 m_animations.insert(item,animation);
48 49 }
49 50
50 51 item->setAnimator(this);
51 52 }
52 53
53 54 void ChartAnimator::addAnimation(ScatterChartItem* item)
54 55 {
55 56 ChartAnimation* animation = m_animations.value(item);
56 57
57 58 if(!animation) {
58 59 animation = new XYAnimation(item);
59 60 m_animations.insert(item,animation);
60 61 }
61 62
62 63 item->setAnimator(this);
63 64 }
64 65
65 66 void ChartAnimator::addAnimation(LineChartItem* item)
66 67 {
67 68 ChartAnimation* animation = m_animations.value(item);
68 69
69 70 if(!animation) {
70 71 animation = new XYAnimation(item);
71 72 m_animations.insert(item,animation);
72 73 }
73 74
74 75 item->setAnimator(this);
75 76 }
76 77
77 78 void ChartAnimator::addAnimation(PieChartItem* item)
78 79 {
79 80 ChartAnimation* animation = m_animations.value(item);
80 81
81 82 if(!animation) {
82 83 animation = new PieAnimation(item);
83 84 m_animations.insert(item,animation);
84 85 }
85 86
86 87 item->setAnimator(this);
87 88 }
88 89
89 90 void ChartAnimator::addAnimation(BarChartItem* item)
90 91 {
91 92 ChartAnimation* animation = m_animations.value(item);
92 93
93 94 if(!animation) {
94 95 animation = new BarAnimation(item);
95 96 m_animations.insert(item,animation);
96 97 }
97 98
98 99 item->setAnimator(this);
99 100 }
100 101
101 102
102 103 void ChartAnimator::removeAnimation(Chart* item)
103 104 {
104 105 item->setAnimator(0);
105 106 m_animations.remove(item);
106 107 }
107 108
108 109 void ChartAnimator::updateLayout(Axis* item , QVector<qreal>& newLayout)
109 110 {
110 111 AxisAnimation* animation = static_cast<AxisAnimation*>(m_animations.value(item));
111 112
112 113 Q_ASSERT(animation);
113 114
114 115 QVector<qreal> oldLayout = item->layout();
115 116
116 117 if(newLayout.count()==0) return;
117 118
118 119 switch(m_state)
119 120 {
120 121 case ZoomOutState: {
121 122 QRectF rect = item->geometry();
122 123 oldLayout.resize(newLayout.count());
123 124
124 125 for(int i=0,j=oldLayout.count()-1;i<(oldLayout.count()+1)/2;i++,j--)
125 126 {
126 127 oldLayout[i]= item->axisType()==Axis::X_AXIS?rect.left():rect.bottom();
127 128 oldLayout[j]= item->axisType()==Axis::X_AXIS?rect.right():rect.top();
128 129 }
129 130 }
130 131 break;
131 132 case ZoomInState: {
132 133 int index = qMin(oldLayout.count()*(item->axisType()==Axis::X_AXIS?m_point.x():(1 -m_point.y())),newLayout.count()-1.0);
133 134 oldLayout.resize(newLayout.count());
134 135
135 136 for(int i=0;i<oldLayout.count();i++)
136 137 {
137 138 oldLayout[i]= oldLayout[index];
138 139 }
139 140 }
140 141 break;
141 142 case ScrollDownState:
142 143 case ScrollRightState: {
143 144 oldLayout.resize(newLayout.count());
144 145
145 146 for(int i=0, j=i+1;i<oldLayout.count()-1;i++,j++)
146 147 {
147 148 oldLayout[i]= oldLayout[j];
148 149 }
149 150 }
150 151 break;
151 152 case ScrollUpState:
152 153 case ScrollLeftState: {
153 154 oldLayout.resize(newLayout.count());
154 155
155 156 for(int i=oldLayout.count()-1, j=i-1;i>0;i--,j--)
156 157 {
157 158 oldLayout[i]= oldLayout[j];
158 159 }
159 160 }
160 161 break;
161 162 default: {
162 163 oldLayout.resize(newLayout.count());
163 164 QRectF rect = item->geometry();
164 165 for(int i=0, j=oldLayout.count()-1;i<oldLayout.count();i++,j--)
165 166 {
166 167 oldLayout[i]= item->axisType()==Axis::X_AXIS?rect.left():rect.top();
167 168 }
168 169 }
169 170 break;
170 171 }
171 172
172 173
173 174 if(animation->state()!=QAbstractAnimation::Stopped) {
174 175 animation->stop();
175 176 }
176 177
177 178 animation->setDuration(duration);
178 179 animation->setEasingCurve(QEasingCurve::OutQuart);
179 180 QVariantAnimation::KeyValues value;
180 181 animation->setKeyValues(value); //workaround for wrong interpolation call
181 182 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
182 183 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
183 184
184 185 QTimer::singleShot(0,animation,SLOT(start()));
185 186 }
186 187
187 188 void ChartAnimator::updateLayout(SplineChartItem* item, QVector<QPointF>& oldPoints ,QVector<QPointF>& newPoints, QVector<QPointF>& oldControlPoints, QVector<QPointF>& newControlPoints,int index)
188 189 {
189 190 SplineAnimation* animation = static_cast<SplineAnimation*>(m_animations.value(item));
190 191
191 192 Q_ASSERT(animation);
192 193
193 194 if(newPoints.count()<2 || newControlPoints.count()<2) return;
194 195
195 196 bool empty = oldPoints.count()==0;
196 197
197 198
198 199 if(animation->state()!=QAbstractAnimation::Stopped) {
199 200 animation->stop();
200 201 }
201 202
202 203 animation->setDuration(duration);
203 204 if(!empty)
204 205 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
205 206 else
206 207 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
207 208
208 209 animation->setEasingCurve(QEasingCurve::OutQuart);
209 210 animation->setValues(oldPoints,newPoints,oldControlPoints,newControlPoints,index);
210 211
211 212 QTimer::singleShot(0,animation,SLOT(start()));
212 213 }
213 214
214 215
215 216 void ChartAnimator::updateLayout(XYChartItem* item, QVector<QPointF>& oldPoints , QVector<QPointF>& newPoints, int index)
216 217 {
217 218 XYAnimation* animation = static_cast<XYAnimation*>(m_animations.value(item));
218 219
219 220 Q_ASSERT(animation);
220 221
221 222 if(newPoints.count()==0) return;
222 223
223 224 bool empty = oldPoints.count()==0;
224 225
225 226
226 227 if(animation->state()!=QAbstractAnimation::Stopped) {
227 228 animation->stop();
228 229 }
229 230
230 231 animation->setDuration(duration);
231 232 if(!empty)
232 233 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
233 234 else
234 235 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
235 236
236 237 animation->setEasingCurve(QEasingCurve::OutQuart);
237 238 animation->setValues(oldPoints,newPoints,index);
238 239
239 240 QTimer::singleShot(0,animation,SLOT(start()));
240 241 }
241 242
242 243 void ChartAnimator::addAnimation(PieChartItem* item, QPieSlice *slice, const PieSliceData &sliceData, bool isEmpty)
243 244 {
244 245 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
245 246 Q_ASSERT(animation);
246 247 animation->addSlice(slice, sliceData, isEmpty);
247 248 }
248 249
249 250 void ChartAnimator::removeAnimation(PieChartItem* item, QPieSlice *slice)
250 251 {
251 252 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
252 253 Q_ASSERT(animation);
253 254 animation->removeSlice(slice);
254 255 }
255 256
256 257 void ChartAnimator::updateLayout(PieChartItem* item, const PieLayout &layout)
257 258 {
258 259 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
259 260 Q_ASSERT(animation);
260 261 animation->updateValues(layout);
261 262 }
262 263
263 264 void ChartAnimator::updateLayout(PieChartItem* item, QPieSlice *slice, const PieSliceData &sliceData)
264 265 {
265 266 PieAnimation* animation = static_cast<PieAnimation*>(m_animations.value(item));
266 267 Q_ASSERT(animation);
267 268 animation->updateValue(slice, sliceData);
268 269 }
269 270
270 void ChartAnimator::updateLayout(BarChartItem* item, const BarLayout &layout)
271 void ChartAnimator::updateLayout(BarChartItem* item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout)
271 272 {
272 273 qDebug() << "ChartAnimator::updateLayout";
273 274 BarAnimation* animation = static_cast<BarAnimation*>(m_animations.value(item));
274 275 Q_ASSERT(animation);
275 animation->updateValues(layout);
276 // animation->updateValues(layout);
277 animation->setDuration(duration);
278 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
279 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
280 QTimer::singleShot(0,animation,SLOT(start()));
276 281 }
277 282
278 283
279 284 void ChartAnimator::setState(State state,const QPointF& point)
280 285 {
281 286 m_state=state;
282 287 m_point=point;
283 288 }
284 289
285 290 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,58 +1,58
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 "barchartitem_p.h"
7 7 #include <QPointF>
8 8
9 9 QTCOMMERCIALCHART_BEGIN_NAMESPACE
10 10
11 11 class ChartItem;
12 12 class Axis;
13 13 class AreaChartItem;
14 14 class SplineChartItem;
15 15 class ScatterChartItem;
16 16 class LineChartItem;
17 17 class XYChartItem;
18 18
19 19 class ChartAnimator : public QObject {
20 20
21 21 public:
22 22 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState,ScrollRightState,ZoomInState,ZoomOutState};
23 23 Q_DECLARE_FLAGS(States, State);
24 24
25 25 ChartAnimator(QObject *parent = 0);
26 26 virtual ~ChartAnimator();
27 27
28 28 void addAnimation(Axis* item);
29 29 void addAnimation(PieChartItem* item);
30 30 void addAnimation(ScatterChartItem* item);
31 31 void addAnimation(LineChartItem* item);
32 32 void addAnimation(SplineChartItem* item);
33 33 void addAnimation(BarChartItem* item);
34 34 void removeAnimation(Chart* item);
35 35
36 36 void animationStarted();
37 37 void updateLayout(XYChartItem* item, QVector<QPointF>& oldLayout,QVector<QPointF>& newLayout,int index);
38 38 void updateLayout(SplineChartItem* item, QVector<QPointF>& oldPoints , QVector<QPointF>& newPoints, QVector<QPointF>& oldControlPoints, QVector<QPointF>& newContorlPoints,int index);
39 39 void updateLayout(Axis* item, QVector<qreal>& layout);
40 40
41 41 void addAnimation(PieChartItem* item, QPieSlice *slice, const PieSliceData &sliceData, bool isEmpty);
42 42 void removeAnimation(PieChartItem* item, QPieSlice *slice);
43 43 void updateLayout(PieChartItem* item, const PieLayout &layout);
44 44 void updateLayout(PieChartItem* item, QPieSlice *slice, const PieSliceData &sliceData);
45 45
46 void updateLayout(BarChartItem* item, const BarLayout &layout);
46 void updateLayout(BarChartItem* item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout);
47 47
48 48 void setState(State state,const QPointF& point = QPointF());
49 49
50 50 private:
51 51 QMap<Chart*,ChartAnimation*> m_animations;
52 52 State m_state;
53 53 QPointF m_point;
54 54 };
55 55
56 56 QTCOMMERCIALCHART_END_NAMESPACE
57 57
58 58 #endif
@@ -1,266 +1,354
1 1 #include "barchartitem_p.h"
2 2 #include "bar_p.h"
3 3 #include "barvalue_p.h"
4 4 #include "qbarset.h"
5 5 #include "qbarseries.h"
6 6 #include "qchart.h"
7 7 #include "qchartaxis.h"
8 8 #include "qchartaxiscategories.h"
9 9 #include "chartpresenter_p.h"
10 10 #include "chartanimator_p.h"
11 11 #include "chartdataset_p.h"
12 12 #include <QDebug>
13 13 #include <QToolTip>
14 14
15 15 QTCOMMERCIALCHART_BEGIN_NAMESPACE
16 16
17 17 BarChartItem::BarChartItem(QBarSeries *series, ChartPresenter *presenter) :
18 18 ChartItem(presenter),
19 19 mLayoutSet(false),
20 20 mSeries(series)
21 21 {
22 22 connect(series,SIGNAL(showToolTip(QPoint,QString)),this,SLOT(showToolTip(QPoint,QString)));
23 connect(series, SIGNAL(updatedBars()), this, SLOT(layoutChanged()));
23 connect(series, SIGNAL(updatedBars()), this, SLOT(handleLayoutChanged()));
24 24 //TODO: connect(series,SIGNAL("position or size has changed"), this, SLOT(handleLayoutChanged()));
25 25 connect(series, SIGNAL(restructuredBar(int)), this, SLOT(handleModelChanged(int)));
26 26 setZValue(ChartPresenter::BarSeriesZValue);
27 27 initAxisLabels();
28 28 dataChanged();
29 29 }
30 30
31 31 BarChartItem::~BarChartItem()
32 32 {
33 33 disconnect(this,SLOT(showToolTip(QPoint,QString)));
34 34 }
35 35
36 36 void BarChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
37 37 {
38 38 if (!mLayoutSet) {
39 39 qDebug() << "BarChartItem::paint called without layout set. Aborting.";
40 40 return;
41 41 }
42 42 foreach(QGraphicsItem* i, childItems()) {
43 43 i->paint(painter,option,widget);
44 44 }
45 45 }
46 46
47 47 QRectF BarChartItem::boundingRect() const
48 48 {
49 49 return m_rect;
50 50 }
51 51
52 52 void BarChartItem::dataChanged()
53 53 {
54 54 // TODO: performance optimizations. Do we really need to delete and create items every time data is changed or can we reuse them?
55 55 // Delete old bars
56 56 foreach (QGraphicsItem* item, childItems()) {
57 57 delete item;
58 58 }
59 59
60 60 mBars.clear();
61 61 mFloatingValues.clear();
62 mLayout.clear();
62 63
63 64 // Create new graphic items for bars
64 65 for (int c=0; c<mSeries->categoryCount(); c++) {
65 66 QString category = mSeries->categoryName(c);
66 67 for (int s=0; s<mSeries->barsetCount(); s++) {
67 68 QBarSet *set = mSeries->barsetAt(s);
68 69 Bar *bar = new Bar(category,this);
69 70 childItems().append(bar);
70 71 mBars.append(bar);
71 72 connect(bar,SIGNAL(clicked(QString)),set,SIGNAL(clicked(QString)));
72 73 connect(bar,SIGNAL(rightClicked(QString)),set,SIGNAL(rightClicked(QString)));
73 74 connect(bar,SIGNAL(hoverEntered(QPoint)),set,SLOT(barHoverEnterEvent(QPoint)));
74 75 connect(bar,SIGNAL(hoverLeaved()),set,SLOT(barHoverLeaveEvent()));
76 mLayout.append(QRectF(0,0,0,0));
75 77 }
76 78 }
77 79
78 80 // Create floating values
79 81 for (int category=0; category<mSeries->categoryCount(); category++) {
80 82 for (int s=0; s<mSeries->barsetCount(); s++) {
81 83 QBarSet *set = mSeries->barsetAt(s);
82 84 BarValue *value = new BarValue(*set, this);
83 85 childItems().append(value);
84 86 mFloatingValues.append(value);
85 87 connect(set,SIGNAL(toggleFloatingValues()),value,SLOT(toggleVisible()));
86 88 }
87 89 }
88 90 }
89
91 /*
90 92 void BarChartItem::layoutChanged()
91 93 {
94 qDebug() << "Deprecated BarChartItem::layoutChanged called. aborting";
95 return;
92 96 // Scale bars to new layout
93 97 // Layout for bars:
94 98 if (mSeries->barsetCount() <= 0) {
95 99 qDebug() << "No sets in model!";
96 100 return;
97 101 }
98 102
99 103 if (childItems().count() == 0) {
100 104 qDebug() << "WARNING: BarChartitem::layoutChanged called before graphics items are created!";
101 105 return;
102 106 }
103 107
104 108
105 109 // Use temporary qreals for accurancy (we might get some compiler warnings... :)
106 110 qreal categoryCount = mSeries->categoryCount();
107 111 qreal setCount = mSeries->barsetCount();
108 112 qreal max = mSeries->max();
109 113
110 114 // Domain:
111 115 if (mDomainMaxY > max) {
112 116 max = mDomainMaxY;
113 117 }
114 118
115 119 qreal width = geometry().width();
116 120 qreal height = geometry().height();
117 121 qreal scale = (height/max);
118 122 qreal categoryWidth = width/categoryCount;
119 123 qreal barWidth = categoryWidth / (setCount+1);
120 124
125 BarLayout layout;
126
121 127 int itemIndex(0);
122 128 for (int category=0; category < categoryCount; category++) {
123 129 qreal xPos = categoryWidth * category + barWidth/2;
124 130 qreal yPos = height;
125 131 for (int set = 0; set < setCount; set++) {
126 132 qreal barHeight = mSeries->valueAt(set,category) * scale;
127 133 Bar* bar = mBars.at(itemIndex);
128 134
135 QRectF rect(xPos,yPos-barHeight,mBarWidth,barHeight);
136 layout.insert(bar,rect);
129 137 // TODO: width settable per bar?
130 138 bar->setRect(xPos, yPos-barHeight,barWidth, barHeight);
131 139 bar->setPen(mSeries->barsetAt(set)->pen());
132 140 bar->setBrush(mSeries->barsetAt(set)->brush());
133 141
142 // bar->resize(mBarWidth, barHeight);
143 // layout.insert(bar,QSizeF(mBarWidth,barHeight));
144 bar->setPen(mSeries->barsetAt(set)->pen());
145 bar->setBrush(mSeries->barsetAt(set)->brush());
146 // bar->setPos(xPos, yPos-barHeight);
134 147 itemIndex++;
135 148 xPos += barWidth;
136 149 }
137 150 }
138 151
139 152 // Position floating values
140 153 itemIndex = 0;
141 154 for (int category=0; category < mSeries->categoryCount(); category++) {
142 155 qreal xPos = categoryWidth * category + categoryWidth/2 + barWidth;
143 156 qreal yPos = height;
144 157 for (int set=0; set < mSeries->barsetCount(); set++) {
145 158 qreal barHeight = mSeries->valueAt(set,category) * scale;
146 159 BarValue* value = mFloatingValues.at(itemIndex);
147 160
148 161 QBarSet* barSet = mSeries->barsetAt(set);
149 162 value->resize(100,50); // TODO: proper layout for this.
150 163 value->setPos(xPos, yPos-barHeight/2);
151 164 value->setPen(barSet->floatingValuePen());
152 165
153 166 if (mSeries->valueAt(set,category) != 0) {
154 167 value->setValueString(QString::number(mSeries->valueAt(set,category)));
155 168 } else {
156 169 value->setValueString(QString(""));
157 170 }
158 171
159 172 itemIndex++;
160 173 xPos += barWidth;
161 174 }
162 175 }
163 update();
176 // update();
164 177 }
165
166 BarLayout BarChartItem::calculateLayout()
178 */
179 QVector<QRectF> BarChartItem::calculateLayout()
167 180 {
181 // layoutChanged();
182 /*
168 183 BarLayout layout;
169 184 foreach(Bar* bar, mBars) {
170 185 layout.insert(bar,bar->boundingRect());
171 186 }
187 */
188 QVector<QRectF> layout;
189
190 // Use temporary qreals for accurancy (we might get some compiler warnings... :)
191 int categoryCount = mSeries->categoryCount();
192 int setCount = mSeries->barsetCount();
193
194 qreal tW = mWidth;
195 qreal tH = mHeight;
196 qreal tM = mSeries->max();
197
198 // Domain:
199 if (mDomainMaxY > tM) {
200 tM = mDomainMaxY;
201 }
202
203 qreal scale = (tH/tM);
204 qreal tC = categoryCount + 1;
205 qreal categoryWidth = tW/tC;
206 mBarWidth = categoryWidth / (setCount+1);
207
208 int itemIndex(0);
209 for (int category=0; category < categoryCount; category++) {
210 qreal xPos = categoryWidth * category + categoryWidth /2 + mBarWidth/2;
211 qreal yPos = mHeight;
212 for (int set = 0; set < setCount; set++) {
213 qreal barHeight = mSeries->valueAt(set,category) * scale;
214 Bar* bar = mBars.at(itemIndex);
215
216 QRectF rect(xPos,yPos-barHeight,mBarWidth,barHeight);
217 //layout.insert(bar,rect);
218 layout.append(rect);
219 // TODO: width settable per bar?
220 // bar->resize(mBarWidth, barHeight);
221 // layout.insert(bar,QSizeF(mBarWidth,barHeight));
222 bar->setPen(mSeries->barsetAt(set)->pen());
223 bar->setBrush(mSeries->barsetAt(set)->brush());
224 // bar->setPos(xPos, yPos-barHeight);
225 itemIndex++;
226 xPos += mBarWidth;
227 }
228 }
229
230 // Position floating values
231 itemIndex = 0;
232 for (int category=0; category < mSeries->categoryCount(); category++) {
233 qreal xPos = categoryWidth * category + categoryWidth/2 + mBarWidth;
234 qreal yPos = mHeight;
235 for (int set=0; set < mSeries->barsetCount(); set++) {
236 qreal barHeight = mSeries->valueAt(set,category) * scale;
237 BarValue* value = mFloatingValues.at(itemIndex);
238
239 QBarSet* barSet = mSeries->barsetAt(set);
240 value->resize(100,50); // TODO: proper layout for this.
241 value->setPos(xPos, yPos-barHeight/2);
242 value->setPen(barSet->floatingValuePen());
243
244 if (mSeries->valueAt(set,category) != 0) {
245 value->setValueString(QString::number(mSeries->valueAt(set,category)));
246 } else {
247 value->setValueString(QString(""));
248 }
249
250 itemIndex++;
251 xPos += mBarWidth;
252 }
253 }
172 254
173 255 return layout;
174 256 }
175 257
176 void BarChartItem::applyLayout(const BarLayout &layout)
258 void BarChartItem::applyLayout(const QVector<QRectF> &layout)
177 259 {
178 260 if (animator())
179 animator()->updateLayout(this, layout);
261 animator()->updateLayout(this, mLayout, layout);
180 262 else
181 263 setLayout(layout);
182 264 }
183 265
184 void BarChartItem::setLayout(const BarLayout &layout)
266 void BarChartItem::setLayout(const QVector<QRectF> &layout)
185 267 {
186 foreach (Bar *bar, layout.keys()) {
187 bar->setRect(layout.value(bar));
268 mLayout = layout;
269
270 for (int i=0; i<mBars.count(); i++) {
271 //mBars.at(i)->setSize(layout.at(i).size());
272 //mBars.at(i)->setPos(layout.at(i).topLeft());
273 mBars.at(i)->setRect(layout.at(i));
188 274 }
275
189 276 update();
190 277 }
191 278
192 279 void BarChartItem::initAxisLabels()
193 280 {
194 281 int count = mSeries->categoryCount();
195 282 if (0 == count) {
196 283 return;
197 284 }
198 285
199 286 Domain* domain = presenter()->dataSet()->domain(mSeries);
200 287
201 288 qreal min = 0;
202 289 qreal max = count+1;
203 290
204 291 domain->setRangeX(min,max,count+1);
205 292 }
206 293
207 294 //handlers
208 295
209 296 void BarChartItem::handleModelChanged(int index)
210 297 {
211 298 Q_UNUSED(index)
212 299 dataChanged();
213 300 }
214 301
215 302 void BarChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
216 303 {
217 304 mDomainMinX = minX;
218 305 mDomainMaxX = maxX;
219 306 mDomainMinY = minY;
220 307 mDomainMaxY = maxY;
221 layoutChanged();
308 handleLayoutChanged();
222 309
223 310 /*
224 311 int count = mSeries->categoryCount();
225 312 if (0 == count) {
226 313 return;
227 314 }
228 315
229 316 // Position labels to domain
230 317 qreal min = domain.minX();
231 318 qreal max = domain.maxX();
232 319 qreal step = (max-min)/count;
233 320 QChartAxisCategories& categories = mChart->axisX()->categories();
234 321 categories.clear();
235 322 for (int i=0; i<count; i++) {
236 323 categories.insert(min,mSeries->categoryName(i));
237 324 min += step;
238 325 }
239 326 */
240 327 }
241 328
242 329 void BarChartItem::handleGeometryChanged(const QRectF& rect)
243 330 {
244 331 m_rect=rect;
245 332 layoutChanged();
246 333 mLayoutSet = true;
247 334 setPos(rect.topLeft());
248 335 }
249 336
250 337 void BarChartItem::handleLayoutChanged()
251 338 {
252 BarLayout layout = calculateLayout();
339 qDebug() << "BarChartItem::handleLayoutChanged";
340 QVector<QRectF> layout = calculateLayout();
253 341 applyLayout(layout);
254 342 update();
255 343 }
256 344
257 345
258 346 void BarChartItem::showToolTip(QPoint pos, QString tip)
259 347 {
260 348 // TODO: cool tooltip instead of default
261 349 QToolTip::showText(pos,tip);
262 350 }
263 351
264 352 #include "moc_barchartitem_p.cpp"
265 353
266 354 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,77 +1,79
1 1 #ifndef BARCHARTITEM_H
2 2 #define BARCHARTITEM_H
3 3
4 4 #include "chartitem_p.h"
5 5 #include "qbarseries.h"
6 6 #include <QPen>
7 7 #include <QBrush>
8 8 #include <QGraphicsItem>
9 9
10 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
11 11
12 12 class Bar;
13 13 class BarValue;
14 14 class QChartAxisCategories;
15 15 class QChart;
16 16
17 typedef QHash<Bar*, QRectF> BarLayout;
17 //typedef QVector<QRectF> BarLayout;
18 18
19 19 class BarChartItem : public ChartItem
20 20 {
21 21 Q_OBJECT
22 22 public:
23 23 BarChartItem(QBarSeries *series, ChartPresenter *presenter);
24 24 virtual ~BarChartItem();
25 25
26 26 // Common implemantation of different presenters. Not to be instantiated.
27 27 // TODO: combine this with BarPresenter and derive other presenters from it?
28 28
29 29 public:
30 30 // From QGraphicsItem
31 31 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
32 32 QRectF boundingRect() const;
33 33
34 34 // TODO: Consider the domain for layoutChanged. May be use case, may not be. If it is, then the derived classes need to implement it
35 35 virtual void dataChanged(); // data of series has changed -> need to recalculate bar sizes
36 36 private slots:
37 virtual void layoutChanged(); // layout has changed -> need to recalculate bar sizes
37 //virtual void layoutChanged(); // layout has changed -> need to recalculate bar sizes
38 38
39 39 public:
40 BarLayout calculateLayout();
41 void applyLayout(const BarLayout &layout);
42 void setLayout(const BarLayout &layout);
40 QVector<QRectF> calculateLayout();
41 void applyLayout(const QVector<QRectF> &layout);
42 void setLayout(const QVector<QRectF> &layout);
43 void updateLayout(const QVector<QRectF> &layout);
43 44
44 45 QRectF geometry() const { return m_rect;}
45 46
46 47 protected:
47 48 void initAxisLabels();
48 49
49 50 public slots:
50 51 void handleModelChanged(int index);
51 52 void handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY);
52 53 void handleGeometryChanged(const QRectF& size);
53 54 void handleLayoutChanged();
54 55
55 56 // Internal slots
56 57 void showToolTip(QPoint pos, QString tip); // shows tooltip (if enabled)
57 58
58 59 protected:
59 60
60 61 // TODO: consider these.
61 62 qreal mDomainMinX;
62 63 qreal mDomainMaxX;
63 64 qreal mDomainMinY;
64 65 qreal mDomainMaxY;
65 66
66 67 QRectF m_rect;
67 68 bool mLayoutSet; // True, if component has been laid out.
69 QVector<QRectF> mLayout;
68 70
69 71 // Not owned.
70 72 QBarSeries* mSeries;
71 73 QList<Bar*> mBars;
72 74 QList<BarValue*> mFloatingValues;
73 75 };
74 76
75 77 QTCOMMERCIALCHART_END_NAMESPACE
76 78
77 79 #endif // BARCHARTITEM_H
@@ -1,368 +1,371
1 1 #include <QDebug>
2 2 #include "qbarseries.h"
3 3 #include "qbarset.h"
4 4 #include "barchartmodel_p.h"
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 /*!
9 9 \class QBarSeries
10 10 \brief part of QtCommercial chart API.
11 11
12 12 QBarSeries represents a series of data shown as bars. One QBarSeries can contain multible
13 13 QBarSet data sets. QBarSeries groups the data from sets to categories, which are defined
14 14 by QStringList.
15 15
16 16 \mainclass
17 17
18 18 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
19 19 */
20 20
21 21 /*!
22 22 \fn virtual QSeriesType QBarSeries::type() const
23 23 \brief Returns type of series.
24 24 \sa QSeries, QSeriesType
25 25 */
26 26
27 27 /*!
28 28 \fn void QBarSeries::showToolTip(QPoint pos, QString tip)
29 29 \brief \internal \a pos \a tip
30 30 */
31 31
32 32 /*!
33 33 Constructs empty QBarSeries. Parameter \a categories defines the categories for chart.
34 34 QBarSeries is QObject which is a child of a \a parent.
35 35 */
36 36 QBarSeries::QBarSeries(QStringList categories, QObject *parent)
37 37 : QSeries(parent)
38 38 ,mModel(new BarChartModel(categories, this))
39 39 {
40 40 m_model = NULL;
41 41 m_mapCategories = -1;
42 42 m_mapBarBottom = -1;
43 43 m_mapBarTop = -1;
44 44 m_mapOrientation = Qt::Vertical;
45 45 }
46 46
47 47 /*!
48 48 Adds a set of bars to series. Takes ownership of \a set.
49 49 Connects the clicked(QString) and rightClicked(QString) signals
50 50 of \a set to this series
51 51 */
52 52 void QBarSeries::addBarSet(QBarSet *set)
53 53 {
54 qDebug() << "add bar set";
54 55 mModel->addBarSet(set);
55 56 connect(set,SIGNAL(clicked(QString)),this,SLOT(barsetClicked(QString)));
56 57 connect(set,SIGNAL(rightClicked(QString)),this,SLOT(barsetRightClicked(QString)));
57 58 connect(set, SIGNAL(valueChanged()), this, SLOT(barsetChanged()));
59 emit updatedBars();
58 60 }
59 61
60 62 /*!
61 63 Removes a set of bars from series. Releases ownership of \a set. Doesnt delete \a set.
62 64 Disconnects the clicked(QString) and rightClicked(QString) signals
63 65 of \a set from this series
64 66 */
65 67 void QBarSeries::removeBarSet(QBarSet *set)
66 68 {
67 69 disconnect(set,SIGNAL(clicked(QString)),this,SLOT(barsetClicked(QString)));
68 70 disconnect(set,SIGNAL(rightClicked(QString)),this,SLOT(barsetRightClicked(QString)));
69 71 mModel->removeBarSet(set);
72 emit updatedBars();
70 73 }
71 74
72 75 void QBarSeries::insertBarSet(int i, QBarSet *set)
73 76 {
74 77 mModel->insertBarSet(i, set);
75 78 // emit barsetChanged();
76 79 }
77 80
78 81 void QBarSeries::insertCategory(int i, QString category)
79 82 {
80 83 mModel->insertCategory(i, category);
81 84 }
82 85
83 86 void QBarSeries::removeCategory(int i)
84 87 {
85 88 mModel->removeCategory(i);
86 89 }
87 90
88 91 /*!
89 92 Returns number of sets in series.
90 93 */
91 94 int QBarSeries::barsetCount()
92 95 {
93 96 // if(m_model)
94 97 // return m_mapBarTop - m_mapBarBottom;
95 98 // else
96 99 return mModel->barsetCount();
97 100 }
98 101
99 102 /*!
100 103 Returns number of categories in series
101 104 */
102 105 int QBarSeries::categoryCount()
103 106 {
104 107 return mModel->categoryCount();
105 108 }
106 109
107 110 /*!
108 111 Returns a list of sets in series. Keeps ownership of sets.
109 112 */
110 113 QList<QBarSet*> QBarSeries::barSets()
111 114 {
112 115 return mModel->barSets();
113 116 }
114 117
115 118 /*!
116 119 \internal \a index
117 120 */
118 121 QBarSet* QBarSeries::barsetAt(int index)
119 122 {
120 123 return mModel->setAt(index);
121 124 }
122 125
123 126 /*!
124 127 \internal \a category
125 128 */
126 129 QString QBarSeries::categoryName(int category)
127 130 {
128 131 return mModel->categoryName(category);
129 132 }
130 133
131 134 /*!
132 135 Enables or disables tooltip depending on parameter \a enabled.
133 136 Tooltip shows the name of set, when mouse is hovering on top of bar.
134 137 Calling without parameter \a enabled, enables the tooltip
135 138 */
136 139 void QBarSeries::setToolTipEnabled(bool enabled)
137 140 {
138 141 // TODO: what if we add sets after call to this function? Those sets won't have tooltip enabled.
139 142 if (enabled) {
140 143 for (int i=0; i<mModel->barsetCount(); i++) {
141 144 QBarSet *set = mModel->setAt(i);
142 145 connect(set,SIGNAL(showToolTip(QPoint,QString)),this,SIGNAL(showToolTip(QPoint,QString)));
143 146 }
144 147 } else {
145 148 for (int i=0; i<mModel->barsetCount(); i++) {
146 149 QBarSet *set = mModel->setAt(i);
147 150 disconnect(set,SIGNAL(showToolTip(QPoint,QString)),this,SIGNAL(showToolTip(QPoint,QString)));
148 151 }
149 152 }
150 153 }
151 154
152 155
153 156 /*!
154 157 \internal \a category
155 158 */
156 159 void QBarSeries::barsetClicked(QString category)
157 160 {
158 161 emit clicked(qobject_cast<QBarSet*>(sender()), category);
159 162 }
160 163
161 164 /*!
162 165 \internal \a category
163 166 */
164 167 void QBarSeries::barsetRightClicked(QString category)
165 168 {
166 169 emit rightClicked(qobject_cast<QBarSet*>(sender()), category);
167 170 }
168 171
169 172
170 173 /*!
171 174 \internal
172 175 */
173 176 qreal QBarSeries::min()
174 177 {
175 178 return mModel->min();
176 179 }
177 180
178 181 /*!
179 182 \internal
180 183 */
181 184 qreal QBarSeries::max()
182 185 {
183 186 return mModel->max();
184 187 }
185 188
186 189 /*!
187 190 \internal \a set \a category
188 191 */
189 192 qreal QBarSeries::valueAt(int set, int category)
190 193 {
191 194 return mModel->valueAt(set,category);
192 195 }
193 196
194 197 /*!
195 198 \internal \a set \a category
196 199 */
197 200 qreal QBarSeries::percentageAt(int set, int category)
198 201 {
199 202 return mModel->percentageAt(set,category);
200 203 }
201 204
202 205 /*!
203 206 \internal \a category
204 207 */
205 208 qreal QBarSeries::categorySum(int category)
206 209 {
207 210 return mModel->categorySum(category);
208 211 }
209 212
210 213 /*!
211 214 \internal
212 215 */
213 216 qreal QBarSeries::maxCategorySum()
214 217 {
215 218 return mModel->maxCategorySum();
216 219 }
217 220
218 221 /*!
219 222 \internal
220 223 */
221 224 BarChartModel& QBarSeries::model()
222 225 {
223 226 return *mModel;
224 227 }
225 228
226 229 bool QBarSeries::setModel(QAbstractItemModel* model)
227 230 {
228 231 // disconnect signals from old model
229 232 if(m_model)
230 233 {
231 234 disconnect(m_model, 0, this, 0);
232 235 m_mapCategories = -1;
233 236 m_mapBarBottom = -1;
234 237 m_mapBarTop = -1;
235 238 m_mapOrientation = Qt::Vertical;
236 239 }
237 240
238 241 // set new model
239 242 if(model)
240 243 {
241 244 m_model = model;
242 245 return true;
243 246 }
244 247 else
245 248 {
246 249 m_model = NULL;
247 250 return false;
248 251 }
249 252 }
250 253
251 254 // TODO
252 255 void QBarSeries::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
253 256 {
254 257 if (m_model == NULL)
255 258 return;
256 259 m_mapCategories = categories;
257 260 m_mapBarBottom = bottomBoundry;
258 261 m_mapBarTop = topBoundry;
259 262 m_mapOrientation = orientation;
260 263
261 264 // connect the signals
262 265 if (m_mapOrientation == Qt::Vertical)
263 266 {
264 267 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
265 268 connect(m_model,SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
266 269 connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
267 270 }
268 271 else
269 272 {
270 273 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex, QModelIndex)));
271 274 connect(m_model,SIGNAL(columnsInserted(QModelIndex, int, int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
272 275 connect(m_model, SIGNAL(columnsRemoved(QModelIndex, int, int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
273 276 }
274 277
275 278
276 279 // create the initial bars
277 280 delete mModel;
278 281 if (m_mapOrientation == Qt::Vertical)
279 282 {
280 283 QStringList categories;
281 284 for (int k = 0; k < m_model->rowCount(); k++)
282 285 categories << m_model->data(m_model->index(k, m_mapCategories), Qt::DisplayRole).toString();
283 286 mModel = new BarChartModel(categories, this);
284 287
285 288 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++)
286 289 {
287 290 QBarSet* barSet = new QBarSet(QString("Column: %1").arg(i + 1));
288 291 for(int m = 0; m < m_model->rowCount(); m++)
289 292 *barSet << m_model->data(m_model->index(m, i), Qt::DisplayRole).toDouble();
290 293 addBarSet(barSet);
291 294 }
292 295 }
293 296 else
294 297 {
295 298 QStringList categories;
296 299 for (int k = 0; k < m_model->columnCount(); k++)
297 300 categories << m_model->data(m_model->index(m_mapCategories, k), Qt::DisplayRole).toString();
298 301 mModel = new BarChartModel(categories, this);
299 302
300 303 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++)
301 304 {
302 305 QBarSet* barSet = new QBarSet(QString("Row: %1").arg(i + 1));
303 306 for(int m = 0; m < m_model->columnCount(); m++)
304 307 *barSet << m_model->data(m_model->index(i, m), Qt::DisplayRole).toDouble();
305 308 addBarSet(barSet);
306 309 }
307 310 }
308 311 }
309 312
310 313 void QBarSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
311 314 {
312 315 Q_UNUSED(bottomRight)
313 316
314 317 if (m_mapOrientation == Qt::Vertical)
315 318 {
316 319 if (topLeft.column() >= m_mapBarBottom && topLeft.column() <= m_mapBarTop)
317 320 barsetAt(topLeft.column() - m_mapBarBottom)->setValue(topLeft.row(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
318 321 // else if (topLeft.column() == m_mapCategories)
319 322 // slices().at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
320 323 }
321 324 else
322 325 {
323 326 if (topLeft.row() >= m_mapBarBottom && topLeft.row() <= m_mapBarTop)
324 327 barsetAt(topLeft.row() - m_mapBarBottom)->setValue(topLeft.column(), m_model->data(topLeft, Qt::DisplayRole).toDouble());
325 328 // else if (topLeft.row() == m_mapCategories)
326 329 // slices().at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
327 330 }
328 331 }
329 332
330 333 void QBarSeries::modelDataAdded(QModelIndex /*parent*/, int start, int /*end*/)
331 334 {
332 335 if (m_mapOrientation == Qt::Vertical)
333 336 {
334 337 insertCategory(start, QString("Row: %1").arg(start + 1));
335 338 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++)
336 339 {
337 340 barsetAt(i)->insertValue(start, m_model->data(m_model->index(start, i), Qt::DisplayRole).toDouble());
338 341 }
339 342 }
340 343 else
341 344 {
342 345 insertCategory(start, QString("Column: %1").arg(start + 1));
343 346 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++)
344 347 {
345 348 barsetAt(i)->insertValue(start, m_model->data(m_model->index(i, start), Qt::DisplayRole).toDouble());
346 349 }
347 350 }
348 351 emit restructuredBar(1);
349 352 }
350 353
351 354 void QBarSeries::modelDataRemoved(QModelIndex /*parent*/, int start, int /*end*/)
352 355 {
353 356 removeCategory(start);
354 357 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++)
355 358 {
356 359 barsetAt(i)->removeValue(start);
357 360 }
358 361 emit restructuredBar(1);
359 362 }
360 363
361 364 void QBarSeries::barsetChanged()
362 365 {
363 366 emit updatedBars();
364 367 }
365 368
366 369 #include "moc_qbarseries.cpp"
367 370
368 371 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now