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

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