1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtGraphs/QValueAxis>
5#include <private/qvalueaxis_p.h>
6#include <private/charthelpers_p.h>
7#include <QtCore/QtMath>
8
9QT_BEGIN_NAMESPACE
10/*!
11 \class QValueAxis
12 \inmodule QtGraphs
13 \ingroup graphs_2D
14 \brief The QValueAxis class adds values to a graph's axes.
15
16 A value axis can be set up to show an axis line with tick marks, grid lines, and shades.
17 The values on the axis are drawn at the positions of tick marks.
18*/
19/*!
20 \qmltype ValueAxis
21 \nativetype QValueAxis
22 \inqmlmodule QtGraphs
23 \ingroup graphs_qml_2D
24 \inherits AbstractAxis
25 \brief Adds values to a graph's axes.
26
27 The ValueAxis type can be set up to show an axis line with tick marks, grid lines, and shades.
28 The values on the axis are drawn at the positions of tick marks.
29
30 The following example code illustrates how to use the ValueAxis type:
31 \code
32 GraphsView {
33 axisX: ValueAxis {
34 max: 10
35 tickInterval: 1
36 }
37 axisY: ValueAxis {
38 min -20
39 max: 40
40 }
41 LineSeries {
42 // Add a few XYPoint data...
43 }
44 }
45 \endcode
46*/
47
48/*!
49 \property QValueAxis::min
50 \brief The minimum value on the axis.
51
52 When setting this property, the maximum value is adjusted if necessary, to ensure that
53 the range remains valid.
54 The default value is 0.0
55*/
56/*!
57 \qmlproperty real ValueAxis::min
58 The minimum value on the axis.
59
60 When setting this property, the maximum value is adjusted if necessary, to ensure that
61 the range remains valid.
62 The default value is 0.0
63*/
64
65/*!
66 \property QValueAxis::max
67 \brief The maximum value on the axis.
68
69 When setting this property, the minimum value is adjusted if necessary, to ensure that
70 the range remains valid.
71 The default value is 10.0
72*/
73/*!
74 \qmlproperty real ValueAxis::max
75 The maximum value on the axis.
76
77 When setting this property, the minimum value is adjusted if necessary, to ensure that
78 the range remains valid.
79 The default value is 10.0
80*/
81
82/*!
83 \property QValueAxis::subTickCount
84 \brief The number of subticks on the axis. This indicates how many subticks are drawn
85 between major lines on the graph. Labels are not drawn for subticks. The default value is 0.
86*/
87/*!
88 \qmlproperty int ValueAxis::subTickCount
89 The number of subticks on the axis. This indicates how many subticks are drawn
90 between major lines on the graph. Labels are not drawn for subticks. The default value is 0.
91*/
92
93/*!
94 \property QValueAxis::tickAnchor
95 \brief The base value where the dynamically placed tick marks and labels are started from.
96 The default value is 0.
97 */
98/*!
99 \qmlproperty real ValueAxis::tickAnchor
100 The base value where the dynamically placed tick marks and labels are started from.
101 The default value is 0.
102 */
103
104/*!
105 \property QValueAxis::tickInterval
106 \brief The interval between dynamically placed tick marks and labels.
107 The default value is 0, which means that intervals are automatically calculated
108 based on the min and max range.
109*/
110/*!
111 \qmlproperty real ValueAxis::tickInterval
112 The interval between dynamically placed tick marks and labels.
113 The default value is 0, which means that intervals are automatically calculated
114 based on the min and max range.
115*/
116
117/*!
118 \property QValueAxis::labelFormat
119 \brief The label format of the axis.
120
121 The format string supports the following conversion specifiers, length modifiers, and flags
122 provided by \c printf() in the standard C++ library: d, i, o, x, X, f, F, e, E, g, G, c.
123
124 The default value is empty, in which case 'f' format is used.
125
126 \sa QString::asprintf()
127*/
128/*!
129 \qmlproperty string ValueAxis::labelFormat
130
131 The format string supports the following conversion specifiers, length modifiers, and flags
132 provided by \c printf() in the standard C++ library: d, i, o, x, X, f, F, e, E, g, G, c.
133
134 The default value is empty, in which case 'f' format is used.
135
136 \sa QString::asprintf()
137*/
138
139/*!
140 \property QValueAxis::labelDecimals
141 \brief The number of decimals used for showing the labels. When set to -1, decimal amount
142 is adjusted automatically based on the values range. The default value is -1.
143*/
144/*!
145 \qmlproperty int ValueAxis::labelDecimals
146 The number of decimals used for showing the labels. When set to -1, decimal amount
147 is adjusted automatically based on the values range. The default value is -1.
148*/
149
150/*!
151 \property QValueAxis::zoom
152 \since 6.9
153 \brief The zoom value of the axis.
154
155 The zoom value enlarges or shrinks the axis and thus the graph without affecting intervals
156 of grid and labels. The default value is 1.
157*/
158/*!
159 \qmlproperty real ValueAxis::zoom
160 \since 6.9
161 The zoom value of the axis.
162
163 The zoom value enlarges or shrinks the axis and thus the graph without affecting intervals
164 of grid and labels. The default value is 1.
165*/
166
167/*!
168 \property QValueAxis::pan
169 \since 6.9
170 \brief The pan value of the axis.
171
172 The pan value moves the center of the axis without affecting intervals
173 of grid and labels. The default value is 0.
174*/
175/*!
176 \qmlproperty real ValueAxis::pan
177 \since 6.9
178 The pan value of the axis.
179
180 The pan value moves the center of the axis without affecting intervals
181 of grid and labels. The default value is 0.
182*/
183
184/*!
185 \qmlsignal ValueAxis::minChanged(real min)
186 This signal is emitted when the minimum value of the axis changes to \a min.
187*/
188
189/*!
190 \qmlsignal ValueAxis::maxChanged(real max)
191 This signal is emitted when the maximum value of the axis changes to \a max.
192*/
193
194/*!
195 \qmlsignal ValueAxis::subTickCountChanged(int subTickCount)
196 This signal is emitted when the number of subticks on the axis, specified by
197 \a subTickCount, changes.
198*/
199
200/*!
201 \qmlsignal ValueAxis::rangeChanged(real min, real max)
202 This signal is emitted when the minimum or maximum value of the axis
203 changes to \a min and \a max, respectively.
204*/
205
206/*!
207 \qmlsignal ValueAxis::labelFormatChanged(string format)
208 This signal is emitted when the format of axis labels changes to \a format.
209*/
210
211/*!
212 \qmlsignal ValueAxis::labelDecimalsChanged(int decimals)
213 This signal is emitted when the amount of axis label decimals changes to \a decimals.
214*/
215
216/*!
217 \qmlsignal ValueAxis::tickAnchorChanged(real tickAnchor)
218 This signal is emitted when the tick anchoring value changes to \a tickAnchor.
219*/
220
221/*!
222 \qmlsignal ValueAxis::tickIntervalChanged(real tickInterval)
223 This signal is emitted when the tick interval value, changes to
224 \a tickInterval.
225*/
226
227/*!
228 Constructs an axis object that is a child of \a parent.
229*/
230QValueAxis::QValueAxis(QObject *parent)
231 : QAbstractAxis(*(new QValueAxisPrivate), parent)
232{}
233
234/*!
235 \internal
236*/
237QValueAxis::QValueAxis(QValueAxisPrivate &d, QObject *parent)
238 : QAbstractAxis(d, parent)
239{}
240
241/*!
242 Destroys the object.
243*/
244QValueAxis::~QValueAxis()
245{
246}
247
248void QValueAxis::setMin(qreal min)
249{
250 Q_D(QValueAxis);
251 setRange(min, max: qMax(a: d->m_max, b: min));
252}
253
254qreal QValueAxis::min() const
255{
256 Q_D(const QValueAxis);
257 return d->m_min;
258}
259
260void QValueAxis::setMax(qreal max)
261{
262 Q_D(QValueAxis);
263 setRange(min: qMin(a: d->m_min, b: max), max);
264}
265
266qreal QValueAxis::max() const
267{
268 Q_D(const QValueAxis);
269 return d->m_max;
270}
271
272/*!
273 Sets the range from \a min to \a max on the axis.
274 If \a min is greater than \a max, this function returns without making any changes.
275*/
276void QValueAxis::setRange(qreal min, qreal max)
277{
278 Q_D(QValueAxis);
279 d->setRange(min,max);
280 emit update();
281}
282
283void QValueAxis::setSubTickCount(qsizetype count)
284{
285 Q_D(QValueAxis);
286 if (d->m_subTickCount != count && count >= 0) {
287 d->m_subTickCount = count;
288 emit update();
289 emit subTickCountChanged(subTickCount: count);
290 }
291}
292
293qsizetype QValueAxis::subTickCount() const
294{
295 Q_D(const QValueAxis);
296 return d->m_subTickCount;
297}
298
299void QValueAxis::setTickAnchor(qreal anchor)
300{
301 Q_D(QValueAxis);
302 if (d->m_tickAnchor != anchor) {
303 d->m_tickAnchor = anchor;
304 emit update();
305 emit tickAnchorChanged(tickAnchor: anchor);
306 }
307}
308
309qreal QValueAxis::tickAnchor() const
310{
311 Q_D(const QValueAxis);
312 return d->m_tickAnchor;
313}
314
315void QValueAxis::setTickInterval(qreal interval)
316{
317 Q_D(QValueAxis);
318 if (d->m_tickInterval != interval) {
319 d->m_tickInterval = interval;
320 emit update();
321 emit tickIntervalChanged(tickInterval: interval);
322 }
323}
324
325qreal QValueAxis::tickInterval() const
326{
327 Q_D(const QValueAxis);
328 return d->m_tickInterval;
329}
330
331void QValueAxis::setLabelFormat(const QString &format)
332{
333 Q_D(QValueAxis);
334 d->m_format = format;
335 emit update();
336 emit labelFormatChanged(format);
337}
338
339QString QValueAxis::labelFormat() const
340{
341 Q_D(const QValueAxis);
342 return d->m_format;
343}
344
345void QValueAxis::setLabelDecimals(int decimals)
346{
347 Q_D(QValueAxis);
348 if (d->m_decimals != decimals) {
349 d->m_decimals = decimals;
350 emit update();
351 emit labelDecimalsChanged(decimals);
352 } else {
353 qCDebug(lcAxis2D, "QValueAxis::setLabelDecimals. Label decimals is already set to: %d",
354 decimals);
355 }
356}
357
358int QValueAxis::labelDecimals() const
359{
360 Q_D(const QValueAxis);
361 return d->m_decimals;
362}
363
364void QValueAxis::setZoom(qreal zoom)
365{
366 Q_D(QValueAxis);
367 if (d->m_zoom != zoom) {
368 d->m_zoom = zoom;
369 emit update();
370 emit zoomChanged(zoom);
371 } else {
372 qCDebug(lcAxis2D, "QValueAxis::setZoom. Zoom is already set to: %f",
373 zoom);
374 }
375}
376
377qreal QValueAxis::zoom() const
378{
379 Q_D(const QValueAxis);
380 return d->m_zoom;
381}
382
383void QValueAxis::setPan(qreal pan)
384{
385 Q_D(QValueAxis);
386 if (d->m_pan != pan) {
387 d->m_pan = pan;
388 emit update();
389 emit panChanged(pan);
390 } else {
391 qCDebug(lcAxis2D, "QValueAxis::setPan. Panning is already set to: %f",
392 pan);
393 }
394}
395
396qreal QValueAxis::pan() const
397{
398 Q_D(const QValueAxis);
399 return d->m_pan;
400}
401
402/*!
403 Returns the type of the axis.
404*/
405QAbstractAxis::AxisType QValueAxis::type() const
406{
407 return QAbstractAxis::AxisType::Value;
408}
409
410/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
411
412QValueAxisPrivate::QValueAxisPrivate()
413 : m_min(0)
414 , m_max(10)
415 , m_subTickCount(0)
416 , m_format()
417 , m_decimals(-1)
418 , m_tickAnchor(0.0)
419 , m_tickInterval(0.0)
420{}
421
422QValueAxisPrivate::~QValueAxisPrivate() {}
423
424void QValueAxisPrivate::setMin(const QVariant &min)
425{
426 Q_Q(QValueAxis);
427 bool ok;
428 qreal value = min.toReal(ok: &ok);
429 if (ok)
430 q->setMin(value);
431}
432
433void QValueAxisPrivate::setMax(const QVariant &max)
434{
435 Q_Q(QValueAxis);
436 bool ok;
437 qreal value = max.toReal(ok: &ok);
438 if (ok)
439 q->setMax(value);
440}
441
442void QValueAxisPrivate::setRange(const QVariant &min, const QVariant &max)
443{
444 Q_Q(QValueAxis);
445 bool ok1;
446 bool ok2;
447 qreal value1 = min.toReal(ok: &ok1);
448 qreal value2 = max.toReal(ok: &ok2);
449 if (ok1 && ok2)
450 q->setRange(min: value1, max: value2);
451}
452
453void QValueAxisPrivate::setRange(qreal min, qreal max)
454{
455 Q_Q(QValueAxis);
456 bool changed = false;
457
458 if (min > max) {
459 qCWarning(lcAxis2D, "min value is higher than max vaue.");
460 return;
461 }
462
463 if (!isValidValue(x: min, y: max)) {
464 qCWarning(lcAxis2D, "attempting to set invalid range for value axis: [%f - %f]", min, max);
465 return;
466 }
467
468 if (m_min != min) {
469 m_min = min;
470 changed = true;
471 emit q->minChanged(min);
472 }
473
474 if (m_max != max) {
475 m_max = max;
476 changed = true;
477 emit q->maxChanged(max);
478 }
479
480 if (changed)
481 emit q->rangeChanged(min, max);
482}
483
484QT_END_NAMESPACE
485
486#include "moc_qvalueaxis.cpp"
487

source code of qtgraphs/src/graphs2d/axis/valueaxis/qvalueaxis.cpp