5#include <QtPositioning/qgeocoordinate.h>
6#include <QtPositioning/qgeorectangle.h>
7#include <QtPositioning/qgeocircle.h>
9#include <QtCore/qhash.h>
10#include <QtCore/qmetaobject.h>
11#include <QtCore/qtimer.h>
12#include <QtCore/qdebug.h>
13#include <QtCore/qmutex.h>
14#include <QtCore/qset.h>
18#define UPDATE_INTERVAL_5S 5000
22typedef QHash<QString, QGeoAreaMonitorInfo> MonitorTable;
26 static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaEntered);
32 static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaExited);
38 static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::monitorExpired);
244 const QGeoPositionInfo &pinfo,
bool isEnteredEvent);
249
250
251
252 const QGeoAreaMonitorInfo info = activeMonitorAreas.take(activeExpiry.second);
253 setupNextExpiryTimeout();
258 void positionUpdated(
const QGeoPositionInfo &info)
260 const auto monInfos = activeMonitors();
261 for (
const QGeoAreaMonitorInfo &monInfo : monInfos) {
262 const QString identifier = monInfo.identifier();
263 if (monInfo.area().contains(info.coordinate())) {
264 if (processInsideArea(identifier))
265 emit areaEventDetected(monInfo, info,
true);
267 if (processOutsideArea(identifier))
268 emit areaEventDetected(monInfo, info,
false);
275 QHash<QString,
int> singleShotTrigger;
276 QTimer* nextExpiryTimer;
277 QSet<QString> insideArea;
279 MonitorTable activeMonitorAreas;
281 QGeoPositionInfoSource* source =
nullptr;
282 QList<QGeoAreaMonitorPolling*> registeredClients;
283 mutable QRecursiveMutex mutex;
290 d = pollingPrivate();
291 d->registerClient(
this);
293 if (!positionInfoSource())
294 setPositionInfoSource(QGeoPositionInfoSource::createDefaultSource(
this));
297QGeoAreaMonitorPolling::~QGeoAreaMonitorPolling()
299 d->deregisterClient(
this);
304 return d->positionSource();
309 d->setPositionSource(source);
319 if (!monitor.isValid())
323 if (monitor.expiration().isValid() &&
324 (monitor.expiration() < QDateTime::currentDateTime()))
328 if (monitor.isPersistent())
331 lastError = QGeoAreaMonitorSource::NoError;
334 d->startMonitoring(monitor);
341 if (qstrlen(signal) < 2)
344 const QByteArray sig = QMetaObject::normalizedSignature(signal + 1);
345 const QMetaObject *
const mo = metaObject();
347 return mo->indexOfSignal(sig.constData());
353 return signalConnections > 0;
358 if (!monitor.isValid())
361 if (monitor.expiration().isValid() &&
362 (monitor.expiration() < QDateTime::currentDateTime()))
366 if (monitor.isPersistent())
370 const int signalId = idForSignal(signal);
375 if (signalId != areaEnteredSignal().methodIndex() &&
376 signalId != areaExitedSignal().methodIndex())
381 lastError = QGeoAreaMonitorSource::NoError;
383 d->requestUpdate(monitor, signalId);
390 QGeoAreaMonitorInfo info = d->stopMonitoring(monitor);
392 return info.isValid();
397 return d->activeMonitors().values();
402 QList<QGeoAreaMonitorInfo> results;
403 if (region.isEmpty())
406 const MonitorTable list = d->activeMonitors();
407 for (
const QGeoAreaMonitorInfo &monitor : list) {
408 if (region.contains(monitor.area().center()))
409 results.append(monitor);
422 QMutexLocker locker(&connectionMutex);
423 if (signal == areaEnteredSignal() || signal == areaExitedSignal()) {
424 const bool alreadyConnected = hasConnections();
426 if (!alreadyConnected)
433 QMutexLocker locker(&connectionMutex);
434 if (signal == areaEnteredSignal() || signal == areaExitedSignal()) {
435 if (hasConnections())
437 if (!hasConnections())
445 case QGeoPositionInfoSource::AccessError:
446 lastError = QGeoAreaMonitorSource::AccessError;
448 case QGeoPositionInfoSource::UnknownSourceError:
449 lastError = QGeoAreaMonitorSource::UnknownSourceError;
451 case QGeoPositionInfoSource::ClosedError:
452 case QGeoPositionInfoSource::UpdateTimeoutError:
453 lastError = QGeoAreaMonitorSource::InsufficientPositionInfo;
455 case QGeoPositionInfoSource::NoError:
459 emit QGeoAreaMonitorSource::errorOccurred(lastError);
464 if (isSignalConnected(monitorExpiredSignal()))
465 emit monitorExpired(monitor);
469 const QGeoPositionInfo &pinfo,
bool isEnteredEvent)
472 emit areaEntered(minfo, pinfo);
474 emit areaExited(minfo, pinfo);
479#include "qgeoareamonitor_polling.moc"
480#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()