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

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