summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2013-08-26 09:35:01 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-17 11:38:14 +0200
commit0ed9f7496656fa0ea52d703c7fddff26c2192857 (patch)
treeec0d4d7dc638e8018a8896a0b62cc91840c9c23d
parent87ce030b7b7336e561779dc9516d5ae2242a5d5f (diff)
downloadqtlocation-0ed9f7496656fa0ea52d703c7fddff26c2192857.tar.gz
Improve area monitoring API.
1.) QGeoAreaMonitor renamed to QGeoAreaMonitorSource 2.) Add new QGeoAreaMonitorInfo data type encpsulating individual areas to be monitored 3.) Port positionpoll plug-in to new features 4.) Make positionpoll monitor thread safe 4.) Extend and fix the QGeoAreaMonitor unit test 5.) Fix documentation. Task-number: QTBUG-31711 Change-Id: Icfc982de4753d2f43cb4d15c234eb7b7c039a0c4 Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
-rw-r--r--src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp2
-rw-r--r--src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h2
-rw-r--r--src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp2
-rw-r--r--src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h2
-rw-r--r--src/plugins/position/positionpoll/positionpollfactory.cpp5
-rw-r--r--src/plugins/position/positionpoll/positionpollfactory.h2
-rw-r--r--src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp480
-rw-r--r--src/plugins/position/positionpoll/qgeoareamonitor_polling.h42
-rw-r--r--src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp2
-rw-r--r--src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h2
-rw-r--r--src/positioning/doc/snippets/cpp/cppqml.cpp40
-rw-r--r--src/positioning/doc/src/cpp-position.qdoc4
-rw-r--r--src/positioning/doc/src/qtpositioning-plugins.qdoc2
-rw-r--r--src/positioning/positioning.pro6
-rw-r--r--src/positioning/qgeoareamonitor.cpp256
-rw-r--r--src/positioning/qgeoareamonitorinfo.cpp379
-rw-r--r--src/positioning/qgeoareamonitorinfo.h105
-rw-r--r--src/positioning/qgeoareamonitorsource.cpp390
-rw-r--r--src/positioning/qgeoareamonitorsource.h109
-rw-r--r--src/positioning/qgeopositioninfosourcefactory.cpp4
-rw-r--r--src/positioning/qgeopositioninfosourcefactory.h4
-rw-r--r--src/positioning/qgeosatelliteinfosource.cpp17
-rw-r--r--src/positioning/qgeosatelliteinfosource.h4
-rw-r--r--tests/auto/positionplugin/plugin.cpp4
-rw-r--r--tests/auto/positionplugintest/tst_positionplugin.cpp4
-rw-r--r--tests/auto/qgeoareamonitor/logfilepositionsource.cpp125
-rw-r--r--tests/auto/qgeoareamonitor/logfilepositionsource.h (renamed from src/positioning/qgeoareamonitor.h)52
-rw-r--r--tests/auto/qgeoareamonitor/qgeoareamonitor.pro7
-rw-r--r--tests/auto/qgeoareamonitor/simplelog.txt87
-rw-r--r--tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp734
30 files changed, 2355 insertions, 519 deletions
diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp
index 5f243d89..9be36053 100644
--- a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp
+++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp
@@ -73,7 +73,7 @@ QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGeoclue::satelliteInfoSour
#endif
}
-QGeoAreaMonitor *QGeoPositionInfoSourceFactoryGeoclue::areaMonitor(QObject *parent)
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryGeoclue::areaMonitor(QObject *parent)
{
Q_UNUSED(parent);
return 0;
diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h
index 0fa95d72..3de93bbf 100644
--- a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h
+++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h
@@ -65,7 +65,7 @@ class QGeoPositionInfoSourceFactoryGeoclue : public QObject, public QGeoPosition
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent);
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
- QGeoAreaMonitor *areaMonitor(QObject *parent);
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent);
};
#endif
diff --git a/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp
index dee265de..3e8b93a3 100644
--- a/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp
+++ b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.cpp
@@ -58,7 +58,7 @@ QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGypsy::satelliteInfoSource
return src;
}
-QGeoAreaMonitor *QGeoPositionInfoSourceFactoryGypsy::areaMonitor(QObject *parent)
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryGypsy::areaMonitor(QObject *parent)
{
Q_UNUSED(parent);
return 0;
diff --git a/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h
index 6cd145ca..dab3cc71 100644
--- a/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h
+++ b/src/plugins/position/gypsy/qgeopositioninfosourcefactory_gypsy.h
@@ -55,7 +55,7 @@ class QGeoPositionInfoSourceFactoryGypsy : public QObject, public QGeoPositionIn
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent);
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
- QGeoAreaMonitor *areaMonitor(QObject *parent);
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent);
};
#endif
diff --git a/src/plugins/position/positionpoll/positionpollfactory.cpp b/src/plugins/position/positionpoll/positionpollfactory.cpp
index a3ec6527..0f02bff1 100644
--- a/src/plugins/position/positionpoll/positionpollfactory.cpp
+++ b/src/plugins/position/positionpoll/positionpollfactory.cpp
@@ -54,10 +54,9 @@ QGeoSatelliteInfoSource *PositionPollFactory::satelliteInfoSource(QObject *paren
return 0;
}
-QGeoAreaMonitor *PositionPollFactory::areaMonitor(QObject *parent)
+QGeoAreaMonitorSource *PositionPollFactory::areaMonitor(QObject *parent)
{
- QGeoAreaMonitorPolling *ret = 0;
- ret = new QGeoAreaMonitorPolling(parent);
+ QGeoAreaMonitorPolling *ret = new QGeoAreaMonitorPolling(parent);
if (ret && ret->isValid())
return ret;
delete ret;
diff --git a/src/plugins/position/positionpoll/positionpollfactory.h b/src/plugins/position/positionpoll/positionpollfactory.h
index 73a4d60a..79ad85eb 100644
--- a/src/plugins/position/positionpoll/positionpollfactory.h
+++ b/src/plugins/position/positionpoll/positionpollfactory.h
@@ -54,7 +54,7 @@ class PositionPollFactory : public QObject, public QGeoPositionInfoSourceFactory
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent);
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
- QGeoAreaMonitor *areaMonitor(QObject *parent);
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent);
};
#endif // POSITIONPOLLFACTORY_H
diff --git a/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp b/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp
index 784c9fad..55d66993 100644
--- a/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp
+++ b/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp
@@ -41,94 +41,476 @@
#include "qgeoareamonitor_polling.h"
#include <qgeocoordinate.h>
+#include <qgeorectangle.h>
+#include <qgeocircle.h>
#include <QtCore/qmetaobject.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qmutex.h>
#define UPDATE_INTERVAL_5S 5000
-QGeoAreaMonitorPolling::QGeoAreaMonitorPolling(QObject *parent) : QGeoAreaMonitor(parent)
+typedef QHash<QString, QGeoAreaMonitorInfo> MonitorTable;
+
+
+static QMetaMethod areaEnteredSignal()
{
- insideArea = false;
- location = QGeoPositionInfoSource::createDefaultSource(this);
- if (location) {
- location->setUpdateInterval(UPDATE_INTERVAL_5S);
- connect(location, SIGNAL(positionUpdated(QGeoPositionInfo)),
- this, SLOT(positionUpdated(QGeoPositionInfo)));
- }
+ static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaEntered);
+ return signal;
}
-QGeoAreaMonitorPolling::~QGeoAreaMonitorPolling()
+static QMetaMethod areaExitedSignal()
{
- if (location)
- location->stopUpdates();
+ static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaExited);
+ return signal;
+}
+
+static QMetaMethod monitorExpiredSignal()
+{
+ static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::monitorExpired);
+ return signal;
}
-void QGeoAreaMonitorPolling::setCenter(const QGeoCoordinate &coordinate)
+class QGeoAreaMonitorPollingPrivate : public QObject
{
- if (coordinate.isValid()) {
- QGeoAreaMonitor::setCenter(coordinate);
+ Q_OBJECT
+public:
+ QGeoAreaMonitorPollingPrivate() : source(0), mutex(QMutex::Recursive)
+ {
+ nextExpiryTimer = new QTimer(this);
+ nextExpiryTimer->setSingleShot(true);
+ connect(nextExpiryTimer, SIGNAL(timeout()),
+ this, SLOT(timeout()));
+ }
+
+ void startMonitoring(const QGeoAreaMonitorInfo &monitor)
+ {
+ QMutexLocker locker(&mutex);
+
+ activeMonitorAreas.insert(monitor.identifier(), monitor);
+ singleShotTrigger.remove(monitor.identifier());
+
+ checkStartStop();
+ setupNextExpiryTimeout();
+ }
+
+ void requestUpdate(const QGeoAreaMonitorInfo &monitor, int signalId)
+ {
+ QMutexLocker locker(&mutex);
+
+ activeMonitorAreas.insert(monitor.identifier(), monitor);
+ singleShotTrigger.insert(monitor.identifier(), signalId);
+
+ checkStartStop();
+ setupNextExpiryTimeout();
+ }
+
+ QGeoAreaMonitorInfo stopMonitoring(const QGeoAreaMonitorInfo &monitor)
+ {
+ QMutexLocker locker(&mutex);
+
+ QGeoAreaMonitorInfo mon = activeMonitorAreas.take(monitor.identifier());
+
checkStartStop();
+ setupNextExpiryTimeout();
+
+ return mon;
}
+
+ void registerClient(QGeoAreaMonitorPolling *client)
+ {
+ QMutexLocker locker(&mutex);
+
+ connect(this, SIGNAL(timeout(QGeoAreaMonitorInfo)),
+ client, SLOT(timeout(QGeoAreaMonitorInfo)));
+
+ connect(this, SIGNAL(positionError(QGeoPositionInfoSource::Error)),
+ client, SLOT(positionError(QGeoPositionInfoSource::Error)));
+
+ connect(this, SIGNAL(areaEventDetected(QGeoAreaMonitorInfo,QGeoPositionInfo,bool)),
+ client, SLOT(processAreaEvent(QGeoAreaMonitorInfo,QGeoPositionInfo,bool)));
+
+ registeredClients.append(client);
+ }
+
+ void deregisterClient(QGeoAreaMonitorPolling *client)
+ {
+ QMutexLocker locker(&mutex);
+
+ registeredClients.removeAll(client);
+ if (registeredClients.isEmpty())
+ checkStartStop();
+ }
+
+ void setPositionSource(QGeoPositionInfoSource *newSource)
+ {
+ QMutexLocker locker(&mutex);
+
+ if (newSource == source)
+ return;
+
+ if (source)
+ delete source;
+
+ source = newSource;
+
+ if (source) {
+ source->setParent(this);
+ source->moveToThread(this->thread());
+ if (source->updateInterval() == 0)
+ source->setUpdateInterval(UPDATE_INTERVAL_5S);
+ disconnect(source, 0, 0, 0); //disconnect all
+ connect(source, SIGNAL(positionUpdated(QGeoPositionInfo)),
+ this, SLOT(positionUpdated(QGeoPositionInfo)));
+ connect(source, SIGNAL(error(QGeoPositionInfoSource::Error)),
+ this, SIGNAL(positionError(QGeoPositionInfoSource::Error)));
+ checkStartStop();
+ }
+ }
+
+ QGeoPositionInfoSource* positionSource() const
+ {
+ QMutexLocker locker(&mutex);
+ return source;
+ }
+
+ MonitorTable activeMonitors() const
+ {
+ QMutexLocker locker(&mutex);
+
+ return activeMonitorAreas;
+ }
+
+ void checkStartStop()
+ {
+ QMutexLocker locker(&mutex);
+
+ bool signalsConnected = false;
+ foreach (const QGeoAreaMonitorPolling *client, registeredClients) {
+ if (client->signalsAreConnected) {
+ signalsConnected = true;
+ break;
+ }
+ }
+
+ if (signalsConnected && !activeMonitorAreas.isEmpty()) {
+ if (source)
+ source->startUpdates();
+ else
+ //translated to InsufficientPositionInfo
+ emit positionError(QGeoPositionInfoSource::ClosedError);
+ } else {
+ if (source)
+ source->stopUpdates();
+ }
+ }
+
+private:
+ void setupNextExpiryTimeout()
+ {
+ nextExpiryTimer->stop();
+ activeExpiry.first = QDateTime();
+ activeExpiry.second = QString();
+
+ foreach (const QGeoAreaMonitorInfo &info, activeMonitors()) {
+ if (info.expiration().isValid()) {
+ if (!activeExpiry.first.isValid()) {
+ activeExpiry.first = info.expiration();
+ activeExpiry.second = info.identifier();
+ continue;
+ }
+ if (info.expiration() < activeExpiry.first) {
+ activeExpiry.first = info.expiration();
+ activeExpiry.second = info.identifier();
+ }
+ }
+ }
+
+ if (activeExpiry.first.isValid())
+ nextExpiryTimer->start(QDateTime::currentDateTime().msecsTo(activeExpiry.first));
+ }
+
+
+ //returns true if areaEntered should be emitted
+ bool processInsideArea(const QString &monitorIdent)
+ {
+ if (!insideArea.contains(monitorIdent)) {
+ if (singleShotTrigger.value(monitorIdent, -1) == areaEnteredSignal().methodIndex()) {
+ //this is the finishing singleshot event
+ singleShotTrigger.remove(monitorIdent);
+ activeMonitorAreas.remove(monitorIdent);
+ setupNextExpiryTimeout();
+ } else {
+ insideArea.insert(monitorIdent);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ //returns true if areaExited should be emitted
+ bool processOutsideArea(const QString &monitorIdent)
+ {
+ if (insideArea.contains(monitorIdent)) {
+ if (singleShotTrigger.value(monitorIdent, -1) == areaExitedSignal().methodIndex()) {
+ //this is the finishing singleShot event
+ singleShotTrigger.remove(monitorIdent);
+ activeMonitorAreas.remove(monitorIdent);
+ setupNextExpiryTimeout();
+ } else {
+ insideArea.remove(monitorIdent);
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+
+Q_SIGNALS:
+ void timeout(const QGeoAreaMonitorInfo &info);
+ void positionError(const QGeoPositionInfoSource::Error error);
+ void areaEventDetected(const QGeoAreaMonitorInfo &minfo,
+ const QGeoPositionInfo &pinfo, bool isEnteredEvent);
+private Q_SLOTS:
+ void timeout()
+ {
+ /*
+ * Don't block timer firing even if monitorExpiredSignal is not connected.
+ * This allows us to continue to remove the existing monitors as they expire.
+ **/
+ const QGeoAreaMonitorInfo info = activeMonitorAreas.take(activeExpiry.second);
+ setupNextExpiryTimeout();
+ emit timeout(info);
+
+ }
+
+ void positionUpdated(const QGeoPositionInfo &info)
+ {
+ foreach (const QGeoAreaMonitorInfo &monInfo, activeMonitors()) {
+ const QString identifier = monInfo.identifier();
+ if (monInfo.area().contains(info.coordinate())) {
+ if (processInsideArea(identifier))
+ emit areaEventDetected(monInfo, info, true);
+ } else {
+ if (processOutsideArea(identifier))
+ emit areaEventDetected(monInfo, info, false);
+ }
+ }
+ }
+
+private:
+ QPair<QDateTime, QString> activeExpiry;
+ QHash<QString, int> singleShotTrigger;
+ QTimer* nextExpiryTimer;
+ QSet<QString> insideArea;
+
+ MonitorTable activeMonitorAreas;
+
+ QGeoPositionInfoSource* source;
+ QList<QGeoAreaMonitorPolling*> registeredClients;
+ mutable QMutex mutex;
+};
+
+Q_GLOBAL_STATIC(QGeoAreaMonitorPollingPrivate, pollingPrivate)
+
+
+QGeoAreaMonitorPolling::QGeoAreaMonitorPolling(QObject *parent)
+ : QGeoAreaMonitorSource(parent), signalsAreConnected(false)
+{
+ d = pollingPrivate();
+ lastError = QGeoAreaMonitorSource::UnknownSourceError;
+ d->registerClient(this);
+ //hookup to default source if existing
+ if (!positionInfoSource())
+ setPositionInfoSource(QGeoPositionInfoSource::createDefaultSource(this));
}
-void QGeoAreaMonitorPolling::setRadius(qreal radius)
+QGeoAreaMonitorPolling::~QGeoAreaMonitorPolling()
{
- QGeoAreaMonitor::setRadius(radius);
- checkStartStop();
+ d->deregisterClient(this);
}
-static QMetaMethod areaEnteredSignal()
+QGeoPositionInfoSource* QGeoAreaMonitorPolling::positionInfoSource() const
{
- static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaEntered);
- return signal;
+ return d->positionSource();
}
-static QMetaMethod areaExitedSignal()
+void QGeoAreaMonitorPolling::setPositionInfoSource(QGeoPositionInfoSource *source)
{
- static QMetaMethod signal = QMetaMethod::fromSignal(&QGeoAreaMonitorPolling::areaExited);
- return signal;
+ d->setPositionSource(source);
}
-void QGeoAreaMonitorPolling::connectNotify(const QMetaMethod &signal)
+QGeoAreaMonitorSource::Error QGeoAreaMonitorPolling::error() const
{
- if (signal == areaEnteredSignal() ||
- signal == areaExitedSignal())
- checkStartStop();
+ return lastError;
}
-void QGeoAreaMonitorPolling::disconnectNotify(const QMetaMethod &signal)
+bool QGeoAreaMonitorPolling::startMonitoring(const QGeoAreaMonitorInfo &monitor)
{
- if (signal == areaEnteredSignal() ||
- signal == areaExitedSignal())
- checkStartStop();
+ if (!monitor.isValid())
+ return false;
+
+ //reject an expiry in the past
+ if (monitor.expiration().isValid() &&
+ (monitor.expiration() < QDateTime::currentDateTime()))
+ return false;
+
+ //don't accept persistent monitor since we don't support it
+ if (monitor.isPersistent())
+ return false;
+
+ //update or insert
+ d->startMonitoring(monitor);
+
+ return true;
+}
+
+int QGeoAreaMonitorPolling::idForSignal(const char *signal)
+{
+ const QByteArray sig = QMetaObject::normalizedSignature(signal + 1);
+ const QMetaObject * const mo = metaObject();
+
+ return mo->indexOfSignal(sig.constData());
+}
+
+bool QGeoAreaMonitorPolling::requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal)
+{
+ if (!monitor.isValid())
+ return false;
+ //reject an expiry in the past
+ if (monitor.expiration().isValid() &&
+ (monitor.expiration() < QDateTime::currentDateTime()))
+ return false;
+
+ //don't accept persistent monitor since we don't support it
+ if (monitor.isPersistent())
+ return false;
+
+ if (!signal)
+ return false;
+
+ const int signalId = idForSignal(signal);
+ if (signalId < 0)
+ return false;
+
+ //only accept area entered or exit signal
+ if (signalId != areaEnteredSignal().methodIndex() &&
+ signalId != areaExitedSignal().methodIndex())
+ {
+ return false;
+ }
+
+ d->requestUpdate(monitor, signalId);
+
+ return true;
+}
+
+bool QGeoAreaMonitorPolling::stopMonitoring(const QGeoAreaMonitorInfo &monitor)
+{
+ QGeoAreaMonitorInfo info = d->stopMonitoring(monitor);
+
+ return info.isValid();
+}
+
+QList<QGeoAreaMonitorInfo> QGeoAreaMonitorPolling::activeMonitors() const
+{
+ return d->activeMonitors().values();
+}
+
+QList<QGeoAreaMonitorInfo> QGeoAreaMonitorPolling::activeMonitors(const QGeoShape &region) const
+{
+ QList<QGeoAreaMonitorInfo> results;
+ if (region.isEmpty())
+ return results;
+
+ const MonitorTable list = d->activeMonitors();
+ foreach (const QGeoAreaMonitorInfo &monitor, list) {
+ QGeoCoordinate center;
+ switch (monitor.area().type()) {
+ case QGeoShape::CircleType:
+ {
+ QGeoCircle circle(monitor.area());
+ center = circle.center();
+ break;
+ }
+ case QGeoShape::RectangleType:
+ {
+ QGeoRectangle rectangle(monitor.area());
+ center = rectangle.center();
+ break;
+ }
+ case QGeoShape::UnknownType:
+ {
+ break;
+ }
+ }
+ if (region.contains(center))
+ results.append(monitor);
+ }
+
+ return results;
}
-void QGeoAreaMonitorPolling::checkStartStop()
+QGeoAreaMonitorSource::AreaMonitorFeatures QGeoAreaMonitorPolling::supportedAreaMonitorFeatures() const
{
- if (!location) return;
+ return 0;
+}
- if ((isSignalConnected(areaEnteredSignal()) ||
- isSignalConnected(areaExitedSignal())) &&
- QGeoAreaMonitor::center().isValid() &&
- QGeoAreaMonitor::radius() > qreal(0.0)) {
- location->startUpdates();
- } else {
- location->stopUpdates();
+void QGeoAreaMonitorPolling::connectNotify(const QMetaMethod &/*signal*/)
+{
+ if (!signalsAreConnected &&
+ (isSignalConnected(areaEnteredSignal()) ||
+ isSignalConnected(areaExitedSignal())) )
+ {
+ signalsAreConnected = true;
+ d->checkStartStop();
}
}
-void QGeoAreaMonitorPolling::positionUpdated(const QGeoPositionInfo &info)
+void QGeoAreaMonitorPolling::disconnectNotify(const QMetaMethod &/*signal*/)
{
- double distance = info.coordinate().distanceTo(QGeoAreaMonitor::center());
+ if (!isSignalConnected(areaEnteredSignal()) &&
+ !isSignalConnected(areaExitedSignal()))
+ {
+ signalsAreConnected = false;
+ d->checkStartStop();
+ }
+}
- if (distance <= QGeoAreaMonitor::radius()) {
- if (!insideArea)
- emit areaEntered(info);
- insideArea = true;
- } else if (insideArea) {
- emit areaExited(info);
- insideArea = false;
+void QGeoAreaMonitorPolling::positionError(const QGeoPositionInfoSource::Error error)
+{
+ switch (error) {
+ case QGeoPositionInfoSource::AccessError:
+ lastError = QGeoAreaMonitorSource::AccessError;
+ break;
+ case QGeoPositionInfoSource::UnknownSourceError:
+ lastError = QGeoAreaMonitorSource::UnknownSourceError;
+ break;
+ case QGeoPositionInfoSource::ClosedError:
+ lastError = QGeoAreaMonitorSource::InsufficientPositionInfo;
+ break;
}
+
+ emit QGeoAreaMonitorSource::error(lastError);
+}
+
+void QGeoAreaMonitorPolling::timeout(const QGeoAreaMonitorInfo& monitor)
+{
+ if (isSignalConnected(monitorExpiredSignal()))
+ emit monitorExpired(monitor);
+}
+
+void QGeoAreaMonitorPolling::processAreaEvent(const QGeoAreaMonitorInfo &minfo,
+ const QGeoPositionInfo &pinfo, bool isEnteredEvent)
+{
+ if (isEnteredEvent)
+ emit areaEntered(minfo, pinfo);
+ else
+ emit areaExited(minfo, pinfo);
}
+#include "qgeoareamonitor_polling.moc"
#include "moc_qgeoareamonitor_polling.cpp"
diff --git a/src/plugins/position/positionpoll/qgeoareamonitor_polling.h b/src/plugins/position/positionpoll/qgeoareamonitor_polling.h
index a94e4e40..f25cd685 100644
--- a/src/plugins/position/positionpoll/qgeoareamonitor_polling.h
+++ b/src/plugins/position/positionpoll/qgeoareamonitor_polling.h
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
@@ -42,37 +42,55 @@
#ifndef QGEOAREAMONITORPOLLING_H
#define QGEOAREAMONITORPOLLING_H
-#include "qgeoareamonitor.h"
-#include "qgeopositioninfosource.h"
+#include <qgeoareamonitorsource.h>
+#include <qgeopositioninfosource.h>
/**
* QGeoAreaMonitorPolling
*
*/
-class QGeoAreaMonitorPolling : public QGeoAreaMonitor
+
+class QGeoAreaMonitorPollingPrivate;
+class QGeoAreaMonitorPolling : public QGeoAreaMonitorSource
{
Q_OBJECT
-
public :
explicit QGeoAreaMonitorPolling(QObject *parent = 0);
~QGeoAreaMonitorPolling();
- void setCenter(const QGeoCoordinate &coordinate);
- void setRadius(qreal radius);
- inline bool isValid() { return location; }
+ void setPositionInfoSource(QGeoPositionInfoSource *source) Q_DECL_OVERRIDE;
+ QGeoPositionInfoSource* positionInfoSource() const Q_DECL_OVERRIDE;
+
+ Error error() const Q_DECL_OVERRIDE;
+
+ bool startMonitoring(const QGeoAreaMonitorInfo &monitor) Q_DECL_OVERRIDE;
+ bool requestUpdate(const QGeoAreaMonitorInfo &monitor,
+ const char *signal) Q_DECL_OVERRIDE;
+ bool stopMonitoring(const QGeoAreaMonitorInfo &monitor) Q_DECL_OVERRIDE;
+
+ QList<QGeoAreaMonitorInfo> activeMonitors() const Q_DECL_OVERRIDE;
+ QList<QGeoAreaMonitorInfo> activeMonitors(const QGeoShape &region) const Q_DECL_OVERRIDE;
+
+ QGeoAreaMonitorSource::AreaMonitorFeatures supportedAreaMonitorFeatures() const Q_DECL_OVERRIDE;
+
+ inline bool isValid() { return positionInfoSource(); }
+
+ bool signalsAreConnected;
private Q_SLOTS:
- void positionUpdated(const QGeoPositionInfo &info);
+ void positionError(QGeoPositionInfoSource::Error error);
+ void timeout(const QGeoAreaMonitorInfo &monitor);
+ void processAreaEvent(const QGeoAreaMonitorInfo &minfo, const QGeoPositionInfo &pinfo, bool isEnteredEvent);
private:
- bool insideArea;
- QGeoPositionInfoSource *location;
+ QGeoAreaMonitorPollingPrivate* d;
+ QGeoAreaMonitorSource::Error lastError;
void connectNotify(const QMetaMethod &signal);
void disconnectNotify(const QMetaMethod &signal);
- void checkStartStop();
+ int idForSignal(const char *signal);
};
#endif // QGEOAREAMONITORPOLLING_H
diff --git a/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp
index efdb65b4..1d737e24 100644
--- a/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp
+++ b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.cpp
@@ -56,7 +56,7 @@ QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactorySimulator::satelliteInfoSo
return src;
}
-QGeoAreaMonitor *QGeoPositionInfoSourceFactorySimulator::areaMonitor(QObject *parent)
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySimulator::areaMonitor(QObject *parent)
{
Q_UNUSED(parent);
return 0;
diff --git a/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h
index 42dadf77..e31a7e01 100644
--- a/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h
+++ b/src/plugins/position/simulator/qgeopositioninfosourcefactory_simulator.h
@@ -57,7 +57,7 @@ class QGeoPositionInfoSourceFactorySimulator : public QObject, public QGeoPositi
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent);
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
- QGeoAreaMonitor *areaMonitor(QObject *parent);
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent);
};
#endif // QGEOPOSITIONINFOSOURCEFACTORY_SIMULATOR_H
diff --git a/src/positioning/doc/snippets/cpp/cppqml.cpp b/src/positioning/doc/snippets/cpp/cppqml.cpp
index 5ab23513..95d34b7c 100644
--- a/src/positioning/doc/snippets/cpp/cppqml.cpp
+++ b/src/positioning/doc/snippets/cpp/cppqml.cpp
@@ -39,9 +39,12 @@
****************************************************************************/
#include <QtCore/QObject>
+#include <QtCore/QDebug>
#include <QtCore/QVariant>
#include <QtPositioning/QGeoAddress>
#include <QtPositioning/QGeoLocation>
+#include <QtPositioning/QGeoCircle>
+#include <QtPositioning/QGeoAreaMonitorSource>
void cppQmlInterface(QObject *qmlObject)
{
@@ -62,3 +65,40 @@ void cppQmlInterface(QObject *qmlObject)
//! [Location set]
}
+class MyClass : public QObject
+{
+ Q_OBJECT
+//! [BigBen]
+public:
+ MyClass() : QObject()
+ {
+ QGeoAreaMonitorSource *monitor = QGeoAreaMonitorSource::createDefaultMonitorSource(this);
+ if (monitor) {
+ connect(monitor, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)),
+ this, SLOT(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo));
+ connect(monitor, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)),
+ this, SLOT(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+
+ QGeoAreaMonitorInfo bigBen("Big Ben");
+ QGeoCoordinate position(51.50104, -0.124632);
+ bigBen.setMonitoredArea(QGeoCircle(position, 100));
+
+ monitor->startMonitoring(bigBen);
+
+ } else {
+ qDebug() << "Could not create default area monitor";
+ }
+ }
+
+public Q_SLOTS:
+ void areaEntered(const QGeoAreaMonitorInfo &mon, const QGeoPositionInfo &update)
+ {
+ qDebug() << "Now within 100 meters, current position is" << update.coordinate();
+ }
+
+ void areaExited(const QGeoAreaMonitorInfo &mon, const QGeoPositionInfo &update)
+ {
+ qDebug() << "No longer within 100 meters, current position is" << update.coordinate();
+ }
+//! [BigBen]
+};
diff --git a/src/positioning/doc/src/cpp-position.qdoc b/src/positioning/doc/src/cpp-position.qdoc
index 75c2e30e..16fceea5 100644
--- a/src/positioning/doc/src/cpp-position.qdoc
+++ b/src/positioning/doc/src/cpp-position.qdoc
@@ -84,10 +84,10 @@ the platform.
If a problem occurs with access to the information source then an
\l {QGeoPositionInfoSource::error()}{error()} signal is emitted.
-The QGeoAreaMonitor class enables client applications to be notified when
+The QGeoAreaMonitorSource class enables client applications to be notified when
the receiving device has moved in or out of a particular area, as specified
by a coordinate and radius. If the platform provides built-in support for
-area monitoring, QGeoAreaMonitor::createDefaultMonitor() returns an instance of
+area monitoring, QGeoAreaMonitorSource::createDefaultMonitor() returns an instance of
the default area monitor.
Satellite information can also be distributed through the
diff --git a/src/positioning/doc/src/qtpositioning-plugins.qdoc b/src/positioning/doc/src/qtpositioning-plugins.qdoc
index 1ed1be1a..5873aadd 100644
--- a/src/positioning/doc/src/qtpositioning-plugins.qdoc
+++ b/src/positioning/doc/src/qtpositioning-plugins.qdoc
@@ -61,7 +61,7 @@ The entries have the following meaning:
\li Set to \c true if the plugin implements a \l QGeoSatelliteInfoSource.
\row
\li Monitor
- \li Set to \c true if the plugin implements a \l QGeoAreaMonitor.
+ \li Set to \c true if the plugin implements a \l QGeoAreaMonitorSource.
\row
\li Priority
\li The plugin priority. If multiple plugins have the same provider name, the plugin
diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro
index da1186bf..296356d0 100644
--- a/src/positioning/positioning.pro
+++ b/src/positioning/positioning.pro
@@ -8,7 +8,8 @@ OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator
PUBLIC_HEADERS += \
qgeoaddress.h \
- qgeoareamonitor.h \
+ qgeoareamonitorinfo.h \
+ qgeoareamonitorsource.h \
qgeoshape.h \
qgeorectangle.h \
qgeocircle.h \
@@ -37,7 +38,8 @@ PRIVATE_HEADERS += \
SOURCES += \
qgeoaddress.cpp \
- qgeoareamonitor.cpp \
+ qgeoareamonitorsource.cpp \
+ qgeoareamonitorinfo.cpp \
qgeoshape.cpp \
qgeorectangle.cpp \
qgeocircle.cpp \
diff --git a/src/positioning/qgeoareamonitor.cpp b/src/positioning/qgeoareamonitor.cpp
deleted file mode 100644
index 5ad69e9a..00000000
--- a/src/positioning/qgeoareamonitor.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtPositioning module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include <qgeoareamonitor.h>
-#include "qgeopositioninfosourcefactory.h"
-#include "qgeopositioninfosource_p.h"
-
-/*!
- \class QGeoAreaMonitor
- \inmodule QtPositioning
- \ingroup QtPositioning-positioning
- \since Qt Positioning 5.0
-
- \brief The QGeoAreaMonitor class enables the detection of proximity
- changes for a specified set of coordinates.
-
- A QGeoAreaMonitor emits signals when the current position is in
- range, or has moved out of range, of a specified circular area.
- The area is specified by a coordinate (the center point) and a
- radius (in meters).
-
- For example:
-
- \code
- public:
- MyClass::MyClass()
- {
- QGeoAreaMonitor *monitor = QGeoAreaMonitor::createDefaultMonitor();
- if (monitor) {
- connect(monitor, SIGNAL(areaEntered(QGeoPositionInfo)),
- this, SLOT(areaEntered(QGeoPositionInfo)));
- connect(monitor, SIGNAL(areaExited(QGeoPositionInfo)),
- this, SLOT(areaExited(QGeoPositionInfo)));
-
- QGeoCoordinate bigBenLocation(51.50104, -0.124632);
- monitor->setCenter(bigBenLocation);
- monitor->setRadius(100);
- } else {
- qDebug() << "Could not create default area monitor";
- }
- }
-
- public Q_SLOTS:
- void areaEntered(const QGeoPositionInfo &update)
- {
- qDebug() << "Now within 100 meters, current position is" << update.coordinate();
- }
-
- void areaExited(const QGeoPositionInfo &update)
- {
- qDebug() << "No longer within 100 meters, current position is" << update.coordinate();
- }
- \endcode
-*/
-
-QT_BEGIN_NAMESPACE
-
-class QGeoAreaMonitorPrivate
-{
-public:
- QGeoCoordinate coord;
- qreal radius;
-};
-
-
-/*!
- Creates a monitor with the given \a parent.
-*/
-QGeoAreaMonitor::QGeoAreaMonitor(QObject *parent)
- : QObject(parent),
- d(new QGeoAreaMonitorPrivate)
-{
- d->radius = qreal(0.0);
-}
-
-/*!
- Destroys the monitor.
-*/
-QGeoAreaMonitor::~QGeoAreaMonitor()
-{
- delete d;
-}
-
-/*!
- \property QGeoAreaMonitor::center
- \brief holds the center of the area to be monitored.
-
- When the center is set, if the radius has already been set and
- the current position is within the monitored area, areaEntered()
- is emitted immediately.
-
- By default, contains an invalid coordinate.
-
- Note: Subclass implementations must call the base implementation of
- setCenter() so that center() returns the correct value.
-*/
-void QGeoAreaMonitor::setCenter(const QGeoCoordinate &coordinate)
-{
- d->coord = coordinate;
-}
-
-QGeoCoordinate QGeoAreaMonitor::center() const
-{
- return d->coord;
-}
-
-/*!
- \property QGeoAreaMonitor::radius
- \brief holds the radius of the area to be monitored, in meters.
-
- If the specified radius is less than the minimum supported radius, the
- radius is set to the minimum radius.
-
- When this property is set, if the center coordinate has already been set and
- the current position is within the monitored area, areaEntered()
- is emitted immediately.
-
- By default, this property is 0.
-
- Note: Subclass implementations must call the base implementation of
- setRadius() so that radius() returns the correct value.
-*/
-void QGeoAreaMonitor::setRadius(qreal radius)
-{
- d->radius = radius;
-}
-
-qreal QGeoAreaMonitor::radius() const
-{
- return d->radius;
-}
-
-/*!
- Creates and returns a monitor with the given \a parent that
- monitors areas using resources on the underlying system.
-
- Returns 0 if the system has no support for position monitoring.
-*/
-QGeoAreaMonitor *QGeoAreaMonitor::createDefaultMonitor(QObject *parent)
-{
- QList<QJsonObject> plugins = QGeoPositionInfoSourcePrivate::pluginsSorted();
- foreach (const QJsonObject &obj, plugins) {
- if (obj.value(QStringLiteral("Monitor")).isBool()
- && obj.value(QStringLiteral("Monitor")).toBool())
- {
- QGeoPositionInfoSourcePrivate d;
- d.metaData = obj;
- d.loadPlugin();
- QGeoAreaMonitor *s = 0;
- if (d.factory)
- s = d.factory->areaMonitor(parent);
- return s;
- }
- }
-
- return 0;
-}
-
-/*!
- Creates and returns a monitor with the given \a parent,
- by loading the plugin named \a sourceName.
-
- Returns 0 if the plugin cannot be found.
-*/
-QGeoAreaMonitor *QGeoAreaMonitor::createMonitor(const QString &sourceName, QObject *parent)
-{
- QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins();
- if (plugins.contains(sourceName)) {
- QGeoPositionInfoSourcePrivate d;
- d.metaData = plugins.value(sourceName);
- d.loadPlugin();
- QGeoAreaMonitor *s = 0;
- if (d.factory)
- s = d.factory->areaMonitor(parent);
- return s;
- }
-
- return 0;
-}
-
-/*!
- Returns a list of available monitor plugins, including the default system
- backend if one is available.
-*/
-QStringList QGeoAreaMonitor::availableMonitors()
-{
- QStringList plugins;
- QHash<QString, QJsonObject> meta = QGeoPositionInfoSourcePrivate::plugins();
- foreach (const QString &name, meta.keys()) {
- if (meta.value(name).value(QStringLiteral("Monitor")).isBool()
- && meta.value(name).value(QStringLiteral("Monitor")).toBool()) {
- plugins << name;
- }
- }
-
- return plugins;
-}
-
-
-
-/*!
- \fn void QGeoAreaMonitor::areaEntered(const QGeoPositionInfo &update);
-
- Emitted when the current position has moved from a position outside the
- monitored area to a position within the monitored area.
-
- The \a update holds the new position.
-*/
-
-/*!
- \fn void QGeoAreaMonitor::areaExited(const QGeoPositionInfo &update);
-
- Emitted when the current position has moved from a position within the
- monitored area to a position outside the monitored area.
-
- The \a update holds the new position.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/positioning/qgeoareamonitorinfo.cpp b/src/positioning/qgeoareamonitorinfo.cpp
new file mode 100644
index 00000000..b4e0d179
--- /dev/null
+++ b/src/positioning/qgeoareamonitorinfo.cpp
@@ -0,0 +1,379 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGeoAreaMonitorInfo>
+#include <QDateTime>
+#include <QSharedData>
+#include <QUuid>
+
+#ifndef QT_NO_DEBUG_STREAM
+#include <QDebug>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGeoAreaMonitorInfo
+ \inmodule QtPositioning
+ \since Qt Positioning 5.2
+ \ingroup QtPositioning-positioning
+
+ \brief The QGeoAreaMonitorInfo class describes the parameters of an area or region
+ to be monitored for proximity.
+
+ The purpose of area monitoring is to inform a user when he/she comes close to an area of
+ interest. In general such an area is described by a \l QGeoCircle. The circle's center
+ represents the place of interest and the area around it identifies the geographical region
+ within which notifications are sent.
+
+ A QGeoAreaMonitorInfo object is valid if it has a non-empty name and a valid \l area().
+ Such objects must be registered with a \l QGeoAreaMonitorSource to start and stop the
+ monitoring process. Note that extensive monitoring can be very resource consuming
+ because the positioning engine must remain active and has to match the current position
+ with each QGeoAreaMonitorInfo instance.
+
+ To further reduce the burden on the system there are optional attributes which can
+ set. Each monitored area can have an expiry date which automatically removes the
+ to-be-monitored area from the monitoring source once the expiry date has been reached.
+ Another option is to adjust the persistence of a monitored area. A QGeoAreaMonitorInfo
+ that \l isPersistent() will remain active beyond
+ the current applications lifetime. If an area is entered while the monitoring
+ application is not running the application will be started. Note that this feature is
+ not available on all platforms. Its availability can be checked via
+ \l QGeoAreaMonitorSource::supportedAreaMonitorFeatures().
+
+ \sa QGeoAreaMonitorSource
+
+ */
+
+class QGeoAreaMonitorInfoPrivate : public QSharedData
+{
+public:
+ QGeoAreaMonitorInfoPrivate() : QSharedData(), persistent(false) {}
+ QGeoAreaMonitorInfoPrivate(const QGeoAreaMonitorInfoPrivate &other)
+ : QSharedData(other)
+ {
+ uid = other.uid;
+ name = other.name;
+ shape = other.shape;
+ persistent = other.persistent;
+ notificationParameters = other.notificationParameters;
+ expiry = other.expiry;
+ }
+ ~QGeoAreaMonitorInfoPrivate() {}
+
+ QUuid uid;
+ QString name;
+ QGeoShape shape;
+ bool persistent;
+ QVariantMap notificationParameters;
+ QDateTime expiry;
+};
+
+/*!
+ Constructs a QGeoAreaMonitorInfo object with the specified \a name.
+
+ \sa name()
+ */
+QGeoAreaMonitorInfo::QGeoAreaMonitorInfo(const QString &name)
+{
+ d = new QGeoAreaMonitorInfoPrivate;
+ d->name = name;
+ d->uid = QUuid::createUuid();
+}
+
+/*!
+ Constructs a QGeoAreaMonitorInfo object as a copy of \a other.
+ */
+QGeoAreaMonitorInfo::QGeoAreaMonitorInfo(const QGeoAreaMonitorInfo &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Destructor
+ */
+QGeoAreaMonitorInfo::~QGeoAreaMonitorInfo()
+{
+}
+
+/*!
+ Assigns \a other to this QGeoAreaMonitorInfo object and returns a reference
+ to this QGeoAreaMonitorInfo object.
+ */
+QGeoAreaMonitorInfo &QGeoAreaMonitorInfo::operator=(const QGeoAreaMonitorInfo &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if all of this object's values are the same as those of
+ \a other.
+*/
+bool QGeoAreaMonitorInfo::operator==(const QGeoAreaMonitorInfo &other) const
+{
+ return (d->name == other.d->name &&
+ d->uid == other.d->uid &&
+ d->shape == other.d->shape &&
+ d->persistent == other.d->persistent &&
+ d->expiry == other.d->expiry &&
+ d->notificationParameters == other.d->notificationParameters);
+}
+
+/*!
+ Returns true if any of this object's values are not the same as those of
+ \a other.
+*/
+bool QGeoAreaMonitorInfo::operator!=(const QGeoAreaMonitorInfo &other) const
+{
+ return !QGeoAreaMonitorInfo::operator ==(other);
+}
+
+/*!
+ Returns the name of the QGeoAreaMonitorInfo object. The name should be used to
+ for user-visibility purposes.
+ */
+QString QGeoAreaMonitorInfo::name() const
+{
+ return d->name;
+}
+
+/*!
+ Sets the user visibile \a name.
+ */
+void QGeoAreaMonitorInfo::setName(const QString &name)
+{
+ if (d->name != name)
+ d->name = name;
+}
+
+/*!
+ Returns the identifier of the QGeoAreaMonitorInfo object.
+ The identifier is automatically generated upon construction of a new
+ QGeoAreaMonitorInfo object.
+*/
+
+QString QGeoAreaMonitorInfo::identifier() const
+{
+ return d->uid.toString();
+}
+
+/*!
+ Returns true, if the monitor is valid. A valid QGeoAreaMonitorInfo has a non-empty name()
+ and the monitored area is not \l {QGeoShape::isEmpty()}{empty()}.
+ Otherwise this function returns false.
+ */
+bool QGeoAreaMonitorInfo::isValid() const
+{
+ return (!d->name.isEmpty() && !d->shape.isEmpty());
+}
+
+/*!
+ Returns the boundaries of the to-be-monitored area. This area must not be empty.
+
+ \sa setArea()
+ */
+QGeoShape QGeoAreaMonitorInfo::area() const
+{
+ return d->shape;
+}
+
+/*!
+ Sets the to-be-monitored area to \a newShape.
+
+ \sa area()
+ */
+void QGeoAreaMonitorInfo::setArea(const QGeoShape &newShape)
+{
+ d->shape = newShape;
+}
+
+/*!
+ Returns the expiry date.
+
+ After an active QGeoAreaMonitorInfo has expired the region is no longer monitored
+ and the QGeoAreaMonitorInfo object is removed from the list of
+ \l {QGeoAreaMonitorSource::activeMonitors()}{active monitors}.
+
+ If the expiry \l QDateTime is invalid the QGeoAreaMonitorInfo object is treated as not having
+ an expiry date. This implies an indefinite monitoring period if the object is persistent or
+ until the current application closes if the object is non-persistent.
+
+ \sa QGeoAreaMonitorSource::activeMonitors()
+ */
+QDateTime QGeoAreaMonitorInfo::expiration() const
+{
+ return d->expiry;
+}
+
+/*!
+ Sets the expiry date and time to \a expiry.
+ */
+void QGeoAreaMonitorInfo::setExpiration(const QDateTime &expiry)
+{
+ d->expiry = expiry;
+}
+
+/*!
+ Returns true if the QGeoAreaMonitorInfo is persistent.
+ The default value for this property is false.
+
+ A non-persistent QGeoAreaMonitorInfo will be removed by the system once
+ the application owning the monitor object stops. Persistent objects remain
+ active and can be retrieved once the application restarts.
+
+ If the system triggers an event associated to a persistent QGeoAreaMonitorInfo
+ the relevant application will be re-started and the appropriate signal emitted.
+
+ \sa setPersistent()
+ */
+bool QGeoAreaMonitorInfo::isPersistent() const
+{
+ return d->persistent;
+}
+
+/*!
+ Sets the QGeoAreaMonitorInfo objects persistence to \a isPersistent.
+
+ Note that setting this flag does not imply that QGeoAreaMonitorInfoSource supports persistent
+ monitoring. \l QGeoAreaMonitorSource::supportedAreaMonitorFeatures() can be used to
+ check for this feature's availability.
+
+ \sa isPersistent()
+ */
+void QGeoAreaMonitorInfo::setPersistent(bool isPersistent)
+{
+ d->persistent = isPersistent;
+}
+
+
+/*!
+ Returns the set of platform specific paraemters used by this QGeoAreaMonitorInfo.
+
+ \sa setNotificationParameters()
+ */
+QVariantMap QGeoAreaMonitorInfo::notificationParameters() const
+{
+ return d->notificationParameters;
+}
+
+/*!
+ Sets the set of platform specific \a parameters used by QGeoAreaMonitorInfo.
+
+ \sa notificationParameters()
+ */
+void QGeoAreaMonitorInfo::setNotificationParameters(const QVariantMap &parameters)
+{
+ d->notificationParameters = parameters;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &stream, const QGeoAreaMonitorInfo &monitor)
+ \relates QGeoAreaMonitorInfo
+
+ Writes the given \a monitor to the specified \a stream.
+
+ \sa {Serializing Qt Data Types}
+*/
+QDataStream &operator<<(QDataStream &ds, const QGeoAreaMonitorInfo &monitor)
+{
+ ds << monitor.name() << monitor.d->uid << monitor.area()
+ << monitor.isPersistent() << monitor.notificationParameters() << monitor.expiration();
+ return ds;
+}
+
+/*!
+ \fn QDataStream &operator>>(QDataStream &stream, QGeoAreaMonitorInfo &monitor)
+ \relates QGeoAreaMonitorInfo
+
+ Reads a area monitoring data from the specified \a stream into the given
+ \a monitor.
+
+ \sa {Serializing Qt Data Types}
+*/
+
+QDataStream &operator>>(QDataStream &ds, QGeoAreaMonitorInfo &monitor)
+{
+ QString s;
+ ds >> s;
+ monitor = QGeoAreaMonitorInfo(s);
+
+ QUuid id;
+ ds >> id;
+ monitor.d->uid = id;
+
+ QGeoShape shape;
+ ds >> shape;
+ monitor.setArea(shape);
+
+ bool persistent;
+ ds >> persistent;
+ monitor.setPersistent(persistent);
+
+ QVariantMap map;
+ ds >> map;
+ monitor.setNotificationParameters(map);
+
+ QDateTime dt;
+ ds >> dt;
+ monitor.setExpiration(dt);
+
+ return ds;
+}
+
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QGeoAreaMonitorInfo &monitor)
+{
+ dbg.nospace() << "QGeoAreaMonitorInfo(\"" << qPrintable(monitor.name())
+ << "\", " << monitor.area()
+ << ", persistent: " << monitor.isPersistent()
+ << ", expiry: " << monitor.expiration() << ")";
+ return dbg.space();
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/positioning/qgeoareamonitorinfo.h b/src/positioning/qgeoareamonitorinfo.h
new file mode 100644
index 00000000..938671df
--- /dev/null
+++ b/src/positioning/qgeoareamonitorinfo.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOAREAMONITORINFO_H
+#define QGEOAREAMONITORINFO_H
+
+#include <QtPositioning/QGeoCoordinate>
+#include <QtPositioning/QGeoShape>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QVariantMap>
+
+QT_BEGIN_NAMESPACE
+
+class QDataStream;
+class QGeoAreaMonitorInfo;
+
+#ifndef QT_NO_DATASTREAM
+Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &, const QGeoAreaMonitorInfo &);
+Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &, QGeoAreaMonitorInfo &);
+#endif
+
+class QGeoAreaMonitorInfoPrivate;
+class Q_POSITIONING_EXPORT QGeoAreaMonitorInfo
+{
+public:
+ explicit QGeoAreaMonitorInfo(const QString &name = QString());
+ QGeoAreaMonitorInfo(const QGeoAreaMonitorInfo &other);
+ ~QGeoAreaMonitorInfo();
+
+ QGeoAreaMonitorInfo &operator=(const QGeoAreaMonitorInfo &other);
+
+ bool operator==(const QGeoAreaMonitorInfo &other) const;
+ bool operator!=(const QGeoAreaMonitorInfo &other) const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString identifier() const;
+ bool isValid() const;
+
+ QGeoShape area() const;
+ void setArea(const QGeoShape &newShape);
+
+ QDateTime expiration() const;
+ void setExpiration(const QDateTime &expiry);
+
+ bool isPersistent() const;
+ void setPersistent(bool isPersistent);
+
+ QVariantMap notificationParameters() const;
+ void setNotificationParameters(const QVariantMap &parameters);
+private:
+ QSharedDataPointer<QGeoAreaMonitorInfoPrivate> d;
+
+#ifndef QT_NO_DATASTREAM
+ friend Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &, const QGeoAreaMonitorInfo &);
+ friend Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &, QGeoAreaMonitorInfo &);
+#endif
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_POSITIONING_EXPORT QDebug operator<<(QDebug, const QGeoAreaMonitorInfo &);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QGEOAREAMONITORINFO_H
diff --git a/src/positioning/qgeoareamonitorsource.cpp b/src/positioning/qgeoareamonitorsource.cpp
new file mode 100644
index 00000000..2f23d942
--- /dev/null
+++ b/src/positioning/qgeoareamonitorsource.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGeoAreaMonitorSource>
+#include "qgeopositioninfosourcefactory.h"
+#include "qgeopositioninfosource_p.h"
+
+/*!
+ \class QGeoAreaMonitorSource
+ \inmodule QtPositioning
+ \ingroup QtPositioning-positioning
+ \since Qt Positioning 5.0
+
+ \brief The QGeoAreaMonitorSource class enables the detection of proximity
+ changes for a specified set of coordinates.
+
+ A QGeoAreaMonitorSource emits signals when the current position is in
+ range, or has moved out of range, of a specified area.
+ Each area is specified by a \l QGeoAreaMonitorInfo object.
+ For example:
+
+ \snippet cpp/cppqml.cpp BigBen
+
+ \c QGeoAreaMonitorSource follows a singleton pattern. Each instance of
+ the class with the same \l sourceName() shares the same area monitoring backend.
+ If a new \l QGeoAreaMonitorInfo object is added via \l startMonitoring()
+ or \l requestUpdate() it can be retrieved by another instance of this class
+ (provided that they are sourced from the same area monitor provider plug-in).
+ The same singleton pattern applies to the \l QGeoPositionInfoSource instance
+ used by this class. The following code snippet emphasizes the behavior:
+
+ \code
+ QGeoAreaMonitorSource *s1 = QGeoAreaMonitorSource::createSource("blah", this);
+ QGeoAreaMonitorSource *s2 = QGeoAreaMonitorSource::createSource("blah", this);
+ QVERIFY(s1->positionInfoSource() == s2->positionInfoSource);
+ \endcode
+*/
+
+QT_BEGIN_NAMESPACE
+
+
+
+class QGeoAreaMonitorSourcePrivate
+{
+public:
+ QGeoPositionInfoSource *source;
+ QString providerName;
+};
+
+/*!
+ \enum QGeoAreaMonitorSource::Error
+ Defines the types of positioning methods.
+
+ The Error enumeration represents the errors which can occur.
+
+ \value AccessError The connection setup to the remote area monitoring backend failed because the
+ application lacked the required privileges.
+ \value InsufficientPositionInfo The area monitoring source could not retrieve a location fix or
+ the accuracy of the fix is not high enough to provide an effective area monitoring.
+ \value UnknownSourceError An unidentified error occurred.
+*/
+
+/*!
+ \enum QGeoAreaMonitorSource::AreaMonitorFeature
+ Defines the types of area monitoring capabilities.
+
+ \value PersistentAreaMonitorFeature QGeoAreaMonitorInfo instances can be made persistent.
+ A persistent monitor continues to be active even when the application managing the monitor is
+ not running.
+ \value AnyAreaMonitorFeature Matches all possible area monitoring features.
+*/
+
+/*!
+ \fn virtual AreaMonitoringFeatures QGeoAreaMonitorSource::supportedAreaMonitorFeatures() const = 0;
+
+ Returns the area monitoring features available to this source.
+*/
+
+/*!
+ \fn virtual QGeoAreaMonitorSource::Error QGeoAreaMonitorSource::error() const
+
+ Returns the type of error that last occurred.
+*/
+
+/*!
+ Creates a monitor with the given \a parent.
+*/
+QGeoAreaMonitorSource::QGeoAreaMonitorSource(QObject *parent)
+ : QObject(parent),
+ d(new QGeoAreaMonitorSourcePrivate)
+{
+ d->source = 0;
+}
+
+/*!
+ Destroys the monitor.
+*/
+QGeoAreaMonitorSource::~QGeoAreaMonitorSource()
+{
+ delete d;
+}
+
+/*!
+ Creates and returns a monitor with the given \a parent that
+ monitors areas using resources on the underlying system.
+
+ Returns 0 if the system has no support for position monitoring.
+*/
+QGeoAreaMonitorSource *QGeoAreaMonitorSource::createDefaultSource(QObject *parent)
+{
+ QList<QJsonObject> plugins = QGeoPositionInfoSourcePrivate::pluginsSorted();
+ foreach (const QJsonObject &obj, plugins) {
+ if (obj.value(QStringLiteral("Monitor")).isBool()
+ && obj.value(QStringLiteral("Monitor")).toBool())
+ {
+ QGeoPositionInfoSourcePrivate d;
+ d.metaData = obj;
+ d.loadPlugin();
+ QGeoAreaMonitorSource *s = 0;
+ if (d.factory)
+ s = d.factory->areaMonitor(parent);
+ if (s)
+ s->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString();
+ return s;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ Creates and returns a monitor with the given \a parent,
+ by loading the plugin named \a sourceName.
+
+ Returns 0 if the plugin cannot be found.
+*/
+QGeoAreaMonitorSource *QGeoAreaMonitorSource::createSource(const QString &sourceName, QObject *parent)
+{
+ QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins();
+ if (plugins.contains(sourceName)) {
+ QGeoPositionInfoSourcePrivate d;
+ d.metaData = plugins.value(sourceName);
+ d.loadPlugin();
+ QGeoAreaMonitorSource *s = 0;
+ if (d.factory)
+ s = d.factory->areaMonitor(parent);
+ if (s)
+ s->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString();
+ return s;
+ }
+
+ return 0;
+}
+
+/*!
+ Returns a list of available monitor plugins, including the default system
+ backend if one is available.
+*/
+QStringList QGeoAreaMonitorSource::availableSources()
+{
+ QStringList plugins;
+ QHash<QString, QJsonObject> meta = QGeoPositionInfoSourcePrivate::plugins();
+ foreach (const QString &name, meta.keys()) {
+ if (meta.value(name).value(QStringLiteral("Monitor")).isBool()
+ && meta.value(name).value(QStringLiteral("Monitor")).toBool()) {
+ plugins << name;
+ }
+ }
+
+ return plugins;
+}
+
+/*!
+ Returns the unique name of the area monitor source implementation in use.
+
+ This is the same name that can be passed to createSource() in order to
+ create a new instance of a particular area monitor source implementation.
+*/
+QString QGeoAreaMonitorSource::sourceName() const
+{
+ return d->providerName;
+}
+
+/*!
+ Returns the current QGeoPositionInfoSource used by this QGeoAreaMonitorSource
+ object. The function will return \l QGeoPositionInfoSource::createDefaultSource()
+ if no other object has been set.
+
+ The function returns 0 if not even a default QGeoPositionInfoSource exists.
+
+ Any usage of the returned \l QGeoPositionInfoSource instance should account
+ for the fact that it may reside in a different thread.
+
+ \sa QGeoPositionInfoSource, setPositionInfoSource()
+*/
+QGeoPositionInfoSource* QGeoAreaMonitorSource::positionInfoSource() const
+{
+ return d->source;
+}
+
+/*!
+ Sets the new \l QGeoPositionInfoSource to be used by this QGeoAreaMonitorSource object.
+ The area monitoring backend becomes the new QObject parent for \a newSource.
+ The previous \l QGeoPositionInfoSource object will be deleted. All QGeoAreaMonitorSource
+ instances based on the same \l sourceName() share the same QGeoPositionInfoSource
+ instance.
+
+ This may be useful when it is desirable to manipulate the positioning system
+ used by the area monitoring engine.
+
+ Note that ownership must be taken care of by subclasses of QGeoAreaMonitorSource.
+ Due to the singleton pattern behind this class \a newSource may be moved to a
+ new thread.
+
+ \sa positionInfoSource()
+ */
+void QGeoAreaMonitorSource::setPositionInfoSource(QGeoPositionInfoSource *newSource)
+{
+ d->source = newSource;
+}
+
+
+/*!
+ \fn virtual bool QGeoAreaMonitorSource::startMonitoring(const QGeoAreaMonitorInfo &monitor)
+
+ Returns \c true if the monitoring of \a monitor could be successfully started; otherwise
+ returns false. A reason for not being able to start monitoring could be the unavailability
+ of an appropriate default position info source while no alternative QGeoPositionInfoSource
+ has been set via \l setPositionInfoSource().
+
+ If \a monitor is already active the existing monitor object will be replaced by the new \a monitor reference.
+ The identification of QGeoAreaMonitorInfo instances happens via \l QGeoAreaMonitorInfo::identifier().
+ Therefore this function can also be used to update active monitors.
+
+ If \a monitor has an expiry date that has been passed this function returns false. Calling
+ this function for an already via \l requestUpdate() registered single shot monitor
+ switches the monitor to a permanent monitoring mode.
+
+ Requesting persistent monitoring on a QGeoAreaMonitorSource instance fails if the area monitoring
+ backend doesn't support \l QGeoAreaMonitorSource::PersistentAreaMonitorFeature.
+
+ \sa stopMonitoring()
+*/
+
+/*!
+ \fn virtual bool QGeoAreaMonitorSource::requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal)
+
+ Enables single shot area monitoring. Area monitoring for \a monitor will be performed
+ until this QGeoAreaMonitorSource instance emits \a signal for the first time. Once
+ the signal was emitted, \a monitor is automatically removed from the list of \l activeMonitors().
+ If \a monitor is invalid or has an expiry date that has been passed this function returns false.
+
+ \code
+ QGeoAreaMonitor singleShotMonitor;
+ QGeoAreaMonitorSource * source = QGeoAreaMonitorSource::createDefaultSource(this);
+ //...
+ bool ret = source->requestUpdate(singleShotMonitor,
+ SIGNAL(areaExited(QGeoAreaMonitor,QGeoPositionInfo)));
+ \endcode
+
+ The above \c singleShotMonitor object will cease to send updates once the \l areaExited() signal
+ was emitted for the first time. Until this point in time any other signal may be emitted
+ zero or more times depending on the area context.
+
+ It is not possible to simultanously request updates for more than one signal of the same monitor object.
+ The last call to this function determines the signal upon which the updates cease to continue.
+ At this stage only the \l areaEntered() and \l areaExited() signals can be used to
+ terminate the monitoring process.
+
+ Requesting persistent monitoring on a QGeoAreaMonitorSource instance fails if the area monitoring
+ backend doesn't support \l QGeoAreaMonitorSource::PersistentAreaMonitorFeature.
+
+ If \a monitor was already registered via \l startMonitoring() it is converted to a single
+ shot behavior.
+
+ \sa startMonitoring(), stopMonitoring()
+ */
+
+/*!
+ \fn virtual bool QGeoAreaMonitorSource::stopMonitoring(const QGeoAreaMonitorInfo &monitor)
+
+ Returns true if \a monitor was successfully removed from the list of \l activeMonitors();
+ otherwise returns false. This behavior is independent on whether \a monitor was registered
+ via \l startMonitoring() or \l requestUpdate().
+*/
+
+/*!
+ \fn virtual QList<QGeoAreaMonitorInfo> QGeoAreaMonitorSource::activeMonitors() const
+
+ Returns the list of all active monitors known to the QGeoAreaMonitorSource object.
+
+ An active monitor was started via startMonitoring() the source object will emit
+ the required signals such as areaEntered() or areaExited(). Multiple \l QGeoAreaMonitorSource
+ instances within the same application share the same active monitor objects.
+
+ Unless an active QGeoAreaMonitorInfo \l {QGeoAreaMonitorInfo::isPersistent()}{isPersistent()} an active QGeoAreaMonitorInfo
+ will be stopped once the current application terminates.
+*/
+
+/*!
+ \fn virtual QList<QGeoAreaMonitorInfo> QGeoAreaMonitorSource::activeMonitors(const QGeoShape &lookupArea) const
+
+ Returns the list of all active monitors known to the QGeoAreaMonitorSource object whose
+ center lies within \a lookupArea. If \a lookupArea is empty the returned list will be empty.
+
+ An active monitor was started via startMonitoring() and the source object will emit
+ the required signals such as areaEntered() or areaExited(). Multiple QGeoAreaMonitorSource
+ instances within the same application share the same monitor objects.
+
+ Unless an active QGeoAreaMonitorInfo \l {QGeoAreaMonitorInfo::isPersistent()}{isPersistent()} an active QGeoAreaMonitorInfo
+ will be stopped once the current application terminates.
+
+ \sa QGeoShape
+*/
+
+
+/*!
+ \fn void QGeoAreaMonitorSource::monitorExpired(const QGeoAreaMonitorInfo &monitor)
+
+ Emitted when \a monitor has expired. An expired area monitor is automatically
+ removed from the list of \l activeMonitors().
+
+ \sa activeMonitors()
+*/
+
+/*!
+ \fn void QGeoAreaMonitorSource::areaEntered(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update)
+
+ Emitted when the current position has moved from a position outside of the active \a monitor
+ to a position within the monitored area.
+
+ The \a update holds the new position.
+*/
+
+/*!
+ \fn void QGeoAreaMonitorSource::areaExited(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update)
+
+ Emitted when the current position has moved from a position within the active \a monitor
+ to a position outside the monitored area.
+
+ The \a update holds the new position.
+*/
+
+/*!
+ \fn void QGeoAreaMonitorSource::error(QGeoAreaMonitorSource::Error areaMonitoringError)
+
+ This signal is emitted after an error occurred. The \a areaMonitoringError
+ parameter describes the type of error that occurred.
+
+*/
+
+QT_END_NAMESPACE
diff --git a/src/positioning/qgeoareamonitorsource.h b/src/positioning/qgeoareamonitorsource.h
new file mode 100644
index 00000000..03c98874
--- /dev/null
+++ b/src/positioning/qgeoareamonitorsource.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QGEOAREAMONITORSOURCE_H
+#define QGEOAREAMONITORSOURCE_H
+
+#include <QtPositioning/QGeoCoordinate>
+#include <QtPositioning/QGeoAreaMonitorInfo>
+#include <QtPositioning/QGeoPositionInfoSource>
+
+#include <QObject>
+#include <QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoPositionInfo;
+class QGeoAreaMonitorSourcePrivate;
+class Q_POSITIONING_EXPORT QGeoAreaMonitorSource : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum Error {
+ AccessError = 0,
+ InsufficientPositionInfo,
+ UnknownSourceError
+ };
+ Q_ENUMS(Error)
+
+ enum AreaMonitorFeature {
+ PersistentAreaMonitorFeature = 0x00000001,
+ AnyAreaMonitorFeature = 0xffffffff
+ };
+ Q_DECLARE_FLAGS(AreaMonitorFeatures, AreaMonitorFeature)
+
+ explicit QGeoAreaMonitorSource(QObject *parent);
+ virtual ~QGeoAreaMonitorSource();
+
+ static QGeoAreaMonitorSource *createDefaultSource(QObject *parent);
+ static QGeoAreaMonitorSource *createSource(const QString& sourceName, QObject *parent);
+ static QStringList availableSources();
+
+ virtual void setPositionInfoSource(QGeoPositionInfoSource *source);
+ virtual QGeoPositionInfoSource* positionInfoSource() const;
+
+ QString sourceName() const;
+
+ virtual Error error() const = 0;
+ virtual AreaMonitorFeatures supportedAreaMonitorFeatures() const = 0;
+
+ virtual bool startMonitoring(const QGeoAreaMonitorInfo &monitor) = 0;
+ virtual bool stopMonitoring(const QGeoAreaMonitorInfo &monitor) = 0;
+ virtual bool requestUpdate(const QGeoAreaMonitorInfo &monitor, const char *signal) = 0;
+
+ virtual QList<QGeoAreaMonitorInfo> activeMonitors() const = 0;
+ virtual QList<QGeoAreaMonitorInfo> activeMonitors(const QGeoShape &lookupArea) const = 0;
+
+Q_SIGNALS:
+ void areaEntered(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update);
+ void areaExited(const QGeoAreaMonitorInfo &monitor, const QGeoPositionInfo &update);
+ void monitorExpired(const QGeoAreaMonitorInfo &monitor);
+ void error(QGeoAreaMonitorSource::Error error);
+
+private:
+ Q_DISABLE_COPY(QGeoAreaMonitorSource)
+ QGeoAreaMonitorSourcePrivate *d;
+};
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/positioning/qgeopositioninfosourcefactory.cpp b/src/positioning/qgeopositioninfosourcefactory.cpp
index a113a4aa..bebbe20e 100644
--- a/src/positioning/qgeopositioninfosourcefactory.cpp
+++ b/src/positioning/qgeopositioninfosourcefactory.cpp
@@ -73,9 +73,9 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QGeoAreaMonitor *QGeoPositionInfoSourceFactory::areaMonitor(QObject *parent);
+ \fn QGeoAreaMonitorSource *QGeoPositionInfoSourceFactory::areaMonitor(QObject *parent);
- Returns a new QGeoAreaMonitor associated with this plugin with parent \a parent.
+ Returns a new QGeoAreaMonitorSource associated with this plugin with parent \a parent.
Can also return 0, in which case the plugin loader will use the factory with the
next highest priority.
*/
diff --git a/src/positioning/qgeopositioninfosourcefactory.h b/src/positioning/qgeopositioninfosourcefactory.h
index 32e0bc00..5704c2dc 100644
--- a/src/positioning/qgeopositioninfosourcefactory.h
+++ b/src/positioning/qgeopositioninfosourcefactory.h
@@ -44,7 +44,7 @@
#include <QtPositioning/QGeoPositionInfoSource>
#include <QtPositioning/QGeoSatelliteInfoSource>
-#include <QtPositioning/QGeoAreaMonitor>
+#include <QtPositioning/QGeoAreaMonitorSource>
#include <QList>
QT_BEGIN_NAMESPACE
@@ -56,7 +56,7 @@ public:
virtual QGeoPositionInfoSource *positionInfoSource(QObject *parent) = 0;
virtual QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent) = 0;
- virtual QGeoAreaMonitor *areaMonitor(QObject *parent) = 0;
+ virtual QGeoAreaMonitorSource *areaMonitor(QObject *parent) = 0;
};
#define QT_POSITION_SOURCE_INTERFACE
diff --git a/src/positioning/qgeosatelliteinfosource.cpp b/src/positioning/qgeosatelliteinfosource.cpp
index faf8dad8..ee1b316a 100644
--- a/src/positioning/qgeosatelliteinfosource.cpp
+++ b/src/positioning/qgeosatelliteinfosource.cpp
@@ -93,6 +93,7 @@ class QGeoSatelliteInfoSourcePrivate
{
public:
int interval;
+ QString providerName;
};
/*!
@@ -114,6 +115,18 @@ QGeoSatelliteInfoSource::~QGeoSatelliteInfoSource()
}
/*!
+ Returns the unique name of the satellite source implementation in use.
+
+ This is the same name that can be passed to createSource() in order to
+ create a new instance of a particular satellite source implementation.
+*/
+QString QGeoSatelliteInfoSource::sourceName() const
+{
+ return d->providerName;
+}
+
+
+/*!
\property QGeoSatelliteInfoSource::updateInterval
\brief This property holds the requested interval in milliseconds between each update.
@@ -168,6 +181,8 @@ QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(QObject *p
QGeoSatelliteInfoSource *s = 0;
if (d.factory)
s = d.factory->satelliteInfoSource(parent);
+ if (s)
+ s->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString();
return s;
}
}
@@ -191,6 +206,8 @@ QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &so
QGeoSatelliteInfoSource *src = 0;
if (d.factory)
src = d.factory->satelliteInfoSource(parent);
+ if (src)
+ src->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString();
return src;
}
diff --git a/src/positioning/qgeosatelliteinfosource.h b/src/positioning/qgeosatelliteinfosource.h
index 35aa2b33..2b25aec7 100644
--- a/src/positioning/qgeosatelliteinfosource.h
+++ b/src/positioning/qgeosatelliteinfosource.h
@@ -57,7 +57,7 @@ class Q_POSITIONING_EXPORT QGeoSatelliteInfoSource : public QObject
public:
enum Error {
- AccessError,
+ AccessError = 0,
ClosedError, /* 1 */
UnknownSourceError = -1
};
@@ -70,6 +70,8 @@ public:
static QGeoSatelliteInfoSource *createSource(const QString &sourceName, QObject *parent);
static QStringList availableSources();
+ QString sourceName() const;
+
virtual void setUpdateInterval(int msec);
int updateInterval() const;
virtual int minimumUpdateInterval() const = 0;
diff --git a/tests/auto/positionplugin/plugin.cpp b/tests/auto/positionplugin/plugin.cpp
index 26f8ed34..bfc4880b 100644
--- a/tests/auto/positionplugin/plugin.cpp
+++ b/tests/auto/positionplugin/plugin.cpp
@@ -190,7 +190,7 @@ class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInf
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent);
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
- QGeoAreaMonitor *areaMonitor(QObject *parent);
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent);
};
QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTest::positionInfoSource(QObject *parent)
@@ -205,7 +205,7 @@ QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTest::satelliteInfoSource(
return 0;
}
-QGeoAreaMonitor *QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject* parent)
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject* parent)
{
Q_UNUSED(parent)
return 0;
diff --git a/tests/auto/positionplugintest/tst_positionplugin.cpp b/tests/auto/positionplugintest/tst_positionplugin.cpp
index 384f7a80..f152e762 100644
--- a/tests/auto/positionplugintest/tst_positionplugin.cpp
+++ b/tests/auto/positionplugintest/tst_positionplugin.cpp
@@ -45,7 +45,7 @@
#include <QSignalSpy>
#include <qgeopositioninfosource.h>
#include <qgeosatelliteinfosource.h>
-#include <qgeoareamonitor.h>
+#include <qgeoareamonitorsource.h>
#include <qgeocoordinate.h>
QT_USE_NAMESPACE
@@ -78,7 +78,7 @@ void tst_PositionPlugin::availableSources()
{
QVERIFY(QGeoPositionInfoSource::availableSources().contains("test.source"));
QVERIFY(!QGeoSatelliteInfoSource::availableSources().contains("test.source"));
- QVERIFY(!QGeoAreaMonitor::availableMonitors().contains("test.source"));
+ QVERIFY(!QGeoAreaMonitorSource::availableSources().contains("test.source"));
}
void tst_PositionPlugin::create()
diff --git a/tests/auto/qgeoareamonitor/logfilepositionsource.cpp b/tests/auto/qgeoareamonitor/logfilepositionsource.cpp
new file mode 100644
index 00000000..fcfb7e0d
--- /dev/null
+++ b/tests/auto/qgeoareamonitor/logfilepositionsource.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtTest>
+
+#include "logfilepositionsource.h"
+
+LogFilePositionSource::LogFilePositionSource(QObject *parent)
+ : QGeoPositionInfoSource(parent),
+ logFile(new QFile(this)),
+ timer(new QTimer(this))
+{
+ connect(timer, SIGNAL(timeout()), this, SLOT(readNextPosition()));
+
+ logFile->setFileName(QFINDTESTDATA("simplelog.txt"));
+ if (!logFile->open(QIODevice::ReadOnly))
+ qWarning() << "Error: cannot open source file" << logFile->fileName();
+}
+
+QGeoPositionInfo LogFilePositionSource::lastKnownPosition(bool /*fromSatellitePositioningMethodsOnly*/) const
+{
+ return lastPosition;
+}
+
+LogFilePositionSource::PositioningMethods LogFilePositionSource::supportedPositioningMethods() const
+{
+ return AllPositioningMethods;
+}
+
+int LogFilePositionSource::minimumUpdateInterval() const
+{
+ return 200;
+}
+
+void LogFilePositionSource::startUpdates()
+{
+ int interval = updateInterval();
+ if (interval < minimumUpdateInterval())
+ interval = minimumUpdateInterval();
+
+ timer->start(interval);
+}
+
+void LogFilePositionSource::stopUpdates()
+{
+ timer->stop();
+}
+
+void LogFilePositionSource::requestUpdate(int /*timeout*/)
+{
+ // For simplicity, ignore timeout - assume that if data is not available
+ // now, no data will be added to the file later
+ if (logFile->canReadLine())
+ readNextPosition();
+ else
+ emit updateTimeout();
+}
+
+void LogFilePositionSource::readNextPosition()
+{
+ QByteArray line = logFile->readLine().trimmed();
+ if (!line.isEmpty()) {
+ QList<QByteArray> data = line.split(' ');
+ double latitude;
+ double longitude;
+ bool hasLatitude = false;
+ bool hasLongitude = false;
+ QDateTime timestamp = QDateTime::fromString(QString(data.value(0)), Qt::ISODate);
+ latitude = data.value(1).toDouble(&hasLatitude);
+ longitude = data.value(2).toDouble(&hasLongitude);
+
+ if (hasLatitude && hasLongitude && timestamp.isValid()) {
+ QGeoCoordinate coordinate(latitude, longitude);
+ QGeoPositionInfo info(coordinate, timestamp);
+ if (info.isValid()) {
+ lastPosition = info;
+ emit positionUpdated(info);
+ }
+ }
+ }
+}
+
+QGeoPositionInfoSource::Error LogFilePositionSource::error() const
+{
+ return QGeoPositionInfoSource::UnknownSourceError;
+}
diff --git a/src/positioning/qgeoareamonitor.h b/tests/auto/qgeoareamonitor/logfilepositionsource.h
index 1aed8b6b..966b2540 100644
--- a/src/positioning/qgeoareamonitor.h
+++ b/tests/auto/qgeoareamonitor/logfilepositionsource.h
@@ -3,7 +3,7 @@
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtPositioning module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -38,48 +38,42 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QGEOAREAMONITOR_H
-#define QGEOAREAMONITOR_H
-#include <QtPositioning/QGeoCoordinate>
+#ifndef LOGFILEPOSITIONSOURCE_H
+#define LOGFILEPOSITIONSOURCE_H
-#include <QObject>
-#include <QStringList>
+#include <qgeopositioninfosource.h>
QT_BEGIN_NAMESPACE
+class QFile;
+class QTimer;
+QT_END_NAMESPACE
-class QGeoPositionInfo;
-class QGeoAreaMonitorPrivate;
-class Q_POSITIONING_EXPORT QGeoAreaMonitor : public QObject
+class LogFilePositionSource : public QGeoPositionInfoSource
{
Q_OBJECT
- Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter)
- Q_PROPERTY(qreal radius READ radius WRITE setRadius)
-
public:
- explicit QGeoAreaMonitor(QObject *parent);
- virtual ~QGeoAreaMonitor() = 0;
+ LogFilePositionSource(QObject *parent = 0);
+
+ QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const;
- virtual void setCenter(const QGeoCoordinate &coordinate);
- QGeoCoordinate center() const;
+ PositioningMethods supportedPositioningMethods() const;
+ int minimumUpdateInterval() const;
+ Error error() const;
- virtual void setRadius(qreal radius);
- qreal radius() const;
+public slots:
+ virtual void startUpdates();
+ virtual void stopUpdates();
- static QGeoAreaMonitor *createDefaultMonitor(QObject *parent);
- static QGeoAreaMonitor *createMonitor(const QString& sourceName, QObject *parent);
- static QStringList availableMonitors();
+ virtual void requestUpdate(int timeout = 5000);
-Q_SIGNALS:
- void areaEntered(const QGeoPositionInfo &update);
- void areaExited(const QGeoPositionInfo &update);
+private slots:
+ void readNextPosition();
private:
- Q_DISABLE_COPY(QGeoAreaMonitor)
- QGeoAreaMonitorPrivate *d;
+ QFile *logFile;
+ QTimer *timer;
+ QGeoPositionInfo lastPosition;
};
-
-QT_END_NAMESPACE
-
#endif
diff --git a/tests/auto/qgeoareamonitor/qgeoareamonitor.pro b/tests/auto/qgeoareamonitor/qgeoareamonitor.pro
index 05cc5ef5..35581bca 100644
--- a/tests/auto/qgeoareamonitor/qgeoareamonitor.pro
+++ b/tests/auto/qgeoareamonitor/qgeoareamonitor.pro
@@ -2,7 +2,12 @@ TEMPLATE = app
CONFIG+=testcase
TARGET=tst_qgeoareamonitor
-SOURCES += tst_qgeoareamonitor.cpp
+SOURCES += tst_qgeoareamonitor.cpp \
+ logfilepositionsource.cpp
+
+HEADERS += logfilepositionsource.h
+
+OTHER_FILES += *.txt
QT += positioning testlib
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qgeoareamonitor/simplelog.txt b/tests/auto/qgeoareamonitor/simplelog.txt
new file mode 100644
index 00000000..5a14fb80
--- /dev/null
+++ b/tests/auto/qgeoareamonitor/simplelog.txt
@@ -0,0 +1,87 @@
+2009-08-24T22:24:34 -27.54 153.090718
+2009-08-24T22:24:35 -27.55 153.090718
+2009-08-24T22:24:36 -27.56 153.090718
+2009-08-24T22:24:37 -27.57 153.090718
+2009-08-24T22:24:38 -27.58 153.090783
+2009-08-24T22:24:39 -27.59 153.090845
+2009-08-24T22:24:40 -27.60 153.090908
+2009-08-24T22:24:41 -27.61 153.090971
+2009-08-24T22:24:42 -27.62 153.091036
+2009-08-24T22:24:43 -27.63 153.091102
+2009-08-24T22:24:44 -27.64 153.091167
+2009-08-24T22:24:45 -27.65 153.091232
+2009-08-24T22:24:46 -27.65 153.091298
+2009-08-24T22:24:47 -27.65 153.091366
+2009-08-24T22:24:48 -27.65 153.091435
+2009-08-24T22:24:49 -27.66 153.091507
+2009-08-24T22:24:50 -27.67 153.091581
+2009-08-24T22:24:51 -27.68 153.091654
+2009-08-24T22:24:52 -27.69 153.091729
+2009-08-24T22:24:53 -27.70 153.091800
+2009-08-24T22:24:54 -27.71 153.091870
+2009-08-24T22:24:55 -27.72 153.091940
+2009-08-24T22:24:56 -27.73 153.092010
+2009-08-24T22:24:57 -27.74 153.092078
+2009-08-24T22:24:58 -27.75 153.092144
+2009-08-24T22:24:59 -27.78 153.092218
+2009-08-24T22:25:00 -27.79 153.092308
+2009-08-24T22:25:01 -27.80 153.092415
+2009-08-24T22:25:02 -27.81 153.092530
+2009-08-24T22:25:03 -27.82 153.092648
+2009-08-24T22:25:04 -27.83 153.092763
+2009-08-24T22:25:05 -27.84 153.092879
+2009-08-24T22:25:06 -27.85 153.092990
+2009-08-24T22:25:07 -27.84 153.093099
+2009-08-24T22:25:08 -27.83 153.093204
+2009-08-24T22:25:09 -27.82 153.093303
+2009-08-24T22:25:10 -27.81 153.093396
+2009-08-24T22:25:11 -27.80 153.093484
+2009-08-24T22:25:12 -27.79 153.093568
+2009-08-24T22:25:13 -27.78 153.093647
+2009-08-24T22:25:14 -27.77 153.093727
+2009-08-24T22:25:15 -27.76 153.093810
+2009-08-24T22:25:16 -27.75 153.093896
+2009-08-24T22:25:17 -27.74 153.093984
+2009-08-24T22:25:18 -27.72 153.094074
+2009-08-24T22:25:19 -27.70 153.094168
+2009-08-24T22:25:20 -27.71 153.094267
+2009-08-24T22:25:21 -27.69 153.094370
+2009-08-24T22:25:22 -27.68 153.094474
+2009-08-24T22:25:23 -27.67 153.094581
+2009-08-24T22:25:24 -27.66 153.094688
+2009-08-24T22:25:25 -27.65 153.094796
+2009-08-24T22:25:26 -27.64 153.094905
+2009-08-24T22:25:27 -27.63 153.095012
+2009-08-24T22:25:28 -27.62 153.095121
+2009-08-24T22:25:29 -27.61 153.095231
+2009-08-24T22:25:30 -27.60 153.095340
+2009-08-24T22:25:31 -27.59 153.095449
+2009-08-24T22:25:32 -27.58 153.095558
+2009-08-24T22:25:33 -27.57 153.095667
+2009-08-24T22:25:34 -27.56 153.095776
+2009-08-24T22:25:35 -27.55 153.095885
+2009-08-24T22:25:36 -27.54 153.095995
+2009-08-24T22:25:37 -27.53 153.096109
+2009-08-24T22:25:38 -27.52 153.096226
+2009-08-24T22:25:39 -27.51 153.096337
+2009-08-24T22:25:40 -27.50 153.096441
+2009-08-24T22:25:41 -27.49 153.096537
+2009-08-24T22:25:42 -27.48 153.096628
+2009-08-24T22:25:43 -27.47 153.096714
+2009-08-24T22:25:44 -27.46 153.096795
+2009-08-24T22:25:45 -27.45 153.096847
+2009-08-24T22:25:46 -27.44 153.096855
+2009-08-24T22:25:47 -27.43 153.096873
+2009-08-24T22:25:48 -27.42 153.096875
+2009-08-24T22:25:49 -27.41 153.096878
+2009-08-24T22:25:50 -27.40 153.096880
+2009-08-24T22:25:51 -27.39 153.096880
+2009-08-24T22:25:52 -27.38 153.096881
+2009-08-24T22:25:53 -27.37 153.096882
+2009-08-24T22:25:54 -27.36 153.096883
+2009-08-24T22:25:55 -27.35 153.096883
+2009-08-24T22:25:56 -27.34 153.096883
+2009-08-24T22:25:57 -27.33 153.096890
+2009-08-24T22:25:58 -27.32 153.096919
+2009-08-24T22:25:59 -27.31 153.096985
+2009-08-24T22:26:00 -27.30 153.097060
diff --git a/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp b/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp
index 347fca19..cd9894e5 100644
--- a/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp
+++ b/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp
@@ -48,41 +48,30 @@
#include <limits.h>
#include <float.h>
-#include <qgeoareamonitor.h>
+#include <QDebug>
+#include <QDataStream>
+
+#include <qgeoareamonitorinfo.h>
+#include <qgeoareamonitorsource.h>
#include <qgeopositioninfo.h>
#include <qgeopositioninfosource.h>
+#include <qnmeapositioninfosource.h>
+#include <qgeocircle.h>
+#include <qgeorectangle.h>
+
+#include "logfilepositionsource.h"
QT_USE_NAMESPACE
-#define MINIMUM_TIMEOUT 5000
+#define UPDATE_INTERVAL 200
Q_DECLARE_METATYPE(QGeoPositionInfo)
+Q_DECLARE_METATYPE(QGeoAreaMonitorInfo)
-
-class MyPositionAreaMonitor : public QGeoAreaMonitor
-{
- Q_OBJECT
-public:
- MyPositionAreaMonitor(QObject* parent = 0) : QGeoAreaMonitor(parent) {}
- ~MyPositionAreaMonitor() {}
-};
-
-
-static qreal tst_qgeoareamonitor_minimumRadius()
-{
- // tests should not be run with minimum radius in this case
- return 0;
-}
-
-
-class tst_QGeoAreaMonitor : public QObject
+class tst_QGeoAreaMonitorSource : public QObject
{
Q_OBJECT
-private:
- QGeoAreaMonitor* monitor;
-
-
private slots:
void initTestCase()
{
@@ -92,179 +81,628 @@ private slots:
QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath()
+ QStringLiteral("/../../../plugins"));
qRegisterMetaType<QGeoPositionInfo>();
+ qRegisterMetaType<QGeoAreaMonitorInfo>();
}
void init()
{
- monitor = 0;
}
void cleanup()
{
- delete monitor;
- monitor = 0;
+ QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
+
+ QList<QGeoAreaMonitorInfo> list = obj->activeMonitors();
+ if (list.count() > 0) {
+ //cleanup installed monitors
+ foreach (const QGeoAreaMonitorInfo& info, list) {
+ QVERIFY(obj->stopMonitoring(info));
+ }
+ }
+ QVERIFY(obj->activeMonitors().count() == 0);
}
void cleanupTestCase()
{
}
- void coordinate()
+ void tst_monitor()
{
- MyPositionAreaMonitor mon;
- QCOMPARE(mon.center(), QGeoCoordinate());
+ QGeoAreaMonitorInfo defaultMonitor;
+ QVERIFY(defaultMonitor.name().isEmpty());
+ QVERIFY(!defaultMonitor.identifier().isEmpty());
+ QCOMPARE(defaultMonitor.isPersistent(), false);
+ QVERIFY(!defaultMonitor.area().isValid());
+ QVERIFY(!defaultMonitor.isValid());
+ QCOMPARE(defaultMonitor.expiration(), QDateTime());
+ QCOMPARE(defaultMonitor.notificationParameters(), QVariantMap());
+
+ QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
+ QVERIFY(!obj->startMonitoring(defaultMonitor));
+ QCOMPARE(obj->activeMonitors().count(), 0);
+ QVERIFY(!obj->requestUpdate(defaultMonitor,
+ SIGNAL(areaEntered(QGeoMonitorInfo,QGeoAreaPositionInfo))));
+ delete obj;
+
+ //copy constructor based
+ QGeoAreaMonitorInfo copy(defaultMonitor);
+ QVERIFY(copy.name().isEmpty());
+ QCOMPARE(copy.identifier(), defaultMonitor.identifier());
+ QVERIFY(copy == defaultMonitor);
+ QVERIFY(!(copy != defaultMonitor));
+ QCOMPARE(copy.isPersistent(), false);
+
+ copy.setName(QString("my name"));
+ QCOMPARE(copy.name(), QString("my name"));
+
+
+ QDateTime now = QDateTime::currentDateTime().addSecs(1000); //little bit in the future
+ copy.setExpiration(now);
+ QVERIFY(copy != defaultMonitor);
+ QCOMPARE(copy.expiration(), now);
+
+ QCOMPARE(copy.isPersistent(), defaultMonitor.isPersistent());
+ copy.setPersistent(true);
+ QCOMPARE(copy.isPersistent(), true);
+ QCOMPARE(defaultMonitor.isPersistent(), false);
+ copy.setPersistent(false);
+
+ QVERIFY(copy.area() == defaultMonitor.area());
+ QVERIFY(!copy.area().isValid());
+ copy.setArea(QGeoCircle(QGeoCoordinate(1, 2), 4));
+ QVERIFY(copy.area().isValid());
+ QVERIFY(copy.area() != defaultMonitor.area());
+ QVERIFY(copy.area().contains(QGeoCoordinate(1, 2)));
+
+ QVERIFY(copy.notificationParameters().isEmpty());
+ QVariantMap map;
+ map.insert(QString("MyKey"), QVariant(123));
+ copy.setNotificationParameters(map);
+ QVERIFY(!copy.notificationParameters().isEmpty());
+ QCOMPARE(copy.notificationParameters().value(QString("MyKey")).toInt(), 123);
+ QCOMPARE(defaultMonitor.notificationParameters().value(QString("MyKey")).toInt(), 0);
+
+ QCOMPARE(defaultMonitor.identifier(), copy.identifier());
+
+ //assignment operator based
+ QGeoAreaMonitorInfo assignmentCopy;
+ assignmentCopy = copy;
+ QVERIFY(copy == assignmentCopy);
+ QVERIFY(assignmentCopy != defaultMonitor);
+
+ QVERIFY(assignmentCopy.area().contains(QGeoCoordinate(1, 2)));
+ QCOMPARE(assignmentCopy.expiration(), now);
+ QCOMPARE(assignmentCopy.isPersistent(), false);
+ QCOMPARE(assignmentCopy.notificationParameters().value(QString("MyKey")).toInt(), 123);
+ QCOMPARE(defaultMonitor.identifier(), assignmentCopy.identifier());
+ QCOMPARE(assignmentCopy.name(), QString("my name"));
+
+ //validity checks for requestUpdate()
+ obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
+ QCOMPARE(obj->activeMonitors().count(), 0);
+ //reference -> should work
+ QVERIFY(obj->requestUpdate(copy, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+ //replaces areaEntered single shot
+ QVERIFY(obj->requestUpdate(copy, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo))));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+ //replaces areaExited single shot
+ QVERIFY(obj->startMonitoring(copy));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+
+
+ //invalid signal
+ QVERIFY(!obj->requestUpdate(copy, 0));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+
+ //signal that doesn't exist
+ QVERIFY(!obj->requestUpdate(copy, SIGNAL(areaEntered(QGeoMonitor))));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+
+ QVERIFY(!obj->requestUpdate(copy, "SIGNAL(areaEntered(QGeoMonitor))"));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+
+ //ensure that we cannot add a persistent monitor to a source
+ //that doesn't support persistence
+ QGeoAreaMonitorInfo persistenceMonitor(copy);
+ persistenceMonitor.setPersistent(obj->supportedAreaMonitorFeatures() & QGeoAreaMonitorSource::PersistentAreaMonitorFeature);
+ persistenceMonitor.setPersistent(!persistenceMonitor.isPersistent());
+
+ QVERIFY(!obj->requestUpdate(persistenceMonitor, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+ QVERIFY(!obj->startMonitoring(persistenceMonitor));
+ QCOMPARE(obj->activeMonitors().count(), 1);
+
+ //ensure that persistence was only reason for rejection
+ persistenceMonitor.setPersistent(!persistenceMonitor.isPersistent());
+ QVERIFY(obj->startMonitoring(persistenceMonitor));
+ //persistenceMonitor is copy of already added monitor
+ //the last call was an update
+ QCOMPARE(obj->activeMonitors().count(), 1);
+
+ delete obj;
}
- void radius()
+ void tst_monitorValid()
{
- MyPositionAreaMonitor mon;
- qFuzzyCompare(mon.radius(), qreal(0.0));
+ QGeoAreaMonitorInfo mon;
+ QVERIFY(!mon.isValid());
+ QCOMPARE(mon.name(), QString());
+ QCOMPARE(mon.area().isValid(), false);
+
+ QGeoAreaMonitorInfo mon2 = mon;
+ QVERIFY(!mon2.isValid());
+
+ QGeoShape invalidShape;
+ QGeoCircle emptyCircle(QGeoCoordinate(0,1), 0);
+ QGeoCircle validCircle(QGeoCoordinate(0,1), 1);
+
+ //all invalid since no name set yet
+ mon2.setArea(invalidShape);
+ QVERIFY(mon2.area() == invalidShape);
+ QVERIFY(!mon2.isValid());
+
+ mon2.setArea(emptyCircle);
+ QVERIFY(mon2.area() == emptyCircle);
+ QVERIFY(!mon2.isValid());
+
+ mon2.setArea(validCircle);
+ QVERIFY(mon2.area() == validCircle);
+ QVERIFY(!mon2.isValid());
+
+ //valid since name and non-empy shape has been set
+ QGeoAreaMonitorInfo validMonitor("TestMonitor");
+ QVERIFY(validMonitor.name() == QString("TestMonitor"));
+ QVERIFY(!validMonitor.isValid());
+
+ validMonitor.setArea(invalidShape);
+ QVERIFY(validMonitor.area() == invalidShape);
+ QVERIFY(!validMonitor.isValid());
+
+ validMonitor.setArea(emptyCircle);
+ QVERIFY(validMonitor.area() == emptyCircle);
+ QVERIFY(!validMonitor.isValid());
+
+ validMonitor.setArea(validCircle);
+ QVERIFY(validCircle == validMonitor.area());
+ QVERIFY(validMonitor.isValid());
}
- void constructor_withoutParent()
+ void tst_monitorStreaming()
{
- MyPositionAreaMonitor *myMonitor = new MyPositionAreaMonitor();
- delete myMonitor;
- }
+ QByteArray container;
+ QDataStream stream(&container, QIODevice::ReadWrite);
- void constructor_withParent()
- {
- QObject* parent = new QObject;
- new MyPositionAreaMonitor(parent);
- delete parent;
+ QGeoAreaMonitorInfo monitor("someName");
+ monitor.setArea(QGeoCircle(QGeoCoordinate(1,3), 5.4));
+ QVERIFY(monitor.isValid());
+ QCOMPARE(monitor.name(), QString("someName"));
+
+ QGeoAreaMonitorInfo target;
+ QVERIFY(!target.isValid());
+ QVERIFY(target.name().isEmpty());
+
+ QVERIFY(target != monitor);
+
+ stream << monitor;
+ stream.device()->seek(0);
+ stream >> target;
+
+ QVERIFY(target == monitor);
+ QVERIFY(target.isValid());
+ QCOMPARE(target.name(), QString("someName"));
+ QVERIFY(target.area() == QGeoCircle(QGeoCoordinate(1,3), 5.4));
}
- void createDefaultMonitor()
+ void tst_createDefaultSource()
{
QObject* parent = new QObject;
- QGeoAreaMonitor* obj = QGeoAreaMonitor::createDefaultMonitor(parent);
+ QGeoAreaMonitorSource* obj = QGeoAreaMonitorSource::createDefaultSource(parent);
QVERIFY(obj != 0);
- delete parent;
+ QVERIFY(obj->parent() == parent);
+ delete obj;
- const QStringList monitors = QGeoAreaMonitor::availableMonitors();
+ const QStringList monitors = QGeoAreaMonitorSource::availableSources();
QVERIFY(!monitors.isEmpty());
QVERIFY(monitors.contains(QStringLiteral("positionpoll")));
- parent = new QObject;
- obj = QGeoAreaMonitor::createMonitor(QStringLiteral("positionpoll"), parent);
+ obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), parent);
QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
delete parent;
- obj = QGeoAreaMonitor::createMonitor(QStringLiteral("randomNonExistingName"), 0);
+ obj = QGeoAreaMonitorSource::createSource(QStringLiteral("randomNonExistingName"), 0);
QVERIFY(obj == 0);
}
- //TC_ID_4_x_1
- void center_createDefaultMonitor()
+ void tst_activeMonitors()
{
- monitor = QGeoAreaMonitor::createDefaultMonitor(0);
- QVERIFY(monitor != 0);
- QVERIFY(monitor->center().isValid() == false);
- }
-
- //TC_ID_4_x_1
- void radius_createDefaultMonitor()
- {
- monitor = QGeoAreaMonitor::createDefaultMonitor(0);
- QVERIFY(monitor != 0);
- qFuzzyCompare(monitor->radius(), qreal(0.0));
- }
-
- void setCenter()
- {
- QFETCH(QGeoCoordinate, coord);
- QFETCH(bool, validity);
-
- monitor = QGeoAreaMonitor::createDefaultMonitor(0);
- QVERIFY(monitor != 0);
-
- monitor->setCenter(coord);
- QCOMPARE(monitor->center().isValid(), validity);
- if (validity)
- QCOMPARE(monitor->center(), coord);
- }
-
- void setCenter_data()
- {
- QTest::addColumn<QGeoCoordinate>("coord");
- QTest::addColumn<bool>("validity");
-
- QTest::newRow("valid coordinate") << QGeoCoordinate(34.56, -12.4, 56) << true; //TC_ID_4_x_1
- QTest::newRow("invalid coordinate") << QGeoCoordinate(173.2, -195.8) << false; //TC_ID_4_x_2
- QTest::newRow("uninitialised coordinate") << QGeoCoordinate() << false; //TC_ID_4_x_3
- }
-
- void setCenter_twice()
- {
- QFETCH(QGeoCoordinate, first_coord);
- QFETCH(QGeoCoordinate, second_coord);
- QFETCH(QGeoCoordinate, expected_coord);
-
- monitor = QGeoAreaMonitor::createDefaultMonitor(0);
- QVERIFY(monitor != 0);
-
- monitor->setCenter(first_coord);
- monitor->setCenter(second_coord);
- QCOMPARE(monitor->center(), expected_coord);
- }
-
- void setCenter_twice_data()
- {
- QTest::addColumn<QGeoCoordinate>("first_coord");
- QTest::addColumn<QGeoCoordinate>("second_coord");
- QTest::addColumn<QGeoCoordinate>("expected_coord");
-
- //TC_ID_4_x_4
- QTest::newRow("setting first valid then invalid coordinate")
- << QGeoCoordinate(34.56, -12.4, 56) << QGeoCoordinate(173.2, -195.8)
- << QGeoCoordinate(34.56, -12.4, 56);
- //TC_ID_4_x_5
- QTest::newRow("setting first invalid then valid coordinate")
- << QGeoCoordinate(173.2, -195.8) << QGeoCoordinate(34.56, -12.4, 56)
- << QGeoCoordinate(34.56, -12.4, 56);
- //TC_ID_4_x_6
- QTest::newRow("setting first valid then valid coordinate")
- << QGeoCoordinate(-12.56, 101.4, 56) << QGeoCoordinate(34.56, -12.4, 56)
- << QGeoCoordinate(34.56, -12.4, 56);
+ QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
+
+ LogFilePositionSource *source = new LogFilePositionSource(this);
+ source->setUpdateInterval(UPDATE_INTERVAL);
+ obj->setPositionInfoSource(source);
+ QCOMPARE(obj->positionInfoSource(), source);
+
+
+ QVERIFY(obj->activeMonitors().isEmpty());
+
+ QGeoAreaMonitorInfo mon("Monitor_Circle");
+ mon.setArea(QGeoCircle(QGeoCoordinate(1,1), 1000));
+ QVERIFY(obj->startMonitoring(mon));
+
+ QGeoAreaMonitorInfo mon2("Monitor_rectangle_below");
+ QGeoRectangle r_below(QGeoCoordinate(1,1),2,2);
+ mon2.setArea(r_below);
+ QVERIFY(obj->startMonitoring(mon2));
+
+ QGeoAreaMonitorInfo mon3("Monitor_rectangle_above");
+ QGeoRectangle r_above(QGeoCoordinate(2,1),2,2);
+ mon3.setArea(r_above);
+ QVERIFY(obj->startMonitoring(mon3));
+
+ QList<QGeoAreaMonitorInfo> results = obj->activeMonitors();
+ QCOMPARE(results.count(), 3);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon || info == mon2 || info == mon3);
+ }
+
+ results = obj->activeMonitors(QGeoShape());
+ QCOMPARE(results.count(), 0);
+
+ results = obj->activeMonitors(QGeoRectangle(QGeoCoordinate(1,1),0.2, 0.2));
+ QCOMPARE(results.count(), 2);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon || info == mon2);
+ }
+
+ results = obj->activeMonitors(QGeoCircle(QGeoCoordinate(1,1),1000));
+ QCOMPARE(results.count(), 2);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon || info == mon2);
+ }
+
+ results = obj->activeMonitors(QGeoCircle(QGeoCoordinate(2,1),1000));
+ QCOMPARE(results.count(), 1);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon3);
+ }
+
+ //same as above except that we use a different monitor source object instance
+ //all monitor objects of same type share same active monitors
+ QGeoAreaMonitorSource *secondObj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(secondObj != 0);
+ QCOMPARE(secondObj->sourceName(), QStringLiteral("positionpoll"));
+
+ results = secondObj->activeMonitors();
+ QCOMPARE(results.count(), 3);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon || info == mon2 || info == mon3);
+ }
+
+ results = secondObj->activeMonitors(QGeoShape());
+ QCOMPARE(results.count(), 0);
+
+ results = secondObj->activeMonitors(QGeoRectangle(QGeoCoordinate(1,1),0.2, 0.2));
+ QCOMPARE(results.count(), 2);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon || info == mon2);
+ }
+
+ results = secondObj->activeMonitors(QGeoCircle(QGeoCoordinate(1,1),1000));
+ QCOMPARE(results.count(), 2);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon || info == mon2);
+ }
+
+ results = secondObj->activeMonitors(QGeoCircle(QGeoCoordinate(2,1),1000));
+ QCOMPARE(results.count(), 1);
+ foreach (const QGeoAreaMonitorInfo& info, results) {
+ QVERIFY(info == mon3);
+ }
+
+ delete obj;
+ delete secondObj;
}
- void setRadius()
+ void tst_testExpiryTimeout()
{
- QFETCH(qreal, radius);
- QFETCH(qreal, expected_radius);
-
- monitor = QGeoAreaMonitor::createDefaultMonitor(0);
- QVERIFY(monitor != 0);
-
- monitor->setRadius(radius);
- qFuzzyCompare(monitor->radius(), expected_radius);
+ QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
+
+ QGeoAreaMonitorSource *secondObj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(secondObj != 0);
+ QCOMPARE(secondObj->sourceName(), QStringLiteral("positionpoll"));
+
+ LogFilePositionSource *source = new LogFilePositionSource(this);
+ source->setUpdateInterval(UPDATE_INTERVAL);
+ obj->setPositionInfoSource(source);
+
+ //Singleton pattern behind QGeoAreaMonitorSource ensures same position info source
+ QCOMPARE(obj->positionInfoSource(), source);
+ QCOMPARE(secondObj->positionInfoSource(), source);
+
+ QSignalSpy expirySpy(obj, SIGNAL(monitorExpired(QGeoAreaMonitorInfo)));
+ QSignalSpy expirySpy2(secondObj, SIGNAL(monitorExpired(QGeoAreaMonitorInfo)));
+
+ QDateTime now = QDateTime::currentDateTime();
+
+ const int monitorCount = 4;
+ for (int i = 1; i <= monitorCount; i++) {
+ QGeoAreaMonitorInfo mon(QString::number(i));
+ mon.setArea(QGeoRectangle(QGeoCoordinate(i,i), i, i));
+ mon.setExpiration(now.addSecs(i*5));
+ QVERIFY(mon.isValid());
+ QVERIFY(obj->startMonitoring(mon));
+ }
+
+
+
+ QCOMPARE(obj->activeMonitors().count(), monitorCount);
+ QCOMPARE(secondObj->activeMonitors().count(), monitorCount);
+
+ QGeoAreaMonitorInfo info("InvalidExpiry");
+ info.setArea(QGeoRectangle(QGeoCoordinate(10,10), 1, 1 ));
+ QVERIFY(info.isValid());
+ info.setExpiration(now.addSecs(-1000));
+ QVERIFY(info.expiration() < now);
+ QVERIFY(!obj->startMonitoring(info));
+ QCOMPARE(obj->activeMonitors().count(), monitorCount);
+ QVERIFY(!obj->requestUpdate(info, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))));
+ QCOMPARE(obj->activeMonitors().count(), monitorCount);
+
+ for (int i = 1; i <= monitorCount; i++) {
+ QTRY_VERIFY_WITH_TIMEOUT(expirySpy.count() == 1, 7000); //each expiry within 5 s
+ QGeoAreaMonitorInfo mon = expirySpy.takeFirst().at(0).value<QGeoAreaMonitorInfo>();
+ QCOMPARE(obj->activeMonitors().count(), monitorCount-i);
+ QCOMPARE(mon.name(), QString::number(i));
+ }
+
+ QCOMPARE(expirySpy2.count(), monitorCount);
+ QCOMPARE(secondObj->activeMonitors().count(), 0); //all monitors expired
+ for (int i = 1; i <= monitorCount; i++) {
+ QGeoAreaMonitorInfo mon = expirySpy2.takeFirst().at(0).value<QGeoAreaMonitorInfo>();
+ QCOMPARE(mon.name(), QString::number(i));
+ }
+
+ delete obj;
+ delete secondObj;
}
- void setRadius_data()
+ void tst_enteredExitedSignal()
{
- QTest::addColumn<qreal>("radius");
- QTest::addColumn<qreal>("expected_radius");
-
- QTest::newRow("zero radius") << qreal(0.0) << tst_qgeoareamonitor_minimumRadius(); //TC_ID_4_x_1
- QTest::newRow("radius ok") << qreal(1000.58) << qreal(1000.58); //TC_ID_4_x_2
- QTest::newRow("negative radius") << qreal(-876.58) << tst_qgeoareamonitor_minimumRadius(); //TC_ID_4_x_3
- QTest::newRow("float min") << qreal(FLT_MIN) << tst_qgeoareamonitor_minimumRadius(); //TC_ID_4
- QTest::newRow("float max") << qreal(FLT_MAX) << qreal(FLT_MAX); //TC_ID_4_x_4_x_5
+ QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
+ obj->setObjectName("firstObject");
+ QSignalSpy enteredSpy(obj, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+ QSignalSpy exitedSpy(obj, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+
+ LogFilePositionSource *source = new LogFilePositionSource(this);
+ source->setUpdateInterval(UPDATE_INTERVAL);
+ obj->setPositionInfoSource(source);
+ QCOMPARE(obj->positionInfoSource(), source);
+
+ QGeoAreaMonitorSource *secondObj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(secondObj != 0);
+ QCOMPARE(secondObj->sourceName(), QStringLiteral("positionpoll"));
+ QSignalSpy enteredSpy2(secondObj, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+ QSignalSpy exitedSpy2(secondObj, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+ secondObj->setObjectName("secondObject");
+
+ QGeoAreaMonitorInfo infoRectangle("Rectangle");
+ infoRectangle.setArea(QGeoRectangle(QGeoCoordinate(-27.65, 153.093), 0.2, 0.2));
+ QVERIFY(infoRectangle.isValid());
+ QVERIFY(obj->startMonitoring(infoRectangle));
+
+ QGeoAreaMonitorInfo infoCircle("Circle");
+ infoCircle.setArea(QGeoCircle(QGeoCoordinate(-27.70, 153.093),10000));
+ QVERIFY(infoCircle.isValid());
+ QVERIFY(obj->startMonitoring(infoCircle));
+
+ QGeoAreaMonitorInfo singleShot_enter("SingleShot_on_Entered");
+ singleShot_enter.setArea(QGeoRectangle(QGeoCoordinate(-27.67, 153.093), 0.2, 0.2));
+ QVERIFY(singleShot_enter.isValid());
+ QVERIFY(obj->requestUpdate(singleShot_enter,
+ SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo))));
+
+ QGeoAreaMonitorInfo singleShot_exit("SingleShot_on_Exited");
+ singleShot_exit.setArea(QGeoRectangle(QGeoCoordinate(-27.70, 153.093), 0.2, 0.2));
+ QVERIFY(singleShot_exit.isValid());
+ QVERIFY(obj->requestUpdate(singleShot_exit,
+ SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo))));
+
+ QVERIFY(obj->activeMonitors().count() == 4); //all monitors active
+ QVERIFY(secondObj->activeMonitors().count() == 4); //all monitors active
+
+ static const int Number_Of_Entered_Events = 6;
+ static const int Number_Of_Exited_Events = 5;
+ //takes 87 (lines)*200(timeout)/1000 seconds to finish
+ QTRY_VERIFY_WITH_TIMEOUT(enteredSpy.count() == Number_Of_Entered_Events, 20000);
+ QTRY_VERIFY_WITH_TIMEOUT(exitedSpy.count() == Number_Of_Exited_Events, 20000);
+ QCOMPARE(enteredSpy.count(), Number_Of_Entered_Events);
+ QCOMPARE(exitedSpy.count(), Number_Of_Exited_Events);
+
+ QList<QGeoAreaMonitorInfo> monitorsInExpectedEnteredEventOrder;
+ monitorsInExpectedEnteredEventOrder << infoRectangle << singleShot_enter << singleShot_exit
+ << infoCircle << infoCircle << infoRectangle;
+
+ QList<QGeoAreaMonitorInfo> monitorsInExpectedExitedEventOrder;
+ monitorsInExpectedExitedEventOrder << infoRectangle << infoCircle
+ << singleShot_exit << infoCircle << infoRectangle;
+
+ QList<QGeoCoordinate> enteredEventCoordinateOrder;
+ enteredEventCoordinateOrder << QGeoCoordinate(-27.55, 153.090718) //infoRectangle
+ << QGeoCoordinate(-27.57, 153.090718) //singleshot_enter
+ << QGeoCoordinate(-27.60, 153.090908) //singleshot_exit
+ << QGeoCoordinate(-27.62, 153.091036) //infoCircle
+ << QGeoCoordinate(-27.78, 153.093647) //infoCircle
+ << QGeoCoordinate(-27.75, 153.093896);//infoRectangle
+ QCOMPARE(enteredEventCoordinateOrder.count(), Number_Of_Entered_Events);
+ QCOMPARE(monitorsInExpectedEnteredEventOrder.count(), Number_Of_Entered_Events);
+
+ QList<QGeoCoordinate> exitedEventCoordinateOrder;
+ exitedEventCoordinateOrder << QGeoCoordinate(-27.78, 153.092218) //infoRectangle
+ << QGeoCoordinate(-27.79, 153.092308) //infoCircle
+ << QGeoCoordinate(-27.81, 153.092530) //singleshot_exit
+ << QGeoCoordinate(-27.61, 153.095231) //infoCircle
+ << QGeoCoordinate(-27.54, 153.095995);//infoCircle
+ QCOMPARE(exitedEventCoordinateOrder.count(), Number_Of_Exited_Events);
+ QCOMPARE(monitorsInExpectedExitedEventOrder.count(), Number_Of_Exited_Events);
+
+ //verify that both sources got the same signals
+ for (int i = 0; i < Number_Of_Entered_Events; i++) {
+ //first source
+ QGeoAreaMonitorInfo monInfo = enteredSpy.first().at(0).value<QGeoAreaMonitorInfo>();
+ QGeoPositionInfo posInfo = enteredSpy.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY2(monInfo == monitorsInExpectedEnteredEventOrder.at(i),
+ qPrintable(QString::number(i) + ": " + monInfo.name()));
+ QVERIFY2(posInfo.coordinate() == enteredEventCoordinateOrder.at(i),
+ qPrintable(QString::number(i) + ". posInfo"));
+
+ //reset info objects to avoid comparing the same
+ monInfo = QGeoAreaMonitorInfo();
+ posInfo = QGeoPositionInfo();
+
+ //second source
+ monInfo = enteredSpy2.first().at(0).value<QGeoAreaMonitorInfo>();
+ posInfo = enteredSpy2.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY2(monInfo == monitorsInExpectedEnteredEventOrder.at(i),
+ qPrintable(QString::number(i) + ": " + monInfo.name()));
+ QVERIFY2(posInfo.coordinate() == enteredEventCoordinateOrder.at(i),
+ qPrintable(QString::number(i) + ". posInfo"));
+ }
+
+ for (int i = 0; i < Number_Of_Exited_Events; i++) {
+ //first source
+ QGeoAreaMonitorInfo monInfo = exitedSpy.first().at(0).value<QGeoAreaMonitorInfo>();
+ QGeoPositionInfo posInfo = exitedSpy.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY2(monInfo == monitorsInExpectedExitedEventOrder.at(i),
+ qPrintable(QString::number(i) + ": " + monInfo.name()));
+ QVERIFY2(posInfo.coordinate() == exitedEventCoordinateOrder.at(i),
+ qPrintable(QString::number(i) + ". posInfo"));
+
+ //reset info objects to avoid comparing the same
+ monInfo = QGeoAreaMonitorInfo();
+ posInfo = QGeoPositionInfo();
+
+ //second source
+ monInfo = exitedSpy2.first().at(0).value<QGeoAreaMonitorInfo>();
+ posInfo = exitedSpy2.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY2(monInfo == monitorsInExpectedExitedEventOrder.at(i),
+ qPrintable(QString::number(i) + ": " + monInfo.name()));
+ QVERIFY2(posInfo.coordinate() == exitedEventCoordinateOrder.at(i),
+ qPrintable(QString::number(i) + ". posInfo"));
+ }
+
+ QCOMPARE(obj->activeMonitors().count(), 2); //single shot monitors have been removed
+ QCOMPARE(secondObj->activeMonitors().count(), 2);
+
+ delete obj;
+ delete secondObj;
}
- //TC_ID_4_x_6
- void setRadius_twice()
+ void tst_swapOfPositionSource()
{
- monitor = QGeoAreaMonitor::createDefaultMonitor(0);
- QVERIFY(monitor != 0);
-
- monitor->setRadius(qreal(1235.985));
- monitor->setRadius(qreal(6754.075));
-
- qFuzzyCompare(monitor->radius(), qreal(6754.075f));
+ QGeoAreaMonitorSource *obj = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->sourceName(), QStringLiteral("positionpoll"));
+ obj->setObjectName("firstObject");
+ QSignalSpy enteredSpy(obj, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+ QSignalSpy exitedSpy(obj, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+
+ QGeoAreaMonitorSource *obj2 = QGeoAreaMonitorSource::createSource(QStringLiteral("positionpoll"), 0);
+ QVERIFY(obj2 != 0);
+ QCOMPARE(obj2->sourceName(), QStringLiteral("positionpoll"));
+ obj2->setObjectName("secondObject");
+ QSignalSpy enteredSpy2(obj2, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+ QSignalSpy exitedSpy2(obj2, SIGNAL(areaExited(QGeoAreaMonitorInfo,QGeoPositionInfo)));
+
+ LogFilePositionSource *source = new LogFilePositionSource(this);
+ source->setUpdateInterval(UPDATE_INTERVAL);
+ source->setObjectName("FirstLogFileSource");
+
+ LogFilePositionSource *source2 = new LogFilePositionSource(this);
+ source2->setUpdateInterval(UPDATE_INTERVAL);
+ source2->setObjectName("SecondLogFileSource");
+
+ obj->setPositionInfoSource(source);
+ QCOMPARE(obj->positionInfoSource(), obj2->positionInfoSource());
+ QCOMPARE(obj2->positionInfoSource(), source);
+
+ QGeoAreaMonitorInfo infoRectangle("Rectangle");
+ infoRectangle.setArea(QGeoRectangle(QGeoCoordinate(-27.70, 153.092), 0.2, 0.2));
+ QVERIFY(infoRectangle.isValid());
+ QVERIFY(obj->startMonitoring(infoRectangle));
+
+ QCOMPARE(obj->activeMonitors().count(), 1);
+ QCOMPARE(obj2->activeMonitors().count(), 1);
+
+ QGeoCoordinate firstBorder(-27.6, 153.090908);
+ QGeoCoordinate secondBorder(-27.81, 153.092530);
+
+ /***********************************/
+ //1. trigger events on source (until areaExit
+ QTRY_VERIFY_WITH_TIMEOUT(exitedSpy.count() == 1, 20000);
+ QCOMPARE(enteredSpy.count(), enteredSpy2.count());
+ QCOMPARE(exitedSpy.count(), exitedSpy2.count());
+
+ //compare entered event
+ QVERIFY(enteredSpy.first().at(0).value<QGeoAreaMonitorInfo>() ==
+ enteredSpy2.first().at(0).value<QGeoAreaMonitorInfo>());
+ QGeoPositionInfo info = enteredSpy.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY(info == enteredSpy2.takeFirst().at(1).value<QGeoPositionInfo>());
+ QVERIFY(info.coordinate() == firstBorder);
+ //compare exit event
+ QVERIFY(exitedSpy.first().at(0).value<QGeoAreaMonitorInfo>() ==
+ exitedSpy2.first().at(0).value<QGeoAreaMonitorInfo>());
+ info = exitedSpy.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY(info == exitedSpy2.takeFirst().at(1).value<QGeoPositionInfo>());
+ QVERIFY(info.coordinate() == secondBorder);
+
+ QCOMPARE(exitedSpy.count(), 0);
+ QCOMPARE(enteredSpy.count(), 0);
+ QCOMPARE(exitedSpy2.count(), 0);
+ QCOMPARE(enteredSpy2.count(), 0);
+
+ /***********************************/
+ //2. change position source -> which restarts at beginning again
+ obj2->setPositionInfoSource(source2);
+ QCOMPARE(obj->positionInfoSource(), obj2->positionInfoSource());
+ QCOMPARE(obj2->positionInfoSource(), source2);
+
+ QTRY_VERIFY_WITH_TIMEOUT(exitedSpy.count() == 1, 20000);
+ QCOMPARE(enteredSpy.count(), enteredSpy2.count());
+ QCOMPARE(exitedSpy.count(), exitedSpy2.count());
+
+ //compare entered event
+ QVERIFY(enteredSpy.first().at(0).value<QGeoAreaMonitorInfo>() ==
+ enteredSpy2.first().at(0).value<QGeoAreaMonitorInfo>());
+ info = enteredSpy.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY(info == enteredSpy2.takeFirst().at(1).value<QGeoPositionInfo>());
+ QVERIFY(info.coordinate() == firstBorder);
+ //compare exit event
+ QVERIFY(exitedSpy.first().at(0).value<QGeoAreaMonitorInfo>() ==
+ exitedSpy2.first().at(0).value<QGeoAreaMonitorInfo>());
+ info = exitedSpy.takeFirst().at(1).value<QGeoPositionInfo>();
+ QVERIFY(info == exitedSpy2.takeFirst().at(1).value<QGeoPositionInfo>());
+ QVERIFY(info.coordinate() == secondBorder);
+
+
+ //obj was deleted when setting new source
+ delete obj2;
}
};
-QTEST_GUILESS_MAIN(tst_QGeoAreaMonitor)
+QTEST_GUILESS_MAIN(tst_QGeoAreaMonitorSource)
#include "tst_qgeoareamonitor.moc"