1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtCharts/QDateTimeAxis>
5#include <private/qdatetimeaxis_p.h>
6#include <private/chartdatetimeaxisx_p.h>
7#include <private/chartdatetimeaxisy_p.h>
8#include <private/polarchartdatetimeaxisangular_p.h>
9#include <private/polarchartdatetimeaxisradial_p.h>
10#include <private/abstractdomain_p.h>
11#include <QtCharts/QChart>
12#include <float.h>
13#include <cmath>
14
15QT_BEGIN_NAMESPACE
16/*!
17 \class QDateTimeAxis
18 \inmodule QtCharts
19 \brief The QDateTimeAxis class adds dates and times to a chart's axis.
20
21 QDateTimeAxis can be set up to show an axis line with tick marks, grid lines, and shades.
22 The labels can be configured by setting an appropriate DateTime format.
23 QDateTimeAxis works correctly with dates from 4714 BCE to 287396 CE.
24 For other limitiations related to QDateTime, see QDateTime documentation.
25
26 \note QDateTimeAxis is disabled on platforms that define qreal as float.
27
28 \image api_datatime_axis.png
29
30 QDateTimeAxis can be used with any QXYSeries.
31 To add a data point to the series, QDateTime::toMSecsSinceEpoch() is used:
32 \code
33 QLineSeries *series = new QLineSeries;
34
35 QDateTime xValue;
36 xValue.setDate(QDate(2012, 1 , 18));
37 xValue.setTime(QTime(9, 34));
38 qreal yValue = 12;
39 series->append(xValue.toMSecsSinceEpoch(), yValue);
40
41 xValue.setDate(QDate(2013, 5 , 11));
42 xValue.setTime(QTime(11, 14));
43 qreal yValue = 22;
44 series->append(xValue.toMSecsSinceEpoch(), yValue);
45 \endcode
46
47 The following code snippet illustrates adding the series to the chart and setting up
48 QDateTimeAxis:
49 \code
50 QChartView *chartView = new QChartView;
51 chartView->chart()->addSeries(series);
52
53 // ...
54 QDateTimeAxis *axisX = new QDateTimeAxis;
55 axisX->setFormat("dd-MM-yyyy h:mm");
56 chartView->chart()->setAxisX(axisX, series);
57 \endcode
58*/
59
60/*!
61 \qmltype DateTimeAxis
62 \instantiates QDateTimeAxis
63 \inqmlmodule QtCharts
64
65 \brief Adds dates and times to a chart's axis.
66 \inherits AbstractAxis
67
68 The DateTimeAxis type can be set up to show an axis line with tick marks, grid lines,
69 and shades. The axis labels display dates and times and can be configured by setting
70 an appropriate DateTime format.
71
72 \note Any date before 4714 BCE or after about 1.4 million CE may not be accurately stored.
73*/
74
75/*!
76 \property QDateTimeAxis::min
77 \brief The minimum value on the axis.
78
79 When setting this property, the maximum value is adjusted if necessary, to ensure that the
80 range remains valid.
81*/
82/*!
83 \qmlproperty datetime DateTimeAxis::min
84 The minimum value on the axis.
85
86 When setting this property, the maximum value is adjusted if necessary, to ensure that the
87 range remains valid.
88*/
89
90/*!
91 \property QDateTimeAxis::max
92 \brief The maximum value on the axis.
93
94 When setting this property, the minimum value is adjusted if necessary, to ensure that the
95 range remains valid.
96*/
97/*!
98 \qmlproperty datetime DateTimeAxis::max
99 The maximum value on the axis.
100
101 When setting this property, the minimum value is adjusted if necessary, to ensure that the
102 range remains valid.
103*/
104
105/*!
106 \fn void QDateTimeAxis::minChanged(QDateTime min)
107 This signal is emitted when the minimum value of the axis, specified by \a min, changes.
108*/
109
110/*!
111 \fn void QDateTimeAxis::maxChanged(QDateTime max)
112 This signal is emitted when the maximum value of the axis, specified by \a max, changes.
113*/
114
115/*!
116 \fn void QDateTimeAxis::rangeChanged(QDateTime min, QDateTime max)
117 This signal is emitted when the minimum or maximum value of the axis, specified by \a min
118 and \a max, changes.
119*/
120
121/*!
122 \qmlmethod DateTimeAxis::rangeChanged(datetime min, datetime max)
123 This signal is emitted when the minimum or maximum value of the axis, specified by \a min
124 and \a max, changes.
125
126 The corresponding signal handler is \c onRangeChanged().
127*/
128
129/*!
130 \property QDateTimeAxis::tickCount
131 \brief The number of tick marks on the axis.
132*/
133
134/*!
135 \qmlproperty int DateTimeAxis::tickCount
136 The number of tick marks on the axis.
137*/
138
139/*!
140 \property QDateTimeAxis::format
141 \brief The format string that is used when creating the label for the axis out of a
142 QDateTime object.
143
144 See QDateTime documentation for information on how the string should be defined.
145
146 \sa QChart::locale
147*/
148/*!
149 \qmlproperty string DateTimeAxis::format
150 The format string that is used when creating the label for the axis out of a QDateTime object.
151 See QDateTime documentation for information on how the string should be defined.
152*/
153
154/*!
155 \fn void QDateTimeAxis::tickCountChanged(int tickCount)
156 This signal is emitted when the number of tick marks on the axis, specified by \a tickCount,
157 changes.
158*/
159
160/*!
161 \fn void QDateTimeAxis::formatChanged(QString format)
162 This signal is emitted when the \a format of the axis changes.
163*/
164
165/*!
166 Constructs an axis object that is a child of \a parent.
167*/
168QDateTimeAxis::QDateTimeAxis(QObject *parent) :
169 QAbstractAxis(*new QDateTimeAxisPrivate(this), parent)
170{
171
172}
173
174/*!
175 \internal
176*/
177QDateTimeAxis::QDateTimeAxis(QDateTimeAxisPrivate &d, QObject *parent) : QAbstractAxis(d, parent)
178{
179
180}
181
182/*!
183 Destroys the object.
184*/
185QDateTimeAxis::~QDateTimeAxis()
186{
187 Q_D(QDateTimeAxis);
188 if (d->m_chart)
189 d->m_chart->removeAxis(axis: this);
190}
191
192void QDateTimeAxis::setMin(QDateTime min)
193{
194 Q_D(QDateTimeAxis);
195 if (min.isValid())
196 d->setRange(min: min.toMSecsSinceEpoch(), max: qMax(a: d->m_max, b: qreal(min.toMSecsSinceEpoch())));
197}
198
199QDateTime QDateTimeAxis::min() const
200{
201 Q_D(const QDateTimeAxis);
202 return QDateTime::fromMSecsSinceEpoch(msecs: d->m_min);
203}
204
205void QDateTimeAxis::setMax(QDateTime max)
206{
207 Q_D(QDateTimeAxis);
208 if (max.isValid())
209 d->setRange(min: qMin(a: d->m_min, b: qreal(max.toMSecsSinceEpoch())), max: max.toMSecsSinceEpoch());
210}
211
212QDateTime QDateTimeAxis::max() const
213{
214 Q_D(const QDateTimeAxis);
215 return QDateTime::fromMSecsSinceEpoch(msecs: d->m_max);
216}
217
218/*!
219 Sets the range on the axis from \a min to \a max.
220 If \a min is greater than \a max, this function returns without making any changes.
221*/
222void QDateTimeAxis::setRange(QDateTime min, QDateTime max)
223{
224 Q_D(QDateTimeAxis);
225 if (!min.isValid() || !max.isValid() || min > max)
226 return;
227
228 d->setRange(min: min.toMSecsSinceEpoch(),max: max.toMSecsSinceEpoch());
229}
230
231void QDateTimeAxis::setFormat(QString format)
232{
233 Q_D(QDateTimeAxis);
234 if (d->m_format != format) {
235 d->m_format = format;
236 if (d->axisItem())
237 static_cast<CartesianChartAxis*>(d->axisItem())->setDateTimeLabelsFormat(format);
238 emit formatChanged(format);
239 }
240}
241
242QString QDateTimeAxis::format() const
243{
244 Q_D(const QDateTimeAxis);
245 return d->m_format;
246}
247
248/*!
249 Sets the number of tick marks on the axis to \a count.
250*/
251void QDateTimeAxis::setTickCount(int count)
252{
253 Q_D(QDateTimeAxis);
254 if (d->m_tickCount != count && count >= 2) {
255 d->m_tickCount = count;
256 emit tickCountChanged(tick: count);
257 }
258}
259
260/*!
261 \fn int QDateTimeAxis::tickCount() const
262 Returns the number of tick marks on the axis.
263*/
264int QDateTimeAxis::tickCount() const
265{
266 Q_D(const QDateTimeAxis);
267 return d->m_tickCount;
268}
269
270/*!
271 Returns the type of the axis.
272*/
273QAbstractAxis::AxisType QDateTimeAxis::type() const
274{
275 return AxisTypeDateTime;
276}
277
278/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
279
280QDateTimeAxisPrivate::QDateTimeAxisPrivate(QDateTimeAxis *q)
281 : QAbstractAxisPrivate(q),
282 m_min(0),
283 m_max(0),
284 m_tickCount(5)
285{
286 m_format = QStringLiteral("dd-MM-yyyy\nh:mm");
287}
288
289QDateTimeAxisPrivate::~QDateTimeAxisPrivate()
290{
291
292}
293
294void QDateTimeAxisPrivate::setRange(qreal min,qreal max)
295{
296 Q_Q(QDateTimeAxis);
297
298 bool changed = false;
299
300 if (m_min != min) {
301 m_min = min;
302 changed = true;
303 emit q->minChanged(min: QDateTime::fromMSecsSinceEpoch(msecs: min));
304 }
305
306 if (m_max != max) {
307 m_max = max;
308 changed = true;
309 emit q->maxChanged(max: QDateTime::fromMSecsSinceEpoch(msecs: max));
310 }
311
312 if (changed) {
313 emit q->rangeChanged(min: QDateTime::fromMSecsSinceEpoch(msecs: min), max: QDateTime::fromMSecsSinceEpoch(msecs: max));
314 emit rangeChanged(min: m_min,max: m_max);
315 }
316}
317
318void QDateTimeAxisPrivate::setMin(const QVariant &min)
319{
320 Q_Q(QDateTimeAxis);
321 if (min.canConvert<QDateTime>())
322 q->setMin(min.toDateTime());
323}
324
325void QDateTimeAxisPrivate::setMax(const QVariant &max)
326{
327
328 Q_Q(QDateTimeAxis);
329 if (max.canConvert<QDateTime>())
330 q->setMax(max.toDateTime());
331}
332
333void QDateTimeAxisPrivate::setRange(const QVariant &min, const QVariant &max)
334{
335 Q_Q(QDateTimeAxis);
336 if (min.canConvert<QDateTime>() && max.canConvert<QDateTime>())
337 q->setRange(min: min.toDateTime(), max: max.toDateTime());
338}
339
340void QDateTimeAxisPrivate::initializeGraphics(QGraphicsItem* parent)
341{
342 Q_Q(QDateTimeAxis);
343 ChartAxisElement *axis(0);
344 if (m_chart->chartType() == QChart::ChartTypeCartesian) {
345 if (orientation() == Qt::Vertical)
346 axis = new ChartDateTimeAxisY(q,parent);
347 if (orientation() == Qt::Horizontal)
348 axis = new ChartDateTimeAxisX(q,parent);
349 axis->setLabelsEditable(q->labelsEditable());
350 }
351
352 if (m_chart->chartType() == QChart::ChartTypePolar) {
353 if (orientation() == Qt::Vertical)
354 axis = new PolarChartDateTimeAxisRadial(q, parent);
355 if (orientation() == Qt::Horizontal)
356 axis = new PolarChartDateTimeAxisAngular(q, parent);
357 }
358
359 m_item.reset(p: axis);
360 QAbstractAxisPrivate::initializeGraphics(parent);
361}
362
363void QDateTimeAxisPrivate::initializeDomain(AbstractDomain *domain)
364{
365 if (m_max == m_min) {
366 if (orientation() == Qt::Vertical)
367 setRange(min: domain->minY(), max: domain->maxY());
368 else
369 setRange(min: domain->minX(), max: domain->maxX());
370 } else {
371 if (orientation() == Qt::Vertical)
372 domain->setRangeY(min: m_min, max: m_max);
373 else
374 domain->setRangeX(min: m_min, max: m_max);
375 }
376}
377
378QT_END_NAMESPACE
379
380#include "moc_qdatetimeaxis.cpp"
381#include "moc_qdatetimeaxis_p.cpp"
382

source code of qtcharts/src/charts/axis/datetimeaxis/qdatetimeaxis.cpp