##// END OF EJS Templates
Bugfixes for spline vector allocation issues
Michal Klocek -
r1082:4c0668542a54
parent child
Show More
@@ -1,404 +1,406
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 #include "chartpresenter_p.h"
21 21 #include "qchart.h"
22 22 #include "qchart_p.h"
23 23 #include "qaxis.h"
24 24 #include "chartdataset_p.h"
25 25 #include "charttheme_p.h"
26 26 #include "chartanimator_p.h"
27 27 #include "qabstractseries_p.h"
28 28 #include "qareaseries.h"
29 29 #include "chartaxis_p.h"
30 30 #include "areachartitem_p.h"
31 31 #include "chartbackground_p.h"
32 32
33 33 QTCOMMERCIALCHART_BEGIN_NAMESPACE
34 34
35 35 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
36 36 m_chart(chart),
37 37 m_animator(0),
38 38 m_dataset(dataset),
39 39 m_chartTheme(0),
40 40 m_chartRect(QRectF(QPoint(0,0),m_chart->size())),
41 41 m_options(QChart::NoAnimation),
42 42 m_minLeftMargin(0),
43 43 m_minBottomMargin(0),
44 44 m_backgroundItem(0),
45 45 m_titleItem(0),
46 46 m_marginBig(60),
47 47 m_marginSmall(20),
48 48 m_marginTiny(10),
49 49 m_chartMargins(QRect(m_marginBig,m_marginBig,0,0))
50 50 {
51 51 }
52 52
53 53 ChartPresenter::~ChartPresenter()
54 54 {
55 55 delete m_chartTheme;
56 56 }
57 57
58 58 void ChartPresenter::setGeometry(const QRectF& rect)
59 59 {
60 60 m_rect = rect;
61 61 Q_ASSERT(m_rect.isValid());
62 62 updateLayout();
63 63 }
64 64
65 65 void ChartPresenter::setMinimumMarginWidth(ChartAxis* axis, qreal width)
66 66 {
67 67 switch(axis->axisType()){
68 68 case ChartAxis::X_AXIS:
69 69 {
70 70 if(width>m_chartRect.width()+ m_chartMargins.left()) {
71 71 m_minLeftMargin= width - m_chartRect.width();
72 72 updateLayout();
73 73 }
74 74 break;
75 75 }
76 76 case ChartAxis::Y_AXIS:
77 77 {
78 78
79 79 if(m_minLeftMargin!=width){
80 80 m_minLeftMargin= width;
81 81 updateLayout();
82 82 }
83 83 break;
84 84 }
85 85
86 86 }
87 87 }
88 88
89 89 void ChartPresenter::setMinimumMarginHeight(ChartAxis* axis, qreal height)
90 90 {
91 91 switch(axis->axisType()){
92 92 case ChartAxis::X_AXIS:
93 93 {
94 94 if(m_minBottomMargin!=height) {
95 95 m_minBottomMargin= height;
96 96 updateLayout();
97 97 }
98 98 break;
99 99 }
100 100 case ChartAxis::Y_AXIS:
101 101 {
102 102
103 103 if(height>m_chartMargins.bottom()+m_chartRect.height()){
104 104 m_minBottomMargin= height - m_chartRect.height();
105 105 updateLayout();
106 106 }
107 107 break;
108 108 }
109 109
110 110 }
111 111 }
112 112
113 113 void ChartPresenter::handleAxisAdded(QAxis* axis,Domain* domain)
114 114 {
115 115 ChartAxis* item = new ChartAxis(axis,this,axis==m_dataset->axisX()?ChartAxis::X_AXIS : ChartAxis::Y_AXIS);
116 116
117 117 if(m_options.testFlag(QChart::GridAxisAnimations)){
118 118 m_animator->addAnimation(item);
119 119 }
120 120
121 121 if(axis==m_dataset->axisX()){
122 122 m_chartTheme->decorate(axis,true);
123 123 QObject::connect(domain,SIGNAL(rangeXChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
124 124 //initialize
125 125 item->handleRangeChanged(domain->minX(),domain->maxX(),domain->tickXCount());
126 126
127 127 }
128 128 else{
129 129 m_chartTheme->decorate(axis,false);
130 130 QObject::connect(domain,SIGNAL(rangeYChanged(qreal,qreal,int)),item,SLOT(handleRangeChanged(qreal,qreal,int)));
131 131 //initialize
132 132 item->handleRangeChanged(domain->minY(),domain->maxY(),domain->tickYCount());
133 133 }
134 134
135 135 QObject::connect(this,SIGNAL(geometryChanged(QRectF)),item,SLOT(handleGeometryChanged(QRectF)));
136 136 //initialize
137 137 item->handleGeometryChanged(m_chartRect);
138 138 m_axisItems.insert(axis, item);
139 139 }
140 140
141 141 void ChartPresenter::handleAxisRemoved(QAxis* axis)
142 142 {
143 143 ChartAxis* item = m_axisItems.take(axis);
144 144 Q_ASSERT(item);
145 145 if(m_animator) m_animator->removeAnimation(item);
146 146 delete item;
147 147 }
148 148
149 149
150 150 void ChartPresenter::handleSeriesAdded(QAbstractSeries* series,Domain* domain)
151 151 {
152 152 Chart *item = series->d_ptr->createGraphics(this);
153 153 Q_ASSERT(item);
154 154 QObject::connect(this,SIGNAL(geometryChanged(QRectF)),item,SLOT(handleGeometryChanged(QRectF)));
155 155 QObject::connect(domain,SIGNAL(domainChanged(qreal,qreal,qreal,qreal)),item,SLOT(handleDomainChanged(qreal,qreal,qreal,qreal)));
156 156 //initialize
157 157 item->handleDomainChanged(domain->minX(),domain->maxX(),domain->minY(),domain->maxY());
158 158 if(m_chartRect.isValid()) item->handleGeometryChanged(m_chartRect);
159 159 m_chartItems.insert(series,item);
160 160 }
161 161
162 162 void ChartPresenter::handleSeriesRemoved(QAbstractSeries* series)
163 163 {
164 164 Chart* item = m_chartItems.take(series);
165 165 Q_ASSERT(item);
166 166 if(m_animator) {
167 167 //small hack to handle area animations
168 168 if(series->type() == QAbstractSeries::SeriesTypeArea){
169 169 QAreaSeries* areaSeries = static_cast<QAreaSeries*>(series);
170 170 AreaChartItem* area = static_cast<AreaChartItem*>(item);
171 171 m_animator->removeAnimation(area->upperLineItem());
172 172 if(areaSeries->lowerSeries()) m_animator->removeAnimation(area->lowerLineItem());
173 173 }else
174 174 m_animator->removeAnimation(item);
175 175 }
176 176 delete item;
177 177 }
178 178
179 179 void ChartPresenter::setTheme(QChart::ChartTheme theme,bool force)
180 180 {
181 181 if(m_chartTheme && m_chartTheme->id() == theme) return;
182 182 delete m_chartTheme;
183 183 m_chartTheme = ChartTheme::createTheme(theme);
184 184 m_chartTheme->setForced(force);
185 185 m_chartTheme->decorate(m_chart);
186 186 m_chartTheme->decorate(m_chart->legend());
187 187 resetAllElements();
188 188 }
189 189
190 190 QChart::ChartTheme ChartPresenter::theme()
191 191 {
192 192 return m_chartTheme->id();
193 193 }
194 194
195 195 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
196 196 {
197 197 if(m_options!=options) {
198 198
199 199 m_options=options;
200 200
201 201 if(m_options!=QChart::NoAnimation && !m_animator) {
202 202 m_animator= new ChartAnimator(this);
203 203 }
204 204 resetAllElements();
205 205 }
206 206
207 207 }
208 208
209 209 void ChartPresenter::resetAllElements()
210 210 {
211 211 QList<QAxis *> axisList = m_axisItems.uniqueKeys();
212 212 QList<QAbstractSeries *> seriesList = m_chartItems.uniqueKeys();
213 213
214 214 foreach(QAxis *axis, axisList) {
215 215 handleAxisRemoved(axis);
216 216 handleAxisAdded(axis,m_dataset->domain(axis));
217 217 }
218 218 foreach(QAbstractSeries *series, seriesList) {
219 219 handleSeriesRemoved(series);
220 220 handleSeriesAdded(series,m_dataset->domain(series));
221 221 // m_dataset->removeSeries(series);
222 222 // m_dataset->addSeries(series);
223 223 }
224 224 }
225 225
226 226 void ChartPresenter::zoomIn()
227 227 {
228 228 QRectF rect = chartGeometry();
229 229 rect.setWidth(rect.width()/2);
230 230 rect.setHeight(rect.height()/2);
231 231 rect.moveCenter(chartGeometry().center());
232 232 zoomIn(rect);
233 233 }
234 234
235 235 void ChartPresenter::zoomIn(const QRectF& rect)
236 236 {
237 237 QRectF r = rect.normalized();
238 238 r.translate(-m_chartMargins.topLeft());
239 if(!r.isValid()) return;
239 240 if(m_animator) {
240 241
241 242 QPointF point(r.center().x()/chartGeometry().width(),r.center().y()/chartGeometry().height());
242 243 m_animator->setState(ChartAnimator::ZoomInState,point);
243 244 }
244 245 m_dataset->zoomInDomain(r,chartGeometry().size());
245 246 if(m_animator) {
246 247 m_animator->setState(ChartAnimator::ShowState);
247 248 }
248 249 }
249 250
250 251 void ChartPresenter::zoomOut()
251 252 {
252 253 if(m_animator)
253 254 {
254 255 m_animator->setState(ChartAnimator::ZoomOutState);
255 256 }
256 257
257 258 QSizeF size = chartGeometry().size();
258 259 QRectF rect = chartGeometry();
259 260 rect.translate(-m_chartMargins.topLeft());
261 if(!rect.isValid()) return;
260 262 m_dataset->zoomOutDomain(rect.adjusted(size.width()/4,size.height()/4,-size.width()/4,-size.height()/4),size);
261 263 //m_dataset->zoomOutDomain(m_zoomStack[m_zoomIndex-1],geometry().size());
262 264
263 265 if(m_animator){
264 266 m_animator->setState(ChartAnimator::ShowState);
265 267 }
266 268 }
267 269
268 270 void ChartPresenter::scroll(int dx,int dy)
269 271 {
270 272 if(m_animator){
271 273 if(dx<0) m_animator->setState(ChartAnimator::ScrollLeftState,QPointF());
272 274 if(dx>0) m_animator->setState(ChartAnimator::ScrollRightState,QPointF());
273 275 if(dy<0) m_animator->setState(ChartAnimator::ScrollUpState,QPointF());
274 276 if(dy>0) m_animator->setState(ChartAnimator::ScrollDownState,QPointF());
275 277 }
276 278
277 279 m_dataset->scrollDomain(dx,dy,chartGeometry().size());
278 280
279 281 if(m_animator){
280 282 m_animator->setState(ChartAnimator::ShowState);
281 283 }
282 284 }
283 285
284 286 QChart::AnimationOptions ChartPresenter::animationOptions() const
285 287 {
286 288 return m_options;
287 289 }
288 290
289 291 void ChartPresenter::updateLayout()
290 292 {
291 293 if (!m_rect.isValid()) return;
292 294
293 295 // recalculate title size
294 296
295 297 QSize titleSize;
296 298 int titlePadding=0;
297 299
298 300 if (m_titleItem) {
299 301 titleSize= m_titleItem->boundingRect().size().toSize();
300 302 }
301 303
302 304 //defaults
303 305 m_chartMargins = QRect(QPoint(m_minLeftMargin>m_marginBig?m_minLeftMargin:m_marginBig,m_marginBig),QPoint(m_marginBig,m_minBottomMargin>m_marginBig?m_minBottomMargin:m_marginBig));
304 306 titlePadding = m_chartMargins.top()/2;
305 307
306 308 QLegend* legend = m_chart->d_ptr->m_legend;
307 309
308 310 // recalculate legend position
309 311 if (legend->isAttachedToChart() && legend->isEnabled()) {
310 312
311 313 QRect legendRect;
312 314
313 315 // Reserve some space for legend
314 316 switch (legend->alignment()) {
315 317
316 318 case QLegend::AlignmentTop: {
317 319 int ledgendSize = legend->minHeight();
318 320 int topPadding = 2*m_marginTiny + titleSize.height() + ledgendSize + m_marginTiny;
319 321 m_chartMargins = QRect(QPoint(m_chartMargins.left(),topPadding),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
320 322 m_legendMargins = QRect(QPoint(m_chartMargins.left(),topPadding - (ledgendSize + m_marginTiny)),QPoint(m_chartMargins.right(),m_rect.height()-topPadding + m_marginTiny));
321 323 titlePadding = m_marginTiny + m_marginTiny;
322 324 break;
323 325 }
324 326 case QLegend::AlignmentBottom: {
325 327 int ledgendSize = legend->minHeight();
326 328 int bottomPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minBottomMargin;
327 329 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(m_chartMargins.right(),bottomPadding));
328 330 m_legendMargins = QRect(QPoint(m_chartMargins.left(),m_rect.height()-bottomPadding + m_marginTiny + m_minBottomMargin),QPoint(m_chartMargins.right(),m_marginTiny + m_marginSmall));
329 331 titlePadding = m_chartMargins.top()/2;
330 332 break;
331 333 }
332 334 case QLegend::AlignmentLeft: {
333 335 int ledgendSize = legend->minWidth();
334 336 int leftPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny + m_minLeftMargin;
335 337 m_chartMargins = QRect(QPoint(leftPadding,m_chartMargins.top()),QPoint(m_chartMargins.right(),m_chartMargins.bottom()));
336 338 m_legendMargins = QRect(QPoint(m_marginTiny + m_marginSmall,m_chartMargins.top()),QPoint(m_rect.width()-leftPadding + m_marginTiny + m_minLeftMargin,m_chartMargins.bottom()));
337 339 titlePadding = m_chartMargins.top()/2;
338 340 break;
339 341 }
340 342 case QLegend::AlignmentRight: {
341 343 int ledgendSize = legend->minWidth();
342 344 int rightPadding = m_marginTiny + m_marginSmall + ledgendSize + m_marginTiny;
343 345 m_chartMargins = QRect(QPoint(m_chartMargins.left(),m_chartMargins.top()),QPoint(rightPadding,m_chartMargins.bottom()));
344 346 m_legendMargins = QRect(QPoint(m_rect.width()- rightPadding+ m_marginTiny ,m_chartMargins.top()),QPoint(m_marginTiny + m_marginSmall,m_chartMargins.bottom()));
345 347 titlePadding = m_chartMargins.top()/2;
346 348 break;
347 349 }
348 350 default: {
349 351 break;
350 352 }
351 353 }
352 354 }
353 355
354 356 if(m_rect.width()<2*(m_chartMargins.top()+m_chartMargins.bottom()) || m_rect.height()< 2*(m_chartMargins.top() + m_chartMargins.bottom()))
355 357 {
356 358 m_chart->setMinimumSize(2*(m_chartMargins.top()+m_chartMargins.bottom()),2*(m_chartMargins.top() + m_chartMargins.bottom()));
357 359 return;
358 360 }
359 361
360 362
361 363 // recalculate title position
362 364 if (m_titleItem) {
363 365 QPointF center = m_rect.center() -m_titleItem->boundingRect().center();
364 366 m_titleItem->setPos(center.x(),titlePadding);
365 367 }
366 368
367 369 //recalculate background gradient
368 370 if (m_backgroundItem) {
369 371 m_backgroundItem->setRect(m_rect.adjusted(m_marginTiny,m_marginTiny, -m_marginTiny, -m_marginTiny));
370 372 }
371 373
372 374
373 375 QRectF chartRect = m_rect.adjusted(m_chartMargins.left(),m_chartMargins.top(),-m_chartMargins.right(),-m_chartMargins.bottom());
374 376
375 377 legend->setGeometry(m_rect.adjusted(m_legendMargins.left(),m_legendMargins.top(),-m_legendMargins.right(),-m_legendMargins.bottom()));
376 378
377 379 if(m_chartRect!=chartRect){
378 380 m_chartRect=chartRect;
379 381 emit geometryChanged(m_chartRect);
380 382 }
381 383
382 384
383 385 }
384 386
385 387 void ChartPresenter::createChartBackgroundItem()
386 388 {
387 389 if (!m_backgroundItem) {
388 390 m_backgroundItem = new ChartBackground(rootItem());
389 391 m_backgroundItem->setPen(Qt::NoPen);
390 392 m_backgroundItem->setZValue(ChartPresenter::BackgroundZValue);
391 393 }
392 394 }
393 395
394 396 void ChartPresenter::createChartTitleItem()
395 397 {
396 398 if (!m_titleItem) {
397 399 m_titleItem = new QGraphicsSimpleTextItem(rootItem());
398 400 m_titleItem->setZValue(ChartPresenter::BackgroundZValue);
399 401 }
400 402 }
401 403
402 404 #include "moc_chartpresenter_p.cpp"
403 405
404 406 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,241 +1,249
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 #include <QAbstractItemModel>
28 28
29 29 /*!
30 30 \class QSplineSeries
31 31 \brief Series type used to store data needed to draw a spline.
32 32
33 33 QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline
34 34 Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn.
35 35
36 36 \image examples_splinechart.png
37 37
38 38 Creating basic spline chart is simple:
39 39 \code
40 40 QSplineSeries* series = new QSplineSeries();
41 41 series->append(0, 6);
42 42 series->append(2, 4);
43 43 ...
44 44 chart->addSeries(series);
45 45 \endcode
46 46 */
47 47
48 48 /*!
49 49 \fn QSeriesType QSplineSeries::type() const
50 50 Returns the type of the series
51 51 */
52 52
53 53 /*!
54 54 \fn QSeriesType QSplineSeries::controlPoint(int index) const
55 55 Returns the control point specified by \a index
56 56 */
57 57
58 58 QTCOMMERCIALCHART_BEGIN_NAMESPACE
59 59
60 60 /*!
61 61 Constructs empty series object which is a child of \a parent.
62 62 When series object is added to QChartView or QChart instance then the ownerships is transferred.
63 63 */
64 64
65 65 QSplineSeries::QSplineSeries(QObject *parent) :
66 66 QLineSeries(*new QSplineSeriesPrivate(this),parent)
67 67 {
68 68 }
69 69
70 QSplineSeries::~QSplineSeries()
71 {
72 Q_D(QSplineSeries);
73 if(d->m_dataset){
74 d->m_dataset->removeSeries(this);
75 }
76 }
77
70 78 QAbstractSeries::QSeriesType QSplineSeries::type() const
71 79 {
72 80 return QAbstractSeries::SeriesTypeSpline;
73 81 }
74 82
75 83 QPointF QSplineSeries::controlPoint(int index) const
76 84 {
77 85 Q_D(const QSplineSeries);
78 86 return d->m_controlPoints[index];
79 87 }
80 88
81 89 /*!
82 90 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
83 91 as a data source for y coordinate. The \a orientation parameter specifies whether the data
84 92 is in columns or in rows.
85 93 \sa setModel()
86 94 */
87 95 void QSplineSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
88 96 {
89 97 Q_D(QSplineSeries);
90 98 QXYSeries::setModelMapping(modelX, modelY, orientation);
91 99 d->updateControlPoints();
92 100 }
93 101
94 102 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
95 103
96 104 QSplineSeriesPrivate::QSplineSeriesPrivate(QSplineSeries* q):QLineSeriesPrivate(q)
97 105 {
98 106 QObject::connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints()));
99 107 QObject::connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints()));
100 108 QObject::connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints()));
101 109 };
102 110
103 111 /*!
104 112 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
105 113 */
106 114 void QSplineSeriesPrivate::calculateControlPoints()
107 115 {
108 116 Q_Q(QSplineSeries);
109 117
110 118 const QList<QPointF>& points = q->points();
111 119
112 120 int n = points.count() - 1;
113 121
114 122 if (n == 1)
115 123 {
116 124 //for n==1
117 125 m_controlPoints[0].setX((2 * points[0].x() + points[1].x()) / 3);
118 126 m_controlPoints[0].setY((2 * points[0].y() + points[1].y()) / 3);
119 127 m_controlPoints[1].setX(2 * m_controlPoints[0].x() - points[0].x());
120 128 m_controlPoints[1].setY(2 * m_controlPoints[0].y() - points[0].y());
121 129 return;
122 130 }
123 131
124 132 // Calculate first Bezier control points
125 133 // Right hand side vector
126 134 // Set of equations for P0 to Pn points.
127 135 //
128 136 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
129 137 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
130 138 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
131 139 // | . . . . . . . . . . . . | | ... | | ... |
132 140 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
133 141 // | . . . . . . . . . . . . | | ... | | ... |
134 142 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
135 143 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
136 144 //
137 145 QVector<qreal> vector;
138 146 vector.resize(n);
139 147
140 148 vector[0] = points[0].x() + 2 * points[1].x();
141 149
142 150
143 151 for (int i = 1; i < n - 1; ++i){
144 152 vector[i] = 4 * points[i].x() + 2 * points[i + 1].x();
145 153 }
146 154
147 155 vector[n - 1] = (8 * points[n-1].x() + points[n].x()) / 2.0;
148 156
149 157 QVector<qreal> xControl = firstControlPoints(vector);
150 158
151 159 vector[0] = points[0].y() + 2 * points[1].y();
152 160
153 161 for (int i = 1; i < n - 1; ++i) {
154 162 vector[i] = 4 * points[i].y() + 2 * points[i + 1].y();
155 163 }
156 164
157 165 vector[n - 1] = (8 * points[n-1].y() + points[n].y()) / 2.0;
158 166
159 167 QVector<qreal> yControl = firstControlPoints(vector);
160 168
161 169 for (int i = 0,j =0; i < n; ++i, ++j) {
162 170
163 171 m_controlPoints[j].setX(xControl[i]);
164 172 m_controlPoints[j].setY(yControl[i]);
165 173
166 174 j++;
167 175
168 176 if (i < n - 1){
169 177 m_controlPoints[j].setX(2 * points[i+1].x() - xControl[i + 1]);
170 178 m_controlPoints[j].setY(2 * points[i+1].y() - yControl[i + 1]);
171 179 }else{
172 180 m_controlPoints[j].setX((points[n].x() + xControl[n - 1]) / 2);
173 181 m_controlPoints[j].setY((points[n].y() + yControl[n - 1]) / 2);
174 182 }
175 183 }
176 184 }
177 185
178 186 QVector<qreal> QSplineSeriesPrivate::firstControlPoints(const QVector<qreal>& vector)
179 187 {
180 188 QVector<qreal> result;
181 189
182 190 int count = vector.count();
183 191 result.resize(count);
184 192 result[0] = vector[0] / 2.0;
185 193
186 194 QVector<qreal> temp;
187 195 temp.resize(count);
188 196 temp[0] = 0;
189 197
190 198 qreal b = 2.0;
191 199
192 200 for (int i = 1; i < count; i++) {
193 201 temp[i] = 1 / b;
194 202 b = (i < count - 1 ? 4.0 : 3.5) - temp[i];
195 203 result[i]=(vector[i] - result[i - 1]) / b;
196 204 }
197 205 for (int i = 1; i < count; i++)
198 206 result[count - i - 1] -= temp[count - i] * result[count - i];
199 207
200 208 return result;
201 209 }
202 210
203 211 /*!
204 212 Updates the control points, besed on currently avaiable knots.
205 213 */
206 214 void QSplineSeriesPrivate::updateControlPoints()
207 215 {
208 216 Q_Q(QSplineSeries);
209 217 if (q->count() > 1) {
210 218 m_controlPoints.resize(2*q->count()-2);
211 219 calculateControlPoints();
212 220 }
213 221 }
214 222
215 223 void QSplineSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
216 224 {
217 225 updateControlPoints();
218 226 QXYSeriesPrivate::modelDataAdded(parent, start, end);
219 227 }
220 228
221 229 void QSplineSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
222 230 {
223 231 updateControlPoints();
224 232 QXYSeriesPrivate::modelDataRemoved(parent, start, end);
225 233 }
226 234
227 235 Chart* QSplineSeriesPrivate::createGraphics(ChartPresenter* presenter)
228 236 {
229 237 Q_Q(QSplineSeries);
230 238 SplineChartItem* spline = new SplineChartItem(q,presenter);
231 239 if(presenter->animationOptions().testFlag(QChart::SeriesAnimations)) {
232 240 presenter->animator()->addAnimation(spline);
233 241 }
234 242 presenter->chartTheme()->decorate(q, presenter->dataSet()->seriesIndex(q));
235 243 return spline;
236 244 }
237 245
238 246 #include "moc_qsplineseries.cpp"
239 247 #include "moc_qsplineseries_p.cpp"
240 248
241 249 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,54 +1,55
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 QSPLINESERIES_H
22 22 #define QSPLINESERIES_H
23 23
24 24 #include <qchartglobal.h>
25 25 #include <qlineseries.h>
26 26 #include <QList>
27 27 #include <QPointF>
28 28 #include <QtGlobal>
29 29
30 30 QTCOMMERCIALCHART_BEGIN_NAMESPACE
31 31
32 32 class QSplineSeriesPrivate;
33 33
34 34 class QTCOMMERCIALCHART_EXPORT QSplineSeries : public QLineSeries
35 35 {
36 36 Q_OBJECT
37 37 public:
38 38
39 39 explicit QSplineSeries(QObject *parent = 0);
40 ~QSplineSeries();
40 41 QAbstractSeries::QSeriesType type() const;
41 42
42 43 QPointF controlPoint(int index) const;
43 44
44 45 void setModelMapping(int modelX, int modelY, Qt::Orientation orientation = Qt::Vertical);
45 46
46 47 private:
47 48 Q_DECLARE_PRIVATE(QSplineSeries);
48 49 Q_DISABLE_COPY(QSplineSeries);
49 50 friend class SplineChartItem;
50 51 };
51 52
52 53 QTCOMMERCIALCHART_END_NAMESPACE
53 54
54 55 #endif // QSPLINESERIES_H
@@ -1,140 +1,144
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 "splinechartitem_p.h"
22 22 #include "qsplineseries_p.h"
23 23 #include "chartpresenter_p.h"
24 24 #include "chartanimator_p.h"
25 25 #include <QPainter>
26 #include <QDebug>
26 27
27 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
28 29
29 30 SplineChartItem::SplineChartItem(QSplineSeries *series, ChartPresenter *presenter) :
30 31 XYChartItem(series, presenter),
31 32 m_series(series),
32 33 m_pointsVisible(false)
33 34 {
34 35 setZValue(ChartPresenter::LineChartZValue);
35 36 QObject::connect(m_series->d_func(),SIGNAL(updated()),this,SLOT(handleUpdated()));
36 37 handleUpdated();
37 38 }
38 39
39 40 QRectF SplineChartItem::boundingRect() const
40 41 {
41 42 return m_rect;
42 43 }
43 44
44 45 QPainterPath SplineChartItem::shape() const
45 46 {
46 47 return m_path;
47 48 }
48 49
49 50 void SplineChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
50 {
51 {
51 52 QVector<QPointF> controlPoints;
52 53
53 controlPoints.resize(newPoints.count()*2-2);
54 if(newPoints.count()>=2){
55 controlPoints.resize(newPoints.count()*2-2);
56 }
54 57
55 58 for (int i = 0; i < newPoints.size() - 1; i++) {
56 59 controlPoints[2*i] = calculateGeometryControlPoint(2 * i);
57 60 controlPoints[2 * i + 1] = calculateGeometryControlPoint(2 * i + 1);
58 61 }
59 62
60 63 if (controlPoints.count()<2) {
61 64 setLayout(newPoints,controlPoints);
62 65 return;
63 66 }
64 67
65 68 if (animator()) {
66 69 animator()->updateLayout(this,oldPoints,newPoints,m_controlPoints,controlPoints,index);
67 70 } else {
68 71 setLayout(newPoints,controlPoints);
69 72 }
70 73 }
71 74
72 75 QPointF SplineChartItem::calculateGeometryControlPoint(int index) const
73 76 {
74 77 return XYChartItem::calculateGeometryPoint(m_series->controlPoint(index));
75 78 }
76 79
77 80 void SplineChartItem::setLayout(QVector<QPointF> &points)
78 81 {
79 82 // Dummy implementation because of a bug in Clang compiler
80 83 XYChartItem::setLayout(points);
81 84 }
82 85
83 86 void SplineChartItem::setLayout(QVector<QPointF> &points, QVector<QPointF> &controlPoints)
84 87 {
85 88 if ((points.size()<2) || (controlPoints.size()<2)) {
86 89 XYChartItem::setLayout(points);
87 90 m_controlPoints=controlPoints;
88 91 return;
89 92 }
90 93
91 94 Q_ASSERT(points.count()*2-2 == controlPoints.count());
92 95
93 96 QPainterPath splinePath(points.at(0));
94 97
95 98 for (int i = 0; i < points.size() - 1; i++) {
96 99 const QPointF& point = points.at(i + 1);
97 100 splinePath.cubicTo(controlPoints[2*i],controlPoints[2 * i + 1],point);
98 101 }
99 102
100 103 prepareGeometryChange();
101 104 m_path = splinePath;
102 105 m_rect = splinePath.boundingRect();
103 106 XYChartItem::setLayout(points);
104 107 m_controlPoints=controlPoints;
108
105 109 }
106 110
107 111 //handlers
108 112
109 113 void SplineChartItem::handleUpdated()
110 114 {
111 115 m_pointsVisible = m_series->pointsVisible();
112 116 m_linePen = m_series->pen();
113 117 m_pointPen = m_series->pen();
114 118 m_pointPen.setWidthF(2*m_pointPen.width());
115 119 update();
116 120 }
117 121
118 122 //painter
119 123
120 124 void SplineChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
121 125 {
122 126 Q_UNUSED(widget)
123 127 Q_UNUSED(option)
124
128 qDebug()<<__FUNCTION__;
125 129 painter->save();
126 130 painter->setClipRect(clipRect());
127 131 painter->setPen(m_linePen);
128 132 painter->drawPath(m_path);
129 133 if (m_pointsVisible) {
130 134 painter->setPen(m_pointPen);
131 135 painter->drawPoints(points());
132 136 }
133 137 painter->restore();
134 138 }
135 139
136 140
137 141
138 142 #include "moc_splinechartitem_p.cpp"
139 143
140 144 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,475 +1,474
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 /*!
53 53 \fn void QXYSeriesPrivate::pointReplaced(int index)
54 54 \brief \internal \a index
55 55 */
56 56
57 57 /*!
58 58 \fn void QXYSeriesPrivate::pointAdded(int index)
59 59 \brief \internal \a index
60 60 */
61 61
62 62 /*!
63 63 \fn void QXYSeriesPrivate::pointRemoved(int index)
64 64 \brief \internal \a index
65 65 */
66 66
67 67 /*!
68 68 \fn void QXYSeriesPrivate::updated()
69 69 \brief \internal
70 70 */
71 71
72 72 /*!
73 73 \internal
74 74
75 75 Constructs empty series object which is a child of \a parent.
76 76 When series object is added to QChartView or QChart instance ownerships is transferred.
77 77 */
78 78 QXYSeries::QXYSeries(QXYSeriesPrivate &d,QObject *parent) : QAbstractSeries(d, parent)
79 79 {
80 80
81 81 }
82 82 /*!
83 83 Destroys the object. Series added to QChartView or QChart instances are owned by those,
84 84 and are deleted when mentioned object are destroyed.
85 85 */
86 86 QXYSeries::~QXYSeries()
87 87 {
88 88 }
89 89
90 90 /*!
91 91 Adds data point \a x \a y to the series. Points are connected with lines on the chart.
92 92 */
93 93 void QXYSeries::append(qreal x,qreal y)
94 94 {
95 95 append(QPointF(x,y));
96 96 }
97 97
98 98 /*!
99 99 This is an overloaded function.
100 100 Adds data \a point to the series. Points are connected with lines on the chart.
101 101 */
102 102 void QXYSeries::append(const QPointF &point)
103 103 {
104 104 Q_D(QXYSeries);
105 105 d->m_points<<point;
106 106 emit d->pointAdded(d->m_points.count()-1);
107 107 }
108 108
109 109 /*!
110 110 This is an overloaded function.
111 111 Adds list of data \a points to the series. Points are connected with lines on the chart.
112 112 */
113 113 void QXYSeries::append(const QList<QPointF> &points)
114 114 {
115 115 foreach(const QPointF& point , points) {
116 116 append(point);
117 117 }
118 118 }
119 119
120 120
121 121 void QXYSeries::replace(qreal oldX,qreal oldY,qreal newX,qreal newY)
122 122 {
123 123 replace(QPointF(oldX,oldY),QPointF(newX,newY));
124 124 }
125 125
126 126 void QXYSeries::replace(const QPointF &oldPoint,const QPointF &newPoint)
127 127 {
128 128 Q_D(QXYSeries);
129 129 int index = d->m_points.indexOf(oldPoint);
130 130 if(index==-1) return;
131 131 d->m_points[index] = newPoint;
132 132 emit d->pointReplaced(index);
133 133 }
134 134
135 135 /*!
136 136 Removes current \a x and \a y value.
137 137 */
138 138 void QXYSeries::remove(qreal x,qreal y)
139 139 {
140 140 remove(QPointF(x,y));
141 141 }
142 142
143 143 /*!
144 144 Removes current \a point x value. Note \a point y value is ignored.
145 145 */
146 146 void QXYSeries::remove(const QPointF &point)
147 147 {
148 148 Q_D(QXYSeries);
149 149 int index = d->m_points.indexOf(point);
150 150 if(index==-1) return;
151 151 d->m_points.remove(index);
152 152 emit d->pointRemoved(index);
153 153 }
154 154
155 155 /*!
156 156 Removes all data points from the series.
157 157 */
158 158 void QXYSeries::removeAll()
159 159 {
160 160 Q_D(QXYSeries);
161 161 foreach(const QPointF& point, d->m_points) {
162 162 remove(point);
163 163 }
164 164 }
165 165
166 166 /*!
167 167 \internal \a pos
168 168 */
169 169 QList<QPointF> QXYSeries::points() const
170 170 {
171 171 // Q_ASSERT(false);
172 172 Q_D(const QXYSeries);
173 173 if (d->m_model) {
174 174 QList<QPointF> result;
175 175 if (d->m_mapOrientation == Qt::Vertical){
176 176 // consecutive data is read from model's column
177 177
178 178 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
179 179 qreal x = d->m_model->data(d->m_model->index(i, d->m_mapX), Qt::DisplayRole).toReal();
180 180 qreal y = d->m_model->data(d->m_model->index(i, d->m_mapY), Qt::DisplayRole).toReal();
181 181 result << QPointF(x,y);
182 182 }
183 183 return result;
184 184 }
185 185 else{
186 186 // consecutive data is read from model's row
187 187 for(int i = d->m_mapFirst; i< d->m_mapFirst + count(); ++i) {
188 188 qreal x = d->m_model->data(d->m_model->index(d->m_mapX, i), Qt::DisplayRole).toReal();
189 189 qreal y = d->m_model->data(d->m_model->index(d->m_mapY, i), Qt::DisplayRole).toReal();
190 190 result << QPointF(x,y);
191 191 }
192 192 return result;
193 193 }
194 194 } else {
195 195 // model is not specified, return the data from series' internal data store
196 196 return d->m_points.toList();
197 197 }
198 198 }
199 199
200 200 /*!
201 201 Returns number of data points within series.
202 202 */
203 203 int QXYSeries::count() const
204 204 {
205 205 Q_D(const QXYSeries);
206 206
207 207 if (d->m_model) {
208 208 if (d->m_mapOrientation == Qt::Vertical) {
209 209 // data is in a column. Return the number of mapped items if the model's column have enough items
210 210 // or the number of items that can be mapped
211 211 if (d->m_mapCount != -1)
212 212 return qMin(d->m_mapCount, qMax(d->m_model->rowCount() - d->m_mapFirst, 0));
213 213 else
214 214 return qMax(d->m_model->rowCount() - d->m_mapFirst, 0);
215 215 } else {
216 216 // data is in a row. Return the number of mapped items if the model's row have enough items
217 217 // or the number of items that can be mapped
218 218 if (d->m_mapCount != -1)
219 219 return qMin(d->m_mapCount, qMax(d->m_model->columnCount() - d->m_mapFirst, 0));
220 220 else
221 221 return qMax(d->m_model->columnCount() - d->m_mapFirst, 0);
222 222 }
223 223 }
224 224
225 225 // model is not specified, return the number of points in the series internal data store
226 226 return d->m_points.count();
227 227 }
228 228
229 229
230 230 /*!
231 231 Sets \a pen used for drawing points on the chart. If the pen is not defined, the
232 232 pen from chart theme is used.
233 233 \sa QChart::setTheme()
234 234 */
235 235 void QXYSeries::setPen(const QPen &pen)
236 236 {
237 237 Q_D(QXYSeries);
238 238 if (d->m_pen!=pen) {
239 239 d->m_pen = pen;
240 240 emit d->updated();
241 241 }
242 242 }
243 243
244 244 QPen QXYSeries::pen() const
245 245 {
246 246 Q_D(const QXYSeries);
247 247 return d->m_pen;
248 248 }
249 249
250 250 /*!
251 251 Sets \a brush used for drawing points on the chart. If the brush is not defined, brush
252 252 from chart theme setting is used.
253 253 \sa QChart::setTheme()
254 254 */
255 255 void QXYSeries::setBrush(const QBrush &brush)
256 256 {
257 257 Q_D(QXYSeries);
258 258 if (d->m_brush!=brush) {
259 259 d->m_brush = brush;
260 260 emit d->updated();
261 261 }
262 262 }
263 263
264 264 QBrush QXYSeries::brush() const
265 265 {
266 266 Q_D(const QXYSeries);
267 267 return d->m_brush;
268 268 }
269 269
270 270
271 271 /*!
272 272 Sets if data points are \a visible and should be drawn on line.
273 273 */
274 274 void QXYSeries::setPointsVisible(bool visible)
275 275 {
276 276 Q_D(QXYSeries);
277 277 if (d->m_pointsVisible != visible){
278 278 d->m_pointsVisible = visible;
279 279 emit d->updated();
280 280 }
281 281 }
282 282
283 283 /*!
284 284 Returns true if drawing the data points of the series is enabled.
285 285 */
286 286 bool QXYSeries::pointsVisible() const
287 287 {
288 288 Q_D(const QXYSeries);
289 289 return d->m_pointsVisible;
290 290 }
291 291
292 292
293 293 /*!
294 294 Stream operator for adding a data \a point to the series.
295 295 \sa append()
296 296 */
297 297 QXYSeries& QXYSeries::operator<< (const QPointF &point)
298 298 {
299 299 append(point);
300 300 return *this;
301 301 }
302 302
303 303
304 304 /*!
305 305 Stream operator for adding a list of \a points to the series.
306 306 \sa append()
307 307 */
308 308
309 309 QXYSeries& QXYSeries::operator<< (const QList<QPointF>& points)
310 310 {
311 311 append(points);
312 312 return *this;
313 313 }
314 314
315 315 /*!
316 316 \fn bool QXYSeries::setModel(QAbstractItemModel *model)
317 317 Sets the \a model to be used as a data source
318 318 \sa setModelMapping()
319 319 */
320 320 bool QXYSeries::setModel(QAbstractItemModel *model)
321 321 {
322 322 Q_D(QXYSeries);
323 323 // disconnect signals from old model
324 324 if (d->m_model) {
325 325 QObject::disconnect(d->m_model, 0, this, 0);
326 326 d->m_mapX = -1;
327 327 d->m_mapY = -1;
328 328 d->m_mapFirst = 0;
329 329 d->m_mapCount = -1;
330 330 d->m_mapOrientation = Qt::Vertical;
331 331 }
332 332
333 333 // set new model
334 334 if (model) {
335 335 d->m_model = model;
336 336 return true;
337 337 } else {
338 338 d->m_model = 0;
339 339 return false;
340 340 }
341 341 }
342 342
343 343 /*!
344 344 Sets the \a modelX to be used as a data source for x coordinate and \a modelY to be used
345 345 as a data source for y coordinate. The \a orientation parameter specifies whether the data
346 346 is in columns or in rows.
347 347 \sa setModel()
348 348 */
349 349 void QXYSeries::setModelMapping(int modelX, int modelY, Qt::Orientation orientation)
350 350 {
351 351 Q_D(QXYSeries);
352 352 if (d->m_model == 0)
353 353 return;
354 354 d->m_mapX = modelX;
355 355 d->m_mapY = modelY;
356 356 d->m_mapOrientation = orientation;
357 357
358 358 // connect the signals from the model
359 359 connect(d->m_model,SIGNAL(dataChanged(QModelIndex,QModelIndex)), d, SLOT(modelUpdated(QModelIndex,QModelIndex)));
360 360 if (d->m_mapOrientation == Qt::Vertical) {
361 361 connect(d->m_model,SIGNAL(rowsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
362 362 connect(d->m_model,SIGNAL(rowsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
363 363 } else {
364 364 connect(d->m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), d, SLOT(modelDataAdded(QModelIndex,int,int)));
365 365 connect(d->m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), d, SLOT(modelDataRemoved(QModelIndex,int,int)));
366 366 }
367 367 }
368 368
369 369 void QXYSeries::setModelMappingRange(int first, int count)
370 370 {
371 371 Q_D(QXYSeries);
372 372 d->m_mapFirst = qMax(first, 0);
373 373 d->m_mapCount = qMax(count, -1);
374 374 }
375 375
376 376 int QXYSeries::mapX() const
377 377 {
378 378 Q_D(const QXYSeries);
379 379 return d->m_mapX;
380 380 }
381 381
382 382 int QXYSeries::mapY() const
383 383 {
384 384 Q_D(const QXYSeries);
385 385 return d->m_mapY;
386 386
387 387 }
388 388
389 389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
390 390
391 391
392 392 QXYSeriesPrivate::QXYSeriesPrivate(QXYSeries *q) : QAbstractSeriesPrivate(q),
393 393 m_mapX(-1),
394 394 m_mapY(-1),
395 395 m_pointsVisible(false)
396 396 {
397 397 }
398 398
399 399 void QXYSeriesPrivate::scaleDomain(Domain& domain)
400 400 {
401 401 qreal minX(domain.minX());
402 402 qreal minY(domain.minY());
403 403 qreal maxX(domain.maxX());
404 404 qreal maxY(domain.maxY());
405 405 int tickXCount(domain.tickXCount());
406 406 int tickYCount(domain.tickYCount());
407 407
408 408 Q_Q(QXYSeries);
409 409
410 410 const QList<QPointF>& points = q->points();
411 411
412 412 if(points.isEmpty()){
413 413 minX=0.0;
414 414 minY=0.0;
415 415 maxX=1.0;
416 416 maxY=1.0;
417 417 }
418 418
419
420 419 for (int i = 0; i < points.count(); i++)
421 420 {
422 421 qreal x = points[i].x();
423 422 qreal y = points[i].y();
424 423 minX = qMin(minX, x);
425 424 minY = qMin(minY, y);
426 425 maxX = qMax(maxX, x);
427 426 maxY = qMax(maxY, y);
428 427 }
429 428
430 429 domain.setRange(minX,maxX,minY,maxY,tickXCount,tickYCount);
431 430 }
432 431
433 432 QList<LegendMarker*> QXYSeriesPrivate::createLegendMarker(QLegend* legend)
434 433 {
435 434 Q_Q(QXYSeries);
436 435 QList<LegendMarker*> list;
437 436 return list << new XYLegendMarker(q,legend);
438 437 }
439 438
440 439 void QXYSeriesPrivate::modelUpdated(QModelIndex topLeft, QModelIndex bottomRight)
441 440 {
442 441 for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
443 442 for (int column = topLeft.column(); column <= bottomRight.column(); column++) {
444 443 if (m_mapOrientation == Qt::Vertical) {
445 444 if ((column == m_mapX || column == m_mapY) // modified item is in a mapped column
446 445 && row >= m_mapFirst // modfied item in not before first item
447 446 && (m_mapCount == -1 || row < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
448 447 emit pointReplaced(row - m_mapFirst);
449 448 } else {
450 449 if ((row == m_mapX || row == m_mapY) // modified item is in a mapped row
451 450 && column >= m_mapFirst // modfied item in not before first item
452 451 && (m_mapCount == -1 || column < m_mapFirst + m_mapCount)) // map is not limited or item lays before the end of map
453 452 emit pointReplaced(column - m_mapFirst);
454 453 }
455 454 }
456 455 }
457 456 }
458 457
459 458
460 459 void QXYSeriesPrivate::modelDataAdded(QModelIndex parent, int start, int end)
461 460 {
462 461 Q_UNUSED(parent);
463 462 emit pointsAdded(start, end);
464 463 }
465 464
466 465 void QXYSeriesPrivate::modelDataRemoved(QModelIndex parent, int start, int end)
467 466 {
468 467 Q_UNUSED(parent);
469 468 emit pointsRemoved(start, end);
470 469 }
471 470
472 471 #include "moc_qxyseries.cpp"
473 472 #include "moc_qxyseries_p.cpp"
474 473
475 474 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,252 +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 "xychartitem_p.h"
22 22 #include "qxyseries.h"
23 23 #include "qxyseries_p.h"
24 24 #include "chartpresenter_p.h"
25 25 #include "chartanimator_p.h"
26 26 #include <QPainter>
27 27 #include <QGraphicsSceneMouseEvent>
28 28 #include <QAbstractItemModel>
29 29
30 30
31 31 QTCOMMERCIALCHART_BEGIN_NAMESPACE
32 32
33 33 //TODO: optimize : remove points which are not visible
34 34
35 35 XYChartItem::XYChartItem(QXYSeries *series, ChartPresenter *presenter):ChartItem(presenter),
36 36 m_minX(0),
37 37 m_maxX(0),
38 38 m_minY(0),
39 39 m_maxY(0),
40 40 m_series(series)
41 41 {
42 42 connect(series->d_func(),SIGNAL(pointReplaced(int)),this,SLOT(handlePointReplaced(int)));
43 43 connect(series->d_func(),SIGNAL(pointAdded(int)),this,SLOT(handlePointAdded(int)));
44 44 connect(series->d_func(),SIGNAL(pointsAdded(int, int)),this,SLOT(handlePointsAdded(int, int)));
45 45 connect(series->d_func(),SIGNAL(pointRemoved(int)),this,SLOT(handlePointRemoved(int)));
46 46 connect(series->d_func(),SIGNAL(pointsRemoved(int, int)),this,SLOT(handlePointsRemoved(int, int)));
47 47 connect(this,SIGNAL(clicked(QPointF)),series,SIGNAL(clicked(QPointF)));
48 48 }
49 49
50 50 QPointF XYChartItem::calculateGeometryPoint(const QPointF &point) const
51 51 {
52 52 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
53 53 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
54 54 qreal x = (point.x() - m_minX)* deltaX;
55 55 qreal y = (point.y() - m_minY)*-deltaY + m_size.height();
56 56 return QPointF(x,y);
57 57 }
58 58
59 59
60 60 QPointF XYChartItem::calculateGeometryPoint(int index) const
61 61 {
62 62 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
63 63 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
64 64 const QList<QPointF>& vector = m_series->points();
65 65 qreal x = (vector[index].x() - m_minX)* deltaX;
66 66 qreal y = (vector[index].y() - m_minY)*-deltaY + m_size.height();
67 67 return QPointF(x,y);
68 68 }
69 69
70 70 QVector<QPointF> XYChartItem::calculateGeometryPoints() const
71 71 {
72 72 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
73 73 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
74 74
75 75 QVector<QPointF> result;
76 76 result.resize(m_series->count());
77 77 const QList<QPointF>& vector = m_series->points();
78 78 for (int i = 0; i < m_series->count(); ++i) {
79 79 qreal x = (vector[i].x() - m_minX)* deltaX;
80 80 qreal y = (vector[i].y() - m_minY)*-deltaY + m_size.height();
81 81 result[i].setX(x);
82 82 result[i].setY(y);
83 83 }
84 84 return result;
85 85 }
86 86
87 87 QPointF XYChartItem::calculateDomainPoint(const QPointF &point) const
88 88 {
89 89 const qreal deltaX = m_size.width()/(m_maxX-m_minX);
90 90 const qreal deltaY = m_size.height()/(m_maxY-m_minY);
91 91 qreal x = point.x()/deltaX +m_minX;
92 92 qreal y = (point.y()-m_size.height())/(-deltaY)+ m_minY;
93 93 return QPointF(x,y);
94 94 }
95 95
96 96 void XYChartItem::updateLayout(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints,int index)
97 97 {
98 98 if (animator()) {
99 99 animator()->updateLayout(this,oldPoints,newPoints,index);
100 100 } else {
101 101 setLayout(newPoints);
102 102 }
103 103 }
104 104
105 105 void XYChartItem::setLayout(QVector<QPointF> &points)
106 106 {
107 107 m_points = points;
108 108 update();
109 109 }
110 110
111 111 //handlers
112 112
113 113 void XYChartItem::handlePointAdded(int index)
114 114 {
115 115 if (m_series->model() == 0) {
116 116 Q_ASSERT(index<m_series->count());
117 117 Q_ASSERT(index>=0);
118 118 }
119 119 QVector<QPointF> points = m_points;
120 120 QPointF point;
121 121 point = calculateGeometryPoint(index);
122 122 points.insert(index, point);
123 123 updateLayout(m_points, points, index);
124 124 update();
125 125 }
126 126
127 127 void XYChartItem::handlePointsAdded(int start, int end)
128 128 {
129 129 if (m_series->model() == 0) {
130 130 for (int i = start; i <= end; i++)
131 131 handlePointAdded(i);
132 132 } else if (m_series->mapCount() != -1 && start >= m_series->mapFirst() + m_series->mapCount()) {
133 133 return;
134 134 } else {
135 135 int addedCount = end - start + 1;
136 136 if (m_series->mapCount() != -1 && addedCount > m_series->mapCount())
137 137 addedCount = m_series->mapCount();
138 138 int first = qMax(start, m_series->mapFirst()); // get the index of the first item that will be added
139 139 int last = qMin(first + addedCount - 1, m_series->count() + m_series->mapFirst() - 1); // get the index of the last item that will be added
140 140 for (int i = first; i <= last; i++) {
141 141 handlePointAdded(i - m_series->mapFirst());
142 142 }
143 143 // the map is limited therefore the items that are now outside the map
144 144 // need to be removed from the drawn points
145 145 if (m_series->mapCount() != -1 && m_points.size() > m_series->mapCount())
146 146 for (int i = m_points.size() - 1; i >= m_series->mapCount(); i--)
147 147 handlePointRemoved(i);
148 148 }
149 149 }
150 150
151 151 void XYChartItem::handlePointRemoved(int index)
152 152 {
153 153 if (m_series->model() == 0) {
154 154 Q_ASSERT(index<m_series->count() + 1);
155 155 Q_ASSERT(index>=0);
156 156 }
157 157 QVector<QPointF> points = m_points;
158 158 points.remove(index);
159 159 updateLayout(m_points, points, index);
160 160 update();
161 161 }
162 162
163 163 void XYChartItem::handlePointsRemoved(int start, int end)
164 164 {
165 165 Q_UNUSED(start)
166 166 Q_UNUSED(end)
167 167 if (m_series->model() == 0) {
168 168 for (int i = end; i >= start; i--)
169 169 handlePointRemoved(i);
170 170 } else {
171 171 // series uses model as a data source
172 172 int mapFirst = m_series->mapFirst();
173 173 int mapCount = m_series->mapCount();
174 174 int removedCount = end - start + 1;
175 175 if (mapCount != -1 && start >= mapFirst + mapCount) {
176 176 return;
177 177 } else {
178 178 int toRemove = qMin(m_points.size(), removedCount); // first find how many items can actually be removed
179 179 int first = qMax(start, mapFirst); // get the index of the first item that will be removed.
180 180 int last = qMin(first + toRemove - 1, m_points.size() + mapFirst - 1); // get the index of the last item that will be removed.
181 181 for (int i = last; i >= first; i--) {
182 182 handlePointRemoved(i - mapFirst);
183 183
184 184 }
185 185 if (mapCount != -1) {
186 186 int itemsAvailable; // check how many are available to be added
187 187 if (m_series->mapOrientation() == Qt::Vertical)
188 188 itemsAvailable = m_series->model()->rowCount() - mapFirst - m_points.size();
189 189 else
190 190 itemsAvailable = m_series->model()->columnCount() - mapFirst - m_points.size();
191 191 int toBeAdded = qMin(itemsAvailable, mapCount - m_points.size()); // add not more items than there is space left to be filled.
192 192 int currentSize = m_points.size();
193 193 if (toBeAdded > 0)
194 194 for (int i = m_points.size(); i < currentSize + toBeAdded; i++) {
195 195 handlePointAdded(i);
196 196 }
197 197 }
198 198 }
199 199 }
200 200
201 201 }
202 202
203 203 void XYChartItem::handlePointReplaced(int index)
204 204 {
205 205 Q_ASSERT(index<m_series->count());
206 206 Q_ASSERT(index>=0);
207 207 QPointF point = calculateGeometryPoint(index);
208 208 QVector<QPointF> points = m_points;
209 209 points.replace(index,point);
210 210 updateLayout(m_points,points,index);
211 211 update();
212 212 }
213 213
214 214 void XYChartItem::handleDomainChanged(qreal minX, qreal maxX, qreal minY, qreal maxY)
215 215 {
216 216 m_minX=minX;
217 217 m_maxX=maxX;
218 218 m_minY=minY;
219 219 m_maxY=maxY;
220 220 if (isEmpty()) return;
221 221 QVector<QPointF> points = calculateGeometryPoints();
222 222 updateLayout(m_points,points);
223 223 update();
224 224 }
225 225
226 226 void XYChartItem::handleGeometryChanged(const QRectF &rect)
227 227 {
228 228 Q_ASSERT(rect.isValid());
229 229 m_size=rect.size();
230 230 m_clipRect=rect.translated(-rect.topLeft());
231 231 setPos(rect.topLeft());
232 232
233 233 if (isEmpty()) return;
234 234 QVector<QPointF> points = calculateGeometryPoints();
235 235 updateLayout(m_points,points);
236 236 update();
237 237 }
238 238
239 239
240 240 bool XYChartItem::isEmpty()
241 241 {
242 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY);
242 return !m_clipRect.isValid() || qFuzzyIsNull(m_maxX - m_minX) || qFuzzyIsNull(m_maxY - m_minY) || m_series->points().isEmpty();
243 243 }
244 244
245 245 void XYChartItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
246 246 {
247 247 emit clicked(calculateDomainPoint(event->pos()));
248 248 }
249 249
250 250 #include "moc_xychartitem_p.cpp"
251 251
252 252 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,572 +1,568
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(QAxis *)
15 15 Q_DECLARE_METATYPE(QAbstractSeries *)
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<QAbstractSeries *>("series");
160 160 QTest::addColumn<QAxis *>("axis");
161 161
162 162 QAbstractSeries* series0 = new QLineSeries(this);
163 163 QAbstractSeries* series1 = new QAreaSeries(static_cast<QLineSeries*>(series0));
164 164 QAbstractSeries* series2 = new QScatterSeries(this);
165 165 QAbstractSeries* series3 = new QSplineSeries(this);
166 166 QAbstractSeries* series4 = new QPieSeries(this);
167 167 QAbstractSeries* series5 = new QBarSeries(QBarCategories(),this);
168 168 QAbstractSeries* series6 = new QPercentBarSeries(QBarCategories(),this);
169 169 QAbstractSeries* series7 = new QStackedBarSeries(QBarCategories(),this);
170 170
171 171 QAxis* axis = new QAxis(this);
172 172
173 173 QTest::newRow("default axis: lineSeries") << series0 << (QAxis*) 0;
174 174 QTest::newRow("axis0: lineSeries") << series0 << axis;
175 175 QTest::newRow("default axis: areaSeries") << series1 << (QAxis*) 0;
176 176 QTest::newRow("axis: areaSeries") << series1 << axis;
177 177 QTest::newRow("default axis: scatterSeries") << series2 << (QAxis*) 0;
178 178 QTest::newRow("axis1: scatterSeries") << series2 << axis;
179 179 QTest::newRow("default axis: splineSeries") << series3 << (QAxis*) 0;
180 180 QTest::newRow("axis: splineSeries") << series3 << axis;
181 181 QTest::newRow("default axis: pieSeries") << series4 << (QAxis*) 0;
182 182 QTest::newRow("axis: pieSeries") << series4 << axis;
183 183 QTest::newRow("default axis: barSeries") << series5 << (QAxis*) 0;
184 184 QTest::newRow("axis: barSeries") << series5 << axis;
185 185 QTest::newRow("default axis: percentBarSeries") << series6 << (QAxis*) 0;
186 186 QTest::newRow("axis: barSeries") << series6 << axis;
187 187 QTest::newRow("default axis: stackedBarSeries") << series7 << (QAxis*) 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(QAbstractSeries *, series);
195 195 QFETCH(QAxis *, 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 201 m_chart->removeSeries(series);
202 202
203 203 }
204 204
205 205 void tst_QChart::animationOptions_data()
206 206 {
207 207 QTest::addColumn<QChart::AnimationOption>("animationOptions");
208 208 QTest::newRow("AllAnimations") << QChart::AllAnimations;
209 209 QTest::newRow("NoAnimation") << QChart::NoAnimation;
210 210 QTest::newRow("GridAxisAnimations") << QChart::GridAxisAnimations;
211 211 QTest::newRow("SeriesAnimations") << QChart::SeriesAnimations;
212 212 }
213 213
214 214 void tst_QChart::animationOptions()
215 215 {
216 216 createTestData();
217 217 QFETCH(QChart::AnimationOption, animationOptions);
218 218 m_chart->setAnimationOptions(animationOptions);
219 219 QCOMPARE(m_chart->animationOptions(), animationOptions);
220 220 }
221 221
222 222 void tst_QChart::axisX_data()
223 223 {
224 224
225 225 }
226 226
227 227 void tst_QChart::axisX()
228 228 {
229 229 QVERIFY(m_chart->axisX());
230 230 QAxis* axis = m_chart->axisX();
231 231 createTestData();
232 232 //it should be the same axis
233 233 QCOMPARE(axis,m_chart->axisX());
234 234 }
235 235
236 236 void tst_QChart::axisY_data()
237 237 {
238 238 QTest::addColumn<QAxis*>("axis0");
239 239 QTest::addColumn<QAxis*>("axis1");
240 240 QTest::addColumn<QAxis*>("axis2");
241 241 QTest::newRow("1 defualt, 2 optional") << (QAxis*)0 << new QAxis() << new QAxis();
242 242 QTest::newRow("3 optional") << new QAxis() << new QAxis() << new QAxis();
243 243 }
244 244
245 245
246 246 void tst_QChart::axisY()
247 247 {
248 248 QFETCH(QAxis*, axis0);
249 249 QFETCH(QAxis*, axis1);
250 250 QFETCH(QAxis*, axis2);
251 251
252 252 QAxis* defaultAxisY = m_chart->axisY();
253 253
254 254 QVERIFY2(defaultAxisY, "Missing axisY.");
255 255
256 256 QLineSeries* series0 = new QLineSeries();
257 257 m_chart->addSeries(series0, axis0);
258 258
259 259 QLineSeries* series1 = new QLineSeries();
260 260 m_chart->addSeries(series1, axis1);
261 261
262 262 QLineSeries* series2 = new QLineSeries();
263 263 m_chart->addSeries(series2, axis2);
264 264
265 265 if (!axis0)
266 266 axis0 = defaultAxisY;
267 267 if (!axis1)
268 268 axis1 = defaultAxisY;
269 269 if (!axis2)
270 270 axis2 = defaultAxisY;
271 271
272 272 QVERIFY(m_chart->axisY(series0) == axis0);
273 273 QVERIFY(m_chart->axisY(series1) == axis1);
274 274 QVERIFY(m_chart->axisY(series2) == axis2);
275 275 }
276 276
277 277 void tst_QChart::backgroundBrush_data()
278 278 {
279 279 QTest::addColumn<QBrush>("backgroundBrush");
280 280 QTest::newRow("null") << QBrush();
281 281 QTest::newRow("blue") << QBrush(Qt::blue);
282 282 QTest::newRow("white") << QBrush(Qt::white);
283 283 QTest::newRow("black") << QBrush(Qt::black);
284 284 }
285 285
286 286 void tst_QChart::backgroundBrush()
287 287 {
288 288 QFETCH(QBrush, backgroundBrush);
289 289 m_chart->setBackgroundBrush(backgroundBrush);
290 290 QCOMPARE(m_chart->backgroundBrush(), backgroundBrush);
291 291 }
292 292
293 293 void tst_QChart::backgroundPen_data()
294 294 {
295 295 QTest::addColumn<QPen>("backgroundPen");
296 296 QTest::newRow("null") << QPen();
297 297 QTest::newRow("blue") << QPen(Qt::blue);
298 298 QTest::newRow("white") << QPen(Qt::white);
299 299 QTest::newRow("black") << QPen(Qt::black);
300 300 }
301 301
302 302
303 303 void tst_QChart::backgroundPen()
304 304 {
305 305 QFETCH(QPen, backgroundPen);
306 306 m_chart->setBackgroundPen(backgroundPen);
307 307 QCOMPARE(m_chart->backgroundPen(), backgroundPen);
308 308 }
309 309
310 310 void tst_QChart::isBackgroundVisible_data()
311 311 {
312 312 QTest::addColumn<bool>("isBackgroundVisible");
313 313 QTest::newRow("true") << true;
314 314 QTest::newRow("false") << false;
315 315 }
316 316
317 317 void tst_QChart::isBackgroundVisible()
318 318 {
319 319 QFETCH(bool, isBackgroundVisible);
320 320 m_chart->setBackgroundVisible(isBackgroundVisible);
321 321 QCOMPARE(m_chart->isBackgroundVisible(), isBackgroundVisible);
322
323 322 }
324 323
325 324 void tst_QChart::legend_data()
326 325 {
327 326
328 327 }
329 328
330 329 void tst_QChart::legend()
331 330 {
332 331 QVERIFY(m_chart->legend());
333 332 }
334 333
335 334 void tst_QChart::margins_data()
336 335 {
337 336
338 337 }
339 338
340 339 void tst_QChart::margins()
341 {QTest::addColumn<int>("seriesCount");
342 QTest::newRow("0") << 0;
343 QTest::newRow("-1") << -1;
340 {
344 341 createTestData();
345 342 QRectF rect = m_chart->geometry();
346 343
347 344 QVERIFY(m_chart->margins().top()+m_chart->margins().bottom() < rect.height());
348 345 QVERIFY(m_chart->margins().left()+m_chart->margins().right() < rect.width());
349
350 346 }
351 347
352 348 void tst_QChart::removeAllSeries_data()
353 349 {
354 350
355 351 }
356 352
357 353 void tst_QChart::removeAllSeries()
358 354 {
359 355 QLineSeries* series0 = new QLineSeries(this);
360 356 QLineSeries* series1 = new QLineSeries(this);
361 357 QLineSeries* series2 = new QLineSeries(this);
362 358
363 359 m_chart->addSeries(series0);
364 360 m_chart->addSeries(series1);
365 361 m_chart->addSeries(series2);
366 362 m_view->show();
367 363 QTest::qWaitForWindowShown(m_view);
368 364
369 365 QVERIFY(m_chart->axisY(series0)!=0);
370 366 QVERIFY(m_chart->axisY(series1)!=0);
371 367 QVERIFY(m_chart->axisY(series2)!=0);
372 368
373 369 m_chart->removeAllSeries();
374 370
375 371 QVERIFY(m_chart->axisY(series0)==0);
376 372 QVERIFY(m_chart->axisY(series1)==0);
377 373 QVERIFY(m_chart->axisY(series2)==0);
378 374 }
379 375
380 376 void tst_QChart::removeSeries_data()
381 377 {
382 378 addSeries_data();
383 379 }
384 380
385 381 void tst_QChart::removeSeries()
386 382 {
387 383 QFETCH(QAbstractSeries *, series);
388 384 QFETCH(QAxis *, axis);
389 385 m_view->show();
390 386 QTest::qWaitForWindowShown(m_view);
391 387 if(!axis) axis = m_chart->axisY();
392 388 m_chart->addSeries(series,axis);
393 389 QCOMPARE(m_chart->axisY(series),axis);
394 390 m_chart->removeSeries(series);
395 391 QVERIFY(m_chart->axisY(series)==0);
396 392 }
397 393
398 394 void tst_QChart::scrollDown_data()
399 395 {
400 396
401 397 }
402 398
403 399 void tst_QChart::scrollDown()
404 400 {
405 401 createTestData();
406 402 qreal min = m_chart->axisY()->min();
407 403 m_chart->scrollDown();
408 404 QVERIFY(m_chart->axisY()->min()<min);
409 405 }
410 406
411 407 void tst_QChart::scrollLeft_data()
412 408 {
413 409
414 410 }
415 411
416 412 void tst_QChart::scrollLeft()
417 413 {
418 414 createTestData();
419 415 qreal min = m_chart->axisX()->min();
420 416 m_chart->scrollLeft();
421 417 QVERIFY(m_chart->axisX()->min()<min);
422 418 }
423 419
424 420 void tst_QChart::scrollRight_data()
425 421 {
426 422
427 423 }
428 424
429 425 void tst_QChart::scrollRight()
430 426 {
431 427 createTestData();
432 428 qreal min = m_chart->axisX()->min();
433 429 m_chart->scrollRight();
434 430 QVERIFY(m_chart->axisX()->min()>min);
435 431 }
436 432
437 433 void tst_QChart::scrollUp_data()
438 434 {
439 435
440 436 }
441 437
442 438 void tst_QChart::scrollUp()
443 439 {
444 440 createTestData();
445 441 qreal min = m_chart->axisY()->min();
446 442 m_chart->scrollUp();
447 443 QVERIFY(m_chart->axisY()->min()>min);
448 444 }
449 445
450 446 void tst_QChart::theme_data()
451 447 {
452 448 QTest::addColumn<QChart::ChartTheme>("theme");
453 449 QTest::newRow("ChartThemeBlueCerulean") << QChart::ChartThemeBlueCerulean;
454 450 QTest::newRow("ChartThemeBlueIcy") << QChart::ChartThemeBlueIcy;
455 451 QTest::newRow("ChartThemeBlueNcs") << QChart::ChartThemeBlueNcs;
456 452 QTest::newRow("ChartThemeBrownSand") << QChart::ChartThemeBrownSand;
457 453 QTest::newRow("ChartThemeDark") << QChart::ChartThemeDark;
458 454 QTest::newRow("hartThemeHighContrast") << QChart::ChartThemeHighContrast;
459 455 QTest::newRow("ChartThemeLight") << QChart::ChartThemeLight;
460 456 }
461 457
462 458 void tst_QChart::theme()
463 459 {
464 460 QFETCH(QChart::ChartTheme, theme);
465 461 createTestData();
466 462 m_chart->setTheme(theme);
467 463 QVERIFY(m_chart->theme()==theme);
468 464 }
469 465
470 466 void tst_QChart::title_data()
471 467 {
472 468 QTest::addColumn<QString>("title");
473 469 QTest::newRow("null") << QString();
474 470 QTest::newRow("foo") << QString("foo");
475 471 }
476 472
477 473 void tst_QChart::title()
478 474 {
479 475 QFETCH(QString, title);
480 476 m_chart->setTitle(title);
481 477 QCOMPARE(m_chart->title(), title);
482 478 }
483 479
484 480 void tst_QChart::titleBrush_data()
485 481 {
486 482 QTest::addColumn<QBrush>("titleBrush");
487 483 QTest::newRow("null") << QBrush();
488 484 QTest::newRow("blue") << QBrush(Qt::blue);
489 485 QTest::newRow("white") << QBrush(Qt::white);
490 486 QTest::newRow("black") << QBrush(Qt::black);
491 487 }
492 488
493 489 void tst_QChart::titleBrush()
494 490 {
495 491 QFETCH(QBrush, titleBrush);
496 492 m_chart->setTitleBrush(titleBrush);
497 493 QCOMPARE(m_chart->titleBrush(), titleBrush);
498 494 }
499 495
500 496 void tst_QChart::titleFont_data()
501 497 {
502 498 QTest::addColumn<QFont>("titleFont");
503 499 QTest::newRow("null") << QFont();
504 500 QTest::newRow("courier") << QFont("Courier", 8, QFont::Bold, true);
505 501 }
506 502
507 503 void tst_QChart::titleFont()
508 504 {
509 505 QFETCH(QFont, titleFont);
510 506 m_chart->setTitleFont(titleFont);
511 507 QCOMPARE(m_chart->titleFont(), titleFont);
512 508 }
513 509
514 510 void tst_QChart::zoomIn_data()
515 511 {
516 512 QTest::addColumn<QRectF>("rect");
517 513 QTest::newRow("null") << QRectF();
518 514 QTest::newRow("100x100") << QRectF(10,10,100,100);
519 515 QTest::newRow("200x200") << QRectF(10,10,200,200);
520 516 }
521 517
522 518
523 519 void tst_QChart::zoomIn()
524 520 {
525 521 QFETCH(QRectF, rect);
526 522 createTestData();
527 523 QRectF marigns = m_chart->margins();
528 524 rect.adjust(marigns.left(),marigns.top(),-marigns.right(),-marigns.bottom());
529 525 qreal minX = m_chart->axisX()->min();
530 526 qreal minY = m_chart->axisY()->min();
531 527 qreal maxX = m_chart->axisX()->max();
532 528 qreal maxY = m_chart->axisY()->max();
533 529 m_chart->zoomIn(rect);
534 530 if(rect.isValid()){
535 531 QVERIFY(minX<m_chart->axisX()->min());
536 532 QVERIFY(maxX>m_chart->axisX()->max());
537 533 QVERIFY(minY<m_chart->axisY()->min());
538 534 QVERIFY(maxY>m_chart->axisY()->max());
539 535 }
540 536 }
541 537
542 538 void tst_QChart::zoomOut_data()
543 539 {
544 540
545 541 }
546 542
547 543 void tst_QChart::zoomOut()
548 544 {
549 545 createTestData();
550 546 qreal minX = m_chart->axisX()->min();
551 547 qreal minY = m_chart->axisY()->min();
552 548 qreal maxX = m_chart->axisX()->max();
553 549 qreal maxY = m_chart->axisY()->max();
554 550
555 551 m_chart->zoomIn();
556 552
557 553 QVERIFY(minX<m_chart->axisX()->min());
558 554 QVERIFY(maxX>m_chart->axisX()->max());
559 555 QVERIFY(minY<m_chart->axisY()->min());
560 556 QVERIFY(maxY>m_chart->axisY()->max());
561 557
562 558 m_chart->zoomOut();
563 559
564 560 QVERIFY(minX==m_chart->axisX()->min());
565 561 QVERIFY(maxX==m_chart->axisX()->max());
566 562 QVERIFY(minY==m_chart->axisY()->min());
567 563 QVERIFY(maxY==m_chart->axisY()->max());
568 564 }
569 565
570 566 QTEST_MAIN(tst_QChart)
571 567 #include "tst_qchart.moc"
572 568
General Comments 0
You need to be logged in to leave comments. Login now