diff options
Diffstat (limited to 'src')
232 files changed, 5180 insertions, 6751 deletions
diff --git a/src/imports/location/declarativeplaces/qdeclarativecategory.cpp b/src/imports/location/declarativeplaces/qdeclarativecategory.cpp index 0edf09d9..ae496c1b 100644 --- a/src/imports/location/declarativeplaces/qdeclarativecategory.cpp +++ b/src/imports/location/declarativeplaces/qdeclarativecategory.cpp @@ -155,7 +155,7 @@ void QDeclarativeCategory::pluginReady() /*! \qmlproperty QPlaceCategory Category::category - \target Category::category + \keyword Category::category For details on how to use this property to interface between C++ and QML see "\l {Category - QPlaceCategory} {Interfaces between C++ and QML Code}". diff --git a/src/imports/location/declarativeplaces/qdeclarativecategory_p.h b/src/imports/location/declarativeplaces/qdeclarativecategory_p.h index ac8747e3..63b255b4 100644 --- a/src/imports/location/declarativeplaces/qdeclarativecategory_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativecategory_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVECATEGORY_P_H #define QDECLARATIVECATEGORY_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtQml/qqml.h> #include <QtQml/QQmlParserStatus> #include <QObject> diff --git a/src/imports/location/declarativeplaces/qdeclarativecontactdetail_p.h b/src/imports/location/declarativeplaces/qdeclarativecontactdetail_p.h index db0a094d..9d404def 100644 --- a/src/imports/location/declarativeplaces/qdeclarativecontactdetail_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativecontactdetail_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVECONTACTDETAIL_P_H #define QDECLARATIVECONTACTDETAIL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtLocation/QPlaceContactDetail> #include <QtQml/QQmlPropertyMap> diff --git a/src/imports/location/declarativeplaces/qdeclarativeperiod_p.h b/src/imports/location/declarativeplaces/qdeclarativeperiod_p.h index 56994eff..3ded0109 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeperiod_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativeperiod_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPERIOD_P_H #define QDECLARATIVEPERIOD_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <qplaceperiod.h> #include <QtQml/qqml.h> diff --git a/src/imports/location/declarativeplaces/qdeclarativeplace_p.h b/src/imports/location/declarativeplaces/qdeclarativeplace_p.h index 1488bb20..78557091 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplace_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativeplace_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPLACE_P_H #define QDECLARATIVEPLACE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtQml/QQmlListProperty> #include <QtQml/QQmlParserStatus> diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceattribute_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceattribute_p.h index 451edfe2..f1c873c3 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplaceattribute_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceattribute_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPLACEATTRIBUTE_P_H #define QDECLARATIVEPLACEATTRIBUTE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QObject> #include <QtQml/qqml.h> #include <QString> diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h index cf588b77..23acb36e 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPLACEICON_P_H #define QDECLARATIVEPLACEICON_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeoserviceprovider_p.h" #include <qplaceicon.h> diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h index 51d46597..8f8f3f4e 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPLACEIMAGEMODEL_P_H #define QDECLARATIVEPLACEIMAGEMODEL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativeplacecontentmodel.h" QT_BEGIN_NAMESPACE diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceuser_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceuser_p.h index ea9a3638..6c6ececf 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeplaceuser_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativeplaceuser_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPLACEUSER_P_H #define QDECLARATIVEPLACEUSER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtQml/qqml.h> #include <QtLocation/QPlaceUser> diff --git a/src/imports/location/declarativeplaces/qdeclarativeratings_p.h b/src/imports/location/declarativeplaces/qdeclarativeratings_p.h index 596eed69..7583e703 100644 --- a/src/imports/location/declarativeplaces/qdeclarativeratings_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativeratings_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVERATINGS_P_H #define QDECLARATIVERATINGS_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <qplaceratings.h> #include <QtQml/qqml.h> diff --git a/src/imports/location/declarativeplaces/qdeclarativereviewmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativereviewmodel_p.h index 343f9f7e..06bf7aa8 100644 --- a/src/imports/location/declarativeplaces/qdeclarativereviewmodel_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativereviewmodel_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEREVIEWMODEL_P_H #define QDECLARATIVEREVIEWMODEL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativeplacecontentmodel.h" QT_BEGIN_NAMESPACE diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel_p.h index fb63d72c..73bf16d3 100644 --- a/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativesearchresultmodel_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVESEARCHRESULTMODEL_P_H #define QDECLARATIVESEARCHRESULTMODEL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativesearchmodelbase.h" #include "qdeclarativecategory_p.h" #include "qdeclarativeplace_p.h" diff --git a/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h index c8d30a51..49e09980 100644 --- a/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVESEARCHSUGGESTIONMODEL_P_H #define QDECLARATIVESEARCHSUGGESTIONMODEL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativesearchmodelbase.h" #include <QtCore/QStringList> diff --git a/src/imports/location/declarativeplaces/qdeclarativesupplier_p.h b/src/imports/location/declarativeplaces/qdeclarativesupplier_p.h index 68e7680f..35b1dbda 100644 --- a/src/imports/location/declarativeplaces/qdeclarativesupplier_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativesupplier_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVESUPPLIER_P_H #define QDECLARATIVESUPPLIER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QObject> #include <QtCore/QUrl> #include <QtQml/qqml.h> diff --git a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h index 6026a79b..98167892 100644 --- a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h +++ b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVESUPPORTEDCATEGORIESMODEL_H #define QDECLARATIVESUPPORTEDCATEGORIESMODEL_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <qdeclarativegeoserviceprovider_p.h> #include <QObject> diff --git a/src/imports/location/error_messages.cpp b/src/imports/location/error_messages.cpp index 3eb5ce0c..a2557f79 100644 --- a/src/imports/location/error_messages.cpp +++ b/src/imports/location/error_messages.cpp @@ -46,11 +46,7 @@ const char PLUGIN_ERROR[] = QT_TRANSLATE_NOOP("QtLocationQML", "Plugin Error (%1 const char PLUGIN_PROVIDER_ERROR[] = QT_TRANSLATE_NOOP("QtLocationQML", "Plugin Error (%1): Could not instantiate provider"); const char PLUGIN_NOT_VALID[] = QT_TRANSLATE_NOOP("QtLocationQML", "Plugin is not valid"); const char CATEGORIES_NOT_INITIALIZED[] = QT_TRANSLATE_NOOP("QtLocationQML", "Unable to initialize categories"); -const char UNABLE_TO_MAKE_REQUEST[]= QT_TRANSLATE_NOOP("QtLocationQML", "Unable to create request"); - -//often used but only visible to developer -> no translation required -const char ROUTE_PLUGIN_NOT_SET[] = "Cannot route, plugin not set."; -const char ROUTE_MGR_NOT_SET[] = "Cannot route, route manager not set."; -const char COORD_NOT_BELONG_TO[] = "Coordinate does not belong to %1"; +const char UNABLE_TO_MAKE_REQUEST[] = QT_TRANSLATE_NOOP("QtLocationQML", "Unable to create request"); +const char INDEX_OUT_OF_RANGE[] = QT_TRANSLATE_NOOP("QtLocationQML", "Index '%1' out of range"); QT_END_NAMESPACE diff --git a/src/imports/location/error_messages.h b/src/imports/location/error_messages.h index a2e4bf49..81c43b34 100644 --- a/src/imports/location/error_messages.h +++ b/src/imports/location/error_messages.h @@ -33,27 +33,22 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #ifndef ERROR_MESSAGES_H #define ERROR_MESSAGES_H -#include <QString> +#include <QtCore/qglobal.h> QT_BEGIN_NAMESPACE extern const char CONTEXT_NAME[]; - extern const char PLUGIN_PROPERTY_NOT_SET[]; extern const char PLUGIN_ERROR[]; extern const char PLUGIN_PROVIDER_ERROR[]; extern const char PLUGIN_NOT_VALID[]; - extern const char CATEGORIES_NOT_INITIALIZED[]; - -extern const char ROUTE_PLUGIN_NOT_SET[]; -extern const char ROUTE_MGR_NOT_SET[]; - -extern const char COORD_NOT_BELONG_TO[]; extern const char UNABLE_TO_MAKE_REQUEST[]; +extern const char INDEX_OUT_OF_RANGE[]; QT_END_NAMESPACE diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp index b78ada1a..dbeb3c5d 100644 --- a/src/imports/location/location.cpp +++ b/src/imports/location/location.cpp @@ -98,7 +98,7 @@ public: qmlRegisterType<QDeclarativeGeoMap >(uri, major, minor, "Map"); qmlRegisterUncreatableType<QDeclarativeGeoMapItemBase >(uri, major, minor, "GeoMapItemBase", - QStringLiteral("HeoMapItemBase is not intended instantiable by developer.")); + QStringLiteral("GeoMapItemBase is not intended instantiable by developer.")); qmlRegisterType<QDeclarativeGeoMapQuickItem >(uri, major, minor, "MapQuickItem"); qmlRegisterType<QDeclarativeGeoMapItemView >(uri, major, minor, "MapItemView"); @@ -108,10 +108,10 @@ public: qmlRegisterType<QDeclarativeGeoRoute >(uri, major, minor, "Route"); // data type qmlRegisterType<QDeclarativeGeoRouteSegment >(uri, major, minor, "RouteSegment"); qmlRegisterType<QDeclarativeGeoManeuver >(uri, major, minor, "RouteManeuver"); - qmlRegisterUncreatableType<QDeclarativeGeoMapPinchEvent >(uri, major, minor, "MapPinchEvent", + qmlRegisterUncreatableType<QGeoMapPinchEvent >(uri, major, minor, "MapPinchEvent", QStringLiteral("(Map)PinchEvent is not intended instantiable by developer.")); - qmlRegisterUncreatableType<QDeclarativeGeoMapGestureArea>(uri, major, minor, "MapGestureArea", - QStringLiteral("(Map)HestureArea is not intended instantiable by developer.")); + qmlRegisterUncreatableType<QQuickGeoMapGestureArea>(uri, major, minor, "MapGestureArea", + QStringLiteral("(Map)GestureArea is not intended instantiable by developer.")); qmlRegisterUncreatableType<QDeclarativeGeoMapType >(uri, major, minor, "MapType", QStringLiteral("MapType is not intended instantiable by developer.")); qmlRegisterType<QDeclarativeCategory >(uri, major, minor, "Category"); @@ -147,9 +147,16 @@ public: // Register the 5.5 types // Implicitly registers 5.3 & 5.4 + minor = 5; + //TODO: this is broken QTBUG-40043 qmlRegisterUncreatableType<QDeclarativeGeoMapType, 1>(uri, major, minor, "MapType", - QStringLiteral("MapType is not intended instantiable by developer.")); + QStringLiteral("MapType is not intended instantiable by developer.")); + minor = 6; + //TODO: this is broken QTBUG-40043 + qmlRegisterUncreatableType<QQuickGeoMapGestureArea, 1>(uri, major, minor, "MapGestureArea", + QStringLiteral("(Map)GestureArea is not intended instantiable by developer.")); + //registrations below are version independent qRegisterMetaType<QPlaceCategory>(); diff --git a/src/imports/location/location.pro b/src/imports/location/location.pro index 53ef61a6..7441fab3 100644 --- a/src/imports/location/location.pro +++ b/src/imports/location/location.pro @@ -3,6 +3,7 @@ QT += quick-private network positioning-private location-private qml-private cor INCLUDEPATH += ../../location INCLUDEPATH += ../../location/maps INCLUDEPATH += ../../positioning +INCLUDEPATH += ../positioning INCLUDEPATH *= $$PWD HEADERS += \ @@ -24,9 +25,11 @@ HEADERS += \ qdeclarativeroutemapitem_p.h \ qgeomapitemgeometry_p.h \ qdeclarativegeomapcopyrightsnotice_p.h \ - qdeclarativegeomapgesturearea_p.h \ error_messages.h \ - locationvaluetypehelper_p.h + locationvaluetypehelper_p.h\ + qquickgeomapgesturearea_p.h\ + ../positioning/qquickgeocoordinateanimation_p.h \ + mapitemviewdelegateincubator.h SOURCES += \ location.cpp \ @@ -48,9 +51,11 @@ SOURCES += \ qdeclarativeroutemapitem.cpp \ qgeomapitemgeometry.cpp \ qdeclarativegeomapcopyrightsnotice.cpp \ - qdeclarativegeomapgesturearea.cpp \ error_messages.cpp \ - locationvaluetypehelper.cpp + locationvaluetypehelper.cpp \ + qquickgeomapgesturearea.cpp \ + ../positioning/qquickgeocoordinateanimation.cpp \ + mapitemviewdelegateincubator.cpp include(declarativeplaces/declarativeplaces.pri) diff --git a/src/imports/location/locationvaluetypehelper_p.h b/src/imports/location/locationvaluetypehelper_p.h index 648dae34..50038e88 100644 --- a/src/imports/location/locationvaluetypehelper_p.h +++ b/src/imports/location/locationvaluetypehelper_p.h @@ -37,6 +37,17 @@ #ifndef LOCATION_VALUE_TYPE_HELPER #define LOCATION_VALUE_TYPE_HELPER +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QJSValue> #include <QGeoCoordinate> #include <QGeoRectangle> diff --git a/src/imports/location/mapitemviewdelegateincubator.cpp b/src/imports/location/mapitemviewdelegateincubator.cpp new file mode 100644 index 00000000..98f0d460 --- /dev/null +++ b/src/imports/location/mapitemviewdelegateincubator.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mapitemviewdelegateincubator.h" +#include "qdeclarativegeomapitemview_p.h" + +QT_BEGIN_NAMESPACE + +MapItemViewDelegateIncubator::MapItemViewDelegateIncubator(QDeclarativeGeoMapItemView *view) +: m_view(view) +{ +} + +void MapItemViewDelegateIncubator::statusChanged(QQmlIncubator::Status status) +{ + m_view->incubatorStatusChanged(this, status); +} + +QT_END_NAMESPACE diff --git a/src/imports/location/mapitemviewdelegateincubator.h b/src/imports/location/mapitemviewdelegateincubator.h new file mode 100644 index 00000000..aa82a6bf --- /dev/null +++ b/src/imports/location/mapitemviewdelegateincubator.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MAPITEMVIEWDELEGATEINCUBATOR_H +#define MAPITEMVIEWDELEGATEINCUBATOR_H + +#include <QtQml/QQmlIncubator> + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoMapItemView; + +class MapItemViewDelegateIncubator : public QQmlIncubator +{ +public: + MapItemViewDelegateIncubator(QDeclarativeGeoMapItemView *view); + +protected: + void statusChanged(Status status) Q_DECL_OVERRIDE; + +private: + QDeclarativeGeoMapItemView *m_view; +}; + +QT_END_NAMESPACE + +#endif // MAPITEMVIEWDELEGATEINCUBATOR_H diff --git a/src/imports/location/plugins.qmltypes b/src/imports/location/plugins.qmltypes index 5b2a72ea..105e8713 100644 --- a/src/imports/location/plugins.qmltypes +++ b/src/imports/location/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtLocation 5.5' +// 'qmlplugindump -nonrelocatable QtLocation 5.6' Module { dependencies: [] @@ -392,12 +392,7 @@ Module { prototype: "QQuickItem" exports: ["QtLocation/Map 5.0"] exportMetaObjectRevisions: [0] - Property { - name: "gesture" - type: "QDeclarativeGeoMapGestureArea" - isReadonly: true - isPointer: true - } + Property { name: "gesture"; type: "QQuickGeoMapGestureArea"; isReadonly: true; isPointer: true } Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } Property { name: "minimumZoomLevel"; type: "double" } Property { name: "maximumZoomLevel"; type: "double" } @@ -443,6 +438,18 @@ Module { name: "toCoordinate" type: "QGeoCoordinate" Parameter { name: "position"; type: "QPointF" } + Parameter { name: "clipToViewPort"; type: "bool" } + } + Method { + name: "toCoordinate" + type: "QGeoCoordinate" + Parameter { name: "position"; type: "QPointF" } + } + Method { + name: "fromCoordinate" + type: "QPointF" + Parameter { name: "coordinate"; type: "QGeoCoordinate" } + Parameter { name: "clipToViewPort"; type: "bool" } } Method { name: "fromCoordinate" @@ -467,57 +474,6 @@ Module { Method { name: "prefetchData" } } Component { - name: "QDeclarativeGeoMapGestureArea" - prototype: "QObject" - exports: ["QtLocation/MapGestureArea 5.0"] - isCreatable: false - exportMetaObjectRevisions: [0] - Enum { - name: "ActiveGesture" - values: { - "NoGesture": 0, - "ZoomGesture": 1, - "PanGesture": 2, - "FlickGesture": 4 - } - } - Enum { - name: "ActiveGestures" - values: { - "NoGesture": 0, - "ZoomGesture": 1, - "PanGesture": 2, - "FlickGesture": 4 - } - } - Property { name: "enabled"; type: "bool" } - Property { name: "pinchEnabled"; type: "bool" } - Property { name: "panEnabled"; type: "bool" } - Property { name: "isPinchActive"; type: "bool"; isReadonly: true } - Property { name: "isPanActive"; type: "bool"; isReadonly: true } - Property { name: "activeGestures"; type: "ActiveGestures" } - Property { name: "maximumZoomLevelChange"; type: "double" } - Property { name: "flickDeceleration"; type: "double" } - Signal { name: "panActiveChanged" } - Signal { name: "pinchActiveChanged" } - Signal { - name: "pinchStarted" - Parameter { name: "pinch"; type: "QDeclarativeGeoMapPinchEvent"; isPointer: true } - } - Signal { - name: "pinchUpdated" - Parameter { name: "pinch"; type: "QDeclarativeGeoMapPinchEvent"; isPointer: true } - } - Signal { - name: "pinchFinished" - Parameter { name: "pinch"; type: "QDeclarativeGeoMapPinchEvent"; isPointer: true } - } - Signal { name: "panStarted" } - Signal { name: "panFinished" } - Signal { name: "flickStarted" } - Signal { name: "flickFinished" } - } - Component { name: "QDeclarativeGeoMapItemBase" defaultProperty: "data" prototype: "QQuickItem" @@ -620,7 +576,9 @@ Module { "CommunicationError": 2, "ParseError": 3, "UnsupportedOptionError": 4, - "UnknownError": 5 + "UnknownError": 5, + "UnknownParameterError": 100, + "MissingRequiredParameterError": 101 } } Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } @@ -1023,7 +981,9 @@ Module { "ParseError": 3, "UnsupportedOptionError": 4, "CombinationError": 5, - "UnknownError": 6 + "UnknownError": 6, + "UnknownParameterError": 100, + "MissingRequiredParameterError": 101 } } Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true } @@ -1426,6 +1386,62 @@ Module { Method { name: "keys"; type: "QStringList" } } Component { + name: "QQuickGeoMapGestureArea" + defaultProperty: "data" + prototype: "QQuickItem" + exports: [ + "QtLocation/MapGestureArea 5.0", + "QtLocation/MapGestureArea 5.6" + ] + isCreatable: false + exportMetaObjectRevisions: [0, 1] + Enum { + name: "ActiveGesture" + values: { + "NoGesture": 0, + "ZoomGesture": 1, + "PanGesture": 2, + "FlickGesture": 4 + } + } + Enum { + name: "ActiveGestures" + values: { + "NoGesture": 0, + "ZoomGesture": 1, + "PanGesture": 2, + "FlickGesture": 4 + } + } + Property { name: "enabled"; type: "bool" } + Property { name: "pinchEnabled"; type: "bool" } + Property { name: "panEnabled"; type: "bool" } + Property { name: "isPinchActive"; type: "bool"; isReadonly: true } + Property { name: "isPanActive"; type: "bool"; isReadonly: true } + Property { name: "activeGestures"; type: "ActiveGestures" } + Property { name: "maximumZoomLevelChange"; type: "double" } + Property { name: "flickDeceleration"; type: "double" } + Property { name: "preventStealing"; revision: 1; type: "bool" } + Signal { name: "panActiveChanged" } + Signal { name: "pinchActiveChanged" } + Signal { + name: "pinchStarted" + Parameter { name: "pinch"; type: "QDeclarativeGeoMapPinchEvent"; isPointer: true } + } + Signal { + name: "pinchUpdated" + Parameter { name: "pinch"; type: "QDeclarativeGeoMapPinchEvent"; isPointer: true } + } + Signal { + name: "pinchFinished" + Parameter { name: "pinch"; type: "QDeclarativeGeoMapPinchEvent"; isPointer: true } + } + Signal { name: "panStarted" } + Signal { name: "panFinished" } + Signal { name: "flickStarted" } + Signal { name: "flickFinished" } + } + Component { name: "QQuickItem" defaultProperty: "data" prototype: "QObject" diff --git a/src/imports/location/qdeclarativecirclemapitem.cpp b/src/imports/location/qdeclarativecirclemapitem.cpp index 92977179..eb3de7a2 100644 --- a/src/imports/location/qdeclarativecirclemapitem.cpp +++ b/src/imports/location/qdeclarativecirclemapitem.cpp @@ -35,7 +35,6 @@ ****************************************************************************/ #include "qdeclarativecirclemapitem_p.h" -#include "qdeclarativegeomapquickitem_p.h" #include "qdeclarativepolygonmapitem_p.h" #include "qgeocameracapabilities_p.h" #include "qgeoprojection_p.h" @@ -302,9 +301,9 @@ QDeclarativeCircleMapItem::QDeclarativeCircleMapItem(QQuickItem *parent) { setFlag(ItemHasContents, true); QObject::connect(&border_, SIGNAL(colorChanged(QColor)), - this, SLOT(updateMapItemAssumeDirty())); + this, SLOT(markSourceDirtyAndUpdate())); QObject::connect(&border_, SIGNAL(widthChanged(qreal)), - this, SLOT(updateMapItemAssumeDirty())); + this, SLOT(markSourceDirtyAndUpdate())); // assume that circles are not self-intersecting // to speed up processing @@ -335,21 +334,18 @@ QDeclarativeMapLineProperties *QDeclarativeCircleMapItem::border() return &border_; } -void QDeclarativeCircleMapItem::updateMapItemAssumeDirty() +void QDeclarativeCircleMapItem::markSourceDirtyAndUpdate() { geometry_.markSourceDirty(); borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); } void QDeclarativeCircleMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) { QDeclarativeGeoMapItemBase::setMap(quickMap,map); - if (map) { - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - updateMapItem(); - } + if (map) + markSourceDirtyAndUpdate(); } /*! @@ -365,10 +361,7 @@ void QDeclarativeCircleMapItem::setCenter(const QGeoCoordinate ¢er) return; center_ = center; - - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - updateMapItem(); + markSourceDirtyAndUpdate(); emit centerChanged(center_); } @@ -389,7 +382,7 @@ void QDeclarativeCircleMapItem::setColor(const QColor &color) return; color_ = color; dirtyMaterial_ = true; - updateMapItem(); + update(); emit colorChanged(color_); } @@ -411,9 +404,7 @@ void QDeclarativeCircleMapItem::setRadius(qreal radius) return; radius_ = radius; - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - updateMapItem(); + markSourceDirtyAndUpdate(); emit radiusChanged(radius); } @@ -459,7 +450,7 @@ QSGNode *QDeclarativeCircleMapItem::updateMapItemPaintNode(QSGNode *oldNode, Upd /*! \internal */ -void QDeclarativeCircleMapItem::updateMapItem() +void QDeclarativeCircleMapItem::updatePolish() { if (!map() || !center().isValid()) return; @@ -501,7 +492,6 @@ void QDeclarativeCircleMapItem::updateMapItem() } setPositionOnMap(circlePath_.at(0), geometry_.firstPointOffset()); - update(); } /*! @@ -541,7 +531,7 @@ void QDeclarativeCircleMapItem::afterViewportChanged(const QGeoMapViewportChange geometry_.markScreenDirty(); borderGeometry_.markScreenDirty(); - updateMapItem(); + polishAndUpdate(); } /*! diff --git a/src/imports/location/qdeclarativecirclemapitem_p.h b/src/imports/location/qdeclarativecirclemapitem_p.h index 9fb98c9a..9b142309 100644 --- a/src/imports/location/qdeclarativecirclemapitem_p.h +++ b/src/imports/location/qdeclarativecirclemapitem_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVECIRCLEMAPITEM_H #define QDECLARATIVECIRCLEMAPITEM_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeomapitembase_p.h" #include "qdeclarativepolylinemapitem_p.h" #include "qdeclarativepolygonmapitem_p.h" @@ -45,8 +56,6 @@ QT_BEGIN_NAMESPACE -class QDeclarativeGeoMapQuickItem; - class QGeoMapCircleGeometry : public QGeoMapPolygonGeometry { public: @@ -90,10 +99,10 @@ Q_SIGNALS: protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; protected Q_SLOTS: - virtual void updateMapItem() Q_DECL_OVERRIDE; - void updateMapItemAssumeDirty(); + void markSourceDirtyAndUpdate(); virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; private: diff --git a/src/imports/location/qdeclarativegeocodemodel.cpp b/src/imports/location/qdeclarativegeocodemodel.cpp index 4c043d49..d8ff4e85 100644 --- a/src/imports/location/qdeclarativegeocodemodel.cpp +++ b/src/imports/location/qdeclarativegeocodemodel.cpp @@ -150,7 +150,7 @@ void QDeclarativeGeocodeModel::update() return; if (!plugin_) { - qmlInfo(this) << QStringLiteral("Cannot geocode, plugin not set."); + setError(EngineNotSetError, tr("Cannot geocode, plugin not set.")); return; } @@ -160,17 +160,16 @@ void QDeclarativeGeocodeModel::update() QGeoCodingManager *geocodingManager = serviceProvider->geocodingManager(); if (!geocodingManager) { - qmlInfo(this) << QStringLiteral("Cannot geocode, geocode manager not set."); + setError(EngineNotSetError, tr("Cannot geocode, geocode manager not set.")); return; } if (!coordinate_.isValid() && (!address_ || address_->address().isEmpty()) && (searchString_.isEmpty())) { - qmlInfo(this) << QStringLiteral("Cannot geocode, valid query not set."); + setError(ParseError, tr("Cannot geocode, valid query not set.")); return; } abortRequest(); // abort possible previous requests - setErrorString(""); // clear previous error string - setError(NoError); + setError(NoError, QString()); if (coordinate_.isValid()) { setStatus(QDeclarativeGeocodeModel::Loading); @@ -291,11 +290,31 @@ void QDeclarativeGeocodeModel::pluginReady() { QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); QGeoCodingManager *geocodingManager = serviceProvider->geocodingManager(); - if (!geocodingManager || serviceProvider->error() != QGeoServiceProvider::NoError) { - qmlInfo(this) << QStringLiteral("Error: Plugin does not support (reverse) geocoding.\nError message:") - << serviceProvider->errorString(); + + if (serviceProvider->error() != QGeoServiceProvider::NoError) { + QDeclarativeGeocodeModel::GeocodeError newError = UnknownError; + switch (serviceProvider->error()) { + case QGeoServiceProvider::NotSupportedError: + newError = EngineNotSetError; break; + case QGeoServiceProvider::UnknownParameterError: + newError = UnknownParameterError; break; + case QGeoServiceProvider::MissingRequiredParameterError: + newError = MissingRequiredParameterError; break; + case QGeoServiceProvider::ConnectionError: + newError = CommunicationError; break; + default: + break; + } + + setError(newError, serviceProvider->errorString()); + return; + } + + if (!geocodingManager) { + setError(EngineNotSetError,tr("Plugin does not support (reverse) geocoding.")); return; } + connect(geocodingManager, SIGNAL(finished(QGeoCodeReply*)), this, SLOT(geocodeFinished(QGeoCodeReply*))); connect(geocodingManager, SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString)), @@ -362,8 +381,7 @@ void QDeclarativeGeocodeModel::geocodeFinished(QGeoCodeReply *reply) return; int oldCount = declarativeLocations_.count(); setLocations(reply->locations()); - setErrorString(""); - setError(NoError); + setError(NoError, QString()); setStatus(QDeclarativeGeocodeModel::Ready); reply->deleteLater(); reply_ = 0; @@ -389,8 +407,7 @@ void QDeclarativeGeocodeModel::geocodeError(QGeoCodeReply *reply, emit locationsChanged(); emit countChanged(); } - setErrorString(errorString); - setError(static_cast<QDeclarativeGeocodeModel::GeocodeError>(error)); + setError(static_cast<QDeclarativeGeocodeModel::GeocodeError>(error), errorString); setStatus(QDeclarativeGeocodeModel::Error); reply->deleteLater(); reply_ = 0; @@ -428,13 +445,17 @@ void QDeclarativeGeocodeModel::setStatus(QDeclarativeGeocodeModel::Status status This read-only property holds the latest error value of the geocoding request. \list - \li GeocodeModel.NoError - No error has occurred - \li GeocodeModel.EngineNotSetError - The plugin/service provider used does not support (reverse) geocoding - \li GeocodeModel.CommunicationError - An error occurred while communicating with the service provider - \li GeocodeModel.ParseError - The response from the service provider was in an unrecognizable format - \li GeocodeModel.UnsupportedOptionError - The requested operation or one of the options for the operation are not supported by the service provider. - \li GeocodeModel.CombinationError - An error occurred while results where being combined from multiple sources - \li GeocodeModel.UnknownError - An error occurred which does not fit into any of the other categories + \li GeocodeModel.NoError - No error has occurred. + \li GeocodeModel.CombinationError - An error occurred while results where being combined from multiple sources. + \li GeocodeModel.CommunicationError - An error occurred while communicating with the service provider. + \li GeocodeModel.EngineNotSetError - The model's plugin property was not set or there is no geocoding manager associated with the plugin. + \li GeocodeModel.MissingRequiredParameterError - A required parameter was not specified. + \li GeocodeModel.ParseError - The response from the service provider was in an unrecognizable format. + \li GeocodeModel.UnknownError - An error occurred which does not fit into any of the other categories. + \li GeocodeModel.UnknownParameterError - The plugin did not recognize one of the parameters it was given. + \li GeocodeModel.UnsupportedOptionError - The requested operation is not supported by the geocoding provider. + This may happen when the loaded engine does not support a particular geocoding request + such as reverse geocoding. \endlist */ @@ -443,11 +464,12 @@ QDeclarativeGeocodeModel::GeocodeError QDeclarativeGeocodeModel::error() const return error_; } -void QDeclarativeGeocodeModel::setError(GeocodeError error) +void QDeclarativeGeocodeModel::setError(GeocodeError error, const QString &errorString) { - if (error_ == error) + if (error_ == error && errorString_ == errorString) return; error_ = error; + errorString_ = errorString; emit errorChanged(); } @@ -466,14 +488,6 @@ QString QDeclarativeGeocodeModel::errorString() const return errorString_; } -void QDeclarativeGeocodeModel::setErrorString(const QString &error) -{ - if (errorString_ == error) - return; - errorString_ = error; - emit errorStringChanged(); -} - /*! \internal */ @@ -592,8 +606,7 @@ void QDeclarativeGeocodeModel::reset() endResetModel(); abortRequest(); - setErrorString(QString()); - setError(NoError); + setError(NoError, QString()); setStatus(QDeclarativeGeocodeModel::Null); } @@ -606,8 +619,7 @@ void QDeclarativeGeocodeModel::reset() void QDeclarativeGeocodeModel::cancel() { abortRequest(); - setErrorString(QString()); - setError(NoError); + setError(NoError, QString()); setStatus(declarativeLocations_.isEmpty() ? Null : Ready); } diff --git a/src/imports/location/qdeclarativegeocodemodel_p.h b/src/imports/location/qdeclarativegeocodemodel_p.h index 2844ee48..2fbe9937 100644 --- a/src/imports/location/qdeclarativegeocodemodel_p.h +++ b/src/imports/location/qdeclarativegeocodemodel_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOCODEMODEL_H #define QDECLARATIVEGEOCODEMODEL_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeoserviceprovider_p.h" #include <qgeocodereply.h> @@ -63,7 +74,7 @@ class QDeclarativeGeocodeModel : public QAbstractListModel, public QQmlParserSta Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) Q_PROPERTY(bool autoUpdate READ autoUpdate WRITE setAutoUpdate NOTIFY autoUpdateChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) Q_PROPERTY(int count READ count NOTIFY countChanged) Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged) Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged) @@ -82,12 +93,17 @@ public: enum GeocodeError { NoError = QGeoCodeReply::NoError, - EngineNotSetError = QGeoCodeReply::EngineNotSetError, - CommunicationError = QGeoCodeReply::CommunicationError, + EngineNotSetError = QGeoCodeReply::EngineNotSetError, //TODO Qt6 consider merge with NotSupportedError + CommunicationError = QGeoCodeReply::CommunicationError, //TODO Qt6 merge with Map's ConnectionError ParseError = QGeoCodeReply::ParseError, - UnsupportedOptionError = QGeoCodeReply::UnsupportedOptionError, + UnsupportedOptionError = QGeoCodeReply::UnsupportedOptionError, //TODO Qt6 consider rename UnsupportedOperationError CombinationError = QGeoCodeReply::CombinationError, - UnknownError = QGeoCodeReply::UnknownError + UnknownError = QGeoCodeReply::UnknownError, + //we leave gap for future QGeoCodeReply errors + + //QGeoServiceProvider related errors start here + UnknownParameterError = 100, + MissingRequiredParameterError }; enum Roles { @@ -136,8 +152,7 @@ Q_SIGNALS: void countChanged(); void pluginChanged(); void statusChanged(); - void errorStringChanged(); - void errorChanged(); + void errorChanged(); //emitted also for errorString notification void locationsChanged(); void autoUpdateChanged(); void boundsChanged(); @@ -159,8 +174,7 @@ protected Q_SLOTS: protected: QGeoCodingManager *searchManager(); void setStatus(Status status); - void setErrorString(const QString &error); - void setError(GeocodeError error); + void setError(GeocodeError error, const QString &errorString); bool autoUpdate_; bool complete_; diff --git a/src/imports/location/qdeclarativegeomaneuver_p.h b/src/imports/location/qdeclarativegeomaneuver_p.h index 5f2facad..b189d83f 100644 --- a/src/imports/location/qdeclarativegeomaneuver_p.h +++ b/src/imports/location/qdeclarativegeomaneuver_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOMANEUVER_H #define QDECLARATIVEGEOMANEUVER_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <qgeomaneuver.h> #include <QtPositioning/QGeoCoordinate> diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp index 53c40a6e..80208a9b 100644 --- a/src/imports/location/qdeclarativegeomap.cpp +++ b/src/imports/location/qdeclarativegeomap.cpp @@ -175,12 +175,13 @@ QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent) m_mappingManager(0), m_center(51.5073,-0.1277), //London city center m_activeMapType(0), - m_gestureArea(0), + m_gestureArea(new QQuickGeoMapGestureArea(this)), m_map(0), m_error(QGeoServiceProvider::NoError), m_zoomLevel(8.0), m_componentCompleted(false), m_mappingManagerInitialized(false), + m_color(QColor::fromRgbF(0.9, 0.9, 0.9)), m_pendingFitViewport(false) { setAcceptHoverEvents(false); @@ -190,8 +191,6 @@ QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent) connect(this, SIGNAL(childrenChanged()), this, SLOT(onMapChildrenChanged()), Qt::QueuedConnection); - // Create internal flickable and pinch area. - m_gestureArea = new QDeclarativeGeoMapGestureArea(this, this); m_activeMapType = new QDeclarativeGeoMapType(QGeoMapType(QGeoMapType::NoMap, tr("No Map"), tr("No Map"), false, false, 0), this); @@ -279,11 +278,14 @@ void QDeclarativeGeoMap::pluginReady() m_serviceProvider = m_plugin->sharedGeoServiceProvider(); m_mappingManager = m_serviceProvider->mappingManager(); - setError(m_serviceProvider->error(), m_serviceProvider->errorString()); + if (m_serviceProvider->error() != QGeoServiceProvider::NoError) { + setError(m_serviceProvider->error(), m_serviceProvider->errorString()); + return; + } - if (!m_mappingManager || m_serviceProvider->error() != QGeoServiceProvider::NoError) { - qmlInfo(this) << QStringLiteral("Error: Plugin does not support mapping.\nError message:") - << m_serviceProvider->errorString(); + if (!m_mappingManager) { + //TODO Should really be EngineNotSetError (see QML GeoCodeModel) + setError(QGeoServiceProvider::NotSupportedError, tr("Plugin does not support mapping.")); return; } @@ -368,7 +370,7 @@ void QDeclarativeGeoMap::touchUngrabEvent() further details. */ -QDeclarativeGeoMapGestureArea *QDeclarativeGeoMap::gesture() +QQuickGeoMapGestureArea *QDeclarativeGeoMap::gesture() { return m_gestureArea; } @@ -416,9 +418,11 @@ QSGNode *QDeclarativeGeoMap::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa QSGSimpleRectNode *root = static_cast<QSGSimpleRectNode *>(oldNode); if (!root) - root = new QSGSimpleRectNode(boundingRect(), QColor::fromRgbF(0.9, 0.9, 0.9)); - else + root = new QSGSimpleRectNode(boundingRect(), m_color); + else { root->setRect(boundingRect()); + root->setColor(m_color); + } QSGNode *content = root->childCount() ? root->firstChild() : 0; content = m_map->updateSceneGraph(content, window()); @@ -538,16 +542,6 @@ void QDeclarativeGeoMap::mappingManagerInitialized() /*! \internal */ -void QDeclarativeGeoMap::updateMapDisplay(const QRectF &target) -{ - Q_UNUSED(target); - QQuickItem::update(); -} - - -/*! - \internal -*/ QDeclarativeGeoServiceProvider *QDeclarativeGeoMap::plugin() const { return m_plugin; @@ -713,7 +707,7 @@ QGeoCoordinate QDeclarativeGeoMap::center() const This property does not provide any change notifications. - \since 5.5 + \since 5.6 */ void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape) { @@ -737,8 +731,8 @@ void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape) QGeoShape QDeclarativeGeoMap::visibleRegion() const { - if (!width() || !height()) - return QGeoShape(); + if (!m_map || !width() || !height()) + return m_region; QGeoCoordinate tl = m_map->itemPositionToCoordinate(QDoubleVector2D(0, 0)); QGeoCoordinate br = m_map->itemPositionToCoordinate(QDoubleVector2D(width(), height())); @@ -746,8 +740,32 @@ QGeoShape QDeclarativeGeoMap::visibleRegion() const return QGeoRectangle(tl, br); } + +/*! + \qmlproperty color QtLocation::Map::color + + This property holds the background color of the map element. + + \since 5.6 +*/ +void QDeclarativeGeoMap::setColor(const QColor &color) +{ + if (color != m_color) { + m_color = color; + update(); + emit colorChanged(m_color); + } +} + +QColor QDeclarativeGeoMap::color() const +{ + return m_color; +} + void QDeclarativeGeoMap::fitViewportToGeoShape() { + if (!m_map) return; + double bboxWidth; double bboxHeight; QGeoCoordinate centerCoordinate; @@ -827,48 +845,38 @@ QQmlListProperty<QDeclarativeGeoMapType> QDeclarativeGeoMap::supportedMapTypes() } /*! - \qmlmethod coordinate QtLocation::Map::toCoordinate(QPointF position) + \qmlmethod coordinate QtLocation::Map::toCoordinate(QPointF position, bool clipToViewPort) Returns the coordinate which corresponds to the \a position relative to the map item. - Returns an invalid coordinate if \a position is not within the current viewport. + If \a cliptoViewPort is \c true, or not supplied then returns an invalid coordinate if + \a position is not within the current viewport. */ -QGeoCoordinate QDeclarativeGeoMap::toCoordinate(const QPointF &position) const +QGeoCoordinate QDeclarativeGeoMap::toCoordinate(const QPointF &position, bool clipToViewPort) const { if (m_map) - return m_map->itemPositionToCoordinate(QDoubleVector2D(position)); + return m_map->itemPositionToCoordinate(QDoubleVector2D(position), clipToViewPort); else return QGeoCoordinate(); } /*! - \qmlmethod point QtLocation::Map::fromCoordinate(coordinate coordinate) + \qmlmethod point QtLocation::Map::fromCoordinate(coordinate coordinate, bool clipToViewPort) Returns the position relative to the map item which corresponds to the \a coordinate. - Returns an invalid QPointF if \a coordinate is not within the current viewport. + If \a cliptoViewPort is \c true, or not supplied then returns an invalid QPointF if + \a coordinate is not within the current viewport. */ -QPointF QDeclarativeGeoMap::fromCoordinate(const QGeoCoordinate &coordinate) const +QPointF QDeclarativeGeoMap::fromCoordinate(const QGeoCoordinate &coordinate, bool clipToViewPort) const { if (m_map) - return m_map->coordinateToItemPosition(coordinate).toPointF(); + return m_map->coordinateToItemPosition(coordinate, clipToViewPort).toPointF(); else return QPointF(qQNaN(), qQNaN()); } /*! - \qmlmethod QtLocation::Map::toScreenPosition(coordinate coordinate) - \obsolete - - This function is missed named and is equilavent to \l {fromCoordinate}, which should be used - instead. -*/ -QPointF QDeclarativeGeoMap::toScreenPosition(const QGeoCoordinate &coordinate) const -{ - return fromCoordinate(coordinate); -} - -/*! \qmlmethod void QtLocation::Map::pan(int dx, int dy) Starts panning the map by \a dx pixels along the x-axis and @@ -900,6 +908,18 @@ void QDeclarativeGeoMap::prefetchData() } /*! + \qmlmethod void QtLocation::Map::clearData() + + Clears map data collected by the currently selected plugin. + \note This method will delete cached files. + \sa plugin +*/ +void QDeclarativeGeoMap::clearData() +{ + m_map->clearData(); +} + +/*! \qmlproperty string QtLocation::Map::errorString This read-only property holds the textual presentation of the latest mapping provider error. @@ -923,7 +943,7 @@ QString QDeclarativeGeoMap::errorString() const \list \li Map.NoError - No error has occurred. - \li Map.NotSupportedError -The plugin does not support mapping functionality. + \li Map.NotSupportedError -The maps plugin property was not set or there is no mapping manager associated with the plugin. \li Map.UnknownParameterError -The plugin did not recognize one of the parameters it was given. \li Map.MissingRequiredParameterError - The plugin did not find one of the parameters it was expecting. \li Map.ConnectionError - The plugin could not connect to its backend service or database. @@ -948,9 +968,10 @@ void QDeclarativeGeoMap::touchEvent(QTouchEvent *event) event->type() == QEvent::TouchCancel) { ungrabTouchPoints(); } + } else { + //ignore event so sythesized event is generated; + QQuickItem::touchEvent(event); } - //this will always ignore event so sythesized event is generated; - QQuickItem::touchEvent(event); } /*! @@ -967,7 +988,7 @@ void QDeclarativeGeoMap::wheelEvent(QWheelEvent *event) bool QDeclarativeGeoMap::isInteractive() { - return (m_gestureArea->enabled() && m_gestureArea->activeGestures()) || m_gestureArea->isActive(); + return (m_gestureArea->enabled() && m_gestureArea->acceptedGestures()) || m_gestureArea->isActive(); } /*! @@ -1144,6 +1165,8 @@ QDeclarativeGeoMapType * QDeclarativeGeoMap::activeMapType() const */ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { + m_gestureArea->setSize(newGeometry.size()); + if (!m_mappingManagerInitialized) return; @@ -1165,89 +1188,6 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF } -// TODO Remove this function -> BC break -/*! - \qmlmethod void QtLocation::Map::fitViewportToGeoShape(QGeoShape shape) - - \internal - - Fits the current viewport to the boundary of the shape. The camera is positioned - in the center of the shape, and at the largest integral zoom level possible which - allows the whole shape to be visible on screen - -*/ -void QDeclarativeGeoMap::fitViewportToGeoShape(const QVariant &variantShape) -{ - if (!m_map || !m_mappingManagerInitialized) - return; - - QGeoShape shape; - - if (variantShape.userType() == qMetaTypeId<QGeoRectangle>()) - shape = variantShape.value<QGeoRectangle>(); - else if (variantShape.userType() == qMetaTypeId<QGeoCircle>()) - shape = variantShape.value<QGeoCircle>(); - else if (variantShape.userType() == qMetaTypeId<QGeoShape>()) - shape = variantShape.value<QGeoShape>(); - - if (!shape.isValid()) - return; - - double bboxWidth; - double bboxHeight; - QGeoCoordinate centerCoordinate; - - switch (shape.type()) { - case QGeoShape::RectangleType: - { - QGeoRectangle rect = shape; - QDoubleVector2D topLeftPoint = m_map->coordinateToItemPosition(rect.topLeft(), false); - QDoubleVector2D botRightPoint = m_map->coordinateToItemPosition(rect.bottomRight(), false); - bboxWidth = qAbs(topLeftPoint.x() - botRightPoint.x()); - bboxHeight = qAbs(topLeftPoint.y() - botRightPoint.y()); - centerCoordinate = rect.center(); - break; - } - case QGeoShape::CircleType: - { - QGeoCircle circle = shape; - centerCoordinate = circle.center(); - QGeoCoordinate edge = centerCoordinate.atDistanceAndAzimuth(circle.radius(), 90); - QDoubleVector2D centerPoint = m_map->coordinateToItemPosition(centerCoordinate, false); - QDoubleVector2D edgePoint = m_map->coordinateToItemPosition(edge, false); - bboxWidth = qAbs(centerPoint.x() - edgePoint.x()) * 2; - bboxHeight = bboxWidth; - break; - } - case QGeoShape::UnknownType: - //Fallthrough to default - default: - return; - } - - // position camera to the center of bounding box - setProperty("center", QVariant::fromValue(centerCoordinate)); - - //If the shape is empty we just change centerposition, not zoom - if (bboxHeight == 0 && bboxWidth == 0) - return; - - // adjust zoom - double bboxWidthRatio = bboxWidth / (bboxWidth + bboxHeight); - double mapWidthRatio = width() / (width() + height()); - double zoomRatio; - - if (bboxWidthRatio > mapWidthRatio) - zoomRatio = bboxWidth / width(); - else - zoomRatio = bboxHeight / height(); - - qreal newZoom = std::log10(zoomRatio) / std::log10(0.5); - - newZoom = std::floor(qMax(minimumZoomLevel(), (m_map->mapController()->zoom() + newZoom))); - setProperty("zoomLevel", QVariant::fromValue(newZoom)); -} - /*! \qmlmethod void QtLocation::Map::fitViewportToMapItems() @@ -1299,6 +1239,10 @@ void QDeclarativeGeoMap::fitViewportToMapItemsRefine(bool refine) continue; } } + // Force map items to update immediately. Needed to ensure correct item size and positions + // when recursively calling this function. + if (item->isPolishScheduled()) + item->updatePolish(); topLeftX = item->position().x(); topLeftY = item->position().y(); diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h index 93f9426b..fb36104a 100644 --- a/src/imports/location/qdeclarativegeomap_p.h +++ b/src/imports/location/qdeclarativegeomap_p.h @@ -37,13 +37,25 @@ #ifndef QDECLARATIVEGEOMAP_H #define QDECLARATIVEGEOMAP_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qgeoserviceprovider.h" #include "qdeclarativegeomapitemview_p.h" -#include "qdeclarativegeomapgesturearea_p.h" +#include "qquickgeomapgesturearea_p.h" #include "qgeocameradata_p.h" #include <QtQuick/QQuickItem> #include <QtCore/QPointer> #include <QtCore/QMutex> +#include <QtGui/QColor> #include <QtPositioning/qgeoshape.h> QT_BEGIN_NAMESPACE @@ -56,7 +68,7 @@ class QDeclarativeGeoMap : public QQuickItem { Q_OBJECT Q_ENUMS(QGeoServiceProvider::Error) - Q_PROPERTY(QDeclarativeGeoMapGestureArea *gesture READ gesture CONSTANT) + Q_PROPERTY(QQuickGeoMapGestureArea *gesture READ gesture CONSTANT) Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) Q_PROPERTY(qreal minimumZoomLevel READ minimumZoomLevel WRITE setMinimumZoomLevel NOTIFY minimumZoomLevelChanged) Q_PROPERTY(qreal maximumZoomLevel READ maximumZoomLevel WRITE setMaximumZoomLevel NOTIFY maximumZoomLevelChanged) @@ -68,6 +80,7 @@ class QDeclarativeGeoMap : public QQuickItem Q_PROPERTY(QGeoServiceProvider::Error error READ error NOTIFY errorChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) Q_PROPERTY(QGeoShape visibleRegion READ visibleRegion WRITE setVisibleRegion) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_INTERFACES(QQmlParserStatus) public: @@ -96,6 +109,9 @@ public: void setVisibleRegion(const QGeoShape &shape); QGeoShape visibleRegion() const; + void setColor(const QColor &color); + QColor color() const; + QQmlListProperty<QDeclarativeGeoMapType> supportedMapTypes(); Q_INVOKABLE void removeMapItem(QDeclarativeGeoMapItemBase *item); @@ -103,19 +119,15 @@ public: Q_INVOKABLE void clearMapItems(); QList<QObject *> mapItems(); - Q_INVOKABLE QGeoCoordinate toCoordinate(const QPointF &position) const; - Q_INVOKABLE QPointF fromCoordinate(const QGeoCoordinate &coordinate) const; - -#if QT_DEPRECATED_SINCE(5,5) - QT_DEPRECATED Q_INVOKABLE QPointF toScreenPosition(const QGeoCoordinate &coordinate) const; -#endif + Q_INVOKABLE QGeoCoordinate toCoordinate(const QPointF &position, bool clipToViewPort = true) const; + Q_INVOKABLE QPointF fromCoordinate(const QGeoCoordinate &coordinate, bool clipToViewPort = true) const; - QDeclarativeGeoMapGestureArea *gesture(); + QQuickGeoMapGestureArea *gesture(); - Q_INVOKABLE void fitViewportToGeoShape(const QVariant &shape); Q_INVOKABLE void fitViewportToMapItems(); Q_INVOKABLE void pan(int dx, int dy); Q_INVOKABLE void prefetchData(); // optional hint for prefetch + Q_INVOKABLE void clearData(); QString errorString() const; QGeoServiceProvider::Error error() const; @@ -131,6 +143,7 @@ Q_SIGNALS: void mapItemsChanged(); void errorChanged(); void copyrightLinkActivated(const QString &link); + void colorChanged(const QColor &color); protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE ; @@ -152,7 +165,6 @@ protected: void setError(QGeoServiceProvider::Error error, const QString &errorString); private Q_SLOTS: - void updateMapDisplay(const QRectF &target); void mappingManagerInitialized(); void mapZoomLevelChanged(qreal zoom); void pluginReady(); @@ -173,7 +185,7 @@ private: QDeclarativeGeoMapType *m_activeMapType; QList<QDeclarativeGeoMapType *> m_supportedMapTypes; QList<QDeclarativeGeoMapItemView *> m_mapViews; - QDeclarativeGeoMapGestureArea *m_gestureArea; + QQuickGeoMapGestureArea *m_gestureArea; QGeoMap *m_map; QPointer<QDeclarativeGeoMapCopyrightNotice> m_copyrights; QList<QPointer<QDeclarativeGeoMapItemBase> > m_mapItems; @@ -184,11 +196,12 @@ private: bool m_componentCompleted; bool m_mappingManagerInitialized; QGeoShape m_region; + QColor m_color; bool m_pendingFitViewport; friend class QDeclarativeGeoMapItem; friend class QDeclarativeGeoMapItemView; - friend class QDeclarativeGeoMapGestureArea; + friend class QQuickGeoMapGestureArea; Q_DISABLE_COPY(QDeclarativeGeoMap) }; diff --git a/src/imports/location/qdeclarativegeomapcopyrightsnotice_p.h b/src/imports/location/qdeclarativegeomapcopyrightsnotice_p.h index 78a0ce30..6ab40111 100644 --- a/src/imports/location/qdeclarativegeomapcopyrightsnotice_p.h +++ b/src/imports/location/qdeclarativegeomapcopyrightsnotice_p.h @@ -38,6 +38,17 @@ #ifndef QDECLARATIVEGEOMAPCOPYRIGHTSNOTICE_H #define QDECLARATIVEGEOMAPCOPYRIGHTSNOTICE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtGui/QImage> #include <QtQuick/QQuickPaintedItem> diff --git a/src/imports/location/qdeclarativegeomapgesturearea.cpp b/src/imports/location/qdeclarativegeomapgesturearea.cpp deleted file mode 100644 index 68178e6d..00000000 --- a/src/imports/location/qdeclarativegeomapgesturearea.cpp +++ /dev/null @@ -1,1174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtLocation module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later 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 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdeclarativegeomapgesturearea_p.h" -#include "qdeclarativegeomap_p.h" -#include "qgeomapcontroller_p.h" -#include "error_messages.h" - -#include <QtGui/QGuiApplication> -#include <QtGui/qevent.h> -#include <QtGui/QWheelEvent> -#include <QtGui/QStyleHints> -#include <QtQml/qqmlinfo.h> -#include <QtQuick/QQuickWindow> -#include <QPropertyAnimation> -#include <QDebug> -#include <QtPositioning/private/qgeoprojection_p.h> -#include "math.h" -#include "qgeomap_p.h" -#include "qdoublevector2d_p.h" - -#define QML_MAP_FLICK_DEFAULTMAXVELOCITY 2500 -#define QML_MAP_FLICK_MINIMUMDECELERATION 500 -#define QML_MAP_FLICK_DEFAULTDECELERATION 2500 -#define QML_MAP_FLICK_MAXIMUMDECELERATION 10000 - -#define QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD 50 -// FlickThreshold determines how far the "mouse" must have moved -// before we perform a flick. -static const int FlickThreshold = 20; -// Really slow flicks can be annoying. -const qreal MinimumFlickVelocity = 75.0; - -QT_BEGIN_NAMESPACE - - -/*! - \qmltype MapPinchEvent - \instantiates QDeclarativeGeoMapPinchEvent - \inqmlmodule QtLocation - - \brief MapPinchEvent type provides basic information about pinch event. - - MapPinchEvent type provides basic information about pinch event. They are - present in handlers of MapPinch (for example pinchStarted/pinchUpdated). Events are only - guaranteed to be valid for the duration of the handler. - - Except for the \l accepted property, all properties are read-only. - - \section2 Example Usage - - The following example enables the pinch gesture on a map and reacts to the - finished event. - - \code - Map { - id: map - gesture.enabled: true - gesture.onPinchFinished:{ - var coordinate1 = map.toCoordinate(gesture.point1) - var coordinate2 = map.toCoordinate(gesture.point2) - console.log("Pinch started at:") - console.log(" Points (" + gesture.point1.x + ", " + gesture.point1.y + ") - (" + gesture.point2.x + ", " + gesture.point2.y + ")") - console.log(" Coordinates (" + coordinate1.latitude + ", " + coordinate1.longitude + ") - (" + coordinate2.latitude + ", " + coordinate2.longitude + ")") - } - } - \endcode - - \ingroup qml-QtLocation5-maps - \since Qt Location 5.0 -*/ - -/*! - \qmlproperty QPoint QtLocation::MapPinchEvent::center - - This read-only property holds the current center point. -*/ - -/*! - \qmlproperty real QtLocation::MapPinchEvent::angle - - This read-only property holds the current angle between the two points in - the range -180 to 180. Positive values for the angles mean counter-clockwise - while negative values mean the clockwise direction. Zero degrees is at the - 3 o'clock position. -*/ - -/*! - \qmlproperty QPoint QtLocation::MapPinchEvent::point1 - \qmlproperty QPoint QtLocation::MapPinchEvent::point2 - - These read-only properties hold the actual touch points generating the pinch. - The points are not in any particular order. -*/ - -/*! - \qmlproperty int QtLocation::MapPinchEvent::pointCount - - This read-only property holds the number of points currently touched. - The MapPinch will not react until two touch points have initiated a gesture, - but will remain active until all touch points have been released. -*/ - -/*! - \qmlproperty bool QtLocation::MapPinchEvent::accepted - - Setting this property to false in the \c MapPinch::onPinchStarted handler - will result in no further pinch events being generated, and the gesture - ignored. -*/ - -/*! - \qmltype MapGestureArea - \instantiates QDeclarativeGeoMapGestureArea - - \inqmlmodule QtLocation - - \brief The MapGestureArea type provides Map gesture interaction. - - MapGestureArea objects are used as part of a Map, to provide for panning, - flicking and pinch-to-zoom gesture used on touch displays. - - A MapGestureArea is automatically created with a new Map and available with - the \l{Map::gesture}{gesture} property. This is the only way - to create a MapGestureArea, and once created this way cannot be destroyed - without its parent Map. - - The two most commonly used properties of the MapGestureArea are the \l enabled - and \l activeGestures properties. Both of these must be set before a - MapGestureArea will have any effect upon interaction with the Map. - The \l flickDeceleration property controls how quickly the map pan slows after contact - is released while panning the map. - - \section2 Performance - - The MapGestureArea, when enabled, must process all incoming touch events in - order to track the shape and size of the "pinch". The overhead added on - touch events can be considered constant time. - - \section2 Example Usage - - The following example enables the zoom and pan gestures on the map, but not flicking. So the - map scrolling will halt immediately on releasing the mouse button / touch. - - \code - Map { - gesture.enabled: true - gesture.activeGestures: MapGestureArea.ZoomGesture | MapGestureArea.PanGesture - } - \endcode - - \ingroup qml-QtLocation5-maps - \since Qt Location 5.0 -*/ - -/*! - \qmlproperty bool QtLocation::MapGestureArea::enabled - - This property holds whether the gestures are enabled. - Note: disabling gestures during an active gesture does not have effect on - the potentially active current gesture. -*/ - - -/*! - \qmlproperty bool QtLocation::MapGestureArea::panEnabled - - This property holds whether the pan gestures are enabled. - Note: disabling gestures during an active gesture does not have effect on - the potentially active current gesture. -*/ - -/*! - \qmlproperty bool QtLocation::MapGestureArea::pinchEnabled - - This property holds whether the pinch gestures are enabled. - Note: disabling gestures during an active gesture does not have effect on - the potentially active current gesture. -*/ - -/*! - \qmlproperty bool QtLocation::MapGestureArea::isPinchActive - - This read-only property holds whether any pinch gesture is active. -*/ - -/*! - \qmlproperty bool QtLocation::MapGestureArea::isPanActive - - This read-only property holds whether any pan gesture (panning or flicking) is active. - - \note Change notifications for this property were introduced in Qt 5.5. -*/ - -/*! - \qmlproperty enumeration QtLocation::MapGestureArea::activeGestures - - This property holds the gestures that will be active. By default - the zoom, pan and flick gestures are enabled. - - \list - \li MapGestureArea.NoGesture - Don't support any additional gestures (value: 0x0000). - \li MapGestureArea.ZoomGesture - Support the map zoom gesture (value: 0x0001). - \li MapGestureArea.PanGesture - Support the map pan gesture (value: 0x0002). - \li MapGestureArea.FlickGesture - Support the map flick gesture (value: 0x0004). - \endlist -*/ - -/*! - \qmlproperty real QtLocation::MapGestureArea::maximumZoomLevelChange - - This property holds the maximum zoom level change per pinch, essentially - meant to be used for setting the zoom sensitivity. - - It is an indicative measure calculated from the dimensions of the - map area, roughly corresponding how much zoom level could change with - maximum pinch zoom. Default value is 4.0, maximum value is 10.0 -*/ - -/*! - \qmlproperty real MapGestureArea::flickDeceleration - - This property holds the rate at which a flick will decelerate. - - The default value is 2500. -*/ - -/*! - \qmlsignal QtLocation::MapGestureArea::pinchStarted(PinchEvent event) - - This signal is emitted when a pinch gesture is started. - - The corresponding handler is \c onPinchStarted. - - \sa pinchUpdated, pinchFinished -*/ - -/*! - \qmlsignal QtLocation::MapGestureArea::pinchUpdated(PinchEvent event) - - This signal is emitted as the user's fingers move across the map, - after the \l pinchStarted signal is emitted. - - The corresponding handler is \c onPinchUpdated. - - \sa pinchStarted, pinchFinished -*/ - -/*! - \qmlsignal QtLocation::MapGestureArea::pinchFinished(PinchEvent event) - - This signal is emitted at the end of a pinch gesture. - - The corresponding handler is \c onPinchFinished. - - \sa pinchStarted, pinchUpdated -*/ - -/*! - \qmlsignal QtLocation::MapGestureArea::panStarted() - - This signal is emitted when the view begins moving due to user - interaction. Typically this means that the user is dragging a finger - - or a mouse with one of more mouse buttons pressed - on the map. - - The corresponding handler is \c onPanStarted. -*/ - -/*! - \qmlsignal QtLocation::MapGestureArea::panFinished() - - This signal is emitted when the view stops moving due to user - interaction. If a flick was generated, this signal is - emitted when the flick stops. If a flick was not - generated, this signal is emitted when the - user stops dragging - that is a mouse or touch release. - - The corresponding handler is \c onPanFinished. - -*/ - -/*! - \qmlsignal QtLocation::MapGestureArea::flickStarted() - - This signal is emitted when the view is flicked. A flick - starts from the point that the mouse or touch is released, - while still in motion. - - The corresponding handler is \c onFlichStarted. -*/ - -/*! - \qmlsignal QtLocation::MapGestureArea::flickFinished() - - This signal is emitted when the view stops moving due to a flick. - The order of panFinished() and flickFinished() is not specified. - - The corresponding handler is \c onFlickFinished. -*/ - -static void registerQGeoCoordinateInterpolator() -{ - // required by QPropertyAnimation - qRegisterAnimationInterpolator<QGeoCoordinate>(geoCoordinateInterpolator); -} -Q_CONSTRUCTOR_FUNCTION(registerQGeoCoordinateInterpolator) - -static void unregisterQGeoCoordinateInterpolator() -{ - qRegisterAnimationInterpolator<QGeoCoordinate>( - (QVariant (*)(const QGeoCoordinate &, const QGeoCoordinate &, qreal))0); -} -Q_DESTRUCTOR_FUNCTION(unregisterQGeoCoordinateInterpolator) - -QDeclarativeGeoMapGestureArea::QDeclarativeGeoMapGestureArea(QDeclarativeGeoMap *map, QObject *parent) - : QObject(parent), - declarativeMap_(map), - enabled_(true), - activeGestures_(ZoomGesture | PanGesture | FlickGesture) -{ - map_ = 0; - pan_.enabled_ = true, - pan_.maxVelocity_ = QML_MAP_FLICK_DEFAULTMAXVELOCITY; - pan_.deceleration_ = QML_MAP_FLICK_DEFAULTDECELERATION; - pan_.animation_ = 0; - touchPointState_ = touchPoints0; - pinchState_ = pinchInactive; - panState_ = panInactive; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::setMap(QGeoMap *map) -{ - if (map_ || !map) - return; - map_ = map; - pan_.animation_ = new QPropertyAnimation(map_->mapController(), "center", this); - pan_.animation_->setEasingCurve(QEasingCurve(QEasingCurve::OutQuad)); - connect(pan_.animation_, SIGNAL(finished()), this, SLOT(endFlick())); -} - -QDeclarativeGeoMapGestureArea::~QDeclarativeGeoMapGestureArea() -{ -} - -/*! - \internal -*/ -QDeclarativeGeoMapGestureArea::ActiveGestures QDeclarativeGeoMapGestureArea::activeGestures() const -{ - return activeGestures_; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::setActiveGestures(ActiveGestures activeGestures) -{ - if (activeGestures == activeGestures_) - return; - activeGestures_ = activeGestures; - emit activeGesturesChanged(); -} - -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::isPinchActive() const -{ - return pinchState_ == pinchActive; -} - -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::isPanActive() const -{ - return panState_ == panActive || panState_ == panFlick; -} - -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::enabled() const -{ - return enabled_; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::setEnabled(bool enabled) -{ - if (enabled == enabled_) - return; - enabled_ = enabled; - emit enabledChanged(); -} - - -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::pinchEnabled() const -{ - return pinch_.enabled; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::setPinchEnabled(bool enabled) -{ - if (enabled == pinch_.enabled) - return; - pinch_.enabled = enabled; - emit pinchEnabledChanged(); -} - -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::panEnabled() const -{ - return pan_.enabled_; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::setPanEnabled(bool enabled) -{ - if (enabled == pan_.enabled_) - return; - pan_.enabled_ = enabled; - emit panEnabledChanged(); - - // unlike the pinch, the pan existing functionality is to stop immediately - if (!enabled) - stopPan(); -} - -/*! - \internal - Used internally to set the minimum zoom level of the gesture area. - The caller is responsible to only send values that are valid - for the map plugin. Negative values are ignored. - */ -void QDeclarativeGeoMapGestureArea::setMinimumZoomLevel(qreal min) -{ - if (min >= 0) - pinch_.zoom.minimum = min; -} - -/*! - \internal - */ -qreal QDeclarativeGeoMapGestureArea::minimumZoomLevel() const -{ - return pinch_.zoom.minimum; -} - -/*! - \internal - Used internally to set the maximum zoom level of the gesture area. - The caller is responsible to only send values that are valid - for the map plugin. Negative values are ignored. - */ -void QDeclarativeGeoMapGestureArea::setMaximumZoomLevel(qreal max) -{ - if (max >= 0) - pinch_.zoom.maximum = max; -} - -/*! - \internal - */ -qreal QDeclarativeGeoMapGestureArea::maximumZoomLevel() const -{ - return pinch_.zoom.maximum; -} - -/*! - \internal -*/ -qreal QDeclarativeGeoMapGestureArea::maximumZoomLevelChange() const -{ - return pinch_.zoom.maximumChange; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::setMaximumZoomLevelChange(qreal maxChange) -{ - if (maxChange == pinch_.zoom.maximumChange || maxChange < 0.1 || maxChange > 10.0) - return; - pinch_.zoom.maximumChange = maxChange; - emit maximumZoomLevelChangeChanged(); -} - -/*! - \internal -*/ -qreal QDeclarativeGeoMapGestureArea::flickDeceleration() const -{ - return pan_.deceleration_; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::setFlickDeceleration(qreal deceleration) -{ - if (deceleration < QML_MAP_FLICK_MINIMUMDECELERATION) - deceleration = QML_MAP_FLICK_MINIMUMDECELERATION; - else if (deceleration > QML_MAP_FLICK_MAXIMUMDECELERATION) - deceleration = QML_MAP_FLICK_MAXIMUMDECELERATION; - if (deceleration == pan_.deceleration_) - return; - pan_.deceleration_ = deceleration; - emit flickDecelerationChanged(); -} - -/*! - \internal -*/ -QTouchEvent::TouchPoint* createTouchPointFromMouseEvent(QMouseEvent *event, Qt::TouchPointState state) -{ - // this is only partially filled. But since it is only partially used it works - // more robust would be to store a list of QPointFs rather than TouchPoints - QTouchEvent::TouchPoint* newPoint = new QTouchEvent::TouchPoint(); - newPoint->setPos(event->localPos()); - newPoint->setScenePos(event->windowPos()); - newPoint->setScreenPos(event->screenPos()); - newPoint->setState(state); - newPoint->setId(0); - return newPoint; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event) -{ - m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointPressed)); - if (m_touchPoints.isEmpty()) update(); - event->accept(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event) -{ - m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointMoved)); - if (m_touchPoints.isEmpty()) update(); - event->accept(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *event) -{ - m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointReleased)); - if (m_touchPoints.isEmpty()) update(); - event->accept(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::handleMouseUngrabEvent() -{ - m_mousePoint.reset(); - update(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::handleTouchUngrabEvent() -{ - m_touchPoints.clear(); - update(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::handleTouchEvent(QTouchEvent *event) -{ - m_touchPoints.clear(); - for (int i = 0; i < event->touchPoints().count(); ++i) - m_touchPoints << event->touchPoints().at(i); - update(); -} - -void QDeclarativeGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) -{ - declarativeMap_->setZoomLevel(qBound(minimumZoomLevel(), declarativeMap_->zoomLevel() + event->angleDelta().y() * qreal(0.001), maximumZoomLevel())); - event->accept(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::clearTouchData() -{ - velocityX_ = 0; - velocityY_ = 0; - sceneCenter_.setX(0); - sceneCenter_.setY(0); - touchCenterCoord_.setLongitude(0); - touchCenterCoord_.setLatitude(0); - startCoord_.setLongitude(0); - startCoord_.setLatitude(0); -} - - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::updateVelocityList(const QPointF &pos) -{ - // Take velocity samples every sufficient period of time, used later to determine the flick - // duration and speed (when mouse is released). - qreal elapsed = qreal(lastPosTime_.elapsed()); - - if (elapsed >= QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { - elapsed /= 1000.; - int dyFromLastPos = pos.y() - lastPos_.y(); - int dxFromLastPos = pos.x() - lastPos_.x(); - lastPos_ = pos; - lastPosTime_.restart(); - qreal velX = qreal(dxFromLastPos) / elapsed; - qreal velY = qreal(dyFromLastPos) / elapsed; - velocityX_ = qBound<qreal>(-pan_.maxVelocity_, velX, pan_.maxVelocity_); - velocityY_ = qBound<qreal>(-pan_.maxVelocity_, velY, pan_.maxVelocity_); - } -} - -/*! - \internal -*/ - -bool QDeclarativeGeoMapGestureArea::isActive() const -{ - return isPanActive() || isPinchActive(); -} - -/*! - \internal -*/ -// simplify the gestures by using a state-machine format (easy to move to a future state machine) -void QDeclarativeGeoMapGestureArea::update() -{ - if (!map_) return; - // First state machine is for the number of touch points - - //combine touch with mouse event - m_allPoints.clear(); - m_allPoints << m_touchPoints; - if (m_allPoints.isEmpty() && !m_mousePoint.isNull()) - m_allPoints << *m_mousePoint.data(); - - touchPointStateMachine(); - - // Parallel state machine for pinch - if (isPinchActive() || (enabled_ && pinch_.enabled && (activeGestures_ & (ZoomGesture)))) - pinchStateMachine(); - - // Parallel state machine for pan (since you can pan at the same time as pinching) - // The stopPan function ensures that pan stops immediately when disabled, - // but the line below allows pan continue its current gesture if you disable - // the whole gesture (enabled_ flag), this keeps the enabled_ consistent with the pinch - if (isPanActive() || (enabled_ && pan_.enabled_ && (activeGestures_ & (PanGesture | FlickGesture)))) - panStateMachine(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::touchPointStateMachine() -{ - // Transitions: - switch (touchPointState_) { - case touchPoints0: - if (m_allPoints.count() == 1) { - clearTouchData(); - startOneTouchPoint(); - touchPointState_ = touchPoints1; - } else if (m_allPoints.count() >= 2) { - clearTouchData(); - startTwoTouchPoints(); - touchPointState_ = touchPoints2; - } - break; - case touchPoints1: - if (m_allPoints.count() == 0) { - touchPointState_ = touchPoints0; - } else if (m_allPoints.count() == 2) { - touchCenterCoord_ = map_->itemPositionToCoordinate(QDoubleVector2D(sceneCenter_), false); - startTwoTouchPoints(); - touchPointState_ = touchPoints2; - } - break; - case touchPoints2: - if (m_allPoints.count() == 0) { - touchPointState_ = touchPoints0; - } else if (m_allPoints.count() == 1) { - touchCenterCoord_ = map_->itemPositionToCoordinate(QDoubleVector2D(sceneCenter_), false); - startOneTouchPoint(); - touchPointState_ = touchPoints1; - } - break; - }; - - // Update - switch (touchPointState_) { - case touchPoints0: - break; // do nothing if no touch points down - case touchPoints1: - updateOneTouchPoint(); - break; - case touchPoints2: - updateTwoTouchPoints(); - break; - } -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::startOneTouchPoint() -{ - sceneStartPoint1_ = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - lastPos_ = sceneStartPoint1_; - lastPosTime_.start(); - QGeoCoordinate startCoord = map_->itemPositionToCoordinate(QDoubleVector2D(sceneStartPoint1_), false); - // ensures a smooth transition for panning - startCoord_.setLongitude(startCoord_.longitude() + startCoord.longitude() - - touchCenterCoord_.longitude()); - startCoord_.setLatitude(startCoord_.latitude() + startCoord.latitude() - - touchCenterCoord_.latitude()); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::updateOneTouchPoint() -{ - sceneCenter_ = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - updateVelocityList(sceneCenter_); -} - - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::startTwoTouchPoints() -{ - sceneStartPoint1_ = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - sceneStartPoint2_ = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos()); - QPointF startPos = (sceneStartPoint1_ + sceneStartPoint2_) * 0.5; - lastPos_ = startPos; - lastPosTime_.start(); - QGeoCoordinate startCoord = map_->itemPositionToCoordinate(QDoubleVector2D(startPos), false); - startCoord_.setLongitude(startCoord_.longitude() + startCoord.longitude() - - touchCenterCoord_.longitude()); - startCoord_.setLatitude(startCoord_.latitude() + startCoord.latitude() - - touchCenterCoord_.latitude()); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::updateTwoTouchPoints() -{ - QPointF p1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - QPointF p2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos()); - qreal dx = p1.x() - p2.x(); - qreal dy = p1.y() - p2.y(); - distanceBetweenTouchPoints_ = sqrt(dx * dx + dy * dy); - sceneCenter_ = (p1 + p2) / 2; - updateVelocityList(sceneCenter_); - - twoTouchAngle_ = QLineF(p1, p2).angle(); - if (twoTouchAngle_ > 180) - twoTouchAngle_ -= 360; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::pinchStateMachine() -{ - PinchState lastState = pinchState_; - // Transitions: - switch (pinchState_) { - case pinchInactive: - if (m_allPoints.count() >= 2) { - if (canStartPinch()) { - startPinch(); - pinchState_ = pinchActive; - } else { - pinchState_ = pinchInactiveTwoPoints; - } - } - break; - case pinchInactiveTwoPoints: - if (m_allPoints.count() <= 1) { - pinchState_ = pinchInactive; - } else { - if (canStartPinch()) { - startPinch(); - pinchState_ = pinchActive; - } - } - break; - case pinchActive: - if (m_allPoints.count() <= 1) { - endPinch(); - pinchState_ = pinchInactive; - } - break; - } - // This line implements an exclusive state machine, where the transitions and updates don't - // happen on the same frame - if (pinchState_ != lastState) { - emit pinchActiveChanged(); - return; - } - - // Update - switch (pinchState_) { - case pinchInactive: - case pinchInactiveTwoPoints: - break; // do nothing - case pinchActive: - updatePinch(); - break; - } -} - -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::canStartPinch() -{ - const int startDragDistance = qApp->styleHints()->startDragDistance(); - - if (m_allPoints.count() >= 2) { - QPointF p1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - QPointF p2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos()); - if (qAbs(p1.x()-sceneStartPoint1_.x()) > startDragDistance - || qAbs(p1.y()-sceneStartPoint1_.y()) > startDragDistance - || qAbs(p2.x()-sceneStartPoint2_.x()) > startDragDistance - || qAbs(p2.y()-sceneStartPoint2_.y()) > startDragDistance) { - pinch_.event.setCenter(declarativeMap_->mapFromScene(sceneCenter_)); - pinch_.event.setAngle(twoTouchAngle_); - pinch_.event.setPoint1(p1); - pinch_.event.setPoint2(p2); - pinch_.event.setPointCount(m_allPoints.count()); - pinch_.event.setAccepted(true); - emit pinchStarted(&pinch_.event); - return pinch_.event.accepted(); - } - } - return false; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::startPinch() -{ - pinch_.startDist = distanceBetweenTouchPoints_; - pinch_.zoom.previous = declarativeMap_->zoomLevel(); - pinch_.lastAngle = twoTouchAngle_; - - pinch_.lastPoint1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - pinch_.lastPoint2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos()); - - pinch_.zoom.start = declarativeMap_->zoomLevel(); -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::updatePinch() -{ - // Calculate the new zoom level if we have distance ( >= 2 touchpoints), otherwise stick with old. - qreal newZoomLevel = pinch_.zoom.previous; - if (distanceBetweenTouchPoints_) { - newZoomLevel = - // How much further/closer the current touchpoints are (in pixels) compared to pinch start - ((distanceBetweenTouchPoints_ - pinch_.startDist) * - // How much one pixel corresponds in units of zoomlevel (and multiply by above delta) - (pinch_.zoom.maximumChange / ((declarativeMap_->width() + declarativeMap_->height()) / 2))) + - // Add to starting zoom level. Sign of (dist-pinchstartdist) takes care of zoom in / out - pinch_.zoom.start; - } - qreal da = pinch_.lastAngle - twoTouchAngle_; - if (da > 180) - da -= 360; - else if (da < -180) - da += 360; - pinch_.event.setCenter(declarativeMap_->mapFromScene(sceneCenter_)); - pinch_.event.setAngle(twoTouchAngle_); - - pinch_.lastPoint1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - pinch_.lastPoint2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos()); - pinch_.event.setPoint1(pinch_.lastPoint1); - pinch_.event.setPoint2(pinch_.lastPoint2); - pinch_.event.setPointCount(m_allPoints.count()); - pinch_.event.setAccepted(true); - - pinch_.lastAngle = twoTouchAngle_; - emit pinchUpdated(&pinch_.event); - - if (activeGestures_ & ZoomGesture) { - // Take maximum and minimumzoomlevel into account - qreal perPinchMinimumZoomLevel = qMax(pinch_.zoom.start - pinch_.zoom.maximumChange, pinch_.zoom.minimum); - qreal perPinchMaximumZoomLevel = qMin(pinch_.zoom.start + pinch_.zoom.maximumChange, pinch_.zoom.maximum); - newZoomLevel = qMin(qMax(perPinchMinimumZoomLevel, newZoomLevel), perPinchMaximumZoomLevel); - declarativeMap_->setZoomLevel(newZoomLevel); - pinch_.zoom.previous = newZoomLevel; - } -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::endPinch() -{ - QPointF p1 = declarativeMap_->mapFromScene(pinch_.lastPoint1); - QPointF p2 = declarativeMap_->mapFromScene(pinch_.lastPoint2); - pinch_.event.setCenter((p1 + p2) / 2); - pinch_.event.setAngle(pinch_.lastAngle); - pinch_.event.setPoint1(p1); - pinch_.event.setPoint2(p2); - pinch_.event.setAccepted(true); - pinch_.event.setPointCount(0); - emit pinchFinished(&pinch_.event); - pinch_.startDist = 0; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::panStateMachine() -{ - PanState lastState = panState_; - - // Transitions - switch (panState_) { - case panInactive: - if (canStartPan()) { - // Update startCoord_ to ensure smooth start for panning when going over startDragDistance - QGeoCoordinate newStartCoord = map_->itemPositionToCoordinate(QDoubleVector2D(sceneCenter_), false); - startCoord_.setLongitude(newStartCoord.longitude()); - startCoord_.setLatitude(newStartCoord.latitude()); - panState_ = panActive; - } - break; - case panActive: - if (m_allPoints.count() == 0) { - panState_ = panFlick; - if (!tryStartFlick()) - { - panState_ = panInactive; - // mark as inactive for use by camera - if (pinchState_ == pinchInactive) { - emit panFinished(); - map_->prefetchData(); - } - } - } - break; - case panFlick: - if (m_allPoints.count() > 0) { // re touched before movement ended - endFlick(); - panState_ = panActive; - } - break; - } - - if (panState_ != lastState) - emit panActiveChanged(); - - // Update - switch (panState_) { - case panInactive: // do nothing - break; - case panActive: - updatePan(); - // this ensures 'panStarted' occurs after the pan has actually started - if (lastState != panActive) - emit panStarted(); - break; - case panFlick: - break; - } -} -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::canStartPan() -{ - if (m_allPoints.count() == 0 || (activeGestures_ & PanGesture) == 0) - return false; - - // Check if thresholds for normal panning are met. - // (normal panning vs flicking: flicking will start from mouse release event). - const int startDragDistance = qApp->styleHints()->startDragDistance() * 2; - QPointF p1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos()); - int dyFromPress = int(p1.y() - sceneStartPoint1_.y()); - int dxFromPress = int(p1.x() - sceneStartPoint1_.x()); - if ((qAbs(dyFromPress) >= startDragDistance || qAbs(dxFromPress) >= startDragDistance)) - return true; - return false; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::updatePan() -{ - QPointF startPoint = map_->coordinateToItemPosition(startCoord_, false).toPointF(); - int dx = static_cast<int>(sceneCenter_.x() - startPoint.x()); - int dy = static_cast<int>(sceneCenter_.y() - startPoint.y()); - QPointF mapCenterPoint; - mapCenterPoint.setY(map_->height() / 2.0 - dy); - mapCenterPoint.setX(map_->width() / 2.0 - dx); - QGeoCoordinate animationStartCoordinate = map_->itemPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false); - map_->mapController()->setCenter(animationStartCoordinate); -} - -/*! - \internal -*/ -bool QDeclarativeGeoMapGestureArea::tryStartFlick() -{ - if ((activeGestures_ & FlickGesture) == 0) - return false; - // if we drag then pause before release we should not cause a flick. - qreal velocityX = 0.0; - qreal velocityY = 0.0; - if (lastPosTime_.elapsed() < QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { - velocityY = velocityY_; - velocityX = velocityX_; - } - int flickTimeY = 0; - int flickTimeX = 0; - int flickPixelsX = 0; - int flickPixelsY = 0; - if (qAbs(velocityY) > MinimumFlickVelocity && qAbs(sceneCenter_.y() - sceneStartPoint1_.y()) > FlickThreshold) { - // calculate Y flick animation values - qreal acceleration = pan_.deceleration_; - if ((velocityY > 0.0f) == (pan_.deceleration_ > 0.0f)) - acceleration = acceleration * -1.0f; - flickTimeY = static_cast<int>(-1000 * velocityY / acceleration); - flickPixelsY = (flickTimeY * velocityY) / (1000.0 * 2); - } - if (qAbs(velocityX) > MinimumFlickVelocity && qAbs(sceneCenter_.x() - sceneStartPoint1_.x()) > FlickThreshold) { - // calculate X flick animation values - qreal acceleration = pan_.deceleration_; - if ((velocityX > 0.0f) == (pan_.deceleration_ > 0.0f)) - acceleration = acceleration * -1.0f; - flickTimeX = static_cast<int>(-1000 * velocityX / acceleration); - flickPixelsX = (flickTimeX * velocityX) / (1000.0 * 2); - } - int flickTime = qMax(flickTimeY, flickTimeX); - if (flickTime > 0) { - startFlick(flickPixelsX, flickPixelsY, flickTime); - return true; - } - return false; -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::startFlick(int dx, int dy, int timeMs) -{ - if (timeMs < 0) - return; - - QGeoCoordinate animationStartCoordinate = map_->mapController()->center(); - - if (pan_.animation_->state() == QPropertyAnimation::Running) - pan_.animation_->stop(); - QGeoCoordinate animationEndCoordinate = map_->mapController()->center(); - pan_.animation_->setDuration(timeMs); - animationEndCoordinate.setLongitude(animationStartCoordinate.longitude() - (dx / pow(2.0, map_->mapController()->zoom()))); - animationEndCoordinate.setLatitude(animationStartCoordinate.latitude() + (dy / pow(2.0, map_->mapController()->zoom()))); - pan_.animation_->setStartValue(QVariant::fromValue(animationStartCoordinate)); - pan_.animation_->setEndValue(QVariant::fromValue(animationEndCoordinate)); - pan_.animation_->start(); - emit flickStarted(); -} - -void QDeclarativeGeoMapGestureArea::stopPan() -{ - velocityX_ = 0; - velocityY_ = 0; - if (panState_ == panFlick) { - endFlick(); - } else if (panState_ == panActive) { - panState_ = panInactive; - emit panFinished(); - emit panActiveChanged(); - map_->prefetchData(); - } -} - -/*! - \internal -*/ -void QDeclarativeGeoMapGestureArea::endFlick() -{ - emit panFinished(); - if (pan_.animation_->state() == QPropertyAnimation::Running) - pan_.animation_->stop(); - emit flickFinished(); - panState_ = panInactive; - emit panActiveChanged(); - map_->prefetchData(); -} - - - - - -#include "moc_qdeclarativegeomapgesturearea_p.cpp" - -QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapitembase.cpp b/src/imports/location/qdeclarativegeomapitembase.cpp index e76c11b0..cde00abf 100644 --- a/src/imports/location/qdeclarativegeomapitembase.cpp +++ b/src/imports/location/qdeclarativegeomapitembase.cpp @@ -39,6 +39,7 @@ #include <QtQml/QQmlInfo> #include <QtQuick/QSGOpacityNode> #include <QtQuick/private/qquickmousearea_p.h> +#include <QtQuick/private/qquickitem_p.h> QT_BEGIN_NAMESPACE @@ -248,6 +249,17 @@ QSGNode *QDeclarativeGeoMapItemBase::updateMapItemPaintNode(QSGNode *oldNode, Up return 0; } +bool QDeclarativeGeoMapItemBase::isPolishScheduled() const +{ + return QQuickItemPrivate::get(this)->polishScheduled; +} + +void QDeclarativeGeoMapItemBase::polishAndUpdate() +{ + polish(); + update(); +} + #include "moc_qdeclarativegeomapitembase_p.cpp" diff --git a/src/imports/location/qdeclarativegeomapitembase_p.h b/src/imports/location/qdeclarativegeomapitembase_p.h index 2ca22821..c7793fbd 100644 --- a/src/imports/location/qdeclarativegeomapitembase_p.h +++ b/src/imports/location/qdeclarativegeomapitembase_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOMAPITEMBASE_H #define QDECLARATIVEGEOMAPITEMBASE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtQuick/QQuickItem> #include "qdeclarativegeomap_p.h" @@ -78,13 +89,14 @@ public: virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *); protected Q_SLOTS: - virtual void updateMapItem() = 0; virtual void afterChildrenChanged(); virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) = 0; + void polishAndUpdate(); protected: float zoomLevelOpacity() const; bool childMouseEventFilter(QQuickItem *item, QEvent *event); + bool isPolishScheduled() const; private Q_SLOTS: void baseCameraDataChanged(const QGeoCameraData &camera); @@ -95,6 +107,8 @@ private: QSizeF lastSize_; QGeoCameraData lastCameraData_; + + friend class QDeclarativeGeoMap; }; QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapitemview.cpp b/src/imports/location/qdeclarativegeomapitemview.cpp index 0ad69dcf..eff03b17 100644 --- a/src/imports/location/qdeclarativegeomapitemview.cpp +++ b/src/imports/location/qdeclarativegeomapitemview.cpp @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2015 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -37,9 +39,11 @@ #include "qdeclarativegeomapitemview_p.h" #include "qdeclarativegeomap_p.h" #include "qdeclarativegeomapitembase_p.h" +#include "mapitemviewdelegateincubator.h" #include <QtCore/QAbstractItemModel> #include <QtQml/QQmlContext> +#include <QtQml/QQmlIncubator> #include <QtQml/private/qqmlopenmetaobject_p.h> QT_BEGIN_NAMESPACE @@ -71,13 +75,15 @@ QT_BEGIN_NAMESPACE QDeclarativeGeoMapItemView::QDeclarativeGeoMapItemView(QQuickItem *parent) : QObject(parent), componentCompleted_(false), delegate_(0), - itemModel_(0), map_(0), fitViewport_(false) + itemModel_(0), map_(0), fitViewport_(false), m_metaObjectType(0) { } QDeclarativeGeoMapItemView::~QDeclarativeGeoMapItemView() { removeInstantiatedItems(); + if (m_metaObjectType) + m_metaObjectType->release(); } /*! @@ -88,6 +94,49 @@ void QDeclarativeGeoMapItemView::componentComplete() componentCompleted_ = true; } +void QDeclarativeGeoMapItemView::incubatorStatusChanged(MapItemViewDelegateIncubator *incubator, + QQmlIncubator::Status status) +{ + if (status == QQmlIncubator::Loading) + return; + + for (int i = 0; i < m_itemData.length(); ++i) { + ItemData *itemData = m_itemData.at(i); + if (itemData->incubator != incubator) + continue; + + switch (status) { + case QQmlIncubator::Ready: + itemData->item = qobject_cast<QDeclarativeGeoMapItemBase *>(incubator->object()); + if (!itemData->item) { + qWarning() << "QDeclarativeGeoMapItemView map item delegate is of unsupported type."; + delete incubator->object(); + } else { + map_->addMapItem(itemData->item); + if (fitViewport_) + fitViewport(); + } + delete itemData->incubator; + itemData->incubator = 0; + break; + case QQmlIncubator::Null: + // Should never get here + delete itemData->incubator; + itemData->incubator = 0; + break; + case QQmlIncubator::Error: + qWarning() << "QDeclarativeGeoMapItemView map item creation failed."; + delete itemData->incubator; + itemData->incubator = 0; + break; + default: + ; + } + + break; + } +} + /*! \qmlproperty model QtLocation::MapItemView::model @@ -111,6 +160,14 @@ void QDeclarativeGeoMapItemView::setModel(const QVariant &model) this, SLOT(itemModelRowsRemoved(QModelIndex,int,int))); disconnect(itemModel_, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(itemModelRowsInserted(QModelIndex,int,int))); + disconnect(itemModel_, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), + this, SLOT(itemModelRowsMoved(QModelIndex,int,int,QModelIndex,int))); + disconnect(itemModel_, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), + this, SLOT(itemModelDataChanged(QModelIndex,QModelIndex,QVector<int>))); + + removeInstantiatedItems(); + m_metaObjectType->release(); + m_metaObjectType = 0; itemModel_ = 0; } @@ -122,9 +179,18 @@ void QDeclarativeGeoMapItemView::setModel(const QVariant &model) this, SLOT(itemModelRowsRemoved(QModelIndex,int,int))); connect(itemModel_, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(itemModelRowsInserted(QModelIndex,int,int))); + connect(itemModel_, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), + this, SLOT(itemModelRowsMoved(QModelIndex,int,int,QModelIndex,int))); + connect(itemModel_, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), + this, SLOT(itemModelDataChanged(QModelIndex,QModelIndex,QVector<int>))); + + m_metaObjectType = new QQmlOpenMetaObjectType(&QObject::staticMetaObject, 0); + foreach (const QByteArray &name, itemModel_->roleNames()) + m_metaObjectType->createProperty(name); + + instantiateAllItems(); } - repopulate(); emit modelChanged(); } @@ -146,15 +212,11 @@ void QDeclarativeGeoMapItemView::itemModelRowsInserted(const QModelIndex &index, if (!componentCompleted_ || !map_ || !delegate_ || !itemModel_) return; - QDeclarativeGeoMapItemBase *mapItem; for (int i = start; i <= end; ++i) { - mapItem = createItemFromItemModel(i); - if (!mapItem) { - break; - } - mapItemList_.append(mapItem); - map_->addMapItem(mapItem); + const QModelIndex insertedIndex = itemModel_->index(i, 0, index); + createItemForIndex(insertedIndex); } + if (fitViewport_) fitViewport(); } @@ -170,17 +232,56 @@ void QDeclarativeGeoMapItemView::itemModelRowsRemoved(const QModelIndex &index, return; for (int i = end; i >= start; --i) { - QDeclarativeGeoMapItemBase *mapItem = mapItemList_.takeAt(i); - Q_ASSERT(mapItem); - if (!mapItem) // bad + ItemData *itemData = m_itemData.takeAt(i); + if (!itemData) break; - map_->removeMapItem(mapItem); - mapItem->deleteLater(); + + map_->removeMapItem(itemData->item); + delete itemData; } + if (fitViewport_) fitViewport(); } +void QDeclarativeGeoMapItemView::itemModelRowsMoved(const QModelIndex &parent, int start, int end, + const QModelIndex &destination, int row) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + Q_UNUSED(destination) + Q_UNUSED(row) + + qWarning() << "QDeclarativeGeoMapItemView does not support models that move rows."; +} + +void QDeclarativeGeoMapItemView::itemModelDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector<int> &roles) +{ + Q_UNUSED(roles) + + for (int i = topLeft.row(); i <= bottomRight.row(); ++i) { + const QModelIndex index = itemModel_->index(i, 0); + ItemData *itemData = m_itemData.at(i); + + QHashIterator<int, QByteArray> iterator(itemModel_->roleNames()); + while (iterator.hasNext()) { + iterator.next(); + + QVariant modelData = itemModel_->data(index, iterator.key()); + if (!modelData.isValid()) + continue; + + itemData->context->setContextProperty(QString::fromLatin1(iterator.value().constData()), + modelData); + + itemData->modelDataMeta->setValue(iterator.value(), modelData); + } + } +} + /*! \qmlproperty Component QtLocation::MapItemView::delegate @@ -254,87 +355,87 @@ void QDeclarativeGeoMapItemView::removeInstantiatedItems() { if (!map_) return; - foreach (QDeclarativeGeoMapItemBase *mapItem, mapItemList_) { - mapItem->deleteLater(); - map_->removeMapItem(mapItem); + + foreach (ItemData *itemData, m_itemData) { + map_->removeMapItem(itemData->item); + delete itemData; } - mapItemList_.clear(); + m_itemData.clear(); } /*! \internal - Removes and repopulates all items. + + Instantiates all items. */ -void QDeclarativeGeoMapItemView::repopulate() +void QDeclarativeGeoMapItemView::instantiateAllItems() { - // Free any earlier instances - removeInstantiatedItems(); - if (!componentCompleted_ || !map_ || !delegate_ || !itemModel_) return; - // Iterate model data and instantiate delegates. for (int i = 0; i < itemModel_->rowCount(); ++i) { - QDeclarativeGeoMapItemBase *mapItem = createItemFromItemModel(i); - Q_ASSERT(mapItem); - if (!mapItem) // bad - break; - mapItemList_.append(mapItem); - map_->addMapItem(mapItem); + const QModelIndex index = itemModel_->index(i, 0); + createItemForIndex(index); } + if (fitViewport_) fitViewport(); } /*! \internal + Removes and repopulates all items. +*/ +void QDeclarativeGeoMapItemView::repopulate() +{ + removeInstantiatedItems(); + instantiateAllItems(); +} + +/*! + \internal */ -QDeclarativeGeoMapItemBase *QDeclarativeGeoMapItemView::createItemFromItemModel(int modelRow) +void QDeclarativeGeoMapItemView::createItemForIndex(const QModelIndex &index) { - if (!delegate_ || !itemModel_) - return 0; + // Expected to be already tested by caller. + Q_ASSERT(delegate_); + Q_ASSERT(itemModel_); - QModelIndex index = itemModel_->index(modelRow, 0); // column 0 - if (!index.isValid()) { - qWarning() << "QDeclarativeGeoMapItemView Index is not valid: " << modelRow; - return 0; - } + ItemData *itemData = new ItemData; - QObject *model = new QObject(this); - QQmlOpenMetaObject *modelMetaObject = new QQmlOpenMetaObject(model); + itemData->modelData = new QObject; + itemData->modelDataMeta = new QQmlOpenMetaObject(itemData->modelData, m_metaObjectType, false); + itemData->context = new QQmlContext(qmlContext(this)); QHashIterator<int, QByteArray> iterator(itemModel_->roleNames()); - QQmlContext *itemContext = new QQmlContext(qmlContext(this)); while (iterator.hasNext()) { iterator.next(); + QVariant modelData = itemModel_->data(index, iterator.key()); if (!modelData.isValid()) continue; - itemContext->setContextProperty(QString::fromLatin1(iterator.value().constData()), - modelData); + itemData->context->setContextProperty(QString::fromLatin1(iterator.value().constData()), + modelData); - modelMetaObject->setValue(iterator.value(), modelData); + itemData->modelDataMeta->setValue(iterator.value(), modelData); } - itemContext->setContextProperty(QStringLiteral("model"), model); - itemContext->setContextProperty(QStringLiteral("index"), modelRow); - QObject *obj = delegate_->create(itemContext); + itemData->context->setContextProperty(QLatin1String("model"), itemData->modelData); + itemData->context->setContextProperty(QLatin1String("index"), index.row()); - if (!obj) { - qWarning() << "QDeclarativeGeoMapItemView map item creation failed."; - delete itemContext; - return 0; - } - QDeclarativeGeoMapItemBase *declMapObj = qobject_cast<QDeclarativeGeoMapItemBase *>(obj); - if (!declMapObj) { - qWarning() << "QDeclarativeGeoMapItemView map item delegate is of unsupported type."; - delete itemContext; - return 0; - } - itemContext->setParent(declMapObj); - model->setParent(declMapObj); - return declMapObj; + itemData->incubator = new MapItemViewDelegateIncubator(this); + delegate_->create(*itemData->incubator, itemData->context); + + m_itemData.insert(index.row(), itemData); +} + +QDeclarativeGeoMapItemView::ItemData::~ItemData() +{ + delete incubator; + delete item; + delete context; + delete modelData; } #include "moc_qdeclarativegeomapitemview_p.cpp" diff --git a/src/imports/location/qdeclarativegeomapitemview_p.h b/src/imports/location/qdeclarativegeomapitemview_p.h index b39a47f0..004e3fb9 100644 --- a/src/imports/location/qdeclarativegeomapitemview_p.h +++ b/src/imports/location/qdeclarativegeomapitemview_p.h @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2015 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -37,8 +39,20 @@ #ifndef QDECLARATIVEGEOMAPITEMVIEW_H #define QDECLARATIVEGEOMAPITEMVIEW_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QModelIndex> #include <QtQml/QQmlParserStatus> +#include <QtQml/QQmlIncubator> #include <QtQml/qqml.h> QT_BEGIN_NAMESPACE @@ -48,6 +62,9 @@ class QQmlComponent; class QQuickItem; class QDeclarativeGeoMap; class QDeclarativeGeoMapItemBase; +class QQmlOpenMetaObject; +class QQmlOpenMetaObjectType; +class MapItemViewDelegateIncubator; class QDeclarativeGeoMapItemView : public QObject, public QQmlParserStatus { @@ -75,6 +92,7 @@ public: void setMap(QDeclarativeGeoMap *); void repopulate(); void removeInstantiatedItems(); + void instantiateAllItems(); qreal zValue(); void setZValue(qreal zValue); @@ -88,25 +106,53 @@ Q_SIGNALS: void delegateChanged(); void autoFitViewportChanged(); -private: - QDeclarativeGeoMapItemBase *createItemFromItemModel(int modelRow); - - void fitViewport(); +protected: + void incubatorStatusChanged(MapItemViewDelegateIncubator *incubator, + QQmlIncubator::Status status); private Q_SLOTS: void itemModelReset(); void itemModelRowsInserted(const QModelIndex &index, int start, int end); void itemModelRowsRemoved(const QModelIndex &index, int start, int end); + void itemModelRowsMoved(const QModelIndex &parent, int start, int end, + const QModelIndex &destination, int row); + void itemModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector<int> &roles); private: + struct ItemData { + ItemData() + : incubator(0), item(0), context(0), modelData(0), modelDataMeta(0) + { + } + + ~ItemData(); + + MapItemViewDelegateIncubator *incubator; + QDeclarativeGeoMapItemBase *item; + QQmlContext *context; + QObject *modelData; + QQmlOpenMetaObject *modelDataMeta; + }; + + void createItemForIndex(const QModelIndex &index); + void fitViewport(); + bool componentCompleted_; QQmlComponent *delegate_; QAbstractItemModel *itemModel_; QDeclarativeGeoMap *map_; - QList<QDeclarativeGeoMapItemBase *> mapItemList_; + QVector<ItemData *> m_itemData; bool fitViewport_; + + QQmlOpenMetaObjectType *m_metaObjectType; + + friend class QTypeInfo<ItemData>; + friend class MapItemViewDelegateIncubator; }; +Q_DECLARE_TYPEINFO(QDeclarativeGeoMapItemView::ItemData, Q_MOVABLE_TYPE); + QT_END_NAMESPACE QML_DECLARE_TYPE(QDeclarativeGeoMapItemView) diff --git a/src/imports/location/qdeclarativegeomapquickitem.cpp b/src/imports/location/qdeclarativegeomapquickitem.cpp index 81f88dac..ca67b183 100644 --- a/src/imports/location/qdeclarativegeomapquickitem.cpp +++ b/src/imports/location/qdeclarativegeomapquickitem.cpp @@ -146,8 +146,7 @@ void QDeclarativeGeoMapQuickItem::setCoordinate(const QGeoCoordinate &coordinate coordinate_ = coordinate; - updateMapItem(); - + polishAndUpdate(); emit coordinateChanged(); } @@ -158,10 +157,11 @@ void QDeclarativeGeoMapQuickItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap * { QDeclarativeGeoMapItemBase::setMap(quickMap,map); if (map && quickMap) { - QObject::connect(quickMap, SIGNAL(heightChanged()), this, SLOT(updateMapItem())); - QObject::connect(quickMap, SIGNAL(widthChanged()), this, SLOT(updateMapItem())); - QObject::connect(map, SIGNAL(cameraDataChanged(QGeoCameraData)), this, SLOT(updateMapItem())); - updateMapItem(); + connect(quickMap, SIGNAL(heightChanged()), this, SLOT(polishAndUpdate())); + connect(quickMap, SIGNAL(widthChanged()), this, SLOT(polishAndUpdate())); + connect(map, SIGNAL(cameraDataChanged(QGeoCameraData)), + this, SLOT(polishAndUpdate())); + polishAndUpdate(); } } @@ -203,8 +203,7 @@ void QDeclarativeGeoMapQuickItem::setSourceItem(QQuickItem *sourceItem) return; sourceItem_ = sourceItem; - updateMapItem(); - + polishAndUpdate(); emit sourceItemChanged(); } @@ -249,7 +248,7 @@ void QDeclarativeGeoMapQuickItem::setAnchorPoint(const QPointF &anchorPoint) if (anchorPoint == anchorPoint_) return; anchorPoint_ = anchorPoint; - updateMapItem(); + polishAndUpdate(); emit anchorPointChanged(); } @@ -281,7 +280,7 @@ void QDeclarativeGeoMapQuickItem::setZoomLevel(qreal zoomLevel) if (zoomLevel == zoomLevel_) return; zoomLevel_ = zoomLevel; - updateMapItem(); + polishAndUpdate(); emit zoomLevelChanged(); } @@ -293,7 +292,7 @@ qreal QDeclarativeGeoMapQuickItem::zoomLevel() const /*! \internal */ -void QDeclarativeGeoMapQuickItem::updateMapItem() +void QDeclarativeGeoMapQuickItem::updatePolish() { if (!quickMap() && sourceItem_) { mapAndSourceItemSet_ = false; @@ -311,13 +310,13 @@ void QDeclarativeGeoMapQuickItem::updateMapItem() sourceItem_.data()->setParentItem(opacityContainer_); sourceItem_.data()->setTransformOrigin(QQuickItem::TopLeft); connect(sourceItem_.data(), SIGNAL(xChanged()), - this, SLOT(updateMapItem())); + this, SLOT(polishAndUpdate())); connect(sourceItem_.data(), SIGNAL(yChanged()), - this, SLOT(updateMapItem())); + this, SLOT(polishAndUpdate())); connect(sourceItem_.data(), SIGNAL(widthChanged()), - this, SLOT(updateMapItem())); + this, SLOT(polishAndUpdate())); connect(sourceItem_.data(), SIGNAL(heightChanged()), - this, SLOT(updateMapItem())); + this, SLOT(polishAndUpdate())); } QScopedValueRollback<bool> rollback(updatingGeometry_); @@ -330,7 +329,6 @@ void QDeclarativeGeoMapQuickItem::updateMapItem() setWidth(sourceItem_.data()->width()); setHeight(sourceItem_.data()->height()); setPositionOnMap(coordinate(), scaleFactor() * anchorPoint_); - update(); } /*! diff --git a/src/imports/location/qdeclarativegeomapquickitem_p.h b/src/imports/location/qdeclarativegeomapquickitem_p.h index 2be5457c..0410f060 100644 --- a/src/imports/location/qdeclarativegeomapquickitem_p.h +++ b/src/imports/location/qdeclarativegeomapquickitem_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOMAPQUICKITEM_H #define QDECLARATIVEGEOMAPQUICKITEM_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtQuick/QQuickItem> #include <QtQuick/QSGNode> @@ -79,9 +90,9 @@ Q_SIGNALS: protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; protected Q_SLOTS: - virtual void updateMapItem() Q_DECL_OVERRIDE; virtual void afterChildrenChanged() Q_DECL_OVERRIDE; virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; diff --git a/src/imports/location/qdeclarativegeomaptype_p.h b/src/imports/location/qdeclarativegeomaptype_p.h index 903b6aac..980c594a 100644 --- a/src/imports/location/qdeclarativegeomaptype_p.h +++ b/src/imports/location/qdeclarativegeomaptype_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOMAPTYPE_H #define QDECLARATIVEGEOMAPTYPE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtQml/qqml.h> #include <QtLocation/private/qgeomaptype_p.h> diff --git a/src/imports/location/qdeclarativegeoroute_p.h b/src/imports/location/qdeclarativegeoroute_p.h index 42fa6789..9bb46087 100644 --- a/src/imports/location/qdeclarativegeoroute_p.h +++ b/src/imports/location/qdeclarativegeoroute_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOROUTE_H #define QDECLARATIVEGEOROUTE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeoroutesegment_p.h" #include <QtCore/QObject> diff --git a/src/imports/location/qdeclarativegeoroutemodel.cpp b/src/imports/location/qdeclarativegeoroutemodel.cpp index b59e6b8e..0c64c23a 100644 --- a/src/imports/location/qdeclarativegeoroutemodel.cpp +++ b/src/imports/location/qdeclarativegeoroutemodel.cpp @@ -169,8 +169,7 @@ void QDeclarativeGeoRouteModel::reset() } abortRequest(); - setErrorString(QString()); - setError(NoError); + setError(NoError, QString()); setStatus(QDeclarativeGeoRouteModel::Null); } @@ -183,8 +182,7 @@ void QDeclarativeGeoRouteModel::reset() void QDeclarativeGeoRouteModel::cancel() { abortRequest(); - setErrorString(QString()); - setError(NoError); + setError(NoError, QString()); setStatus(routes_.isEmpty() ? Null : Ready); } @@ -214,8 +212,7 @@ void QDeclarativeGeoRouteModel::abortRequest() QDeclarativeGeoRoute *QDeclarativeGeoRouteModel::get(int index) { if (index < 0 || index >= routes_.count()) { - qmlInfo(this) << QStringLiteral("Error, invalid index for get():") - << index; + qmlInfo(this) << QStringLiteral("Index '%1' out of range").arg(index); return 0; } return routes_.at(index); @@ -308,11 +305,31 @@ void QDeclarativeGeoRouteModel::pluginReady() { QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); QGeoRoutingManager *routingManager = serviceProvider->routingManager(); - if (!routingManager || serviceProvider->error() != QGeoServiceProvider::NoError) { - qmlInfo(this) << QStringLiteral("Error: Plugin does not support routing.\nError message:") - << serviceProvider->errorString(); + + if (serviceProvider->error() != QGeoServiceProvider::NoError) { + QDeclarativeGeoRouteModel::RouteError newError = UnknownError; + switch (serviceProvider->error()) { + case QGeoServiceProvider::NotSupportedError: + newError = EngineNotSetError; break; + case QGeoServiceProvider::UnknownParameterError: + newError = UnknownParameterError; break; + case QGeoServiceProvider::MissingRequiredParameterError: + newError = MissingRequiredParameterError; break; + case QGeoServiceProvider::ConnectionError: + newError = CommunicationError; break; + default: + break; + } + + setError(newError, serviceProvider->errorString()); + return; + } + + if (!routingManager) { + setError(EngineNotSetError, tr("Plugin does not support routing.")); return; } + connect(routingManager, SIGNAL(finished(QGeoRouteReply*)), this, SLOT(routingFinished(QGeoRouteReply*))); connect(routingManager, SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString)), @@ -420,20 +437,16 @@ bool QDeclarativeGeoRouteModel::autoUpdate() const */ void QDeclarativeGeoRouteModel::setMeasurementSystem(QLocale::MeasurementSystem ms) { - if (!plugin_) { - qmlInfo(this) << ROUTE_PLUGIN_NOT_SET; + if (!plugin_) return; - } QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); if (!serviceProvider) return; QGeoRoutingManager *routingManager = serviceProvider->routingManager(); - if (!routingManager) { - qmlInfo(this) << ROUTE_MGR_NOT_SET; + if (!routingManager) return; - } if (routingManager->measurementSystem() == ms) return; @@ -457,7 +470,6 @@ QLocale::MeasurementSystem QDeclarativeGeoRouteModel::measurementSystem() const QGeoRoutingManager *routingManager = serviceProvider->routingManager(); if (!routingManager) { - qmlInfo(this) << ROUTE_MGR_NOT_SET; if (plugin_->locales().isEmpty()) return QLocale().measurementSystem(); @@ -500,20 +512,6 @@ QDeclarativeGeoRouteModel::Status QDeclarativeGeoRouteModel::status() const } /*! - \internal -*/ -void QDeclarativeGeoRouteModel::setErrorString(const QString &error) -{ - if (errorString_ == error) - return; - - errorString_ = error; - - if (complete_) - emit errorStringChanged(); -} - -/*! \qmlproperty string QtLocation::RouteModel::errorString This read-only property holds the textual presentation of the latest routing error. @@ -534,12 +532,16 @@ QString QDeclarativeGeoRouteModel::errorString() const This read-only property holds the latest error value of the routing request. \list - \li RouteModel.NoError - No error has occurred - \li RouteModel.EngineNotSetError - The plugin/service provider used does not support routing - \li RouteModel.CommunicationError - An error occurred while communicating with the service provider - \li RouteModel.ParseError - The response from the service provider was in an unrecognizable format - \li RouteModel.UnsupportedOptionError - The requested operation or one of the options for the operation are not supported by the service provider. - \li RouteModel.UnknownError - An error occurred which does not fit into any of the other categories + \li RouteModel.NoError - No error has occurred. + \li RouteModel.CommunicationError - An error occurred while communicating with the service provider. + \li RouteModel.EngineNotSetError - The model's plugin property was not set or there is no routing manager associated with the plugin. + \li RouteModel.MissingRequiredParameterError - A required parameter was not specified. + \li RouteModel.ParseError - The response from the service provider was in an unrecognizable format. + \li RouteModel.UnknownError - An error occurred which does not fit into any of the other categories. + \li RouteModel.UnknownParameterError - The plugin did not recognize one of the parameters it was given. + \li RouteModel.UnsupportedOptionError - The requested operation is not supported by the routing provider. + This may happen when the loaded engine does not support a particular + type of routing request. \endlist */ @@ -548,11 +550,12 @@ QDeclarativeGeoRouteModel::RouteError QDeclarativeGeoRouteModel::error() const return error_; } -void QDeclarativeGeoRouteModel::setError(RouteError error) +void QDeclarativeGeoRouteModel::setError(RouteError error, const QString& errorString) { - if (error_ == error) + if (error_ == error && errorString_ == errorString) return; error_ = error; + errorString_ = errorString; emit errorChanged(); } @@ -569,7 +572,7 @@ void QDeclarativeGeoRouteModel::update() return; if (!plugin_) { - qmlInfo(this) << ROUTE_PLUGIN_NOT_SET; + setError(EngineNotSetError, tr("Cannot route, plugin not set.")); return; } @@ -579,22 +582,21 @@ void QDeclarativeGeoRouteModel::update() QGeoRoutingManager *routingManager = serviceProvider->routingManager(); if (!routingManager) { - qmlInfo(this) << ROUTE_MGR_NOT_SET; + setError(EngineNotSetError, tr("Cannot route, route manager not set.")); return; } if (!routeQuery_) { - qmlInfo(this) << QStringLiteral("Cannot route, valid query not set."); + setError(ParseError,"Cannot route, valid query not set."); return; } abortRequest(); // Clear previus requests QGeoRouteRequest request = routeQuery_->routeRequest(); if (request.waypoints().count() < 2) { - qmlInfo(this) << QStringLiteral("Not enough waypoints for routing."); + setError(ParseError,tr("Not enough waypoints for routing.")); return; } - setErrorString(""); // clear previous error string - setError(NoError); + setError(NoError, QString()); reply_ = routingManager->calculateRoute(request); setStatus(QDeclarativeGeoRouteModel::Loading); @@ -627,8 +629,7 @@ void QDeclarativeGeoRouteModel::routingFinished(QGeoRouteReply *reply) } endResetModel(); - setErrorString(""); - setError(NoError); + setError(NoError, QString()); setStatus(QDeclarativeGeoRouteModel::Ready); reply->deleteLater(); @@ -649,8 +650,7 @@ void QDeclarativeGeoRouteModel::routingError(QGeoRouteReply *reply, { if (reply != reply_) return; - setErrorString(errorString); - setError(static_cast<QDeclarativeGeoRouteModel::RouteError>(error)); + setError(static_cast<QDeclarativeGeoRouteModel::RouteError>(error), errorString); setStatus(QDeclarativeGeoRouteModel::Error); reply->deleteLater(); reply_ = 0; diff --git a/src/imports/location/qdeclarativegeoroutemodel_p.h b/src/imports/location/qdeclarativegeoroutemodel_p.h index c820aa52..66769ea7 100644 --- a/src/imports/location/qdeclarativegeoroutemodel_p.h +++ b/src/imports/location/qdeclarativegeoroutemodel_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOROUTEMODEL_H #define QDECLARATIVEGEOROUTEMODEL_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeoserviceprovider_p.h" #include <QtPositioning/QGeoCoordinate> @@ -70,7 +81,7 @@ class QDeclarativeGeoRouteModel : public QAbstractListModel, public QQmlParserSt Q_PROPERTY(int count READ count NOTIFY countChanged) Q_PROPERTY(bool autoUpdate READ autoUpdate WRITE setAutoUpdate NOTIFY autoUpdateChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) - Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) Q_PROPERTY(RouteError error READ error NOTIFY errorChanged) Q_PROPERTY(QLocale::MeasurementSystem measurementSystem READ measurementSystem WRITE setMeasurementSystem NOTIFY measurementSystemChanged) @@ -94,7 +105,12 @@ public: CommunicationError = QGeoRouteReply::CommunicationError, ParseError = QGeoRouteReply::ParseError, UnsupportedOptionError = QGeoRouteReply::UnsupportedOptionError, - UnknownError = QGeoRouteReply::UnknownError + UnknownError = QGeoRouteReply::UnknownError, + //we leave gap for future QGeoRouteReply errors + + //QGeoServiceProvider related errors start here + UnknownParameterError = 100, + MissingRequiredParameterError }; explicit QDeclarativeGeoRouteModel(QObject *parent = 0); @@ -136,8 +152,7 @@ Q_SIGNALS: void queryChanged(); void autoUpdateChanged(); void statusChanged(); - void errorStringChanged(); - void errorChanged(); + void errorChanged(); //emitted also for errorString notification void routesChanged(); void measurementSystemChanged(); @@ -154,8 +169,7 @@ private Q_SLOTS: private: void setStatus(Status status); - void setErrorString(const QString &error); - void setError(RouteError error); + void setError(RouteError error, const QString &errorString); void abortRequest(); bool complete_; diff --git a/src/imports/location/qdeclarativegeoroutesegment_p.h b/src/imports/location/qdeclarativegeoroutesegment_p.h index b02e8f2b..e6cf5aa5 100644 --- a/src/imports/location/qdeclarativegeoroutesegment_p.h +++ b/src/imports/location/qdeclarativegeoroutesegment_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEGEOROUTESEGMENT_H #define QDECLARATIVEGEOROUTESEGMENT_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeomaneuver_p.h" #include <QtCore/QObject> diff --git a/src/imports/location/qdeclarativegeoserviceprovider_p.h b/src/imports/location/qdeclarativegeoserviceprovider_p.h index 56529aa6..f7a2ee83 100644 --- a/src/imports/location/qdeclarativegeoserviceprovider_p.h +++ b/src/imports/location/qdeclarativegeoserviceprovider_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEQGEOSERVICEPROVIDER_H #define QDECLARATIVEQGEOSERVICEPROVIDER_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QMap> #include <QtCore/QString> #include <QtCore/QStringList> diff --git a/src/imports/location/qdeclarativepolygonmapitem.cpp b/src/imports/location/qdeclarativepolygonmapitem.cpp index 5b94d009..6fdef816 100644 --- a/src/imports/location/qdeclarativepolygonmapitem.cpp +++ b/src/imports/location/qdeclarativepolygonmapitem.cpp @@ -332,7 +332,7 @@ QDeclarativePolygonMapItem::QDeclarativePolygonMapItem(QQuickItem *parent) void QDeclarativePolygonMapItem::handleBorderUpdated() { borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); } QDeclarativePolygonMapItem::~QDeclarativePolygonMapItem() @@ -367,7 +367,7 @@ void QDeclarativePolygonMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *m if (map) { geometry_.markSourceDirty(); borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); } } @@ -423,7 +423,7 @@ void QDeclarativePolygonMapItem::setPath(const QJSValue &value) geometry_.markSourceDirty(); borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); emit pathChanged(); } @@ -441,38 +441,31 @@ void QDeclarativePolygonMapItem::addCoordinate(const QGeoCoordinate &coordinate) geometry_.markSourceDirty(); borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); emit pathChanged(); } /*! \qmlmethod void MapPolygon::removeCoordinate(coordinate) - Removes a coordinate from the path. If there are multiple instances of the + Removes \a coordinate from the path. If there are multiple instances of the same coordinate, the one added last is removed. - \sa addCoordinate, path + If \a coordinate is not in the path this method does nothing. + \sa addCoordinate, path */ - void QDeclarativePolygonMapItem::removeCoordinate(const QGeoCoordinate &coordinate) { int index = path_.lastIndexOf(coordinate); - - if (index == -1) { - qmlInfo(this) << COORD_NOT_BELONG_TO << QStringLiteral("PolygonMapItem"); + if (index == -1) return; - } - if (path_.count() < index + 1) { - qmlInfo(this) << COORD_NOT_BELONG_TO << QStringLiteral("PolygonMapItem"); - return; - } path_.removeAt(index); geometry_.markSourceDirty(); borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); emit pathChanged(); } @@ -496,7 +489,7 @@ void QDeclarativePolygonMapItem::setColor(const QColor &color) color_ = color; dirtyMaterial_ = true; - updateMapItem(); + update(); emit colorChanged(color_); } @@ -526,7 +519,7 @@ QSGNode *QDeclarativePolygonMapItem::updateMapItemPaintNode(QSGNode *oldNode, Up /*! \internal */ -void QDeclarativePolygonMapItem::updateMapItem() +void QDeclarativePolygonMapItem::updatePolish() { if (!map() || path_.count() == 0) return; @@ -553,7 +546,6 @@ void QDeclarativePolygonMapItem::updateMapItem() setHeight(combined.height()); setPositionOnMap(path_.at(0), -1 * geometry_.sourceBoundingBox().topLeft()); - update(); } /*! @@ -589,7 +581,7 @@ void QDeclarativePolygonMapItem::afterViewportChanged(const QGeoMapViewportChang borderGeometry_.setPreserveGeometry(true, borderGeometry_.geoLeftBound()); geometry_.markScreenDirty(); borderGeometry_.markScreenDirty(); - updateMapItem(); + polishAndUpdate(); } /*! @@ -646,7 +638,7 @@ void QDeclarativePolygonMapItem::geometryChanged(const QRectF &newGeometry, cons borderGeometry_.setPreserveGeometry(true, leftBoundCoord); geometry_.markSourceDirty(); borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); emit pathChanged(); } diff --git a/src/imports/location/qdeclarativepolygonmapitem_p.h b/src/imports/location/qdeclarativepolygonmapitem_p.h index 38249354..8b803b1d 100644 --- a/src/imports/location/qdeclarativepolygonmapitem_p.h +++ b/src/imports/location/qdeclarativepolygonmapitem_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPOLYGONMAPITEM #define QDECLARATIVEPOLYGONMAPITEM +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeomapitembase_p.h" #include "qdeclarativepolylinemapitem_p.h" #include "qgeomapitemgeometry_p.h" @@ -100,9 +111,9 @@ Q_SIGNALS: protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; protected Q_SLOTS: - virtual void updateMapItem() Q_DECL_OVERRIDE; void handleBorderUpdated(); virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; diff --git a/src/imports/location/qdeclarativepolylinemapitem.cpp b/src/imports/location/qdeclarativepolylinemapitem.cpp index f39c6f53..f2373abf 100644 --- a/src/imports/location/qdeclarativepolylinemapitem.cpp +++ b/src/imports/location/qdeclarativepolylinemapitem.cpp @@ -199,6 +199,7 @@ void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map, QDoubleVector2D origin, lastPoint, lastAddedPoint; + const double mapWidthHalf = map.width()/2.0; double unwrapBelowX = 0; if (preserveGeometry_) unwrapBelowX = map.coordinateToItemPosition(geoLeftBound_, false).x(); @@ -219,7 +220,8 @@ void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map, // unwrap x to preserve geometry if moved to border of map if (preserveGeometry_ && point.x() < unwrapBelowX && !qFuzzyCompare(geoLeftBound_.longitude(), coord.longitude()) - && !qFuzzyCompare(point.x(), unwrapBelowX)) + && !qFuzzyCompare(point.x(), unwrapBelowX) + && !qFuzzyCompare(mapWidthHalf, point.x())) point.setX(unwrapBelowX + geoDistanceToScreenWidth(map, geoLeftBound_, coord)); if (!foundValid) { @@ -472,7 +474,7 @@ void QDeclarativePolylineMapItem::updateAfterLinePropertiesChanged() { // mark dirty just in case we're a width change geometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); } /*! @@ -483,7 +485,7 @@ void QDeclarativePolylineMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap * QDeclarativeGeoMapItemBase::setMap(quickMap,map); if (map) { geometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); } } @@ -534,7 +536,6 @@ void QDeclarativePolylineMapItem::setPath(const QJSValue &value) setPathFromGeoList(pathList); } - /*! \internal */ @@ -546,53 +547,155 @@ void QDeclarativePolylineMapItem::setPathFromGeoList(const QList<QGeoCoordinate> path_ = path; geometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); emit pathChanged(); } /*! - \qmlmethod void MapPolyline::addCoordinate(coordinate) + \qmlmethod int MapPolyline::pathLength() + + Returns the number of coordinates of the polyline. - Adds a coordinate to the path. + \since Qt Location 5.6 - \sa removeCoordinate, path + \sa path */ +int QDeclarativePolylineMapItem::pathLength() const +{ + return path_.size(); +} + +/*! + \qmlmethod void MapPolyline::addCoordinate(coordinate) + + Adds a coordinate to the end of the path. + \sa insertCoordinate, removeCoordinate, path +*/ void QDeclarativePolylineMapItem::addCoordinate(const QGeoCoordinate &coordinate) { path_.append(coordinate); geometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod void MapPolyline::insertCoordinate(index, coordinate) + + Inserts a \a coordinate to the path at the given \a index. + + \since Qt Location 5.6 + + \sa addCoordinate, removeCoordinate, path +*/ +void QDeclarativePolylineMapItem::insertCoordinate(int index, const QGeoCoordinate &coordinate) +{ + if (index < 0 || index > path_.size()) + return; + + path_.insert(index, coordinate); + + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod void MapPolyline::replaceCoordinate(index, coordinate) + + Replaces the coordinate in the current path at the given \a index + with the new \a coordinate. + + \since Qt Location 5.6 + + \sa addCoordinate, insertCoordinate, removeCoordinate, path +*/ +void QDeclarativePolylineMapItem::replaceCoordinate(int index, const QGeoCoordinate &coordinate) +{ + if (index < 0 || index >= path_.size()) + return; + + path_[index] = coordinate; + + geometry_.markSourceDirty(); + polishAndUpdate(); emit pathChanged(); } /*! + \qmlmethod coordinate MapPolyline::coordinateAt(index) + + Gets the coordinate of the polyline at the given \a index. + If the index is outside the path's bounds then an invalid + coordinate is returned. + + \since Qt Location 5.6 +*/ +QGeoCoordinate QDeclarativePolylineMapItem::coordinateAt(int index) const +{ + if (index < 0 || index >= path_.size()) + return QGeoCoordinate(); + + return path_.at(index); +} + +/*! + \qmlmethod coordinate MapPolyline::containsCoordinate(coordinate) + + Returns true if the given \a coordinate is part of the path. + + \since Qt Location 5.6 +*/ +bool QDeclarativePolylineMapItem::containsCoordinate(const QGeoCoordinate &coordinate) +{ + return path_.indexOf(coordinate) > -1; +} + +/*! \qmlmethod void MapPolyline::removeCoordinate(coordinate) - Removes a coordinate from the path. If there are multiple instances of the + Removes \a coordinate from the path. If there are multiple instances of the same coordinate, the one added last is removed. - \sa addCoordinate, path -*/ + If \a coordinate is not in the path this method does nothing. + \sa addCoordinate, insertCoordinate, path +*/ void QDeclarativePolylineMapItem::removeCoordinate(const QGeoCoordinate &coordinate) { int index = path_.lastIndexOf(coordinate); - - if (index == -1) { - qmlInfo(this) << COORD_NOT_BELONG_TO << QStringLiteral("PolylineMapItem"); + if (index == -1) return; - } - if (path_.count() < index + 1) { - qmlInfo(this) << COORD_NOT_BELONG_TO << QStringLiteral("PolylineMapItem"); + path_.removeAt(index); + + geometry_.markSourceDirty(); + polishAndUpdate(); + emit pathChanged(); +} + +/*! + \qmlmethod void MapPolyline::removeCoordinate(index) + + Removes a coordinate from the path at the given \a index. + + If \a index is invalid then this method does nothing. + + \since Qt Location 5.6 + + \sa addCoordinate, insertCoordinate, path +*/ +void QDeclarativePolylineMapItem::removeCoordinate(int index) +{ + if (index < 0 || index >= path_.size()) return; - } + path_.removeAt(index); geometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); emit pathChanged(); } @@ -658,7 +761,7 @@ void QDeclarativePolylineMapItem::geometryChanged(const QRectF &newGeometry, con + newCoordinate.longitude() - firstLongitude)); geometry_.setPreserveGeometry(true, leftBoundCoord); geometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); emit pathChanged(); } @@ -694,13 +797,13 @@ void QDeclarativePolylineMapItem::afterViewportChanged(const QGeoMapViewportChan } geometry_.setPreserveGeometry(true, geometry_.geoLeftBound()); geometry_.markScreenDirty(); - updateMapItem(); + polishAndUpdate(); } /*! \internal */ -void QDeclarativePolylineMapItem::updateMapItem() +void QDeclarativePolylineMapItem::updatePolish() { if (!map() || path_.count() == 0) return; @@ -715,7 +818,6 @@ void QDeclarativePolylineMapItem::updateMapItem() setHeight(geometry_.sourceBoundingBox().height()); setPositionOnMap(path_.at(0), -1 * geometry_.sourceBoundingBox().topLeft()); - update(); } /*! @@ -732,7 +834,7 @@ QSGNode *QDeclarativePolylineMapItem::updateMapItemPaintNode(QSGNode *oldNode, U } //TODO: update only material - if (geometry_.isScreenDirty() || dirtyMaterial_) { + if (geometry_.isScreenDirty() || dirtyMaterial_ || !oldNode) { node->update(line_.color(), &geometry_); geometry_.setPreserveGeometry(false); geometry_.markClean(); @@ -743,9 +845,10 @@ QSGNode *QDeclarativePolylineMapItem::updateMapItemPaintNode(QSGNode *oldNode, U bool QDeclarativePolylineMapItem::contains(const QPointF &point) const { + QVector<QPointF> vertices = geometry_.vertices(); QPolygonF tri; - for (int i = 0; i < geometry_.vertices().size(); ++i) { - tri << geometry_.vertices()[i]; + for (int i = 0; i < vertices.size(); ++i) { + tri << vertices[i]; if (tri.size() == 3) { if (tri.containsPoint(point,Qt::OddEvenFill)) return true; diff --git a/src/imports/location/qdeclarativepolylinemapitem_p.h b/src/imports/location/qdeclarativepolylinemapitem_p.h index 8822f49d..298dc3bc 100644 --- a/src/imports/location/qdeclarativepolylinemapitem_p.h +++ b/src/imports/location/qdeclarativepolylinemapitem_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEPOLYLINEMAPITEM #define QDECLARATIVEPOLYLINEMAPITEM +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeomapitembase_p.h" #include "qgeomapitemgeometry_p.h" @@ -105,8 +116,14 @@ public: //from QuickItem virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE; + Q_INVOKABLE int pathLength() const; Q_INVOKABLE void addCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void insertCoordinate(int index, const QGeoCoordinate &coordinate); + Q_INVOKABLE void replaceCoordinate(int index, const QGeoCoordinate &coordinate); + Q_INVOKABLE QGeoCoordinate coordinateAt(int index) const; + Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate &coordinate); Q_INVOKABLE void removeCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void removeCoordinate(int index); QJSValue path() const; virtual void setPath(const QJSValue &value); @@ -121,9 +138,9 @@ Q_SIGNALS: protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; void setPathFromGeoList(const QList<QGeoCoordinate> &path); + void updatePolish() Q_DECL_OVERRIDE; protected Q_SLOTS: - virtual void updateMapItem() Q_DECL_OVERRIDE; void updateAfterLinePropertiesChanged(); virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; diff --git a/src/imports/location/qdeclarativerectanglemapitem.cpp b/src/imports/location/qdeclarativerectanglemapitem.cpp index 2dbb630b..c28bcf3e 100644 --- a/src/imports/location/qdeclarativerectanglemapitem.cpp +++ b/src/imports/location/qdeclarativerectanglemapitem.cpp @@ -177,9 +177,9 @@ QDeclarativeRectangleMapItem::QDeclarativeRectangleMapItem(QQuickItem *parent) { setFlag(ItemHasContents, true); QObject::connect(&border_, SIGNAL(colorChanged(QColor)), - this, SLOT(updateMapItemAssumeDirty())); + this, SLOT(markSourceDirtyAndUpdate())); QObject::connect(&border_, SIGNAL(widthChanged(qreal)), - this, SLOT(updateMapItemAssumeDirty())); + this, SLOT(markSourceDirtyAndUpdate())); } QDeclarativeRectangleMapItem::~QDeclarativeRectangleMapItem() @@ -192,11 +192,8 @@ QDeclarativeRectangleMapItem::~QDeclarativeRectangleMapItem() void QDeclarativeRectangleMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *map) { QDeclarativeGeoMapItemBase::setMap(quickMap,map); - if (map) { - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - updateMapItem(); - } + if (map) + markSourceDirtyAndUpdate(); } /*! @@ -229,9 +226,7 @@ void QDeclarativeRectangleMapItem::setTopLeft(const QGeoCoordinate &topLeft) topLeft_ = topLeft; - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - updateMapItem(); + markSourceDirtyAndUpdate(); emit topLeftChanged(topLeft_); } @@ -243,11 +238,11 @@ QGeoCoordinate QDeclarativeRectangleMapItem::topLeft() /*! \internal */ -void QDeclarativeRectangleMapItem::updateMapItemAssumeDirty() +void QDeclarativeRectangleMapItem::markSourceDirtyAndUpdate() { geometry_.markSourceDirty(); borderGeometry_.markSourceDirty(); - updateMapItem(); + polishAndUpdate(); } /*! @@ -263,9 +258,7 @@ void QDeclarativeRectangleMapItem::setBottomRight(const QGeoCoordinate &bottomRi bottomRight_ = bottomRight; - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - updateMapItem(); + markSourceDirtyAndUpdate(); emit bottomRightChanged(bottomRight_); } @@ -291,7 +284,7 @@ void QDeclarativeRectangleMapItem::setColor(const QColor &color) return; color_ = color; dirtyMaterial_ = true; - updateMapItem(); + polishAndUpdate(); emit colorChanged(color_); } @@ -333,7 +326,7 @@ QSGNode *QDeclarativeRectangleMapItem::updateMapItemPaintNode(QSGNode *oldNode, /*! \internal */ -void QDeclarativeRectangleMapItem::updateMapItem() +void QDeclarativeRectangleMapItem::updatePolish() { if (!map() || !topLeft().isValid() || !bottomRight().isValid()) return; @@ -368,7 +361,6 @@ void QDeclarativeRectangleMapItem::updateMapItem() } setPositionOnMap(pathClosed.at(0), geometry_.firstPointOffset()); - update(); } /*! @@ -404,7 +396,7 @@ void QDeclarativeRectangleMapItem::afterViewportChanged(const QGeoMapViewportCha borderGeometry_.setPreserveGeometry(true, borderGeometry_.geoLeftBound()); geometry_.markScreenDirty(); borderGeometry_.markScreenDirty(); - updateMapItem(); + polishAndUpdate(); } /*! @@ -448,9 +440,7 @@ void QDeclarativeRectangleMapItem::geometryChanged(const QRectF &newGeometry, co bottomRight_ = newBottomRight; geometry_.setPreserveGeometry(true, newTopLeft); borderGeometry_.setPreserveGeometry(true, newTopLeft); - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - updateMapItem(); + markSourceDirtyAndUpdate(); emit topLeftChanged(topLeft_); emit bottomRightChanged(bottomRight_); } diff --git a/src/imports/location/qdeclarativerectanglemapitem_p.h b/src/imports/location/qdeclarativerectanglemapitem_p.h index 6046c190..fb9936b0 100644 --- a/src/imports/location/qdeclarativerectanglemapitem_p.h +++ b/src/imports/location/qdeclarativerectanglemapitem_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVERECTANGLEMAPITEM_H_ #define QDECLARATIVERECTANGLEMAPITEM_H_ +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeomapitembase_p.h" #include "qgeomapitemgeometry_p.h" #include "qdeclarativepolylinemapitem_p.h" @@ -94,10 +105,10 @@ Q_SIGNALS: protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; + void updatePolish() Q_DECL_OVERRIDE; protected Q_SLOTS: - virtual void updateMapItem() Q_DECL_OVERRIDE; - void updateMapItemAssumeDirty(); + void markSourceDirtyAndUpdate(); virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) Q_DECL_OVERRIDE; private: diff --git a/src/imports/location/qdeclarativeroutemapitem.cpp b/src/imports/location/qdeclarativeroutemapitem.cpp index 78485cc0..19930cc3 100644 --- a/src/imports/location/qdeclarativeroutemapitem.cpp +++ b/src/imports/location/qdeclarativeroutemapitem.cpp @@ -119,12 +119,19 @@ void QDeclarativeRouteMapItem::setRoute(QDeclarativeGeoRoute *route) route_ = route; + connect(route_, SIGNAL(pathChanged()), this, SLOT(updateRoutePath())); + if (route_) setPathFromGeoList(route_->routePath()); emit routeChanged(route_); } +void QDeclarativeRouteMapItem::updateRoutePath() +{ + setPathFromGeoList(route_->routePath()); +} + /*! \internal void QDeclarativeRouteMapItem::setPath(const QJSValue &value) diff --git a/src/imports/location/qdeclarativeroutemapitem_p.h b/src/imports/location/qdeclarativeroutemapitem_p.h index 5ba9f071..3acac3cc 100644 --- a/src/imports/location/qdeclarativeroutemapitem_p.h +++ b/src/imports/location/qdeclarativeroutemapitem_p.h @@ -37,6 +37,17 @@ #ifndef QDECLARATIVEROUTEMAPITEM_H_ #define QDECLARATIVEROUTEMAPITEM_H_ +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativegeomapitembase_p.h" #include "qdeclarativegeomap_p.h" #include "qdeclarativepolylinemapitem_p.h" @@ -63,6 +74,9 @@ public: Q_SIGNALS: void routeChanged(const QDeclarativeGeoRoute *route); +private slots: + void updateRoutePath(); + protected: void setPath(const QJSValue &value) Q_DECL_OVERRIDE; diff --git a/src/imports/location/qgeomapitemgeometry_p.h b/src/imports/location/qgeomapitemgeometry_p.h index eac90042..36b670f9 100644 --- a/src/imports/location/qgeomapitemgeometry_p.h +++ b/src/imports/location/qgeomapitemgeometry_p.h @@ -37,6 +37,17 @@ #ifndef QGEOMAPITEMGEOMETRY_H #define QGEOMAPITEMGEOMETRY_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QPainterPath> #include <QPointF> #include <QRectF> diff --git a/src/imports/location/qquickgeomapgesturearea.cpp b/src/imports/location/qquickgeomapgesturearea.cpp new file mode 100644 index 00000000..70dffc19 --- /dev/null +++ b/src/imports/location/qquickgeomapgesturearea.cpp @@ -0,0 +1,1278 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickgeomapgesturearea_p.h" +#include "qdeclarativegeomap_p.h" +#include "qgeomapcontroller_p.h" +#include "error_messages.h" + +#include <QtGui/QGuiApplication> +#include <QtGui/qevent.h> +#include <QtGui/QWheelEvent> +#include <QtGui/QStyleHints> +#include <QtQml/qqmlinfo.h> +#include <QtQuick/QQuickWindow> +#include <QPropertyAnimation> +#include <QDebug> +#include <QtPositioning/private/qgeoprojection_p.h> +#include "math.h" +#include "qgeomap_p.h" +#include "qdoublevector2d_p.h" + +#define QML_MAP_FLICK_DEFAULTMAXVELOCITY 2500 +#define QML_MAP_FLICK_MINIMUMDECELERATION 500 +#define QML_MAP_FLICK_DEFAULTDECELERATION 2500 +#define QML_MAP_FLICK_MAXIMUMDECELERATION 10000 + +#define QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD 50 +// FlickThreshold determines how far the "mouse" must have moved +// before we perform a flick. +static const int FlickThreshold = 20; +// Really slow flicks can be annoying. +const qreal MinimumFlickVelocity = 75.0; + +QT_BEGIN_NAMESPACE + + +/*! + \qmltype MapPinchEvent + \instantiates QGeoMapPinchEvent + \inqmlmodule QtLocation + + \brief MapPinchEvent type provides basic information about pinch event. + + MapPinchEvent type provides basic information about pinch event. They are + present in handlers of MapPinch (for example pinchStarted/pinchUpdated). Events are only + guaranteed to be valid for the duration of the handler. + + Except for the \l accepted property, all properties are read-only. + + \section2 Example Usage + + The following example enables the pinch gesture on a map and reacts to the + finished event. + + \code + Map { + id: map + gesture.enabled: true + gesture.onPinchFinished:{ + var coordinate1 = map.toCoordinate(gesture.point1) + var coordinate2 = map.toCoordinate(gesture.point2) + console.log("Pinch started at:") + console.log(" Points (" + gesture.point1.x + ", " + gesture.point1.y + ") - (" + gesture.point2.x + ", " + gesture.point2.y + ")") + console.log(" Coordinates (" + coordinate1.latitude + ", " + coordinate1.longitude + ") - (" + coordinate2.latitude + ", " + coordinate2.longitude + ")") + } + } + \endcode + + \ingroup qml-QtLocation5-maps + \since Qt Location 5.0 +*/ + +/*! + \qmlproperty QPoint QtLocation::MapPinchEvent::center + + This read-only property holds the current center point. +*/ + +/*! + \qmlproperty real QtLocation::MapPinchEvent::angle + + This read-only property holds the current angle between the two points in + the range -180 to 180. Positive values for the angles mean counter-clockwise + while negative values mean the clockwise direction. Zero degrees is at the + 3 o'clock position. +*/ + +/*! + \qmlproperty QPoint QtLocation::MapPinchEvent::point1 + \qmlproperty QPoint QtLocation::MapPinchEvent::point2 + + These read-only properties hold the actual touch points generating the pinch. + The points are not in any particular order. +*/ + +/*! + \qmlproperty int QtLocation::MapPinchEvent::pointCount + + This read-only property holds the number of points currently touched. + The MapPinch will not react until two touch points have initiated a gesture, + but will remain active until all touch points have been released. +*/ + +/*! + \qmlproperty bool QtLocation::MapPinchEvent::accepted + + Setting this property to false in the \c MapPinch::onPinchStarted handler + will result in no further pinch events being generated, and the gesture + ignored. +*/ + +/*! + \qmltype MapGestureArea + \instantiates QQuickGeoMapGestureArea + + \inqmlmodule QtLocation + + \brief The MapGestureArea type provides Map gesture interaction. + + MapGestureArea objects are used as part of a Map, to provide for panning, + flicking and pinch-to-zoom gesture used on touch displays. + + A MapGestureArea is automatically created with a new Map and available with + the \l{Map::gesture}{gesture} property. This is the only way + to create a MapGestureArea, and once created this way cannot be destroyed + without its parent Map. + + The two most commonly used properties of the MapGestureArea are the \l enabled + and \l acceptedGestures properties. Both of these must be set before a + MapGestureArea will have any effect upon interaction with the Map. + The \l flickDeceleration property controls how quickly the map pan slows after contact + is released while panning the map. + + \section2 Performance + + The MapGestureArea, when enabled, must process all incoming touch events in + order to track the shape and size of the "pinch". The overhead added on + touch events can be considered constant time. + + \section2 Example Usage + + The following example enables the pinch and pan gestures on the map, but not flicking. So the + map scrolling will halt immediately on releasing the mouse button / touch. + + \code + Map { + gesture.enabled: true + gesture.acceptedGestures: MapGestureArea.PinchGesture | MapGestureArea.PanGesture + } + \endcode + + \ingroup qml-QtLocation5-maps + \since Qt Location 5.0 +*/ + +/*! + \qmlproperty bool QtLocation::MapGestureArea::enabled + + This property holds whether the gestures are enabled. +*/ + +/*! + \qmlproperty bool QtLocation::MapGestureArea::pinchActive + + This read-only property holds whether pinch gesture is active. +*/ + +/*! + \qmlproperty bool QtLocation::MapGestureArea::panActive + + This read-only property holds whether pan gesture is active. + + \note Change notifications for this property were introduced in Qt 5.5. +*/ + +/*! + \qmlproperty real QtLocation::MapGestureArea::maximumZoomLevelChange + + This property holds the maximum zoom level change per pinch, essentially + meant to be used for setting the zoom sensitivity. + + It is an indicative measure calculated from the dimensions of the + map area, roughly corresponding how much zoom level could change with + maximum pinch zoom. Default value is 4.0, maximum value is 10.0 +*/ + +/*! + \qmlproperty real MapGestureArea::flickDeceleration + + This property holds the rate at which a flick will decelerate. + + The default value is 2500. +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::pinchStarted(PinchEvent event) + + This signal is emitted when a pinch gesture is started. + + The corresponding handler is \c onPinchStarted. + + \sa pinchUpdated, pinchFinished +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::pinchUpdated(PinchEvent event) + + This signal is emitted as the user's fingers move across the map, + after the \l pinchStarted signal is emitted. + + The corresponding handler is \c onPinchUpdated. + + \sa pinchStarted, pinchFinished +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::pinchFinished(PinchEvent event) + + This signal is emitted at the end of a pinch gesture. + + The corresponding handler is \c onPinchFinished. + + \sa pinchStarted, pinchUpdated +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::panStarted() + + This signal is emitted when the map begins to move due to user + interaction. Typically this means that the user is dragging a finger - + or a mouse with one of more mouse buttons pressed - on the map. + + The corresponding handler is \c onPanStarted. +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::panFinished() + + This signal is emitted when the map stops moving due to user + interaction. If a flick was generated, this signal is + emitted before flick starts. If a flick was not + generated, this signal is emitted when the + user stops dragging - that is a mouse or touch release. + + The corresponding handler is \c onPanFinished. + +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::flickStarted() + + This signal is emitted when the map is flicked. A flick + starts from the point where the mouse or touch was released, + while still in motion. + + The corresponding handler is \c onFlichStarted. +*/ + +/*! + \qmlsignal QtLocation::MapGestureArea::flickFinished() + + This signal is emitted when the map stops moving due to a flick. + + The corresponding handler is \c onFlickFinished. +*/ + +QQuickGeoMapGestureArea::QQuickGeoMapGestureArea(QDeclarativeGeoMap *map) + : QQuickItem(map), + m_map(0), + m_declarativeMap(map), + m_enabled(true), + m_acceptedGestures(PinchGesture | PanGesture | FlickGesture), + m_preventStealing(false), + m_panEnabled(true) +{ + m_flick.m_enabled = true, + m_flick.m_maxVelocity = QML_MAP_FLICK_DEFAULTMAXVELOCITY; + m_flick.m_deceleration = QML_MAP_FLICK_DEFAULTDECELERATION; + m_flick.m_animation = 0; + m_touchPointState = touchPoints0; + m_pinchState = pinchInactive; + m_flickState = flickInactive; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setMap(QGeoMap *map) +{ + if (m_map || !map) + return; + + m_map = map; + m_flick.m_animation = new QQuickGeoCoordinateAnimation(this); + m_flick.m_animation->setTargetObject(m_map->mapController()); + m_flick.m_animation->setProperty(QStringLiteral("center")); + m_flick.m_animation->setEasing(QEasingCurve(QEasingCurve::OutQuad)); + connect(m_flick.m_animation, &QQuickAbstractAnimation::stopped, this, &QQuickGeoMapGestureArea::handleFlickAnimationStopped); +} + +/*! + \qmlproperty bool QtQuick::MapGestureArea::preventStealing + This property holds whether the mouse events may be stolen from this + MapGestureArea. + + If a Map is placed within an item that filters child mouse + and touch events, such as Flickable, the mouse and touch events + may be stolen from the MapGestureArea if a gesture is recognized + by the parent item, e.g. a flick gesture. If preventStealing is + set to true, no item will steal the mouse and touch events. + + Note that setting preventStealing to true once an item has started + stealing events will have no effect until the next press event. + + By default this property is false. +*/ + +bool QQuickGeoMapGestureArea::preventStealing() const +{ + return m_preventStealing; +} + +void QQuickGeoMapGestureArea::setPreventStealing(bool prevent) +{ + if (prevent != m_preventStealing) { + m_preventStealing = prevent; + m_declarativeMap->setKeepMouseGrab(m_preventStealing && m_enabled); + m_declarativeMap->setKeepTouchGrab(m_preventStealing && m_enabled); + emit preventStealingChanged(); + } +} + +QQuickGeoMapGestureArea::~QQuickGeoMapGestureArea() +{ +} + +/*! + \qmlproperty enumeration QtLocation::MapGestureArea::acceptedGestures + + This property holds the gestures that will be active. By default + the zoom, pan and flick gestures are enabled. + + \list + \li MapGestureArea.NoGesture - Don't support any additional gestures (value: 0x0000). + \li MapGestureArea.PinchGesture - Support the map pinch gesture (value: 0x0001). + \li MapGestureArea.PanGesture - Support the map pan gesture (value: 0x0002). + \li MapGestureArea.FlickGesture - Support the map flick gesture (value: 0x0004). + \endlist +*/ + +QQuickGeoMapGestureArea::AcceptedGestures QQuickGeoMapGestureArea::acceptedGestures() const +{ + return m_acceptedGestures; +} + + +void QQuickGeoMapGestureArea::setAcceptedGestures(AcceptedGestures acceptedGestures) +{ + if (acceptedGestures == m_acceptedGestures) + return; + m_acceptedGestures = acceptedGestures; + + setPanEnabled(acceptedGestures & GeoMapGesture::PanGesture); + setFlickEnabled(acceptedGestures & GeoMapGesture::FlickGesture); + setPinchEnabled(acceptedGestures & GeoMapGesture::PinchGesture); + + emit acceptedGesturesChanged(); +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::isPinchActive() const +{ + return m_pinchState == pinchActive; +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::isPanActive() const +{ + return m_flickState == panActive || m_flickState == flickActive; +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::enabled() const +{ + return m_enabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setEnabled(bool enabled) +{ + if (enabled == m_enabled) + return; + m_enabled = enabled; + + if (enabled) { + setPanEnabled(m_acceptedGestures & GeoMapGesture::PanGesture); + setFlickEnabled(m_acceptedGestures & GeoMapGesture::FlickGesture); + setPinchEnabled(m_acceptedGestures & GeoMapGesture::PinchGesture); + } else { + setPanEnabled(false); + setFlickEnabled(false); + setPinchEnabled(false); + } + + emit enabledChanged(); +} + + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::pinchEnabled() const +{ + return m_pinch.m_enabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setPinchEnabled(bool enabled) +{ + if (enabled == m_pinch.m_enabled) + return; + m_pinch.m_enabled = enabled; +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::panEnabled() const +{ + return m_panEnabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setPanEnabled(bool enabled) +{ + if (enabled == m_flick.m_enabled) + return; + m_panEnabled = enabled; + + // unlike the pinch, the pan existing functionality is to stop immediately + if (!enabled) + stopPan(); +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::flickEnabled() const +{ + return m_flick.m_enabled; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setFlickEnabled(bool enabled) +{ + if (enabled == m_flick.m_enabled) + return; + m_flick.m_enabled = enabled; + // unlike the pinch, the flick existing functionality is to stop immediately + if (!enabled) { + stopFlick(); + } +} + +/*! + \internal + Used internally to set the minimum zoom level of the gesture area. + The caller is responsible to only send values that are valid + for the map plugin. Negative values are ignored. + */ +void QQuickGeoMapGestureArea::setMinimumZoomLevel(qreal min) +{ + if (min >= 0) + m_pinch.m_zoom.m_minimum = min; +} + +/*! + \internal + */ +qreal QQuickGeoMapGestureArea::minimumZoomLevel() const +{ + return m_pinch.m_zoom.m_minimum; +} + +/*! + \internal + Used internally to set the maximum zoom level of the gesture area. + The caller is responsible to only send values that are valid + for the map plugin. Negative values are ignored. + */ +void QQuickGeoMapGestureArea::setMaximumZoomLevel(qreal max) +{ + if (max >= 0) + m_pinch.m_zoom.m_maximum = max; +} + +/*! + \internal + */ +qreal QQuickGeoMapGestureArea::maximumZoomLevel() const +{ + return m_pinch.m_zoom.m_maximum; +} + +/*! + \internal +*/ +qreal QQuickGeoMapGestureArea::maximumZoomLevelChange() const +{ + return m_pinch.m_zoom.maximumChange; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setMaximumZoomLevelChange(qreal maxChange) +{ + if (maxChange == m_pinch.m_zoom.maximumChange || maxChange < 0.1 || maxChange > 10.0) + return; + m_pinch.m_zoom.maximumChange = maxChange; + emit maximumZoomLevelChangeChanged(); +} + +/*! + \internal +*/ +qreal QQuickGeoMapGestureArea::flickDeceleration() const +{ + return m_flick.m_deceleration; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::setFlickDeceleration(qreal deceleration) +{ + if (deceleration < QML_MAP_FLICK_MINIMUMDECELERATION) + deceleration = QML_MAP_FLICK_MINIMUMDECELERATION; + else if (deceleration > QML_MAP_FLICK_MAXIMUMDECELERATION) + deceleration = QML_MAP_FLICK_MAXIMUMDECELERATION; + if (deceleration == m_flick.m_deceleration) + return; + m_flick.m_deceleration = deceleration; + emit flickDecelerationChanged(); +} + +/*! + \internal +*/ +QTouchEvent::TouchPoint* createTouchPointFromMouseEvent(QMouseEvent *event, Qt::TouchPointState state) +{ + // this is only partially filled. But since it is only partially used it works + // more robust would be to store a list of QPointFs rather than TouchPoints + QTouchEvent::TouchPoint* newPoint = new QTouchEvent::TouchPoint(); + newPoint->setPos(event->localPos()); + newPoint->setScenePos(event->windowPos()); + newPoint->setScreenPos(event->screenPos()); + newPoint->setState(state); + newPoint->setId(0); + return newPoint; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event) +{ + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointPressed)); + if (m_touchPoints.isEmpty()) update(); + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event) +{ + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointMoved)); + if (m_touchPoints.isEmpty()) update(); + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *event) +{ + if (!m_mousePoint.isNull()) { + //this looks super ugly , however is required in case we do not get synthesized MouseReleaseEvent + //and we reset the point already in handleTouchUngrabEvent + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointReleased)); + if (m_touchPoints.isEmpty()) update(); + } + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleMouseUngrabEvent() +{ + + if (m_touchPoints.isEmpty() && !m_mousePoint.isNull()) { + m_mousePoint.reset(); + update(); + } else { + m_mousePoint.reset(); + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleTouchUngrabEvent() +{ + m_touchPoints.clear(); + //this is needed since in some cases mouse release is not delivered + //(second touch point brakes mouse synthesized events) + m_mousePoint.reset(); + update(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::handleTouchEvent(QTouchEvent *event) +{ + m_touchPoints.clear(); + for (int i = 0; i < event->touchPoints().count(); ++i) + m_touchPoints << event->touchPoints().at(i); + if (event->touchPoints().count() >= 2) + event->accept(); + else + event->ignore(); + update(); +} + +void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) +{ + if (!m_map) + return; + + QGeoCoordinate wheelGeoPos = m_map->itemPositionToCoordinate(QDoubleVector2D(event->posF()), false); + QPointF preZoomPoint = m_map->coordinateToItemPosition(wheelGeoPos, false).toPointF(); + + m_declarativeMap->setZoomLevel(qBound(minimumZoomLevel(), m_declarativeMap->zoomLevel() + event->angleDelta().y() * qreal(0.001), maximumZoomLevel())); + + QPointF postZoomPoint = m_map->coordinateToItemPosition(wheelGeoPos, false).toPointF(); + + if (preZoomPoint != postZoomPoint) + { + qreal dx = postZoomPoint.x() - preZoomPoint.x(); + qreal dy = postZoomPoint.y() - preZoomPoint.y(); + QPointF mapCenterPoint(m_map->width() / 2.0 + dx, m_map->height() / 2.0 + dy); + + QGeoCoordinate mapCenterCoordinate = m_map->itemPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false); + m_map->mapController()->setCenter(mapCenterCoordinate); + } + event->accept(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::clearTouchData() +{ + m_velocityX = 0; + m_velocityY = 0; + m_sceneCenter.setX(0); + m_sceneCenter.setY(0); + m_touchCenterCoord.setLongitude(0); + m_touchCenterCoord.setLatitude(0); + m_startCoord.setLongitude(0); + m_startCoord.setLatitude(0); +} + + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updateVelocityList(const QPointF &pos) +{ + // Take velocity samples every sufficient period of time, used later to determine the flick + // duration and speed (when mouse is released). + qreal elapsed = qreal(m_lastPosTime.elapsed()); + + if (elapsed >= QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { + elapsed /= 1000.; + int dyFromLastPos = pos.y() - m_lastPos.y(); + int dxFromLastPos = pos.x() - m_lastPos.x(); + m_lastPos = pos; + m_lastPosTime.restart(); + qreal velX = qreal(dxFromLastPos) / elapsed; + qreal velY = qreal(dyFromLastPos) / elapsed; + m_velocityX = qBound<qreal>(-m_flick.m_maxVelocity, velX, m_flick.m_maxVelocity); + m_velocityY = qBound<qreal>(-m_flick.m_maxVelocity, velY, m_flick.m_maxVelocity); + } +} + +/*! + \internal +*/ + +bool QQuickGeoMapGestureArea::isActive() const +{ + return isPanActive() || isPinchActive(); +} + +/*! + \internal +*/ +// simplify the gestures by using a state-machine format (easy to move to a future state machine) +void QQuickGeoMapGestureArea::update() +{ + if (!m_map) + return; + + // First state machine is for the number of touch points + + //combine touch with mouse event + m_allPoints.clear(); + m_allPoints << m_touchPoints; + if (m_allPoints.isEmpty() && !m_mousePoint.isNull()) + m_allPoints << *m_mousePoint.data(); + + touchPointStateMachine(); + + // Parallel state machine for pinch + if (isPinchActive() || (m_enabled && m_pinch.m_enabled && (m_acceptedGestures & (PinchGesture)))) + pinchStateMachine(); + + // Parallel state machine for pan (since you can pan at the same time as pinching) + // The stopPan function ensures that pan stops immediately when disabled, + // but the line below allows pan continue its current gesture if you disable + // the whole gesture (enabled_ flag), this keeps the enabled_ consistent with the pinch + if (isPanActive() || (m_enabled && m_flick.m_enabled && (m_acceptedGestures & (PanGesture | FlickGesture)))) + panStateMachine(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::touchPointStateMachine() +{ + // Transitions: + switch (m_touchPointState) { + case touchPoints0: + if (m_allPoints.count() == 1) { + clearTouchData(); + startOneTouchPoint(); + m_touchPointState = touchPoints1; + } else if (m_allPoints.count() >= 2) { + clearTouchData(); + startTwoTouchPoints(); + m_touchPointState = touchPoints2; + } + break; + case touchPoints1: + if (m_allPoints.count() == 0) { + m_touchPointState = touchPoints0; + } else if (m_allPoints.count() == 2) { + m_touchCenterCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneCenter), false); + startTwoTouchPoints(); + m_touchPointState = touchPoints2; + } + break; + case touchPoints2: + if (m_allPoints.count() == 0) { + m_touchPointState = touchPoints0; + } else if (m_allPoints.count() == 1) { + m_touchCenterCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneCenter), false); + startOneTouchPoint(); + m_touchPointState = touchPoints1; + } + break; + }; + + // Update + switch (m_touchPointState) { + case touchPoints0: + break; // do nothing if no touch points down + case touchPoints1: + updateOneTouchPoint(); + break; + case touchPoints2: + updateTwoTouchPoints(); + break; + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startOneTouchPoint() +{ + m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_lastPos = m_sceneStartPoint1; + m_lastPosTime.start(); + QGeoCoordinate startCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneStartPoint1), false); + // ensures a smooth transition for panning + m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - + m_touchCenterCoord.longitude()); + m_startCoord.setLatitude(m_startCoord.latitude() + startCoord.latitude() - + m_touchCenterCoord.latitude()); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updateOneTouchPoint() +{ + m_sceneCenter = mapFromScene(m_allPoints.at(0).scenePos()); + updateVelocityList(m_sceneCenter); +} + + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startTwoTouchPoints() +{ + m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_sceneStartPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + QPointF startPos = (m_sceneStartPoint1 + m_sceneStartPoint2) * 0.5; + m_lastPos = startPos; + m_lastPosTime.start(); + QGeoCoordinate startCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(startPos), false); + m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - + m_touchCenterCoord.longitude()); + m_startCoord.setLatitude(m_startCoord.latitude() + startCoord.latitude() - + m_touchCenterCoord.latitude()); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updateTwoTouchPoints() +{ + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + qreal dx = p1.x() - p2.x(); + qreal dy = p1.y() - p2.y(); + m_distanceBetweenTouchPoints = sqrt(dx * dx + dy * dy); + m_sceneCenter = (p1 + p2) / 2; + updateVelocityList(m_sceneCenter); + + m_twoTouchAngle = QLineF(p1, p2).angle(); + if (m_twoTouchAngle > 180) + m_twoTouchAngle -= 360; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::pinchStateMachine() +{ + PinchState lastState = m_pinchState; + // Transitions: + switch (m_pinchState) { + case pinchInactive: + if (m_allPoints.count() >= 2) { + if (canStartPinch()) { + m_declarativeMap->setKeepMouseGrab(true); + m_declarativeMap->setKeepTouchGrab(true); + startPinch(); + m_pinchState = pinchActive; + } else { + m_pinchState = pinchInactiveTwoPoints; + } + } + break; + case pinchInactiveTwoPoints: + if (m_allPoints.count() <= 1) { + m_pinchState = pinchInactive; + } else { + if (canStartPinch()) { + m_declarativeMap->setKeepMouseGrab(true); + m_declarativeMap->setKeepTouchGrab(true); + startPinch(); + m_pinchState = pinchActive; + } + } + break; + case pinchActive: + if (m_allPoints.count() <= 1) { + m_pinchState = pinchInactive; + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + m_declarativeMap->setKeepTouchGrab(m_preventStealing); + endPinch(); + } + break; + } + // This line implements an exclusive state machine, where the transitions and updates don't + // happen on the same frame + if (m_pinchState != lastState) { + emit pinchActiveChanged(); + return; + } + + // Update + switch (m_pinchState) { + case pinchInactive: + case pinchInactiveTwoPoints: + break; // do nothing + case pinchActive: + updatePinch(); + break; + } +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::canStartPinch() +{ + const int startDragDistance = qApp->styleHints()->startDragDistance(); + + if (m_allPoints.count() >= 2) { + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + if (qAbs(p1.x()-m_sceneStartPoint1.x()) > startDragDistance + || qAbs(p1.y()-m_sceneStartPoint1.y()) > startDragDistance + || qAbs(p2.x()-m_sceneStartPoint2.x()) > startDragDistance + || qAbs(p2.y()-m_sceneStartPoint2.y()) > startDragDistance) { + m_pinch.m_event.setCenter(mapFromScene(m_sceneCenter)); + m_pinch.m_event.setAngle(m_twoTouchAngle); + m_pinch.m_event.setPoint1(p1); + m_pinch.m_event.setPoint2(p2); + m_pinch.m_event.setPointCount(m_allPoints.count()); + m_pinch.m_event.setAccepted(true); + emit pinchStarted(&m_pinch.m_event); + return m_pinch.m_event.accepted(); + } + } + return false; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startPinch() +{ + m_pinch.m_startDist = m_distanceBetweenTouchPoints; + m_pinch.m_zoom.m_previous = m_declarativeMap->zoomLevel(); + m_pinch.m_lastAngle = m_twoTouchAngle; + + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + + m_pinch.m_zoom.m_start = m_declarativeMap->zoomLevel(); +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updatePinch() +{ + // Calculate the new zoom level if we have distance ( >= 2 touchpoints), otherwise stick with old. + qreal newZoomLevel = m_pinch.m_zoom.m_previous; + if (m_distanceBetweenTouchPoints) { + newZoomLevel = + // How much further/closer the current touchpoints are (in pixels) compared to pinch start + ((m_distanceBetweenTouchPoints - m_pinch.m_startDist) * + // How much one pixel corresponds in units of zoomlevel (and multiply by above delta) + (m_pinch.m_zoom.maximumChange / ((width() + height()) / 2))) + + // Add to starting zoom level. Sign of (dist-pinchstartdist) takes care of zoom in / out + m_pinch.m_zoom.m_start; + } + qreal da = m_pinch.m_lastAngle - m_twoTouchAngle; + if (da > 180) + da -= 360; + else if (da < -180) + da += 360; + m_pinch.m_event.setCenter(mapFromScene(m_sceneCenter)); + m_pinch.m_event.setAngle(m_twoTouchAngle); + + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_pinch.m_event.setPoint1(m_pinch.m_lastPoint1); + m_pinch.m_event.setPoint2(m_pinch.m_lastPoint2); + m_pinch.m_event.setPointCount(m_allPoints.count()); + m_pinch.m_event.setAccepted(true); + + m_pinch.m_lastAngle = m_twoTouchAngle; + emit pinchUpdated(&m_pinch.m_event); + + if (m_acceptedGestures & PinchGesture) { + // Take maximum and minimumzoomlevel into account + qreal perPinchMinimumZoomLevel = qMax(m_pinch.m_zoom.m_start - m_pinch.m_zoom.maximumChange, m_pinch.m_zoom.m_minimum); + qreal perPinchMaximumZoomLevel = qMin(m_pinch.m_zoom.m_start + m_pinch.m_zoom.maximumChange, m_pinch.m_zoom.m_maximum); + newZoomLevel = qMin(qMax(perPinchMinimumZoomLevel, newZoomLevel), perPinchMaximumZoomLevel); + m_declarativeMap->setZoomLevel(newZoomLevel); + m_pinch.m_zoom.m_previous = newZoomLevel; + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::endPinch() +{ + QPointF p1 = mapFromScene(m_pinch.m_lastPoint1); + QPointF p2 = mapFromScene(m_pinch.m_lastPoint2); + m_pinch.m_event.setCenter((p1 + p2) / 2); + m_pinch.m_event.setAngle(m_pinch.m_lastAngle); + m_pinch.m_event.setPoint1(p1); + m_pinch.m_event.setPoint2(p2); + m_pinch.m_event.setAccepted(true); + m_pinch.m_event.setPointCount(0); + emit pinchFinished(&m_pinch.m_event); + m_pinch.m_startDist = 0; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::panStateMachine() +{ + FlickState lastState = m_flickState; + + // Transitions + switch (m_flickState) { + case flickInactive: + if (canStartPan()) { + // Update startCoord_ to ensure smooth start for panning when going over startDragDistance + QGeoCoordinate newStartCoord = m_map->itemPositionToCoordinate(QDoubleVector2D(m_sceneCenter), false); + m_startCoord.setLongitude(newStartCoord.longitude()); + m_startCoord.setLatitude(newStartCoord.latitude()); + m_declarativeMap->setKeepMouseGrab(true); + m_flickState = panActive; + } + break; + case panActive: + if (m_allPoints.count() == 0) { + if (!tryStartFlick()) + { + m_flickState = flickInactive; + // mark as inactive for use by camera + if (m_pinchState == pinchInactive) { + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + m_map->prefetchData(); + } + emit panFinished(); + } else { + m_flickState = flickActive; + emit panFinished(); + emit flickStarted(); + } + } + break; + case flickActive: + if (m_allPoints.count() > 0) { // re touched before movement ended + stopFlick(); + m_declarativeMap->setKeepMouseGrab(true); + m_flickState = panActive; + } + break; + } + + if (m_flickState != lastState) + emit panActiveChanged(); + + // Update + switch (m_flickState) { + case flickInactive: // do nothing + break; + case panActive: + updatePan(); + // this ensures 'panStarted' occurs after the pan has actually started + if (lastState != panActive) + emit panStarted(); + break; + case flickActive: + break; + } +} +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::canStartPan() +{ + if (m_allPoints.count() == 0 || (m_acceptedGestures & PanGesture) == 0) + return false; + + // Check if thresholds for normal panning are met. + // (normal panning vs flicking: flicking will start from mouse release event). + const int startDragDistance = qApp->styleHints()->startDragDistance() * 2; + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); + int dyFromPress = int(p1.y() - m_sceneStartPoint1.y()); + int dxFromPress = int(p1.x() - m_sceneStartPoint1.x()); + if ((qAbs(dyFromPress) >= startDragDistance || qAbs(dxFromPress) >= startDragDistance)) + return true; + return false; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::updatePan() +{ + QPointF startPoint = m_map->coordinateToItemPosition(m_startCoord, false).toPointF(); + int dx = static_cast<int>(m_sceneCenter.x() - startPoint.x()); + int dy = static_cast<int>(m_sceneCenter.y() - startPoint.y()); + QPointF mapCenterPoint; + mapCenterPoint.setY(m_map->height() / 2.0 - dy); + mapCenterPoint.setX(m_map->width() / 2.0 - dx); + QGeoCoordinate animationStartCoordinate = m_map->itemPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false); + m_map->mapController()->setCenter(animationStartCoordinate); +} + +/*! + \internal +*/ +bool QQuickGeoMapGestureArea::tryStartFlick() +{ + if ((m_acceptedGestures & FlickGesture) == 0) + return false; + // if we drag then pause before release we should not cause a flick. + qreal velocityX = 0.0; + qreal velocityY = 0.0; + if (m_lastPosTime.elapsed() < QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { + velocityY = m_velocityY; + velocityX = m_velocityX; + } + int flickTimeY = 0; + int flickTimeX = 0; + int flickPixelsX = 0; + int flickPixelsY = 0; + if (qAbs(velocityY) > MinimumFlickVelocity && qAbs(m_sceneCenter.y() - m_sceneStartPoint1.y()) > FlickThreshold) { + // calculate Y flick animation values + qreal acceleration = m_flick.m_deceleration; + if ((velocityY > 0.0f) == (m_flick.m_deceleration > 0.0f)) + acceleration = acceleration * -1.0f; + flickTimeY = static_cast<int>(-1000 * velocityY / acceleration); + flickPixelsY = (flickTimeY * velocityY) / (1000.0 * 2); + } + if (qAbs(velocityX) > MinimumFlickVelocity && qAbs(m_sceneCenter.x() - m_sceneStartPoint1.x()) > FlickThreshold) { + // calculate X flick animation values + qreal acceleration = m_flick.m_deceleration; + if ((velocityX > 0.0f) == (m_flick.m_deceleration > 0.0f)) + acceleration = acceleration * -1.0f; + flickTimeX = static_cast<int>(-1000 * velocityX / acceleration); + flickPixelsX = (flickTimeX * velocityX) / (1000.0 * 2); + } + int flickTime = qMax(flickTimeY, flickTimeX); + if (flickTime > 0) { + startFlick(flickPixelsX, flickPixelsY, flickTime); + return true; + } + return false; +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::startFlick(int dx, int dy, int timeMs) +{ + if (timeMs < 0) + return; + + QGeoCoordinate animationStartCoordinate = m_map->mapController()->center(); + + if (m_flick.m_animation->isRunning()) + m_flick.m_animation->stop(); + QGeoCoordinate animationEndCoordinate = m_map->mapController()->center(); + m_flick.m_animation->setDuration(timeMs); + + double zoom = pow(2.0, m_map->mapController()->zoom()); + double longitude = animationStartCoordinate.longitude() - (dx / zoom); + double latitude = animationStartCoordinate.latitude() + (dy / zoom); + + if (dx > 0) + m_flick.m_animation->setDirection(QQuickGeoCoordinateAnimation::East); + else + m_flick.m_animation->setDirection(QQuickGeoCoordinateAnimation::West); + + //keep animation in correct bounds + if (latitude > 85.05113) + latitude = 85.05113; + else if (latitude < -85.05113) + latitude = -85.05113; + + animationEndCoordinate.setLongitude(longitude); + animationEndCoordinate.setLatitude(latitude); + + m_flick.m_animation->setFrom(animationStartCoordinate); + m_flick.m_animation->setTo(animationEndCoordinate); + m_flick.m_animation->start(); +} + +void QQuickGeoMapGestureArea::stopPan() +{ + if (m_flickState == flickActive) { + stopFlick(); + } else if (m_flickState == panActive) { + m_velocityX = 0; + m_velocityY = 0; + m_flickState = flickInactive; + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + emit panFinished(); + emit panActiveChanged(); + m_map->prefetchData(); + } +} + +/*! + \internal +*/ +void QQuickGeoMapGestureArea::stopFlick() +{ + m_velocityX = 0; + m_velocityY = 0; + if (m_flick.m_animation->isRunning()) + m_flick.m_animation->stop(); + else + handleFlickAnimationStopped(); +} + +void QQuickGeoMapGestureArea::handleFlickAnimationStopped() +{ + m_declarativeMap->setKeepMouseGrab(m_preventStealing); + if (m_flickState == flickActive) { + m_flickState = flickInactive; + emit flickFinished(); + m_map->prefetchData(); + } +} + +#include "moc_qquickgeomapgesturearea_p.cpp" + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapgesturearea_p.h b/src/imports/location/qquickgeomapgesturearea_p.h index d968cab6..cfd8738e 100644 --- a/src/imports/location/qdeclarativegeomapgesturearea_p.h +++ b/src/imports/location/qquickgeomapgesturearea_p.h @@ -34,16 +34,27 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVEGEOMAPGESTUREAREA_P_H -#define QDECLARATIVEGEOMAPGESTUREAREA_P_H - -#include <QtQml/qqml.h> +#ifndef QQUICKGEOMAPGESTUREAREA_P_H +#define QQUICKGEOMAPGESTUREAREA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuick/QQuickItem> #include <QTouchEvent> -#include <QObject> #include <QDebug> #include <QElapsedTimer> #include "qgeocoordinate.h" #include "qgeomap_p.h" +#include "qquickgeocoordinateanimation_p.h" QT_BEGIN_NAMESPACE @@ -52,10 +63,8 @@ class QDeclarativeGeoMap; class QTouchEvent; class QWheelEvent; class QGeoMap; -class QPropertyAnimation; -class QQuickItem; -class QDeclarativeGeoMapPinchEvent : public QObject +class QGeoMapPinchEvent : public QObject { Q_OBJECT @@ -67,71 +76,69 @@ class QDeclarativeGeoMapPinchEvent : public QObject Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) public: - QDeclarativeGeoMapPinchEvent(const QPointF ¢er, qreal angle, + QGeoMapPinchEvent(const QPointF ¢er, qreal angle, const QPointF &point1, const QPointF &point2, int pointCount = 0, bool accepted = true) - : QObject(), center_(center), angle_(angle), - point1_(point1), point2_(point2), - pointCount_(pointCount), accepted_(accepted) {} - QDeclarativeGeoMapPinchEvent() + : QObject(), m_center(center), m_angle(angle), + m_point1(point1), m_point2(point2), + m_pointCount(pointCount), m_accepted(accepted) {} + QGeoMapPinchEvent() : QObject(), - angle_(0.0), - pointCount_(0), - accepted_(true) {} - - QPointF center() const { return center_; } - void setCenter(const QPointF ¢er) { center_ = center; } - qreal angle() const { return angle_; } - void setAngle(qreal angle) { angle_ = angle; } - QPointF point1() const { return point1_; } - void setPoint1(const QPointF &p) { point1_ = p; } - QPointF point2() const { return point2_; } - void setPoint2(const QPointF &p) { point2_ = p; } - int pointCount() const { return pointCount_; } - void setPointCount(int count) { pointCount_ = count; } - bool accepted() const { return accepted_; } - void setAccepted(bool a) { accepted_ = a; } + m_angle(0.0), + m_pointCount(0), + m_accepted(true) {} + + QPointF center() const { return m_center; } + void setCenter(const QPointF ¢er) { m_center = center; } + qreal angle() const { return m_angle; } + void setAngle(qreal angle) { m_angle = angle; } + QPointF point1() const { return m_point1; } + void setPoint1(const QPointF &p) { m_point1 = p; } + QPointF point2() const { return m_point2; } + void setPoint2(const QPointF &p) { m_point2 = p; } + int pointCount() const { return m_pointCount; } + void setPointCount(int count) { m_pointCount = count; } + bool accepted() const { return m_accepted; } + void setAccepted(bool a) { m_accepted = a; } private: - QPointF center_; - qreal angle_; - QPointF point1_; - QPointF point2_; - int pointCount_; - bool accepted_; + QPointF m_center; + qreal m_angle; + QPointF m_point1; + QPointF m_point2; + int m_pointCount; + bool m_accepted; }; -// tbd: should we have a 'active' / 'moving' boolean attribute when pinch is active? - -// class QDeclarativeGeoMapGestureArea: public QObject // supporting pinching, panning, flicking -class QDeclarativeGeoMapGestureArea: public QObject +class QQuickGeoMapGestureArea: public QQuickItem { Q_OBJECT - Q_ENUMS(ActiveGesture) - Q_FLAGS(ActiveGestures) + Q_ENUMS(GeoMapGesture) + Q_FLAGS(AcceptedGestures) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool pinchEnabled READ pinchEnabled WRITE setPinchEnabled NOTIFY pinchEnabledChanged) - Q_PROPERTY(bool panEnabled READ panEnabled WRITE setPanEnabled NOTIFY panEnabledChanged) - Q_PROPERTY(bool isPinchActive READ isPinchActive NOTIFY pinchActiveChanged) - Q_PROPERTY(bool isPanActive READ isPanActive NOTIFY panActiveChanged) - Q_PROPERTY(ActiveGestures activeGestures READ activeGestures WRITE setActiveGestures NOTIFY activeGesturesChanged) + Q_PROPERTY(bool pinchActive READ isPinchActive NOTIFY pinchActiveChanged) + Q_PROPERTY(bool panActive READ isPanActive NOTIFY panActiveChanged) + Q_PROPERTY(AcceptedGestures acceptedGestures READ acceptedGestures WRITE setAcceptedGestures NOTIFY acceptedGesturesChanged) Q_PROPERTY(qreal maximumZoomLevelChange READ maximumZoomLevelChange WRITE setMaximumZoomLevelChange NOTIFY maximumZoomLevelChangeChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) + Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1) + public: - QDeclarativeGeoMapGestureArea(QDeclarativeGeoMap *map, QObject *parent = 0); - ~QDeclarativeGeoMapGestureArea(); + QQuickGeoMapGestureArea(QDeclarativeGeoMap *map); + ~QQuickGeoMapGestureArea(); - enum ActiveGesture { + enum GeoMapGesture { NoGesture = 0x0000, - ZoomGesture = 0x0001, + PinchGesture = 0x0001, PanGesture = 0x0002, FlickGesture = 0x004 }; - Q_DECLARE_FLAGS(ActiveGestures, ActiveGesture) - ActiveGestures activeGestures() const; - void setActiveGestures(ActiveGestures activeGestures); + Q_DECLARE_FLAGS(AcceptedGestures, GeoMapGesture) + + AcceptedGestures acceptedGestures() const; + void setAcceptedGestures(AcceptedGestures acceptedGestures); bool isPinchActive() const; bool isPanActive() const; @@ -140,12 +147,6 @@ public: bool enabled() const; void setEnabled(bool enabled); - // backwards compatibility - bool pinchEnabled() const; - void setPinchEnabled(bool enabled); - bool panEnabled() const; - void setPanEnabled(bool enabled); - qreal maximumZoomLevelChange() const; void setMaximumZoomLevelChange(qreal maxChange); @@ -168,26 +169,24 @@ public: void setMap(QGeoMap *map); + bool preventStealing() const; + void setPreventStealing(bool prevent); + Q_SIGNALS: void panActiveChanged(); void pinchActiveChanged(); void enabledChanged(); void maximumZoomLevelChangeChanged(); - void activeGesturesChanged(); + void acceptedGesturesChanged(); void flickDecelerationChanged(); - - // backwards compatibility - void pinchEnabledChanged(); - void panEnabledChanged(); - - void pinchStarted(QDeclarativeGeoMapPinchEvent *pinch); - void pinchUpdated(QDeclarativeGeoMapPinchEvent *pinch); - void pinchFinished(QDeclarativeGeoMapPinchEvent *pinch); + void pinchStarted(QGeoMapPinchEvent *pinch); + void pinchUpdated(QGeoMapPinchEvent *pinch); + void pinchFinished(QGeoMapPinchEvent *pinch); void panStarted(); void panFinished(); void flickStarted(); void flickFinished(); - + void preventStealingChanged(); private: void update(); @@ -212,8 +211,18 @@ private: void updatePan(); bool tryStartFlick(); void startFlick(int dx, int dy, int timeMs = 0); + void stopFlick(); + + bool pinchEnabled() const; + void setPinchEnabled(bool enabled); + bool panEnabled() const; + void setPanEnabled(bool enabled); + bool flickEnabled() const; + void setFlickEnabled(bool enabled); + private Q_SLOTS: - void endFlick(); + void handleFlickAnimationStopped(); + private: void stopPan(); @@ -221,60 +230,63 @@ private: void updateVelocityList(const QPointF &pos); private: - QGeoMap *map_; - QDeclarativeGeoMap *declarativeMap_; - bool enabled_; + QGeoMap *m_map; + QDeclarativeGeoMap *m_declarativeMap; + bool m_enabled; struct Pinch { - Pinch() : enabled(true), startDist(0), lastAngle(0.0) {} + Pinch() : m_enabled(true), m_startDist(0), m_lastAngle(0.0) {} - QDeclarativeGeoMapPinchEvent event; - bool enabled; + QGeoMapPinchEvent m_event; + bool m_enabled; struct Zoom { - Zoom() : minimum(-1.0), maximum(-1.0), start(0.0), previous(0.0), + Zoom() : m_minimum(-1.0), m_maximum(-1.0), m_start(0.0), m_previous(0.0), maximumChange(4.0) {} - qreal minimum; - qreal maximum; - qreal start; - qreal previous; + qreal m_minimum; + qreal m_maximum; + qreal m_start; + qreal m_previous; qreal maximumChange; - } zoom; + } m_zoom; - QPointF lastPoint1; - QPointF lastPoint2; - qreal startDist; - qreal lastAngle; - } pinch_; + QPointF m_lastPoint1; + QPointF m_lastPoint2; + qreal m_startDist; + qreal m_lastAngle; + } m_pinch; - ActiveGestures activeGestures_; + AcceptedGestures m_acceptedGestures; struct Pan { - qreal maxVelocity_; - qreal deceleration_; - QPropertyAnimation *animation_; - bool enabled_; - } pan_; + qreal m_maxVelocity; + qreal m_deceleration; + QQuickGeoCoordinateAnimation *m_animation; + bool m_enabled; + } m_flick; + // these are calculated regardless of gesture or number of touch points - qreal velocityX_; - qreal velocityY_; - QElapsedTimer lastPosTime_; - QPointF lastPos_; + qreal m_velocityX; + qreal m_velocityY; + QElapsedTimer m_lastPosTime; + QPointF m_lastPos; QList<QTouchEvent::TouchPoint> m_allPoints; QList<QTouchEvent::TouchPoint> m_touchPoints; QScopedPointer<QTouchEvent::TouchPoint> m_mousePoint; - QPointF sceneStartPoint1_; + QPointF m_sceneStartPoint1; // only set when two points in contact - QPointF sceneStartPoint2_; - QGeoCoordinate startCoord_; - QGeoCoordinate touchCenterCoord_; - qreal twoTouchAngle_; - qreal distanceBetweenTouchPoints_; - QPointF sceneCenter_; + QPointF m_sceneStartPoint2; + QGeoCoordinate m_startCoord; + QGeoCoordinate m_touchCenterCoord; + qreal m_twoTouchAngle; + qreal m_distanceBetweenTouchPoints; + QPointF m_sceneCenter; + bool m_preventStealing; + bool m_panEnabled; // prototype state machine... enum TouchPointState @@ -282,24 +294,24 @@ private: touchPoints0, touchPoints1, touchPoints2 - } touchPointState_; + } m_touchPointState; enum PinchState { pinchInactive, pinchInactiveTwoPoints, pinchActive - } pinchState_; + } m_pinchState; - enum PanState + enum FlickState { - panInactive, + flickInactive, panActive, - panFlick - } panState_; + flickActive + } m_flickState; }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeGeoMapGestureArea) +QML_DECLARE_TYPE(QQuickGeoMapGestureArea) -#endif // QDECLARATIVEGEOMAPGESTUREAREA_P_H +#endif // QQUICKGEOMAPGESTUREAREA_P_H diff --git a/src/imports/positioning/plugins.qmltypes b/src/imports/positioning/plugins.qmltypes index 853c55cb..a47aa277 100644 --- a/src/imports/positioning/plugins.qmltypes +++ b/src/imports/positioning/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtPositioning 5.5' +// 'qmlplugindump -nonrelocatable QtPositioning 5.6' Module { dependencies: [] @@ -90,14 +90,6 @@ Module { Property { name: "isTextGenerated"; type: "bool"; isReadonly: true } } Component { - name: "QDeclarativeGeoCoordinateAnimation" - prototype: "QQuickPropertyAnimation" - exports: ["QtPositioning/CoordinateAnimation 5.3"] - exportMetaObjectRevisions: [0] - Property { name: "from"; type: "QGeoCoordinate" } - Property { name: "to"; type: "QGeoCoordinate" } - } - Component { name: "QDeclarativeGeoLocation" prototype: "QObject" exports: ["QtPositioning/Location 5.0"] @@ -114,7 +106,7 @@ Module { "QtPositioning/Position 5.0", "QtPositioning/Position 5.3", "QtPositioning/Position 5.4", - "QtPositioning/Position 5.5" + "QtPositioning/Position 5.6" ] exportMetaObjectRevisions: [0, 1, 2, 2] Property { name: "latitudeValid"; type: "bool"; isReadonly: true } @@ -251,6 +243,23 @@ Module { Method { name: "complete" } } Component { + name: "QQuickGeoCoordinateAnimation" + prototype: "QQuickPropertyAnimation" + exports: ["QtPositioning/CoordinateAnimation 5.3"] + exportMetaObjectRevisions: [0] + Enum { + name: "Direction" + values: { + "Shortest": 0, + "West": 1, + "East": 2 + } + } + Property { name: "from"; type: "QGeoCoordinate" } + Property { name: "to"; type: "QGeoCoordinate" } + Property { name: "direction"; type: "Direction" } + } + Component { name: "QQuickPropertyAnimation" prototype: "QQuickAbstractAnimation" Property { name: "duration"; type: "int" } diff --git a/src/imports/positioning/positioning.cpp b/src/imports/positioning/positioning.cpp index ce68cb46..c9a64a47 100644 --- a/src/imports/positioning/positioning.cpp +++ b/src/imports/positioning/positioning.cpp @@ -39,7 +39,7 @@ #include "qdeclarativepositionsource_p.h" #include "qdeclarativeposition_p.h" -#include "qdeclarativegeocoordinateanimation_p.h" +#include "qquickgeocoordinateanimation_p.h" #include "locationsingleton.h" #include <QtCore/QVariantAnimation> @@ -517,7 +517,7 @@ public: qRegisterMetaType<QGeoShape>(); QMetaType::registerEqualsComparator<QGeoShape>(); - qRegisterAnimationInterpolator<QGeoCoordinate>(geoCoordinateInterpolator); + qRegisterAnimationInterpolator<QGeoCoordinate>(q_coordinateInterpolator); // Register the 5.0 types // 5.0 is silent and not advertised @@ -531,7 +531,7 @@ public: // Register the 5.3 types // Introduction of 5.3 version; existing 5.0 exports become automatically available under 5.3 minor = 3; - qmlRegisterType<QDeclarativeGeoCoordinateAnimation >(uri, major, minor, "CoordinateAnimation"); + qmlRegisterType<QQuickGeoCoordinateAnimation >(uri, major, minor, "CoordinateAnimation"); qmlRegisterType<QDeclarativePosition, 1 >(uri, major, minor, "Position"); // Register the 5.4 types @@ -539,7 +539,7 @@ public: minor = 4; qmlRegisterType<QDeclarativePosition, 2>(uri, major, minor, "Position"); - minor = 5; + minor = 6; qmlRegisterType<QDeclarativePosition, 2>(uri, major, minor, "Position"); } else { qDebug() << "Unsupported URI given to load positioning QML plugin: " << QLatin1String(uri); diff --git a/src/imports/positioning/positioning.pro b/src/imports/positioning/positioning.pro index 7e49ec8e..119c3dea 100644 --- a/src/imports/positioning/positioning.pro +++ b/src/imports/positioning/positioning.pro @@ -5,13 +5,14 @@ INCLUDEPATH *= $$PWD HEADERS += qdeclarativeposition_p.h \ qdeclarativepositionsource_p.h \ locationsingleton.h \ - qdeclarativegeocoordinateanimation_p.h + qquickgeocoordinateanimation_p.h \ + qquickgeocoordinateanimation_p_p.h SOURCES += qdeclarativeposition.cpp \ positioning.cpp \ qdeclarativepositionsource.cpp \ locationsingleton.cpp \ - qdeclarativegeocoordinateanimation.cpp + qquickgeocoordinateanimation.cpp load(qml_plugin) diff --git a/src/imports/positioning/qdeclarativegeocoordinateanimation.cpp b/src/imports/positioning/qdeclarativegeocoordinateanimation.cpp deleted file mode 100644 index 8bb677ad..00000000 --- a/src/imports/positioning/qdeclarativegeocoordinateanimation.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdeclarativegeocoordinateanimation_p.h" -#include <QtQuick/private/qquickanimation_p_p.h> -#include <QtPositioning/private/qdoublevector2d_p.h> - -QT_BEGIN_NAMESPACE - -/*! - \qmltype CoordinateAnimation - \instantiates QDeclarativeGeoCoordinateAnimation - \inherits PropertyAnimation - \inqmlmodule QtPositioning - \since 5.3 - - \brief A PropertyAnimation for geo coordinate properties. - - A specialized \l{PropertyAnimation} that defines an animation - between two geo coordinates. -*/ - -QDeclarativeGeoCoordinateAnimation::QDeclarativeGeoCoordinateAnimation(QObject *parent) - : QQuickPropertyAnimation(parent) -{ - Q_D(QQuickPropertyAnimation); - d->interpolatorType = qMetaTypeId<QGeoCoordinate>(); - d->defaultToInterpolatorType = true; - d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); -} - -QDeclarativeGeoCoordinateAnimation::~QDeclarativeGeoCoordinateAnimation() -{ -} - -/*! - \qmlproperty coordinate CoordinateAnimation::from - This property holds the coordinate where the animation should begin. -*/ -QGeoCoordinate QDeclarativeGeoCoordinateAnimation::from() const -{ - Q_D(const QQuickPropertyAnimation); - return d->from.value<QGeoCoordinate>(); -} - -void QDeclarativeGeoCoordinateAnimation::setFrom(const QGeoCoordinate &f) -{ - QQuickPropertyAnimation::setFrom(QVariant::fromValue(f)); -} - -/*! - \qmlproperty coordinate CoordinateAnimation::to - This property holds the coordinate where the animation should end. -*/ -QGeoCoordinate QDeclarativeGeoCoordinateAnimation::to() const -{ - Q_D(const QQuickPropertyAnimation); - return d->to.value<QGeoCoordinate>(); -} - -void QDeclarativeGeoCoordinateAnimation::setTo(const QGeoCoordinate &t) -{ - QQuickPropertyAnimation::setTo(QVariant::fromValue(t)); -} - -QT_END_NAMESPACE diff --git a/src/imports/positioning/qdeclarativeposition_p.h b/src/imports/positioning/qdeclarativeposition_p.h index 67253abe..78f78464 100644 --- a/src/imports/positioning/qdeclarativeposition_p.h +++ b/src/imports/positioning/qdeclarativeposition_p.h @@ -36,6 +36,17 @@ #ifndef QDECLARATIVEPOSITION_H #define QDECLARATIVEPOSITION_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtCore/QDateTime> #include <QtQml/qqml.h> diff --git a/src/imports/positioning/qdeclarativepositionsource_p.h b/src/imports/positioning/qdeclarativepositionsource_p.h index 376014e4..b4530aff 100644 --- a/src/imports/positioning/qdeclarativepositionsource_p.h +++ b/src/imports/positioning/qdeclarativepositionsource_p.h @@ -34,6 +34,17 @@ #ifndef QDECLARATIVEPOSITIONSOURCE_H #define QDECLARATIVEPOSITIONSOURCE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qdeclarativeposition_p.h" #include <QtCore/QObject> diff --git a/src/imports/positioning/qquickgeocoordinateanimation.cpp b/src/imports/positioning/qquickgeocoordinateanimation.cpp new file mode 100644 index 00000000..11f9542e --- /dev/null +++ b/src/imports/positioning/qquickgeocoordinateanimation.cpp @@ -0,0 +1,291 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickgeocoordinateanimation_p.h" +#include "qquickgeocoordinateanimation_p_p.h" +#include <QtQuick/private/qquickanimation_p_p.h> +#include <QtPositioning/private/qdoublevector2d_p.h> +#include <QtPositioning/private/qgeoprojection_p.h> +#include <QtPositioning/private/qgeocoordinate_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype CoordinateAnimation + \instantiates QQuickGeoCoordinateAnimation + \inherits PropertyAnimation + \inqmlmodule QtPositioning + \since 5.3 + + \brief A PropertyAnimation for geo coordinate properties. + + A specialized \l{PropertyAnimation} that defines an animation + between two \l{coordinate}{coordinates}. + + By default, a \l{latitude} of the \l{coordinate} is animated in the direction of shortest + (geodesic) distance between those coordinates. Since CoordinateAnimation uses Mercator + map projection, the \l{latitude} animation is always between -90 and 90 degrees. + The \l{longitude} animation path is not limited and can go over 180 degrees + in both west and east directions. + + The \l{direction} property can be set to specify the direction in which the \l{longitude} + animation should occur. + + \sa {Animation and Transitions in Qt Quick} +*/ + +QVariant q_coordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + if (from == to) { + if (progress < 0.5) { + return QVariant::fromValue(from); + } else { + return QVariant::fromValue(to); + } + } + + QGeoCoordinate result = QGeoProjection::coordinateInterpolation(from, to, progress); + + return QVariant::fromValue(result); +} + +QVariant q_coordinateShortestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + const QGeoMercatorCoordinatePrivate* fromMercator = + static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&from)); + const QGeoMercatorCoordinatePrivate* toMercator = + static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&to)); + + double toX = toMercator->m_mercatorX; + double toY = toMercator->m_mercatorY; + double fromX = fromMercator->m_mercatorX; + double fromY = fromMercator->m_mercatorY; + double x; + if (0.5 < qAbs(toX - fromX)) { + // handle dateline crossing + double ex = toX; + double sx = fromX; + if (ex < sx) + sx -= 1.0; + else if (sx < ex) + ex -= 1.0; + + x = fromX + (toX - fromX) * progress; + + if (x < 0.0) + x += 1.0; + + } else { + x = fromX + (toX - fromX) * progress; + } + + double y = fromY + (toY - fromY) * progress; + + QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y)); + result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress); + return QVariant::fromValue(result); +} + +QVariant q_coordinateWestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + const QGeoMercatorCoordinatePrivate* fromMercator = + static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&from)); + const QGeoMercatorCoordinatePrivate* toMercator = + static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&to)); + + double toX = toMercator->m_mercatorX; + double toY = toMercator->m_mercatorY; + double fromX = fromMercator->m_mercatorX; + double fromY = fromMercator->m_mercatorY; + double diff = toX - fromX; + + while (diff < 0.0) { + toX += 1.0; + diff += 1.0; + } + + double x = fromX + (toX - fromX) * progress; + double y = fromY + (toY - fromY) * progress; + + while (x > 1.0) + x -= 1.0; + + QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y)); + result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress); + + return QVariant::fromValue(result); +} + +QVariant q_coordinateEastInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) +{ + const QGeoMercatorCoordinatePrivate* fromMercator = + static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&from)); + const QGeoMercatorCoordinatePrivate* toMercator = + static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&to)); + + double toX = toMercator->m_mercatorX; + double toY = toMercator->m_mercatorY; + double fromX = fromMercator->m_mercatorX; + double fromY = fromMercator->m_mercatorY; + double diff = toX - fromX; + + while (diff > 0.0) { + toX -= 1.0; + diff -= 1.0; + } + + double x = fromX + (toX - fromX) * progress; + double y = fromY + (toY - fromY) * progress; + + while (x < 0.0) + x += 1.0; + + QGeoCoordinate result = QGeoProjection::mercatorToCoord(QDoubleVector2D(x, y)); + result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress); + + return QVariant::fromValue(result); +} + +QQuickGeoCoordinateAnimation::QQuickGeoCoordinateAnimation(QObject *parent) + : QQuickPropertyAnimation(*(new QQuickGeoCoordinateAnimationPrivate), parent) + +{ + Q_D(QQuickGeoCoordinateAnimation); + d->interpolatorType = qMetaTypeId<QGeoCoordinate>(); + d->defaultToInterpolatorType = true; + d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); +} + +QQuickGeoCoordinateAnimation::~QQuickGeoCoordinateAnimation() +{ +} + +/*! + \qmlproperty coordinate CoordinateAnimation::from + This property holds the coordinate where the animation should begin. +*/ +QGeoCoordinate QQuickGeoCoordinateAnimation::from() const +{ + Q_D(const QQuickGeoCoordinateAnimation); + return d->from.value<QGeoCoordinate>(); +} + +void QQuickGeoCoordinateAnimation::setFrom(const QGeoCoordinate &f) +{ + QGeoMercatorCoordinatePrivate *mercator = new QGeoMercatorCoordinatePrivate(); + QDoubleVector2D fromVector = QGeoProjection::coordToMercator(f); + mercator->lat = f.latitude(); + mercator->lng = f.longitude(); + mercator->alt = f.altitude(); + mercator->m_mercatorX = fromVector.x(); + mercator->m_mercatorY = fromVector.y(); + QGeoCoordinate from(*mercator); + QQuickPropertyAnimation::setFrom(QVariant::fromValue(from)); +} + +/*! + \qmlproperty coordinate CoordinateAnimation::to + This property holds the coordinate where the animation should end. +*/ +QGeoCoordinate QQuickGeoCoordinateAnimation::to() const +{ + Q_D(const QQuickGeoCoordinateAnimation); + return d->to.value<QGeoCoordinate>(); +} + +void QQuickGeoCoordinateAnimation::setTo(const QGeoCoordinate &t) +{ + QGeoMercatorCoordinatePrivate *mercator = new QGeoMercatorCoordinatePrivate(); + QDoubleVector2D toVector = QGeoProjection::coordToMercator(t); + mercator->lat = t.latitude(); + mercator->lng = t.longitude(); + mercator->alt = t.altitude(); + mercator->m_mercatorX = toVector.x(); + mercator->m_mercatorY = toVector.y(); + QGeoCoordinate to(*mercator); + QQuickPropertyAnimation::setTo(QVariant::fromValue(to)); +} + +/*! + \qmlproperty enumeration CoordinateAnimation::direction + This property holds the direction of the \l{longitude} animation of the \l{coordinate}. + + Possible values are: + + \list + \li CoordinateAnimation.Shortest (default) - the longitude animation goes in the direction + that produces the shortest animation path. + \li CoordinateAnimation.West - the longitude animation always goes into western direction + and may cross the date line. + \li CoordinateAnimation.East - the longitude animation always goes into eastern direction + and may cross the date line. + \endlist + \since 5.5 +*/ + + +QQuickGeoCoordinateAnimation::Direction QQuickGeoCoordinateAnimation::direction() const +{ + Q_D(const QQuickGeoCoordinateAnimation); + return d->m_direction; +} + +void QQuickGeoCoordinateAnimation::setDirection(QQuickGeoCoordinateAnimation::Direction direction) +{ + Q_D( QQuickGeoCoordinateAnimation); + if (d->m_direction == direction) + return; + + d->m_direction = direction; + switch (direction) { + case West: + d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&q_coordinateWestInterpolator); + break; + case East: + d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&q_coordinateEastInterpolator); + break; + case Shortest: + default: + d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&q_coordinateShortestInterpolator); + break; + } + emit directionChanged(); + +} + +QQuickGeoCoordinateAnimationPrivate::QQuickGeoCoordinateAnimationPrivate(): + m_direction(QQuickGeoCoordinateAnimation::Shortest) +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/blackberry/bb/ppsobject.h b/src/imports/positioning/qquickgeocoordinateanimation_p.h index 9f290448..526aa456 100644 --- a/src/plugins/position/blackberry/bb/ppsobject.h +++ b/src/imports/positioning/qquickgeocoordinateanimation_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. +** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtPositioning module of the Qt Toolkit. @@ -31,60 +31,63 @@ ** ****************************************************************************/ -#ifndef BB_CORE_PPSOBJECT_HPP -#define BB_CORE_PPSOBJECT_HPP +#ifndef QQUICKGEOCOORDINATEANIMATION_P_H +#define QQUICKGEOCOORDINATEANIMATION_P_H -#include <bb/Global> -#include <bb/PpsAttribute> -#include <bb/PpsOpenMode> +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// -#include <QMap> -#include <QObject> -#include <QVariantMap> +#include <QtQuick/private/qquickanimation_p.h> +#include <QtPositioning/qgeocoordinate.h> -namespace bb -{ -class PpsObjectPrivate; +QT_BEGIN_NAMESPACE + +class QQuickGeoCoordinateAnimationPrivate; -class BB_CORE_EXPORT PpsObject : public QObject +class QQuickGeoCoordinateAnimation : public QQuickPropertyAnimation { Q_OBJECT + Q_DECLARE_PRIVATE(QQuickGeoCoordinateAnimation) + Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom) + Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo) + Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged) public: - explicit PpsObject(const QString &path, QObject *parent = 0); - virtual ~PpsObject(); + enum Direction { + Shortest, + West, + East + }; + Q_ENUM(Direction) - int error() const; - QString errorString() const; + QQuickGeoCoordinateAnimation(QObject *parent=0); + ~QQuickGeoCoordinateAnimation(); - bool isReadyReadEnabled() const; - bool isBlocking() const; - bool setBlocking(bool enable); - bool isOpen() const; - bool open(PpsOpenMode::Types mode = PpsOpenMode::PublishSubscribe); - bool close(); - QByteArray read(bool * ok = 0); - bool write(const QByteArray &byteArray); - bool remove(); + QGeoCoordinate from() const; + void setFrom(const QGeoCoordinate &); - static QVariantMap decode( const QByteArray &rawData, bool * ok = 0 ); - static QMap<QString, PpsAttribute> decodeWithFlags( const QByteArray &rawData, bool * ok = 0 ); - static QByteArray encode( const QVariantMap &ppsData, bool * ok = 0 ); + QGeoCoordinate to() const; + void setTo(const QGeoCoordinate &); -public Q_SLOTS: - void setReadyReadEnabled(bool enable); + Direction direction() const; + void setDirection(Direction direction); Q_SIGNALS: - void readyRead(); - -private: -//!@cond PRIVATE - QScopedPointer<PpsObjectPrivate> d_ptr; - Q_DECLARE_PRIVATE(PpsObject) - Q_DISABLE_COPY(PpsObject) -//!@endcond PRIVATE + void directionChanged(); }; -} // namespace bb +QVariant q_coordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress); + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickGeoCoordinateAnimation) -#endif // BB_CORE_PPSOBJECT_HPP +#endif // QQUICKCOORDINATEANIMATION_P_H diff --git a/src/imports/positioning/qdeclarativegeocoordinateanimation_p.h b/src/imports/positioning/qquickgeocoordinateanimation_p_p.h index 2aafc8f6..daa59b73 100644 --- a/src/imports/positioning/qdeclarativegeocoordinateanimation_p.h +++ b/src/imports/positioning/qquickgeocoordinateanimation_p_p.h @@ -31,34 +31,33 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVEGEOCOORDINATEANIMATION_P_H -#define QDECLARATIVEGEOCOORDINATEANIMATION_P_H - -#include <QtQuick/private/qquickanimation_p.h> -#include <QtPositioning/qgeocoordinate.h> +#ifndef QQUICKGEOCOORDINATEANIMATION_P_P_H +#define QQUICKGEOCOORDINATEANIMATION_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickgeocoordinateanimation_p.h" +#include <QtQuick/private/qquickanimation_p_p.h> QT_BEGIN_NAMESPACE -class QDeclarativeGeoCoordinateAnimation : public QQuickPropertyAnimation +class QQuickGeoCoordinateAnimationPrivate : public QQuickPropertyAnimationPrivate { - Q_OBJECT - Q_DECLARE_PRIVATE(QQuickPropertyAnimation) - Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom) - Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo) - + Q_DECLARE_PUBLIC(QQuickGeoCoordinateAnimation) public: - QDeclarativeGeoCoordinateAnimation(QObject *parent=0); - ~QDeclarativeGeoCoordinateAnimation(); - - QGeoCoordinate from() const; - void setFrom(const QGeoCoordinate &); - - QGeoCoordinate to() const; - void setTo(const QGeoCoordinate &); + QQuickGeoCoordinateAnimationPrivate(); + QQuickGeoCoordinateAnimation::Direction m_direction; }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QDeclarativeGeoCoordinateAnimation) - -#endif // QDECLARATIVEGEOCOORDINATEANIMATION_P_H +#endif // QQUICKGEOCOORDINATEANIMATION_P_P_H diff --git a/src/location/doc/qtlocation.qdocconf b/src/location/doc/qtlocation.qdocconf index 695860a0..abe48974 100644 --- a/src/location/doc/qtlocation.qdocconf +++ b/src/location/doc/qtlocation.qdocconf @@ -41,7 +41,7 @@ sourcedirs += .. \ ../../imports/location \ ../../plugins/geoservices/nokia -examplesinstallpath = location +examplesinstallpath = qtlocation/location exampledirs += ../../../examples/location \ snippets/ diff --git a/src/location/doc/snippets/declarative/maps.qml b/src/location/doc/snippets/declarative/maps.qml index 59e92c45..3378ee06 100644 --- a/src/location/doc/snippets/declarative/maps.qml +++ b/src/location/doc/snippets/declarative/maps.qml @@ -43,7 +43,7 @@ import QtQuick 2.0 //! [QtQuick import] //! [QtLocation import] import QtPositioning 5.5 -import QtLocation 5.5 +import QtLocation 5.6 //! [QtLocation import] Item { diff --git a/src/location/doc/snippets/declarative/nmealog.txt b/src/location/doc/snippets/declarative/nmealog.txt index 8c8286dd..8c8286dd 100755..100644 --- a/src/location/doc/snippets/declarative/nmealog.txt +++ b/src/location/doc/snippets/declarative/nmealog.txt diff --git a/src/location/doc/snippets/declarative/places.qml b/src/location/doc/snippets/declarative/places.qml index a0081bd9..7dab804c 100644 --- a/src/location/doc/snippets/declarative/places.qml +++ b/src/location/doc/snippets/declarative/places.qml @@ -42,7 +42,7 @@ import QtQuick 2.0 //! [QtQuick import] import QtPositioning 5.5 -import QtLocation 5.5 +import QtLocation 5.6 Item { width: 400; height: 400; diff --git a/src/location/doc/snippets/declarative/routing.qml b/src/location/doc/snippets/declarative/routing.qml index 75d18c5b..643722bf 100644 --- a/src/location/doc/snippets/declarative/routing.qml +++ b/src/location/doc/snippets/declarative/routing.qml @@ -42,7 +42,7 @@ import QtQuick 2.3 //! [QtQuick import] import QtPositioning 5.5 -import QtLocation 5.5 +import QtLocation 5.6 Item { width: 1000 diff --git a/src/location/doc/src/plugins/nokia.qdoc b/src/location/doc/src/plugins/nokia.qdoc index f1a6828a..1ed5e6e1 100644 --- a/src/location/doc/src/plugins/nokia.qdoc +++ b/src/location/doc/src/plugins/nokia.qdoc @@ -92,7 +92,9 @@ a prefix. \li here.mapping.cache.directory \li Absolute path to map tile cache directory used as network disk cache. - Default place for the cache is "QtLocation" directory in \l {QStandardPaths::writableLocation()} {QStandardPaths::writableLocation}(\l{QStandardPaths::GenericCacheLocation}). + The default place for the cache is \c{QtLocation/here} directory in \l {QStandardPaths::writableLocation()} {QStandardPaths::writableLocation}(\l{QStandardPaths::GenericCacheLocation}). + On systems that have no concept of a shared cache, the application-specific \l{QStandardPaths::CacheLocation} is used instead. + \row \li here.mapping.cache.disk.size \li Map tile disk cache size in bytes. Default size of the cache is 20MB. diff --git a/src/location/doc/src/plugins/osm.qdoc b/src/location/doc/src/plugins/osm.qdoc index f6de9c20..1c924fd3 100644 --- a/src/location/doc/src/plugins/osm.qdoc +++ b/src/location/doc/src/plugins/osm.qdoc @@ -106,4 +106,12 @@ Plugin { PluginParameter { name: "osm.geocoding.host"; value: "http://geocoding.server.address" } } \endcode + +\section1 Other Plugin-specific Information + +\section2 Tile cache + +The tiles are cached in a \c{QtLocation/osm} directory in \l {QStandardPaths::writableLocation()}{QStandardPaths::writableLocation} +(\l{QStandardPaths::GenericCacheLocation}). On systems that have no concept of a shared cache, the application-specific +\l{QStandardPaths::CacheLocation} is used instead. */ diff --git a/src/location/doc/src/qml-maps.qdoc b/src/location/doc/src/qml-maps.qdoc index ebae9582..9b6232f5 100644 --- a/src/location/doc/src/qml-maps.qdoc +++ b/src/location/doc/src/qml-maps.qdoc @@ -48,8 +48,7 @@ Map item you can center the map, zoom, pinch and make the item flickable. The places to be added to the map are \l {Maps and Navigation (QML)#Putting Objects on a Map (Map Overlay Objects)}{MapItems}. The item's position is defined by a \l {coordinate}{coordinate} which includes latitude, -longitude and altitude. The item is then displayed automatically after it is added to the Map. -\l {Maps and Navigation (QML)#Putting Objects on a Map (Map Overlay Objects)}{MapItems} or \l Map. +longitude and altitude. The item is then displayed automatically after it is added to the \l Map. \section2 Position on map diff --git a/src/location/doc/src/qtlocation-changes.qdoc b/src/location/doc/src/qtlocation-changes.qdoc index 0645c088..1c79c582 100644 --- a/src/location/doc/src/qtlocation-changes.qdoc +++ b/src/location/doc/src/qtlocation-changes.qdoc @@ -33,18 +33,24 @@ \b{\l{QtLocation::Map}{Map} Component} \list \li removed wheelAngleChanged() signal - \li added \l[QML]{QtLocation::Map}{error} property - \li added \l[QML]{QtLocation::Map}{errorString} property - \li added \l[QML]{QtLocation::Map}{copyrightLinkActivated} signal + \li added \l[QML]{QtLocation::Map::}{error} property + \li added \l[QML]{QtLocation::Map::}{errorString} property + \li added \l[QML]{QtLocation::Map::}{copyrightLinkActivated} signal \li removed toScreenPosition() method - \li added \l[QML]{QtLocation::Map}{fromCoordinate}() method - \li replaced cameraStopped() method with \l[QML]{QtLocation::Map}{prefetchData}() method + \li added \l[QML]{QtLocation::Map::}{fromCoordinate}() method + \li replaced cameraStopped() method with \l[QML]{QtLocation::Map::}{prefetchData} method + \li replaced fitViewportToGeoShape() method with \l[QML]{QtLocation::Map::}{visibleRegion} property + \endlist \b{\l{QtLocation::MapGestureArea}{MapGestureArea} Component} \list - \li added missing panActiveChanged() signal to \l[QML]{QtLocation::MapGestureArea::}{isPanActive} property + \li added missing panActiveChanged() signal to \l[QML]{QtLocation::MapGestureArea::}{panActive} property \li removed movementStopped() signal + \li replaced isPanActive, isPinchActive with panActive, pinchActive + \li replaced activeGestures with acceptedGestures + \li replaced ZoomGesture with PinchGesture + \li removed properties panEnabled pinchEnable, please use acceptedGestures instead \endlist \b Geoservice's plugin parameters diff --git a/src/location/doc/src/qtlocation.qdoc b/src/location/doc/src/qtlocation.qdoc index 11d0d2f7..7979bbe5 100644 --- a/src/location/doc/src/qtlocation.qdoc +++ b/src/location/doc/src/qtlocation.qdoc @@ -68,9 +68,6 @@ applications. The Qt Location API helps you create viable mapping solutions using the data available from some of the popular location services. -The release of this API with Qt 5.5 is a Technology Preview. This implies a -soft API freeze for Qt Location. - \section1 Overview The Qt Location API enables you to: @@ -88,7 +85,7 @@ To load the Qt Location module, add the following statement to your .qml files \code import QtPositioning 5.5 - import QtLocation 5.5 + import QtLocation 5.6 \endcode The QtLocation QML module depends on the QtPositioning QML module. diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri index 43e0f747..93af4f4d 100644 --- a/src/location/maps/maps.pri +++ b/src/location/maps/maps.pri @@ -49,7 +49,8 @@ PRIVATE_HEADERS += \ maps/qgeoroutingmanagerengine_p.h \ maps/qgeoroutingmanager_p.h \ maps/qgeoserviceprovider_p.h \ - maps/qgeotilecache_p.h \ + maps/qabstractgeotilecache_p.h \ + maps/qgeofiletilecache_p.h \ maps/qgeotiledmapreply_p.h \ maps/qgeotiledmapreply_p_p.h \ maps/qgeotilespec_p.h \ @@ -81,7 +82,8 @@ SOURCES += \ maps/qgeoroutingmanagerengine.cpp \ maps/qgeoserviceprovider.cpp \ maps/qgeoserviceproviderfactory.cpp \ - maps/qgeotilecache.cpp \ + maps/qabstractgeotilecache.cpp \ + maps/qgeofiletilecache.cpp \ maps/qgeotiledmapreply.cpp \ maps/qgeotilespec.cpp \ maps/qgeotiledmap.cpp diff --git a/src/location/maps/qabstractgeotilecache.cpp b/src/location/maps/qabstractgeotilecache.cpp new file mode 100644 index 00000000..739123db --- /dev/null +++ b/src/location/maps/qabstractgeotilecache.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qabstractgeotilecache_p.h" + +#include "qgeotilespec_p.h" + +#include "qgeomappingmanager_p.h" + +#include <QDir> +#include <QStandardPaths> +#include <QMetaType> +#include <QPixmap> +#include <QDebug> + +Q_DECLARE_METATYPE(QList<QGeoTileSpec>) +Q_DECLARE_METATYPE(QSet<QGeoTileSpec>) + +QT_BEGIN_NAMESPACE + +QGeoTileTexture::QGeoTileTexture() + : textureBound(false) {} + +QGeoTileTexture::~QGeoTileTexture() +{ +} + +QAbstractGeoTileCache::QAbstractGeoTileCache(QObject *parent) + : QObject(parent) +{ + qRegisterMetaType<QGeoTileSpec>(); + qRegisterMetaType<QList<QGeoTileSpec> >(); + qRegisterMetaType<QSet<QGeoTileSpec> >(); +} + +QAbstractGeoTileCache::~QAbstractGeoTileCache() +{ +} + +void QAbstractGeoTileCache::printStats() +{ +} + +void QAbstractGeoTileCache::handleError(const QGeoTileSpec &, const QString &error) +{ + qWarning() << "tile request error " << error; +} + +void QAbstractGeoTileCache::setMaxDiskUsage(int diskUsage) +{ + Q_UNUSED(diskUsage); +} + +int QAbstractGeoTileCache::maxDiskUsage() const +{ + return 0; +} + +int QAbstractGeoTileCache::diskUsage() const +{ + return 0; +} + +void QAbstractGeoTileCache::setMaxMemoryUsage(int memoryUsage) +{ + Q_UNUSED(memoryUsage); +} + +int QAbstractGeoTileCache::maxMemoryUsage() const +{ + return 0; +} + +int QAbstractGeoTileCache::memoryUsage() const +{ + return 0; +} + +QString QAbstractGeoTileCache::baseCacheDirectory() +{ + QString dir; + + // Try the shared cache first and use a specific directory. (e.g. ~/.cache/QtLocation) + // If this is not supported by the platform, use the application-specific cache + // location. (e.g. ~/.cache/<app_name>/QtLocation) + dir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); + + if (!dir.isEmpty()) { + // The shared cache may not be writable when application isolation is enforced. + static bool writable = false; + static bool writableChecked = false; + if (!writableChecked) { + writableChecked = true; + QDir::root().mkpath(dir); + QFile writeTestFile(QDir(dir).filePath(QStringLiteral("qt_cache_check"))); + writable = writeTestFile.open(QIODevice::WriteOnly); + if (writable) + writeTestFile.remove(); + } + if (!writable) + dir = QString(); + } + + if (dir.isEmpty()) + dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + + if (!dir.endsWith(QLatin1Char('/'))) + dir += QLatin1Char('/'); + + dir += QLatin1String("QtLocation/"); + + return dir; +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qabstractgeotilecache_p.h b/src/location/maps/qabstractgeotilecache_p.h new file mode 100644 index 00000000..141aa9b4 --- /dev/null +++ b/src/location/maps/qabstractgeotilecache_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QABSTRACTGEOTILECACHE_P_H +#define QABSTRACTGEOTILECACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtLocation/qlocationglobal.h> + +#include <QObject> +#include <QCache> +#include "qcache3q_p.h" +#include <QSet> +#include <QMutex> +#include <QTimer> + +#include "qgeotilespec_p.h" +#include "qgeotiledmappingmanagerengine_p.h" + +#include <QImage> + +QT_BEGIN_NAMESPACE + +class QGeoMappingManager; + +class QGeoTile; +class QAbstractGeoTileCache; + +class QThread; + +/* This is also used in the mapgeometry */ +class Q_LOCATION_EXPORT QGeoTileTexture +{ +public: + + QGeoTileTexture(); + ~QGeoTileTexture(); + + QGeoTileSpec spec; + QImage image; + bool textureBound; +}; + +class Q_LOCATION_EXPORT QAbstractGeoTileCache : public QObject +{ + Q_OBJECT +public: + virtual ~QAbstractGeoTileCache(); + + virtual void setMaxDiskUsage(int diskUsage); + virtual int maxDiskUsage() const; + virtual int diskUsage() const; + + virtual void setMaxMemoryUsage(int memoryUsage); + virtual int maxMemoryUsage() const; + virtual int memoryUsage() const; + + virtual void setMinTextureUsage(int textureUsage) = 0; + virtual void setExtraTextureUsage(int textureUsage) = 0; + virtual int maxTextureUsage() const = 0; + virtual int minTextureUsage() const = 0; + virtual int textureUsage() const = 0; + virtual void clearAll() = 0; + + virtual QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec) = 0; + + virtual void insert(const QGeoTileSpec &spec, + const QByteArray &bytes, + const QString &format, + QGeoTiledMappingManagerEngine::CacheAreas areas = QGeoTiledMappingManagerEngine::AllCaches) = 0; + virtual void handleError(const QGeoTileSpec &spec, const QString &errorString); + + static QString baseCacheDirectory(); + +protected: + QAbstractGeoTileCache(QObject *parent = 0); + + virtual void printStats() = 0; +}; + +QT_END_NAMESPACE + +#endif // QABSTRACTGEOTILECACHE_P_H diff --git a/src/location/maps/qgeocameracapabilities.cpp b/src/location/maps/qgeocameracapabilities.cpp index 41f71b97..7b4a014a 100644 --- a/src/location/maps/qgeocameracapabilities.cpp +++ b/src/location/maps/qgeocameracapabilities.cpp @@ -107,7 +107,7 @@ QGeoCameraCapabilitiesPrivate &QGeoCameraCapabilitiesPrivate::operator = (const \class QGeoCameraCapabilities \inmodule QtLocation \ingroup QtLocation-impl - \since 5.5 + \since 5.6 \internal \brief The QGeoCameraCapabilities class describes the limitations on camera settings imposed by a mapping plugin. diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp index abce5c3e..d2783a5b 100644 --- a/src/location/maps/qgeocameratiles.cpp +++ b/src/location/maps/qgeocameratiles.cpp @@ -179,7 +179,7 @@ QSet<QGeoTileSpec> QGeoCameraTiles::prefetchTiles(PrefetchStle style) return d_ptr->m_tiles; } -void QGeoCameraTiles::setCamera(const QGeoCameraData &camera) +void QGeoCameraTiles::setCameraData(const QGeoCameraData &camera) { if (d_ptr->m_camera == camera) return; @@ -217,7 +217,7 @@ void QGeoCameraTiles::setMapType(const QGeoMapType &mapType) d_ptr->m_mapType = mapType; } -void QGeoCameraTiles::setMapVersion(const int mapVersion) +void QGeoCameraTiles::setMapVersion(int mapVersion) { if (d_ptr->m_mapVersion == mapVersion) return; @@ -249,7 +249,7 @@ void QGeoCameraTiles::setMaximumZoomLevel(int maxZoom) d_ptr->m_maxZoom = maxZoom; } -QSet<QGeoTileSpec> QGeoCameraTiles::visibleTiles() +const QSet<QGeoTileSpec>& QGeoCameraTiles::visibleTiles() { if (d_ptr->m_dirtyGeometry) { d_ptr->m_tiles.clear(); diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h index e3260283..e133f8e6 100644 --- a/src/location/maps/qgeocameratiles_p.h +++ b/src/location/maps/qgeocameratiles_p.h @@ -65,7 +65,7 @@ public: enum PrefetchStle { PrefetchNeighbourLayer, PrefetchTwoNeighbourLayers}; - void setCamera(const QGeoCameraData &camera); + void setCameraData(const QGeoCameraData &camera); void setScreenSize(const QSize &size); void setTileSize(int tileSize); void setMaximumZoomLevel(int maxZoom); @@ -76,7 +76,7 @@ public: void setMapType(const QGeoMapType &mapType); void setMapVersion(int mapVersion); - QSet<QGeoTileSpec> visibleTiles(); + const QSet<QGeoTileSpec>& visibleTiles(); QSet<QGeoTileSpec> prefetchTiles(PrefetchStle style); protected: diff --git a/src/location/maps/qgeocodereply.cpp b/src/location/maps/qgeocodereply.cpp index 7ed18b17..47018217 100644 --- a/src/location/maps/qgeocodereply.cpp +++ b/src/location/maps/qgeocodereply.cpp @@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE \class QGeoCodeReply \inmodule QtLocation \ingroup QtLocation-geocoding - \since 5.5 + \since 5.6 \brief The QGeoCodeReply class manages an operation started by an instance of QGeoCodingManager. diff --git a/src/location/maps/qgeocodingmanager.cpp b/src/location/maps/qgeocodingmanager.cpp index a84686e3..70c5de82 100644 --- a/src/location/maps/qgeocodingmanager.cpp +++ b/src/location/maps/qgeocodingmanager.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE \class QGeoCodingManager \inmodule QtLocation \ingroup QtLocation-geocoding - \since 5.5 + \since 5.6 \brief The QGeoCodingManager class provides support for geocoding operations. @@ -170,9 +170,6 @@ int QGeoCodingManager::managerVersion() const */ QGeoCodeReply *QGeoCodingManager::geocode(const QGeoAddress &address, const QGeoShape &bounds) { -// if (!d_ptr->engine) -// return new QGeoCodeReply(QGeoCodeReply::EngineNotSetError, "The geocoding manager was not created with a valid engine.", this); - return d_ptr->engine->geocode(address, bounds); } @@ -215,9 +212,6 @@ QGeoCodeReply *QGeoCodingManager::geocode(const QGeoAddress &address, const QGeo */ QGeoCodeReply *QGeoCodingManager::reverseGeocode(const QGeoCoordinate &coordinate, const QGeoShape &bounds) { -// if (!d_ptr->engine) -// return new QGeoCodeReply(QGeoCodeReply::EngineNotSetError, "The geocoding manager was not created with a valid engine.", this); - return d_ptr->engine->reverseGeocode(coordinate, bounds); } @@ -255,9 +249,6 @@ QGeoCodeReply *QGeoCodingManager::geocode(const QString &address, int offset, const QGeoShape &bounds) { -// if (!d_ptr->engine) -// return new QGeoCodeReply(QGeoCodeReply::EngineNotSetError, "The geocoding manager was not created with a valid engine.", this); - QGeoCodeReply *reply = d_ptr->engine->geocode(address, limit, offset, diff --git a/src/location/maps/qgeocodingmanagerengine.cpp b/src/location/maps/qgeocodingmanagerengine.cpp index 97d0f75d..b163d173 100644 --- a/src/location/maps/qgeocodingmanagerengine.cpp +++ b/src/location/maps/qgeocodingmanagerengine.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE \class QGeoCodingManagerEngine \inmodule QtLocation \ingroup QtLocation-impl - \since 5.5 + \since 5.6 \brief The QGeoCodingManagerEngine class provides an interface and convenience methods to implementers of QGeoServiceProvider plugins who want diff --git a/src/location/maps/qgeotilecache.cpp b/src/location/maps/qgeofiletilecache.cpp index aa76735f..3d381dc2 100644 --- a/src/location/maps/qgeotilecache.cpp +++ b/src/location/maps/qgeofiletilecache.cpp @@ -33,7 +33,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "qgeotilecache_p.h" +#include "qgeofiletilecache_p.h" #include "qgeotilespec_p.h" @@ -60,14 +60,11 @@ public: } QGeoTileSpec spec; - QGeoTileCache *cache; + QGeoFileTileCache *cache; QByteArray bytes; QString format; }; -QGeoTileTexture::QGeoTileTexture() - : textureBound(false) {} - void QCache3QTileEvictionPolicy::aboutToBeRemoved(const QGeoTileSpec &key, QSharedPointer<QGeoCachedTileDisk> obj) { Q_UNUSED(key); @@ -88,26 +85,14 @@ QGeoCachedTileDisk::~QGeoCachedTileDisk() cache->evictFromDiskCache(this); } -QGeoTileTexture::~QGeoTileTexture() -{ -} - -QGeoTileCache::QGeoTileCache(const QString &directory, QObject *parent) - : QObject(parent), directory_(directory), +QGeoFileTileCache::QGeoFileTileCache(const QString &directory, QObject *parent) + : QAbstractGeoTileCache(parent), directory_(directory), minTextureUsage_(0), extraTextureUsage_(0) { - qRegisterMetaType<QGeoTileSpec>(); - qRegisterMetaType<QList<QGeoTileSpec> >(); - qRegisterMetaType<QSet<QGeoTileSpec> >(); - - // We keep default values here so that they are in one place - // rather than in each individual plugin (the plugins can - // of course override them) - - const QString basePath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) - + QLatin1String("/QtLocation"); + const QString basePath = baseCacheDirectory(); // delete old tiles from QtLocation 5.4 or prior + // Newer version use plugin-specific subdirectories so those are not affected. // TODO Remove cache cleanup in Qt 6 QDir baseDir(basePath); if (baseDir.exists()) { @@ -118,8 +103,7 @@ QGeoTileCache::QGeoTileCache(const QString &directory, QObject *parent) if (directory_.isEmpty()) { directory_ = basePath; - qWarning() << "Plugin uses uninitialized directory for QGeoTileCache" - " which will was deleted during startup"; + qWarning() << "Plugin uses uninitialized QGeoFileTileCache directory which was deleted during startup"; } QDir::root().mkpath(directory_); @@ -132,7 +116,7 @@ QGeoTileCache::QGeoTileCache(const QString &directory, QObject *parent) loadTiles(); } -void QGeoTileCache::loadTiles() +void QGeoFileTileCache::loadTiles() { QStringList formats; formats << QLatin1String("*.*"); @@ -186,7 +170,7 @@ void QGeoTileCache::loadTiles() } } -QGeoTileCache::~QGeoTileCache() +QGeoFileTileCache::~QGeoFileTileCache() { // write disk cache queues to disk QDir dir(directory_); @@ -212,72 +196,85 @@ QGeoTileCache::~QGeoTileCache() } } -void QGeoTileCache::printStats() +void QGeoFileTileCache::printStats() { textureCache_.printStats(); memoryCache_.printStats(); diskCache_.printStats(); } -void QGeoTileCache::setMaxDiskUsage(int diskUsage) +void QGeoFileTileCache::setMaxDiskUsage(int diskUsage) { diskCache_.setMaxCost(diskUsage); } -int QGeoTileCache::maxDiskUsage() const +int QGeoFileTileCache::maxDiskUsage() const { return diskCache_.maxCost(); } -int QGeoTileCache::diskUsage() const +int QGeoFileTileCache::diskUsage() const { return diskCache_.totalCost(); } -void QGeoTileCache::setMaxMemoryUsage(int memoryUsage) +void QGeoFileTileCache::setMaxMemoryUsage(int memoryUsage) { memoryCache_.setMaxCost(memoryUsage); } -int QGeoTileCache::maxMemoryUsage() const +int QGeoFileTileCache::maxMemoryUsage() const { return memoryCache_.maxCost(); } -int QGeoTileCache::memoryUsage() const +int QGeoFileTileCache::memoryUsage() const { return memoryCache_.totalCost(); } -void QGeoTileCache::setExtraTextureUsage(int textureUsage) +void QGeoFileTileCache::setExtraTextureUsage(int textureUsage) { extraTextureUsage_ = textureUsage; textureCache_.setMaxCost(minTextureUsage_ + extraTextureUsage_); } -void QGeoTileCache::setMinTextureUsage(int textureUsage) +void QGeoFileTileCache::setMinTextureUsage(int textureUsage) { minTextureUsage_ = textureUsage; textureCache_.setMaxCost(minTextureUsage_ + extraTextureUsage_); } -int QGeoTileCache::maxTextureUsage() const +int QGeoFileTileCache::maxTextureUsage() const { return textureCache_.maxCost(); } -int QGeoTileCache::minTextureUsage() const +int QGeoFileTileCache::minTextureUsage() const { return minTextureUsage_; } -int QGeoTileCache::textureUsage() const +int QGeoFileTileCache::textureUsage() const { return textureCache_.totalCost(); } -QSharedPointer<QGeoTileTexture> QGeoTileCache::get(const QGeoTileSpec &spec) +void QGeoFileTileCache::clearAll() +{ + textureCache_.clear(); + memoryCache_.clear(); + diskCache_.clear(); + QDir dir(directory_); + dir.setNameFilters(QStringList() << QLatin1String("*-*-*-*.*")); + dir.setFilter(QDir::Files); + foreach (QString dirFile, dir.entryList()) { + dir.remove(dirFile); + } +} + +QSharedPointer<QGeoTileTexture> QGeoFileTileCache::get(const QGeoTileSpec &spec) { QSharedPointer<QGeoTileTexture> tt = textureCache_.object(spec); if (tt) @@ -285,32 +282,32 @@ QSharedPointer<QGeoTileTexture> QGeoTileCache::get(const QGeoTileSpec &spec) QSharedPointer<QGeoCachedTileMemory> tm = memoryCache_.object(spec); if (tm) { - QPixmap pixmap; - if (!pixmap.loadFromData(tm->bytes)) { + QImage image; + if (!image.loadFromData(tm->bytes)) { handleError(spec, QLatin1String("Problem with tile image")); return QSharedPointer<QGeoTileTexture>(0); } - QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, pixmap); + QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, image); if (tt) return tt; } QSharedPointer<QGeoCachedTileDisk> td = diskCache_.object(spec); if (td) { - QStringList parts = td->filename.split('.'); + const QString format = QFileInfo(td->filename).suffix(); QFile file(td->filename); file.open(QIODevice::ReadOnly); QByteArray bytes = file.readAll(); file.close(); - QPixmap pixmap; - if (!pixmap.loadFromData(bytes, (parts.size() == 2 ? parts.at(1).toLocal8Bit().constData() : 0))) { + QImage image; + if (!image.loadFromData(bytes)) { handleError(spec, QLatin1String("Problem with tile image")); return QSharedPointer<QGeoTileTexture>(0); } - addToMemoryCache(spec, bytes, (parts.size() == 2 ? parts.at(1) : QLatin1String(""))); - QSharedPointer<QGeoTileTexture> tt = addToTextureCache(td->spec, pixmap); + addToMemoryCache(spec, bytes, format); + QSharedPointer<QGeoTileTexture> tt = addToTextureCache(td->spec, image); if (tt) return tt; } @@ -318,16 +315,14 @@ QSharedPointer<QGeoTileTexture> QGeoTileCache::get(const QGeoTileSpec &spec) return QSharedPointer<QGeoTileTexture>(); } -QString QGeoTileCache::directory() const -{ - return directory_; -} - -void QGeoTileCache::insert(const QGeoTileSpec &spec, +void QGeoFileTileCache::insert(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format, QGeoTiledMappingManagerEngine::CacheAreas areas) { + if (bytes.isEmpty()) + return; + if (areas & QGeoTiledMappingManagerEngine::DiskCache) { QString filename = tileSpecToFilename(spec, format, directory_); QFile file(filename); @@ -347,16 +342,16 @@ void QGeoTileCache::insert(const QGeoTileSpec &spec, * and act as a poison */ } -void QGeoTileCache::evictFromDiskCache(QGeoCachedTileDisk *td) +void QGeoFileTileCache::evictFromDiskCache(QGeoCachedTileDisk *td) { QFile::remove(td->filename); } -void QGeoTileCache::evictFromMemoryCache(QGeoCachedTileMemory * /* tm */) +void QGeoFileTileCache::evictFromMemoryCache(QGeoCachedTileMemory * /* tm */) { } -QSharedPointer<QGeoCachedTileDisk> QGeoTileCache::addToDiskCache(const QGeoTileSpec &spec, const QString &filename) +QSharedPointer<QGeoCachedTileDisk> QGeoFileTileCache::addToDiskCache(const QGeoTileSpec &spec, const QString &filename) { QSharedPointer<QGeoCachedTileDisk> td(new QGeoCachedTileDisk); td->spec = spec; @@ -369,7 +364,7 @@ QSharedPointer<QGeoCachedTileDisk> QGeoTileCache::addToDiskCache(const QGeoTileS return td; } -QSharedPointer<QGeoCachedTileMemory> QGeoTileCache::addToMemoryCache(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format) +QSharedPointer<QGeoCachedTileMemory> QGeoFileTileCache::addToMemoryCache(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format) { QSharedPointer<QGeoCachedTileMemory> tm(new QGeoCachedTileMemory); tm->spec = spec; @@ -383,24 +378,19 @@ QSharedPointer<QGeoCachedTileMemory> QGeoTileCache::addToMemoryCache(const QGeoT return tm; } -QSharedPointer<QGeoTileTexture> QGeoTileCache::addToTextureCache(const QGeoTileSpec &spec, const QPixmap &pixmap) +QSharedPointer<QGeoTileTexture> QGeoFileTileCache::addToTextureCache(const QGeoTileSpec &spec, const QImage &image) { QSharedPointer<QGeoTileTexture> tt(new QGeoTileTexture); tt->spec = spec; - tt->image = pixmap.toImage(); + tt->image = image; - int textureCost = tt->image.width() * tt->image.height() * tt->image.depth() / 8; + int textureCost = image.width() * image.height() * image.depth() / 8; textureCache_.insert(spec, tt, textureCost); return tt; } -void QGeoTileCache::handleError(const QGeoTileSpec &, const QString &error) -{ - qWarning() << "tile request error " << error; -} - -QString QGeoTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) +QString QGeoFileTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) { QString filename = spec.plugin(); filename += QLatin1String("-"); @@ -426,7 +416,7 @@ QString QGeoTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QStrin return dir.filePath(filename); } -QGeoTileSpec QGeoTileCache::filenameToTileSpec(const QString &filename) +QGeoTileSpec QGeoFileTileCache::filenameToTileSpec(const QString &filename) { QGeoTileSpec emptySpec; @@ -465,4 +455,9 @@ QGeoTileSpec QGeoTileCache::filenameToTileSpec(const QString &filename) numbers.at(4)); } +QString QGeoFileTileCache::directory() const +{ + return directory_; +} + QT_END_NAMESPACE diff --git a/src/location/maps/qgeotilecache_p.h b/src/location/maps/qgeofiletilecache_p.h index 9cf31db0..bd3e684b 100644 --- a/src/location/maps/qgeotilecache_p.h +++ b/src/location/maps/qgeofiletilecache_p.h @@ -33,8 +33,8 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef QGEOTILECACHE_P_H -#define QGEOTILECACHE_P_H +#ifndef QGEOFILETILECACHE_P_H +#define QGEOFILETILECACHE_P_H // // W A R N I N G @@ -58,6 +58,7 @@ #include "qgeotilespec_p.h" #include "qgeotiledmappingmanagerengine_p.h" +#include "qabstractgeotilecache_p.h" #include <QImage> @@ -67,12 +68,12 @@ class QGeoMappingManager; class QGeoTile; class QGeoCachedTileMemory; -class QGeoTileCache; +class QGeoFileTileCache; class QPixmap; class QThread; -/* This would be internal to qgeotilecache.cpp except that the eviction +/* This would be internal to qgeofiletilecache.cpp except that the eviction * policy can't be defined without it being concrete here */ class QGeoCachedTileDisk { @@ -82,20 +83,7 @@ public: QGeoTileSpec spec; QString filename; QString format; - QGeoTileCache *cache; -}; - -/* This is also used in the mapgeometry */ -class Q_LOCATION_EXPORT QGeoTileTexture -{ -public: - - QGeoTileTexture(); - ~QGeoTileTexture(); - - QGeoTileSpec spec; - QImage image; - bool textureBound; + QGeoFileTileCache *cache; }; /* Custom eviction policy for the disk cache, to avoid deleting all the files @@ -107,29 +95,29 @@ protected: void aboutToBeEvicted(const QGeoTileSpec &key, QSharedPointer<QGeoCachedTileDisk> obj); }; -class Q_LOCATION_EXPORT QGeoTileCache : public QObject +class Q_LOCATION_EXPORT QGeoFileTileCache : public QAbstractGeoTileCache { Q_OBJECT public: - QGeoTileCache(const QString &directory = QString(), QObject *parent = 0); - ~QGeoTileCache(); + QGeoFileTileCache(const QString &directory = QString(), QObject *parent = 0); + ~QGeoFileTileCache(); - void setMaxDiskUsage(int diskUsage); - int maxDiskUsage() const; - int diskUsage() const; + void setMaxDiskUsage(int diskUsage) Q_DECL_OVERRIDE; + int maxDiskUsage() const Q_DECL_OVERRIDE; + int diskUsage() const Q_DECL_OVERRIDE; - void setMaxMemoryUsage(int memoryUsage); - int maxMemoryUsage() const; - int memoryUsage() const; + void setMaxMemoryUsage(int memoryUsage) Q_DECL_OVERRIDE; + int maxMemoryUsage() const Q_DECL_OVERRIDE; + int memoryUsage() const Q_DECL_OVERRIDE; - void setMinTextureUsage(int textureUsage); - void setExtraTextureUsage(int textureUsage); - int maxTextureUsage() const; - int minTextureUsage() const; - int textureUsage() const; + void setMinTextureUsage(int textureUsage) Q_DECL_OVERRIDE; + void setExtraTextureUsage(int textureUsage) Q_DECL_OVERRIDE; + int maxTextureUsage() const Q_DECL_OVERRIDE; + int minTextureUsage() const Q_DECL_OVERRIDE; + int textureUsage() const Q_DECL_OVERRIDE; + void clearAll() Q_DECL_OVERRIDE; - QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec); - QString directory() const; + QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec) Q_DECL_OVERRIDE; // can be called without a specific tileCache pointer static void evictFromDiskCache(QGeoCachedTileDisk *td); @@ -138,31 +126,31 @@ public: void insert(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format, - QGeoTiledMappingManagerEngine::CacheAreas areas = QGeoTiledMappingManagerEngine::AllCaches); - void handleError(const QGeoTileSpec &spec, const QString &errorString); - -public Q_SLOTS: - void printStats(); + QGeoTiledMappingManagerEngine::CacheAreas areas = QGeoTiledMappingManagerEngine::AllCaches) Q_DECL_OVERRIDE; private: + void printStats() Q_DECL_OVERRIDE; void loadTiles(); + QString directory() const; + QSharedPointer<QGeoCachedTileDisk> addToDiskCache(const QGeoTileSpec &spec, const QString &filename); QSharedPointer<QGeoCachedTileMemory> addToMemoryCache(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format); - QSharedPointer<QGeoTileTexture> addToTextureCache(const QGeoTileSpec &spec, const QPixmap &pixmap); + QSharedPointer<QGeoTileTexture> addToTextureCache(const QGeoTileSpec &spec, const QImage &image); static QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory); static QGeoTileSpec filenameToTileSpec(const QString &filename); - QString directory_; QCache3Q<QGeoTileSpec, QGeoCachedTileDisk, QCache3QTileEvictionPolicy > diskCache_; QCache3Q<QGeoTileSpec, QGeoCachedTileMemory > memoryCache_; QCache3Q<QGeoTileSpec, QGeoTileTexture > textureCache_; + QString directory_; + int minTextureUsage_; int extraTextureUsage_; }; QT_END_NAMESPACE -#endif // QGEOTILECACHE_P_H +#endif // QGEOFILETILECACHE_P_H diff --git a/src/location/maps/qgeomaneuver.cpp b/src/location/maps/qgeomaneuver.cpp index 679390ed..f38cb293 100644 --- a/src/location/maps/qgeomaneuver.cpp +++ b/src/location/maps/qgeomaneuver.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE \class QGeoManeuver \inmodule QtLocation \ingroup QtLocation-routing - \since 5.5 + \since 5.6 \brief The QGeoManeuver class represents the information relevant to the point at which two QGeoRouteSegments meet. diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index f6f8d5e2..37bf139a 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -109,6 +109,7 @@ void QGeoMap::setActiveMapType(const QGeoMapType type) d->m_activeMapType = type; d->changeActiveMapType(type); d->setCameraData(d->m_cameraData); + emit activeMapTypeChanged(); update(); } @@ -118,12 +119,6 @@ const QGeoMapType QGeoMap::activeMapType() const return d->m_activeMapType; } -QString QGeoMap::pluginString() -{ - Q_D(const QGeoMap); - return d->m_pluginString; -} - QGeoCameraCapabilities QGeoMap::cameraCapabilities() { Q_D(const QGeoMap); @@ -133,12 +128,12 @@ QGeoCameraCapabilities QGeoMap::cameraCapabilities() return QGeoCameraCapabilities(); } -int QGeoMap::mapVersion() +void QGeoMap::prefetchData() { - return -1; + } -void QGeoMap::prefetchData() +void QGeoMap::clearData() { } @@ -152,9 +147,6 @@ QGeoMapPrivate::QGeoMapPrivate(QGeoMappingManagerEngine *engine) m_controller(0), m_activeMapType(QGeoMapType()) { - if (!m_engine.isNull()) { - m_pluginString = m_engine->managerName() + QLatin1Char('_') + QString::number(m_engine->managerVersion()); - } } QGeoMapPrivate::~QGeoMapPrivate() diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index 9e4d5a0d..acc928ea 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -83,12 +83,12 @@ public: virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0; virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0; - virtual int mapVersion(); virtual void prefetchData(); + virtual void clearData(); - QString pluginString(); QGeoCameraCapabilities cameraCapabilities(); + protected: QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0); void setCameraData(const QGeoCameraData &cameraData); diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h index e7a23060..3b996ecc 100644 --- a/src/location/maps/qgeomap_p_p.h +++ b/src/location/maps/qgeomap_p_p.h @@ -78,7 +78,6 @@ protected: int m_height; double m_aspectRatio; QPointer<QGeoMappingManagerEngine> m_engine; - QString m_pluginString; QGeoMapController *m_controller; QGeoCameraData m_cameraData; QGeoMapType m_activeMapType; diff --git a/src/location/maps/qgeomappingmanager.cpp b/src/location/maps/qgeomappingmanager.cpp index d009bbdd..681e68a7 100644 --- a/src/location/maps/qgeomappingmanager.cpp +++ b/src/location/maps/qgeomappingmanager.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE \class QGeoMappingManager \inmodule QtLocation \ingroup QtLocation-maps - \since 5.5 + \since 5.6 \internal \brief The QGeoMappingManager class provides support for displaying diff --git a/src/location/maps/qgeomappingmanagerengine.cpp b/src/location/maps/qgeomappingmanagerengine.cpp index 9129e69b..70b1e836 100644 --- a/src/location/maps/qgeomappingmanagerengine.cpp +++ b/src/location/maps/qgeomappingmanagerengine.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE \class QGeoMappingManagerEngine \inmodule QtLocation \ingroup QtLocation-impl - \since 5.5 + \since 5.6 \internal \brief Provides support functionality for map display with QGeoServiceProvider. diff --git a/src/location/maps/qgeomappingmanagerengine_p.h b/src/location/maps/qgeomappingmanagerengine_p.h index b9565d87..7e866d89 100644 --- a/src/location/maps/qgeomappingmanagerengine_p.h +++ b/src/location/maps/qgeomappingmanagerengine_p.h @@ -81,8 +81,6 @@ public: virtual ~QGeoMappingManagerEngine(); virtual QGeoMap *createMap() = 0; - virtual void registerMap(QGeoMap *map) = 0; - virtual void deregisterMap(QGeoMap *map) = 0; QVariantMap parameters() const; diff --git a/src/location/maps/qgeomapscene.cpp b/src/location/maps/qgeomapscene.cpp index a448937b..4a457005 100644 --- a/src/location/maps/qgeomapscene.cpp +++ b/src/location/maps/qgeomapscene.cpp @@ -36,7 +36,7 @@ ****************************************************************************/ #include "qgeomapscene_p.h" #include "qgeocameradata_p.h" -#include "qgeotilecache_p.h" +#include "qabstractgeotilecache_p.h" #include "qgeotilespec_p.h" #include <QtPositioning/private/qdoublevector3d_p.h> #include <QtCore/private/qobject_p.h> @@ -156,6 +156,12 @@ void QGeoMapScene::setVisibleTiles(const QSet<QGeoTileSpec> &tiles) d->setVisibleTiles(tiles); } +const QSet<QGeoTileSpec> &QGeoMapScene::visibleTiles() const +{ + Q_D(const QGeoMapScene); + return d->m_visibleTiles; +} + void QGeoMapScene::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture) { Q_D(QGeoMapScene); @@ -325,14 +331,8 @@ void QGeoMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoT m_textures.insert(spec, texture); } -// return true if new tiles introduced in [tiles] void QGeoMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &tiles) { - Q_Q(QGeoMapScene); - - // detect if new tiles introduced - bool newTilesIntroduced = !m_visibleTiles.contains(tiles); - // work out the tile bounds for the new scene setTileBounds(tiles); @@ -344,8 +344,6 @@ void QGeoMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &tiles) removeTiles(toRemove); m_visibleTiles = tiles; - if (newTilesIntroduced) - emit q->newTilesVisible(m_visibleTiles); } void QGeoMapScenePrivate::removeTiles(const QSet<QGeoTileSpec> &oldTiles) @@ -584,7 +582,7 @@ public: ~QGeoMapRootNode() { - qDeleteAll(textures.values()); + qDeleteAll(textures); } void setClipRect(const QRect &rect) diff --git a/src/location/maps/qgeomapscene_p.h b/src/location/maps/qgeomapscene_p.h index a4a9e4e4..34d4a11f 100644 --- a/src/location/maps/qgeomapscene_p.h +++ b/src/location/maps/qgeomapscene_p.h @@ -73,6 +73,7 @@ public: void setCameraData(const QGeoCameraData &cameraData); void setVisibleTiles(const QSet<QGeoTileSpec> &tiles); + const QSet<QGeoTileSpec> &visibleTiles() const; void setUseVerticalLock(bool lock); diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp index 2406ee86..52fa4a5e 100644 --- a/src/location/maps/qgeoroute.cpp +++ b/src/location/maps/qgeoroute.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE \class QGeoRoute \inmodule QtLocation \ingroup QtLocation-routing - \since 5.5 + \since 5.6 \brief The QGeoRoute class represents a route between two points. diff --git a/src/location/maps/qgeoroutereply.cpp b/src/location/maps/qgeoroutereply.cpp index 99b4f2f3..ab869d3c 100644 --- a/src/location/maps/qgeoroutereply.cpp +++ b/src/location/maps/qgeoroutereply.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE \class QGeoRouteReply \inmodule QtLocation \ingroup QtLocation-routing - \since 5.5 + \since 5.6 \brief The QGeoRouteReply class manages an operation started by an instance of QGeoRoutingManager. diff --git a/src/location/maps/qgeorouterequest.cpp b/src/location/maps/qgeorouterequest.cpp index e01cbe46..369606ea 100644 --- a/src/location/maps/qgeorouterequest.cpp +++ b/src/location/maps/qgeorouterequest.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE \class QGeoRouteRequest \inmodule QtLocation \ingroup QtLocation-routing - \since 5.5 + \since 5.6 \brief The QGeoRouteRequest class represents the parameters and restrictions which define a request for routing information. diff --git a/src/location/maps/qgeoroutesegment.cpp b/src/location/maps/qgeoroutesegment.cpp index bee136eb..45c2cc69 100644 --- a/src/location/maps/qgeoroutesegment.cpp +++ b/src/location/maps/qgeoroutesegment.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE \class QGeoRouteSegment \inmodule QtLocation \ingroup QtLocation-routing - \since 5.5 + \since 5.6 \brief The QGeoRouteSegment class represents a segment of a route. diff --git a/src/location/maps/qgeoroutingmanager.cpp b/src/location/maps/qgeoroutingmanager.cpp index 18e6fa04..8eca6719 100644 --- a/src/location/maps/qgeoroutingmanager.cpp +++ b/src/location/maps/qgeoroutingmanager.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE \class QGeoRoutingManager \inmodule QtLocation \ingroup QtLocation-routing - \since 5.5 + \since 5.6 \brief The QGeoRoutingManager class provides support for geographic routing operations. diff --git a/src/location/maps/qgeoroutingmanagerengine.cpp b/src/location/maps/qgeoroutingmanagerengine.cpp index e59f89b2..9c552682 100644 --- a/src/location/maps/qgeoroutingmanagerengine.cpp +++ b/src/location/maps/qgeoroutingmanagerengine.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE \class QGeoRoutingManagerEngine \inmodule QtLocation \ingroup QtLocation-impl - \since 5.5 + \since 5.6 \brief The QGeoRoutingManagerEngine class provides an interface and convenience methods to implementers of QGeoServiceProvider plugins who want diff --git a/src/location/maps/qgeoserviceprovider.cpp b/src/location/maps/qgeoserviceprovider.cpp index 4056662c..b1b9cb86 100644 --- a/src/location/maps/qgeoserviceprovider.cpp +++ b/src/location/maps/qgeoserviceprovider.cpp @@ -75,7 +75,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, \class QGeoServiceProvider \inmodule QtLocation \ingroup QtLocation-common - \since 5.5 + \since 5.6 \brief The QGeoServiceProvider class aggregates access to services which provide geographical information. diff --git a/src/location/maps/qgeoserviceproviderfactory.cpp b/src/location/maps/qgeoserviceproviderfactory.cpp index 4a1a46fd..7efc8a9f 100644 --- a/src/location/maps/qgeoserviceproviderfactory.cpp +++ b/src/location/maps/qgeoserviceproviderfactory.cpp @@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE \class QGeoServiceProviderFactory \inmodule QtLocation \ingroup QtLocation-impl - \since 5.5 + \since 5.6 \brief The QGeoServiceProviderFactory class is a factory class used as the plugin interface for services related to geographical information. diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index 60e27d8e..97747049 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -37,7 +37,7 @@ #include "qgeotiledmap_p_p.h" #include "qgeotiledmappingmanagerengine_p.h" -#include "qgeotilecache_p.h" +#include "qabstractgeotilecache_p.h" #include "qgeotilespec_p.h" #include "qgeocameratiles_p.h" @@ -56,15 +56,8 @@ QGeoTiledMap::QGeoTiledMap(QGeoTiledMappingManagerEngine *engine, QObject *paren d->m_tileRequests = new QGeoTileRequestManager(this, engine); - QObject::connect(d->m_mapScene, - SIGNAL(newTilesVisible(QSet<QGeoTileSpec>)), - this, - SLOT(evaluateCopyrights(QSet<QGeoTileSpec>))); - QObject::connect(engine, - SIGNAL(mapVersionChanged()), - this, - SLOT(updateMapVersion())); - QMetaObject::invokeMethod(this, "updateMapVersion", Qt::QueuedConnection); + QObject::connect(engine,&QGeoTiledMappingManagerEngine::tileVersionChanged, + this,&QGeoTiledMap::handleTileVersionChanged); } QGeoTiledMap::~QGeoTiledMap() @@ -72,6 +65,12 @@ QGeoTiledMap::~QGeoTiledMap() Q_D(QGeoTiledMap); delete d->m_tileRequests; d->m_tileRequests = 0; + + if (!d->m_engine.isNull()) { + QGeoTiledMappingManagerEngine *engine = qobject_cast<QGeoTiledMappingManagerEngine*>(d->m_engine); + Q_ASSERT(engine); + engine->releaseMap(this); + } } QGeoTileRequestManager *QGeoTiledMap::requestManager() @@ -86,7 +85,7 @@ void QGeoTiledMap::updateTile(const QGeoTileSpec &spec) d->updateTile(spec); } -QGeoTileCache *QGeoTiledMap::tileCache() +QAbstractGeoTileCache *QGeoTiledMap::tileCache() { Q_D(QGeoTiledMap); return d->m_cache; @@ -104,10 +103,20 @@ void QGeoTiledMap::prefetchData() d->prefetchTiles(); } -void QGeoTiledMap::updateMapVersion() +void QGeoTiledMap::clearData() +{ + Q_D(QGeoTiledMap); + d->m_cache->clearAll(); +} + +void QGeoTiledMap::handleTileVersionChanged() { Q_D(QGeoTiledMap); - d->changeMapVersion(mapVersion()); + if (!d->m_engine.isNull()) { + QGeoTiledMappingManagerEngine* engine = qobject_cast<QGeoTiledMappingManagerEngine*>(d->m_engine); + Q_ASSERT(engine); + d->changeTileVersion(engine->tileVersion()); + } } void QGeoTiledMap::evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles) @@ -154,8 +163,7 @@ QGeoTiledMapPrivate::QGeoTiledMapPrivate(QGeoTiledMappingManagerEngine *engine) { m_cameraTiles->setMaximumZoomLevel(static_cast<int>(std::ceil(engine->cameraCapabilities().maximumZoomLevel()))); m_cameraTiles->setTileSize(engine->tileSize().width()); - m_cameraTiles->setPluginString(m_pluginString); - + m_cameraTiles->setPluginString(engine->managerName() + QLatin1Char('_') + QString::number(engine->managerVersion())); m_mapScene->setTileSize(engine->tileSize().width()); } @@ -202,23 +210,32 @@ void QGeoTiledMapPrivate::changeCameraData(const QGeoCameraData &oldCameraData) cam.setZoomLevel(izl); } - m_cameraTiles->setCamera(cam); - + m_cameraTiles->setCameraData(cam); m_mapScene->setCameraData(cam); - m_mapScene->setVisibleTiles(m_cameraTiles->visibleTiles()); + updateScene(); +} + +void QGeoTiledMapPrivate::updateScene() +{ + Q_Q(QGeoTiledMap); + // detect if new tiles introduced + const QSet<QGeoTileSpec>& tiles = m_cameraTiles->visibleTiles(); + bool newTilesIntroduced = !m_mapScene->visibleTiles().contains(tiles); + m_mapScene->setVisibleTiles(tiles); - if (m_tileRequests) { - // don't request tiles that are already built and textured - QList<QSharedPointer<QGeoTileTexture> > cachedTiles = - m_tileRequests->requestTiles(m_cameraTiles->visibleTiles() - m_mapScene->texturedTiles()); + if (newTilesIntroduced) + q->evaluateCopyrights(tiles); - foreach (const QSharedPointer<QGeoTileTexture> &tex, cachedTiles) { - m_mapScene->addTile(tex->spec, tex); - } + // don't request tiles that are already built and textured + QList<QSharedPointer<QGeoTileTexture> > cachedTiles = + m_tileRequests->requestTiles(m_cameraTiles->visibleTiles() - m_mapScene->texturedTiles()); - if (!cachedTiles.isEmpty()) - q->update(); + foreach (const QSharedPointer<QGeoTileTexture> &tex, cachedTiles) { + m_mapScene->addTile(tex->spec, tex); } + + if (!cachedTiles.isEmpty()) + q->update(); } void QGeoTiledMapPrivate::changeActiveMapType(const QGeoMapType mapType) @@ -226,9 +243,10 @@ void QGeoTiledMapPrivate::changeActiveMapType(const QGeoMapType mapType) m_cameraTiles->setMapType(mapType); } -void QGeoTiledMapPrivate::changeMapVersion(int mapVersion) +void QGeoTiledMapPrivate::changeTileVersion(int version) { - m_cameraTiles->setMapVersion(mapVersion); + m_cameraTiles->setMapVersion(version); + updateScene(); } void QGeoTiledMapPrivate::mapResized(int width, int height) diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h index 2dbf1754..87dac5d1 100644 --- a/src/location/maps/qgeotiledmap_p.h +++ b/src/location/maps/qgeotiledmap_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE class QGeoTileSpec; class QGeoTileTexture; -class QGeoTileCache; +class QAbstractGeoTileCache; class QGeoTiledMapPrivate; class QGeoTiledMappingManagerEngine; class QGeoTileRequestManager; @@ -79,21 +79,21 @@ public: QGeoTiledMap(QGeoTiledMappingManagerEngine *engine, QObject *parent); virtual ~QGeoTiledMap(); - QGeoTileCache *tileCache(); + QAbstractGeoTileCache *tileCache(); QGeoTileRequestManager *requestManager(); void updateTile(const QGeoTileSpec &spec); QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const Q_DECL_OVERRIDE; QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const Q_DECL_OVERRIDE; void prefetchData() Q_DECL_OVERRIDE; - + void clearData() Q_DECL_OVERRIDE; protected: QSGNode *updateSceneGraph(QSGNode *, QQuickWindow *window) Q_DECL_OVERRIDE; - -protected Q_SLOTS: virtual void evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles); - void updateMapVersion(); + +private Q_SLOTS: + void handleTileVersionChanged(); private: Q_DISABLE_COPY(QGeoTiledMap) diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h index bd4b4c05..2e93a006 100644 --- a/src/location/maps/qgeotiledmap_p_p.h +++ b/src/location/maps/qgeotiledmap_p_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE class QGeoCameraTiles; class QGeoMapScene; -class QGeoTileCache; +class QAbstractGeoTileCache; class QGeoTiledMappingManagerEngine; class QGeoTiledMap; class QGeoTileRequestManager; @@ -74,8 +74,6 @@ public: ~QGeoTiledMapPrivate(); QSGNode *updateSceneGraph(QSGNode *node, QQuickWindow *window); - - void changeMapVersion(int mapVersion); void resized(int width, int height); QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos) const; @@ -88,9 +86,13 @@ protected: void mapResized(int width, int height) Q_DECL_OVERRIDE; void changeCameraData(const QGeoCameraData &oldCameraData) Q_DECL_OVERRIDE; void changeActiveMapType(const QGeoMapType mapType) Q_DECL_OVERRIDE; + void changeTileVersion(int version); + +private: + void updateScene(); private: - QGeoTileCache *m_cache; + QAbstractGeoTileCache *m_cache; QGeoCameraTiles *m_cameraTiles; QGeoMapScene *m_mapScene; QGeoTileRequestManager *m_tileRequests; diff --git a/src/location/maps/qgeotiledmappingmanagerengine.cpp b/src/location/maps/qgeotiledmappingmanagerengine.cpp index 96758854..4e777ab2 100644 --- a/src/location/maps/qgeotiledmappingmanagerengine.cpp +++ b/src/location/maps/qgeotiledmappingmanagerengine.cpp @@ -41,7 +41,7 @@ #include "qgeotiledmap_p.h" #include "qgeotilerequestmanager_p.h" -#include "qgeotilecache_p.h" +#include "qgeofiletilecache_p.h" #include "qgeotilespec_p.h" #include <QTimer> @@ -99,24 +99,8 @@ QGeoMap *QGeoTiledMappingManagerEngine::createMap() return NULL; } -void QGeoTiledMappingManagerEngine::registerMap(QGeoMap *m) +void QGeoTiledMappingManagerEngine::releaseMap(QGeoTiledMap *map) { - QGeoTiledMap* map = qobject_cast<QGeoTiledMap*>(m); - if (!map) { - qWarning() << "QGeoTiledMappingManagerEngine can only register QGeoTiledMap"; - return; - } - d_ptr->tileMaps_.insert(map); -} - -void QGeoTiledMappingManagerEngine::deregisterMap(QGeoMap *m) -{ - QGeoTiledMap* map = qobject_cast<QGeoTiledMap*>(m); - if (!map) { - qWarning() << "QGeoTiledMappingManagerEngine can only deregister QGeoTiledMap"; - return; - } - d_ptr->tileMaps_.remove(map); d_ptr->mapHash_.remove(map); QHash<QGeoTileSpec, QSet<QGeoTiledMap *> > newTileHash = d_ptr->tileHash_; @@ -217,7 +201,6 @@ void QGeoTiledMappingManagerEngine::engineTileFinished(const QGeoTileSpec &spec, } d->tileHash_.remove(spec); - tileCache()->insert(spec, bytes, format, d->cacheHint_); map = maps.constBegin(); @@ -259,12 +242,27 @@ void QGeoTiledMappingManagerEngine::setTileSize(const QSize &tileSize) d->tileSize_ = tileSize; } +void QGeoTiledMappingManagerEngine::setTileVersion(int version) +{ + Q_D(QGeoTiledMappingManagerEngine); + if (d->m_tileVersion != version) { + d->m_tileVersion = version; + emit tileVersionChanged(); + } +} + QSize QGeoTiledMappingManagerEngine::tileSize() const { Q_D(const QGeoTiledMappingManagerEngine); return d->tileSize_; } +int QGeoTiledMappingManagerEngine::tileVersion() const +{ + Q_D(const QGeoTiledMappingManagerEngine); + return d->m_tileVersion; +} + QGeoTiledMappingManagerEngine::CacheAreas QGeoTiledMappingManagerEngine::cacheHint() const { Q_D(const QGeoTiledMappingManagerEngine); @@ -277,24 +275,21 @@ void QGeoTiledMappingManagerEngine::setCacheHint(QGeoTiledMappingManagerEngine:: d->cacheHint_ = cacheHint; } -QGeoTileCache *QGeoTiledMappingManagerEngine::createTileCacheWithDir(const QString &cacheDirectory) +void QGeoTiledMappingManagerEngine::setTileCache(QAbstractGeoTileCache *cache) { Q_D(QGeoTiledMappingManagerEngine); Q_ASSERT_X(!d->tileCache_, Q_FUNC_INFO, "This should be called only once"); - d->tileCache_ = new QGeoTileCache(cacheDirectory); - return d->tileCache_; + d->tileCache_ = cache; } -QGeoTileCache *QGeoTiledMappingManagerEngine::tileCache() +QAbstractGeoTileCache *QGeoTiledMappingManagerEngine::tileCache() { Q_D(QGeoTiledMappingManagerEngine); if (!d->tileCache_) { QString cacheDirectory; - if (!managerName().isEmpty()) { - cacheDirectory = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) - + QLatin1String("/QtLocation/") + managerName(); - } - d->tileCache_ = new QGeoTileCache(cacheDirectory); + if (!managerName().isEmpty()) + cacheDirectory = QAbstractGeoTileCache::baseCacheDirectory() + managerName(); + d->tileCache_ = new QGeoFileTileCache(cacheDirectory); } return d->tileCache_; } @@ -308,7 +303,10 @@ QSharedPointer<QGeoTileTexture> QGeoTiledMappingManagerEngine::getTileTexture(co *******************************************************************************/ QGeoTiledMappingManagerEnginePrivate::QGeoTiledMappingManagerEnginePrivate() -: cacheHint_(QGeoTiledMappingManagerEngine::AllCaches), tileCache_(0), fetcher_(0) +: m_tileVersion(-1), + cacheHint_(QGeoTiledMappingManagerEngine::AllCaches), + tileCache_(0), + fetcher_(0) { } diff --git a/src/location/maps/qgeotiledmappingmanagerengine_p.h b/src/location/maps/qgeotiledmappingmanagerengine_p.h index 6cc4caea..86c5b63c 100644 --- a/src/location/maps/qgeotiledmappingmanagerengine_p.h +++ b/src/location/maps/qgeotiledmappingmanagerengine_p.h @@ -37,6 +37,17 @@ #ifndef QGEOTILEDMAPPINGMANAGERENGINE_H #define QGEOTILEDMAPPINGMANAGERENGINE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QObject> #include <QSize> #include <QPair> @@ -53,7 +64,7 @@ class QGeoTileTexture; class QGeoTileSpec; class QGeoTiledMap; -class QGeoTileCache; +class QAbstractGeoTileCache; class Q_LOCATION_EXPORT QGeoTiledMappingManagerEngine : public QGeoMappingManagerEngine { @@ -73,16 +84,16 @@ public: QGeoTileFetcher *tileFetcher(); QGeoMap *createMap() Q_DECL_OVERRIDE; - void registerMap(QGeoMap *map) Q_DECL_OVERRIDE; - void deregisterMap(QGeoMap *map) Q_DECL_OVERRIDE; + void releaseMap(QGeoTiledMap *map); QSize tileSize() const; + int tileVersion() const; void updateTileRequests(QGeoTiledMap *map, const QSet<QGeoTileSpec> &tilesAdded, const QSet<QGeoTileSpec> &tilesRemoved); - QGeoTileCache *tileCache(); // TODO: check this is still used + QAbstractGeoTileCache *tileCache(); QSharedPointer<QGeoTileTexture> getTileTexture(const QGeoTileSpec &spec); @@ -94,14 +105,14 @@ private Q_SLOTS: Q_SIGNALS: void tileError(const QGeoTileSpec &spec, const QString &errorString); - void mapVersionChanged(); + void tileVersionChanged(); protected: void setTileFetcher(QGeoTileFetcher *fetcher); void setTileSize(const QSize &tileSize); + void setTileVersion(int version); void setCacheHint(QGeoTiledMappingManagerEngine::CacheAreas cacheHint); - - QGeoTileCache *createTileCacheWithDir(const QString &cacheDirectory); + void setTileCache(QAbstractGeoTileCache *cache); private: QGeoTiledMappingManagerEnginePrivate *d_ptr; diff --git a/src/location/maps/qgeotiledmappingmanagerengine_p_p.h b/src/location/maps/qgeotiledmappingmanagerengine_p_p.h index 77e84e85..86ad0f08 100644 --- a/src/location/maps/qgeotiledmappingmanagerengine_p_p.h +++ b/src/location/maps/qgeotiledmappingmanagerengine_p_p.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE class QGeoTiledMap; -class QGeoTileCache; +class QAbstractGeoTileCache; class QGeoTileSpec; class QGeoTileFetcher; @@ -68,11 +68,11 @@ public: ~QGeoTiledMappingManagerEnginePrivate(); QSize tileSize_; - QSet<QGeoTiledMap *> tileMaps_; + int m_tileVersion; QHash<QGeoTiledMap *, QSet<QGeoTileSpec> > mapHash_; QHash<QGeoTileSpec, QSet<QGeoTiledMap *> > tileHash_; QGeoTiledMappingManagerEngine::CacheAreas cacheHint_; - QGeoTileCache *tileCache_; + QAbstractGeoTileCache *tileCache_; QGeoTileFetcher *fetcher_; private: diff --git a/src/location/maps/qgeotiledmapreply.cpp b/src/location/maps/qgeotiledmapreply.cpp index abbebc4b..f2dfd9eb 100644 --- a/src/location/maps/qgeotiledmapreply.cpp +++ b/src/location/maps/qgeotiledmapreply.cpp @@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE \class QGeoTiledMapReply \inmodule QtLocation \ingroup QtLocation-impl - \since 5.5 + \since 5.6 \internal \brief The QGeoTiledMapReply class manages a tile fetch operation started diff --git a/src/location/maps/qgeotilefetcher_p_p.h b/src/location/maps/qgeotilefetcher_p_p.h index ce2a5481..acd7288e 100644 --- a/src/location/maps/qgeotilefetcher_p_p.h +++ b/src/location/maps/qgeotilefetcher_p_p.h @@ -62,7 +62,6 @@ QT_BEGIN_NAMESPACE class QGeoTileSpec; class QGeoTiledMapReply; -class QGeoTileCache; class QGeoTiledMappingManagerEngine; class QGeoTileFetcherPrivate diff --git a/src/location/maps/qgeotilerequestmanager.cpp b/src/location/maps/qgeotilerequestmanager.cpp index d689d618..1409856a 100644 --- a/src/location/maps/qgeotilerequestmanager.cpp +++ b/src/location/maps/qgeotilerequestmanager.cpp @@ -37,7 +37,7 @@ #include "qgeotilespec_p.h" #include "qgeotiledmap_p.h" #include "qgeotiledmappingmanagerengine_p.h" -#include "qgeotilecache_p.h" +#include "qabstractgeotilecache_p.h" #include <QtCore/QPointer> QT_BEGIN_NAMESPACE @@ -66,14 +66,12 @@ public: QGeoTileRequestManager::QGeoTileRequestManager(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine) : d_ptr(new QGeoTileRequestManagerPrivate(map, engine)) { - if (!d_ptr->m_engine.isNull()) - d_ptr->m_engine->registerMap(d_ptr->m_map); + } QGeoTileRequestManager::~QGeoTileRequestManager() { - if (!d_ptr->m_engine.isNull()) - d_ptr->m_engine->deregisterMap(d_ptr->m_map); + } QList<QSharedPointer<QGeoTileTexture> > QGeoTileRequestManager::requestTiles(const QSet<QGeoTileSpec> &tiles) diff --git a/src/location/maps/qgeotilerequestmanager_p.h b/src/location/maps/qgeotilerequestmanager_p.h index 8ae7360a..66d2251e 100644 --- a/src/location/maps/qgeotilerequestmanager_p.h +++ b/src/location/maps/qgeotilerequestmanager_p.h @@ -54,7 +54,6 @@ QT_BEGIN_NAMESPACE class QGeoTiledMap; class QGeoTiledMappingManagerEngine; class QGeoTileSpec; -class QGeoTileCache; class QGeoTileTexture; class QGeoTileRequestManagerPrivate; diff --git a/src/location/places/qplace.cpp b/src/location/places/qplace.cpp index c3e99eab..82f9f641 100644 --- a/src/location/places/qplace.cpp +++ b/src/location/places/qplace.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlace class represents a set of data about a place. diff --git a/src/location/places/qplaceattribute.cpp b/src/location/places/qplaceattribute.cpp index e2546f3c..e7812a78 100644 --- a/src/location/places/qplaceattribute.cpp +++ b/src/location/places/qplaceattribute.cpp @@ -69,7 +69,7 @@ bool QPlaceAttributePrivate::isEmpty() const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceAttribute class represents generic attribute information about a place. diff --git a/src/location/places/qplacecategory.cpp b/src/location/places/qplacecategory.cpp index 408eacca..5629631a 100644 --- a/src/location/places/qplacecategory.cpp +++ b/src/location/places/qplacecategory.cpp @@ -78,7 +78,7 @@ bool QPlaceCategoryPrivate::isEmpty() const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceCategory class represents a category that a \l QPlace can be associated with. diff --git a/src/location/places/qplacecategory_p.h b/src/location/places/qplacecategory_p.h index c12c9d5e..07fec3c3 100644 --- a/src/location/places/qplacecategory_p.h +++ b/src/location/places/qplacecategory_p.h @@ -37,6 +37,17 @@ #ifndef QPLACECATEGORY_P_H #define QPLACECATEGORY_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QSharedData> #include <QtCore/QString> #include <QtLocation/QLocation> diff --git a/src/location/places/qplacecontent.cpp b/src/location/places/qplacecontent.cpp index 88f0e898..a3334c6a 100644 --- a/src/location/places/qplacecontent.cpp +++ b/src/location/places/qplacecontent.cpp @@ -68,7 +68,7 @@ bool QPlaceContentPrivate::compare(const QPlaceContentPrivate *other) const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceContent class serves as the base class for rich content types. diff --git a/src/location/places/qplacecontentreply.cpp b/src/location/places/qplacecontentreply.cpp index df02d094..f6030198 100644 --- a/src/location/places/qplacecontentreply.cpp +++ b/src/location/places/qplacecontentreply.cpp @@ -61,7 +61,7 @@ QT_USE_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-replies - \since 5.5 + \since 5.6 \brief The QPlaceContentReply class manages a content retrieval operation started by an instance of QPlaceManager. diff --git a/src/location/places/qplacecontentrequest.cpp b/src/location/places/qplacecontentrequest.cpp index 8ab14774..5a211ae9 100644 --- a/src/location/places/qplacecontentrequest.cpp +++ b/src/location/places/qplacecontentrequest.cpp @@ -72,7 +72,7 @@ void QPlaceContentRequestPrivate::clear() \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-requests - \since 5.5 + \since 5.6 \brief The QPlaceContentRequest class represents the parameters of a content request. diff --git a/src/location/places/qplacecontentrequest_p.h b/src/location/places/qplacecontentrequest_p.h index d82c1101..d9ba3700 100644 --- a/src/location/places/qplacecontentrequest_p.h +++ b/src/location/places/qplacecontentrequest_p.h @@ -37,6 +37,17 @@ #ifndef QPLACECONTENTREQUEST_P_H #define QPLACECONTENTREQUEST_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QSharedData> #include <QtCore/QVariant> #include <QtLocation/QPlaceContent> diff --git a/src/location/places/qplacedetailsreply.cpp b/src/location/places/qplacedetailsreply.cpp index 11ad191f..84ea9f84 100644 --- a/src/location/places/qplacedetailsreply.cpp +++ b/src/location/places/qplacedetailsreply.cpp @@ -55,7 +55,7 @@ QT_USE_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-replies - \since 5.5 + \since 5.6 \brief The QPlaceDetailsReply class manages a place details fetch operation started by an instance of QPlaceManager. diff --git a/src/location/places/qplaceeditorial.cpp b/src/location/places/qplaceeditorial.cpp index 6018770f..bd1cb647 100644 --- a/src/location/places/qplaceeditorial.cpp +++ b/src/location/places/qplaceeditorial.cpp @@ -68,7 +68,7 @@ bool QPlaceEditorialPrivate::compare(const QPlaceContentPrivate *other) const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceEditorial class represents a publisher's article describing a place. diff --git a/src/location/places/qplaceeditorial.h b/src/location/places/qplaceeditorial.h index 4a7e790f..ecfe8db8 100644 --- a/src/location/places/qplaceeditorial.h +++ b/src/location/places/qplaceeditorial.h @@ -48,7 +48,7 @@ class Q_LOCATION_EXPORT QPlaceEditorial : public QPlaceContent public: QPlaceEditorial(); #ifdef Q_QDOC - QPlaceEditorial::QPlaceEditorial(const QPlaceContent &other) + QPlaceEditorial(const QPlaceContent &other); #else Q_DECLARE_CONTENT_COPY_CTOR(QPlaceEditorial) #endif diff --git a/src/location/places/qplaceeditorial_p.h b/src/location/places/qplaceeditorial_p.h index 9d74b0d5..f502db73 100644 --- a/src/location/places/qplaceeditorial_p.h +++ b/src/location/places/qplaceeditorial_p.h @@ -37,6 +37,17 @@ #ifndef QPLACEDESCRIPTION_P_H #define QPLACEDESCRIPTION_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QUrl> #include <QtLocation/QPlaceSupplier> diff --git a/src/location/places/qplaceicon.cpp b/src/location/places/qplaceicon.cpp index 914c079e..c3a2b851 100644 --- a/src/location/places/qplaceicon.cpp +++ b/src/location/places/qplaceicon.cpp @@ -79,7 +79,7 @@ bool QPlaceIconPrivate::operator == (const QPlaceIconPrivate &other) const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceIcon class represents an icon. diff --git a/src/location/places/qplaceidreply.cpp b/src/location/places/qplaceidreply.cpp index d2f54c82..7fb8bbe8 100644 --- a/src/location/places/qplaceidreply.cpp +++ b/src/location/places/qplaceidreply.cpp @@ -57,7 +57,7 @@ QT_USE_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-replies - \since 5.5 + \since 5.6 \brief The QPlaceIdReply class manages operations which return an identifier such as saving and removal operations of places and categories. diff --git a/src/location/places/qplaceimage.cpp b/src/location/places/qplaceimage.cpp index 7143d290..f3dda154 100644 --- a/src/location/places/qplaceimage.cpp +++ b/src/location/places/qplaceimage.cpp @@ -67,7 +67,7 @@ bool QPlaceImagePrivate::compare(const QPlaceContentPrivate *other) const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceImage class represents a reference to an image. diff --git a/src/location/places/qplaceimage_p.h b/src/location/places/qplaceimage_p.h index b8a4d0f7..4030b08d 100644 --- a/src/location/places/qplaceimage_p.h +++ b/src/location/places/qplaceimage_p.h @@ -37,6 +37,17 @@ #ifndef QPLACEIMAGE_P_H #define QPLACEIMAGE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QSharedData> #include <QtCore/QUrl> diff --git a/src/location/places/qplacemanager.cpp b/src/location/places/qplacemanager.cpp index 8ed1afc3..e78489f7 100644 --- a/src/location/places/qplacemanager.cpp +++ b/src/location/places/qplacemanager.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-manager - \since 5.5 + \since 5.6 \brief The QPlaceManager class provides the interface which allows clients to access places stored in a particular backend. diff --git a/src/location/places/qplacemanagerengine.cpp b/src/location/places/qplacemanagerengine.cpp index 65c4933e..c1b5f237 100644 --- a/src/location/places/qplacemanagerengine.cpp +++ b/src/location/places/qplacemanagerengine.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE \ingroup QtLocation-impl \ingroup QtLocation-places \ingroup QtLocation-places-manager - \since 5.5 + \since 5.6 \brief The QPlaceManagerEngine class provides an interface for implementers of QGeoServiceProvider plugins who want to provide access to place diff --git a/src/location/places/qplacematchreply.cpp b/src/location/places/qplacematchreply.cpp index dc4a79bc..9794b3f3 100644 --- a/src/location/places/qplacematchreply.cpp +++ b/src/location/places/qplacematchreply.cpp @@ -56,7 +56,7 @@ QT_USE_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-replies - \since 5.5 + \since 5.6 \brief The QPlaceMatchReply class manages a place matching operation started by an instance of QPlaceManager. diff --git a/src/location/places/qplacematchrequest.cpp b/src/location/places/qplacematchrequest.cpp index 7c5fb749..89343dc6 100644 --- a/src/location/places/qplacematchrequest.cpp +++ b/src/location/places/qplacematchrequest.cpp @@ -101,7 +101,7 @@ void QPlaceMatchRequestPrivate::clear() \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-requests - \since 5.5 + \since 5.6 \brief The QPlaceMatchRequest class is used to find places from one manager that match those from another. It represents a set of request parameters. diff --git a/src/location/places/qplaceproposedsearchresult_p.h b/src/location/places/qplaceproposedsearchresult_p.h index 90cbbe10..46f95106 100644 --- a/src/location/places/qplaceproposedsearchresult_p.h +++ b/src/location/places/qplaceproposedsearchresult_p.h @@ -37,6 +37,17 @@ #ifndef QPROPOSEDSEARCHRESULT_P_H #define QPROPOSEDSEARCHRESULT_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qplacesearchresult_p.h" QT_BEGIN_NAMESPACE diff --git a/src/location/places/qplaceratings.cpp b/src/location/places/qplaceratings.cpp index db5dd3ac..391db376 100644 --- a/src/location/places/qplaceratings.cpp +++ b/src/location/places/qplaceratings.cpp @@ -68,7 +68,7 @@ bool QPlaceRatingsPrivate::isEmpty() const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceRatings class holds rating information about a place. diff --git a/src/location/places/qplaceratings_p.h b/src/location/places/qplaceratings_p.h index 4a3d8731..21d441a2 100644 --- a/src/location/places/qplaceratings_p.h +++ b/src/location/places/qplaceratings_p.h @@ -37,6 +37,17 @@ #ifndef QPLACERATINGS_P_H #define QPLACERATINGS_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QSharedData> QT_BEGIN_NAMESPACE diff --git a/src/location/places/qplacereply.cpp b/src/location/places/qplacereply.cpp index 758d6fea..0590871d 100644 --- a/src/location/places/qplacereply.cpp +++ b/src/location/places/qplacereply.cpp @@ -44,7 +44,7 @@ QT_USE_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-replies - \since 5.5 + \since 5.6 \brief The QPlaceReply class manages an operation started by an instance of QPlaceManager and serves as a base class for more specialized replies. diff --git a/src/location/places/qplaceresult.cpp b/src/location/places/qplaceresult.cpp index 8ed5fed6..fe89eff7 100644 --- a/src/location/places/qplaceresult.cpp +++ b/src/location/places/qplaceresult.cpp @@ -70,7 +70,7 @@ bool QPlaceResultPrivate::compare(const QPlaceSearchResultPrivate *other) const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceResult class represents a search result containing a place. diff --git a/src/location/places/qplaceresult_p.h b/src/location/places/qplaceresult_p.h index d3d2f6c2..0e0bf8cd 100644 --- a/src/location/places/qplaceresult_p.h +++ b/src/location/places/qplaceresult_p.h @@ -37,6 +37,17 @@ #ifndef QPLACERESULT_P_H #define QPLACERESULT_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qplacesearchresult_p.h" QT_BEGIN_NAMESPACE diff --git a/src/location/places/qplacereview.cpp b/src/location/places/qplacereview.cpp index afc31c49..ca79b076 100644 --- a/src/location/places/qplacereview.cpp +++ b/src/location/places/qplacereview.cpp @@ -76,7 +76,7 @@ bool QPlaceReviewPrivate::compare(const QPlaceContentPrivate *other) const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceReview class represents a review of a place. diff --git a/src/location/places/qplacereview_p.h b/src/location/places/qplacereview_p.h index 19fa8fa6..345aa192 100644 --- a/src/location/places/qplacereview_p.h +++ b/src/location/places/qplacereview_p.h @@ -37,6 +37,17 @@ #ifndef QPLACEREVIEW_P_H #define QPLACEREVIEW_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QUrl> #include <QtCore/QDateTime> diff --git a/src/location/places/qplacesearchreply.cpp b/src/location/places/qplacesearchreply.cpp index a29e49f7..06eef4e5 100644 --- a/src/location/places/qplacesearchreply.cpp +++ b/src/location/places/qplacesearchreply.cpp @@ -56,7 +56,7 @@ public: \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-replies - \since 5.5 + \since 5.6 \brief The QPlaceSearchReply class manages a place search operation started by an instance of QPlaceManager. diff --git a/src/location/places/qplacesearchrequest.cpp b/src/location/places/qplacesearchrequest.cpp index 2fddbe9a..c2d993e3 100644 --- a/src/location/places/qplacesearchrequest.cpp +++ b/src/location/places/qplacesearchrequest.cpp @@ -136,7 +136,7 @@ void QPlaceSearchRequestPrivate::clear() \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-requests - \since 5.5 + \since 5.6 \brief The QPlaceSearchRequest class represents the set of parameters for a search request. diff --git a/src/location/places/qplacesearchresult.cpp b/src/location/places/qplacesearchresult.cpp index f0ed5f5b..d8ddc50a 100644 --- a/src/location/places/qplacesearchresult.cpp +++ b/src/location/places/qplacesearchresult.cpp @@ -67,7 +67,7 @@ bool QPlaceSearchResultPrivate::compare(const QPlaceSearchResultPrivate *other) \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceSearchResult class is the base class for search results. diff --git a/src/location/places/qplacesearchresult_p.h b/src/location/places/qplacesearchresult_p.h index 6960c129..e7c1aaf5 100644 --- a/src/location/places/qplacesearchresult_p.h +++ b/src/location/places/qplacesearchresult_p.h @@ -37,6 +37,17 @@ #ifndef QPLACESEARCHRESULT_P_H #define QPLACESEARCHRESULT_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qplacesearchresult.h" #include "qplacesearchrequest.h" diff --git a/src/location/places/qplacesearchsuggestionreply.cpp b/src/location/places/qplacesearchsuggestionreply.cpp index 09ed9390..9bfc5f0a 100644 --- a/src/location/places/qplacesearchsuggestionreply.cpp +++ b/src/location/places/qplacesearchsuggestionreply.cpp @@ -55,7 +55,7 @@ QT_USE_NAMESPACE \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-replies - \since 5.5 + \since 5.6 \brief The QPlaceSearchSuggestionReply class manages a search suggestion operation started by an instance of QPlaceManager. diff --git a/src/location/places/qplacesupplier.cpp b/src/location/places/qplacesupplier.cpp index fb8b6b6e..aa9e1220 100644 --- a/src/location/places/qplacesupplier.cpp +++ b/src/location/places/qplacesupplier.cpp @@ -80,7 +80,7 @@ bool QPlaceSupplierPrivate::isEmpty() const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceSupplier class represents a supplier of a place or content associated with a place. diff --git a/src/location/places/qplacesupplier_p.h b/src/location/places/qplacesupplier_p.h index 072c0fe3..ab09349d 100644 --- a/src/location/places/qplacesupplier_p.h +++ b/src/location/places/qplacesupplier_p.h @@ -37,6 +37,17 @@ #ifndef QPLACESUPPLIER_P_H #define QPLACESUPPLIER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QString> #include <QSharedData> #include <QUrl> diff --git a/src/location/places/qplaceuser.cpp b/src/location/places/qplaceuser.cpp index fd176525..fbfba621 100644 --- a/src/location/places/qplaceuser.cpp +++ b/src/location/places/qplaceuser.cpp @@ -63,7 +63,7 @@ bool QPlaceUserPrivate::operator==(const QPlaceUserPrivate &other) const \inmodule QtLocation \ingroup QtLocation-places \ingroup QtLocation-places-data - \since 5.5 + \since 5.6 \brief The QPlaceUser class represents an individual user. */ diff --git a/src/location/places/qplaceuser_p.h b/src/location/places/qplaceuser_p.h index 334683b6..f49110b5 100644 --- a/src/location/places/qplaceuser_p.h +++ b/src/location/places/qplaceuser_p.h @@ -37,6 +37,17 @@ #ifndef QPLACEUSER_P_H #define QPLACEUSER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QSharedData> #include <QString> diff --git a/src/location/places/unsupportedreplies_p.h b/src/location/places/unsupportedreplies_p.h index 7b0bef1a..b23a3b34 100644 --- a/src/location/places/unsupportedreplies_p.h +++ b/src/location/places/unsupportedreplies_p.h @@ -37,6 +37,17 @@ #ifndef UNSUPPORTEDREPLIES_P_H #define UNSUPPORTEDREPLIES_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qplacedetailsreply.h" #include "qplacecontentreply.h" #include "qplacesearchreply.h" diff --git a/src/location/qlocation.cpp b/src/location/qlocation.cpp index e9f8cf37..2afed10b 100644 --- a/src/location/qlocation.cpp +++ b/src/location/qlocation.cpp @@ -43,7 +43,7 @@ namespace QLocation { /*! \namespace QLocation \inmodule QtLocation - \target QLocation Namespace + \keyword QLocation Namespace \brief The QLocation namespace contains miscellaneous identifiers used throughout the QtLocation module. diff --git a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp index af6cbcf0..a33d1ba8 100644 --- a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp @@ -376,18 +376,15 @@ QString QGeoRoutingManagerEngineNokia::routeRequestString(const QGeoRouteRequest { QString requestString; - const QList<QGeoRectangle> excludeAreas = request.excludeAreas(); - QList<QGeoRectangle>::const_iterator beg = excludeAreas.begin(); - QList<QGeoRectangle>::const_iterator end = excludeAreas.begin(); - for (QList<QGeoRectangle>::const_iterator it = beg; it != end; ++it) { + foreach (const QGeoRectangle &area, request.excludeAreas()) { requestString += QLatin1String("&avoidareas="); - requestString += trimDouble(it->topLeft().latitude()); + requestString += trimDouble(area.topLeft().latitude()); requestString += QLatin1String(","); - requestString += trimDouble(it->topLeft().longitude()); + requestString += trimDouble(area.topLeft().longitude()); requestString += QLatin1String(";"); - requestString += trimDouble(it->bottomRight().latitude()); + requestString += trimDouble(area.bottomRight().latitude()); requestString += QLatin1String(","); - requestString += trimDouble(it->bottomRight().longitude()); + requestString += trimDouble(area.bottomRight().longitude()); } // TODO: work out what was going on here diff --git a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp index bf58ad34..98777d09 100644 --- a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp @@ -110,13 +110,4 @@ void QGeoTiledMapNokia::evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTile emit copyrightsChanged(m_copyrightsSlab); } -int QGeoTiledMapNokia::mapVersion() -{ - if (!m_engine.isNull()) - return m_engine->mapVersion(); - else - return QGeoTiledMap::mapVersion(); - -} - QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.h b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.h index d0253343..9651cc80 100644 --- a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.h +++ b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.h @@ -54,7 +54,6 @@ public: QString getViewCopyright(); void evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles); - int mapVersion(); private: QImage m_logo; diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp index 02e6f12c..0713ba10 100644 --- a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp @@ -39,7 +39,7 @@ #include "qgeotiledmap_nokia.h" #include "qgeotilefetcher_nokia.h" #include "qgeotilespec_p.h" -#include "qgeotilecache_p.h" +#include "qgeofiletilecache_p.h" #include <QDebug> #include <QDir> @@ -101,16 +101,15 @@ QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia( // TODO: do this in a plugin-neutral way so that other tiled map plugins // don't need this boilerplate or hardcode plugin name - QString cacheDir; if (parameters.contains(QStringLiteral("here.mapping.cache.directory"))) { - cacheDir = parameters.value(QStringLiteral("here.mapping.cache.directory")).toString(); + m_cacheDirectory = parameters.value(QStringLiteral("here.mapping.cache.directory")).toString(); } else { // managerName() is not yet set, we have to hardcode the plugin name below - cacheDir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) - + QLatin1String("/QtLocation/here"); + m_cacheDirectory = QAbstractGeoTileCache::baseCacheDirectory() + QLatin1String("here"); } - QGeoTileCache *tileCache = createTileCacheWithDir(cacheDir); + QAbstractGeoTileCache *tileCache = new QGeoFileTileCache(m_cacheDirectory); + setTileCache(tileCache); if (parameters.contains(QStringLiteral("here.mapping.cache.disk.size"))) { bool ok = false; @@ -258,14 +257,13 @@ void QGeoTiledMappingManagerEngineNokia::updateVersion(const QJsonObject &newVer m_mapVersion.setVersion(m_mapVersion.version() + 1); saveMapVersion(); - - emit mapVersionChanged(); + setTileVersion(m_mapVersion.version()); } } void QGeoTiledMappingManagerEngineNokia::saveMapVersion() { - QDir saveDir(tileCache()->directory()); + QDir saveDir(m_cacheDirectory); QFile saveFile(saveDir.filePath(QStringLiteral("here_version"))); if (!saveFile.open(QIODevice::WriteOnly)) { @@ -279,8 +277,7 @@ void QGeoTiledMappingManagerEngineNokia::saveMapVersion() void QGeoTiledMappingManagerEngineNokia::loadMapVersion() { - - QDir saveDir(tileCache()->directory()); + QDir saveDir(m_cacheDirectory); QFile loadFile(saveDir.filePath(QStringLiteral("here_version"))); if (!loadFile.open(QIODevice::ReadOnly)) { @@ -297,6 +294,7 @@ void QGeoTiledMappingManagerEngineNokia::loadMapVersion() m_mapVersion.setVersion(object[QStringLiteral("version")].toInt()); m_mapVersion.setVersionData(object[QStringLiteral("data")].toObject()); + setTileVersion(m_mapVersion.version()); } QString QGeoTiledMappingManagerEngineNokia::evaluateCopyrightsText(const QGeoMapType mapType, diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h index acaf61d7..16483120 100644 --- a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h +++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.h @@ -101,6 +101,8 @@ private: QHash<QString, QList<CopyrightDesc> > m_copyrights; QHash<int, QString> m_mapSchemes; QGeoMapVersion m_mapVersion; + + QString m_cacheDirectory; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeomapreplyosm.cpp b/src/plugins/geoservices/osm/qgeomapreplyosm.cpp index b540683b..d020716e 100644 --- a/src/plugins/geoservices/osm/qgeomapreplyosm.cpp +++ b/src/plugins/geoservices/osm/qgeomapreplyosm.cpp @@ -75,7 +75,11 @@ void QGeoMapReplyOsm::networkReplyFinished() QByteArray a = m_reply->readAll(); setMapImageData(a); - setMapImageFormat("png"); + int mapId = tileSpec().mapId(); + if (mapId == 1 || mapId == 2) + setMapImageFormat(QStringLiteral("jpg")); + else + setMapImageFormat(QStringLiteral("png")); setFinished(true); diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp index 95a4355e..9d2a83fa 100644 --- a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp +++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp @@ -62,13 +62,16 @@ QGeoTiledMapReply *QGeoTileFetcherOsm::getTileImage(const QGeoTileSpec &spec) request.setRawHeader("User-Agent", m_userAgent); QString urlPrefix; + QString suffix = QStringLiteral(".png"); switch (spec.mapId()) { case 1: urlPrefix = QStringLiteral("http://otile1.mqcdn.com/tiles/1.0.0/map/"); + suffix = QStringLiteral(".jpg"); break; case 2: urlPrefix = QStringLiteral("http://otile1.mqcdn.com/tiles/1.0.0/sat/"); + suffix = QStringLiteral(".jpg"); break; case 3: urlPrefix = QStringLiteral("http://a.tile.thunderforest.com/cycle/"); @@ -94,7 +97,7 @@ QGeoTiledMapReply *QGeoTileFetcherOsm::getTileImage(const QGeoTileSpec &spec) request.setUrl(QUrl(urlPrefix + QString::number(spec.zoom()) + QLatin1Char('/') + QString::number(spec.x()) + QLatin1Char('/') + - QString::number(spec.y()) + QStringLiteral(".png"))); + QString::number(spec.y()) + suffix)); QNetworkReply *reply = m_networkManager->get(request); diff --git a/src/plugins/position/android/src/plugin.json b/src/plugins/position/android/src/plugin.json index b84fafea..4fd87892 100644 --- a/src/plugins/position/android/src/plugin.json +++ b/src/plugins/position/android/src/plugin.json @@ -4,5 +4,6 @@ "Position": true, "Satellite": true, "Monitor": false, - "Priority": 1000 + "Priority": 1000, + "Testable": false } diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android_p.h b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h index 0980a0ce..cdff1e13 100644 --- a/src/plugins/position/android/src/qgeopositioninfosource_android_p.h +++ b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h @@ -34,6 +34,17 @@ #ifndef QGEOPOSITIONINFOSOURCE_ANDROID_P_H #define QGEOPOSITIONINFOSOURCE_ANDROID_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QGeoPositionInfoSource> #include <QTimer> diff --git a/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h index 0bc8f5dd..06cc25b9 100644 --- a/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h +++ b/src/plugins/position/android/src/qgeosatelliteinfosource_android_p.h @@ -35,6 +35,17 @@ #ifndef QGEOSATELLITEINFOSOURCEANDROID_H #define QGEOSATELLITEINFOSOURCEANDROID_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QGeoSatelliteInfoSource> #include <QTimer> diff --git a/src/plugins/position/blackberry/bb/ppsattribute.cpp b/src/plugins/position/blackberry/bb/ppsattribute.cpp deleted file mode 100644 index 4e8bb6c8..00000000 --- a/src/plugins/position/blackberry/bb/ppsattribute.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <bb/PpsAttribute> -#include "ppsattribute_p.h" - -#include <QDebug> -#include <QVariant> - -Q_DECLARE_METATYPE(QList<bb::PpsAttribute>) -typedef QMap<QString, bb::PpsAttribute> PpsAttributeMap; -Q_DECLARE_METATYPE(PpsAttributeMap) - -namespace bb -{ - -/////////////////////////// -// -// PpsAttributePrivate -// -/////////////////////////// - -PpsAttributePrivate::PpsAttributePrivate(): - _type(PpsAttribute::None) -{ -} - -/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( int value, PpsAttributeFlag::Types flags ) -{ - PpsAttribute attribute; - attribute.d->_type = PpsAttribute::Number; - attribute.d->_data = value; - attribute.d->_flags = flags; - return attribute; -} - -/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( long long value, PpsAttributeFlag::Types flags ) -{ - PpsAttribute attribute; - attribute.d->_type = PpsAttribute::Number; - attribute.d->_data = value; - attribute.d->_flags = flags; - return attribute; -} - -/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( double value, PpsAttributeFlag::Types flags ) -{ - PpsAttribute attribute; - attribute.d->_type = PpsAttribute::Number; - attribute.d->_data = value; - attribute.d->_flags = flags; - return attribute; -} - -/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( bool value, PpsAttributeFlag::Types flags ) -{ - PpsAttribute attribute; - attribute.d->_type = PpsAttribute::Bool; - attribute.d->_data = value; - attribute.d->_flags = flags; - return attribute; -} - -/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( const QString &value, PpsAttributeFlag::Types flags ) -{ - PpsAttribute attribute; - attribute.d->_type = PpsAttribute::String; - attribute.d->_data = value; - attribute.d->_flags = flags; - return attribute; -} - -/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( const QList<PpsAttribute> &value, PpsAttributeFlag::Types flags ) -{ - PpsAttribute attribute; - attribute.d->_type = PpsAttribute::Array; - attribute.d->_data = QVariant::fromValue(value); - attribute.d->_flags = flags; - return attribute; -} - -/*static*/ PpsAttribute PpsAttributePrivate::ppsAttribute( const QMap<QString, PpsAttribute> &value, PpsAttributeFlag::Types flags ) -{ - PpsAttribute attribute; - attribute.d->_type = PpsAttribute::Object; - attribute.d->_data = QVariant::fromValue(value); - attribute.d->_flags = flags; - return attribute; -} - -/////////////////////////// -// -// PpsAttribute -// -/////////////////////////// - -PpsAttribute::PpsAttribute(): - d(new PpsAttributePrivate()) -{ -} - -PpsAttribute::~PpsAttribute() -{ -} - -PpsAttribute::PpsAttribute(const PpsAttribute & other): - d(other.d) -{ -} - -PpsAttribute &PpsAttribute::operator=(const PpsAttribute & other) -{ - d = other.d; - return *this; -} - -bool PpsAttribute::operator==(const PpsAttribute & other) const -{ - if ( type() != other.type() ) { - return false; - } - if ( flags() != other.flags() ) { - return false; - } - - switch ( type() ) { - case PpsAttribute::Number: - case PpsAttribute::Bool: - case PpsAttribute::String: - // QVariant can compare double, int, longlong, bool, and QString for us. - return d->_data == other.d->_data; - case PpsAttribute::Array: - // QVariant can't compare custom types (like QList<PpsAttribute>), always returning false. So we pull - // the lists out manually and compare them. - return toList() == other.toList(); - case PpsAttribute::Object: - // QVariant can't compare custom types (like QMap<QString, PpsAttribute>), always returning false. So - // we pull the maps out manually and compare them. - return toMap() == other.toMap(); - case PpsAttribute::None: - // Both are "None" type, so the actual content doesn't matter. - return true; - } - return d->_data == other.d->_data; -} - -bool PpsAttribute::operator!=(const PpsAttribute & other) const -{ - return !(*this == other); -} - -bool PpsAttribute::isValid() const -{ - return d->_type != PpsAttribute::None; -} - -PpsAttribute::Type PpsAttribute::type() const -{ - return d->_type; -} - -bool PpsAttribute::isNumber() const -{ - return type() == PpsAttribute::Number; -} - -bool PpsAttribute::isBool() const -{ - return type() == PpsAttribute::Bool; -} - -bool PpsAttribute::isString() const -{ - return type() == PpsAttribute::String; -} - -bool PpsAttribute::isArray() const -{ - return type() == PpsAttribute::Array; -} - -bool PpsAttribute::isObject() const -{ - return type() == PpsAttribute::Object; -} - -double PpsAttribute::toDouble() const -{ - return d->_data.toDouble(); -} - -qlonglong PpsAttribute::toLongLong() const -{ - return d->_data.toLongLong(); -} - -int PpsAttribute::toInt() const -{ - return d->_data.toInt(); -} - -bool PpsAttribute::toBool() const -{ - return d->_data.toBool(); -} - -QString PpsAttribute::toString() const -{ - return d->_data.toString(); -} - -QList<PpsAttribute> PpsAttribute::toList() const -{ - return d->_data.value< QList<PpsAttribute> >(); -} - -QMap<QString, PpsAttribute> PpsAttribute::toMap() const -{ - return d->_data.value< QMap<QString, PpsAttribute> >(); -} - -PpsAttributeFlag::Types PpsAttribute::flags() const -{ - return d->_flags; -} - -QVariant PpsAttribute::toVariant() const -{ - return d->_data; -} - -QDebug operator<<(QDebug dbg, const PpsAttribute &attribute) -{ - dbg << "PpsAttribute("; - - switch ( attribute.type() ) { - case PpsAttribute::Number: - switch (attribute.toVariant().type()) { - case QVariant::Int: - dbg << "Number, " << attribute.flags() << ", " << attribute.toInt(); - break; - case QVariant::LongLong: - dbg << "Number, " << attribute.flags() << ", " << attribute.toLongLong(); - break; - default: - dbg << "Number, " << attribute.flags() << ", " << attribute.toDouble(); - break; - } - break; - case PpsAttribute::Bool: - dbg << "Bool, " << attribute.flags() << ", " << attribute.toBool(); - break; - case PpsAttribute::String: - dbg << "String, " << attribute.flags() << ", " << attribute.toString(); - break; - case PpsAttribute::Array: - dbg << "Array, " << attribute.flags() << ", " << attribute.toList(); - break; - case PpsAttribute::Object: - dbg << "Object, " << attribute.flags() << ", " << attribute.toMap(); - break; - case PpsAttribute::None: - dbg << "None"; - break; - } - - dbg << ')'; - - return dbg; -} - -} // namespace bb diff --git a/src/plugins/position/blackberry/bb/ppsattribute_p.h b/src/plugins/position/blackberry/bb/ppsattribute_p.h deleted file mode 100644 index 8178648a..00000000 --- a/src/plugins/position/blackberry/bb/ppsattribute_p.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BB_CORE_PPSATTRIBUTEPRIVATE_HPP -#define BB_CORE_PPSATTRIBUTEPRIVATE_HPP - -#include <bb/PpsAttribute> -#include <bb/PpsAttributeFlag> - -#include <QList> -#include <QMap> -#include <QSharedData> -#include <QString> -#include <QVariant> - -namespace bb -{ - -class PpsAttributePrivate : public QSharedData -{ -public: - PpsAttributePrivate(); - - static PpsAttribute ppsAttribute( double value, PpsAttributeFlag::Types flags ); - static PpsAttribute ppsAttribute( long long value, PpsAttributeFlag::Types flags ); - static PpsAttribute ppsAttribute( int value, PpsAttributeFlag::Types flags ); - static PpsAttribute ppsAttribute( bool value, PpsAttributeFlag::Types flags ); - static PpsAttribute ppsAttribute( const QString &value, PpsAttributeFlag::Types flags ); - static PpsAttribute ppsAttribute( const QList<PpsAttribute> &value, PpsAttributeFlag::Types flags ); - static PpsAttribute ppsAttribute( const QMap<QString, PpsAttribute> &value, PpsAttributeFlag::Types flags ); - -private: - friend class PpsAttribute; - - QVariant _data; - PpsAttribute::Type _type; - PpsAttributeFlag::Types _flags; -}; - -} // namespace bb - -#endif // BB_CORE_PPSOBJECTPRIVATE_HPP diff --git a/src/plugins/position/blackberry/bb/ppsobject.cpp b/src/plugins/position/blackberry/bb/ppsobject.cpp deleted file mode 100644 index 15f797ec..00000000 --- a/src/plugins/position/blackberry/bb/ppsobject.cpp +++ /dev/null @@ -1,735 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// Indicate which dependencies to mock when testing -// NOTE: These defines must occur before including any headers and -// ProxyInjector.hpp must be the first header included -#define USE_QT_QSOCKETNOTIFIER_PROXY -#define USE_UNISTD_PROXY -#define USE_FCNTL_PROXY -#define USE_ERRNO_PROXY -#define USE_STRING_PROXY -//#include <private/proxy/ProxyInjector.hpp> - -// Disable symbol renaming when testing for open, close, read, and -// write as these dependency names conflict with member method names -// and we don't want to rename the member methods. Instead, use dummy -// names for the dependencies in the production code and toggle -// between the real/proxy versions here. -#ifdef BB_TEST_BUILD -# undef open -# undef close -# undef read -# undef write -# define PosixOpen open_proxy -# define PosixClose close_proxy -# define PosixRead read_proxy -# define PosixWrite write_proxy -#else -# define PosixOpen ::open -# define PosixClose ::close -# define PosixRead ::read -# define PosixWrite ::write -#endif - -#include "ppsobject.h" - -#include "ppsattribute_p.h" -#include "safeassign.h" - -#include <bb/PpsAttribute> - -#include <QDebug> -#include <QObject> -#include <QSocketNotifier> - -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> - -#include <exception> - -extern "C" { -#include "sys/pps.h" -} - -namespace bb -{ - -/** - * From "QNX Persistent Publish/Subscribe Developer's Guide": - * - * "the maximum size for a PPS object is 64 kilobytes" - */ -static const int PPS_MAX_SIZE = 64 * 1024; - -class PpsDecoder -{ -public: - PpsDecoder(char *str) - { - throwOnPpsDecoderError( pps_decoder_initialize(&_decoder, str) ); - } - - ~PpsDecoder() - { - pps_decoder_cleanup(&_decoder); - } - - QMap<QString, PpsAttribute> decode() - { - return decodeObject(); - } - - static QVariantMap variantMapFromPpsAttributeMap(const QMap<QString, PpsAttribute> &data) - { - QVariantMap variantMap; - - for ( QMap<QString, PpsAttribute>::const_iterator it = data.begin(); it != data.end(); it++ ) { - variantMap[it.key()] = variantFromPpsAttribute( it.value() ); - } - - return variantMap; - } - -private: - pps_decoder_t _decoder; - - static void throwOnPpsDecoderError(pps_decoder_error_t error) - { - switch ( error ) { - case PPS_DECODER_OK: - return; - default: - throw std::exception(); - } - } - - bb::PpsAttributeFlag::Types readFlags() - { - int rawFlags = pps_decoder_flags(&_decoder, NULL); - - bb::PpsAttributeFlag::Types attributeFlags; - - if ( rawFlags & PPS_INCOMPLETE ) { - attributeFlags |= bb::PpsAttributeFlag::Incomplete; - } - if ( rawFlags & PPS_DELETED ) { - attributeFlags |= bb::PpsAttributeFlag::Deleted; - } - if ( rawFlags & PPS_CREATED ) { - attributeFlags |= bb::PpsAttributeFlag::Created; - } - if ( rawFlags & PPS_TRUNCATED ) { - attributeFlags |= bb::PpsAttributeFlag::Truncated; - } - if ( rawFlags & PPS_PURGED ) { - attributeFlags |= bb::PpsAttributeFlag::Purged; - } - - return attributeFlags; - } - - bb::PpsAttribute decodeString() - { - const char * value = NULL; - throwOnPpsDecoderError( pps_decoder_get_string(&_decoder, NULL, &value) ); - bb::PpsAttributeFlag::Types flags = readFlags(); - return bb::PpsAttributePrivate::ppsAttribute( QString::fromUtf8(value), flags ); - } - - bb::PpsAttribute decodeNumber() - { - // In order to support more number types, we have to do something stupid because - // the PPS library won't let us work any other way - // Basically, we have to probe the encoded type in order to try to get exactly what - // we want - long long llValue; - double dValue; - int iValue; - bb::PpsAttributeFlag::Types flags; - - if (pps_decoder_is_integer( &_decoder, NULL )) { - int result = pps_decoder_get_int(&_decoder, NULL, &iValue ); - switch (result) { - case PPS_DECODER_OK: - flags = readFlags(); - return bb::PpsAttributePrivate::ppsAttribute( iValue, flags ); - case PPS_DECODER_CONVERSION_FAILED: - throwOnPpsDecoderError( pps_decoder_get_int64(&_decoder, NULL, &llValue) ); - flags = readFlags(); - return bb::PpsAttributePrivate::ppsAttribute( llValue, flags ); - default: - throw std::exception(); - } - } else { - throwOnPpsDecoderError( pps_decoder_get_double(&_decoder, NULL, &dValue)); - flags = readFlags(); - return bb::PpsAttributePrivate::ppsAttribute( dValue, flags ); - } - } - - bb::PpsAttribute decodeBool() - { - bool value; - throwOnPpsDecoderError( pps_decoder_get_bool(&_decoder, NULL, &value) ); - bb::PpsAttributeFlag::Types flags = readFlags(); - return bb::PpsAttributePrivate::ppsAttribute( value, flags ); - } - - bb::PpsAttribute decodeData() - { - pps_node_type_t nodeType = pps_decoder_type(&_decoder, NULL); - switch ( nodeType ) { - case PPS_TYPE_BOOL: - return decodeBool(); - case PPS_TYPE_NUMBER: - return decodeNumber(); - case PPS_TYPE_STRING: - return decodeString(); - case PPS_TYPE_ARRAY: { - // We must read the flags before we push into the array, otherwise we'll get the flags for the first element in the array. - bb::PpsAttributeFlag::Types flags = readFlags(); - throwOnPpsDecoderError( pps_decoder_push(&_decoder, NULL) ); - bb::PpsAttribute returnVal = bb::PpsAttributePrivate::ppsAttribute( decodeArray(), flags ); - throwOnPpsDecoderError( pps_decoder_pop(&_decoder) ); - return returnVal; - } - case PPS_TYPE_OBJECT: { - // We must read the flags before we push into the object, otherwise we'll get the flags for the first alement in the object. - bb::PpsAttributeFlag::Types flags = readFlags(); - throwOnPpsDecoderError( pps_decoder_push(&_decoder, NULL) ); - bb::PpsAttribute returnVal = bb::PpsAttributePrivate::ppsAttribute( decodeObject(), flags ); - throwOnPpsDecoderError( pps_decoder_pop(&_decoder) ); - return returnVal; - } - case PPS_TYPE_NULL: - case PPS_TYPE_NONE: - case PPS_TYPE_UNKNOWN: - case PPS_TYPE_DELETED: - default: - return bb::PpsAttribute(); - } - } - - QList<bb::PpsAttribute> decodeArray() - { - QList<bb::PpsAttribute> list; - - int length = pps_decoder_length( &_decoder ); - for ( int i = 0; i < length; i += 1 ) { - // Force movement to a specific index. - throwOnPpsDecoderError( pps_decoder_goto_index(&_decoder, i) ); - list << decodeData(); - } - - return list; - } - - QMap<QString, bb::PpsAttribute> decodeObject() - { - QMap<QString, bb::PpsAttribute> map; - - int length = pps_decoder_length(&_decoder); - for ( int i = 0; i < length; i += 1 ) { - // Force movement to a specific index. - throwOnPpsDecoderError( pps_decoder_goto_index(&_decoder, i) ); - QString name = QString::fromUtf8( pps_decoder_name(&_decoder) ); - map[name] = decodeData(); - } - - return map; - } - - static QVariant variantFromPpsAttribute(const PpsAttribute &attribute) - { - switch ( attribute.type() ) { - case PpsAttribute::Number: - switch (attribute.toVariant().type()) { - case QVariant::Int: - return attribute.toInt(); - break; - case QVariant::LongLong: - return attribute.toLongLong(); - break; - default: - return attribute.toDouble(); - break; - } - break; - case PpsAttribute::Bool: - return attribute.toBool(); - break; - case PpsAttribute::String: - return attribute.toString(); - break; - case PpsAttribute::Array: { - QVariantList variantList; - Q_FOREACH ( PpsAttribute attr, attribute.toList() ) { - variantList << variantFromPpsAttribute(attr); - } - return variantList; - } - case PpsAttribute::Object: { - return variantMapFromPpsAttributeMap( attribute.toMap() ); - } - case PpsAttribute::None: - default: - return QVariant(); - } - } -}; - -/////////////////////////////////////////////////////////////////////////////// - -class PpsEncoder -{ -public: - PpsEncoder() - { - pps_encoder_initialize(&_encoder, false); - } - - ~PpsEncoder() - { - pps_encoder_cleanup(&_encoder); - } - - QByteArray encode(const QVariantMap &ppsData) - { - encodeObject(ppsData); - const char *rawData = pps_encoder_buffer(&_encoder); - if (!rawData) { - throw std::exception(); - } - return QByteArray(rawData); - } - -private: - pps_encoder_t _encoder; - - static void throwOnPpsEncoderError(pps_encoder_error_t error) - { - switch ( error ) { - case PPS_ENCODER_OK: - return; - default: - throw std::exception(); - } - } - - void encodeData(const char *name, QVariant data) - { - switch ( data.type() ) { - case QVariant::Bool: - throwOnPpsEncoderError( pps_encoder_add_bool(&_encoder, name, data.toBool()) ); - break; - // We want to support encoding uint even though libpps doesn't support it directly. We can't encoding uint as an int - // since that will lose precision (e.g. 2^31+1 can't be encoded that way). However, we can convert uint to double - // without losing precision. QVariant.toDouble() conveniently takes care of the conversion for us. - case QVariant::UInt: - case QVariant::Double: - throwOnPpsEncoderError( pps_encoder_add_double(&_encoder, name, data.toDouble()) ); - break; - case QVariant::Int: - throwOnPpsEncoderError( pps_encoder_add_int(&_encoder, name, data.toInt()) ); - break; - case QVariant::LongLong: - throwOnPpsEncoderError( pps_encoder_add_int64(&_encoder, name, data.toLongLong()) ); - break; - case QVariant::String: - throwOnPpsEncoderError( pps_encoder_add_string(&_encoder, name, data.toString().toUtf8().constData()) ); - break; - case QVariant::List: { - throwOnPpsEncoderError( pps_encoder_start_array(&_encoder, name) ); - encodeArray( data.toList() ); - throwOnPpsEncoderError( pps_encoder_end_array(&_encoder) ); - break; - } - case QVariant::Map: { - throwOnPpsEncoderError( pps_encoder_start_object(&_encoder, name) ); - encodeObject( data.toMap() ); - throwOnPpsEncoderError( pps_encoder_end_object(&_encoder) ); - break; - } - case QVariant::Invalid: { - throwOnPpsEncoderError( pps_encoder_add_null(&_encoder, name) ); - break; - } - default: - throw std::exception(); - } - } - - void encodeArray(QVariantList data) - { - for ( QVariantList::const_iterator it = data.constBegin(); it != data.constEnd(); it ++ ) { - encodeData( NULL, *it ); - } - } - - void encodeObject(QVariantMap data) { - for ( QVariantMap::const_iterator it = data.constBegin(); it != data.constEnd(); it ++ ) { - encodeData( it.key().toUtf8().constData(), it.value() ); - } - } -}; - -/////////////////////////////////////////////////////////////////////////////// - -class PpsObjectPrivate -{ -public: - QSocketNotifier *_notifier; - QString _path; - mutable int _error; - int _fd; - bool _readyReadEnabled; - - explicit PpsObjectPrivate(const QString &path) : - _notifier(NULL), - _path(path), - _error(EOK), - _fd(-1), - _readyReadEnabled(true) - { - } -}; - -/////////////////////////////////////////////////////////////////////////////// - -PpsObject::PpsObject(const QString &path, QObject *parent) : - QObject(parent), - d_ptr(new PpsObjectPrivate(path)) -{ -} - -PpsObject::~PpsObject() -{ - // RAII - ensure file gets closed - if (isOpen()) { - close(); - } -} - -int PpsObject::error() const -{ - Q_D(const PpsObject); - return d->_error; -} - -QString PpsObject::errorString() const -{ - Q_D(const PpsObject); - return QString(strerror(d->_error)); -} - -bool PpsObject::isReadyReadEnabled() const -{ - Q_D(const PpsObject); - - // query state of read ready signal - return d->_readyReadEnabled; -} - -void PpsObject::setReadyReadEnabled(bool enable) -{ - Q_D(PpsObject); - - // toggle whether socket notifier will emit a signal on read ready - d->_readyReadEnabled = enable; - if (isOpen()) { - d->_notifier->setEnabled(enable); - } -} - -bool PpsObject::isBlocking() const -{ - Q_D(const PpsObject); - - // reset last error - d->_error = EOK; - - // abort if file not open - if (!isOpen()) { - d->_error = EBADF; - return false; - } - - // query file status flags - int flags = fcntl(d->_fd, F_GETFL); - if (flags != -1) { - // check if non-blocking flag is unset - return ((flags & O_NONBLOCK) != O_NONBLOCK); - } else { - d->_error = errno; - return false; - } -} - -bool PpsObject::setBlocking(bool enable) -{ - Q_D(PpsObject); - - // reset last error - d->_error = EOK; - - // abort if file not open - if (!isOpen()) { - d->_error = EBADF; - return false; - } - - // query file status flags - int flags = fcntl(d->_fd, F_GETFL); - if (flags == -1) { - d->_error = errno; - return false; - } - - // configure non-blocking flag - if (enable) { - flags &= ~O_NONBLOCK; - } else { - flags |= O_NONBLOCK; - } - - // update file status flags - flags = fcntl(d->_fd, F_SETFL, flags); - if (flags == -1) { - d->_error = errno; - return false; - } - - return true; -} - -bool PpsObject::isOpen() const -{ - Q_D(const PpsObject); - return (d->_fd != -1); -} - -bool PpsObject::open(PpsOpenMode::Types mode) -{ - Q_D(PpsObject); - - // reset last error - d->_error = EOK; - - // abort if file already open - if (isOpen()) { - d->_error = EBUSY; - return false; - } - - // convert pps flags to open flags - int oflags = 0; - if ((mode & PpsOpenMode::Publish) && (mode & PpsOpenMode::Subscribe)) { - oflags |= O_RDWR; - } else if (mode & PpsOpenMode::Publish) { - oflags |= O_WRONLY; - } else if (mode & PpsOpenMode::Subscribe) { - oflags |= O_RDONLY; - } - - if (mode & PpsOpenMode::Create) { - oflags |= O_CREAT | O_EXCL; - } - - if (mode & PpsOpenMode::DeleteContents) { - oflags |= O_TRUNC; - } - - // open pps file - d->_fd = PosixOpen(d->_path.toUtf8().data(), oflags, 0666); - - // wire up socket notifier to know when reads are ready - if (d->_fd != -1) { - d->_notifier = new QSocketNotifier(d->_fd, QSocketNotifier::Read, this); - d->_notifier->setEnabled(d->_readyReadEnabled); - QObject::connect(d->_notifier, SIGNAL(activated(int)), this, SIGNAL(readyRead())); - return true; - } else { - d->_error = errno; - return false; - } -} - -bool PpsObject::close() -{ - Q_D(PpsObject); - - // reset last error - d->_error = EOK; - - // abort if file not open - if (!isOpen()) { - d->_error = EBADF; - return false; - } - - // shutdown socket notifier - delete d->_notifier; - d->_notifier = NULL; - - // close pps file - int result = PosixClose(d->_fd); - d->_fd = -1; - - // check success of operation - if (result == 0) { - return true; - } else { - d->_error = errno; - return false; - } -} - -QByteArray PpsObject::read(bool * ok) -{ - Q_D(PpsObject); - - // reset last error - d->_error = EOK; - - // abort if file not open - if (!isOpen()) { - d->_error = EBADF; - safeAssign(ok, false); - return QByteArray(); - } - - QByteArray byteArray; - byteArray.resize(PPS_MAX_SIZE); // resize doesn't initialize the data - int result = PosixRead(d->_fd, byteArray.data(), byteArray.size()); - - // check result of read operation - if (result > 0) { - // resize byte array to amount actually read - byteArray.resize(result); - safeAssign(ok, true); - return byteArray; - } else if (result == 0) { - // normalize the behavior of read() when no data is ready so a pps object - // put in non-blocking mode via opening w/o ?wait (read returns 0) looks - // the same as a pps object put in non-blocking mode by setting O_NONBLOCK - // (read returns EAGAIN) - d->_error = EAGAIN; - safeAssign(ok, false); - return QByteArray(); // Specifically return a default-constructed QByteArray. - } else { - d->_error = errno; - qWarning() << "PpsObject::read failed to read pps data, error " << errorString(); - safeAssign(ok, false); - return QByteArray(); // Specifically return a default-constructed QByteArray. - } -} - -bool PpsObject::write(const QByteArray &byteArray) -{ - Q_D(PpsObject); - - // reset last error - d->_error = EOK; - - // abort if file not open - if (!isOpen()) { - d->_error = EBADF; - return false; - } - - // write entire byte array to pps file - int result = PosixWrite(d->_fd, byteArray.data(), byteArray.size()); - if (result == -1) { - d->_error = errno; - } - return (result == byteArray.size()); -} - -bool PpsObject::remove() -{ - Q_D(PpsObject); - - // reset last error - d->_error = EOK; - - // delete pps file - int result = unlink(d->_path.toUtf8().data()); - - // check success of operation - if (result == 0) { - return true; - } else { - d->_error = errno; - return false; - } -} - -QVariantMap PpsObject::decode(const QByteArray &rawData, bool *ok) -{ - QMap<QString, PpsAttribute> mapData = decodeWithFlags(rawData, ok); - - // If *ok is false, then mapData is empty, so the resulting QVariantMap will also be empty, as desired. - return PpsDecoder::variantMapFromPpsAttributeMap(mapData); -} - -QMap<QString, PpsAttribute> PpsObject::decodeWithFlags(const QByteArray &rawData, bool *ok) -{ - bb::safeAssign(ok, true); - - try { - QByteArray mutableData(rawData); - PpsDecoder decoder(mutableData.data()); - return decoder.decode(); - } catch (...) { - bb::safeAssign(ok, false); - return QMap<QString, bb::PpsAttribute>(); - } -} - -QByteArray PpsObject::encode(const QVariantMap &ppsData, bool *ok) -{ - bb::safeAssign( ok, true ); - - try { - PpsEncoder encoder; - return encoder.encode(ppsData); - } catch (...) { - bb::safeAssign(ok, false); - return QByteArray(); - } -} - -} // namespace bb diff --git a/src/plugins/position/blackberry/blackberry.pro b/src/plugins/position/blackberry/blackberry.pro deleted file mode 100644 index 7e140391..00000000 --- a/src/plugins/position/blackberry/blackberry.pro +++ /dev/null @@ -1,26 +0,0 @@ -TARGET = qtposition_blackberry -QT = core positioning - -PLUGIN_TYPE = position -PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryBb -load(qt_plugin) - -LIBS = -lwmm -llocation_manager -lpps - -SOURCES += qgeopositioninfosource_bb.cpp \ - qgeosatelliteinfosource_bb.cpp \ - locationmanagerutil_bb.cpp \ - qgeopositioninfosourcefactory_bb.cpp -SOURCES += bb/ppsobject.cpp \ - bb/ppsattribute.cpp -HEADERS += qgeopositioninfosource_bb_p.h \ - qgeopositioninfosource_bb.h \ - qgeosatelliteinfosource_bb_p.h \ - qgeosatelliteinfosource_bb.h \ - locationmanagerutil_bb.h \ - qgeopositioninfosourcefactory_bb.h -HEADERS += bb/ppsobject.h \ - bb/ppsattribute_p.h - -OTHER_FILES += \ - plugin.json diff --git a/src/plugins/position/blackberry/locationmanagerutil_bb.cpp b/src/plugins/position/blackberry/locationmanagerutil_bb.cpp deleted file mode 100644 index b2fc9a1e..00000000 --- a/src/plugins/position/blackberry/locationmanagerutil_bb.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "locationmanagerutil_bb.h" - -#include <bb/PpsObject> - -#include <QtCore/QVariantMap> -#include <QtCore/QByteArray> -#include <QtDebug> - -#include <errno.h> - -namespace { - -// Create a QVariantMap suitable for writing to a PpsObject specifying a cancel request to the -// Location Manager. -QVariantMap createCancelRequest() -{ - QVariantMap map; - - map.insert("msg", "cancel"); - map.insert("id", ::global::libQtLocationId); - - return map; -} - -} // unnamed namespace - -namespace global { - -const QString libQtLocationId = "libQtLocation"; -const QString locationManagerPpsFile = "/pps/services/geolocation/control"; -const int minUpdateInterval = 1000; -const QVariantMap cancelRequest = createCancelRequest(); - -} // namespace global - - -// send a generic server-mode request, wrapped in a @control map, to ppsObject -bool sendRequest(bb::PpsObject &ppsObject, const QVariantMap &request) -{ - if (!ppsObject.isOpen()) { - if (!ppsObject.open()) { - qWarning() << "LocationManagerUtil.cpp:sendRequest(): error opening pps object, errno =" - << ppsObject.error() << "(" - << strerror(ppsObject.error()) - << "). Clients should verify that they have access_location_services " - "permission."; - return false; - } - } - - // wrap the request in a @control map - QVariantMap map; - map.insert("@control", request); - - - // encode it - bool ok; - QByteArray encodedRequest = bb::PpsObject::encode(map, &ok); - if (!ok) { - qWarning() << "LocationManagerUtil.cpp:sendRequest(): error encoding position request"; - ppsObject.close(); - return false; - } - - // write it - bool success = ppsObject.write(encodedRequest); - if (!success) { - qWarning() << "LocationManagerUtil.cpp:sendRequest(): error" - << ppsObject.error() - << "writing position request"; - ppsObject.close(); - return false; - } - - return true; -} - -// receive a generic server-mode reply from ppsObject, removing the @control map container -bool receiveReply(QVariantMap *reply, bb::PpsObject &ppsObject) -{ - if (!ppsObject.isOpen()) { - if (!ppsObject.open()) { - qWarning() << "LocationManagerUtil.cpp:receiveReply(): error opening pps object"; - return false; - } - } - - // read the reply - bool ok; - QByteArray encodedReply = ppsObject.read(&ok); - if (!ok) { - qWarning() << "LocationManagerUtil.cpp:receiveReply(): error" - << ppsObject.error() - << "reading position reply"; - ppsObject.close(); - return false; - } - - // decode the reply - *reply = bb::PpsObject::decode(encodedReply, &ok); - if (!ok) { - qWarning() << "LocationManagerUtil.cpp:receiveReply(): error decoding position reply"; - ppsObject.close(); - return false; - } - - // peel out the control map from the reply - *reply = reply->value("@control").toMap(); - - // check for an error in the reply - if (reply->contains("errCode")) { - int errCode = reply->value("errCode").toInt(); - if (errCode) { - qWarning() << "LocationManagerUtil.cpp:receiveReply(): (" << errCode << ")" << - reply->value("err").toString().toLocal8Bit().constData() << ":" << - reply->value("errstr").toString().toLocal8Bit().constData(); - return false; - } - } - - return true; -} - diff --git a/src/plugins/position/blackberry/locationmanagerutil_bb.h b/src/plugins/position/blackberry/locationmanagerutil_bb.h deleted file mode 100644 index 5b053c54..00000000 --- a/src/plugins/position/blackberry/locationmanagerutil_bb.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LOCATIONMANAGERUTIL_BB_H -#define LOCATIONMANAGERUTIL_BB_H - -#include <QtCore/QVariantMap> - -namespace bb -{ -class PpsObject; -} - -namespace global { - -// the libQtLocation id for the server-mode accessed pps file id field -extern const QString libQtLocationId; - -// the path to the location manager pps file that is the gateway for positioning requests/replies -extern const QString locationManagerPpsFile; - -// the minimum interval (in msec) that positional and satellite updates can be provided for -extern const int minUpdateInterval; - -// a QVariantMap suitable for writing to a PpsObject specifying a cancel request to the Location -// Manager. This cancels the current request -extern const QVariantMap cancelRequest; - -} // namespace global - -// send a generic server-mode request, wrapped in a @control map, to ppsObject -bool sendRequest(bb::PpsObject &ppsObject, const QVariantMap &request); - -// receive a generic server-mode reply from ppsObject, removing the @control map container -bool receiveReply(QVariantMap *reply, bb::PpsObject &ppsObject); - -#endif diff --git a/src/plugins/position/blackberry/plugin.json b/src/plugins/position/blackberry/plugin.json deleted file mode 100644 index dca8e6a4..00000000 --- a/src/plugins/position/blackberry/plugin.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Keys": ["blackberry"], - "Provider": "blackberry", - "Position": true, - "Satellite": true, - "Monitor": false, - "Priority": 1000 -} diff --git a/src/plugins/position/blackberry/qgeopositioninfosource_bb.cpp b/src/plugins/position/blackberry/qgeopositioninfosource_bb.cpp deleted file mode 100644 index ae58c7b7..00000000 --- a/src/plugins/position/blackberry/qgeopositioninfosource_bb.cpp +++ /dev/null @@ -1,1268 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgeopositioninfosource_bb_p.h" -#include "locationmanagerutil_bb.h" - -#ifndef BB_TEST_BUILD -# include <bb/PpsObject> -#else -# include "../tests/include/PpsObjectStuntDouble.hpp" -#endif - -extern "C" { -#include <wmm/wmm.h> -} - -#include <location_manager.h> - -#include <QMap> -#include <QVariantMap> -#include <QByteArray> -#include <QtDebug> -#include <QStringList> - -#include <errno.h> - -/////////////////////////// -// -// local variables/functions -// -/////////////////////////// - -namespace global -{ - -// Currently the default behavior for Location Manager is simply to set a constant default -// interval. 5 sec has been chosen as a compromise between timely updates and conserving power. -static const int defaultPositionUpdatePeriod = 5; - -} // namespace global - -namespace -{ - -// map the Location Manager reply error codes to the PositionErrorCode enum values. -QMap<int, bb::location::PositionErrorCode::Type> createIntToPositionErrorCodeMap() -{ - QMap<int, bb::location::PositionErrorCode::Type> map; - - map.insert(0, bb::location::PositionErrorCode::None); - map.insert(1, bb::location::PositionErrorCode::FatalDisabled); - map.insert(2, bb::location::PositionErrorCode::FatalNoLastKnownPosition); - map.insert(3, bb::location::PositionErrorCode::FatalInsufficientProviders); - map.insert(4, bb::location::PositionErrorCode::FatalInvalidRequest); - map.insert(5, bb::location::PositionErrorCode::FatalUnknown); - map.insert(6, bb::location::PositionErrorCode::FatalPermission); - map.insert(0x10000, bb::location::PositionErrorCode::WarnTimeout); - map.insert(0x10001, bb::location::PositionErrorCode::WarnLostTracking); - map.insert(0x10002, bb::location::PositionErrorCode::WarnStationary); - - return map; -} - -const QMap<int, bb::location::PositionErrorCode::Type> intToPositionErrorCodeMap = - createIntToPositionErrorCodeMap(); - -bool fatalError(bb::location::PositionErrorCode::Type code) -{ - if ( code == bb::location::PositionErrorCode::FatalDisabled - || code == bb::location::PositionErrorCode::FatalNoLastKnownPosition - || code == bb::location::PositionErrorCode::FatalInsufficientProviders - || code == bb::location::PositionErrorCode::FatalInvalidRequest - || code == bb::location::PositionErrorCode::FatalUnknown - || code == bb::location::PositionErrorCode::FatalPermission ) { - return true; - } - return false; -} - -// map the PositionErrorCode enum values to the Qt5 QGeoPositionInfoSource::Error enum values. -QMap<bb::location::PositionErrorCode::Type, QGeoPositionInfoSource::Error> - createPositionErrorCodeToErrorMap() -{ - QMap<bb::location::PositionErrorCode::Type, QGeoPositionInfoSource::Error> map; - - map.insert(bb::location::PositionErrorCode::FatalDisabled, - QGeoPositionInfoSource::ClosedError); - map.insert(bb::location::PositionErrorCode::FatalNoLastKnownPosition, - QGeoPositionInfoSource::UnknownSourceError); - map.insert(bb::location::PositionErrorCode::FatalInsufficientProviders, - QGeoPositionInfoSource::UnknownSourceError); - map.insert(bb::location::PositionErrorCode::FatalInvalidRequest, - QGeoPositionInfoSource::UnknownSourceError); - map.insert(bb::location::PositionErrorCode::FatalUnknown, - QGeoPositionInfoSource::UnknownSourceError); - map.insert(bb::location::PositionErrorCode::FatalPermission, - QGeoPositionInfoSource::AccessError); - - return map; -} - -const QMap<bb::location::PositionErrorCode::Type, QGeoPositionInfoSource::Error> - positionErrorCodeToErrorMap = createPositionErrorCodeToErrorMap(); - -// map the Location Manager provider names to the QGeoPositionInfoSource positioning methods -QMap<QGeoPositionInfoSource::PositioningMethods, QString> createPositioningMethodsToProviderMap() -{ - QMap<QGeoPositionInfoSource::PositioningMethods, QString> map; - - map.insert(QGeoPositionInfoSource::SatellitePositioningMethods, QString("gnss")); - map.insert(QGeoPositionInfoSource::NonSatellitePositioningMethods, QString("network")); - map.insert(QGeoPositionInfoSource::AllPositioningMethods, QString("hybrid")); - - return map; -} - -const QMap<QGeoPositionInfoSource::PositioningMethods, QString> - positioningMethodsToProviderMap = createPositioningMethodsToProviderMap(); - -// list of valid strings for the Location Manager reset types -QStringList createValidResetTypesList() -{ - QStringList list; - list.append("cold"); - list.append("warm"); - list.append("hot"); - list.append("factory"); - list.append("ee_data"); - list.append("almanac"); - list.append("ephemeris"); - - return list; -} - -const QStringList validResetTypes = createValidResetTypesList(); - -void printGetGeomagneticFieldInputs(const wmm_location_t &location, const struct tm &date) -{ - qWarning() << "location = (" - << location.latitude_deg - << "," - << location.longitude_deg - << "," - << location.altitude_meters - << ")"; - qWarning() << "date = (" << date.tm_sec << - "," << date.tm_min << - "," << date.tm_hour << - "," << date.tm_mday << - "," << date.tm_mon << - "," << date.tm_year << - "," << date.tm_wday << - "," << date.tm_yday << - "," << date.tm_isdst << -#ifndef BB_TEST_BUILD -// the following fields are not present on host (at least Win32) - "," << date.tm_gmtoff << - "," << date.tm_zone << -#endif - ")"; -} - -bool magneticDeclination(double *declination, const QGeoPositionInfo &position) -{ - if (!declination) - return false; - - wmm_location_t location; - struct tm date; - wmm_geomagnetic_field_t field; - - location.latitude_deg = position.coordinate().latitude(); - location.longitude_deg = position.coordinate().longitude(); - if (position.coordinate().type() == QGeoCoordinate::Coordinate3D) - location.altitude_meters = position.coordinate().altitude(); - else - location.altitude_meters = 0.0; - - time_t time = (time_t)position.timestamp().toTime_t(); -#ifdef BB_TEST_BUILD - // since gmtime_r() is not defined on host (at least Win32) risk reentrant side effects on the - // returned data. - struct tm *pDate = gmtime(&time); - if (pDate == NULL) { - qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): " - "gmtime() returned NULL"; - return false; - } - date = *pDate; -#else - if (gmtime_r(&time, &date) == NULL) { - qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): " - "gmtime_r() returned NULL"; - return false; - } -#endif - - switch (wmm_get_geomagnetic_field(&location, &date, &field)) { - case 0: - break; - - case 1: - qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): " - "wmm_get_geomagnetic_field() returned: inputs limited to model range"; - printGetGeomagneticFieldInputs(location, date); - break; - - case -1: - default: - qWarning() << "QGeoPositionInfoSourceBbPrivate.cpp:magneticDeclination(): " - "wmm_get_geomagnetic_field() returned: error"; - printGetGeomagneticFieldInputs(location, date); - return false; - } - - *declination = field.declination_deg; - return true; -} - -QVariantMap populateLastKnownPositionRequest(bool fromSatellitePositioningMethodsOnly) -{ - QVariantMap map; - QVariantMap datMap; - - if (fromSatellitePositioningMethodsOnly) - datMap.insert("provider", "gnss"); - else - datMap.insert("provider", "hybrid"); - - datMap.insert("last_known", true); - datMap.insert("period", 0); - - map.insert("msg", "location"); - map.insert("id", ::global::libQtLocationId); - map.insert("dat", datMap); - - return map; -} - -// From a QvariantMap representing a location response from the Location Manager fill a -// QGeoPositionInfo instance intended to be emitted via positionUpdated() signal. Returns true -// if the position info was successfully populated. -bool populatePositionInfo(QGeoPositionInfo *position, const QVariantMap &map) -{ - // populate position - - // set the reply dat property, which can be accessed by the user in the slot connected to - //the positionUpdated() signal - QVariantMap replyDat = map.value("dat").toMap(); - - // check for required fields - if (!replyDat.contains("latitude") || !replyDat.contains("longitude") - || !replyDat.contains("accuracy")) { - return false; - } - - // set the lat/long/alt coordinate - QGeoCoordinate coord; - coord.setLatitude(replyDat.value("latitude").toDouble()); - coord.setLongitude(replyDat.value("longitude").toDouble()); - if (replyDat.contains("altitude")) - coord.setAltitude(replyDat.value("altitude").toDouble()); - - if (!coord.isValid()) - return false; - - position->setCoordinate(coord); - - // set the time stamp - QDateTime dateTime; - dateTime.setTimeSpec(Qt::UTC); - if (replyDat.contains("utc") && static_cast<int>(replyDat.value("utc").toDouble()) != 0) { - // utc is msec since epoch (1970-01-01T00:00:00) - dateTime.setTime_t(qRound((replyDat.value("utc").toDouble() / 1000.0))); - } else { - // this relies on the device's clock being accurate - dateTime = QDateTime::currentDateTimeUtc(); - } - position->setTimestamp(dateTime); - - // attributes - if (replyDat.contains("heading")) { - position->setAttribute(QGeoPositionInfo::Direction, - static_cast<qreal>(replyDat.value("heading").toDouble())); - } else { - position->removeAttribute(QGeoPositionInfo::Direction); - } - - if (replyDat.contains("speed")) { - position->setAttribute(QGeoPositionInfo::GroundSpeed, - static_cast<qreal>(replyDat.value("speed").toDouble())); - } else { - position->removeAttribute(QGeoPositionInfo::GroundSpeed); - } - - if (replyDat.contains("verticalSpeed")) { - position->setAttribute(QGeoPositionInfo::VerticalSpeed, - static_cast<qreal>(replyDat.value("verticalSpeed").toDouble())); - } else { - position->removeAttribute(QGeoPositionInfo::VerticalSpeed); - } - - if (replyDat.contains("declination")) { - position->setAttribute(QGeoPositionInfo::MagneticVariation, - static_cast<qreal>(replyDat.value("declination").toDouble())); - } else { - double declination; - - if (magneticDeclination(&declination, *position) == true) { - position->setAttribute(QGeoPositionInfo::MagneticVariation, - static_cast<qreal>(declination)); - } else { - position->removeAttribute(QGeoPositionInfo::MagneticVariation); - } - } - - // replyDat.contains("accuracy") was confirmed above - position->setAttribute(QGeoPositionInfo::HorizontalAccuracy, - static_cast<qreal>(replyDat.value("accuracy").toDouble())); - - if (replyDat.contains("altitudeAccuracy")) { - position->setAttribute(QGeoPositionInfo::VerticalAccuracy, - static_cast<qreal>(replyDat.value("altitudeAccuracy").toDouble())); - } else { - position->removeAttribute(QGeoPositionInfo::VerticalAccuracy); - } - - return true; -} - -} // unnamed namespace - -/////////////////////////// -// -// QGeoPositionInfoSourceBbPrivate -// -/////////////////////////// - -// Create a QVariantMap suitable for writing to a PpsObject specifying a location request to the -// Location Manager. If the request is periodic then the update interval is used. Otherwise 0 -// indicates to the Location Manager that it is a request for a single, immediate location response. -// singleRequestMsec applies only to the single, immediate location response. It represents the -// expected location response time, after which it is assumed a timeout response occurs. -QVariantMap QGeoPositionInfoSourceBbPrivate::populateLocationRequest(bool periodic, - int singleRequestMsec) const -{ - Q_Q(const QGeoPositionInfoSourceBb); - - QVariantMap map; - QVariantMap datMap; - - int period; - int responseTime; - if (periodic) { - // rounding is performed here because the Location Manager truncates to nearest integer - period = (q->updateInterval() + 500) / 1000; - // The Qt MObility API treats a period of 0 as indicating default behavior - if (period == 0) { - // specify global::defaultPositionUpdatePeriod as the default behavior for Location - // Manager - period = ::global::defaultPositionUpdatePeriod; - } - responseTime = qRound(_responseTime); - } else { - period = 0; - responseTime = (singleRequestMsec + 500) / 1000; - } - - // period is the only mandatory field - datMap.insert("period", period); - - if (_accuracy > 0.0) - datMap.insert("accuracy", _accuracy); - if (responseTime > 0.0) - datMap.insert("response_time", responseTime); - - // since there is no uninitialized state for bool always specify the background mode - datMap.insert("background", _canRunInBackground); - - QString provider = positioningMethodsToProviderMap.value(q->preferredPositioningMethods()); - if (!provider.isEmpty()) - datMap.insert("provider", provider); - - if (!_fixType.isEmpty()) - datMap.insert("fix_type", _fixType); - - if (!_appId.isEmpty()) - datMap.insert("app_id", _appId); - - if (!_appPassword.isEmpty()) - datMap.insert("app_password", _appPassword); - - if (!_pdeUrl.isEmpty()) - datMap.insert("pde_url", _pdeUrl.toEncoded().constData()); - - if (!_slpUrl.isEmpty()) - datMap.insert("slp_url", _slpUrl.toEncoded().constData()); - - map.insert("msg", "location"); - map.insert("id", global::libQtLocationId); - map.insert("dat", datMap); - - return map; -} - -QVariantMap QGeoPositionInfoSourceBbPrivate::populateResetRequest() const -{ - QVariantMap map; - QVariantMap datMap; - - datMap.insert("reset_type", _resetType); - - map.insert("msg", "reset"); - map.insert("id", ::global::libQtLocationId); - map.insert("dat", datMap); - - return map; -} - -bool QGeoPositionInfoSourceBbPrivate::requestPositionInfo(bool periodic, int singleRequestMsec) -{ - // build up the request - QVariantMap request = populateLocationRequest(periodic, singleRequestMsec); - - bb::PpsObject *ppsObject; - if (periodic) - ppsObject = _periodicUpdatePpsObject; - else - ppsObject = _singleUpdatePpsObject; - - bool returnVal = sendRequest(*ppsObject, request); -#ifndef BB_TEST_BUILD - if (!returnVal) { - // test for pps file error - switch (ppsObject->error()) { - case EACCES: - _replyErrorCode = bb::location::PositionErrorCode::FatalPermission; - _replyErr = "failed"; - _replyErrStr = ppsObject->errorString(); - break; - - case EOK: - _replyErrorCode = bb::location::PositionErrorCode::FatalUnknown; - _replyErr = "failed"; - _replyErrStr = "Unknown error occurred sending request"; - qWarning() << "QGeoPositionInfoSourceBbPrivate::requestPositionInfo() :" - << _replyErrStr; - break; - - default: - _replyErrorCode = bb::location::PositionErrorCode::FatalUnknown; - _replyErr = "failed"; - _replyErrStr = ppsObject->errorString(); - qWarning() << "QGeoPositionInfoSourceBbPrivate::requestPositionInfo() : " - "unexpected error, errno =" - << ppsObject->error() - << " (" - << ppsObject->errorString() - << ")"; - break; - } - } -#endif // !BB_TEST_BUILD - - return returnVal; -} - -void QGeoPositionInfoSourceBbPrivate::cancelPositionInfo(bool periodic) -{ - bb::PpsObject *ppsObject; - if (periodic) - ppsObject = _periodicUpdatePpsObject; - else - ppsObject = _singleUpdatePpsObject; - - (void)sendRequest(*ppsObject, global::cancelRequest); -} - -void QGeoPositionInfoSourceBbPrivate::resetLocationProviders() -{ - QVariantMap map = populateResetRequest(); - (void)sendRequest(*_periodicUpdatePpsObject, map); -} - -// Get the last known position from the Location Manager. Any error results in the return of an -// invalid position. -QGeoPositionInfo QGeoPositionInfoSourceBbPrivate::lastKnownPosition( - bool fromSatellitePositioningMethodsOnly) const -{ - QGeoPositionInfo position = QGeoPositionInfo(); - bb::PpsObject ppsObject(global::locationManagerPpsFile); - QVariantMap lastKnown = populateLastKnownPositionRequest(fromSatellitePositioningMethodsOnly); - - if (!ppsObject.open()) - return position; - - // Location Manager promises to reply immediately with the last known position or an error. - ppsObject.setBlocking(true); - - if (!sendRequest(ppsObject, lastKnown)) - return position; - - if (!receiveReply(&lastKnown, ppsObject)) - return position; - - if (!lastKnown.contains("res") || lastKnown.value("res").toString() != "location") - return position; - - // the return value of populatePositionInfo() is ignored since either way position is returned - // by lastKnownPosition() - (void)populatePositionInfo(&position, lastKnown); - - return position; -} - -// Constructor. Note there are two PpsObjects for handling the two different types of requests that -// can be simultaneously made and which must be handled independently (apart from both being -// emitted through the same signal when done-part of Qt Mobility spec. -QGeoPositionInfoSourceBbPrivate::QGeoPositionInfoSourceBbPrivate(QGeoPositionInfoSourceBb *parent) - : QObject(parent), - _startUpdatesInvoked(false), - _requestUpdateInvoked(false), - _canEmitPeriodicUpdatesTimeout(true), - q_ptr(parent), - _periodicUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)), - _singleUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)), - _sourceError(QGeoPositionInfoSource::NoError), - _accuracy(0.0), - _responseTime(0.0), - _canRunInBackground(false), - _fixType(QString()), - _appId(QString()), - _appPassword(QString()), - _pdeUrl(QUrl()), - _slpUrl(QUrl()), - _replyDat(QVariantMap()), - _replyErrorCode(bb::location::PositionErrorCode::None), - _replyErr(QString()), - _replyErrStr(QString()), - _resetType(QString()) -{ - // register bb::location::PositionErrorCode::Type so it can be used with QObject::property() - qRegisterMetaType<bb::location::PositionErrorCode::Type>(); - - // connect to periodic update PpsObject::readyRead() - connect(_periodicUpdatePpsObject, SIGNAL(readyRead()), SLOT(receivePeriodicPositionReply())); - - // connect to single update PpsObject::readyRead() - connect(_singleUpdatePpsObject, SIGNAL(readyRead()), SLOT(receiveSinglePositionReply())); - - // queued connection to signal updateTimeout() - connect(this, SIGNAL(queuedUpdateTimeout()), SLOT(emitUpdateTimeout()), Qt::QueuedConnection); -} - -QGeoPositionInfoSourceBbPrivate::~QGeoPositionInfoSourceBbPrivate() -{ - stopUpdates(); -} - -// request periodic updates -void QGeoPositionInfoSourceBbPrivate::startUpdates() -{ - // do nothing if periodic updates have already been started - if (_startUpdatesInvoked) - return; - - // This flag is used to limit emitting the timeout signal to once per each interruption in the - // periodic updates. Since updates are being started here ensure the flag is set to true. - _canEmitPeriodicUpdatesTimeout = true; - - // build a request and initiate it - if (requestPositionInfo(true)) { - _startUpdatesInvoked = true; - _currentPosition = QGeoPositionInfo(); - } else { - // With Qt5 the error() signal was introduced. If there are any receivers emit error() else - // maintain QtMobility behavior. - _sourceError - = positionErrorCodeToErrorMap.value(_replyErrorCode, - QGeoPositionInfoSource::UnknownSourceError); - Q_Q(QGeoPositionInfoSourceBb); - if (q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) { - Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError); - } else { - // user is expecting a signal to be emitted, cannot emit positionUpdated() because of - // error so emit timeout signal. The connection is queued because it is possible for the - // user to call startUpdates() from within the slot handling the timeout. The queued - // connection avoids potential infinite recursion. - Q_EMIT queuedUpdateTimeout(); - } - } -} - -// stop periodic updates -void QGeoPositionInfoSourceBbPrivate::stopUpdates() -{ - // do nothing if periodic updates have not been started - if (!_startUpdatesInvoked) - return; - - cancelPositionInfo(true); - _startUpdatesInvoked = false; - _currentPosition = QGeoPositionInfo(); - - // close the pps file to ensure readyRead() does not spin in the event that we don't read the - // reply to the cancel request. Note that open() is done lazily in sendRequest(). - _periodicUpdatePpsObject->close(); -} - -// periodic updates have timed out -void QGeoPositionInfoSourceBbPrivate::periodicUpdatesTimeout() -{ - // do nothing if periodic updates have not been started - if (!_startUpdatesInvoked) - return; - - // timeout has occurred, but periodic updates are still active. Ensure the timeout signal is - // emitted only once per interruption of updates. _canEmitPeriodicUpdatesTimeout is set back - // to true when the next successful periodic update occurs (see emitPositionUpdated()). This - // behavior is per the Qt Mobility Location API documentation. - if (_canEmitPeriodicUpdatesTimeout) { - _canEmitPeriodicUpdatesTimeout = false; - emitUpdateTimeout(); - } -} - -// request single update -void QGeoPositionInfoSourceBbPrivate::requestUpdate(int msec) -{ - // do nothing if an immediate update has already been requested - if (_requestUpdateInvoked) - return; - - if (msec) { - // If it is not possible to update in msec timeout immediately. - Q_Q(QGeoPositionInfoSourceBb); - if (msec < q->minimumUpdateInterval()) { - // The connection is queued because it is possible for the user to call requestUpdate() - // from within the slot handling the timeout. The queued connection avoids potential - // infinite recursion. - Q_EMIT queuedUpdateTimeout(); - return; - } - } - - if (requestPositionInfo(false, msec)) { - _requestUpdateInvoked = true; - } else { - // With Qt5 the error() signal was introduced. If there are any receivers emit error() else - // maintain QtMobility behavior. - _sourceError - = positionErrorCodeToErrorMap.value(_replyErrorCode, - QGeoPositionInfoSource::UnknownSourceError); - Q_Q(QGeoPositionInfoSourceBb); - if (q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) { - Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError); - } else { - // user is expecting a signal to be emitted, cannot emit positionUpdated() because of - // error so emit timeout signal. The connection is queued because it is possible for the - // user to call startUpdates() from within the slot handling the timeout. The queued - // connection avoids potential infinite recursion. - Q_EMIT queuedUpdateTimeout(); - } - } -} - -// single update has timed out. This is a slot for the requestUpdate timer -void QGeoPositionInfoSourceBbPrivate::singleUpdateTimeout() -{ - _requestUpdateInvoked = false; - - emitUpdateTimeout(); - - if (!_requestUpdateInvoked) { - // close the pps file to ensure readyRead() does not spin in the event that there are - // unexpected replies that we don't read. Note that open() is done lazily in sendRequest(). - _singleUpdatePpsObject->close(); - } -} - -// This slot is intended for queued connection to the signal queuedUpdateTimeout(). If an error -// occurs when an update is requested the error is relayed via updateTimeout() but the connection -// is queued to avoid potential infinite recursion. -void QGeoPositionInfoSourceBbPrivate::emitUpdateTimeout() -{ - Q_Q(QGeoPositionInfoSourceBb); - Q_EMIT q->updateTimeout(); -} - -void QGeoPositionInfoSourceBbPrivate::emitPositionUpdated(const QGeoPositionInfo &update) -{ - // having successfully received a position update, set _canEmitPeriodicUpdatesTimeout to true, - // which (re)enables a timeout to be emitted upon any subsequent error in periodic updating. - _canEmitPeriodicUpdatesTimeout = true; - - Q_Q(QGeoPositionInfoSourceBb); - Q_EMIT q->positionUpdated(update); -} - -bool QGeoPositionInfoSourceBbPrivate::receivePositionReply(bb::PpsObject &ppsObject) -{ - QVariantMap reply; - // receiveReply() tests for errors associated with the request being replied to - if (!receiveReply(&reply, ppsObject)) { - _replyErrorCode = bb::location::PositionErrorCode::FatalUnknown; - - // if there is an error from Location Manager report it so user can access it through the - // properties when responding to the updateTimeout() signal. - if (reply.contains("errCode")) { - int errCode = reply.value("errCode").toInt(); - _replyErrorCode - = intToPositionErrorCodeMap.value(errCode, - bb::location::PositionErrorCode::FatalUnknown); - if (fatalError(_replyErrorCode)) { - _sourceError - = positionErrorCodeToErrorMap.value(_replyErrorCode, - QGeoPositionInfoSource::UnknownSourceError); - } - - if (reply.contains("err")) { - _replyErr = reply.value("err").toString(); - if (reply.contains("errstr")) { - _replyErrStr = reply.value("errstr").toString(); - } - } - } else { - _sourceError = QGeoPositionInfoSource::UnknownSourceError; - } - return false; - } - - // clear any errors - _replyErrorCode = bb::location::PositionErrorCode::None; - _replyErr = QString(); - _replyErrStr = QString(); - - // check that this is a location reply (could be a reply to another request type, eg. cancel, - // which is ignored here) - if (reply.contains("res") && reply.value("res").toString() == "location") { - // keep the raw LM reply for access via Qt properties. - _replyDat = reply.value("dat").toMap(); - - // extract the geo position info from the reply into _currentPosition - if (populatePositionInfo(&_currentPosition, reply)) { - emitPositionUpdated(_currentPosition); - } - } - - return true; -} - -void QGeoPositionInfoSourceBbPrivate::receivePeriodicPositionReply() -{ - // don't try to receive a reply if periodic updates have not been started. This is - // necessary because this slot is connected to PpsObject::readyRead() and could be - // invoked any time the pps file is updated by the server. Under error conditions - // this would otherwise lead to a circular calling sequence: receive, timeout due to - // error, cancel, receive... - if (!_startUpdatesInvoked) - return; - - if (!receivePositionReply(*_periodicUpdatePpsObject)) { - Q_Q(QGeoPositionInfoSourceBb); - if (fatalError(_replyErrorCode) - && q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) { - Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError); - } else { - periodicUpdatesTimeout(); - } - } -} - -void QGeoPositionInfoSourceBbPrivate::receiveSinglePositionReply() -{ - // don't try to receive a reply if a single update has not been requested. This is - // necessary because this slot is connected to PpsObject::readyRead() and could be - // invoked any time the pps file is updated by the server. Under error conditions - // this would otherwise lead to a circular calling sequence: receive, timeout due to - // error, cancel, receive... - if (!_requestUpdateInvoked) - return; - - // clear this before calling receivePositionReply() which can emit the positionUpdated() - // signal. It is possible to call requestUpdate() in the slot connected to - // positionUpdated() so for requestUpdate() to work _requestUpdateInvoked must be false - _requestUpdateInvoked = false; - - if (!receivePositionReply(*_singleUpdatePpsObject)) { - Q_Q(QGeoPositionInfoSourceBb); - if (fatalError(_replyErrorCode) - && q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) { - Q_EMIT ((QGeoPositionInfoSource *)q)->error(_sourceError); - } else { - singleUpdateTimeout(); - } - } - - if (!_requestUpdateInvoked) { - // close the pps file to ensure readyRead() does not spin in the event that there are - // unexpected replies that we don't read. Note that open() is done lazily in sendRequest(). - _singleUpdatePpsObject->close(); - } -} - -/////////////////////////// -// -// QGeoPositionInfoSourceBb -// -/////////////////////////// - -/*! - \class QGeoPositionInfoSourceBb - \brief The QGeoPositionInfoSourceBb class is for the distribution of positional updates obtained - from the underlying Qnx Location Manager. - - QGeoPositionInfoSourceBb is a subclass of QGeoPositionInfoSource. The static function - QGeoPositionInfoSource::createDefaultSource() creates a default - position source that is appropriate for the platform, if one is available. On BB10 this is - a QGeoPositionInfoSourceBb instance. - - Users of a QGeoPositionInfoSource subclass can request the current position using - requestUpdate(), or start and stop regular position updates using - startUpdates() and stopUpdates(). When an update is available, - positionUpdated() is emitted. The last known position can be accessed with - lastKnownPosition(). - - If regular position updates are required, setUpdateInterval() can be used - to specify how often these updates should be emitted. If no interval is - specified, updates are simply provided whenever they are available. - For example: - - \code - // Emit updates every 10 seconds if available - QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(0); - if (source) - source->setUpdateInterval(10000); - \endcode - - To remove an update interval that was previously set, call - setUpdateInterval() with a value of 0. - - Note that the position source may have a minimum value requirement for - update intervals, as returned by minimumUpdateInterval(). -*/ - -/*! - Constructs a QGeoPositionInfoSourceBb instance with the given \a parent - and \a updateMode. -*/ -QGeoPositionInfoSourceBb::QGeoPositionInfoSourceBb(QObject *parent) - : QGeoPositionInfoSource(parent), - d_ptr(new QGeoPositionInfoSourceBbPrivate(this)) -{ -} - -/*! - Destroys the position source. -*/ -QGeoPositionInfoSourceBb::~QGeoPositionInfoSourceBb() -{ -} - -/*! - \reimp -*/ -void QGeoPositionInfoSourceBb::setUpdateInterval(int msec) -{ - int interval = msec; - if (interval != 0) - interval = qMax(msec, minimumUpdateInterval()); - - if (interval == updateInterval()) - return; - - QGeoPositionInfoSource::setUpdateInterval(interval); - - Q_D(QGeoPositionInfoSourceBb); - if (d->_startUpdatesInvoked) { - d->stopUpdates(); - d->startUpdates(); - } -} - -/*! - \reimp -*/ -void QGeoPositionInfoSourceBb::setPreferredPositioningMethods(PositioningMethods methods) -{ - PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); - QGeoPositionInfoSource::setPreferredPositioningMethods(methods); - if (previousPreferredPositioningMethods == preferredPositioningMethods()) - return; - - Q_D(QGeoPositionInfoSourceBb); - if (d->_startUpdatesInvoked) { - d->stopUpdates(); - d->startUpdates(); - } -} - -/*! - \reimp -*/ -void QGeoPositionInfoSourceBb::startUpdates() -{ - Q_D(QGeoPositionInfoSourceBb); - d->startUpdates(); -} - -/*! - \reimp -*/ -void QGeoPositionInfoSourceBb::stopUpdates() -{ - Q_D(QGeoPositionInfoSourceBb); - d->stopUpdates(); -} - -/*! - \reimp -*/ -void QGeoPositionInfoSourceBb::requestUpdate(int msec) -{ - Q_D(QGeoPositionInfoSourceBb); - d->requestUpdate(msec); -} - -/*! - \reimp -*/ -QGeoPositionInfo - QGeoPositionInfoSourceBb::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->lastKnownPosition(fromSatellitePositioningMethodsOnly); -} - -/*! - \reimp -*/ -QGeoPositionInfoSource::PositioningMethods - QGeoPositionInfoSourceBb::supportedPositioningMethods() const -{ - return AllPositioningMethods; -} - -/*! - \reimp -*/ -int QGeoPositionInfoSourceBb::minimumUpdateInterval() const -{ - return global::minUpdateInterval; -} - -QGeoPositionInfoSource::Error QGeoPositionInfoSourceBb::error() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_sourceError; -} - -// these properties extend QGeoPositionInfoSource allowing use of additional features of the Qnx Location Manager - -// the following properties are the fields of the dat parameter of the location request - -/*! - \property QGeoPositionInfoSourceBb::period - \brief This property specifies the period of the location request, in seconds. A value of - '0' indicates a one-time location request. -*/ -double QGeoPositionInfoSourceBb::period() const -{ - // convert from msec to sec - return updateInterval() / 1000.0; -} - -void QGeoPositionInfoSourceBb::setPeriod(double period) -{ - // convert from sec to msec, round to nearest msec - setUpdateInterval(qRound(static_cast<qreal>(period * 1000.0))); -} - -/*! - \property QGeoPositionInfoSourceBb::accuracy - \brief This property specifies the desired accuracy of the fix, in meters. A value of '0' - disables accuracy criteria. -*/ -double QGeoPositionInfoSourceBb::accuracy() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_accuracy; -} - -void QGeoPositionInfoSourceBb::setAccuracy(double accuracy) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_accuracy = accuracy; -} - -/*! - \property QGeoPositionInfoSourceBb::responseTime - \brief This property specifies the desired response time of the fix, in seconds. A value of - '0' disables response time criteria. -*/ -double QGeoPositionInfoSourceBb::responseTime() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_responseTime; -} - -void QGeoPositionInfoSourceBb::setResponseTime(double responseTime) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_responseTime = responseTime; -} - -/*! - \property QGeoPositionInfoSourceBb::canRunInBackground - \brief This property determines whether or not requests are allowed to run with the device - in standby (i.e. screen off) -*/ -bool QGeoPositionInfoSourceBb::canRunInBackground() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_canRunInBackground; -} - -void QGeoPositionInfoSourceBb::setCanRunInBackground(bool canRunInBackground) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_canRunInBackground = canRunInBackground; -} - -/*! - \property QGeoPositionInfoSourceBb::provider - \brief This property specifies the location provider you wish to use (hybrid, gnss, - network). -*/ -QString QGeoPositionInfoSourceBb::provider() const -{ - return positioningMethodsToProviderMap.value(preferredPositioningMethods()); -} - -void QGeoPositionInfoSourceBb::setProvider(const QString &provider) -{ - setPreferredPositioningMethods(positioningMethodsToProviderMap.key(provider)); -} - -/*! - \property QGeoPositionInfoSourceBb::fixType - \brief This property specifies the fix type you wish to use (best, gps_ms_based, - gps_ms_assisted, gps_autonomous, cellsite, wifi). -*/ -QString QGeoPositionInfoSourceBb::fixType() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_fixType; -} - -void QGeoPositionInfoSourceBb::setFixType(const QString &fixType) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_fixType = fixType; -} - -/*! - \property QGeoPositionInfoSourceBb::appId - \brief This property specifies a special application id. -*/ -QString QGeoPositionInfoSourceBb::appId() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_appId; -} - -void QGeoPositionInfoSourceBb::setAppId(const QString &appId) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_appId = appId; -} - -/*! - \property QGeoPositionInfoSourceBb::appPassword - \brief This property specifies a special application password, goes with appId above. -*/ -QString QGeoPositionInfoSourceBb::appPassword() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_appPassword; -} - -void QGeoPositionInfoSourceBb::setAppPassword(const QString &appPassword) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_appPassword = appPassword; -} - -/*! - \property QGeoPositionInfoSourceBb::pdeUrl - \brief This property specifies the PDE URL (i.e. tcp://user:pass@address.dom:1234). -*/ -QUrl QGeoPositionInfoSourceBb::pdeUrl() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_pdeUrl; -} - -void QGeoPositionInfoSourceBb::setPdeUrl(const QUrl &pdeUrl) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_pdeUrl = pdeUrl; -} - -/*! - \property QGeoPositionInfoSourceBb::slpUrl - \brief This property specifies the SLP URL (i.e. tcp://user:pass@address.dom:1234). -*/ -QUrl QGeoPositionInfoSourceBb::slpUrl() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_slpUrl; -} - -void QGeoPositionInfoSourceBb::setSlpUrl(const QUrl &slpUrl) -{ - Q_D(QGeoPositionInfoSourceBb); - d->_slpUrl = slpUrl; -} - -// the following read-only properties are the fields of the Location Manager generic reply - -/*! - \property QGeoPositionInfoSourceBb::replyDat - \brief This property specifies the object containing the reply data (such as latitude, - longitude, satellites, etc). If the replyErr is not empty then replyDat may be empty or - stale. replyDat is expected to be consumed in the slot connected to the positionUpdated() - signal, otherwise its contents are undefined. -*/ -QVariantMap QGeoPositionInfoSourceBb::replyDat() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_replyDat; -} - -/*! - \property QGeoPositionInfoSourceBb::replyErrorCode - \brief If not empty this property indicates that an error has occurred, and identifies the - error. - - Possible values are: - - Code | Description - None | No error - FatalDisabled | Location services is disabled - FatalNoLastKnownPosition | There is no last known position on the device - FatalInsufficientProviders | There are insufficient available location technology providers - to process your request - FatalInvalidRequest | One or more of the request parameters are invalid. - WarnTimeout | A timeout has occurred while processing your request. The request will - continue until your location is obtained - WarnLostTracking | The location fix has been lost due to insufficient coverage. The request - will continue until your location is reacquired - WarnStationary | The device is stationary. No further updates until the device resumes - movement - - replyErrorCode is expected to be consumed in the slot connected to the updateTimeout() - signal, which is emitted when an error is detected. Otherwise its contents are undefined. -*/ -bb::location::PositionErrorCode::Type QGeoPositionInfoSourceBb::replyErrorCode() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_replyErrorCode; -} - -/*! - \property QGeoPositionInfoSourceBb::replyErr - \brief If not empty this property indicates that an error has occurred, and identifies the - error. replyErr is expected to be consumed in the slot connected to the updateTimeout() - signal, which is emitted when an error is detected. Otherwise its contents are undefined. -*/ -QString QGeoPositionInfoSourceBb::replyErr() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_replyErr; -} - -/*! - \property QGeoPositionInfoSourceBb::replyErrStr - \brief This property is not empty if and only if the replyErr parameter is present, it - describes the error. replyErrStr is expected to be consumed in the slot connected to the - updateTimeout() signal, which is emitted when an error is detected. Otherwise its contents - are undefined. -*/ -QString QGeoPositionInfoSourceBb::replyErrStr() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_replyErrStr; -} - -/*! - \property QGeoPositionInfoSourceBb::locationServicesEnabled - \brief This property indicates whether the location services are enabled or not. If - location services are disabled then no position updates will occur. The user must enable - location services through the Settings app before any position updates will be available. -*/ -bool QGeoPositionInfoSourceBb::locationServicesEnabled() const -{ - bool locationEnabled = false; - if (location_manager_get_status(&locationEnabled) != 0) { - qWarning() << "QGeoPositionInfoSourceBb::locationServicesEnabled() : " - "call to location_manager_get_status() failed."; - } - return locationEnabled; -} - -/*! - \property QGeoPositionInfoSourceBb::reset - \brief By setting this property a reset of all location providers is requested through the - Location Manager. The value of reset specifies the type of reset to be performed. Valid - reset types are "cold", "warm", "hot", and "factory". The reset is not actually carried out - until position updates are restarted. The current value of this property, i.e. - property("reset"), is not particularly useful, it is simply the reset type corresponding to - the last time setProperty("reset", resetType) was called. A Qt property must have a READ - method, hence the reason for defining resetType(). -*/ -QString QGeoPositionInfoSourceBb::resetType() const -{ - Q_D(const QGeoPositionInfoSourceBb); - return d->_resetType; -} - -void QGeoPositionInfoSourceBb::requestReset(const QString &resetType) -{ - if (validResetTypes.contains(resetType)) { - Q_D(QGeoPositionInfoSourceBb); - d->_resetType = resetType; - d->resetLocationProviders(); - } -} diff --git a/src/plugins/position/blackberry/qgeopositioninfosource_bb.h b/src/plugins/position/blackberry/qgeopositioninfosource_bb.h deleted file mode 100644 index cd1ab331..00000000 --- a/src/plugins/position/blackberry/qgeopositioninfosource_bb.h +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGEOPOSITIONINFOSOURCE_BB_H -#define QGEOPOSITIONINFOSOURCE_BB_H - -#include <QGeoPositionInfoSource> - -#include <bb/location/PositionErrorCode> - -#include <QString> -#include <QVariantMap> -#include <QScopedPointer> -#include <QUrl> - -class QGeoPositionInfoSourceBbPrivate; -class BB_LOCATION_EXPORT QGeoPositionInfoSourceBb : public QGeoPositionInfoSource -{ - Q_OBJECT - - Q_PROPERTY(double period READ period WRITE setPeriod FINAL) - Q_PROPERTY(double accuracy READ accuracy WRITE setAccuracy FINAL) - Q_PROPERTY(double responseTime READ responseTime WRITE setResponseTime FINAL) - Q_PROPERTY(bool canRunInBackground READ canRunInBackground WRITE setCanRunInBackground FINAL) - Q_PROPERTY(QString provider READ provider WRITE setProvider FINAL) - Q_PROPERTY(QString fixType READ fixType WRITE setFixType FINAL) - Q_PROPERTY(QString appId READ appId WRITE setAppId FINAL) - Q_PROPERTY(QString appPassword READ appPassword WRITE setAppPassword FINAL) - Q_PROPERTY(QUrl pdeUrl READ pdeUrl WRITE setPdeUrl FINAL) - Q_PROPERTY(QUrl slpUrl READ slpUrl WRITE setSlpUrl FINAL) - - Q_PROPERTY(QVariantMap replyDat READ replyDat FINAL) - Q_PROPERTY(bb::location::PositionErrorCode::Type replyErrorCode READ replyErrorCode FINAL) - Q_PROPERTY(QString replyErr READ replyErr FINAL) - Q_PROPERTY(QString replyErrStr READ replyErrStr FINAL) - - Q_PROPERTY(bool locationServicesEnabled READ locationServicesEnabled FINAL) - - Q_PROPERTY(QString reset READ resetType WRITE requestReset FINAL) - -public: - explicit QGeoPositionInfoSourceBb(QObject *parent = 0); - virtual ~QGeoPositionInfoSourceBb(); - - void setUpdateInterval(int msec); - void setPreferredPositioningMethods(PositioningMethods methods); - QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; - PositioningMethods supportedPositioningMethods() const; - int minimumUpdateInterval() const; - Error error() const; - - double period() const; - void setPeriod(double period); - - double accuracy() const; - void setAccuracy(double accuracy); - - double responseTime() const; - void setResponseTime(double responseTime); - - bool canRunInBackground() const; - void setCanRunInBackground(bool canRunInBackground); - - QString provider() const; - void setProvider(const QString &provider); - - QString fixType() const; - void setFixType(const QString &fixType); - - QString appId() const; - void setAppId(const QString &appId); - - QString appPassword() const; - void setAppPassword(const QString &appPassword); - - QUrl pdeUrl() const; - void setPdeUrl(const QUrl &pdeUrl); - - QUrl slpUrl() const; - void setSlpUrl(const QUrl &slpUrl); - - QVariantMap replyDat() const; - - bb::location::PositionErrorCode::Type replyErrorCode() const; - - QString replyErr() const; - - QString replyErrStr() const; - - bool locationServicesEnabled() const; - - QString resetType() const; - void requestReset(const QString &resetType); - - -public Q_SLOTS: - void startUpdates(); - void stopUpdates(); - void requestUpdate(int timeout = 0); - -private: - Q_DECLARE_PRIVATE(QGeoPositionInfoSourceBb) - Q_DISABLE_COPY(QGeoPositionInfoSourceBb) - QScopedPointer<QGeoPositionInfoSourceBbPrivate> d_ptr; -}; - -#endif diff --git a/src/plugins/position/blackberry/qgeopositioninfosource_bb_p.h b/src/plugins/position/blackberry/qgeopositioninfosource_bb_p.h deleted file mode 100644 index f6a6304b..00000000 --- a/src/plugins/position/blackberry/qgeopositioninfosource_bb_p.h +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGEOPOSITIONINFOSOURCEBB_P_H -#define QGEOPOSITIONINFOSOURCEBB_P_H - -#include "qgeopositioninfosource_bb.h" -#include "qgeopositioninfo.h" - -#include <bb/location/PositionErrorCode> - -#include <QObject> -#include <QVariantMap> -#include <QUrl> - -namespace bb -{ -class PpsObject; -} - -class QGeoPositionInfoSourceBbPrivate : public QObject -{ - Q_OBJECT -public: - ~QGeoPositionInfoSourceBbPrivate(); - - void startUpdates(); - void stopUpdates(); - void requestUpdate(int msec); - - bool _startUpdatesInvoked; - bool _requestUpdateInvoked; - -private Q_SLOTS: - void singleUpdateTimeout(); - void receivePeriodicPositionReply(); - void receiveSinglePositionReply(); - - void emitUpdateTimeout(); - -Q_SIGNALS: - void queuedUpdateTimeout(); - -private: - Q_DECLARE_PUBLIC(QGeoPositionInfoSourceBb) - explicit QGeoPositionInfoSourceBbPrivate(QGeoPositionInfoSourceBb *parent); - - void periodicUpdatesTimeout(); - - void emitPositionUpdated(const QGeoPositionInfo &update); - bool requestPositionInfo(bool periodic, int singleRequestMsec = 0); - void cancelPositionInfo(bool periodic); - void resetLocationProviders(); - QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const; - - QVariantMap populateLocationRequest(bool periodic, int singleRequestMsec = 0) const; - QVariantMap populateResetRequest() const; - - bool receivePositionReply(bb::PpsObject &ppsObject); - - bool _canEmitPeriodicUpdatesTimeout; - - QGeoPositionInfoSourceBb *q_ptr; - bb::PpsObject *_periodicUpdatePpsObject; - bb::PpsObject *_singleUpdatePpsObject; - QGeoPositionInfo _currentPosition; - QGeoPositionInfoSource::Error _sourceError; - - // these are Location Manager parameters that are represented by properties. These parameters - // represent additional functionality beyond what is provided by the base class - // QGeoPositionInfoSource - double _accuracy; - double _responseTime; - bool _canRunInBackground; - QString _fixType; - QString _appId; - QString _appPassword; - QUrl _pdeUrl; - QUrl _slpUrl; - QVariantMap _replyDat; - bb::location::PositionErrorCode::Type _replyErrorCode; - QString _replyErr; - QString _replyErrStr; - QString _resetType; - -}; - -#endif diff --git a/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.cpp b/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.cpp deleted file mode 100644 index 99e3a630..00000000 --- a/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgeopositioninfosourcefactory_bb.h" -#include "qgeopositioninfosource_bb.h" -#include "qgeosatelliteinfosource_bb.h" - -#include <QGeoPositionInfoSource> -#include <QGeoSatelliteInfoSource> - - -/////////////////////////// -// -// QGeoPositionInfoSourceFactoryBb -// -/////////////////////////// - -QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryBb::positionInfoSource(QObject *parent) -{ - return new QGeoPositionInfoSourceBb(parent); -} - -QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryBb::satelliteInfoSource(QObject *parent) -{ - return new QGeoSatelliteInfoSourceBb(parent); -} - -QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryBb::areaMonitor(QObject *parent) -{ - Q_UNUSED(parent); - return 0; -} diff --git a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.cpp b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.cpp deleted file mode 100644 index d87ff12d..00000000 --- a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <bb/PpsObject> - -#include "qgeosatelliteinfosource_bb_p.h" -#include "locationmanagerutil_bb.h" - -#include <location_manager.h> - -extern "C" { -#include <wmm/wmm.h> -} - -#include <QVariantMap> -#include <QByteArray> -#include <QtDebug> - -#include <errno.h> - -/////////////////////////// -// -// local variables/functions -// -/////////////////////////// - -namespace global -{ - -// While waiting for a position fix a satellite update period of 1 sec is considered reasonable. -static const double defaultSatelliteUpdatePeriod = 1.0; - -} // namespace global - -namespace -{ -// map the Location Manager reply error codes to the QGeoSatelliteInfoSource::Error enum values. -QMap<int, QGeoSatelliteInfoSource::Error> createIntToErrorCodeMap() -{ - QMap<int, QGeoSatelliteInfoSource::Error> map; - - map.insert(0, QGeoSatelliteInfoSource::NoError); - map.insert(1, QGeoSatelliteInfoSource::ClosedError); - map.insert(2, QGeoSatelliteInfoSource::UnknownSourceError); - map.insert(3, QGeoSatelliteInfoSource::UnknownSourceError); - map.insert(4, QGeoSatelliteInfoSource::UnknownSourceError); - map.insert(5, QGeoSatelliteInfoSource::UnknownSourceError); - map.insert(6, QGeoSatelliteInfoSource::AccessError); - // the following are not considered errors from QGeoSatelliteInfoSource perspective - // (they are timeout conditions) - map.insert(0x10000, QGeoSatelliteInfoSource::NoError); - map.insert(0x10001, QGeoSatelliteInfoSource::NoError); - map.insert(0x10002, QGeoSatelliteInfoSource::NoError); - - return map; -} - -const QMap<int, QGeoSatelliteInfoSource::Error> intToErrorCodeMap = - createIntToErrorCodeMap(); - -QGeoSatelliteInfo::SatelliteSystem determineSatSystem(int satId) -{ - if (satId >= 1 && satId <= 32) - return QGeoSatelliteInfo::GPS; - - if (satId >= 65 && satId <= 88) - return QGeoSatelliteInfo::GLONASS; - - return QGeoSatelliteInfo::Undefined; -} - -} - -/////////////////////////// -// -// QGeoSatelliteInfoSourceBbPrivate -// -/////////////////////////// - -// Create a QVariantMap suitable for writing to a PpsObject specifying a location request to the -// Location Manager. If the request is periodic then the update interval is used. Otherwise 0 -// indicates to the Location Manager that it is a request for a single, immediate location response. -// singleRequestMsec applies only to the single, immediate location response. It represents the -// expected location response time, after which it is assumed a timeout response occurs. -QVariantMap QGeoSatelliteInfoSourceBbPrivate::populateLocationRequest(bool periodic, - int singleRequestMsec) -{ - Q_Q(const QGeoSatelliteInfoSourceBb); - - QVariantMap map; - QVariantMap datMap; - - int period; - int responseTime; - if (periodic) { - // rounding is performed here because the Location Manager truncates to nearest integer - period = (q->updateInterval() + 500) / 1000; - if (period == 0) - period = ::global::defaultSatelliteUpdatePeriod; - - responseTime = _responseTime; - } else { - period = 0; - responseTime = (singleRequestMsec + 500) / 1000; - } - - datMap.insert("period", period); - datMap.insert("accuracy", 0); - datMap.insert("response_time", responseTime); - datMap.insert("background", _backgroundMode); - - datMap.insert("provider", "gnss"); - datMap.insert("fix_type", "gps_autonomous"); - - // have the Location Manager return the satellite information even if it does not have a - // position fix. - datMap.insert("report_sat", true); - - map.insert("msg", "location"); - map.insert("id", global::libQtLocationId); - map.insert("dat", datMap); - - return map; -} - -// From a QvariantMap representing a location response from the Location Manager fill the lists of -// QGeoSatelliteInfo instances intended to be emitted via satellitesInUseUpdated() and -// satellitesInViewUpdated() signals. -void QGeoSatelliteInfoSourceBbPrivate::populateSatelliteLists(const QVariantMap &map) -{ - // populate _currentSatelliteInfo - QVariantMap datMap = map.value("dat").toMap(); - QVariantList satelliteList = datMap.value("satellites").toList(); - - _satellitesInView.clear(); - _satellitesInUse.clear(); - - Q_FOREACH (const QVariant &satelliteData, satelliteList) { - datMap = satelliteData.toMap(); - QGeoSatelliteInfo satelliteInfo = QGeoSatelliteInfo(); - - if (datMap.contains("id")) - satelliteInfo.setSatelliteIdentifier(static_cast<int>(datMap.value("id").toDouble())); - - satelliteInfo.setSatelliteSystem(determineSatSystem(satelliteInfo.satelliteIdentifier())); - - if (datMap.contains("cno")) - satelliteInfo.setSignalStrength(static_cast<int>(datMap.value("cno").toDouble())); - - // attributes - if (datMap.contains("elevation")) - satelliteInfo.setAttribute(QGeoSatelliteInfo::Elevation, - static_cast<qreal>(datMap.value("elevation").toDouble())); - else - satelliteInfo.removeAttribute(QGeoSatelliteInfo::Elevation); - - if (datMap.contains("azimuth")) - satelliteInfo.setAttribute(QGeoSatelliteInfo::Azimuth, - static_cast<qreal>(datMap.value("azimuth").toDouble())); - else - satelliteInfo.removeAttribute(QGeoSatelliteInfo::Azimuth); - - // each satellite in this list is considered "in view" - _satellitesInView.append(satelliteInfo); - - if (datMap.value("used").toBool() == true) - _satellitesInUse.append(satelliteInfo); - } -} - -// The satellite data is retrieved from a location request -bool QGeoSatelliteInfoSourceBbPrivate::requestSatelliteInfo(bool periodic, - int singleRequestMsec) -{ - // build up the request - QVariantMap request = populateLocationRequest(periodic, singleRequestMsec); - - bb::PpsObject *ppsObject; - if (periodic) - ppsObject = _periodicUpdatePpsObject; - else - ppsObject = _singleUpdatePpsObject; - - if (sendRequest(*ppsObject, request) == false) { - stopUpdates(); - -#ifndef BB_TEST_BUILD - // test for pps file error - switch (ppsObject->error()) { - case EACCES: - _sourceError = QGeoSatelliteInfoSource::AccessError; - break; - default: - _sourceError = QGeoSatelliteInfoSource::UnknownSourceError; - break; - } -#endif // !BB_TEST_BUILD - - return false; - } - - return true; -} - -void QGeoSatelliteInfoSourceBbPrivate::cancelSatelliteInfo(bool periodic) -{ - bb::PpsObject *ppsObject; - if (periodic) - ppsObject = _periodicUpdatePpsObject; - else - ppsObject = _singleUpdatePpsObject; - - (void)sendRequest(*ppsObject, global::cancelRequest); -} - -// Constructor. Note there are two PpsObjects for handling the two different types of requests that -// can be simultaneously made and which must be handled independently (apart from both being emitted -// through the same signal when done-part of Qt Mobility spec. -QGeoSatelliteInfoSourceBbPrivate::QGeoSatelliteInfoSourceBbPrivate( - QGeoSatelliteInfoSourceBb *parent) - : QObject(parent), - _startUpdatesInvoked(false), - _requestUpdateInvoked(false), - q_ptr(parent), - _periodicUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)), - _singleUpdatePpsObject(new bb::PpsObject(global::locationManagerPpsFile, this)), - _sourceError(QGeoSatelliteInfoSource::NoError), - _backgroundMode(false), - _responseTime(0) -{ - // connect to periodic update PpsObject::readyRead() - connect(_periodicUpdatePpsObject, SIGNAL(readyRead()), SLOT(receivePeriodicSatelliteReply())); - - // connect to single update PpsObject::readyRead() - connect(_singleUpdatePpsObject, SIGNAL(readyRead()), SLOT(receiveSingleSatelliteReply())); - - // queued connection to signal requestTimeout() - connect(this, SIGNAL(queuedRequestTimeout()), SLOT(emitRequestTimeout()), Qt::QueuedConnection); -} - -QGeoSatelliteInfoSourceBbPrivate::~QGeoSatelliteInfoSourceBbPrivate() -{ - stopUpdates(); -} - -// request periodic updates -void QGeoSatelliteInfoSourceBbPrivate::startUpdates() -{ - // do nothing if periodic updates have already been started - if (_startUpdatesInvoked) - return; - - // build a request and initiate it - if (requestSatelliteInfo(true)) { - _startUpdatesInvoked = true; - } else { - Q_Q(QGeoSatelliteInfoSourceBb); - Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError); - } -} - -// stop periodic updates -void QGeoSatelliteInfoSourceBbPrivate::stopUpdates() -{ - // do nothing if periodic updates have not been started - if (!_startUpdatesInvoked) - return; - - cancelSatelliteInfo(true); - _startUpdatesInvoked = false; - - // close the pps file to ensure readyRead() does not spin in the event that we don't read the - // reply to the cancel request. Note that open() is done lazily in sendRequest(). - _periodicUpdatePpsObject->close(); -} - -// request single update -void QGeoSatelliteInfoSourceBbPrivate::requestUpdate(int msec) -{ - // do nothing if an immediate update has already been requested - if (_requestUpdateInvoked) - return; - - if (msec) { - // If it is not possible to update in msec timeout immediately. - if (msec < global::minUpdateInterval) { - // The connection is queued because it is possible for the user to call requestUpdate() - // from within the slot handling the timeout. The queued connection avoids potential - // infinite recursion. - Q_EMIT queuedRequestTimeout(); - return; - } - } - - if (requestSatelliteInfo(false, msec)) { - _requestUpdateInvoked = true; - } else { - // With Qt5 the error() signal was introduced. If there are any receivers emit error() else - // maintain QtMobility behavior. - Q_Q(QGeoSatelliteInfoSourceBb); - if (q->receivers(SIGNAL(error(QGeoPositionInfoSource::Error)))) { - Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError); - } else { - // The connection is queued because it is possible for the user to call requestUpdate() - // from within the slot handling the timeout. The queued connection avoids potential - // infinite recursion. - Q_EMIT queuedRequestTimeout(); - } - } -} - -// single update has timed out. This is a slot for the requestUpdate timer -void QGeoSatelliteInfoSourceBbPrivate::singleUpdateTimeout() -{ - _requestUpdateInvoked = false; - - emitRequestTimeout(); - - if (!_requestUpdateInvoked) { - // close the pps file to ensure readyRead() does not spin in the event that there are - // unexpected replies that we don't read. Note that open() is done lazily in sendRequest(). - _singleUpdatePpsObject->close(); - } -} - -// This slot is intended for queued connection to the signal queuedUpdateTimeout(). If an error -// occurs when an update is requested the error is relayed via updateTimeout() but the connection -// is queued to avoid potential infinite recursion. -void QGeoSatelliteInfoSourceBbPrivate::emitRequestTimeout() -{ - Q_Q(QGeoSatelliteInfoSourceBb); - Q_EMIT q->requestTimeout(); -} - -bool QGeoSatelliteInfoSourceBbPrivate::receiveSatelliteReply(bool periodic) -{ - bb::PpsObject *ppsObject; - if (periodic) - ppsObject = _periodicUpdatePpsObject; - else - ppsObject = _singleUpdatePpsObject; - - QVariantMap reply; - // receiveReply() tests for errors associated with the request being replied to - if (!receiveReply(&reply, *ppsObject)) { - QGeoSatelliteInfoSource::Error fatalError = QGeoSatelliteInfoSource::UnknownSourceError; - - // if there is an error from Location Manager translate it to a - // QGeoSatelliteInfoSource::Error - if (reply.contains("errCode")) { - fatalError = intToErrorCodeMap.value(reply.value("errCode").toInt(), - QGeoSatelliteInfoSource::UnknownSourceError); - } - - if (fatalError != QGeoSatelliteInfoSource::NoError) - _sourceError = fatalError; - - if (!periodic || fatalError != QGeoSatelliteInfoSource::NoError) - return false; - } - - // check that this is a location reply (could be a reply to another request type, eg. cancel, - // which is ignored here) - if (reply.contains("res") && reply.value("res").toString() == "location") { - // extract the satellite info from the reply into _satellitesInView and _satellitesInUse - populateSatelliteLists(reply); - - Q_Q(QGeoSatelliteInfoSourceBb); - Q_EMIT q->satellitesInUseUpdated(_satellitesInUse); - Q_EMIT q->satellitesInViewUpdated(_satellitesInView); - } - - return true; -} - -void QGeoSatelliteInfoSourceBbPrivate::receivePeriodicSatelliteReply() -{ - // don't try to receive a reply if periodic updates have not been started. This is - // necessary because this slot is connected to PpsObject::readyRead() and could be - // invoked any time the pps file is updated by the server. Under error conditions - // this would otherwise lead to a circular calling sequence: receive, timeout due to - // error, cancel, receive... - if (!_startUpdatesInvoked) - return; - - if (!receiveSatelliteReply(true)) { - Q_Q(QGeoSatelliteInfoSourceBb); - Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError); - } -} - -void QGeoSatelliteInfoSourceBbPrivate::receiveSingleSatelliteReply() -{ - // don't try to receive a reply if a single update has not been requested. This is - // necessary because this slot is connected to PpsObject::readyRead() and could be - // invoked any time the pps file is updated by the server. Under error conditions - // this would otherwise lead to a circular calling sequence: receive, timeout due to - // error, cancel, receive... - if (!_requestUpdateInvoked) - return; - - // clear this before calling receivePositionReply() which can emit the positionUpdated() - // signal. It is possible to call requestUpdate() in the slot connected to - // positionUpdated() so for requestUpdate() to work _requestUpdateInvoked must be false - _requestUpdateInvoked = false; - - if (!receiveSatelliteReply(false)) { - Q_Q(QGeoSatelliteInfoSourceBb); - if (_sourceError != QGeoSatelliteInfoSource::NoError) - Q_EMIT ((QGeoSatelliteInfoSource *)q)->error(_sourceError); - else - singleUpdateTimeout(); - } - - if (!_requestUpdateInvoked) { - // close the pps file to ensure readyRead() does not spin in the event that there are - // unexpected replies that we don't read. Note that open() is done lazily in sendRequest(). - _singleUpdatePpsObject->close(); - } -} - -/////////////////////////// -// -// QGeoSatelliteInfoSourceBb -// -/////////////////////////// - -/*! - \class QGeoSatelliteInfoSourceBb - \brief The QGeoSatelliteInfoSourceBb class is for the distribution of positional updates - obtained from the underlying Qnx Location Manager. - - QGeoSatelliteInfoSourceBb is a subclass of QGeoSatelliteInfoSource. - The static function QGeoSatelliteInfoSource::createDefaultSource() creates a default - satellite data source that is appropriate for the platform, if one is - available. On BB10 this is a QGeoSatelliteInfoSourceBb instance. Otherwise, available - QGeoPositionInfoSourceFactory plugins will - be checked for one that has a satellite data source available. - - Call startUpdates() and stopUpdates() to start and stop regular updates, - or requestUpdate() to request a single update. - When an update is available, satellitesInViewUpdated() and/or - satellitesInUseUpdated() will be emitted. -*/ - - - -/*! - Constructs a QGeoSatelliteInfoSourceBb instance with the given \a parent - and \a updateMode. -*/ -QGeoSatelliteInfoSourceBb::QGeoSatelliteInfoSourceBb(QObject *parent) - : QGeoSatelliteInfoSource(parent), - d_ptr(new QGeoSatelliteInfoSourceBbPrivate(this)) -{ -} - -/*! - Destroys the satellite source. -*/ -QGeoSatelliteInfoSourceBb::~QGeoSatelliteInfoSourceBb() -{ -} - -/*! - \reimp -*/ -int QGeoSatelliteInfoSourceBb::minimumUpdateInterval() const -{ - return global::minUpdateInterval; -} - -/*! - \reimp -*/ -void QGeoSatelliteInfoSourceBb::setUpdateInterval(int msec) -{ - int interval = msec; - if (interval != 0) - interval = qMax(msec, minimumUpdateInterval()); - - if (interval == updateInterval()) - return; - - QGeoSatelliteInfoSource::setUpdateInterval(interval); - - Q_D(QGeoSatelliteInfoSourceBb); - if (d->_startUpdatesInvoked) { - d->stopUpdates(); - d->startUpdates(); - } -} - -/*! - \reimp -*/ -void QGeoSatelliteInfoSourceBb::startUpdates() -{ - Q_D(QGeoSatelliteInfoSourceBb); - d->startUpdates(); -} - -/*! - \reimp -*/ -void QGeoSatelliteInfoSourceBb::stopUpdates() -{ - Q_D(QGeoSatelliteInfoSourceBb); - d->stopUpdates(); -} - -/*! - \reimp -*/ -void QGeoSatelliteInfoSourceBb::requestUpdate(int msec) -{ - Q_D(QGeoSatelliteInfoSourceBb); - d->requestUpdate(msec); -} - -/*! - \reimp -*/ -QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceBb::error() const -{ - Q_D(const QGeoSatelliteInfoSourceBb); - return d->_sourceError; -} - -// property managers. These properties extend QGeoSatelliteInfoSource by allowing additional -// control provided by the Location Manager - -/*! - \property QGeoSatelliteInfoSourceBb::period - \brief The period of the location request, in seconds. A value of '0' indicates that this - would be a one-time location request. -*/ -double QGeoSatelliteInfoSourceBb::period() const -{ - // convert from msec to sec - return updateInterval() / 1000.0; -} - -void QGeoSatelliteInfoSourceBb::setPeriod(double period) -{ - // convert from sec to msec, round to nearest msec - setUpdateInterval(qRound(static_cast<qreal>(period * 1000.0))); -} - - -/*! - \property QGeoSatelliteInfoSourceBb::backgroundMode - \brief This property determines whether or not requests are allowed to run with the device - in standby (i.e. screen off) -*/ -bool QGeoSatelliteInfoSourceBb::backgroundMode() const -{ - Q_D(const QGeoSatelliteInfoSourceBb); - return d->_backgroundMode; -} - -void QGeoSatelliteInfoSourceBb::setBackgroundMode(bool mode) -{ - Q_D(QGeoSatelliteInfoSourceBb); - d->_backgroundMode = mode; -} - -/*! - \property QGeoSatelliteInfoSourceBb::responseTime - \brief This property specifies the desired response time of the fix, in seconds. A value - of '0' disables response time criteria. -*/ -int QGeoSatelliteInfoSourceBb::responseTime() const -{ - Q_D(const QGeoSatelliteInfoSourceBb); - return d->_responseTime; -} - -void QGeoSatelliteInfoSourceBb::setResponseTime(int responseTime) -{ - Q_D(QGeoSatelliteInfoSourceBb); - d->_responseTime = responseTime; -} diff --git a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb_p.h b/src/plugins/position/blackberry/qgeosatelliteinfosource_bb_p.h deleted file mode 100644 index 9feabafa..00000000 --- a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb_p.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGEOSATELLITEINFOSOURCE_BB_P_H -#define QGEOSATELLITEINFOSOURCE_BB_P_H - -#include "qgeosatelliteinfosource_bb.h" -#include "qgeosatelliteinfo.h" - -#include <QObject> -#include <QtCore/QVariantMap> - -namespace bb -{ -class PpsObject; -} - -class QGeoSatelliteInfoSourceBbPrivate : public QObject -{ - Q_OBJECT -public: - ~QGeoSatelliteInfoSourceBbPrivate(); - - void startUpdates(); - void stopUpdates(); - void requestUpdate(int msec); - - bool _startUpdatesInvoked; - bool _requestUpdateInvoked; - -private Q_SLOTS: - void singleUpdateTimeout(); - void receivePeriodicSatelliteReply(); - void receiveSingleSatelliteReply(); - - void emitRequestTimeout(); - -Q_SIGNALS: - void queuedRequestTimeout(); - -private: - Q_DECLARE_PUBLIC(QGeoSatelliteInfoSourceBb) - explicit QGeoSatelliteInfoSourceBbPrivate(QGeoSatelliteInfoSourceBb *parent); - - void emitSatelliteUpdated(const QGeoSatelliteInfo &update); - bool requestSatelliteInfo(bool periodic, int singleRequestMsec = 0); - void cancelSatelliteInfo(bool periodic); - - QVariantMap populateLocationRequest(bool periodic, int singleRequestMsec = 0); - void populateSatelliteLists(const QVariantMap &reply); - - bool receiveSatelliteReply(bool periodic); - - QGeoSatelliteInfoSourceBb *q_ptr; - bb::PpsObject *_periodicUpdatePpsObject; - bb::PpsObject *_singleUpdatePpsObject; - QList<QGeoSatelliteInfo> _satellitesInUse; - QList<QGeoSatelliteInfo> _satellitesInView; - QGeoSatelliteInfoSource::Error _sourceError; - - // properties (extension of QGeoSatelliteInfoSource for additional Location Manager features) - bool _backgroundMode; - int _responseTime; - -}; - -#endif diff --git a/src/plugins/position/corelocation/plugin.json b/src/plugins/position/corelocation/plugin.json index 96e5cbf1..58e3acd0 100644 --- a/src/plugins/position/corelocation/plugin.json +++ b/src/plugins/position/corelocation/plugin.json @@ -4,5 +4,6 @@ "Position": true, "Satellite": false, "Monitor" : false, - "Priority": 1000 + "Priority": 1000, + "Testable": false } diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm index c92e468f..0e5e261b 100644 --- a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm +++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm @@ -88,6 +88,10 @@ m_positionInfoSource->setError(QGeoPositionInfoSource::AccessError); qWarning() << QString::fromNSString([error localizedDescription]); + + if ([error code] == 0 + && QString::fromNSString([error domain]) == QStringLiteral("kCLErrorDomain")) + qWarning() << "(is Wi-Fi turned on?)"; } @end diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h b/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h index d5c0313c..53b3d412 100644 --- a/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h +++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl_p.h @@ -34,6 +34,17 @@ #ifndef QGEOPOSITIONINFOSOURCECL_H #define QGEOPOSITIONINFOSOURCECL_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #import <CoreLocation/CoreLocation.h> #include "qgeopositioninfosource.h" diff --git a/src/plugins/position/geoclue/geoclue.pro b/src/plugins/position/geoclue/geoclue.pro index a3c34ece..0d9aab7d 100644 --- a/src/plugins/position/geoclue/geoclue.pro +++ b/src/plugins/position/geoclue/geoclue.pro @@ -1,32 +1,37 @@ TARGET = qtposition_geoclue -QT = core positioning +QT = core positioning dbus PLUGIN_TYPE = position PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryGeoclue load(qt_plugin) HEADERS += \ - qgeopositioninfosource_geocluemaster_p.h \ + qgeopositioninfosource_geocluemaster.h \ + qgeosatelliteinfosource_geocluemaster.h \ qgeopositioninfosourcefactory_geoclue.h \ - qgeocluemaster.h + qgeocluemaster.h \ + geocluetypes.h SOURCES += \ qgeopositioninfosource_geocluemaster.cpp \ + qgeosatelliteinfosource_geocluemaster.cpp \ qgeopositioninfosourcefactory_geoclue.cpp \ - qgeocluemaster.cpp + qgeocluemaster.cpp \ + geocluetypes.cpp + +QDBUSXML2CPP_INTERFACE_HEADER_FLAGS += "-N -i geocluetypes.h" +DBUS_INTERFACES += \ + org.freedesktop.Geoclue.MasterClient.xml \ + org.freedesktop.Geoclue.Master.xml \ + org.freedesktop.Geoclue.Position.xml \ + org.freedesktop.Geoclue.Velocity.xml \ + org.freedesktop.Geoclue.Satellite.xml \ + org.freedesktop.Geoclue.xml -qtHaveModule(dbus):config_geoclue-satellite { - DEFINES += HAS_SATELLITE - - QT *= dbus - - HEADERS += qgeosatelliteinfosource_geocluemaster.h - SOURCES += qgeosatelliteinfosource_geocluemaster.cpp -} +OTHER_FILES += \ + $$DBUS_INTERFACES -CONFIG += link_pkgconfig -PKGCONFIG += geoclue +INCLUDEPATH += $$QT.location.includes $$OUT_PWD OTHER_FILES += \ - plugin.json \ - plugin-satellite.json + plugin.json diff --git a/src/plugins/position/geoclue/geocluetypes.cpp b/src/plugins/position/geoclue/geocluetypes.cpp new file mode 100644 index 00000000..ece3d113 --- /dev/null +++ b/src/plugins/position/geoclue/geocluetypes.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Aaron McCarthy <mccarthy.aaron@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "geocluetypes.h" + +const QDBusArgument &dbus_argument_helper(const QDBusArgument &arg, Accuracy &accuracy) +{ + arg.beginStructure(); + qint32 level; + arg >> level; + accuracy.m_level = static_cast<Accuracy::Level>(level); + arg >> accuracy.m_horizontal; + arg >> accuracy.m_vertical; + arg.endStructure(); + + return arg; +} + +QT_BEGIN_NAMESPACE + +QDBusArgument &operator<<(QDBusArgument &arg, const Accuracy &accuracy) +{ + arg.beginStructure(); + arg << qint32(accuracy.level()); + arg << accuracy.horizontal(); + arg << accuracy.vertical(); + arg.endStructure(); + + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, Accuracy &accuracy) +{ + return dbus_argument_helper(arg, accuracy); +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, QGeoSatelliteInfo &si) +{ + qint32 a; + + argument.beginStructure(); + argument >> a; + si.setSatelliteIdentifier(a); + argument >> a; + si.setAttribute(QGeoSatelliteInfo::Elevation, a); + argument >> a; + si.setAttribute(QGeoSatelliteInfo::Azimuth, a); + argument >> a; + si.setSignalStrength(a); + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, QList<QGeoSatelliteInfo> &sis) +{ + sis.clear(); + + argument.beginArray(); + while (!argument.atEnd()) { + QGeoSatelliteInfo si; + argument >> si; + sis.append(si); + } + argument.endArray(); + + return argument; +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.h b/src/plugins/position/geoclue/geocluetypes.h index 89fcf716..ff748b13 100644 --- a/src/plugins/position/blackberry/qgeosatelliteinfosource_bb.h +++ b/src/plugins/position/geoclue/geocluetypes.h @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2015 Aaron McCarthy <mccarthy.aaron@gmail.com> +** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtPositioning module of the Qt Toolkit. ** @@ -31,49 +31,57 @@ ** ****************************************************************************/ -#ifndef QGEOSATELLITEINFOSOURCE_BB_H -#define QGEOSATELLITEINFOSOURCE_BB_H +#ifndef GEOCLUETYPES_H +#define GEOCLUETYPES_H -#include <QGeoSatelliteInfoSource> +#include <QtDBus/QDBusArgument> +#include <QtPositioning/QGeoSatelliteInfo> -#include <QString> -#include <QScopedPointer> - -class QGeoSatelliteInfoSourceBbPrivate; -class QGeoSatelliteInfoSourceBb : public QGeoSatelliteInfoSource +class Accuracy { - Q_OBJECT +public: + enum Level { + None = 0, + Country, + Region, + Locality, + PostalCode, + Street, + Detailed + }; - Q_PROPERTY(double period READ period WRITE setPeriod FINAL) - Q_PROPERTY(bool backgroundMode READ backgroundMode WRITE setBackgroundMode FINAL) - Q_PROPERTY(int responseTime READ responseTime WRITE setResponseTime FINAL) + Accuracy() + : m_level(None), m_horizontal(0), m_vertical(0) + { + } -public: - explicit QGeoSatelliteInfoSourceBb(QObject *parent = 0); - virtual ~QGeoSatelliteInfoSourceBb(); + inline Level level() const { return m_level; } + inline double horizontal() const { return m_horizontal; } + inline double vertical() const { return m_vertical; } - void setUpdateInterval(int msec); - int minimumUpdateInterval() const; - Error error() const; +private: + Level m_level; + double m_horizontal; + double m_vertical; - double period() const; - void setPeriod(double period); + friend const QDBusArgument &dbus_argument_helper(const QDBusArgument &arg, Accuracy &accuracy); +}; - bool backgroundMode() const; - void setBackgroundMode(bool mode); +Q_DECLARE_METATYPE(Accuracy) +Q_DECLARE_METATYPE(QList<QGeoSatelliteInfo>) - int responseTime() const; - void setResponseTime(int responseTime); -public Q_SLOTS: - void startUpdates(); - void stopUpdates(); - void requestUpdate(int timeout = 0); +QT_BEGIN_NAMESPACE -private: - Q_DECLARE_PRIVATE(QGeoSatelliteInfoSourceBb) - Q_DISABLE_COPY(QGeoSatelliteInfoSourceBb) - QScopedPointer<QGeoSatelliteInfoSourceBbPrivate> d_ptr; -}; +Q_DECLARE_TYPEINFO(Accuracy, Q_MOVABLE_TYPE); + +QDBusArgument &operator<<(QDBusArgument &arg, const Accuracy &accuracy); +const QDBusArgument &operator>>(const QDBusArgument &arg, Accuracy &accuracy); + +const QDBusArgument &operator>>(const QDBusArgument &arg, QGeoSatelliteInfo &si); +const QDBusArgument &operator>>(const QDBusArgument &arg, QList<QGeoSatelliteInfo> &sis); + +QT_END_NAMESPACE + +#endif // GEOCLUETYPES_H -#endif diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Master.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Master.xml new file mode 100644 index 00000000..e7df140c --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Master.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.Geoclue.Master"> + <method name="Create"> + <arg name="path" type="o" direction="out"/> + </method> + </interface> +</node> + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.MasterClient.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.MasterClient.xml new file mode 100644 index 00000000..29c95885 --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.MasterClient.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.Geoclue.MasterClient"> + <method name="GetPositionProvider"> + <arg name="name" type="s" direction="out"/> + <arg name="description" type="s" direction="out"/> + <arg name="service" type="s" direction="out"/> + <arg name="path" type="s" direction="out"/> + </method> + <method name="GetAddressProvider"> + <arg name="name" type="s" direction="out"/> + <arg name="description" type="s" direction="out"/> + <arg name="service" type="s" direction="out"/> + <arg name="path" type="s" direction="out"/> + </method> + <method name="PositionStart"> + </method> + <method name="AddressStart"> + </method> + <method name="SetRequirements"> + <arg name="accuracyLevel" type="i" direction="in"/> + <arg name="time" type="i" direction="in"/> + <arg name="requireUpdates" type="b" direction="in"/> + <arg name="allowedResources" type="i" direction="in"/> + </method> + <signal name="PositionProviderChanged"> + <arg name="name" type="s"/> + <arg name="description" type="s"/> + <arg name="service" type="s"/> + <arg name="path" type="s"/> + </signal> + <signal name="AddressProviderChanged"> + <arg name="name" type="s"/> + <arg name="description" type="s"/> + <arg name="service" type="s"/> + <arg name="path" type="s"/> + </signal> + </interface> +</node> + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml new file mode 100644 index 00000000..ce5c80de --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.Geoclue.Position"> + <method name="GetPosition"> + <arg name="fields" type="i" direction="out"/> + <arg name="timestamp" type="i" direction="out"/> + <arg name="latitude" type="d" direction="out"/> + <arg name="longitude" type="d" direction="out"/> + <arg name="altitude" type="d" direction="out"/> + <arg name="accuracy" type="(idd)" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out5" value="Accuracy"/> + </method> + <signal name="PositionChanged"> + <arg name="fields" type="i"/> + <arg name="timestamp" type="i"/> + <arg name="latitude" type="d"/> + <arg name="longitude" type="d"/> + <arg name="altitude" type="d"/> + <arg name="accuracy" type="(idd)"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In5" value="Accuracy"/> + </signal> + </interface> +</node> + diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml new file mode 100644 index 00000000..2ed112c9 --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="org.freedesktop.Geoclue.Satellite"> + <method name="GetSatellite"> + <arg name="timestamp" type="i" direction="out" /> + <arg name="satelliteUsed" type="i" direction="out" /> + <arg name="satelliteVisible" type="i" direction="out" /> + <arg name="usedPrn" type="ai" direction="out" /> + <arg name="satInfo" type="a(iiii)" direction="out" /> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out3" value="QList<qint32>"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out4" value="QList<QGeoSatelliteInfo>"/> + </method> + <method name="GetLastSatellite"> + <arg name="timestamp" type="i" direction="out" /> + <arg name="satelliteUsed" type="i" direction="out" /> + <arg name="satelliteVisible" type="i" direction="out" /> + <arg name="usedPrn" type="ai" direction="out" /> + <arg name="satInfo" type="a(iiii)" direction="out" /> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out3" value="QList<qint32>"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out4" value="QList<QGeoSatelliteInfo>"/> + </method> + <signal name="SatelliteChanged"> + <arg name="timestamp" type="i" /> + <arg name="satelliteUsed" type="i" /> + <arg name="satelliteVisible" type="i" /> + <arg name="usedPrn" type="ai" /> + <arg name="satInfo" type="a(iiii)" />' + <annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="QList<qint32>"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In4" value="QList<QGeoSatelliteInfo>"/> + </signal> + </interface> +</node> diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Velocity.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Velocity.xml new file mode 100644 index 00000000..a1be122a --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Velocity.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node name="/"> + <interface name="org.freedesktop.Geoclue.Velocity"> + <method name="GetVelocity"> + <arg name="fields" type="i" direction="out" /> + <arg name="timestamp" type="i" direction="out" /> + <arg name="speed" type="d" direction="out" /> + <arg name="direction" type="d" direction="out" /> + <arg name="climb" type="d" direction="out" /> + </method> + <signal name="VelocityChanged"> + <arg name="fields" type="i" /> + <arg name="timestamp" type="i" /> + <arg name="speed" type="d" /> + <arg name="direction" type="d" /> + <arg name="climb" type="d" /> + </signal> + </interface> +</node> diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.xml new file mode 100644 index 00000000..c9b6f635 --- /dev/null +++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.Geoclue"> + <method name="RemoveReference"> + </method> + <method name="AddReference"> + </method> + <method name="SetOptions"> + <arg name="options" type="a{sv}" direction="in"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/> + </method> + <method name="GetStatus"> + <arg name="status" type="i" direction="out"/> + </method> + <method name="GetProviderInfo"> + <arg name="name" type="s" direction="out"/> + <arg name="description" type="s" direction="out"/> + </method> + <signal name="StatusChanged"> + <arg name="status" type="i"/> + </signal> + </interface> +</node> diff --git a/src/plugins/position/geoclue/plugin-satellite.json b/src/plugins/position/geoclue/plugin-satellite.json deleted file mode 100644 index 59e190f1..00000000 --- a/src/plugins/position/geoclue/plugin-satellite.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "Keys": ["geoclue"], - "Provider": "geoclue", - "Position": true, - "Satellite": true, - "Priority": 1000 -} diff --git a/src/plugins/position/geoclue/plugin.json b/src/plugins/position/geoclue/plugin.json index cac7345b..82f8afc6 100644 --- a/src/plugins/position/geoclue/plugin.json +++ b/src/plugins/position/geoclue/plugin.json @@ -2,7 +2,8 @@ "Keys": ["geoclue"], "Provider": "geoclue", "Position": true, - "Satellite": false, + "Satellite": true, "Monitor": false, - "Priority": 1000 + "Priority": 999, + "Testable": false } diff --git a/src/plugins/position/geoclue/qgeocluemaster.cpp b/src/plugins/position/geoclue/qgeocluemaster.cpp index 7c340ba7..b7f4c6a3 100644 --- a/src/plugins/position/geoclue/qgeocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeocluemaster.cpp @@ -33,94 +33,85 @@ #include "qgeocluemaster.h" -#include <QtCore/QByteArray> -#include <QtCore/QMetaMethod> +#include <master_interface.h> +#include <geoclue_interface.h> +#include <masterclient_interface.h> -QT_BEGIN_NAMESPACE - -namespace -{ - -void position_provider_changed(GeoclueMasterClient *client, char *name, char *description, - char *service, char *path, QObject *handler) -{ - Q_UNUSED(client) - Q_UNUSED(name) - Q_UNUSED(description) +#include <QtCore/QLoggingCategory> - const QByteArray pService = QByteArray(service); - const QByteArray pPath = QByteArray(path); +Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue) - QMetaObject::invokeMethod(handler, "positionProviderChanged", Qt::QueuedConnection, - Q_ARG(QByteArray, pService), Q_ARG(QByteArray, pPath)); -} - -} +QT_BEGIN_NAMESPACE -QGeoclueMaster::QGeoclueMaster(QObject *handler) -: m_client(0), m_masterPosition(0), m_handler(handler) +QGeoclueMaster::QGeoclueMaster(QObject *parent) +: QObject(parent), m_master(0), m_provider(0), m_client(0) { -#if !defined(GLIB_VERSION_2_36) - g_type_init(); -#endif } QGeoclueMaster::~QGeoclueMaster() { releaseMasterClient(); + + delete m_master; } bool QGeoclueMaster::hasMasterClient() const { - return m_client && m_masterPosition; + return m_client; } -bool QGeoclueMaster::createMasterClient(GeoclueAccuracyLevel accuracy, GeoclueResourceFlags resourceFlags) +bool QGeoclueMaster::createMasterClient(Accuracy::Level accuracyLevel, ResourceFlags resourceFlags) { - Q_ASSERT(!m_client && !m_masterPosition); + Q_ASSERT(!m_provider || !m_client); - GeoclueMaster *master = geoclue_master_get_default(); - if (!master) { - qCritical("QGeoclueMaster error creating GeoclueMaster"); + if (!m_master) { + qCDebug(lcPositioningGeoclue) << "creating master interface"; + m_master = new OrgFreedesktopGeoclueMasterInterface(QStringLiteral("org.freedesktop.Geoclue.Master"), + QStringLiteral("/org/freedesktop/Geoclue/Master"), + QDBusConnection::sessionBus()); + } + + qCDebug(lcPositioningGeoclue) << "creating client"; + QDBusPendingReply<QDBusObjectPath> client = m_master->Create(); + if (client.isError()) { + QDBusError e = client.error(); + qCritical("Failed to create Geoclue client interface. Geoclue error: %s", + qPrintable(e.errorString(e.type()))); return false; } - GError *error = 0; + qCDebug(lcPositioningGeoclue) << "Geoclue client path:" << client.value().path(); - m_client = geoclue_master_create_client(master, 0, &error); - g_object_unref (master); + m_provider = new OrgFreedesktopGeoclueInterface(QStringLiteral("org.freedesktop.Geoclue.Master"), + client.value().path(), QDBusConnection::sessionBus()); + m_provider->AddReference(); - if (!m_client) { - qCritical("QGeoclueMaster error creating GeoclueMasterClient."); - if (error) { - qCritical("Geoclue error: %s", error->message); - g_error_free(error); - } - return false; - } + m_client = new OrgFreedesktopGeoclueMasterClientInterface(QStringLiteral("org.freedesktop.Geoclue.Master"), + client.value().path(), + QDBusConnection::sessionBus()); + + connect(m_client, SIGNAL(PositionProviderChanged(QString,QString,QString,QString)), + this, SIGNAL(positionProviderChanged(QString,QString,QString,QString))); - g_signal_connect(G_OBJECT(m_client), "position-provider-changed", - G_CALLBACK(position_provider_changed), m_handler); - - if (!geoclue_master_client_set_requirements(m_client, accuracy, 0, true, - resourceFlags, &error)) { - qCritical("QGeoclueMaster geoclue set_requirements failed."); - if (error) { - qCritical ("Geoclue error: %s", error->message); - g_error_free (error); - } - g_object_unref(m_client); - m_client = 0; + QDBusPendingReply<> reply = m_client->SetRequirements(accuracyLevel, 0, true, resourceFlags); + if (reply.isError()) { + QDBusError e = reply.error(); + qCritical("Failed to set Geoclue positioning requirements. Geoclue error: %s", + qPrintable(e.errorString(e.type()))); + + releaseMasterClient(); return false; } // Need to create the master position interface even though it will not be used, otherwise // GetPositionProvider always returns empty strings. - m_masterPosition = geoclue_master_client_create_position(m_client, 0); - if (!m_masterPosition) { - qCritical("QGeoclueMaster failed to get master position object"); - g_object_unref(m_client); - m_client = 0; + reply = m_client->PositionStart(); + if (reply.isError()) { + QDBusError e = reply.error(); + qCritical("Failed to start positioning. Geoclue error: %s", + qPrintable(e.errorString(e.type()))); + + releaseMasterClient(); return false; } @@ -129,16 +120,12 @@ bool QGeoclueMaster::createMasterClient(GeoclueAccuracyLevel accuracy, GeoclueRe void QGeoclueMaster::releaseMasterClient() { - if (m_masterPosition) { - g_object_unref(m_masterPosition); - m_masterPosition = 0; - } - if (m_client) { - g_signal_handlers_disconnect_by_func(G_OBJECT(m_client), (void *)position_provider_changed, - m_handler); - g_object_unref(m_client); - m_client = 0; - } + if (m_provider) + m_provider->RemoveReference(); + delete m_provider; + m_provider = 0; + delete m_client; + m_client = 0; } QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeocluemaster.h b/src/plugins/position/geoclue/qgeocluemaster.h index 0451f812..83c1eb94 100644 --- a/src/plugins/position/geoclue/qgeocluemaster.h +++ b/src/plugins/position/geoclue/qgeocluemaster.h @@ -34,29 +34,51 @@ #ifndef QGEOCLUEMASTER_H #define QGEOCLUEMASTER_H +#include "geocluetypes.h" + #include <QtCore/QObject> -#include <geoclue/geoclue-master.h> +class OrgFreedesktopGeoclueMasterInterface; +class OrgFreedesktopGeoclueInterface; +class OrgFreedesktopGeoclueMasterClientInterface; QT_BEGIN_NAMESPACE -class QGeoclueMaster +class QGeoclueMaster : public QObject { + Q_OBJECT + public: - QGeoclueMaster(QObject *handler); - virtual ~QGeoclueMaster(); + QGeoclueMaster(QObject *parent = 0); + ~QGeoclueMaster(); + + enum ResourceFlag + { + ResourceNone = 0, + ResourceNetwork = 1 << 0, + ResourceCell = 1 << 1, + ResourceGps = 1 << 2, + ResourceAll = (1 << 10) - 1 + }; + + Q_DECLARE_FLAGS(ResourceFlags, ResourceFlag) bool hasMasterClient() const; - bool createMasterClient(GeoclueAccuracyLevel accuracy, GeoclueResourceFlags resourceFlags); + bool createMasterClient(Accuracy::Level accuracyLevel, ResourceFlags resourceFlags); void releaseMasterClient(); -private: - GeoclueMasterClient *m_client; - GeocluePosition *m_masterPosition; +signals: + void positionProviderChanged(const QString &name, const QString &description, + const QString &service, const QString &path); - QObject *m_handler; +private: + OrgFreedesktopGeoclueMasterInterface *m_master; + OrgFreedesktopGeoclueInterface *m_provider; + OrgFreedesktopGeoclueMasterClientInterface *m_client; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoclueMaster::ResourceFlags) + QT_END_NAMESPACE #endif // QGEOCLUEMASTER_H diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp index fe5b048e..5311e18f 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp @@ -33,7 +33,11 @@ ** ****************************************************************************/ -#include "qgeopositioninfosource_geocluemaster_p.h" +#include "qgeopositioninfosource_geocluemaster.h" + +#include <geoclue_interface.h> +#include <position_interface.h> +#include <velocity_interface.h> #include <QtCore/QDateTime> #include <QtCore/QFile> @@ -41,64 +45,22 @@ #include <QtCore/QStandardPaths> #include <QtCore/QVariantMap> #include <QtCore/QtNumeric> - -#ifdef Q_LOCATION_GEOCLUE_DEBUG -#include <QDebug> -#endif - -#include <dbus/dbus-glib.h> +#include <QtCore/QLoggingCategory> +#include <QtDBus/QDBusMetaType> #ifndef QT_NO_DATASTREAM #include <QtCore/QDataStream> #endif -QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue) #define MINIMUM_UPDATE_INTERVAL 1000 #define UPDATE_TIMEOUT_COLD_START 120000 -namespace -{ - -void position_changed(GeocluePosition *position, GeocluePositionFields fields, int timestamp, - double latitude, double longitude, double altitude, - GeoclueAccuracy *accuracy, QGeoPositionInfoSourceGeoclueMaster *master) -{ - Q_UNUSED(position) - - if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE && fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) - master->updatePosition(fields, timestamp, latitude, longitude, altitude, accuracy); - else - master->regularUpdateFailed(); -} - -void velocity_changed(GeoclueVelocity *velocity, GeoclueVelocityFields fields, int timestamp, - double speed, double direction, double climb, - QGeoPositionInfoSourceGeoclueMaster *master) -{ - Q_UNUSED(velocity) - - if (fields == GEOCLUE_VELOCITY_FIELDS_NONE) - master->velocityUpdateFailed(); - else - master->velocityUpdateSucceeded(fields, timestamp, speed, direction, climb); -} +QT_BEGIN_NAMESPACE -void position_callback(GeocluePosition *pos, GeocluePositionFields fields, int timestamp, - double latitude, double longitude, double altitude, - GeoclueAccuracy *accuracy, GError *error, gpointer userdata) +namespace { - Q_UNUSED(pos) - - if (error) - g_error_free(error); - - QGeoPositionInfoSourceGeoclueMaster *master = - static_cast<QGeoPositionInfoSourceGeoclueMaster *>(userdata); - - if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE && fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) - master->updatePosition(fields, timestamp, latitude, longitude, altitude, accuracy); -} double knotsToMetersPerSecond(double knots) { @@ -108,11 +70,13 @@ double knotsToMetersPerSecond(double knots) } QGeoPositionInfoSourceGeoclueMaster::QGeoPositionInfoSourceGeoclueMaster(QObject *parent) -: QGeoPositionInfoSource(parent), QGeoclueMaster(this), m_pos(0), m_vel(0), - m_lastVelocityIsFresh(false), m_regularUpdateTimedOut(false), m_lastVelocity(qQNaN()), +: QGeoPositionInfoSource(parent), m_master(new QGeoclueMaster(this)), m_provider(0), m_pos(0), + m_vel(0), m_lastVelocityIsFresh(false), m_regularUpdateTimedOut(false), m_lastVelocity(qQNaN()), m_lastDirection(qQNaN()), m_lastClimb(qQNaN()), m_lastPositionFromSatellite(false), - m_methods(AllPositioningMethods), m_running(false), m_error(NoError) + m_running(false), m_error(NoError) { + qDBusRegisterMetaType<Accuracy>(); + #ifndef QT_NO_DATASTREAM // Load the last known location QFile file(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + @@ -123,8 +87,11 @@ QGeoPositionInfoSourceGeoclueMaster::QGeoPositionInfoSourceGeoclueMaster(QObject } #endif + connect(m_master, SIGNAL(positionProviderChanged(QString,QString,QString,QString)), + this, SLOT(positionProviderChanged(QString,QString,QString,QString))); + m_requestTimer.setSingleShot(true); - QObject::connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); + connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); setPreferredPositioningMethods(AllPositioningMethods); } @@ -144,54 +111,12 @@ QGeoPositionInfoSourceGeoclueMaster::~QGeoPositionInfoSourceGeoclueMaster() } #endif - if (m_pos) - g_object_unref (m_pos); - if (m_vel) - g_object_unref(m_vel); -} - -void QGeoPositionInfoSourceGeoclueMaster::velocityUpdateFailed() -{ -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster velocity update failed."; -#endif - // Set the velocitydata non-fresh. - m_lastVelocityIsFresh = false; -} - -void QGeoPositionInfoSourceGeoclueMaster::velocityUpdateSucceeded(GeoclueVelocityFields fields, - int timestamp, double speed, - double direction, double climb) -{ - Q_UNUSED(timestamp); - -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster velocity update succeeded, speed: " << speed; -#endif - // Store the velocity and mark it as fresh. Simple but hopefully adequate. - if (fields & GEOCLUE_VELOCITY_FIELDS_SPEED) - m_lastVelocity = knotsToMetersPerSecond(speed); - else - m_lastVelocity = qQNaN(); - - if (fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION) - m_lastDirection = direction; - else - m_lastDirection = qQNaN(); - - if (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB) - m_lastClimb = climb; - else - m_lastClimb = qQNaN(); - - m_lastVelocityIsFresh = true; + cleanupPositionSource(); } -void QGeoPositionInfoSourceGeoclueMaster::regularUpdateFailed() +void QGeoPositionInfoSourceGeoclueMaster::positionUpdateFailed() { -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster regular update failed."; -#endif + qCDebug(lcPositioningGeoclue) << "position update failed."; m_lastVelocityIsFresh = false; if (m_running && !m_regularUpdateTimedOut) { @@ -200,33 +125,25 @@ void QGeoPositionInfoSourceGeoclueMaster::regularUpdateFailed() } } -void QGeoPositionInfoSourceGeoclueMaster::updatePosition(GeocluePositionFields fields, - int timestamp, double latitude, - double longitude, double altitude, - GeoclueAccuracy *accuracy) +void QGeoPositionInfoSourceGeoclueMaster::updatePosition(PositionFields fields, int timestamp, + double latitude, double longitude, + double altitude, Accuracy accuracy) { if (m_requestTimer.isActive()) m_requestTimer.stop(); QGeoCoordinate coordinate(latitude, longitude); - if (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE) + if (fields & Altitude) coordinate.setAltitude(altitude); m_lastPosition = QGeoPositionInfo(coordinate, QDateTime::fromTime_t(timestamp)); - if (accuracy) { - double horizontalAccuracy = qQNaN(); - double verticalAccuracy = qQNaN(); - GeoclueAccuracyLevel accuracyLevel = GEOCLUE_ACCURACY_LEVEL_NONE; - geoclue_accuracy_get_details(accuracy, &accuracyLevel, &horizontalAccuracy, &verticalAccuracy); - - m_lastPositionFromSatellite = accuracyLevel & GEOCLUE_ACCURACY_LEVEL_DETAILED; + m_lastPositionFromSatellite = accuracy.level() == Accuracy::Detailed; - if (!qIsNaN(horizontalAccuracy)) - m_lastPosition.setAttribute(QGeoPositionInfo::HorizontalAccuracy, horizontalAccuracy); - if (!qIsNaN(verticalAccuracy)) - m_lastPosition.setAttribute(QGeoPositionInfo::VerticalAccuracy, verticalAccuracy); - } + if (!qIsNaN(accuracy.horizontal())) + m_lastPosition.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy.horizontal()); + if (!qIsNaN(accuracy.vertical())) + m_lastPosition.setAttribute(QGeoPositionInfo::VerticalAccuracy, accuracy.vertical()); if (m_lastVelocityIsFresh) { if (!qIsNaN(m_lastVelocity)) @@ -242,80 +159,61 @@ void QGeoPositionInfoSourceGeoclueMaster::updatePosition(GeocluePositionFields f emit positionUpdated(m_lastPosition); -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "Lat, lon, alt, speed:" - << m_lastPosition.coordinate().latitude() - << m_lastPosition.coordinate().longitude() - << m_lastPosition.coordinate().altitude() - << m_lastPosition.attribute(QGeoPositionInfo::GroundSpeed); -#endif + qCDebug(lcPositioningGeoclue) << m_lastPosition; // Only stop positioning if regular updates not active. if (!m_running) { cleanupPositionSource(); - releaseMasterClient(); + m_master->releaseMasterClient(); } } +void QGeoPositionInfoSourceGeoclueMaster::velocityUpdateFailed() +{ + qCDebug(lcPositioningGeoclue) << "velocity update failed."; + + // Set the velocitydata non-fresh. + m_lastVelocityIsFresh = false; +} + +void QGeoPositionInfoSourceGeoclueMaster::updateVelocity(VelocityFields fields, int timestamp, + double speed, double direction, + double climb) +{ + Q_UNUSED(timestamp) + + // Store the velocity and mark it as fresh. Simple but hopefully adequate. + m_lastVelocity = (fields & Speed) ? knotsToMetersPerSecond(speed) : qQNaN(); + m_lastDirection = (fields & Direction) ? direction : qQNaN(); + m_lastClimb = (fields & Climb) ? climb : qQNaN(); + m_lastVelocityIsFresh = true; + + qCDebug(lcPositioningGeoclue) << m_lastVelocity << m_lastDirection << m_lastClimb; +} + void QGeoPositionInfoSourceGeoclueMaster::cleanupPositionSource() { - if (m_pos) { - g_object_unref(m_pos); - m_pos = 0; - } - if (m_vel) { - g_object_unref(m_vel); - m_vel = 0; - } + qCDebug(lcPositioningGeoclue) << "cleaning up position source"; + + if (m_provider) + m_provider->RemoveReference(); + delete m_provider; + m_provider = 0; + delete m_pos; + m_pos = 0; + delete m_vel; + m_vel = 0; } void QGeoPositionInfoSourceGeoclueMaster::setOptions() { - if (!m_pos) + if (!m_provider) return; QVariantMap options; options.insert(QStringLiteral("UpdateInterval"), updateInterval()); - GHashTable *gOptions = g_hash_table_new(g_str_hash, g_str_equal); - - for (QVariantMap::ConstIterator i = options.constBegin(); i != options.constEnd(); ++i) { - char *key = qstrdup(i.key().toUtf8().constData()); - - const QVariant v = i.value(); - - GValue *value = new GValue; - memset(value, 0, sizeof(*value)); - - switch (v.userType()) { - case QMetaType::QString: - g_value_init(value, G_TYPE_STRING); - g_value_set_string(value, v.toString().toUtf8().constData()); - break; - case QMetaType::Int: - g_value_init(value, G_TYPE_INT); - g_value_set_int(value, v.toInt()); - break; - default: - qWarning("Unexpected type %d %s", v.userType(), v.typeName()); - } - - g_hash_table_insert(gOptions, key, value); - } - - geoclue_provider_set_options(GEOCLUE_PROVIDER(m_pos), gOptions, 0); - - GHashTableIter iter; - char *key; - GValue *value; - - g_hash_table_iter_init(&iter, gOptions); - while (g_hash_table_iter_next(&iter, reinterpret_cast<void **>(&key), reinterpret_cast<void **>(&value))) { - delete[] key; - delete value; - } - - g_hash_table_destroy(gOptions); + m_provider->SetOptions(options); } void QGeoPositionInfoSourceGeoclueMaster::setUpdateInterval(int msec) @@ -331,23 +229,21 @@ void QGeoPositionInfoSourceGeoclueMaster::setPreferredPositioningMethods(Positio if (previousPreferredPositioningMethods == preferredPositioningMethods()) return; -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster requested to set methods to" << methods - << ", and set them to:" << preferredPositioningMethods(); -#endif + qCDebug(lcPositioningGeoclue) << "requested to set methods to" << methods + << ", and set them to:" << preferredPositioningMethods(); m_lastVelocityIsFresh = false; m_regularUpdateTimedOut = false; // Don't start Geoclue provider until necessary. Don't currently have a master client, no need // no recreate one. - if (!hasMasterClient()) + if (!m_master->hasMasterClient()) return; // Free potential previous sources, because new requirements can't be set for the client // (creating a position object after changing requirements seems to fail). cleanupPositionSource(); - releaseMasterClient(); + m_master->releaseMasterClient(); // Restart Geoclue provider with new requirements. configurePositionSource(); @@ -356,34 +252,30 @@ void QGeoPositionInfoSourceGeoclueMaster::setPreferredPositioningMethods(Positio QGeoPositionInfo QGeoPositionInfoSourceGeoclueMaster::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const { - if (fromSatellitePositioningMethodsOnly) { - if (m_lastPositionFromSatellite) - return m_lastPosition; - else - return QGeoPositionInfo(); - } + if (fromSatellitePositioningMethodsOnly && !m_lastPositionFromSatellite) + return QGeoPositionInfo(); + return m_lastPosition; } QGeoPositionInfoSourceGeoclueMaster::PositioningMethods QGeoPositionInfoSourceGeoclueMaster::supportedPositioningMethods() const { - // There is no really knowing which methods the GeoClue master supports. return AllPositioningMethods; } void QGeoPositionInfoSourceGeoclueMaster::startUpdates() { if (m_running) { -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster already running"; -#endif + qCDebug(lcPositioningGeoclue) << "already running."; return; } m_running = true; + qCDebug(lcPositioningGeoclue) << "starting updates"; + // Start Geoclue provider. - if (!hasMasterClient()) { + if (!m_master->hasMasterClient()) { configurePositionSource(); setOptions(); } @@ -402,20 +294,29 @@ int QGeoPositionInfoSourceGeoclueMaster::minimumUpdateInterval() const void QGeoPositionInfoSourceGeoclueMaster::stopUpdates() { - if (!m_running) + if (!m_running) { + qCDebug(lcPositioningGeoclue) << "already stopped."; return; + } - if (m_pos) - g_signal_handlers_disconnect_by_func(G_OBJECT(m_pos), (void *)position_changed, this); - if (m_vel) - g_signal_handlers_disconnect_by_func(G_OBJECT(m_vel), (void *)velocity_changed, this); + qCDebug(lcPositioningGeoclue) << "stopping updates"; + + if (m_pos) { + disconnect(m_pos, SIGNAL(PositionChanged(qint32,qint32,double,double,double,Accuracy)), + this, SLOT(positionChanged(qint32,qint32,double,double,double,Accuracy))); + } + + if (m_vel) { + disconnect(m_vel, SIGNAL(VelocityChanged(qint32,qint32,double,double,double)), + this, SLOT(velocityChanged(qint32,qint32,double,double,double))); + } m_running = false; // Only stop positioning if single update not requested. if (!m_requestTimer.isActive()) { cleanupPositionSource(); - releaseMasterClient(); + m_master->releaseMasterClient(); } } @@ -426,13 +327,11 @@ void QGeoPositionInfoSourceGeoclueMaster::requestUpdate(int timeout) return; } if (m_requestTimer.isActive()) { -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster request timer was active, ignoring startUpdates."; -#endif + qCDebug(lcPositioningGeoclue) << "request timer was active, ignoring startUpdates."; return; } - if (!hasMasterClient()) { + if (!m_master->hasMasterClient()) { configurePositionSource(); setOptions(); } @@ -442,85 +341,141 @@ void QGeoPositionInfoSourceGeoclueMaster::requestUpdate(int timeout) // for whole cold start time. m_requestTimer.start(timeout ? timeout : UPDATE_TIMEOUT_COLD_START); - if (m_pos) - geoclue_position_get_position_async(m_pos, position_callback, this); + if (m_pos) { + QDBusPendingReply<qint32, qint32, double, double, double, Accuracy> reply = m_pos->GetPosition(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(getPositionFinished(QDBusPendingCallWatcher*))); + } +} + +void QGeoPositionInfoSourceGeoclueMaster::positionProviderChanged(const QString &name, + const QString &description, + const QString &service, + const QString &path) +{ + Q_UNUSED(name) + Q_UNUSED(description) + + cleanupPositionSource(); + + if (service.isEmpty() || path.isEmpty()) { + if (!m_regularUpdateTimedOut) { + m_regularUpdateTimedOut = true; + emit updateTimeout(); + } + return; + } + + qCDebug(lcPositioningGeoclue) << "position provider changed to" << name; + + m_provider = new OrgFreedesktopGeoclueInterface(service, path, QDBusConnection::sessionBus()); + m_provider->AddReference(); + + m_pos = new OrgFreedesktopGeocluePositionInterface(service, path, QDBusConnection::sessionBus()); + + if (m_running) { + connect(m_pos, SIGNAL(PositionChanged(qint32,qint32,double,double,double,Accuracy)), + this, SLOT(positionChanged(qint32,qint32,double,double,double,Accuracy))); + } + + // Get the current position immediately. + QDBusPendingReply<qint32, qint32, double, double, double, Accuracy> reply = m_pos->GetPosition(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(getPositionFinished(QDBusPendingCallWatcher*))); + + setOptions(); + + m_vel = new OrgFreedesktopGeoclueVelocityInterface(service, path, QDBusConnection::sessionBus()); + if (m_vel->isValid() && m_running) { + connect(m_vel, SIGNAL(VelocityChanged(qint32,qint32,double,double,double)), + this, SLOT(velocityChanged(qint32,qint32,double,double,double))); + } } void QGeoPositionInfoSourceGeoclueMaster::requestUpdateTimeout() { -#ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster requestUpdate timeout occurred."; -#endif + qCDebug(lcPositioningGeoclue) << "request update timeout occurred."; + // If we end up here, there has not been valid position update. emit updateTimeout(); // Only stop positioning if regular updates not active. if (!m_running) { cleanupPositionSource(); - releaseMasterClient(); + m_master->releaseMasterClient(); } } -void QGeoPositionInfoSourceGeoclueMaster::positionProviderChanged(const QByteArray &service, const QByteArray &path) +void QGeoPositionInfoSourceGeoclueMaster::getPositionFinished(QDBusPendingCallWatcher *watcher) { - if (m_pos) - cleanupPositionSource(); + QDBusPendingReply<qint32, qint32, double, double, double, Accuracy> reply = *watcher; + watcher->deleteLater(); - if (service.isEmpty() || path.isEmpty()) { - if (!m_regularUpdateTimedOut) { - m_regularUpdateTimedOut = true; - emit updateTimeout(); - } + if (reply.isError()) return; - } - m_pos = geoclue_position_new(service.constData(), path.constData()); - if (m_pos) { - if (m_running) { - g_signal_connect(G_OBJECT(m_pos), "position-changed", - G_CALLBACK(position_changed), this); - } + PositionFields fields = static_cast<PositionFields>(reply.argumentAt<0>()); - // Get the current position immediately. - geoclue_position_get_position_async(m_pos, position_callback, this); - setOptions(); + qCDebug(lcPositioningGeoclue) << "got position update with fields" << int(fields); - m_vel = geoclue_velocity_new(service.constData(), path.constData()); - if (m_vel && m_running) { - g_signal_connect(G_OBJECT(m_vel), "velocity-changed", - G_CALLBACK(velocity_changed), this); - } + if (fields & Latitude && fields & Longitude) { + qint32 timestamp = reply.argumentAt<1>(); + double latitude = reply.argumentAt<2>(); + double longitude = reply.argumentAt<3>(); + double altitude = reply.argumentAt<4>(); + Accuracy accuracy = reply.argumentAt<5>(); + updatePosition(fields, timestamp, latitude, longitude, altitude, accuracy); } } +void QGeoPositionInfoSourceGeoclueMaster::positionChanged(qint32 fields, qint32 timestamp, double latitude, double longitude, double altitude, const Accuracy &accuracy) +{ + PositionFields pFields = static_cast<PositionFields>(fields); + + qCDebug(lcPositioningGeoclue) << "position changed with fields" << fields; + + if (pFields & Latitude && pFields & Longitude) + updatePosition(pFields, timestamp, latitude, longitude, altitude, accuracy); + else + positionUpdateFailed(); +} + +void QGeoPositionInfoSourceGeoclueMaster::velocityChanged(qint32 fields, qint32 timestamp, double speed, double direction, double climb) +{ + VelocityFields vFields = static_cast<VelocityFields>(fields); + + if (vFields == NoVelocityFields) + velocityUpdateFailed(); + else + updateVelocity(vFields, timestamp, speed, direction, climb); +} + void QGeoPositionInfoSourceGeoclueMaster::configurePositionSource() { - GeoclueAccuracyLevel accuracy; - GeoclueResourceFlags resourceFlags; + qCDebug(lcPositioningGeoclue); + + bool created = false; switch (preferredPositioningMethods()) { case SatellitePositioningMethods: - accuracy = GEOCLUE_ACCURACY_LEVEL_DETAILED; - resourceFlags = GEOCLUE_RESOURCE_GPS; + created = m_master->createMasterClient(Accuracy::Detailed, QGeoclueMaster::ResourceGps); break; case NonSatellitePositioningMethods: - accuracy = GEOCLUE_ACCURACY_LEVEL_NONE; - resourceFlags = GeoclueResourceFlags(GEOCLUE_RESOURCE_CELL | GEOCLUE_RESOURCE_NETWORK); + created = m_master->createMasterClient(Accuracy::None, QGeoclueMaster::ResourceCell | QGeoclueMaster::ResourceNetwork); break; case AllPositioningMethods: - accuracy = GEOCLUE_ACCURACY_LEVEL_NONE; - resourceFlags = GEOCLUE_RESOURCE_ALL; + created = m_master->createMasterClient(Accuracy::None, QGeoclueMaster::ResourceAll); break; default: - qWarning("GeoPositionInfoSourceGeoClueMaster unknown preferred method."); + qWarning("QGeoPositionInfoSourceGeoclueMaster unknown preferred method."); m_error = UnknownSourceError; emit QGeoPositionInfoSource::error(m_error); return; } - if (createMasterClient(accuracy, resourceFlags)) { - m_error = NoError; - } else { + if (!created) { m_error = UnknownSourceError; emit QGeoPositionInfoSource::error(m_error); } @@ -531,6 +486,4 @@ QGeoPositionInfoSource::Error QGeoPositionInfoSourceGeoclueMaster::error() const return m_error; } -#include "moc_qgeopositioninfosource_geocluemaster_p.cpp" - QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h index 2dcd3824..09f6812c 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h @@ -36,33 +36,26 @@ #ifndef QGEOPOSITIONINFOSOURCE_GEOCLUEMASTER_H #define QGEOPOSITIONINFOSOURCE_GEOCLUEMASTER_H -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - #include "qgeocluemaster.h" +#include "geocluetypes.h" -#include <qgeopositioninfosource.h> -#include <geoclue/geoclue-velocity.h> -#include <QTimer> +#include <QtCore/QTimer> +#include <QtPositioning/QGeoPositionInfoSource> -//#define Q_LOCATION_GEOCLUE_DEBUG +class OrgFreedesktopGeoclueInterface; +class OrgFreedesktopGeocluePositionInterface; +class OrgFreedesktopGeoclueVelocityInterface; QT_BEGIN_NAMESPACE -class QGeoPositionInfoSourceGeoclueMaster : public QGeoPositionInfoSource, public QGeoclueMaster +class QDBusPendingCallWatcher; + +class QGeoPositionInfoSourceGeoclueMaster : public QGeoPositionInfoSource { Q_OBJECT public: - QGeoPositionInfoSourceGeoclueMaster(QObject *parent = 0); + explicit QGeoPositionInfoSourceGeoclueMaster(QObject *parent = 0); ~QGeoPositionInfoSourceGeoclueMaster(); // From QGeoPositionInfoSource @@ -72,34 +65,61 @@ public: void setPreferredPositioningMethods(PositioningMethods methods); int minimumUpdateInterval() const; - void updatePosition(GeocluePositionFields fields, int timestamp, double latitude, - double longitude, double altitude, GeoclueAccuracy *accuracy); - - void regularUpdateFailed(); - - void velocityUpdateFailed(); - void velocityUpdateSucceeded(GeoclueVelocityFields fields, int timestamp, double speed, - double direction, double climb); - Error error() const; -public slots: - virtual void startUpdates(); - virtual void stopUpdates(); - virtual void requestUpdate(int timeout = 5000); + virtual void startUpdates() Q_DECL_OVERRIDE; + virtual void stopUpdates() Q_DECL_OVERRIDE; + virtual void requestUpdate(int timeout = 5000) Q_DECL_OVERRIDE; private slots: + void positionProviderChanged(const QString &name, const QString &description, + const QString &service, const QString &path); void requestUpdateTimeout(); - void positionProviderChanged(const QByteArray &service, const QByteArray &path); + + void getPositionFinished(QDBusPendingCallWatcher *watcher); + void positionChanged(qint32 fields, qint32 timestamp, double latitude, double longitude, + double altitude, const Accuracy &accuracy); + void velocityChanged(qint32 fields, qint32 timestamp, double speed, double direction, + double climb); private: void configurePositionSource(); void cleanupPositionSource(); void setOptions(); + enum PositionField + { + NoPositionFields = 0, + Latitude = 1 << 0, + Longitude = 1 << 1, + Altitude = 1 << 2 + }; + Q_DECLARE_FLAGS(PositionFields, PositionField) + + void updatePosition(PositionFields fields, int timestamp, double latitude, + double longitude, double altitude, Accuracy accuracy); + void positionUpdateFailed(); + + enum VelocityField + { + NoVelocityFields = 0, + Speed = 1 << 0, + Direction = 1 << 1, + Climb = 1 << 2 + }; + Q_DECLARE_FLAGS(VelocityFields, VelocityField) + + void updateVelocity(VelocityFields fields, int timestamp, double speed, double direction, + double climb); + void velocityUpdateFailed(); + private: - GeocluePosition *m_pos; - GeoclueVelocity *m_vel; + QGeoclueMaster *m_master; + + OrgFreedesktopGeoclueInterface *m_provider; + OrgFreedesktopGeocluePositionInterface *m_pos; + OrgFreedesktopGeoclueVelocityInterface *m_vel; + QTimer m_requestTimer; bool m_lastVelocityIsFresh; bool m_regularUpdateTimedOut; @@ -108,7 +128,6 @@ private: double m_lastClimb; bool m_lastPositionFromSatellite; QGeoPositionInfo m_lastPosition; - PositioningMethods m_methods; bool m_running; QGeoPositionInfoSource::Error m_error; }; diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp index a7c92678..05d96547 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp +++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp @@ -34,13 +34,17 @@ ****************************************************************************/ #include "qgeopositioninfosourcefactory_geoclue.h" -#include "qgeopositioninfosource_geocluemaster_p.h" -#ifdef HAS_SATELLITE +#include "qgeopositioninfosource_geocluemaster.h" #include "qgeosatelliteinfosource_geocluemaster.h" -#endif + +#include <QtCore/QLoggingCategory> Q_DECLARE_METATYPE(QGeoPositionInfo) +Q_LOGGING_CATEGORY(lcPositioningGeoclue, "qt.positioning.geoclue") + +QT_BEGIN_NAMESPACE + QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue::positionInfoSource(QObject *parent) { qRegisterMetaType<QGeoPositionInfo>(); @@ -49,17 +53,13 @@ QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue::positionInfoSource QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGeoclue::satelliteInfoSource(QObject *parent) { -#ifdef HAS_SATELLITE return new QGeoSatelliteInfoSourceGeoclueMaster(parent); -#else - Q_UNUSED(parent) - - return 0; -#endif } QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryGeoclue::areaMonitor(QObject *parent) { - Q_UNUSED(parent); + Q_UNUSED(parent) return 0; } + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h index fdd0675f..17da509e 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h +++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h @@ -36,28 +36,29 @@ #ifndef QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE_H #define QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE_H -#include <QObject> -#include <qgeopositioninfosourcefactory.h> +#include <QtCore/QObject> +#include <QtPositioning/QGeoPositionInfoSourceFactory> -#ifdef HAS_SATELLITE -#define PLUGIN_JSON "plugin-satellite.json" -#else -#define PLUGIN_JSON "plugin.json" -#endif +QT_BEGIN_NAMESPACE +/* + Qt Positioning plugin for Geoclue. This plugin supports Geoclue version 0.12.99. +*/ class QGeoPositionInfoSourceFactoryGeoclue : public QObject, public QGeoPositionInfoSourceFactory { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" - FILE PLUGIN_JSON) + FILE "plugin.json") Q_INTERFACES(QGeoPositionInfoSourceFactory) public: - QGeoPositionInfoSource *positionInfoSource(QObject *parent); - QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent); - QGeoAreaMonitorSource *areaMonitor(QObject *parent); + QGeoPositionInfoSource *positionInfoSource(QObject *parent) Q_DECL_OVERRIDE; + QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent) Q_DECL_OVERRIDE; + QGeoAreaMonitorSource *areaMonitor(QObject *parent) Q_DECL_OVERRIDE; }; +QT_END_NAMESPACE + #endif diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp index 501a983c..8e646bff 100644 --- a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp @@ -33,122 +33,25 @@ #include "qgeosatelliteinfosource_geocluemaster.h" -#include <QtDBus/QDBusConnection> -#include <QtDBus/QDBusMessage> -#include <QtDBus/QDBusArgument> +#include <geoclue_interface.h> +#include <satellite_interface.h> -#define MINIMUM_UPDATE_INTERVAL 1000 - -QT_BEGIN_NAMESPACE - -namespace -{ - -void satellite_changed(GeoclueSatellite *satellite, int timestamp, int satellite_used, - int satellite_visible, GArray *used_prn, GPtrArray *sat_info, - gpointer userdata) -{ - Q_UNUSED(satellite) - - QGeoSatelliteInfoSourceGeoclueMaster *source = - static_cast<QGeoSatelliteInfoSourceGeoclueMaster *>(userdata); - - QList<int> usedPrns; - for (unsigned int i = 0; i < used_prn->len; ++i) - usedPrns.append(g_array_index(used_prn, int, i)); - - QList<QGeoSatelliteInfo> satInfos; - for (unsigned int i = 0; i < sat_info->len; ++i) { - GValueArray *a = static_cast<GValueArray *>(g_ptr_array_index(sat_info, i)); - - QGeoSatelliteInfo satInfo; - - satInfo.setSatelliteIdentifier(g_value_get_int(g_value_array_get_nth(a, 0))); - satInfo.setAttribute(QGeoSatelliteInfo::Elevation, - g_value_get_int(g_value_array_get_nth(a, 1))); - satInfo.setAttribute(QGeoSatelliteInfo::Azimuth, - g_value_get_int(g_value_array_get_nth(a, 2))); - satInfo.setSignalStrength(g_value_get_int(g_value_array_get_nth(a, 3))); - - satInfos.append(satInfo); - } - - source->satelliteChanged(timestamp, satellite_used, satellite_visible, usedPrns, satInfos); -} - -void satellite_callback(GeoclueSatellite *satellite, int timestamp, int satellite_used, - int satellite_visible, GArray *used_prn, GPtrArray *sat_info, - GError *error, gpointer userdata) -{ - Q_UNUSED(satellite) - - if (error) - g_error_free(error); - - QGeoSatelliteInfoSourceGeoclueMaster *source = - static_cast<QGeoSatelliteInfoSourceGeoclueMaster *>(userdata); +#include <QtCore/QLoggingCategory> +#include <QtDBus/QDBusPendingCallWatcher> - QList<int> usedPrns; - for (unsigned int i = 0; i < used_prn->len; ++i) - usedPrns.append(g_array_index(used_prn, int, i)); +Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue) - QList<QGeoSatelliteInfo> satInfos; - for (unsigned int i = 0; i < sat_info->len; ++i) { - GValueArray *a = static_cast<GValueArray *>(g_ptr_array_index(sat_info, i)); - - QGeoSatelliteInfo satInfo; - - satInfo.setSatelliteIdentifier(g_value_get_int(g_value_array_get_nth(a, 0))); - satInfo.setAttribute(QGeoSatelliteInfo::Elevation, - g_value_get_int(g_value_array_get_nth(a, 1))); - satInfo.setAttribute(QGeoSatelliteInfo::Azimuth, - g_value_get_int(g_value_array_get_nth(a, 2))); - satInfo.setSignalStrength(g_value_get_int(g_value_array_get_nth(a, 3))); - - satInfos.append(satInfo); - } - - source->requestUpdateFinished(timestamp, satellite_used, satellite_visible, usedPrns, satInfos); -} - -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, QGeoSatelliteInfo &si) -{ - int a; - - argument.beginStructure(); - argument >> a; - si.setSatelliteIdentifier(a); - argument >> a; - si.setAttribute(QGeoSatelliteInfo::Elevation, a); - argument >> a; - si.setAttribute(QGeoSatelliteInfo::Azimuth, a); - argument >> a; - si.setSignalStrength(a); - argument.endStructure(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, QList<QGeoSatelliteInfo> &sis) -{ - sis.clear(); - - argument.beginArray(); - while (!argument.atEnd()) { - QGeoSatelliteInfo si; - argument >> si; - sis.append(si); - } - argument.endArray(); +#define MINIMUM_UPDATE_INTERVAL 1000 - return argument; -} +QT_BEGIN_NAMESPACE QGeoSatelliteInfoSourceGeoclueMaster::QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent) -: QGeoSatelliteInfoSource(parent), QGeoclueMaster(this), m_sat(0), m_error(NoError), - m_satellitesChangedConnected(false), m_running(false) +: QGeoSatelliteInfoSource(parent), m_master(new QGeoclueMaster(this)), m_provider(0), m_sat(0), + m_error(NoError), m_satellitesChangedConnected(false), m_running(false) { + connect(m_master, SIGNAL(positionProviderChanged(QString,QString,QString,QString)), + this, SLOT(positionProviderChanged(QString,QString,QString,QString))); + m_requestTimer.setSingleShot(true); connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); } @@ -163,6 +66,14 @@ int QGeoSatelliteInfoSourceGeoclueMaster::minimumUpdateInterval() const return MINIMUM_UPDATE_INTERVAL; } +void QGeoSatelliteInfoSourceGeoclueMaster::setUpdateInterval(int msec) +{ + if (msec < 0 || (msec > 0 && msec < MINIMUM_UPDATE_INTERVAL)) + msec = MINIMUM_UPDATE_INTERVAL; + + QGeoSatelliteInfoSource::setUpdateInterval(msec); +} + QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceGeoclueMaster::error() const { return m_error; @@ -176,14 +87,10 @@ void QGeoSatelliteInfoSourceGeoclueMaster::startUpdates() m_running = true; // Start Geoclue provider. - if (!hasMasterClient()) + if (!m_master->hasMasterClient()) configureSatelliteSource(); - // m_sat is likely to be invalid until Geoclue master selects a position provider. - if (!m_sat) - return; - - g_signal_connect(G_OBJECT(m_sat), "satellite-changed", G_CALLBACK(satellite_changed), this); + m_requestTimer.start(updateInterval()); } void QGeoSatelliteInfoSourceGeoclueMaster::stopUpdates() @@ -191,15 +98,17 @@ void QGeoSatelliteInfoSourceGeoclueMaster::stopUpdates() if (!m_running) return; - if (m_sat) - g_signal_handlers_disconnect_by_func(G_OBJECT(m_sat), gpointer(satellite_changed), this); + if (m_sat) { + disconnect(m_sat, SIGNAL(SatelliteChanged(qint32,qint32,qint32,QList<qint32>,QList<QGeoSatelliteInfo>)), + this, SLOT(satelliteChanged(qint32,qint32,qint32,QList<qint32>,QList<QGeoSatelliteInfo>))); + } m_running = false; // Only stop positioning if single update not requested. if (!m_requestTimer.isActive()) { cleanupSatelliteSource(); - releaseMasterClient(); + m_master->releaseMasterClient(); } } @@ -213,19 +122,24 @@ void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdate(int timeout) if (m_requestTimer.isActive()) return; - if (!hasMasterClient()) + if (!m_master->hasMasterClient()) configureSatelliteSource(); m_requestTimer.start(qMax(timeout, minimumUpdateInterval())); - if (m_sat) - geoclue_satellite_get_satellite_async(m_sat, satellite_callback, this); + if (m_sat) { + QDBusPendingReply<qint32, qint32, qint32, QList<qint32>, QList<QGeoSatelliteInfo> > reply = + m_sat->GetSatellite(); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(getSatelliteFinished(QDBusPendingCallWatcher*))); + } } -void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(int timestamp, int satellitesUsed, - int satellitesVisible, - const QList<int> &usedPrn, - const QList<QGeoSatelliteInfo> &satInfos) +void QGeoSatelliteInfoSourceGeoclueMaster::updateSatelliteInfo(int timestamp, int satellitesUsed, + int satellitesVisible, + const QList<int> &usedPrn, + const QList<QGeoSatelliteInfo> &satInfos) { Q_UNUSED(timestamp) @@ -252,36 +166,57 @@ void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(int timestamp, int s m_inUse = inUse; emit satellitesInUseUpdated(m_inUse); -} -void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdateFinished(int timestamp, int satellitesUsed, - int satellitesVisible, - const QList<int> &usedPrn, - const QList<QGeoSatelliteInfo> &satInfos) -{ - m_requestTimer.stop(); - satelliteChanged(timestamp, satellitesUsed, satellitesVisible, usedPrn, satInfos); + m_requestTimer.start(updateInterval()); } void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdateTimeout() { // If we end up here, there has not been a valid satellite info update. - emit requestTimeout(); + if (m_running) { + m_inView.clear(); + m_inUse.clear(); + emit satellitesInViewUpdated(m_inView); + emit satellitesInUseUpdated(m_inUse); + } else { + emit requestTimeout(); - // Only stop satellite info if regular updates not active. - if (!m_running) { + // Only stop satellite info if regular updates not active. cleanupSatelliteSource(); - releaseMasterClient(); + m_master->releaseMasterClient(); } } -void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QByteArray &service, const QByteArray &path) +void QGeoSatelliteInfoSourceGeoclueMaster::getSatelliteFinished(QDBusPendingCallWatcher *watcher) { - if (m_sat) - cleanupSatelliteSource(); + QDBusPendingReply<qint32, qint32, qint32, QList<qint32>, QList<QGeoSatelliteInfo> > reply = *watcher; + watcher->deleteLater(); + + if (reply.isError()) + return; + + m_requestTimer.stop(); + updateSatelliteInfo(reply.argumentAt<0>(), reply.argumentAt<1>(), reply.argumentAt<2>(), + reply.argumentAt<3>(), reply.argumentAt<4>()); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(int timestamp, int satellitesUsed, int satellitesVisible, const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos) +{ + updateSatelliteInfo(timestamp, satellitesUsed, satellitesVisible, usedPrn, satInfos); +} - QByteArray providerService; - QByteArray providerPath; +void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QString &name, + const QString &description, + const QString &service, + const QString &path) +{ + Q_UNUSED(name) + Q_UNUSED(description) + + cleanupSatelliteSource(); + + QString providerService; + QString providerPath; if (service.isEmpty() || path.isEmpty()) { // No valid position provider has been selected. This probably means that the GPS provider @@ -290,7 +225,7 @@ void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QByteAr QDBusConnection conn = QDBusConnection::sessionBus(); conn.connect(QString(), QString(), QStringLiteral("org.freedesktop.Geoclue.Satellite"), QStringLiteral("SatelliteChanged"), this, - SLOT(satellitesChanged(QDBusMessage))); + SLOT(satelliteChanged(QDBusMessage))); m_satellitesChangedConnected = true; return; } @@ -300,7 +235,7 @@ void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QByteAr conn.disconnect(QString(), QString(), QStringLiteral("org.freedesktop.Geoclue.Satellite"), QStringLiteral("SatelliteChanged"), this, - SLOT(satellitesChanged(QDBusMessage))); + SLOT(satelliteChanged(QDBusMessage))); m_satellitesChangedConnected = false; } @@ -314,17 +249,18 @@ void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QByteAr return; } - m_sat = geoclue_satellite_new(providerService.constData(), providerPath.constData()); - if (!m_sat) { - m_error = AccessError; - emit QGeoSatelliteInfoSource::error(m_error); - return; - } + m_provider = new OrgFreedesktopGeoclueInterface(providerService, providerPath, QDBusConnection::sessionBus()); + m_provider->AddReference(); - g_signal_connect(G_OBJECT(m_sat), "satellite-changed", G_CALLBACK(satellite_changed), this); + m_sat = new OrgFreedesktopGeoclueSatelliteInterface(providerService, providerPath, QDBusConnection::sessionBus()); + + if (m_running) { + connect(m_sat, SIGNAL(SatelliteChanged(qint32,qint32,qint32,QList<qint32>,QList<QGeoSatelliteInfo>)), + this, SLOT(satelliteChanged(qint32,qint32,qint32,QList<qint32>,QList<QGeoSatelliteInfo>))); + } } -void QGeoSatelliteInfoSourceGeoclueMaster::satellitesChanged(const QDBusMessage &message) +void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(const QDBusMessage &message) { QVariantList arguments = message.arguments(); if (arguments.length() != 5) @@ -347,17 +283,22 @@ void QGeoSatelliteInfoSourceGeoclueMaster::satellitesChanged(const QDBusMessage satelliteChanged(timestamp, usedSatellites, visibleSatellites, usedPrn, satelliteInfos); } -bool QGeoSatelliteInfoSourceGeoclueMaster::configureSatelliteSource() +void QGeoSatelliteInfoSourceGeoclueMaster::configureSatelliteSource() { - return createMasterClient(GEOCLUE_ACCURACY_LEVEL_DETAILED, GEOCLUE_RESOURCE_GPS); + if (!m_master->createMasterClient(Accuracy::Detailed, QGeoclueMaster::ResourceGps)) { + m_error = UnknownSourceError; + emit QGeoSatelliteInfoSource::error(m_error); + } } void QGeoSatelliteInfoSourceGeoclueMaster::cleanupSatelliteSource() { - if (m_sat) { - g_object_unref(m_sat); - m_sat = 0; - } + if (m_provider) + m_provider->RemoveReference(); + delete m_provider; + m_provider = 0; + delete m_sat; + m_sat = 0; } QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h index 3269a423..e840e8a3 100644 --- a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h @@ -36,17 +36,18 @@ #include "qgeocluemaster.h" -#include <geoclue/geoclue-satellite.h> - -#include <QtCore/qcompilerdetection.h> #include <QtCore/QTimer> #include <QtPositioning/QGeoSatelliteInfoSource> +class OrgFreedesktopGeoclueInterface; +class OrgFreedesktopGeoclueSatelliteInterface; + QT_BEGIN_NAMESPACE class QDBusMessage; +class QDBusPendingCallWatcher; -class QGeoSatelliteInfoSourceGeoclueMaster : public QGeoSatelliteInfoSource, public QGeoclueMaster +class QGeoSatelliteInfoSourceGeoclueMaster : public QGeoSatelliteInfoSource { Q_OBJECT @@ -55,28 +56,36 @@ public: ~QGeoSatelliteInfoSourceGeoclueMaster(); int minimumUpdateInterval() const Q_DECL_OVERRIDE; + void setUpdateInterval(int msec) Q_DECL_OVERRIDE; + Error error() const Q_DECL_OVERRIDE; void startUpdates() Q_DECL_OVERRIDE; void stopUpdates() Q_DECL_OVERRIDE; void requestUpdate(int timeout = 0) Q_DECL_OVERRIDE; - void satelliteChanged(int timestamp, int satellitesUsed, int satellitesVisible, - const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos); - - void requestUpdateFinished(int timestamp, int satellitesUsed, int satellitesVisible, - const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos); - private slots: + void positionProviderChanged(const QString &name, const QString &description, + const QString &service, const QString &path); void requestUpdateTimeout(); - void positionProviderChanged(const QByteArray &service, const QByteArray &path); - void satellitesChanged(const QDBusMessage &message); + + void getSatelliteFinished(QDBusPendingCallWatcher *watcher); + void satelliteChanged(int timestamp, int satellitesUsed, int satellitesVisible, + const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos); + void satelliteChanged(const QDBusMessage &message); private: - bool configureSatelliteSource(); + void configureSatelliteSource(); void cleanupSatelliteSource(); - GeoclueSatellite *m_sat; + void updateSatelliteInfo(int timestamp, int satellitesUsed, int satellitesVisible, + const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos); + + QGeoclueMaster *m_master; + + OrgFreedesktopGeoclueInterface *m_provider; + OrgFreedesktopGeoclueSatelliteInterface *m_sat; + QTimer m_requestTimer; QList<QGeoSatelliteInfo> m_inView; QList<QGeoSatelliteInfo> m_inUse; diff --git a/src/plugins/position/gypsy/plugin.json b/src/plugins/position/gypsy/plugin.json index b3ecc0f7..9cef03f8 100644 --- a/src/plugins/position/gypsy/plugin.json +++ b/src/plugins/position/gypsy/plugin.json @@ -4,5 +4,6 @@ "Position": false, "Satellite": true, "Monitor" : false, - "Priority": 1000 + "Priority": 1000, + "Testable": false } diff --git a/src/plugins/position/position.pro b/src/plugins/position/position.pro index 636bcc54..f9492a79 100644 --- a/src/plugins/position/position.pro +++ b/src/plugins/position/position.pro @@ -1,12 +1,12 @@ TEMPLATE = subdirs -config_geoclue:SUBDIRS += geoclue +qtHaveModule(dbus):SUBDIRS += geoclue config_gypsy:SUBDIRS += gypsy qtHaveModule(simulator):SUBDIRS += simulator -blackberry:SUBDIRS += blackberry -ios:SUBDIRS += corelocation +osx|ios:SUBDIRS += corelocation android:!android-no-sdk:SUBDIRS += android winrt:SUBDIRS += winrt +win32:qtHaveModule(serialport):SUBDIRS += serialnmea SUBDIRS += \ positionpoll diff --git a/src/plugins/position/positionpoll/plugin.json b/src/plugins/position/positionpoll/plugin.json index a5b2f602..df1f47de 100644 --- a/src/plugins/position/positionpoll/plugin.json +++ b/src/plugins/position/positionpoll/plugin.json @@ -4,5 +4,6 @@ "Position": false, "Satellite": false, "Monitor": true, - "Priority": 1000 + "Priority": 1000, + "Testable": true } diff --git a/src/plugins/position/serialnmea/plugin.json b/src/plugins/position/serialnmea/plugin.json new file mode 100644 index 00000000..826836c3 --- /dev/null +++ b/src/plugins/position/serialnmea/plugin.json @@ -0,0 +1,9 @@ +{ + "Keys": ["serialnmea"], + "Provider": "serialnmea", + "Position": true, + "Satellite": false, + "Monitor" : false, + "Priority": 1000, + "Testable": false +} diff --git a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp new file mode 100644 index 00000000..a3f8ac98 --- /dev/null +++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopositioninfosourcefactory_serialnmea.h" +#include <QtPositioning/qnmeapositioninfosource.h> +#include <QtSerialPort/qserialport.h> +#include <QtSerialPort/qserialportinfo.h> +#include <QtCore/qloggingcategory.h> +#include <QSet> + +Q_LOGGING_CATEGORY(lcSerial, "qt.positioning.serialnmea") + +class NmeaSource : public QNmeaPositionInfoSource +{ +public: + NmeaSource(QObject *parent); + bool isValid() const { return !m_port.isNull(); } + +private: + QScopedPointer<QSerialPort> m_port; +}; + +NmeaSource::NmeaSource(QObject *parent) + : QNmeaPositionInfoSource(RealTimeMode, parent), + m_port(new QSerialPort) +{ + QByteArray requestedPort = qgetenv("QT_NMEA_SERIAL_PORT"); + if (requestedPort.isEmpty()) { + const QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts(); + qCDebug(lcSerial) << "Found" << ports.count() << "serial ports"; + if (ports.isEmpty()) { + qWarning("serialnmea: No serial ports found"); + m_port.reset(); + return; + } + + // Try to find a well-known device. + QSet<int> supportedDevices; + supportedDevices << 0x67b; // GlobalSat (BU-353S4 and probably others) + supportedDevices << 0xe8d; // Qstarz MTK II + QString portName; + foreach (const QSerialPortInfo& port, ports) { + if (port.hasVendorIdentifier() && supportedDevices.contains(port.vendorIdentifier())) { + portName = port.portName(); + break; + } + } + + if (portName.isEmpty()) { + qWarning("serialnmea: No known GPS device found. Specify the COM port via QT_NMEA_SERIAL_PORT."); + m_port.reset(); + return; + } + + m_port->setPortName(portName); + } else { + m_port->setPortName(QString::fromUtf8(requestedPort)); + } + + m_port->setBaudRate(4800); + + qCDebug(lcSerial) << "Opening serial port" << m_port->portName(); + + if (!m_port->open(QIODevice::ReadOnly)) { + qWarning("serialnmea: Failed to open %s", qPrintable(m_port->portName())); + m_port.reset(); + return; + } + + setDevice(m_port.data()); + + qCDebug(lcSerial) << "Opened successfully"; +} + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactorySerialNmea::positionInfoSource(QObject *parent) +{ + QScopedPointer<NmeaSource> src(new NmeaSource(parent)); + return src->isValid() ? src.take() : Q_NULLPTR; +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactorySerialNmea::satelliteInfoSource(QObject *parent) +{ + Q_UNUSED(parent); + return Q_NULLPTR; +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySerialNmea::areaMonitor(QObject *parent) +{ + Q_UNUSED(parent); + return Q_NULLPTR; +} diff --git a/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.h b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h index 30153a70..b28d9834 100644 --- a/src/plugins/position/blackberry/qgeopositioninfosourcefactory_bb.h +++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. +** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtPositioning module of the Qt Toolkit. @@ -31,16 +31,13 @@ ** ****************************************************************************/ -#ifndef QGEOPOSITIONINFOSOURCEFACTORY_BB_H -#define QGEOPOSITIONINFOSOURCEFACTORY_BB_H - -#include <bb/Global> - -#include <QGeoPositionInfoSourceFactory> +#ifndef QGEOPOSITIONINFOSOURCEFACTORY_SERIALNMEA_H +#define QGEOPOSITIONINFOSOURCEFACTORY_SERIALNMEA_H #include <QObject> +#include <qgeopositioninfosourcefactory.h> -class QGeoPositionInfoSourceFactoryBb : public QObject, public QGeoPositionInfoSourceFactory +class QGeoPositionInfoSourceFactorySerialNmea : public QObject, public QGeoPositionInfoSourceFactory { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" @@ -53,4 +50,4 @@ public: QGeoAreaMonitorSource *areaMonitor(QObject *parent); }; -#endif // include guard +#endif diff --git a/src/plugins/position/serialnmea/serialnmea.pro b/src/plugins/position/serialnmea/serialnmea.pro new file mode 100644 index 00000000..81570837 --- /dev/null +++ b/src/plugins/position/serialnmea/serialnmea.pro @@ -0,0 +1,15 @@ +TARGET = qtposition_serialnmea +QT = core positioning serialport + +PLUGIN_TYPE = position +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactorySerialNmea +load(qt_plugin) + +HEADERS += \ + qgeopositioninfosourcefactory_serialnmea.h + +SOURCES += \ + qgeopositioninfosourcefactory_serialnmea.cpp + +OTHER_FILES += \ + plugin.json diff --git a/src/plugins/position/simulator/plugin.json b/src/plugins/position/simulator/plugin.json index 8aa5e79f..0935f4dc 100644 --- a/src/plugins/position/simulator/plugin.json +++ b/src/plugins/position/simulator/plugin.json @@ -4,5 +4,6 @@ "Position": true, "Satellite": true, "Monitor" : false, - "Priority": 1000 + "Priority": 1000, + "Testable": true } diff --git a/src/plugins/position/simulator/qgeopositioninfosource_simulator_p.h b/src/plugins/position/simulator/qgeopositioninfosource_simulator_p.h index 323956aa..0f5cce6e 100644 --- a/src/plugins/position/simulator/qgeopositioninfosource_simulator_p.h +++ b/src/plugins/position/simulator/qgeopositioninfosource_simulator_p.h @@ -34,6 +34,17 @@ #ifndef QGEOPOSITIONINFOSOURCESIMULATOR_H #define QGEOPOSITIONINFOSOURCESIMULATOR_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qgeopositioninfosource.h" #include "qgeopositioninfo.h" #include "qlocationdata_simulator_p.h" diff --git a/src/plugins/position/simulator/qgeosatelliteinfosource_simulator_p.h b/src/plugins/position/simulator/qgeosatelliteinfosource_simulator_p.h index 5a687368..745d76b3 100644 --- a/src/plugins/position/simulator/qgeosatelliteinfosource_simulator_p.h +++ b/src/plugins/position/simulator/qgeosatelliteinfosource_simulator_p.h @@ -34,6 +34,17 @@ #ifndef QGEOSATELLITEINFOSOURCE_SIMULATOR_H #define QGEOSATELLITEINFOSOURCE_SIMULATOR_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QTimer> #include "qgeosatelliteinfosource.h" #include "qgeosatelliteinfo.h" diff --git a/src/plugins/position/simulator/qlocationconnection_simulator_p.h b/src/plugins/position/simulator/qlocationconnection_simulator_p.h index 17635dfc..21b1fdef 100644 --- a/src/plugins/position/simulator/qlocationconnection_simulator_p.h +++ b/src/plugins/position/simulator/qlocationconnection_simulator_p.h @@ -34,6 +34,17 @@ #ifndef QLOCATIONCONNECTION_H #define QLOCATIONCONNECTION_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qlocationdata_simulator_p.h" #include <QtCore/QObject> diff --git a/src/plugins/position/simulator/simulator.pro b/src/plugins/position/simulator/simulator.pro index f9e2bdb5..dc00ae1a 100644 --- a/src/plugins/position/simulator/simulator.pro +++ b/src/plugins/position/simulator/simulator.pro @@ -4,16 +4,15 @@ QT = core network positioning PLUGIN_TYPE = position PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactorySimulator load(qt_plugin) +INCLUDEPATH += ../../../positioning QT += simulator DEFINES += QT_SIMULATOR SOURCES += qgeopositioninfosource_simulator.cpp \ - qlocationdata_simulator.cpp \ qgeosatelliteinfosource_simulator.cpp \ qlocationconnection_simulator.cpp \ qgeopositioninfosourcefactory_simulator.cpp HEADERS += qgeopositioninfosource_simulator_p.h \ - qlocationdata_simulator_p.h \ qgeosatelliteinfosource_simulator_p.h \ qlocationconnection_simulator_p.h \ qgeopositioninfosourcefactory_simulator.h diff --git a/src/plugins/position/winrt/plugin.json b/src/plugins/position/winrt/plugin.json index 5bb21702..0696cb0a 100644 --- a/src/plugins/position/winrt/plugin.json +++ b/src/plugins/position/winrt/plugin.json @@ -4,5 +4,6 @@ "Position": true, "Satellite": false, "Monitor" : false, - "Priority": 1000 + "Priority": 1000, + "Testable": false } diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp index 4e70cc07..5dbbacb5 100644 --- a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp +++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp @@ -37,75 +37,119 @@ #include "qgeopositioninfosource_winrt_p.h" #include <QCoreApplication> +#include <QMutex> +#include <qfunctions_winrt.h> +#include <private/qeventdispatcher_winrt_p.h> +#include <functional> #include <windows.system.h> #include <windows.devices.geolocation.h> +#include <windows.foundation.h> #include <windows.foundation.collections.h> using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Devices::Geolocation; using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::System; +using namespace ABI::Windows::Foundation::Collections; typedef ITypedEventHandler<Geolocator *, PositionChangedEventArgs *> GeoLocatorPositionHandler; typedef ITypedEventHandler<Geolocator *, StatusChangedEventArgs *> GeoLocatorStatusHandler; +typedef IAsyncOperationCompletedHandler<Geoposition*> PositionHandler; +#if _MSC_VER >= 1900 +typedef IAsyncOperationCompletedHandler<GeolocationAccessStatus> AccessHandler; +#endif QT_BEGIN_NAMESPACE -QGeoPositionInfoSourceWinrt::QGeoPositionInfoSourceWinrt(QObject *parent) +Q_DECLARE_METATYPE(QGeoPositionInfo) + +class QGeoPositionInfoSourceWinRTPrivate { +public: + ComPtr<IGeolocator> locator; + QTimer periodicTimer; + QTimer singleUpdateTimer; + QGeoPositionInfo lastPosition; + QGeoPositionInfoSource::Error positionError; + EventRegistrationToken statusToken; + EventRegistrationToken positionToken; + QMutex mutex; + bool updatesOngoing; +}; + + +QGeoPositionInfoSourceWinRT::QGeoPositionInfoSourceWinRT(QObject *parent) : QGeoPositionInfoSource(parent) - , m_positionError(QGeoPositionInfoSource::NoError) - , m_updatesOngoing(false) + , d_ptr(new QGeoPositionInfoSourceWinRTPrivate) { - HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(), - &m_locator); + Q_D(QGeoPositionInfoSourceWinRT); + d->positionError = QGeoPositionInfoSource::NoError; + d->updatesOngoing = false; + + qRegisterMetaType<QGeoPositionInfo>(); + + requestAccess(); + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { + HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(), + &d->locator); + RETURN_HR_IF_FAILED("Could not initialize native location services."); + + // StatusChanged throws an exception on Windows 8.1 +#if _MSC_VER >= 1900 + hr = d->locator->add_StatusChanged(Callback<GeoLocatorStatusHandler>(this, + &QGeoPositionInfoSourceWinRT::onStatusChanged).Get(), + &d->statusToken); + RETURN_HR_IF_FAILED("Could not add status callback."); +#endif - if (FAILED(hr)) { - setError(QGeoPositionInfoSource::UnknownSourceError); - qErrnoWarning(hr, "Could not initialize native location services"); - return; - } + hr = d->locator->put_ReportInterval(1000); + RETURN_HR_IF_FAILED("Could not initialize report interval."); - hr = m_locator->put_ReportInterval(minimumUpdateInterval()); - if (FAILED(hr)) { - setError(QGeoPositionInfoSource::UnknownSourceError); - qErrnoWarning(hr, "Could not initialize report interval"); - return; - } - hr = m_locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_High); + return hr; + }); + Q_ASSERT_SUCCEEDED(hr); + + hr = d->locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_Default); if (FAILED(hr)) { setError(QGeoPositionInfoSource::UnknownSourceError); - qErrnoWarning(hr, "Could not initialize desired accuracy"); + qErrnoWarning(hr, "Could not initialize desired accuracy."); return; } - m_positionToken.value = 0; + d->positionToken.value = 0; - m_periodicTimer.setSingleShot(true); - m_periodicTimer.setInterval(minimumUpdateInterval()); - connect(&m_periodicTimer, SIGNAL(timeout()), this, SLOT(virtualPositionUpdate())); + d->periodicTimer.setSingleShot(true); + d->periodicTimer.setInterval(minimumUpdateInterval()); + connect(&d->periodicTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::virtualPositionUpdate); - m_singleUpdateTimer.setSingleShot(true); - connect(&m_singleUpdateTimer, SIGNAL(timeout()), this, SLOT(singleUpdateTimeOut())); + d->singleUpdateTimer.setSingleShot(true); + connect(&d->singleUpdateTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::singleUpdateTimeOut); setPreferredPositioningMethods(QGeoPositionInfoSource::AllPositioningMethods); + + connect(this, &QGeoPositionInfoSourceWinRT::nativePositionUpdate, this, &QGeoPositionInfoSourceWinRT::updateSynchronized); } -QGeoPositionInfoSourceWinrt::~QGeoPositionInfoSourceWinrt() +QGeoPositionInfoSourceWinRT::~QGeoPositionInfoSourceWinRT() { } -QGeoPositionInfo QGeoPositionInfoSourceWinrt::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +QGeoPositionInfo QGeoPositionInfoSourceWinRT::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const { + Q_D(const QGeoPositionInfoSourceWinRT); Q_UNUSED(fromSatellitePositioningMethodsOnly) - return m_lastPosition; + return d->lastPosition; } -QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinrt::supportedPositioningMethods() const +QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinRT::supportedPositioningMethods() const { + Q_D(const QGeoPositionInfoSourceWinRT); + PositionStatus status; - HRESULT hr = m_locator->get_LocationStatus(&status); + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, &status]() { + HRESULT hr = d->locator->get_LocationStatus(&status); + return hr; + }); if (FAILED(hr)) return QGeoPositionInfoSource::NoPositioningMethods; @@ -119,88 +163,94 @@ QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinrt::supporte return QGeoPositionInfoSource::AllPositioningMethods; } -void QGeoPositionInfoSourceWinrt::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods) +void QGeoPositionInfoSourceWinRT::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods) { + Q_D(QGeoPositionInfoSourceWinRT); + PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods(); QGeoPositionInfoSource::setPreferredPositioningMethods(methods); if (previousPreferredPositioningMethods == preferredPositioningMethods()) return; - bool needsRestart = m_positionToken.value != 0; + bool needsRestart = d->positionToken.value != 0; if (needsRestart) stopHandler(); - HRESULT hr; - if (methods & PositioningMethod::SatellitePositioningMethods) - hr = m_locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_High); - else - hr = m_locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_Default); - - if (FAILED(hr)) { - qErrnoWarning(hr, "Could not set positioning accuracy"); - return; - } + PositionAccuracy acc = methods & PositioningMethod::SatellitePositioningMethods ? + PositionAccuracy::PositionAccuracy_High : + PositionAccuracy::PositionAccuracy_Default; + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, acc]() { + HRESULT hr = d->locator->put_DesiredAccuracy(acc); + return hr; + }); + RETURN_VOID_IF_FAILED("Could not set positioning accuracy."); if (needsRestart) startHandler(); } -void QGeoPositionInfoSourceWinrt::setUpdateInterval(int msec) +void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec) { - // Windows Phone does not support 0 interval -#ifdef Q_OS_WINPHONE + Q_D(QGeoPositionInfoSourceWinRT); + // Windows Phone 8.1 and Windows 10 do not support 0 interval +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) if (msec == 0) msec = minimumUpdateInterval(); #endif + // 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(); - HRESULT hr = m_locator->put_ReportInterval(msec); + HRESULT hr = d->locator->put_ReportInterval(msec); if (FAILED(hr)) { setError(QGeoPositionInfoSource::UnknownSourceError); qErrnoWarning(hr, "Failed to set update interval"); return; } - if (msec != 0) - m_periodicTimer.setInterval(msec); - else - m_periodicTimer.setInterval(minimumUpdateInterval()); + + d->periodicTimer.setInterval(qMax(msec, minimumUpdateInterval())); QGeoPositionInfoSource::setUpdateInterval(msec); } -int QGeoPositionInfoSourceWinrt::minimumUpdateInterval() const +int QGeoPositionInfoSourceWinRT::minimumUpdateInterval() const { // We use one second to reduce potential timer events // in case the platform itself stops reporting return 1000; } -void QGeoPositionInfoSourceWinrt::startUpdates() +void QGeoPositionInfoSourceWinRT::startUpdates() { - if (m_updatesOngoing) + Q_D(QGeoPositionInfoSourceWinRT); + + if (d->updatesOngoing) return; if (!startHandler()) return; - m_updatesOngoing = true; - m_periodicTimer.start(); + d->updatesOngoing = true; + d->periodicTimer.start(); } -void QGeoPositionInfoSourceWinrt::stopUpdates() +void QGeoPositionInfoSourceWinRT::stopUpdates() { + Q_D(QGeoPositionInfoSourceWinRT); + stopHandler(); - m_updatesOngoing = false; - m_periodicTimer.stop(); + d->updatesOngoing = false; + d->periodicTimer.stop(); } -bool QGeoPositionInfoSourceWinrt::startHandler() +bool QGeoPositionInfoSourceWinRT::startHandler() { + Q_D(QGeoPositionInfoSourceWinRT); + // Check if already attached - if (m_positionToken.value != 0) + if (d->positionToken.value != 0) return true; if (preferredPositioningMethods() == QGeoPositionInfoSource::NoPositioningMethods) { @@ -208,31 +258,49 @@ bool QGeoPositionInfoSourceWinrt::startHandler() return false; } - if (!checkNativeState()) + if (!requestAccess() || !checkNativeState()) return false; - HRESULT hr = m_locator->add_PositionChanged(Callback<GeoLocatorPositionHandler>(this, - &QGeoPositionInfoSourceWinrt::onPositionChanged).Get(), - &m_positionToken); + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { + HRESULT hr; + // We need to call this at least once on Windows 10 Mobile. + // Unfortunately this operation does not have a completion handler + // registered. That could have helped in the single update case + ComPtr<IAsyncOperation<Geoposition*>> op; + hr = d->locator->GetGeopositionAsync(&op); + + hr = d->locator->add_PositionChanged(Callback<GeoLocatorPositionHandler>(this, + &QGeoPositionInfoSourceWinRT::onPositionChanged).Get(), + &d->positionToken); + return hr; + }); if (FAILED(hr)) { setError(QGeoPositionInfoSource::UnknownSourceError); qErrnoWarning(hr, "Could not add position handler"); return false; } + return true; } -void QGeoPositionInfoSourceWinrt::stopHandler() +void QGeoPositionInfoSourceWinRT::stopHandler() { - if (!m_positionToken.value) + Q_D(QGeoPositionInfoSourceWinRT); + + if (!d->positionToken.value) return; - m_locator->remove_PositionChanged(m_positionToken); - m_positionToken.value = 0; + QEventDispatcherWinRT::runOnXamlThread([d]() { + d->locator->remove_PositionChanged(d->positionToken); + return S_OK; + }); + d->positionToken.value = 0; } -void QGeoPositionInfoSourceWinrt::requestUpdate(int timeout) +void QGeoPositionInfoSourceWinRT::requestUpdate(int timeout) { + Q_D(QGeoPositionInfoSourceWinRT); + if (timeout != 0 && timeout < minimumUpdateInterval()) { emit updateTimeout(); return; @@ -242,11 +310,14 @@ void QGeoPositionInfoSourceWinrt::requestUpdate(int timeout) timeout = 2*60*1000; // Maximum time for cold start (see Android) startHandler(); - m_singleUpdateTimer.start(timeout); + d->singleUpdateTimer.start(timeout); } -void QGeoPositionInfoSourceWinrt::virtualPositionUpdate() +void QGeoPositionInfoSourceWinRT::virtualPositionUpdate() { + Q_D(QGeoPositionInfoSourceWinRT); + QMutexLocker locker(&d->mutex); + // Need to check if services are still running and ok if (!checkNativeState()) { stopUpdates(); @@ -258,39 +329,69 @@ void QGeoPositionInfoSourceWinrt::virtualPositionUpdate() // between backends. // This only applies to the periodic timer, not for single requests // We can only do this if we received a valid position before - if (m_lastPosition.isValid()) { - QGeoPositionInfo sent = m_lastPosition; + if (d->lastPosition.isValid()) { + QGeoPositionInfo sent = d->lastPosition; sent.setTimestamp(QDateTime::currentDateTime()); - m_lastPosition = sent; + d->lastPosition = sent; emit positionUpdated(sent); } - m_periodicTimer.start(); + d->periodicTimer.start(); } -void QGeoPositionInfoSourceWinrt::singleUpdateTimeOut() +void QGeoPositionInfoSourceWinRT::singleUpdateTimeOut() { - emit updateTimeout(); - if (!m_updatesOngoing) + Q_D(QGeoPositionInfoSourceWinRT); + QMutexLocker locker(&d->mutex); + + if (d->singleUpdateTimer.isActive()) { + emit updateTimeout(); + if (!d->updatesOngoing) + stopHandler(); + } +} + +void QGeoPositionInfoSourceWinRT::updateSynchronized(QGeoPositionInfo currentInfo) +{ + Q_D(QGeoPositionInfoSourceWinRT); + QMutexLocker locker(&d->mutex); + + d->periodicTimer.stop(); + d->lastPosition = currentInfo; + + if (d->updatesOngoing) + d->periodicTimer.start(); + + if (d->singleUpdateTimer.isActive()) { + d->singleUpdateTimer.stop(); + if (!d->updatesOngoing) stopHandler(); + } + + emit positionUpdated(currentInfo); } -QGeoPositionInfoSource::Error QGeoPositionInfoSourceWinrt::error() const +QGeoPositionInfoSource::Error QGeoPositionInfoSourceWinRT::error() const { - return m_positionError; + Q_D(const QGeoPositionInfoSourceWinRT); + return d->positionError; } -void QGeoPositionInfoSourceWinrt::setError(QGeoPositionInfoSource::Error positionError) +void QGeoPositionInfoSourceWinRT::setError(QGeoPositionInfoSource::Error positionError) { - if (positionError == m_positionError) + Q_D(QGeoPositionInfoSourceWinRT); + + if (positionError == d->positionError) return; - m_positionError = positionError; + d->positionError = positionError; emit QGeoPositionInfoSource::error(positionError); } -bool QGeoPositionInfoSourceWinrt::checkNativeState() +bool QGeoPositionInfoSourceWinRT::checkNativeState() { + Q_D(QGeoPositionInfoSourceWinRT); + PositionStatus status; - HRESULT hr = m_locator->get_LocationStatus(&status); + HRESULT hr = d->locator->get_LocationStatus(&status); if (FAILED(hr)) { setError(QGeoPositionInfoSource::UnknownSourceError); qErrnoWarning(hr, "Could not query status"); @@ -314,17 +415,14 @@ bool QGeoPositionInfoSourceWinrt::checkNativeState() return result; } -HRESULT QGeoPositionInfoSourceWinrt::onPositionChanged(IGeolocator *locator, IPositionChangedEventArgs *args) +HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPositionChangedEventArgs *args) { Q_UNUSED(locator); - m_periodicTimer.stop(); - HRESULT hr; ComPtr<IGeoposition> pos; hr = args->get_Position(&pos); - if (FAILED(hr)) - qErrnoWarning(hr, "Could not access position object"); + RETURN_HR_IF_FAILED("Could not access position object."); QGeoPositionInfo currentInfo; @@ -378,19 +476,48 @@ HRESULT QGeoPositionInfoSourceWinrt::onPositionChanged(IGeolocator *locator, IPo currentInfo.setTimestamp(QDateTime::currentDateTime()); - m_lastPosition = currentInfo; + emit nativePositionUpdate(currentInfo); - if (m_updatesOngoing) - m_periodicTimer.start(); - - if (m_singleUpdateTimer.isActive()) { - m_singleUpdateTimer.stop(); - if (!m_updatesOngoing) - stopHandler(); - } + return S_OK; +} - emit positionUpdated(currentInfo); +HRESULT QGeoPositionInfoSourceWinRT::onStatusChanged(IGeolocator*, IStatusChangedEventArgs *args) +{ + PositionStatus st; + args->get_Status(&st); return S_OK; } +bool QGeoPositionInfoSourceWinRT::requestAccess() const +{ +#if _MSC_VER >= 1900 + static GeolocationAccessStatus accessStatus = GeolocationAccessStatus_Unspecified; + static ComPtr<IGeolocatorStatics> statics; + + if (accessStatus == GeolocationAccessStatus_Allowed) + return true; + else if (accessStatus == GeolocationAccessStatus_Denied) + return false; + + ComPtr<IAsyncOperation<GeolocationAccessStatus>> op; + HRESULT hr; + hr = QEventDispatcherWinRT::runOnXamlThread([&op]() { + HRESULT hr; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(), + IID_PPV_ARGS(&statics)); + RETURN_HR_IF_FAILED("Could not access Geolocation Statics."); + + hr = statics->RequestAccessAsync(&op); + return hr; + }); + Q_ASSERT_SUCCEEDED(hr); + + // We cannot wait inside the XamlThread as that would deadlock + QWinRTFunctions::await(op, &accessStatus); + return accessStatus == GeolocationAccessStatus_Allowed; +#else // _MSC_VER < 1900 + return true; +#endif // _MSC_VER < 1900 +} + QT_END_NAMESPACE diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h index a7d3cae1..b8820dd2 100644 --- a/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h +++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h @@ -37,6 +37,17 @@ #ifndef QGEOPOSITIONINFOSOURCEWINRT_H #define QGEOPOSITIONINFOSOURCEWINRT_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qgeopositioninfosource.h" #include "qgeopositioninfo.h" @@ -59,12 +70,14 @@ namespace ABI { QT_BEGIN_NAMESPACE -class QGeoPositionInfoSourceWinrt : public QGeoPositionInfoSource +class QGeoPositionInfoSourceWinRTPrivate; + +class QGeoPositionInfoSourceWinRT : public QGeoPositionInfoSource { Q_OBJECT public: - QGeoPositionInfoSourceWinrt(QObject *parent = 0); - ~QGeoPositionInfoSourceWinrt(); + QGeoPositionInfoSourceWinRT(QObject *parent = 0); + ~QGeoPositionInfoSourceWinRT(); QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const; PositioningMethods supportedPositioningMethods() const; @@ -78,6 +91,12 @@ public: HRESULT onPositionChanged(ABI::Windows::Devices::Geolocation::IGeolocator *locator, ABI::Windows::Devices::Geolocation::IPositionChangedEventArgs *args); + HRESULT onStatusChanged(ABI::Windows::Devices::Geolocation::IGeolocator*, + ABI::Windows::Devices::Geolocation::IStatusChangedEventArgs *args); + + bool requestAccess() const; +Q_SIGNALS: + void nativePositionUpdate(const QGeoPositionInfo); public slots: void startUpdates(); void stopUpdates(); @@ -88,23 +107,16 @@ private slots: void stopHandler(); void virtualPositionUpdate(); void singleUpdateTimeOut(); + void updateSynchronized(const QGeoPositionInfo info); private: bool startHandler(); - Q_DISABLE_COPY(QGeoPositionInfoSourceWinrt) + Q_DISABLE_COPY(QGeoPositionInfoSourceWinRT) void setError(QGeoPositionInfoSource::Error positionError); bool checkNativeState(); - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Geolocation::IGeolocator> m_locator; - EventRegistrationToken m_positionToken; - - QGeoPositionInfo m_lastPosition; - QGeoPositionInfoSource::Error m_positionError; - - //EventRegistrationToken m_StatusToken; - QTimer m_periodicTimer; - QTimer m_singleUpdateTimer; - bool m_updatesOngoing; + QScopedPointer<QGeoPositionInfoSourceWinRTPrivate> d_ptr; + Q_DECLARE_PRIVATE(QGeoPositionInfoSourceWinRT) }; QT_END_NAMESPACE diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp index 0f9a21f2..81656c21 100644 --- a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp +++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp @@ -37,18 +37,18 @@ #include "qgeopositioninfosourcefactory_winrt.h" #include "qgeopositioninfosource_winrt_p.h" -QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryWinrt::positionInfoSource(QObject *parent) +QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryWinRT::positionInfoSource(QObject *parent) { - return new QGeoPositionInfoSourceWinrt(parent); + return new QGeoPositionInfoSourceWinRT(parent); } -QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryWinrt::satelliteInfoSource(QObject *parent) +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryWinRT::satelliteInfoSource(QObject *parent) { Q_UNUSED(parent); return 0; } -QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryWinrt::areaMonitor(QObject *parent) +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryWinRT::areaMonitor(QObject *parent) { Q_UNUSED(parent); return 0; diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h index 0627abc4..46cd3853 100644 --- a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h +++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h @@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE -class QGeoPositionInfoSourceFactoryWinrt : public QObject, public QGeoPositionInfoSourceFactory +class QGeoPositionInfoSourceFactoryWinRT : public QObject, public QGeoPositionInfoSourceFactory { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" diff --git a/src/plugins/position/winrt/winrt.pro b/src/plugins/position/winrt/winrt.pro index 228a9e78..c58c6c18 100644 --- a/src/plugins/position/winrt/winrt.pro +++ b/src/plugins/position/winrt/winrt.pro @@ -1,8 +1,8 @@ TARGET = qtposition_winrt -QT = core positioning +QT = core core-private positioning PLUGIN_TYPE = position -PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryWinrt +PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryWinRT load(qt_plugin) SOURCES += qgeopositioninfosource_winrt.cpp \ diff --git a/src/positioning/doc/qtpositioning.qdocconf b/src/positioning/doc/qtpositioning.qdocconf index 608b30a1..1645c092 100644 --- a/src/positioning/doc/qtpositioning.qdocconf +++ b/src/positioning/doc/qtpositioning.qdocconf @@ -40,7 +40,7 @@ headerdirs += .. \ sourcedirs += .. \ ../../imports/positioning -examplesinstallpath = positioning +examplesinstallpath = qtlocation/positioning exampledirs += ../../../examples/positioning \ snippets/ diff --git a/src/positioning/doc/src/examples/weatherinfo.qdoc b/src/positioning/doc/src/examples/weatherinfo.qdoc index e32127d4..3db6fcbf 100644 --- a/src/positioning/doc/src/examples/weatherinfo.qdoc +++ b/src/positioning/doc/src/examples/weatherinfo.qdoc @@ -45,6 +45,8 @@ \include examples-run.qdocinc + The example uses weather data provided by \l http://www.openweathermap.org. + The key part of this example is the application's data model, contained in the WeatherData and AppModel classes. WeatherData represents the weather information taken from the HTTP service. It is a simple data class, but we diff --git a/src/positioning/doc/src/qtpositioning.qdoc b/src/positioning/doc/src/qtpositioning.qdoc index c2d6912d..1ce33085 100644 --- a/src/positioning/doc/src/qtpositioning.qdoc +++ b/src/positioning/doc/src/qtpositioning.qdoc @@ -61,10 +61,12 @@ The Qt Positioning API provides positioning information via QML and C++ interfaces. -Currently the API is supported on \l{Qt for Android}{Android}, -\l{Qt for iOS}{iOS}, -\l{Qt for Linux/X11}{Linux} (using \l{http://www.freedesktop.org/wiki/Software/GeoClue}{GeoClue}) -and \l {Qt for WinRT} {WinRT}. +Currently the API is supported on \l {Qt for Android}{Android}, \l {Qt for iOS}{iOS}, +\l {Qt for OS X}{OS X}, +\l {Qt for Linux/X11}{Linux} (using +\l {http://www.freedesktop.org/wiki/Software/GeoClue}{GeoClue version 0.12.99}), +\l {Qt for Windows}{Windows} (with GPS receivers exposed as a serial port providing NMEA sentences), +and \l {Qt for WinRT}{WinRT} (using Windows.Devices.Geolocation). \section1 Overview diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro index 2e751bfb..0dd91272 100644 --- a/src/positioning/positioning.pro +++ b/src/positioning/positioning.pro @@ -46,7 +46,9 @@ PRIVATE_HEADERS += \ qdeclarativegeolocation_p.h \ qdoublevector2d_p.h \ qdoublevector3d_p.h \ - qgeoprojection_p.h + qgeoprojection_p.h \ + qpositioningglobal_p.h \ + qlocationdata_simulator_p.h SOURCES += \ qgeoaddress.cpp \ @@ -68,7 +70,8 @@ SOURCES += \ qdeclarativegeolocation.cpp \ qdoublevector2d.cpp \ qdoublevector3d.cpp \ - qgeoprojection.cpp + qgeoprojection.cpp \ + qlocationdata_simulator.cpp HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS diff --git a/src/positioning/qdeclarativegeoaddress_p.h b/src/positioning/qdeclarativegeoaddress_p.h index 7f51d555..c8210878 100644 --- a/src/positioning/qdeclarativegeoaddress_p.h +++ b/src/positioning/qdeclarativegeoaddress_p.h @@ -34,6 +34,17 @@ #ifndef QDECLARATIVEGEOADDRESS_P_H #define QDECLARATIVEGEOADDRESS_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtPositioning/QGeoAddress> diff --git a/src/positioning/qdeclarativegeolocation_p.h b/src/positioning/qdeclarativegeolocation_p.h index 832dac61..446dd1f0 100644 --- a/src/positioning/qdeclarativegeolocation_p.h +++ b/src/positioning/qdeclarativegeolocation_p.h @@ -34,6 +34,17 @@ #ifndef QDECLARATIVEGEOLOCATION_P_H #define QDECLARATIVEGEOLOCATION_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QObject> #include <QtPositioning/QGeoLocation> #include <QtPositioning/QGeoRectangle> diff --git a/src/positioning/qgeocoordinate.cpp b/src/positioning/qgeocoordinate.cpp index d061562b..36434eba 100644 --- a/src/positioning/qgeocoordinate.cpp +++ b/src/positioning/qgeocoordinate.cpp @@ -60,11 +60,11 @@ inline static double qgeocoordinate_radToDeg(double rad) } -QGeoCoordinatePrivate::QGeoCoordinatePrivate() { - lat = qQNaN(); - lng = qQNaN(); - alt = qQNaN(); -} +QGeoCoordinatePrivate::QGeoCoordinatePrivate(): + lat(qQNaN()), + lng(qQNaN()), + alt(qQNaN()) +{} QGeoCoordinatePrivate::QGeoCoordinatePrivate(const QGeoCoordinatePrivate &other) : QSharedData(other), @@ -77,6 +77,21 @@ QGeoCoordinatePrivate::~QGeoCoordinatePrivate() {} +QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate(): + QGeoCoordinatePrivate(), + m_mercatorX(qQNaN()), + m_mercatorY(qQNaN()) +{} + +QGeoMercatorCoordinatePrivate::QGeoMercatorCoordinatePrivate(const QGeoMercatorCoordinatePrivate &other) + : QGeoCoordinatePrivate(other), + m_mercatorX(other.m_mercatorX), + m_mercatorY(other.m_mercatorY) +{} + +QGeoMercatorCoordinatePrivate::~QGeoMercatorCoordinatePrivate() +{} + /*! \class QGeoCoordinate \inmodule QtPositioning @@ -666,6 +681,11 @@ QString QGeoCoordinate::toString(CoordinateFormat format) const return QString::fromLatin1("%1, %2, %3m").arg(latStr, longStr, QString::number(d->alt)); } +QGeoCoordinate::QGeoCoordinate(QGeoCoordinatePrivate &dd): + d(&dd) +{ +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QGeoCoordinate &coord) { diff --git a/src/positioning/qgeocoordinate.h b/src/positioning/qgeocoordinate.h index a1a636db..3c08bc04 100644 --- a/src/positioning/qgeocoordinate.h +++ b/src/positioning/qgeocoordinate.h @@ -104,9 +104,10 @@ public: Q_INVOKABLE QString toString(CoordinateFormat format = DegreesMinutesSecondsWithHemisphere) const; private: + QGeoCoordinate(QGeoCoordinatePrivate &dd); QSharedDataPointer<QGeoCoordinatePrivate> d; - friend class QGeoCoordinatePrivate; + friend class QQuickGeoCoordinateAnimation; }; Q_DECLARE_TYPEINFO(QGeoCoordinate, Q_MOVABLE_TYPE); diff --git a/src/positioning/qgeocoordinate_p.h b/src/positioning/qgeocoordinate_p.h index b9304b0c..c052d465 100644 --- a/src/positioning/qgeocoordinate_p.h +++ b/src/positioning/qgeocoordinate_p.h @@ -64,8 +64,23 @@ public: static void atDistanceAndAzimuth(const QGeoCoordinate &coord, qreal distance, qreal azimuth, double *lon, double *lat); + static const QGeoCoordinatePrivate *get(const QGeoCoordinate *c) { + return c->d.constData(); + } }; +class Q_POSITIONING_EXPORT QGeoMercatorCoordinatePrivate : public QGeoCoordinatePrivate +{ +public: + QGeoMercatorCoordinatePrivate(); + QGeoMercatorCoordinatePrivate(const QGeoMercatorCoordinatePrivate &other); + ~QGeoMercatorCoordinatePrivate(); + + double m_mercatorX; + double m_mercatorY; +}; + + QT_END_NAMESPACE #endif // QGEOCOORDINATE_P_H diff --git a/src/positioning/qgeolocation_p.h b/src/positioning/qgeolocation_p.h index cafcafea..62db53b3 100644 --- a/src/positioning/qgeolocation_p.h +++ b/src/positioning/qgeolocation_p.h @@ -34,6 +34,17 @@ #ifndef QGEOLOCATION_P_H #define QGEOLOCATION_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QSharedData> #include <QtPositioning/QGeoAddress> #include <QtPositioning/QGeoCoordinate> diff --git a/src/positioning/qgeopositioninfosource.cpp b/src/positioning/qgeopositioninfosource.cpp index 1cdd4116..0cec8eaa 100644 --- a/src/positioning/qgeopositioninfosource.cpp +++ b/src/positioning/qgeopositioninfosource.cpp @@ -158,6 +158,12 @@ void QGeoPositionInfoSourcePrivate::loadPluginMetadata(QHash<QString, QJsonObjec QList<QJsonObject> meta = l->metaData(); for (int i = 0; i < meta.size(); ++i) { QJsonObject obj = meta.at(i).value(QStringLiteral("MetaData")).toObject(); + const QString testableKey = QStringLiteral("Testable"); + if (obj.contains(testableKey) && !obj.value(testableKey).toBool()) { + static bool inTest = qEnvironmentVariableIsSet("QT_QTESTLIB_RUNNING"); + if (inTest) + continue; + } obj.insert(QStringLiteral("index"), i); plugins.insertMulti(obj.value(QStringLiteral("Provider")).toString(), obj); } diff --git a/src/positioning/qgeopositioninfosource_p.h b/src/positioning/qgeopositioninfosource_p.h index aedf3319..b11d6451 100644 --- a/src/positioning/qgeopositioninfosource_p.h +++ b/src/positioning/qgeopositioninfosource_p.h @@ -34,6 +34,17 @@ #ifndef QGEOPOSITIONINFOSOURCE_P_H #define QGEOPOSITIONINFOSOURCE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qgeopositioninfosource.h" #include "qgeopositioninfosourcefactory.h" #include <QJsonObject> diff --git a/src/positioning/qgeoprojection.cpp b/src/positioning/qgeoprojection.cpp index a2e087b0..ff708567 100644 --- a/src/positioning/qgeoprojection.cpp +++ b/src/positioning/qgeoprojection.cpp @@ -128,19 +128,4 @@ QGeoCoordinate QGeoProjection::coordinateInterpolation(const QGeoCoordinate &fro return result; } -QVariant geoCoordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress) -{ - if (from == to) { - if (progress < 0.5) { - return QVariant::fromValue(from); - } else { - return QVariant::fromValue(to); - } - } - - QGeoCoordinate result = QGeoProjection::coordinateInterpolation(from, to, progress); - - return QVariant::fromValue(result); -} - QT_END_NAMESPACE diff --git a/src/positioning/qgeoprojection_p.h b/src/positioning/qgeoprojection_p.h index f1b32525..fba8442a 100644 --- a/src/positioning/qgeoprojection_p.h +++ b/src/positioning/qgeoprojection_p.h @@ -57,10 +57,6 @@ QT_BEGIN_NAMESPACE class QGeoCoordinate; class QDoubleVector2D; -Q_POSITIONING_EXPORT QVariant geoCoordinateInterpolator(const QGeoCoordinate &from, - const QGeoCoordinate &to, - qreal progress); - class Q_POSITIONING_EXPORT QGeoProjection { public: diff --git a/src/positioning/qgeosatelliteinfosource.cpp b/src/positioning/qgeosatelliteinfosource.cpp index 06d6771d..da6eb8a0 100644 --- a/src/positioning/qgeosatelliteinfosource.cpp +++ b/src/positioning/qgeosatelliteinfosource.cpp @@ -167,6 +167,12 @@ QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(QObject *p if (obj.value(QStringLiteral("Satellite")).isBool() && obj.value(QStringLiteral("Satellite")).toBool()) { + const QString testableKey = QStringLiteral("Testable"); + if (obj.contains(testableKey) && !obj.value(testableKey).toBool()) { + static bool inTest = qEnvironmentVariableIsSet("QT_QTESTLIB_RUNNING"); + if (inTest) + continue; + } QGeoPositionInfoSourcePrivate d; d.metaData = obj; d.loadPlugin(); diff --git a/src/plugins/position/simulator/qlocationdata_simulator.cpp b/src/positioning/qlocationdata_simulator.cpp index b1ab808c..b1ab808c 100644 --- a/src/plugins/position/simulator/qlocationdata_simulator.cpp +++ b/src/positioning/qlocationdata_simulator.cpp diff --git a/src/plugins/position/simulator/qlocationdata_simulator_p.h b/src/positioning/qlocationdata_simulator_p.h index a847a80f..8848123d 100644 --- a/src/plugins/position/simulator/qlocationdata_simulator_p.h +++ b/src/positioning/qlocationdata_simulator_p.h @@ -45,13 +45,22 @@ // We mean it. // +// +// DO NOT REMOVE +// ------------- +// +// This header file contains structures used to serialize communication between +// simulator's client and server implementations, it is included by simulator +// positioning plugin. + +#include "qpositioningglobal_p.h" #include <QtCore/QMetaType> #include <QtCore/QDateTime> #include <QtCore/QList> QT_BEGIN_NAMESPACE -struct QGeoPositionInfoData +struct Q_POSITIONING_PRIVATE_EXPORT QGeoPositionInfoData { QGeoPositionInfoData(); @@ -76,7 +85,7 @@ struct QGeoPositionInfoData bool enabled; }; -struct QGeoSatelliteInfoData +struct Q_POSITIONING_PRIVATE_EXPORT QGeoSatelliteInfoData { struct SatelliteInfo { @@ -102,7 +111,13 @@ struct QGeoSatelliteInfoData QList<SatelliteInfo> satellites; }; -void qt_registerLocationTypes(); +Q_POSITIONING_PRIVATE_EXPORT void qt_registerLocationTypes(); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &out, const QGeoPositionInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &in, QGeoPositionInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &out, const QGeoSatelliteInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &in, QGeoSatelliteInfoData &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &out, const QGeoSatelliteInfoData::SatelliteInfo &s); +Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &in, QGeoSatelliteInfoData::SatelliteInfo &s); QT_END_NAMESPACE diff --git a/src/plugins/position/blackberry/bb/safeassign.h b/src/positioning/qpositioningglobal_p.h index 8797f7b7..04a5b18d 100644 --- a/src/plugins/position/blackberry/bb/safeassign.h +++ b/src/positioning/qpositioningglobal_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. +** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtPositioning module of the Qt Toolkit. @@ -30,20 +30,27 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef QPOSITIONINGGLOBAL_P_H +#define QPOSITIONINGGLOBAL_P_H -#ifndef BB_CORE_SAFEASSIGN_HPP -#define BB_CORE_SAFEASSIGN_HPP +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// -namespace bb -{ - template <typename T> - void safeAssign( T * pointer, const T & value ) - { - if ( pointer ) { - *pointer = value; - } - } -} // namespace bb +#include "qpositioningglobal.h" -#endif // HEADER GUARD +QT_BEGIN_NAMESPACE + +#define Q_POSITIONING_PRIVATE_EXPORT Q_POSITIONING_EXPORT + +QT_END_NAMESPACE + +#endif // QPOSITIONINGGLOBAL_P_H |