diff options
author | Alex Blasche <alexander.blasche@digia.com> | 2014-01-28 15:08:18 +0100 |
---|---|---|
committer | Alex Blasche <alexander.blasche@digia.com> | 2014-01-28 15:09:35 +0100 |
commit | c056043611675eb894a6d4417324438b28fd952c (patch) | |
tree | 7718e252ee29f71658c0746b8af6a70ff8089a94 | |
parent | 0d134c50669ae963fc87547e5d716b9bcf7a3752 (diff) | |
parent | 691728d060058d5b27974f2e548d92a992e5425e (diff) | |
download | qtlocation-c056043611675eb894a6d4417324438b28fd952c.tar.gz |
Merge remote-tracking branch 'gerrit/dev' into noqt3d
Change-Id: Ide59f885491a417ca59d01217b1e734f0302fbf5
178 files changed, 3904 insertions, 769 deletions
diff --git a/.qmake.conf b/.qmake.conf index 16328b7d..efd0e68f 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,4 @@ load(qt_build_config) +CONFIG += qt_example_installs MODULE_VERSION = 5.3.0 diff --git a/dist/changes-5.2.1 b/dist/changes-5.2.1 new file mode 100644 index 00000000..a3e7058c --- /dev/null +++ b/dist/changes-5.2.1 @@ -0,0 +1,67 @@ +Qt 5.2.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.2.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://qt-project.org/doc/qt-5.2/ + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt-project.org/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + + +**************************************************************************** +* General * +**************************************************************************** + +General Improvements +-------------------- + + - [QTBUG-34910] + * Fix too long weather status string in weatherinfo example (UI change). + + - [QTBUG-36187] + * Byte order marker removed from positionpoll plugin which caused compile + errors on some older compilers. + + - Fix make install rules for all examples. + + - declarative_core unit test was fixed and re-enabled. + +Third party components +---------------------- + +**************************************************************************** +* Important Behavior Changes * +**************************************************************************** + +**************************************************************************** +* Library * +**************************************************************************** + +QtPositioning +------ + + - [QTBUG-33220] + * Removes QtQml dependency from QtPositioning. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +**************************************************************************** +* Plugin Specific Changes * +**************************************************************************** + +GeoClue +------ + + - Delay satellite provider until requested. + - Sets the default preferred positioning method to AllPositioningMethods. + - Fix for incorrect accuracy values reported by the plug-in. + diff --git a/examples/location/mapviewer/mapviewer.pro b/examples/location/mapviewer/mapviewer.pro index 36fead08..8c667498 100644 --- a/examples/location/mapviewer/mapviewer.pro +++ b/examples/location/mapviewer/mapviewer.pro @@ -32,10 +32,12 @@ OTHER_FILES += $$qmlcontentdialogs.files include(../common/common.pri) -target.path = $$[QT_INSTALL_EXAMPLES]/qtlocation/mapviewer - -INSTALLS += target +target.path = $$[QT_INSTALL_EXAMPLES]/location/mapviewer +additional.files = ../common +additional.path = $$[QT_INSTALL_EXAMPLES]/location/common +INSTALLS += target additional +# ensure copying of media file while shadow building !equals($${_PRO_FILE_PWD_}, $${OUT_PWD}) { MEDIAFILE = $${_PRO_FILE_PWD_}/demo.ogv copy2build.input = MEDIAFILE diff --git a/examples/location/places/content/places/SearchResultView.qml b/examples/location/places/content/places/SearchResultView.qml index b9d48776..da62a5c5 100644 --- a/examples/location/places/content/places/SearchResultView.qml +++ b/examples/location/places/content/places/SearchResultView.qml @@ -97,6 +97,7 @@ Item { Button { text: qsTr("Previous") + enabled: placeSearchModel.previousPagesAvailable onClicked: placeSearchModel.previousPage() anchors.left: parent.left @@ -111,6 +112,7 @@ Item { Button { text: qsTr("Next") + enabled: placeSearchModel.nextPagesAvailable onClicked: placeSearchModel.nextPage() anchors.right: parent.right diff --git a/examples/location/places/places.pro b/examples/location/places/places.pro index 459a241e..fa79387d 100644 --- a/examples/location/places/places.pro +++ b/examples/location/places/places.pro @@ -37,7 +37,8 @@ OTHER_FILES += $$qmlcontentplaces.files include(../common/common.pri) -target.path = $$[QT_INSTALL_EXAMPLES]/qtlocation/places - -INSTALLS += target +target.path = $$[QT_INSTALL_EXAMPLES]/location/places +additional.files = ../common +additional.path = $$[QT_INSTALL_EXAMPLES]/location/common +INSTALLS += target additional diff --git a/examples/location/places/places.qml b/examples/location/places/places.qml index 6b4b32dd..4a144d55 100644 --- a/examples/location/places/places.qml +++ b/examples/location/places/places.qml @@ -366,7 +366,6 @@ Item { recommendationId = ""; searchArea = searchRegion limit = -1; - offset = 0; update(); } @@ -376,7 +375,6 @@ Item { recommendationId = ""; searchArea = searchRegion limit = -1; - offset = 0; update(); } @@ -386,21 +384,6 @@ Item { recommendationId = placeId; searchArea = null; limit = -1; - offset = 0; - update(); - } - - function previousPage() { - if (limit === -1) - limit = count; - offset = Math.max(0, offset - limit); - update(); - } - - function nextPage() { - if (limit === -1) - limit = count; - offset += limit; update(); } diff --git a/examples/location/places_list/places_list.pro b/examples/location/places_list/places_list.pro index 2d4b29ab..68a6d494 100644 --- a/examples/location/places_list/places_list.pro +++ b/examples/location/places_list/places_list.pro @@ -6,7 +6,7 @@ SOURCES = main.cpp qmlcontent.files += $$files(*.qml) -target.path = $$[QT_INSTALL_EXAMPLES]/qtlocation/places_list -qmlcontent.path = $$[QT_INSTALL_EXAMPLES]/qtlocation/places_list +target.path = $$[QT_INSTALL_EXAMPLES]/location/places_list +qmlcontent.path = $$[QT_INSTALL_EXAMPLES]/location/places_list INSTALLS += target qmlcontent diff --git a/examples/location/places_map/places_map.pro b/examples/location/places_map/places_map.pro index 5f7d3eaf..7f4bf81b 100644 --- a/examples/location/places_map/places_map.pro +++ b/examples/location/places_map/places_map.pro @@ -7,7 +7,7 @@ SOURCES = main.cpp qmlcontent.files += $$files(*.qml) \ marker.png -target.path = $$[QT_INSTALL_EXAMPLES]/qtlocation/places_map -qmlcontent.path = $$[QT_INSTALL_EXAMPLES]/qtlocation/places_map +target.path = $$[QT_INSTALL_EXAMPLES]/location/places_map +qmlcontent.path = $$[QT_INSTALL_EXAMPLES]/location/places_map INSTALLS += target qmlcontent diff --git a/examples/positioning/flickr/flickr.pro b/examples/positioning/flickr/flickr.pro index 9014935d..1d7cce50 100644 --- a/examples/positioning/flickr/flickr.pro +++ b/examples/positioning/flickr/flickr.pro @@ -7,10 +7,9 @@ SOURCES += qmllocationflickr.cpp RESOURCES += \ flickr.qrc -OTHER_FILES += flickr.qml +OTHER_FILES += flickr.qml \ + flickrcommon/* \ + flickrmobile/* -target.path = $$[QT_INSTALL_EXAMPLES]/qtpositioning/flickr -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro *.qml flickrcommon flickrmobile -sources.path = $$[QT_INSTALL_EXAMPLES]/qtpositioning/flickr - -INSTALLS += target sources +target.path = $$[QT_INSTALL_EXAMPLES]/positioning/flickr +INSTALLS += target diff --git a/examples/positioning/logfilepositionsource/logfilepositionsource.pro b/examples/positioning/logfilepositionsource/logfilepositionsource.pro index bd00a169..eb492340 100644 --- a/examples/positioning/logfilepositionsource/logfilepositionsource.pro +++ b/examples/positioning/logfilepositionsource/logfilepositionsource.pro @@ -9,8 +9,8 @@ SOURCES = logfilepositionsource.cpp \ clientapplication.cpp \ main.cpp -target.path = $$[QT_INSTALL_EXAMPLES]/qtpositioning/logfilepositionsource -sources.files = $$SOURCES $$HEADERS *.pro simplelog.txt -sources.path = $$[QT_INSTALL_EXAMPLES]/qtpositioning/logfilepositionsource -INSTALLS += target sources +target.path = $$[QT_INSTALL_EXAMPLES]/positioning/logfilepositionsource +log.files = simplelog.txt +log.path = $$[QT_INSTALL_EXAMPLES]/positioning/logfilepositionsource +INSTALLS += target log diff --git a/examples/positioning/weatherinfo/components/BigForecastIcon.qml b/examples/positioning/weatherinfo/components/BigForecastIcon.qml index 6583d6d3..16e99bf8 100644 --- a/examples/positioning/weatherinfo/components/BigForecastIcon.qml +++ b/examples/positioning/weatherinfo/components/BigForecastIcon.qml @@ -70,7 +70,10 @@ Item { Text { text: current.bottomText - font.pointSize: 28 + font.pointSize: 23 + wrapMode: Text.WordWrap + width: parent.width + horizontalAlignment: Text.AlignRight anchors { bottom: current.bottom right: current.right diff --git a/examples/positioning/weatherinfo/weatherinfo.pro b/examples/positioning/weatherinfo/weatherinfo.pro index 1470b8a0..e2b2102d 100644 --- a/examples/positioning/weatherinfo/weatherinfo.pro +++ b/examples/positioning/weatherinfo/weatherinfo.pro @@ -9,14 +9,13 @@ SOURCES += main.cpp \ OTHER_FILES += weatherinfo.qml \ components/WeatherIcon.qml \ components/ForecastIcon.qml \ - components/BigForecastIcon.qml + components/BigForecastIcon.qml \ + icons/* + RESOURCES += weatherinfo.qrc HEADERS += appmodel.h -#install -target.path = $$[QT_INSTALL_EXAMPLES]/qtpositioning/weatherinfo -sources.files = $$SOURCES $HEADERS $$RESOURCES $$FORMS *.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/qtpositioning/weatherinfo -INSTALLS += target sources +target.path = $$[QT_INSTALL_EXAMPLES]/positioning/weatherinfo +INSTALLS += target diff --git a/src/imports/location/declarativeplaces/qdeclarativeplace.cpp b/src/imports/location/declarativeplaces/qdeclarativeplace.cpp index 49e61769..985de8db 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplace.cpp +++ b/src/imports/location/declarativeplaces/qdeclarativeplace.cpp @@ -46,6 +46,8 @@ #include "qdeclarativeplaceicon_p.h" #include "error_messages.h" +#include <QtCore/QCoreApplication> +#include <QtCore/QMetaObject> #include <QtQml/QQmlEngine> #include <QtQml/QQmlInfo> #include <QtLocation/QGeoServiceProvider> @@ -54,7 +56,6 @@ #include <QtLocation/QPlaceReply> #include <QtLocation/QPlaceIdReply> #include <QtLocation/QPlaceContactDetail> -#include <QCoreApplication> QT_USE_NAMESPACE @@ -965,7 +966,7 @@ void QDeclarativePlace::category_clear(QQmlListProperty<QDeclarativeCategory> *p object->m_categories.clear(); object->m_src.setCategories(QList<QPlaceCategory>()); emit object->categoriesChanged(); - QTimer::singleShot(0, object, SLOT(cleanupDeletedCategories())); + QMetaObject::invokeMethod(object, "cleanupDeletedCategories", Qt::QueuedConnection); } /*! diff --git a/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp index 6f0ad05e..2308ba96 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp +++ b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp @@ -121,26 +121,6 @@ int QDeclarativePlaceContentModel::totalCount() const /*! \internal -*/ -static QPair<int, int> findMissingKey(const QMap<int, QPlaceContent> &map) -{ - int start = 0; - while (map.contains(start)) - ++start; - - QMap<int, QPlaceContent>::const_iterator it = map.lowerBound(start); - if (it == map.end()) - return qMakePair(start, -1); - - int end = start; - while (!map.contains(end)) - ++end; - - return qMakePair(start, end - 1); -} - -/*! - \internal Clears the model data but does not reset it. */ void QDeclarativePlaceContentModel::clearData() @@ -160,6 +140,8 @@ void QDeclarativePlaceContentModel::clearData() m_reply->deleteLater(); m_reply = 0; } + + m_nextRequest.clear(); } /*! @@ -288,22 +270,17 @@ void QDeclarativePlaceContentModel::fetchMore(const QModelIndex &parent) if (!placeManager) return; - QPlaceContentRequest request; - request.setContentType(m_type); - - if (m_contentCount == -1) { - request.setOffset(0); + if (m_nextRequest == QPlaceContentRequest()) { + QPlaceContentRequest request; + request.setContentType(m_type); + request.setPlaceId(m_place->place().placeId()); request.setLimit(m_batchSize); + + m_reply = placeManager->getPlaceContent(request); } else { - QPair<int, int> missing = findMissingKey(m_content); - request.setOffset(missing.first); - if (missing.second == -1) - request.setLimit(m_batchSize); - else - request.setLimit(qMin(m_batchSize, missing.second - missing.first + 1)); + m_reply = placeManager->getPlaceContent(m_nextRequest); } - m_reply = placeManager->getPlaceContent(m_place->place().placeId(), request); connect(m_reply, SIGNAL(finished()), this, SLOT(fetchFinished()), Qt::QueuedConnection); } @@ -334,6 +311,8 @@ void QDeclarativePlaceContentModel::fetchFinished() QPlaceContentReply *reply = m_reply; m_reply = 0; + m_nextRequest = reply->nextPageRequest(); + if (m_contentCount != reply->totalCount()) { m_contentCount = reply->totalCount(); emit totalCountChanged(); @@ -409,6 +388,12 @@ void QDeclarativePlaceContentModel::fetchFinished() startIndex = -1; } } + + // The fetch didn't add any new content and we haven't fetched all content yet. This is + // likely due to the model being prepopulated by Place::getDetails(). Keep fetching more + // data until new content is available. + if (newIndexes.isEmpty() && m_content.count() != m_contentCount) + fetchMore(QModelIndex()); } reply->deleteLater(); diff --git a/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.h b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.h index 930726cb..b5a8a56d 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.h +++ b/src/imports/location/declarativeplaces/qdeclarativeplacecontentmodel.h @@ -120,6 +120,7 @@ private: int m_contentCount; QPlaceContentReply *m_reply; + QPlaceContentRequest m_nextRequest; bool m_complete; }; diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.cpp b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.cpp index 217ff9da..d773c3b9 100644 --- a/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.cpp +++ b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.cpp @@ -43,6 +43,7 @@ #include "qdeclarativeplace_p.h" #include "error_messages.h" +#include <QtCore/QCoreApplication> #include <QtQml/QQmlInfo> #include <QtLocation/QGeoServiceProvider> #include <QtLocation/QPlaceManager> @@ -119,41 +120,37 @@ void QDeclarativeSearchModelBase::setSearchArea(const QVariant &searchArea) /*! \internal */ -int QDeclarativeSearchModelBase::offset() const +int QDeclarativeSearchModelBase::limit() const { - return m_request.offset(); + return m_request.limit(); } /*! \internal */ -void QDeclarativeSearchModelBase::setOffset(int offset) +void QDeclarativeSearchModelBase::setLimit(int limit) { - if (m_request.offset() == offset) + if (m_request.limit() == limit) return; - m_request.setOffset(offset); - emit offsetChanged(); + m_request.setLimit(limit); + emit limitChanged(); } /*! \internal */ -int QDeclarativeSearchModelBase::limit() const +bool QDeclarativeSearchModelBase::previousPagesAvailable() const { - return m_request.limit(); + return m_previousPageRequest != QPlaceSearchRequest(); } /*! \internal */ -void QDeclarativeSearchModelBase::setLimit(int limit) +bool QDeclarativeSearchModelBase::nextPagesAvailable() const { - if (m_request.limit() == limit) - return; - - m_request.setLimit(limit); - emit limitChanged(); + return m_nextPageRequest != QPlaceSearchRequest(); } /*! @@ -262,6 +259,30 @@ QString QDeclarativeSearchModelBase::errorString() const /*! \internal */ +void QDeclarativeSearchModelBase::previousPage() +{ + if (m_previousPageRequest == QPlaceSearchRequest()) + return; + + m_request = m_previousPageRequest; + update(); +} + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::nextPage() +{ + if (m_nextPageRequest == QPlaceSearchRequest()) + return; + + m_request = m_nextPageRequest; + update(); +} + +/*! + \internal +*/ void QDeclarativeSearchModelBase::clearData(bool suppressSignal) { Q_UNUSED(suppressSignal) @@ -319,3 +340,24 @@ void QDeclarativeSearchModelBase::pluginNameChanged() { initializePlugin(m_plugin); } + +/*! + \internal +*/ +void QDeclarativeSearchModelBase::setPreviousPageRequest(const QPlaceSearchRequest &previous) +{ + if (m_previousPageRequest == previous) + return; + + m_previousPageRequest = previous; + emit previousPagesAvailableChanged(); +} + +void QDeclarativeSearchModelBase::setNextPageRequest(const QPlaceSearchRequest &next) +{ + if (m_nextPageRequest == next) + return; + + m_nextPageRequest = next; + emit nextPagesAvailableChanged(); +} diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.h b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.h index 5b3b831c..a9516407 100644 --- a/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.h +++ b/src/imports/location/declarativeplaces/qdeclarativesearchmodelbase.h @@ -63,8 +63,9 @@ class QDeclarativeSearchModelBase : public QAbstractListModel, public QQmlParser Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) Q_PROPERTY(QVariant searchArea READ searchArea WRITE setSearchArea NOTIFY searchAreaChanged) - Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged) + Q_PROPERTY(bool previousPagesAvailable READ previousPagesAvailable NOTIFY previousPagesAvailableChanged) + Q_PROPERTY(bool nextPagesAvailable READ nextPagesAvailable NOTIFY nextPagesAvailableChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_ENUMS(Status) @@ -88,12 +89,12 @@ public: QVariant searchArea() const; void setSearchArea(const QVariant &searchArea); - int offset() const; - void setOffset(int offset); - int limit() const; void setLimit(int limit); + bool previousPagesAvailable() const; + bool nextPagesAvailable() const; + Status status() const; void setStatus(Status status, const QString &errorString = QString()); @@ -104,6 +105,9 @@ public: Q_INVOKABLE QString errorString() const; + Q_INVOKABLE void previousPage(); + Q_INVOKABLE void nextPage(); + virtual void clearData(bool suppressSignal = false); // From QQmlParserStatus @@ -113,8 +117,9 @@ public: Q_SIGNALS: void pluginChanged(); void searchAreaChanged(); - void offsetChanged(); void limitChanged(); + void previousPagesAvailableChanged(); + void nextPagesAvailableChanged(); void statusChanged(); protected: @@ -128,6 +133,8 @@ private Q_SLOTS: protected: virtual QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request) = 0; + void setPreviousPageRequest(const QPlaceSearchRequest &previous); + void setNextPageRequest(const QPlaceSearchRequest &next); QPlaceSearchRequest m_request; QDeclarativeGeoServiceProvider *m_plugin; @@ -137,6 +144,8 @@ private: bool m_complete; Status m_status; QString m_errorString; + QPlaceSearchRequest m_previousPageRequest; + QPlaceSearchRequest m_nextPageRequest; }; QT_END_NAMESPACE diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel.cpp index d9492ca2..f36f1d78 100644 --- a/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel.cpp +++ b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel.cpp @@ -223,19 +223,25 @@ QT_USE_NAMESPACE */ /*! - \qmlproperty int PlaceSearchModel::offset + \qmlproperty int PlaceSearchModel::limit - This property holds the index of the first search result in the model. + This property holds the limit of the number of items that will be returned. +*/ + +/*! + \qmlproperty bool PlaceSearchModel::previousPagesAvailable - \sa limit + This property holds whether there is one or more previous pages of search results available. + + \sa previousPage() */ /*! - \qmlproperty int PlaceSearchModel::limit + \qmlproperty bool PlaceSearchModel::nextPagesAvailable - This property holds the limit of the number of items that will be returned. + This property holds whether there is one or more additional pages of search results available. - \sa offset + \sa nextPage() */ /*! @@ -325,6 +331,20 @@ QT_USE_NAMESPACE textual representation. */ +/*! + \qmlmethod PlaceSearchModel::previousPage() + + Updates the model to display the previous page of search results. If there is no previous page + then this method does nothing. +*/ + +/*! + \qmlmethod PlaceSearchModel::nextPage() + + Updates the model to display the next page of search results. If there is no next page then + this method does nothing. +*/ + QDeclarativeSearchResultModel::QDeclarativeSearchResultModel(QObject *parent) : QDeclarativeSearchModelBase(parent), m_favoritesPlugin(0) { @@ -730,6 +750,9 @@ void QDeclarativeSearchResultModel::queryFinished() Q_ASSERT(searchReply); m_resultsBuffer = searchReply->results(); + setPreviousPageRequest(searchReply->previousPageRequest()); + setNextPageRequest(searchReply->nextPageRequest()); + reply->deleteLater(); if (!m_favoritesPlugin) { diff --git a/src/imports/location/qdeclarativegeocodemodel.cpp b/src/imports/location/qdeclarativegeocodemodel.cpp index 797f7ee8..2159e70a 100644 --- a/src/imports/location/qdeclarativegeocodemodel.cpp +++ b/src/imports/location/qdeclarativegeocodemodel.cpp @@ -42,10 +42,11 @@ #include "qdeclarativegeocodemodel_p.h" #include "error_messages.h" -#include <QtQml/qqmlinfo.h> +#include <QtCore/QCoreApplication> +#include <QtQml/QQmlInfo> +#include <QtPositioning/QGeoCircle> #include <QtLocation/QGeoServiceProvider> #include <QtLocation/QGeoCodingManager> -#include <QtPositioning/QGeoCircle> QT_BEGIN_NAMESPACE diff --git a/src/imports/location/qdeclarativegeoroutemodel.cpp b/src/imports/location/qdeclarativegeoroutemodel.cpp index f315cea2..829398cf 100644 --- a/src/imports/location/qdeclarativegeoroutemodel.cpp +++ b/src/imports/location/qdeclarativegeoroutemodel.cpp @@ -286,7 +286,14 @@ void QDeclarativeGeoRouteModel::setPlugin(QDeclarativeGeoServiceProvider *plugin return; reset(); // reset the model + + if (plugin_) + disconnect(plugin_, SIGNAL(localesChanged()), this, SIGNAL(measurementSystemChanged())); + if (plugin) + connect(plugin, SIGNAL(localesChanged()), this, SIGNAL(measurementSystemChanged())); + plugin_ = plugin; + if (complete_) emit pluginChanged(); @@ -408,6 +415,65 @@ bool QDeclarativeGeoRouteModel::autoUpdate() const } /*! + \qmlproperty Locale::MeasurementSystem QtLocation::RouteModel::measurementSystem + + This property holds the measurement system which will be used when calculating the route. This + property is changed when the \l {QtLocation::Plugin::locales}{Plugin::locales} property of + \l {QtLocation::RouteModel::plugin}{plugin} changes. + + If setting this property it must be set after the \l {QtLocation::RouteModel::plugin}{plugin} + property is set. +*/ +void QDeclarativeGeoRouteModel::setMeasurementSystem(QLocale::MeasurementSystem ms) +{ + if (!plugin_) { + qmlInfo(this) << QCoreApplication::translate(CONTEXT_NAME, ROUTE_PLUGIN_NOT_SET); + return; + } + + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + if (!serviceProvider) + return; + + QGeoRoutingManager *routingManager = serviceProvider->routingManager(); + if (!routingManager) { + qmlInfo(this) << QCoreApplication::translate(CONTEXT_NAME, ROUTE_MGR_NOT_SET); + return; + } + + if (routingManager->measurementSystem() == ms) + return; + + routingManager->setMeasurementSystem(ms); + emit measurementSystemChanged(); +} + +QLocale::MeasurementSystem QDeclarativeGeoRouteModel::measurementSystem() const +{ + if (!plugin_) + return QLocale().measurementSystem(); + + QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); + if (!serviceProvider) { + if (plugin_->locales().isEmpty()) + return QLocale().measurementSystem(); + + return QLocale(plugin_->locales().first()).measurementSystem(); + } + + QGeoRoutingManager *routingManager = serviceProvider->routingManager(); + if (!routingManager) { + qmlInfo(this) << QCoreApplication::translate(CONTEXT_NAME, ROUTE_MGR_NOT_SET); + if (plugin_->locales().isEmpty()) + return QLocale().measurementSystem(); + + return QLocale(plugin_->locales().first()).measurementSystem(); + } + + return routingManager->measurementSystem(); +} + +/*! \internal */ void QDeclarativeGeoRouteModel::setStatus(QDeclarativeGeoRouteModel::Status status) @@ -823,7 +889,7 @@ void QDeclarativeGeoRouteQuery::setExcludedAreas(const QJSValue &value) QGeoRectangle r = parseRectangle(value.property(i), &ok); if (!ok || !r.isValid()) { - qmlInfo(this) << "Unsupported waypoint type"; + qmlInfo(this) << "Unsupported area type"; return; } diff --git a/src/imports/location/qdeclarativegeoroutemodel_p.h b/src/imports/location/qdeclarativegeoroutemodel_p.h index 0d663eed..bd9b9718 100644 --- a/src/imports/location/qdeclarativegeoroutemodel_p.h +++ b/src/imports/location/qdeclarativegeoroutemodel_p.h @@ -77,6 +77,8 @@ class QDeclarativeGeoRouteModel : public QAbstractListModel, public QQmlParserSt Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged) Q_PROPERTY(RouteError error READ error NOTIFY errorChanged) + Q_PROPERTY(QLocale::MeasurementSystem measurementSystem READ measurementSystem WRITE setMeasurementSystem NOTIFY measurementSystemChanged) + Q_INTERFACES(QQmlParserStatus) public: @@ -121,6 +123,9 @@ public: void setAutoUpdate(bool autoUpdate); bool autoUpdate() const; + void setMeasurementSystem(QLocale::MeasurementSystem ms); + QLocale::MeasurementSystem measurementSystem() const; + Status status() const; QString errorString() const; RouteError error() const; @@ -139,6 +144,7 @@ Q_SIGNALS: void errorStringChanged(); void errorChanged(); void routesChanged(); + void measurementSystemChanged(); public Q_SLOTS: void update(); diff --git a/src/imports/location/qdeclarativegeoserviceprovider.cpp b/src/imports/location/qdeclarativegeoserviceprovider.cpp index f91b9ed1..da92644c 100644 --- a/src/imports/location/qdeclarativegeoserviceprovider.cpp +++ b/src/imports/location/qdeclarativegeoserviceprovider.cpp @@ -571,9 +571,9 @@ void QDeclarativeGeoServiceProvider::parameter_clear(QQmlListProperty<QDeclarati /*! \internal */ -QMap<QString, QVariant> QDeclarativeGeoServiceProvider::parameterMap() const +QVariantMap QDeclarativeGeoServiceProvider::parameterMap() const { - QMap<QString, QVariant> map; + QVariantMap map; for (int i = 0; i < parameters_.size(); ++i) { QDeclarativeGeoServiceProviderParameter *parameter = parameters_.at(i); diff --git a/src/imports/location/qdeclarativegeoserviceprovider_p.h b/src/imports/location/qdeclarativegeoserviceprovider_p.h index 75743f83..b859f803 100644 --- a/src/imports/location/qdeclarativegeoserviceprovider_p.h +++ b/src/imports/location/qdeclarativegeoserviceprovider_p.h @@ -169,7 +169,7 @@ public: QString name() const; QQmlListProperty<QDeclarativeGeoServiceProviderParameter> parameters(); - QMap<QString, QVariant> parameterMap() const; + QVariantMap parameterMap() const; QStringList availableServiceProviders(); diff --git a/src/imports/positioning/qdeclarativepositionsource.cpp b/src/imports/positioning/qdeclarativepositionsource.cpp index 1d1d3a15..a13092fc 100644 --- a/src/imports/positioning/qdeclarativepositionsource.cpp +++ b/src/imports/positioning/qdeclarativepositionsource.cpp @@ -464,14 +464,8 @@ int QDeclarativePositionSource::updateInterval() const QDeclarativePositionSource::PositioningMethods QDeclarativePositionSource::supportedPositioningMethods() const { if (m_positionSource) { - QGeoPositionInfoSource::PositioningMethods methods = m_positionSource->supportedPositioningMethods(); - if ( (methods & QGeoPositionInfoSource::AllPositioningMethods) == methods ) { - return QDeclarativePositionSource::AllPositioningMethods; - } else if (methods & QGeoPositionInfoSource::SatellitePositioningMethods) { - return QDeclarativePositionSource::SatellitePositioningMethods; - } else if (methods & QGeoPositionInfoSource::NonSatellitePositioningMethods) { - return QDeclarativePositionSource::NonSatellitePositioningMethods; - } + return static_cast<QDeclarativePositionSource::PositioningMethods>( + int(m_positionSource->supportedPositioningMethods())); } return QDeclarativePositionSource::NoPositioningMethods; } @@ -515,16 +509,8 @@ void QDeclarativePositionSource::setPreferredPositioningMethods(PositioningMetho QDeclarativePositionSource::PositioningMethods QDeclarativePositionSource::preferredPositioningMethods() const { if (m_positionSource) { - QGeoPositionInfoSource::PositioningMethods methods = - m_positionSource->preferredPositioningMethods(); - if ( (methods & QGeoPositionInfoSource::AllPositioningMethods) == methods) { - return QDeclarativePositionSource::AllPositioningMethods; - } else if (methods & QGeoPositionInfoSource::SatellitePositioningMethods) { - return QDeclarativePositionSource::SatellitePositioningMethods; - } else if (methods & QGeoPositionInfoSource::NonSatellitePositioningMethods) { - return QDeclarativePositionSource::NonSatellitePositioningMethods; - } else if (methods == QGeoPositionInfoSource::NoPositioningMethods) - return QDeclarativePositionSource::NoPositioningMethods; + return static_cast<QDeclarativePositionSource::PositioningMethods>( + int(m_positionSource->preferredPositioningMethods())); } return m_preferredPositioningMethods; } diff --git a/src/location/doc/snippets/declarative/declarative.pro b/src/location/doc/snippets/declarative/declarative.pro index 40fb082f..e6ff7ce6 100644 --- a/src/location/doc/snippets/declarative/declarative.pro +++ b/src/location/doc/snippets/declarative/declarative.pro @@ -7,6 +7,9 @@ content.files = \ routing.qml \ places_loader.qml +OTHER_FILES = \ + $${content.files} + # Put content in INSTALLS so that content.files become part of the project tree in Qt Creator, # but scoped with false as we don't actually want to install them. They are documentation # snippets. diff --git a/src/location/doc/snippets/places/requesthandler.h b/src/location/doc/snippets/places/requesthandler.h index 92e1a935..e18b6276 100644 --- a/src/location/doc/snippets/places/requesthandler.h +++ b/src/location/doc/snippets/places/requesthandler.h @@ -100,7 +100,6 @@ public: { //! [Search paging] QPlaceSearchRequest searchRequest; - searchRequest.setOffset(10); //specify the index of the first result searchRequest.setLimit(15); //specify how many results are to be retrieved. //! [Search paging] } @@ -123,9 +122,9 @@ public: //! [Image request] QPlaceContentRequest request; request.setContentType(QPlaceContent::ImageType); - request.setOffset(0); + request.setPlaceId(place.placeId()); request.setLimit(5); - /*QPlaceContentReply * */ contentReply = manager->getPlaceContent(place.placeId(), request); + /*QPlaceContentReply * */ contentReply = manager->getPlaceContent(request); connect(contentReply, SIGNAL(finished()), this, SLOT(handleImagesReply())); //! [Image request] } @@ -220,9 +219,8 @@ public: //closer places have greater weighting in the ranking of results. searchRequest.setRelevanceHint(QPlaceSearchRequest::DistanceHint); - //use offset and limit to provide pagination. - //this retrieves the next 5 items from the 10th index - searchRequest.setOffset(9); + //use limit to adjust pagination. + //this limits the number of place results to 5 per page. searchRequest.setLimit(5); //provide some categories to narrow down search @@ -237,10 +235,10 @@ public: //! [Content request] QPlaceContentRequest request; request.setContentType(QPlaceContent::ImageType); - request.setOffset(9); + request.setPlaceId(place.placeId()); request.setLimit(5); - QPlaceContentReply *contentReply = manager->getPlaceContent(place.placeId(), request); + QPlaceContentReply *contentReply = manager->getPlaceContent(request); //..connect signals..// //! [Content request] diff --git a/src/location/doc/src/places.qdoc b/src/location/doc/src/places.qdoc index 62a6d0d5..74a25b79 100644 --- a/src/location/doc/src/places.qdoc +++ b/src/location/doc/src/places.qdoc @@ -248,7 +248,7 @@ Any places similar to the given place are retrieved. \section3 Paging - If the plugin supports paging, limit and offset parameters may be provided to the search request. + If the plugin supports paging, the limit parameter may be provided to the search request. \snippet places/requesthandler.h Search paging \section2 Fetching Place Details diff --git a/src/location/doc/src/plugins/nokia.qdoc b/src/location/doc/src/plugins/nokia.qdoc index 181acbb8..2ab29fb2 100644 --- a/src/location/doc/src/plugins/nokia.qdoc +++ b/src/location/doc/src/plugins/nokia.qdoc @@ -85,7 +85,7 @@ The following table lists optional parameters that can be passed to the Nokia pl \li mapping.cache.directory \li Map tile cache directory used as network disk cache. - Default place for the cache is "QtLocation" directory in \l {QStandardPaths::writableLocation(QStandardPaths::CacheLocation)}. + Default place for the cache is "QtLocation" directory in \l {QStandardPaths::writableLocation()} {QStandardPaths::writableLocation}(\l{QStandardPaths::GenericCacheLocation}). \row \li mapping.cache.disk.size \li Map tile disk cache size in bytes. Default size of the cache is 20MB. diff --git a/src/location/maps/qgeocodingmanagerengine.cpp b/src/location/maps/qgeocodingmanagerengine.cpp index f3aa2870..965f09a5 100644 --- a/src/location/maps/qgeocodingmanagerengine.cpp +++ b/src/location/maps/qgeocodingmanagerengine.cpp @@ -84,7 +84,7 @@ QT_BEGIN_NAMESPACE Constructs a new engine with the specified \a parent, using \a parameters to pass any implementation specific data to the engine. */ -QGeoCodingManagerEngine::QGeoCodingManagerEngine(const QMap<QString, QVariant> ¶meters, QObject *parent) +QGeoCodingManagerEngine::QGeoCodingManagerEngine(const QVariantMap ¶meters, QObject *parent) : QObject(parent), d_ptr(new QGeoCodingManagerEnginePrivate()) { diff --git a/src/location/maps/qgeocodingmanagerengine.h b/src/location/maps/qgeocodingmanagerengine.h index aa2839a0..11862db3 100644 --- a/src/location/maps/qgeocodingmanagerengine.h +++ b/src/location/maps/qgeocodingmanagerengine.h @@ -56,7 +56,7 @@ class Q_LOCATION_EXPORT QGeoCodingManagerEngine : public QObject { Q_OBJECT public: - QGeoCodingManagerEngine(const QMap<QString, QVariant> ¶meters, QObject *parent = 0); + QGeoCodingManagerEngine(const QVariantMap ¶meters, QObject *parent = 0); virtual ~QGeoCodingManagerEngine(); QString managerName() const; diff --git a/src/location/maps/qgeomappingmanagerengine_p.h b/src/location/maps/qgeomappingmanagerengine_p.h index 903ac14b..a26a4cbd 100644 --- a/src/location/maps/qgeomappingmanagerengine_p.h +++ b/src/location/maps/qgeomappingmanagerengine_p.h @@ -87,7 +87,7 @@ public: virtual QGeoMapData *createMapData() = 0; - QMap<QString, QVariant> parameters() const; + QVariantMap parameters() const; QString managerName() const; int managerVersion() const; diff --git a/src/location/maps/qgeoroutingmanager.cpp b/src/location/maps/qgeoroutingmanager.cpp index 5637a269..07af687b 100644 --- a/src/location/maps/qgeoroutingmanager.cpp +++ b/src/location/maps/qgeoroutingmanager.cpp @@ -347,6 +347,33 @@ QLocale QGeoRoutingManager::locale() const } /*! + Sets the measurement system used by this manager to \a system. + + The measurement system can be set independently of the locale. Both setLocale() and this + function set the measurement system. The value set by the last function called will be used. + + \sa measurementSystem(), locale(), setLocale() +*/ +void QGeoRoutingManager::setMeasurementSystem(QLocale::MeasurementSystem system) +{ + d_ptr->engine->setMeasurementSystem(system); +} + +/*! + Returns the measurement system used by this manager. + + If setMeasurementSystem() has been called then the value returned by this function may be + different to that returned by locale().\l {QLocale::measurementSystem()}{measurementSystem()}. + In which case the value returned by this function is what will be used by the manager. + + \sa setMeasurementSystem(), setLocale() +*/ +QLocale::MeasurementSystem QGeoRoutingManager::measurementSystem() const +{ + return d_ptr->engine->measurementSystem(); +} + +/*! \fn void QGeoRoutingManager::finished(QGeoRouteReply *reply) This signal is emitted when \a reply has finished processing. diff --git a/src/location/maps/qgeoroutingmanager.h b/src/location/maps/qgeoroutingmanager.h index d9ff6816..72dfc370 100644 --- a/src/location/maps/qgeoroutingmanager.h +++ b/src/location/maps/qgeoroutingmanager.h @@ -42,22 +42,20 @@ #ifndef QGEOROUTINGMANAGER_H #define QGEOROUTINGMANAGER_H +#include <QtCore/QObject> +#include <QtCore/QLocale> #include <QtLocation/QGeoRouteRequest> #include <QtLocation/QGeoRouteReply> -#include <QObject> -#include <QMap> - QT_BEGIN_NAMESPACE -class QLocale; - class QGeoRoutingManagerEngine; class QGeoRoutingManagerPrivate; class Q_LOCATION_EXPORT QGeoRoutingManager : public QObject { Q_OBJECT + public: ~QGeoRoutingManager(); @@ -76,6 +74,8 @@ public: void setLocale(const QLocale &locale); QLocale locale() const; + void setMeasurementSystem(QLocale::MeasurementSystem system); + QLocale::MeasurementSystem measurementSystem() const; Q_SIGNALS: void finished(QGeoRouteReply *reply); diff --git a/src/location/maps/qgeoroutingmanagerengine.cpp b/src/location/maps/qgeoroutingmanagerengine.cpp index 8629bcb5..7b81d7a6 100644 --- a/src/location/maps/qgeoroutingmanagerengine.cpp +++ b/src/location/maps/qgeoroutingmanagerengine.cpp @@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE Constructs a new engine with the specified \a parent, using \a parameters to pass any implementation specific data to the engine. */ -QGeoRoutingManagerEngine::QGeoRoutingManagerEngine(const QMap<QString, QVariant> ¶meters, QObject *parent) +QGeoRoutingManagerEngine::QGeoRoutingManagerEngine(const QVariantMap ¶meters, QObject *parent) : QObject(parent), d_ptr(new QGeoRoutingManagerEnginePrivate()) { @@ -347,6 +347,7 @@ QGeoRouteRequest::ManeuverDetails QGeoRoutingManagerEngine::supportedManeuverDet void QGeoRoutingManagerEngine::setLocale(const QLocale &locale) { d_ptr->locale = locale; + d_ptr->measurementSystem = locale.measurementSystem(); } /*! @@ -359,6 +360,33 @@ QLocale QGeoRoutingManagerEngine::locale() const } /*! + Sets the measurement system used by this manager to \a system. + + The measurement system can be set independently of the locale. Both setLocale() and this + function set the measurement system. The value set by the last function called will be used. + + \sa measurementSystem(), locale(), setLocale() +*/ +void QGeoRoutingManagerEngine::setMeasurementSystem(QLocale::MeasurementSystem system) +{ + d_ptr->measurementSystem = system; +} + +/*! + Returns the measurement system used by this manager. + + If setMeasurementSystem() has been called then the value returned by this function may be + different to that returned by locale().\l {QLocale::measurementSystem()}{measurementSystem()}. + In which case the value returned by this function is what will be used by the manager. + + \sa setMeasurementSystem(), setLocale() +*/ +QLocale::MeasurementSystem QGeoRoutingManagerEngine::measurementSystem() const +{ + return d_ptr->measurementSystem; +} + +/*! \fn void QGeoRoutingManagerEngine::finished(QGeoRouteReply *reply) This signal is emitted when \a reply has finished processing. @@ -391,7 +419,7 @@ Use deleteLater() instead. *******************************************************************************/ QGeoRoutingManagerEnginePrivate::QGeoRoutingManagerEnginePrivate() - : managerVersion(-1) +: managerVersion(-1), measurementSystem(locale.measurementSystem()) { } diff --git a/src/location/maps/qgeoroutingmanagerengine.h b/src/location/maps/qgeoroutingmanagerengine.h index fa05b984..1e05b890 100644 --- a/src/location/maps/qgeoroutingmanagerengine.h +++ b/src/location/maps/qgeoroutingmanagerengine.h @@ -42,23 +42,21 @@ #ifndef QGEOROUTINGMANAGERENGINE_H #define QGEOROUTINGMANAGERENGINE_H +#include <QtCore/QObject> +#include <QtCore/QMap> +#include <QtCore/QLocale> #include <QtLocation/QGeoRouteRequest> #include <QtLocation/QGeoRouteReply> -#include <QObject> -#include <QMap> - QT_BEGIN_NAMESPACE -class QLocale; - class QGeoRoutingManagerEnginePrivate; class Q_LOCATION_EXPORT QGeoRoutingManagerEngine : public QObject { Q_OBJECT public: - QGeoRoutingManagerEngine(const QMap<QString, QVariant> ¶meters, QObject *parent = 0); + QGeoRoutingManagerEngine(const QVariantMap ¶meters, QObject *parent = 0); virtual ~QGeoRoutingManagerEngine(); QString managerName() const; @@ -76,6 +74,8 @@ public: void setLocale(const QLocale &locale); QLocale locale() const; + void setMeasurementSystem(QLocale::MeasurementSystem system); + QLocale::MeasurementSystem measurementSystem() const; Q_SIGNALS: void finished(QGeoRouteReply *reply); diff --git a/src/location/maps/qgeoroutingmanagerengine_p.h b/src/location/maps/qgeoroutingmanagerengine_p.h index e868fad8..ad6f8660 100644 --- a/src/location/maps/qgeoroutingmanagerengine_p.h +++ b/src/location/maps/qgeoroutingmanagerengine_p.h @@ -77,6 +77,7 @@ public: QGeoRouteRequest::ManeuverDetails supportedManeuverDetails; QLocale locale; + QLocale::MeasurementSystem measurementSystem; private: Q_DISABLE_COPY(QGeoRoutingManagerEnginePrivate) diff --git a/src/location/maps/qgeoserviceprovider.cpp b/src/location/maps/qgeoserviceprovider.cpp index c91ef8a5..2babbba6 100644 --- a/src/location/maps/qgeoserviceprovider.cpp +++ b/src/location/maps/qgeoserviceprovider.cpp @@ -641,7 +641,7 @@ void QGeoServiceProviderPrivate::loadMeta() } } -void QGeoServiceProviderPrivate::loadPlugin(const QMap<QString, QVariant> ¶meters) +void QGeoServiceProviderPrivate::loadPlugin(const QVariantMap ¶meters) { Q_UNUSED(parameters) diff --git a/src/location/maps/qgeoserviceprovider_p.h b/src/location/maps/qgeoserviceprovider_p.h index 1ec19c89..1d92149e 100644 --- a/src/location/maps/qgeoserviceprovider_p.h +++ b/src/location/maps/qgeoserviceprovider_p.h @@ -75,7 +75,7 @@ public: ~QGeoServiceProviderPrivate(); void loadMeta(); - void loadPlugin(const QMap<QString, QVariant> ¶meters); + void loadPlugin(const QVariantMap ¶meters); void unload(); /* helper templates for generating the feature and manager accessors */ @@ -88,7 +88,7 @@ public: QGeoServiceProviderFactory *factory; QJsonObject metaData; - QMap<QString, QVariant> parameterMap; + QVariantMap parameterMap; bool experimental; diff --git a/src/location/maps/qgeoserviceproviderfactory.cpp b/src/location/maps/qgeoserviceproviderfactory.cpp index 8fbfb3d7..b1c7759c 100644 --- a/src/location/maps/qgeoserviceproviderfactory.cpp +++ b/src/location/maps/qgeoserviceproviderfactory.cpp @@ -78,7 +78,7 @@ Destroys this QGeoServiceProviderFactory instance. The default implementation returns 0, which causes a QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. */ -QGeoCodingManagerEngine *QGeoServiceProviderFactory::createGeocodingManagerEngine(const QMap<QString, QVariant> ¶meters, +QGeoCodingManagerEngine *QGeoServiceProviderFactory::createGeocodingManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const { @@ -104,7 +104,7 @@ QGeoCodingManagerEngine *QGeoServiceProviderFactory::createGeocodingManagerEngin \internal */ -QGeoMappingManagerEngine *QGeoServiceProviderFactory::createMappingManagerEngine(const QMap<QString, QVariant> ¶meters, +QGeoMappingManagerEngine *QGeoServiceProviderFactory::createMappingManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const { @@ -128,7 +128,7 @@ QGeoMappingManagerEngine *QGeoServiceProviderFactory::createMappingManagerEngine The default implementation returns 0, which causes a QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. */ -QGeoRoutingManagerEngine *QGeoServiceProviderFactory::createRoutingManagerEngine(const QMap<QString, QVariant> ¶meters, +QGeoRoutingManagerEngine *QGeoServiceProviderFactory::createRoutingManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const @@ -153,7 +153,7 @@ QGeoRoutingManagerEngine *QGeoServiceProviderFactory::createRoutingManagerEngine The default implementation returns 0, which causes a QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. */ -QPlaceManagerEngine *QGeoServiceProviderFactory::createPlaceManagerEngine(const QMap<QString, QVariant> ¶meters, +QPlaceManagerEngine *QGeoServiceProviderFactory::createPlaceManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const diff --git a/src/location/maps/qgeoserviceproviderfactory.h b/src/location/maps/qgeoserviceproviderfactory.h index 28c27ef0..b2843301 100644 --- a/src/location/maps/qgeoserviceproviderfactory.h +++ b/src/location/maps/qgeoserviceproviderfactory.h @@ -55,16 +55,16 @@ class Q_LOCATION_EXPORT QGeoServiceProviderFactory public: virtual ~QGeoServiceProviderFactory() {} - virtual QGeoCodingManagerEngine *createGeocodingManagerEngine(const QMap<QString, QVariant> ¶meters, + virtual QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; - virtual QGeoMappingManagerEngine *createMappingManagerEngine(const QMap<QString, QVariant> ¶meters, + virtual QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; - virtual QGeoRoutingManagerEngine *createRoutingManagerEngine(const QMap<QString, QVariant> ¶meters, + virtual QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; - virtual QPlaceManagerEngine *createPlaceManagerEngine(const QMap<QString, QVariant> ¶meters, + virtual QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; }; diff --git a/src/location/maps/qgeotilecache.cpp b/src/location/maps/qgeotilecache.cpp index 70709ce5..8a86b7c4 100644 --- a/src/location/maps/qgeotilecache.cpp +++ b/src/location/maps/qgeotilecache.cpp @@ -116,7 +116,7 @@ QGeoTileCache::QGeoTileCache(const QString &directory, QObject *parent) // of course override them) if (directory_.isEmpty()) { - directory_ = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + directory_ = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1String("/QtLocation"); QDir::root().mkpath(directory_); } @@ -318,8 +318,7 @@ QSharedPointer<QGeoTileTexture> QGeoTileCache::get(const QGeoTileSpec &spec) file.close(); QPixmap pixmap; - const char *format = (parts.size() == 2 ? parts.at(1).toLocal8Bit().constData() : 0); - if (!pixmap.loadFromData(bytes, format)) { + if (!pixmap.loadFromData(bytes, (parts.size() == 2 ? parts.at(1).toLocal8Bit().constData() : 0))) { handleError(spec, QLatin1String("Problem with tile image")); return QSharedPointer<QGeoTileTexture>(0); } diff --git a/src/location/maps/qgeotiledmappingmanagerengine.cpp b/src/location/maps/qgeotiledmappingmanagerengine.cpp index 6b60a1ce..c0382b1a 100644 --- a/src/location/maps/qgeotiledmappingmanagerengine.cpp +++ b/src/location/maps/qgeotiledmappingmanagerengine.cpp @@ -327,9 +327,6 @@ QGeoTiledMappingManagerEnginePrivate::~QGeoTiledMappingManagerEnginePrivate() { delete tileCache_; - // but we still want to stop the fetcher's timer immediately - fetcher_->stopTimer(); - // will delete fetcher and thread later thread_->exit(); } diff --git a/src/location/maps/qgeotilefetcher.cpp b/src/location/maps/qgeotilefetcher.cpp index 450bf322..a86c0a43 100644 --- a/src/location/maps/qgeotilefetcher.cpp +++ b/src/location/maps/qgeotilefetcher.cpp @@ -39,6 +39,8 @@ ** ****************************************************************************/ +#include <QtCore/QTimerEvent> + #include "qgeomappingmanagerengine_p.h" #include "qgeotilefetcher_p.h" #include "qgeotilefetcher_p_p.h" @@ -66,21 +68,10 @@ void QGeoTileFetcher::threadStarted() { Q_D(QGeoTileFetcher); - if (d->stopped_) - return; - - d->timer_ = new QTimer(this); - - d->timer_->setInterval(0); - - connect(d->timer_, - SIGNAL(timeout()), - this, - SLOT(requestNextTile())); + d->enabled_ = true; - d->started_ = true; if (!d->queue_.isEmpty()) - d->timer_->start(); + d->timer_.start(0, this); } bool QGeoTileFetcher::init() @@ -88,19 +79,12 @@ bool QGeoTileFetcher::init() return false; } -void QGeoTileFetcher::stopTimer() +void QGeoTileFetcher::threadFinished() { Q_D(QGeoTileFetcher); - d->stopped_ = true; - if (d->timer_) { - disconnect(d->timer_); - d->timer_->stop(); - } -} -void QGeoTileFetcher::threadFinished() -{ - stopTimer(); + d->enabled_ = false; + d->timer_.stop(); this->deleteLater(); } @@ -111,15 +95,12 @@ void QGeoTileFetcher::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded, QMutexLocker ml(&d->queueMutex_); - if (d->stopped_) - return; - cancelTileRequests(tilesRemoved); d->queue_ += tilesAdded.toList(); - if (!d->queue_.empty()) - d->timer_->start(); + if (d->enabled_ && !d->queue_.isEmpty() && !d->timer_.isActive()) + d->timer_.start(0, this); } void QGeoTileFetcher::cancelTileRequests(const QSet<QGeoTileSpec> &tiles) @@ -139,9 +120,6 @@ void QGeoTileFetcher::cancelTileRequests(const QSet<QGeoTileSpec> &tiles) } d->queue_.removeAll(*tile); } - - if (d->queue_.isEmpty()) - d->timer_->stop(); } void QGeoTileFetcher::requestNextTile() @@ -150,13 +128,11 @@ void QGeoTileFetcher::requestNextTile() QMutexLocker ml(&d->queueMutex_); - if (d->stopped_) + if (!d->enabled_) return; - if (d->queue_.isEmpty()) { - d->timer_->stop(); + if (d->queue_.isEmpty()) return; - } QGeoTileSpec ts = d->queue_.takeFirst(); @@ -175,7 +151,7 @@ void QGeoTileFetcher::requestNextTile() } if (d->queue_.isEmpty()) - d->timer_->stop(); + d->timer_.stop(); } void QGeoTileFetcher::finished() @@ -200,11 +176,27 @@ void QGeoTileFetcher::finished() handleReply(reply, spec); } +void QGeoTileFetcher::timerEvent(QTimerEvent *event) +{ + Q_D(QGeoTileFetcher); + if (event->timerId() != d->timer_.timerId()) { + QObject::timerEvent(event); + return; + } + + if (d->queue_.isEmpty()) { + d->timer_.stop(); + return; + } + + requestNextTile(); +} + void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec) { Q_D(QGeoTileFetcher); - if (d->stopped_) { + if (!d->enabled_) { reply->deleteLater(); return; } @@ -222,21 +214,12 @@ void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec & *******************************************************************************/ QGeoTileFetcherPrivate::QGeoTileFetcherPrivate(QGeoTiledMappingManagerEngine *engine) - : engine_(engine), - started_(false), - stopped_(false), - timer_(0) {} +: engine_(engine), enabled_(false) +{ +} QGeoTileFetcherPrivate::~QGeoTileFetcherPrivate() { } QT_END_NAMESPACE - - - - - - - - diff --git a/src/location/maps/qgeotilefetcher_p.h b/src/location/maps/qgeotilefetcher_p.h index 45e38e05..d08092b9 100644 --- a/src/location/maps/qgeotilefetcher_p.h +++ b/src/location/maps/qgeotilefetcher_p.h @@ -74,7 +74,6 @@ class Q_LOCATION_EXPORT QGeoTileFetcher : public QObject public: QGeoTileFetcher(QGeoTiledMappingManagerEngine *engine, QObject *parent = 0); virtual ~QGeoTileFetcher(); - void stopTimer(); public Q_SLOTS: void threadStarted(); @@ -91,6 +90,7 @@ Q_SIGNALS: void tileError(const QGeoTileSpec &spec, const QString &errorString); protected: + void timerEvent(QTimerEvent *event); virtual bool init(); QGeoTiledMappingManagerEngine::CacheAreas cacheHint() const; diff --git a/src/location/maps/qgeotilefetcher_p_p.h b/src/location/maps/qgeotilefetcher_p_p.h index ba71a750..c47f8f90 100644 --- a/src/location/maps/qgeotilefetcher_p_p.h +++ b/src/location/maps/qgeotilefetcher_p_p.h @@ -78,9 +78,8 @@ public: QGeoTiledMappingManagerEngine *engine_; - bool started_; - bool stopped_; - QTimer *timer_; + bool enabled_; + QBasicTimer timer_; QMutex queueMutex_; QList<QGeoTileSpec> queue_; QHash<QGeoTileSpec, QGeoTiledMapReply *> invmap_; diff --git a/src/location/places/qplacecontentreply.cpp b/src/location/places/qplacecontentreply.cpp index 23252ea0..3b7d40f2 100644 --- a/src/location/places/qplacecontentreply.cpp +++ b/src/location/places/qplacecontentreply.cpp @@ -53,6 +53,8 @@ public: QPlaceContent::Collection contentCollection; int totalCount; QPlaceContentRequest contentRequest; + QPlaceContentRequest previousPageRequest; + QPlaceContentRequest nextPageRequest; }; QT_END_NAMESPACE @@ -145,6 +147,26 @@ QPlaceContentRequest QPlaceContentReply::request() const } /*! + Returns a place content request that can be used to request the previous batch of place content + results. +*/ +QPlaceContentRequest QPlaceContentReply::previousPageRequest() const +{ + Q_D(const QPlaceContentReply); + return d->previousPageRequest; +} + +/*! + Returns a place content request that can be used to request the next batch of place content + results. +*/ +QPlaceContentRequest QPlaceContentReply::nextPageRequest() const +{ + Q_D(const QPlaceContentReply); + return d->nextPageRequest; +} + +/*! Sets the content \a request used to generate this this reply. */ void QPlaceContentReply::setRequest(const QPlaceContentRequest &request) @@ -152,3 +174,23 @@ void QPlaceContentReply::setRequest(const QPlaceContentRequest &request) Q_D(QPlaceContentReply); d->contentRequest = request; } + +/*! + Sets the place content request that can be used to request the previous batch of place content + results to \a previous. +*/ +void QPlaceContentReply::setPreviousPageRequest(const QPlaceContentRequest &previous) +{ + Q_D(QPlaceContentReply); + d->previousPageRequest = previous; +} + +/*! + Sets the place content request that can be used to request the next batch of place content + results to \a next. +*/ +void QPlaceContentReply::setNextPageRequest(const QPlaceContentRequest &next) +{ + Q_D(QPlaceContentReply); + d->nextPageRequest = next; +} diff --git a/src/location/places/qplacecontentreply.h b/src/location/places/qplacecontentreply.h index 8d781a46..dcdcddc4 100644 --- a/src/location/places/qplacecontentreply.h +++ b/src/location/places/qplacecontentreply.h @@ -65,10 +65,15 @@ public: QPlaceContentRequest request() const; + QPlaceContentRequest previousPageRequest() const; + QPlaceContentRequest nextPageRequest() const; + protected: void setContent(const QPlaceContent::Collection &content); void setTotalCount(int total); void setRequest(const QPlaceContentRequest &request); + void setPreviousPageRequest(const QPlaceContentRequest &previous); + void setNextPageRequest(const QPlaceContentRequest &next); private: Q_DISABLE_COPY(QPlaceContentReply) diff --git a/src/location/places/qplacecontentrequest.cpp b/src/location/places/qplacecontentrequest.cpp index 1353ada4..9ad82149 100644 --- a/src/location/places/qplacecontentrequest.cpp +++ b/src/location/places/qplacecontentrequest.cpp @@ -46,14 +46,13 @@ QT_BEGIN_NAMESPACE QPlaceContentRequestPrivate::QPlaceContentRequestPrivate() - : QSharedData(), contentType(QPlaceContent::NoType), - limit(-1), offset(0) +: QSharedData(), contentType(QPlaceContent::NoType), limit(-1) { } QPlaceContentRequestPrivate::QPlaceContentRequestPrivate(const QPlaceContentRequestPrivate &other) - : QSharedData(other), contentType(other.contentType), - limit(other.limit), offset(other.offset) +: QSharedData(other), contentType(other.contentType), placeId(other.placeId), + contentContext(other.contentContext), limit(other.limit) { } @@ -64,15 +63,13 @@ QPlaceContentRequestPrivate::~QPlaceContentRequestPrivate() bool QPlaceContentRequestPrivate::operator==(const QPlaceContentRequestPrivate &other) const { return contentType == other.contentType - && limit == other.limit - && offset == other.offset; + && limit == other.limit; } void QPlaceContentRequestPrivate::clear() { contentType = QPlaceContent::NoType; limit = -1; - offset = 0; } /*! @@ -171,48 +168,75 @@ void QPlaceContentRequest::setContentType(QPlaceContent::Type type) } /*! - Returns the maximum number of content items to retrieve. + Returns the identifier of the place content is to be fetched for. +*/ +QString QPlaceContentRequest::placeId() const +{ + Q_D(const QPlaceContentRequest); + return d->placeId; +} - A negative value for limit means that it is undefined. It is left up to the backend - provider to choose an appropriate number of items to return. +/*! + Sets the identifier of the place to fetch content for to \a identifier. +*/ +void QPlaceContentRequest::setPlaceId(const QString &identifier) +{ + Q_D(QPlaceContentRequest); + d->placeId = identifier; +} - The default limit is -1. +/*! + Returns backend specific additional content context associated with this place content request. */ -int QPlaceContentRequest::limit() const +QVariant QPlaceContentRequest::contentContext() const { Q_D(const QPlaceContentRequest); - return d->limit; + return d->contentContext; } /*! - Set the maximum number of content items to retrieve to - \a limit. + Sets the content context to \a context. + + \note This method is intended to be used by geo service plugins when returning place content + results. + + The content context is used by backends to store additional content context related to the + content request. Other relevant fields should also be filled in. For example, if the content + request is for image content the content type should also be set with \l setContentType(). The + content context allows additional context to be kept which is not directly accessible via the + Qt Location API. + + The content context can be of any type storable in a QVariant. The value of the content context + is not intended to be used directly by applications. */ -void QPlaceContentRequest::setLimit(int limit) +void QPlaceContentRequest::setContentContext(const QVariant &context) { Q_D(QPlaceContentRequest); - d->limit = limit; + d->contentContext = context; } /*! - Returns the offset index of the first item that is to be retrieved. + Returns the maximum number of content items to retrieve. - The default offset is 0. + A negative value for limit means that it is undefined. It is left up to the backend + provider to choose an appropriate number of items to return. + + The default limit is -1. */ -int QPlaceContentRequest::offset() const +int QPlaceContentRequest::limit() const { Q_D(const QPlaceContentRequest); - return d->offset; + return d->limit; } /*! - Sets the starting index of the first item to be retrieved - to \a offset. + Set the maximum number of content items to retrieve to + \a limit. */ -void QPlaceContentRequest::setOffset(int offset) +void QPlaceContentRequest::setLimit(int limit) { Q_D(QPlaceContentRequest); - d->offset = offset; + d->limit = limit; } /*! diff --git a/src/location/places/qplacecontentrequest.h b/src/location/places/qplacecontentrequest.h index b535a133..164c4df9 100644 --- a/src/location/places/qplacecontentrequest.h +++ b/src/location/places/qplacecontentrequest.h @@ -65,8 +65,12 @@ public: QPlaceContent::Type contentType() const; void setContentType(QPlaceContent::Type type); - int offset() const; - void setOffset(int offset); + QString placeId() const; + void setPlaceId(const QString &identifier); + + QVariant contentContext() const; + void setContentContext(const QVariant &context); + int limit() const; void setLimit(int limit); diff --git a/src/location/places/qplacecontentrequest_p.h b/src/location/places/qplacecontentrequest_p.h index 05fb580b..213bdb58 100644 --- a/src/location/places/qplacecontentrequest_p.h +++ b/src/location/places/qplacecontentrequest_p.h @@ -43,7 +43,8 @@ #define QPLACECONTENTREQUEST_P_H #include <QtCore/QSharedData> -#include "qplacecontent.h" +#include <QtCore/QVariant> +#include <QtLocation/QPlaceContent> QT_BEGIN_NAMESPACE @@ -60,8 +61,9 @@ public: void clear(); QPlaceContent::Type contentType; + QString placeId; + QVariant contentContext; int limit; - int offset; }; QT_END_NAMESPACE diff --git a/src/location/places/qplacemanager.cpp b/src/location/places/qplacemanager.cpp index d0e91312..863e8adc 100644 --- a/src/location/places/qplacemanager.cpp +++ b/src/location/places/qplacemanager.cpp @@ -208,14 +208,13 @@ QPlaceDetailsReply *QPlaceManager::getPlaceDetails(const QString &placeId) const } /*! - Retrieves content for the place corresponding to \a placeId, according to the parameters specified in - \a request. + Retrieves content for a place according to the parameters specified in \a request. See \l {Fetching Rich Content} for an example of usage. */ -QPlaceContentReply *QPlaceManager::getPlaceContent(const QString &placeId, const QPlaceContentRequest &request) const +QPlaceContentReply *QPlaceManager::getPlaceContent(const QPlaceContentRequest &request) const { - return d->getPlaceContent(placeId, request); + return d->getPlaceContent(request); } /*! diff --git a/src/location/places/qplacemanager.h b/src/location/places/qplacemanager.h index 786fdc1d..a29e5ea6 100644 --- a/src/location/places/qplacemanager.h +++ b/src/location/places/qplacemanager.h @@ -76,7 +76,7 @@ public: QPlaceDetailsReply *getPlaceDetails(const QString &placeId) const; - QPlaceContentReply *getPlaceContent(const QString &placeId, const QPlaceContentRequest &request) const; + QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &request) const; QPlaceSearchReply *search(const QPlaceSearchRequest &query) const; diff --git a/src/location/places/qplacemanagerengine.cpp b/src/location/places/qplacemanagerengine.cpp index 67dbf9c6..74d96f0f 100644 --- a/src/location/places/qplacemanagerengine.cpp +++ b/src/location/places/qplacemanagerengine.cpp @@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE Constructs a new engine with the specified \a parent, using \a parameters to pass any implementation specific data to the engine. */ -QPlaceManagerEngine::QPlaceManagerEngine(const QMap<QString, QVariant> ¶meters, +QPlaceManagerEngine::QPlaceManagerEngine(const QVariantMap ¶meters, QObject *parent) : QObject(parent), d_ptr(new QPlaceManagerEnginePrivate) { @@ -151,13 +151,10 @@ QPlaceDetailsReply *QPlaceManagerEngine::getPlaceDetails(const QString &placeId) } /*! - Retrieves content for the place corresponding to \a placeId, according to the parameters - specified in \a request. + Retrieves content for a place according to the parameters specified in \a request. */ -QPlaceContentReply *QPlaceManagerEngine::getPlaceContent(const QString &placeId, - const QPlaceContentRequest &request) +QPlaceContentReply *QPlaceManagerEngine::getPlaceContent(const QPlaceContentRequest &request) { - Q_UNUSED(placeId) Q_UNUSED(request) return new QPlaceContentReplyUnsupported(this); diff --git a/src/location/places/qplacemanagerengine.h b/src/location/places/qplacemanagerengine.h index ee019637..0eefa7ca 100644 --- a/src/location/places/qplacemanagerengine.h +++ b/src/location/places/qplacemanagerengine.h @@ -58,7 +58,7 @@ class Q_LOCATION_EXPORT QPlaceManagerEngine : public QObject Q_OBJECT public: - QPlaceManagerEngine(const QMap<QString, QVariant> ¶meters, QObject *parent = 0); + QPlaceManagerEngine(const QVariantMap ¶meters, QObject *parent = 0); virtual ~QPlaceManagerEngine(); QString managerName() const; @@ -66,8 +66,7 @@ public: virtual QPlaceDetailsReply *getPlaceDetails(const QString &placeId); - virtual QPlaceContentReply *getPlaceContent(const QString &placeId, - const QPlaceContentRequest &request); + virtual QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &request); virtual QPlaceSearchReply *search(const QPlaceSearchRequest &request); diff --git a/src/location/places/qplacesearchreply.cpp b/src/location/places/qplacesearchreply.cpp index 26829607..9d89748a 100644 --- a/src/location/places/qplacesearchreply.cpp +++ b/src/location/places/qplacesearchreply.cpp @@ -39,23 +39,23 @@ ** ****************************************************************************/ -#include "qplacesearchreply.h" -#include "qplacereply_p.h" - +#include <QtLocation/QPlaceSearchRequest> +#include <QtLocation/QPlaceSearchReply> +#include <QtLocation/QPlaceProposedSearchResult> +#include <QtLocation/private/qplacereply_p.h> QT_BEGIN_NAMESPACE + class QPlaceSearchReplyPrivate : public QPlaceReplyPrivate { public: QPlaceSearchReplyPrivate(){} QList<QPlaceSearchResult> results; QPlaceSearchRequest searchRequest; + QPlaceSearchRequest previousPageRequest; + QPlaceSearchRequest nextPageRequest; }; -QT_END_NAMESPACE - -QT_USE_NAMESPACE - /*! \class QPlaceSearchReply \inmodule QtLocation @@ -121,6 +121,30 @@ QPlaceSearchRequest QPlaceSearchReply::request() const } /*! + Returns a place search request which can be used to request the previous page of search + results. An empty place search request is returned if there is no previous page of results. + + \sa nextPageRequest(), setPreviousPageRequest() +*/ +QPlaceSearchRequest QPlaceSearchReply::previousPageRequest() const +{ + Q_D(const QPlaceSearchReply); + return d->previousPageRequest; +} + +/*! + Returns a place search request which can be used to request the next page of search results. An + empty place search request is returned if there is no next page of results. + + \sa previousPageRequest(), setNextPageRequest() +*/ +QPlaceSearchRequest QPlaceSearchReply::nextPageRequest() const +{ + Q_D(const QPlaceSearchReply); + return d->nextPageRequest; +} + +/*! Sets the search \a request used to generate this reply. */ void QPlaceSearchReply::setRequest(const QPlaceSearchRequest &request) @@ -128,3 +152,27 @@ void QPlaceSearchReply::setRequest(const QPlaceSearchRequest &request) Q_D(QPlaceSearchReply); d->searchRequest = request; } + +/*! + Sets the previous page of search results request to \a previous. + + \sa previousPageRequest() +*/ +void QPlaceSearchReply::setPreviousPageRequest(const QPlaceSearchRequest &previous) +{ + Q_D(QPlaceSearchReply); + d->previousPageRequest = previous; +} + +/*! + Sets the next page of search results request to \a next. + + \sa nextPageRequest() +*/ +void QPlaceSearchReply::setNextPageRequest(const QPlaceSearchRequest &next) +{ + Q_D(QPlaceSearchReply); + d->nextPageRequest = next; +} + +QT_END_NAMESPACE diff --git a/src/location/places/qplacesearchreply.h b/src/location/places/qplacesearchreply.h index 4266b988..51cb315f 100644 --- a/src/location/places/qplacesearchreply.h +++ b/src/location/places/qplacesearchreply.h @@ -44,11 +44,12 @@ #include <QtLocation/QPlaceReply> #include <QtLocation/QPlaceSearchResult> -#include <QtLocation/QPlaceSearchRequest> QT_BEGIN_NAMESPACE +class QPlaceSearchResult; class QPlaceSearchReplyPrivate; + class Q_LOCATION_EXPORT QPlaceSearchReply : public QPlaceReply { Q_OBJECT @@ -61,9 +62,15 @@ public: QList<QPlaceSearchResult> results() const; QPlaceSearchRequest request() const; + QPlaceSearchRequest previousPageRequest() const; + QPlaceSearchRequest nextPageRequest() const; + protected: void setResults(const QList<QPlaceSearchResult> &results); void setRequest(const QPlaceSearchRequest &request); + void setPreviousPageRequest(const QPlaceSearchRequest &previous); + void setNextPageRequest(const QPlaceSearchRequest &next); + private: Q_DISABLE_COPY(QPlaceSearchReply) Q_DECLARE_PRIVATE(QPlaceSearchReply) diff --git a/src/location/places/qplacesearchrequest.cpp b/src/location/places/qplacesearchrequest.cpp index c5878b22..81cfeba4 100644 --- a/src/location/places/qplacesearchrequest.cpp +++ b/src/location/places/qplacesearchrequest.cpp @@ -68,7 +68,6 @@ public: QLocation::VisibilityScope visibilityScope; QPlaceSearchRequest::RelevanceHint relevanceHint; int limit; - int offset; QVariant searchContext; }; @@ -76,7 +75,7 @@ QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate() : QSharedData(), visibilityScope(QLocation::UnspecifiedVisibility), relevanceHint(QPlaceSearchRequest::UnspecifiedHint), - limit(-1), offset(0) + limit(-1) { } @@ -89,7 +88,6 @@ QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate(const QPlaceSearchRequest visibilityScope(other.visibilityScope), relevanceHint(other.relevanceHint), limit(other.limit), - offset(other.offset), searchContext(other.searchContext) { } @@ -108,7 +106,6 @@ QPlaceSearchRequestPrivate &QPlaceSearchRequestPrivate::operator=(const QPlaceSe visibilityScope = other.visibilityScope; relevanceHint = other.relevanceHint; limit = other.limit; - offset = other.offset; searchContext = other.searchContext; } @@ -124,14 +121,12 @@ bool QPlaceSearchRequestPrivate::operator==(const QPlaceSearchRequestPrivate &ot visibilityScope == other.visibilityScope && relevanceHint == other.relevanceHint && limit == other.limit && - offset == other.offset && searchContext == other.searchContext; } void QPlaceSearchRequestPrivate::clear() { limit = -1; - offset = 0; searchTerm.clear(); categories.clear(); searchArea = QGeoShape(); @@ -429,27 +424,6 @@ void QPlaceSearchRequest::setLimit(int limit) } /*! - Returns the offset index of the first item that is to be retrieved. - - The default offset is 0. -*/ -int QPlaceSearchRequest::offset() const -{ - Q_D(const QPlaceSearchRequest); - return d->offset; -} - -/*! - Sets the starting index of the first item to be retrieved - to \a offset. -*/ -void QPlaceSearchRequest::setOffset(int offset) -{ - Q_D(QPlaceSearchRequest); - d->offset = offset; -} - -/*! Clears the search request. */ void QPlaceSearchRequest::clear() diff --git a/src/location/places/qplacesearchrequest.h b/src/location/places/qplacesearchrequest.h index 65ca3fe0..34a6a1dd 100644 --- a/src/location/places/qplacesearchrequest.h +++ b/src/location/places/qplacesearchrequest.h @@ -94,8 +94,6 @@ public: RelevanceHint relevanceHint() const; void setRelevanceHint(RelevanceHint hint); - int offset() const; - void setOffset(int offset); int limit() const; void setLimit(int limit); diff --git a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp index 1a18d15d..ac294d6e 100644 --- a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp +++ b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp @@ -200,6 +200,7 @@ QPlaceEditorial parseEditorial(const QJsonObject &editorialObject, void parseCollection(QPlaceContent::Type type, const QJsonObject &object, QPlaceContent::Collection *collection, int *totalCount, + QPlaceContentRequest *previous, QPlaceContentRequest *next, const QPlaceManagerEngineNokiaV2 *engine) { Q_ASSERT(engine); @@ -211,6 +212,16 @@ void parseCollection(QPlaceContent::Type type, const QJsonObject &object, if (object.contains(QLatin1String("offset"))) offset = object.value(QLatin1String("offset")).toDouble(); + if (previous && object.contains(QStringLiteral("previous"))) { + previous->setContentType(type); + previous->setContentContext(QUrl(object.value(QStringLiteral("previous")).toString())); + } + + if (next && object.contains(QStringLiteral("next"))) { + next->setContentType(type); + next->setContentContext(QUrl(object.value(QStringLiteral("next")).toString())); + } + if (collection) { QJsonArray items = object.value(QLatin1String("items")).toArray(); for (int i = 0; i < items.count(); ++i) { diff --git a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.h b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.h index 092addb9..ef01de19 100644 --- a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.h +++ b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.h @@ -54,6 +54,7 @@ class QPlaceImage; class QPlaceReview; class QPlaceEditorial; class QPlaceCategory; +class QPlaceContentRequest; class QPlaceManagerEngineNokiaV2; QGeoCoordinate parseCoordinate(const QJsonArray &coordinateArray); @@ -74,6 +75,7 @@ QPlaceEditorial parseEditorial(const QJsonObject &editorialObject, void parseCollection(QPlaceContent::Type type, const QJsonObject &object, QPlaceContent::Collection *collection, int *totalCount, + QPlaceContentRequest *previous, QPlaceContentRequest *next, const QPlaceManagerEngineNokiaV2 *engine); QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp index e47bd4d5..1b5a1776 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp +++ b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp @@ -94,22 +94,29 @@ void QPlaceContentReplyImpl::setError(QPlaceReply::Error error_, const QString & void QPlaceContentReplyImpl::replyFinished() { - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); - if (!document.isObject()) { - setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); - return; + if (m_reply->isOpen()) { + QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + if (!document.isObject()) { + setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); + return; + } + + QJsonObject object = document.object(); + + QPlaceContent::Collection collection; + int totalCount; + QPlaceContentRequest previous; + QPlaceContentRequest next; + + parseCollection(request().contentType(), object, &collection, &totalCount, + &previous, &next, m_engine); + + setTotalCount(totalCount); + setContent(collection); + setPreviousPageRequest(previous); + setNextPageRequest(next); } - QJsonObject object = document.object(); - - QPlaceContent::Collection collection; - int totalCount; - - parseCollection(request().contentType(), object, &collection, &totalCount, m_engine); - - setTotalCount(totalCount); - setContent(collection); - m_reply->deleteLater(); m_reply = 0; diff --git a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp index fda0c776..a5386341 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp +++ b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp @@ -307,7 +307,7 @@ void QPlaceDetailsReplyImpl::replyFinished() parseCollection(QPlaceContent::ImageType, mediaObject.value(QLatin1String("images")).toObject(), - &collection, &totalCount, m_engine); + &collection, &totalCount, 0, 0, m_engine); place.setTotalContentCount(QPlaceContent::ImageType, totalCount); place.setContent(QPlaceContent::ImageType, collection); @@ -318,7 +318,7 @@ void QPlaceDetailsReplyImpl::replyFinished() parseCollection(QPlaceContent::EditorialType, mediaObject.value(QLatin1String("editorials")).toObject(), - &collection, &totalCount, m_engine); + &collection, &totalCount, 0, 0, m_engine); place.setTotalContentCount(QPlaceContent::EditorialType, totalCount); place.setContent(QPlaceContent::EditorialType, collection); @@ -329,7 +329,7 @@ void QPlaceDetailsReplyImpl::replyFinished() parseCollection(QPlaceContent::ReviewType, mediaObject.value(QLatin1String("reviews")).toObject(), - &collection, &totalCount, m_engine); + &collection, &totalCount, 0, 0, m_engine); place.setTotalContentCount(QPlaceContent::ReviewType, totalCount); place.setContent(QPlaceContent::ReviewType, collection); diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyimpl.cpp index 7bd20599..3b43c357 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyimpl.cpp +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyimpl.cpp @@ -121,11 +121,11 @@ void QPlaceSearchReplyImpl::replyFinished() return; } - QJsonObject object = document.object(); + QJsonObject resultsObject = document.object(); - //QJsonObject searchObject = object.value(QLatin1String("search")).toObject(); + if (resultsObject.contains(QStringLiteral("results"))) + resultsObject = resultsObject.value(QStringLiteral("results")).toObject(); - QJsonObject resultsObject = object.value(QLatin1String("results")).toObject(); QJsonArray items = resultsObject.value(QLatin1String("items")).toArray(); QList<QPlaceSearchResult> results; @@ -139,6 +139,18 @@ void QPlaceSearchReplyImpl::replyFinished() results.append(parseSearchResult(item)); } + if (resultsObject.contains(QStringLiteral("next"))) { + QPlaceSearchRequest request; + request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("next")).toString())); + setNextPageRequest(request); + } + + if (resultsObject.contains(QStringLiteral("previous"))) { + QPlaceSearchRequest request; + request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("previous")).toString())); + setPreviousPageRequest(request); + } + setResults(results); m_reply->deleteLater(); diff --git a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp index d00f4fb9..cbdf98f2 100644 --- a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE QGeoCodingManagerEngineNokia::QGeoCodingManagerEngineNokia( QGeoNetworkAccessManager *networkManager, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoCodingManagerEngine(parameters) diff --git a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h index 6b9bf1e2..b4e5c75d 100644 --- a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h +++ b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h @@ -66,7 +66,7 @@ class QGeoCodingManagerEngineNokia : public QGeoCodingManagerEngine Q_OBJECT public: QGeoCodingManagerEngineNokia(QGeoNetworkAccessManager *networkManager, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString); ~QGeoCodingManagerEngineNokia(); diff --git a/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.cpp b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.cpp index 42da0070..69f3c9c9 100644 --- a/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.cpp +++ b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.cpp @@ -54,7 +54,7 @@ QGeoIntrinsicNetworkAccessManager::QGeoIntrinsicNetworkAccessManager(QObject *pa { } -QGeoIntrinsicNetworkAccessManager::QGeoIntrinsicNetworkAccessManager(const QMap<QString, QVariant> ¶meters, const QString &token, QObject *parent) +QGeoIntrinsicNetworkAccessManager::QGeoIntrinsicNetworkAccessManager(const QVariantMap ¶meters, const QString &token, QObject *parent) : QGeoNetworkAccessManager(parent) , m_customProxyToken(token) , m_networkManager(new QNetworkAccessManager(this)) @@ -62,7 +62,7 @@ QGeoIntrinsicNetworkAccessManager::QGeoIntrinsicNetworkAccessManager(const QMap< configure(parameters); } -void QGeoIntrinsicNetworkAccessManager::configure(const QMap<QString, QVariant> ¶meters) +void QGeoIntrinsicNetworkAccessManager::configure(const QVariantMap ¶meters) { QString proxy = parameters.value(QStringLiteral("proxy")).toString(); if (proxy.isEmpty() && !m_customProxyToken.isEmpty()) diff --git a/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.h b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.h index 18f655f6..72ae2990 100644 --- a/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.h +++ b/src/plugins/geoservices/nokia/qgeointrinsicnetworkaccessmanager.h @@ -54,13 +54,13 @@ class QGeoIntrinsicNetworkAccessManager : public QGeoNetworkAccessManager { public: explicit QGeoIntrinsicNetworkAccessManager(QObject *parent = 0); - QGeoIntrinsicNetworkAccessManager(const QMap<QString, QVariant> ¶meters, const QString &token = QString(), QObject *parent = 0); + QGeoIntrinsicNetworkAccessManager(const QVariantMap ¶meters, const QString &token = QString(), QObject *parent = 0); virtual QNetworkReply *get(const QNetworkRequest &request); virtual QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data); private: - void configure(const QMap<QString, QVariant> ¶meters); + void configure(const QVariantMap ¶meters); const QString m_customProxyToken; QNetworkAccessManager *m_networkManager; diff --git a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp index 9bd60155..4380494a 100644 --- a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE QGeoRoutingManagerEngineNokia::QGeoRoutingManagerEngineNokia( QGeoNetworkAccessManager *networkManager, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoRoutingManagerEngine(parameters) @@ -442,14 +442,14 @@ QString QGeoRoutingManagerEngineNokia::routeRequestString(const QGeoRouteRequest requestString += "&instructionformat=text"; - const QLocale loc(locale()); - requestString += "&metricSystem="; - if (QLocale::MetricSystem == loc.measurementSystem()) + if (QLocale::MetricSystem == measurementSystem()) requestString += "metric"; else requestString += "imperial"; + const QLocale loc(locale()); + if (QLocale::C != loc.language() && QLocale::AnyLanguage != loc.language()) { requestString += "&language="; requestString += loc.name(); diff --git a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h index 42a3c939..cf9caab0 100644 --- a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h +++ b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.h @@ -64,7 +64,7 @@ class QGeoRoutingManagerEngineNokia : public QGeoRoutingManagerEngine Q_OBJECT public: QGeoRoutingManagerEngineNokia(QGeoNetworkAccessManager *networkInterface, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString); ~QGeoRoutingManagerEngineNokia(); diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp index fbffcc5e..1c7c12e5 100644 --- a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia( QGeoNetworkAccessManager *networkManager, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoTiledMappingManagerEngine() diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h index 3ba30d90..56af20c4 100644 --- a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h +++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h @@ -71,7 +71,7 @@ class QGeoTiledMappingManagerEngineNokia : public QGeoTiledMappingManagerEngine public: QGeoTiledMappingManagerEngineNokia(QGeoNetworkAccessManager *networkManager, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString); ~QGeoTiledMappingManagerEngineNokia(); diff --git a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp index 31fa12e0..13616dbe 100644 --- a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp @@ -110,7 +110,7 @@ namespace } } QGeoTileFetcherNokia::QGeoTileFetcherNokia( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoNetworkAccessManager *networkManager, QGeoTiledMappingManagerEngine *engine, const QSize &tileSize) diff --git a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h index 534dfddb..2d9c385f 100644 --- a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h +++ b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h @@ -69,7 +69,7 @@ class QGeoTileFetcherNokia : public QGeoTileFetcher public: QGeoTileFetcherNokia( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoNetworkAccessManager *networkManager, QGeoTiledMappingManagerEngine *engine, const QSize &tileSize); @@ -96,7 +96,7 @@ private: QPointer<QGeoTiledMappingManagerEngineNokia> m_engineNokia; QGeoNetworkAccessManager *m_networkManager; - QMap<QString, QVariant> m_parameters; + QVariantMap m_parameters; QSize m_tileSize; QString m_token; QNetworkReply *m_copyrightsReply; diff --git a/src/plugins/geoservices/nokia/qgeouriprovider.cpp b/src/plugins/geoservices/nokia/qgeouriprovider.cpp index 0ce3611e..77c47b03 100644 --- a/src/plugins/geoservices/nokia/qgeouriprovider.cpp +++ b/src/plugins/geoservices/nokia/qgeouriprovider.cpp @@ -68,7 +68,7 @@ namespace QGeoUriProvider::QGeoUriProvider( QObject *parent, - const QMap<QString, QVariant> & parameters, + const QVariantMap ¶meters, const QString &hostParameterName, const QString &internationalHost, const QString &localizedHost) diff --git a/src/plugins/geoservices/nokia/qgeouriprovider.h b/src/plugins/geoservices/nokia/qgeouriprovider.h index d9f3e570..82f2bb45 100644 --- a/src/plugins/geoservices/nokia/qgeouriprovider.h +++ b/src/plugins/geoservices/nokia/qgeouriprovider.h @@ -62,7 +62,7 @@ class QGeoUriProvider : public QObject public: QGeoUriProvider(QObject *parent, - const QMap<QString, QVariant> & parameters, + const QVariantMap ¶meters, const QString &hostParameterName, const QString &internationalHost, const QString &localizedHost = QString()); diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp index 9c2a9b85..5543d001 100644 --- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp +++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp @@ -198,7 +198,7 @@ void CategoryParser::processCategory(int level, const QString &id, const QString QPlaceManagerEngineNokiaV2::QPlaceManagerEngineNokiaV2( QGeoNetworkAccessManager *networkManager, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QPlaceManagerEngine(parameters) @@ -261,75 +261,63 @@ QPlaceDetailsReply *QPlaceManagerEngineNokiaV2::getPlaceDetails(const QString &p return reply; } -QPlaceContentReply *QPlaceManagerEngineNokiaV2::getPlaceContent(const QString &placeId, - const QPlaceContentRequest &request) +QPlaceContentReply *QPlaceManagerEngineNokiaV2::getPlaceContent(const QPlaceContentRequest &request) { - QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + - QLatin1String("/places/v1/places/") + placeId + QLatin1String("/media/")); - QNetworkReply *networkReply = 0; - QUrlQuery queryItems; + if (request.contentContext().userType() == qMetaTypeId<QUrl>()) { + QUrl u = request.contentContext().value<QUrl>(); - switch (request.contentType()) { - case QPlaceContent::ImageType: - requestUrl.setPath(requestUrl.path() + QLatin1String("images")); + networkReply = sendRequest(u); + } else { + QUrl requestUrl(QString::fromLatin1("http://") + m_uriProvider->getCurrentHost() + + QLatin1String("/places/v1/places/") + request.placeId() + + QLatin1String("/media/")); - queryItems.addQueryItem(QLatin1String("tf"), QLatin1String("html")); + QUrlQuery queryItems; - if (request.limit() > 0) { - queryItems.addQueryItem(QLatin1String("size"), - QString::number(request.limit())); - } - if (request.offset() > -1) { - queryItems.addQueryItem(QLatin1String("offset"), - QString::number(request.offset())); - } + switch (request.contentType()) { + case QPlaceContent::ImageType: + requestUrl.setPath(requestUrl.path() + QLatin1String("images")); - //queryItems.append(qMakePair<QString, QString>(QLatin1String("image_dimensions"), QLatin1String("w64-h64,w100"))); + queryItems.addQueryItem(QLatin1String("tf"), QLatin1String("html")); - requestUrl.setQuery(queryItems); + if (request.limit() > 0) + queryItems.addQueryItem(QLatin1String("size"), QString::number(request.limit())); - networkReply = sendRequest(requestUrl); - break; - case QPlaceContent::ReviewType: - requestUrl.setPath(requestUrl.path() + QLatin1String("reviews")); + //queryItems.append(qMakePair<QString, QString>(QLatin1String("image_dimensions"), QLatin1String("w64-h64,w100"))); - queryItems.addQueryItem(QLatin1String("tf"), QLatin1String("html")); + requestUrl.setQuery(queryItems); - if (request.limit() > 0) { - queryItems.addQueryItem(QLatin1String("size"), - QString::number(request.limit())); - } - if (request.offset() > -1) { - queryItems.addQueryItem(QLatin1String("offset"), - QString::number(request.offset())); - } + networkReply = sendRequest(requestUrl); + break; + case QPlaceContent::ReviewType: + requestUrl.setPath(requestUrl.path() + QLatin1String("reviews")); - requestUrl.setQuery(queryItems); + queryItems.addQueryItem(QLatin1String("tf"), QLatin1String("html")); - networkReply = sendRequest(requestUrl); - break; - case QPlaceContent::EditorialType: - requestUrl.setPath(requestUrl.path() + QLatin1String("editorials")); + if (request.limit() > 0) + queryItems.addQueryItem(QLatin1String("size"), QString::number(request.limit())); - queryItems.addQueryItem(QLatin1String("tf"), QLatin1String("html")); + requestUrl.setQuery(queryItems); - if (request.limit() > 0) { - queryItems.addQueryItem(QLatin1String("size"), - QString::number(request.limit())); - } - if (request.offset() > -1) { - queryItems.addQueryItem(QLatin1String("offset"), - QString::number(request.offset())); - } + networkReply = sendRequest(requestUrl); + break; + case QPlaceContent::EditorialType: + requestUrl.setPath(requestUrl.path() + QLatin1String("editorials")); - requestUrl.setQuery(queryItems); + queryItems.addQueryItem(QLatin1String("tf"), QLatin1String("html")); - networkReply = sendRequest(requestUrl); - break; - case QPlaceContent::NoType: - ; + if (request.limit() > 0) + queryItems.addQueryItem(QLatin1String("size"), QString::number(request.limit())); + + requestUrl.setQuery(queryItems); + + networkReply = sendRequest(requestUrl); + break; + case QPlaceContent::NoType: + ; + } } QPlaceContentReply *reply = new QPlaceContentReplyImpl(request, networkReply, this); @@ -379,8 +367,6 @@ QPlaceSearchReply *QPlaceManagerEngineNokiaV2::search(const QPlaceSearchRequest unsupported |= query.visibilityScope() != QLocation::UnspecifiedVisibility && query.visibilityScope() != QLocation::PublicVisibility; - unsupported |= !query.searchTerm().isEmpty() && query.offset() > 0; - // Both a search term and search categories are not supported. unsupported |= !query.searchTerm().isEmpty() && !query.categories().isEmpty(); @@ -432,9 +418,6 @@ QPlaceSearchReply *QPlaceManagerEngineNokiaV2::search(const QPlaceSearchRequest if (query.limit() > 0) queryItems.addQueryItem(QStringLiteral("size"), QString::number(query.limit())); - if (query.offset() > -1) - queryItems.addQueryItem(QStringLiteral("offset"), QString::number(query.offset())); - u.setQuery(queryItems); networkReply = sendRequest(u); @@ -493,10 +476,6 @@ QPlaceSearchReply *QPlaceManagerEngineNokiaV2::search(const QPlaceSearchRequest queryItems.addQueryItem(QLatin1String("size"), QString::number(query.limit())); } - if (query.offset() > -1) { - queryItems.addQueryItem(QLatin1String("offset"), - QString::number(query.offset())); - } requestUrl.setQuery(queryItems); @@ -518,7 +497,6 @@ QPlaceSearchSuggestionReply *QPlaceManagerEngineNokiaV2::searchSuggestions(const unsupported |= query.visibilityScope() != QLocation::UnspecifiedVisibility && query.visibilityScope() != QLocation::PublicVisibility; - unsupported |= query.offset() > 0; unsupported |= !query.categories().isEmpty(); unsupported |= !query.recommendationId().isEmpty(); diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h index 6b31e165..c186d6bd 100644 --- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h +++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.h @@ -78,14 +78,14 @@ class QPlaceManagerEngineNokiaV2 : public QPlaceManagerEngine public: QPlaceManagerEngineNokiaV2(QGeoNetworkAccessManager *networkManager, - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString); ~QPlaceManagerEngineNokiaV2(); QPlaceDetailsReply *getPlaceDetails(const QString &placeId); - QPlaceContentReply *getPlaceContent(const QString &placeId, const QPlaceContentRequest &request); + QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &request) Q_DECL_OVERRIDE; QPlaceSearchReply *search(const QPlaceSearchRequest &query); diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp index f3cae726..9f71c0b1 100644 --- a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp +++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp @@ -128,46 +128,117 @@ static QGeoManeuver::InstructionDirection osrmInstructionDirection(const QString const QString osrmInstructionText(const QString &instructionCode, const QString &wayname) { - if (instructionCode == QLatin1String("0")) + if (instructionCode == QLatin1String("0")) { return QString(); - else if (instructionCode == QLatin1String("1")) - return QGeoRouteReplyOsm::tr("Go straight."); - else if (instructionCode == QLatin1String("2")) - return QGeoRouteReplyOsm::tr("Turn slightly right onto %1.").arg(wayname); - else if (instructionCode == QLatin1String("3")) - return QGeoRouteReplyOsm::tr("Turn right onto %1.").arg(wayname); - else if (instructionCode == QLatin1String("4")) - return QGeoRouteReplyOsm::tr("Make a sharp right onto %1.").arg(wayname); - else if (instructionCode == QLatin1String("5")) + } else if (instructionCode == QLatin1String("1")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Go straight."); + else + return QGeoRouteReplyOsm::tr("Go straight onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("2")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Turn slightly right."); + else + return QGeoRouteReplyOsm::tr("Turn slightly right onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("3")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Turn right."); + else + return QGeoRouteReplyOsm::tr("Turn right onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("4")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Make a sharp right."); + else + return QGeoRouteReplyOsm::tr("Make a sharp right onto %1.").arg(wayname); + } + else if (instructionCode == QLatin1String("5")) { return QGeoRouteReplyOsm::tr("When it is safe to do so, perform a U-turn."); - else if (instructionCode == QLatin1String("6")) - return QGeoRouteReplyOsm::tr("Make a sharp left onto %1.").arg(wayname); - else if (instructionCode == QLatin1String("7")) - return QGeoRouteReplyOsm::tr("Turn left onto %1.").arg(wayname); - else if (instructionCode == QLatin1String("8")) - return QGeoRouteReplyOsm::tr("Turn slightly left onto %1.").arg(wayname); - else if (instructionCode == QLatin1String("9")) + } else if (instructionCode == QLatin1String("6")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Make a sharp left."); + else + return QGeoRouteReplyOsm::tr("Make a sharp left onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("7")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Turn left."); + else + return QGeoRouteReplyOsm::tr("Turn left onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("8")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Turn slightly left."); + else + return QGeoRouteReplyOsm::tr("Turn slightly left onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("9")) { return QGeoRouteReplyOsm::tr("Reached waypoint."); - else if (instructionCode == QLatin1String("10")) - return QGeoRouteReplyOsm::tr("Head onto %1.").arg(wayname); - else if (instructionCode == QLatin1String("11")) - return QGeoRouteReplyOsm::tr("Enter the round about."); - else if (instructionCode == QLatin1String("11-1")) - return QGeoRouteReplyOsm::tr("At the round about take the 1st exit."); - else if (instructionCode == QLatin1String("11-2")) - return QGeoRouteReplyOsm::tr("At the round about take the 2nd exit."); - else if (instructionCode == QLatin1String("11-3")) - return QGeoRouteReplyOsm::tr("At the round about take the 3rd exit."); - else if (instructionCode == QLatin1String("12")) - return QGeoRouteReplyOsm::tr("Leave the round about."); - else if (instructionCode == QLatin1String("13")) - return QGeoRouteReplyOsm::tr("Stay on the round about."); - else if (instructionCode == QLatin1String("14")) - return QGeoRouteReplyOsm::tr("Start at the end of the street."); - else if (instructionCode == QLatin1String("15")) + } else if (instructionCode == QLatin1String("10")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Head on."); + else + return QGeoRouteReplyOsm::tr("Head onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11")) { + return QGeoRouteReplyOsm::tr("Enter the roundabout."); + } else if (instructionCode == QLatin1String("11-1")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the first exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the first exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-2")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the second exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the second exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-3")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the third exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the third exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-4")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the fourth exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the fourth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-5")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the fifth exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the fifth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-6")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the sixth exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the sixth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-7")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the seventh exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the seventh exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-8")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the eighth exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the eighth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("11-9")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("At the roundabout take the ninth exit."); + else + return QGeoRouteReplyOsm::tr("At the roundabout take the ninth exit onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("12")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Leave the roundabout."); + else + return QGeoRouteReplyOsm::tr("Leave the roundabout onto %1.").arg(wayname); + } else if (instructionCode == QLatin1String("13")) { + return QGeoRouteReplyOsm::tr("Stay on the roundabout."); + } else if (instructionCode == QLatin1String("14")) { + if (wayname.isEmpty()) + return QGeoRouteReplyOsm::tr("Start at the end of the street."); + else + return QGeoRouteReplyOsm::tr("Start at the end of %1.").arg(wayname); + } else if (instructionCode == QLatin1String("15")) { return QGeoRouteReplyOsm::tr("You have reached your destination."); - else + } else { return QGeoRouteReplyOsm::tr("Don't know what to say for '%1'").arg(instructionCode); + } } QGeoRouteReplyOsm::QGeoRouteReplyOsm(QNetworkReply *reply, const QGeoRouteRequest &request, diff --git a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp index 6f7bbb30..077c55ba 100644 --- a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp +++ b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp @@ -46,7 +46,7 @@ #include <QtCore/QDebug> -QGeoRoutingManagerEngineOsm::QGeoRoutingManagerEngineOsm(const QMap<QString, QVariant> ¶meters, +QGeoRoutingManagerEngineOsm::QGeoRoutingManagerEngineOsm(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoRoutingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this)) diff --git a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h index 25016887..dd49a826 100644 --- a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h +++ b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h @@ -54,7 +54,7 @@ class QGeoRoutingManagerEngineOsm : public QGeoRoutingManagerEngine Q_OBJECT public: - QGeoRoutingManagerEngineOsm(const QMap<QString, QVariant> ¶meters, + QGeoRoutingManagerEngineOsm(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString); ~QGeoRoutingManagerEngineOsm(); diff --git a/src/plugins/position/android/android.pro b/src/plugins/position/android/android.pro new file mode 100644 index 00000000..0dc6a3fc --- /dev/null +++ b/src/plugins/position/android/android.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += jar src diff --git a/src/plugins/position/android/jar/AndroidManifest.xml b/src/plugins/position/android/jar/AndroidManifest.xml new file mode 100644 index 00000000..2d066dbb --- /dev/null +++ b/src/plugins/position/android/jar/AndroidManifest.xml @@ -0,0 +1,6 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.qtproject.qt5.android.positioning" + android:versionCode="1" + android:versionName="1.0" > + <supports-screens android:smallScreens="true" android:largeScreens="true" android:anyDensity="true" android:normalScreens="true"/> +</manifest> diff --git a/src/plugins/position/android/jar/bundledjar.pro b/src/plugins/position/android/jar/bundledjar.pro new file mode 100644 index 00000000..e7bd106d --- /dev/null +++ b/src/plugins/position/android/jar/bundledjar.pro @@ -0,0 +1,3 @@ +TARGET = QtPositioning-bundled +CONFIG += bundled_jar_file +include(jar.pri) diff --git a/src/plugins/position/android/jar/distributedjar.pro b/src/plugins/position/android/jar/distributedjar.pro new file mode 100644 index 00000000..4a5faaa4 --- /dev/null +++ b/src/plugins/position/android/jar/distributedjar.pro @@ -0,0 +1,3 @@ +TARGET = QtPositioning +include(jar.pri) + diff --git a/src/plugins/position/android/jar/jar.pri b/src/plugins/position/android/jar/jar.pri new file mode 100644 index 00000000..9fa548ff --- /dev/null +++ b/src/plugins/position/android/jar/jar.pri @@ -0,0 +1,14 @@ +load(qt_build_paths) + +CONFIG += java +DESTDIR = $$MODULE_BASE_OUTDIR/jar + +JAVACLASSPATH += $$PWD/src + +JAVASOURCES += \ + $$PWD/src/org/qtproject/qt5/android/positioning/QtPositioning.java + +# install +target.path = $$[QT_INSTALL_PREFIX]/jar +INSTALLS += target + diff --git a/src/plugins/position/android/jar/jar.pro b/src/plugins/position/android/jar/jar.pro new file mode 100644 index 00000000..8d19c1b7 --- /dev/null +++ b/src/plugins/position/android/jar/jar.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += bundledjar.pro distributedjar.pro diff --git a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java new file mode 100644 index 00000000..f5725813 --- /dev/null +++ b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java @@ -0,0 +1,543 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +package org.qtproject.qt5.android.positioning; + +import android.app.Activity; +import android.content.Context; +import android.location.GpsSatellite; +import android.location.GpsStatus; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import android.util.Log; + +public class QtPositioning implements LocationListener +{ + + private static final String TAG = "QtPositioning"; + static LocationManager locationManager = null; + static Object m_syncObject = new Object(); + static HashMap<Integer, QtPositioning> runningListeners = new HashMap<Integer, QtPositioning>(); + + /* + The positionInfo instance to which this + QtPositioning instance is attached to. + */ + private int nativeClassReference = 0; + + /* + The provider type requested by Qt + */ + private int expectedProviders = 0; + + public static final int QT_GPS_PROVIDER = 1; + public static final int QT_NETWORK_PROVIDER = 2; + + /* The following values must match the corresponding error enums in the Qt API*/ + public static final int QT_ACCESS_ERROR = 0; + public static final int QT_CLOSED_ERROR = 1; + public static final int QT_POSITION_UNKNOWN_SOURCE_ERROR = 2; + public static final int QT_POSITION_NO_ERROR = 3; + public static final int QT_SATELLITE_NO_ERROR = 2; + public static final int QT_SATELLITE_UNKNOWN_SOURCE_ERROR = -1; + + /* True, if updates were caused by requestUpdate() */ + private boolean isSingleUpdate = false; + /* The length requested for regular intervals in msec. */ + private int updateIntervalTime = 0; + + /* The last received GPS update */ + private Location lastGps = null; + /* The last received network update */ + private Location lastNetwork = null; + /* If true this class acts as satellite signal monitor rather than location monitor */ + private boolean isSatelliteUpdate = false; + + private PositioningLooper looperThread; + + static public void setActivity(Activity activity, Object activityDelegate) + { + try { + locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE); + } catch(Exception e) { + e.printStackTrace(); + } + } + + static private int[] providerList() + { + List<String> providers = locationManager.getAllProviders(); + int retList[] = new int[providers.size()]; + for (int i = 0; i < providers.size(); i++) { + if (providers.get(i).equals(LocationManager.GPS_PROVIDER)) { + //must be in sync with AndroidPositioning::PositionProvider::PROVIDER_GPS + retList[i] = 0; + } else if (providers.get(i).equals(LocationManager.NETWORK_PROVIDER)) { + //must be in sync with AndroidPositioning::PositionProvider::PROVIDER_NETWORK + retList[i] = 1; + } else if (providers.get(i).equals(LocationManager.PASSIVE_PROVIDER)) { + //must be in sync with AndroidPositioning::PositionProvider::PROVIDER_PASSIVE + retList[i] = 2; + } else { + retList[i] = -1; + } + } + return retList; + } + + static public Location lastKnownPosition(boolean fromSatelliteOnly) + { + Location gps = null; + Location network = null; + try { + gps = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + if (!fromSatelliteOnly) + network = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); + } catch(Exception e) { + e.printStackTrace(); + gps = network = null; + } + + if (gps != null && network != null) { + //we return the most recent location but slightly prefer GPS + //prefer GPS if it is max 4 hrs older than network + long delta = network.getTime() - gps.getTime(); + if (delta < 4*60*60*1000) { + return gps; + } else { + return network; + } + } else if (gps != null ) { + return gps; + } else if (network != null) { + return network; + } + + return null; + } + + /* Returns true if at least on of the given providers is enabled. */ + static private boolean expectedProvidersAvailable(int desiredProviders) + { + List<String> enabledProviders = locationManager.getProviders(true); + if ((desiredProviders & QT_GPS_PROVIDER) > 0) { //gps desired + if (enabledProviders.contains(LocationManager.GPS_PROVIDER)) { + return true; + } + } + if ((desiredProviders & QT_NETWORK_PROVIDER) > 0) { //network desired + if (enabledProviders.contains(LocationManager.NETWORK_PROVIDER)) { + return true; + } + } + + return false; + } + + static public int startUpdates(int androidClassKey, int locationProvider, int updateInterval) + { + synchronized (m_syncObject) { + try { + boolean exceptionOccurred = false; + QtPositioning positioningListener = new QtPositioning(); + positioningListener.setActiveLooper(true); + positioningListener.nativeClassReference = androidClassKey; + positioningListener.expectedProviders = locationProvider; + positioningListener.isSatelliteUpdate = false; + + if (updateInterval == 0) + updateInterval = 1000; //don't update more often than once per second + + positioningListener.updateIntervalTime = updateInterval; + if ((locationProvider & QT_GPS_PROVIDER) > 0) { + Log.d(TAG, "Regular updates using GPS"); + try { + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, + updateInterval, 0, + positioningListener, + positioningListener.looper()); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + + if ((locationProvider & QT_NETWORK_PROVIDER) > 0) { + Log.d(TAG, "Regular updates using network"); + try { + locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, + updateInterval, 0, + positioningListener, + positioningListener.looper()); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + if (exceptionOccurred) { + positioningListener.setActiveLooper(false); + locationManager.removeUpdates(positioningListener); + return QT_ACCESS_ERROR; + } + + if (!expectedProvidersAvailable(locationProvider)) { + //all location providers unavailbe -> when they come back we resume automatically + return QT_CLOSED_ERROR; + } + + runningListeners.put(androidClassKey, positioningListener); + } catch(Exception e) { + e.printStackTrace(); + return QT_POSITION_UNKNOWN_SOURCE_ERROR; + } + + return QT_POSITION_NO_ERROR; + } + } + + static public void stopUpdates(int androidClassKey) + { + synchronized (m_syncObject) { + try { + Log.d(TAG, "Stopping updates"); + QtPositioning listener = runningListeners.remove(androidClassKey); + locationManager.removeUpdates(listener); + listener.setActiveLooper(false); + } catch(Exception e) { + e.printStackTrace(); + return; + } + } + } + + static public int requestUpdate(int androidClassKey, int locationProvider) + { + synchronized (m_syncObject) { + try { + boolean exceptionOccurred = false; + QtPositioning positioningListener = new QtPositioning(); + positioningListener.setActiveLooper(true); + positioningListener.nativeClassReference = androidClassKey; + positioningListener.isSingleUpdate = true; + positioningListener.expectedProviders = locationProvider; + positioningListener.isSatelliteUpdate = false; + + if ((locationProvider & QT_GPS_PROVIDER) > 0) { + Log.d(TAG, "Single update using GPS"); + try { + locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, + positioningListener, + positioningListener.looper()); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + + if ((locationProvider & QT_NETWORK_PROVIDER) > 0) { + Log.d(TAG, "Single update using network"); + try { + locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, + positioningListener, + positioningListener.looper()); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + } + if (exceptionOccurred) { + positioningListener.setActiveLooper(false); + locationManager.removeUpdates(positioningListener); + return QT_ACCESS_ERROR; + } + + if (!expectedProvidersAvailable(locationProvider)) { + //all location providers unavailable -> when they come back we resume automatically + //in the mean time return ClosedError + return QT_CLOSED_ERROR; + } + + runningListeners.put(androidClassKey, positioningListener); + } catch(Exception e) { + e.printStackTrace(); + return QT_POSITION_UNKNOWN_SOURCE_ERROR; + } + + return QT_POSITION_NO_ERROR; + } + } + + static public int startSatelliteUpdates(int androidClassKey, int updateInterval, boolean isSingleRequest) + { + synchronized (m_syncObject) { + try { + boolean exceptionOccurred = false; + QtPositioning positioningListener = new QtPositioning(); + positioningListener.isSatelliteUpdate = true; + positioningListener.setActiveLooper(true); + positioningListener.nativeClassReference = androidClassKey; + positioningListener.expectedProviders = 1; //always satellite provider + positioningListener.isSingleUpdate = isSingleRequest; + + if (updateInterval == 0) + updateInterval = 1000; //don't update more often than once per second + + if (isSingleRequest) + Log.d(TAG, "Single update for Satellites " + updateInterval); + else + Log.d(TAG, "Regular updates for Satellites " + updateInterval); + try { + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, + updateInterval, 0, + positioningListener, + positioningListener.looper()); + } catch (SecurityException se) { + se.printStackTrace(); + exceptionOccurred = true; + } + + if (exceptionOccurred) { + positioningListener.setActiveLooper(false); + locationManager.removeUpdates(positioningListener); + return QT_ACCESS_ERROR; + } + + if (!expectedProvidersAvailable(positioningListener.expectedProviders)) { + //all location providers unavailable -> when they come back we resume automatically + //in the mean time return ClosedError + return QT_CLOSED_ERROR; + } + + runningListeners.put(androidClassKey, positioningListener); + } catch(Exception e) { + e.printStackTrace(); + return QT_SATELLITE_UNKNOWN_SOURCE_ERROR; + } + + return QT_SATELLITE_NO_ERROR; + } + } + + public QtPositioning() + { + looperThread = new PositioningLooper(); + } + + public Looper looper() + { + return looperThread.looper(); + } + + private void setActiveLooper(boolean setActive) + { + try{ + if (setActive) { + if (looperThread.isAlive()) + return; + + if (isSatelliteUpdate) + looperThread.isSatelliteListener(true); + + looperThread.start(); + while (!looperThread.isReady()); + Thread.sleep(1000); + } else { + looperThread.quitLooper(); + } + } catch(Exception e) { + e.printStackTrace(); + } + } + + private class PositioningLooper extends Thread implements GpsStatus.Listener{ + private boolean looperRunning; + private Looper posLooper; + private boolean isSatelliteLooper = false; + private LocationManager locManager = null; + + private PositioningLooper() + { + looperRunning = false; + } + + public void run() + { + Looper.prepare(); + Handler handler = new Handler(); + looperRunning = true; + + if (isSatelliteLooper) { + try { + locationManager.addGpsStatusListener(this); + } catch(Exception e) { + e.printStackTrace(); + } + } + + posLooper = Looper.myLooper(); + Looper.loop(); + looperRunning = false; + } + + public void quitLooper() + { + if (isSatelliteLooper) + locationManager.removeGpsStatusListener(this); + looper().quit(); + } + + public boolean isReady() + { + return looperRunning; + } + + public void isSatelliteListener(boolean isListener) + { + isSatelliteLooper = isListener; + } + + public Looper looper() + { + return posLooper; + } + + @Override + public void onGpsStatusChanged(int event) { + switch (event) { + case GpsStatus.GPS_EVENT_FIRST_FIX: + break; + case GpsStatus.GPS_EVENT_SATELLITE_STATUS: + GpsStatus status = locationManager.getGpsStatus(null); + Iterable<GpsSatellite> iterable = status.getSatellites(); + Iterator<GpsSatellite> it = iterable.iterator(); + + ArrayList<GpsSatellite> list = new ArrayList<GpsSatellite>(); + while (it.hasNext()) { + GpsSatellite sat = (GpsSatellite) it.next(); + list.add(sat); + } + GpsSatellite[] sats = list.toArray(new GpsSatellite[list.size()]); + satelliteUpdated(sats, nativeClassReference, isSingleUpdate); + + break; + case GpsStatus.GPS_EVENT_STARTED: + break; + case GpsStatus.GPS_EVENT_STOPPED: + break; + } + } + } + + + + public static native void positionUpdated(Location update, int androidClassKey, boolean isSingleUpdate); + public static native void locationProvidersDisabled(int androidClassKey); + public static native void satelliteUpdated(GpsSatellite[] update, int androidClassKey, boolean isSingleUpdate); + + @Override + public void onLocationChanged(Location location) { + //Log.d(TAG, "**** Position Update ****: " + location.toString() + " " + isSingleUpdate); + if (location == null) + return; + + if (isSatelliteUpdate) //we are a QGeoSatelliteInfoSource -> ignore + return; + + if (isSingleUpdate || expectedProviders < 3) { + positionUpdated(location, nativeClassReference, isSingleUpdate); + return; + } + + /* + We can use GPS and Network, pick the better location provider. + Generally we prefer GPS data due to their higher accurancy but we + let Network data pass until GPS fix is available + */ + + if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { + lastGps = location; + + // assumption: GPS always better -> pass it on + positionUpdated(location, nativeClassReference, isSingleUpdate); + } else if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { + lastNetwork = location; + + if (lastGps == null) { //no GPS fix yet use network location + positionUpdated(location, nativeClassReference, isSingleUpdate); + return; + } + + long delta = location.getTime() - lastGps.getTime(); + + // Ignore if network update is older than last GPS (delta < 0) + // Ignore if gps update still has time to provide next location (delta < updateInterval) + if (delta < updateIntervalTime) + return; + + // Use network data -> GPS has timed out on updateInterval + positionUpdated(location, nativeClassReference, isSingleUpdate); + } + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) {} + + @Override + public void onProviderEnabled(String provider) { + Log.d(TAG, "Enabled provider: " + provider); + } + + @Override + public void onProviderDisabled(String provider) { + Log.d(TAG, "Disabled provider: " + provider); + if (!expectedProvidersAvailable(expectedProviders)) + locationProvidersDisabled(nativeClassReference); + } +} diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp new file mode 100644 index 00000000..6b49b9fe --- /dev/null +++ b/src/plugins/position/android/src/jnipositioning.cpp @@ -0,0 +1,568 @@ +/**************************************************************************** +** +** 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 <QDateTime> +#include <QDebug> +#include <QMap> +#include <QtGlobal> +#include <android/log.h> +#include <jni.h> +#include <QGeoPositionInfo> +#include "qgeopositioninfosource_android_p.h" +#include "qgeosatelliteinfosource_android_p.h" + +#include "jnipositioning.h" + +static JavaVM *javaVM = 0; +jclass positioningClass; + +static jmethodID providerListMethodId; +static jmethodID lastKnownPositionMethodId; +static jmethodID startUpdatesMethodId; +static jmethodID stopUpdatesMethodId; +static jmethodID requestUpdateMethodId; +static jmethodID startSatelliteUpdatesMethodId; + +static const char logTag[] = "QtPositioning"; +static const char classErrorMsg[] = "Can't find class \"%s\""; +static const char methodErrorMsg[] = "Can't find method \"%s%s\""; + +namespace AndroidPositioning { + typedef QMap<int, QGeoPositionInfoSourceAndroid * > PositionSourceMap; + typedef QMap<int, QGeoSatelliteInfoSourceAndroid * > SatelliteSourceMap; + + Q_GLOBAL_STATIC(PositionSourceMap, idToPosSource) + + Q_GLOBAL_STATIC(SatelliteSourceMap, idToSatSource) + + struct AttachedJNIEnv + { + AttachedJNIEnv() + { + attached = false; + if (javaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) { + if (javaVM->AttachCurrentThread(&jniEnv, NULL) < 0) { + __android_log_print(ANDROID_LOG_ERROR, logTag, "AttachCurrentThread failed"); + jniEnv = 0; + return; + } + attached = true; + } + } + + ~AttachedJNIEnv() + { + if (attached) + javaVM->DetachCurrentThread(); + } + bool attached; + JNIEnv *jniEnv; + }; + + int registerPositionInfoSource(QObject *obj) + { + static bool firstInit = true; + if (firstInit) { + qsrand( QDateTime::currentDateTime().toTime_t() ); + firstInit = false; + } + + int key = -1; + if (obj->inherits("QGeoPositionInfoSource")) { + QGeoPositionInfoSourceAndroid *src = qobject_cast<QGeoPositionInfoSourceAndroid *>(obj); + Q_ASSERT(src); + do { + key = qrand(); + } while (idToPosSource()->contains(key)); + + idToPosSource()->insert(key, src); + } else if (obj->inherits("QGeoSatelliteInfoSource")) { + QGeoSatelliteInfoSourceAndroid *src = qobject_cast<QGeoSatelliteInfoSourceAndroid *>(obj); + Q_ASSERT(src); + do { + key = qrand(); + } while (idToSatSource()->contains(key)); + + idToSatSource()->insert(key, src); + } + + return key; + } + + void unregisterPositionInfoSource(int key) + { + idToPosSource()->remove(key); + idToSatSource()->remove(key); + } + + enum PositionProvider + { + PROVIDER_GPS = 0, + PROVIDER_NETWORK = 1, + PROVIDER_PASSIVE = 2 + }; + + + QGeoPositionInfoSource::PositioningMethods availableProviders() + { + QGeoPositionInfoSource::PositioningMethods ret = + static_cast<QGeoPositionInfoSource::PositioningMethods>(0); + AttachedJNIEnv env; + if (!env.jniEnv) + return ret; + jintArray jProviders = static_cast<jintArray>(env.jniEnv->CallStaticObjectMethod( + positioningClass, providerListMethodId)); + jint *providers = env.jniEnv->GetIntArrayElements(jProviders, 0); + const uint size = env.jniEnv->GetArrayLength(jProviders); + for (uint i = 0; i < size; i++) { + switch (providers[i]) { + case PROVIDER_GPS: + ret |= QGeoPositionInfoSource::SatellitePositioningMethods; + break; + case PROVIDER_NETWORK: + ret |= QGeoPositionInfoSource::NonSatellitePositioningMethods; + break; + case PROVIDER_PASSIVE: + //we ignore as Qt doesn't have interface for it right now + break; + default: + __android_log_print(ANDROID_LOG_INFO, logTag, "Unknown positioningMethod"); + } + } + env.jniEnv->ReleaseIntArrayElements(jProviders, providers, 0); + + return ret; + } + + //caching originally taken from corelib/kernel/qjni.cpp + typedef QHash<QByteArray, jmethodID> JMethodIDHash; + Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID) + + static jmethodID getCachedMethodID(JNIEnv *env, + jclass clazz, + const char *name, + const char *sig) + { + jmethodID id = 0; + int offset_name = qstrlen(name); + int offset_signal = qstrlen(sig); + QByteArray key(offset_name + offset_signal, Qt::Uninitialized); + memcpy(key.data(), name, offset_name); + memcpy(key.data()+offset_name, sig, offset_signal); + QHash<QByteArray, jmethodID>::iterator it = cachedMethodID->find(key); + if (it == cachedMethodID->end()) { + id = env->GetMethodID(clazz, name, sig); + if (env->ExceptionCheck()) { + id = 0; + #ifdef QT_DEBUG + env->ExceptionDescribe(); + #endif // QT_DEBUG + env->ExceptionClear(); + } + + cachedMethodID->insert(key, id); + } else { + id = it.value(); + } + return id; + } + + QGeoPositionInfo positionInfoFromJavaLocation(JNIEnv * jniEnv, const jobject &location) + { + QGeoPositionInfo info; + jclass thisClass = jniEnv->GetObjectClass(location); + if (!thisClass) + return QGeoPositionInfo(); + + jmethodID mid = getCachedMethodID(jniEnv, thisClass, "getLatitude", "()D"); + jdouble latitude = jniEnv->CallDoubleMethod(location, mid); + mid = getCachedMethodID(jniEnv, thisClass, "getLongitude", "()D"); + jdouble longitude = jniEnv->CallDoubleMethod(location, mid); + QGeoCoordinate coordinate(latitude, longitude); + + //altitude + mid = getCachedMethodID(jniEnv, thisClass, "hasAltitude", "()Z"); + jboolean attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getAltitude", "()D"); + jdouble value = jniEnv->CallDoubleMethod(location, mid); + coordinate.setAltitude(value); + } + + info.setCoordinate(coordinate); + + //time stamp + mid = getCachedMethodID(jniEnv, thisClass, "getTime", "()J"); + jlong timestamp = jniEnv->CallLongMethod(location, mid); + info.setTimestamp(QDateTime::fromMSecsSinceEpoch(timestamp)); + + //accuracy + mid = getCachedMethodID(jniEnv, thisClass, "hasAccuracy", "()Z"); + attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getAccuracy", "()F"); + jfloat accuracy = jniEnv->CallFloatMethod(location, mid); + info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy); + } + + //ground speed + mid = getCachedMethodID(jniEnv, thisClass, "hasSpeed", "()Z"); + attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getSpeed", "()F"); + jfloat speed = jniEnv->CallFloatMethod(location, mid); + info.setAttribute(QGeoPositionInfo::GroundSpeed, speed); + } + + //bearing + mid = getCachedMethodID(jniEnv, thisClass, "hasBearing", "()Z"); + attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getBearing", "()F"); + jfloat bearing = jniEnv->CallFloatMethod(location, mid); + info.setAttribute(QGeoPositionInfo::Direction, bearing); + } + + return info; + } + + QList<QGeoSatelliteInfo> satelliteInfoFromJavaLocation(JNIEnv *jniEnv, + jobjectArray satellites, + QList<QGeoSatelliteInfo>* usedInFix) + { + QList<QGeoSatelliteInfo> sats; + jsize length = jniEnv->GetArrayLength(satellites); + for (int i = 0; i<length; i++) { + jobject element = jniEnv->GetObjectArrayElement(satellites, i); + if (jniEnv->ExceptionOccurred()) { + qWarning() << "Cannot process all satellite data due to exception."; + break; + } + + jclass thisClass = jniEnv->GetObjectClass(element); + if (!thisClass) + continue; + + QGeoSatelliteInfo info; + + //signal strength + jmethodID mid = getCachedMethodID(jniEnv, thisClass, "getSnr", "()F"); + jfloat snr = jniEnv->CallFloatMethod(element, mid); + info.setSignalStrength((int)snr); + + //ignore any satellite with no signal whatsoever + if (qFuzzyIsNull(snr)) + continue; + + //prn + mid = getCachedMethodID(jniEnv, thisClass, "getPrn", "()I"); + jint prn = jniEnv->CallIntMethod(element, mid); + info.setSatelliteIdentifier(prn); + + if (prn >= 1 && prn <= 32) + info.setSatelliteSystem(QGeoSatelliteInfo::GPS); + else if (prn >= 65 && prn <= 96) + info.setSatelliteSystem(QGeoSatelliteInfo::GLONASS); + + //azimuth + mid = getCachedMethodID(jniEnv, thisClass, "getAzimuth", "()F"); + jfloat azimuth = jniEnv->CallFloatMethod(element, mid); + info.setAttribute(QGeoSatelliteInfo::Azimuth, azimuth); + + //elevation + mid = getCachedMethodID(jniEnv, thisClass, "getElevation", "()F"); + jfloat elevation = jniEnv->CallFloatMethod(element, mid); + info.setAttribute(QGeoSatelliteInfo::Elevation, elevation); + + //used in a fix + mid = getCachedMethodID(jniEnv, thisClass, "usedInFix", "()Z"); + jboolean inFix = jniEnv->CallBooleanMethod(element, mid); + + sats.append(info); + + if (inFix) + usedInFix->append(info); + + jniEnv->DeleteLocalRef(thisClass); + jniEnv->DeleteLocalRef(element); + } + + return sats; + } + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoPositionInfo(); + + jobject location = env.jniEnv->CallStaticObjectMethod(positioningClass, + lastKnownPositionMethodId, + fromSatellitePositioningMethodsOnly); + if (location == 0) + return QGeoPositionInfo(); + + return positionInfoFromJavaLocation(env.jniEnv, location); + } + + inline int positioningMethodToInt(QGeoPositionInfoSource::PositioningMethods m) + { + int providerSelection = 0; + if (m & QGeoPositionInfoSource::SatellitePositioningMethods) + providerSelection |= 1; + if (m & QGeoPositionInfoSource::NonSatellitePositioningMethods) + providerSelection |= 2; + + return providerSelection; + } + + QGeoPositionInfoSource::Error startUpdates(int androidClassKey) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoPositionInfoSource::UnknownSourceError; + + QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + + if (source) { + int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startUpdatesMethodId, + androidClassKey, + positioningMethodToInt(source->preferredPositioningMethods()), + source->updateInterval()); + switch (errorCode) { + case 0: + case 1: + case 2: + case 3: + return static_cast<QGeoPositionInfoSource::Error>(errorCode); + default: + break; + } + } + + return QGeoPositionInfoSource::UnknownSourceError; + } + + //used for stopping regular and single updates + void stopUpdates(int androidClassKey) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return; + + env.jniEnv->CallStaticVoidMethod(positioningClass, stopUpdatesMethodId, androidClassKey); + } + + QGeoPositionInfoSource::Error requestUpdate(int androidClassKey) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoPositionInfoSource::UnknownSourceError; + + QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + + if (source) { + int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, requestUpdateMethodId, + androidClassKey, + positioningMethodToInt(source->preferredPositioningMethods())); + switch (errorCode) { + case 0: + case 1: + case 2: + case 3: + return static_cast<QGeoPositionInfoSource::Error>(errorCode); + default: + break; + } + } + return QGeoPositionInfoSource::UnknownSourceError; + } + + QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, bool isSingleRequest, int requestTimeout) + { + AttachedJNIEnv env; + if (!env.jniEnv) + return QGeoSatelliteInfoSource::UnknownSourceError; + + QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey); + + if (source) { + int interval = source->updateInterval(); + if (isSingleRequest) + interval = requestTimeout; + int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startSatelliteUpdatesMethodId, + androidClassKey, + interval, isSingleRequest); + switch (errorCode) { + case -1: + case 0: + case 1: + case 2: + return static_cast<QGeoSatelliteInfoSource::Error>(errorCode); + default: + qWarning() << "startSatelliteUpdates: Unknown error code " << errorCode; + break; + } + } + return QGeoSatelliteInfoSource::UnknownSourceError; + } +} + + +static void positionUpdated(JNIEnv *env, jobject /*thiz*/, jobject location, jint androidClassKey, jboolean isSingleUpdate) +{ + QGeoPositionInfo info = AndroidPositioning::positionInfoFromJavaLocation(env, location); + + QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + if (!source) { + qFatal("positionUpdated: source == 0"); + return; + } + + //we need to invoke indirectly as the Looper thread is likely to be not the same thread + if (!isSingleUpdate) + QMetaObject::invokeMethod(source, "processPositionUpdate", Qt::AutoConnection, + Q_ARG(QGeoPositionInfo, info)); + else + QMetaObject::invokeMethod(source, "processSinglePositionUpdate", Qt::AutoConnection, + Q_ARG(QGeoPositionInfo, info)); +} + +static void locationProvidersDisabled(JNIEnv *env, jobject /*thiz*/, jint androidClassKey) +{ + Q_UNUSED(env); + QObject *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + if (!source) + source = AndroidPositioning::idToSatSource()->value(androidClassKey); + if (!source) { + qFatal("locationProvidersDisabled: source == 0"); + return; + } + + QMetaObject::invokeMethod(source, "locationProviderDisabled", Qt::AutoConnection); +} + +static void satelliteUpdated(JNIEnv *env, jobject /*thiz*/, jobjectArray satellites, jint androidClassKey, jboolean isSingleUpdate) +{ + QList<QGeoSatelliteInfo> inUse; + QList<QGeoSatelliteInfo> sats = AndroidPositioning::satelliteInfoFromJavaLocation(env, satellites, &inUse); + + QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey); + if (!source) { + qFatal("satelliteUpdated: source == 0"); + return; + } + + QMetaObject::invokeMethod(source, "processSatelliteUpdateInView", Qt::AutoConnection, + Q_ARG(QList<QGeoSatelliteInfo>, sats), Q_ARG(bool, isSingleUpdate)); + + QMetaObject::invokeMethod(source, "processSatelliteUpdateInUse", Qt::AutoConnection, + Q_ARG(QList<QGeoSatelliteInfo>, inUse), Q_ARG(bool, isSingleUpdate)); +} + + +#define FIND_AND_CHECK_CLASS(CLASS_NAME) \ +clazz = env->FindClass(CLASS_NAME); \ +if (!clazz) { \ + __android_log_print(ANDROID_LOG_FATAL, logTag, classErrorMsg, CLASS_NAME); \ + return JNI_FALSE; \ +} + +#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ +VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ +if (!VAR) { \ + __android_log_print(ANDROID_LOG_FATAL, logTag, methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \ + return JNI_FALSE; \ +} + +static JNINativeMethod methods[] = { + {"positionUpdated", "(Landroid/location/Location;IZ)V", (void *)positionUpdated}, + {"locationProvidersDisabled", "(I)V", (void *) locationProvidersDisabled}, + {"satelliteUpdated", "([Landroid/location/GpsSatellite;IZ)V", (void *)satelliteUpdated} +}; + +static bool registerNatives(JNIEnv *env) +{ + jclass clazz; + FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/positioning/QtPositioning"); + positioningClass = static_cast<jclass>(env->NewGlobalRef(clazz)); + + if (env->RegisterNatives(positioningClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "RegisterNatives failed"); + return JNI_FALSE; + } + + GET_AND_CHECK_STATIC_METHOD(providerListMethodId, positioningClass, "providerList", "()[I"); + GET_AND_CHECK_STATIC_METHOD(lastKnownPositionMethodId, positioningClass, "lastKnownPosition", "(Z)Landroid/location/Location;"); + GET_AND_CHECK_STATIC_METHOD(startUpdatesMethodId, positioningClass, "startUpdates", "(III)I"); + GET_AND_CHECK_STATIC_METHOD(stopUpdatesMethodId, positioningClass, "stopUpdates", "(I)V"); + GET_AND_CHECK_STATIC_METHOD(requestUpdateMethodId, positioningClass, "requestUpdate", "(II)I"); + GET_AND_CHECK_STATIC_METHOD(startSatelliteUpdatesMethodId, positioningClass, "startSatelliteUpdates", "(IIZ)I"); + + return true; +} + +Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) +{ + typedef union { + JNIEnv *nativeEnvironment; + void *venv; + } UnionJNIEnvToVoid; + + __android_log_print(ANDROID_LOG_INFO, logTag, "Positioning start"); + UnionJNIEnvToVoid uenv; + uenv.venv = NULL; + javaVM = 0; + + if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed"); + return -1; + } + JNIEnv *env = uenv.nativeEnvironment; + if (!registerNatives(env)) { + __android_log_print(ANDROID_LOG_FATAL, logTag, "registerNatives failed"); + return -1; + } + + javaVM = vm; + return JNI_VERSION_1_4; +} + diff --git a/src/plugins/position/android/src/jnipositioning.h b/src/plugins/position/android/src/jnipositioning.h new file mode 100644 index 00000000..51341720 --- /dev/null +++ b/src/plugins/position/android/src/jnipositioning.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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 JNIPOSITIONING_H +#define JNIPOSITIONING_H + +#include <QGeoPositionInfoSource> +#include <QGeoSatelliteInfoSource> + +namespace AndroidPositioning +{ + int registerPositionInfoSource(QObject *obj); + void unregisterPositionInfoSource(int key); + + QGeoPositionInfoSource::PositioningMethods availableProviders(); + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly); + + QGeoPositionInfoSource::Error startUpdates(int androidClassKey); + void stopUpdates(int androidClassKey); + QGeoPositionInfoSource::Error requestUpdate(int androidClassKey); + + QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey, + bool isSingleRequest, + int updateRequestTimeout); +} + +#endif // JNIPOSITIONING_H diff --git a/src/plugins/position/android/src/plugin.json b/src/plugins/position/android/src/plugin.json new file mode 100644 index 00000000..b84fafea --- /dev/null +++ b/src/plugins/position/android/src/plugin.json @@ -0,0 +1,8 @@ +{ + "Keys": ["android"], + "Provider": "android", + "Position": true, + "Satellite": true, + "Monitor": false, + "Priority": 1000 +} diff --git a/src/plugins/position/android/src/positionfactory_android.cpp b/src/plugins/position/android/src/positionfactory_android.cpp new file mode 100644 index 00000000..047c313d --- /dev/null +++ b/src/plugins/position/android/src/positionfactory_android.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 "positionfactory_android.h" +#include "qgeopositioninfosource_android_p.h" +#include "qgeosatelliteinfosource_android_p.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryAndroid::positionInfoSource(QObject *parent) +{ + QGeoPositionInfoSourceAndroid *src = new QGeoPositionInfoSourceAndroid(parent); + return src; +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryAndroid::satelliteInfoSource(QObject *parent) +{ + QGeoSatelliteInfoSourceAndroid *src = new QGeoSatelliteInfoSourceAndroid(parent); + return src; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryAndroid::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} diff --git a/src/plugins/position/android/src/positionfactory_android.h b/src/plugins/position/android/src/positionfactory_android.h new file mode 100644 index 00000000..4b7818d4 --- /dev/null +++ b/src/plugins/position/android/src/positionfactory_android.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 POSITIONPOLLFACTORY_H +#define POSITIONPOLLFACTORY_H + +#include <QObject> +#include <QGeoPositionInfoSourceFactory> + +class QGeoPositionInfoSourceFactoryAndroid : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif // POSITIONPOLLFACTORY_H diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android.cpp b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp new file mode 100644 index 00000000..d4a95aa3 --- /dev/null +++ b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp @@ -0,0 +1,263 @@ +/**************************************************************************** +** +** 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 "qgeopositioninfosource_android_p.h" +#include "jnipositioning.h" +//#include <QDebug> +#include <QGeoPositionInfo> + +Q_DECLARE_METATYPE(QGeoPositionInfo) +#define UPDATE_FROM_COLD_START 2*60*1000 + + +QGeoPositionInfoSourceAndroid::QGeoPositionInfoSourceAndroid(QObject *parent) : + QGeoPositionInfoSource(parent), updatesRunning(false), m_error(UnknownSourceError) +{ + qRegisterMetaType< QGeoPositionInfo >(); + androidClassKeyForUpdate = AndroidPositioning::registerPositionInfoSource(this); + androidClassKeyForSingleRequest = AndroidPositioning::registerPositionInfoSource(this); + + //qDebug() << "androidClassKey: " << androidClassKeyForUpdate << androidClassKeyForSingleRequest; + //by default use all methods + setPreferredPositioningMethods(AllPositioningMethods); + + m_requestTimer.setSingleShot(true); + QObject::connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestTimeout())); +} + +QGeoPositionInfoSourceAndroid::~QGeoPositionInfoSourceAndroid() +{ + stopUpdates(); + + if (m_requestTimer.isActive()) { + m_requestTimer.stop(); + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + } + + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForUpdate); + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForSingleRequest); +} + +void QGeoPositionInfoSourceAndroid::setUpdateInterval(int msec) +{ + int previousInterval = updateInterval(); + msec = (((msec > 0) && (msec < minimumUpdateInterval())) || msec < 0)? minimumUpdateInterval() : msec; + + if (msec == previousInterval) + return; + + QGeoPositionInfoSource::setUpdateInterval(msec); + + if (updatesRunning) + reconfigureRunningSystem(); +} + +QGeoPositionInfo QGeoPositionInfoSourceAndroid::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + return AndroidPositioning::lastKnownPosition(fromSatellitePositioningMethodsOnly); +} + +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceAndroid::supportedPositioningMethods() const +{ + return AndroidPositioning::availableProviders(); +} + +void QGeoPositionInfoSourceAndroid::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods) +{ + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); + QGeoPositionInfoSource::setPreferredPositioningMethods(methods); + if (previousPreferredPositioningMethods == preferredPositioningMethods()) + return; + + if (updatesRunning) + reconfigureRunningSystem(); +} + +int QGeoPositionInfoSourceAndroid::minimumUpdateInterval() const +{ + return 1000; +} + +QGeoPositionInfoSource::Error QGeoPositionInfoSourceAndroid::error() const +{ + return m_error; +} + +void QGeoPositionInfoSourceAndroid::startUpdates() +{ + if (updatesRunning) + return; + + if (preferredPositioningMethods() == 0) { + m_error = UnknownSourceError; + emit QGeoPositionInfoSource::error(m_error); + + return; + } + + updatesRunning = true; + QGeoPositionInfoSource::Error error = AndroidPositioning::startUpdates(androidClassKeyForUpdate); + //if (error != QGeoPositionInfoSource::NoError) { //TODO + if (error != 3) { + updatesRunning = false; + m_error = error; + emit QGeoPositionInfoSource::error(m_error); + } +} + +void QGeoPositionInfoSourceAndroid::stopUpdates() +{ + if (!updatesRunning) + return; + + updatesRunning = false; + AndroidPositioning::stopUpdates(androidClassKeyForUpdate); +} + +void QGeoPositionInfoSourceAndroid::requestUpdate(int timeout) +{ + if (m_requestTimer.isActive()) + return; + + if (timeout != 0 && timeout < minimumUpdateInterval()) { + emit updateTimeout(); + return; + } + + if (timeout == 0) + timeout = UPDATE_FROM_COLD_START; + + m_requestTimer.start(timeout); + + // if updates already running with interval equal to timeout + // then we wait for next update coming through + // assume that a single update will not be quicker than regular updates anyway + if (updatesRunning && updateInterval() <= timeout) + return; + + QGeoPositionInfoSource::Error error = AndroidPositioning::requestUpdate(androidClassKeyForSingleRequest); + //if (error != QGeoPositionInfoSource::NoError) { //TODO + if (error != 3) { + m_requestTimer.stop(); + m_error = error; + emit QGeoPositionInfoSource::error(m_error); + } +} + +void QGeoPositionInfoSourceAndroid::processPositionUpdate(const QGeoPositionInfo &pInfo) +{ + //single update request and served as part of regular update + if (m_requestTimer.isActive()) + m_requestTimer.stop(); + + emit positionUpdated(pInfo); +} + +// Might still be called multiple times (once for each provider) +void QGeoPositionInfoSourceAndroid::processSinglePositionUpdate(const QGeoPositionInfo &pInfo) +{ + //timeout but we received a late update -> ignore + if (!m_requestTimer.isActive()) + return; + + queuedSingleUpdates.append(pInfo); +} + +void QGeoPositionInfoSourceAndroid::locationProviderDisabled() +{ + m_error = QGeoPositionInfoSource::ClosedError; + emit QGeoPositionInfoSource::error(m_error); +} + +void QGeoPositionInfoSourceAndroid::requestTimeout() +{ + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + //no queued update to process -> timeout + const int count = queuedSingleUpdates.count(); + + if (!count) { + emit updateTimeout(); + return; + } + + //pick best + QGeoPositionInfo best = queuedSingleUpdates[0]; + for (int i = 1; i < count; i++) { + const QGeoPositionInfo info = queuedSingleUpdates[i]; + + //anything newer by 20s is always better + const int timeDelta = best.timestamp().secsTo(info.timestamp()); + if (abs(timeDelta) > 20) { + if (timeDelta > 0) + best = info; + continue; + } + + //compare accuracy + if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) && + info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + { + best = info.attribute(QGeoPositionInfo::HorizontalAccuracy) < + best.attribute(QGeoPositionInfo::HorizontalAccuracy) ? info : best; + continue; + } + + //prefer info with accuracy information + if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + best = info; + } + + queuedSingleUpdates.clear(); + emit positionUpdated(best); +} + +/* + Updates the system assuming that updateInterval + and/or preferredPositioningMethod have changed. + */ +void QGeoPositionInfoSourceAndroid::reconfigureRunningSystem() +{ + if (!updatesRunning) + return; + + stopUpdates(); + startUpdates(); +} diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android_p.h b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h new file mode 100644 index 00000000..938b6564 --- /dev/null +++ b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 QGEOPOSITIONINFOSOURCE_ANDROID_P_H +#define QGEOPOSITIONINFOSOURCE_ANDROID_P_H + +#include <QGeoPositionInfoSource> +#include <QTimer> + +class QGeoPositionInfoSourceAndroid : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + QGeoPositionInfoSourceAndroid(QObject *parent = 0); + ~QGeoPositionInfoSourceAndroid(); + + // From QGeoPositionInfoSource + void setUpdateInterval(int msec); + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + void setPreferredPositioningMethods(PositioningMethods methods); + int minimumUpdateInterval() const; + Error error() const; + +public Q_SLOTS: + virtual void startUpdates(); + virtual void stopUpdates(); + + virtual void requestUpdate(int timeout = 0); + + void processPositionUpdate(const QGeoPositionInfo& pInfo); + void processSinglePositionUpdate(const QGeoPositionInfo& pInfo); + + void locationProviderDisabled(); +private Q_SLOTS: + void requestTimeout(); + +private: + void reconfigureRunningSystem(); + + bool updatesRunning; + int androidClassKeyForUpdate; + int androidClassKeyForSingleRequest; + QList<QGeoPositionInfo> queuedSingleUpdates; + Error m_error; + QTimer m_requestTimer; +}; + +#endif // QGEOPOSITIONINFOSOURCE_ANDROID_P_H diff --git a/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp b/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp new file mode 100644 index 00000000..f9e627d0 --- /dev/null +++ b/src/plugins/position/android/src/qgeosatelliteinfosource_android.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** 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 <QDebug> + +#include "qgeosatelliteinfosource_android_p.h" +#include "jnipositioning.h" + +Q_DECLARE_METATYPE(QGeoSatelliteInfo) +Q_DECLARE_METATYPE(QList<QGeoSatelliteInfo>) + +#define UPDATE_FROM_COLD_START 2*60*1000 + +QGeoSatelliteInfoSourceAndroid::QGeoSatelliteInfoSourceAndroid(QObject *parent) : + QGeoSatelliteInfoSource(parent), m_error(NoError), updatesRunning(false) +{ + qRegisterMetaType< QGeoSatelliteInfo >(); + qRegisterMetaType< QList<QGeoSatelliteInfo> >(); + androidClassKeyForUpdate = AndroidPositioning::registerPositionInfoSource(this); + androidClassKeyForSingleRequest = AndroidPositioning::registerPositionInfoSource(this); + + requestTimer.setSingleShot(true); + QObject::connect(&requestTimer, SIGNAL(timeout()), + this, SLOT(requestTimeout())); +} + +QGeoSatelliteInfoSourceAndroid::~QGeoSatelliteInfoSourceAndroid() +{ + stopUpdates(); + + if (requestTimer.isActive()) { + requestTimer.stop(); + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + } + + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForUpdate); + AndroidPositioning::unregisterPositionInfoSource(androidClassKeyForSingleRequest); +} + + +void QGeoSatelliteInfoSourceAndroid::setUpdateInterval(int msec) +{ + int previousInterval = updateInterval(); + msec = (((msec > 0) && (msec < minimumUpdateInterval())) || msec < 0)? minimumUpdateInterval() : msec; + + if (msec == previousInterval) + return; + + QGeoSatelliteInfoSource::setUpdateInterval(msec); + + if (updatesRunning) + reconfigureRunningSystem(); +} + +int QGeoSatelliteInfoSourceAndroid::minimumUpdateInterval() const +{ + return 1000; +} + +QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceAndroid::error() const +{ + return m_error; +} + +void QGeoSatelliteInfoSourceAndroid::startUpdates() +{ + if (updatesRunning) + return; + + updatesRunning = true; + + QGeoSatelliteInfoSource::Error error = AndroidPositioning::startSatelliteUpdates( + androidClassKeyForUpdate, false, updateInterval()); + if (error != QGeoSatelliteInfoSource::NoError) { + updatesRunning = false; + m_error = error; + emit QGeoSatelliteInfoSource::error(m_error); + } +} + +void QGeoSatelliteInfoSourceAndroid::stopUpdates() +{ + if (!updatesRunning) + return; + + updatesRunning = false; + AndroidPositioning::stopUpdates(androidClassKeyForUpdate); +} + +void QGeoSatelliteInfoSourceAndroid::requestUpdate(int timeout) +{ + if (requestTimer.isActive()) + return; + + if (timeout != 0 && timeout < minimumUpdateInterval()) { + emit requestTimeout(); + return; + } + + if (timeout == 0) + timeout = UPDATE_FROM_COLD_START; + + requestTimer.start(timeout); + + // if updates already running with interval equal or less then timeout + // then we wait for next update coming through + // assume that a single update will not be quicker than regular updates anyway + if (updatesRunning && updateInterval() <= timeout) + return; + + QGeoSatelliteInfoSource::Error error = AndroidPositioning::startSatelliteUpdates( + androidClassKeyForSingleRequest, true, timeout); + if (error != QGeoSatelliteInfoSource::NoError) { + requestTimer.stop(); + m_error = error; + emit QGeoSatelliteInfoSource::error(m_error); + } +} + +void QGeoSatelliteInfoSourceAndroid::processSatelliteUpdateInView(const QList<QGeoSatelliteInfo> &satsInView, bool isSingleUpdate) +{ + if (!isSingleUpdate) { + //if requested while regular updates were running + if (requestTimer.isActive()) + requestTimer.stop(); + emit QGeoSatelliteInfoSource::satellitesInViewUpdated(satsInView); + return; + } + + m_satsInView = satsInView; +} + +void QGeoSatelliteInfoSourceAndroid::processSatelliteUpdateInUse(const QList<QGeoSatelliteInfo> &satsInUse, bool isSingleUpdate) +{ + if (!isSingleUpdate) { + //if requested while regular updates were running + if (requestTimer.isActive()) + requestTimer.stop(); + emit QGeoSatelliteInfoSource::satellitesInUseUpdated(satsInUse); + return; + } + + m_satsInUse = satsInUse; +} + +void QGeoSatelliteInfoSourceAndroid::requestTimeout() +{ + AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); + + const int count = m_satsInView.count(); + if (!count) { + emit requestTimeout(); + return; + } + + emit QGeoSatelliteInfoSource::satellitesInViewUpdated(m_satsInView); + emit QGeoSatelliteInfoSource::satellitesInUseUpdated(m_satsInUse); + + m_satsInUse.clear(); + m_satsInView.clear(); +} + +/* + Updates the system assuming that updateInterval + and/or preferredPositioningMethod have changed. + */ +void QGeoSatelliteInfoSourceAndroid::reconfigureRunningSystem() +{ + if (!updatesRunning) + return; + + stopUpdates(); + startUpdates(); +} + +void QGeoSatelliteInfoSourceAndroid::locationProviderDisabled() +{ + m_error = QGeoSatelliteInfoSource::ClosedError; + emit QGeoSatelliteInfoSource::error(m_error); +} diff --git a/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h new file mode 100644 index 00000000..75711a3e --- /dev/null +++ b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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 QGEOSATELLITEINFOSOURCEANDROID_H +#define QGEOSATELLITEINFOSOURCEANDROID_H + +#include <QGeoSatelliteInfoSource> +#include <QTimer> + +class QGeoSatelliteInfoSourceAndroid : public QGeoSatelliteInfoSource +{ + Q_OBJECT +public: + explicit QGeoSatelliteInfoSourceAndroid(QObject *parent = 0); + ~QGeoSatelliteInfoSourceAndroid(); + + //From QGeoSatelliteInfoSource + void setUpdateInterval(int msec); + int minimumUpdateInterval() const; + + Error error() const; + +public Q_SLOTS: + void startUpdates(); + void stopUpdates(); + void requestUpdate(int timeout = 0); + + void processSatelliteUpdateInView(const QList<QGeoSatelliteInfo> &satsInView, bool isSingleUpdate); + void processSatelliteUpdateInUse(const QList<QGeoSatelliteInfo> &satsInUse, bool isSingleUpdate); + + void locationProviderDisabled(); +private Q_SLOTS: + void requestTimeout(); + +private: + void reconfigureRunningSystem(); + + Error m_error; + int androidClassKeyForUpdate; + int androidClassKeyForSingleRequest; + bool updatesRunning; + + QTimer requestTimer; + QList<QGeoSatelliteInfo> m_satsInUse; + QList<QGeoSatelliteInfo> m_satsInView; + +}; + +#endif // QGEOSATELLITEINFOSOURCEANDROID_H diff --git a/src/plugins/position/android/src/src.pro b/src/plugins/position/android/src/src.pro new file mode 100644 index 00000000..a61b77b5 --- /dev/null +++ b/src/plugins/position/android/src/src.pro @@ -0,0 +1,20 @@ +TARGET = qtposition_android +QT = core positioning + +PLUGIN_TYPE = position +load(qt_plugin) + + +HEADERS = \ + positionfactory_android.h \ + qgeopositioninfosource_android_p.h \ + jnipositioning.h \ + qgeosatelliteinfosource_android_p.h + +SOURCES = \ + positionfactory_android.cpp \ + qgeopositioninfosource_android.cpp \ + jnipositioning.cpp \ + qgeosatelliteinfosource_android.cpp + +OTHER_FILES = plugin.json diff --git a/src/plugins/position/corelocation/corelocation.pro b/src/plugins/position/corelocation/corelocation.pro new file mode 100644 index 00000000..bc65ee5d --- /dev/null +++ b/src/plugins/position/corelocation/corelocation.pro @@ -0,0 +1,23 @@ +TARGET = qtposition_cl +QT += positioning gui + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryCL +load(qt_plugin) + +INCLUDEPATH += $$QT.location.includes + +OBJECTIVE_SOURCES += \ + qgeopositioninfosource_cl.mm \ + qgeopositioninfosourcefactory_cl.mm + +HEADERS += \ + qgeopositioninfosource_cl_p.h \ + qgeopositioninfosourcefactory_cl.h + +OTHER_FILES += \ + plugin.json + +osx: LIBS += -framework Foundation +else: ios: LIBS += -framework CoreFoundation +LIBS += -framework CoreLocation diff --git a/src/plugins/position/corelocation/plugin.json b/src/plugins/position/corelocation/plugin.json new file mode 100644 index 00000000..96e5cbf1 --- /dev/null +++ b/src/plugins/position/corelocation/plugin.json @@ -0,0 +1,8 @@ +{ + "Keys": ["corelocation"], + "Provider": "corelocation", + "Position": true, + "Satellite": false, + "Monitor" : false, + "Priority": 1000 +} diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm new file mode 100644 index 00000000..47ceb6b6 --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** 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 <QTimerEvent> +#include <QDebug> + +#include "qgeopositioninfosource_cl_p.h" + +#define MINIMUM_UPDATE_INTERVAL 1000 + +@interface locationDelegate : NSObject <CLLocationManagerDelegate> +{ + QGeoPositionInfoSourceCL *m_positionInfoSource; +} +@end + +@implementation locationDelegate +- (id)initWithInfoSource:(QGeoPositionInfoSourceCL*) positionInfoSource +{ + self = [super init]; + if (self) { + m_positionInfoSource = positionInfoSource; + } + return self; +} + +- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation +{ + Q_UNUSED(manager) + Q_UNUSED(oldLocation) + + // Convert location timestamp to QDateTime + QDateTime timeStamp; + NSTimeInterval locationTimeStamp = [newLocation.timestamp timeIntervalSince1970]; + timeStamp.setTime_t((uint) locationTimeStamp); + timeStamp.setTime(timeStamp.time().addMSecs((uint)(locationTimeStamp * 1000) % 1000)); + + // Construct position info from location data + QGeoPositionInfo location(QGeoCoordinate(newLocation.coordinate.latitude, + newLocation.coordinate.longitude, + newLocation.altitude), + timeStamp); + location.setAttribute(QGeoPositionInfo::HorizontalAccuracy, newLocation.horizontalAccuracy); + location.setAttribute(QGeoPositionInfo::VerticalAccuracy, newLocation.verticalAccuracy); + location.setAttribute(QGeoPositionInfo::Direction, newLocation.course); + location.setAttribute(QGeoPositionInfo::GroundSpeed, newLocation.speed); + + m_positionInfoSource->locationDataAvailable(location); +} + +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error +{ + Q_UNUSED(manager) + m_positionInfoSource->setError(QGeoPositionInfoSource::AccessError); + + qWarning() << QString::fromNSString([error localizedDescription]); +} +@end + +QT_BEGIN_NAMESPACE + +QGeoPositionInfoSourceCL::QGeoPositionInfoSourceCL(QObject *parent) + : QGeoPositionInfoSource(parent) + , m_locationManager(0) + , m_started(false) + , m_updateTimer(0) + , m_updateTimeout(0) + , m_positionError(QGeoPositionInfoSource::UnknownSourceError) +{ +} + +QGeoPositionInfoSourceCL::~QGeoPositionInfoSourceCL() +{ + stopUpdates(); + [m_locationManager release]; +} + +void QGeoPositionInfoSourceCL::setUpdateInterval(int msec) +{ + // If msec is 0 we send updates as data becomes available, otherwise we force msec to be equal + // to or larger than the minimum update interval. + if (msec != 0 && msec < minimumUpdateInterval()) + msec = minimumUpdateInterval(); + + QGeoPositionInfoSource::setUpdateInterval(msec); + + // Must timeout if update takes longer than specified interval + m_updateTimeout = msec; + if (m_started) setTimeoutInterval(m_updateTimeout); +} + +bool QGeoPositionInfoSourceCL::enableLocationManager() +{ + if (!m_locationManager) { + m_locationManager = [[CLLocationManager alloc] init]; + m_locationManager.desiredAccuracy = kCLLocationAccuracyBest; + m_locationManager.delegate = [[locationDelegate alloc] initWithInfoSource:this]; + } + + return (m_locationManager != 0); +} + +void QGeoPositionInfoSourceCL::setTimeoutInterval(int msec) +{ + // Start timeout timer + if (m_updateTimer) killTimer(m_updateTimer); + if (msec > 0) m_updateTimer = startTimer(msec); + else m_updateTimer = 0; +} + +void QGeoPositionInfoSourceCL::startUpdates() +{ + if (enableLocationManager()) { + [m_locationManager startUpdatingLocation]; + m_started = true; + + setTimeoutInterval(m_updateTimeout); + } else setError(QGeoPositionInfoSource::AccessError); +} + +void QGeoPositionInfoSourceCL::stopUpdates() +{ + if (m_locationManager) { + [m_locationManager stopUpdatingLocation]; + m_started = false; + + // Stop timeout timer + setTimeoutInterval(0); + } else setError(QGeoPositionInfoSource::AccessError); +} + +void QGeoPositionInfoSourceCL::requestUpdate(int timeout) +{ + // Get a single update within timeframe + if (timeout < minimumUpdateInterval() && timeout != 0) + emit updateTimeout(); + else if (enableLocationManager()) { + // This will force LM to generate a new update + [m_locationManager stopUpdatingLocation]; + [m_locationManager startUpdatingLocation]; + + setTimeoutInterval(timeout); + } else setError(QGeoPositionInfoSource::AccessError); +} + +void QGeoPositionInfoSourceCL::timerEvent( QTimerEvent * event ) +{ + // Update timed out? + if (event->timerId() == m_updateTimer) { + emit updateTimeout(); + + // Only timeout once since last data + setTimeoutInterval(0); + + // Started for single update? + if (!m_started) stopUpdates(); + } +} + +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceCL::supportedPositioningMethods() const +{ + // CoreLocation doesn't say which positioning method(s) it used + return QGeoPositionInfoSource::AllPositioningMethods; +} + +int QGeoPositionInfoSourceCL::minimumUpdateInterval() const +{ + return MINIMUM_UPDATE_INTERVAL; +} + +void QGeoPositionInfoSourceCL::locationDataAvailable(QGeoPositionInfo location) +{ + // Signal position data available + m_lastUpdate = location; + emit positionUpdated(location); + + // Started for single update? + if (!m_started) stopUpdates(); + // ...otherwise restart timeout timer + else setTimeoutInterval(m_updateTimeout); +} + +QGeoPositionInfo QGeoPositionInfoSourceCL::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + Q_UNUSED(fromSatellitePositioningMethodsOnly) + + return m_lastUpdate; +} + +QGeoPositionInfoSource::Error QGeoPositionInfoSourceCL::error() const +{ + return m_positionError; +} + +void QGeoPositionInfoSourceCL::setError(QGeoPositionInfoSource::Error positionError) +{ + m_positionError = positionError; + emit QGeoPositionInfoSource::error(positionError); +} + +#include "moc_qgeopositioninfosource_cl_p.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h b/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h new file mode 100644 index 00000000..a73ce70e --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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 QGEOPOSITIONINFOSOURCECL_H +#define QGEOPOSITIONINFOSOURCECL_H + +#import <CoreLocation/CoreLocation.h> + +#include "qgeopositioninfosource.h" +#include "qgeopositioninfo.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGeoPositionInfoSourceCL : public QGeoPositionInfoSource +{ + Q_OBJECT +public: + QGeoPositionInfoSourceCL(QObject *parent = 0); + ~QGeoPositionInfoSourceCL(); + + QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; + PositioningMethods supportedPositioningMethods() const; + + void setUpdateInterval(int msec); + int minimumUpdateInterval() const; + Error error() const; + + void locationDataAvailable(QGeoPositionInfo location); + void setError(QGeoPositionInfoSource::Error positionError); + +private: + bool enableLocationManager(); + void setTimeoutInterval(int msec); + +public Q_SLOTS: + void startUpdates(); + void stopUpdates(); + + void requestUpdate(int timeout = 0); + +protected: + virtual void timerEvent(QTimerEvent *event); + +private: + Q_DISABLE_COPY(QGeoPositionInfoSourceCL); + CLLocationManager *m_locationManager; + bool m_started; + + QGeoPositionInfo m_lastUpdate; + + int m_updateTimer; + int m_updateTimeout; + + QGeoPositionInfoSource::Error m_positionError; +}; + +QT_END_NAMESPACE + +#endif // QGEOPOSITIONINFOSOURCECL_H diff --git a/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.h b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.h new file mode 100644 index 00000000..2ebbe5fc --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 QGEOPOSITIONINFOSOURCEFACTORY_CL_H +#define QGEOPOSITIONINFOSOURCEFACTORY_CL_H + +#include <QObject> +#include <QGeoPositionInfoSourceFactory> + +class QGeoPositionInfoSourceFactoryCL : public QObject, public QGeoPositionInfoSourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" + FILE "plugin.json") + Q_INTERFACES(QGeoPositionInfoSourceFactory) +public: + QGeoPositionInfoSource *positionInfoSource(QObject *parent); + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); + QGeoAreaMonitorSource *areaMonitor(QObject *parent); +}; + +#endif // QGEOPOSITIONINFOSOURCEFACTORY_CL_H diff --git a/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.mm b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.mm new file mode 100644 index 00000000..6566a255 --- /dev/null +++ b/src/plugins/position/corelocation/qgeopositioninfosourcefactory_cl.mm @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 "qgeopositioninfosource_cl_p.h" +#include "qgeopositioninfosourcefactory_cl.h" + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryCL::positionInfoSource(QObject *parent) +{ + return new QGeoPositionInfoSourceCL(parent); +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryCL::satelliteInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryCL::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return 0; +} diff --git a/src/plugins/position/geoclue/qgeocluemaster.cpp b/src/plugins/position/geoclue/qgeocluemaster.cpp index 7e05564d..a14ad896 100644 --- a/src/plugins/position/geoclue/qgeocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeocluemaster.cpp @@ -70,6 +70,9 @@ void position_provider_changed(GeoclueMasterClient *client, char *name, char *de QGeoclueMaster::QGeoclueMaster(QObject *handler) : m_client(0), m_masterPosition(0), m_handler(handler) { +#if !defined(GLIB_VERSION_2_36) + g_type_init(); +#endif } QGeoclueMaster::~QGeoclueMaster() diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp index e9124bcb..8401f187 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp @@ -47,6 +47,7 @@ #include <QtCore/QFile> #include <QtCore/QSaveFile> #include <QtCore/QStandardPaths> +#include <QtCore/QtNumeric> #ifdef Q_LOCATION_GEOCLUE_DEBUG #include <QDebug> @@ -134,6 +135,8 @@ QGeoPositionInfoSourceGeoclueMaster::QGeoPositionInfoSourceGeoclueMaster(QObject m_requestTimer.setSingleShot(true); QObject::connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); QObject::connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(startUpdatesTimeout())); + + setPreferredPositioningMethods(AllPositioningMethods); } QGeoPositionInfoSourceGeoclueMaster::~QGeoPositionInfoSourceGeoclueMaster() @@ -241,13 +244,6 @@ void QGeoPositionInfoSourceGeoclueMaster::regularUpdateSucceeded(GeocluePosition #endif } -bool QGeoPositionInfoSourceGeoclueMaster::init() -{ - g_type_init (); - - return true; -} - void QGeoPositionInfoSourceGeoclueMaster::cleanupPositionSource() { if (m_pos) { @@ -495,21 +491,19 @@ QGeoPositionInfo QGeoPositionInfoSourceGeoclueMaster::geoclueToPositionInfo( } QGeoPositionInfo info(coordinate, dateTime); if (accuracy) { - double horizontalAccuracy; - double verticalAccuracy; - GeoclueAccuracyLevel accuracyLevel; + double horizontalAccuracy = qQNaN(); + double verticalAccuracy = qQNaN(); + GeoclueAccuracyLevel accuracyLevel = GEOCLUE_ACCURACY_LEVEL_NONE; geoclue_accuracy_get_details(accuracy, &accuracyLevel, &horizontalAccuracy, &verticalAccuracy); #ifdef Q_LOCATION_GEOCLUE_DEBUG qDebug() << "QGeoPositionInfoSourceGeoclueMaster::accuracy horizontal vertical level: " << horizontalAccuracy << verticalAccuracy << accuracyLevel; #endif - if (accuracyLevel & GEOCLUE_ACCURACY_LEVEL_DETAILED) - m_lastPositionFromSatellite = true; - else - m_lastPositionFromSatellite = false; - if (accuracyLevel != GEOCLUE_ACCURACY_LEVEL_NONE) { + m_lastPositionFromSatellite = accuracyLevel & GEOCLUE_ACCURACY_LEVEL_DETAILED; + + if (!qIsNaN(horizontalAccuracy)) info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, horizontalAccuracy); + if (!qIsNaN(verticalAccuracy)) info.setAttribute(QGeoPositionInfo::VerticalAccuracy, verticalAccuracy); - } } return info; } diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h index 4ddf6603..912f32c1 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h @@ -78,7 +78,6 @@ public: PositioningMethods supportedPositioningMethods() const; void setPreferredPositioningMethods(PositioningMethods methods); int minimumUpdateInterval() const; - bool init(); void singleUpdateSucceeded(GeocluePositionFields fields, int timestamp, diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp index 9be36053..6be7888b 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp +++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp @@ -47,25 +47,18 @@ #include "qgeosatelliteinfosource_geocluemaster.h" #endif +Q_DECLARE_METATYPE(QGeoPositionInfo) + QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue::positionInfoSource(QObject *parent) { - QGeoPositionInfoSourceGeoclueMaster *src = new QGeoPositionInfoSourceGeoclueMaster(parent); - if (!src->init()) { - delete src; - src = 0; - } - return src; + qRegisterMetaType<QGeoPositionInfo>(); + return new QGeoPositionInfoSourceGeoclueMaster(parent); } QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGeoclue::satelliteInfoSource(QObject *parent) { #ifdef HAS_SATELLITE - QGeoSatelliteInfoSourceGeoclueMaster *src = new QGeoSatelliteInfoSourceGeoclueMaster(parent); - if (!src->init()) { - delete src; - src = 0; - } - return src; + return new QGeoSatelliteInfoSourceGeoclueMaster(parent); #else Q_UNUSED(parent) diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp index 6dcedeec..a5ef14a6 100644 --- a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp @@ -155,10 +155,10 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, QList<QGeoSatelli QGeoSatelliteInfoSourceGeoclueMaster::QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent) : QGeoSatelliteInfoSource(parent), QGeoclueMaster(this), m_sat(0), m_error(NoError), - m_satellitesChangedConnected(false) + m_satellitesChangedConnected(false), m_running(false) { m_requestTimer.setSingleShot(true); - connect(&m_requestTimer, SIGNAL(timeout()), this, SIGNAL(requestTimeout())); + connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); } QGeoSatelliteInfoSourceGeoclueMaster::~QGeoSatelliteInfoSourceGeoclueMaster() @@ -166,13 +166,6 @@ QGeoSatelliteInfoSourceGeoclueMaster::~QGeoSatelliteInfoSourceGeoclueMaster() cleanupSatelliteSource(); } -bool QGeoSatelliteInfoSourceGeoclueMaster::init() -{ - g_type_init(); - - return configureSatelliteSource(); -} - int QGeoSatelliteInfoSourceGeoclueMaster::minimumUpdateInterval() const { return MINIMUM_UPDATE_INTERVAL; @@ -185,6 +178,16 @@ QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceGeoclueMaster::error() con void QGeoSatelliteInfoSourceGeoclueMaster::startUpdates() { + if (m_running) + return; + + m_running = true; + + // Start Geoclue provider. + if (!hasMasterClient()) + configureSatelliteSource(); + + // m_sat is likely to be invalid until Geoclue master selects a position provider. if (!m_sat) return; @@ -193,13 +196,24 @@ void QGeoSatelliteInfoSourceGeoclueMaster::startUpdates() void QGeoSatelliteInfoSourceGeoclueMaster::stopUpdates() { - if (!m_sat) + if (!m_running) + return; + + if (m_sat) g_signal_handlers_disconnect_by_func(G_OBJECT(m_sat), gpointer(satellite_changed), this); + + m_running = false; + + // Only stop positioning if single update not requested. + if (!m_requestTimer.isActive()) { + cleanupSatelliteSource(); + releaseMasterClient(); + } } void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdate(int timeout) { - if ((timeout < minimumUpdateInterval() && timeout != 0) || !m_sat) { + if (timeout < minimumUpdateInterval() && timeout != 0) { emit requestTimeout(); return; } @@ -207,8 +221,13 @@ void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdate(int timeout) if (m_requestTimer.isActive()) return; + if (!hasMasterClient()) + configureSatelliteSource(); + m_requestTimer.start(qMax(timeout, minimumUpdateInterval())); - geoclue_satellite_get_satellite_async(m_sat, satellite_callback, this); + + if (m_sat) + geoclue_satellite_get_satellite_async(m_sat, satellite_callback, this); } void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(int timestamp, int satellitesUsed, @@ -252,6 +271,18 @@ void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdateFinished(int timestamp, satelliteChanged(timestamp, satellitesUsed, satellitesVisible, usedPrn, satInfos); } +void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdateTimeout() +{ + // If we end up here, there has not been a valid satellite info update. + emit requestTimeout(); + + // Only stop satellite info if regular updates not active. + if (!m_running) { + cleanupSatelliteSource(); + releaseMasterClient(); + } +} + void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QByteArray &service, const QByteArray &path) { if (m_sat) @@ -326,9 +357,6 @@ void QGeoSatelliteInfoSourceGeoclueMaster::satellitesChanged(const QDBusMessage bool QGeoSatelliteInfoSourceGeoclueMaster::configureSatelliteSource() { - cleanupSatelliteSource(); - releaseMasterClient(); - return createMasterClient(GEOCLUE_ACCURACY_LEVEL_DETAILED, GEOCLUE_RESOURCE_GPS); } diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h index 52cbb316..4ef1e8cf 100644 --- a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h @@ -62,8 +62,6 @@ public: explicit QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent = 0); ~QGeoSatelliteInfoSourceGeoclueMaster(); - bool init(); - int minimumUpdateInterval() const Q_DECL_OVERRIDE; Error error() const Q_DECL_OVERRIDE; @@ -78,6 +76,7 @@ public: const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos); private slots: + void requestUpdateTimeout(); void positionProviderChanged(const QByteArray &service, const QByteArray &path); void satellitesChanged(const QDBusMessage &message); @@ -91,6 +90,7 @@ private: QList<QGeoSatelliteInfo> m_inUse; Error m_error; bool m_satellitesChangedConnected; + bool m_running; }; QT_END_NAMESPACE diff --git a/src/plugins/position/position.pro b/src/plugins/position/position.pro index af2a5009..207b949b 100644 --- a/src/plugins/position/position.pro +++ b/src/plugins/position/position.pro @@ -4,6 +4,8 @@ config_geoclue:SUBDIRS += geoclue config_gypsy:SUBDIRS += gypsy simulator:SUBDIRS += simulator blackberry:SUBDIRS += blackberry +ios:SUBDIRS += corelocation +android:SUBDIRS += android SUBDIRS += \ positionpoll diff --git a/src/plugins/position/positionpoll/positionpollfactory.cpp b/src/plugins/position/positionpoll/positionpollfactory.cpp index 0f02bff1..2acafbc7 100644 --- a/src/plugins/position/positionpoll/positionpollfactory.cpp +++ b/src/plugins/position/positionpoll/positionpollfactory.cpp @@ -42,19 +42,19 @@ #include "positionpollfactory.h" #include "qgeoareamonitor_polling.h" -QGeoPositionInfoSource *PositionPollFactory::positionInfoSource(QObject *parent) +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryAndroid::positionInfoSource(QObject *parent) { Q_UNUSED(parent); return 0; } -QGeoSatelliteInfoSource *PositionPollFactory::satelliteInfoSource(QObject *parent) +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryAndroid::satelliteInfoSource(QObject *parent) { Q_UNUSED(parent); return 0; } -QGeoAreaMonitorSource *PositionPollFactory::areaMonitor(QObject *parent) +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryAndroid::areaMonitor(QObject *parent) { QGeoAreaMonitorPolling *ret = new QGeoAreaMonitorPolling(parent); if (ret && ret->isValid()) diff --git a/src/plugins/position/positionpoll/positionpollfactory.h b/src/plugins/position/positionpoll/positionpollfactory.h index 79ad85eb..4b7818d4 100644 --- a/src/plugins/position/positionpoll/positionpollfactory.h +++ b/src/plugins/position/positionpoll/positionpollfactory.h @@ -45,7 +45,7 @@ #include <QObject> #include <QGeoPositionInfoSourceFactory> -class PositionPollFactory : public QObject, public QGeoPositionInfoSourceFactory +class QGeoPositionInfoSourceFactoryAndroid : public QObject, public QGeoPositionInfoSourceFactory { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" diff --git a/src/plugins/position/positionpoll/qgeoareamonitor_polling.h b/src/plugins/position/positionpoll/qgeoareamonitor_polling.h index f25cd685..41e15d30 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 diff --git a/src/positioning/doc/snippets/cpp/cppqml.cpp b/src/positioning/doc/snippets/cpp/cppqml.cpp index 95d34b7c..605a5ed2 100644 --- a/src/positioning/doc/snippets/cpp/cppqml.cpp +++ b/src/positioning/doc/snippets/cpp/cppqml.cpp @@ -72,16 +72,16 @@ class MyClass : public QObject public: MyClass() : QObject() { - QGeoAreaMonitorSource *monitor = QGeoAreaMonitorSource::createDefaultMonitorSource(this); + QGeoAreaMonitorSource *monitor = QGeoAreaMonitorSource::createDefaultSource(this); if (monitor) { connect(monitor, SIGNAL(areaEntered(QGeoAreaMonitorInfo,QGeoPositionInfo)), - this, SLOT(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)); + bigBen.setArea(QGeoCircle(position, 100)); monitor->startMonitoring(bigBen); @@ -93,11 +93,15 @@ public: public Q_SLOTS: void areaEntered(const QGeoAreaMonitorInfo &mon, const QGeoPositionInfo &update) { + Q_UNUSED(mon) + qDebug() << "Now within 100 meters, current position is" << update.coordinate(); } void areaExited(const QGeoAreaMonitorInfo &mon, const QGeoPositionInfo &update) { + Q_UNUSED(mon) + qDebug() << "No longer within 100 meters, current position is" << update.coordinate(); } //! [BigBen] diff --git a/src/positioning/doc/snippets/snippets.pro b/src/positioning/doc/snippets/snippets.pro new file mode 100644 index 00000000..451d1c36 --- /dev/null +++ b/src/positioning/doc/snippets/snippets.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += cpp diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro index 7ad5f480..2e751bfb 100644 --- a/src/positioning/positioning.pro +++ b/src/positioning/positioning.pro @@ -1,11 +1,20 @@ TARGET = QtPositioning QT = core-private -QT += qml # the dependecy should be removed, see QTBUG-22330 - QMAKE_DOCS = $$PWD/doc/qtpositioning.qdocconf OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator +ANDROID_BUNDLED_JAR_DEPENDENCIES = \ + jar/QtPositioning-bundled.jar:org.qtproject.qt5.android.positioning.QtPositioning +ANDROID_JAR_DEPENDENCIES = \ + jar/QtPositioning.jar:org.qtproject.qt5.android.positioning.QtPositioning +ANDROID_PERMISSIONS = \ + android.permission.ACCESS_FINE_LOCATION +ANDROID_LIB_DEPENDENCIES = \ + plugins/position/libqtposition_android.so +MODULE_PLUGIN_TYPES = \ + position + PUBLIC_HEADERS += \ qgeoaddress.h \ qgeoareamonitorinfo.h \ diff --git a/src/positioning/qdeclarativegeoaddress_p.h b/src/positioning/qdeclarativegeoaddress_p.h index c3904a4f..6d8f5136 100644 --- a/src/positioning/qdeclarativegeoaddress_p.h +++ b/src/positioning/qdeclarativegeoaddress_p.h @@ -42,9 +42,8 @@ #ifndef QDECLARATIVEGEOADDRESS_P_H #define QDECLARATIVEGEOADDRESS_P_H -#include <qgeoaddress.h> -#include <QtCore> -#include <QtQml/qqml.h> +#include <QtCore/QObject> +#include <QtPositioning/QGeoAddress> QT_BEGIN_NAMESPACE @@ -108,6 +107,5 @@ private: }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeGeoAddress) #endif // QDECLARATIVEGEOADDRESS_P_H diff --git a/src/positioning/qdeclarativegeolocation_p.h b/src/positioning/qdeclarativegeolocation_p.h index 1352d827..08f28ef5 100644 --- a/src/positioning/qdeclarativegeolocation_p.h +++ b/src/positioning/qdeclarativegeolocation_p.h @@ -42,9 +42,7 @@ #ifndef QDECLARATIVEGEOLOCATION_P_H #define QDECLARATIVEGEOLOCATION_P_H - #include <QtCore/QObject> -#include <QtQml/qqml.h> #include <QtPositioning/QGeoLocation> #include <QtPositioning/QGeoRectangle> #include <QtPositioning/private/qdeclarativegeoaddress_p.h> @@ -89,6 +87,4 @@ private: QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeGeoLocation) - #endif // QDECLARATIVELOCATION_P_H diff --git a/src/positioning/qdoublevector2d_p.h b/src/positioning/qdoublevector2d_p.h index 760100c2..c3000f86 100644 --- a/src/positioning/qdoublevector2d_p.h +++ b/src/positioning/qdoublevector2d_p.h @@ -98,7 +98,9 @@ public: inline QDoubleVector2D &operator*=(const QDoubleVector2D &vector); inline QDoubleVector2D &operator/=(double divisor); - Q_DECL_CONSTEXPR static inline double dotProduct(const QDoubleVector2D &v1, const QDoubleVector2D &v2); + Q_DECL_CONSTEXPR static inline double dotProduct(const QDoubleVector2D &v1, const QDoubleVector2D &v2) + { return v1.xp * v2.xp + v1.yp * v2.yp; } + friend Q_DECL_CONSTEXPR inline bool operator==(const QDoubleVector2D &v1, const QDoubleVector2D &v2); friend Q_DECL_CONSTEXPR inline bool operator!=(const QDoubleVector2D &v1, const QDoubleVector2D &v2); @@ -183,11 +185,6 @@ inline QDoubleVector2D &QDoubleVector2D::operator/=(double divisor) return *this; } -Q_DECL_CONSTEXPR inline double QDoubleVector2D::dotProduct(const QDoubleVector2D &v1, const QDoubleVector2D &v2) -{ - return v1.xp * v2.xp + v1.yp * v2.yp; -} - Q_DECL_CONSTEXPR inline bool operator==(const QDoubleVector2D &v1, const QDoubleVector2D &v2) { return v1.xp == v2.xp && v1.yp == v2.yp; diff --git a/src/positioning/qdoublevector3d_p.h b/src/positioning/qdoublevector3d_p.h index 68e6475d..75966a36 100644 --- a/src/positioning/qdoublevector3d_p.h +++ b/src/positioning/qdoublevector3d_p.h @@ -101,8 +101,14 @@ public: inline QDoubleVector3D &operator*=(const QDoubleVector3D &vector); inline QDoubleVector3D &operator/=(double divisor); - Q_DECL_CONSTEXPR static inline double dotProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2); - Q_DECL_CONSTEXPR static inline QDoubleVector3D crossProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2); + Q_DECL_CONSTEXPR static inline double dotProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2) + { return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp; } + + Q_DECL_CONSTEXPR static inline QDoubleVector3D crossProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2) + { return QDoubleVector3D(v1.yp * v2.zp - v1.zp * v2.yp, + v1.zp * v2.xp - v1.xp * v2.zp, + v1.xp * v2.yp - v1.yp * v2.xp); } + static QDoubleVector3D normal(const QDoubleVector3D &v1, const QDoubleVector3D &v2); static QDoubleVector3D normal (const QDoubleVector3D &v1, const QDoubleVector3D &v2, const QDoubleVector3D &v3); @@ -231,18 +237,6 @@ inline QDoubleVector3D &QDoubleVector3D::operator/=(double divisor) return *this; } -Q_DECL_CONSTEXPR inline double QDoubleVector3D::dotProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2) -{ - return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp; -} - -Q_DECL_CONSTEXPR inline QDoubleVector3D QDoubleVector3D::crossProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2) -{ - return QDoubleVector3D(v1.yp * v2.zp - v1.zp * v2.yp, - v1.zp * v2.xp - v1.xp * v2.zp, - v1.xp * v2.yp - v1.yp * v2.xp); -} - Q_DECL_CONSTEXPR inline bool operator==(const QDoubleVector3D &v1, const QDoubleVector3D &v2) { return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp; diff --git a/src/positioning/qgeoaddress.h b/src/positioning/qgeoaddress.h index 5d9371c5..1aedd1a5 100644 --- a/src/positioning/qgeoaddress.h +++ b/src/positioning/qgeoaddress.h @@ -44,7 +44,7 @@ #include <QtCore/QMetaType> #include <QtCore/QSharedDataPointer> -#include "qpositioningglobal.h" +#include <QtPositioning/qpositioningglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/positioning/qgeocoordinate.h b/src/positioning/qgeocoordinate.h index a4e76906..23001ad1 100644 --- a/src/positioning/qgeocoordinate.h +++ b/src/positioning/qgeocoordinate.h @@ -45,7 +45,7 @@ #include <QtCore/QMetaType> #include <QtCore/QString> #include <QSharedDataPointer> -#include "qpositioningglobal.h" +#include <QtPositioning/qpositioningglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/positioning/qgeolocation.h b/src/positioning/qgeolocation.h index 5d1aa98c..395f83f1 100644 --- a/src/positioning/qgeolocation.h +++ b/src/positioning/qgeolocation.h @@ -44,7 +44,7 @@ #include <QtCore/QSharedDataPointer> #include <QtCore/QMetaType> -#include "qpositioningglobal.h" +#include <QtPositioning/qpositioningglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/positioning/qgeosatelliteinfo.h b/src/positioning/qgeosatelliteinfo.h index b6c70e4c..fb13157d 100644 --- a/src/positioning/qgeosatelliteinfo.h +++ b/src/positioning/qgeosatelliteinfo.h @@ -41,7 +41,7 @@ #ifndef QGEOSATELLITEINFO_H #define QGEOSATELLITEINFO_H -#include "qpositioningglobal.h" +#include <QtPositioning/qpositioningglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/positioning/qlocationutils.cpp b/src/positioning/qlocationutils.cpp index 5d6cfbb2..830ac64a 100644 --- a/src/positioning/qlocationutils.cpp +++ b/src/positioning/qlocationutils.cpp @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -58,7 +60,8 @@ static double qlocationutils_nmeaDegreesToDecimal(double nmeaDegrees) return deg + (min / 60.0); } -static void qlocationutils_readGga(const char *data, int size, QGeoPositionInfo *info, bool *hasFix) +static void qlocationutils_readGga(const char *data, int size, QGeoPositionInfo *info, double uere, + bool *hasFix) { QByteArray sentence(data, size); QList<QByteArray> parts = sentence.split(','); @@ -82,6 +85,13 @@ static void qlocationutils_readGga(const char *data, int size, QGeoPositionInfo } } + if (parts.count() > 8 && !parts[8].isEmpty()) { + bool hasHdop = false; + double hdop = parts[8].toDouble(&hasHdop); + if (hasHdop) + info->setAttribute(QGeoPositionInfo::HorizontalAccuracy, 2 * hdop * uere); + } + if (parts.count() > 9 && parts[9].count() > 0) { bool hasAlt = false; double alt = parts[9].toDouble(&hasAlt); @@ -93,6 +103,29 @@ static void qlocationutils_readGga(const char *data, int size, QGeoPositionInfo info->setCoordinate(coord); } +static void qlocationutils_readGsa(const char *data, int size, QGeoPositionInfo *info, double uere, + bool *hasFix) +{ + QList<QByteArray> parts = QByteArray::fromRawData(data, size).split(','); + + if (hasFix && parts.count() > 2 && !parts[2].isEmpty()) + *hasFix = parts[2].toInt() > 0; + + if (parts.count() > 16 && !parts[16].isEmpty()) { + bool hasHdop = false; + double hdop = parts[16].toDouble(&hasHdop); + if (hasHdop) + info->setAttribute(QGeoPositionInfo::HorizontalAccuracy, 2 * hdop * uere); + } + + if (parts.count() > 17 && !parts[17].isEmpty()) { + bool hasVdop = false; + double vdop = parts[17].toDouble(&hasVdop); + if (hasVdop) + info->setAttribute(QGeoPositionInfo::VerticalAccuracy, 2 * vdop * uere); + } +} + static void qlocationutils_readGll(const char *data, int size, QGeoPositionInfo *info, bool *hasFix) { QByteArray sentence(data, size); @@ -227,7 +260,8 @@ static void qlocationutils_readZda(const char *data, int size, QGeoPositionInfo info->setTimestamp(QDateTime(date, time, Qt::UTC)); } -bool QLocationUtils::getPosInfoFromNmea(const char *data, int size, QGeoPositionInfo *info, bool *hasFix) +bool QLocationUtils::getPosInfoFromNmea(const char *data, int size, QGeoPositionInfo *info, + double uere, bool *hasFix) { if (!info) return false; @@ -237,9 +271,23 @@ bool QLocationUtils::getPosInfoFromNmea(const char *data, int size, QGeoPosition if (size < 6 || data[0] != '$' || !hasValidNmeaChecksum(data, size)) return false; + // Adjust size so that * and following characters are not parsed by the following functions. + for (int i = 0; i < size; ++i) { + if (data[i] == '*') { + size = i; + break; + } + } + if (data[3] == 'G' && data[4] == 'G' && data[5] == 'A') { // "$--GGA" sentence. - qlocationutils_readGga(data, size, info, hasFix); + qlocationutils_readGga(data, size, info, uere, hasFix); + return true; + } + + if (data[3] == 'G' && data[4] == 'S' && data[5] == 'A') { + // "$--GSA" sentence. + qlocationutils_readGsa(data, size, info, uere, hasFix); return true; } diff --git a/src/positioning/qlocationutils_p.h b/src/positioning/qlocationutils_p.h index 4b42695c..10dd61d4 100644 --- a/src/positioning/qlocationutils_p.h +++ b/src/positioning/qlocationutils_p.h @@ -94,7 +94,9 @@ public: - RMC reports date with a two-digit year so in this case the year is assumed to be after the year 2000. */ - Q_AUTOTEST_EXPORT static bool getPosInfoFromNmea(const char *data, int size, QGeoPositionInfo *info, bool *hasFix = 0); + Q_AUTOTEST_EXPORT static bool getPosInfoFromNmea(const char *data, int size, + QGeoPositionInfo *info, double uere, + bool *hasFix = 0); /* Returns true if the given NMEA sentence has a valid checksum. diff --git a/src/positioning/qnmeapositioninfosource.cpp b/src/positioning/qnmeapositioninfosource.cpp index 9ac928b2..23706a4f 100644 --- a/src/positioning/qnmeapositioninfosource.cpp +++ b/src/positioning/qnmeapositioninfosource.cpp @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -45,6 +47,7 @@ #include <QBasicTimer> #include <QTimerEvent> #include <QTimer> +#include <QtCore/QtNumeric> QT_BEGIN_NAMESPACE @@ -133,8 +136,7 @@ void QNmeaSimulatedReader::simulatePendingUpdate() if (m_pendingUpdates.size() > 0) { // will be dequeued in processNextSentence() QPendingGeoPositionInfo &pending = m_pendingUpdates.head(); - if (pending.info.coordinate().type() != QGeoCoordinate::InvalidCoordinate) - m_proxy->notifyNewUpdate(&pending.info, pending.hasFix); + m_proxy->notifyNewUpdate(&pending.info, pending.hasFix); } processNextSentence(); @@ -173,6 +175,9 @@ void QNmeaSimulatedReader::processNextSentence() timeToNextUpdate = prevTime.msecsTo(time); if (timeToNextUpdate >= 0) break; + } else { + timeToNextUpdate = 0; + break; } } } @@ -199,10 +204,13 @@ QNmeaPositionInfoSourcePrivate::QNmeaPositionInfoSourcePrivate(QNmeaPositionInfo m_device(0), m_invokedStart(false), m_positionError(QGeoPositionInfoSource::UnknownSourceError), + m_userEquivalentRangeError(qQNaN()), m_source(parent), m_nmeaReader(0), m_updateTimer(0), m_requestTimer(0), + m_horizontalAccuracy(qQNaN()), + m_verticalAccuracy(qQNaN()), m_noUpdateLastInterval(false), m_updateTimeoutSent(false), m_connectedReadyRead(false) @@ -375,6 +383,17 @@ void QNmeaPositionInfoSourcePrivate::notifyNewUpdate(QGeoPositionInfo *update, b update->setTimestamp(QDateTime(m_currentDate, time, Qt::UTC)); } + // Some attributes are sent in separate NMEA sentences. Save and restore the accuracy + // measurements. + if (update->hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + m_horizontalAccuracy = update->attribute(QGeoPositionInfo::HorizontalAccuracy); + else if (!qIsNaN(m_horizontalAccuracy)) + update->setAttribute(QGeoPositionInfo::HorizontalAccuracy, m_horizontalAccuracy); + if (update->hasAttribute(QGeoPositionInfo::VerticalAccuracy)) + m_verticalAccuracy = update->attribute(QGeoPositionInfo::VerticalAccuracy); + else if (!qIsNaN(m_verticalAccuracy)) + update->setAttribute(QGeoPositionInfo::VerticalAccuracy, m_verticalAccuracy); + if (hasFix && update->isValid()) { if (m_requestTimer && m_requestTimer->isActive()) { m_requestTimer->stop(); @@ -451,6 +470,10 @@ void QNmeaPositionInfoSourcePrivate::emitUpdated(const QGeoPositionInfo &update) In both cases the position information is received via the positionUpdated() signal and the last known position can be accessed with lastKnownPosition(). + + QNmeaPositionInfoSource supports reporting the accuracy of the horizontal and vertical position. + To enable position accuracy reporting an estimate of the User Equivalent Range Error associated + with the NMEA source must be set with setUserEquivalentRangeError(). */ @@ -482,6 +505,41 @@ QNmeaPositionInfoSource::~QNmeaPositionInfoSource() } /*! + Sets the User Equivalent Range Error (UERE) to \a uere. The UERE is used in calculating an + estimate of the accuracy of the position information reported by the position info source. The + UERE should be set to a value appropriate for the GPS device which generated the NMEA stream. + + The true UERE value is calculated from multiple error sources including errors introduced by + the satellites and signal propogation delays through the atmosphere as well as errors + introduced by the receiving GPS equipment. For details on GPS accuracy see + \l {http://edu-observatory.org/gps/gps_accuracy.html}. + + A typical value for UERE is approximately 5.1. + + \since 5.3 + + \sa userEquivalentRangeError() +*/ +void QNmeaPositionInfoSource::setUserEquivalentRangeError(double uere) +{ + d->m_userEquivalentRangeError = uere; +} + +/*! + Returns the current User Equivalent Range Error (UERE). The UERE is used in calculating an + estimate of the accuracy of the position information reported by the position info source. The + default value is NaN which means no accuracy information will be provided. + + \since 5.3 + + \sa setUserEquivalentRangeError() +*/ +double QNmeaPositionInfoSource::userEquivalentRangeError() const +{ + return d->m_userEquivalentRangeError; +} + +/*! Parses an NMEA sentence string into a QGeoPositionInfo. The default implementation will parse standard NMEA sentences. @@ -498,7 +556,8 @@ QNmeaPositionInfoSource::~QNmeaPositionInfoSource() bool QNmeaPositionInfoSource::parsePosInfoFromNmeaData(const char *data, int size, QGeoPositionInfo *posInfo, bool *hasFix) { - return QLocationUtils::getPosInfoFromNmea(data, size, posInfo, hasFix); + return QLocationUtils::getPosInfoFromNmea(data, size, posInfo, d->m_userEquivalentRangeError, + hasFix); } /*! diff --git a/src/positioning/qnmeapositioninfosource.h b/src/positioning/qnmeapositioninfosource.h index 605a5696..ae19309f 100644 --- a/src/positioning/qnmeapositioninfosource.h +++ b/src/positioning/qnmeapositioninfosource.h @@ -60,6 +60,9 @@ public: explicit QNmeaPositionInfoSource(UpdateMode updateMode, QObject *parent = 0); ~QNmeaPositionInfoSource(); + void setUserEquivalentRangeError(double uere); + double userEquivalentRangeError() const; + UpdateMode updateMode() const; void setDevice(QIODevice *source); diff --git a/src/positioning/qnmeapositioninfosource_p.h b/src/positioning/qnmeapositioninfosource_p.h index ec9ebeaf..afe0b3aa 100644 --- a/src/positioning/qnmeapositioninfosource_p.h +++ b/src/positioning/qnmeapositioninfosource_p.h @@ -96,6 +96,7 @@ public: QGeoPositionInfo m_lastUpdate; bool m_invokedStart; QGeoPositionInfoSource::Error m_positionError; + double m_userEquivalentRangeError; public Q_SLOTS: void readyRead(); @@ -120,6 +121,8 @@ private: QGeoPositionInfo m_pendingUpdate; QDate m_currentDate; QTimer *m_requestTimer; + qreal m_horizontalAccuracy; + qreal m_verticalAccuracy; bool m_noUpdateLastInterval; bool m_updateTimeoutSent; bool m_connectedReadyRead; diff --git a/src/src.pro b/src/src.pro index f6e41510..72274cdc 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,13 +1,30 @@ TEMPLATE = subdirs -CONFIG += ordered SUBDIRS += positioning +plugins.depends = positioning +SUBDIRS += plugins + +positioning_doc_snippets.subdir = positioning/doc/snippets +positioning_doc_snippets.depends = positioning +SUBDIRS += positioning_doc_snippets + #no point in building QtLocation without Qt3D qtHaveModule(3d) { - SUBDIRS += location 3rdparty -} + SUBDIRS += 3rdparty -SUBDIRS += plugins -qtHaveModule(quick): SUBDIRS += imports + location.depends = positioning 3rdparty + SUBDIRS += location + plugins.depends += location + qtHaveModule(quick):imports.depends += location + + location_doc_snippets.subdir = location/doc/snippets + location_doc_snippets.depends = location + SUBDIRS += location_doc_snippets +} + +qtHaveModule(quick) { + imports.depends += positioning + SUBDIRS += imports +} diff --git a/tests/auto/declarative_core/declarative_core.pro b/tests/auto/declarative_core/declarative_core.pro index cc6b3d89..34f54b2a 100644 --- a/tests/auto/declarative_core/declarative_core.pro +++ b/tests/auto/declarative_core/declarative_core.pro @@ -11,5 +11,3 @@ QT += location quick OTHER_FILES = *.qml *.js TESTDATA = $$OTHER_FILES DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 - -CONFIG+=insignificant_test # QTBUG-31798 diff --git a/tests/auto/declarative_core/main.cpp b/tests/auto/declarative_core/main.cpp index 10f4a1a7..2a30f5c3 100644 --- a/tests/auto/declarative_core/main.cpp +++ b/tests/auto/declarative_core/main.cpp @@ -39,5 +39,16 @@ ** ****************************************************************************/ +#include <QtCore/QCoreApplication> #include <QtQuickTest/quicktest.h> + +static void initializeLibraryPath() +{ + // Set custom path since CI doesn't install test plugins + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +} + +Q_COREAPP_STARTUP_FUNCTION(initializeLibraryPath) + QUICK_TEST_MAIN(declarative_core) diff --git a/tests/auto/declarative_core/tst_category.qml b/tests/auto/declarative_core/tst_category.qml index 068ae5f9..0f8addb8 100644 --- a/tests/auto/declarative_core/tst_category.qml +++ b/tests/auto/declarative_core/tst_category.qml @@ -137,18 +137,10 @@ TestCase { } function test_save() { - var modelSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); - modelSpy.target = categoryModel.model; - modelSpy.signalName = "statusChanged" - categoryModel.model.update(); tryCompare(categoryModel.model, "status", CategoryModel.Ready); compare(categoryModel.count, 0); - var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); - signalSpy.target = saveCategory; - signalSpy.signalName = "statusChanged"; - saveCategory.plugin = testPlugin; saveCategory.categoryId = "invalid-category-id"; @@ -211,15 +203,9 @@ TestCase { tryCompare(saveCategory, "status", Category.Error); verify(saveCategory.errorString().length > 0); - - signalSpy.destroy(); } function test_saveWithoutPlugin() { - var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); - signalSpy.target = saveCategory; - signalSpy.signalName = "statusChanged"; - saveCategory.plugin = null; saveCategory.categoryId = ""; @@ -238,15 +224,9 @@ TestCase { verify(saveCategory.errorString().length > 0); compare(saveCategory.categoryId, ""); - - signalSpy.destroy(); } function test_removeWithoutPlugin() { - var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); - signalSpy.target = saveCategory; - signalSpy.signalName = "statusChanged"; - saveCategory.plugin = null; saveCategory.categoryId = "test-category-id"; @@ -265,7 +245,5 @@ TestCase { verify(saveCategory.errorString().length > 0); compare(saveCategory.categoryId, "test-category-id"); - - signalSpy.destroy(); } } diff --git a/tests/auto/declarative_core/tst_editorialmodel.qml b/tests/auto/declarative_core/tst_editorialmodel.qml index 9c551972..ae01b4fd 100644 --- a/tests/auto/declarative_core/tst_editorialmodel.qml +++ b/tests/auto/declarative_core/tst_editorialmodel.qml @@ -93,7 +93,16 @@ TestCase { Utils.testObjectProperties(testCase, testModel, data); } - function test_consecutive_fetch() { + function test_consecutive_fetch_data() { + return [ + { tag: "batchSize 1", batchSize: 1 }, + { tag: "batchSize 2", batchSize: 2 }, + { tag: "batchSize 5", batchSize: 5 }, + { tag: "batchSize 10", batchSize: 10 }, + ]; + } + + function test_consecutive_fetch(data) { var expectedEditorials = [ { "title": "Editorial 1", @@ -123,7 +132,7 @@ TestCase { ] var model = createModel(); - Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedEditorials); + Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedEditorials, data); model.destroy(); } diff --git a/tests/auto/declarative_core/tst_imagemodel.qml b/tests/auto/declarative_core/tst_imagemodel.qml index afb596e4..31f1e448 100644 --- a/tests/auto/declarative_core/tst_imagemodel.qml +++ b/tests/auto/declarative_core/tst_imagemodel.qml @@ -93,7 +93,16 @@ TestCase { Utils.testObjectProperties(testCase, testModel, data); } - function test_consecutive_fetch() { + function test_consecutive_fetch_data() { + return [ + { tag: "batchSize 1", batchSize: 1 }, + { tag: "batchSize 2", batchSize: 2 }, + { tag: "batchSize 5", batchSize: 5 }, + { tag: "batchSize 10", batchSize: 10 }, + ]; + } + + function test_consecutive_fetch(data) { var expectedImages = [ { "url": "http://somewhere.com/image1.png", @@ -123,7 +132,7 @@ TestCase { ] var model = createModel(); - Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedImages); + Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedImages, data); model.destroy(); } diff --git a/tests/auto/declarative_core/tst_place.qml b/tests/auto/declarative_core/tst_place.qml index de73ab88..598872a7 100644 --- a/tests/auto/declarative_core/tst_place.qml +++ b/tests/auto/declarative_core/tst_place.qml @@ -242,22 +242,18 @@ TestCase { // check icon if (place1.icon === null && place2.icon !== null) { - console.log("f1"); return false; } if (place1.icon !== null && place2.icon === null) { - console.log("f2"); return false; } if (place1.icon !== null && place2.icon !== null) { if (place1.icon.plugin !== place2.icon.plugin) { - console.log("f3"); console.log(place1.icon.plugin + " " + place2.icon.plugin); return false; } if (place1.icon.parameters.keys().length !== place2.icon.parameters.keys().length) { - console.log("f4"); return false; } diff --git a/tests/auto/declarative_core/tst_placesearchmodel.qml b/tests/auto/declarative_core/tst_placesearchmodel.qml index fba80815..2020a4f8 100644 --- a/tests/auto/declarative_core/tst_placesearchmodel.qml +++ b/tests/auto/declarative_core/tst_placesearchmodel.qml @@ -101,7 +101,6 @@ TestCase { return [ { tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin }, { tag: "searchArea", property: "searchArea", signal: "searchAreaChanged", value: testSearchArea, reset: QtPositioning.shape() }, - { tag: "offset", property: "offset", signal: "offsetChanged", value: 10, reset: 0 }, { tag: "limit", property: "limit", signal: "limitChanged", value: 10, reset: -1 }, { tag: "searchTerm", property: "searchTerm", signal: "searchTermChanged", value: "Test term", reset: "" }, @@ -257,7 +256,7 @@ TestCase { //try cancelling from an initially ready state testModel.update(); - tryCompare(testModel.status, PlaceSearchModel.Loading); + tryCompare(testModel, "status", PlaceSearchModel.Loading); testModel.cancel(); tryCompare(testModel, "status", PlaceSearchModel.Ready); compare(testModel.count, numResults); diff --git a/tests/auto/declarative_core/tst_placesearchsuggestionmodel.qml b/tests/auto/declarative_core/tst_placesearchsuggestionmodel.qml index 35d61c2f..51f348e3 100644 --- a/tests/auto/declarative_core/tst_placesearchsuggestionmodel.qml +++ b/tests/auto/declarative_core/tst_placesearchsuggestionmodel.qml @@ -54,6 +54,10 @@ TestCase { id: testModel } + PlaceSearchSuggestionModel { + id: testModelError + } + Plugin { id: testPlugin name: "qmlgeo.test.plugin" @@ -74,7 +78,6 @@ TestCase { return [ { tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin }, { tag: "searchArea", property: "searchArea", signal: "searchAreaChanged", value: testSearchArea, reset: QtPositioning.shape() }, - { tag: "offset", property: "offset", signal: "offsetChanged", value: 10, reset: 0 }, { tag: "limit", property: "limit", signal: "limitChanged", value: 10, reset: -1 }, { tag: "searchTerm", property: "searchTerm", signal: "searchTermChanged", value: "Test term", reset: "" }, @@ -85,17 +88,13 @@ TestCase { Utils.testObjectProperties(testCase, testModel, data); } + SignalSpy { id: statusChangedSpy; target: testModel; signalName: "statusChanged" } + SignalSpy { id: suggestionsChangedSpy; target: testModel; signalName: "suggestionsChanged" } + function test_suggestions() { + compare(statusChangedSpy.count, 0); testModel.plugin = testPlugin; - var statusChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); - statusChangedSpy.target = testModel; - statusChangedSpy.signalName = "statusChanged"; - - var suggestionsChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); - suggestionsChangedSpy.target = testModel; - suggestionsChangedSpy.signalName = "suggestionsChanged"; - compare(testModel.status, PlaceSearchSuggestionModel.Null); testModel.searchTerm = "test"; @@ -129,45 +128,39 @@ TestCase { compare(statusChangedSpy.count, 5); compare(testModel.status, PlaceSearchSuggestionModel.Ready); - //chack that an encountering an error will cause the model + //check that an encountering an error will cause the model //to clear its data testModel.plugin = null; testModel.update(); tryCompare(testModel.suggestions, "length", 0); compare(testModel.status, PlaceSearchSuggestionModel.Error); - - suggestionsChangedSpy.destroy(); - statusChangedSpy.destroy(); } - function test_error() { - var testModel = Qt.createQmlObject('import QtLocation 5.0; PlaceSearchSuggestionModel {}', testCase, "PlaceSearchSuggestionModel"); - - var statusChangedSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); - statusChangedSpy.target = testModel; - statusChangedSpy.signalName = "statusChanged"; + SignalSpy { id: statusChangedSpyError; target: testModelError; signalName: "statusChanged" } + function test_error() { + compare(statusChangedSpyError.count, 0); //try searching without a plugin instance - testModel.update(); - tryCompare(statusChangedSpy, "count", 2); - compare(testModel.status, PlaceSearchSuggestionModel.Error); - statusChangedSpy.clear(); + testModelError.update(); + tryCompare(statusChangedSpyError, "count", 2); + compare(testModelError.status, PlaceSearchSuggestionModel.Error); + statusChangedSpyError.clear(); //Aside: there is some difficulty in checking the transition to the Loading state //since the model transitions from Loading to Error before the next event loop //iteration. //try searching with an uninitialized plugin instance. - testModel.plugin = uninitializedPlugin; - testModel.update(); - tryCompare(statusChangedSpy, "count", 2); - compare(testModel.status, PlaceSearchSuggestionModel.Error); - statusChangedSpy.clear(); + testModelError.plugin = uninitializedPlugin; + testModelError.update(); + tryCompare(statusChangedSpyError, "count", 2); + compare(testModelError.status, PlaceSearchSuggestionModel.Error); + statusChangedSpyError.clear(); //try searching with plugin a instance //that has been provided a non-existent name - testModel.plugin = nonExistantPlugin; - testModel.update(); - tryCompare(statusChangedSpy, "count", 2); - compare(testModel.status, PlaceSearchSuggestionModel.Error); + testModelError.plugin = nonExistantPlugin; + testModelError.update(); + tryCompare(statusChangedSpyError, "count", 2); + compare(testModelError.status, PlaceSearchSuggestionModel.Error); } } diff --git a/tests/auto/declarative_core/tst_positionsource.qml b/tests/auto/declarative_core/tst_positionsource.qml index e11408b6..6cf99d04 100644 --- a/tests/auto/declarative_core/tst_positionsource.qml +++ b/tests/auto/declarative_core/tst_positionsource.qml @@ -91,19 +91,24 @@ TestCase { // On construction, if the provided source name is invalid, the default source will be // used. Test that the source is valid as expected. - compare(testSetSource.name, "test.source"); + verify(testSetSource.name !== ""); + //we don't really know what the default source is named. + //It may not be "test.source" + var defaultSourceName = testSetSource.name; verify(testSetSource.valid); // Test that setting name to "" will still use the default. testSetSource.name = ""; compare(testingSourcePluginSpy.count, 0); - compare(testSetSource.name, "test.source"); + compare(testSetSource.name, defaultSourceName); verify(testSetSource.valid); testSetSource.name = "test.source"; - compare(testingSourcePluginSpy.count, 0); + if (defaultSourceName === "test.source") + compare(testingSourcePluginSpy.count, 0); compare(testSetSource.name, "test.source"); verify(testSetSource.valid); + testingSourcePluginSpy.clear(); testSetSource.name = "bogus"; compare(testingSourcePluginSpy.count, 1); @@ -122,6 +127,15 @@ TestCase { compare(testingSource.updateInterval, 1000); } + function test_preferredPositioningMethods() { + testingSource.preferredPositioningMethods = PositionSource.AllPositioningMethods; + compare(testingSource.preferredPositioningMethods, PositionSource.AllPositioningMethods); + testingSource.preferredPositioningMethods = PositionSource.SatellitePositioningMethods; + compare(testingSource.preferredPositioningMethods, PositionSource.SatellitePositioningMethods); + testingSource.preferredPositioningMethods = PositionSource.NonSatellitePositioningMethods; + compare(testingSource.preferredPositioningMethods, PositionSource.NonSatellitePositioningMethods); + } + function test_updates() { updateSpy.clear(); diff --git a/tests/auto/declarative_core/tst_reviewmodel.qml b/tests/auto/declarative_core/tst_reviewmodel.qml index ca195077..62a7ac5e 100644 --- a/tests/auto/declarative_core/tst_reviewmodel.qml +++ b/tests/auto/declarative_core/tst_reviewmodel.qml @@ -92,7 +92,16 @@ TestCase { Utils.testObjectProperties(testCase, testModel, data); } - function test_consecutive_fetch() { + function test_consecutive_fetch_data() { + return [ + { tag: "batchSize 1", batchSize: 1 }, + { tag: "batchSize 2", batchSize: 2 }, + { tag: "batchSize 5", batchSize: 5 }, + { tag: "batchSize 10", batchSize: 10 }, + ]; + } + + function test_consecutive_fetch(data) { //Note: in javascript the months go from 0(Jan) to 11(Dec) var expectedReviews = [ { @@ -138,7 +147,7 @@ TestCase { ] var model = createModel(); - Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedReviews); + Utils.testConsecutiveFetch(testCase, model, parkViewHotel, expectedReviews, data); model.destroy(); } diff --git a/tests/auto/declarative_core/utils.js b/tests/auto/declarative_core/utils.js index 0a659ab2..5370bab5 100644 --- a/tests/auto/declarative_core/utils.js +++ b/tests/auto/declarative_core/utils.js @@ -91,7 +91,7 @@ function compareObj(testCase, obj1, obj2) { } } -function testConsecutiveFetch(testCase, model, place, expectedValues) +function testConsecutiveFetch(testCase, model, place, expectedValues, data) { var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy"); signalSpy.target = model; @@ -108,35 +108,31 @@ function testConsecutiveFetch(testCase, model, place, expectedValues) testCase.compare(visDataModel.items.count, 0); //perform an initial fetch with the default batch size + model.batchSize = data.batchSize model.place = place; testCase.tryCompare(signalSpy, "count", 1); signalSpy.clear(); var totalCount = model.totalCount; testCase.compare(totalCount, 5); - testCase.compare(visDataModel.items.count, 1); + testCase.compare(visDataModel.items.count, Math.min(data.batchSize, totalCount)); compareObj(testCase, visDataModel.items.get(0).model, expectedValues[0]); - //set a non-default batch size and fetch the next batch - model.batchSize = 2; - visDataModel.items.create(0); //'creating' the last item will trigger a fetch - testCase.tryCompare(visDataModel.items, "count", 3); - testCase.compare(signalSpy.count, 0); - testCase.compare(model.totalCount, totalCount); - - compareObj(testCase, visDataModel.items.get(1).model, expectedValues[1]); - compareObj(testCase, visDataModel.items.get(2).model, expectedValues[2]); - - //set a batch size greater than the number of remaining items and fetch that batch - model.batchSize = 10; - visDataModel.items.create(2); - testCase.tryCompare(visDataModel.items, "count", totalCount); - testCase.compare(signalSpy.count, 0); - testCase.compare(model.totalCount, totalCount); - - compareObj(testCase, visDataModel.items.get(3).model, expectedValues[3]); - compareObj(testCase, visDataModel.items.get(4).model, expectedValues[4]); + //fetch remaining items, in batchSize batches + while (visDataModel.items.count < totalCount) { + var startIndex = visDataModel.items.count + + //'creating' the last item will trigger a fetch + visDataModel.items.create(visDataModel.items.count - 1); + + testCase.tryCompare(visDataModel.items, "count", Math.min(totalCount, startIndex + data.batchSize)); + testCase.compare(signalSpy.count, 0); + testCase.compare(model.totalCount, totalCount); + + for (var i = startIndex; i < Math.min(totalCount, startIndex + data.batchSize); ++i) + compareObj(testCase, visDataModel.items.get(i).model, expectedValues[i]); + } visDataModel.destroy(); signalSpy.destroy(); diff --git a/tests/auto/declarative_ui/declarative_ui.pro b/tests/auto/declarative_ui/declarative_ui.pro index 9fdf3538..0cd6735a 100644 --- a/tests/auto/declarative_ui/declarative_ui.pro +++ b/tests/auto/declarative_ui/declarative_ui.pro @@ -13,3 +13,6 @@ TESTDATA = $$OTHER_FILES win32|linux:CONFIG+=insignificant_test # QTBUG-31797 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +# Import path used by 'make check' since CI doesn't install test imports +IMPORTPATH = $$OUT_PWD/../../../qml diff --git a/tests/auto/declarative_ui/main.cpp b/tests/auto/declarative_ui/main.cpp index df5d9621..ec27fd56 100644 --- a/tests/auto/declarative_ui/main.cpp +++ b/tests/auto/declarative_ui/main.cpp @@ -39,5 +39,16 @@ ** ****************************************************************************/ +#include <QtCore/QCoreApplication> #include <QtQuickTest/quicktest.h> + +static void initializeLibraryPath() +{ + // Set custom path since CI doesn't install test plugins + QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + + QStringLiteral("/../../../plugins")); +} + +Q_COREAPP_STARTUP_FUNCTION(initializeLibraryPath) + QUICK_TEST_MAIN(declarative_ui) diff --git a/tests/auto/declarative_ui/tst_map_coordinateanimation.qml b/tests/auto/declarative_ui/tst_map_coordinateanimation.qml index 72c6aed8..54448973 100644 --- a/tests/auto/declarative_ui/tst_map_coordinateanimation.qml +++ b/tests/auto/declarative_ui/tst_map_coordinateanimation.qml @@ -59,7 +59,13 @@ Item { plugin: testPlugin width: 100 height: 100 - Behavior on center { CoordinateAnimation { duration: animationDuration } } + + Behavior on center { + id: centerBehavior + + enabled: false + CoordinateAnimation { duration: animationDuration } + } onCenterChanged: { if (!coordinateList) { @@ -101,8 +107,14 @@ Item { var delta = (toMerc.latitude - fromMerc.latitude) / (toMerc.longitude - fromMerc.longitude) + // Set from coordinate with animation disabled. map.center = QtPositioning.coordinate(from.latitude, from.longitude) - wait(animationDuration * 2) + + // Expect only one update + compare(coordinateList.length, 1) + + // Set to coordinate with animation enabled + centerBehavior.enabled = true map.center = QtPositioning.coordinate(to.latitude, to.longitude) wait(animationDuration * 2) diff --git a/tests/auto/declarative_ui/tst_map_item.qml b/tests/auto/declarative_ui/tst_map_item.qml index 16ee16b4..6533e964 100644 --- a/tests/auto/declarative_ui/tst_map_item.qml +++ b/tests/auto/declarative_ui/tst_map_item.qml @@ -43,6 +43,7 @@ import QtQuick 2.0 import QtTest 1.0 import QtLocation 5.0 import QtLocation.test 5.0 +import QtPositioning 5.0 /* diff --git a/tests/auto/declarative_ui/tst_map_item_details.qml b/tests/auto/declarative_ui/tst_map_item_details.qml index 0182bb8d..ccaba322 100644 --- a/tests/auto/declarative_ui/tst_map_item_details.qml +++ b/tests/auto/declarative_ui/tst_map_item_details.qml @@ -41,6 +41,7 @@ import QtQuick 2.0 import QtTest 1.0 +import QtPositioning 5.0 import QtLocation 5.0 import QtLocation.test 5.0 diff --git a/tests/auto/declarative_ui/tst_map_pinch_and_flick.qml b/tests/auto/declarative_ui/tst_map_pinch_and_flick.qml index 965da57c..4b46674f 100644 --- a/tests/auto/declarative_ui/tst_map_pinch_and_flick.qml +++ b/tests/auto/declarative_ui/tst_map_pinch_and_flick.qml @@ -785,7 +785,7 @@ Item { // 16. moving center clear_data() pinchGenerator.pinch(Qt.point(0, 50), Qt.point(50,100), Qt.point(50,0), Qt.point(100, 50)) - tryCompare(pinchStartedSpy.count, 1) + tryCompare(pinchStartedSpy, "count", 1) compare(map.lastPinchEvent.center.x, (map.lastPinchEvent.point1.x + map.lastPinchEvent.point2.x) /2) compare(map.lastPinchEvent.center.x, (map.lastPinchEvent.point1.y + map.lastPinchEvent.point2.y) /2) tryCompare(pinchFinishedSpy, "count", 1) diff --git a/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h b/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h index 29058c83..b48c0bb0 100644 --- a/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h @@ -82,7 +82,7 @@ class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine { Q_OBJECT public: - QGeoCodingManagerEngineTest(const QMap<QString, QVariant> ¶meters, + QGeoCodingManagerEngineTest(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoCodingManagerEngine(parameters), validateWellKnownValues_(false), diff --git a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h index ebdd3fa7..b9612ba9 100644 --- a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h @@ -83,7 +83,7 @@ class QGeoRoutingManagerEngineTest: public QGeoRoutingManagerEngine QString errorString_; public: - QGeoRoutingManagerEngineTest(const QMap<QString, QVariant> ¶meters, + QGeoRoutingManagerEngineTest(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoRoutingManagerEngine(parameters), routeReply_(0), diff --git a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.cpp b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.cpp index b902d75c..5e770475 100644 --- a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.cpp +++ b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.cpp @@ -56,15 +56,15 @@ QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() } QGeoRoutingManagerEngine* QGeoServiceProviderFactoryTest::createRoutingManagerEngine( - const QMap<QString, QVariant> & parameters, - QGeoServiceProvider::Error * error, QString *errorString) const + const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, QString *errorString) const { return new QGeoRoutingManagerEngineTest(parameters, error, errorString); } QGeoCodingManagerEngine* QGeoServiceProviderFactoryTest::createGeocodingManagerEngine( - const QMap<QString, QVariant> ¶meters, QGeoServiceProvider::Error *error, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const { return new QGeoCodingManagerEngineTest(parameters, error, errorString); @@ -72,14 +72,14 @@ QGeoCodingManagerEngine* QGeoServiceProviderFactoryTest::createGeocodingManagerE QGeoMappingManagerEngine* QGeoServiceProviderFactoryTest::createMappingManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const { return new QGeoTiledMappingManagerEngineTest(parameters, error, errorString); } QPlaceManagerEngine* QGeoServiceProviderFactoryTest::createPlaceManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const { Q_UNUSED(error); diff --git a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h index 84939133..3b62850b 100644 --- a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h +++ b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h @@ -59,16 +59,16 @@ public: ~QGeoServiceProviderFactoryTest(); QGeoMappingManagerEngine* createMappingManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; QGeoRoutingManagerEngine* createRoutingManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString ) const; QGeoCodingManagerEngine* createGeocodingManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; QPlaceManagerEngine* createPlaceManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; }; diff --git a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h index 5e166544..1a499792 100644 --- a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h @@ -58,7 +58,7 @@ class QGeoTiledMappingManagerEngineTest: public QGeoTiledMappingManagerEngine { Q_OBJECT public: - QGeoTiledMappingManagerEngineTest(const QMap<QString, QVariant> ¶meters, + QGeoTiledMappingManagerEngineTest(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoTiledMappingManagerEngine() { diff --git a/tests/auto/geotestplugin/qgeotilefetcher_test.h b/tests/auto/geotestplugin/qgeotilefetcher_test.h index 7affbc69..9c939b9d 100644 --- a/tests/auto/geotestplugin/qgeotilefetcher_test.h +++ b/tests/auto/geotestplugin/qgeotilefetcher_test.h @@ -82,7 +82,6 @@ public: : QGeoTileFetcher(engine, parent), finishRequestImmediately_(false), mappingReply_(0), - timerId_(0), errorCode_(QGeoTiledMapReply::NoError) {} bool init() @@ -125,12 +124,13 @@ public: mappingReply_->callSetMapImageData(bytes); mappingReply_->callSetMapImageFormat("png"); - mappingReply_->callSetFinished(true); + + timer_.start(500, this); return mappingReply_; } - void setParams(const QMap<QString, QVariant> ¶meters) + void setParams(const QVariantMap ¶meters) { parameters_ = parameters; } @@ -143,38 +143,37 @@ public: public Q_SLOTS: void requestAborted() { - if (timerId_) { - killTimer(timerId_); - timerId_ = 0; - } - errorString_ = ""; + timer_.stop(); + errorString_.clear(); errorCode_ = QGeoTiledMapReply::NoError; } protected: void timerEvent(QTimerEvent *event) { - Q_ASSERT(timerId_ == event->timerId()); + if (event->timerId() != timer_.timerId()) { + QGeoTileFetcher::timerEvent(event); + return; + } + Q_ASSERT(mappingReply_); - killTimer(timerId_); - timerId_ = 0; + timer_.stop(); if (errorCode_) { mappingReply_->callSetError(errorCode_, errorString_); emit tileError(mappingReply_->tileSpec(), errorString_); - } else { + } else { mappingReply_->callSetError(QGeoTiledMapReply::NoError, "no error"); mappingReply_->callSetFinished(true); } - // emit finished(mappingReply_); todo tileFinished } private: bool finishRequestImmediately_; TiledMapReplyTest* mappingReply_; - int timerId_; + QBasicTimer timer_; QGeoTiledMapReply::Error errorCode_; QString errorString_; - QMap<QString, QVariant> parameters_; + QVariantMap parameters_; QSize tileSize_; }; diff --git a/tests/auto/geotestplugin/qplacemanagerengine_test.h b/tests/auto/geotestplugin/qplacemanagerengine_test.h index 6096ffe1..edcf09b7 100644 --- a/tests/auto/geotestplugin/qplacemanagerengine_test.h +++ b/tests/auto/geotestplugin/qplacemanagerengine_test.h @@ -208,7 +208,7 @@ class QPlaceManagerEngineTest : public QPlaceManagerEngine { Q_OBJECT public: - QPlaceManagerEngineTest(const QMap<QString, QVariant> ¶meters) + QPlaceManagerEngineTest(const QVariantMap ¶meters) : QPlaceManagerEngine(parameters) { m_locales << QLocale(); @@ -363,10 +363,10 @@ public: return reply; } - QPlaceContentReply *getPlaceContent(const QString &placeId, const QPlaceContentRequest &query) + QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &query) Q_DECL_OVERRIDE { ContentReply *reply = new ContentReply(this); - if (placeId.isEmpty() || !m_places.contains(placeId)) { + if (query.placeId().isEmpty() || !m_places.contains(query.placeId())) { reply->setError(QPlaceReply::PlaceDoesNotExistError, tr("Place does not exist")); QMetaObject::invokeMethod(reply, "emitError", Qt::QueuedConnection); @@ -375,31 +375,33 @@ public: int totalCount = 0; switch (query.contentType()) { case QPlaceContent::ReviewType: - totalCount = m_placeReviews.value(placeId).count(); + totalCount = m_placeReviews.value(query.placeId()).count(); break; case QPlaceContent::ImageType: - totalCount = m_placeImages.value(placeId).count(); + totalCount = m_placeImages.value(query.placeId()).count(); break; case QPlaceContent::EditorialType: - totalCount = m_placeEditorials.value(placeId).count(); + totalCount = m_placeEditorials.value(query.placeId()).count(); default: //do nothing break; } - int offset = qMax(query.offset(), 0); + QVariantMap context = query.contentContext().toMap(); + + int offset = context.value(QStringLiteral("offset"), 0).toInt(); int max = (query.limit() == -1) ? totalCount : qMin(offset + query.limit(), totalCount); for (int i = offset; i < max; ++i) { switch (query.contentType()) { case QPlaceContent::ReviewType: - collection.insert(i, m_placeReviews.value(placeId).at(i)); + collection.insert(i, m_placeReviews.value(query.placeId()).at(i)); break; case QPlaceContent::ImageType: - collection.insert(i, m_placeImages.value(placeId).at(i)); + collection.insert(i, m_placeImages.value(query.placeId()).at(i)); break; case QPlaceContent::EditorialType: - collection.insert(i, m_placeEditorials.value(placeId).at(i)); + collection.insert(i, m_placeEditorials.value(query.placeId()).at(i)); default: //do nothing break; @@ -408,6 +410,21 @@ public: reply->setContent(collection); reply->setTotalCount(totalCount); + + if (max != totalCount) { + context.clear(); + context.insert(QStringLiteral("offset"), offset + query.limit()); + QPlaceContentRequest request = query; + request.setContentContext(context); + reply->setNextPageRequest(request); + } + if (offset > 0) { + context.clear(); + context.insert(QStringLiteral("offset"), qMin(0, offset - query.limit())); + QPlaceContentRequest request = query; + request.setContentContext(context); + reply->setPreviousPageRequest(request); + } } QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection); diff --git a/tests/auto/nokia_services/places_semiauto/tst_places.cpp b/tests/auto/nokia_services/places_semiauto/tst_places.cpp index e6e7859f..a0170144 100644 --- a/tests/auto/nokia_services/places_semiauto/tst_places.cpp +++ b/tests/auto/nokia_services/places_semiauto/tst_places.cpp @@ -90,7 +90,7 @@ private: QList<QPlaceReply::Error> *errors, QList<ExpectedResults> *results); - static const QLatin1String AuvergneEmbassyId; + static const QLatin1String ValidKnownPlaceId; static const QLatin1String ProxyEnv; static const QLatin1String AppIdEnv; static const QLatin1String TokenEnv; @@ -100,7 +100,10 @@ private: Q_DECLARE_METATYPE(tst_QPlaceManagerNokia::ExpectedResults) -const QLatin1String tst_QPlaceManagerNokia::AuvergneEmbassyId("250u09tv-be16478e55314b338c551aab2651c9d3"); +// ValidKnownPlaceId is the id of a place with a full complement of place content. Editorials, +// reviews, images, recommendations. If it disappears these tests will fail. +// Currently it is set to an Eiffel Tower tourist office. +const QLatin1String tst_QPlaceManagerNokia::ValidKnownPlaceId("250u09tu-4561b8da952f4fd79c4e1998c3fcf032"); const QLatin1String tst_QPlaceManagerNokia::ProxyEnv("NOKIA_PLUGIN_PROXY"); const QLatin1String tst_QPlaceManagerNokia::AppIdEnv("NOKIA_APP_ID"); @@ -335,7 +338,7 @@ void tst_QPlaceManagerNokia::recommendations_data() eatDrinkCat.setCategoryId(QStringLiteral("eat-drink")); QTest::newRow("search recommendations with valid id") - << QString(AuvergneEmbassyId) + << QString(ValidKnownPlaceId) << QString() << QGeoShape() << QList<QPlaceCategory>() @@ -349,28 +352,28 @@ void tst_QPlaceManagerNokia::recommendations_data() << QPlaceReply::PlaceDoesNotExistError; QTest::newRow("search for recommendations with id and search term") - << QString(AuvergneEmbassyId) + << QString(ValidKnownPlaceId) << QStringLiteral("sushi") << QGeoShape() << QList<QPlaceCategory>() << QPlaceReply::BadArgumentError; QTest::newRow("search for recommendations with an id and category") - << QString(AuvergneEmbassyId) + << QString(ValidKnownPlaceId) << QString() << QGeoShape() << (QList<QPlaceCategory>() << eatDrinkCat) << QPlaceReply::BadArgumentError; QTest::newRow("search for recommendations with id, search term and category") - << QString(AuvergneEmbassyId) + << QString(ValidKnownPlaceId) << QStringLiteral("sushi") << QGeoShape() << (QList<QPlaceCategory>() << eatDrinkCat) << QPlaceReply::BadArgumentError; QTest::newRow("search for recommendations with an id and search area") - << QString(AuvergneEmbassyId) + << QString(ValidKnownPlaceId) << QString() << static_cast<QGeoShape>(QGeoCircle(QGeoCoordinate(-27.5, 153))) << QList<QPlaceCategory>() @@ -381,7 +384,7 @@ void tst_QPlaceManagerNokia::details() { //fetch the details of a valid place QPlace place; - QVERIFY(doFetchDetails(AuvergneEmbassyId, &place)); + QVERIFY(doFetchDetails(ValidKnownPlaceId, &place)); QVERIFY(!place.name().isEmpty()); QVERIFY(!place.icon().url().isEmpty()); QStringList contactTypes = place.contactTypes(); @@ -515,17 +518,9 @@ void tst_QPlaceManagerNokia::suggestions_data() void tst_QPlaceManagerNokia::suggestionsMisc() { - //check providing an offset + //check providing a distance relevancy hint (should be ignored) QPlaceSearchRequest searchRequest; - searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153))); - searchRequest.setSearchTerm(QStringLiteral("sus")); - searchRequest.setOffset(5); QStringList results; - QVERIFY(doSearchSuggestions(searchRequest, &results, QPlaceReply::BadArgumentError)); - QCOMPARE(results.count(), 0); - searchRequest.clear(); - - //check porviding a distance relevancy hint (should be ignored) searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(-27.5, 153))); searchRequest.setSearchTerm(QStringLiteral("sus")); searchRequest.setRelevanceHint(QPlaceSearchRequest::DistanceHint); @@ -586,11 +581,11 @@ void tst_QPlaceManagerNokia::locale() //check that setting a locale will affect place detail fetches. QPlace place; placeManager->setLocale(QLocale("en")); - QVERIFY(doFetchDetails(AuvergneEmbassyId, + QVERIFY(doFetchDetails(ValidKnownPlaceId, &place)); QString englishName = place.name(); placeManager->setLocale(QLocale("fr")); - QVERIFY(doFetchDetails(AuvergneEmbassyId, + QVERIFY(doFetchDetails(ValidKnownPlaceId, &place)); QVERIFY(englishName != place.name()); } @@ -602,9 +597,9 @@ void tst_QPlaceManagerNokia::content() //check fetching of content QPlaceContentRequest request; request.setContentType(type); + request.setPlaceId(ValidKnownPlaceId); QPlaceContent::Collection results; - QVERIFY(doFetchContent(AuvergneEmbassyId, - request, &results)); + QVERIFY(doFetchContent(request, &results)); QVERIFY(results.count() > 0); @@ -638,39 +633,18 @@ void tst_QPlaceManagerNokia::content() } //check total count - QPlaceContentReply *contentReply = - placeManager->getPlaceContent(AuvergneEmbassyId, - request); + QPlaceContentReply *contentReply = placeManager->getPlaceContent(request); QSignalSpy contentSpy(contentReply, SIGNAL(finished())); QTRY_VERIFY_WITH_TIMEOUT(contentSpy.count() ==1, Timeout); QVERIFY(contentReply->totalCount() > 0); if (contentReply->totalCount() >= 2) { - //try testing with an offset - request.setOffset(1); - QPlaceContent::Collection newResults; - QVERIFY(doFetchContent(AuvergneEmbassyId, - request, &newResults)); - QVERIFY(!newResults.keys().contains(0)); - QCOMPARE(newResults.value(1), results.value(1)); - //try testing with a limit - request.setOffset(0); request.setLimit(1); - QVERIFY(doFetchContent(AuvergneEmbassyId, - request, &newResults)); + QPlaceContent::Collection newResults; + QVERIFY(doFetchContent(request, &newResults)); QCOMPARE(newResults.count(), 1); QCOMPARE(newResults.values().first(), results.value(0)); - - //try testing both limit and offset - if (contentReply->totalCount() >= 3) { - request.setLimit(1); - request.setOffset(1); - QVERIFY(doFetchContent(AuvergneEmbassyId, - request, &newResults)); - QCOMPARE(newResults.count(), 1); - QCOMPARE(newResults.values().first(), results.value(1)); - } } } diff --git a/tests/auto/nokia_services/routing/tst_routing.cpp b/tests/auto/nokia_services/routing/tst_routing.cpp index f3e24a93..95d034da 100644 --- a/tests/auto/nokia_services/routing/tst_routing.cpp +++ b/tests/auto/nokia_services/routing/tst_routing.cpp @@ -335,7 +335,7 @@ void tst_nokia_routing::initTestCase() m_networkManager = new MockGeoNetworkAccessManager(); - QMap<QString, QVariant> parameters; + QVariantMap parameters; parameters.insert(QStringLiteral("nam"), QVariant::fromValue<void*>(m_networkManager)); parameters.insert(QStringLiteral("app_id"), "stub"); parameters.insert(QStringLiteral("token"), "stub"); diff --git a/tests/auto/placemanager_utils/placemanager_utils.cpp b/tests/auto/placemanager_utils/placemanager_utils.cpp index 8934790a..205d0c39 100644 --- a/tests/auto/placemanager_utils/placemanager_utils.cpp +++ b/tests/auto/placemanager_utils/placemanager_utils.cpp @@ -244,13 +244,12 @@ bool PlaceManagerUtils::doFetchCategory(QPlaceManager *manager, } bool PlaceManagerUtils::doFetchContent(QPlaceManager *manager, - const QString &placeId, const QPlaceContentRequest &request, QPlaceContent::Collection *results, QPlaceReply::Error expectedError) { Q_ASSERT(results); - QPlaceContentReply *reply = manager->getPlaceContent(placeId, request); + QPlaceContentReply *reply = manager->getPlaceContent(request); bool isSuccessful = checkSignals(reply, expectedError, manager); *results = reply->content(); diff --git a/tests/auto/placemanager_utils/placemanager_utils.h b/tests/auto/placemanager_utils/placemanager_utils.h index 88a857e0..a8edede4 100644 --- a/tests/auto/placemanager_utils/placemanager_utils.h +++ b/tests/auto/placemanager_utils/placemanager_utils.h @@ -128,7 +128,6 @@ public: QPlaceReply::Error expectedError = QPlaceReply::NoError); static bool doFetchContent(QPlaceManager *manager, - const QString &placeId, const QPlaceContentRequest &request, QPlaceContent::Collection *results, QPlaceReply::Error expectedError = QPlaceReply::NoError); @@ -219,13 +218,11 @@ protected: category, expectedError); } - bool doFetchContent(const QString &placeId, - const QPlaceContentRequest &request, + bool doFetchContent(const QPlaceContentRequest &request, QPlaceContent::Collection *results, QPlaceReply::Error expectedError = QPlaceReply::NoError) { - return doFetchContent(placeManager, placeId, - request, results, expectedError); + return doFetchContent(placeManager, request, results, expectedError); } bool doMatch(const QPlaceMatchRequest &request, diff --git a/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.cpp b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.cpp index 710fb97b..20c88d27 100644 --- a/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.cpp +++ b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.cpp @@ -53,7 +53,7 @@ QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() } QPlaceManagerEngine *QGeoServiceProviderFactoryTest::createPlaceManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const { Q_UNUSED(error); diff --git a/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.h b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.h index 210ac7cc..66869947 100644 --- a/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.h +++ b/tests/auto/placesplugin_unsupported/qgeoserviceproviderplugin_test.h @@ -57,7 +57,7 @@ public: QGeoServiceProviderFactoryTest(); ~QGeoServiceProviderFactoryTest(); - QPlaceManagerEngine *createPlaceManagerEngine(const QMap<QString, QVariant> ¶meters, + QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; }; diff --git a/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerengine_test.h b/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerengine_test.h index c1c17b1b..ada63803 100644 --- a/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerengine_test.h +++ b/tests/auto/qgeocodingmanagerplugins/qgeocodingmanagerengine_test.h @@ -73,7 +73,7 @@ class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine { Q_OBJECT public: - QGeoCodingManagerEngineTest(const QMap<QString, QVariant> ¶meters, + QGeoCodingManagerEngineTest(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoCodingManagerEngine(parameters) { diff --git a/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.cpp b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.cpp index d16ba32e..878c0fa1 100644 --- a/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.cpp +++ b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.cpp @@ -53,7 +53,7 @@ QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() } QGeoCodingManagerEngine* QGeoServiceProviderFactoryTest::createGeocodingManagerEngine( - const QMap<QString, QVariant> ¶meters, QGeoServiceProvider::Error *error, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const { return new QGeoCodingManagerEngineTest(parameters, error, errorString); diff --git a/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.h b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.h index c49e90bb..fe442b4f 100644 --- a/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.h +++ b/tests/auto/qgeocodingmanagerplugins/qgeoserviceproviderplugin_test.h @@ -59,7 +59,7 @@ public: ~QGeoServiceProviderFactoryTest(); QGeoCodingManagerEngine* createGeocodingManagerEngine( - const QMap<QString, QVariant> ¶meters, + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; }; diff --git a/tests/auto/qgeomapcontroller/tst_qgeomapcontroller.cpp b/tests/auto/qgeomapcontroller/tst_qgeomapcontroller.cpp index 0123d375..7b7f8b98 100644 --- a/tests/auto/qgeomapcontroller/tst_qgeomapcontroller.cpp +++ b/tests/auto/qgeomapcontroller/tst_qgeomapcontroller.cpp @@ -91,7 +91,7 @@ tst_QGeoMapController::tst_QGeoMapController() QGeoServiceProviderFactoryTest serviceProviderTest; // empty constructor // TODO: check whether the default constructors of these objects allow the create to work - QMap<QString, QVariant> parameterMap; + QVariantMap parameterMap; QGeoServiceProvider::Error mappingError; QString mappingErrorString; diff --git a/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.cpp b/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.cpp index cfff7bd2..f8315348 100644 --- a/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.cpp +++ b/tests/auto/qgeoroutingmanager/tst_qgeoroutingmanager.cpp @@ -104,17 +104,21 @@ void tst_QGeoRoutingManager::supports() void tst_QGeoRoutingManager::locale() { - QLocale *german = new QLocale(QLocale::German, QLocale::Germany); - QLocale *english = new QLocale(QLocale::C, QLocale::AnyCountry); + QLocale german = QLocale(QLocale::German, QLocale::Germany); + QLocale english = QLocale(QLocale::C, QLocale::AnyCountry); - qgeoroutingmanager->setLocale(*german); + qgeoroutingmanager->setLocale(german); - QCOMPARE(qgeoroutingmanager->locale(), *german); + QCOMPARE(qgeoroutingmanager->locale(), german); - QVERIFY(qgeoroutingmanager->locale() != *english); + QVERIFY(qgeoroutingmanager->locale() != english); - delete german; - delete english; + QLocale en_UK = QLocale(QLocale::English, QLocale::UnitedKingdom); + qgeoroutingmanager->setLocale(en_UK); + QCOMPARE(qgeoroutingmanager->measurementSystem(), en_UK.measurementSystem()); + qgeoroutingmanager->setMeasurementSystem(QLocale::MetricSystem); + QCOMPARE(qgeoroutingmanager->measurementSystem(), QLocale::MetricSystem); + QVERIFY(qgeoroutingmanager->locale().measurementSystem() != qgeoroutingmanager->measurementSystem()); } void tst_QGeoRoutingManager::name() diff --git a/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerengine_test.h b/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerengine_test.h index 7bfb506c..33dfba4a 100644 --- a/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerengine_test.h +++ b/tests/auto/qgeoroutingmanagerplugins/qgeoroutingmanagerengine_test.h @@ -55,7 +55,7 @@ class QGeoRoutingManagerEngineTest: public QGeoRoutingManagerEngine { Q_OBJECT public: - QGeoRoutingManagerEngineTest(const QMap<QString, QVariant> ¶meters, + QGeoRoutingManagerEngineTest(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) : QGeoRoutingManagerEngine(parameters) { diff --git a/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.cpp b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.cpp index 1f3a1b50..8079ed21 100644 --- a/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.cpp +++ b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.cpp @@ -52,8 +52,9 @@ QGeoServiceProviderFactoryTest::~QGeoServiceProviderFactoryTest() { } -QGeoRoutingManagerEngine* QGeoServiceProviderFactoryTest::createRoutingManagerEngine(const QMap< - QString, QVariant> ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +QGeoRoutingManagerEngine* QGeoServiceProviderFactoryTest::createRoutingManagerEngine( + const QVariantMap ¶meters, QGeoServiceProvider::Error *error, + QString *errorString) const { return new QGeoRoutingManagerEngineTest(parameters, error, errorString); } diff --git a/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.h b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.h index 1d6ceb96..bb4ac7ee 100644 --- a/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.h +++ b/tests/auto/qgeoroutingmanagerplugins/qgeoserviceproviderplugin_test.h @@ -58,7 +58,7 @@ public: QGeoServiceProviderFactoryTest(); ~QGeoServiceProviderFactoryTest(); - QGeoRoutingManagerEngine* createRoutingManagerEngine(const QMap<QString, QVariant> ¶meters, + QGeoRoutingManagerEngine* createRoutingManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; }; diff --git a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.cpp b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.cpp index be8dfa78..6bf85173 100644 --- a/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.cpp +++ b/tests/auto/qnmeapositioninfosource/qnmeapositioninfosourceproxyfactory.cpp @@ -86,14 +86,21 @@ QNmeaPositionInfoSourceProxy *QNmeaPositionInfoSourceProxyFactory::createProxy(Q { QTcpSocket *client = new QTcpSocket; client->connectToHost(m_server->serverAddress(), m_server->serverPort()); - //qDebug() << "listening on" << m_server->serverAddress() << m_server->serverPort(); - bool b = m_server->waitForNewConnection(5000); - Q_ASSERT(b); + qDebug() << "listening on" << m_server->serverAddress() << m_server->serverPort(); + bool b = m_server->waitForNewConnection(15000); + if (!b) + qWarning() << "Server didin't receive new connection"; b = client->waitForConnected(); - Q_ASSERT(b); + if (!b) + qWarning() << "Client could not connect to server"; //QNmeaPositionInfoSource *source = new QNmeaPositionInfoSource(m_mode); - source->setDevice(m_server->nextPendingConnection()); + QIODevice *device = m_server->nextPendingConnection(); + if (!device) + qWarning() << "Missing pending connection. Test is going to fail."; + else + qWarning() << "Received pending connection:" << device << b; + source->setDevice(device); Q_ASSERT(source->device() != 0); QNmeaPositionInfoSourceProxy *proxy = new QNmeaPositionInfoSourceProxy(source, client); proxy->setParent(source); diff --git a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp index 4b5f4ff6..c0a57535 100644 --- a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp +++ b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -43,6 +45,8 @@ #include "tst_qnmeapositioninfosource.h" +#include <QtCore/QtNumeric> + #ifdef Q_OS_WIN // Windows seems to require longer timeouts and step length @@ -103,6 +107,14 @@ void tst_QNmeaPositionInfoSource::minimumUpdateInterval() QCOMPARE(source.minimumUpdateInterval(), 100); } +void tst_QNmeaPositionInfoSource::userEquivalentRangeError() +{ + QNmeaPositionInfoSource source(m_mode); + QVERIFY(qIsNaN(source.userEquivalentRangeError())); + source.setUserEquivalentRangeError(5.1); + QVERIFY(qFuzzyCompare(source.userEquivalentRangeError(), 5.1)); +} + void tst_QNmeaPositionInfoSource::setUpdateInterval_delayedUpdate() { // If an update interval is set, and an update is not available at a @@ -348,8 +360,11 @@ void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime() QFETCH(QByteArray, bytes); QFETCH(QList<QDateTime>, dateTimes); + QFETCH(QList<bool>, expectHorizontalAccuracy); + QFETCH(QList<bool>, expectVerticalAccuracy); QNmeaPositionInfoSource source(m_mode); + source.setUserEquivalentRangeError(5.1); QNmeaPositionInfoSourceProxyFactory factory; QNmeaPositionInfoSourceProxy *proxy = static_cast<QNmeaPositionInfoSourceProxy*>(factory.createProxy(&source)); @@ -359,14 +374,33 @@ void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime() proxy->feedBytes(bytes); QTRY_COMPARE(spy.count(), dateTimes.count()); - for (int i=0; i<spy.count(); i++) - QCOMPARE(spy[i][0].value<QGeoPositionInfo>().timestamp(), dateTimes[i]); + for (int i=0; i<spy.count(); i++) { + QGeoPositionInfo pInfo = spy[i][0].value<QGeoPositionInfo>(); + + QCOMPARE(pInfo.timestamp(), dateTimes[i]); + + // Generated GGA/GSA sentences have hard coded HDOP of 3.5, which corrisponds to a + // horizontal accuracy of 35.7, for the user equivalent range error of 5.1 set above. + QCOMPARE(pInfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy), + expectHorizontalAccuracy[i]); + if (pInfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + QVERIFY(qFuzzyCompare(pInfo.attribute(QGeoPositionInfo::HorizontalAccuracy), 35.7)); + + // Generate GSA sentences have hard coded VDOP of 4.0, which corrisponds to a vertical + // accuracy of 40.8, for the user equivalent range error of 5.1 set above. + QCOMPARE(pInfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy), + expectVerticalAccuracy[i]); + if (pInfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) + QVERIFY(qFuzzyCompare(pInfo.attribute(QGeoPositionInfo::VerticalAccuracy), 40.8)); + } } void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime_data() { QTest::addColumn<QByteArray>("bytes"); QTest::addColumn<QList<QDateTime> >("dateTimes"); + QTest::addColumn<QList<bool> >("expectHorizontalAccuracy"); + QTest::addColumn<QList<bool> >("expectVerticalAccuracy"); QDateTime dt = QDateTime::currentDateTime().toUTC(); QByteArray bytes; @@ -376,7 +410,9 @@ void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime_data() bytes += QLocationTestUtils::createRmcSentence(dt.addSecs(2)).toLatin1(); bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(3).time()).toLatin1(); QTest::newRow("Feed GGA,RMC,GGA; expect RMC, second GGA only") - << bytes << (QList<QDateTime>() << dt.addSecs(2) << dt.addSecs(3)); + << bytes << (QList<QDateTime>() << dt.addSecs(2) << dt.addSecs(3)) + << (QList<bool>() << true << true) + << (QList<bool>() << false << false); // should not receive ZDA (has no coordinates) but should get the GGA // sentence after it since it got the date/time from ZDA @@ -385,7 +421,20 @@ void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime_data() bytes += QLocationTestUtils::createZdaSentence(dt.addSecs(2)).toLatin1(); bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(3).time()).toLatin1(); QTest::newRow("Feed GGA,ZDA,GGA; expect second GGA only") - << bytes << (QList<QDateTime>() << dt.addSecs(3)); + << bytes << (QList<QDateTime>() << dt.addSecs(3)) + << (QList<bool>() << true) + << (QList<bool>() << false); + + // Feed ZDA,GGA,GSA,GGA; expect vertical accuracy from second GGA. + bytes.clear(); + bytes += QLocationTestUtils::createZdaSentence(dt.addSecs(1)).toLatin1(); + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(2).time()).toLatin1(); + bytes += QLocationTestUtils::createGsaSentence().toLatin1(); + bytes += QLocationTestUtils::createGgaSentence(dt.addSecs(3).time()).toLatin1(); + QTest::newRow("Feed ZDA,GGA,GSA,GGA; expect vertical accuracy from second GGA") + << bytes << (QList<QDateTime>() << dt.addSecs(2) << dt.addSecs(3)) + << (QList<bool>() << true << true) + << (QList<bool>() << false << true); if (m_mode == QNmeaPositionInfoSource::SimulationMode) { // In sim m_mode, should ignore sentence with a date/time before the known date/time @@ -395,7 +444,9 @@ void tst_QNmeaPositionInfoSource::startUpdates_waitForValidDateTime_data() bytes += QLocationTestUtils::createRmcSentence(dt.addSecs(-2)).toLatin1(); bytes += QLocationTestUtils::createRmcSentence(dt.addSecs(2)).toLatin1(); QTest::newRow("Feed good RMC, RMC with bad date/time, good RMC; expect first and third RMC only") - << bytes << (QList<QDateTime>() << dt.addSecs(1) << dt.addSecs(2)); + << bytes << (QList<QDateTime>() << dt.addSecs(1) << dt.addSecs(2)) + << (QList<bool>() << false << false) + << (QList<bool>() << false << false); } } diff --git a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.h b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.h index d541465d..9d837933 100644 --- a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.h +++ b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.h @@ -96,6 +96,8 @@ private slots: void minimumUpdateInterval(); + void userEquivalentRangeError(); + void setUpdateInterval_delayedUpdate(); void lastKnownPosition(); diff --git a/tests/auto/qplacecontentrequest/tst_qplacecontentrequest.cpp b/tests/auto/qplacecontentrequest/tst_qplacecontentrequest.cpp index 13bc2998..c5b72e35 100644 --- a/tests/auto/qplacecontentrequest/tst_qplacecontentrequest.cpp +++ b/tests/auto/qplacecontentrequest/tst_qplacecontentrequest.cpp @@ -66,25 +66,20 @@ void tst_QPlaceContentRequest::contentTest() { QPlaceContentRequest req; QCOMPARE(req.limit(), -1); - QCOMPARE(req.offset(), 0); QCOMPARE(req.contentType(), QPlaceContent::NoType); //check that we can set the request fields req.setLimit(100); - req.setOffset(5); req.setContentType(QPlaceContent::ImageType); QCOMPARE(req.limit(), 100); - QCOMPARE(req.offset(), 5); QCOMPARE(req.contentType(), QPlaceContent::ImageType); //check that we assignment works correctly QPlaceContentRequest otherReq; otherReq.setLimit(10); - otherReq.setOffset(15); otherReq.setContentType(QPlaceContent::ReviewType); req = otherReq; QCOMPARE(req.limit(), 10); - QCOMPARE(req.offset(), 15); QCOMPARE(req.contentType(), QPlaceContent::ReviewType); QCOMPARE(req, otherReq); @@ -98,11 +93,9 @@ void tst_QPlaceContentRequest::clearTest() QPlaceContentRequest req; req.setContentType(QPlaceContent::ReviewType); req.setLimit(9000); - req.setOffset(1); req.clear(); QVERIFY(req.contentType() == QPlaceContent::NoType); QVERIFY(req.limit() == -1); - QVERIFY(req.offset() == 0); } QTEST_APPLESS_MAIN(tst_QPlaceContentRequest) diff --git a/tests/auto/qplacemanager_nokia/tst_qplacemanager_nokia.cpp b/tests/auto/qplacemanager_nokia/tst_qplacemanager_nokia.cpp index 74c33d86..c8128925 100644 --- a/tests/auto/qplacemanager_nokia/tst_qplacemanager_nokia.cpp +++ b/tests/auto/qplacemanager_nokia/tst_qplacemanager_nokia.cpp @@ -91,7 +91,7 @@ void tst_QPlaceManagerNokia::initTestCase() QStringList providers = QGeoServiceProvider::availableServiceProviders(); - QMap<QString, QVariant> params; + QVariantMap params; params.insert("app_id", "stub"); params.insert("token", "stub"); provider = new QGeoServiceProvider("nokia", params); diff --git a/tests/auto/qplacemanager_unsupported/tst_qplacemanager_unsupported.cpp b/tests/auto/qplacemanager_unsupported/tst_qplacemanager_unsupported.cpp index f1615536..ad14db1e 100644 --- a/tests/auto/qplacemanager_unsupported/tst_qplacemanager_unsupported.cpp +++ b/tests/auto/qplacemanager_unsupported/tst_qplacemanager_unsupported.cpp @@ -149,7 +149,7 @@ void tst_QPlaceManagerUnsupported::testGetPlaceDetails() void tst_QPlaceManagerUnsupported::testGetPlaceContent() { - QPlaceContentReply *reply = m_manager->getPlaceContent(QString(), QPlaceContentRequest()); + QPlaceContentReply *reply = m_manager->getPlaceContent(QPlaceContentRequest()); if (!checkSignals(reply, QPlaceReply::UnsupportedError)) return; } diff --git a/tests/auto/qplacesearchreply/tst_qplacesearchreply.cpp b/tests/auto/qplacesearchreply/tst_qplacesearchreply.cpp index 24a76bc7..43638334 100644 --- a/tests/auto/qplacesearchreply/tst_qplacesearchreply.cpp +++ b/tests/auto/qplacesearchreply/tst_qplacesearchreply.cpp @@ -42,9 +42,11 @@ #include <QtCore/QString> #include <QtTest/QtTest> +#include <QtPositioning/QGeoCircle> +#include <QtLocation/QPlaceSearchRequest> #include <QtLocation/QPlaceSearchReply> #include <QtLocation/QPlaceResult> -#include <QtPositioning/QGeoCircle> + QT_USE_NAMESPACE @@ -101,7 +103,6 @@ void tst_QPlaceSearchReply::requestTest() TestSearchReply *reply = new TestSearchReply(this); QPlaceSearchRequest request; request.setLimit(10); - request.setOffset(50); QGeoCircle circle; circle.setCenter(QGeoCoordinate(10,20)); diff --git a/tests/auto/qplacesearchrequest/tst_qplacesearchrequest.cpp b/tests/auto/qplacesearchrequest/tst_qplacesearchrequest.cpp index 318e8353..bd7589dd 100644 --- a/tests/auto/qplacesearchrequest/tst_qplacesearchrequest.cpp +++ b/tests/auto/qplacesearchrequest/tst_qplacesearchrequest.cpp @@ -268,16 +268,14 @@ void tst_QPlaceSearchRequest::clearTest() category.setName("Fast Food"); req.setCategory(category); req.setLimit(100); - req.setOffset(5); req.clear(); QVERIFY(req.searchTerm().isEmpty()); QVERIFY(req.searchArea() == QGeoShape()); QVERIFY(req.categories().isEmpty()); QVERIFY(req.limit() == -1); - QVERIFY(req.offset() == 0); } -QTEST_APPLESS_MAIN(tst_QPlaceSearchRequest); +QTEST_APPLESS_MAIN(tst_QPlaceSearchRequest) #include "tst_qplacesearchrequest.moc" diff --git a/tests/auto/utils/qlocationtestutils.cpp b/tests/auto/utils/qlocationtestutils.cpp index 97e4f8d9..d5eed344 100644 --- a/tests/auto/utils/qlocationtestutils.cpp +++ b/tests/auto/utils/qlocationtestutils.cpp @@ -93,3 +93,8 @@ QString QLocationTestUtils::createZdaSentence(const QDateTime &dt) .arg(time).arg(dt.toString("dd")).arg(dt.toString("MM")).arg(dt.toString("yyyy")); return addNmeaChecksumAndBreaks(nmea); } + +QString QLocationTestUtils::createGsaSentence() +{ + return addNmeaChecksumAndBreaks(QStringLiteral("$GPGSA,A,3,,,,,,,,,,,,,3.0,3.5,4.0*")); +} diff --git a/tests/auto/utils/qlocationtestutils_p.h b/tests/auto/utils/qlocationtestutils_p.h index 2c827d41..6ed5de38 100644 --- a/tests/auto/utils/qlocationtestutils_p.h +++ b/tests/auto/utils/qlocationtestutils_p.h @@ -57,6 +57,7 @@ namespace QLocationTestUtils QString createGgaSentence(const QTime &time); QString createGgaSentence(int lat, int lng, const QTime &time); QString createZdaSentence(const QDateTime &dt); + QString createGsaSentence(); //The purpose of compareEquality() is to test equality //operators where it is expected that A == B. |