##// END OF EJS Templates
Fix crash when axis range is infinite....
Miikka Heikkinen -
r2875:6961daf29fe7
parent child
Show More
@@ -1,458 +1,464
1 1 /******************************************************************************
2 2 **
3 3 ** Copyright (C) 2015 The Qt Company Ltd.
4 4 ** Contact: http://www.qt.io/licensing/
5 5 **
6 6 ** This file is part of the Qt Charts module.
7 7 **
8 8 ** $QT_BEGIN_LICENSE:COMM$
9 9 **
10 10 ** Commercial License Usage
11 11 ** Licensees holding valid commercial Qt licenses may use this file in
12 12 ** accordance with the commercial license agreement provided with the
13 13 ** Software or, alternatively, in accordance with the terms contained in
14 14 ** a written agreement between you and The Qt Company. For licensing terms
15 15 ** and conditions see http://www.qt.io/terms-conditions. For further
16 16 ** information use the contact form at http://www.qt.io/contact-us.
17 17 **
18 18 ** $QT_END_LICENSE$
19 19 **
20 20 ******************************************************************************/
21 21
22 22 #include <QtCharts/QValueAxis>
23 23 #include <private/qvalueaxis_p.h>
24 24 #include <private/chartvalueaxisx_p.h>
25 25 #include <private/chartvalueaxisy_p.h>
26 26 #include <private/abstractdomain_p.h>
27 27 #include <private/polarchartvalueaxisangular_p.h>
28 28 #include <private/polarchartvalueaxisradial_p.h>
29 29 #include <private/chartdataset_p.h>
30 30 #include <private/chartpresenter_p.h>
31 31 #include <private/charttheme_p.h>
32
32 #include <private/charthelpers_p.h>
33 33
34 34 QT_CHARTS_BEGIN_NAMESPACE
35 35 /*!
36 36 \class QValueAxis
37 37 \inmodule Qt Charts
38 38 \brief The QValueAxis class is used for manipulating chart's axis.
39 39
40 40 ValueAxis can be setup to show axis line with tick marks, grid lines and shades.
41 41 Values of axis are drawn to position of ticks.
42 42
43 43 Example code on how to use QValueAxis.
44 44 \code
45 45 QChartView *chartView = new QChartView;
46 46 QLineSeries *series = new QLineSeries;
47 47 // ...
48 48 chartView->chart()->addSeries(series);
49 49
50 50 QValueAxis *axisX = new QValueAxis;
51 51 axisX->setRange(10, 20.5);
52 52 axisX->setTickCount(10);
53 53 axisX->setLabelFormat("%.2f");
54 54 chartView->chart()->setAxisX(axisX, series);
55 55 \endcode
56 56 */
57 57 /*!
58 58 \qmltype ValueAxis
59 59 \instantiates QValueAxis
60 60 \inqmlmodule QtCharts
61 61
62 62 \inherits AbstractAxis
63 63 \brief The ValueAxis element is used for manipulating chart's axes
64 64
65 65 ValueAxis can be setup to show axis line with tick marks, grid lines and shades.
66 66 Values of axis are drawn to position of ticks
67 67
68 68 Example about using ValueAxis:
69 69 \code
70 70 ChartView {
71 71 ValueAxis {
72 72 id: xAxis
73 73 min: 0
74 74 max: 10
75 75 }
76 76 // Add a few series...
77 77 }
78 78 \endcode
79 79 */
80 80
81 81 /*!
82 82 \property QValueAxis::min
83 83 Defines the minimum value on the axis.
84 84 When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
85 85 */
86 86 /*!
87 87 \qmlproperty real ValueAxis::min
88 88 Defines the minimum value on the axis.
89 89 When setting this property the max is adjusted if necessary, to ensure that the range remains valid.
90 90 */
91 91
92 92 /*!
93 93 \property QValueAxis::max
94 94 Defines the maximum value on the axis.
95 95 When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
96 96 */
97 97 /*!
98 98 \qmlproperty real ValueAxis::max
99 99 Defines the maximum value on the axis.
100 100 When setting this property the min is adjusted if necessary, to ensure that the range remains valid.
101 101 */
102 102
103 103 /*!
104 104 \property QValueAxis::tickCount
105 105 Defines the number of ticks on the axis. This indicates how many grid lines are drawn on the
106 106 chart. The default value is 5, and it can not be below 2.
107 107 */
108 108 /*!
109 109 \qmlproperty int ValueAxis::tickCount
110 110 Defines the number of ticks on the axis. This indicates how many grid lines are drawn on the
111 111 chart. The default value is 5, and it can not be below 2.
112 112 */
113 113
114 114 /*!
115 115 \property QValueAxis::minorTickCount
116 116 Defines the number of minor ticks on the axis. This indicates how many grid lines are drawn
117 117 between major ticks on the chart. Labels are not drawn for minor ticks. The default value is 0.
118 118 */
119 119 /*!
120 120 \qmlproperty int ValueAxis::minorTickCount
121 121 Defines the number of minor ticks on the axis. This indicates how many grid lines are drawn
122 122 between major ticks on the chart. Labels are not drawn for minor ticks. The default value is 0.
123 123 */
124 124
125 125 /*!
126 126 \property QValueAxis::labelFormat
127 127 Defines the label format of the axis.
128 128 Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, and c.
129 129 See QString::sprintf() for additional details.
130 130
131 131 If the QChart::localizeNumbers is \c{true}, the supported specifiers are limited to: d, e, E, f,
132 132 g, G, and i. Also, only the precision modifier is supported. The rest of the formatting comes from
133 133 the default QLocale of the application.
134 134 */
135 135 /*!
136 136 \qmlproperty real ValueAxis::labelFormat
137 137 Defines the label format of the axis.
138 138 Supported specifiers are: d, i, o, x, X, f, F, e, E, g, G, and c.
139 139 See QString::sprintf() for additional details.
140 140
141 141 If the ChartView::localizeNumbers is \c{true}, the supported specifiers are limited to: d, e, E, f,
142 142 g, G, and i. Also, only the precision modifier is supported. The rest of the formatting comes from
143 143 the default QLocale of the application.
144 144 */
145 145
146 146 /*!
147 147 \fn void QValueAxis::minChanged(qreal min)
148 148 Axis emits signal when \a min of axis has changed.
149 149 */
150 150 /*!
151 151 \qmlsignal ValueAxis::onMinChanged(real min)
152 152 Axis emits signal when \a min of axis has changed.
153 153 */
154 154
155 155 /*!
156 156 \fn void QValueAxis::maxChanged(qreal max)
157 157 Axis emits signal when \a max of axis has changed.
158 158 */
159 159 /*!
160 160 \qmlsignal ValueAxis::onMaxChanged(real max)
161 161 Axis emits signal when \a max of axis has changed.
162 162 */
163 163
164 164 /*!
165 165 \fn void QValueAxis::tickCountChanged(int tickCount)
166 166 Axis emits signal when \a tickCount of axis has changed.
167 167 */
168 168 /*!
169 169 \qmlsignal ValueAxis::tickCountChanged(int tickCount)
170 170 Axis emits signal when \a tickCount of axis has changed.
171 171 */
172 172
173 173 /*!
174 174 \fn void QValueAxis::minorTickCountChanged(int minorTickCount)
175 175 Axis emits signal when \a minorTickCount of axis has changed.
176 176 */
177 177 /*!
178 178 \qmlsignal ValueAxis::minorTickCountChanged(int minorTickCount)
179 179 Axis emits signal when \a minorTickCount of axis has changed.
180 180 */
181 181
182 182 /*!
183 183 \fn void QValueAxis::rangeChanged(qreal min, qreal max)
184 184 Axis emits signal when \a min or \a max of axis has changed.
185 185 */
186 186
187 187 /*!
188 188 \fn void QValueAxis::labelFormatChanged(const QString &format)
189 189 Axis emits signal when \a format of axis labels has changed.
190 190 */
191 191 /*!
192 192 \qmlsignal ValueAxis::labelFormatChanged(const QString &format)
193 193 Axis emits signal when \a format of axis labels has changed.
194 194 */
195 195
196 196 /*!
197 197 Constructs an axis object which is a child of \a parent.
198 198 */
199 199 QValueAxis::QValueAxis(QObject *parent) :
200 200 QAbstractAxis(*new QValueAxisPrivate(this), parent)
201 201 {
202 202
203 203 }
204 204
205 205 /*!
206 206 \internal
207 207 */
208 208 QValueAxis::QValueAxis(QValueAxisPrivate &d, QObject *parent)
209 209 : QAbstractAxis(d, parent)
210 210 {
211 211
212 212 }
213 213
214 214 /*!
215 215 Destroys the object
216 216 */
217 217 QValueAxis::~QValueAxis()
218 218 {
219 219 Q_D(QValueAxis);
220 220 if (d->m_chart)
221 221 d->m_chart->removeAxis(this);
222 222 }
223 223
224 224 void QValueAxis::setMin(qreal min)
225 225 {
226 226 Q_D(QValueAxis);
227 227 setRange(min, qMax(d->m_max, min));
228 228 }
229 229
230 230 qreal QValueAxis::min() const
231 231 {
232 232 Q_D(const QValueAxis);
233 233 return d->m_min;
234 234 }
235 235
236 236 void QValueAxis::setMax(qreal max)
237 237 {
238 238 Q_D(QValueAxis);
239 239 setRange(qMin(d->m_min, max), max);
240 240 }
241 241
242 242 qreal QValueAxis::max() const
243 243 {
244 244 Q_D(const QValueAxis);
245 245 return d->m_max;
246 246 }
247 247
248 248 /*!
249 249 Sets range from \a min to \a max on the axis.
250 250 If min is greater than max then this function returns without making any changes.
251 251 */
252 252 void QValueAxis::setRange(qreal min, qreal max)
253 253 {
254 254 Q_D(QValueAxis);
255 255 d->setRange(min,max);
256 256 }
257 257
258 258 void QValueAxis::setTickCount(int count)
259 259 {
260 260 Q_D(QValueAxis);
261 261 if (d->m_tickCount != count && count >= 2) {
262 262 d->m_tickCount = count;
263 263 emit tickCountChanged(count);
264 264 }
265 265 }
266 266
267 267 int QValueAxis::tickCount() const
268 268 {
269 269 Q_D(const QValueAxis);
270 270 return d->m_tickCount;
271 271 }
272 272
273 273 void QValueAxis::setMinorTickCount(int count)
274 274 {
275 275 Q_D(QValueAxis);
276 276 if (d->m_minorTickCount != count && count >= 0) {
277 277 d->m_minorTickCount = count;
278 278 emit minorTickCountChanged(count);
279 279 }
280 280 }
281 281
282 282 int QValueAxis::minorTickCount() const
283 283 {
284 284 Q_D(const QValueAxis);
285 285 return d->m_minorTickCount;
286 286 }
287 287
288 288 void QValueAxis::setLabelFormat(const QString &format)
289 289 {
290 290 Q_D(QValueAxis);
291 291 d->m_format = format;
292 292 emit labelFormatChanged(format);
293 293 }
294 294
295 295 QString QValueAxis::labelFormat() const
296 296 {
297 297 Q_D(const QValueAxis);
298 298 return d->m_format;
299 299 }
300 300
301 301 /*!
302 302 Returns the type of the axis
303 303 */
304 304 QAbstractAxis::AxisType QValueAxis::type() const
305 305 {
306 306 return AxisTypeValue;
307 307 }
308 308
309 309 /*!
310 310 This method modifies range and number of ticks on the axis to look "nice". Algorithm considers numbers that
311 311 can be expressed as form of 1*10^n, 2* 10^n or 5*10^n as a nice numbers. These numbers are used for spacing the ticks.
312 312 This method will modify the current range and number of ticks.
313 313 \sa setRange(), setTickCount()
314 314 */
315 315 void QValueAxis::applyNiceNumbers()
316 316 {
317 317 Q_D(QValueAxis);
318 318 if(d->m_applying) return;
319 319 qreal min = d->m_min;
320 320 qreal max = d->m_max;
321 321 int ticks = d->m_tickCount;
322 322 AbstractDomain::looseNiceNumbers(min,max,ticks);
323 323 d->m_applying=true;
324 324 d->setRange(min,max);
325 325 setTickCount(ticks);
326 326 d->m_applying=false;
327 327 }
328 328
329 329 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
330 330
331 331 QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q)
332 332 : QAbstractAxisPrivate(q),
333 333 m_min(0),
334 334 m_max(0),
335 335 m_tickCount(5),
336 336 m_minorTickCount(0),
337 337 m_format(QString::null),
338 338 m_applying(false)
339 339 {
340 340
341 341 }
342 342
343 343 QValueAxisPrivate::~QValueAxisPrivate()
344 344 {
345 345
346 346 }
347 347
348 348 void QValueAxisPrivate::setMin(const QVariant &min)
349 349 {
350 350 Q_Q(QValueAxis);
351 351 bool ok;
352 352 qreal value = min.toReal(&ok);
353 353 if (ok)
354 354 q->setMin(value);
355 355 }
356 356
357 357 void QValueAxisPrivate::setMax(const QVariant &max)
358 358 {
359 359 Q_Q(QValueAxis);
360 360 bool ok;
361 361 qreal value = max.toReal(&ok);
362 362 if (ok)
363 363 q->setMax(value);
364 364 }
365 365
366 366 void QValueAxisPrivate::setRange(const QVariant &min, const QVariant &max)
367 367 {
368 368 Q_Q(QValueAxis);
369 369 bool ok1;
370 370 bool ok2;
371 371 qreal value1 = min.toReal(&ok1);
372 372 qreal value2 = max.toReal(&ok2);
373 373 if (ok1 && ok2)
374 374 q->setRange(value1, value2);
375 375 }
376 376
377 377 void QValueAxisPrivate::setRange(qreal min, qreal max)
378 378 {
379 379 Q_Q(QValueAxis);
380 380 bool changed = false;
381 381
382 382 if (min > max)
383 383 return;
384 384
385 if (!isValidValue(min, max)) {
386 qWarning() << "Attempting to set invalid range for value axis: ["
387 << min << " - " << max << "]";
388 return;
389 }
390
385 391 bool changeMin = false;
386 392 if (m_min == 0 || min == 0)
387 393 changeMin = !qFuzzyCompare(1 + m_min, 1 + min);
388 394 else
389 395 changeMin = !qFuzzyCompare(m_min, min);
390 396
391 397 bool changeMax = false;
392 398 if (m_max == 0 || max == 0)
393 399 changeMax = !qFuzzyCompare(1 + m_max, 1 + max);
394 400 else
395 401 changeMax = !qFuzzyCompare(m_max, max);
396 402
397 403 if (changeMin) {
398 404 m_min = min;
399 405 changed = true;
400 406 emit q->minChanged(min);
401 407 }
402 408
403 409 if (changeMax) {
404 410 m_max = max;
405 411 changed = true;
406 412 emit q->maxChanged(max);
407 413 }
408 414
409 415 if (changed) {
410 416 emit rangeChanged(min,max);
411 417 emit q->rangeChanged(min, max);
412 418 }
413 419 }
414 420
415 421 void QValueAxisPrivate::initializeGraphics(QGraphicsItem *parent)
416 422 {
417 423 Q_Q(QValueAxis);
418 424 ChartAxisElement *axis(0);
419 425
420 426 if (m_chart->chartType() == QChart::ChartTypeCartesian) {
421 427 if (orientation() == Qt::Vertical)
422 428 axis = new ChartValueAxisY(q,parent);
423 429 if (orientation() == Qt::Horizontal)
424 430 axis = new ChartValueAxisX(q,parent);
425 431 }
426 432
427 433 if (m_chart->chartType() == QChart::ChartTypePolar) {
428 434 if (orientation() == Qt::Vertical)
429 435 axis = new PolarChartValueAxisRadial(q, parent);
430 436 if (orientation() == Qt::Horizontal)
431 437 axis = new PolarChartValueAxisAngular(q, parent);
432 438 }
433 439
434 440 m_item.reset(axis);
435 441 QAbstractAxisPrivate::initializeGraphics(parent);
436 442 }
437 443
438 444
439 445 void QValueAxisPrivate::initializeDomain(AbstractDomain *domain)
440 446 {
441 447 if (orientation() == Qt::Vertical) {
442 448 if (!qFuzzyIsNull(m_max - m_min))
443 449 domain->setRangeY(m_min, m_max);
444 450 else
445 451 setRange(domain->minY(), domain->maxY());
446 452 }
447 453 if (orientation() == Qt::Horizontal) {
448 454 if (!qFuzzyIsNull(m_max - m_min))
449 455 domain->setRangeX(m_min, m_max);
450 456 else
451 457 setRange(domain->minX(), domain->maxX());
452 458 }
453 459 }
454 460
455 461 #include "moc_qvalueaxis.cpp"
456 462 #include "moc_qvalueaxis_p.cpp"
457 463
458 464 QT_CHARTS_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now