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 
41 #include <QtPositioningQuick/private/qdeclarativegeoaddress_p.h>
42 #include <QtPositioningQuick/private/qdeclarativegeolocation_p.h>
43 #include <QtPositioning/private/qwebmercator_p.h>
44 #include <QtPositioningQuick/private/qdeclarativeposition_p.h>
45 #include <QtPositioningQuick/private/qdeclarativepositionsource_p.h>
46 #include <QtPositioningQuick/private/qdeclarativepluginparameter_p.h>
47 
48 #include <QtPositioningQuick/private/qquickgeocoordinateanimation_p.h>
49 #include "locationsingleton.h"
50 
51 #include <QtCore/QVariantAnimation>
52 
53 #include <QtQml/qqmlextensionplugin.h>
54 #include <QtQml/private/qqmlvaluetype_p.h>
55 
56 #include <QtPositioning/QGeoRectangle>
57 #include <QtPositioning/QGeoCircle>
58 #include <QtPositioning/QGeoPath>
59 #include <QtPositioning/QGeoLocation>
60 #include <QtPositioning/QGeoPositionInfo>
61 #include <QtPositioning/private/qgeocoordinateobject_p.h>
62 
63 #include <QtCore/QDebug>
64 
65 QT_BEGIN_NAMESPACE
66 
67 /*!
68     \qmlbasictype coordinate
69     \inqmlmodule QtPositioning
70     \ingroup qml-QtPositioning5-basictypes
71     \since 5.2
72 
73     \brief The coordinate type represents and stores a geographic position.
74 
75     This type is a QML representation of \l QGeoCoordinate and represents a geographic
76     position in the form of \l {latitude}, \l longitude and \l altitude attributes.
77     The \l latitude attribute specifies the number of
78     decimal degrees above and below the equator.  A positive latitude indicates the Northern
79     Hemisphere and a negative latitude indicates the Southern Hemisphere.  The \l longitude
80     attribute specifies the number of decimal degrees east and west.  A positive longitude
81     indicates the Eastern Hemisphere and a negative longitude indicates the Western Hemisphere.
82     The \l altitude attribute specifies the number of meters above sea level.  Together, these
83     attributes specify a 3-dimensional position anywhere on or near the Earth's surface.
84 
85     The \l isValid attribute can be used to test if a coordinate is valid.  A coordinate is
86     considered valid if it has a valid latitude and longitude.  A valid altitude is not required.
87     The latitude must be between -90 and 90 inclusive and the longitude must be between -180 and
88     180 inclusive.
89 
90     The \c coordinate type is used by many other types in the Qt Location module, for specifying
91     the position of an object on a Map, the current position of a device and many other tasks.
92     They also feature a number of important utility methods that make otherwise complex
93     calculations simple to use, such as \l {atDistanceAndAzimuth}().
94 
95     \section1 Accuracy
96 
97     The latitude, longitude and altitude attributes stored in the coordinate type are represented
98     as doubles, giving them approximately 16 decimal digits of precision -- enough to specify
99     micrometers.  The calculations performed in coordinate's methods such as \l {azimuthTo}() and
100     \l {distanceTo}() also use doubles for all intermediate values, but the inherent inaccuracies in
101     their spherical Earth model dominate the amount of error in their output.
102 
103     \section1 Example Usage
104 
105     Use properties of type \l variant to store a \c {coordinate}.  To create a \c coordinate use
106     one of the methods described below.  In all cases, specifying the \l altitude attribute is
107     optional.
108 
109     To create a \c coordinate value, use the \l{QtPositioning::coordinate}{QtPositioning.coordinate()}
110     function:
111 
112     \qml
113     import QtPositioning 5.2
114 
115     Location { coordinate: QtPositioning.coordinate(-27.5, 153.1) }
116     \endqml
117 
118     or as separate \l latitude, \l longitude and \l altitude components:
119 
120     \qml
121     Location {
122         coordinate {
123             latitude: -27.5
124             longitude: 153.1
125         }
126     }
127     \endqml
128 
129     When integrating with C++, note that any QGeoCoordinate value passed into QML from C++ is
130     automatically converted into a \c coordinate value, and vice-versa.
131 
132     \section1 Properties
133 
134     \section2 latitude
135 
136     \code
137     real latitude
138     \endcode
139 
140     This property holds the latitude value of the geographical position
141     (decimal degrees). A positive latitude indicates the Northern Hemisphere,
142     and a negative latitude indicates the Southern Hemisphere.
143     If the property has not been set, its default value is NaN.
144 
145     For more details see the \l {QGeoCoordinate::latitude} property
146 
147     \section2 longitude
148 
149     \code
150     real longitude
151     \endcode
152 
153     This property holds the longitude value of the geographical position
154     (decimal degrees). A positive longitude indicates the Eastern Hemisphere,
155     and a negative longitude indicates the Western Hemisphere
156     If the property has not been set, its default value is NaN.
157 
158     For more details see the \l {QGeoCoordinate::longitude} property
159 
160     \section2 altitude
161 
162     \code
163     real altitude
164     \endcode
165 
166     This property holds the altitude value (meters above sea level).
167     If the property has not been set, its default value is NaN.
168 
169     For more details see the \l {QGeoCoordinate::altitude} property
170 
171     \section2 isValid
172 
173     \code
174     bool isValid
175     \endcode
176 
177     This property holds the current validity of the coordinate. Coordinates
178     are considered valid if they have been set with a valid latitude and
179     longitude (altitude is not required).
180 
181     The latitude must be between -90 to 90 inclusive to be considered valid,
182     and the longitude must be between -180 to 180 inclusive to be considered
183     valid.
184 
185     This is a read-only property.
186 
187     \section1 Methods
188 
189     \section2 distanceTo()
190 
191     \code
192     real distanceTo(coordinate other)
193     \endcode
194 
195     Returns the distance (in meters) from this coordinate to the coordinate specified by \a other.
196     Altitude is not used in the calculation.
197 
198     This calculation returns the great-circle distance between the two coordinates, with an
199     assumption that the Earth is spherical for the purpose of this calculation.
200 
201     \section2 azimuthTo()
202 
203     \code
204     real azimuth(coordinate other)
205     \endcode
206 
207     Returns the azimuth (or bearing) in degrees from this coordinate to the coordinate specified by
208     \a other.  Altitude is not used in the calculation.
209 
210     There is an assumption that the Earth is spherical for the purpose of this calculation.
211 
212     \section2 atDistanceAndAzimuth()
213 
214     \code
215     coordinate atDistanceAndAzimuth(real distance, real azimuth)
216     \endcode
217 
218     Returns the coordinate that is reached by traveling \a distance metres from this coordinate at
219     \a azimuth degrees along a great-circle.
220 
221     There is an assumption that the Earth is spherical for the purpose of this calculation.
222 */
223 
224 /*!
225     \qmlbasictype geoshape
226     \inqmlmodule QtPositioning
227     \ingroup qml-QtPositioning5-basictypes
228     \since 5.2
229 
230     \brief A geoshape type represents an abstract geographic area.
231 
232     This type is a QML representation of \l QGeoShape which is an abstract geographic area.
233     It includes attributes and methods common to all geographic areas. To create objects
234     that represent a valid geographic area use \l {georectangle} or \l {geocircle}.
235 
236     The \l isValid attribute can be used to test if the geoshape represents a valid geographic
237     area.
238 
239     The \l isEmpty attribute can be used to test if the geoshape represents a region with a
240     geometrical area of 0.
241 
242     The \l {contains}() method can be used to test if a \l {coordinate} is
243     within the geoshape.
244 
245     \section1 Example Usage
246 
247     Use properties of type \l variant to store a \c {geoshape}.  To create a \c geoshape use one
248     of the methods described below.
249 
250     To create a \c geoshape value, specify it as a "shape()" string:
251 
252     \qml
253     import QtPositioning
254 
255     Item {
256         property variant region: "shape()"
257     }
258     \endqml
259 
260     or with the \l {QtPositioning::shape}{QtPositioning.shape()} function:
261 
262     \qml
263     import QtPositioning 5.2
264 
265     Item {
266         property variant region: QtPositioning.shape()
267     }
268     \endqml
269 
270     When integrating with C++, note that any QGeoShape value passed into QML from C++ is
271     automatically converted into a \c geoshape value, and vice-versa.
272 
273     \section1 Properties
274 
275     \section2 isEmpty
276 
277     \code
278     bool isEmpty
279     \endcode
280 
281     Returns whether this geoshape is empty. An empty geoshape is a region which has
282     a geometrical area of 0.
283 
284     \section2 isValid
285 
286     \code
287     bool isValid
288     \endcode
289 
290     Returns whether this geoshape is valid.
291 
292     A geoshape is considered to be invalid if some of the data that is required to
293     unambiguously describe the geoshape has not been set or has been set to an
294     unsuitable value.
295 
296     \section2 type
297 
298     \code
299     ShapeType type
300     \endcode
301 
302     Returns the current type of the shape.
303 
304     \list
305         \li \c GeoShape.UnknownType - The shape's type is not known.
306         \li \c GeoShape.RectangleType - The shape is a \l georectangle.
307         \li \c GeoShape.CircleType - The shape is a \l geocircle.
308         \li \c GeoShape.PathType - The shape is a \l geopath. (Since Qt 5.9)
309         \li \c GeoShape.PolygonType - The shape is a \l geopolygon. (Since Qt 5.10)
310     \endlist
311 
312     This QML property was introduced by Qt 5.5.
313 
314     \section1 Methods
315 
316     \section2 contains()
317 
318     \code
319     bool contains(coordinate coord)
320     \endcode
321 
322     Returns true if the \l {QtPositioning::coordinate}{coordinate} specified by \a coord is within
323     this geoshape; Otherwise returns false.
324 */
325 
326 /*!
327     \qmlbasictype georectangle
328     \inqmlmodule QtPositioning
329     \ingroup qml-QtPositioning5-basictypes
330     \since 5.2
331 
332     \brief The georectangle type represents a rectangular geographic area.
333 
334     The \c georectangle type is a \l {geoshape} that represents a
335     rectangular geographic area. The type is direct representation of a \l QGeoRectangle.
336     It is defined by a pair of \l {coordinate}{coordinates} which represent the top-left
337     and bottom-right corners of the \c {georectangle}.  The coordinates are accessible
338     from the \l topLeft and \l bottomRight attributes.
339 
340     A \c georectangle is considered invalid if the top-left or bottom-right coordinates are invalid
341     or if the top-left coordinate is south of the bottom-right coordinate.
342 
343     The coordinates of the four corners of the \c georectangle can be accessed with the
344     \l {topLeft}, \l {topRight}, \l {bottomLeft} and \l {bottomRight} attributes.  The \l center
345     attribute can be used to get the coordinate of the center of the \c georectangle.  The \l width
346     and \l height attributes can be used to get the width and height of the \c georectangle in
347     degrees.  Setting one of these attributes will cause the other attributes to be adjusted
348     accordingly.
349 
350     \section1 Limitations
351 
352     A \c georectangle can never cross the poles.
353 
354     If the height or center of a \c georectangle is adjusted such that it would cross one of the
355     poles the height is modified such that the \c georectangle touches but does not cross the pole
356     and that the center coordinate is still in the center of the \c georectangle.
357 
358     \section1 Example Usage
359 
360     Use properties of type \l variant to store a \c {georectangle}.  To create a \c georectangle
361     value, use the \l {QtPositioning::rectangle}{QtPositioning.rectangle()} function:
362 
363     \qml
364     import QtPositioning 5.2
365 
366     Item {
367         property variant region: QtPositioning.rectangle(QtPositioning.coordinate(-27.5, 153.1), QtPositioning.coordinate(-27.6, 153.2))
368     }
369     \endqml
370 
371     When integrating with C++, note that any QGeoRectangle value passed into QML from C++ is
372     automatically converted into a \c georectangle value, and vice-versa.
373 
374     \section1 Properties
375 
376     \section2 bottomLeft
377 
378     \code
379     coordinate bottomLeft
380     \endcode
381 
382     This property holds the bottom left coordinate of this georectangle.
383 
384     \section2 bottomRight
385 
386     \code
387     coordinate bottomRight
388     \endcode
389 
390     This property holds the bottom right coordinate of this georectangle.
391 
392     \section2 center
393 
394     \code
395     coordinate center
396     \endcode
397 
398     This property holds the center coordinate of this georectangle. For more details
399     see \l {QGeoRectangle::setCenter()}.
400 
401     \section2 height
402 
403     \code
404     double height
405     \endcode
406 
407     This property holds the height of this georectangle (in degrees). For more details
408     see \l {QGeoRectangle::setHeight()}.
409 
410     \note If the georectangle is invalid, it is not possible to set the height. QtPositioning
411     releases prior to Qt 5.5 permitted the setting of the height even on invalid georectangles.
412 
413     \section2 topLeft
414 
415     \code
416     coordinate topLeft
417     \endcode
418 
419     This property holds the top left coordinate of this georectangle.
420 
421     \section2 topRight
422 
423     \code
424     coordinate topRight
425     \endcode
426 
427     This property holds the top right coordinate of this georectangle.
428 
429     \section2 width
430 
431     \code
432     double width
433     \endcode
434 
435     This property holds the width of this georectangle (in degrees). For more details
436     see \l {QGeoRectangle::setWidth()}.
437 
438     \note If the georectangle is invalid, it is not possible to set the width. QtPositioning
439     releases prior to Qt 5.5 permitted the setting of the width even on invalid georectangles.
440 */
441 
442 /*!
443     \qmlbasictype geocircle
444     \inqmlmodule QtPositioning
445     \ingroup qml-QtPositioning5-basictypes
446     \since 5.2
447 
448     \brief The geocircle type represents a circular geographic area.
449 
450     The \c geocircle type is a \l {geoshape} that represents a circular
451     geographic area. It is a direct representation of a \l QGeoCircle and is defined
452     in terms of a \l {coordinate} which specifies the \l center of the circle and
453     a qreal which specifies the \l radius of the circle in meters.
454 
455     The circle is considered invalid if the \l center coordinate is invalid or if
456     the \l radius is less than zero.
457 
458     \section1 Example Usage
459 
460     Use properties of type \l variant to store a \c {geocircle}.  To create a \c geocircle value,
461     use the \l {QtPositioning::circle}{QtPositioning.circle()} function:
462 
463     \qml
464     import QtPositioning 5.2
465 
466     Item {
467         property variant region: QtPositioning.circle(QtPositioning.coordinate(-27.5, 153.1), 1000)
468     }
469     \endqml
470 
471     When integrating with C++, note that any QGeoCircle value passed into QML from C++ is
472     automatically converted into a \c geocircle value, and vise-versa.
473 
474     \section1 Properties
475 
476     \section2 center
477 
478     \code
479     coordinate radius
480     \endcode
481 
482     This property holds the coordinate of the center of the geocircle.
483 
484     \section2 radius
485 
486     \code
487     real radius
488     \endcode
489 
490     This property holds the radius of the geocircle in meters.
491 
492     The default value for the radius is -1 indicating an invalid geocircle area.
493 */
494 
495 /*!
496     \qmlbasictype geopath
497     \inqmlmodule QtPositioning
498     \ingroup qml-QtPositioning5-basictypes
499     \since 5.9
500 
501     \brief The geopath type represents a geographic path.
502 
503     The \c geopath type is a \l {geoshape} that represents a geographic
504     path. It is a direct representation of a \l QGeoPath and is defined
505     in terms of a \l {path} which holds the list of geo coordinates in the
506     path.
507 
508     The path is considered invalid if it is empty.
509 
510     When integrating with C++, note that any QGeoPath value passed into QML from C++ is
511     automatically converted into a \c geopath value, and vice versa.
512 
513     \section1 Properties
514 
515     \section2 path
516 
517     This property holds the list of coordinates defining the path.
518 
519     \section2 width
520 
521     This property holds the width of the path in meters. This is currently only used
522     when calling the \l {contains}() method.
523 
524     The default value for the width is 0.
525 */
526 
527 /*!
528    \qmlbasictype geopolygon
529    \inqmlmodule QtPositioning
530    \ingroup qml-QtPositioning5-basictypes
531    \since 5.10
532 
533    \brief The geopolygon type represents a geographic polygon.
534 
535    The \c geopolygon type is a \l [QML] geoshape that represents a geographic
536    polygon. It is a direct representation of QGeoPolygon and is defined in
537    terms of a \l path which holds a list of geo coordinates in the polygon.
538 
539    The polygon is considered invalid if its path holds less than three
540    coordinates.
541 
542    When integrating with C++, note that any QGeoPolygon value passed into QML
543    is automatically converted into a \c geopolygon, and vice versa.
544 
545    \section1 Properties
546 
547    \section2 path
548 
549    This property holds the list of coordinates defining the polygon.
550 */
551 
singleton_type_factory(QQmlEngine * engine,QJSEngine * jsEngine)552 static QObject *singleton_type_factory(QQmlEngine *engine, QJSEngine *jsEngine)
553 {
554     Q_UNUSED(engine);
555     Q_UNUSED(jsEngine);
556 
557     return new LocationSingleton;
558 }
559 
560 class QtPositioningDeclarativeModule: public QQmlExtensionPlugin
561 {
562     Q_OBJECT
563 
564     Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid
565                       FILE "plugin.json")
566 
567 public:
QtPositioningDeclarativeModule(QObject * parent=0)568     QtPositioningDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }
registerTypes(const char * uri)569     virtual void registerTypes(const char *uri)
570     {
571         if (QLatin1String(uri) == QStringLiteral("QtPositioning")) {
572 
573             // @uri QtPositioning 5.0
574 
575             int major = 5;
576             int minor = 0;
577 
578             qRegisterMetaType<QGeoCoordinate>();
579             QMetaType::registerEqualsComparator<QGeoCoordinate>();
580             qRegisterMetaType<QGeoAddress>();
581             qRegisterMetaType<QGeoRectangle>();
582             QMetaType::registerEqualsComparator<QGeoRectangle>();
583             qRegisterMetaType<QGeoCircle>();
584             QMetaType::registerEqualsComparator<QGeoCircle>();
585             qRegisterMetaType<QGeoPath>();
586             QMetaType::registerEqualsComparator<QGeoPath>();
587             qRegisterMetaType<QGeoPolygon>();
588             QMetaType::registerEqualsComparator<QGeoPolygon>();
589             qRegisterMetaType<QGeoLocation>();
590             qRegisterMetaType<QGeoShape>();
591             QMetaType::registerEqualsComparator<QGeoShape>();
592             qRegisterMetaType<QGeoCoordinateObject *>();
593             qRegisterMetaType<QGeoPositionInfo>();
594             QMetaType::registerEqualsComparator<QGeoPositionInfo>();
595 
596             qRegisterAnimationInterpolator<QGeoCoordinate>(q_coordinateInterpolator);
597 
598             // Register the 5.0 types
599             // 5.0 is silent and not advertised
600             qmlRegisterSingletonType<LocationSingleton  >(uri, major, minor, "QtPositioning", singleton_type_factory);
601             qmlRegisterValueTypeEnums<QGeoShape         >(uri, major, minor, "GeoShape");
602             qmlRegisterType<QDeclarativePosition        >(uri, major, minor, "Position");
603             qmlRegisterType<QDeclarativePositionSource  >(uri, major, minor, "PositionSource");
604             qmlRegisterType<QDeclarativeGeoAddress      >(uri, major, minor, "Address");
605             qmlRegisterType<QDeclarativeGeoLocation     >(uri, major, minor, "Location");
606 
607             // Register the 5.3 types
608             // Introduction of 5.3 version; existing 5.0 exports become automatically available under 5.3
609             minor = 3;
610             qmlRegisterType<QQuickGeoCoordinateAnimation  >(uri, major, minor, "CoordinateAnimation");
611             qmlRegisterType<QDeclarativePosition, 1>(uri, major, minor, "Position");
612 
613             minor = 4;
614             qmlRegisterType<QDeclarativePosition, 2>(uri, major, minor, "Position");
615 
616             minor = 13;
617             qmlRegisterType<QDeclarativeGeoLocation, 13>(uri, major, minor, "Location");
618 
619             minor = 14;
620             qmlRegisterType<QDeclarativePluginParameter >(uri, major, minor, "PluginParameter");
621 
622             // Register the latest Qt version as QML type version
623             qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
624         } else {
625             qDebug() << "Unsupported URI given to load positioning QML plugin: " << QLatin1String(uri);
626         }
627     }
628 };
629 
630 QT_END_NAMESPACE
631 
632 #include "positioning.moc"
633