Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgeopositioninfo.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
5#include "private/qgeopositioninfo_p.h"
6#include <QHash>
7#include <QDebug>
8#include <QDataStream>
9#include <QtCore/QtNumeric>
10
11#include <algorithm>
12
13QT_BEGIN_NAMESPACE
14
15QT_IMPL_METATYPE_EXTERN(QGeoPositionInfo)
16
17/*!
18 \class QGeoPositionInfo
19 \inmodule QtPositioning
20 \ingroup QtPositioning-positioning
21 \ingroup shared
22 \since 5.2
23
24 \brief The QGeoPositionInfo class contains information gathered on a global position, direction and velocity at a particular point in time.
25
26 A QGeoPositionInfo contains, at a minimum, a geographical coordinate and
27 a timestamp. It may also have heading and speed measurements as well as
28 estimates of the accuracy of the provided data.
29
30 \sa QGeoPositionInfoSource
31*/
32
33/*!
34 \enum QGeoPositionInfo::Attribute
35 Defines the attributes for positional information.
36
37 \value Direction The bearing measured in degrees clockwise from true north to the direction of travel.
38 \value GroundSpeed The ground speed, in meters/sec.
39 \value VerticalSpeed The vertical speed, in meters/sec.
40 \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.
41 \value HorizontalAccuracy The accuracy of the provided latitude-longitude value, in meters.
42 \value VerticalAccuracy The accuracy of the provided altitude value, in meters.
43 \value DirectionAccuracy The accuracy of the provided bearing, in degrees.
44 This attribute is available only on Android (API level 26 or above) and
45 macOS/iOS. See corresponding \l {Android getBearingAccuracyDegrees}
46 {Android} and \l {iOS courseAccuracy}{Apple} documentation for more details.
47
48 NMEA protocol also suggests another type of accuracy - PositionAccuracy,
49 which is a 3D accuracy value. Qt does not provide a separate attribute for
50 it. If you need this value, you can calculate it based on the following
51 formula:
52
53 \c {PositionAccuracy} \sup 2 \c {= HorizontalAccuracy} \sup 2 \c { +
54 VerticalAccuracy} \sup 2
55*/
56
57/*!
58 Creates an invalid QGeoPositionInfo object.
59
60 \sa isValid()
61*/
62QGeoPositionInfo::QGeoPositionInfo()
63 : d(new QGeoPositionInfoPrivate)
64{
65}
66
67/*!
68 Creates a QGeoPositionInfo for the given \a coordinate and \a timestamp.
69*/
70QGeoPositionInfo::QGeoPositionInfo(const QGeoCoordinate &coordinate, const QDateTime &timestamp)
71 : d(new QGeoPositionInfoPrivate)
72{
73 d->timestamp = timestamp;
74 d->coord = coordinate;
75}
76
77/*!
78 Creates a QGeoPositionInfo with the values of \a other.
79*/
80QGeoPositionInfo::QGeoPositionInfo(const QGeoPositionInfo &other)
81 : d(other.d)
82{
83}
84
85/*!
86 \fn QGeoPositionInfo::QGeoPositionInfo(QGeoPositionInfo &&other) noexcept
87 \since 6.2
88
89 Creates a QGeoPositionInfo object by moving from \a other.
90
91 Note that a moved-from QGeoPositionInfo can only be destroyed or
92 assigned to. The effect of calling other functions than the destructor
93 or one of the assignment operators is undefined.
94*/
95
96QGeoPositionInfo::QGeoPositionInfo(QGeoPositionInfoPrivate &dd) : d(&dd)
97{
98}
99
100/*!
101 Destroys a QGeoPositionInfo object.
102*/
103QGeoPositionInfo::~QGeoPositionInfo()
104{
105}
106
107QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGeoPositionInfoPrivate)
108
109/*!
110 Assigns the values from \a other to this QGeoPositionInfo.
111*/
112QGeoPositionInfo &QGeoPositionInfo::operator=(const QGeoPositionInfo & other)
114 if (this == &other)
115 return *this;
116
117 d = other.d;
118 return *this;
119}
120
121/*!
122 \fn QGeoPositionInfo &QGeoPositionInfo::operator=(QGeoPositionInfo &&other) noexcept
123 \since 6.2
124
125 Move-assigns the values from \a other to this object.
126
127 Note that a moved-from QGeoPositionInfo can only be destroyed or
128 assigned to. The effect of calling other functions than the destructor
129 or one of the assignment operators is undefined.
130*/
131
132/*!
133 \fn bool QGeoPositionInfo::operator==(const QGeoPositionInfo &lhs, const QGeoPositionInfo &rhs)
134
135 Returns \c true if all of the \a lhs object's values are the same as those
136 of \a rhs. Otherwise returns \c false.
137*/
138
139/*!
140 \fn bool QGeoPositionInfo::operator!=(const QGeoPositionInfo &lhs, const QGeoPositionInfo &rhs)
141
142 Returns \c true if any of the \a lhs object's values are not the same as
143 those of \a rhs. Otherwise returns \c false.
144*/
145
146/*!
147 \fn void QGeoPositionInfo::swap(QGeoPositionInfo &other)
148 \since 6.2
149 \memberswap{position information}
150*/
151
152/*!
153 Returns true if the timestamp() and coordinate() values are both valid.
154
155 \sa QGeoCoordinate::isValid(), QDateTime::isValid()
156*/
157bool QGeoPositionInfo::isValid() const
158{
159 return d->timestamp.isValid() && d->coord.isValid();
160}
161
162/*!
163 Sets the date and time at which this position was reported to \a timestamp.
164
165 The \a timestamp must be in UTC time.
166
167 \sa timestamp()
168*/
169void QGeoPositionInfo::setTimestamp(const QDateTime &timestamp)
170{
171 d.detach();
172 d->timestamp = timestamp;
173}
174
175/*!
176 Returns the date and time at which this position was reported, in UTC time.
177
178 Returns an invalid QDateTime if no date/time value has been set.
179
180 \sa setTimestamp()
181*/
182QDateTime QGeoPositionInfo::timestamp() const
183{
184 return d->timestamp;
185}
186
187/*!
188 Sets the coordinate for this position to \a coordinate.
189
190 \sa coordinate()
191*/
192void QGeoPositionInfo::setCoordinate(const QGeoCoordinate &coordinate)
193{
194 d.detach();
195 d->coord = coordinate;
196}
197
198/*!
199 Returns the coordinate for this position.
200
201 Returns an invalid coordinate if no coordinate has been set.
202
203 \sa setCoordinate()
204*/
205QGeoCoordinate QGeoPositionInfo::coordinate() const
206{
207 return d->coord;
208}
209
210/*!
211 Sets the value for \a attribute to \a value.
212
213 \sa attribute()
214*/
215void QGeoPositionInfo::setAttribute(Attribute attribute, qreal value)
216{
217 d.detach();
218 d->doubleAttribs[attribute] = value;
219}
220
221/*!
222 Returns the value of the specified \a attribute as a qreal value.
223
224 Returns NaN if the value has not been set.
225
226 The function hasAttribute() should be used to determine whether or
227 not a value has been set for an attribute.
228
229 \sa hasAttribute(), setAttribute()
230*/
231qreal QGeoPositionInfo::attribute(Attribute attribute) const
232{
233 return d->doubleAttribs.value(attribute, qQNaN());
234}
235
236/*!
237 Removes the specified \a attribute and its value.
238*/
239void QGeoPositionInfo::removeAttribute(Attribute attribute)
240{
241 const auto it = d->doubleAttribs.constFind(attribute);
242 if (it != d->doubleAttribs.cend()) {
243 d.detach();
244 d->doubleAttribs.erase(it);
245 }
246}
247
248/*!
249 Returns true if the specified \a attribute is present for this
250 QGeoPositionInfo object.
251*/
252bool QGeoPositionInfo::hasAttribute(Attribute attribute) const
253{
254 return d->doubleAttribs.contains(attribute);
255}
256
257/*!
258 \internal
259*/
260void QGeoPositionInfo::detach()
261{
262 if (d)
263 d.detach();
264 else
265 d = new QGeoPositionInfoPrivate;
266}
267
268bool QGeoPositionInfo::equals(const QGeoPositionInfo &lhs, const QGeoPositionInfo &rhs)
269{
270 return *lhs.d == *rhs.d;
271}
272
273#ifndef QT_NO_DEBUG_STREAM
274QDebug QGeoPositionInfo::debugStreaming(QDebug dbg, const QGeoPositionInfo &info)
275{
276 QDebugStateSaver saver(dbg);
277 dbg.nospace() << "QGeoPositionInfo(" << info.d->timestamp;
278 dbg.nospace() << ", "; // timestamp force dbg.space() -> reverting here
279 dbg << info.d->coord;
280
281 QList<QGeoPositionInfo::Attribute> attribs = info.d->doubleAttribs.keys();
282 std::stable_sort(attribs.begin(), attribs.end()); // Output a sorted list from an unsorted hash.
283 for (int i = 0; i < attribs.size(); ++i) {
284 dbg << ", ";
285 switch (attribs[i]) {
286 case QGeoPositionInfo::Direction:
287 dbg << "Direction=";
288 break;
289 case QGeoPositionInfo::GroundSpeed:
290 dbg << "GroundSpeed=";
291 break;
292 case QGeoPositionInfo::VerticalSpeed:
293 dbg << "VerticalSpeed=";
294 break;
295 case QGeoPositionInfo::MagneticVariation:
296 dbg << "MagneticVariation=";
297 break;
298 case QGeoPositionInfo::HorizontalAccuracy:
299 dbg << "HorizontalAccuracy=";
300 break;
301 case QGeoPositionInfo::VerticalAccuracy:
302 dbg << "VerticalAccuracy=";
303 break;
304 case QGeoPositionInfo::DirectionAccuracy:
305 dbg << "DirectionAccuracy=";
306 break;
307 }
308 dbg << info.d->doubleAttribs[attribs[i]];
309 }
310 dbg << ')';
311 return dbg;
312}
313#endif
314
315
316#ifndef QT_NO_DATASTREAM
317/*!
318 \fn QDataStream &QGeoPositionInfo::operator<<(QDataStream &stream, QGeoPositionInfo::Attribute attr)
319
320 Writes the given \a attr enumeration to the specified \a stream.
321
322 \sa {Serializing Qt Data Types}
323*/
324QDataStream &QGeoPositionInfo::dataStreamOut(QDataStream &stream, QGeoPositionInfo::Attribute attr)
325{
326 return stream << qint32(attr);
327}
328
329/*!
330 \fn QDataStream &QGeoPositionInfo::operator>>(QDataStream &stream, QGeoPositionInfo::Attribute &attr)
331
332 Reads an attribute enumeration from the specified \a stream info the given \a attr.
333
334 \sa {Serializing Qt Data Types}
335*/
336QDataStream &QGeoPositionInfo::dataStreamIn(QDataStream &stream, QGeoPositionInfo::Attribute &attr)
337{
338 qint32 a;
339 stream >> a;
340 attr = static_cast<QGeoPositionInfo::Attribute>(a);
341 return stream;
342}
343
344/*!
345 \fn QDataStream &QGeoPositionInfo::operator<<(QDataStream &stream, const QGeoPositionInfo &info)
346
347 Writes the given \a info to the specified \a stream.
348
349 \sa {Serializing Qt Data Types}
350*/
351
352QDataStream &QGeoPositionInfo::dataStreamOut(QDataStream &stream, const QGeoPositionInfo &info)
353{
354 stream << info.d->timestamp;
355 stream << info.d->coord;
356 stream << info.d->doubleAttribs;
357 return stream;
358}
359
360/*!
361 \fn QDataStream &QGeoPositionInfo::operator>>(QDataStream &stream, QGeoPositionInfo &info)
362
363 Reads a coordinate from the specified \a stream into the given
364 \a info.
365
366 \sa {Serializing Qt Data Types}
367*/
368
369QDataStream &QGeoPositionInfo::dataStreamIn(QDataStream &stream, QGeoPositionInfo &info)
370{
371 stream >> info.d->timestamp;
372 stream >> info.d->coord;
373 stream >> info.d->doubleAttribs;
374 return stream;
375}
376#endif
377
378QGeoPositionInfoPrivate::QGeoPositionInfoPrivate() : QSharedData()
379{
380}
381
382QGeoPositionInfoPrivate::QGeoPositionInfoPrivate(const QGeoPositionInfoPrivate &other)
383 : QSharedData(other),
384 timestamp(other.timestamp),
385 coord(other.coord),
386 doubleAttribs(other.doubleAttribs)
387{
388}
389
390QGeoPositionInfoPrivate::~QGeoPositionInfoPrivate()
391{
392
393}
394
395bool QGeoPositionInfoPrivate::operator==(const QGeoPositionInfoPrivate &other) const
396{
397 return timestamp == other.timestamp
398 && coord == other.coord
399 && doubleAttribs == other.doubleAttribs;
400}
401
402QGeoPositionInfoPrivate *QGeoPositionInfoPrivate::get(const QGeoPositionInfo &info)
403{
404 return info.d.data();
405}
406
407size_t qHash(const QGeoPositionInfo &key, size_t seed) noexcept
408{
409 return qHashMulti(seed, key.d->coord);
410}
411
412namespace QTest
413{
414
415char *toString(const QGeoPositionInfo &info)
416{
417 QString result;
418 QDebug dbg(&result);
419 dbg << info;
420
421 return qstrdup(qPrintable(result));
422}
423
424} // namespace QTest
425
426QT_END_NAMESPACE