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 QtPositioning module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
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 Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | #include "qgeopositioninfo.h" |
40 | #include "qgeopositioninfo_p.h" |
41 | #include <QHash> |
42 | #include <QDebug> |
43 | #include <QDataStream> |
44 | #include <QtCore/QtNumeric> |
45 | |
46 | #include <algorithm> |
47 | |
48 | QT_BEGIN_NAMESPACE |
49 | |
50 | /*! |
51 | \class QGeoPositionInfo |
52 | \inmodule QtPositioning |
53 | \ingroup QtPositioning-positioning |
54 | \since 5.2 |
55 | |
56 | \brief The QGeoPositionInfo class contains information gathered on a global position, direction and velocity at a particular point in time. |
57 | |
58 | A QGeoPositionInfo contains, at a minimum, a geographical coordinate and |
59 | a timestamp. It may also have heading and speed measurements as well as |
60 | estimates of the accuracy of the provided data. |
61 | |
62 | \sa QGeoPositionInfoSource |
63 | */ |
64 | |
65 | /*! |
66 | \enum QGeoPositionInfo::Attribute |
67 | Defines the attributes for positional information. |
68 | |
69 | \value Direction The bearing measured in degrees clockwise from true north to the direction of travel. |
70 | \value GroundSpeed The ground speed, in meters/sec. |
71 | \value VerticalSpeed The vertical speed, in meters/sec. |
72 | \value MagneticVariation The angle between the horizontal component of the magnetic field and true north, in degrees. Also known as magnetic declination. A positive value indicates a clockwise direction from true north and a negative value indicates a counter-clockwise direction. |
73 | \value HorizontalAccuracy The accuracy of the provided latitude-longitude value, in meters. |
74 | \value VerticalAccuracy The accuracy of the provided altitude value, in meters. |
75 | */ |
76 | |
77 | /*! |
78 | Creates an invalid QGeoPositionInfo object. |
79 | |
80 | \sa isValid() |
81 | */ |
82 | QGeoPositionInfo::QGeoPositionInfo() |
83 | : d(new QGeoPositionInfoPrivate) |
84 | { |
85 | } |
86 | |
87 | /*! |
88 | Creates a QGeoPositionInfo for the given \a coordinate and \a timestamp. |
89 | */ |
90 | QGeoPositionInfo::QGeoPositionInfo(const QGeoCoordinate &coordinate, const QDateTime ×tamp) |
91 | : d(new QGeoPositionInfoPrivate) |
92 | { |
93 | d->timestamp = timestamp; |
94 | d->coord = coordinate; |
95 | } |
96 | |
97 | /*! |
98 | Creates a QGeoPositionInfo with the values of \a other. |
99 | */ |
100 | QGeoPositionInfo::QGeoPositionInfo(const QGeoPositionInfo &other) |
101 | : d(other.d->clone()) |
102 | { |
103 | } |
104 | |
105 | QGeoPositionInfo::QGeoPositionInfo(QGeoPositionInfoPrivate &dd) : d(&dd) |
106 | { |
107 | } |
108 | |
109 | /*! |
110 | Destroys a QGeoPositionInfo object. |
111 | */ |
112 | QGeoPositionInfo::~QGeoPositionInfo() |
113 | { |
114 | delete d; |
115 | } |
116 | |
117 | /*! |
118 | Assigns the values from \a other to this QGeoPositionInfo. |
119 | */ |
120 | QGeoPositionInfo &QGeoPositionInfo::operator=(const QGeoPositionInfo & other) |
121 | { |
122 | if (this == &other) |
123 | return *this; |
124 | |
125 | delete d; |
126 | d = other.d->clone(); |
127 | |
128 | // d->timestamp = other.d->timestamp; |
129 | // d->coord = other.d->coord; |
130 | // d->doubleAttribs = other.d->doubleAttribs; |
131 | |
132 | return *this; |
133 | } |
134 | |
135 | /*! |
136 | Returns true if all of this object's values are the same as those of |
137 | \a other. |
138 | */ |
139 | bool QGeoPositionInfo::operator==(const QGeoPositionInfo &other) const |
140 | { |
141 | return *d == *other.d; |
142 | } |
143 | |
144 | /*! |
145 | \fn bool QGeoPositionInfo::operator!=(const QGeoPositionInfo &other) const |
146 | |
147 | Returns true if any of this object's values are not the same as those of |
148 | \a other. |
149 | */ |
150 | |
151 | /*! |
152 | Returns true if the timestamp() and coordinate() values are both valid. |
153 | |
154 | \sa QGeoCoordinate::isValid(), QDateTime::isValid() |
155 | */ |
156 | bool QGeoPositionInfo::isValid() const |
157 | { |
158 | return d->timestamp.isValid() && d->coord.isValid(); |
159 | } |
160 | |
161 | /*! |
162 | Sets the date and time at which this position was reported to \a timestamp. |
163 | |
164 | The \a timestamp must be in UTC time. |
165 | |
166 | \sa timestamp() |
167 | */ |
168 | void QGeoPositionInfo::setTimestamp(const QDateTime ×tamp) |
169 | { |
170 | d->timestamp = timestamp; |
171 | } |
172 | |
173 | /*! |
174 | Returns the date and time at which this position was reported, in UTC time. |
175 | |
176 | Returns an invalid QDateTime if no date/time value has been set. |
177 | |
178 | \sa setTimestamp() |
179 | */ |
180 | QDateTime QGeoPositionInfo::timestamp() const |
181 | { |
182 | return d->timestamp; |
183 | } |
184 | |
185 | /*! |
186 | Sets the coordinate for this position to \a coordinate. |
187 | |
188 | \sa coordinate() |
189 | */ |
190 | void QGeoPositionInfo::setCoordinate(const QGeoCoordinate &coordinate) |
191 | { |
192 | d->coord = coordinate; |
193 | } |
194 | |
195 | /*! |
196 | Returns the coordinate for this position. |
197 | |
198 | Returns an invalid coordinate if no coordinate has been set. |
199 | |
200 | \sa setCoordinate() |
201 | */ |
202 | QGeoCoordinate QGeoPositionInfo::coordinate() const |
203 | { |
204 | return d->coord; |
205 | } |
206 | |
207 | /*! |
208 | Sets the value for \a attribute to \a value. |
209 | |
210 | \sa attribute() |
211 | */ |
212 | void QGeoPositionInfo::setAttribute(Attribute attribute, qreal value) |
213 | { |
214 | d->doubleAttribs[attribute] = value; |
215 | } |
216 | |
217 | /*! |
218 | Returns the value of the specified \a attribute as a qreal value. |
219 | |
220 | Returns NaN if the value has not been set. |
221 | |
222 | The function hasAttribute() should be used to determine whether or |
223 | not a value has been set for an attribute. |
224 | |
225 | \sa hasAttribute(), setAttribute() |
226 | */ |
227 | qreal QGeoPositionInfo::attribute(Attribute attribute) const |
228 | { |
229 | if (d->doubleAttribs.contains(akey: attribute)) |
230 | return d->doubleAttribs[attribute]; |
231 | return qQNaN(); |
232 | } |
233 | |
234 | /*! |
235 | Removes the specified \a attribute and its value. |
236 | */ |
237 | void QGeoPositionInfo::removeAttribute(Attribute attribute) |
238 | { |
239 | d->doubleAttribs.remove(akey: attribute); |
240 | } |
241 | |
242 | /*! |
243 | Returns true if the specified \a attribute is present for this |
244 | QGeoPositionInfo object. |
245 | */ |
246 | bool QGeoPositionInfo::hasAttribute(Attribute attribute) const |
247 | { |
248 | return d->doubleAttribs.contains(akey: attribute); |
249 | } |
250 | |
251 | #ifndef QT_NO_DEBUG_STREAM |
252 | QDebug operator<<(QDebug dbg, const QGeoPositionInfo &info) |
253 | { |
254 | QDebugStateSaver saver(dbg); |
255 | dbg.nospace() << "QGeoPositionInfo(" << info.d->timestamp; |
256 | dbg.nospace() << ", " ; // timestamp force dbg.space() -> reverting here |
257 | dbg << info.d->coord; |
258 | |
259 | QList<QGeoPositionInfo::Attribute> attribs = info.d->doubleAttribs.keys(); |
260 | std::stable_sort(first: attribs.begin(), last: attribs.end()); // Output a sorted list from an unsorted hash. |
261 | for (int i = 0; i < attribs.count(); ++i) { |
262 | dbg << ", " ; |
263 | switch (attribs[i]) { |
264 | case QGeoPositionInfo::Direction: |
265 | dbg << "Direction=" ; |
266 | break; |
267 | case QGeoPositionInfo::GroundSpeed: |
268 | dbg << "GroundSpeed=" ; |
269 | break; |
270 | case QGeoPositionInfo::VerticalSpeed: |
271 | dbg << "VerticalSpeed=" ; |
272 | break; |
273 | case QGeoPositionInfo::MagneticVariation: |
274 | dbg << "MagneticVariation=" ; |
275 | break; |
276 | case QGeoPositionInfo::HorizontalAccuracy: |
277 | dbg << "HorizontalAccuracy=" ; |
278 | break; |
279 | case QGeoPositionInfo::VerticalAccuracy: |
280 | dbg << "VerticalAccuracy=" ; |
281 | break; |
282 | } |
283 | dbg << info.d->doubleAttribs[attribs[i]]; |
284 | } |
285 | dbg << ')'; |
286 | return dbg; |
287 | } |
288 | #endif |
289 | |
290 | |
291 | #ifndef QT_NO_DATASTREAM |
292 | /*! |
293 | \relates QGeoPositionInfo |
294 | |
295 | Writes the given \a attr enumeration to the specified \a stream. |
296 | |
297 | \sa {Serializing Qt Data Types} |
298 | */ |
299 | QDataStream &operator<<(QDataStream &stream, QGeoPositionInfo::Attribute attr) |
300 | { |
301 | return stream << int(attr); |
302 | } |
303 | |
304 | /*! |
305 | \relates QGeoPositionInfo |
306 | |
307 | Reads an attribute enumeration from the specified \a stream info the given \a attr. |
308 | |
309 | \sa {Serializing Qt Data Types} |
310 | */ |
311 | QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo::Attribute &attr) |
312 | { |
313 | int a; |
314 | stream >> a; |
315 | attr = static_cast<QGeoPositionInfo::Attribute>(a); |
316 | return stream; |
317 | } |
318 | |
319 | /*! |
320 | \fn QDataStream &operator<<(QDataStream &stream, const QGeoPositionInfo &info) |
321 | \relates QGeoPositionInfo |
322 | |
323 | Writes the given \a info to the specified \a stream. |
324 | |
325 | \sa {Serializing Qt Data Types} |
326 | */ |
327 | |
328 | QDataStream &operator<<(QDataStream &stream, const QGeoPositionInfo &info) |
329 | { |
330 | stream << info.d->timestamp; |
331 | stream << info.d->coord; |
332 | stream << info.d->doubleAttribs; |
333 | return stream; |
334 | } |
335 | |
336 | /*! |
337 | \fn QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo &info) |
338 | \relates QGeoPositionInfo |
339 | |
340 | Reads a coordinate from the specified \a stream into the given |
341 | \a info. |
342 | |
343 | \sa {Serializing Qt Data Types} |
344 | */ |
345 | |
346 | QDataStream &operator>>(QDataStream &stream, QGeoPositionInfo &info) |
347 | { |
348 | stream >> info.d->timestamp; |
349 | stream >> info.d->coord; |
350 | stream >> info.d->doubleAttribs; |
351 | return stream; |
352 | } |
353 | #endif |
354 | |
355 | QGeoPositionInfoPrivate::~QGeoPositionInfoPrivate() |
356 | { |
357 | |
358 | } |
359 | |
360 | QGeoPositionInfoPrivate *QGeoPositionInfoPrivate::clone() const |
361 | { |
362 | return new QGeoPositionInfoPrivate(*this); |
363 | } |
364 | |
365 | bool QGeoPositionInfoPrivate::operator==(const QGeoPositionInfoPrivate &other) const |
366 | { |
367 | return timestamp == other.timestamp |
368 | && coord == other.coord |
369 | && doubleAttribs == other.doubleAttribs; |
370 | } |
371 | |
372 | QGeoPositionInfoPrivate *QGeoPositionInfoPrivate::get(const QGeoPositionInfo &info) |
373 | { |
374 | return info.d; |
375 | } |
376 | |
377 | QT_END_NAMESPACE |
378 | |
379 | |