##// END OF EJS Templates
Krazy reported errors...
Michal Klocek -
r974:de7be57d3935
parent child
Show More
@@ -1,42 +1,42
1 1 /*!
2 2 \example examples/stackedbarchartdrilldown
3 3 \title StackedBarChart Drilldown Example
4 4 \subtitle
5 5
6 6 The example shows how to implement drilldown using stacked barchart. In drilldown example we create stacked barchart, which shows the harvest of various chili peppers during season. In season view the harvest is grouped by month. To drill down to weekly view, user clicks selected month with right mouse button. On weekly view, the harvest of clicked month is shown by week. For example purposes each month is 4 weeks long :)
7 7
8 8 Season view looks like this:
9 9 \image stackedbarchart_drilldown_season.png
10 10
11 11 Right mouse button clicked on august, shows the harvest from august:
12 12 \image stackedbarchart_drilldown_august.png
13 13
14 14 Here we define a drilldown series, which adds mapping for categories to other drilldown series.
15 15 Purpose of drilldown series is to contain knowledge of the drilldown structure. The mapDrilldownSeries function maps the category to given series. We can ask the mapping for category with drilldownSeries(QString category) function.
16 16
17 17 \snippet ../examples/stackedbarchartdrilldown/main.cpp 1
18 18
19 To enable drilldown we create own view, which implements handler for right click. All QBarSeries derived classes send out rightClicked(QBarSet*, QString) signal when series is clicked with right mouse button. The parameters QBarSet and QString contain the pointer to clicked bar set and name of category, where click occured.
19 To enable drilldown we create own view, which implements handler for right click. All QBarSeries derived classes send out rightClicked(QBarSet*, QString) signal when series is clicked with right mouse button. The parameters QBarSet and QString contain the pointer to clicked bar set and name of category, where click occurred.
20 20
21 21 In our DrilldownChart we implement handler, which selects the drilldown chart with the category.
22 22
23 23 \snippet ../examples/stackedbarchartdrilldown/main.cpp 2
24 24
25 25 Here we define data, which we use to construct the chart.
26 26
27 27 \snippet ../examples/stackedbarchartdrilldown/main.cpp 3
28 28
29 29 To create the drilldown structure, we first create our top level series, which we call seasonSeries. For each month in seasonSeries we create a drilldown series, called weeklySeries which contains more detailed data for that month.
30 30 In weeklySeries, we use the drilldown handler to bring us back to seasonSeries. To do this we add mapping to the series. The seasonSeries is mapped to weeklySeries for each month. Every weeklySeries is mapped back to the seasonSeries.
31 31 To make mapping work, we connect the rightClicked signals from our series to the drilldownChart.
32 32
33 33 \snippet ../examples/stackedbarchartdrilldown/main.cpp 4
34 34
35 35 When we have our drilldown structure ready, we can add the data to it. Here we generate random crop for each plant in each week. The monthly crop is calculated from weekly crops. To enable floating values, we connect the clicked signal to toggle the value of corresponding set.
36 36
37 37 \snippet ../examples/stackedbarchartdrilldown/main.cpp 5
38 38
39 39 Here we set the chart to show top level series initially.
40 40
41 41 \snippet ../examples/stackedbarchartdrilldown/main.cpp 6
42 42 */
@@ -1,299 +1,301
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartanimator_p.h"
22 22 #include "axisanimation_p.h"
23 23 #include "xyanimation_p.h"
24 24 #include "splineanimation_p.h"
25 25 #include "xychartitem_p.h"
26 26 #include "pieanimation_p.h"
27 27 #include "baranimation_p.h"
28 28 #include "barchartitem_p.h"
29 29 #include "areachartitem_p.h"
30 30 #include "splinechartitem_p.h"
31 31 #include "scatterchartitem_p.h"
32 32 #include <QTimer>
33 33
34 34 Q_DECLARE_METATYPE(QVector<QPointF>)
35 35 Q_DECLARE_METATYPE(QVector<qreal>)
36 36 Q_DECLARE_METATYPE(QVector<QRectF>)
37 37
38 38 QTCOMMERCIALCHART_BEGIN_NAMESPACE
39 39
40 40 const static int duration = 1000;
41 41
42 42 ChartAnimator::ChartAnimator(QObject *parent):QObject(parent),
43 43 m_state(ShowState)
44 44 {
45 45 }
46 46
47 47 ChartAnimator::~ChartAnimator()
48 48 {
49 49 }
50 50
51 51 void ChartAnimator::addAnimation(Axis *item)
52 52 {
53 53 ChartAnimation *animation = m_animations.value(item);
54 54
55 55 if (!animation) {
56 56 animation = new AxisAnimation(item);
57 57 m_animations.insert(item, animation);
58 58 }
59 59
60 60 item->setAnimator(this);
61 61 }
62 62
63 63 void ChartAnimator::addAnimation(SplineChartItem *item)
64 64 {
65 65 ChartAnimation *animation = m_animations.value(item);
66 66
67 67 if (!animation) {
68 68 animation = new SplineAnimation(item);
69 69 m_animations.insert(item, animation);
70 70 }
71 71
72 72 item->setAnimator(this);
73 73 }
74 74
75 75 void ChartAnimator::addAnimation(ScatterChartItem *item)
76 76 {
77 77 ChartAnimation *animation = m_animations.value(item);
78 78
79 79 if (!animation) {
80 80 animation = new XYAnimation(item);
81 81 m_animations.insert(item, animation);
82 82 }
83 83
84 84 item->setAnimator(this);
85 85 }
86 86
87 87 void ChartAnimator::addAnimation(LineChartItem *item)
88 88 {
89 89 ChartAnimation *animation = m_animations.value(item);
90 90
91 91 if (!animation) {
92 92 animation = new XYAnimation(item);
93 93 m_animations.insert(item, animation);
94 94 }
95 95
96 96 item->setAnimator(this);
97 97 }
98 98
99 99 void ChartAnimator::addAnimation(PieChartItem *item)
100 100 {
101 101 ChartAnimation *animation = m_animations.value(item);
102 102
103 103 if (!animation) {
104 104 animation = new PieAnimation(item);
105 105 m_animations.insert(item, animation);
106 106 }
107 107
108 108 item->setAnimator(this);
109 109 }
110 110
111 111 void ChartAnimator::addAnimation(BarChartItem *item)
112 112 {
113 113 ChartAnimation *animation = m_animations.value(item);
114 114
115 115 if (!animation) {
116 116 animation = new BarAnimation(item);
117 117 m_animations.insert(item, animation);
118 118 }
119 119
120 120 item->setAnimator(this);
121 121 }
122 122
123 123
124 124 void ChartAnimator::removeAnimation(Chart *item)
125 125 {
126 126 item->setAnimator(0);
127 127 m_animations.remove(item);
128 128 }
129 129
130 130 void ChartAnimator::updateLayout(Axis *item , QVector<qreal> &newLayout)
131 131 {
132 132 AxisAnimation *animation = static_cast<AxisAnimation*>(m_animations.value(item));
133 133
134 134 Q_ASSERT(animation);
135 135
136 136 QVector<qreal> oldLayout = item->layout();
137 137
138 138 if (newLayout.count() == 0)
139 139 return;
140 140
141 141 switch (m_state) {
142 142 case ZoomOutState: {
143 143 QRectF rect = item->geometry();
144 144 oldLayout.resize(newLayout.count());
145 145
146 for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; i++, j--) {
146 for(int i = 0, j = oldLayout.count() - 1; i < (oldLayout.count() + 1) / 2; ++i, --j) {
147 147 oldLayout[i] = item->axisType() == Axis::X_AXIS ? rect.left() : rect.bottom();
148 148 oldLayout[j] = item->axisType() == Axis::X_AXIS ? rect.right() : rect.top();
149 149 }
150 150 }
151 151 break;
152 152 case ZoomInState: {
153 153 int index = qMin(oldLayout.count() * (item->axisType() == Axis::X_AXIS ? m_point.x() : (1 - m_point.y())), newLayout.count() - 1.0);
154 154 oldLayout.resize(newLayout.count());
155 155
156 156 for(int i = 0; i < oldLayout.count(); i++)
157 157 oldLayout[i]= oldLayout[index];
158 158 }
159 159 break;
160 160 case ScrollDownState:
161 161 case ScrollRightState: {
162 162 oldLayout.resize(newLayout.count());
163 163
164 for(int i = 0, j = i + 1; i < oldLayout.count() - 1; i++, j++)
164 for(int i = 0, j = i + 1; i < oldLayout.count() - 1; ++i, ++j)
165 165 oldLayout[i]= oldLayout[j];
166 166 }
167 167 break;
168 168 case ScrollUpState:
169 169 case ScrollLeftState: {
170 170 oldLayout.resize(newLayout.count());
171 171
172 for(int i = oldLayout.count() - 1, j = i - 1; i > 0; i--, j--)
172 for(int i = oldLayout.count() - 1, j = i - 1; i > 0; --i, --j)
173 173 oldLayout[i]= oldLayout[j];
174 174 }
175 175 break;
176 176 default: {
177 177 oldLayout.resize(newLayout.count());
178 178 QRectF rect = item->geometry();
179 for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); i++, j--)
179 for(int i = 0, j = oldLayout.count() - 1; i < oldLayout.count(); ++i, --j)
180 180 oldLayout[i] = item->axisType() == Axis::X_AXIS ? rect.left() : rect.top();
181 181 }
182 182 break;
183 183 }
184 184
185 185
186 186 if (animation->state() != QAbstractAnimation::Stopped)
187 187 animation->stop();
188 188
189 189 animation->setDuration(duration);
190 190 animation->setEasingCurve(QEasingCurve::OutQuart);
191 191 QVariantAnimation::KeyValues value;
192 192 animation->setKeyValues(value); //workaround for wrong interpolation call
193 193 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
194 194 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
195 195
196 196 QTimer::singleShot(0, animation, SLOT(start()));
197 197 }
198 198
199 199 void ChartAnimator::updateLayout(SplineChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index)
200 200 {
201 201 SplineAnimation *animation = static_cast<SplineAnimation *>(m_animations.value(item));
202 202
203 203 Q_ASSERT(animation);
204 204
205 205 if (newPoints.count() < 2 || newControlPoints.count() < 2)
206 206 return;
207 207
208 208 bool empty = oldPoints.count() == 0;
209 209
210 210
211 211 if (animation->state() != QAbstractAnimation::Stopped)
212 212 animation->stop();
213 213
214 214 animation->setDuration(duration);
215 215 if (!empty)
216 216 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
217 217 else
218 218 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
219 219
220 220 animation->setEasingCurve(QEasingCurve::OutQuart);
221 221 animation->setValues(oldPoints, newPoints, oldControlPoints, newControlPoints, index);
222 222
223 223 QTimer::singleShot(0, animation, SLOT(start()));
224 224 }
225 225
226 226
227 227 void ChartAnimator::updateLayout(XYChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
228 228 {
229 229 XYAnimation *animation = static_cast<XYAnimation *>(m_animations.value(item));
230 230
231 231 Q_ASSERT(animation);
232 232
233 233 if (newPoints.count() == 0)
234 234 return;
235 235
236 236 bool empty = oldPoints.count() == 0;
237 237
238 238
239 239 if (animation->state() != QAbstractAnimation::Stopped)
240 240 animation->stop();
241 241
242 242 animation->setDuration(duration);
243 243 if (!empty)
244 244 animation->setAnimationType(ChartAnimation::MoveDownAnimation);
245 245 else
246 246 animation->setAnimationType(ChartAnimation::LineDrawAnimation);
247 247
248 248 animation->setEasingCurve(QEasingCurve::OutQuart);
249 249 animation->setValues(oldPoints, newPoints, index);
250 250
251 251 QTimer::singleShot(0, animation, SLOT(start()));
252 252 }
253 253
254 254 void ChartAnimator::addAnimation(PieChartItem *item, QPieSlice *slice, const PieSliceData &sliceData, bool isEmpty)
255 255 {
256 256 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
257 257 Q_ASSERT(animation);
258 258 animation->addSlice(slice, sliceData, isEmpty);
259 259 }
260 260
261 261 void ChartAnimator::removeAnimation(PieChartItem *item, QPieSlice *slice)
262 262 {
263 263 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
264 264 Q_ASSERT(animation);
265 265 animation->removeSlice(slice);
266 266 }
267 267
268 268 void ChartAnimator::updateLayout(PieChartItem *item, const PieLayout &layout)
269 269 {
270 270 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
271 271 Q_ASSERT(animation);
272 272 animation->updateValues(layout);
273 273 }
274 274
275 275 void ChartAnimator::updateLayout(PieChartItem *item, QPieSlice *slice, const PieSliceData &sliceData)
276 276 {
277 277 PieAnimation *animation = static_cast<PieAnimation *>(m_animations.value(item));
278 278 Q_ASSERT(animation);
279 279 animation->updateValue(slice, sliceData);
280 280 }
281 281
282 282 void ChartAnimator::updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout)
283 283 {
284 284 BarAnimation *animation = static_cast<BarAnimation *>(m_animations.value(item));
285 285 Q_ASSERT(animation);
286 286 animation->setDuration(duration);
287 287 animation->setKeyValueAt(0.0, qVariantFromValue(oldLayout));
288 288 animation->setKeyValueAt(1.0, qVariantFromValue(newLayout));
289 289 QTimer::singleShot(0, animation, SLOT(start()));
290 290 }
291 291
292 292
293 293 void ChartAnimator::setState(State state, const QPointF &point)
294 294 {
295 295 m_state = state;
296 296 m_point = point;
297 297 }
298 298
299 #include "moc_chartanimator_p.cpp"
300
299 301 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,78 +1,79
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef CHARTANIMATOR_P_H
22 22 #define CHARTANIMATOR_P_H
23 23
24 24 #include "qchartglobal.h"
25 25 #include "chartanimation_p.h"
26 26 #include "piechartitem_p.h"
27 27 #include "barchartitem_p.h"
28 28 #include <QPointF>
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31
32 32 class ChartItem;
33 33 class Axis;
34 34 class AreaChartItem;
35 35 class SplineChartItem;
36 36 class ScatterChartItem;
37 37 class LineChartItem;
38 38 class XYChartItem;
39 39
40 class ChartAnimator : public QObject {
41
40 class ChartAnimator : public QObject
41 {
42 Q_OBJECT
42 43 public:
43 44 enum State{ShowState, ScrollUpState, ScrollDownState, ScrollLeftState, ScrollRightState, ZoomInState, ZoomOutState};
44 45
45 46 ChartAnimator(QObject *parent = 0);
46 47 virtual ~ChartAnimator();
47 48
48 49 void addAnimation(Axis *item);
49 50 void addAnimation(PieChartItem *item);
50 51 void addAnimation(ScatterChartItem *item);
51 52 void addAnimation(LineChartItem *item);
52 53 void addAnimation(SplineChartItem *item);
53 54 void addAnimation(BarChartItem *item);
54 55 void removeAnimation(Chart *item);
55 56
56 57 void animationStarted();
57 58 void updateLayout(XYChartItem *item, QVector<QPointF> &oldLayout, QVector<QPointF> &newLayout, int index);
58 59 void updateLayout(SplineChartItem *item, QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newContorlPoints, int index);
59 60 void updateLayout(Axis *item, QVector<qreal> &layout);
60 61
61 62 void addAnimation(PieChartItem *item, QPieSlice *slice, const PieSliceData &sliceData, bool isEmpty);
62 63 void removeAnimation(PieChartItem *item, QPieSlice *slice);
63 64 void updateLayout(PieChartItem *item, const PieLayout &layout);
64 65 void updateLayout(PieChartItem *item, QPieSlice *slice, const PieSliceData &sliceData);
65 66
66 67 void updateLayout(BarChartItem *item, const QVector<QRectF> &oldLayout, const QVector<QRectF> &newLayout);
67 68
68 69 void setState(State state,const QPointF &point = QPointF());
69 70
70 71 private:
71 72 QMap<Chart *, ChartAnimation *> m_animations;
72 73 State m_state;
73 74 QPointF m_point;
74 75 };
75 76
76 77 QTCOMMERCIALCHART_END_NAMESPACE
77 78
78 79 #endif
@@ -1,149 +1,149
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "splineanimation_p.h"
22 22 #include "splinechartitem_p.h"
23 23
24 24 Q_DECLARE_METATYPE(QVector<QPointF>)
25 25 Q_DECLARE_METATYPE(SplineVector)
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 SplineAnimation::SplineAnimation(SplineChartItem* item):ChartAnimation(item),
30 30 m_item(item),
31 31 m_dirty(true)
32 32 {
33 33 }
34 34
35 35 SplineAnimation::~SplineAnimation()
36 36 {
37 37 }
38 38
39 39 void SplineAnimation::setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, QVector<QPointF> &oldControlPoints, QVector<QPointF> &newControlPoints, int index)
40 40 {
41 41 int x = oldPoints.count();
42 42 int y = newPoints.count();
43 43
44 44 Q_ASSERT(newPoints.count() * 2 - 2 == newControlPoints.count());
45 45
46 46 if (x != y && abs(x - y) != 1) {
47 47 m_oldSpline.first = newPoints;
48 48 m_oldSpline.second = newControlPoints;
49 49 oldPoints.resize(newPoints.size());
50 50 oldControlPoints.resize(newControlPoints.size());
51 51 SplineVector oldPair;
52 52 oldPair.first = oldPoints;
53 53 oldPair.second = oldControlPoints;
54 54 SplineVector newPair;
55 55 newPair.first = newPoints;
56 56 newPair.second = newControlPoints;
57 57 setKeyValueAt(0.0, qVariantFromValue(oldPair));
58 58 setKeyValueAt(1.0, qVariantFromValue(newPair));
59 59 m_dirty = false;
60 60 }
61 61 else {
62 62 if(m_dirty) {
63 63 m_oldSpline.first = oldPoints;
64 64 m_oldSpline.second = oldControlPoints;
65 65 m_dirty = false;
66 66 }
67 67 oldPoints = newPoints;
68 68 oldControlPoints = newControlPoints;
69 69 if (y < x) {
70 70 m_oldSpline.first.remove(index); //remove
71 71 m_oldSpline.second.remove(index * 2);
72 72 m_oldSpline.second.remove(index * 2);
73 73 }
74 74 if (y > x) {
75 75 m_oldSpline.first.insert(index, x > 0 ? m_oldSpline.first[index-1] : newPoints[index]); //add
76 76 m_oldSpline.second.insert((index - 1) * 2, x > 1 ? m_oldSpline.second[(index-2)*2] : newControlPoints[(index - 1) * 2]); //add
77 77 m_oldSpline.second.insert((index - 1) * 2 + 1, x > 1 ? m_oldSpline.second[(index - 2) * 2 + 1] : newControlPoints[(index - 1) * 2 + 1]); //add
78 78 }
79 79 SplineVector newPair;
80 80 newPair.first=newPoints;
81 81 newPair.second=newControlPoints;
82 82 setKeyValueAt(0.0, qVariantFromValue(m_oldSpline));
83 83 setKeyValueAt(1.0, qVariantFromValue(newPair));
84 84
85 85 }
86 86 }
87 87
88 88 QVariant SplineAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const
89 89 {
90 90
91 91 SplineVector startPair = qVariantValue< SplineVector >(start);
92 92 SplineVector endPair = qVariantValue< SplineVector >(end);
93 93 SplineVector result;
94 94
95 95
96 96 switch (m_type) {
97 97
98 98 case MoveDownAnimation: {
99 99 if (startPair.first.count() != endPair.first.count())
100 100 break;
101 101 Q_ASSERT(startPair.first.count() * 2 - 2 == startPair.second.count());
102 102 Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count());
103 103 for(int i = 0; i < endPair.first.count(); i++) {
104 104 qreal x = startPair.first[i].x() + ((endPair.first[i].x() - startPair.first[i].x()) * progress);
105 105 qreal y = startPair.first[i].y() + ((endPair.first[i].y() - startPair.first[i].y()) * progress);
106 106 result.first << QPointF(x,y);
107 107 if (i + 1 >= endPair.first.count())
108 108 continue;
109 109 x = startPair.second[i * 2].x() + ((endPair.second[i * 2].x() - startPair.second[i * 2].x()) * progress);
110 110 y = startPair.second[i * 2].y() + ((endPair.second[i * 2].y() - startPair.second[i * 2].y()) * progress);
111 111 result.second << QPoint(x,y);
112 112 x = startPair.second[i * 2 + 1].x() + ((endPair.second[i * 2 + 1].x() - startPair.second[i * 2 + 1].x()) * progress);
113 113 y = startPair.second[i * 2 + 1].y() + ((endPair.second[i * 2 + 1].y() - startPair.second[i * 2 + 1].y()) * progress);
114 114 result.second << QPoint(x,y);
115 115 }
116 116
117 117 }
118 118 break;
119 119 case LineDrawAnimation:{
120 120 Q_ASSERT(endPair.first.count() * 2 - 2 == endPair.second.count());
121 int count = endPair.first.count()* qBound(0.0, progress, 1.0);
121 int count = endPair.first.count()* qBound(qreal(0), progress, qreal(1));
122 122 for(int i = 0; i < count; i++) {
123 123 result.first << endPair.first[i];
124 124 if(i + 1 == count)
125 125 break;
126 126 result.second << endPair.second[2 * i];
127 127 result.second << endPair.second[2 * i + 1];
128 128 }
129 129 }
130 130 break;
131 131 default:
132 132 qWarning() << "Unknow type of animation";
133 133 break;
134 134 }
135 135
136 136 return qVariantFromValue(result);
137 137 }
138 138
139 139 void SplineAnimation::updateCurrentValue (const QVariant &value )
140 140 {
141 141 if (state() != QAbstractAnimation::Stopped) { //workaround
142 142 m_dirty = true;
143 143 QPair<QVector<QPointF >, QVector<QPointF > > pair = qVariantValue< QPair< QVector<QPointF>, QVector<QPointF> > >(value);
144 144 m_item->setLayout(pair.first, pair.second);
145 145 }
146 146 }
147 147
148 148
149 149 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,109 +1,109
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "xyanimation_p.h"
22 22 #include "xychartitem_p.h"
23 23
24 24 Q_DECLARE_METATYPE(QVector<QPointF>)
25 25
26 26 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 27
28 28 XYAnimation::XYAnimation(XYChartItem *item):ChartAnimation(item),
29 29 m_item(item),
30 30 m_dirty(false)
31 31 {
32 32 }
33 33
34 34 XYAnimation::~XYAnimation()
35 35 {
36 36 }
37 37
38 38 void XYAnimation::setValues(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
39 39 {
40 40 int x = oldPoints.count();
41 41 int y = newPoints.count();
42 42
43 43 if (x != y && abs(x - y) != 1) {
44 44 m_oldPoints = newPoints;
45 45 oldPoints.resize(newPoints.size());
46 46 setKeyValueAt(0.0, qVariantFromValue(oldPoints));
47 47 setKeyValueAt(1.0, qVariantFromValue(newPoints));
48 48 m_dirty = false;
49 49 }
50 50 else {
51 51 if (m_dirty) {
52 52 m_oldPoints = oldPoints;
53 53 m_dirty = false;
54 54 }
55 55 oldPoints = newPoints;
56 56 if (y < x)
57 57 m_oldPoints.remove(index); //remove
58 58 if (y > x)
59 59 m_oldPoints.insert(index, x > 0 ? m_oldPoints[index-1] : newPoints[index]); //add
60 60 setKeyValueAt(0.0, qVariantFromValue(m_oldPoints));
61 61 setKeyValueAt(1.0, qVariantFromValue(newPoints));
62 62 Q_ASSERT(m_oldPoints.count() == newPoints.count());
63 63 }
64 64 }
65 65
66 66 QVariant XYAnimation::interpolated(const QVariant &start, const QVariant &end, qreal progress ) const
67 67 {
68 68 QVector<QPointF> startVector = qVariantValue<QVector<QPointF> >(start);
69 69 QVector<QPointF> endVector = qVariantValue<QVector<QPointF> >(end);
70 70 QVector<QPointF> result;
71 71
72 72 switch (m_type) {
73 73
74 74 case MoveDownAnimation: {
75 75
76 76 if (startVector.count() != endVector.count())
77 77 break;
78 78
79 79 for(int i = 0; i < startVector.count(); i++) {
80 80 qreal x = startVector[i].x() + ((endVector[i].x() - startVector[i].x()) * progress);
81 81 qreal y = startVector[i].y() + ((endVector[i].y() - startVector[i].y()) * progress);
82 82 result << QPointF(x, y);
83 83 }
84 84
85 85 }
86 86 break;
87 87 case LineDrawAnimation: {
88 for(int i = 0; i < endVector.count() * qBound(0.0, progress, 1.0); i++)
88 for(int i = 0; i < endVector.count() * qBound(qreal(0), progress, qreal(1)); i++)
89 89 result << endVector[i];
90 90 }
91 91 break;
92 92 default:
93 93 qWarning() << "Unknown type of animation";
94 94 break;
95 95 }
96 96
97 97 return qVariantFromValue(result);
98 98 }
99 99
100 100 void XYAnimation::updateCurrentValue (const QVariant &value)
101 101 {
102 102 if(state()!=QAbstractAnimation::Stopped){ //workaround
103 103 m_dirty = true;
104 104 QVector<QPointF> vector = qVariantValue<QVector<QPointF> >(value);
105 105 m_item->setLayout(vector);
106 106 }
107 107 }
108 108
109 109 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,282 +1,282
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qareaseries.h"
22 22 #include "qareaseries_p.h"
23 23 #include "qlineseries.h"
24 24 #include "areachartitem_p.h"
25 25 #include "legendmarker_p.h"
26 26 #include "domain_p.h"
27 27 #include "chartdataset_p.h"
28 28 #include "charttheme_p.h"
29 29 #include "chartanimator_p.h"
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 /*!
34 34 \class QAreaSeries
35 35 \brief The QAreaSeries class is used for making area charts.
36 36
37 37 \mainclass
38 38
39 39 An area chart is used to show quantitative data. It is based on line chart, in the way that area between axis and the line
40 40 is emphasized with color. Since the area chart is based on line chart, QAreaSeries constructor needs QLineSeries instance,
41 41 which defines "upper" boundary of the area. "Lower" boundary is defined by default by axis X. Instead of axis X "lower" boundary can be specified by other line.
42 42 In that case QAreaSeries should be initiated with two QLineSerie instances. Please note terms "upper" and "lower" boundary can be misleading in cases
43 43 where "lower" boundary had bigger values than the "upper" one, however the main point that area between these two boundary lines will be filled.
44 44
45 45 \image areachart.png
46 46
47 47 Creating basic area chart is simple:
48 48 \code
49 49 QLineSeries* lineSeries = new QLineSeries();
50 50 series->append(0, 6);
51 51 series->append(2, 4);
52 52 QAreaSeries* areaSeries = new QAreaSeries(lineSeries);
53 53 ...
54 54 chartView->addSeries(areaSeries);
55 55 \endcode
56 56 */
57 57
58 58 /*!
59 59 \fn virtual QSeriesType QAreaSeries::type() const
60 60 \brief Returns type of series.
61 61 \sa QSeries, QSeriesType
62 62 */
63 63
64 64 /*!
65 65 \fn QLineSeries* QAreaSeries::upperSeries() const
66 66 \brief Returns upperSeries used to define one of area boundaries.
67 67 */
68 68
69 69 /*!
70 70 \fn QLineSeries* QAreaSeries::lowerSeries() const
71 71 \brief Returns lowerSeries used to define one of area boundaries. Note if QAreaSeries where counstucted wihtout a\ lowerSeries
72 72 this function return Null pointer.
73 73 */
74 74
75 75 /*!
76 76 \fn QPen QAreaSeries::pen() const
77 77 \brief Returns the pen used to draw line for this series.
78 78 \sa setPen()
79 79 */
80 80
81 81 /*!
82 82 \fn QPen QAreaSeries::brush() const
83 83 \brief Returns the brush used to draw line for this series.
84 84 \sa setBrush()
85 85 */
86 86
87 87 /*!
88 88 \fn bool QAreaSeries::pointsVisible() const
89 89 \brief Returns if the points are drawn for this series.
90 90 \sa setPointsVisible()
91 91 */
92 92
93 93 /*!
94 94 \fn void QAreaSeries::clicked(const QPointF& point)
95 95 \brief Signal is emitted when user clicks the \a point on area chart.
96 96 */
97 97
98 98 /*!
99 99 \fn void QAreaSeries::selected()
100 100
101 101 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
102 102 implemented by the user of QAreaSeries API.
103 103 */
104 104
105 105 /*!
106 106 \fn void QAreaSeriesPrivate::updated()
107 107 \brief \internal
108 108 */
109 109
110 110 /*!
111 111 Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a
112 112 upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead.
113 When series object is added to QChartView or QChart instance ownerships is transfered.
113 When series object is added to QChartView or QChart instance ownerships is transferred.
114 114 */
115 115 QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries)
116 116 : QSeries(*new QAreaSeriesPrivate(upperSeries,lowerSeries,this),upperSeries)
117 117 {
118 118 }
119 119
120 120 /*!
121 121 Destroys the object. Series added to QChartView or QChart instances are owned by those,
122 122 and are deleted when mentioned object are destroyed.
123 123 */
124 124 QAreaSeries::~QAreaSeries()
125 125 {
126 126 }
127 127
128 128
129 129 QSeries::QSeriesType QAreaSeries::type() const
130 130 {
131 131 return QSeries::SeriesTypeArea;
132 132 }
133 133
134 134 QLineSeries* QAreaSeries::upperSeries() const
135 135 {
136 136 Q_D(const QAreaSeries);
137 137 return d->m_upperSeries;
138 138 }
139 139
140 140 QLineSeries* QAreaSeries::lowerSeries() const
141 141 {
142 142 Q_D(const QAreaSeries);
143 143 return d->m_lowerSeries;
144 144 }
145 145
146 146 /*!
147 147 Sets \a pen used for drawing area outline.
148 148 */
149 149 void QAreaSeries::setPen(const QPen &pen)
150 150 {
151 151 Q_D(QAreaSeries);
152 152 if (d->m_pen != pen) {
153 153 d->m_pen = pen;
154 154 emit d->updated();
155 155 }
156 156 }
157 157
158 158 QPen QAreaSeries::pen() const
159 159 {
160 160 Q_D(const QAreaSeries);
161 161 return d->m_pen;
162 162 }
163 163
164 164 /*!
165 165 Sets \a brush used for filling the area.
166 166 */
167 167 void QAreaSeries::setBrush(const QBrush &brush)
168 168 {
169 169 Q_D(QAreaSeries);
170 170 if (d->m_brush != brush) {
171 171 d->m_brush = brush;
172 172 emit d->updated();
173 173 }
174 174 }
175 175
176 176 QBrush QAreaSeries::brush() const
177 177 {
178 178 Q_D(const QAreaSeries);
179 179 return d->m_brush;
180 180 }
181 181 /*!
182 182 Sets if data points are \a visible and should be drawn on line.
183 183 */
184 184 void QAreaSeries::setPointsVisible(bool visible)
185 185 {
186 186 Q_D(QAreaSeries);
187 187 if (d->m_pointsVisible != visible) {
188 188 d->m_pointsVisible = visible;
189 189 emit d->updated();
190 190 }
191 191 }
192 192
193 193 bool QAreaSeries::pointsVisible() const
194 194 {
195 195 Q_D(const QAreaSeries);
196 196 return d->m_pointsVisible;
197 197 }
198 198
199 199 bool QAreaSeries::setModel(QAbstractItemModel* model)
200 200 {
201 201 Q_UNUSED(model);
202 202 qWarning()<<"Not implemented";
203 203 return false;
204 204 }
205 205
206 206 QAbstractItemModel* QAreaSeries::model() const
207 207 {
208 208 return 0;
209 209 }
210 210
211 211 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
212 212
213 213 QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries,QAreaSeries* q) :
214 214 QSeriesPrivate(q),
215 215 m_upperSeries(upperSeries),
216 216 m_lowerSeries(lowerSeries),
217 217 m_pointsVisible(false)
218 218 {
219 219 }
220 220
221 221 void QAreaSeriesPrivate::scaleDomain(Domain& domain)
222 222 {
223 223 Q_Q(QAreaSeries);
224 224
225 225 qreal minX(domain.minX());
226 226 qreal minY(domain.minY());
227 227 qreal maxX(domain.maxX());
228 228 qreal maxY(domain.maxY());
229 229 int tickXCount(domain.tickXCount());
230 230 int tickYCount(domain.tickYCount());
231 231
232 232 QLineSeries* upperSeries = q->upperSeries();
233 233 QLineSeries* lowerSeries = q->lowerSeries();
234 234
235 235 for (int i = 0; i < upperSeries->count(); i++)
236 236 {
237 237 qreal x = upperSeries->x(i);
238 238 qreal y = upperSeries->y(i);
239 239 minX = qMin(minX, x);
240 240 minY = qMin(minY, y);
241 241 maxX = qMax(maxX, x);
242 242 maxY = qMax(maxY, y);
243 243 }
244 244 if(lowerSeries) {
245 245 for (int i = 0; i < lowerSeries->count(); i++)
246 246 {
247 247 qreal x = lowerSeries->x(i);
248 248 qreal y = lowerSeries->y(i);
249 249 minX = qMin(minX, x);
250 250 minY = qMin(minY, y);
251 251 maxX = qMax(maxX, x);
252 252 maxY = qMax(maxY, y);
253 253 }}
254 254
255 255 domain.setRangeX(minX,maxX,tickXCount);
256 256 domain.setRangeY(minY,maxY,tickYCount);
257 257 }
258 258
259 259 Chart* QAreaSeriesPrivate::createGraphics(ChartPresenter* presenter)
260 260 {
261 261 Q_Q(QAreaSeries);
262 262
263 263 AreaChartItem* area = new AreaChartItem(q,presenter);
264 264 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
265 265 presenter->animator()->addAnimation(area->upperLineItem());
266 266 if(q->lowerSeries()) presenter->animator()->addAnimation(area->lowerLineItem());
267 267 }
268 268 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
269 269 return area;
270 270 }
271 271
272 272 QList<LegendMarker*> QAreaSeriesPrivate::createLegendMarker(QLegend* legend)
273 273 {
274 274 Q_Q(QAreaSeries);
275 275 QList<LegendMarker*> list;
276 276 return list << new AreaLegendMarker(q,legend);
277 277 }
278 278
279 279 #include "moc_qareaseries.cpp"
280 280 #include "moc_qareaseries_p.cpp"
281 281
282 282 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,96 +1,96
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchartaxiscategories.h"
22 22 #include "qchartaxiscategories_p.h"
23 23
24 24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 25
26 26 QChartAxisCategories::QChartAxisCategories():
27 27 d_ptr(new QChartAxisCategoriesPrivate(this))
28 28 {
29 29
30 30 }
31 31
32 32 QChartAxisCategories::~QChartAxisCategories()
33 33 {
34 34
35 35 }
36 36
37 37 void QChartAxisCategories::insert(const QBarCategories &categories)
38 38 {
39 39 int i=1;
40 foreach (QString string , categories) {
40 foreach (const QString& string , categories) {
41 41 d_ptr->m_map.insert(i,string);
42 42 i++;
43 43 }
44 44 emit d_ptr->updated();
45 45 }
46 46
47 47 void QChartAxisCategories::insert(qreal value,QString label)
48 48 {
49 49 d_ptr->m_map.insert(value,label);
50 50 emit d_ptr->updated();
51 51 }
52 52
53 53 void QChartAxisCategories::remove(qreal value)
54 54 {
55 55 d_ptr->m_map.remove(value);
56 56 emit d_ptr->updated();
57 57 }
58 58
59 59 void QChartAxisCategories::clear()
60 60 {
61 61 d_ptr->m_map.clear();
62 62 emit d_ptr->updated();
63 63 }
64 64
65 65 int QChartAxisCategories::count()
66 66 {
67 67 return d_ptr->m_map.count();
68 68 }
69 69
70 70 QList<qreal> QChartAxisCategories::values() const
71 71 {
72 72 return d_ptr->m_map.keys();
73 73 }
74 74
75 75 QString QChartAxisCategories::label(qreal value) const
76 76 {
77 77 return d_ptr->m_map.value(value);
78 78 }
79 79
80 80 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 81
82 82 QChartAxisCategoriesPrivate::QChartAxisCategoriesPrivate(QChartAxisCategories *q):
83 83 q_ptr(q)
84 84 {
85 85
86 86 }
87 87
88 88 QChartAxisCategoriesPrivate::~QChartAxisCategoriesPrivate()
89 89 {
90 90
91 91 }
92 92
93 93 #include "moc_qchartaxiscategories.cpp"
94 94 #include "moc_qchartaxiscategories_p.cpp"
95 95
96 96 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,198 +1,198
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "barchartmodel_p.h"
22 22 #include "qbarset.h"
23 23 #include <limits.h>
24 24 #include <QVector>
25 25 #include <QDebug>
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 BarChartModel::BarChartModel(QStringList categories, QObject *parent) : QObject(parent),
30 30 m_category(categories)
31 31 {
32 32 }
33 33
34 34 QStringList BarChartModel::category()
35 35 {
36 36 return m_category;
37 37 }
38 38
39 39 void BarChartModel::appendBarSet(QBarSet *set)
40 40 {
41 41 m_dataModel.append(set);
42 42 }
43 43
44 44 void BarChartModel::removeBarSet(QBarSet *set)
45 45 {
46 46 if (m_dataModel.contains(set)) {
47 47 m_dataModel.removeOne(set);
48 48 }
49 49 }
50 50
51 51 void BarChartModel::insertBarSet(int i, QBarSet *set)
52 52 {
53 53 m_dataModel.insert(i, set);
54 54 }
55 55
56 56 void BarChartModel::insertCategory(int i, QString category)
57 57 {
58 58 m_category.insert(i, category);
59 59 }
60 60
61 61 void BarChartModel::removeCategory(int i)
62 62 {
63 63 m_category.removeAt(i);
64 64 }
65 65
66 66 QBarSet* BarChartModel::barsetAt(int index) const
67 67 {
68 68 return m_dataModel.at(index);
69 69 }
70 70
71 71 QList<QBarSet*> BarChartModel::barSets() const
72 72 {
73 73 return m_dataModel;
74 74 }
75 75
76 76 int BarChartModel::barsetCount() const
77 77 {
78 78 return m_dataModel.count();
79 79 }
80 80
81 81 int BarChartModel::categoryCount() const
82 82 {
83 83 return m_category.count();
84 84 }
85 85
86 86 qreal BarChartModel::min() const
87 87 {
88 88 Q_ASSERT(m_dataModel.count() > 0);
89 89 // TODO: make min and max members and update them when data changes.
90 90 // This is slower since they are checked every time, even if data is same since previous call.
91 91 qreal min = INT_MAX;
92 92
93 93 for (int i = 0; i < m_dataModel.count(); i++) {
94 94 int itemCount = m_dataModel.at(i)->count();
95 95 for (int j = 0; j < itemCount; j++) {
96 96 qreal temp = m_dataModel.at(i)->valueAt(j);
97 97 if (temp < min)
98 98 min = temp;
99 99 }
100 100 }
101 101 return min;
102 102 }
103 103
104 104 qreal BarChartModel::max() const
105 105 {
106 106 if (m_dataModel.count() == 0) return 0;
107 107 // TODO: make min and max members and update them when data changes.
108 108 // This is slower since they are checked every time, even if data is same since previous call.
109 109 qreal max = INT_MIN;
110 110
111 111 for (int i = 0; i < m_dataModel.count(); i++) {
112 112 int itemCount = m_dataModel.at(i)->count();
113 113 for (int j = 0; j < itemCount; j++) {
114 114 qreal temp = m_dataModel.at(i)->valueAt(j);
115 115 if (temp > max)
116 116 max = temp;
117 117 }
118 118 }
119 119
120 120 return max;
121 121 }
122 122
123 123 qreal BarChartModel::valueAt(int set, int category) const
124 124 {
125 125 if ((set < 0) || (set >= m_dataModel.count())) {
126 126 // No set, no value.
127 127 return 0;
128 128 } else if ((category < 0) || (category >= m_dataModel.at(set)->count())) {
129 129 // No category, no value.
130 130 return 0;
131 131 }
132 132
133 133 return m_dataModel.at(set)->valueAt(category);
134 134 }
135 135
136 136 qreal BarChartModel::percentageAt(int set, int category) const
137 137 {
138 138 if ((set < 0) || (set >= m_dataModel.count())) {
139 139 // No set, no value.
140 140 return 0;
141 141 } else if ((category < 0) || (category >= m_dataModel.at(set)->count())) {
142 142 // No category, no value.
143 143 return 0;
144 144 }
145 145
146 146 qreal value = m_dataModel.at(set)->valueAt(category);
147 147 qreal total = categorySum(category);
148 148 if ( qFuzzyCompare(total, 0) )
149 149 return 0;
150 150
151 151 return value / total;
152 152 }
153 153
154 154 qreal BarChartModel::categorySum(int category) const
155 155 {
156 156 qreal sum(0);
157 157 int count = m_dataModel.count(); // Count sets
158 158
159 159 for (int set = 0; set < count; set++) {
160 160 if (category < m_dataModel.at(set)->count())
161 161 sum += m_dataModel.at(set)->valueAt(category);
162 162 }
163 163 return sum;
164 164 }
165 165
166 166 qreal BarChartModel::absoluteCategorySum(int category) const
167 167 {
168 168 qreal sum(0);
169 169 int count = m_dataModel.count(); // Count sets
170 170
171 171 for (int set = 0; set < count; set++) {
172 172 if (category < m_dataModel.at(set)->count())
173 173 sum += qAbs(m_dataModel.at(set)->valueAt(category));
174 174 }
175 175 return sum;
176 176 }
177 177
178 178 qreal BarChartModel::maxCategorySum() const
179 179 {
180 180 qreal max = INT_MIN;
181 181 int count = categoryCount();
182 182
183 183 for (int col = 0; col < count; col++) {
184 184 qreal sum = categorySum(col);
185 185 if (sum > max)
186 186 max = sum;
187 187 }
188 188 return max;
189 189 }
190 190
191 191 QString BarChartModel::categoryName(int category)
192 192 {
193 193 return m_category.at(category);
194 194 }
195 195
196 196 #include "moc_barchartmodel_p.cpp"
197 197
198 QTCOMMERCIALCHART_END_NAMESPACE No newline at end of file
198 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,540 +1,540
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qbarseries.h"
22 22 #include "qbarseries_p.h"
23 23 #include "qbarset.h"
24 24 #include "qbarset_p.h"
25 25 #include "barchartmodel_p.h"
26 26 #include "domain_p.h"
27 27 #include "legendmarker_p.h"
28 28 #include "chartdataset_p.h"
29 29 #include "charttheme_p.h"
30 30 #include "chartanimator_p.h"
31 31
32 32 #include <QAbstractItemModel>
33 33 #include <QModelIndex>
34 34
35 35 QTCOMMERCIALCHART_BEGIN_NAMESPACE
36 36
37 37 /*!
38 38 \class QBarSeries
39 39 \brief part of QtCommercial chart API.
40 40
41 QBarSeries represents a series of data shown as bars. One QBarSeries can contain multible
41 QBarSeries represents a series of data shown as bars. One QBarSeries can contain multiple
42 42 QBarSet data sets. QBarSeries groups the data from sets to categories, which are defined
43 43 by QStringList.
44 44
45 45 \mainclass
46 46
47 47 \sa QBarSet, QStackedBarSeries, QPercentBarSeries
48 48 */
49 49
50 50 /*!
51 51 \fn virtual QSeriesType QBarSeries::type() const
52 52 \brief Returns type of series.
53 53 \sa QSeries, QSeriesType
54 54 */
55 55
56 56 /*!
57 57 \fn void QBarSeries::clicked(QBarSet *barset, QString category, Qt::MouseButtons button)
58 58
59 59 The signal is emitted if the user clicks with a mouse \a button on top of QBarSet \a barset of category \a category
60 60 contained by the series.
61 61 */
62 62
63 63 /*!
64 64 \fn void QBarSeries::selected()
65 65
66 66 The signal is emitted if the user selects/deselects the series. The logic for storing selections should be
67 67 implemented by the user of QBarSeries API.
68 68 */
69 69
70 70 /*!
71 71 Constructs empty QBarSeries. Parameter \a categories defines the categories for chart.
72 72 QBarSeries is QObject which is a child of a \a parent.
73 73 */
74 74 QBarSeries::QBarSeries(QBarCategories categories, QObject *parent) :
75 75 QSeries(*new QBarSeriesPrivate(categories, this),parent)
76 76 {
77 77 }
78 78
79 79 /*!
80 80 \internal
81 81 */
82 82 QBarSeries::QBarSeries(QBarSeriesPrivate &d, QObject *parent) :
83 83 QSeries(d,parent)
84 84 {
85 85 }
86 86
87 87 QSeries::QSeriesType QBarSeries::type() const
88 88 {
89 89 return QSeries::SeriesTypeBar;
90 90 }
91 91
92 92 /*!
93 93 Adds a set of bars to series. Takes ownership of \a set.
94 94 Connects the clicked(QString, Qt::MouseButtons) signal
95 95 of \a set to this series
96 96 */
97 97 void QBarSeries::appendBarSet(QBarSet *set)
98 98 {
99 99 Q_D(QBarSeries);
100 100 d->m_internalModel->appendBarSet(set);
101 101 QObject::connect(set->d_ptr.data(), SIGNAL(valueChanged()), d, SLOT(barsetChanged()));
102 102 emit d->restructuredBars();
103 103 }
104 104
105 105 /*!
106 Removes a set of bars from series. Releases ownership of \a set. Doesnt delete \a set.
106 Removes a set of bars from series. Releases ownership of \a set. Doesn't delete \a set.
107 107 Disconnects the clicked(QString, Qt::MouseButtons) signal
108 108 of \a set from this series
109 109 */
110 110 void QBarSeries::removeBarSet(QBarSet *set)
111 111 {
112 112 Q_D(QBarSeries);
113 113 d->m_internalModel->removeBarSet(set);
114 114 emit d->restructuredBars();
115 115 }
116 116
117 117 /*!
118 118 Adds a list of barsets to series. Takes ownership of \a sets.
119 119 Connects the clicked(QString, Qt::MouseButtons) signals
120 120 of \a sets to this series
121 121 */
122 122 void QBarSeries::appendBarSets(QList<QBarSet* > sets)
123 123 {
124 124 Q_D(QBarSeries);
125 125 foreach (QBarSet* barset, sets) {
126 126 d->m_internalModel->appendBarSet(barset);
127 127 QObject::connect(barset, SIGNAL(valueChanged()), this, SLOT(barsetChanged()));
128 128 }
129 129 emit d->restructuredBars();
130 130
131 131 }
132 132
133 133 /*!
134 Removes a list of barsets from series. Releases ownership of \a sets. Doesnt delete \a sets.
134 Removes a list of barsets from series. Releases ownership of \a sets. Doesn't delete \a sets.
135 135 Disconnects the clicked(QString, Qt::MouseButtons) signal
136 136 of \a sets from this series
137 137 */
138 138 void QBarSeries::removeBarSets(QList<QBarSet* > sets)
139 139 {
140 140 Q_D(QBarSeries);
141 141
142 142 foreach (QBarSet* barset, sets) {
143 143 d->m_internalModel->removeBarSet(barset);
144 144 }
145 145 emit d->restructuredBars();
146 146 }
147 147
148 148 /*!
149 149 Inserts new \a set on the \a i position.
150 150 The barset that is currently at this postion is moved to postion i + 1
151 151 */
152 152 void QBarSeries::insertBarSet(int i, QBarSet *set)
153 153 {
154 154 Q_D(QBarSeries);
155 155 d->m_internalModel->insertBarSet(i, set);
156 156 emit d->barsetChanged();
157 157 }
158 158
159 159 /*!
160 160 Inserts new \a category on the \a i position.
161 161 The category that is currently at this postion is moved to postion i + 1
162 162 \sa removeCategory()
163 163 */
164 164 void QBarSeries::insertCategory(int i, QString category)
165 165 {
166 166 Q_D(QBarSeries);
167 167 d->m_internalModel->insertCategory(i, category);
168 168 }
169 169
170 170 /*!
171 171 Removes the category specified by \a i
172 172 \sa insertCategory()
173 173 */
174 174 void QBarSeries::removeCategory(int i)
175 175 {
176 176 Q_D(QBarSeries);
177 177 d->m_internalModel->removeCategory(i);
178 178 }
179 179
180 180 /*!
181 181 Returns number of sets in series.
182 182 */
183 183 int QBarSeries::barsetCount() const
184 184 {
185 185 Q_D(const QBarSeries);
186 186 return d->m_internalModel->barsetCount();
187 187 }
188 188
189 189 /*!
190 190 Returns number of categories in series
191 191 */
192 192 int QBarSeries::categoryCount() const
193 193 {
194 194 Q_D(const QBarSeries);
195 195 return d->m_internalModel->categoryCount();
196 196 }
197 197
198 198 /*!
199 199 Returns a list of sets in series. Keeps ownership of sets.
200 200 */
201 201 QList<QBarSet*> QBarSeries::barSets() const
202 202 {
203 203 Q_D(const QBarSeries);
204 204 return d->m_internalModel->barSets();
205 205 }
206 206
207 207 /*!
208 208 Enables or disables tooltip depending on parameter \a enabled.
209 209 Tooltip shows the name of set, when mouse is hovering on top of bar.
210 210 Calling without parameter \a enabled, enables the tooltip
211 211 */
212 212 void QBarSeries::setToolTipEnabled(bool enabled)
213 213 {
214 214 Q_D(QBarSeries);
215 215 d->setToolTipEnabled(enabled);
216 216 }
217 217
218 218 /*!
219 219 \fn bool QBarSeries::setModel(QAbstractItemModel *model)
220 220 Sets the \a model to be used as a data source
221 221 */
222 222 bool QBarSeries::setModel(QAbstractItemModel *model)
223 223 {
224 224 Q_D(QBarSeries);
225 225 return d->setModel(model);
226 226 }
227 227
228 228 /*!
229 229 \fn bool QBarSeries::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
230 230 Sets column/row specified by \a categories to be used as a list of bar series categories.
231 231 Parameter \a bottomBoundry indicates the column/row where the first bar set is located in the model.
232 232 Parameter \a topBoundry indicates the column/row where the last bar set is located in the model.
233 233 All the columns/rows inbetween those two values are also used as data for bar sets.
234 The \a orientation paramater specifies whether the data is in columns or in rows.
234 The \a orientation parameter specifies whether the data is in columns or in rows.
235 235 */
236 236 void QBarSeries::setModelMapping(int categories, int bottomBoundary, int topBoundary, Qt::Orientation orientation)
237 237 {
238 238 Q_D(QBarSeries);
239 239 d->setModelMapping(categories,bottomBoundary,topBoundary,orientation);
240 240 }
241 241
242 242 /*!
243 243 Returns the bar categories of the series.
244 244 */
245 245 QBarCategories QBarSeries::categories() const
246 246 {
247 247 Q_D(const QBarSeries);
248 248
249 249 QBarCategories categories;
250 250 int count = d->m_internalModel->categoryCount();
251 251 for (int i=1; i <= count; i++) {
252 252 categories.insert(i, d->m_internalModel->categoryName(i - 1));
253 253 }
254 254 return categories;
255 255
256 256 }
257 257
258 258 /*!
259 259 Sets the visibility of labels in series to \a visible
260 260 */
261 261 void QBarSeries::setLabelsVisible(bool visible)
262 262 {
263 263 foreach (QBarSet* s, barSets()) {
264 264 s->setLabelsVisible(visible);
265 265 }
266 266 }
267 267
268 268 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
269 269
270 270 QBarSeriesPrivate::QBarSeriesPrivate(QBarCategories categories, QBarSeries *q) : QSeriesPrivate(q),
271 271 m_internalModel(new BarChartModel(categories,this)),
272 272 m_model(0),
273 273 m_mapCategories(-1),
274 274 m_mapBarBottom(-1),
275 275 m_mapBarTop(-1),
276 276 m_mapFirst(0),
277 277 m_mapCount(0),
278 278 m_mapOrientation(Qt::Vertical)
279 279 {
280 280 }
281 281
282 282 QBarSet* QBarSeriesPrivate::barsetAt(int index)
283 283 {
284 284 return m_internalModel->barsetAt(index);
285 285 }
286 286
287 287 QString QBarSeriesPrivate::categoryName(int category)
288 288 {
289 289 return m_internalModel->categoryName(category);
290 290 }
291 291
292 292 void QBarSeriesPrivate::setToolTipEnabled(bool enabled)
293 293 {
294 294 // TODO: what if we add sets after call to this function? Those sets won't have tooltip enabled.
295 295 if (enabled) {
296 296 for (int i=0; i<m_internalModel->barsetCount(); i++) {
297 297 QBarSet *set = m_internalModel->barsetAt(i);
298 298 connect(set->d_ptr.data(), SIGNAL(showToolTip(QPoint,QString)), this, SIGNAL(showToolTip(QPoint,QString)));
299 299 }
300 300 } else {
301 301 for (int i=0; i<m_internalModel->barsetCount(); i++) {
302 302 QBarSet *set = m_internalModel->barsetAt(i);
303 303 disconnect(set->d_ptr.data(), SIGNAL(showToolTip(QPoint,QString)), this, SIGNAL(showToolTip(QPoint,QString)));
304 304 }
305 305 }
306 306 }
307 307
308 308 qreal QBarSeriesPrivate::min()
309 309 {
310 310 return m_internalModel->min();
311 311 }
312 312
313 313 qreal QBarSeriesPrivate::max()
314 314 {
315 315 return m_internalModel->max();
316 316 }
317 317
318 318 qreal QBarSeriesPrivate::valueAt(int set, int category)
319 319 {
320 320 return m_internalModel->valueAt(set, category);
321 321 }
322 322
323 323 qreal QBarSeriesPrivate::percentageAt(int set, int category)
324 324 {
325 325 return m_internalModel->percentageAt(set, category);
326 326 }
327 327
328 328 qreal QBarSeriesPrivate::categorySum(int category)
329 329 {
330 330 return m_internalModel->categorySum(category);
331 331 }
332 332
333 333 qreal QBarSeriesPrivate::absoluteCategorySum(int category)
334 334 {
335 335 return m_internalModel->absoluteCategorySum(category);
336 336 }
337 337
338 338 qreal QBarSeriesPrivate::maxCategorySum()
339 339 {
340 340 return m_internalModel->maxCategorySum();
341 341 }
342 342
343 343 BarChartModel& QBarSeriesPrivate::modelInternal()
344 344 {
345 345 return *m_internalModel;
346 346 }
347 347
348 348 bool QBarSeriesPrivate::setModel(QAbstractItemModel *model)
349 349 {
350 350 // disconnect signals from old model
351 351 if(m_model)
352 352 {
353 353 disconnect(m_model, 0, this, 0);
354 354 m_mapCategories = -1;
355 355 m_mapBarBottom = -1;
356 356 m_mapBarTop = -1;
357 357 m_mapFirst = 0;
358 358 m_mapCount = 0;
359 359 m_mapOrientation = Qt::Vertical;
360 360 }
361 361
362 362 // set new model
363 363 if(model)
364 364 {
365 365 m_model = model;
366 366 return true;
367 367 }
368 368 else
369 369 {
370 370 m_model = 0;
371 371 return false;
372 372 }
373 373 }
374 374
375 375 void QBarSeriesPrivate::setModelMapping(int categories, int bottomBoundry, int topBoundry, Qt::Orientation orientation)
376 376 {
377 377 Q_Q(QBarSeries);
378 378
379 379 if (m_model == 0)
380 380 return;
381 381
382 382 m_mapCategories = categories;
383 383 m_mapBarBottom = bottomBoundry;
384 384 m_mapBarTop = topBoundry;
385 385 // m_mapFirst = 1;
386 386 m_mapOrientation = orientation;
387 387
388 388 // connect the signals
389 389 if (m_mapOrientation == Qt::Vertical) {
390 390 m_mapCount = m_model->rowCount() - m_mapFirst;
391 391 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)),
392 392 this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
393 393 connect(m_model,SIGNAL(rowsInserted(QModelIndex,int,int)),
394 394 this, SLOT(modelDataAdded(QModelIndex,int,int)));
395 395 connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
396 396 this, SLOT(modelDataRemoved(QModelIndex,int,int)));
397 397 } else {
398 398 m_mapCount = m_model->columnCount() - m_mapFirst;
399 399 connect(m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)),
400 400 this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
401 401 connect(m_model,SIGNAL(columnsInserted(QModelIndex,int,int)),
402 402 this, SLOT(modelDataAdded(QModelIndex,int,int)));
403 403 connect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
404 404 this, SLOT(modelDataRemoved(QModelIndex,int,int)));
405 405 }
406 406
407 407 // create the initial bars
408 408 delete m_internalModel;
409 409 if (m_mapOrientation == Qt::Vertical) {
410 410 QStringList categories;
411 411 for (int k = m_mapFirst; k < m_mapFirst + m_mapCount; k++)
412 412 categories << m_model->data(m_model->index(k, m_mapCategories), Qt::DisplayRole).toString();
413 413 m_internalModel = new BarChartModel(categories, this);
414 414
415 415 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) {
416 416 QBarSet* barSet = new QBarSet(QString("Column: %1").arg(i + 1));
417 417 for(int m = m_mapFirst; m < m_mapFirst + m_mapCount; m++)
418 418 *barSet << m_model->data(m_model->index(m, i), Qt::DisplayRole).toDouble();
419 419 q->appendBarSet(barSet);
420 420 }
421 421 } else {
422 422 QStringList categories;
423 423 for (int k = m_mapFirst; k < m_mapFirst + m_mapCount; k++)
424 424 categories << m_model->data(m_model->index(m_mapCategories, k), Qt::DisplayRole).toString();
425 425 m_internalModel = new BarChartModel(categories, this);
426 426
427 427 for (int i = m_mapBarBottom; i <= m_mapBarTop; i++) {
428 428 QBarSet* barSet = new QBarSet(QString("Row: %1").arg(i + 1));
429 429 for(int m = m_mapFirst; m < m_mapFirst + m_mapCount; m++)
430 430 *barSet << m_model->data(m_model->index(i, m), Qt::DisplayRole).toDouble();
431 431 q->appendBarSet(barSet);
432 432 }
433 433 }
434 434 }
435 435
436 436 void QBarSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
437 437 {
438 438 Q_UNUSED(bottomRight)
439 439
440 440 if (m_mapOrientation == Qt::Vertical)
441 441 {
442 442 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
443 443 if (topLeft.column() >= m_mapBarBottom && topLeft.column() <= m_mapBarTop && topLeft.row() >= m_mapFirst && topLeft.row() < m_mapFirst + m_mapCount)
444 444 barsetAt(topLeft.column() - m_mapBarBottom)->setValue(topLeft.row() - m_mapFirst, m_model->data(topLeft, Qt::DisplayRole).toDouble());
445 445 }
446 446 else
447 447 {
448 448 // model update is relevant to BarSeries if the change was made to the part of the model that was mapped to BarSeries
449 449 if (topLeft.row() >= m_mapBarBottom && topLeft.row() <= m_mapBarTop && topLeft.column() >= m_mapFirst && topLeft.column() < m_mapFirst + m_mapCount)
450 450 barsetAt(topLeft.row() - m_mapBarBottom)->setValue(topLeft.column() - m_mapFirst, m_model->data(topLeft, Qt::DisplayRole).toDouble());
451 451 }
452 452 }
453 453
454 454 void QBarSeriesPrivate::modelDataAdded(QModelIndex /*parent*/, int start, int /*end*/)
455 455 {
456 456 Q_Q(QBarSeries);
457 457
458 458 if (m_mapOrientation == Qt::Vertical) {
459 459 q->insertCategory(start - m_mapFirst, QString("Row: %1").arg(start + 1));
460 460 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++) {
461 461 barsetAt(i)->insertValue(start - m_mapFirst, m_model->data(m_model->index(start, i), Qt::DisplayRole).toDouble());
462 462 }
463 463 } else {
464 464 q->insertCategory(start - m_mapFirst, QString("Column: %1").arg(start + 1));
465 465 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++) {
466 466 barsetAt(i)->insertValue(start - m_mapFirst, m_model->data(m_model->index(i, start), Qt::DisplayRole).toDouble());
467 467 }
468 468 }
469 469 emit restructuredBars();
470 470 }
471 471
472 472 void QBarSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
473 473 {
474 474 Q_Q(QBarSeries);
475 475 Q_UNUSED(parent)
476 476 Q_UNUSED(end)
477 477
478 478 q->removeCategory(start - m_mapFirst);
479 479 for (int i = 0; i <= m_mapBarTop - m_mapBarBottom; i++)
480 480 {
481 481 barsetAt(i)->removeValue(start - m_mapFirst);
482 482 }
483 483 emit restructuredBars();
484 484 }
485 485
486 486 void QBarSeriesPrivate::barsetChanged()
487 487 {
488 488 emit updatedBars();
489 489 }
490 490
491 491 void QBarSeriesPrivate::scaleDomain(Domain& domain)
492 492 {
493 493 qreal minX(domain.minX());
494 494 qreal minY(domain.minY());
495 495 qreal maxX(domain.maxX());
496 496 qreal maxY(domain.maxY());
497 497 int tickXCount(domain.tickXCount());
498 498 int tickYCount(domain.tickYCount());
499 499
500 500 qreal x = m_internalModel->categoryCount();
501 501 qreal y = max();
502 502 minX = qMin(minX, x);
503 503 minY = qMin(minY, y);
504 504 maxX = qMax(maxX, x);
505 505 maxY = qMax(maxY, y);
506 506 tickXCount = x+1;
507 507
508 508 domain.setRangeX(minX,maxX,tickXCount);
509 509 domain.setRangeY(minY,maxY,tickYCount);
510 510 }
511 511
512 512 Chart* QBarSeriesPrivate::createGraphics(ChartPresenter* presenter)
513 513 {
514 514 Q_Q(QBarSeries);
515 515
516 516 BarChartItem* bar = new BarChartItem(q,presenter);
517 517 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
518 518 presenter->animator()->addAnimation(bar);
519 519 }
520 520 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
521 521 return bar;
522 522
523 523 }
524 524
525 525 QList<LegendMarker*> QBarSeriesPrivate::createLegendMarker(QLegend* legend)
526 526 {
527 527 Q_Q(QBarSeries);
528 528 QList<LegendMarker*> markers;
529 529 foreach(QBarSet* set, q->barSets()) {
530 530 BarLegendMarker* marker = new BarLegendMarker(q,set,legend);
531 531 markers << marker;
532 532 }
533 533
534 534 return markers;
535 535 }
536 536
537 537 #include "moc_qbarseries.cpp"
538 538 #include "moc_qbarseries_p.cpp"
539 539
540 540 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,108 +1,108
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qpercentbarseries.h"
22 22 #include "qpercentbarseries_p.h"
23 23 #include "percentbarchartitem_p.h"
24 24 #include "chartdataset_p.h"
25 25 #include "charttheme_p.h"
26 26 #include "chartanimator_p.h"
27 27
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 /*!
32 32 \class QPercentBarSeries
33 33 \brief part of QtCommercial chart API.
34 34
35 35 QPercentBarSeries represents a series of data shown as bars. Each bar of QBarSet is shown as percentage
36 of all bars in category. One QPercentBarSeries can contain multible QBarSet data sets.
36 of all bars in category. One QPercentBarSeries can contain multiple QBarSet data sets.
37 37 QBarSeries groups the data from sets to categories, which are defined by QStringList.
38 38
39 39 \mainclass
40 40
41 41 \sa QBarSet, QStackedBarSeries, QBarSeries
42 42 */
43 43
44 44 /*!
45 45 \fn virtual QSeriesType QPercentBarSeries::type() const
46 46 \brief Returns type of series.
47 47 \sa QSeries, QSeriesType
48 48 */
49 49
50 50 /*!
51 51 Constructs empty QPercentBarSeries. Parameter \a categories defines the categories for chart.
52 52 QPercentBarSeries is QObject which is a child of a \a parent.
53 53 */
54 54 QPercentBarSeries::QPercentBarSeries(QBarCategories categories, QObject *parent)
55 55 : QBarSeries(*new QPercentBarSeriesPrivate(categories,this), parent)
56 56 {
57 57 }
58 58
59 59 QSeries::QSeriesType QPercentBarSeries::type() const
60 60 {
61 61 return QSeries::SeriesTypePercentBar;
62 62 }
63 63
64 64 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65 65
66 66 QPercentBarSeriesPrivate::QPercentBarSeriesPrivate(QBarCategories categories, QPercentBarSeries *q) : QBarSeriesPrivate(categories,q)
67 67 {
68 68
69 69 }
70 70
71 71 void QPercentBarSeriesPrivate::scaleDomain(Domain& domain)
72 72 {
73 73 Q_Q(QPercentBarSeries);
74 74 qreal minX(domain.minX());
75 75 qreal minY(domain.minY());
76 76 qreal maxX(domain.maxX());
77 77 qreal maxY(domain.maxY());
78 78 int tickXCount(domain.tickXCount());
79 79 int tickYCount(domain.tickYCount());
80 80
81 81 qreal x = q->categoryCount();
82 82 minX = qMin(minX, x);
83 83 maxX = qMax(maxX, x);
84 84 minY = 0;
85 85 maxY = 100;
86 86 tickXCount = x+1;
87 87
88 88 domain.setRangeX(minX,maxX,tickXCount);
89 89 domain.setRangeY(minY,maxY,tickYCount);
90 90 }
91 91
92 92
93 93 Chart* QPercentBarSeriesPrivate::createGraphics(ChartPresenter* presenter)
94 94 {
95 95 Q_Q(QPercentBarSeries);
96 96
97 97 PercentBarChartItem* bar = new PercentBarChartItem(q,presenter);
98 98 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
99 99 presenter->animator()->addAnimation(bar);
100 100 }
101 101 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
102 102 return bar;
103 103 }
104 104
105 105 #include "moc_qpercentbarseries.cpp"
106 106
107 107 QTCOMMERCIALCHART_END_NAMESPACE
108 108
@@ -1,108 +1,108
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qstackedbarseries.h"
22 22 #include "qstackedbarseries_p.h"
23 23 #include "stackedbarchartitem_p.h"
24 24 #include "barchartmodel_p.h"
25 25 #include "chartdataset_p.h"
26 26 #include "charttheme_p.h"
27 27 #include "chartanimator_p.h"
28 28
29 29 QTCOMMERCIALCHART_BEGIN_NAMESPACE
30 30
31 31 /*!
32 32 \class QStackedBarSeries
33 33 \brief part of QtCommercial chart API.
34 34
35 35 QStackedBarSeries represents a series of data shown as bars. All bars in same category are
36 stacked on top of each other. One QStackedBarSeries can contain multible QBarSet data sets.
36 stacked on top of each other. One QStackedBarSeries can contain multiple QBarSet data sets.
37 37 QStackedBarSeries groups the data from sets to categories, which are defined by QStringList.
38 38
39 39 \mainclass
40 40
41 41 \sa QBarSet, QPercentBarSeries, QBarSeries
42 42 */
43 43
44 44 /*!
45 45 \fn virtual QSeriesType QStackedBarSeries::type() const
46 46 \brief Returns type of series.
47 47 \sa QSeries, QSeriesType
48 48 */
49 49
50 50 /*!
51 51 Constructs empty QStackedBarSeries. Parameter \a categories defines the categories for chart.
52 52 QStackedBarSeries is QObject which is a child of a \a parent.
53 53 */
54 54 QStackedBarSeries::QStackedBarSeries(QBarCategories categories, QObject *parent)
55 55 : QBarSeries(*new QStackedBarSeriesPrivate(categories,this), parent)
56 56 {
57 57 }
58 58
59 59 QSeries::QSeriesType QStackedBarSeries::type() const
60 60 {
61 61 return QSeries::SeriesTypeStackedBar;
62 62 }
63 63
64 64 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65 65
66 66 QStackedBarSeriesPrivate::QStackedBarSeriesPrivate(QBarCategories categories, QStackedBarSeries *q) : QBarSeriesPrivate(categories,q)
67 67 {
68 68
69 69 }
70 70
71 71 void QStackedBarSeriesPrivate::scaleDomain(Domain& domain)
72 72 {
73 73 qreal minX(domain.minX());
74 74 qreal minY(domain.minY());
75 75 qreal maxX(domain.maxX());
76 76 qreal maxY(domain.maxY());
77 77 int tickXCount(domain.tickXCount());
78 78 int tickYCount(domain.tickYCount());
79 79
80 80 qreal x = m_internalModel->categoryCount();
81 81 qreal y = maxCategorySum();
82 82 minX = qMin(minX, x);
83 83 minY = qMin(minY, y);
84 84 maxX = qMax(maxX, x);
85 85 maxY = qMax(maxY, y);
86 86 tickXCount = x+1;
87 87
88 88 domain.setRangeX(minX,maxX,tickXCount);
89 89 domain.setRangeY(minY,maxY,tickYCount);
90 90 }
91 91
92 92
93 93 Chart* QStackedBarSeriesPrivate::createGraphics(ChartPresenter* presenter)
94 94 {
95 95 Q_Q(QStackedBarSeries);
96 96
97 97 StackedBarChartItem* bar = new StackedBarChartItem(q,presenter);
98 98 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
99 99 presenter->animator()->addAnimation(bar);
100 100 }
101 101 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
102 102 return bar;
103 103 }
104 104
105 105 #include "moc_qstackedbarseries.cpp"
106 106
107 107 QTCOMMERCIALCHART_END_NAMESPACE
108 108
@@ -1,255 +1,252
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartdataset_p.h"
22 22 #include "qchartaxis.h"
23 23 #include "qchartaxis_p.h"
24 24 #include "qseries_p.h"
25 25 #include "qbarseries.h"
26 26 #include "qstackedbarseries.h"
27 27 #include "qpercentbarseries.h"
28 28 #include "qpieseries.h"
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31
32 32 ChartDataSet::ChartDataSet(QObject *parent):QObject(parent),
33 33 m_axisX(new QChartAxis(this)),
34 34 m_axisY(new QChartAxis(this)),
35 35 m_domainIndex(0),
36 36 m_axisXInitialized(false)
37 37 {
38 38 }
39 39
40 40 ChartDataSet::~ChartDataSet()
41 41 {
42 42 }
43 43
44 44 void ChartDataSet::addSeries(QSeries* series, QChartAxis *axisY)
45 45 {
46 46 if(axisY==0) axisY = m_axisY;
47 47
48 48 QChartAxis* axis = m_seriesAxisMap.value(series);
49 49
50 50 if(axis) {
51 51 qWarning() << "Can not add series. Series already on the chart";
52 52 return;
53 53 }
54 54
55 if(!series->parent()){
56 series->setParent(this); // take ownership
57 };
58
59 if(!axisY->parent()){
60 axisY->setParent(this); // take ownership
61 }
55 series->setParent(this); // take ownership
56 axisY->setParent(this); // take ownership
62 57
63 58 Domain* domain = m_axisDomainMap.value(axisY);
64 59
65 60 if(!domain) {
66 61 domain = new Domain(axisY);
67 62 QObject::connect(axisY->d_ptr.data(),SIGNAL(changed(qreal,qreal,int,bool)),domain,SLOT(handleAxisYChanged(qreal,qreal,int,bool)));
68 63 QObject::connect(axisX()->d_ptr.data(),SIGNAL(changed(qreal,qreal,int,bool)),domain,SLOT(handleAxisXChanged(qreal,qreal,int,bool)));
69 64 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),axisY->d_ptr.data(),SLOT(handleAxisRangeChanged(qreal,qreal,int)));
70 65 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),axisX()->d_ptr.data(),SLOT(handleAxisRangeChanged(qreal,qreal,int)));
71 66 //initialize
72 67 m_axisDomainMap.insert(axisY,domain);
73 68 emit axisAdded(axisY,domain);
74 69 }
75 70
76 71 if(!m_axisXInitialized){
77 72 emit axisAdded(axisX(),domain);
78 73 m_axisXInitialized=true;
79 74 }
80 75
81 76 series->d_ptr->scaleDomain(*domain);
82 77
83 78 if(series->type() == QSeries::SeriesTypeBar || series->type() == QSeries::SeriesTypeStackedBar || series->type() == QSeries::SeriesTypePercentBar)
84 79 {
85 80 QBarSeries* barSeries = static_cast<QBarSeries*>(series);
86 81 setupCategories(barSeries);
87 82 }
88 83
89 84 if (series->type()== QSeries::SeriesTypePie && m_seriesAxisMap.count()==0)
90 85 {
91 86 axisX()->hide();
92 87 this->axisY()->hide();
93 88 }
94 89
95 90 m_seriesAxisMap.insert(series,axisY);
96 91
97 92 QMapIterator<int, QSeries*> i(m_indexSeriesMap);
98 93
99 94 int key=0;
100 95 while (i.hasNext()) {
101 96 i.next();
102 97 if(i.key()!=key) {
103 98 break;
104 99 }
105 100 key++;
106 101 }
107 102
108 103 m_indexSeriesMap.insert(key,series);
109 104
110 105 emit seriesAdded(series,domain);
111 106
112 107 }
113 108
114 void ChartDataSet::removeSeries(QSeries* series)
109 QChartAxis* ChartDataSet::removeSeries(QSeries* series)
115 110 {
116
117 111 QChartAxis* axis = m_seriesAxisMap.value(series);
118 112
119 113 if(!axis){
120 114 qWarning()<<"Can not remove series. Series not found on the chart.";
121 return;
115 return 0;
122 116 }
117
123 118 emit seriesRemoved(series);
119
124 120 m_seriesAxisMap.remove(series);
125 121 int key = seriesIndex(series);
126 122 Q_ASSERT(key!=-1);
127 123
128 124 m_indexSeriesMap.remove(key);
129
130 if(series->parent()==this){
131 delete series;
132 series=0;
133 }
125 series->setParent(0);
134 126
135 127 QList<QChartAxis*> axes = m_seriesAxisMap.values();
136 128
137 129 int i = axes.indexOf(axis);
138 130
139 131 if(i==-1){
140 132 Domain* domain = m_axisDomainMap.take(axis);
141 133 emit axisRemoved(axis);
142 134 if(axis!=axisY()){
143 if(axis->parent()==this){
144 delete axis;
145 axis=0;
146 }
135 axis->setParent(0);
147 136 }
148 137 delete domain;
149 138 }
150 139
151 140 if(m_seriesAxisMap.values().size()==0)
152 141 {
153 142 m_axisXInitialized=false;
154 143 emit axisRemoved(axisX());
155 144 }
145
146 return axis;
156 147 }
157 148
158 149 void ChartDataSet::removeAllSeries()
159 150 {
160
161 151 QList<QSeries*> series = m_seriesAxisMap.keys();
162
152 QList<QChartAxis*> axes;
163 153 foreach(QSeries* s , series) {
164 removeSeries(s);
154 QChartAxis* axis = removeSeries(s);
155 if(axis==axisY()) continue;
156 int i = axes.indexOf(axis);
157 if(i==-1){
158 axes<<axis;
159 }
165 160 }
166 161
167 162 Q_ASSERT(m_seriesAxisMap.count()==0);
168 163 Q_ASSERT(m_axisDomainMap.count()==0);
169 164
165 qDeleteAll(series);
166 qDeleteAll(axes);
170 167 }
171 168
172 169 void ChartDataSet::setupCategories(QBarSeries* series)
173 170 {
174 171 QChartAxisCategories* categories = axisX()->categories();
175 172 categories->clear();
176 173 categories->insert(series->categories());
177 174 }
178 175
179 176 void ChartDataSet::zoomInDomain(const QRectF& rect, const QSizeF& size)
180 177 {
181 178 QMapIterator<QChartAxis*, Domain*> i(m_axisDomainMap);
182 179 while (i.hasNext()) {
183 180 i.next();
184 181 i.value()->zoomIn(rect,size);
185 182 }
186 183 }
187 184
188 185 void ChartDataSet::zoomOutDomain(const QRectF& rect, const QSizeF& size)
189 186 {
190 187 QMapIterator<QChartAxis*, Domain*> i(m_axisDomainMap);
191 188 while (i.hasNext()) {
192 189 i.next();
193 190 i.value()->zoomOut(rect,size);
194 191 }
195 192 }
196 193
197 194 int ChartDataSet::seriesCount(QSeries::QSeriesType type)
198 195 {
199 196 int count=0;
200 197 QMapIterator<QSeries*, QChartAxis*> i(m_seriesAxisMap);
201 198 while (i.hasNext()) {
202 199 i.next();
203 200 if(i.key()->type()==type) count++;
204 201 }
205 202 return count;
206 203 }
207 204
208 205 int ChartDataSet::seriesIndex(QSeries *series)
209 206 {
210 207 QMapIterator<int, QSeries*> i(m_indexSeriesMap);
211 208 while (i.hasNext()) {
212 209 i.next();
213 210 if (i.value() == series)
214 211 return i.key();
215 212 }
216 213 return -1;
217 214 }
218 215
219 216 QChartAxis* ChartDataSet::axisY(QSeries* series) const
220 217 {
221 218 if(series == 0) return m_axisY;
222 219 return m_seriesAxisMap.value(series);
223 220 }
224 221
225 222 Domain* ChartDataSet::domain(QSeries* series) const
226 223 {
227 224 QChartAxis* axis = m_seriesAxisMap.value(series);
228 225 if(axis){
229 226 return m_axisDomainMap.value(axis);
230 227 }else
231 228 return 0;
232 229 }
233 230
234 231 Domain* ChartDataSet::domain(QChartAxis* axis) const
235 232 {
236 233 if(!axis || axis==axisX()) {
237 234 return m_axisDomainMap.value(axisY());
238 235 }
239 236 else {
240 237 return m_axisDomainMap.value(axis);
241 238 }
242 239 }
243 240
244 241 void ChartDataSet::scrollDomain(int dx,int dy,const QSizeF& size)
245 242 {
246 243 QMapIterator<QChartAxis*, Domain*> i( m_axisDomainMap);
247 244 while (i.hasNext()) {
248 245 i.next();
249 246 i.value()->move(dx,dy,size);
250 247 }
251 248 }
252 249
253 250 #include "moc_chartdataset_p.cpp"
254 251
255 252 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,90 +1,90
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef CHARTDATASET_P_H
31 31 #define CHARTDATASET_P_H
32 32
33 33 #include "qseries.h"
34 34 #include "domain_p.h"
35 35 #include <QVector>
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 class QChartAxis;
40 40 class QBarSeries;
41 41
42 42 class ChartDataSet : public QObject
43 43 {
44 44 Q_OBJECT
45 45 public:
46 46 ChartDataSet(QObject* parent=0);
47 47 virtual ~ChartDataSet();
48 48
49 49 void addSeries(QSeries* series,QChartAxis *axisY = 0);
50 void removeSeries(QSeries* series);
50 QChartAxis* removeSeries(QSeries* series);
51 51 void removeAllSeries();
52 52
53 53 void zoomInDomain(const QRectF& rect, const QSizeF& size);
54 54 void zoomOutDomain(const QRectF& rect, const QSizeF& size);
55 55 void scrollDomain(int dx,int dy,const QSizeF& size);
56 56
57 57 int seriesCount(QSeries::QSeriesType type);
58 58 int seriesIndex(QSeries *series);
59 59
60 60 Domain* domain(QSeries* series) const;
61 61 Domain* domain(QChartAxis* axis) const;
62 62
63 63 QChartAxis* axisX() const { return m_axisX; }
64 64 QChartAxis* axisY(QSeries* series = 0) const;
65 65
66 66 Q_SIGNALS:
67 67 void seriesAdded(QSeries* series,Domain* domain);
68 68 void seriesRemoved(QSeries* series);
69 69 void axisAdded(QChartAxis* axis,Domain* domain);
70 70 void axisRemoved(QChartAxis* axis);
71 71
72 72 private:
73 73 QStringList createLabels(QChartAxis* axis,qreal min, qreal max);
74 74 void calculateDomain(QSeries* series,Domain* domain);
75 75 void setupCategories(QBarSeries* series);
76 76
77 77 private:
78 78 QMap<QSeries*, QChartAxis*> m_seriesAxisMap;
79 79 QMap<QChartAxis*, Domain*> m_axisDomainMap;
80 80 QMap<int,QSeries*> m_indexSeriesMap;
81 81 QChartAxis* m_axisX;
82 82 QChartAxis* m_axisY;
83 83
84 84 int m_domainIndex;
85 85 bool m_axisXInitialized;
86 86 };
87 87
88 88 QTCOMMERCIALCHART_END_NAMESPACE
89 89
90 90 #endif /* CHARTENGINE_P_H_ */
@@ -1,398 +1,398
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "charttheme_p.h"
22 22 #include "qchart.h"
23 23 #include "qchartview.h"
24 24 #include "qlegend.h"
25 25 #include "qchartaxis.h"
26 26 #include <QTime>
27 27
28 28 //series
29 29 #include "qbarset.h"
30 30 #include "qbarseries.h"
31 31 #include "qstackedbarseries.h"
32 32 #include "qpercentbarseries.h"
33 33 #include "qlineseries.h"
34 34 #include "qareaseries.h"
35 35 #include "qscatterseries.h"
36 36 #include "qpieseries.h"
37 37 #include "qpieslice.h"
38 38 #include "qsplineseries.h"
39 39
40 40 //items
41 41 #include "axis_p.h"
42 42 #include "barchartitem_p.h"
43 43 #include "stackedbarchartitem_p.h"
44 44 #include "percentbarchartitem_p.h"
45 45 #include "linechartitem_p.h"
46 46 #include "areachartitem_p.h"
47 47 #include "scatterchartitem_p.h"
48 48 #include "piechartitem_p.h"
49 49 #include "splinechartitem_p.h"
50 50
51 51 //themes
52 52 #include "chartthemesystem_p.h"
53 53 #include "chartthemelight_p.h"
54 54 #include "chartthemebluecerulean_p.h"
55 55 #include "chartthemedark_p.h"
56 56 #include "chartthemebrownsand_p.h"
57 57 #include "chartthemebluencs_p.h"
58 58 #include "chartthemehighcontrast_p.h"
59 59 #include "chartthemeblueicy_p.h"
60 60
61 61 QTCOMMERCIALCHART_BEGIN_NAMESPACE
62 62
63 63 ChartTheme::ChartTheme(QChart::ChartTheme id) :
64 64 m_masterFont(QFont("arial", 14)),
65 65 m_labelFont(QFont("arial", 10)),
66 66 m_titleBrush(QColor(QRgb(0x000000))),
67 67 m_axisLinePen(QPen(QRgb(0x000000))),
68 68 m_axisLabelBrush(QColor(QRgb(0x000000))),
69 69 m_backgroundShadesPen(Qt::NoPen),
70 70 m_backgroundShadesBrush(Qt::NoBrush),
71 71 m_backgroundShades(BackgroundShadesNone),
72 72 m_gridLinePen(QPen(QRgb(0x000000))),
73 73 m_force(false)
74 74 {
75 75 m_id = id;
76 76 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
77 77 }
78 78
79 79
80 80 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
81 81 {
82 82 switch(theme) {
83 83 case QChart::ChartThemeLight:
84 84 return new ChartThemeLight();
85 85 case QChart::ChartThemeBlueCerulean:
86 86 return new ChartThemeBlueCerulean();
87 87 case QChart::ChartThemeDark:
88 88 return new ChartThemeDark();
89 89 case QChart::ChartThemeBrownSand:
90 90 return new ChartThemeBrownSand();
91 91 case QChart::ChartThemeBlueNcs:
92 92 return new ChartThemeBlueNcs();
93 93 case QChart::ChartThemeHighContrast:
94 94 return new ChartThemeHighContrast();
95 95 case QChart::ChartThemeBlueIcy:
96 96 return new ChartThemeBlueIcy();
97 97 default:
98 98 return new ChartThemeSystem();
99 99 }
100 100 }
101 101
102 102 void ChartTheme::decorate(QChart *chart)
103 103 {
104 104 QBrush brush;
105 105
106 106 if(brush == chart->backgroundBrush() || m_force)
107 107 chart->setBackgroundBrush(m_chartBackgroundGradient);
108 108 chart->setTitleFont(m_masterFont);
109 109 chart->setTitleBrush(m_titleBrush);
110 110 }
111 111
112 112 void ChartTheme::decorate(QLegend *legend)
113 113 {
114 114 QPen pen;
115 115 QBrush brush;
116 116
117 117 if (pen == legend->pen() || m_force){
118 118 legend->setPen(Qt::NoPen);
119 119 }
120 120
121 121
122 122 if (brush == legend->brush() || m_force) {
123 123 legend->setBrush(m_chartBackgroundGradient);
124 124 }
125 125 }
126 126
127 127 void ChartTheme::decorate(QAreaSeries *series, int index)
128 128 {
129 129 QPen pen;
130 130 QBrush brush;
131 131
132 132 if (pen == series->pen() || m_force){
133 133 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
134 134 pen.setWidthF(2);
135 135 series->setPen(pen);
136 136 }
137 137
138 138 if (brush == series->brush() || m_force) {
139 139 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
140 140 series->setBrush(brush);
141 141 }
142 142 }
143 143
144 144
145 145 void ChartTheme::decorate(QLineSeries *series,int index)
146 146 {
147 147 QPen pen;
148 148 if(pen == series->pen() || m_force ){
149 149 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
150 150 pen.setWidthF(2);
151 151 series->setPen(pen);
152 152 }
153 153 }
154 154
155 155 void ChartTheme::decorate(QBarSeries *series, int index)
156 156 {
157 157 QBrush brush;
158 158 QPen pen;
159 159 QList<QBarSet *> sets = series->barSets();
160 160
161 161 qreal takeAtPos = 0.5;
162 162 qreal step = 0.2;
163 163 if (sets.count() > 1 ) {
164 164 step = 1.0 / (qreal) sets.count();
165 165 if (sets.count() % m_seriesGradients.count())
166 166 step *= m_seriesGradients.count();
167 167 else
168 168 step *= (m_seriesGradients.count() - 1);
169 169 }
170 170
171 171 for (int i(0); i < sets.count(); i++) {
172 172 int colorIndex = (index + i) % m_seriesGradients.count();
173 173 if (i > 0 && i % m_seriesGradients.count() == 0) {
174 174 // There is no dedicated base color for each sets, generate more colors
175 175 takeAtPos += step;
176 176 if (takeAtPos == 1.0)
177 177 takeAtPos += step;
178 178 takeAtPos -= (int) takeAtPos;
179 179 }
180 180 if (brush == sets.at(i)->brush() || m_force )
181 181 sets.at(i)->setBrush(colorAt(m_seriesGradients.at(colorIndex), takeAtPos));
182 182
183 183 // Pick label color from the opposite end of the gradient.
184 184 // 0.3 as a boundary seems to work well.
185 185 if (takeAtPos < 0.3)
186 186 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
187 187 else
188 188 sets.at(i)->setLabelBrush(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
189 189
190 190 if (pen == sets.at(i)->pen() || m_force) {
191 191 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
192 192 sets.at(i)->setPen(c);
193 193 }
194 194 }
195 195 }
196 196
197 197 void ChartTheme::decorate(QScatterSeries *series, int index)
198 198 {
199 199 QPen pen;
200 200 QBrush brush;
201 201
202 202 if (pen == series->pen() || m_force) {
203 203 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
204 204 pen.setWidthF(2);
205 205 series->setPen(pen);
206 206 }
207 207
208 208 if (brush == series->brush() || m_force) {
209 209 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
210 210 series->setBrush(brush);
211 211 }
212 212 }
213 213
214 214 void ChartTheme::decorate(QPieSeries *series, int index)
215 215 {
216 216
217 217 for (int i(0); i < series->slices().count(); i++) {
218 218
219 219 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
220 220
221 221 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
222 222 qreal pos = (qreal) (i + 1) / (qreal) series->count();
223 223 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
224 224
225 225 QPieSlice *s = series->slices().at(i);
226 226 PieSliceData data = PieSliceData::data(s);
227 227
228 228 if (data.m_slicePen.isThemed() || m_force) {
229 229 data.m_slicePen = penColor;
230 230 data.m_slicePen.setThemed(true);
231 231 }
232 232
233 233 if (data.m_sliceBrush.isThemed() || m_force) {
234 234 data.m_sliceBrush = brushColor;
235 235 data.m_sliceBrush.setThemed(true);
236 236 }
237 237
238 238 if (data.m_labelPen.isThemed() || m_force) {
239 239 data.m_labelPen = QPen(m_titleBrush.color());
240 240 data.m_labelPen.setThemed(true);
241 241 }
242 242
243 243 if (data.m_labelFont.isThemed() || m_force) {
244 244 data.m_labelFont = m_labelFont;
245 245 data.m_labelFont.setThemed(true);
246 246 }
247 247
248 248 if (PieSliceData::data(s) != data) {
249 249 PieSliceData::data(s) = data;
250 250 emit PieSliceData::data(s).emitChangedSignal(s);
251 251 }
252 252 }
253 253 }
254 254
255 255 void ChartTheme::decorate(QSplineSeries *series, int index)
256 256 {
257 257 QPen pen;
258 258 if(pen == series->pen() || m_force){
259 259 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
260 260 pen.setWidthF(2);
261 261 series->setPen(pen);
262 262 }
263 263 }
264 264
265 265 void ChartTheme::decorate(QChartAxis *axis,bool axisX)
266 266 {
267 267 QPen pen;
268 268 QBrush brush;
269 269 QFont font;
270 270
271 271 if (axis->isAxisVisible()) {
272 272
273 273 if(brush == axis->labelsBrush() || m_force){
274 274 axis->setLabelsBrush(m_axisLabelBrush);
275 275 }
276 276 if(pen == axis->labelsPen() || m_force){
277 277 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
278 278 }
279 279
280 280
281 281 if (axis->shadesVisible() || m_force) {
282 282
283 283 if(brush == axis->shadesBrush() || m_force){
284 284 axis->setShadesBrush(m_backgroundShadesBrush);
285 285 }
286 286
287 287 if(pen == axis->shadesPen() || m_force){
288 288 axis->setShadesPen(m_backgroundShadesPen);
289 289 }
290 290
291 291 if( m_force && (m_backgroundShades == BackgroundShadesBoth
292 292 || (m_backgroundShades == BackgroundShadesVertical && axisX)
293 293 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))){
294 294 axis->setShadesVisible(true);
295 295
296 296 }
297 297 }
298 298
299 299 if(pen == axis->axisPen() || m_force){
300 300 axis->setAxisPen(m_axisLinePen);
301 301 }
302 302
303 303 if(pen == axis->gridLinePen() || m_force){
304 304 axis->setGridLinePen(m_gridLinePen);
305 305 }
306 306
307 307 if(font == axis->labelsFont() || m_force){
308 308 axis->setLabelsFont(m_labelFont);
309 309 }
310 310 }
311 311 }
312 312
313 313 void ChartTheme::generateSeriesGradients()
314 314 {
315 315 // Generate gradients in HSV color space
316 foreach (QColor color, m_seriesColors) {
316 foreach (const QColor& color, m_seriesColors) {
317 317 QLinearGradient g;
318 318 qreal h = color.hsvHueF();
319 319 qreal s = color.hsvSaturationF();
320 320
321 321 // TODO: tune the algorithm to give nice results with most base colors defined in
322 322 // most themes. The rest of the gradients we can define manually in theme specific
323 323 // implementation.
324 324 QColor start = color;
325 325 start.setHsvF(h, 0.0, 1.0);
326 326 g.setColorAt(0.0, start);
327 327
328 328 g.setColorAt(0.5, color);
329 329
330 330 QColor end = color;
331 331 end.setHsvF(h, s, 0.25);
332 332 g.setColorAt(1.0, end);
333 333
334 334 m_seriesGradients << g;
335 335 }
336 336 }
337 337
338 338
339 339 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
340 340 {
341 341 Q_ASSERT(pos >= 0.0 && pos <= 1.0);
342 342 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
343 343 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
344 344 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
345 345 QColor c;
346 346 c.setRgbF(r, g, b);
347 347 return c;
348 348 }
349 349
350 350 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
351 351 {
352 352 Q_ASSERT(pos >= 0 && pos <= 1.0);
353 353
354 354 // another possibility:
355 355 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
356 356
357 357 QGradientStops stops = gradient.stops();
358 358 int count = stops.count();
359 359
360 360 // find previous stop relative to position
361 361 QGradientStop prev = stops.first();
362 362 for (int i = 0; i < count; i++) {
363 363 QGradientStop stop = stops.at(i);
364 364 if (pos > stop.first)
365 365 prev = stop;
366 366
367 367 // given position is actually a stop position?
368 368 if (pos == stop.first) {
369 369 //qDebug() << "stop color" << pos;
370 370 return stop.second;
371 371 }
372 372 }
373 373
374 374 // find next stop relative to position
375 375 QGradientStop next = stops.last();
376 376 for (int i = count - 1; i >= 0; i--) {
377 377 QGradientStop stop = stops.at(i);
378 378 if (pos < stop.first)
379 379 next = stop;
380 380 }
381 381
382 382 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
383 383
384 384 qreal range = next.first - prev.first;
385 385 qreal posDelta = pos - prev.first;
386 386 qreal relativePos = posDelta / range;
387 387
388 388 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
389 389
390 390 return colorAt(prev.second, next.second, relativePos);
391 391 }
392 392
393 393 void ChartTheme::setForced(bool enabled)
394 394 {
395 395 m_force=enabled;
396 396 }
397 397
398 398 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,451 +1,451
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qlegend.h"
22 22 #include "qlegend_p.h"
23 23 #include "qseries.h"
24 24 #include "qseries_p.h"
25 25 #include "qchart_p.h"
26 26
27 27 #include "legendmarker_p.h"
28 28 #include "qxyseries.h"
29 29 #include "qlineseries.h"
30 30 #include "qareaseries.h"
31 31 #include "qscatterseries.h"
32 32 #include "qsplineseries.h"
33 33 #include "qbarseries.h"
34 34 #include "qstackedbarseries.h"
35 35 #include "qpercentbarseries.h"
36 36 #include "qbarset.h"
37 37 #include "qpieseries.h"
38 38 #include "qpieslice.h"
39 39 #include "chartpresenter_p.h"
40 40 #include <QPainter>
41 41 #include <QPen>
42 42 #include <QTimer>
43 43
44 44 #include <QGraphicsSceneEvent>
45 45
46 46 QTCOMMERCIALCHART_BEGIN_NAMESPACE
47 47
48 48 /*!
49 49 \class QLegend
50 50 \brief part of QtCommercial chart API.
51 51
52 52 QLegend is a graphical object, whics displays legend of the chart. Legend state is updated by QChart, when
53 53 series have been changed. By default, legend is drawn by QChart, but user can set a new parent to legend and
54 54 handle the drawing manually.
55 55 User isn't supposed to create or delete legend objects, but can reference it via QChart class.
56 56
57 57 \mainclass
58 58
59 59 \sa QChart, QSeries
60 60 */
61 61
62 62 /*!
63 63 \enum QLegend::Alignment
64 64
65 65 This enum describes the possible position for legend inside chart.
66 66
67 67 \value AlignmentTop
68 68 \value AlignmentBottom
69 69 \value AlignmentLeft
70 70 \value AlignmentRight
71 71 */
72 72
73 73 /*!
74 74 \fn qreal QLegend::minWidth() const
75 75 Returns minimum width of the legend
76 76 */
77 77
78 78 /*!
79 79 \fn qreal QLegend::minHeight() const
80 80 Returns minimum height of the legend
81 81 */
82 82
83 83 /*!
84 84 Constructs the legend object and sets the parent to \a parent
85 85 */
86 86
87 87 QLegend::QLegend(QChart *chart):QGraphicsWidget(chart),
88 88 d_ptr(new QLegendPrivate(chart->d_ptr->m_presenter,this))
89 89 {
90 90 setZValue(ChartPresenter::LegendZValue);
91 91 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
92 92 setEnabled(false); // By default legend is disabled
93 93 setVisible(false);
94 94 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesAdded(QSeries*,Domain*)),d_ptr.data(),SLOT(handleSeriesAdded(QSeries*,Domain*)));
95 95 QObject::connect(chart->d_ptr->m_dataset,SIGNAL(seriesRemoved(QSeries*)),d_ptr.data(),SLOT(handleSeriesRemoved(QSeries*)));
96 96 }
97 97
98 98 QLegend::~QLegend()
99 99 {
100 100
101 101 }
102 102
103 103 /*!
104 104 Paints the legend to given \a painter. Paremeters \a option and \a widget arent used.
105 105 */
106 106
107 107 void QLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
108 108 {
109 109 Q_UNUSED(option)
110 110 Q_UNUSED(widget)
111 111 if(!d_ptr->m_backgroundVisible) return;
112 112
113 113 painter->setOpacity(opacity());
114 114 painter->setPen(d_ptr->m_pen);
115 115 painter->setBrush(d_ptr->m_brush);
116 116 painter->drawRect(boundingRect());
117 117 }
118 118
119 119 /*!
120 120 Bounding rect of legend.
121 121 */
122 122
123 123 QRectF QLegend::boundingRect() const
124 124 {
125 125 return d_ptr->m_rect;
126 126 }
127 127
128 128 /*!
129 129 Sets the \a brush of legend. Brush affects the background of legend.
130 130 */
131 131 void QLegend::setBrush(const QBrush &brush)
132 132 {
133 133 if (d_ptr->m_brush != brush) {
134 134 d_ptr->m_brush = brush;
135 135 update();
136 136 }
137 137 }
138 138
139 139 /*!
140 140 Returns the brush used by legend.
141 141 */
142 142 QBrush QLegend::brush() const
143 143 {
144 144 return d_ptr->m_brush;
145 145 }
146 146
147 147 /*!
148 148 Sets the \a pen of legend. Pen affects the legend borders.
149 149 */
150 150 void QLegend::setPen(const QPen &pen)
151 151 {
152 152 if (d_ptr->m_pen != pen) {
153 153 d_ptr->m_pen = pen;
154 154 update();
155 155 }
156 156 }
157 157
158 158 /*!
159 159 Returns the pen used by legend
160 160 */
161 161
162 162 QPen QLegend::pen() const
163 163 {
164 164 return d_ptr->m_pen;
165 165 }
166 166
167 167 /*!
168 168 Sets the \a alignment for legend. Legend tries to paint itself on the defined position in chart.
169 169 \sa QLegend::Alignment
170 170 */
171 171 void QLegend::setAlignment(QLegend::Alignments alignment)
172 172 {
173 173 if(d_ptr->m_alignment!=alignment && d_ptr->m_attachedToChart) {
174 174 d_ptr->m_alignment = alignment;
175 175 d_ptr->updateLayout();
176 176 }
177 177 }
178 178
179 179 /*!
180 180 Returns the preferred layout for legend
181 181 */
182 182 QLegend::Alignments QLegend::alignment() const
183 183 {
184 184 return d_ptr->m_alignment;
185 185 }
186 186
187 187 /*!
188 188 Detaches the legend from chart. Chart won't change layout of the legend.
189 189 */
190 190 void QLegend::detachFromChart()
191 191 {
192 192 d_ptr->m_attachedToChart = false;
193 193 }
194 194
195 195 /*!
196 196 Attaches the legend to chart. Chart may change layout of the legend.
197 197 */
198 198 void QLegend::attachToChart()
199 199 {
200 200 d_ptr->m_attachedToChart = true;
201 201 }
202 202
203 203 /*!
204 204 Returns true, if legend is attached to chart.
205 205 */
206 206 bool QLegend::isAttachedToChart()
207 207 {
208 208 return d_ptr->m_attachedToChart;
209 209 }
210 210
211 211 void QLegend::setOffset(const QPointF& point)
212 212 {
213 213 d_ptr->setOffset(point.x(),point.y());
214 214 }
215 215
216 216 QPointF QLegend::offset() const
217 217 {
218 218 return QPointF(d_ptr->m_offsetX,d_ptr->m_offsetY);
219 219 }
220 220
221 221 /*!
222 222 Sets the visibility of legend background to \a visible
223 223 */
224 224 void QLegend::setBackgroundVisible(bool visible)
225 225 {
226 226 if(d_ptr->m_backgroundVisible!=visible)
227 227 {
228 228 d_ptr->m_backgroundVisible=visible;
229 229 update();
230 230 }
231 231 }
232 232
233 233 /*!
234 234 Returns the visibility of legend background
235 235 */
236 236 bool QLegend::isBackgroundVisible() const
237 237 {
238 238 return d_ptr->m_backgroundVisible;
239 239 }
240 240
241 241 /*!
242 242 \internal \a event see QGraphicsWidget for details
243 243 */
244 244 void QLegend::resizeEvent(QGraphicsSceneResizeEvent *event)
245 245 {
246 246 const QRectF& rect = QRectF(QPoint(0,0),event->newSize());
247 247 QGraphicsWidget::resizeEvent(event);
248 248 if(d_ptr->m_rect != rect) {
249 249 d_ptr->m_rect = rect;
250 250 d_ptr->updateLayout();
251 251 }
252 252 }
253 253
254 254 /*!
255 255 \internal \a event see QGraphicsWidget for details
256 256 */
257 257 void QLegend::hideEvent(QHideEvent *event)
258 258 {
259 259 QGraphicsWidget::hideEvent(event);
260 260 setEnabled(false);
261 261 d_ptr->updateLayout();
262 262 }
263 263
264 264 /*!
265 265 \internal \a event see QGraphicsWidget for details
266 266 */
267 267 void QLegend::showEvent(QShowEvent *event)
268 268 {
269 269 QGraphicsWidget::showEvent(event);
270 270 setEnabled(true);
271 271 d_ptr->updateLayout();
272 272 }
273 273
274 274 qreal QLegend::minWidth() const
275 275 {
276 276 return d_ptr->m_minWidth;
277 277 }
278 278
279 279 qreal QLegend::minHeight() const
280 280 {
281 281 return d_ptr->m_minHeight;
282 282 }
283 283
284 284 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
285 285
286 286 QLegendPrivate::QLegendPrivate(ChartPresenter* presenter,QLegend *q):
287 287 q_ptr(q),
288 288 m_presenter(presenter),
289 289 m_markers(new QGraphicsItemGroup(q)),
290 290 m_alignment(QLegend::AlignmentTop),
291 291 m_offsetX(0),
292 292 m_offsetY(0),
293 293 m_minWidth(0),
294 294 m_minHeight(0),
295 295 m_width(0),
296 296 m_height(0),
297 297 m_attachedToChart(true),
298 298 m_backgroundVisible(false)
299 299 {
300 300
301 301 }
302 302
303 303 QLegendPrivate::~QLegendPrivate()
304 304 {
305 305
306 306 }
307 307
308 308 void QLegendPrivate::setOffset(qreal x, qreal y)
309 309 {
310 310
311 311 switch(m_alignment) {
312 312
313 313 case QLegend::AlignmentTop:
314 314 case QLegend::AlignmentBottom: {
315 315 if(m_width<=m_rect.width()) return;
316 316
317 317 if (x != m_offsetX) {
318 m_offsetX = qBound(0.0, x, m_width - m_rect.width());
318 m_offsetX = qBound(qreal(0), x, m_width - m_rect.width());
319 319 m_markers->setPos(-m_offsetX,m_rect.top());
320 320 }
321 321 break;
322 322 }
323 323 case QLegend::AlignmentLeft:
324 324 case QLegend::AlignmentRight: {
325 325
326 326 if(m_height<=m_rect.height()) return;
327 327
328 328 if (y != m_offsetY) {
329 m_offsetY = qBound(0.0, y, m_height - m_rect.height());
329 m_offsetY = qBound(qreal(0), y, m_height - m_rect.height());
330 330 m_markers->setPos(m_rect.left(),-m_offsetY);
331 331 }
332 332 break;
333 333 }
334 334 }
335 335 }
336 336
337 337
338 338 void QLegendPrivate::updateLayout()
339 339 {
340 340 m_offsetX=0;
341 341 QList<QGraphicsItem *> items = m_markers->childItems();
342 342
343 343 if(items.isEmpty()) return;
344 344
345 345 m_minWidth=0;
346 346 m_minHeight=0;
347 347
348 348 switch(m_alignment) {
349 349
350 350 case QLegend::AlignmentTop:
351 351 case QLegend::AlignmentBottom: {
352 352 QPointF point = m_rect.topLeft();
353 353 m_width = 0;
354 354 foreach (QGraphicsItem *item, items) {
355 355 item->setPos(point.x(),m_rect.height()/2 -item->boundingRect().height()/2);
356 356 const QRectF& rect = item->boundingRect();
357 357 qreal w = rect.width();
358 358 m_minWidth=qMax(m_minWidth,w);
359 359 m_minHeight=qMax(m_minHeight,rect.height());
360 360 m_width+=w;
361 361 point.setX(point.x() + w);
362 362 }
363 363 if(m_width<m_rect.width()) {
364 364 m_markers->setPos(m_rect.width()/2-m_width/2,m_rect.top());
365 365 }
366 366 else {
367 367 m_markers->setPos(m_rect.topLeft());
368 368 }
369 369 m_height=m_minHeight;
370 370 }
371 371 break;
372 372 case QLegend::AlignmentLeft:
373 373 case QLegend::AlignmentRight: {
374 374 QPointF point = m_rect.topLeft();
375 375 m_height = 0;
376 376 foreach (QGraphicsItem *item, items) {
377 377 item->setPos(point);
378 378 const QRectF& rect = item->boundingRect();
379 379 qreal h = rect.height();
380 380 m_minWidth=qMax(m_minWidth,rect.width());
381 381 m_minHeight=qMax(m_minHeight,h);
382 382 m_height+=h;
383 383 point.setY(point.y() + h);
384 384 }
385 385 if(m_height<m_rect.height()) {
386 386 m_markers->setPos(m_rect.left(),m_rect.height()/2-m_height/2);
387 387 }
388 388 else {
389 389 m_markers->setPos(m_rect.topLeft());
390 390 }
391 391 m_width=m_minWidth;
392 392 }
393 393 break;
394 394 }
395 395
396 396 m_presenter->updateLayout();
397 397 }
398 398
399 399 void QLegendPrivate::handleSeriesAdded(QSeries *series, Domain *domain)
400 400 {
401 401 Q_UNUSED(domain)
402 402
403 403 QList<LegendMarker*> markers = series->d_ptr->createLegendMarker(q_ptr);
404 404 foreach(LegendMarker* marker , markers)
405 405 m_markers->addToGroup(marker);
406 406
407 407 if(series->type()==QSeries::SeriesTypePie)
408 408 {
409 409 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
410 410 QObject::connect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleUpdateSeries()));
411 411 QObject::connect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleUpdateSeries()));
412 412 }
413 413
414 414 updateLayout();
415 415 }
416 416
417 417 void QLegendPrivate::handleSeriesRemoved(QSeries *series)
418 418 {
419 419
420 420 QList<QGraphicsItem *> items = m_markers->childItems();
421 421
422 422 foreach (QGraphicsItem *markers, items) {
423 423 LegendMarker *marker = static_cast<LegendMarker*>(markers);
424 424 if (marker->series() == series) {
425 425 delete marker;
426 426 }
427 427 }
428 428
429 429 if(series->type()==QSeries::SeriesTypePie)
430 430 {
431 431 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
432 432 QObject::disconnect(pieSeries,SIGNAL(added(QList<QPieSlice*>)),this,SLOT(handleUpdateSeries()));
433 433 QObject::disconnect(pieSeries,SIGNAL(removed(QList<QPieSlice*>)),this,SLOT(handleUpdateSeries()));
434 434 }
435 435
436 436 updateLayout();
437 437 }
438 438
439 439 void QLegendPrivate::handleUpdateSeries()
440 440 {
441 441 //TODO: reimplement to be optimal
442 442 QSeries* series = qobject_cast<QSeries *> (sender());
443 443 Q_ASSERT(series);
444 444 handleSeriesRemoved(series);
445 445 handleSeriesAdded(series,0);
446 446 }
447 447
448 448 #include "moc_qlegend.cpp"
449 449 #include "moc_qlegend_p.cpp"
450 450
451 451 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,116 +1,116
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qlineseries.h"
22 22 #include "qlineseries_p.h"
23 23 #include "linechartitem_p.h"
24 24 #include "chartdataset_p.h"
25 25 #include "charttheme_p.h"
26 26 #include "chartanimator_p.h"
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 /*!
31 31 \class QLineSeries
32 32 \brief The QLineSeries class is used for making line charts.
33 33
34 34 \mainclass
35 35
36 36 A line chart is used to show information as a series of data points
37 37 connected by straight lines.
38 38
39 39 \image linechart.png
40 40
41 41 Creating basic line chart is simple:
42 42 \code
43 43 QLineSeries* series = new QLineSeries();
44 44 series->append(0, 6);
45 45 series->append(2, 4);
46 46 ...
47 47 chartView->addSeries(series);
48 48 \endcode
49 49 */
50 50
51 51 /*!
52 52 \fn virtual QSeriesType QLineSeries::type() const
53 53 \brief Returns type of series.
54 54 \sa QSeries, QSeriesType
55 55 */
56 56
57 57 /*!
58 58 Constructs empty series object which is a child of \a parent.
59 When series object is added to QChartView or QChart instance ownerships is transfered.
59 When series object is added to QChartView or QChart instance ownerships is transferred.
60 60 */
61 61 QLineSeries::QLineSeries(QObject *parent) : QXYSeries(*new QLineSeriesPrivate(this),parent)
62 62 {
63 63
64 64 }
65 65
66 66 /*!
67 67 \internal
68 68 */
69 69 QLineSeries::QLineSeries(QLineSeriesPrivate &d,QObject *parent) : QXYSeries (d,parent)
70 70 {
71 71
72 72 }
73 73 /*!
74 74 Destroys the object. Series added to QChartView or QChart instances are owned by those,
75 75 and are deleted when mentioned object are destroyed.
76 76 */
77 77 QLineSeries::~QLineSeries()
78 78 {
79 79 }
80 80
81 81 QSeries::QSeriesType QLineSeries::type() const
82 82 {
83 83 return QSeries::SeriesTypeLine;
84 84 }
85 85
86 86 /*
87 87 QDebug operator<< (QDebug debug, const QLineSeries series)
88 88 {
89 89 Q_ASSERT(series.d_func()->m_x.size() == series.d_func()->m_y.size());
90 90 int size = series.d_func()->m_x.size();
91 91 for (int i=0; i<size; i++) {
92 92 debug.nospace() << "(" << series.d_func()->m_x.at(i) << ','<< series.d_func()->m_y.at(i) << ") ";
93 93 }
94 94 return debug.space();
95 95 }
96 96 */
97 97
98 98 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99 99
100 100 QLineSeriesPrivate::QLineSeriesPrivate(QLineSeries* q):QXYSeriesPrivate(q)
101 101 {
102 102
103 103 };
104 104
105 105 Chart* QLineSeriesPrivate::createGraphics(ChartPresenter* presenter)
106 106 {
107 107 Q_Q(QLineSeries);
108 108 LineChartItem* line = new LineChartItem(q,presenter);
109 109 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
110 110 presenter->animator()->addAnimation(line);
111 111 }
112 112 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
113 113 return line;
114 114 }
115 115
116 116 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,52 +1,52
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #ifndef QLINESERIES_H
22 22 #define QLINESERIES_H
23 23
24 24 #include <qchartglobal.h>
25 25 #include <qxyseries.h>
26 26 #include <QPen>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 class QLineSeriesPrivate;
31 31
32 32 class QTCOMMERCIALCHART_EXPORT QLineSeries : public QXYSeries
33 33 {
34 34 public:
35 explicit QLineSeries(QObject *parent=0);
35 explicit QLineSeries(QObject *parent = 0);
36 36 ~QLineSeries();
37 37
38 38 QSeries::QSeriesType type() const;
39 39
40 40 protected:
41 41 QLineSeries(QLineSeriesPrivate &d,QObject *parent = 0);
42 42
43 43 private:
44 44 Q_DECLARE_PRIVATE(QLineSeries);
45 45 Q_DISABLE_COPY(QLineSeries);
46 46 friend class LineChartItem;
47 47
48 48 };
49 49
50 50 QTCOMMERCIALCHART_END_NAMESPACE
51 51
52 52 #endif
@@ -1,738 +1,738
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qpieseries.h"
22 22 #include "qpieseries_p.h"
23 23 #include "qpieslice.h"
24 24 #include "pieslicedata_p.h"
25 25 #include "chartdataset_p.h"
26 26 #include "charttheme_p.h"
27 27 #include "chartanimator_p.h"
28 28 #include "legendmarker_p.h"
29 29 #include <QAbstractItemModel>
30 30 #include <QDebug>
31 31
32 32 QTCOMMERCIALCHART_BEGIN_NAMESPACE
33 33
34 34 /*!
35 35 \class QPieSeries
36 36 \brief Pie series API for QtCommercial Charts
37 37
38 38 The pie series defines a pie chart which consists of pie slices which are defined as QPieSlice objects.
39 39 The slices can have any values as the QPieSeries will calculate its relative value to the sum of all slices.
40 40 The actual slice size is determined by that relative value.
41 41
42 42 Pie size and position on the chart is controlled by using relative values which range from 0.0 to 1.0
43 43 These relate to the actual chart rectangle.
44 44
45 45 By default the pie is defined as a full pie but it can also be a partial pie.
46 46 This can be done by setting a starting angle and angle span to the series.
47 47 Full pie is 360 degrees where 0 is at 12 a'clock.
48 48 */
49 49
50 50 /*!
51 51 \property QPieSeries::horizontalPosition
52 52 \brief Defines the horizontal position of the pie.
53 53
54 54 The value is a relative value to the chart rectangle where:
55 55
56 56 \list
57 57 \o 0.0 is the absolute left.
58 58 \o 1.0 is the absolute right.
59 59 \endlist
60 60
61 61 Default value is 0.5 (center).
62 62 */
63 63
64 64 /*!
65 65 \property QPieSeries::verticalPosition
66 66 \brief Defines the vertical position of the pie.
67 67
68 68 The value is a relative value to the chart rectangle where:
69 69
70 70 \list
71 71 \o 0.0 is the absolute top.
72 72 \o 1.0 is the absolute bottom.
73 73 \endlist
74 74
75 75 Default value is 0.5 (center).
76 76 */
77 77
78 78 /*!
79 79 \property QPieSeries::size
80 80 \brief Defines the pie size.
81 81
82 82 The value is a relative value to the chart rectangle where:
83 83
84 84 \list
85 \o 0.0 is the minumum size (pie not drawn).
85 \o 0.0 is the minimum size (pie not drawn).
86 86 \o 1.0 is the maximum size that can fit the chart.
87 87 \endlist
88 88
89 89 Default value is 0.7.
90 90 */
91 91
92 92 /*!
93 93 \property QPieSeries::startAngle
94 94 \brief Defines the starting angle of the pie.
95 95
96 96 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
97 97
98 98 Default is value is 0.
99 99 */
100 100
101 101 /*!
102 102 \property QPieSeries::endAngle
103 103 \brief Defines the ending angle of the pie.
104 104
105 105 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
106 106
107 107 Default is value is 360.
108 108 */
109 109
110 110
111 111 /*!
112 112 Constructs a series object which is a child of \a parent.
113 113 */
114 114 QPieSeries::QPieSeries(QObject *parent) :
115 115 QSeries(*new QPieSeriesPrivate(this),parent)
116 116 {
117 117
118 118 }
119 119
120 120 /*!
121 121 Destroys the series and its slices.
122 122 */
123 123 QPieSeries::~QPieSeries()
124 124 {
125 125 // NOTE: d_prt destroyed by QObject
126 126 }
127 127
128 128 /*!
129 129 Returns QChartSeries::SeriesTypePie.
130 130 */
131 131 QSeries::QSeriesType QPieSeries::type() const
132 132 {
133 133 return QSeries::SeriesTypePie;
134 134 }
135 135
136 136 /*!
137 137 Sets an array of \a slices to the series replacing the existing slices.
138 138 Slice ownership is passed to the series.
139 139 */
140 140 void QPieSeries::replace(QList<QPieSlice*> slices)
141 141 {
142 142 clear();
143 143 append(slices);
144 144 }
145 145
146 146 /*!
147 147 Appends an array of \a slices to the series.
148 148 Slice ownership is passed to the series.
149 149 */
150 150 void QPieSeries::append(QList<QPieSlice*> slices)
151 151 {
152 152 Q_D(QPieSeries);
153 153
154 154 foreach (QPieSlice* s, slices) {
155 155 s->setParent(this);
156 156 d->m_slices << s;
157 157 }
158 158
159 159 d->updateDerivativeData();
160 160
161 161 foreach (QPieSlice* s, slices) {
162 162 connect(s, SIGNAL(changed()), d, SLOT(sliceChanged()));
163 163 connect(s, SIGNAL(clicked(Qt::MouseButtons)), d, SLOT(sliceClicked(Qt::MouseButtons)));
164 164 connect(s, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter()));
165 165 connect(s, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave()));
166 166 }
167 167
168 168 emit added(slices);
169 169 }
170 170
171 171 /*!
172 172 Appends a single \a slice to the series.
173 173 Slice ownership is passed to the series.
174 174 */
175 175 void QPieSeries::append(QPieSlice* slice)
176 176 {
177 177 append(QList<QPieSlice*>() << slice);
178 178 }
179 179
180 180 /*!
181 181 Appends a single \a slice to the series and returns a reference to the series.
182 182 Slice ownership is passed to the series.
183 183 */
184 184 QPieSeries& QPieSeries::operator << (QPieSlice* slice)
185 185 {
186 186 append(slice);
187 187 return *this;
188 188 }
189 189
190 190
191 191 /*!
192 192 Appends a single slice to the series with give \a value and \a name.
193 193 Slice ownership is passed to the series.
194 194 */
195 195 QPieSlice* QPieSeries::append(qreal value, QString name)
196 196 {
197 197 QPieSlice* slice = new QPieSlice(value, name);
198 198 append(slice);
199 199 return slice;
200 200 }
201 201
202 202 /*!
203 203 Inserts a single \a slice to the series before the slice at \a index position.
204 204 Slice ownership is passed to the series.
205 205 */
206 206 void QPieSeries::insert(int index, QPieSlice* slice)
207 207 {
208 208 Q_D(QPieSeries);
209 209 Q_ASSERT(index <= d->m_slices.count());
210 210 slice->setParent(this);
211 211 d->m_slices.insert(index, slice);
212 212
213 213 d->updateDerivativeData();
214 214
215 215 connect(slice, SIGNAL(changed()), d, SLOT(sliceChanged()));
216 216 connect(slice, SIGNAL(clicked(Qt::MouseButtons)), d, SLOT(sliceClicked(Qt::MouseButtons)));
217 217 connect(slice, SIGNAL(hoverEnter()), d, SLOT(sliceHoverEnter()));
218 218 connect(slice, SIGNAL(hoverLeave()), d, SLOT(sliceHoverLeave()));
219 219
220 220 emit added(QList<QPieSlice*>() << slice);
221 221 }
222 222
223 223 /*!
224 224 Removes a single \a slice from the series and deletes the slice.
225 225
226 226 Do not reference the pointer after this call.
227 227 */
228 228 void QPieSeries::remove(QPieSlice* slice)
229 229 {
230 230 Q_D(QPieSeries);
231 231 if (!d->m_slices.removeOne(slice)) {
232 232 Q_ASSERT(0); // TODO: how should this be reported?
233 233 return;
234 234 }
235 235
236 236 d->updateDerivativeData();
237 237
238 238 emit removed(QList<QPieSlice*>() << slice);
239 239
240 240 delete slice;
241 241 slice = 0;
242 242 }
243 243
244 244 /*!
245 245 Clears all slices from the series.
246 246 */
247 247 void QPieSeries::clear()
248 248 {
249 249 Q_D(QPieSeries);
250 250 if (d->m_slices.count() == 0)
251 251 return;
252 252
253 253 QList<QPieSlice*> slices = d->m_slices;
254 254 foreach (QPieSlice* s, d->m_slices) {
255 255 d->m_slices.removeOne(s);
256 256 delete s;
257 257 }
258 258
259 259 d->updateDerivativeData();
260 260
261 261 emit removed(slices);
262 262 }
263 263
264 264 /*!
265 265 returns the number of the slices in this series.
266 266 */
267 267 int QPieSeries::count() const
268 268 {
269 269 Q_D(const QPieSeries);
270 270 return d->m_slices.count();
271 271 }
272 272
273 273 /*!
274 274 Returns true is the series is empty.
275 275 */
276 276 bool QPieSeries::isEmpty() const
277 277 {
278 278 Q_D(const QPieSeries);
279 279 return d->m_slices.isEmpty();
280 280 }
281 281
282 282 /*!
283 283 Returns a list of slices that belong to this series.
284 284 */
285 285 QList<QPieSlice*> QPieSeries::slices() const
286 286 {
287 287 Q_D(const QPieSeries);
288 288 return d->m_slices;
289 289 }
290 290
291 291 void QPieSeries::setHorizontalPosition(qreal relativePosition)
292 292 {
293 293 Q_D(QPieSeries);
294 294 if (d->setRealValue(d->m_pieRelativeHorPos, relativePosition, 1.0))
295 295 emit piePositionChanged();
296 296 }
297 297
298 298 void QPieSeries::setVerticalPosition(qreal relativePosition)
299 299 {
300 300 Q_D(QPieSeries);
301 301 if (d->setRealValue(d->m_pieRelativeVerPos, relativePosition, 1.0))
302 302 emit piePositionChanged();
303 303 }
304 304
305 305 qreal QPieSeries::horizontalPosition() const
306 306 {
307 307 Q_D(const QPieSeries);
308 308 return d->m_pieRelativeHorPos;
309 309 }
310 310
311 311 qreal QPieSeries::verticalPosition() const
312 312 {
313 313 Q_D(const QPieSeries);
314 314 return d->m_pieRelativeVerPos;
315 315 }
316 316
317 317 void QPieSeries::setPieSize(qreal relativeSize)
318 318 {
319 319 Q_D(QPieSeries);
320 320 if (d->setRealValue(d->m_pieRelativeSize, relativeSize, 1.0))
321 321 emit pieSizeChanged();
322 322 }
323 323
324 324 qreal QPieSeries::pieSize() const
325 325 {
326 326 Q_D(const QPieSeries);
327 327 return d->m_pieRelativeSize;
328 328 }
329 329
330 330
331 331 void QPieSeries::setPieStartAngle(qreal angle)
332 332 {
333 333 Q_D(QPieSeries);
334 334 if (d->setRealValue(d->m_pieStartAngle, angle, d->m_pieEndAngle))
335 335 d->updateDerivativeData();
336 336 }
337 337
338 338 qreal QPieSeries::pieStartAngle() const
339 339 {
340 340 Q_D(const QPieSeries);
341 341 return d->m_pieStartAngle;
342 342 }
343 343
344 344 /*!
345 345 Sets the end angle of the pie.
346 346
347 347 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
348 348
349 349 \a angle must be greater than start angle.
350 350
351 351 \sa pieEndAngle(), pieStartAngle(), setPieStartAngle()
352 352 */
353 353 void QPieSeries::setPieEndAngle(qreal angle)
354 354 {
355 355 Q_D(QPieSeries);
356 356
357 357 if (d->setRealValue(d->m_pieEndAngle, angle, 360.0, d->m_pieStartAngle))
358 358 d->updateDerivativeData();
359 359 }
360 360
361 361 /*!
362 362 Returns the end angle of the pie.
363 363
364 364 Full pie is 360 degrees where 0 degrees is at 12 a'clock.
365 365
366 366 \sa setPieEndAngle(), pieStartAngle(), setPieStartAngle()
367 367 */
368 368 qreal QPieSeries::pieEndAngle() const
369 369 {
370 370 Q_D(const QPieSeries);
371 371 return d->m_pieEndAngle;
372 372 }
373 373
374 374 /*!
375 375 Sets the all the slice labels \a visible or invisible.
376 376
377 377 \sa QPieSlice::isLabelVisible(), QPieSlice::setLabelVisible()
378 378 */
379 379 void QPieSeries::setLabelsVisible(bool visible)
380 380 {
381 381 Q_D(QPieSeries);
382 382 foreach (QPieSlice* s, d->m_slices)
383 383 s->setLabelVisible(visible);
384 384 }
385 385
386 386 /*!
387 387 Returns the sum of all slice values in this series.
388 388
389 389 \sa QPieSlice::value(), QPieSlice::setValue(), QPieSlice::percentage()
390 390 */
391 391 qreal QPieSeries::sum() const
392 392 {
393 393 Q_D(const QPieSeries);
394 394 return d->m_sum;
395 395 }
396 396
397 397 /*!
398 398 \fn void QPieSeries::clicked(QPieSlice* slice, Qt::MouseButtons buttons)
399 399
400 400 This signal is emitted when a \a slice has been clicked with mouse \a buttons.
401 401
402 402 \sa QPieSlice::clicked()
403 403 */
404 404
405 405 /*!
406 406 \fn void QPieSeries::hoverEnter(QPieSlice* slice)
407 407
408 408 This signal is emitted when user has hovered over a \a slice.
409 409
410 410 \sa QPieSlice::hoverEnter()
411 411 */
412 412
413 413 /*!
414 414 \fn void QPieSeries::hoverLeave(QPieSlice* slice)
415 415
416 416 This signal is emitted when user has hovered away from a \a slice.
417 417
418 418 \sa QPieSlice::hoverLeave()
419 419 */
420 420
421 421 /*!
422 422 \fn void QPieSeries::added(QList<QPieSlice*> slices)
423 423
424 424 This signal is emitted when \a slices has been added to the series.
425 425
426 426 \sa append(), insert()
427 427 */
428 428
429 429 /*!
430 430 \fn void QPieSeries::removed(QList<QPieSlice*> slices)
431 431
432 432 This signal is emitted when \a slices has been removed from the series.
433 433
434 434 \sa remove(), clear()
435 435 */
436 436
437 437 /*!
438 438 \fn void QPieSeries::piePositionChanged()
439 439
440 440 This signal is emitted when pie position has changed.
441 441
442 442 \sa verticalPosition(), setVerticalPosition(), horizontalPosition(), setHorizontalPosition()
443 443 */
444 444
445 445 /*!
446 446 \fn void QPieSeries::pieSizeChanged()
447 447
448 448 This signal is emitted when pie size has changed.
449 449
450 450 \sa pieSize(), setPieSize()
451 451 */
452 452
453 453 /*!
454 454 \fn bool QPieSeries::setModel(QAbstractItemModel *model)
455 455 Sets the \a model to be used as a data source
456 456 */
457 457 bool QPieSeries::setModel(QAbstractItemModel* model)
458 458 {
459 459 Q_D(QPieSeries);
460 460 // disconnect signals from old model
461 461 if(d->m_model)
462 462 {
463 463 disconnect(d->m_model, 0, this, 0);
464 464 d->m_mapValues = -1;
465 465 d->m_mapLabels = -1;
466 466 d->m_mapOrientation = Qt::Vertical;
467 467 }
468 468
469 469 // set new model
470 470 if(model)
471 471 {
472 472 d->m_model = model;
473 473 return true;
474 474 }
475 475 else
476 476 {
477 477 d->m_model = 0;
478 478 return false;
479 479 }
480 480 }
481 481
482 482 /*!
483 483 \fn bool QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
484 484 Sets column/row specified by \a modelValuesLine to be used as a list of pie slice values for the pie.
485 485 Parameter \a modelValuesLine indicates the column/row where the values for the pie slices are located in the model.
486 486 Parameter \a modelLabelsLine indicates the column/row where the labels for the pie slices are located in the model.
487 The \a orientation paramater specifies whether the data is in columns or in rows.
487 The \a orientation parameter specifies whether the data is in columns or in rows.
488 488 */
489 489 void QPieSeries::setModelMapping(int modelValuesLine, int modelLabelsLine, Qt::Orientation orientation)
490 490 {
491 491 Q_D(QPieSeries);
492 492
493 493 if (d->m_model == 0)
494 494 return;
495 495
496 496 d->m_mapValues = modelValuesLine;
497 497 d->m_mapLabels = modelLabelsLine;
498 498 d->m_mapOrientation = orientation;
499 499
500 500 // connect the signals
501 501 if (d->m_mapOrientation == Qt::Vertical) {
502 502 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
503 503 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
504 504 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
505 505 } else {
506 506 connect(d->m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
507 507 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
508 508 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
509 509 }
510 510
511 511 // create the initial slices set
512 512 if (d->m_mapOrientation == Qt::Vertical) {
513 513 for (int i = 0; i < d->m_model->rowCount(); i++)
514 514 append(d->m_model->data(d->m_model->index(i, d->m_mapValues), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(i, d->m_mapLabels), Qt::DisplayRole).toString());
515 515 } else {
516 516 for (int i = 0; i < d->m_model->columnCount(); i++)
517 517 append(d->m_model->data(d->m_model->index(d->m_mapValues, i), Qt::DisplayRole).toDouble(), d->m_model->data(d->m_model->index(d->m_mapLabels, i), Qt::DisplayRole).toString());
518 518 }
519 519 }
520 520
521 521 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
522 522
523 523
524 524 QPieSeriesPrivate::QPieSeriesPrivate(QPieSeries *parent)
525 525 :QSeriesPrivate(parent),
526 526 m_pieRelativeHorPos(0.5),
527 527 m_pieRelativeVerPos(0.5),
528 528 m_pieRelativeSize(0.7),
529 529 m_pieStartAngle(0),
530 530 m_pieEndAngle(360),
531 531 m_sum(0),
532 532 m_mapValues(0),
533 533 m_mapLabels(0),
534 534 m_mapOrientation(Qt::Horizontal)
535 535 {
536 536
537 537 }
538 538
539 539 QPieSeriesPrivate::~QPieSeriesPrivate()
540 540 {
541 541
542 542 }
543 543
544 544 void QPieSeriesPrivate::updateDerivativeData()
545 545 {
546 546 m_sum = 0;
547 547
548 548 // nothing to do?
549 549 if (m_slices.count() == 0)
550 550 return;
551 551
552 552 // calculate sum of all slices
553 553 foreach (QPieSlice* s, m_slices)
554 554 m_sum += s->value();
555 555
556 556 // nothing to show..
557 557 if (qFuzzyIsNull(m_sum))
558 558 return;
559 559
560 560 // update slice attributes
561 561 qreal sliceAngle = m_pieStartAngle;
562 562 qreal pieSpan = m_pieEndAngle - m_pieStartAngle;
563 563 QVector<QPieSlice*> changed;
564 564 foreach (QPieSlice* s, m_slices) {
565 565
566 566 PieSliceData data = PieSliceData::data(s);
567 567 data.m_percentage = s->value() / m_sum;
568 568 data.m_angleSpan = pieSpan * data.m_percentage;
569 569 data.m_startAngle = sliceAngle;
570 570 sliceAngle += data.m_angleSpan;
571 571
572 572 if (PieSliceData::data(s) != data) {
573 573 PieSliceData::data(s) = data;
574 574 changed << s;
575 575 }
576 576 }
577 577
578 578 // emit signals
579 579 foreach (QPieSlice* s, changed)
580 580 PieSliceData::data(s).emitChangedSignal(s);
581 581 }
582 582
583 583 void QPieSeriesPrivate::sliceChanged()
584 584 {
585 585 Q_ASSERT(m_slices.contains(qobject_cast<QPieSlice *>(sender())));
586 586 updateDerivativeData();
587 587 }
588 588
589 589 void QPieSeriesPrivate::sliceClicked(Qt::MouseButtons buttons)
590 590 {
591 591 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
592 592 Q_ASSERT(m_slices.contains(slice));
593 593 Q_Q(QPieSeries);
594 594 emit q->clicked(slice, buttons);
595 595 }
596 596
597 597 void QPieSeriesPrivate::sliceHoverEnter()
598 598 {
599 599 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
600 600 Q_ASSERT(m_slices.contains(slice));
601 601 Q_Q(QPieSeries);
602 602 emit q->hoverEnter(slice);
603 603 }
604 604
605 605 void QPieSeriesPrivate::sliceHoverLeave()
606 606 {
607 607 QPieSlice* slice = qobject_cast<QPieSlice *>(sender());
608 608 Q_ASSERT(m_slices.contains(slice));
609 609 Q_Q(QPieSeries);
610 610 emit q->hoverLeave(slice);
611 611 }
612 612
613 613 void QPieSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
614 614 {
615 615 Q_UNUSED(bottomRight)
616 616
617 617 if (m_mapOrientation == Qt::Vertical)
618 618 {
619 619 if (topLeft.column() == m_mapValues)
620 620 if (m_mapValues == m_mapLabels)
621 621 {
622 622 m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
623 623 m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
624 624 }
625 625 else
626 626 {
627 627 m_slices.at(topLeft.row())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
628 628 }
629 629 else if (topLeft.column() == m_mapLabels)
630 630 m_slices.at(topLeft.row())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
631 631 }
632 632 else
633 633 {
634 634 if (topLeft.row() == m_mapValues)
635 635 if (m_mapValues == m_mapLabels)
636 636 {
637 637 m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
638 638 m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
639 639 }
640 640 else
641 641 {
642 642 m_slices.at(topLeft.column())->setValue(m_model->data(topLeft, Qt::DisplayRole).toDouble());
643 643 }
644 644 else if (topLeft.row() == m_mapLabels)
645 645 m_slices.at(topLeft.column())->setLabel(m_model->data(topLeft, Qt::DisplayRole).toString());
646 646 }
647 647 }
648 648
649 649 void QPieSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
650 650 {
651 651 Q_UNUSED(parent)
652 652 Q_UNUSED(end)
653 653 Q_Q(QPieSeries);
654 654
655 655 QPieSlice* newSlice = new QPieSlice;
656 656 newSlice->setLabelVisible(true);
657 657 if (m_mapOrientation == Qt::Vertical)
658 658 {
659 659 newSlice->setValue(m_model->data(m_model->index(start, m_mapValues), Qt::DisplayRole).toDouble());
660 660 newSlice->setLabel(m_model->data(m_model->index(start, m_mapLabels), Qt::DisplayRole).toString());
661 661 }
662 662 else
663 663 {
664 664 newSlice->setValue(m_model->data(m_model->index(m_mapValues, start), Qt::DisplayRole).toDouble());
665 665 newSlice->setLabel(m_model->data(m_model->index(m_mapLabels, start), Qt::DisplayRole).toString());
666 666 }
667 667
668 668 q->insert(start, newSlice);
669 669 }
670 670
671 671 void QPieSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
672 672 {
673 673 Q_UNUSED(parent)
674 674 Q_UNUSED(end)
675 675 Q_Q(QPieSeries);
676 676 q->remove(m_slices.at(start));
677 677 }
678 678
679 679 bool QPieSeriesPrivate::setRealValue(qreal &value, qreal newValue, qreal max, qreal min)
680 680 {
681 681 // Remove rounding errors
682 682 qreal roundedValue = newValue;
683 683 if (qFuzzyIsNull(min) && qFuzzyIsNull(newValue))
684 684 roundedValue = 0.0;
685 685 else if (qFuzzyCompare(newValue, max))
686 686 roundedValue = max;
687 687 else if (qFuzzyCompare(newValue, min))
688 688 roundedValue = min;
689 689
690 690 // Check if the position is valid after removing the rounding errors
691 691 if (roundedValue < min || roundedValue > max) {
692 692 qWarning("QPieSeries: Illegal value");
693 693 return false;
694 694 }
695 695
696 696 if (!qFuzzyIsNull(value - roundedValue)) {
697 697 value = roundedValue;
698 698 return true;
699 699 }
700 700
701 701 // The change was so small it is considered a rounding error
702 702 return false;
703 703 }
704 704
705 705 void QPieSeriesPrivate::scaleDomain(Domain& domain)
706 706 {
707 707 Q_UNUSED(domain);
708 708 #ifndef QT_NO_DEBUG
709 709 qWarning() << __FILE__<<__FUNCTION__<<"not implemented";
710 710 #endif
711 711 }
712 712
713 713 Chart* QPieSeriesPrivate::createGraphics(ChartPresenter* presenter)
714 714 {
715 715 Q_Q(QPieSeries);
716 716 PieChartItem* pie = new PieChartItem(q,presenter);
717 717 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
718 718 presenter->animator()->addAnimation(pie);
719 719 }
720 720 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
721 721 return pie;
722 722 }
723 723
724 724 QList<LegendMarker*> QPieSeriesPrivate::createLegendMarker(QLegend* legend)
725 725 {
726 726 Q_Q(QPieSeries);
727 727 QList<LegendMarker*> markers;
728 728 foreach(QPieSlice* slice, q->slices()) {
729 729 PieLegendMarker* marker = new PieLegendMarker(q,slice,legend);
730 730 markers << marker;
731 731 }
732 732 return markers;
733 733 }
734 734
735 735 #include "moc_qpieseries.cpp"
736 736 #include "moc_qpieseries_p.cpp"
737 737
738 738 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,132 +1,133
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qseries.h"
22 22 #include "qseries_p.h"
23 23
24 24 QTCOMMERCIALCHART_BEGIN_NAMESPACE
25 25
26 26 /*!
27 27 \class QSeries
28 28 \brief Base class for all QtCommercial Chart series.
29 29 \mainclass
30 30
31 31 Usually you use the series type specific inherited classes instead of the base class.
32 32 \sa QXYSeries, QLineSeries, QSplineSeries, QScatterSeries, QAreaSeries, QBarSeries, QStackedBarSeries,
33 33 QPercentBarSeries, QPieSeries
34 34 */
35 35
36 36 /*!
37 37 \enum QSeries::QSeriesType
38 38
39 39 The type of the series object.
40 40
41 41 \value SeriesTypeLine
42 42 \value SeriesTypeArea
43 43 \value SeriesTypeBar
44 44 \value SeriesTypeStackedBar
45 45 \value SeriesTypePercentBar
46 46 \value SeriesTypePie
47 47 \value SeriesTypeScatter
48 48 \value SeriesTypeSpline
49 49 */
50 50
51 51 /*!
52 52 \fn QSeriesType QSeries::type() const
53 53 \brief The type of the series.
54 54 */
55 55
56 56 /*!
57 57 \fn bool QSeries::setModel(QAbstractItemModel *model)
58 58 \brief Use the \a model to provide data for the series. The model overrides possible user data
59 59 set with QChartSeries type specific data setters. For example if you call both
60 60 QScatterSeries::addData() and QScatterSeries::setModel, only the data provided by the model is
61 61 used by the series. Returns true if the model is valid for the series.
62 62 */
63 63
64 64 /*!
65 65 \property QSeries::name
66 66 \brief name of the series property
67 67 */
68 68
69 69 /*!
70 70 \fn void QSeries::setName(const QString& name)
71 71 \brief Sets a \a name for the series.
72 72
73 73 The name of a series is shown in the legend for QXYSeries.
74 74 \sa QChart::setTitle()
75 75 \sa QPieSlice::setLabel()
76 76 \sa QBarSet::setName()
77 77 */
78 78
79 79 /*!
80 80 \internal
81 81 \brief Constructs ChartSeries object with \a parent.
82 82 */
83 83 QSeries::QSeries(QSeriesPrivate &d, QObject *parent) :
84 84 QObject(parent),
85 85 d_ptr(&d)
86 86 {
87 87 }
88 88
89 89 /*!
90 90 \brief Virtual destructor for the chart series.
91 91 */
92 92 QSeries::~QSeries()
93 93 {
94 94 }
95 95
96 96 /*!
97 97 \brief Returns the pointer to the model that is used as the series data source
98 98 */
99 99 QAbstractItemModel* QSeries::model() const
100 100 {
101 101 return d_ptr->m_model;
102 102 }
103 103
104 104 void QSeries::setName(const QString& name)
105 105 {
106 106 d_ptr->m_name = name;
107 107 }
108 108
109 109 /*!
110 110 \brief Returns the name of the series.
111 111 \sa setName()
112 112 */
113 113 QString QSeries::name() const
114 114 {
115 115 return d_ptr->m_name;
116 116 }
117 117
118 118 ///////////////////////////////////////////////////////////////////////////////////////////////////
119 119
120 120 QSeriesPrivate::QSeriesPrivate(QSeries* q): q_ptr(q),m_model(0)
121 121 {
122 122 }
123 123
124 124 QSeriesPrivate::~QSeriesPrivate()
125 125 {
126 126 }
127 127
128 128 #include "moc_qseries.cpp"
129 #include "moc_qseries_p.cpp"
129 130
130 131 QTCOMMERCIALCHART_END_NAMESPACE
131 132
132 133
@@ -1,65 +1,66
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef QSERIES_P_H
31 31 #define QSERIES_P_H
32 32
33 33 #include "qseries.h"
34 34
35 35 class QAbstractItemModel;
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 class Domain;
40 40 class ChartPresenter;
41 41 class Chart;
42 42 class LegendMarker;
43 43 class QLegend;
44 44
45 45 class QSeriesPrivate : public QObject
46 46 {
47 Q_OBJECT
47 48 public:
48 49 QSeriesPrivate(QSeries *q);
49 50 ~QSeriesPrivate();
50 51
51 52 virtual void scaleDomain(Domain& domain) = 0;
52 53 virtual Chart* createGraphics(ChartPresenter* presenter) = 0;
53 54 virtual QList<LegendMarker*> createLegendMarker(QLegend* legend) = 0;
54 55
55 56 protected:
56 57 QSeries *q_ptr;
57 58 QAbstractItemModel *m_model;
58 59 QString m_name;
59 60
60 61 friend class QSeries;
61 62 };
62 63
63 64 QTCOMMERCIALCHART_END_NAMESPACE
64 65
65 66 #endif
@@ -1,248 +1,250
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "scroller_p.h"
22 22 #include "qlegend.h"
23 23 #include <QGraphicsSceneMouseEvent>
24 24
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 Scroller::Scroller():
28 28 m_ticker(this),
29 29 m_state(Idle),
30 30 m_moveThreshold(10),
31 31 m_timeTreshold(50)
32 32 {
33 33
34 34 }
35 35
36 36 Scroller::~Scroller()
37 37 {
38 38 }
39 39
40 40 void Scroller::mousePressEvent(QGraphicsSceneMouseEvent* event)
41 41 {
42 42 if (event->button() == Qt::LeftButton) {
43 43
44 44 switch (m_state) {
45 45 case Idle:
46 46 {
47 47 m_state = Pressed;
48 48 m_offset = offset();
49 49 m_press = event->pos();
50 50 m_timeStamp = QTime::currentTime();
51 51 event->accept();
52 52 break;
53 53 }
54 54 case Scroll:
55 55 {
56 56 m_state = Stop;
57 57 m_speed = QPoint(0, 0);
58 58 m_offset = offset();
59 59 m_press = event->pos();
60 60 event->accept();
61 61 break;
62 62 }
63 63 case Pressed:
64 64 case Move:
65 65 case Stop:
66 66 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
67 67 event->ignore();
68 68 break;
69 69 }
70 70 }
71 71 }
72 72
73 73 void Scroller::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
74 74 {
75 75 QPointF delta = event->pos() - m_press;
76 76
77 77 switch (m_state) {
78 78 case Pressed:
79 79 case Stop:
80 80 {
81 81 if (qAbs(delta.x()) > m_moveThreshold || qAbs(delta.y()) > m_moveThreshold) {
82 82 m_state = Move;
83 83 m_timeStamp = QTime::currentTime();
84 84 m_distance = QPointF(0, 0);
85 85 m_press = event->pos();
86 86 event->accept();
87 87 break;
88 88 }
89 89 else {
90 90 event->ignore();
91 91 break;
92 92 }
93 93 }
94 94 case Move:
95 95 {
96 96 setOffset(m_offset - delta);
97 97 calculateSpeed(event->pos());
98 98 event->accept();
99 99 break;
100 100 }
101 101 case Idle:
102 102 case Scroll:
103 103 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
104 104 event->ignore();
105 105 break;
106 106 }
107 107
108 108 }
109 109
110 110 void Scroller::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
111 111 {
112 112 if (event->button() == Qt::LeftButton) {
113 113
114 114 switch (m_state) {
115 115
116 116 case Scroll:
117 117 m_state = Stop;
118 118 m_speed = QPointF(0, 0);
119 119 m_offset = offset();
120 120 event->accept();
121 121 break;
122 122 case Pressed:
123 123 {
124 124 m_state = Idle;
125 125 //if (m_timeStamp.elapsed() < m_clickedPressDelay) {
126 126
127 127 //emit clicked(m_offset.toPoint());
128 128 //}
129 129 event->accept();
130 130 break;
131 131 }
132 132 case Move:
133 133 {
134 134 calculateSpeed(event->pos());
135 135 m_offset = offset();
136 136 m_press = event->pos();
137 137 if (m_speed == QPointF(0, 0)) {
138 138 m_state = Idle;
139 139 }
140 140 else {
141 141 m_speed /= 4;
142 142 m_state = Scroll;
143 143 m_ticker.start(20);
144 144 }
145 145 event->accept();
146 146 break;
147 147 }
148 148
149 149 case Stop:
150 150 case Idle:
151 151 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
152 152 event->ignore();
153 153 break;
154 154
155 155 }
156 156 }
157 157 }
158 158
159 159 void Scroller::scrollTick()
160 160 {
161 161 switch (m_state) {
162 162 case Scroll:
163 163 {
164 164 lowerSpeed(m_speed);
165 165 setOffset(m_offset - m_speed);
166 166 m_offset = offset();
167 167 if (m_speed == QPointF(0, 0)) {
168 168 m_state = Idle;
169 169 m_ticker.stop();
170 170 }
171 171 break;
172 172 }
173 173 case Stop:
174 174 m_ticker.stop();
175 175 break;
176 176 case Idle:
177 177 case Move:
178 178 case Pressed:
179 179 qWarning() << __FUNCTION__<<"Scroller unexpected state" << m_state;
180 180 m_ticker.stop();
181 181 break;
182 182
183 183 }
184 184 }
185 185
186 186 void Scroller::lowerSpeed(QPointF& speed, qreal maxSpeed)
187 187 {
188 188 qreal x = qBound(-maxSpeed, speed.x(), maxSpeed);
189 189 qreal y = qBound(-maxSpeed, speed.y(), maxSpeed);
190 190
191 191 x = (x == 0) ? x :
192 192 (x > 0) ? qMax(qreal(0), x - m_fraction.x()) : qMin(qreal(0), x + m_fraction.x());
193 193 y = (y == 0) ? y :
194 194 (y > 0) ? qMax(qreal(0), y - m_fraction.y()) : qMin(qreal(0), y + m_fraction.y());
195 195 speed.setX(x);
196 196 speed.setY(y);
197 197 }
198 198
199 199 void Scroller::calculateSpeed(const QPointF& position)
200 200 {
201 201 if (m_timeStamp.elapsed() > m_timeTreshold) {
202 202
203 203 QPointF distance = position - m_press;
204 204
205 205 m_timeStamp = QTime::currentTime();
206 206 m_speed = distance - m_distance;
207 207 m_distance = distance;
208 208
209 209 qreal fraction = qMax(qAbs(m_speed.x()), qAbs(m_speed.y()));
210 210
211 211 if (fraction != 0) {
212 212 m_fraction.setX(qAbs(m_speed.x() / fraction));
213 213 m_fraction.setY(qAbs(m_speed.y() / fraction));
214 214 }
215 215 else {
216 216 m_fraction.setX(1);
217 217 m_fraction.setY(1);
218 218 }
219 219 }
220 220 }
221 221
222 222 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
223 223
224 224 ScrollTicker::ScrollTicker(Scroller *scroller,QObject* parent):QObject(parent),
225 225 m_scroller(scroller)
226 226 {
227 227
228 228 }
229 229
230 230 void ScrollTicker::start(int interval)
231 231 {
232 232 if (!m_timer.isActive()){
233 233 m_timer.start(interval, this);
234 234 }
235 235 }
236 236
237 237 void ScrollTicker::stop()
238 238 {
239 239 m_timer.stop();
240 240 }
241 241
242 242 void ScrollTicker::timerEvent(QTimerEvent *event)
243 243 {
244 244 Q_UNUSED(event);
245 245 m_scroller->scrollTick();
246 246 }
247 247
248 #include "moc_scroller_p.cpp"
249
248 250 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,106 +1,107
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 // W A R N I N G
22 22 // -------------
23 23 //
24 24 // This file is not part of the QtCommercial Chart API. It exists purely as an
25 25 // implementation detail. This header file may change from version to
26 26 // version without notice, or even be removed.
27 27 //
28 28 // We mean it.
29 29
30 30 #ifndef SCROLLER_P_H
31 31 #define SCROLLER_P_H
32 32
33 33 #include "qchartglobal.h"
34 34 #include <QBasicTimer>
35 35 #include <QTime>
36 36 #include <QPointF>
37 37
38 38 class QGraphicsSceneMouseEvent;
39 39
40 40 QTCOMMERCIALCHART_BEGIN_NAMESPACE
41 41
42 42 class Scroller;
43 43 class QLegend;
44 44
45 45 class ScrollTicker : public QObject
46 46 {
47 Q_OBJECT
47 48 public:
48 49 explicit ScrollTicker(Scroller *scroller,QObject *parent = 0);
49 50 void start(int interval);
50 51 void stop();
51 52 protected:
52 53 void timerEvent(QTimerEvent *event);
53 54
54 55 private:
55 56 QBasicTimer m_timer;
56 57 Scroller *m_scroller;
57 58 };
58 59
59 60 class Scroller
60 61 {
61 62 public:
62 63 enum State {
63 64 Idle,
64 65 Pressed,
65 66 Move,
66 67 Scroll,
67 68 Stop
68 69 };
69 70
70 71 Scroller();
71 72 virtual ~Scroller();
72 73
73 74 virtual void setOffset(const QPointF& point) = 0;
74 75 virtual QPointF offset() const = 0;
75 76
76 77 public:
77 78 void scrollTick();
78 79
79 80
80 81 public:
81 82 void mousePressEvent(QGraphicsSceneMouseEvent* event);
82 83 void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
83 84 void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
84 85
85 86 private:
86 87 void calculateSpeed(const QPointF& position);
87 88 void lowerSpeed(QPointF& speed,qreal maxSpeed=100);
88 89
89 90 private:
90 91 ScrollTicker m_ticker;
91 92 State m_state;
92 93 QTime m_timeStamp;
93 94 QPointF m_press;
94 95 QPointF m_offset;
95 96 QPointF m_speed;
96 97 QPointF m_distance;
97 98 QPointF m_fraction;
98 99 int m_moveThreshold;
99 100 int m_timeTreshold;
100 101
101 102
102 103 };
103 104
104 105 QTCOMMERCIALCHART_END_NAMESPACE
105 106
106 107 #endif /* SCROLLER_P_H_ */
@@ -1,236 +1,236
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qsplineseries.h"
22 22 #include "qsplineseries_p.h"
23 23 #include "splinechartitem_p.h"
24 24 #include "chartdataset_p.h"
25 25 #include "charttheme_p.h"
26 26 #include "chartanimator_p.h"
27 27
28 28 /*!
29 29 \class QSplineSeries
30 30 \brief Series type used to store data needed to draw a spline.
31 31
32 32 QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
33 33 Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn.
34 34 */
35 35
36 36 /*!
37 37 \fn QSeriesType QSplineSeries::type() const
38 38 Returns the type of the series
39 39 */
40 40
41 41 /*!
42 42 \fn QSeriesType QSplineSeries::controlPoint(int index) const
43 43 Returns the control point specified by \a index
44 44 */
45 45
46 46 QTCOMMERCIALCHART_BEGIN_NAMESPACE
47 47
48 48 /*!
49 49 Constructs empty series object which is a child of \a parent.
50 When series object is added to QChartView or QChart instance then the ownerships is transfered.
50 When series object is added to QChartView or QChart instance then the ownerships is transferred.
51 51 */
52 52
53 53 QSplineSeries::QSplineSeries(QObject *parent) :
54 54 QLineSeries(*new QSplineSeriesPrivate(this),parent)
55 55 {
56 56 }
57 57
58 58 QSeries::QSeriesType QSplineSeries::type() const
59 59 {
60 60 return QSeries::SeriesTypeSpline;
61 61 }
62 62
63 63 QPointF QSplineSeries::controlPoint(int index) const
64 64 {
65 65 Q_D(const QSplineSeries);
66 66 return d->m_controlPoints[index];
67 67 }
68 68
69 69 void QSplineSeries::setModelMappingRange(int first, int count)
70 70 {
71 71 Q_D(QSplineSeries);
72 72 QLineSeries::setModelMappingRange(first, count);
73 73 d->calculateControlPoints();
74 74 }
75 75
76 76 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77 77
78 78 QSplineSeriesPrivate::QSplineSeriesPrivate(QSplineSeries* q):QLineSeriesPrivate(q)
79 79 {
80 80 QObject::connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints()));
81 81 QObject::connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints()));
82 82 QObject::connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints()));
83 83 };
84 84
85 85 /*!
86 86 \internal
87 87 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
88 88 */
89 89 void QSplineSeriesPrivate::calculateControlPoints()
90 90 {
91 91
92 92 Q_Q(QSplineSeries);
93 93 // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit
94 94 // CPOL License
95 95
96 96 int n = q->count() - 1;
97 97 if (n == 1)
98 98 { // Special case: Bezier curve should be a straight line.
99 99 // firstControlPoints = new Point[1];
100 100 // 3P1 = 2P0 + P3
101 101 m_controlPoints.append(QPointF((2 * q->x(0) + q->x(1)) / 3, (2 * q->y(0) + q->y(1)) / 3));
102 102
103 103 // P2 = 2P1 P0
104 104 m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - q->x(0), 2 * m_controlPoints[0].y() - q->y(0)));
105 105 return;
106 106 }
107 107
108 108 // Calculate first Bezier control points
109 109 // Right hand side vector
110 110 // Set of equations for P0 to Pn points.
111 111 //
112 112 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
113 113 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
114 114 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
115 115 // | . . . . . . . . . . . . | | ... | | ... |
116 116 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
117 117 // | . . . . . . . . . . . . | | ... | | ... |
118 118 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
119 119 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
120 120 //
121 121 QList<qreal> rhs;
122 122 rhs.append(q->x(0) + 2 * q->x(1));
123 123
124 124 // Set right hand side X values
125 125 for (int i = 1; i < n - 1; ++i)
126 126 rhs.append(4 * q->x(i) + 2 * q->x(i + 1));
127 127
128 128 rhs.append((8 * q->x(n - 1) + q->x(n)) / 2.0);
129 129 // Get first control points X-values
130 130 QList<qreal> xControl = getFirstControlPoints(rhs);
131 131 rhs[0] = q->y(0) + 2 * q->y(1);
132 132
133 133 // Set right hand side Y values
134 134 for (int i = 1; i < n - 1; ++i)
135 135 rhs[i] = 4 * q->y(i) + 2 * q->y(i + 1);
136 136
137 137 rhs[n - 1] = (8 * q->y(n - 1) + q->y(n)) / 2.0;
138 138 // Get first control points Y-values
139 139 QList<qreal> yControl = getFirstControlPoints(rhs);
140 140
141 141 // Fill output arrays.
142 142 for (int i = 0; i < n; ++i) {
143 143 // First control point
144 144 m_controlPoints.append(QPointF(xControl[i], yControl[i]));
145 145 // Second control point
146 146 if (i < n - 1)
147 147 m_controlPoints.append(QPointF(2 * q->x(i + 1) - xControl[i + 1], 2 * q->y(i + 1) - yControl[i + 1]));
148 148 else
149 149 m_controlPoints.append(QPointF((q->x(n) + xControl[n - 1]) / 2, (q->y(n) + yControl[n - 1]) / 2));
150 150 }
151 151 }
152 152
153 153 /*!
154 154 \internal
155 155 */
156 156 QList<qreal> QSplineSeriesPrivate::getFirstControlPoints(QList<qreal> rhs)
157 157 {
158 158 QList<qreal> x; // Solution vector.
159 159 QList<qreal> tmp; // Temp workspace.
160 160
161 161 qreal b = 2.0;
162 162 x.append(rhs[0] / b);
163 163 tmp.append(0);
164 164 for (int i = 1; i < rhs.size(); i++) {
165 165 // Decomposition and forward substitution.
166 166 tmp.append(1 / b);
167 167 b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i];
168 168 x.append((rhs[i] - x[i - 1]) / b);
169 169 }
170 170 for (int i = 1; i < rhs.size(); i++)
171 171 x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution.
172 172
173 173 return x;
174 174 }
175 175
176 176 /*!
177 177 \internal
178 178 Updates the control points, besed on currently avaiable knots.
179 179 */
180 180 void QSplineSeriesPrivate::updateControlPoints()
181 181 {
182 182 Q_Q(QSplineSeries);
183 183 if (q->count() > 1) {
184 184 m_controlPoints.clear();
185 185 calculateControlPoints();
186 186 }
187 187 }
188 188
189 189 /*//!
190 190 \fn bool QSplineSeries::setModel(QAbstractItemModel *model)
191 191 Sets the \a model to be used as a data source
192 192 \sa setModelMapping(), setModelMappingRange()
193 193 */
194 194 //bool QSplineSeries::setModel(QAbstractItemModel* model)
195 195 //{
196 196 // QXYSeries::setModel(model);
197 197 //// calculateControlPoints();
198 198 // return true;
199 199 //}
200 200
201 201 /*//!
202 202 \fn bool QSplineSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
203 203 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
204 as a data source for y coordinate. The \a orientation paramater specifies whether the data
204 as a data source for y coordinate. The \a orientation parameter specifies whether the data
205 205 is in columns or in rows.
206 206 */
207 207 //void QSplineSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
208 208 //{
209 209 // QLineSeries::setModelMapping(modelX, modelY, orientation);
210 210 //// calculateControlPoints();
211 211 //}
212 212
213 213 /*!
214 214 \fn bool QSplineSeries::setModelMappingRange(int first, int count)
215 215 Allows limiting the model mapping.
216 216 Parameter \a first specifies which element of the model should be used as a first one of the series.
217 217 Parameter \a count specifies how many elements should be mapped. If count is not specified (defaults to -1)
218 218 then all the items following \a first item in a model are used.
219 219 \sa setModel(), setModelMapping()
220 220 */
221 221
222 222 Chart* QSplineSeriesPrivate::createGraphics(ChartPresenter* presenter)
223 223 {
224 224 Q_Q(QSplineSeries);
225 225 SplineChartItem* spline = new SplineChartItem(q,presenter);
226 226 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
227 227 presenter->animator()->addAnimation(spline);
228 228 }
229 229 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
230 230 return spline;
231 231 }
232 232
233 233 #include "moc_qsplineseries.cpp"
234 234 #include "moc_qsplineseries_p.cpp"
235 235
236 236 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,671 +1,671
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qxyseries.h"
22 22 #include "qxyseries_p.h"
23 23 #include "domain_p.h"
24 24 #include "legendmarker_p.h"
25 25 #include <QAbstractItemModel>
26 26
27 27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 28
29 29 /*!
30 30 \class QXYSeries
31 31 \brief The QXYSeries class is a base class for line, spline and scatter series.
32 32 */
33 33
34 34 /*!
35 35 \fn QPen QXYSeries::pen() const
36 36 \brief Returns pen used to draw points for series.
37 37 \sa setPen()
38 38 */
39 39
40 40 /*!
41 41 \fn QBrush QXYSeries::brush() const
42 42 \brief Returns brush used to draw points for series.
43 43 \sa setBrush()
44 44 */
45 45
46 46 /*!
47 47 \fn void QXYSeries::clicked(const QPointF& point)
48 48 \brief Signal is emitted when user clicks the \a point on chart.
49 49 */
50 50
51 51 /*!
52 52 \fn void QXYSeries::selected()
53 53
54 54 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
55 55 implemented by the user of QXYSeries API.
56 56 */
57 57
58 58 /*!
59 59 \fn void QXYSeriesPrivate::pointReplaced(int index)
60 60 \brief \internal \a index
61 61 */
62 62
63 63 /*!
64 64 \fn void QXYSeriesPrivate::pointAdded(int index)
65 65 \brief \internal \a index
66 66 */
67 67
68 68 /*!
69 69 \fn void QXYSeriesPrivate::pointRemoved(int index)
70 70 \brief \internal \a index
71 71 */
72 72
73 73 /*!
74 74 \fn void QXYSeriesPrivate::updated()
75 75 \brief \internal
76 76 */
77 77
78 78 /*!
79 79 \fn int QXYSeries::mapFirst() const
80 80 Returns the index of the model's item that is used as a first one for the series.
81 81 \sa mapCount()
82 82 */
83 83
84 84 /*!
85 85 \fn int QXYSeries::mapCount() const
86 86 Returns the number of the items that are taken from the model.
87 87 If -1 it means all the items of the model following the first one are used.
88 88 \sa mapFirst()
89 89 */
90 90
91 91 /*!
92 92 \internal
93 93
94 94 Constructs empty series object which is a child of \a parent.
95 When series object is added to QChartView or QChart instance ownerships is transfered.
95 When series object is added to QChartView or QChart instance ownerships is transferred.
96 96 */
97 97 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent):QSeries(d,parent)
98 98 {
99 99
100 100 }
101 101 /*!
102 102 Destroys the object. Series added to QChartView or QChart instances are owned by those,
103 103 and are deleted when mentioned object are destroyed.
104 104 */
105 105 QXYSeries::~QXYSeries()
106 106 {
107 107 }
108 108
109 109 /*!
110 110 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
111 111 */
112 112 void QXYSeries::append(qreal x,qreal y)
113 113 {
114 114 Q_D(QXYSeries);
115 115 Q_ASSERT(d->m_x.size() == d->m_y.size());
116 116 d->m_x<<x;
117 117 d->m_y<<y;
118 118 emit d->pointAdded(d->m_x.size()-1);
119 119 }
120 120
121 121 /*!
122 122 This is an overloaded function.
123 123 Adds data \a point to the series. Points are connected with lines on the chart.
124 124 */
125 125 void QXYSeries::append(const QPointF &point)
126 126 {
127 127 append(point.x(),point.y());
128 128 }
129 129
130 130 /*!
131 131 This is an overloaded function.
132 132 Adds list of data \a points to the series. Points are connected with lines on the chart.
133 133 */
134 134 void QXYSeries::append(const QList<QPointF> points)
135 135 {
136 136 foreach(const QPointF& point , points) {
137 137 append(point.x(),point.y());
138 138 }
139 139 }
140 140
141 141 /*!
142 142 Modifies \a y value for given \a x a value.
143 143 */
144 144 void QXYSeries::replace(qreal x,qreal y)
145 145 {
146 146 Q_D(QXYSeries);
147 147 int index = d->m_x.indexOf(x);
148 148 d->m_x[index] = x;
149 149 d->m_y[index] = y;
150 150 emit d->pointReplaced(index);
151 151 }
152 152
153 153 /*!
154 154 This is an overloaded function.
155 155 Replaces current y value of for given \a point x value with \a point y value.
156 156 */
157 157 void QXYSeries::replace(const QPointF &point)
158 158 {
159 159 replace(point.x(),point.y());
160 160 }
161 161
162 162 /*!
163 163 Removes first \a x value and related y value.
164 164 */
165 165 void QXYSeries::remove(qreal x)
166 166 {
167 167 Q_D(QXYSeries);
168 168 int index = d->m_x.indexOf(x);
169 169
170 170 if (index == -1) return;
171 171
172 172 d->m_x.remove(index);
173 173 d->m_y.remove(index);
174 174
175 175 emit d->pointRemoved(index);
176 176 }
177 177
178 178 /*!
179 179 Removes current \a x and \a y value.
180 180 */
181 181 void QXYSeries::remove(qreal x,qreal y)
182 182 {
183 183 Q_D(QXYSeries);
184 184 int index =-1;
185 185 do {
186 186 index = d->m_x.indexOf(x,index+1);
187 187 } while (index !=-1 && d->m_y.at(index)!=y);
188 188
189 189 if (index==-1) return;
190 190
191 191 d->m_x.remove(index);
192 192 d->m_y.remove(index);
193 193 emit d->pointRemoved(index);
194 194 }
195 195
196 196 /*!
197 197 Removes current \a point x value. Note \a point y value is ignored.
198 198 */
199 199 void QXYSeries::remove(const QPointF &point)
200 200 {
201 201 remove(point.x(),point.y());
202 202 }
203 203
204 204 /*!
205 205 Removes all data points from the series.
206 206 */
207 207 void QXYSeries::removeAll()
208 208 {
209 209 Q_D(QXYSeries);
210 210 d->m_x.clear();
211 211 d->m_y.clear();
212 212 }
213 213
214 214 /*!
215 215 \internal \a pos
216 216 */
217 217 qreal QXYSeries::x(int pos) const
218 218 {
219 219 Q_D(const QXYSeries);
220 220 if (d->m_model) {
221 221 if (d->m_mapOrientation == Qt::Vertical)
222 222 // consecutive data is read from model's column
223 223 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapX), Qt::DisplayRole).toDouble();
224 224 else
225 225 // consecutive data is read from model's row
226 226 return d->m_model->data(d->m_model->index(d->m_mapX, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
227 227 } else {
228 228 // model is not specified, return the data from series' internal data store
229 229 return d->m_x.at(pos);
230 230 }
231 231 }
232 232
233 233 /*!
234 234 \internal \a pos
235 235 */
236 236 qreal QXYSeries::y(int pos) const
237 237 {
238 238 Q_D(const QXYSeries);
239 239 if (d->m_model) {
240 240 if (d->m_mapOrientation == Qt::Vertical)
241 241 // consecutive data is read from model's column
242 242 return d->m_model->data(d->m_model->index(pos + d->m_mapFirst, d->m_mapY), Qt::DisplayRole).toDouble();
243 243 else
244 244 // consecutive data is read from model's row
245 245 return d->m_model->data(d->m_model->index(d->m_mapY, pos + d->m_mapFirst), Qt::DisplayRole).toDouble();
246 246 } else {
247 247 // model is not specified, return the data from series' internal data store
248 248 return d->m_y.at(pos);
249 249 }
250 250 }
251 251
252 252 /*!
253 253 Returns number of data points within series.
254 254 */
255 255 int QXYSeries::count() const
256 256 {
257 257 Q_D(const QXYSeries);
258 258
259 259 Q_ASSERT(d->m_x.size() == d->m_y.size());
260 260
261 261 if (d->m_model) {
262 262 if (d->m_mapOrientation == Qt::Vertical) {
263 263 // data is in a column. Return the number of mapped items if the model's column have enough items
264 264 // or the number of items that can be mapped
265 265 if (d->m_mapLimited)
266 266 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
267 267 else
268 268 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
269 269 } else {
270 270 // data is in a row. Return the number of mapped items if the model's row have enough items
271 271 // or the number of items that can be mapped
272 272 if (d->m_mapLimited)
273 273 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
274 274 else
275 275 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
276 276 }
277 277 }
278 278
279 279 // model is not specified, return the number of points in the series internal data store
280 280 return d->m_x.size();
281 281 }
282 282
283 283 /*!
284 284 Returns the data points of the series.
285 285 */
286 286 QList<QPointF> QXYSeries::data()
287 287 {
288 288 Q_D(QXYSeries);
289 289 QList<QPointF> data;
290 290 for (int i(0); i < d->m_x.count() && i < d->m_y.count(); i++)
291 291 data.append(QPointF(d->m_x.at(i), d->m_y.at(i)));
292 292 return data;
293 293 }
294 294
295 295
296 296 /*!
297 297 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
298 298 pen from chart theme is used.
299 299 \sa QChart::setTheme()
300 300 */
301 301 void QXYSeries::setPen(const QPen &pen)
302 302 {
303 303 Q_D(QXYSeries);
304 304 if (d->m_pen!=pen) {
305 305 d->m_pen = pen;
306 306 emit d->updated();
307 307 }
308 308 }
309 309
310 310 QPen QXYSeries::pen() const
311 311 {
312 312 Q_D(const QXYSeries);
313 313 return d->m_pen;
314 314 }
315 315
316 316 /*!
317 317 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
318 318 from chart theme setting is used.
319 319 \sa QChart::setTheme()
320 320 */
321 321 void QXYSeries::setBrush(const QBrush &brush)
322 322 {
323 323 Q_D(QXYSeries);
324 324 if (d->m_brush!=brush) {
325 325 d->m_brush = brush;
326 326 emit d->updated();
327 327 }
328 328 }
329 329
330 330 QBrush QXYSeries::brush() const
331 331 {
332 332 Q_D(const QXYSeries);
333 333 return d->m_brush;
334 334 }
335 335
336 336
337 337 /*!
338 338 Sets if data points are \a visible and should be drawn on line.
339 339 */
340 340 void QXYSeries::setPointsVisible(bool visible)
341 341 {
342 342 Q_D(QXYSeries);
343 343 if (d->m_pointsVisible != visible){
344 344 d->m_pointsVisible = visible;
345 345 emit d->updated();
346 346 }
347 347 }
348 348
349 349 /*!
350 350 Returns true if drawing the data points of the series is enabled.
351 351 */
352 352 bool QXYSeries::pointsVisible() const
353 353 {
354 354 Q_D(const QXYSeries);
355 355 return d->m_pointsVisible;
356 356 }
357 357
358 358
359 359 /*!
360 360 Stream operator for adding a data \a point to the series.
361 361 \sa append()
362 362 */
363 363 QXYSeries& QXYSeries::operator<< (const QPointF &point)
364 364 {
365 365 append(point);
366 366 return *this;
367 367 }
368 368
369 369
370 370 /*!
371 371 Stream operator for adding a list of \a points to the series.
372 372 \sa append()
373 373 */
374 374
375 375 QXYSeries& QXYSeries::operator<< (const QList<QPointF> points)
376 376 {
377 377 append(points);
378 378 return *this;
379 379 }
380 380
381 381 /*!
382 382 \internal
383 383 */
384 384 void QXYSeries::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
385 385 {
386 386 Q_UNUSED(bottomRight)
387 387 Q_D(QXYSeries);
388 388 if (d->m_mapOrientation == Qt::Vertical) {
389 389 if (topLeft.row() >= d->m_mapFirst && (!d->m_mapLimited || topLeft.row() < d->m_mapFirst + d->m_mapCount))
390 390 emit d->pointReplaced(topLeft.row() - d->m_mapFirst);
391 391 } else {
392 392 if (topLeft.column() >= d->m_mapFirst && (!d->m_mapLimited || topLeft.column() < d->m_mapFirst + d->m_mapCount))
393 393 emit d->pointReplaced(topLeft.column() - d->m_mapFirst);
394 394 }
395 395 }
396 396
397 397 /*!
398 398 \internal
399 399 */
400 400 void QXYSeries::modelDataAboutToBeAdded(QModelIndex parent, int start, int end)
401 401 {
402 402 Q_UNUSED(parent)
403 403 // Q_UNUSED(end)
404 404 Q_D(QXYSeries);
405 405 if (d->m_mapLimited) {
406 406 if (start >= d->m_mapFirst + d->m_mapCount) {
407 407 // the added data is below mapped area
408 408 // therefore it has no relevance
409 409 return;
410 410 } else {
411 411 // the added data is in the mapped area or before it and update is needed
412 412
413 413 // check how many mapped items there is currently (before new items are added)
414 414 // if the number of items currently is equal the m_mapCount then some needs to be removed from xychartitem
415 415 // internal storage before new ones can be added
416 416
417 417 int itemsToRemove = qMin(count() - qMax(start - d->m_mapFirst, 0), end - start + 1);
418 418 if (d->m_mapCount == count()) {
419 419 for (int i = 0; i < itemsToRemove; i++)
420 420 emit d->pointRemoved(qMin(end, count()) - i);
421 421 }
422 422 }
423 423 } else {
424 424 // map is not limited (it includes all the items starting from m_mapFirst till the end of model)
425 425 // nothing to do
426 426 // emit pointAdded(qMax(start - m_mapFirst, 0));
427 427 }
428 428 }
429 429
430 430 /*!
431 431 \internal
432 432 */
433 433 void QXYSeries::modelDataAdded(QModelIndex parent, int start, int end)
434 434 {
435 435 Q_UNUSED(parent)
436 436 // Q_UNUSED(end)
437 437 Q_D(QXYSeries);
438 438 if (d->m_mapLimited) {
439 439 if (start >= d->m_mapFirst + d->m_mapCount) {
440 440 // the added data is below mapped area
441 441 // therefore it has no relevance
442 442 return;
443 443 } else {
444 444 // the added data is in the mapped area or before it
445 445 // update needed
446 446 if (count() > 0) {
447 447 int toBeAdded = qMin(d->m_mapCount - (start - d->m_mapFirst), end - start + 1);
448 448 for (int i = 0; i < toBeAdded; i++)
449 449 if (start + i >= d->m_mapFirst)
450 450 emit d->pointAdded(start + i);
451 451 }
452 452 }
453 453 } else {
454 454 // map is not limited (it included all the items starting from m_mapFirst till the end of model)
455 455 for (int i = 0; i < end - start + 1; i++)
456 456 emit d->pointAdded(start + i);
457 457 }
458 458 }
459 459
460 460 /*!
461 461 \internal
462 462 */
463 463 void QXYSeries::modelDataAboutToBeRemoved(QModelIndex parent, int start, int end)
464 464 {
465 465 Q_UNUSED(parent)
466 466 // Q_UNUSED(end)
467 467 Q_D(QXYSeries);
468 468 if (d->m_mapLimited) {
469 469 if (start >= d->m_mapFirst + d->m_mapCount) {
470 470 // the removed data is below mapped area
471 471 // therefore it has no relevance
472 472 return;
473 473 } else {
474 474 // the removed data is in the mapped area or before it
475 475 // update needed
476 476
477 477 // check how many items need to be removed from the xychartitem storage
478 478 // the number equals the number of items that are removed and that lay before
479 479 // or in the mapped area. Items that lay beyond the map do not count
480 480 // the max is the current number of items in storage (count())
481 481 int itemsToRemove = qMin(count(), qMin(end, d->m_mapFirst + d->m_mapCount - 1) - start + 1);
482 482 for (int i = 0; i < itemsToRemove; i++)
483 483 emit d->pointRemoved(start);
484 484 }
485 485 } else {
486 486 // map is not limited (it included all the items starting from m_mapFirst till the end of model)
487 487 for (int i = 0; i < end - start + 1; i++)
488 488 emit d->pointRemoved(start);
489 489 }
490 490 }
491 491
492 492 /*!
493 493 \internal
494 494 */
495 495 void QXYSeries::modelDataRemoved(QModelIndex parent, int start, int end)
496 496 {
497 497
498 498 Q_UNUSED(parent)
499 499 Q_UNUSED(end)
500 500 Q_D(QXYSeries);
501 501 // how many items there were before data was removed
502 502 // int oldCount = count() - 1;
503 503
504 504 if (d->m_mapLimited) {
505 505 if (start >= d->m_mapFirst + d->m_mapCount) {
506 506 // the removed data is below mapped area
507 507 // therefore it has no relevance
508 508 return;
509 509 } else {
510 510 // if the current items count in the whole model is bigger than the index of the last item
511 511 // that was removed than it means there are some extra items available
512 512
513 513 int removedItemsCount = qMin(count(), qMin(end, d->m_mapFirst + d->m_mapCount - 1) - start + 1);
514 514 int extraItemsAvailable = 0;
515 515 if (d->m_mapOrientation == Qt::Vertical) {
516 516 extraItemsAvailable = qMax(d->m_model->rowCount() + (end - start + 1) - qMax(end + 1, d->m_mapFirst + d->m_mapCount), 0);
517 517 } else {
518 518 extraItemsAvailable = qMax(d->m_model->columnCount() + (end - start + 1) - qMax(end + 1, d->m_mapFirst + d->m_mapCount), 0);
519 519 }
520 520
521 521 // if there are excess items available (below the mapped area) use them to repopulate mapped area
522 522 int toBeAdded = qMin(extraItemsAvailable, removedItemsCount);
523 523 for (int k = 0; k < toBeAdded; k++)
524 524 emit d->pointAdded(d->m_mapFirst + d->m_mapCount - removedItemsCount + k);
525 525 }
526 526 } else {
527 527 // data was removed from XYSeries interal storage. Nothing more to do
528 528 }
529 529 }
530 530
531 531 /*!
532 532 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
533 533 Sets the \a model to be used as a data source
534 534 \sa setModelMapping(), setModelMappingRange()
535 535 */
536 536 bool QXYSeries::setModel(QAbstractItemModel *model)
537 537 {
538 538 Q_D(QXYSeries);
539 539 // disconnect signals from old model
540 540 if (d->m_model) {
541 541 QObject::disconnect(d->m_model, 0, this, 0);
542 542 d->m_mapX = -1;
543 543 d->m_mapY = -1;
544 544 d->m_mapFirst = 0;
545 545 d->m_mapCount = 0;
546 546 d->m_mapLimited = false;
547 547 d->m_mapOrientation = Qt::Vertical;
548 548 }
549 549
550 550 // set new model
551 551 if (model) {
552 552 d->m_model = model;
553 553 return true;
554 554 } else {
555 555 d->m_model = 0;
556 556 return false;
557 557 }
558 558 }
559 559
560 560 /*!
561 561 \fn bool QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
562 562 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
563 as a data source for y coordinate. The \a orientation paramater specifies whether the data
563 as a data source for y coordinate. The \a orientation parameter specifies whether the data
564 564 is in columns or in rows.
565 565 \sa setModel(), setModelMappingRange()
566 566 */
567 567 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
568 568 {
569 569 Q_D(QXYSeries);
570 570 if (d->m_model == 0)
571 571 return;
572 572 d->m_mapX = modelX;
573 573 d->m_mapY = modelY;
574 574 d->m_mapFirst = 0;
575 575 d->m_mapOrientation = orientation;
576 576 if (d->m_mapOrientation == Qt::Vertical) {
577 577 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
578 578 connect(d->m_model,SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(modelDataAboutToBeAdded(QModelIndex,int,int)));
579 579 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
580 580 connect(d->m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(modelDataAboutToBeRemoved(QModelIndex,int,int)));
581 581 connect(d->m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
582 582 } else {
583 583 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelUpdated(QModelIndex,QModelIndex)));
584 584 connect(d->m_model,SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(modelDataAboutToBeAdded(QModelIndex,int,int)));
585 585 connect(d->m_model,SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(modelDataAdded(QModelIndex,int,int)));
586 586 connect(d->m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(modelDataAboutToBeRemoved(QModelIndex,int,int)));
587 587 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(modelDataRemoved(QModelIndex,int,int)));
588 588 }
589 589 }
590 590
591 591 /*!
592 592 \fn bool QXYSeries::setModelMappingRange(int first, int count)
593 593 Allows limiting the model mapping.
594 594 Parameter \a first specifies which element of the model should be used as a first one of the series.
595 595 Parameter \a count specifies how many elements should be mapped. If count is not specified (defaults to -1)
596 596 then all the items following \a first item in a model are used.
597 597 \sa setModel(), setModelMapping()
598 598 */
599 599 void QXYSeries::setModelMappingRange(int first, int count)
600 600 {
601 601 Q_D(QXYSeries);
602 602 d->m_mapFirst = first;
603 603 if (count == 0) {
604 604 d->m_mapLimited = false;
605 605 } else {
606 606 d->m_mapCount = count;
607 607 d->m_mapLimited = true;
608 608 }
609 609 }
610 610
611 611 int QXYSeries::mapFirst() const
612 612 {
613 613 Q_D(const QXYSeries);
614 614 return d->m_mapFirst;
615 615 }
616 616
617 617 int QXYSeries::mapCount() const
618 618 {
619 619 Q_D(const QXYSeries);
620 620 return d->m_mapCount;
621 621 }
622 622
623 623 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
624 624
625 625 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q): QSeriesPrivate(q),
626 626 m_mapX(-1),
627 627 m_mapY(-1),
628 628 m_mapFirst(0),
629 629 m_mapCount(0),
630 630 m_mapLimited(false),
631 631 m_mapOrientation( Qt::Vertical),
632 632 m_pointsVisible(false)
633 633 {
634 634
635 635 }
636 636
637 637 void QXYSeriesPrivate::scaleDomain(Domain& domain)
638 638 {
639 639 qreal minX(domain.minX());
640 640 qreal minY(domain.minY());
641 641 qreal maxX(domain.maxX());
642 642 qreal maxY(domain.maxY());
643 643 int tickXCount(domain.tickXCount());
644 644 int tickYCount(domain.tickYCount());
645 645
646 646 Q_Q(QXYSeries);
647 647 for (int i = 0; i < q->count(); i++)
648 648 {
649 649 qreal x = q->x(i);
650 650 qreal y = q->y(i);
651 651 minX = qMin(minX, x);
652 652 minY = qMin(minY, y);
653 653 maxX = qMax(maxX, x);
654 654 maxY = qMax(maxY, y);
655 655 }
656 656
657 657 domain.setRangeX(minX,maxX,tickXCount);
658 658 domain.setRangeY(minY,maxY,tickYCount);
659 659 }
660 660
661 661 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
662 662 {
663 663 Q_Q(QXYSeries);
664 664 QList<LegendMarker*> list;
665 665 return list << new XYLegendMarker(q,legend);
666 666 }
667 667
668 668 #include "moc_qxyseries.cpp"
669 669 #include "moc_qxyseries_p.cpp"
670 670
671 671 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,538 +1,570
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2012 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include <QtTest/QtTest>
22 22 #include <qchartaxis.h>
23 23 #include <qlineseries.h>
24 24 #include <private/chartdataset_p.h>
25 25 #include <private/domain_p.h>
26 26
27 27 QTCOMMERCIALCHART_USE_NAMESPACE
28 28
29 29 Q_DECLARE_METATYPE(Domain*)
30 30 Q_DECLARE_METATYPE(QChartAxis*)
31 31 Q_DECLARE_METATYPE(QSeries*)
32 32 Q_DECLARE_METATYPE(QLineSeries*)
33 33
34 34 class tst_ChartDataSet: public QObject {
35 35
36 36 Q_OBJECT
37 37
38 38 public Q_SLOTS:
39 39 void initTestCase();
40 40 void cleanupTestCase();
41 41 void init();
42 42 void cleanup();
43 43
44 44 private Q_SLOTS:
45 45 void chartdataset_data();
46 46 void chartdataset();
47 47 void addSeries_data();
48 48 void addSeries();
49 49 void removeSeries_data();
50 50 void removeSeries();
51 51 void removeAllSeries_data();
52 52 void removeAllSeries();
53 53 void axisY_data();
54 54 void axisY();
55 55 void seriesCount_data();
56 56 void seriesCount();
57 57 void seriesIndex_data();
58 58 void seriesIndex();
59 59 void domain_data();
60 60 void domain();
61 61 void zoomInDomain_data();
62 62 void zoomInDomain();
63 63 void zoomOutDomain_data();
64 64 void zoomOutDomain();
65 65 void scrollDomain_data();
66 66 void scrollDomain();
67 67 };
68 68
69 69 void tst_ChartDataSet::initTestCase()
70 70 {
71 71 qRegisterMetaType<Domain*>();
72 72 qRegisterMetaType<QChartAxis*>();
73 73 qRegisterMetaType<QSeries*>();
74 74 }
75 75
76 76 void tst_ChartDataSet::cleanupTestCase()
77 77 {
78 78 }
79 79
80 80 void tst_ChartDataSet::init()
81 81 {
82 82 }
83 83
84 84 void tst_ChartDataSet::cleanup()
85 85 {
86 86 }
87 87
88 88 void tst_ChartDataSet::chartdataset_data()
89 89 {
90 90 }
91 91
92 92 void tst_ChartDataSet::chartdataset()
93 93 {
94 94 ChartDataSet dataSet;
95 95 QVERIFY2(dataSet.axisX(), "Missing axisX.");
96 96 QVERIFY2(dataSet.axisY(), "Missing axisY.");
97 97 //check if not dangling pointer
98 98 dataSet.axisX()->objectName();
99 99 dataSet.axisY()->objectName();
100 100 QLineSeries* series = new QLineSeries(this);
101 101 QCOMPARE(dataSet.seriesIndex(series),-1);
102 102 }
103 103
104 104 void tst_ChartDataSet::addSeries_data()
105 105 {
106 106 QTest::addColumn<QLineSeries*>("series0");
107 107 QTest::addColumn<QChartAxis*>("axis0");
108 108 QTest::addColumn<QLineSeries*>("series1");
109 109 QTest::addColumn<QChartAxis*>("axis1");
110 110 QTest::addColumn<QLineSeries*>("series2");
111 111 QTest::addColumn<QChartAxis*>("axis2");
112 112 QTest::addColumn<int>("axisCount");
113 113
114 114 QLineSeries* series0 = new QLineSeries(this);
115 115 QLineSeries* series1 = new QLineSeries(this);
116 116 QLineSeries* series2 = new QLineSeries(this);
117 117
118 118 QChartAxis* axis0 = new QChartAxis(this);
119 119 QChartAxis* axis1 = new QChartAxis(this);
120 120 QChartAxis* axis2 = new QChartAxis(this);
121 121
122 122 QTest::newRow("default axis Y: series0,series1,series2") << series0 << (QChartAxis*)0 << series1 << (QChartAxis*)0 << series2 << (QChartAxis*)0 << 2;
123 123 QTest::newRow("default axis Y: series0, axis 0: series1,series2") << series0 << (QChartAxis*)0 << series1 << axis0 << series2 << axis0 << 3;
124 124 QTest::newRow("axis0: series0, axis1: series1, axis2: series2") << series0 << axis0 << series1 << axis1 << series2 << axis2 << 4;
125 125 }
126 126
127 127 void tst_ChartDataSet::addSeries()
128 128 {
129 129 QFETCH(QLineSeries*, series0);
130 130 QFETCH(QChartAxis*, axis0);
131 131 QFETCH(QLineSeries*, series1);
132 132 QFETCH(QChartAxis*, axis1);
133 133 QFETCH(QLineSeries*, series2);
134 134 QFETCH(QChartAxis*, axis2);
135 135 QFETCH(int, axisCount);
136 136
137 137 ChartDataSet dataSet;
138 138
139 139 QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*)));
140 140 QSignalSpy spy1(&dataSet, SIGNAL(axisRemoved(QChartAxis*)));
141 141 QSignalSpy spy2(&dataSet, SIGNAL(seriesAdded(QSeries*,Domain*)));
142 142 QSignalSpy spy3(&dataSet, SIGNAL(seriesRemoved(QSeries*)));
143 143
144 144 dataSet.addSeries(series0,axis0);
145 145 dataSet.addSeries(series1,axis1);
146 146 dataSet.addSeries(series2,axis2);
147 147
148 148 QCOMPARE(spy0.count(), axisCount);
149 149 QCOMPARE(spy1.count(), 0);
150 150 QCOMPARE(spy2.count(), 3);
151 151 QCOMPARE(spy3.count(), 0);
152 152
153 if(axis0==0) axis0 = dataSet.axisY();
154 if(axis1==0) axis1 = dataSet.axisY();
155 if(axis2==0) axis2 = dataSet.axisY();
156
157 QVERIFY(axis0 == dataSet.removeSeries(series0));
158 QVERIFY(axis1 == dataSet.removeSeries(series1));
159 QVERIFY(axis2 == dataSet.removeSeries(series2));
153 160 }
154 161
155 162 void tst_ChartDataSet::removeSeries_data()
156 163 {
157 164 addSeries_data();
158 165 }
159 166
160 167 void tst_ChartDataSet::removeSeries()
161 168 {
162 169 QFETCH(QLineSeries*, series0);
163 170 QFETCH(QChartAxis*, axis0);
164 171 QFETCH(QLineSeries*, series1);
165 172 QFETCH(QChartAxis*, axis1);
166 173 QFETCH(QLineSeries*, series2);
167 174 QFETCH(QChartAxis*, axis2);
168 175 QFETCH(int, axisCount);
169 176
170 177 ChartDataSet dataSet;
171 178
172 179 dataSet.addSeries(series0,axis0);
173 180 dataSet.addSeries(series1,axis1);
174 181 dataSet.addSeries(series2,axis2);
175 182
176 183 QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*)));
177 184 QSignalSpy spy1(&dataSet, SIGNAL(axisRemoved(QChartAxis*)));
178 185 QSignalSpy spy2(&dataSet, SIGNAL(seriesAdded(QSeries*,Domain*)));
179 186 QSignalSpy spy3(&dataSet, SIGNAL(seriesRemoved(QSeries*)));
180 187
181 188 dataSet.removeSeries(series0);
182 189 dataSet.removeSeries(series1);
183 190 dataSet.removeSeries(series2);
184 191
185 192 QCOMPARE(spy0.count(), 0);
186 193 QCOMPARE(spy1.count(), axisCount);
187 194 QCOMPARE(spy2.count(), 0);
188 195 QCOMPARE(spy3.count(), 3);
189 196 }
190 197
191 198 void tst_ChartDataSet::removeAllSeries_data()
192 199 {
193 addSeries_data();
200
194 201 }
195 202
196 203 void tst_ChartDataSet::removeAllSeries()
197 204 {
198 QFETCH(QLineSeries*, series0);
199 QFETCH(QChartAxis*, axis0);
200 QFETCH(QLineSeries*, series1);
201 QFETCH(QChartAxis*, axis1);
202 QFETCH(QLineSeries*, series2);
203 QFETCH(QChartAxis*, axis2);
204 QFETCH(int, axisCount);
205
206 ChartDataSet dataSet;
207
208 dataSet.addSeries(series0,axis0);
209 dataSet.addSeries(series1,axis1);
210 dataSet.addSeries(series2,axis2);
211
212 QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*)));
213 QSignalSpy spy1(&dataSet, SIGNAL(axisRemoved(QChartAxis*)));
214 QSignalSpy spy2(&dataSet, SIGNAL(seriesAdded(QSeries*,Domain*)));
215 QSignalSpy spy3(&dataSet, SIGNAL(seriesRemoved(QSeries*)));
216
217 dataSet.removeAllSeries();
218
219 QCOMPARE(spy0.count(), 0);
220 QCOMPARE(spy1.count(), axisCount);
221 QCOMPARE(spy2.count(), 0);
222 QCOMPARE(spy3.count(), 3);
205 QLineSeries* series0 = new QLineSeries(this);
206 QLineSeries* series1 = new QLineSeries(this);
207 QLineSeries* series2 = new QLineSeries(this);
208
209 QChartAxis* axis0 = new QChartAxis(this);
210 QChartAxis* axis1 = new QChartAxis(this);
211 QChartAxis* axis2 = new QChartAxis(this);
212
213
214 ChartDataSet dataSet;
215
216 dataSet.addSeries(series0, axis0);
217 dataSet.addSeries(series1, axis1);
218 dataSet.addSeries(series2, axis2);
219
220 QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*)));
221 QSignalSpy spy1(&dataSet, SIGNAL(axisRemoved(QChartAxis*)));
222 QSignalSpy spy2(&dataSet, SIGNAL(seriesAdded(QSeries*,Domain*)));
223 QSignalSpy spy3(&dataSet, SIGNAL(seriesRemoved(QSeries*)));
224
225 dataSet.removeAllSeries();
226
227 QCOMPARE(spy0.count(), 0);
228 QCOMPARE(spy1.count(), 4);
229 QCOMPARE(spy2.count(), 0);
230 QCOMPARE(spy3.count(), 3);
223 231 }
224 232
225 233
226 234 void tst_ChartDataSet::axisY_data()
227 235 {
228 236 QTest::addColumn<QChartAxis*>("axis0");
229 237 QTest::addColumn<QChartAxis*>("axis1");
230 238 QTest::addColumn<QChartAxis*>("axis2");
231 239 QTest::newRow("1 defualt, 2 optional") << (QChartAxis*)0 << new QChartAxis() << new QChartAxis();
232 240 QTest::newRow("3 optional") << new QChartAxis() << new QChartAxis() << new QChartAxis();
233 241 }
234 242
235 243 void tst_ChartDataSet::axisY()
236 244 {
237 245 QFETCH(QChartAxis*, axis0);
238 246 QFETCH(QChartAxis*, axis1);
239 247 QFETCH(QChartAxis*, axis2);
240 248
241 249 ChartDataSet dataSet;
242 250
243 251 QChartAxis* defaultAxisY = dataSet.axisY();
244 252
245 253 QVERIFY2(defaultAxisY, "Missing axisY.");
246 254
247 255 QLineSeries* series0 = new QLineSeries();
248 256 dataSet.addSeries(series0,axis0);
249 257
250 258 QLineSeries* series1 = new QLineSeries();
251 259 dataSet.addSeries(series1,axis1);
252 260
253 261 QLineSeries* series2 = new QLineSeries();
254 262 dataSet.addSeries(series2,axis2);
255 263
256 264 if(!axis0) axis0=defaultAxisY ;
257 265 if(!axis1) axis1=defaultAxisY ;
258 266 if(!axis2) axis2=defaultAxisY ;
259 267
260 268 QVERIFY(dataSet.axisY(series0) == axis0);
261 269 QVERIFY(dataSet.axisY(series1) == axis1);
262 270 QVERIFY(dataSet.axisY(series2) == axis2);
263 271
264 272 }
265 273
266 274 void tst_ChartDataSet::seriesCount_data()
267 275 {
268 276 addSeries_data();
269 277 }
270 278
271 279 void tst_ChartDataSet::seriesCount()
272 280 {
273 281 QFETCH(QLineSeries*, series0);
274 282 QFETCH(QChartAxis*, axis0);
275 283 QFETCH(QLineSeries*, series1);
276 284 QFETCH(QChartAxis*, axis1);
277 285 QFETCH(QLineSeries*, series2);
278 286 QFETCH(QChartAxis*, axis2);
279 287 QFETCH(int, axisCount);
280 288 Q_UNUSED(axisCount);
281 289
282 290 ChartDataSet dataSet;
283 291
284 292 dataSet.addSeries(series0, axis0);
285 293 dataSet.addSeries(series1, axis1);
286 294 dataSet.addSeries(series2, axis2);
287 295
288 296 QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*)));
289 297 QSignalSpy spy1(&dataSet, SIGNAL(axisRemoved(QChartAxis*)));
290 298 QSignalSpy spy2(&dataSet, SIGNAL(seriesAdded(QSeries*,Domain*)));
291 299 QSignalSpy spy3(&dataSet, SIGNAL(seriesRemoved(QSeries*)));
292 300
293 301 QCOMPARE(dataSet.seriesCount(series0->type()),3);
294 302 QCOMPARE(spy0.count(), 0);
295 303 QCOMPARE(spy1.count(), 0);
296 304 QCOMPARE(spy2.count(), 0);
297 305 QCOMPARE(spy3.count(), 0);
306
307 dataSet.removeSeries(series0);
308 dataSet.removeSeries(series1);
309 dataSet.removeSeries(series2);
298 310 }
299 311
300 312 void tst_ChartDataSet::seriesIndex_data()
301 313 {
302 314 addSeries_data();
303 315 }
304 316
305 317 void tst_ChartDataSet::seriesIndex()
306 318 {
307 319 //TODO: rewrite this series_index_data to match better
308 320
309 321 QFETCH(QLineSeries*, series0);
310 322 QFETCH(QChartAxis*, axis0);
311 323 QFETCH(QLineSeries*, series1);
312 324 QFETCH(QChartAxis*, axis1);
313 325 QFETCH(QLineSeries*, series2);
314 326 QFETCH(QChartAxis*, axis2);
315 327 QFETCH(int, axisCount);
316 328 Q_UNUSED(axisCount);
317 329
318 330 ChartDataSet dataSet;
319 331
320 332 dataSet.addSeries(series0, axis0);
321 333 dataSet.addSeries(series1, axis1);
322 334 dataSet.addSeries(series2, axis2);
323 335
324 336 QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*)));
325 337 QSignalSpy spy1(&dataSet, SIGNAL(axisRemoved(QChartAxis*)));
326 338 QSignalSpy spy2(&dataSet, SIGNAL(seriesAdded(QSeries*,Domain*)));
327 339 QSignalSpy spy3(&dataSet, SIGNAL(seriesRemoved(QSeries*)));
328 340
329 341 QCOMPARE(dataSet.seriesIndex(series0),0);
330 342 QCOMPARE(dataSet.seriesIndex(series1),1);
331 343 QCOMPARE(dataSet.seriesIndex(series2),2);
332 344
333 345 QCOMPARE(spy0.count(), 0);
334 346 QCOMPARE(spy1.count(), 0);
335 347 QCOMPARE(spy2.count(), 0);
336 348 QCOMPARE(spy3.count(), 0);
337 349
338 350 dataSet.removeSeries(series0);
339 351 dataSet.removeSeries(series1);
340 352 dataSet.removeSeries(series2);
341 353
342 354 QCOMPARE(dataSet.seriesIndex(series0),-1);
343 355 QCOMPARE(dataSet.seriesIndex(series1),-1);
344 356 QCOMPARE(dataSet.seriesIndex(series2),-1);
345 357
346 358 dataSet.addSeries(series0, axis0);
347 359 dataSet.addSeries(series1, axis1);
348 360 dataSet.addSeries(series2, axis2);
349 361
350 362 QCOMPARE(dataSet.seriesIndex(series0),0);
351 363 QCOMPARE(dataSet.seriesIndex(series1),1);
352 364 QCOMPARE(dataSet.seriesIndex(series2),2);
353 365
354 366 dataSet.removeSeries(series1);
355 367
356 368 QCOMPARE(dataSet.seriesIndex(series0),0);
357 369 QCOMPARE(dataSet.seriesIndex(series1),-1);
358 370 QCOMPARE(dataSet.seriesIndex(series2),2);
359 371
360 372 dataSet.addSeries(series1, axis1);
361 373 QCOMPARE(dataSet.seriesIndex(series0),0);
362 374 QCOMPARE(dataSet.seriesIndex(series1),1);
363 375 QCOMPARE(dataSet.seriesIndex(series2),2);
364 376
365 377 dataSet.removeSeries(series2);
366 378 QCOMPARE(dataSet.seriesIndex(series0),0);
367 379 QCOMPARE(dataSet.seriesIndex(series1),1);
368 380 QCOMPARE(dataSet.seriesIndex(series2),-1);
369 381
370 382 dataSet.removeSeries(series0);
371 383 QCOMPARE(dataSet.seriesIndex(series0),-1);
372 384 QCOMPARE(dataSet.seriesIndex(series1),1);
373 385 QCOMPARE(dataSet.seriesIndex(series2),-1);
374 386
375 387 dataSet.addSeries(series2);
376 388 QCOMPARE(dataSet.seriesIndex(series0),-1);
377 389 QCOMPARE(dataSet.seriesIndex(series1),1);
378 390 QCOMPARE(dataSet.seriesIndex(series2),0);
379 391
380 392 dataSet.addSeries(series0);
381 393 QCOMPARE(dataSet.seriesIndex(series0),2);
382 394 QCOMPARE(dataSet.seriesIndex(series1),1);
383 395 QCOMPARE(dataSet.seriesIndex(series2),0);
384 396
397 dataSet.removeSeries(series0);
398 dataSet.removeSeries(series1);
399 dataSet.removeSeries(series2);
400
385 401 }
386 402
387 403 void tst_ChartDataSet::domain_data()
388 404 {
389 405 addSeries_data();
390 406 }
391 407
392 408 void tst_ChartDataSet::domain()
393 409 {
394 410 QFETCH(QLineSeries*, series0);
395 411 QFETCH(QChartAxis*, axis0);
396 412 QFETCH(QLineSeries*, series1);
397 413 QFETCH(QChartAxis*, axis1);
398 414 QFETCH(QLineSeries*, series2);
399 415 QFETCH(QChartAxis*, axis2);
400 416 QFETCH(int, axisCount);
401 417 Q_UNUSED(axisCount);
402 418
403 419 ChartDataSet dataSet;
404 420
405 421 dataSet.addSeries(series0, axis0);
406 422 dataSet.addSeries(series1, axis1);
407 423 dataSet.addSeries(series2, axis2);
408 424
409 425 QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*)));
410 426 QSignalSpy spy1(&dataSet, SIGNAL(axisRemoved(QChartAxis*)));
411 427 QSignalSpy spy2(&dataSet, SIGNAL(seriesAdded(QSeries*,Domain*)));
412 428 QSignalSpy spy3(&dataSet, SIGNAL(seriesRemoved(QSeries*)));
413 429
414 430 QVERIFY(dataSet.domain(axis0)==dataSet.domain(series0));
415 431 QVERIFY(dataSet.domain(axis1)==dataSet.domain(series1));
416 432 QVERIFY(dataSet.domain(axis2)==dataSet.domain(series2));
417 433 QCOMPARE(spy0.count(), 0);
418 434 QCOMPARE(spy1.count(), 0);
419 435 QCOMPARE(spy2.count(), 0);
420 436 QCOMPARE(spy3.count(), 0);
437
438 dataSet.removeSeries(series0);
439 dataSet.removeSeries(series1);
440 dataSet.removeSeries(series2);
421 441 }
422 442
423 443 void tst_ChartDataSet::zoomInDomain_data()
424 444 {
425 445 addSeries_data();
426 446 }
427 447
428 448 void tst_ChartDataSet::zoomInDomain()
429 449 {
430 450 QFETCH(QLineSeries*, series0);
431 451 QFETCH(QChartAxis*, axis0);
432 452 QFETCH(QLineSeries*, series1);
433 453 QFETCH(QChartAxis*, axis1);
434 454 QFETCH(QLineSeries*, series2);
435 455 QFETCH(QChartAxis*, axis2);
436 456 QFETCH(int, axisCount);
437 457
438 458 Q_UNUSED(axisCount);
439 459 ChartDataSet dataSet;
440 460
441 461 dataSet.addSeries(series0, axis0);
442 462 dataSet.addSeries(series1, axis1);
443 463 dataSet.addSeries(series2, axis2);
444 464
445 465 Domain* domain0 = dataSet.domain(series0);
446 466 Domain* domain1 = dataSet.domain(series1);
447 467 Domain* domain2 = dataSet.domain(series2);
448 468
449 469 QSignalSpy spy0(domain0, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
450 470 QSignalSpy spy1(domain1, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
451 471 QSignalSpy spy2(domain2, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
452 472
453 473 dataSet.zoomInDomain(QRect(0,0,100,100),QSize(1000,1000));
454 474
455 475 QCOMPARE(spy0.count(), 1);
456 476 QCOMPARE(spy1.count(), 1);
457 477 QCOMPARE(spy2.count(), 1);
478
479 dataSet.removeSeries(series0);
480 dataSet.removeSeries(series1);
481 dataSet.removeSeries(series2);
458 482 }
459 483
460 484 void tst_ChartDataSet::zoomOutDomain_data()
461 485 {
462 486 addSeries_data();
463 487 }
464 488
465 489 void tst_ChartDataSet::zoomOutDomain()
466 490 {
467 491 QFETCH(QLineSeries*, series0);
468 492 QFETCH(QChartAxis*, axis0);
469 493 QFETCH(QLineSeries*, series1);
470 494 QFETCH(QChartAxis*, axis1);
471 495 QFETCH(QLineSeries*, series2);
472 496 QFETCH(QChartAxis*, axis2);
473 497 QFETCH(int, axisCount);
474 498
475 499 Q_UNUSED(axisCount);
476 500
477 501 ChartDataSet dataSet;
478 502
479 503 dataSet.addSeries(series0, axis0);
480 504 dataSet.addSeries(series1, axis1);
481 505 dataSet.addSeries(series2, axis2);
482 506
483 507 Domain* domain0 = dataSet.domain(series0);
484 508 Domain* domain1 = dataSet.domain(series1);
485 509 Domain* domain2 = dataSet.domain(series2);
486 510
487 511 QSignalSpy spy0(domain0, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
488 512 QSignalSpy spy1(domain1, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
489 513 QSignalSpy spy2(domain2, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
490 514
491 515 dataSet.zoomOutDomain(QRect(0,0,100,100),QSize(1000,1000));
492 516
493 517 QCOMPARE(spy0.count(), 1);
494 518 QCOMPARE(spy1.count(), 1);
495 519 QCOMPARE(spy2.count(), 1);
520
521 dataSet.removeSeries(series0);
522 dataSet.removeSeries(series1);
523 dataSet.removeSeries(series2);
496 524 }
497 525
498 526 void tst_ChartDataSet::scrollDomain_data()
499 527 {
500 528 addSeries_data();
501 529 }
502 530
503 531 void tst_ChartDataSet::scrollDomain()
504 532 {
505 533 QFETCH(QLineSeries*, series0);
506 534 QFETCH(QChartAxis*, axis0);
507 535 QFETCH(QLineSeries*, series1);
508 536 QFETCH(QChartAxis*, axis1);
509 537 QFETCH(QLineSeries*, series2);
510 538 QFETCH(QChartAxis*, axis2);
511 539 QFETCH(int, axisCount);
512 540
513 541 Q_UNUSED(axisCount);
514 542
515 543 ChartDataSet dataSet;
516 544
517 545 dataSet.addSeries(series0, axis0);
518 546 dataSet.addSeries(series1, axis1);
519 547 dataSet.addSeries(series2, axis2);
520 548
521 549 Domain* domain0 = dataSet.domain(series0);
522 550 Domain* domain1 = dataSet.domain(series1);
523 551 Domain* domain2 = dataSet.domain(series2);
524 552
525 553 QSignalSpy spy0(domain0, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
526 554 QSignalSpy spy1(domain1, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
527 555 QSignalSpy spy2(domain2, SIGNAL(domainChanged(qreal,qreal,qreal,qreal)));
528 556
529 557 dataSet.scrollDomain(10,10,QSize(1000,1000));
530 558
531 559 QCOMPARE(spy0.count(), 1);
532 560 QCOMPARE(spy1.count(), 1);
533 561 QCOMPARE(spy2.count(), 1);
562
563 dataSet.removeSeries(series0);
564 dataSet.removeSeries(series1);
565 dataSet.removeSeries(series2);
534 566 }
535 567
536 568 QTEST_MAIN(tst_ChartDataSet)
537 569 #include "tst_chartdataset.moc"
538 570
@@ -1,570 +1,572
1 1 #include <QtTest/QtTest>
2 2 #include <qchartview.h>
3 3 #include <qlineseries.h>
4 4 #include <qareaseries.h>
5 5 #include <qscatterseries.h>
6 6 #include <qsplineseries.h>
7 7 #include <qpieseries.h>
8 8 #include <qbarseries.h>
9 9 #include <qpercentbarseries.h>
10 10 #include <qstackedbarseries.h>
11 11
12 12 QTCOMMERCIALCHART_USE_NAMESPACE
13 13
14 14 Q_DECLARE_METATYPE(QChartAxis*)
15 15 Q_DECLARE_METATYPE(QSeries*)
16 16 Q_DECLARE_METATYPE(QChart::AnimationOption)
17 17 Q_DECLARE_METATYPE(QBrush)
18 18 Q_DECLARE_METATYPE(QPen)
19 19 Q_DECLARE_METATYPE(QChart::ChartTheme)
20 20
21 21 class tst_QChart : public QObject
22 22 {
23 23 Q_OBJECT
24 24
25 25 public slots:
26 26 void initTestCase();
27 27 void cleanupTestCase();
28 28 void init();
29 29 void cleanup();
30 30
31 31 private slots:
32 32 void qchart_data();
33 33 void qchart();
34 34
35 35 void addSeries_data();
36 36 void addSeries();
37 37 void animationOptions_data();
38 38 void animationOptions();
39 39 void axisX_data();
40 40 void axisX();
41 41 void axisY_data();
42 42 void axisY();
43 43 void backgroundBrush_data();
44 44 void backgroundBrush();
45 45 void backgroundPen_data();
46 46 void backgroundPen();
47 47 void isBackgroundVisible_data();
48 48 void isBackgroundVisible();
49 49 void legend_data();
50 50 void legend();
51 51 void margins_data();
52 52 void margins();
53 53 void removeAllSeries_data();
54 54 void removeAllSeries();
55 55 void removeSeries_data();
56 56 void removeSeries();
57 57 void scrollDown_data();
58 58 void scrollDown();
59 59 void scrollLeft_data();
60 60 void scrollLeft();
61 61 void scrollRight_data();
62 62 void scrollRight();
63 63 void scrollUp_data();
64 64 void scrollUp();
65 65 void theme_data();
66 66 void theme();
67 67 void title_data();
68 68 void title();
69 69 void titleBrush_data();
70 70 void titleBrush();
71 71 void titleFont_data();
72 72 void titleFont();
73 73 void zoomIn_data();
74 74 void zoomIn();
75 75 void zoomOut_data();
76 76 void zoomOut();
77 77
78 78 private:
79 79 void createTestData();
80 80
81 81 private:
82 82 QChartView* m_view;
83 83 QChart* m_chart;
84 84 };
85 85
86 86 void tst_QChart::initTestCase()
87 87 {
88 88
89 89 }
90 90
91 91 void tst_QChart::cleanupTestCase()
92 92 {
93 93
94 94 }
95 95
96 96 void tst_QChart::init()
97 97 {
98 98 m_view = new QChartView(new QChart());
99 99 m_chart = m_view->chart();
100 100 }
101 101
102 102 void tst_QChart::createTestData()
103 103 {
104 104 QLineSeries* series0 = new QLineSeries(this);
105 105 *series0 << QPointF(0, 0) << QPointF(100, 100);
106 106 m_chart->addSeries(series0);
107 107 m_view->show();
108 108 QTest::qWaitForWindowShown(m_view);
109 109 }
110 110
111 111 void tst_QChart::cleanup()
112 112 {
113 113 delete m_view;
114 114 m_view = 0;
115 115 m_chart = 0;
116 116 }
117 117
118 118 void tst_QChart::qchart_data()
119 119 {
120 120 }
121 121
122 122 void tst_QChart::qchart()
123 123 {
124 124 QVERIFY(m_chart);
125 125 QVERIFY(m_chart->legend());
126 126 QVERIFY(!m_chart->legend()->isVisible());
127 127
128 128 QCOMPARE(m_chart->animationOptions(), QChart::NoAnimation);
129 129 QVERIFY(m_chart->axisX());
130 130 QVERIFY(m_chart->axisY());
131 131 QVERIFY(m_chart->backgroundBrush()!=QBrush());
132 132 QVERIFY(m_chart->backgroundPen()!=QPen());
133 133 QCOMPARE(m_chart->isBackgroundVisible(), true);
134 134
135 135 QVERIFY(m_chart->margins().top()>0);
136 136 QVERIFY(m_chart->margins().left()>0);
137 137 QVERIFY(m_chart->margins().right()>0);
138 138 QVERIFY(m_chart->margins().bottom()>0);
139 139
140 140 QCOMPARE(m_chart->theme(), QChart::ChartThemeLight);
141 141 QCOMPARE(m_chart->title(), QString());
142 142
143 143 //QCOMPARE(m_chart->titleBrush(),QBrush());
144 144 //QCOMPARE(m_chart->titleFont(),QFont());
145 145
146 146 m_chart->removeAllSeries();
147 147 m_chart->scrollDown();
148 148 m_chart->scrollLeft();
149 149 m_chart->scrollRight();
150 150 m_chart->scrollUp();
151 151
152 152 m_chart->zoomIn();
153 153 m_chart->zoomIn(QRectF());
154 154 m_chart->zoomOut();
155 155 }
156 156
157 157 void tst_QChart::addSeries_data()
158 158 {
159 159 QTest::addColumn<QSeries*>("series");
160 160 QTest::addColumn<QChartAxis*>("axis");
161 161
162 162 QSeries* series0 = new QLineSeries(this);
163 163 QSeries* series1 = new QAreaSeries(static_cast<QLineSeries*>(series0));
164 164 QSeries* series2 = new QScatterSeries(this);
165 165 QSeries* series3 = new QSplineSeries(this);
166 166 QSeries* series4 = new QPieSeries(this);
167 167 QSeries* series5 = new QBarSeries(QBarCategories(),this);
168 168 QSeries* series6 = new QPercentBarSeries(QBarCategories(),this);
169 169 QSeries* series7 = new QStackedBarSeries(QBarCategories(),this);
170 170
171 171 QChartAxis* axis = new QChartAxis(this);
172 172
173 173 QTest::newRow("default axis: lineSeries") << series0 << (QChartAxis*) 0;
174 174 QTest::newRow("axis0: lineSeries") << series0 << axis;
175 175 QTest::newRow("default axis: areaSeries") << series1 << (QChartAxis*) 0;
176 176 QTest::newRow("axis: areaSeries") << series1 << axis;
177 177 QTest::newRow("default axis: scatterSeries") << series2 << (QChartAxis*) 0;
178 178 QTest::newRow("axis1: scatterSeries") << series2 << axis;
179 179 QTest::newRow("default axis: splineSeries") << series3 << (QChartAxis*) 0;
180 180 QTest::newRow("axis: splineSeries") << series3 << axis;
181 181 QTest::newRow("default axis: pieSeries") << series4 << (QChartAxis*) 0;
182 182 QTest::newRow("axis: pieSeries") << series4 << axis;
183 183 QTest::newRow("default axis: barSeries") << series5 << (QChartAxis*) 0;
184 184 QTest::newRow("axis: barSeries") << series5 << axis;
185 185 QTest::newRow("default axis: percentBarSeries") << series6 << (QChartAxis*) 0;
186 186 QTest::newRow("axis: barSeries") << series6 << axis;
187 187 QTest::newRow("default axis: stackedBarSeries") << series7 << (QChartAxis*) 0;
188 188 QTest::newRow("axis: barSeries") << series7 << axis;
189 189
190 190 }
191 191
192 192 void tst_QChart::addSeries()
193 193 {
194 194 QFETCH(QSeries*, series);
195 195 QFETCH(QChartAxis*, axis);
196 196 m_view->show();
197 197 QTest::qWaitForWindowShown(m_view);
198 198 if(!axis) axis = m_chart->axisY();
199 199 m_chart->addSeries(series,axis);
200 200 QCOMPARE(m_chart->axisY(series),axis);
201 m_chart->removeSeries(series);
202
201 203 }
202 204
203 205 void tst_QChart::animationOptions_data()
204 206 {
205 207 QTest::addColumn<QChart::AnimationOption>("animationOptions");
206 208 QTest::newRow("AllAnimations") << QChart::AllAnimations;
207 209 QTest::newRow("NoAnimation") << QChart::NoAnimation;
208 210 QTest::newRow("GridAxisAnimations") << QChart::GridAxisAnimations;
209 211 QTest::newRow("SeriesAnimations") << QChart::SeriesAnimations;
210 212 }
211 213
212 214 void tst_QChart::animationOptions()
213 215 {
214 216 createTestData();
215 217 QFETCH(QChart::AnimationOption, animationOptions);
216 218 m_chart->setAnimationOptions(animationOptions);
217 219 QCOMPARE(m_chart->animationOptions(), animationOptions);
218 220 }
219 221
220 222 void tst_QChart::axisX_data()
221 223 {
222 224
223 225 }
224 226
225 227 void tst_QChart::axisX()
226 228 {
227 229 QVERIFY(m_chart->axisX());
228 230 QChartAxis* axis = m_chart->axisX();
229 231 createTestData();
230 232 //it should be the same axis
231 233 QCOMPARE(axis,m_chart->axisX());
232 234 }
233 235
234 236 void tst_QChart::axisY_data()
235 237 {
236 238 QTest::addColumn<QChartAxis*>("axis0");
237 239 QTest::addColumn<QChartAxis*>("axis1");
238 240 QTest::addColumn<QChartAxis*>("axis2");
239 241 QTest::newRow("1 defualt, 2 optional") << (QChartAxis*)0 << new QChartAxis() << new QChartAxis();
240 242 QTest::newRow("3 optional") << new QChartAxis() << new QChartAxis() << new QChartAxis();
241 243 }
242 244
243 245
244 246 void tst_QChart::axisY()
245 247 {
246 248 QFETCH(QChartAxis*, axis0);
247 249 QFETCH(QChartAxis*, axis1);
248 250 QFETCH(QChartAxis*, axis2);
249 251
250 252 QChartAxis* defaultAxisY = m_chart->axisY();
251 253
252 254 QVERIFY2(defaultAxisY, "Missing axisY.");
253 255
254 256 QLineSeries* series0 = new QLineSeries();
255 257 m_chart->addSeries(series0, axis0);
256 258
257 259 QLineSeries* series1 = new QLineSeries();
258 260 m_chart->addSeries(series1, axis1);
259 261
260 262 QLineSeries* series2 = new QLineSeries();
261 263 m_chart->addSeries(series2, axis2);
262 264
263 265 if (!axis0)
264 266 axis0 = defaultAxisY;
265 267 if (!axis1)
266 268 axis1 = defaultAxisY;
267 269 if (!axis2)
268 270 axis2 = defaultAxisY;
269 271
270 272 QVERIFY(m_chart->axisY(series0) == axis0);
271 273 QVERIFY(m_chart->axisY(series1) == axis1);
272 274 QVERIFY(m_chart->axisY(series2) == axis2);
273 275 }
274 276
275 277 void tst_QChart::backgroundBrush_data()
276 278 {
277 279 QTest::addColumn<QBrush>("backgroundBrush");
278 280 QTest::newRow("null") << QBrush();
279 281 QTest::newRow("blue") << QBrush(Qt::blue);
280 282 QTest::newRow("white") << QBrush(Qt::white);
281 283 QTest::newRow("black") << QBrush(Qt::black);
282 284 }
283 285
284 286 void tst_QChart::backgroundBrush()
285 287 {
286 288 QFETCH(QBrush, backgroundBrush);
287 289 m_chart->setBackgroundBrush(backgroundBrush);
288 290 QCOMPARE(m_chart->backgroundBrush(), backgroundBrush);
289 291 }
290 292
291 293 void tst_QChart::backgroundPen_data()
292 294 {
293 295 QTest::addColumn<QPen>("backgroundPen");
294 296 QTest::newRow("null") << QPen();
295 297 QTest::newRow("blue") << QPen(Qt::blue);
296 298 QTest::newRow("white") << QPen(Qt::white);
297 299 QTest::newRow("black") << QPen(Qt::black);
298 300 }
299 301
300 302
301 303 void tst_QChart::backgroundPen()
302 304 {
303 305 QFETCH(QPen, backgroundPen);
304 306 m_chart->setBackgroundPen(backgroundPen);
305 307 QCOMPARE(m_chart->backgroundPen(), backgroundPen);
306 308 }
307 309
308 310 void tst_QChart::isBackgroundVisible_data()
309 311 {
310 312 QTest::addColumn<bool>("isBackgroundVisible");
311 313 QTest::newRow("true") << true;
312 314 QTest::newRow("false") << false;
313 315 }
314 316
315 317 void tst_QChart::isBackgroundVisible()
316 318 {
317 319 QFETCH(bool, isBackgroundVisible);
318 320 m_chart->setBackgroundVisible(isBackgroundVisible);
319 321 QCOMPARE(m_chart->isBackgroundVisible(), isBackgroundVisible);
320 322
321 323 }
322 324
323 325 void tst_QChart::legend_data()
324 326 {
325 327
326 328 }
327 329
328 330 void tst_QChart::legend()
329 331 {
330 332 QVERIFY(m_chart->legend());
331 333 }
332 334
333 335 void tst_QChart::margins_data()
334 336 {
335 337
336 338 }
337 339
338 340 void tst_QChart::margins()
339 341 {QTest::addColumn<int>("seriesCount");
340 342 QTest::newRow("0") << 0;
341 343 QTest::newRow("-1") << -1;
342 344 createTestData();
343 345 QRectF rect = m_chart->geometry();
344 346
345 347 QVERIFY(m_chart->margins().top()+m_chart->margins().bottom() < rect.height());
346 348 QVERIFY(m_chart->margins().left()+m_chart->margins().right() < rect.width());
347 349
348 350 }
349 351
350 352 void tst_QChart::removeAllSeries_data()
351 353 {
352 354
353 355 }
354 356
355 357 void tst_QChart::removeAllSeries()
356 358 {
357 359 QLineSeries* series0 = new QLineSeries(this);
358 360 QLineSeries* series1 = new QLineSeries(this);
359 361 QLineSeries* series2 = new QLineSeries(this);
360 362
361 363 m_chart->addSeries(series0);
362 364 m_chart->addSeries(series1);
363 365 m_chart->addSeries(series2);
364 366 m_view->show();
365 367 QTest::qWaitForWindowShown(m_view);
366 368
367 369 QVERIFY(m_chart->axisY(series0)!=0);
368 370 QVERIFY(m_chart->axisY(series1)!=0);
369 371 QVERIFY(m_chart->axisY(series2)!=0);
370 372
371 373 m_chart->removeAllSeries();
372 374
373 375 QVERIFY(m_chart->axisY(series0)==0);
374 376 QVERIFY(m_chart->axisY(series1)==0);
375 377 QVERIFY(m_chart->axisY(series2)==0);
376 378 }
377 379
378 380 void tst_QChart::removeSeries_data()
379 381 {
380 382 addSeries_data();
381 383 }
382 384
383 385 void tst_QChart::removeSeries()
384 386 {
385 387 QFETCH(QSeries*, series);
386 388 QFETCH(QChartAxis*, axis);
387 389 m_view->show();
388 390 QTest::qWaitForWindowShown(m_view);
389 391 if(!axis) axis = m_chart->axisY();
390 392 m_chart->addSeries(series,axis);
391 393 QCOMPARE(m_chart->axisY(series),axis);
392 394 m_chart->removeSeries(series);
393 395 QVERIFY(m_chart->axisY(series)==0);
394 396 }
395 397
396 398 void tst_QChart::scrollDown_data()
397 399 {
398 400
399 401 }
400 402
401 403 void tst_QChart::scrollDown()
402 404 {
403 405 createTestData();
404 406 qreal min = m_chart->axisY()->min();
405 407 m_chart->scrollDown();
406 408 QVERIFY(m_chart->axisY()->min()<min);
407 409 }
408 410
409 411 void tst_QChart::scrollLeft_data()
410 412 {
411 413
412 414 }
413 415
414 416 void tst_QChart::scrollLeft()
415 417 {
416 418 createTestData();
417 419 qreal min = m_chart->axisX()->min();
418 420 m_chart->scrollLeft();
419 421 QVERIFY(m_chart->axisX()->min()<min);
420 422 }
421 423
422 424 void tst_QChart::scrollRight_data()
423 425 {
424 426
425 427 }
426 428
427 429 void tst_QChart::scrollRight()
428 430 {
429 431 createTestData();
430 432 qreal min = m_chart->axisX()->min();
431 433 m_chart->scrollRight();
432 434 QVERIFY(m_chart->axisX()->min()>min);
433 435 }
434 436
435 437 void tst_QChart::scrollUp_data()
436 438 {
437 439
438 440 }
439 441
440 442 void tst_QChart::scrollUp()
441 443 {
442 444 createTestData();
443 445 qreal min = m_chart->axisY()->min();
444 446 m_chart->scrollUp();
445 447 QVERIFY(m_chart->axisY()->min()>min);
446 448 }
447 449
448 450 void tst_QChart::theme_data()
449 451 {
450 452 QTest::addColumn<QChart::ChartTheme>("theme");
451 453 QTest::newRow("ChartThemeBlueCerulean") << QChart::ChartThemeBlueCerulean;
452 454 QTest::newRow("ChartThemeBlueIcy") << QChart::ChartThemeBlueIcy;
453 455 QTest::newRow("ChartThemeBlueNcs") << QChart::ChartThemeBlueNcs;
454 456 QTest::newRow("ChartThemeBrownSand") << QChart::ChartThemeBrownSand;
455 457 QTest::newRow("ChartThemeDark") << QChart::ChartThemeDark;
456 458 QTest::newRow("hartThemeHighContrast") << QChart::ChartThemeHighContrast;
457 459 QTest::newRow("ChartThemeLight") << QChart::ChartThemeLight;
458 460 }
459 461
460 462 void tst_QChart::theme()
461 463 {
462 464 QFETCH(QChart::ChartTheme, theme);
463 465 createTestData();
464 466 m_chart->setTheme(theme);
465 467 QVERIFY(m_chart->theme()==theme);
466 468 }
467 469
468 470 void tst_QChart::title_data()
469 471 {
470 472 QTest::addColumn<QString>("title");
471 473 QTest::newRow("null") << QString();
472 474 QTest::newRow("foo") << QString("foo");
473 475 }
474 476
475 477 void tst_QChart::title()
476 478 {
477 479 QFETCH(QString, title);
478 480 m_chart->setTitle(title);
479 481 QCOMPARE(m_chart->title(), title);
480 482 }
481 483
482 484 void tst_QChart::titleBrush_data()
483 485 {
484 486 QTest::addColumn<QBrush>("titleBrush");
485 487 QTest::newRow("null") << QBrush();
486 488 QTest::newRow("blue") << QBrush(Qt::blue);
487 489 QTest::newRow("white") << QBrush(Qt::white);
488 490 QTest::newRow("black") << QBrush(Qt::black);
489 491 }
490 492
491 493 void tst_QChart::titleBrush()
492 494 {
493 495 QFETCH(QBrush, titleBrush);
494 496 m_chart->setTitleBrush(titleBrush);
495 497 QCOMPARE(m_chart->titleBrush(), titleBrush);
496 498 }
497 499
498 500 void tst_QChart::titleFont_data()
499 501 {
500 502 QTest::addColumn<QFont>("titleFont");
501 503 QTest::newRow("null") << QFont();
502 504 QTest::newRow("courier") << QFont("Courier", 8, QFont::Bold, true);
503 505 }
504 506
505 507 void tst_QChart::titleFont()
506 508 {
507 509 QFETCH(QFont, titleFont);
508 510 m_chart->setTitleFont(titleFont);
509 511 QCOMPARE(m_chart->titleFont(), titleFont);
510 512 }
511 513
512 514 void tst_QChart::zoomIn_data()
513 515 {
514 516 QTest::addColumn<QRectF>("rect");
515 517 QTest::newRow("null") << QRectF();
516 518 QTest::newRow("100x100") << QRectF(10,10,100,100);
517 519 QTest::newRow("200x200") << QRectF(10,10,200,200);
518 520 }
519 521
520 522
521 523 void tst_QChart::zoomIn()
522 524 {
523 525 QFETCH(QRectF, rect);
524 526 createTestData();
525 527 QRectF marigns = m_chart->margins();
526 528 rect.adjust(marigns.left(),marigns.top(),-marigns.right(),-marigns.bottom());
527 529 qreal minX = m_chart->axisX()->min();
528 530 qreal minY = m_chart->axisY()->min();
529 531 qreal maxX = m_chart->axisX()->max();
530 532 qreal maxY = m_chart->axisY()->max();
531 533 m_chart->zoomIn(rect);
532 534 if(rect.isValid()){
533 535 QVERIFY(minX<m_chart->axisX()->min());
534 536 QVERIFY(maxX>m_chart->axisX()->max());
535 537 QVERIFY(minY<m_chart->axisY()->min());
536 538 QVERIFY(maxY>m_chart->axisY()->max());
537 539 }
538 540 }
539 541
540 542 void tst_QChart::zoomOut_data()
541 543 {
542 544
543 545 }
544 546
545 547 void tst_QChart::zoomOut()
546 548 {
547 549 createTestData();
548 550 qreal minX = m_chart->axisX()->min();
549 551 qreal minY = m_chart->axisY()->min();
550 552 qreal maxX = m_chart->axisX()->max();
551 553 qreal maxY = m_chart->axisY()->max();
552 554
553 555 m_chart->zoomIn();
554 556
555 557 QVERIFY(minX<m_chart->axisX()->min());
556 558 QVERIFY(maxX>m_chart->axisX()->max());
557 559 QVERIFY(minY<m_chart->axisY()->min());
558 560 QVERIFY(maxY>m_chart->axisY()->max());
559 561
560 562 m_chart->zoomOut();
561 563
562 564 QVERIFY(minX==m_chart->axisX()->min());
563 565 QVERIFY(maxX==m_chart->axisX()->max());
564 566 QVERIFY(minY==m_chart->axisY()->min());
565 567 QVERIFY(maxY==m_chart->axisY()->max());
566 568 }
567 569
568 570 QTEST_MAIN(tst_QChart)
569 571 #include "tst_qchart.moc"
570 572
General Comments 0
You need to be logged in to leave comments. Login now