##// END OF EJS Templates
Fix xy series model issues due to API changes
Michal Klocek -
r1059:c23240068c61
parent child
Show More
@@ -1,286 +1,286
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qareaseries.h"
21 #include "qareaseries.h"
22 #include "qareaseries_p.h"
22 #include "qareaseries_p.h"
23 #include "qlineseries.h"
23 #include "qlineseries.h"
24 #include "areachartitem_p.h"
24 #include "areachartitem_p.h"
25 #include "legendmarker_p.h"
25 #include "legendmarker_p.h"
26 #include "domain_p.h"
26 #include "domain_p.h"
27 #include "chartdataset_p.h"
27 #include "chartdataset_p.h"
28 #include "charttheme_p.h"
28 #include "charttheme_p.h"
29 #include "chartanimator_p.h"
29 #include "chartanimator_p.h"
30
30
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
32
33 /*!
33 /*!
34 \class QAreaSeries
34 \class QAreaSeries
35 \brief The QAreaSeries class is used for making area charts.
35 \brief The QAreaSeries class is used for making area charts.
36
36
37 \mainclass
37 \mainclass
38
38
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
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 is emphasized with color. Since the area chart is based on line chart, QAreaSeries constructor needs QLineSeries instance,
40 is emphasized with color. Since the area chart is based on line chart, QAreaSeries constructor needs QLineSeries instance,
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.
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 In that case QAreaSeries should be initiated with two QLineSerie instances. Please note terms "upper" and "lower" boundary can be misleading in cases
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 where "lower" boundary had bigger values than the "upper" one, however the main point that area between these two boundary lines will be filled.
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 See the \l {AreaChart Example} {area chart example} to learn how to create a simple area chart.
45 See the \l {AreaChart Example} {area chart example} to learn how to create a simple area chart.
46 \image examples_areachart.png
46 \image examples_areachart.png
47 */
47 */
48
48
49 /*!
49 /*!
50 \fn virtual QSeriesType QAreaSeries::type() const
50 \fn virtual QSeriesType QAreaSeries::type() const
51 \brief Returns type of series.
51 \brief Returns type of series.
52 \sa QAbstractSeries, QSeriesType
52 \sa QAbstractSeries, QSeriesType
53 */
53 */
54
54
55 /*!
55 /*!
56 \fn QLineSeries* QAreaSeries::upperSeries() const
56 \fn QLineSeries* QAreaSeries::upperSeries() const
57 \brief Returns upperSeries used to define one of area boundaries.
57 \brief Returns upperSeries used to define one of area boundaries.
58 */
58 */
59
59
60 /*!
60 /*!
61 \fn QLineSeries* QAreaSeries::lowerSeries() const
61 \fn QLineSeries* QAreaSeries::lowerSeries() const
62 \brief Returns lowerSeries used to define one of area boundaries. Note if QAreaSeries where counstucted wihtout a\ lowerSeries
62 \brief Returns lowerSeries used to define one of area boundaries. Note if QAreaSeries where counstucted wihtout a\ lowerSeries
63 this function return Null pointer.
63 this function return Null pointer.
64 */
64 */
65
65
66 /*!
66 /*!
67 \fn QPen QAreaSeries::pen() const
67 \fn QPen QAreaSeries::pen() const
68 \brief Returns the pen used to draw line for this series.
68 \brief Returns the pen used to draw line for this series.
69 \sa setPen()
69 \sa setPen()
70 */
70 */
71
71
72 /*!
72 /*!
73 \fn QPen QAreaSeries::brush() const
73 \fn QPen QAreaSeries::brush() const
74 \brief Returns the brush used to draw line for this series.
74 \brief Returns the brush used to draw line for this series.
75 \sa setBrush()
75 \sa setBrush()
76 */
76 */
77
77
78 /*!
78 /*!
79 \fn bool QAreaSeries::pointsVisible() const
79 \fn bool QAreaSeries::pointsVisible() const
80 \brief Returns if the points are drawn for this series.
80 \brief Returns if the points are drawn for this series.
81 \sa setPointsVisible()
81 \sa setPointsVisible()
82 */
82 */
83
83
84 /*!
84 /*!
85 \fn void QAreaSeries::clicked(const QPointF& point)
85 \fn void QAreaSeries::clicked(const QPointF& point)
86 \brief Signal is emitted when user clicks the \a point on area chart.
86 \brief Signal is emitted when user clicks the \a point on area chart.
87 */
87 */
88
88
89 /*!
89 /*!
90 \fn void QAreaSeries::selected()
90 \fn void QAreaSeries::selected()
91
91
92 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
92 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
93 implemented by the user of QAreaSeries API.
93 implemented by the user of QAreaSeries API.
94 */
94 */
95
95
96 /*!
96 /*!
97 \fn void QAreaSeriesPrivate::updated()
97 \fn void QAreaSeriesPrivate::updated()
98 \brief \internal
98 \brief \internal
99 */
99 */
100
100
101 /*!
101 /*!
102 Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a
102 Constructs area series object which is a child of \a upperSeries. Area will be spanned between \a
103 upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead.
103 upperSeries line and \a lowerSeries line. If no \a lowerSeries is passed to constructor, area is specified by axis x (y=0) instead.
104 When series object is added to QChartView or QChart instance ownerships is transferred.
104 When series object is added to QChartView or QChart instance ownerships is transferred.
105 */
105 */
106 QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries)
106 QAreaSeries::QAreaSeries(QLineSeries *upperSeries, QLineSeries *lowerSeries)
107 : QAbstractSeries(*new QAreaSeriesPrivate(upperSeries,lowerSeries,this),upperSeries)
107 : QAbstractSeries(*new QAreaSeriesPrivate(upperSeries,lowerSeries,this),upperSeries)
108 {
108 {
109 }
109 }
110
110
111 /*!
111 /*!
112 Destroys the object. Series added to QChartView or QChart instances are owned by those,
112 Destroys the object. Series added to QChartView or QChart instances are owned by those,
113 and are deleted when mentioned object are destroyed.
113 and are deleted when mentioned object are destroyed.
114 */
114 */
115 QAreaSeries::~QAreaSeries()
115 QAreaSeries::~QAreaSeries()
116 {
116 {
117 }
117 }
118
118
119
119
120 QAbstractSeries::QSeriesType QAreaSeries::type() const
120 QAbstractSeries::QSeriesType QAreaSeries::type() const
121 {
121 {
122 return QAbstractSeries::SeriesTypeArea;
122 return QAbstractSeries::SeriesTypeArea;
123 }
123 }
124
124
125 QLineSeries* QAreaSeries::upperSeries() const
125 QLineSeries* QAreaSeries::upperSeries() const
126 {
126 {
127 Q_D(const QAreaSeries);
127 Q_D(const QAreaSeries);
128 return d->m_upperSeries;
128 return d->m_upperSeries;
129 }
129 }
130
130
131 QLineSeries* QAreaSeries::lowerSeries() const
131 QLineSeries* QAreaSeries::lowerSeries() const
132 {
132 {
133 Q_D(const QAreaSeries);
133 Q_D(const QAreaSeries);
134 return d->m_lowerSeries;
134 return d->m_lowerSeries;
135 }
135 }
136
136
137 /*!
137 /*!
138 Sets \a pen used for drawing area outline.
138 Sets \a pen used for drawing area outline.
139 */
139 */
140 void QAreaSeries::setPen(const QPen &pen)
140 void QAreaSeries::setPen(const QPen &pen)
141 {
141 {
142 Q_D(QAreaSeries);
142 Q_D(QAreaSeries);
143 if (d->m_pen != pen) {
143 if (d->m_pen != pen) {
144 d->m_pen = pen;
144 d->m_pen = pen;
145 emit d->updated();
145 emit d->updated();
146 }
146 }
147 }
147 }
148
148
149 QPen QAreaSeries::pen() const
149 QPen QAreaSeries::pen() const
150 {
150 {
151 Q_D(const QAreaSeries);
151 Q_D(const QAreaSeries);
152 return d->m_pen;
152 return d->m_pen;
153 }
153 }
154
154
155 /*!
155 /*!
156 Sets \a brush used for filling the area.
156 Sets \a brush used for filling the area.
157 */
157 */
158 void QAreaSeries::setBrush(const QBrush &brush)
158 void QAreaSeries::setBrush(const QBrush &brush)
159 {
159 {
160 Q_D(QAreaSeries);
160 Q_D(QAreaSeries);
161 if (d->m_brush != brush) {
161 if (d->m_brush != brush) {
162 d->m_brush = brush;
162 d->m_brush = brush;
163 emit d->updated();
163 emit d->updated();
164 }
164 }
165 }
165 }
166
166
167 QBrush QAreaSeries::brush() const
167 QBrush QAreaSeries::brush() const
168 {
168 {
169 Q_D(const QAreaSeries);
169 Q_D(const QAreaSeries);
170 return d->m_brush;
170 return d->m_brush;
171 }
171 }
172 /*!
172 /*!
173 Sets if data points are \a visible and should be drawn on line.
173 Sets if data points are \a visible and should be drawn on line.
174 */
174 */
175 void QAreaSeries::setPointsVisible(bool visible)
175 void QAreaSeries::setPointsVisible(bool visible)
176 {
176 {
177 Q_D(QAreaSeries);
177 Q_D(QAreaSeries);
178 if (d->m_pointsVisible != visible) {
178 if (d->m_pointsVisible != visible) {
179 d->m_pointsVisible = visible;
179 d->m_pointsVisible = visible;
180 emit d->updated();
180 emit d->updated();
181 }
181 }
182 }
182 }
183
183
184 bool QAreaSeries::pointsVisible() const
184 bool QAreaSeries::pointsVisible() const
185 {
185 {
186 Q_D(const QAreaSeries);
186 Q_D(const QAreaSeries);
187 return d->m_pointsVisible;
187 return d->m_pointsVisible;
188 }
188 }
189
189
190 /*!
190 /*!
191 Does nothing at present. Paremeter \a model is not used. Always returns false.
191 Does nothing at present. Paremeter \a model is not used. Always returns false.
192 To set the model for area series set the models for upperSeries, lowerSeries
192 To set the model for area series set the models for upperSeries, lowerSeries
193 */
193 */
194 bool QAreaSeries::setModel(QAbstractItemModel* model)
194 bool QAreaSeries::setModel(QAbstractItemModel* model)
195 {
195 {
196 Q_UNUSED(model);
196 Q_UNUSED(model);
197 qWarning()<<"Not implemented";
197 qWarning()<<"Not implemented";
198 return false;
198 return false;
199 }
199 }
200
200
201 /*!
201 /*!
202 Does nothing at present. Always returns 0;
202 Does nothing at present. Always returns 0;
203 To get the model set for area series call upperSeries->model(), lowerSeries->model()
203 To get the model set for area series call upperSeries->model(), lowerSeries->model()
204 */
204 */
205 QAbstractItemModel* QAreaSeries::model() const
205 QAbstractItemModel* QAreaSeries::model() const
206 {
206 {
207 return 0;
207 return 0;
208 }
208 }
209
209
210 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
210 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
211
211
212 QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries,QAreaSeries* q) :
212 QAreaSeriesPrivate::QAreaSeriesPrivate(QLineSeries *upperSeries, QLineSeries *lowerSeries,QAreaSeries* q) :
213 QAbstractSeriesPrivate(q),
213 QAbstractSeriesPrivate(q),
214 m_upperSeries(upperSeries),
214 m_upperSeries(upperSeries),
215 m_lowerSeries(lowerSeries),
215 m_lowerSeries(lowerSeries),
216 m_pointsVisible(false)
216 m_pointsVisible(false)
217 {
217 {
218 }
218 }
219
219
220 void QAreaSeriesPrivate::scaleDomain(Domain& domain)
220 void QAreaSeriesPrivate::scaleDomain(Domain& domain)
221 {
221 {
222 Q_Q(QAreaSeries);
222 Q_Q(QAreaSeries);
223
223
224 qreal minX(domain.minX());
224 qreal minX(domain.minX());
225 qreal minY(domain.minY());
225 qreal minY(domain.minY());
226 qreal maxX(domain.maxX());
226 qreal maxX(domain.maxX());
227 qreal maxY(domain.maxY());
227 qreal maxY(domain.maxY());
228 int tickXCount(domain.tickXCount());
228 int tickXCount(domain.tickXCount());
229 int tickYCount(domain.tickYCount());
229 int tickYCount(domain.tickYCount());
230
230
231 QLineSeries* upperSeries = q->upperSeries();
231 QLineSeries* upperSeries = q->upperSeries();
232 QLineSeries* lowerSeries = q->lowerSeries();
232 QLineSeries* lowerSeries = q->lowerSeries();
233
233
234 const QList<QPointF>& points = upperSeries->points();
234 const QList<QPointF>& points = upperSeries->points();
235
235
236 for (int i = 0; i < points.count(); i++)
236 for (int i = 0; i < points.count(); i++)
237 {
237 {
238 qreal x = points[i].x();
238 qreal x = points[i].x();
239 qreal y = points[i].y();
239 qreal y = points[i].y();
240 minX = qMin(minX, x);
240 minX = qMin(minX, x);
241 minY = qMin(minY, y);
241 minY = qMin(minY, y);
242 maxX = qMax(maxX, x);
242 maxX = qMax(maxX, x);
243 maxY = qMax(maxY, y);
243 maxY = qMax(maxY, y);
244 }
244 }
245 if(lowerSeries) {
245 if(lowerSeries) {
246
246
247 const QList<QPointF>& points = upperSeries->points();
247 const QList<QPointF>& points = lowerSeries->points();
248
248
249 for (int i = 0; i < points.count(); i++)
249 for (int i = 0; i < points.count(); i++)
250 {
250 {
251 qreal x = points[i].x();
251 qreal x = points[i].x();
252 qreal y = points[i].y();
252 qreal y = points[i].y();
253 minX = qMin(minX, x);
253 minX = qMin(minX, x);
254 minY = qMin(minY, y);
254 minY = qMin(minY, y);
255 maxX = qMax(maxX, x);
255 maxX = qMax(maxX, x);
256 maxY = qMax(maxY, y);
256 maxY = qMax(maxY, y);
257 }}
257 }}
258
258
259 domain.setRangeX(minX,maxX,tickXCount);
259 domain.setRangeX(minX,maxX,tickXCount);
260 domain.setRangeY(minY,maxY,tickYCount);
260 domain.setRangeY(minY,maxY,tickYCount);
261 }
261 }
262
262
263 Chart* QAreaSeriesPrivate::createGraphics(ChartPresenter* presenter)
263 Chart* QAreaSeriesPrivate::createGraphics(ChartPresenter* presenter)
264 {
264 {
265 Q_Q(QAreaSeries);
265 Q_Q(QAreaSeries);
266
266
267 AreaChartItem* area = new AreaChartItem(q,presenter);
267 AreaChartItem* area = new AreaChartItem(q,presenter);
268 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
268 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
269 presenter->animator()->addAnimation(area->upperLineItem());
269 presenter->animator()->addAnimation(area->upperLineItem());
270 if(q->lowerSeries()) presenter->animator()->addAnimation(area->lowerLineItem());
270 if(q->lowerSeries()) presenter->animator()->addAnimation(area->lowerLineItem());
271 }
271 }
272 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
272 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
273 return area;
273 return area;
274 }
274 }
275
275
276 QList<LegendMarker*> QAreaSeriesPrivate::createLegendMarker(QLegend* legend)
276 QList<LegendMarker*> QAreaSeriesPrivate::createLegendMarker(QLegend* legend)
277 {
277 {
278 Q_Q(QAreaSeries);
278 Q_Q(QAreaSeries);
279 QList<LegendMarker*> list;
279 QList<LegendMarker*> list;
280 return list << new AreaLegendMarker(q,legend);
280 return list << new AreaLegendMarker(q,legend);
281 }
281 }
282
282
283 #include "moc_qareaseries.cpp"
283 #include "moc_qareaseries.cpp"
284 #include "moc_qareaseries_p.cpp"
284 #include "moc_qareaseries_p.cpp"
285
285
286 QTCOMMERCIALCHART_END_NAMESPACE
286 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,224 +1,228
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qsplineseries.h"
21 #include "qsplineseries.h"
22 #include "qsplineseries_p.h"
22 #include "qsplineseries_p.h"
23 #include "splinechartitem_p.h"
23 #include "splinechartitem_p.h"
24 #include "chartdataset_p.h"
24 #include "chartdataset_p.h"
25 #include "charttheme_p.h"
25 #include "charttheme_p.h"
26 #include "chartanimator_p.h"
26 #include "chartanimator_p.h"
27
27
28 /*!
28 /*!
29 \class QSplineSeries
29 \class QSplineSeries
30 \brief Series type used to store data needed to draw a spline.
30 \brief Series type used to store data needed to draw a spline.
31
31
32 QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
32 QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
33 Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn.
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 \image examples_splinechart.png
35 \image examples_splinechart.png
36
36
37 Creating basic spline chart is simple:
37 Creating basic spline chart is simple:
38 \code
38 \code
39 QSplineSeries* series = new QSplineSeries();
39 QSplineSeries* series = new QSplineSeries();
40 series->append(0, 6);
40 series->append(0, 6);
41 series->append(2, 4);
41 series->append(2, 4);
42 ...
42 ...
43 chart->addSeries(series);
43 chart->addSeries(series);
44 \endcode
44 \endcode
45 */
45 */
46
46
47 /*!
47 /*!
48 \fn QSeriesType QSplineSeries::type() const
48 \fn QSeriesType QSplineSeries::type() const
49 Returns the type of the series
49 Returns the type of the series
50 */
50 */
51
51
52 /*!
52 /*!
53 \fn QSeriesType QSplineSeries::controlPoint(int index) const
53 \fn QSeriesType QSplineSeries::controlPoint(int index) const
54 Returns the control point specified by \a index
54 Returns the control point specified by \a index
55 */
55 */
56
56
57 QTCOMMERCIALCHART_BEGIN_NAMESPACE
57 QTCOMMERCIALCHART_BEGIN_NAMESPACE
58
58
59 /*!
59 /*!
60 Constructs empty series object which is a child of \a parent.
60 Constructs empty series object which is a child of \a parent.
61 When series object is added to QChartView or QChart instance then the ownerships is transferred.
61 When series object is added to QChartView or QChart instance then the ownerships is transferred.
62 */
62 */
63
63
64 QSplineSeries::QSplineSeries(QObject *parent) :
64 QSplineSeries::QSplineSeries(QObject *parent) :
65 QLineSeries(*new QSplineSeriesPrivate(this),parent)
65 QLineSeries(*new QSplineSeriesPrivate(this),parent)
66 {
66 {
67 }
67 }
68
68
69 QAbstractSeries::QSeriesType QSplineSeries::type() const
69 QAbstractSeries::QSeriesType QSplineSeries::type() const
70 {
70 {
71 return QAbstractSeries::SeriesTypeSpline;
71 return QAbstractSeries::SeriesTypeSpline;
72 }
72 }
73
73
74 QPointF QSplineSeries::controlPoint(int index) const
74 QPointF QSplineSeries::controlPoint(int index) const
75 {
75 {
76 Q_D(const QSplineSeries);
76 Q_D(const QSplineSeries);
77 return d->m_controlPoints[index];
77 return d->m_controlPoints[index];
78 }
78 }
79
79
80 /*!
80 /*!
81 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
81 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
82 as a data source for y coordinate. The \a orientation parameter specifies whether the data
82 as a data source for y coordinate. The \a orientation parameter specifies whether the data
83 is in columns or in rows.
83 is in columns or in rows.
84 \sa setModel()
84 \sa setModel()
85 */
85 */
86 void QSplineSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
86 void QSplineSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
87 {
87 {
88 Q_D(QSplineSeries);
88 Q_D(QSplineSeries);
89 QXYSeries::setModelMapping(modelX, modelY, orientation);
89 QXYSeries::setModelMapping(modelX, modelY, orientation);
90 d->calculateControlPoints();
90 d->updateControlPoints();
91 }
91 }
92
92
93 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94
94
95 QSplineSeriesPrivate::QSplineSeriesPrivate(QSplineSeries* q):QLineSeriesPrivate(q)
95 QSplineSeriesPrivate::QSplineSeriesPrivate(QSplineSeries* q):QLineSeriesPrivate(q)
96 {
96 {
97 QObject::connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints()));
97 QObject::connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints()));
98 QObject::connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints()));
98 QObject::connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints()));
99 QObject::connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints()));
99 QObject::connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints()));
100 };
100 };
101
101
102 /*!
102 /*!
103 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
103 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
104 */
104 */
105 void QSplineSeriesPrivate::calculateControlPoints()
105 void QSplineSeriesPrivate::calculateControlPoints()
106 {
106 {
107 Q_Q(QSplineSeries);
108
109 const QList<QPointF>& points = q->points();
107
110
108 int n = m_points.count() - 1;
111 int n = points.count() - 1;
109
112
110 if (n == 1)
113 if (n == 1)
111 {
114 {
112 //for n==1
115 //for n==1
113 m_controlPoints[0].setX((2 * m_points[0].x() + m_points[1].x()) / 3);
116 m_controlPoints[0].setX((2 * points[0].x() + points[1].x()) / 3);
114 m_controlPoints[0].setY((2 * m_points[0].y() + m_points[1].y()) / 3);
117 m_controlPoints[0].setY((2 * points[0].y() + points[1].y()) / 3);
115 m_controlPoints[1].setX(2 * m_controlPoints[0].x() - m_points[0].x());
118 m_controlPoints[1].setX(2 * m_controlPoints[0].x() - points[0].x());
116 m_controlPoints[1].setY(2 * m_controlPoints[0].y() - m_points[0].y());
119 m_controlPoints[1].setY(2 * m_controlPoints[0].y() - points[0].y());
117 return;
120 return;
118 }
121 }
119
122
120 // Calculate first Bezier control points
123 // Calculate first Bezier control points
121 // Right hand side vector
124 // Right hand side vector
122 // Set of equations for P0 to Pn points.
125 // Set of equations for P0 to Pn points.
123 //
126 //
124 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
127 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
125 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
128 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
126 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
129 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
127 // | . . . . . . . . . . . . | | ... | | ... |
130 // | . . . . . . . . . . . . | | ... | | ... |
128 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
131 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
129 // | . . . . . . . . . . . . | | ... | | ... |
132 // | . . . . . . . . . . . . | | ... | | ... |
130 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
133 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
131 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
134 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
132 //
135 //
133 QVector<qreal> vector;
136 QVector<qreal> vector;
134 vector.resize(n);
137 vector.resize(n);
135
138
136 vector[0] = m_points[0].x() + 2 * m_points[1].x();
139 vector[0] = points[0].x() + 2 * points[1].x();
137
140
138
141
139 for (int i = 1; i < n - 1; ++i){
142 for (int i = 1; i < n - 1; ++i){
140 vector[i] = 4 * m_points[i].x() + 2 * m_points[i + 1].x();
143 vector[i] = 4 * points[i].x() + 2 * points[i + 1].x();
141 }
144 }
142
145
143 vector[n - 1] = (8 * m_points[n-1].x() + m_points[n].x()) / 2.0;
146 vector[n - 1] = (8 * points[n-1].x() + points[n].x()) / 2.0;
144
147
145 QVector<qreal> xControl = firstControlPoints(vector);
148 QVector<qreal> xControl = firstControlPoints(vector);
146
149
147 vector[0] = m_points[0].y() + 2 * m_points[1].y();
150 vector[0] = points[0].y() + 2 * points[1].y();
148
151
149 for (int i = 1; i < n - 1; ++i) {
152 for (int i = 1; i < n - 1; ++i) {
150 vector[i] = 4 * m_points[i].y() + 2 * m_points[i + 1].y();
153 vector[i] = 4 * points[i].y() + 2 * points[i + 1].y();
151 }
154 }
152
155
153 vector[n - 1] = (8 * m_points[n-1].y() + m_points[n].y()) / 2.0;
156 vector[n - 1] = (8 * points[n-1].y() + points[n].y()) / 2.0;
154
157
155 QVector<qreal> yControl = firstControlPoints(vector);
158 QVector<qreal> yControl = firstControlPoints(vector);
156
159
157 for (int i = 0,j =0; i < n; ++i, ++j) {
160 for (int i = 0,j =0; i < n; ++i, ++j) {
158
161
159 m_controlPoints[j].setX(xControl[i]);
162 m_controlPoints[j].setX(xControl[i]);
160 m_controlPoints[j].setY(yControl[i]);
163 m_controlPoints[j].setY(yControl[i]);
161
164
162 j++;
165 j++;
163
166
164 if (i < n - 1){
167 if (i < n - 1){
165 m_controlPoints[j].setX(2 * m_points[i+1].x() - xControl[i + 1]);
168 m_controlPoints[j].setX(2 * points[i+1].x() - xControl[i + 1]);
166 m_controlPoints[j].setY(2 * m_points[i+1].y() - yControl[i + 1]);
169 m_controlPoints[j].setY(2 * points[i+1].y() - yControl[i + 1]);
167 }else{
170 }else{
168 m_controlPoints[j].setX((m_points[n].x() + xControl[n - 1]) / 2);
171 m_controlPoints[j].setX((points[n].x() + xControl[n - 1]) / 2);
169 m_controlPoints[j].setY((m_points[n].y() + yControl[n - 1]) / 2);
172 m_controlPoints[j].setY((points[n].y() + yControl[n - 1]) / 2);
170 }
173 }
171 }
174 }
172 }
175 }
173
176
174 QVector<qreal> QSplineSeriesPrivate::firstControlPoints(const QVector<qreal>& vector)
177 QVector<qreal> QSplineSeriesPrivate::firstControlPoints(const QVector<qreal>& vector)
175 {
178 {
176 QVector<qreal> result;
179 QVector<qreal> result;
177
180
178 int count = vector.count();
181 int count = vector.count();
179 result.resize(count);
182 result.resize(count);
180 result[0] = vector[0] / 2.0;
183 result[0] = vector[0] / 2.0;
181
184
182 QVector<qreal> temp;
185 QVector<qreal> temp;
183 temp.resize(count);
186 temp.resize(count);
184 temp[0] = 0;
187 temp[0] = 0;
185
188
186 qreal b = 2.0;
189 qreal b = 2.0;
187
190
188 for (int i = 1; i < count; i++) {
191 for (int i = 1; i < count; i++) {
189 temp[i] = 1 / b;
192 temp[i] = 1 / b;
190 b = (i < count - 1 ? 4.0 : 3.5) - temp[i];
193 b = (i < count - 1 ? 4.0 : 3.5) - temp[i];
191 result[i]=(vector[i] - result[i - 1]) / b;
194 result[i]=(vector[i] - result[i - 1]) / b;
192 }
195 }
193 for (int i = 1; i < count; i++)
196 for (int i = 1; i < count; i++)
194 result[count - i - 1] -= temp[count - i] * result[count - i];
197 result[count - i - 1] -= temp[count - i] * result[count - i];
195
198
196 return result;
199 return result;
197 }
200 }
198
201
199 /*!
202 /*!
200 Updates the control points, besed on currently avaiable knots.
203 Updates the control points, besed on currently avaiable knots.
201 */
204 */
202 void QSplineSeriesPrivate::updateControlPoints()
205 void QSplineSeriesPrivate::updateControlPoints()
203 {
206 {
204 if (m_points.count() > 1) {
207 Q_Q(QSplineSeries);
205 m_controlPoints.resize(2*m_points.count()-2);
208 if (q->count() > 1) {
209 m_controlPoints.resize(2*q->count()-2);
206 calculateControlPoints();
210 calculateControlPoints();
207 }
211 }
208 }
212 }
209
213
210 Chart* QSplineSeriesPrivate::createGraphics(ChartPresenter* presenter)
214 Chart* QSplineSeriesPrivate::createGraphics(ChartPresenter* presenter)
211 {
215 {
212 Q_Q(QSplineSeries);
216 Q_Q(QSplineSeries);
213 SplineChartItem* spline = new SplineChartItem(q,presenter);
217 SplineChartItem* spline = new SplineChartItem(q,presenter);
214 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
218 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
215 presenter->animator()->addAnimation(spline);
219 presenter->animator()->addAnimation(spline);
216 }
220 }
217 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
221 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
218 return spline;
222 return spline;
219 }
223 }
220
224
221 #include "moc_qsplineseries.cpp"
225 #include "moc_qsplineseries.cpp"
222 #include "moc_qsplineseries_p.cpp"
226 #include "moc_qsplineseries_p.cpp"
223
227
224 QTCOMMERCIALCHART_END_NAMESPACE
228 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,455 +1,457
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "qxyseries.h"
21 #include "qxyseries.h"
22 #include "qxyseries_p.h"
22 #include "qxyseries_p.h"
23 #include "domain_p.h"
23 #include "domain_p.h"
24 #include "legendmarker_p.h"
24 #include "legendmarker_p.h"
25 #include <QAbstractItemModel>
25 #include <QAbstractItemModel>
26
26
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
27 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28
28
29 /*!
29 /*!
30 \class QXYSeries
30 \class QXYSeries
31 \brief The QXYSeries class is a base class for line, spline and scatter series.
31 \brief The QXYSeries class is a base class for line, spline and scatter series.
32 */
32 */
33
33
34 /*!
34 /*!
35 \fn QPen QXYSeries::pen() const
35 \fn QPen QXYSeries::pen() const
36 \brief Returns pen used to draw points for series.
36 \brief Returns pen used to draw points for series.
37 \sa setPen()
37 \sa setPen()
38 */
38 */
39
39
40 /*!
40 /*!
41 \fn QBrush QXYSeries::brush() const
41 \fn QBrush QXYSeries::brush() const
42 \brief Returns brush used to draw points for series.
42 \brief Returns brush used to draw points for series.
43 \sa setBrush()
43 \sa setBrush()
44 */
44 */
45
45
46 /*!
46 /*!
47 \fn void QXYSeries::clicked(const QPointF& point)
47 \fn void QXYSeries::clicked(const QPointF& point)
48 \brief Signal is emitted when user clicks the \a point on chart.
48 \brief Signal is emitted when user clicks the \a point on chart.
49 */
49 */
50
50
51 /*!
51 /*!
52 \fn void QXYSeries::selected()
52 \fn void QXYSeries::selected()
53
53
54 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
54 The signal is emitted if the user selects/deselects the XY series. The logic for maintaining selections should be
55 implemented by the user of QXYSeries API.
55 implemented by the user of QXYSeries API.
56 */
56 */
57
57
58 /*!
58 /*!
59 \fn void QXYSeriesPrivate::pointReplaced(int index)
59 \fn void QXYSeriesPrivate::pointReplaced(int index)
60 \brief \internal \a index
60 \brief \internal \a index
61 */
61 */
62
62
63 /*!
63 /*!
64 \fn void QXYSeriesPrivate::pointAdded(int index)
64 \fn void QXYSeriesPrivate::pointAdded(int index)
65 \brief \internal \a index
65 \brief \internal \a index
66 */
66 */
67
67
68 /*!
68 /*!
69 \fn void QXYSeriesPrivate::pointRemoved(int index)
69 \fn void QXYSeriesPrivate::pointRemoved(int index)
70 \brief \internal \a index
70 \brief \internal \a index
71 */
71 */
72
72
73 /*!
73 /*!
74 \fn void QXYSeriesPrivate::updated()
74 \fn void QXYSeriesPrivate::updated()
75 \brief \internal
75 \brief \internal
76 */
76 */
77
77
78 /*!
78 /*!
79 \internal
79 \internal
80
80
81 Constructs empty series object which is a child of \a parent.
81 Constructs empty series object which is a child of \a parent.
82 When series object is added to QChartView or QChart instance ownerships is transferred.
82 When series object is added to QChartView or QChart instance ownerships is transferred.
83 */
83 */
84 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent) : QAbstractSeries(d, parent)
84 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent) : QAbstractSeries(d, parent)
85 {
85 {
86
86
87 }
87 }
88 /*!
88 /*!
89 Destroys the object. Series added to QChartView or QChart instances are owned by those,
89 Destroys the object. Series added to QChartView or QChart instances are owned by those,
90 and are deleted when mentioned object are destroyed.
90 and are deleted when mentioned object are destroyed.
91 */
91 */
92 QXYSeries::~QXYSeries()
92 QXYSeries::~QXYSeries()
93 {
93 {
94 }
94 }
95
95
96 /*!
96 /*!
97 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
97 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
98 */
98 */
99 void QXYSeries::append(qreal x,qreal y)
99 void QXYSeries::append(qreal x,qreal y)
100 {
100 {
101 append(QPointF(x,y));
101 append(QPointF(x,y));
102 }
102 }
103
103
104 /*!
104 /*!
105 This is an overloaded function.
105 This is an overloaded function.
106 Adds data \a point to the series. Points are connected with lines on the chart.
106 Adds data \a point to the series. Points are connected with lines on the chart.
107 */
107 */
108 void QXYSeries::append(const QPointF &point)
108 void QXYSeries::append(const QPointF &point)
109 {
109 {
110 Q_D(QXYSeries);
110 Q_D(QXYSeries);
111 d->m_points<<point;
111 d->m_points<<point;
112 emit d->pointAdded(d->m_points.count()-1);
112 emit d->pointAdded(d->m_points.count()-1);
113 }
113 }
114
114
115 /*!
115 /*!
116 This is an overloaded function.
116 This is an overloaded function.
117 Adds list of data \a points to the series. Points are connected with lines on the chart.
117 Adds list of data \a points to the series. Points are connected with lines on the chart.
118 */
118 */
119 void QXYSeries::append(const QList<QPointF> &points)
119 void QXYSeries::append(const QList<QPointF> &points)
120 {
120 {
121 foreach(const QPointF& point , points) {
121 foreach(const QPointF& point , points) {
122 append(point);
122 append(point);
123 }
123 }
124 }
124 }
125
125
126
126
127 void QXYSeries::replace(qreal oldX,qreal oldY,qreal newX,qreal newY)
127 void QXYSeries::replace(qreal oldX,qreal oldY,qreal newX,qreal newY)
128 {
128 {
129 replace(QPointF(oldX,oldY),QPointF(newX,newY));
129 replace(QPointF(oldX,oldY),QPointF(newX,newY));
130 }
130 }
131
131
132 void QXYSeries::replace(const QPointF &oldPoint,const QPointF &newPoint)
132 void QXYSeries::replace(const QPointF &oldPoint,const QPointF &newPoint)
133 {
133 {
134 Q_D(QXYSeries);
134 Q_D(QXYSeries);
135 int index = d->m_points.indexOf(oldPoint);
135 int index = d->m_points.indexOf(oldPoint);
136 if(index==1) return;
136 if(index==1) return;
137 d->m_points[index] = newPoint;
137 d->m_points[index] = newPoint;
138 emit d->pointReplaced(index);
138 emit d->pointReplaced(index);
139 }
139 }
140
140
141 /*!
141 /*!
142 Removes current \a x and \a y value.
142 Removes current \a x and \a y value.
143 */
143 */
144 void QXYSeries::remove(qreal x,qreal y)
144 void QXYSeries::remove(qreal x,qreal y)
145 {
145 {
146 remove(QPointF(x,y));
146 remove(QPointF(x,y));
147 }
147 }
148
148
149 /*!
149 /*!
150 Removes current \a point x value. Note \a point y value is ignored.
150 Removes current \a point x value. Note \a point y value is ignored.
151 */
151 */
152 void QXYSeries::remove(const QPointF &point)
152 void QXYSeries::remove(const QPointF &point)
153 {
153 {
154 Q_D(QXYSeries);
154 Q_D(QXYSeries);
155 int index = d->m_points.indexOf(point);
155 int index = d->m_points.indexOf(point);
156 if(index==1) return;
156 if(index==1) return;
157 d->m_points.remove(index);
157 d->m_points.remove(index);
158 emit d->pointRemoved(index);
158 emit d->pointRemoved(index);
159 }
159 }
160
160
161 /*!
161 /*!
162 Removes all data points from the series.
162 Removes all data points from the series.
163 */
163 */
164 void QXYSeries::removeAll()
164 void QXYSeries::removeAll()
165 {
165 {
166 Q_D(QXYSeries);
166 Q_D(QXYSeries);
167 foreach(const QPointF& point, d->m_points) {
167 foreach(const QPointF& point, d->m_points) {
168 remove(point);
168 remove(point);
169 }
169 }
170 }
170 }
171
171
172 /*!
172 /*!
173 \internal \a pos
173 \internal \a pos
174 */
174 */
175 QList<QPointF> QXYSeries::points() const
175 QList<QPointF> QXYSeries::points() const
176 {
176 {
177 Q_D(const QXYSeries);
177 Q_D(const QXYSeries);
178 if (d->m_model) {
178 if (d->m_model) {
179 QList<QPointF> result;
179 QList<QPointF> result;
180 if (d->m_mapOrientation == Qt::Vertical){
180 if (d->m_mapOrientation == Qt::Vertical){
181 // consecutive data is read from model's column
181 // consecutive data is read from model's column
182
182
183 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
183 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
184 qreal x = d->m_model->data(d->m_model->index(i, d->m_mapX), Qt::DisplayRole).toReal();
184 qreal x = d->m_model->data(d->m_model->index(i, d->m_mapX), Qt::DisplayRole).toReal();
185 qreal y = d->m_model->data(d->m_model->index(i, d->m_mapY), Qt::DisplayRole).toReal();
185 qreal y = d->m_model->data(d->m_model->index(i, d->m_mapY), Qt::DisplayRole).toReal();
186 result << QPointF(x,y);
186 result << QPointF(x,y);
187 }
187 }
188 return result;
188 return result;
189 }
189 }
190 else{
190 else{
191 // consecutive data is read from model's row
191 // consecutive data is read from model's row
192 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
192 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
193 qreal x = d->m_model->data(d->m_model->index(d->m_mapX, i), Qt::DisplayRole).toReal();
193 qreal x = d->m_model->data(d->m_model->index(d->m_mapX, i), Qt::DisplayRole).toReal();
194 qreal y = d->m_model->data(d->m_model->index(d->m_mapY, i), Qt::DisplayRole).toReal();
194 qreal y = d->m_model->data(d->m_model->index(d->m_mapY, i), Qt::DisplayRole).toReal();
195 result << QPointF(x,y);
195 result << QPointF(x,y);
196 }
196 }
197 return result;
197 return result;
198 }
198 }
199 } else {
199 } else {
200 // model is not specified, return the data from series' internal data store
200 // model is not specified, return the data from series' internal data store
201 return d->m_points.toList();
201 return d->m_points.toList();
202 }
202 }
203 }
203 }
204
204
205 /*!
205 /*!
206 Returns number of data points within series.
206 Returns number of data points within series.
207 */
207 */
208 int QXYSeries::count() const
208 int QXYSeries::count() const
209 {
209 {
210 Q_D(const QXYSeries);
210 Q_D(const QXYSeries);
211
211
212 if (d->m_model) {
212 if (d->m_model) {
213 if (d->m_mapOrientation == Qt::Vertical) {
213 if (d->m_mapOrientation == Qt::Vertical) {
214 // data is in a column. Return the number of mapped items if the model's column have enough items
214 // data is in a column. Return the number of mapped items if the model's column have enough items
215 // or the number of items that can be mapped
215 // or the number of items that can be mapped
216 if (d->m_mapCount != -1)
216 if (d->m_mapCount != -1)
217 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
217 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
218 else
218 else
219 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
219 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
220 } else {
220 } else {
221 // data is in a row. Return the number of mapped items if the model's row have enough items
221 // data is in a row. Return the number of mapped items if the model's row have enough items
222 // or the number of items that can be mapped
222 // or the number of items that can be mapped
223 if (d->m_mapCount != -1)
223 if (d->m_mapCount != -1)
224 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
224 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
225 else
225 else
226 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
226 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
227 }
227 }
228 }
228 }
229
229
230 // model is not specified, return the number of points in the series internal data store
230 // model is not specified, return the number of points in the series internal data store
231 return d->m_points.count();
231 return d->m_points.count();
232 }
232 }
233
233
234
234
235 /*!
235 /*!
236 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
236 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
237 pen from chart theme is used.
237 pen from chart theme is used.
238 \sa QChart::setTheme()
238 \sa QChart::setTheme()
239 */
239 */
240 void QXYSeries::setPen(const QPen &pen)
240 void QXYSeries::setPen(const QPen &pen)
241 {
241 {
242 Q_D(QXYSeries);
242 Q_D(QXYSeries);
243 if (d->m_pen!=pen) {
243 if (d->m_pen!=pen) {
244 d->m_pen = pen;
244 d->m_pen = pen;
245 emit d->updated();
245 emit d->updated();
246 }
246 }
247 }
247 }
248
248
249 QPen QXYSeries::pen() const
249 QPen QXYSeries::pen() const
250 {
250 {
251 Q_D(const QXYSeries);
251 Q_D(const QXYSeries);
252 return d->m_pen;
252 return d->m_pen;
253 }
253 }
254
254
255 /*!
255 /*!
256 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
256 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
257 from chart theme setting is used.
257 from chart theme setting is used.
258 \sa QChart::setTheme()
258 \sa QChart::setTheme()
259 */
259 */
260 void QXYSeries::setBrush(const QBrush &brush)
260 void QXYSeries::setBrush(const QBrush &brush)
261 {
261 {
262 Q_D(QXYSeries);
262 Q_D(QXYSeries);
263 if (d->m_brush!=brush) {
263 if (d->m_brush!=brush) {
264 d->m_brush = brush;
264 d->m_brush = brush;
265 emit d->updated();
265 emit d->updated();
266 }
266 }
267 }
267 }
268
268
269 QBrush QXYSeries::brush() const
269 QBrush QXYSeries::brush() const
270 {
270 {
271 Q_D(const QXYSeries);
271 Q_D(const QXYSeries);
272 return d->m_brush;
272 return d->m_brush;
273 }
273 }
274
274
275
275
276 /*!
276 /*!
277 Sets if data points are \a visible and should be drawn on line.
277 Sets if data points are \a visible and should be drawn on line.
278 */
278 */
279 void QXYSeries::setPointsVisible(bool visible)
279 void QXYSeries::setPointsVisible(bool visible)
280 {
280 {
281 Q_D(QXYSeries);
281 Q_D(QXYSeries);
282 if (d->m_pointsVisible != visible){
282 if (d->m_pointsVisible != visible){
283 d->m_pointsVisible = visible;
283 d->m_pointsVisible = visible;
284 emit d->updated();
284 emit d->updated();
285 }
285 }
286 }
286 }
287
287
288 /*!
288 /*!
289 Returns true if drawing the data points of the series is enabled.
289 Returns true if drawing the data points of the series is enabled.
290 */
290 */
291 bool QXYSeries::pointsVisible() const
291 bool QXYSeries::pointsVisible() const
292 {
292 {
293 Q_D(const QXYSeries);
293 Q_D(const QXYSeries);
294 return d->m_pointsVisible;
294 return d->m_pointsVisible;
295 }
295 }
296
296
297
297
298 /*!
298 /*!
299 Stream operator for adding a data \a point to the series.
299 Stream operator for adding a data \a point to the series.
300 \sa append()
300 \sa append()
301 */
301 */
302 QXYSeries& QXYSeries::operator<< (const QPointF &point)
302 QXYSeries& QXYSeries::operator<< (const QPointF &point)
303 {
303 {
304 append(point);
304 append(point);
305 return *this;
305 return *this;
306 }
306 }
307
307
308
308
309 /*!
309 /*!
310 Stream operator for adding a list of \a points to the series.
310 Stream operator for adding a list of \a points to the series.
311 \sa append()
311 \sa append()
312 */
312 */
313
313
314 QXYSeries& QXYSeries::operator<< (const QList<QPointF>& points)
314 QXYSeries& QXYSeries::operator<< (const QList<QPointF>& points)
315 {
315 {
316 append(points);
316 append(points);
317 return *this;
317 return *this;
318 }
318 }
319
319
320 /*!
320 /*!
321 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
321 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
322 Sets the \a model to be used as a data source
322 Sets the \a model to be used as a data source
323 \sa setModelMapping()
323 \sa setModelMapping()
324 */
324 */
325 bool QXYSeries::setModel(QAbstractItemModel *model)
325 bool QXYSeries::setModel(QAbstractItemModel *model)
326 {
326 {
327 Q_D(QXYSeries);
327 Q_D(QXYSeries);
328 // disconnect signals from old model
328 // disconnect signals from old model
329 if (d->m_model) {
329 if (d->m_model) {
330 QObject::disconnect(d->m_model, 0, this, 0);
330 QObject::disconnect(d->m_model, 0, this, 0);
331 d->m_mapX = -1;
331 d->m_mapX = -1;
332 d->m_mapY = -1;
332 d->m_mapY = -1;
333 d->m_mapOrientation = Qt::Vertical;
333 d->m_mapOrientation = Qt::Vertical;
334 }
334 }
335
335
336 // set new model
336 // set new model
337 if (model) {
337 if (model) {
338 d->m_model = model;
338 d->m_model = model;
339 return true;
339 return true;
340 } else {
340 } else {
341 d->m_model = 0;
341 d->m_model = 0;
342 return false;
342 return false;
343 }
343 }
344 }
344 }
345
345
346 /*!
346 /*!
347 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
347 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
348 as a data source for y coordinate. The \a orientation parameter specifies whether the data
348 as a data source for y coordinate. The \a orientation parameter specifies whether the data
349 is in columns or in rows.
349 is in columns or in rows.
350 \sa setModel()
350 \sa setModel()
351 */
351 */
352 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
352 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
353 {
353 {
354 Q_D(QXYSeries);
354 Q_D(QXYSeries);
355 if (d->m_model == 0)
355 if (d->m_model == 0)
356 return;
356 return;
357 d->m_mapX = modelX;
357 d->m_mapX = modelX;
358 d->m_mapY = modelY;
358 d->m_mapY = modelY;
359 d->m_mapOrientation = orientation;
359 d->m_mapOrientation = orientation;
360
360
361 // connect the signals from the model
361 // connect the signals from the model
362 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
362 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
363 if (d->m_mapOrientation == Qt::Vertical) {
363 if (d->m_mapOrientation == Qt::Vertical) {
364 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
364 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
365 connect(d->m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
365 connect(d->m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
366 } else {
366 } else {
367 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
367 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
368 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
368 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
369 }
369 }
370 }
370 }
371
371
372 void QXYSeries::setModelMappingRange(int first, int count)
372 void QXYSeries::setModelMappingRange(int first, int count)
373 {
373 {
374 Q_D(QXYSeries);
374 Q_D(QXYSeries);
375 d->m_mapFirst = first;
375 d->m_mapFirst = first;
376 d->m_mapCount = count;
376 d->m_mapCount = count;
377 }
377 }
378
378
379 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
379 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
380
380
381
381
382 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q) : QAbstractSeriesPrivate(q),
382 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q) : QAbstractSeriesPrivate(q),
383 m_mapX(-1),
383 m_mapX(-1),
384 m_mapY(-1),
384 m_mapY(-1),
385 m_pointsVisible(false)
385 m_pointsVisible(false)
386 {
386 {
387 }
387 }
388
388
389 void QXYSeriesPrivate::scaleDomain(Domain& domain)
389 void QXYSeriesPrivate::scaleDomain(Domain& domain)
390 {
390 {
391 qreal minX(domain.minX());
391 qreal minX(domain.minX());
392 qreal minY(domain.minY());
392 qreal minY(domain.minY());
393 qreal maxX(domain.maxX());
393 qreal maxX(domain.maxX());
394 qreal maxY(domain.maxY());
394 qreal maxY(domain.maxY());
395 int tickXCount(domain.tickXCount());
395 int tickXCount(domain.tickXCount());
396 int tickYCount(domain.tickYCount());
396 int tickYCount(domain.tickYCount());
397
397
398 for (int i = 0; i < m_points.count(); i++)
398 Q_Q(QXYSeries);
399 {
400
399
401 qreal x = m_points[i].x();
400 const QList<QPointF>& points = q->points();
402 qreal y = m_points[i].y();
401 for (int i = 0; i < points.count(); i++)
402 {
403 qreal x = points[i].x();
404 qreal y = points[i].y();
403 minX = qMin(minX, x);
405 minX = qMin(minX, x);
404 minY = qMin(minY, y);
406 minY = qMin(minY, y);
405 maxX = qMax(maxX, x);
407 maxX = qMax(maxX, x);
406 maxY = qMax(maxY, y);
408 maxY = qMax(maxY, y);
407 }
409 }
408
410
409 domain.setRangeX(minX,maxX,tickXCount);
411 domain.setRangeX(minX,maxX,tickXCount);
410 domain.setRangeY(minY,maxY,tickYCount);
412 domain.setRangeY(minY,maxY,tickYCount);
411 }
413 }
412
414
413 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
415 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
414 {
416 {
415 Q_Q(QXYSeries);
417 Q_Q(QXYSeries);
416 QList<LegendMarker*> list;
418 QList<LegendMarker*> list;
417 return list << new XYLegendMarker(q,legend);
419 return list << new XYLegendMarker(q,legend);
418 }
420 }
419
421
420 void QXYSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
422 void QXYSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
421 {
423 {
422 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
424 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
423 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
425 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
424 if (m_mapOrientation == Qt::Vertical) {
426 if (m_mapOrientation == Qt::Vertical) {
425 if ((column == m_mapX || column == m_mapY) // modified item is in a mapped column
427 if ((column == m_mapX || column == m_mapY) // modified item is in a mapped column
426 && row >= m_mapFirst // modfied item in not before first item
428 && row >= m_mapFirst // modfied item in not before first item
427 && (m_mapCount == -1 || row < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
429 && (m_mapCount == -1 || row < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
428 emit pointReplaced(row - m_mapFirst);
430 emit pointReplaced(row - m_mapFirst);
429 } else {
431 } else {
430 if ((row == m_mapX || row == m_mapY) // modified item is in a mapped row
432 if ((row == m_mapX || row == m_mapY) // modified item is in a mapped row
431 && column >= m_mapFirst // modfied item in not before first item
433 && column >= m_mapFirst // modfied item in not before first item
432 && (m_mapCount == -1 || column < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
434 && (m_mapCount == -1 || column < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
433 emit pointReplaced(column - m_mapFirst);
435 emit pointReplaced(column - m_mapFirst);
434 }
436 }
435 }
437 }
436 }
438 }
437 }
439 }
438
440
439
441
440 void QXYSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
442 void QXYSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
441 {
443 {
442 Q_UNUSED(parent);
444 Q_UNUSED(parent);
443 emit pointsAdded(start, end);
445 emit pointsAdded(start, end);
444 }
446 }
445
447
446 void QXYSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
448 void QXYSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
447 {
449 {
448 Q_UNUSED(parent);
450 Q_UNUSED(parent);
449 emit pointsRemoved(start, end);
451 emit pointsRemoved(start, end);
450 }
452 }
451
453
452 #include "moc_qxyseries.cpp"
454 #include "moc_qxyseries.cpp"
453 #include "moc_qxyseries_p.cpp"
455 #include "moc_qxyseries_p.cpp"
454
456
455 QTCOMMERCIALCHART_END_NAMESPACE
457 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,309 +1,308
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2012 Digia Plc
3 ** Copyright (C) 2012 Digia Plc
4 ** All rights reserved.
4 ** All rights reserved.
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 **
6 **
7 ** This file is part of the Qt Commercial Charts Add-on.
7 ** This file is part of the Qt Commercial Charts Add-on.
8 **
8 **
9 ** $QT_BEGIN_LICENSE$
9 ** $QT_BEGIN_LICENSE$
10 ** Licensees holding valid Qt Commercial licenses may use this file in
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.
13 ** a written agreement between you and Digia.
14 **
14 **
15 ** If you have questions regarding the use of this file, please use
15 ** If you have questions regarding the use of this file, please use
16 ** contact form at http://qt.digia.com
16 ** contact form at http://qt.digia.com
17 ** $QT_END_LICENSE$
17 ** $QT_END_LICENSE$
18 **
18 **
19 ****************************************************************************/
19 ****************************************************************************/
20
20
21 #include "xychartitem_p.h"
21 #include "xychartitem_p.h"
22 #include "qxyseries.h"
22 #include "qxyseries.h"
23 #include "qxyseries_p.h"
23 #include "qxyseries_p.h"
24 #include "chartpresenter_p.h"
24 #include "chartpresenter_p.h"
25 #include "chartanimator_p.h"
25 #include "chartanimator_p.h"
26 #include <QPainter>
26 #include <QPainter>
27 #include <QGraphicsSceneMouseEvent>
27 #include <QGraphicsSceneMouseEvent>
28 #include <QAbstractItemModel>
28 #include <QAbstractItemModel>
29
29
30
30
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32
32
33 //TODO: optimize : remove points which are not visible
33 //TODO: optimize : remove points which are not visible
34
34
35 XYChartItem::XYChartItem(QXYSeries *series, ChartPresenter *presenter):ChartItem(presenter),
35 XYChartItem::XYChartItem(QXYSeries *series, ChartPresenter *presenter):ChartItem(presenter),
36 m_minX(0),
36 m_minX(0),
37 m_maxX(0),
37 m_maxX(0),
38 m_minY(0),
38 m_minY(0),
39 m_maxY(0),
39 m_maxY(0),
40 m_series(series)
40 m_series(series)
41 {
41 {
42 connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
42 connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
43 connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
43 connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
44 connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
44 connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
45 connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
45 connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
46 connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
46 connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
47 connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
47 connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
48 }
48 }
49
49
50 QPointF XYChartItem::calculateGeometryPoint(const QPointF &point) const
50 QPointF XYChartItem::calculateGeometryPoint(const QPointF &point) const
51 {
51 {
52 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
52 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
53 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
53 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
54 qreal x = (point.x() - m_minX)* deltaX;
54 qreal x = (point.x() - m_minX)* deltaX;
55 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
55 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
56 return QPointF(x,y);
56 return QPointF(x,y);
57 }
57 }
58
58
59
59
60 QPointF XYChartItem::calculateGeometryPoint(int index) const
60 QPointF XYChartItem::calculateGeometryPoint(int index) const
61 {
61 {
62 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
62 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
63 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
63 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
64 const QList<QPointF>& vector = m_series->points();
64 const QList<QPointF>& vector = m_series->points();
65 qreal x = (vector[index].x() - m_minX)* deltaX;
65 qreal x = (vector[index].x() - m_minX)* deltaX;
66 qreal y = (vector[index].y() - m_minY)*-deltaY + m_size.height();
66 qreal y = (vector[index].y() - m_minY)*-deltaY + m_size.height();
67 return QPointF(x,y);
67 return QPointF(x,y);
68 }
68 }
69
69
70 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
70 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
71 {
71 {
72 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
72 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
73 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
73 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
74
74
75 QVector<QPointF> result;
75 QVector<QPointF> result;
76 result.resize(m_series->count());
76 result.resize(m_series->count());
77 const QList<QPointF>& vector = m_series->points();
77 const QList<QPointF>& vector = m_series->points();
78 for (int i = 0; i < m_series->count(); ++i) {
78 for (int i = 0; i < m_series->count(); ++i) {
79 qreal x = (vector[i].x() - m_minX)* deltaX;
79 qreal x = (vector[i].x() - m_minX)* deltaX;
80 qreal y = (vector[i].y() - m_minY)*-deltaY + m_size.height();
80 qreal y = (vector[i].y() - m_minY)*-deltaY + m_size.height();
81 result[i].setX(x);
81 result[i].setX(x);
82 result[i].setY(y);
82 result[i].setY(y);
83 }
83 }
84 return result;
84 return result;
85 }
85 }
86
86
87 QPointF XYChartItem::calculateDomainPoint(const QPointF &point) const
87 QPointF XYChartItem::calculateDomainPoint(const QPointF &point) const
88 {
88 {
89 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
89 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
90 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
90 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
91 qreal x = point.x()/deltaX +m_minX;
91 qreal x = point.x()/deltaX +m_minX;
92 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
92 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
93 return QPointF(x,y);
93 return QPointF(x,y);
94 }
94 }
95
95
96 void XYChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
96 void XYChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
97 {
97 {
98 if (animator()) {
98 if (animator()) {
99 animator()->updateLayout(this,oldPoints,newPoints,index);
99 animator()->updateLayout(this,oldPoints,newPoints,index);
100 } else {
100 } else {
101 setLayout(newPoints);
101 setLayout(newPoints);
102 }
102 }
103 }
103 }
104
104
105 void XYChartItem::setLayout(QVector<QPointF> &points)
105 void XYChartItem::setLayout(QVector<QPointF> &points)
106 {
106 {
107 m_points = points;
107 m_points = points;
108 update();
108 update();
109 }
109 }
110
110
111 //handlers
111 //handlers
112
112
113 void XYChartItem::handlePointAdded(int index)
113 void XYChartItem::handlePointAdded(int index)
114 {
114 {
115 if (m_series->model() == 0) {
115 if (m_series->model() == 0) {
116 Q_ASSERT(index<m_series->count());
116 Q_ASSERT(index<m_series->count());
117 Q_ASSERT(index>=0);
117 Q_ASSERT(index>=0);
118 }
118 }
119 QVector<QPointF> points = m_points;
119 QVector<QPointF> points = m_points;
120 QPointF point;
120 QPointF point;
121 point = calculateGeometryPoint(index);
121 point = calculateGeometryPoint(index);
122 points.insert(index, point);
122 points.insert(index, point);
123 updateLayout(m_points, points, index);
123 updateLayout(m_points, points, index);
124 update();
124 update();
125 }
125 }
126
126
127 void XYChartItem::handlePointsAdded(int start, int end)
127 void XYChartItem::handlePointsAdded(int start, int end)
128 {
128 {
129 if (m_series->model() == 0) {
129 if (m_series->model() == 0) {
130 for (int i = start; i <= end; i++)
130 for (int i = start; i <= end; i++)
131 handlePointAdded(i);
131 handlePointAdded(i);
132 } else {
132 } else {
133 // series uses model as a data source
133 // series uses model as a data source
134 int first = m_series->mapFirst();
134 int first = m_series->mapFirst();
135 int count = m_series->mapCount();
135 int count = m_series->mapCount();
136 int addedCount = end - start + 1;
136 int addedCount = end - start + 1;
137 if (count != -1 && start >= first + count) {
137 if (count != -1 && start >= first + count) {
138 return;
138 return;
139 }
139 }
140
140
141 // adding items to unlimited map
141 // adding items to unlimited map
142 else if (count == -1 && start >= first) {
142 else if (count == -1 && start >= first) {
143 for (int i = start; i <= end; i++)
143 for (int i = start; i <= end; i++)
144 handlePointAdded(i - first);
144 handlePointAdded(i - first);
145 } else if (count == - 1 && start < first) {
145 } else if (count == - 1 && start < first) {
146 // not all newly added items
146 // not all newly added items
147 for (int i = first; i < first + addedCount; i++)
147 for (int i = first; i < first + addedCount; i++)
148 handlePointAdded(i - first);
148 handlePointAdded(i - first);
149 }
149 }
150 // commented out code below does the same thing, but its more confusing.
150 // commented out code below does the same thing, but its more confusing.
151 // } else if (count == -1) {
151 // } else if (count == -1) {
152 // int begin = qMax(start, first);
152 // int begin = qMax(start, first);
153 // for (int i = begin; i < begin + (end - start + 1); i++)
153 // for (int i = begin; i < begin + (end - start + 1); i++)
154 // handlePointAdded(i - first);
154 // handlePointAdded(i - first);
155 // }
155 // }
156
156
157 // adding items to limited map
157 // adding items to limited map
158 else if (start >= first) {
158 else if (start >= first) {
159 // remove the items that will no longer fit into the map
159 // remove the items that will no longer fit into the map
160 // int toRemove = addedCount - (count - points().size());
160 // int toRemove = addedCount - (count - points().size());
161 for (int i = start; i <= end; i++) {
161 for (int i = start; i <= end; i++) {
162 handlePointAdded(i - first);
162 handlePointAdded(i - first);
163 }
163 }
164 if (m_points.size() > count)
164 if (m_points.size() > count)
165 for (int i = m_points.size() - 1; i >= count; i--)
165 for (int i = m_points.size() - 1; i >= count; i--)
166 handlePointRemoved(i);
166 handlePointRemoved(i);
167 // update();
167 // update();
168 } else {
168 } else {
169 //
169 //
170 for (int i = first; i < first + addedCount; i++) {
170 for (int i = first; i < first + addedCount; i++) {
171 handlePointAdded(i - first);
171 handlePointAdded(i - first);
172 }
172 }
173 if (m_points.size() > count)
173 if (m_points.size() > count)
174 for (int i = m_points.size() - 1; i >= count; i--)
174 for (int i = m_points.size() - 1; i >= count; i--)
175 handlePointRemoved(i);
175 handlePointRemoved(i);
176 }
176 }
177 }
177 }
178 }
178 }
179
179
180 void XYChartItem::handlePointRemoved(int index)
180 void XYChartItem::handlePointRemoved(int index)
181 {
181 {
182 if (m_series->model() == 0) {
182 if (m_series->model() == 0) {
183 Q_ASSERT(index<m_series->count() + 1);
183 Q_ASSERT(index<m_series->count() + 1);
184 Q_ASSERT(index>=0);
184 Q_ASSERT(index>=0);
185 }
185 }
186 QVector<QPointF> points = m_points;
186 QVector<QPointF> points = m_points;
187 points.remove(index);
187 points.remove(index);
188 updateLayout(m_points, points, index);
188 updateLayout(m_points, points, index);
189 update();
189 update();
190 }
190 }
191
191
192 void XYChartItem::handlePointsRemoved(int start, int end)
192 void XYChartItem::handlePointsRemoved(int start, int end)
193 {
193 {
194 Q_UNUSED(start)
194 Q_UNUSED(start)
195 Q_UNUSED(end)
195 Q_UNUSED(end)
196 if (m_series->model() == 0) {
196 if (m_series->model() == 0) {
197 for (int i = end; i >= start; i--)
197 for (int i = end; i >= start; i--)
198 handlePointRemoved(i);
198 handlePointRemoved(i);
199 } else {
199 } else {
200 // series uses model as a data source
200 // series uses model as a data source
201 int first = m_series->mapFirst();
201 int first = m_series->mapFirst();
202 int count = m_series->mapCount();
202 int count = m_series->mapCount();
203 int removedCount = end - start + 1;
203 int removedCount = end - start + 1;
204 if (count != -1 && start >= first + count) {
204 if (count != -1 && start >= first + count) {
205 return;
205 return;
206 }
206 }
207
207
208 // removing items from unlimited map
208 // removing items from unlimited map
209 else if (count == -1 && start >= first) {
209 else if (count == -1 && start >= first) {
210 for (int i = end; i >= start; i--)
210 for (int i = end; i >= start; i--)
211 handlePointRemoved(i - first);
211 handlePointRemoved(i - first);
212 } else if (count == - 1 && start < first) {
212 } else if (count == - 1 && start < first) {
213 // not all removed items
213 // not all removed items
214 for (int i = first + removedCount - 1; i >= first; i--)
214 for (int i = first + removedCount - 1; i >= first; i--)
215 handlePointRemoved(i - first);
215 handlePointRemoved(i - first);
216 }
216 }
217
217
218 // removing items from limited map
218 // removing items from limited map
219 else if (start >= first) {
219 else if (start >= first) {
220 //
220 //
221 int lastExisting = qMin(first + m_points.size() - 1, end);
221 int lastExisting = qMin(first + m_points.size() - 1, end);
222 for (int i = lastExisting; i >= start; i--) {
222 for (int i = lastExisting; i >= start; i--) {
223 handlePointRemoved(i - first);
223 handlePointRemoved(i - first);
224 }
224 }
225
225
226 // the map is limited, so after removing the items some new items may have fall within the mapped area
226 // the map is limited, so after removing the items some new items may have fall within the mapped area
227 int itemsAvailable;
227 int itemsAvailable;
228 if (m_series->mapOrientation() == Qt::Vertical)
228 if (m_series->mapOrientation() == Qt::Vertical)
229 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
229 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
230 else
230 else
231 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
231 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
232 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
232 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
233 int currentSize = m_points.size();
233 int currentSize = m_points.size();
234 if (itemsAvailable > 0)
234 if (itemsAvailable > 0)
235 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
235 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
236 handlePointAdded(i);
236 handlePointAdded(i);
237 } else {
237 } else {
238 // first removed item lays before the mapped area
238 // first removed item lays before the mapped area
239 int toRemove = qMin(m_points.size() - 1, removedCount);
239 int toRemove = qMin(m_points.size() - 1, removedCount);
240 for (int i = first; i < first + toRemove; i++)
240 for (int i = first; i < first + toRemove; i++)
241 handlePointRemoved(0);
241 handlePointRemoved(0);
242
242
243 // the map is limited, so after removing the items some new items may have fall into the map
243 // the map is limited, so after removing the items some new items may have fall into the map
244 int itemsAvailable;
244 int itemsAvailable;
245 if (m_series->mapOrientation() == Qt::Vertical)
245 if (m_series->mapOrientation() == Qt::Vertical)
246 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
246 itemsAvailable = m_series->model()->rowCount() - first - m_points.size();
247 else
247 else
248 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
248 itemsAvailable = m_series->model()->columnCount() - first - m_points.size();
249 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
249 int toBeAdded = qMin(itemsAvailable, count - m_points.size());
250 int currentSize = m_points.size();
250 int currentSize = m_points.size();
251 if (itemsAvailable > 0)
251 if (itemsAvailable > 0)
252 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
252 for (int i = m_points.size(); i < currentSize + toBeAdded; i++)
253 handlePointAdded(i);
253 handlePointAdded(i);
254 }
254 }
255 }
255 }
256
256
257 }
257 }
258
258
259 void XYChartItem::handlePointReplaced(int index)
259 void XYChartItem::handlePointReplaced(int index)
260 {
260 {
261 Q_ASSERT(index<m_series->count());
261 Q_ASSERT(index<m_series->count());
262 Q_ASSERT(index>=0);
262 Q_ASSERT(index>=0);
263 QPointF point = calculateGeometryPoint(index);
263 QPointF point = calculateGeometryPoint(index);
264 QVector<QPointF> points = m_points;
264 QVector<QPointF> points = m_points;
265 points.replace(index,point);
265 points.replace(index,point);
266 updateLayout(m_points,points,index);
266 updateLayout(m_points,points,index);
267 update();
267 update();
268 }
268 }
269
269
270 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
270 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
271 {
271 {
272 m_minX=minX;
272 m_minX=minX;
273 m_maxX=maxX;
273 m_maxX=maxX;
274 m_minY=minY;
274 m_minY=minY;
275 m_maxY=maxY;
275 m_maxY=maxY;
276
277 if (isEmpty()) return;
276 if (isEmpty()) return;
278 QVector<QPointF> points = calculateGeometryPoints();
277 QVector<QPointF> points = calculateGeometryPoints();
279 updateLayout(m_points,points);
278 updateLayout(m_points,points);
280 update();
279 update();
281 }
280 }
282
281
283 void XYChartItem::handleGeometryChanged(const QRectF &rect)
282 void XYChartItem::handleGeometryChanged(const QRectF &rect)
284 {
283 {
285 Q_ASSERT(rect.isValid());
284 Q_ASSERT(rect.isValid());
286 m_size=rect.size();
285 m_size=rect.size();
287 m_clipRect=rect.translated(-rect.topLeft());
286 m_clipRect=rect.translated(-rect.topLeft());
288 setPos(rect.topLeft());
287 setPos(rect.topLeft());
289
288
290 if (isEmpty()) return;
289 if (isEmpty()) return;
291 QVector<QPointF> points = calculateGeometryPoints();
290 QVector<QPointF> points = calculateGeometryPoints();
292 updateLayout(m_points,points);
291 updateLayout(m_points,points);
293 update();
292 update();
294 }
293 }
295
294
296
295
297 bool XYChartItem::isEmpty()
296 bool XYChartItem::isEmpty()
298 {
297 {
299 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY);
298 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY);
300 }
299 }
301
300
302 void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
301 void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
303 {
302 {
304 emit clicked(calculateDomainPoint(event->pos()));
303 emit clicked(calculateDomainPoint(event->pos()));
305 }
304 }
306
305
307 #include "moc_xychartitem_p.cpp"
306 #include "moc_xychartitem_p.cpp"
308
307
309 QTCOMMERCIALCHART_END_NAMESPACE
308 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now