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