1 | // Copyright (C) 2024 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include <QtCore/QObject> |
5 | #include <QtGraphs/QDateTimeAxis> |
6 | #include "private/qdatetimeaxis_p.h" |
7 | |
8 | QT_BEGIN_NAMESPACE |
9 | /*! |
10 | \class QDateTimeAxis |
11 | \inmodule QtGraphs |
12 | \ingroup graphs_2D |
13 | \brief The QDateTimeAxis adds support for DateTime values to be added to a graph's axis. |
14 | |
15 | A DateTime Axis can be used to display DateTime representations with tick marks and grid lines. |
16 | The DateTime items on the axis are displayed at the position of the ticks. |
17 | */ |
18 | |
19 | /*! |
20 | \qmltype DateTimeAxis |
21 | \nativetype QDateTimeAxis |
22 | \inqmlmodule QtGraphs |
23 | \ingroup graphs_qml_2D |
24 | \inherits AbstractAxis |
25 | \brief Adds DateTime items to a graph's axis. |
26 | |
27 | A DateTime Axis can be used to display DateTime representations with tick marks and grid lines. |
28 | The DateTime items on the axis are displayed at the position of the ticks. |
29 | |
30 | The following example code illustrates how to use the DateTimeAxis type: |
31 | \code |
32 | GraphsView { |
33 | axisX: DateTimeAxis { |
34 | min: new Date(2000,1,1) |
35 | max: new Date(1970,1,1) |
36 | } |
37 | LineSeries { |
38 | // Add a few XYPoint data... |
39 | } |
40 | } |
41 | \endcode |
42 | */ |
43 | |
44 | /*! |
45 | \property QDateTimeAxis::min |
46 | \brief The minimum value on the axis |
47 | |
48 | This value can be lower or higher than the maximum. |
49 | The DateTime is stored as UTC internally. |
50 | The default value is new Date(1970,1,1) |
51 | */ |
52 | /*! |
53 | \qmlproperty real DateTimeAxis::min |
54 | The minimum value on the axis. |
55 | |
56 | This value can be lower or higher than the maximum. |
57 | The DateTime is stored as UTC internally. |
58 | The default value is new Date(1970,1,1) |
59 | */ |
60 | |
61 | /*! |
62 | \property QDateTimeAxis::max |
63 | \brief The maximum value on the axis |
64 | |
65 | This value can be lower or higher than the minimum. |
66 | The DateTime is stored as UTC internally. |
67 | The default value is new Date(1980,1,1) |
68 | */ |
69 | /*! |
70 | \qmlproperty real DateTimeAxis::max |
71 | The maximum value on the axis. |
72 | |
73 | This value can be lower or higher than the minimum. |
74 | The DateTime is stored as UTC internally. |
75 | The default value is new Date(1980,1,1) |
76 | */ |
77 | /*! |
78 | \property QDateTimeAxis::subTickCount |
79 | \brief The number of subticks on the axis. This indicates how many subticks are drawn |
80 | between major lines on the graph. Labels are not drawn for subticks. The default value is 0. |
81 | */ |
82 | /*! |
83 | \qmlproperty int DateTimeAxis::subTickCount |
84 | The number of subticks on the axis. This indicates how many subticks are drawn |
85 | between major lines on the graph. Labels are not drawn for subticks. The default value is 0. |
86 | */ |
87 | /*! |
88 | \property QDateTimeAxis::tickInterval |
89 | \brief The interval between dynamically placed tick marks and labels. |
90 | The default value is 0, which means that intervals are automatically calculated |
91 | based on the min and max range. |
92 | */ |
93 | /*! |
94 | \qmlproperty real DateTimeAxis::tickInterval |
95 | The interval between dynamically placed tick marks and labels. |
96 | The default value is 0, which means that intervals are automatically calculated |
97 | based on the min and max range. |
98 | */ |
99 | |
100 | /*! |
101 | \property QDateTimeAxis::labelFormat |
102 | \brief The format of the DateTime labels on the axis. |
103 | The format property allows to signify the visual representation of the DateTime object, in days, |
104 | months, and years. The default value is dd-MMMM-yy. |
105 | */ |
106 | |
107 | /*! |
108 | \qmlproperty string DateTimeAxis::labelFormat |
109 | The format of the DateTime labels on the axis |
110 | The format property allows to signify the visual representation of the DateTime object, in days, |
111 | months, and years. The default value is dd-MMMM-yy. |
112 | */ |
113 | /*! |
114 | \qmlsignal DateTimeAxis::minChanged(DateTime min) |
115 | This signal is emitted when the minimum value of the axis, specified by \a min, changes. |
116 | */ |
117 | /*! |
118 | \qmlsignal DateTimeAxis::maxChanged(DateTime max) |
119 | This signal is emitted when the maximum value of the axis, specified by \a max, changes. |
120 | */ |
121 | /*! |
122 | \qmlsignal DateTimeAxis::subTickCountChanged(int subTickCount) |
123 | This signal is emitted when the number of subticks on the axis, specified by |
124 | \a subTickCount, changes. |
125 | */ |
126 | /*! |
127 | \qmlsignal DateTimeAxis::rangeChanged(real min, real max) |
128 | This signal is emitted when the minimum or maximum value of the axis, specified by \a min |
129 | and \a max, changes. |
130 | */ |
131 | /*! |
132 | \qmlsignal DateTimeAxis::labelFormatChanged(string format) |
133 | This signal is emitted when the \a format of axis labels changes. |
134 | */ |
135 | /*! |
136 | \qmlsignal DateTimeAxis::tickIntervalChanged(real tickInterval) |
137 | This signal is emitted when the tick interval value, specified by |
138 | \a tickInterval, changes. |
139 | */ |
140 | |
141 | QDateTimeAxis::QDateTimeAxis(QObject *parent) |
142 | : QAbstractAxis(*(new QDateTimeAxisPrivate), parent) |
143 | {} |
144 | |
145 | QDateTimeAxis::~QDateTimeAxis() |
146 | { |
147 | } |
148 | |
149 | QAbstractAxis::AxisType QDateTimeAxis::type() const |
150 | { |
151 | return QAbstractAxis::AxisType::DateTime; |
152 | } |
153 | |
154 | void QDateTimeAxis::setMin(const QDateTime &min) |
155 | { |
156 | Q_D(QDateTimeAxis); |
157 | if (min.isValid()) { |
158 | d->setRange(min: min.toMSecsSinceEpoch(), max: d->m_max); |
159 | emit update(); |
160 | } |
161 | } |
162 | |
163 | QDateTime QDateTimeAxis::min() const |
164 | { |
165 | Q_D(const QDateTimeAxis); |
166 | return QDateTime::fromMSecsSinceEpoch(msecs: d->m_min, timeZone: QTimeZone::UTC); |
167 | } |
168 | |
169 | void QDateTimeAxis::setMax(const QDateTime &max) |
170 | { |
171 | Q_D(QDateTimeAxis); |
172 | if (max.isValid()) { |
173 | d->setRange(min: d->m_min, max: max.toMSecsSinceEpoch()); |
174 | emit update(); |
175 | } |
176 | } |
177 | |
178 | QDateTime QDateTimeAxis::max() const |
179 | { |
180 | Q_D(const QDateTimeAxis); |
181 | return QDateTime::fromMSecsSinceEpoch(msecs: d->m_max, timeZone: QTimeZone::UTC); |
182 | } |
183 | |
184 | void QDateTimeAxis::setLabelFormat(const QString &format) |
185 | { |
186 | Q_D(QDateTimeAxis); |
187 | if (d->m_format != format) { |
188 | d->m_format = format; |
189 | emit labelFormatChanged(format); |
190 | emit update(); |
191 | } |
192 | } |
193 | |
194 | QString QDateTimeAxis::labelFormat() const |
195 | { |
196 | Q_D(const QDateTimeAxis); |
197 | return d->m_format; |
198 | } |
199 | |
200 | qreal QDateTimeAxis::tickInterval() const |
201 | { |
202 | Q_D(const QDateTimeAxis); |
203 | return d->m_tickInterval; |
204 | } |
205 | |
206 | void QDateTimeAxis::setTickInterval(qreal newTickInterval) |
207 | { |
208 | Q_D(QDateTimeAxis); |
209 | |
210 | if (newTickInterval < 0.0) |
211 | newTickInterval = 0.0; |
212 | |
213 | if (qFuzzyCompare(p1: d->m_tickInterval, p2: newTickInterval)) |
214 | return; |
215 | d->m_tickInterval = newTickInterval; |
216 | emit tickIntervalChanged(); |
217 | emit update(); |
218 | } |
219 | |
220 | int QDateTimeAxis::subTickCount() const |
221 | { |
222 | Q_D(const QDateTimeAxis); |
223 | return d->m_subTickCount; |
224 | } |
225 | |
226 | void QDateTimeAxis::setSubTickCount(int newSubTickCount) |
227 | { |
228 | Q_D(QDateTimeAxis); |
229 | |
230 | if (newSubTickCount < 0.0) |
231 | newSubTickCount = 0.0; |
232 | |
233 | if (d->m_subTickCount == newSubTickCount) |
234 | return; |
235 | d->m_subTickCount = newSubTickCount; |
236 | emit subTickCountChanged(); |
237 | emit update(); |
238 | } |
239 | |
240 | /////////////////////////////////////////////////////////////////////////////// |
241 | |
242 | QDateTimeAxisPrivate::QDateTimeAxisPrivate() {} |
243 | |
244 | QDateTimeAxisPrivate::~QDateTimeAxisPrivate() {} |
245 | |
246 | void QDateTimeAxisPrivate::setMin(const QVariant &min) |
247 | { |
248 | Q_Q(QDateTimeAxis); |
249 | if (min.canConvert<QDateTime>()) |
250 | q->setMin(min.toDateTime()); |
251 | } |
252 | |
253 | void QDateTimeAxisPrivate::setMax(const QVariant &max) |
254 | { |
255 | Q_Q(QDateTimeAxis); |
256 | if (max.canConvert<QDateTime>()) |
257 | q->setMax(max.toDateTime()); |
258 | } |
259 | |
260 | void QDateTimeAxisPrivate::setRange(const QVariant &min, const QVariant &max) |
261 | { |
262 | Q_Q(QDateTimeAxis); |
263 | if (min.canConvert<QDateTime>() && max.canConvert<QDateTime>()) |
264 | q->setRange(min: min.toDateTime(), max: max.toDateTime()); |
265 | } |
266 | |
267 | void QDateTimeAxisPrivate::setRange(qreal min, qreal max) |
268 | { |
269 | Q_Q(QDateTimeAxis); |
270 | |
271 | bool changed = false; |
272 | |
273 | if (m_min != min) { |
274 | m_min = min; |
275 | changed = true; |
276 | emit q->minChanged(min: QDateTime::fromMSecsSinceEpoch(msecs: min, timeZone: QTimeZone::UTC)); |
277 | } |
278 | |
279 | if (m_max != max) { |
280 | m_max = max; |
281 | changed = true; |
282 | emit q->maxChanged(max: QDateTime::fromMSecsSinceEpoch(msecs: max, timeZone: QTimeZone::UTC)); |
283 | } |
284 | |
285 | if (changed) |
286 | emit q->rangeChanged(min, max); |
287 | } |
288 | |
289 | QT_END_NAMESPACE |
290 | |