1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCore/qdebug.h>
5#include "qabstract3daxis_p.h"
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 * \class QAbstract3DAxis
11 * \inmodule QtGraphs
12 * \ingroup graphs_3D
13 * \brief The QAbstract3DAxis class is a base class for the axes of a 3D graph.
14 *
15 * This class specifies the enumerations, properties, and functions shared by
16 * graph axes. It should not be used directly, but one of its subclasses should
17 * be used instead.
18 *
19 * \sa QCategory3DAxis, QValue3DAxis
20 */
21
22/*!
23 * \qmltype Abstract3DAxis
24 * \qmlabstract
25 * \inqmlmodule QtGraphs
26 * \ingroup graphs_qml_3D
27 * \nativetype QAbstract3DAxis
28 * \brief A base type for the axes of a 3D graph.
29 * For Abstract3DAxis enums, see \l QAbstract3DAxis::AxisOrientation and
30 * \l{QAbstract3DAxis::AxisType}.
31 */
32
33/*!
34 * \qmlproperty string Abstract3DAxis::title
35 * The title for the axis.
36 *
37 * \sa titleVisible, titleFixed
38 */
39
40/*!
41 * \qmlproperty list Abstract3DAxis::labels
42 * The labels for the axis.
43 * \note Setting this property for Value3DAxis does nothing, as it generates
44 * labels automatically.
45 */
46
47/*!
48 * \qmlproperty Abstract3DAxis.AxisOrientation Abstract3DAxis::orientation
49 * The orientation of the axis.
50 */
51
52/*!
53 * \qmlproperty Abstract3DAxis.AxisType Abstract3DAxis::type
54 * The type of the axis.
55 */
56
57/*!
58 * \qmlproperty real Abstract3DAxis::min
59 *
60 * The minimum value on the axis.
61 * When setting this property, the maximum value is adjusted if necessary, so
62 * the range remains valid.
63 */
64
65/*!
66 * \qmlproperty real Abstract3DAxis::max
67 *
68 * The maximum value on the axis.
69 * When setting this property, the minimum value is adjusted if necessary, so
70 * the range remains valid.
71 */
72
73/*!
74 * \qmlproperty bool Abstract3DAxis::autoAdjustRange
75 *
76 * Defines whether the axis will automatically adjust the range so that all data
77 * fits in it.
78 */
79
80/*!
81 * \qmlproperty real Abstract3DAxis::labelAutoAngle
82 *
83 * The maximum angle the labels can autorotate when the camera angle changes.
84 * The angle can be between 0 and 90, inclusive. The default value is 0.
85 * If the value is 0, axis labels do not automatically rotate.
86 * If the value is greater than zero, labels attempt to orient themselves toward
87 * the camera, up to the specified angle.
88 */
89
90/*!
91 * \qmlproperty bool Abstract3DAxis::titleVisible
92 *
93 * Defines whether the axis title is visible in the primary graph view.
94 *
95 * The default value is \c{false}.
96 *
97 * \sa title, titleFixed
98 */
99
100/*!
101 * \qmlproperty bool Abstract3DAxis::labelsVisible
102 *
103 * Defines whether the axis labels are visible in the primary graph view.
104 *
105 * The default value is \c{true}.
106 *
107 */
108
109/*!
110 * \qmlproperty bool Abstract3DAxis::titleFixed
111 *
112 * The rotation of axis titles.
113 *
114 * If \c{false}, axis titles in the primary graph view will be rotated towards
115 * the camera similarly to the axis labels. If \c{true}, axis titles are only
116 * rotated around their axis but are not otherwise oriented towards the camera.
117 * This property does not have any effect if the labelAutoAngle property
118 * value is zero.
119 * Default value is \c{true}.
120 *
121 * \sa labelAutoAngle, title, titleVisible
122 */
123
124/*!
125 * \qmlproperty real Abstract3DAxis::titleOffset
126 *
127 * The position of the axis title on the axis.
128 * The value must be between \c -1.0f and \c 1.0f
129 *
130 * Default value is \c{0}.
131 *
132 * \sa title, titleVisible
133 */
134
135/*!
136 \qmlsignal Abstract3DAxis::titleChanged(string newTitle)
137
138 This signal is emitted when \l title changes to \a newTitle.
139*/
140/*!
141 \qmlsignal Abstract3DAxis::labelsChanged()
142
143 This signal is emitted when axis labels change.
144*/
145/*!
146 \qmlsignal Abstract3DAxis::orientationChanged(AxisOrientation orientation)
147
148 This signal is emitted when axis orientation changes to \a orientation.
149*/
150/*!
151 \qmlsignal Abstract3DAxis::minChanged(real value)
152
153 This signal is emitted when the minimum value of the axis changes
154 to \a value.
155*/
156/*!
157 \qmlsignal Abstract3DAxis::maxChanged(real value)
158
159 This signal is emitted when the maximum value of the axis changes
160 to \a value.
161*/
162/*!
163 \qmlsignal Abstract3DAxis::rangeChanged(real min, real max)
164
165 This signal is emitted when the axis range changes. \a min and \a max are
166 the min and max of the new range.
167*/
168/*!
169 \qmlsignal Abstract3DAxis::autoAdjustRangeChanged(bool autoAdjust)
170
171 This signal is emitted when the \l autoAdjustRange property value changes
172 to \a autoAdjust.
173*/
174/*!
175 \qmlsignal Abstract3DAxis::labelAutoAngleChanged(real angle)
176
177 This signal is emitted when the angle of label rotation changes to
178 \a angle.
179*/
180/*!
181 \qmlsignal Abstract3DAxis::titleVisibilityChanged(bool visible)
182
183 This signal is emitted when the title visibility changes to \a visible.
184*/
185/*!
186 \qmlsignal Abstract3DAxis::labelVisibilityChanged(bool visible)
187
188 This signal is emitted when the label visibility changes to \a visible.
189*/
190/*!
191 \qmlsignal Abstract3DAxis::titleFixedChanged(bool fixed)
192
193 This signal is emitted when the titleFixed property value changes to
194 \a fixed.
195*/
196/*!
197 \qmlsignal Abstract3DAxis::titleOffsetChanged(real offset)
198
199 This signal is emitted when the titleOffset property value changes to
200 \a offset.
201*/
202
203/*!
204 * \enum QAbstract3DAxis::AxisOrientation
205 *
206 * The orientation of the axis object.
207 *
208 * \value None
209 * \value X
210 * \value Y
211 * \value Z
212 */
213
214/*!
215 * \enum QAbstract3DAxis::AxisType
216 *
217 * The type of the axis object.
218 *
219 * \value None
220 * \value Category
221 * \value Value
222 */
223
224/*!
225 * \internal
226 */
227QAbstract3DAxis::QAbstract3DAxis(QAbstract3DAxisPrivate &d, QObject *parent)
228 : QObject(d, parent)
229
230{}
231
232/*!
233 * Destroys QAbstract3DAxis.
234 */
235QAbstract3DAxis::~QAbstract3DAxis() {}
236
237/*!
238 * \property QAbstract3DAxis::orientation
239 *
240 * \brief The orientation of the axis.
241 *
242 * The value is one of AxisOrientation values.
243 */
244QAbstract3DAxis::AxisOrientation QAbstract3DAxis::orientation() const
245{
246 Q_D(const QAbstract3DAxis);
247 return d->m_orientation;
248}
249
250/*!
251 * \property QAbstract3DAxis::type
252 *
253 * \brief The type of the axis.
254 *
255 * The value is one of AxisType values.
256 */
257QAbstract3DAxis::AxisType QAbstract3DAxis::type() const
258{
259 Q_D(const QAbstract3DAxis);
260 return d->m_type;
261}
262
263/*!
264 * \property QAbstract3DAxis::title
265 *
266 * \brief The title for the axis.
267 *
268 * \sa titleVisible, titleFixed
269 */
270void QAbstract3DAxis::setTitle(const QString &title)
271{
272 Q_D(QAbstract3DAxis);
273 if (d->m_title != title) {
274 d->m_title = title;
275 emit titleChanged(newTitle: title);
276 }
277}
278
279QString QAbstract3DAxis::title() const
280{
281 Q_D(const QAbstract3DAxis);
282 return d->m_title;
283}
284
285/*!
286 * \property QAbstract3DAxis::labels
287 *
288 * \brief The labels for the axis.
289 * \note Setting this property for QValue3DAxis does nothing, as it generates
290 * labels automatically.
291 */
292void QAbstract3DAxis::setLabels(const QStringList &labels)
293{
294 Q_UNUSED(labels);
295}
296
297QStringList QAbstract3DAxis::labels() const
298{
299 Q_D(const QAbstract3DAxis);
300 const_cast<QAbstract3DAxisPrivate *>(d)->updateLabels();
301 return const_cast<QAbstract3DAxisPrivate *>(d)->m_labels;
302}
303
304/*!
305 * Sets the value range of the axis from \a min to \a max.
306 * When setting the range, the maximum value is adjusted if necessary, to ensure
307 * that the range remains valid.
308 * \note For QCategory3DAxis, specifies the index range of rows or columns to
309 * show.
310 */
311void QAbstract3DAxis::setRange(float min, float max)
312{
313 Q_D(QAbstract3DAxis);
314 d->setRange(min, max);
315 setAutoAdjustRange(false);
316}
317
318/*!
319 * \property QAbstract3DAxis::labelAutoAngle
320 *
321 * \brief The maximum angle the labels can autorotate when the camera angle
322 * changes.
323 *
324 * The angle can be between 0 and 90, inclusive. The default value is 0.
325 * If the value is 0, axis labels do not automatically rotate.
326 * If the value is greater than zero, labels attempt to orient themselves toward
327 * the camera, up to the specified angle.
328 */
329void QAbstract3DAxis::setLabelAutoAngle(float degree)
330{
331 Q_D(QAbstract3DAxis);
332 if (degree < 0.0f)
333 degree = 0.0f;
334 if (degree > 90.0f)
335 degree = 90.0f;
336 if (d->m_labelAutoAngle != degree) {
337 d->m_labelAutoAngle = degree;
338 emit labelAutoAngleChanged(angle: degree);
339 }
340}
341
342float QAbstract3DAxis::labelAutoAngle() const
343{
344 Q_D(const QAbstract3DAxis);
345 return d->m_labelAutoAngle;
346}
347
348/*!
349 * \property QAbstract3DAxis::titleVisible
350 *
351 * \brief Whether the axis title is visible in the primary graph view.
352 *
353 * The default value is \c{false}.
354 *
355 * \sa title, titleFixed
356 */
357void QAbstract3DAxis::setTitleVisible(bool visible)
358{
359 Q_D(QAbstract3DAxis);
360 if (d->m_titleVisible != visible) {
361 d->m_titleVisible = visible;
362 emit titleVisibleChanged(visible);
363 }
364}
365
366bool QAbstract3DAxis::isTitleVisible() const
367{
368 Q_D(const QAbstract3DAxis);
369 return d->m_titleVisible;
370}
371
372/*!
373 * \property QAbstract3DAxis::labelsVisible
374 *
375 * \brief Whether the axis labels are visible in the primary graph view.
376 *
377 * The default value is \c{true}.
378 *
379 */
380void QAbstract3DAxis::setLabelsVisible(bool visible)
381{
382 Q_D(QAbstract3DAxis);
383 if (d->m_labelsVisible != visible) {
384 d->m_labelsVisible = visible;
385 emit labelVisibleChanged(visible);
386 }
387}
388
389bool QAbstract3DAxis::labelsVisible() const
390{
391 Q_D(const QAbstract3DAxis);
392 return d->m_labelsVisible;
393}
394
395/*!
396 * \property QAbstract3DAxis::titleFixed
397 *
398 * \brief The rotation of the axis titles.
399 *
400 * If \c{false}, axis titles in the primary graph view will be rotated towards
401 * the camera similarly to the axis labels. If \c{true}, axis titles are only
402 * rotated around their axis but are not otherwise oriented towards the camera.
403 * This property does not have any effect if the labelAutoAngle property
404 * value is zero.
405 * Default value is \c{true}.
406 *
407 * \sa labelAutoAngle, title, titleVisible
408 */
409void QAbstract3DAxis::setTitleFixed(bool fixed)
410{
411 Q_D(QAbstract3DAxis);
412 if (d->m_titleFixed != fixed) {
413 d->m_titleFixed = fixed;
414 emit titleFixedChanged(fixed);
415 }
416}
417
418bool QAbstract3DAxis::isTitleFixed() const
419{
420 Q_D(const QAbstract3DAxis);
421 return d->m_titleFixed;
422}
423
424/*!
425 * \property QAbstract3DAxis::min
426 *
427 * \brief The minimum value on the axis.
428 *
429 * When setting this property, the maximum value is adjusted if necessary, to
430 * ensure that the range remains valid.
431 * \note For QCategory3DAxis, specifies the index of the first row or column to
432 * show.
433 */
434void QAbstract3DAxis::setMin(float min)
435{
436 Q_D(QAbstract3DAxis);
437 d->setMin(min);
438 setAutoAdjustRange(false);
439}
440
441/*!
442 * \property QAbstract3DAxis::max
443 *
444 * \brief The maximum value on the axis.
445 *
446 * When setting this property, the minimum value is adjusted if necessary, to
447 * ensure that the range remains valid.
448 * \note For QCategory3DAxis, specifies the index of the last row or column to
449 * show.
450 */
451void QAbstract3DAxis::setMax(float max)
452{
453 Q_D(QAbstract3DAxis);
454 d->setMax(max);
455 setAutoAdjustRange(false);
456}
457
458float QAbstract3DAxis::min() const
459{
460 Q_D(const QAbstract3DAxis);
461 return d->m_min;
462}
463
464float QAbstract3DAxis::max() const
465{
466 Q_D(const QAbstract3DAxis);
467 return d->m_max;
468}
469
470/*!
471 * \property QAbstract3DAxis::autoAdjustRange
472 *
473 * \brief Whether the axis will automatically adjust the range so that all data
474 * fits in it.
475 *
476 * \sa setRange(), setMin(), setMax()
477 */
478void QAbstract3DAxis::setAutoAdjustRange(bool autoAdjust)
479{
480 Q_D(QAbstract3DAxis);
481 if (d->m_autoAdjust != autoAdjust) {
482 d->m_autoAdjust = autoAdjust;
483 emit autoAdjustRangeChanged(autoAdjust);
484 }
485}
486
487bool QAbstract3DAxis::isAutoAdjustRange() const
488{
489 Q_D(const QAbstract3DAxis);
490 return d->m_autoAdjust;
491}
492
493/*!
494 * \property QAbstract3DAxis::titleOffset
495 *
496 * The position of the axis title on the axis.
497 * The value must be between \c -1.0f and \c 1.0f
498 *
499 * \sa title, titleFixed
500 */
501void QAbstract3DAxis::setTitleOffset(float offset)
502{
503 Q_D(QAbstract3DAxis);
504 if (offset < -1.0f || offset > 1.0f) {
505 qWarning(msg: "Invalid value. Valid range for title offset is between "
506 "-1.0f and 1.0f");
507 } else if (d->m_titleOffset != offset) {
508 d->m_titleOffset = offset;
509 emit titleOffsetChanged(offset);
510 }
511}
512
513float QAbstract3DAxis::titleOffset() const
514{
515 Q_D(const QAbstract3DAxis);
516 return d->m_titleOffset;
517}
518
519/*!
520 * \fn QAbstract3DAxis::rangeChanged(float min, float max)
521 *
522 * Emits the minimum and maximum values of the range, \a min and \a max, when
523 * the range changes.
524 */
525
526// QAbstract3DAxisPrivate
527QAbstract3DAxisPrivate::QAbstract3DAxisPrivate(QAbstract3DAxis::AxisType type)
528 : m_orientation(QAbstract3DAxis::AxisOrientation::None)
529 , m_type(type)
530 , m_isDefaultAxis(false)
531 , m_min(0.0f)
532 , m_max(10.0f)
533 , m_autoAdjust(true)
534 , m_labelAutoAngle(0.0f)
535 , m_titleOffset(0.0f)
536 , m_titleVisible(false)
537 , m_labelsVisible(true)
538 , m_titleFixed(true)
539
540{}
541
542QAbstract3DAxisPrivate::~QAbstract3DAxisPrivate() {}
543
544void QAbstract3DAxisPrivate::setOrientation(QAbstract3DAxis::AxisOrientation orientation)
545{
546 Q_Q(QAbstract3DAxis);
547 if (m_orientation == QAbstract3DAxis::AxisOrientation::None) {
548 m_orientation = orientation;
549 emit q->orientationChanged(orientation);
550 } else {
551 Q_ASSERT("Attempted to reset axis orientation.");
552 }
553}
554
555void QAbstract3DAxisPrivate::updateLabels()
556{
557 // Default implementation does nothing
558}
559
560void QAbstract3DAxisPrivate::setRange(float min, float max, bool suppressWarnings)
561{
562 Q_Q(QAbstract3DAxis);
563 bool adjusted = false;
564 if (!allowNegatives()) {
565 if (allowZero()) {
566 if (min < 0.0f) {
567 min = 0.0f;
568 adjusted = true;
569 }
570 if (max < 0.0f) {
571 max = 0.0f;
572 adjusted = true;
573 }
574 } else {
575 if (min <= 0.0f) {
576 min = 1.0f;
577 adjusted = true;
578 }
579 if (max <= 0.0f) {
580 max = 1.0f;
581 adjusted = true;
582 }
583 }
584 }
585 // If min >= max, we adjust ranges so that
586 // m_max becomes (min + 1.0f)
587 // as axes need some kind of valid range.
588 bool minDirty = false;
589 bool maxDirty = false;
590 if (m_min != min) {
591 m_min = min;
592 minDirty = true;
593 }
594 if (m_max != max || min > max || (!allowMinMaxSame() && min == max)) {
595 if (min > max || (!allowMinMaxSame() && min == max)) {
596 m_max = min + 1.0f;
597 adjusted = true;
598 } else {
599 m_max = max;
600 }
601 maxDirty = true;
602 }
603
604 if (minDirty || maxDirty) {
605 if (adjusted && !suppressWarnings) {
606 qWarning(msg: "Warning: Tried to set invalid range for axis. Range automatically adjusted "
607 "to a valid one: %f - %f --> %f - %f",
608 min,
609 max,
610 m_min,
611 m_max);
612 }
613 emit q->rangeChanged(min: m_min, max: m_max);
614 }
615
616 if (minDirty)
617 emit q->minChanged(value: m_min);
618 if (maxDirty)
619 emit q->maxChanged(value: m_max);
620}
621
622void QAbstract3DAxisPrivate::setMin(float min)
623{
624 Q_Q(QAbstract3DAxis);
625 if (!allowNegatives()) {
626 if (allowZero()) {
627 if (min < 0.0f) {
628 min = 0.0f;
629 qWarning(msg: "Warning: Tried to set negative minimum for an axis that only"
630 "supports positive values and zero: %f",
631 min);
632 }
633 } else {
634 if (min <= 0.0f) {
635 min = 1.0f;
636 qWarning(msg: "Warning: Tried to set negative or zero minimum for an "
637 "axis that only"
638 "supports positive values: %f",
639 min);
640 }
641 }
642 }
643
644 if (m_min != min) {
645 bool maxChanged = false;
646 if (min > m_max || (!allowMinMaxSame() && min == m_max)) {
647 float oldMax = m_max;
648 m_max = min + 1.0f;
649 qWarning(msg: "Warning: Tried to set minimum to equal or larger than maximum for"
650 " value axis. Maximum automatically adjusted to a valid one: %f --> %f",
651 oldMax,
652 m_max);
653 maxChanged = true;
654 }
655 m_min = min;
656
657 emit q->rangeChanged(min: m_min, max: m_max);
658 emit q->minChanged(value: m_min);
659 if (maxChanged)
660 emit q->maxChanged(value: m_max);
661 }
662}
663
664void QAbstract3DAxisPrivate::setMax(float max)
665{
666 Q_Q(QAbstract3DAxis);
667 if (!allowNegatives()) {
668 if (allowZero()) {
669 if (max < 0.0f) {
670 max = 0.0f;
671 qWarning(msg: "Warning: Tried to set negative maximum for an axis that only"
672 "supports positive values and zero: %f",
673 max);
674 }
675 } else {
676 if (max <= 0.0f) {
677 max = 1.0f;
678 qWarning(msg: "Warning: Tried to set negative or zero maximum for an "
679 "axis that only"
680 "supports positive values: %f",
681 max);
682 }
683 }
684 }
685
686 if (m_max != max) {
687 bool minChanged = false;
688 if (m_min > max || (!allowMinMaxSame() && m_min == max)) {
689 float oldMin = m_min;
690 m_min = max - 1.0f;
691 if (!allowNegatives() && m_min < 0.0f) {
692 if (allowZero())
693 m_min = 0.0f;
694 else
695 m_min = max / 2.0f; // Need some positive value smaller than max
696
697 if (!allowMinMaxSame() && max == 0.0f) {
698 m_min = oldMin;
699 qWarning(msg: "Unable to set maximum value to zero.");
700 return;
701 }
702 }
703 qWarning(msg: "Warning: Tried to set maximum to equal or smaller than minimum "
704 "for value axis. Minimum automatically adjusted to a valid one: %f --> %f",
705 oldMin,
706 m_min);
707 minChanged = true;
708 }
709 m_max = max;
710 emit q->rangeChanged(min: m_min, max: m_max);
711 emit q->maxChanged(value: m_max);
712 if (minChanged)
713 emit q->minChanged(value: m_min);
714 }
715}
716
717QT_END_NAMESPACE
718

Provided by KDAB

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

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