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 <QGeoAreaMonitorSource> |
41 | #include "qgeopositioninfosourcefactory.h" |
42 | #include "qgeopositioninfosource_p.h" |
43 | |
44 | /*! |
45 | \class QGeoAreaMonitorSource |
46 | \inmodule QtPositioning |
47 | \ingroup QtPositioning-positioning |
48 | \since 5.2 |
49 | |
50 | \brief The QGeoAreaMonitorSource class enables the detection of proximity |
51 | changes for a specified set of coordinates. |
52 | |
53 | A QGeoAreaMonitorSource emits signals when the current position is in |
54 | range, or has moved out of range, of a specified area. |
55 | Each area is specified by a \l QGeoAreaMonitorInfo object. |
56 | For example: |
57 | |
58 | \snippet cpp/cppqml.cpp BigBen |
59 | |
60 | \c QGeoAreaMonitorSource follows a singleton pattern. Each instance of |
61 | the class with the same \l sourceName() shares the same area monitoring backend. |
62 | If a new \l QGeoAreaMonitorInfo object is added via \l startMonitoring() |
63 | or \l requestUpdate() it can be retrieved by another instance of this class |
64 | (provided that they are sourced from the same area monitor provider plug-in). |
65 | The same singleton pattern applies to the \l QGeoPositionInfoSource instance |
66 | used by this class. The following code snippet emphasizes the behavior: |
67 | |
68 | \code |
69 | QGeoAreaMonitorSource *s1 = QGeoAreaMonitorSource::createSource("blah", this); |
70 | QGeoAreaMonitorSource *s2 = QGeoAreaMonitorSource::createSource("blah", this); |
71 | QVERIFY(s1->positionInfoSource() == s2->positionInfoSource); |
72 | \endcode |
73 | */ |
74 | |
75 | QT_BEGIN_NAMESPACE |
76 | |
77 | |
78 | |
79 | class QGeoAreaMonitorSourcePrivate |
80 | { |
81 | public: |
82 | QGeoPositionInfoSource *source; |
83 | QString providerName; |
84 | }; |
85 | |
86 | /*! |
87 | \enum QGeoAreaMonitorSource::Error |
88 | Defines the types of positioning methods. |
89 | |
90 | The Error enumeration represents the errors which can occur. |
91 | |
92 | \value AccessError The connection setup to the remote area monitoring backend failed because the |
93 | application lacked the required privileges. |
94 | \value InsufficientPositionInfo The area monitoring source could not retrieve a location fix or |
95 | the accuracy of the fix is not high enough to provide an effective area monitoring. |
96 | \value NoError No error has occurred. |
97 | \value UnknownSourceError An unidentified error occurred. |
98 | */ |
99 | |
100 | /*! |
101 | \enum QGeoAreaMonitorSource::AreaMonitorFeature |
102 | Defines the types of area monitoring capabilities. |
103 | |
104 | \value PersistentAreaMonitorFeature QGeoAreaMonitorInfo instances can be made persistent. |
105 | A persistent monitor continues to be active even when the application managing the monitor is |
106 | not running. |
107 | \value AnyAreaMonitorFeature Matches all possible area monitoring features. |
108 | */ |
109 | |
110 | /*! |
111 | \fn virtual AreaMonitoringFeatures QGeoAreaMonitorSource::supportedAreaMonitorFeatures() const = 0; |
112 | |
113 | Returns the area monitoring features available to this source. |
114 | */ |
115 | |
116 | /*! |
117 | \fn virtual QGeoAreaMonitorSource::Error QGeoAreaMonitorSource::error() const |
118 | |
119 | Returns the type of error that last occurred. |
120 | */ |
121 | |
122 | /*! |
123 | Creates a monitor with the given \a parent. |
124 | */ |
125 | QGeoAreaMonitorSource::QGeoAreaMonitorSource(QObject *parent) |
126 | : QObject(parent), |
127 | d(new QGeoAreaMonitorSourcePrivate) |
128 | { |
129 | d->source = 0; |
130 | } |
131 | |
132 | /*! |
133 | Destroys the monitor. |
134 | */ |
135 | QGeoAreaMonitorSource::~QGeoAreaMonitorSource() |
136 | { |
137 | delete d; |
138 | } |
139 | |
140 | /*! |
141 | Creates and returns a monitor with the given \a parent that |
142 | monitors areas using resources on the underlying system. |
143 | |
144 | Returns 0 if the system has no support for position monitoring. |
145 | */ |
146 | QGeoAreaMonitorSource *QGeoAreaMonitorSource::createDefaultSource(QObject *parent) |
147 | { |
148 | QList<QJsonObject> plugins = QGeoPositionInfoSourcePrivate::pluginsSorted(); |
149 | foreach (const QJsonObject &obj, plugins) { |
150 | if (obj.value(QStringLiteral("Monitor" )).isBool() |
151 | && obj.value(QStringLiteral("Monitor" )).toBool()) |
152 | { |
153 | QGeoPositionInfoSourcePrivate d; |
154 | d.metaData = obj; |
155 | d.loadPlugin(); |
156 | QGeoAreaMonitorSource *s = 0; |
157 | if (d.factory) |
158 | s = d.factory->areaMonitor(parent); |
159 | if (s) |
160 | s->d->providerName = d.metaData.value(QStringLiteral("Provider" )).toString(); |
161 | return s; |
162 | } |
163 | } |
164 | |
165 | return 0; |
166 | } |
167 | |
168 | /*! |
169 | Creates and returns a monitor with the given \a parent, |
170 | by loading the plugin named \a sourceName. |
171 | |
172 | Returns 0 if the plugin cannot be found. |
173 | */ |
174 | QGeoAreaMonitorSource *QGeoAreaMonitorSource::createSource(const QString &sourceName, QObject *parent) |
175 | { |
176 | QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins(); |
177 | if (plugins.contains(akey: sourceName)) { |
178 | QGeoPositionInfoSourcePrivate d; |
179 | d.metaData = plugins.value(akey: sourceName); |
180 | d.loadPlugin(); |
181 | QGeoAreaMonitorSource *s = 0; |
182 | if (d.factory) |
183 | s = d.factory->areaMonitor(parent); |
184 | if (s) |
185 | s->d->providerName = d.metaData.value(QStringLiteral("Provider" )).toString(); |
186 | return s; |
187 | } |
188 | |
189 | return 0; |
190 | } |
191 | |
192 | /*! |
193 | Returns a list of available monitor plugins, including the default system |
194 | backend if one is available. |
195 | */ |
196 | QStringList QGeoAreaMonitorSource::availableSources() |
197 | { |
198 | QStringList plugins; |
199 | const QHash<QString, QJsonObject> meta = QGeoPositionInfoSourcePrivate::plugins(); |
200 | for (auto it = meta.cbegin(), end = meta.cend(); it != end; ++it) { |
201 | if (it.value().value(QStringLiteral("Monitor" )).isBool() |
202 | && it.value().value(QStringLiteral("Monitor" )).toBool()) { |
203 | plugins << it.key(); |
204 | } |
205 | } |
206 | |
207 | return plugins; |
208 | } |
209 | |
210 | /*! |
211 | Returns the unique name of the area monitor source implementation in use. |
212 | |
213 | This is the same name that can be passed to createSource() in order to |
214 | create a new instance of a particular area monitor source implementation. |
215 | */ |
216 | QString QGeoAreaMonitorSource::sourceName() const |
217 | { |
218 | return d->providerName; |
219 | } |
220 | |
221 | /*! |
222 | Returns the current QGeoPositionInfoSource used by this QGeoAreaMonitorSource |
223 | object. The function will return \l QGeoPositionInfoSource::createDefaultSource() |
224 | if no other object has been set. |
225 | |
226 | The function returns 0 if not even a default QGeoPositionInfoSource exists. |
227 | |
228 | Any usage of the returned \l QGeoPositionInfoSource instance should account |
229 | for the fact that it may reside in a different thread. |
230 | |
231 | \sa QGeoPositionInfoSource, setPositionInfoSource() |
232 | */ |
233 | QGeoPositionInfoSource* QGeoAreaMonitorSource::positionInfoSource() const |
234 | { |
235 | return d->source; |
236 | } |
237 | |
238 | /*! |
239 | Sets the new \l QGeoPositionInfoSource to be used by this QGeoAreaMonitorSource object. |
240 | The area monitoring backend becomes the new QObject parent for \a newSource. |
241 | The previous \l QGeoPositionInfoSource object will be deleted. All QGeoAreaMonitorSource |
242 | instances based on the same \l sourceName() share the same QGeoPositionInfoSource |
243 | instance. |
244 | |
245 | This may be useful when it is desirable to manipulate the positioning system |
246 | used by the area monitoring engine. |
247 | |
248 | Note that ownership must be taken care of by subclasses of QGeoAreaMonitorSource. |
249 | Due to the singleton pattern behind this class \a newSource may be moved to a |
250 | new thread. |
251 | |
252 | \sa positionInfoSource() |
253 | */ |
254 | void QGeoAreaMonitorSource::setPositionInfoSource(QGeoPositionInfoSource *newSource) |
255 | { |
256 | d->source = newSource; |
257 | } |
258 | |
259 | |
260 | /*! |
261 | \fn virtual bool QGeoAreaMonitorSource::startMonitoring(const QGeoAreaMonitorInfo &monitor) |
262 | |
263 | Returns \c true if the monitoring of \a monitor could be successfully started; otherwise |
264 | returns false. A reason for not being able to start monitoring could be the unavailability |
265 | of an appropriate default position info source while no alternative QGeoPositionInfoSource |
266 | has been set via \l setPositionInfoSource(). |
267 | |
268 | If \a monitor is already active the existing monitor object will be replaced by the new \a monitor reference. |
269 | The identification of QGeoAreaMonitorInfo instances happens via \l QGeoAreaMonitorInfo::identifier(). |
270 | Therefore this function can also be used to update active monitors. |
271 | |
272 | If \a monitor has an expiry date that has been passed this function returns false. Calling |
273 | this function for an already via \l requestUpdate() registered single shot monitor |
274 | switches the monitor to a permanent monitoring mode. |
275 | |
276 | Requesting persistent monitoring on a QGeoAreaMonitorSource instance fails if the area monitoring |
277 | backend doesn't support \l QGeoAreaMonitorSource::PersistentAreaMonitorFeature. |
278 | |
279 | \sa stopMonitoring() |
280 | */ |
281 | |
282 | /*! |
283 | \fn virtual bool QGeoAreaMonitorSource::requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal) |
284 | |
285 | Enables single shot area monitoring. Area monitoring for \a monitor will be performed |
286 | until this QGeoAreaMonitorSource instance emits \a signal for the first time. Once |
287 | the signal was emitted, \a monitor is automatically removed from the list of \l activeMonitors(). |
288 | If \a monitor is invalid or has an expiry date that has been passed this function returns false. |
289 | |
290 | \code |
291 | QGeoAreaMonitor singleShotMonitor; |
292 | QGeoAreaMonitorSource * source = QGeoAreaMonitorSource::createDefaultSource(this); |
293 | //... |
294 | bool ret = source->requestUpdate(singleShotMonitor, |
295 | SIGNAL(areaExited(QGeoAreaMonitor,QGeoPositionInfo))); |
296 | \endcode |
297 | |
298 | The above \c singleShotMonitor object will cease to send updates once the \l areaExited() signal |
299 | was emitted for the first time. Until this point in time any other signal may be emitted |
300 | zero or more times depending on the area context. |
301 | |
302 | It is not possible to simultanously request updates for more than one signal of the same monitor object. |
303 | The last call to this function determines the signal upon which the updates cease to continue. |
304 | At this stage only the \l areaEntered() and \l areaExited() signals can be used to |
305 | terminate the monitoring process. |
306 | |
307 | Requesting persistent monitoring on a QGeoAreaMonitorSource instance fails if the area monitoring |
308 | backend doesn't support \l QGeoAreaMonitorSource::PersistentAreaMonitorFeature. |
309 | |
310 | If \a monitor was already registered via \l startMonitoring() it is converted to a single |
311 | shot behavior. |
312 | |
313 | \sa startMonitoring(), stopMonitoring() |
314 | */ |
315 | |
316 | /*! |
317 | \fn virtual bool QGeoAreaMonitorSource::stopMonitoring(const QGeoAreaMonitorInfo &monitor) |
318 | |
319 | Returns true if \a monitor was successfully removed from the list of \l activeMonitors(); |
320 | otherwise returns false. This behavior is independent on whether \a monitor was registered |
321 | via \l startMonitoring() or \l requestUpdate(). |
322 | */ |
323 | |
324 | /*! |
325 | \fn virtual QList<QGeoAreaMonitorInfo> QGeoAreaMonitorSource::activeMonitors() const |
326 | |
327 | Returns the list of all active monitors known to the QGeoAreaMonitorSource object. |
328 | |
329 | An active monitor was started via startMonitoring() the source object will emit |
330 | the required signals such as areaEntered() or areaExited(). Multiple \l QGeoAreaMonitorSource |
331 | instances within the same application share the same active monitor objects. |
332 | |
333 | Unless an active QGeoAreaMonitorInfo \l {QGeoAreaMonitorInfo::isPersistent()}{isPersistent()} an active QGeoAreaMonitorInfo |
334 | will be stopped once the current application terminates. |
335 | */ |
336 | |
337 | /*! |
338 | \fn virtual QList<QGeoAreaMonitorInfo> QGeoAreaMonitorSource::activeMonitors(const QGeoShape &lookupArea) const |
339 | |
340 | Returns the list of all active monitors known to the QGeoAreaMonitorSource object whose |
341 | center lies within \a lookupArea. If \a lookupArea is empty the returned list will be empty. |
342 | |
343 | An active monitor was started via startMonitoring() and the source object will emit |
344 | the required signals such as areaEntered() or areaExited(). Multiple QGeoAreaMonitorSource |
345 | instances within the same application share the same monitor objects. |
346 | |
347 | Unless an active QGeoAreaMonitorInfo \l {QGeoAreaMonitorInfo::isPersistent()}{isPersistent()} an active QGeoAreaMonitorInfo |
348 | will be stopped once the current application terminates. |
349 | |
350 | \sa QGeoShape |
351 | */ |
352 | |
353 | |
354 | /*! |
355 | \fn void QGeoAreaMonitorSource::monitorExpired(const QGeoAreaMonitorInfo &monitor) |
356 | |
357 | Emitted when \a monitor has expired. An expired area monitor is automatically |
358 | removed from the list of \l activeMonitors(). |
359 | |
360 | \sa activeMonitors() |
361 | */ |
362 | |
363 | /*! |
364 | \fn void QGeoAreaMonitorSource::areaEntered(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update) |
365 | |
366 | Emitted when the current position has moved from a position outside of the active \a monitor |
367 | to a position within the monitored area. |
368 | |
369 | The \a update holds the new position. |
370 | */ |
371 | |
372 | /*! |
373 | \fn void QGeoAreaMonitorSource::areaExited(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update) |
374 | |
375 | Emitted when the current position has moved from a position within the active \a monitor |
376 | to a position outside the monitored area. |
377 | |
378 | The \a update holds the new position. |
379 | */ |
380 | |
381 | /*! |
382 | \fn void QGeoAreaMonitorSource::error(QGeoAreaMonitorSource::Error areaMonitoringError) |
383 | |
384 | This signal is emitted after an error occurred. The \a areaMonitoringError |
385 | parameter describes the type of error that occurred. |
386 | |
387 | */ |
388 | |
389 | QT_END_NAMESPACE |
390 | |