1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qvalue3daxis_p.h"
5#include "qvalue3daxisformatter_p.h"
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 * \class QValue3DAxis
11 * \inmodule QtGraphs
12 * \ingroup graphs_3D
13 * \brief The QValue3DAxis class manipulates an axis of a graph.
14 *
15 * A value axis can be given a range of values and segment and subsegment
16 * counts to divide the range into.
17 *
18 * Labels are drawn between each segment, and grid lines are drawn between each
19 * segment and each subsegment. \note If visible, there will always be at least
20 * two grid lines and labels indicating the minimum and maximum values of
21 * the range, as there is always at least one segment.
22 */
23
24/*!
25 * \qmltype Value3DAxis
26 * \inqmlmodule QtGraphs
27 * \ingroup graphs_qml_3D
28 * \nativetype QValue3DAxis
29 * \inherits Abstract3DAxis
30 * \brief Manipulates an axis of a graph.
31 *
32 * This type provides an axis that can be given a range of values and segment
33 * and subsegment counts to divide the range into.
34 */
35
36/*!
37 * \qmlproperty qsizetype Value3DAxis::segmentCount
38 *
39 * The number of segments on the axis. This indicates how many labels are drawn.
40 * The number of grid lines to be drawn is calculated with the following
41 * formula: \c {segments * subsegments + 1}. The preset default is \c 5. The
42 * value cannot be below \c 1.
43 */
44
45/*!
46 * \qmlproperty qsizetype Value3DAxis::subSegmentCount
47 *
48 * The number of subsegments inside each segment on the axis. Grid lines are
49 * drawn between each subsegment, in addition to each segment. The preset
50 * default is \c 1. The value cannot be below \c 1.
51 */
52
53/*!
54 * \qmlproperty string Value3DAxis::labelFormat
55 *
56 * The label format to be used for the labels on this axis.
57 *
58 * The format string supports the following conversion specifiers, length
59 * modifiers, and flags provided by \c printf() in the standard C++ library:
60 * d, i, o, x, X, f, F, e, E, g, G, c.
61 *
62 * If GraphsItem3D::locale is anything else than \c{"C"}, the supported
63 * specifiers are limited to: d, e, E, f, g, G, and i. Also, only the precision
64 * modifier is supported. The rest of the formatting comes from the default
65 * \l [QML] Locale of the application.
66 *
67 * \sa GraphsItem3D::locale
68 */
69
70/*!
71 * \qmlproperty Value3DAxisFormatter Value3DAxis::formatter
72 *
73 * The axis formatter to be used. Any existing formatter is deleted when a new
74 * formatter is set.
75 *
76 */
77
78/*!
79 * \qmlproperty bool Value3DAxis::reversed
80 *
81 * If \c{true}, the axis will be rendered in reverse. That is, the positions of
82 * the minimum and maximum values are swapped when the graph is rendered. This
83 * property does not affect the actual minimum and maximum values of the axis.
84 */
85
86/*!
87 \qmlsignal Value3DAxis::segmentCountChanged(qsizetype count)
88
89 This signal is emitted when segmentCount changes to \a count.
90*/
91/*!
92 \qmlsignal Value3DAxis::subSegmentCountChanged(qsizetype count)
93
94 This signal is emitted when subSegmentCount changes to \a count.
95*/
96/*!
97 \qmlsignal Value3DAxis::labelFormatChanged(string format)
98
99 This signal is emitted when labelFormat changes to \a format.
100*/
101/*!
102 \qmlsignal Value3DAxis::formatterChanged(Value3DAxisFormatter formatter)
103
104 This signal is emitted when \l formatter changes to \a formatter.
105*/
106/*!
107 \qmlsignal Value3DAxis::reversedChanged(bool enable)
108
109 This signal is emitted when \l reversed changes to \a enable.
110*/
111
112/*!
113 * Constructs QValue3DAxis with the given \a parent.
114 */
115QValue3DAxis::QValue3DAxis(QObject *parent)
116 : QAbstract3DAxis(*(new QValue3DAxisPrivate()), parent)
117{
118 setFormatter(new QValue3DAxisFormatter);
119}
120
121/*!
122 * Destroys QValue3DAxis.
123 */
124QValue3DAxis::~QValue3DAxis() {}
125
126/*!
127 * \property QValue3DAxis::segmentCount
128 *
129 * \brief The number of segments on the axis.
130 *
131 * This indicates how many labels are drawn. The number
132 * of grid lines to be drawn is calculated with formula: \c {segments *
133 * subsegments + 1}. The preset default is \c 5. The value cannot be below \c 1.
134 *
135 * \sa setSubSegmentCount()
136 */
137void QValue3DAxis::setSegmentCount(qsizetype count)
138{
139 Q_D(QValue3DAxis);
140 if (count <= 0) {
141 qWarning(
142 msg: "Warning: Illegal segment count automatically adjusted to a legal one: %" PRIdQSIZETYPE
143 " --> 1",
144 count);
145 count = 1;
146 }
147 if (d->m_segmentCount != count) {
148 d->m_segmentCount = count;
149 d->emitLabelsChanged();
150 emit segmentCountChanged(count);
151 }
152}
153
154qsizetype QValue3DAxis::segmentCount() const
155{
156 Q_D(const QValue3DAxis);
157 return d->m_segmentCount;
158}
159
160/*!
161 * \property QValue3DAxis::subSegmentCount
162 *
163 * \brief The number of subsegments inside each segment on the axis.
164 *
165 * Grid lines are drawn between
166 * each subsegment, in addition to each segment.
167 * The preset default is \c 1. The value cannot be below \c 1.
168 *
169 * \sa setSegmentCount()
170 */
171void QValue3DAxis::setSubSegmentCount(qsizetype count)
172{
173 Q_D(QValue3DAxis);
174 if (count <= 0) {
175 qWarning(msg: "Warning: Illegal subsegment count automatically adjusted to a legal one: "
176 "%" PRIdQSIZETYPE " -> 1",
177 count);
178 count = 1;
179 }
180 if (d->m_subSegmentCount != count) {
181 d->m_subSegmentCount = count;
182 emit subSegmentCountChanged(count);
183 }
184}
185
186qsizetype QValue3DAxis::subSegmentCount() const
187{
188 Q_D(const QValue3DAxis);
189 return d->m_subSegmentCount;
190}
191
192/*!
193 * \property QValue3DAxis::labelFormat
194 *
195 * \brief The label format to be used for the labels on this axis.
196 *
197 * The format string supports the following conversion specifiers, length
198 * modifiers, and flags provided by \c printf() in the standard C++ library:
199 * d, i, o, x, X, f, F, e, E, g, G, c.
200 *
201 * If Q3DGraphsWidgetItem::locale is anything else than \c{"C"}, the supported
202 * specifiers are limited to: d, e, E, f, g, G, and i. Also, only the precision
203 * modifier is supported. The rest of the formatting comes from the default
204 * QLocale of the application.
205 *
206 * Usage example:
207 *
208 * \c {axis->setLabelFormat("%.2f mm");}
209 *
210 * \sa formatter, Q3DGraphsWidgetItem::locale
211 */
212void QValue3DAxis::setLabelFormat(const QString &format)
213{
214 Q_D(QValue3DAxis);
215 if (d->m_labelFormat != format) {
216 d->m_labelFormat = format;
217 d->emitLabelsChanged();
218 emit labelFormatChanged(format);
219 }
220}
221
222QString QValue3DAxis::labelFormat() const
223{
224 Q_D(const QValue3DAxis);
225 return d->m_labelFormat;
226}
227
228/*!
229 * \property QValue3DAxis::formatter
230 *
231 * \brief The axis formatter to be used.
232 *
233 * Any existing formatter is deleted when a new formatter
234 * is set.
235 */
236void QValue3DAxis::setFormatter(QValue3DAxisFormatter *formatter)
237{
238 Q_ASSERT(formatter);
239 Q_D(QValue3DAxis);
240
241 if (formatter != d->m_formatter) {
242 delete d->m_formatter;
243 d->m_formatter = formatter;
244 formatter->setParent(this);
245 formatter->setAxis(this);
246 emit formatterChanged(formatter);
247 emit formatterDirty();
248 }
249}
250
251QValue3DAxisFormatter *QValue3DAxis::formatter() const
252{
253 Q_D(const QValue3DAxis);
254 return d->m_formatter;
255}
256
257/*!
258 * \property QValue3DAxis::reversed
259 *
260 * \brief Whether the axis is rendered in reverse.
261 *
262 * If \c{true}, the axis will be rendered in reverse, which means the positions
263 * of minimum and maximum values are swapped when the graph is rendered. This
264 * property doesn't affect the actual minimum and maximum values of the axis.
265 */
266void QValue3DAxis::setReversed(bool enable)
267{
268 Q_D(QValue3DAxis);
269 if (d->m_reversed != enable) {
270 d->m_reversed = enable;
271 emit reversedChanged(enable);
272 }
273}
274
275bool QValue3DAxis::reversed() const
276{
277 Q_D(const QValue3DAxis);
278 return d->m_reversed;
279}
280
281void QValue3DAxis::recalculate()
282{
283 formatter()->d_func()->recalculate();
284}
285
286qsizetype QValue3DAxis::gridSize()
287{
288 return formatter()->gridPositions().size();
289}
290
291qsizetype QValue3DAxis::subGridSize()
292{
293 return formatter()->subGridPositions().size();
294}
295
296float QValue3DAxis::gridPositionAt(qsizetype gridLine)
297{
298 return formatter()->gridPositions().at(i: gridLine);
299}
300
301float QValue3DAxis::subGridPositionAt(qsizetype gridLine)
302{
303 return formatter()->subGridPositions().at(i: gridLine);
304}
305
306float QValue3DAxis::labelPositionAt(qsizetype index)
307{
308 return formatter()->labelPositions().at(i: index);
309}
310
311float QValue3DAxis::positionAt(float x)
312{
313 return formatter()->positionAt(value: x);
314}
315
316QString QValue3DAxis::stringForValue(float x)
317{
318 return formatter()->stringForValue(value: x, format: labelFormat());
319}
320
321QValue3DAxisPrivate::QValue3DAxisPrivate()
322 : QAbstract3DAxisPrivate(QAbstract3DAxis::AxisType::Value)
323 , m_segmentCount(5)
324 , m_subSegmentCount(1)
325 , m_labelFormat(Utils::defaultLabelFormat())
326 , m_labelsDirty(true)
327 , m_formatter(0)
328 , m_reversed(false)
329{}
330
331QValue3DAxisPrivate::~QValue3DAxisPrivate() {}
332
333void QValue3DAxisPrivate::setRange(float min, float max, bool suppressWarnings)
334{
335 bool dirty = (min != m_min || max != m_max);
336
337 QAbstract3DAxisPrivate::setRange(min, max, suppressWarnings);
338
339 if (dirty)
340 emitLabelsChanged();
341}
342
343void QValue3DAxisPrivate::setMin(float min)
344{
345 bool dirty = (min != m_min);
346
347 QAbstract3DAxisPrivate::setMin(min);
348
349 if (dirty)
350 emitLabelsChanged();
351}
352
353void QValue3DAxisPrivate::setMax(float max)
354{
355 bool dirty = (max != m_max);
356
357 QAbstract3DAxisPrivate::setMax(max);
358
359 if (dirty)
360 emitLabelsChanged();
361}
362
363void QValue3DAxisPrivate::emitLabelsChanged()
364{
365 Q_Q(QValue3DAxis);
366 m_labelsDirty = true;
367 emit q->labelsChanged();
368}
369
370void QValue3DAxisPrivate::emitFormatterDirty()
371{
372 Q_Q(QValue3DAxis);
373 m_labelsDirty = true;
374 emit q->formatterDirty();
375}
376
377void QValue3DAxisPrivate::updateLabels()
378{
379 if (!m_labelsDirty)
380 return;
381
382 m_labelsDirty = false;
383
384 m_formatter->d_func()->recalculate();
385
386 m_labels = m_formatter->labelStrings();
387}
388
389bool QValue3DAxisPrivate::allowZero()
390{
391 return m_formatter->allowZero();
392}
393
394bool QValue3DAxisPrivate::allowNegatives()
395{
396 return m_formatter->allowNegatives();
397}
398
399bool QValue3DAxisPrivate::allowMinMaxSame()
400{
401 return false;
402}
403
404QT_END_NAMESPACE
405

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtgraphs/src/graphs3d/axis/qvalue3daxis.cpp