1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCharts/QColorAxis>
5#include <QtCharts/QXYSeries>
6#include <private/abstractdomain_p.h>
7#include <private/qcoloraxis_p.h>
8#include <private/qxyseries_p.h>
9#include <private/chartcoloraxisx_p.h>
10#include <private/chartcoloraxisy_p.h>
11#include <private/chartvalueaxisy_p.h>
12#include <private/charthelpers_p.h>
13
14#include <QtCharts/QChart>
15
16QT_BEGIN_NAMESPACE
17/*!
18 \class QColorAxis
19 \inmodule QtCharts
20 \brief The QColorAxis class displays a color scale as one of the chart's axes.
21 \since 6.2
22
23 A color axis can be set up to show a color scale based on the passed gradient.
24 The scale has tick marks with labels based on data passed in QXYSeries::colorby method.
25*/
26
27/*!
28 \property QColorAxis::min
29 \brief The minimum value on the axis.
30
31 When setting this property, the maximum value is adjusted if necessary, to ensure that
32 the range remains valid.
33*/
34
35/*!
36 \property QColorAxis::max
37 \brief The maximum value on the axis.
38
39 When setting this property, the minimum value is adjusted if necessary, to ensure that
40 the range remains valid.
41*/
42
43/*!
44 \property QColorAxis::tickCount
45 \brief The number of tick marks on the axis. This indicates how many grid lines are drawn on the
46 chart if QColorAxis::gridVisible is equal to \c true. The default value is 5, and the number
47 cannot be less than 2.
48
49 \note Grid lines are intentionally invisible by default in QColorAxis as this type of axis
50 does not represent geometric values.
51*/
52
53/*!
54 \property QColorAxis::size
55 \brief The size of the color scale.
56
57 Depending on the alignment the value indicates either width or height.
58*/
59
60/*!
61 \property QColorAxis::autoRange
62 \brief The property indicating if the range should be set from the list of values
63 passed in QXYSeries::colorBy method or rather taken from the axis itself.
64
65 The default value is \c true.
66*/
67
68/*!
69 \fn void QColorAxis::minChanged(qreal min)
70 This signal is emitted when the minimum value of the axis, specified by \a min, changes.
71*/
72
73/*!
74 \fn void QColorAxis::maxChanged(qreal max)
75 This signal is emitted when the maximum value of the axis, specified by \a max, changes.
76*/
77
78/*!
79 \fn void QColorAxis::tickCountChanged(int tickCount)
80 This signal is emitted when the number of tick marks on the axis, specified by \a tickCount,
81 changes.
82*/
83
84/*!
85 \fn void QColorAxis::sizeChanged(qreal size)
86 This signal is emitted when the size of the color scale, specified by \a size, changes.
87*/
88
89/*!
90 \fn void QColorAxis::autoRangeChanged(bool autoRange)
91 This signal is emitted when the auto range mode, specified by \a autoRange, changes.
92*/
93
94/*!
95 \fn void QColorAxis::rangeChanged(qreal min, qreal max)
96 This signal is emitted when the minimum or maximum value of the axis, specified by \a min
97 and \a max, changes.
98*/
99
100QColorAxis::QColorAxis(QObject *parent)
101 : QAbstractAxis(*new QColorAxisPrivate(this), parent)
102{
103 setGridLineVisible(false);
104 QPen linePen = QPen(Qt::black);
105 linePen.setWidthF(2.0);
106 setLinePen(linePen);
107}
108
109/*!
110 \internal
111*/
112QColorAxis::QColorAxis(QColorAxisPrivate &d, QObject *parent)
113 : QAbstractAxis(d, parent)
114{
115
116}
117
118/*!
119 Destroys the object.
120*/
121QColorAxis::~QColorAxis()
122{
123 Q_D(QColorAxis);
124 if (d->m_chart)
125 d->m_chart->removeAxis(axis: this);
126}
127
128QAbstractAxis::AxisType QColorAxis::type() const
129{
130 return QAbstractAxis::AxisTypeColor;
131}
132
133void QColorAxis::setMin(qreal min)
134{
135 Q_D(QColorAxis);
136 setRange(min, max: qMax(a: d->m_max, b: min));
137}
138
139qreal QColorAxis::min() const
140{
141 Q_D(const QColorAxis);
142 return d->m_min;
143}
144
145void QColorAxis::setMax(qreal max)
146{
147 Q_D(QColorAxis);
148 setRange(min: qMin(a: d->m_min, b: max), max);
149}
150
151qreal QColorAxis::max() const
152{
153 Q_D(const QColorAxis);
154 return d->m_max;
155}
156
157void QColorAxis::setRange(qreal min, qreal max)
158{
159 Q_D(QColorAxis);
160 d->setRange(min, max);
161}
162
163void QColorAxis::setTickCount(int count)
164{
165 Q_D(QColorAxis);
166 if (d->m_tickCount != count && count >= 2) {
167 d->m_tickCount = count;
168 emit tickCountChanged(tickCount: count);
169 }
170}
171
172int QColorAxis::tickCount() const
173{
174 Q_D(const QColorAxis);
175 return d->m_tickCount;
176}
177
178void QColorAxis::setSize(const qreal size)
179{
180 Q_D(QColorAxis);
181 if (d->m_size != size) {
182 d->m_size = size;
183 emit sizeChanged(size);
184 }
185}
186
187qreal QColorAxis::size() const
188{
189 Q_D(const QColorAxis);
190 return d->m_size;
191}
192
193/*!
194 Sets the gradient on the color scale to \a gradient.
195
196 \note If the axis is attached to a series, the gradient is also used
197 by the QXYSeries::colorBy method.
198 \sa gradient
199*/
200void QColorAxis::setGradient(const QLinearGradient &gradient)
201{
202 Q_D(QColorAxis);
203 if (d->m_gradient != gradient) {
204 d->m_gradient = gradient;
205 emit gradientChanged(gradient);
206 }
207}
208
209/*!
210 Returns the gradient currently used on the color scale.
211
212 \note If the axis is attached to a series, the gradient is also used
213 by the QXYSeries::colorBy method.
214 \sa setGradient
215*/
216QLinearGradient QColorAxis::gradient() const
217{
218 Q_D(const QColorAxis);
219 return d->m_gradient;
220}
221
222void QColorAxis::setAutoRange(bool autoRange)
223{
224 Q_D(QColorAxis);
225 if (d->m_autoRange != autoRange) {
226 d->m_autoRange = autoRange;
227 emit autoRangeChanged(autoRange: d->m_autoRange);
228 }
229}
230
231bool QColorAxis::autoRange() const
232{
233 Q_D(const QColorAxis);
234 return d->m_autoRange;
235}
236
237QColorAxisPrivate::QColorAxisPrivate(QColorAxis *q)
238 : QAbstractAxisPrivate(q)
239 , m_min(0)
240 , m_max(1)
241 , m_tickCount(5)
242 , m_size(15)
243 , m_autoRange(true)
244{
245 m_gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100));
246 m_gradient.setColorAt(pos: 0, color: Qt::white);
247 m_gradient.setColorAt(pos: 1, color: Qt::black);
248}
249
250QColorAxisPrivate::~QColorAxisPrivate()
251{
252
253}
254
255void QColorAxisPrivate::initializeGraphics(QGraphicsItem *parent)
256{
257 Q_Q(QColorAxis);
258 ChartAxisElement *axis(0);
259 if (m_chart->chartType() == QChart::ChartTypeCartesian) {
260 if (orientation() == Qt::Vertical)
261 axis = new ChartColorAxisY(q, parent);
262 else if (orientation() == Qt::Horizontal)
263 axis = new ChartColorAxisX(q, parent);
264 }
265
266 if (m_chart->chartType() == QChart::ChartTypePolar)
267 qWarning() << "Polar chart is not supported by color axis.";
268
269 m_item.reset(p: axis);
270 QAbstractAxisPrivate::initializeGraphics(parent);
271}
272
273void QColorAxisPrivate::initializeDomain(AbstractDomain *domain)
274{
275 Q_UNUSED(domain);
276 if (orientation() == Qt::Vertical) {
277 if (m_autoRange)
278 updateSeries();
279 else
280 setRange(min: m_min, max: m_max);
281 }
282
283 if (orientation() == Qt::Horizontal) {
284 if (m_autoRange)
285 updateSeries();
286 else
287 setRange(min: m_min, max: m_max);
288 }
289}
290
291void QColorAxisPrivate::setRange(qreal min, qreal max)
292{
293 Q_Q(QColorAxis);
294 bool changed = false;
295
296 if (min > max)
297 return;
298
299 if (!isValidValue(x: min, y: max)) {
300 qWarning() << "Attempting to set invalid range for value axis: ["
301 << min << " - " << max << "]";
302 return;
303 }
304
305 if (m_min != min) {
306 m_min = min;
307 changed = true;
308 emit q->minChanged(min);
309 }
310
311 if (m_max != max) {
312 m_max = max;
313 changed = true;
314 emit q->maxChanged(max);
315 }
316
317 if (changed) {
318 emit rangeChanged(min,max);
319 emit q->rangeChanged(min, max);
320
321 if (!m_autoRange)
322 updateSeries();
323 }
324}
325
326void QColorAxisPrivate::updateSeries()
327{
328 const QList<QAbstractSeries *> series = m_series;
329 for (const auto &serie : series) {
330 if (serie->type() == QAbstractSeries::SeriesTypeLine
331 || serie->type() == QAbstractSeries::SeriesTypeSpline
332 || serie->type() == QAbstractSeries::SeriesTypeScatter) {
333 QXYSeries *xySeries = static_cast<QXYSeries *>(serie);
334 const auto &colorByData = xySeries->d_func()->colorByData();
335 if (!colorByData.isEmpty())
336 xySeries->colorBy(sourceData: colorByData);
337 }
338 }
339}
340
341void QColorAxisPrivate::setMin(const QVariant &min)
342{
343 Q_Q(QColorAxis);
344 bool ok;
345 qreal value = min.toReal(ok: &ok);
346 if (ok)
347 q->setMin(value);
348}
349
350void QColorAxisPrivate::setMax(const QVariant &max)
351{
352 Q_Q(QColorAxis);
353 bool ok;
354 qreal value = max.toReal(ok: &ok);
355 if (ok)
356 q->setMax(value);
357}
358
359void QColorAxisPrivate::setRange(const QVariant &min, const QVariant &max)
360{
361 Q_Q(QColorAxis);
362 bool ok1;
363 bool ok2;
364 qreal value1 = min.toReal(ok: &ok1);
365 qreal value2 = max.toReal(ok: &ok2);
366 if (ok1 && ok2)
367 q->setRange(min: value1, max: value2);
368}
369
370QT_END_NAMESPACE
371
372#include "moc_qcoloraxis.cpp"
373#include "moc_qcoloraxis_p.cpp"
374

source code of qtcharts/src/charts/axis/coloraxis/qcoloraxis.cpp