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 
40 #include "locationsingleton.h"
41 #include <QtPositioning/private/qwebmercator_p.h>
42 #include <QtPositioning/private/qdoublevector2d_p.h>
43 #include <QDebug>
44 
parseCoordinate(const QJSValue & value,bool * ok)45 static QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok)
46 {
47     QGeoCoordinate c;
48 
49     if (value.isObject()) {
50         if (value.hasProperty(QStringLiteral("latitude")))
51             c.setLatitude(value.property(QStringLiteral("latitude")).toNumber());
52         if (value.hasProperty(QStringLiteral("longitude")))
53             c.setLongitude(value.property(QStringLiteral("longitude")).toNumber());
54         if (value.hasProperty(QStringLiteral("altitude")))
55             c.setAltitude(value.property(QStringLiteral("altitude")).toNumber());
56 
57         if (ok)
58             *ok = true;
59     }
60 
61     return c;
62 }
63 
64 
65 /*!
66     \qmltype QtPositioning
67     \instantiates LocationSingleton
68     \inqmlmodule QtPositioning
69     \since 5.2
70 
71     \brief The QtPositioning global object provides useful functions for working with location-based
72            types in QML.
73 
74     \qml
75     import QtPositioning 5.2
76 
77     Item {
78         property variant coordinate: QtPositioning.coordinate(-27.5, 153.1)
79     }
80     \endqml
81 */
82 
LocationSingleton(QObject * parent)83 LocationSingleton::LocationSingleton(QObject *parent)
84 :   QObject(parent)
85 {
86 }
87 
88 /*!
89     \qmlmethod coordinate ::QtPositioning::coordinate()
90 
91     Constructs an invalid coordinate.
92 
93 */
coordinate() const94 QGeoCoordinate LocationSingleton::coordinate() const
95 {
96     return QGeoCoordinate();
97 }
98 
99 /*!
100     \qmlmethod coordinate QtPositioning::coordinate(real latitude, real longitude, real altitude) const
101 
102     Constructs a coordinate with the specified \a latitude, \a longitude and optional \a altitude.
103     Both \a latitude and \a longitude must be valid, otherwise an invalid coordinate is returned.
104 
105     \sa {coordinate}
106 */
coordinate(double latitude,double longitude,double altitude) const107 QGeoCoordinate LocationSingleton::coordinate(double latitude, double longitude, double altitude) const
108 {
109     return QGeoCoordinate(latitude, longitude, altitude);
110 }
111 
112 /*!
113     \qmlmethod geoshape QtPositioning::shape() const
114 
115     Constructs an invalid geoshape.
116 
117     \sa {geoshape}
118 */
shape() const119 QGeoShape LocationSingleton::shape() const
120 {
121     return QGeoShape();
122 }
123 
124 /*!
125     \qmlmethod georectangle QtPositioning::rectangle() const
126 
127     Constructs an invalid georectangle.
128 
129     \sa {georectangle}
130 */
rectangle() const131 QGeoRectangle LocationSingleton::rectangle() const
132 {
133     return QGeoRectangle();
134 }
135 
136 /*!
137     \qmlmethod georectangle QtPositioning::rectangle(coordinate center, real width, real height) const
138 
139     Constructs a georectangle centered at \a center with a width of \a width degrees and a hight of
140     \a height degrees.
141 
142     \sa {georectangle}
143 */
rectangle(const QGeoCoordinate & center,double width,double height) const144 QGeoRectangle LocationSingleton::rectangle(const QGeoCoordinate &center,
145                                            double width, double height) const
146 {
147     return QGeoRectangle(center, width, height);
148 }
149 
150 /*!
151     \qmlmethod georectangle QtPositioning::rectangle(coordinate topLeft, coordinate bottomRight) const
152 
153     Constructs a georectangle with its top left corner positioned at \a topLeft and its bottom
154     right corner positioned at \a {bottomRight}.
155 
156     \sa {georectangle}
157 */
rectangle(const QGeoCoordinate & topLeft,const QGeoCoordinate & bottomRight) const158 QGeoRectangle LocationSingleton::rectangle(const QGeoCoordinate &topLeft,
159                                            const QGeoCoordinate &bottomRight) const
160 {
161     return QGeoRectangle(topLeft, bottomRight);
162 }
163 
164 /*!
165     \qmlmethod georectangle QtLocation5::QtLocation::rectangle(list<coordinate> coordinates) const
166 
167     Constructs a georectangle from the list of coordinates, the returned list is the smallest possible
168     containing all the coordinates.
169 
170     \sa {georectangle}
171 */
rectangle(const QVariantList & coordinates) const172 QGeoRectangle LocationSingleton::rectangle(const QVariantList &coordinates) const
173 {
174     QList<QGeoCoordinate> internalCoordinates;
175     for (int i = 0; i < coordinates.size(); i++) {
176         if (coordinates.at(i).canConvert<QGeoCoordinate>())
177             internalCoordinates << coordinates.at(i).value<QGeoCoordinate>();
178     }
179     return QGeoRectangle(internalCoordinates);
180 }
181 
182 /*!
183     \qmlmethod geocircle QtPositioning::circle() const
184 
185     Constructs an invalid geocircle.
186 
187     \sa {geocircle}
188 */
circle() const189 QGeoCircle LocationSingleton::circle() const
190 {
191     return QGeoCircle();
192 }
193 
194 /*!
195     \qmlmethod geocircle QtPositioning::circle(coordinate center, real radius) const
196 
197     Constructs a geocircle centered at \a center with a radius of \a radius meters.
198 */
circle(const QGeoCoordinate & center,qreal radius) const199 QGeoCircle LocationSingleton::circle(const QGeoCoordinate &center, qreal radius) const
200 {
201     return QGeoCircle(center, radius);
202 }
203 
204 /*!
205     \qmlmethod geopath QtPositioning::path() const
206 
207     Constructs an empty geopath.
208 
209     \sa {geopath}
210     \since 5.9
211 */
path() const212 QGeoPath LocationSingleton::path() const
213 {
214     return QGeoPath();
215 }
216 
217 /*!
218     \qmlmethod geopath QtPositioning::path(list<coordinate> coordinates, real width) const
219 
220     Constructs a geopath from coordinates and width.
221 
222     \sa {geopath}
223     \since 5.9
224 */
path(const QJSValue & value,qreal width) const225 QGeoPath LocationSingleton::path(const QJSValue &value, qreal width) const
226 {
227     QList<QGeoCoordinate> pathList;
228 
229     if (value.isArray()) {
230         quint32 length = value.property(QStringLiteral("length")).toUInt();
231         for (quint32 i = 0; i < length; ++i) {
232             bool ok;
233             QGeoCoordinate c = parseCoordinate(value.property(i), &ok);
234 
235             if (!ok || !c.isValid()) {
236                 pathList.clear(); // aborting
237                 break;
238             }
239 
240             pathList.append(c);
241         }
242     }
243 
244     return QGeoPath(pathList, width);
245 }
246 
247 /*!
248     \qmlmethod geopolygon QtPositioning::polygon() const
249 
250     Constructs an empty polygon.
251 
252     \sa {geopolygon}
253     \since 5.10
254 */
polygon() const255 QGeoPolygon LocationSingleton::polygon() const
256 {
257     return QGeoPolygon();
258 }
259 
260 /*!
261     \qmlmethod geopolygon QtPositioning::polygon(list<coordinate> coordinates) const
262 
263     Constructs a polygon from coordinates.
264 
265     \sa {geopolygon}
266     \since 5.10
267 */
polygon(const QVariantList & coordinates) const268 QGeoPolygon LocationSingleton::polygon(const QVariantList &coordinates) const
269 {
270     QList<QGeoCoordinate> internalCoordinates;
271     for (int i = 0; i < coordinates.size(); i++) {
272         if (coordinates.at(i).canConvert<QGeoCoordinate>())
273             internalCoordinates << coordinates.at(i).value<QGeoCoordinate>();
274     }
275     return QGeoPolygon(internalCoordinates);
276 }
277 
278 /*!
279     \qmlmethod geopolygon QtPositioning::polygon(list<coordinate> perimeter, list<list<coordinate>> holes) const
280 
281     Constructs a polygon from coordinates for perimeter and inner holes.
282 
283     \sa {geopolygon}
284     \since 5.12
285 */
polygon(const QVariantList & perimeter,const QVariantList & holes) const286 QGeoPolygon LocationSingleton::polygon(const QVariantList &perimeter, const QVariantList &holes) const
287 {
288     QList<QGeoCoordinate> internalCoordinates;
289     for (int i = 0; i < perimeter.size(); i++) {
290         if (perimeter.at(i).canConvert<QGeoCoordinate>())
291             internalCoordinates << perimeter.at(i).value<QGeoCoordinate>();
292     }
293     QGeoPolygon poly(internalCoordinates);
294 
295     for (int i = 0; i < holes.size(); i++) {
296         if (holes.at(i).type() == QVariant::List) {
297             QList<QGeoCoordinate> hole;
298             const QVariantList &holeData = holes.at(i).toList();
299             for (int j = 0; j < holeData.size(); j++) {
300                 if (holeData.at(j).canConvert<QGeoCoordinate>())
301                     hole << holeData.at(j).value<QGeoCoordinate>();
302             }
303             if (hole.size())
304                 poly.addHole(hole);
305         }
306     }
307 
308     return poly;
309 }
310 
311 /*!
312     \qmlmethod geocircle QtPositioning::shapeToCircle(geoshape shape) const
313 
314     Converts \a shape to a geocircle.
315 
316     \sa {geocircle}
317     \since 5.5
318 */
shapeToCircle(const QGeoShape & shape) const319 QGeoCircle LocationSingleton::shapeToCircle(const QGeoShape &shape) const
320 {
321     return QGeoCircle(shape);
322 }
323 
324 /*!
325     \qmlmethod georectangle QtPositioning::shapeToRectangle(geoshape shape) const
326 
327     Converts \a shape to a georectangle.
328 
329     \sa {georectangle}
330     \since 5.5
331 */
shapeToRectangle(const QGeoShape & shape) const332 QGeoRectangle LocationSingleton::shapeToRectangle(const QGeoShape &shape) const
333 {
334     return QGeoRectangle(shape);
335 }
336 
337 /*!
338     \qmlmethod geopath QtPositioning::shapeToPath(geoshape shape) const
339 
340     Converts \a shape to a geopath.
341 
342     \sa {geopath}
343     \since 5.9
344 */
shapeToPath(const QGeoShape & shape) const345 QGeoPath LocationSingleton::shapeToPath(const QGeoShape &shape) const
346 {
347     return QGeoPath(shape);
348 }
349 
350 /*!
351     \qmlmethod geopolygon QtPositioning::shapeToPolygon(geoshape shape) const
352 
353     Converts \a shape to a polygon.
354 
355     \sa {geopolygon}
356     \since 5.10
357 */
shapeToPolygon(const QGeoShape & shape) const358 QGeoPolygon LocationSingleton::shapeToPolygon(const QGeoShape &shape) const
359 {
360     return QGeoPolygon(shape);
361 }
362 
363 /*!
364     \qmlmethod coordinate QtPositioning::mercatorToCoord(point mercator) const
365 
366     Converts a \a mercator coordinate into a latitude-longitude coordinate.
367 
368     \sa {coordToMercator}
369     \since 5.12
370 */
mercatorToCoord(const QPointF & mercator) const371 QGeoCoordinate LocationSingleton::mercatorToCoord(const QPointF &mercator) const
372 {
373     return QWebMercator::mercatorToCoord(QDoubleVector2D(mercator.x(), mercator.y()));
374 }
375 
376 /*!
377     \qmlmethod point QtPositioning::coordToMercator(coordinate coord) const
378 
379     Converts a coordinate \a coord into a mercator coordinate and returns it.
380     \sa {mercatorToCoord}
381     \since 5.12
382 */
coordToMercator(const QGeoCoordinate & coord) const383 QPointF LocationSingleton::coordToMercator(const QGeoCoordinate &coord) const
384 {
385     return QWebMercator::coordToMercator(coord).toPointF();
386 }
387