@@ -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; |
|
|
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; |
|
|
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; |
|
|
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(); |
|
|
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( |
|
|
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( |
|
|
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 multi |
|
|
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 param |
|
|
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 multi |
|
|
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 multi |
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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 |
|
|
|
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( |
|
|
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( |
|
|
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 min |
|
|
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 param |
|
|
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 param |
|
|
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 param |
|
|
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 |
|
|
|
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 |
|
|
|
210 |
|
|
|
211 | ||
|
212 | QSignalSpy spy0(&dataSet, SIGNAL(axisAdded(QChartAxis*,Domain*))); | |
|
213 |
|
|
|
214 |
|
|
|
215 |
|
|
|
216 | ||
|
217 | dataSet.removeAllSeries(); | |
|
218 | ||
|
219 | QCOMPARE(spy0.count(), 0); | |
|
220 |
|
|
|
221 |
|
|
|
222 |
|
|
|
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