1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Charts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <QtCharts/QValueAxis>
31#include <private/qvalueaxis_p.h>
32#include <private/chartvalueaxisx_p.h>
33#include <private/chartvalueaxisy_p.h>
34#include <private/abstractdomain_p.h>
35#include <private/polarchartvalueaxisangular_p.h>
36#include <private/polarchartvalueaxisradial_p.h>
37#include <private/chartdataset_p.h>
38#include <private/chartpresenter_p.h>
39#include <private/charttheme_p.h>
40#include <private/charthelpers_p.h>
41
42QT_CHARTS_BEGIN_NAMESPACE
43/*!
44 \class QValueAxis
45 \inmodule QtCharts
46 \brief The QValueAxis class adds values to a chart's axes.
47
48 A value axis can be set up to show an axis line with tick marks, grid lines, and shades.
49 The values on the axis are drawn at the positions of tick marks.
50
51 The following example code illustrates how to use the QValueAxis class:
52 \code
53 QChartView *chartView = new QChartView;
54 QLineSeries *series = new QLineSeries;
55 // ...
56 chartView->chart()->addSeries(series);
57
58 QValueAxis *axisX = new QValueAxis;
59 axisX->setRange(10, 20.5);
60 axisX->setTickCount(10);
61 axisX->setLabelFormat("%.2f");
62 chartView->chart()->setAxisX(axisX, series);
63 \endcode
64*/
65/*!
66 \qmltype ValueAxis
67 \instantiates QValueAxis
68 \inqmlmodule QtCharts
69
70 \inherits AbstractAxis
71 \brief Adds values to a chart's axes.
72
73 The ValueAxis type can be set up to show an axis line with tick marks, grid lines, and shades.
74 The values on the axis are drawn at the positions of tick marks.
75
76 The following example code illustrates how to use the ValueAxis type:
77 \code
78 ChartView {
79 ValueAxis {
80 id: xAxis
81 min: 0
82 max: 10
83 }
84 // Add a few series...
85 }
86 \endcode
87*/
88
89/*!
90 \property QValueAxis::min
91 \brief The minimum value on the axis.
92
93 When setting this property, the maximum value is adjusted if necessary, to ensure that
94 the range remains valid.
95*/
96/*!
97 \qmlproperty real ValueAxis::min
98 The minimum value on the axis.
99
100 When setting this property, the maximum value is adjusted if necessary, to ensure that
101 the range remains valid.
102*/
103
104/*!
105 \property QValueAxis::max
106 \brief The maximum value on the axis.
107
108 When setting this property, the minimum value is adjusted if necessary, to ensure that
109 the range remains valid.
110*/
111/*!
112 \qmlproperty real ValueAxis::max
113 The maximum value on the axis.
114
115 When setting this property, the minimum value is adjusted if necessary, to ensure that
116 the range remains valid.
117*/
118
119/*!
120 \property QValueAxis::tickCount
121 \brief The number of tick marks on the axis. This indicates how many grid lines are drawn on the
122 chart. The default value is 5, and the number cannot be less than 2.
123*/
124/*!
125 \qmlproperty int ValueAxis::tickCount
126 The number of tick marks on the axis. This indicates how many grid lines are drawn on the
127 chart. The default value is 5, and the number cannot be less than 2.
128*/
129
130/*!
131 \property QValueAxis::minorTickCount
132 \brief The number of minor tick marks on the axis. This indicates how many grid lines are drawn
133 between major ticks on the chart. Labels are not drawn for minor ticks. The default value is 0.
134*/
135/*!
136 \qmlproperty int ValueAxis::minorTickCount
137 The number of minor tick marks on the axis. This indicates how many grid lines are drawn
138 between major ticks on the chart. Labels are not drawn for minor ticks. The default value is 0.
139*/
140
141/*!
142 \property QValueAxis::tickAnchor
143 \since 5.12
144 \brief The base value where the dynamically placed tick marks and labels are started from.
145*/
146/*!
147 \qmlproperty real ValueAxis::tickAnchor
148 \since QtCharts 2.3
149 The base value where the dynamically placed tick marks and labels are started from.
150*/
151
152/*!
153 \property QValueAxis::tickInterval
154 \since 5.12
155 \brief The interval between dynamically placed tick marks and labels.
156*/
157/*!
158 \qmlproperty real ValueAxis::tickInterval
159 \since QtCharts 2.3
160 The interval between dynamically placed tick marks and labels.
161*/
162
163/*!
164 \enum QValueAxis::TickType
165
166 This enum describes how the ticks and labels are positioned on the axis.
167
168 \value TicksDynamic Ticks are placed according to tickAnchor and tickInterval values.
169 \value TicksFixed Ticks are placed evenly across the axis range. The tickCount value
170 specifies the number of ticks.
171 */
172/*!
173 \property QValueAxis::tickType
174 \since 5.12
175 \brief The positioning method of tick and labels.
176*/
177/*!
178 \qmlproperty enumeration ValueAxis::tickType
179 \since QtCharts 2.3
180
181 The positioning method of tick and labels.
182
183 \value ValueAxis.TicksDynamic
184 Ticks are placed according to tickAnchor and tickInterval values.
185 \value ValueAxis.TicksFixed
186 Ticks are placed evenly across the axis range. The tickCount value specifies the number of ticks.
187*/
188
189/*!
190 \property QValueAxis::labelFormat
191 \brief The label format of the axis.
192
193 The format string supports the following conversion specifiers, length modifiers, and flags
194 provided by \c printf() in the standard C++ library: d, i, o, x, X, f, F, e, E, g, G, c.
195
196 If QChart::localizeNumbers is \c true, the supported specifiers are limited to:
197 d, e, E, f, g, G, and i. Also, only the precision modifier is supported. The rest of the
198 formatting comes from the default QLocale of the application.
199
200 \sa QString::asprintf()
201*/
202/*!
203 \qmlproperty string ValueAxis::labelFormat
204
205 The format string supports the following conversion specifiers, length modifiers, and flags
206 provided by \c printf() in the standard C++ library: d, i, o, x, X, f, F, e, E, g, G, c.
207
208 If \l{ChartView::localizeNumbers}{ChartView.localizeNumbers} is \c true, the supported
209 specifiers are limited to: d, e, E, f, g, G, and i. Also, only the precision modifier is
210 supported. The rest of the formatting comes from the default QLocale of the application.
211
212 \sa QString::asprintf()
213*/
214
215/*!
216 \fn void QValueAxis::minChanged(qreal min)
217 This signal is emitted when the minimum value of the axis, specified by \a min, changes.
218*/
219
220/*!
221 \fn void QValueAxis::maxChanged(qreal max)
222 This signal is emitted when the maximum value of the axis, specified by \a max, changes.
223*/
224
225/*!
226 \fn void QValueAxis::tickCountChanged(int tickCount)
227 This signal is emitted when the number of tick marks on the axis, specified by \a tickCount,
228 changes.
229*/
230
231/*!
232 \fn void QValueAxis::minorTickCountChanged(int minorTickCount)
233 This signal is emitted when the number of minor tick marks on the axis, specified by
234 \a minorTickCount, changes.
235*/
236
237/*!
238 \fn void QValueAxis::rangeChanged(qreal min, qreal max)
239 This signal is emitted when the minimum or maximum value of the axis, specified by \a min
240 and \a max, changes.
241*/
242
243/*!
244 \qmlsignal ValueAxis::rangeChanged(string min, string max)
245 This signal is emitted when \a min or \a max value of the axis changes.
246
247 The corresponding signal handler is \c onRangeChanged.
248*/
249
250/*!
251 \fn void QValueAxis::labelFormatChanged(const QString &format)
252 This signal is emitted when the \a format of axis labels changes.
253*/
254
255/*!
256 Constructs an axis object that is a child of \a parent.
257*/
258QValueAxis::QValueAxis(QObject *parent) :
259 QAbstractAxis(*new QValueAxisPrivate(this), parent)
260{
261
262}
263
264/*!
265 \internal
266*/
267QValueAxis::QValueAxis(QValueAxisPrivate &d, QObject *parent)
268 : QAbstractAxis(d, parent)
269{
270
271}
272
273/*!
274 Destroys the object.
275*/
276QValueAxis::~QValueAxis()
277{
278 Q_D(QValueAxis);
279 if (d->m_chart)
280 d->m_chart->removeAxis(axis: this);
281}
282
283void QValueAxis::setMin(qreal min)
284{
285 Q_D(QValueAxis);
286 setRange(min, max: qMax(a: d->m_max, b: min));
287}
288
289qreal QValueAxis::min() const
290{
291 Q_D(const QValueAxis);
292 return d->m_min;
293}
294
295void QValueAxis::setMax(qreal max)
296{
297 Q_D(QValueAxis);
298 setRange(min: qMin(a: d->m_min, b: max), max);
299}
300
301qreal QValueAxis::max() const
302{
303 Q_D(const QValueAxis);
304 return d->m_max;
305}
306
307/*!
308 Sets the range from \a min to \a max on the axis.
309 If \a min is greater than \a max, this function returns without making any changes.
310*/
311void QValueAxis::setRange(qreal min, qreal max)
312{
313 Q_D(QValueAxis);
314 d->setRange(min,max);
315}
316
317void QValueAxis::setTickCount(int count)
318{
319 Q_D(QValueAxis);
320 if (d->m_tickCount != count && count >= 2) {
321 d->m_tickCount = count;
322 emit tickCountChanged(tickCount: count);
323 }
324}
325
326int QValueAxis::tickCount() const
327{
328 Q_D(const QValueAxis);
329 return d->m_tickCount;
330}
331
332void QValueAxis::setMinorTickCount(int count)
333{
334 Q_D(QValueAxis);
335 if (d->m_minorTickCount != count && count >= 0) {
336 d->m_minorTickCount = count;
337 emit minorTickCountChanged(tickCount: count);
338 }
339}
340
341int QValueAxis::minorTickCount() const
342{
343 Q_D(const QValueAxis);
344 return d->m_minorTickCount;
345}
346
347
348void QValueAxis::setTickInterval(qreal interval)
349{
350 Q_D(QValueAxis);
351 if (d->m_tickInterval != interval) {
352 d->m_tickInterval = interval;
353 emit tickIntervalChanged(interval);
354 }
355}
356
357qreal QValueAxis::tickInterval() const
358{
359 Q_D(const QValueAxis);
360 return d->m_tickInterval;
361}
362
363void QValueAxis::setTickAnchor(qreal anchor)
364{
365 Q_D(QValueAxis);
366 if (d->m_tickAnchor != anchor) {
367 d->m_tickAnchor = anchor;
368 emit tickAnchorChanged(anchor);
369 }
370}
371
372qreal QValueAxis::tickAnchor() const
373{
374 Q_D(const QValueAxis);
375 return d->m_tickAnchor;
376}
377
378void QValueAxis::setTickType(QValueAxis::TickType type)
379{
380 Q_D(QValueAxis);
381 if (d->m_tickType != type) {
382 d->m_tickType = type;
383 emit tickTypeChanged(type);
384 }
385}
386
387QValueAxis::TickType QValueAxis::tickType() const
388{
389 Q_D(const QValueAxis);
390 return d->m_tickType;
391}
392
393void QValueAxis::setLabelFormat(const QString &format)
394{
395 Q_D(QValueAxis);
396 d->m_format = format;
397 emit labelFormatChanged(format);
398}
399
400QString QValueAxis::labelFormat() const
401{
402 Q_D(const QValueAxis);
403 return d->m_format;
404}
405
406/*!
407 Returns the type of the axis.
408*/
409QAbstractAxis::AxisType QValueAxis::type() const
410{
411 return AxisTypeValue;
412}
413
414/*!
415 \qmlmethod ValueAxis::applyNiceNumbers()
416 Modifies the current range and number of tick marks on the axis to look
417 \e nice. The algorithm considers numbers that can be expressed as a form of
418 1*10^n, 2* 10^n, or 5*10^n to be nice numbers. These numbers are used for
419 setting spacing for the tick marks.
420*/
421
422/*!
423 Modifies the current range and number of tick marks on the axis to look \e nice. The algorithm
424 considers numbers that can be expressed as a form of 1*10^n, 2* 10^n, or 5*10^n to be
425 nice numbers. These numbers are used for setting spacing for the tick marks.
426
427 \sa setRange(), setTickCount()
428*/
429void QValueAxis::applyNiceNumbers()
430{
431 Q_D(QValueAxis);
432 if(d->m_applying) return;
433 qreal min = d->m_min;
434 qreal max = d->m_max;
435 int ticks = d->m_tickCount;
436 AbstractDomain::looseNiceNumbers(min,max,ticksCount&: ticks);
437 d->m_applying=true;
438 d->setRange(min,max);
439 setTickCount(ticks);
440 d->m_applying=false;
441}
442
443/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
444
445QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q)
446 : QAbstractAxisPrivate(q),
447 m_min(0),
448 m_max(0),
449 m_tickCount(5),
450 m_minorTickCount(0),
451 m_format(),
452 m_applying(false),
453 m_tickInterval(0.0),
454 m_tickAnchor(0.0),
455 m_tickType(QValueAxis::TicksFixed)
456{
457
458}
459
460QValueAxisPrivate::~QValueAxisPrivate()
461{
462
463}
464
465void QValueAxisPrivate::setMin(const QVariant &min)
466{
467 Q_Q(QValueAxis);
468 bool ok;
469 qreal value = min.toReal(ok: &ok);
470 if (ok)
471 q->setMin(value);
472}
473
474void QValueAxisPrivate::setMax(const QVariant &max)
475{
476 Q_Q(QValueAxis);
477 bool ok;
478 qreal value = max.toReal(ok: &ok);
479 if (ok)
480 q->setMax(value);
481}
482
483void QValueAxisPrivate::setRange(const QVariant &min, const QVariant &max)
484{
485 Q_Q(QValueAxis);
486 bool ok1;
487 bool ok2;
488 qreal value1 = min.toReal(ok: &ok1);
489 qreal value2 = max.toReal(ok: &ok2);
490 if (ok1 && ok2)
491 q->setRange(min: value1, max: value2);
492}
493
494void QValueAxisPrivate::setRange(qreal min, qreal max)
495{
496 Q_Q(QValueAxis);
497 bool changed = false;
498
499 if (min > max)
500 return;
501
502 if (!isValidValue(x: min, y: max)) {
503 qWarning() << "Attempting to set invalid range for value axis: ["
504 << min << " - " << max << "]";
505 return;
506 }
507
508 if (m_min != min) {
509 m_min = min;
510 changed = true;
511 emit q->minChanged(min);
512 }
513
514 if (m_max != max) {
515 m_max = max;
516 changed = true;
517 emit q->maxChanged(max);
518 }
519
520 if (changed) {
521 emit rangeChanged(min,max);
522 emit q->rangeChanged(min, max);
523 }
524}
525
526void QValueAxisPrivate::initializeGraphics(QGraphicsItem *parent)
527{
528 Q_Q(QValueAxis);
529 ChartAxisElement *axis(0);
530
531 if (m_chart->chartType() == QChart::ChartTypeCartesian) {
532 if (orientation() == Qt::Vertical)
533 axis = new ChartValueAxisY(q,parent);
534 if (orientation() == Qt::Horizontal)
535 axis = new ChartValueAxisX(q,parent);
536 axis->setLabelsEditable(q->labelsEditable());
537 }
538
539 if (m_chart->chartType() == QChart::ChartTypePolar) {
540 if (orientation() == Qt::Vertical)
541 axis = new PolarChartValueAxisRadial(q, parent);
542 if (orientation() == Qt::Horizontal)
543 axis = new PolarChartValueAxisAngular(q, parent);
544 }
545
546 m_item.reset(other: axis);
547 QAbstractAxisPrivate::initializeGraphics(parent);
548}
549
550
551void QValueAxisPrivate::initializeDomain(AbstractDomain *domain)
552{
553 if (orientation() == Qt::Vertical) {
554 if (!qFuzzyIsNull(d: m_max - m_min))
555 domain->setRangeY(min: m_min, max: m_max);
556 else
557 setRange(min: domain->minY(), max: domain->maxY());
558 }
559 if (orientation() == Qt::Horizontal) {
560 if (!qFuzzyIsNull(d: m_max - m_min))
561 domain->setRangeX(min: m_min, max: m_max);
562 else
563 setRange(min: domain->minX(), max: domain->maxX());
564 }
565}
566
567QT_CHARTS_END_NAMESPACE
568
569#include "moc_qvalueaxis.cpp"
570#include "moc_qvalueaxis_p.cpp"
571

source code of qtcharts/src/charts/axis/valueaxis/qvalueaxis.cpp