6#include <QtPositioning/qgeocoordinate.h>
7#include <QtPositioning/qgeorectangle.h>
8#include <QtPositioning/qgeocircle.h>
10#include <QtCore/qhash.h>
11#include <QtCore/qmetaobject.h>
12#include <QtCore/qtimer.h>
13#include <QtCore/qdebug.h>
14#include <QtCore/qmutex.h>
15#include <QtCore/qset.h>
19#define UPDATE_INTERVAL_5S 5000
23typedef QHash<QString, QGeoAreaMonitorInfo> MonitorTable;
27 static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaEntered);
33 static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaExited);
39 static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::monitorExpired);
245 const QGeoPositionInfo &pinfo,
bool isEnteredEvent);
250
251
252
253 const QGeoAreaMonitorInfo info = activeMonitorAreas.take(activeExpiry.second);
254 setupNextExpiryTimeout();
259 void positionUpdated(
const QGeoPositionInfo &info)
261 const auto monInfos = activeMonitors();
262 for (
const QGeoAreaMonitorInfo &monInfo : monInfos) {
263 const QString identifier = monInfo.identifier();
264 if (monInfo.area().contains(info.coordinate())) {
265 if (processInsideArea(identifier))
266 emit areaEventDetected(monInfo, info,
true);
268 if (processOutsideArea(identifier))
269 emit areaEventDetected(monInfo, info,
false);
276 QHash<QString,
int> singleShotTrigger;
277 QTimer* nextExpiryTimer;
278 QSet<QString> insideArea;
280 MonitorTable activeMonitorAreas;
282 QGeoPositionInfoSource* source =
nullptr;
283 QList<QGeoAreaMonitorPolling*> registeredClients;
284 mutable QRecursiveMutex mutex;
291 d = pollingPrivate();
292 d->registerClient(
this);
294 if (!positionInfoSource())
295 setPositionInfoSource(QGeoPositionInfoSource::createDefaultSource(
this));
298QGeoAreaMonitorPolling::~QGeoAreaMonitorPolling()
300 d->deregisterClient(
this);
305 return d->positionSource();
310 d->setPositionSource(source);
320 if (!monitor.isValid())
324 if (monitor.expiration().isValid() &&
325 (monitor.expiration() < QDateTime::currentDateTime()))
329 if (monitor.isPersistent())
332 lastError = QGeoAreaMonitorSource::NoError;
335 d->startMonitoring(monitor);
342 if (qstrlen(signal) < 2)
345 const QByteArray sig = QMetaObject::normalizedSignature(signal + 1);
346 const QMetaObject *
const mo = metaObject();
348 return mo->indexOfSignal(sig.constData());
354 return signalConnections > 0;
359 if (!monitor.isValid())
362 if (monitor.expiration().isValid() &&
363 (monitor.expiration() < QDateTime::currentDateTime()))
367 if (monitor.isPersistent())
371 const int signalId = idForSignal(signal);
376 if (signalId != areaEnteredSignal().methodIndex() &&
377 signalId != areaExitedSignal().methodIndex())
382 lastError = QGeoAreaMonitorSource::NoError;
384 d->requestUpdate(monitor, signalId);
391 QGeoAreaMonitorInfo info = d->stopMonitoring(monitor);
393 return info.isValid();
398 return d->activeMonitors().values();
403 QList<QGeoAreaMonitorInfo> results;
404 if (region.isEmpty())
407 const MonitorTable list = d->activeMonitors();
408 for (
const QGeoAreaMonitorInfo &monitor : list) {
409 if (region.contains(monitor.area().center()))
410 results.append(monitor);
423 QMutexLocker locker(&connectionMutex);
424 if (signal == areaEnteredSignal() || signal == areaExitedSignal()) {
425 const bool alreadyConnected = hasConnections();
427 if (!alreadyConnected)
434 QMutexLocker locker(&connectionMutex);
435 if (signal == areaEnteredSignal() || signal == areaExitedSignal()) {
436 if (hasConnections())
438 if (!hasConnections())
446 case QGeoPositionInfoSource::AccessError:
447 lastError = QGeoAreaMonitorSource::AccessError;
449 case QGeoPositionInfoSource::UnknownSourceError:
450 lastError = QGeoAreaMonitorSource::UnknownSourceError;
452 case QGeoPositionInfoSource::ClosedError:
453 case QGeoPositionInfoSource::UpdateTimeoutError:
454 lastError = QGeoAreaMonitorSource::InsufficientPositionInfo;
456 case QGeoPositionInfoSource::NoError:
460 emit QGeoAreaMonitorSource::errorOccurred(lastError);
465 if (isSignalConnected(monitorExpiredSignal()))
466 emit monitorExpired(monitor);
470 const QGeoPositionInfo &pinfo,
bool isEnteredEvent)
473 emit areaEntered(minfo, pinfo);
475 emit areaExited(minfo, pinfo);
480#include "qgeoareamonitor_polling.moc"
481#include "moc_qgeoareamonitor_polling.cpp"
void areaEventDetected(const QGeoAreaMonitorInfo &minfo, const QGeoPositionInfo &pinfo, bool isEnteredEvent)
void positionError(const QGeoPositionInfoSource::Error error)
Error error() const override
Returns the type of error that last occurred.
QGeoPositionInfoSource * positionInfoSource() const override
Returns the current QGeoPositionInfoSource used by this QGeoAreaMonitorSource object.
void connectNotify(const QMetaMethod &signal) override
QGeoAreaMonitorSource::AreaMonitorFeatures supportedAreaMonitorFeatures() const override
Returns the area monitoring features available to this source.
QList< QGeoAreaMonitorInfo > activeMonitors() const override
Returns the list of all active monitors known to the QGeoAreaMonitorSource object.
bool stopMonitoring(const QGeoAreaMonitorInfo &monitor) override
Returns true if monitor was successfully removed from the list of \l activeMonitors(); otherwise retu...
void setPositionInfoSource(QGeoPositionInfoSource *source) override
Sets the new \l QGeoPositionInfoSource to be used by this QGeoAreaMonitorSource object.
bool requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal) override
Enables single shot area monitoring.
QList< QGeoAreaMonitorInfo > activeMonitors(const QGeoShape ®ion) const override
Returns the list of all active monitors known to the QGeoAreaMonitorSource object whose center lies w...
bool startMonitoring(const QGeoAreaMonitorInfo &monitor) override
Returns true if the monitoring of monitor could be successfully started; otherwise returns false.
void disconnectNotify(const QMetaMethod &signal) override
static QMetaMethod areaEnteredSignal()
#define UPDATE_INTERVAL_5S
static QMetaMethod monitorExpiredSignal()
static QMetaMethod areaExitedSignal()