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 | |
7 | QT_BEGIN_NAMESPACE |
8 | |
9 | /*! |
10 | * \class QValue3DAxisFormatter |
11 | * \inmodule QtGraphs |
12 | * \ingroup graphs_3D |
13 | * \brief The QValue3DAxisFormatter class is a base class for 3D value axis |
14 | * formatters. |
15 | * |
16 | * This class provides formatting rules for a linear value 3D axis. Subclass it |
17 | * if you want to implement custom value axes. |
18 | * |
19 | * The base class has no public API beyond constructors and destructors. It is |
20 | * meant to be only used internally. However, subclasses may implement public |
21 | * properties as needed. |
22 | * |
23 | * \sa QValue3DAxis, QLogValue3DAxisFormatter |
24 | */ |
25 | |
26 | /*! |
27 | * \qmltype Value3DAxisFormatter |
28 | * \inqmlmodule QtGraphs |
29 | * \ingroup graphs_qml_3D |
30 | * \nativetype QValue3DAxisFormatter |
31 | * \brief A base type for 3D value axis formatters. |
32 | * |
33 | * This type provides formatting rules for a linear value 3D axis. |
34 | * This type is the default type for Value3DAxis and thus never needs to be |
35 | * explicitly created. This type has no public functionality. |
36 | * |
37 | * \sa Value3DAxis |
38 | */ |
39 | |
40 | /*! |
41 | * \internal |
42 | */ |
43 | QValue3DAxisFormatter::QValue3DAxisFormatter(QValue3DAxisFormatterPrivate &d, QObject *parent) |
44 | : QObject(d, parent) |
45 | {} |
46 | |
47 | /*! |
48 | * Constructs a new value 3D axis formatter with the optional parent \a parent. |
49 | */ |
50 | QValue3DAxisFormatter::QValue3DAxisFormatter(QObject *parent) |
51 | : QObject(*(new QValue3DAxisFormatterPrivate()), parent) |
52 | {} |
53 | |
54 | /*! |
55 | * Deletes the value 3D axis formatter. |
56 | */ |
57 | QValue3DAxisFormatter::~QValue3DAxisFormatter() {} |
58 | |
59 | /*! |
60 | * Allows the parent axis to have negative values if \a allow is \c true. |
61 | */ |
62 | void QValue3DAxisFormatter::setAllowNegatives(bool allow) |
63 | { |
64 | Q_D(QValue3DAxisFormatter); |
65 | d->m_allowNegatives = allow; |
66 | } |
67 | |
68 | /*! |
69 | * Returns \c true if negative values are valid values for the parent axis. |
70 | * The default implementation always returns \c true. |
71 | */ |
72 | bool QValue3DAxisFormatter::allowNegatives() const |
73 | { |
74 | Q_D(const QValue3DAxisFormatter); |
75 | return d->m_allowNegatives; |
76 | } |
77 | |
78 | /*! |
79 | * Allows the parent axis to have a zero value if \a allow is \c true. |
80 | */ |
81 | void QValue3DAxisFormatter::setAllowZero(bool allow) |
82 | { |
83 | Q_D(QValue3DAxisFormatter); |
84 | d->m_allowZero = allow; |
85 | } |
86 | |
87 | /*! |
88 | * Returns \c true if zero is a valid value for the parent axis. |
89 | * The default implementation always returns \c true. |
90 | */ |
91 | bool QValue3DAxisFormatter::allowZero() const |
92 | { |
93 | Q_D(const QValue3DAxisFormatter); |
94 | return d->m_allowZero; |
95 | } |
96 | |
97 | /*! |
98 | * \internal |
99 | */ |
100 | void QValue3DAxisFormatter::setAxis(QValue3DAxis *axis) |
101 | { |
102 | Q_ASSERT(axis); |
103 | Q_D(QValue3DAxisFormatter); |
104 | |
105 | // These signals are all connected to markDirtyNoLabelChange slot, even though |
106 | // most of them do require labels to be regenerated. This is because the label |
107 | // regeneration is triggered elsewhere in these cases. |
108 | connect(sender: axis, |
109 | signal: &QValue3DAxis::segmentCountChanged, |
110 | context: this, |
111 | slot: &QValue3DAxisFormatter::markDirtyNoLabelChange); |
112 | connect(sender: axis, |
113 | signal: &QValue3DAxis::subSegmentCountChanged, |
114 | context: this, |
115 | slot: &QValue3DAxisFormatter::markDirtyNoLabelChange); |
116 | connect(sender: axis, |
117 | signal: &QValue3DAxis::labelFormatChanged, |
118 | context: this, |
119 | slot: &QValue3DAxisFormatter::markDirtyNoLabelChange); |
120 | connect(sender: axis, |
121 | signal: &QAbstract3DAxis::rangeChanged, |
122 | context: this, |
123 | slot: &QValue3DAxisFormatter::markDirtyNoLabelChange); |
124 | |
125 | d->setAxis(axis); |
126 | } |
127 | |
128 | /*! |
129 | * \internal |
130 | */ |
131 | void QValue3DAxisFormatter::markDirtyNoLabelChange() |
132 | { |
133 | Q_D(QValue3DAxisFormatter); |
134 | d->markDirty(labelsChange: false); |
135 | } |
136 | |
137 | /*! |
138 | * Creates a new empty value 3D axis formatter. Must be reimplemented in a |
139 | * subclass. |
140 | * |
141 | * Returns the new formatter. The renderer uses this method to cache a copy of |
142 | * the formatter. The ownership of the new copy is transferred to the caller. |
143 | */ |
144 | QValue3DAxisFormatter *QValue3DAxisFormatter::createNewInstance() const |
145 | { |
146 | return new QValue3DAxisFormatter(); |
147 | } |
148 | |
149 | /*! |
150 | * Resizes and populates the label and grid line position arrays and the label |
151 | * strings array, as well as calculates any values needed to map a value to its |
152 | * position. The parent axis can be accessed from inside this function. |
153 | * |
154 | * This method must be reimplemented in a subclass if the default array contents |
155 | * are not suitable. |
156 | * |
157 | * See gridPositions(), subGridPositions(), labelPositions(), and labelStrings() |
158 | * methods for documentation about the arrays that need to be resized and |
159 | * populated. |
160 | * |
161 | * \sa gridPositions(), subGridPositions(), labelPositions(), labelStrings(), |
162 | * axis() |
163 | */ |
164 | void QValue3DAxisFormatter::recalculate() |
165 | { |
166 | Q_D(QValue3DAxisFormatter); |
167 | d->doRecalculate(); |
168 | } |
169 | |
170 | /*! |
171 | * Returns the formatted label string using the specified \a value and |
172 | * \a format. |
173 | * |
174 | * Reimplement this method in a subclass to resolve the formatted string for a |
175 | * given \a value if the default formatting rules specified for |
176 | * QValue3DAxis::labelFormat property are not sufficient. |
177 | * |
178 | * \sa recalculate(), labelStrings(), QValue3DAxis::labelFormat |
179 | */ |
180 | QString QValue3DAxisFormatter::stringForValue(qreal value, const QString &format) |
181 | { |
182 | Q_D(QValue3DAxisFormatter); |
183 | return d->stringForValue(value, format); |
184 | } |
185 | |
186 | /*! |
187 | * Returns the normalized position along the axis for the given \a value. |
188 | * The returned value should be between \c 0.0 (the minimum value) and |
189 | * \c 1.0 (the maximum value), inclusive, if the value is within the parent |
190 | * axis range. |
191 | * |
192 | * Reimplement this method if the position cannot be resolved by linear |
193 | * interpolation between the parent axis minimum and maximum values. |
194 | * |
195 | * \sa recalculate(), valueAt() |
196 | */ |
197 | float QValue3DAxisFormatter::positionAt(float value) const |
198 | { |
199 | Q_D(const QValue3DAxisFormatter); |
200 | return d->positionAt(value); |
201 | } |
202 | |
203 | /*! |
204 | * Returns the value at the normalized \a position along the axis. |
205 | * The \a position value should be between \c 0.0 (the minimum value) and |
206 | * \c 1.0 (the maximum value), inclusive, to obtain values within the parent |
207 | * axis range. |
208 | * |
209 | * Reimplement this method if the value cannot be resolved by linear |
210 | * interpolation between the parent axis minimum and maximum values. |
211 | * |
212 | * \sa recalculate(), positionAt() |
213 | */ |
214 | float QValue3DAxisFormatter::valueAt(float position) const |
215 | { |
216 | Q_D(const QValue3DAxisFormatter); |
217 | return d->valueAt(position); |
218 | } |
219 | |
220 | /*! |
221 | * Copies all the values necessary for resolving positions, values, and strings |
222 | * with this formatter to the \a copy of the formatter. When reimplementing |
223 | * this method in a subclass, call the superclass version at some point. |
224 | * The renderer uses this method to cache a copy of the formatter. |
225 | * |
226 | * Returns the new copy. The ownership of the new copy transfers to the caller. |
227 | */ |
228 | void QValue3DAxisFormatter::populateCopy(QValue3DAxisFormatter ©) |
229 | { |
230 | Q_D(QValue3DAxisFormatter); |
231 | d->doPopulateCopy(copy&: *(copy.d_func())); |
232 | } |
233 | |
234 | /*! |
235 | * Marks this formatter as dirty, prompting the renderer to make a new copy of its |
236 | * cache on the next renderer synchronization. This method should be called by a |
237 | * subclass whenever the formatter is changed in a way that affects the resolved |
238 | * values. Set \a labelsChange to \c true if the change requires regenerating |
239 | * the parent axis label strings. |
240 | */ |
241 | void QValue3DAxisFormatter::markDirty(bool labelsChange) |
242 | { |
243 | Q_D(QValue3DAxisFormatter); |
244 | d->markDirty(labelsChange); |
245 | } |
246 | |
247 | /*! |
248 | * Returns the parent axis. The parent axis must only be accessed in the |
249 | * recalculate() method to maintain thread safety in environments using a |
250 | * threaded renderer. |
251 | * |
252 | * \sa recalculate() |
253 | */ |
254 | QValue3DAxis *QValue3DAxisFormatter::axis() const |
255 | { |
256 | Q_D(const QValue3DAxisFormatter); |
257 | return d->m_axis; |
258 | } |
259 | |
260 | /*! |
261 | * Returns a reference to the array of normalized grid line positions. |
262 | * The default array size is equal to the segment count of the parent axis plus |
263 | * one, but a subclassed implementation of the recalculate() method may resize |
264 | * the array differently. |
265 | * |
266 | * \sa QValue3DAxis::segmentCount, recalculate() |
267 | */ |
268 | const QList<float> &QValue3DAxisFormatter::gridPositions() const & |
269 | { |
270 | Q_D(const QValue3DAxisFormatter); |
271 | return d->m_gridPositions; |
272 | } |
273 | |
274 | /*! |
275 | * Returns an array of normalized grid line positions by value. |
276 | * The default array size is equal to the segment count of the parent axis plus |
277 | * one, but a subclassed implementation of the recalculate() method may resize |
278 | * the array differently. |
279 | * |
280 | * \sa QValue3DAxis::segmentCount, recalculate() |
281 | */ |
282 | QList<float> QValue3DAxisFormatter::gridPositions() && |
283 | { |
284 | Q_D(QValue3DAxisFormatter); |
285 | return std::move(d->m_gridPositions); |
286 | } |
287 | |
288 | /*! |
289 | * Sets a list of new grid positions from \a gridPositions. |
290 | * The values should be between \c 0.0 (the minimum value) and \c 1.0 (the |
291 | * maximum value), inclusive. |
292 | * |
293 | * \sa QValue3DAxis::segmentCount, recalculate(), gridPositions |
294 | */ |
295 | void QValue3DAxisFormatter::setGridPoitions(QList<float> gridPositions) |
296 | { |
297 | Q_D(QValue3DAxisFormatter); |
298 | d->m_gridPositions = gridPositions; |
299 | } |
300 | |
301 | /*! |
302 | * Returns a reference to the array of normalized sub-grid line positions. |
303 | * The default array size is equal to the segment count of the parent axis times |
304 | * the sub-segment count of the parent axis minus one, but a subclassed |
305 | * implementation of the recalculate() method may resize the array differently. |
306 | * |
307 | * \sa QValue3DAxis::segmentCount, QValue3DAxis::subSegmentCount, recalculate() |
308 | */ |
309 | const QList<float> &QValue3DAxisFormatter::subGridPositions() const & |
310 | { |
311 | Q_D(const QValue3DAxisFormatter); |
312 | return d->m_subGridPositions; |
313 | } |
314 | |
315 | /*! |
316 | * Returns an array of normalized sub-grid line positions by value. |
317 | * The default array size is equal to the segment count of the parent axis times |
318 | * the sub-segment count of the parent axis minus one, but a subclassed |
319 | * implementation of the recalculate() method may resize the array differently. |
320 | * |
321 | * \sa QValue3DAxis::segmentCount, QValue3DAxis::subSegmentCount, recalculate() |
322 | */ |
323 | QList<float> QValue3DAxisFormatter::subGridPositions() && |
324 | { |
325 | Q_D(QValue3DAxisFormatter); |
326 | return std::move(d->m_subGridPositions); |
327 | } |
328 | |
329 | /*! |
330 | * Sets a list of new sub-grid positions from \a subGridPositions. |
331 | * The values should be between \c 0.0 (the minimum value) and \c 1.0 (the |
332 | * maximum value), inclusive. |
333 | * |
334 | * \sa QValue3DAxis::segmentCount, QValue3DAxis::subSegmentCount, recalculate(), |
335 | * subGridPositions |
336 | */ |
337 | void QValue3DAxisFormatter::setSubGridPositions(QList<float> subGridPositions) |
338 | { |
339 | Q_D(QValue3DAxisFormatter); |
340 | d->m_subGridPositions = subGridPositions; |
341 | } |
342 | |
343 | /*! |
344 | * Returns a reference to the array of normalized label positions. |
345 | * The default array size is equal to the segment count of the parent axis plus |
346 | * one, but a subclassed implementation of the recalculate() method may resize |
347 | * the array differently. By default, the label at the index zero corresponds to |
348 | * the minimum value of the axis. |
349 | * |
350 | * \sa QValue3DAxis::segmentCount, QAbstract3DAxis::labels, recalculate() |
351 | */ |
352 | const QList<float> &QValue3DAxisFormatter::labelPositions() const & |
353 | { |
354 | Q_D(const QValue3DAxisFormatter); |
355 | return d->m_labelPositions; |
356 | } |
357 | |
358 | /*! |
359 | * Returns an array of normalized label positions by value. |
360 | * The default array size is equal to the segment count of the parent axis plus |
361 | * one, but a subclassed implementation of the recalculate() method may resize |
362 | * the array differently. By default, the label at the index zero corresponds to |
363 | * the minimum value of the axis. |
364 | * |
365 | * \sa QValue3DAxis::segmentCount, QAbstract3DAxis::labels, recalculate() |
366 | */ |
367 | QList<float> QValue3DAxisFormatter::labelPositions() && |
368 | { |
369 | Q_D(QValue3DAxisFormatter); |
370 | return std::move(d->m_labelPositions); |
371 | } |
372 | |
373 | /*! |
374 | * Sets a list of new label positions from \a labelPositions. |
375 | * The values should be between \c 0.0 (the minimum value) and |
376 | * \c 1.0 (the maximum value), inclusive. |
377 | * |
378 | * \sa QValue3DAxis::segmentCount, QAbstract3DAxis::labels, recalculate(), |
379 | * labelPositions() |
380 | */ |
381 | void QValue3DAxisFormatter::setlabelPositions(QList<float> labelPositions) |
382 | { |
383 | Q_D(QValue3DAxisFormatter); |
384 | d->m_labelPositions = labelPositions; |
385 | } |
386 | |
387 | /*! |
388 | * Returns a reference to the string list containing formatter label strings. |
389 | * |
390 | * \sa labelPositions() |
391 | */ |
392 | const QStringList &QValue3DAxisFormatter::labelStrings() const & |
393 | { |
394 | Q_D(const QValue3DAxisFormatter); |
395 | return d->m_labelStrings; |
396 | } |
397 | |
398 | /*! |
399 | * Returns a string list by value containing formatter label strings. |
400 | * |
401 | * \sa labelPositions() |
402 | */ |
403 | QStringList QValue3DAxisFormatter::labelStrings() && |
404 | { |
405 | Q_D(QValue3DAxisFormatter); |
406 | return std::move(d->m_labelStrings); |
407 | } |
408 | |
409 | /*! |
410 | * Sets a list of new label strings from \a labelStrings. |
411 | * The array size must be equal to the size of the label positions array, which |
412 | * the indexes also correspond to. |
413 | * \sa labelPositions(), labelStrings() |
414 | */ |
415 | void QValue3DAxisFormatter::setLabelStrings(QStringList labelStrings) |
416 | { |
417 | Q_D(QValue3DAxisFormatter); |
418 | d->m_labelStrings = labelStrings; |
419 | } |
420 | |
421 | /*! |
422 | * Sets the \a locale that this formatter uses. |
423 | * The graph automatically sets the formatter's locale to a graph's locale |
424 | * whenever the parent axis is set as an active axis of the graph, the axis |
425 | * formatter is set to an axis attached to the graph, or the graph's locale |
426 | * changes. |
427 | * |
428 | * \sa locale(), Q3DGraphsWidgetItem::locale |
429 | */ |
430 | void QValue3DAxisFormatter::setLocale(const QLocale &locale) |
431 | { |
432 | Q_D(QValue3DAxisFormatter); |
433 | d->m_cLocaleInUse = (locale == QLocale::c()); |
434 | d->m_locale = locale; |
435 | markDirty(labelsChange: true); |
436 | } |
437 | /*! |
438 | * Returns the current locale this formatter is using. |
439 | */ |
440 | QLocale QValue3DAxisFormatter::locale() const |
441 | { |
442 | Q_D(const QValue3DAxisFormatter); |
443 | return d->m_locale; |
444 | } |
445 | |
446 | // QValue3DAxisFormatterPrivate |
447 | QValue3DAxisFormatterPrivate::QValue3DAxisFormatterPrivate() |
448 | : m_needsRecalculate(true) |
449 | , m_min(0.0f) |
450 | , m_max(0.0f) |
451 | , m_rangeNormalizer(0.0f) |
452 | , m_axis(0) |
453 | , m_preparsedParamType(Utils::ParamType::Unknown) |
454 | , m_allowNegatives(true) |
455 | , m_allowZero(true) |
456 | , m_formatPrecision(6) |
457 | , // 6 and 'g' are defaults in Qt API for format precision and spec |
458 | m_formatSpec('g') |
459 | , m_cLocaleInUse(true) |
460 | {} |
461 | |
462 | QValue3DAxisFormatterPrivate::~QValue3DAxisFormatterPrivate() {} |
463 | |
464 | void QValue3DAxisFormatterPrivate::recalculate() |
465 | { |
466 | Q_Q(QValue3DAxisFormatter); |
467 | // Only recalculate if we need to and have m_axis pointer. If we do not have |
468 | // m_axis, either we are not attached to an axis or this is a renderer cache. |
469 | if (m_axis && m_needsRecalculate) { |
470 | m_min = m_axis->min(); |
471 | m_max = m_axis->max(); |
472 | m_rangeNormalizer = (m_max - m_min); |
473 | |
474 | q->recalculate(); |
475 | m_needsRecalculate = false; |
476 | } |
477 | } |
478 | |
479 | void QValue3DAxisFormatterPrivate::doRecalculate() |
480 | { |
481 | Q_Q(QValue3DAxisFormatter); |
482 | int segmentCount = m_axis->segmentCount(); |
483 | int subGridCount = m_axis->subSegmentCount() - 1; |
484 | QString labelFormat = m_axis->labelFormat(); |
485 | |
486 | m_gridPositions.resize(size: segmentCount + 1); |
487 | m_subGridPositions.resize(size: segmentCount * subGridCount); |
488 | |
489 | m_labelPositions.resize(size: segmentCount + 1); |
490 | m_labelStrings.clear(); |
491 | m_labelStrings.reserve(asize: segmentCount + 1); |
492 | |
493 | // Use qreals for intermediate calculations for better accuracy on label |
494 | // values |
495 | qreal segmentStep = 1.0 / qreal(segmentCount); |
496 | qreal subSegmentStep = 0; |
497 | if (subGridCount > 0) |
498 | subSegmentStep = segmentStep / qreal(subGridCount + 1); |
499 | |
500 | // Calculate positions |
501 | qreal rangeNormalizer = qreal(m_max - m_min); |
502 | for (int i = 0; i < segmentCount; i++) { |
503 | qreal gridValue = segmentStep * qreal(i); |
504 | m_gridPositions[i] = float(gridValue); |
505 | m_labelPositions[i] = float(gridValue); |
506 | m_labelStrings << q->stringForValue(value: gridValue * rangeNormalizer + qreal(m_min), format: labelFormat); |
507 | if (m_subGridPositions.size()) { |
508 | for (int j = 0; j < subGridCount; j++) |
509 | m_subGridPositions[i * subGridCount + j] = gridValue + subSegmentStep * (j + 1); |
510 | } |
511 | } |
512 | |
513 | // Ensure max value doesn't suffer from any rounding errors |
514 | m_gridPositions[segmentCount] = 1.0f; |
515 | m_labelPositions[segmentCount] = 1.0f; |
516 | m_labelStrings << q->stringForValue(value: qreal(m_max), format: labelFormat); |
517 | } |
518 | |
519 | void QValue3DAxisFormatterPrivate::populateCopy(QValue3DAxisFormatter ©) |
520 | { |
521 | Q_Q(QValue3DAxisFormatter); |
522 | recalculate(); |
523 | q->populateCopy(copy); |
524 | } |
525 | |
526 | void QValue3DAxisFormatterPrivate::doPopulateCopy(QValue3DAxisFormatterPrivate ©) |
527 | { |
528 | copy.m_min = m_min; |
529 | copy.m_max = m_max; |
530 | copy.m_rangeNormalizer = m_rangeNormalizer; |
531 | |
532 | copy.m_gridPositions = m_gridPositions; |
533 | copy.m_labelPositions = m_labelPositions; |
534 | copy.m_subGridPositions = m_subGridPositions; |
535 | } |
536 | |
537 | QString QValue3DAxisFormatterPrivate::stringForValue(qreal value, const QString &format) |
538 | { |
539 | if (m_previousLabelFormat.compare(s: format)) { |
540 | // Format string different than the previous one used, reparse it |
541 | m_labelFormatArray = format.toUtf8(); |
542 | m_previousLabelFormat = format; |
543 | m_preparsedParamType = Utils::preParseFormat(format, |
544 | preStr&: m_formatPreStr, |
545 | postStr&: m_formatPostStr, |
546 | precision&: m_formatPrecision, |
547 | formatSpec&: m_formatSpec); |
548 | } |
549 | |
550 | if (m_cLocaleInUse) { |
551 | return Utils::formatLabelSprintf(format: m_labelFormatArray, paramType: m_preparsedParamType, value); |
552 | } else { |
553 | return Utils::formatLabelLocalized(paramType: m_preparsedParamType, |
554 | value, |
555 | locale: m_locale, |
556 | preStr: m_formatPreStr, |
557 | postStr: m_formatPostStr, |
558 | precision: m_formatPrecision, |
559 | formatSpec: m_formatSpec, |
560 | format: m_labelFormatArray); |
561 | } |
562 | } |
563 | |
564 | float QValue3DAxisFormatterPrivate::positionAt(float value) const |
565 | { |
566 | return ((value - m_min) / m_rangeNormalizer); |
567 | } |
568 | |
569 | float QValue3DAxisFormatterPrivate::valueAt(float position) const |
570 | { |
571 | return ((position * m_rangeNormalizer) + m_min); |
572 | } |
573 | |
574 | void QValue3DAxisFormatterPrivate::setAxis(QValue3DAxis *axis) |
575 | { |
576 | Q_ASSERT(axis); |
577 | m_axis = axis; |
578 | } |
579 | |
580 | void QValue3DAxisFormatterPrivate::markDirty(bool labelsChange) |
581 | { |
582 | m_needsRecalculate = true; |
583 | if (m_axis) { |
584 | if (labelsChange) |
585 | m_axis->d_func()->emitLabelsChanged(); |
586 | if (m_axis && m_axis->orientation() != QAbstract3DAxis::AxisOrientation::None) |
587 | m_axis->d_func()->emitFormatterDirty(); |
588 | } |
589 | } |
590 | |
591 | QT_END_NAMESPACE |
592 |
Definitions
- QValue3DAxisFormatter
- QValue3DAxisFormatter
- ~QValue3DAxisFormatter
- setAllowNegatives
- allowNegatives
- setAllowZero
- allowZero
- setAxis
- markDirtyNoLabelChange
- createNewInstance
- recalculate
- stringForValue
- positionAt
- valueAt
- populateCopy
- markDirty
- axis
- gridPositions
- gridPositions
- setGridPoitions
- subGridPositions
- subGridPositions
- setSubGridPositions
- labelPositions
- labelPositions
- setlabelPositions
- labelStrings
- labelStrings
- setLabelStrings
- setLocale
- locale
- QValue3DAxisFormatterPrivate
- ~QValue3DAxisFormatterPrivate
- recalculate
- doRecalculate
- populateCopy
- doPopulateCopy
- stringForValue
- positionAt
- valueAt
- setAxis
Learn Advanced QML with KDAB
Find out more