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 */
QGeoPositionInfo()82 QGeoPositionInfo::QGeoPositionInfo()
83         : d(new QGeoPositionInfoPrivate)
84 {
85 }
86 
87 /*!
88     Creates a QGeoPositionInfo for the given \a coordinate and \a timestamp.
89 */
QGeoPositionInfo(const QGeoCoordinate & coordinate,const QDateTime & timestamp)90 QGeoPositionInfo::QGeoPositionInfo(const QGeoCoordinate &coordinate, const QDateTime &timestamp)
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 */
QGeoPositionInfo(const QGeoPositionInfo & other)100 QGeoPositionInfo::QGeoPositionInfo(const QGeoPositionInfo &other)
101         : d(other.d->clone())
102 {
103 }
104 
QGeoPositionInfo(QGeoPositionInfoPrivate & dd)105 QGeoPositionInfo::QGeoPositionInfo(QGeoPositionInfoPrivate &dd) : d(&dd)
106 {
107 }
108 
109 /*!
110     Destroys a QGeoPositionInfo object.
111 */
~QGeoPositionInfo()112 QGeoPositionInfo::~QGeoPositionInfo()
113 {
114     delete d;
115 }
116 
117 /*!
118     Assigns the values from \a other to this QGeoPositionInfo.
119 */
operator =(const QGeoPositionInfo & other)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 */
operator ==(const QGeoPositionInfo & other) const139 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 */
isValid() const156 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 */
setTimestamp(const QDateTime & timestamp)168 void QGeoPositionInfo::setTimestamp(const QDateTime &timestamp)
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 */
timestamp() const180 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 */
setCoordinate(const QGeoCoordinate & coordinate)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 */
coordinate() const202 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 */
setAttribute(Attribute attribute,qreal value)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 */
attribute(Attribute attribute) const227 qreal QGeoPositionInfo::attribute(Attribute attribute) const
228 {
229     if (d->doubleAttribs.contains(attribute))
230         return d->doubleAttribs[attribute];
231     return qQNaN();
232 }
233 
234 /*!
235     Removes the specified \a attribute and its value.
236 */
removeAttribute(Attribute attribute)237 void QGeoPositionInfo::removeAttribute(Attribute attribute)
238 {
239     d->doubleAttribs.remove(attribute);
240 }
241 
242 /*!
243     Returns true if the specified \a attribute is present for this
244     QGeoPositionInfo object.
245 */
hasAttribute(Attribute attribute) const246 bool QGeoPositionInfo::hasAttribute(Attribute attribute) const
247 {
248     return d->doubleAttribs.contains(attribute);
249 }
250 
251 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QGeoPositionInfo & info)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(attribs.begin(), 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 */
operator <<(QDataStream & stream,QGeoPositionInfo::Attribute attr)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 */
operator >>(QDataStream & stream,QGeoPositionInfo::Attribute & attr)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 
operator <<(QDataStream & stream,const QGeoPositionInfo & info)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 
operator >>(QDataStream & stream,QGeoPositionInfo & info)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 
~QGeoPositionInfoPrivate()355 QGeoPositionInfoPrivate::~QGeoPositionInfoPrivate()
356 {
357 
358 }
359 
clone() const360 QGeoPositionInfoPrivate *QGeoPositionInfoPrivate::clone() const
361 {
362     return new QGeoPositionInfoPrivate(*this);
363 }
364 
operator ==(const QGeoPositionInfoPrivate & other) const365 bool QGeoPositionInfoPrivate::operator==(const QGeoPositionInfoPrivate &other) const
366 {
367     return timestamp == other.timestamp
368            && coord == other.coord
369             && doubleAttribs == other.doubleAttribs;
370 }
371 
get(const QGeoPositionInfo & info)372 QGeoPositionInfoPrivate *QGeoPositionInfoPrivate::get(const QGeoPositionInfo &info)
373 {
374     return info.d;
375 }
376 
377 QT_END_NAMESPACE
378 
379