diff options
Diffstat (limited to 'src')
19 files changed, 226 insertions, 74 deletions
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp index 41ab3453..d404fd47 100644 --- a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp +++ b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp @@ -175,6 +175,9 @@ void QDeclarativeGeoMapItemView::createdItem(int index, QObject */*object*/) void QDeclarativeGeoMapItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) { + if (!m_map) // everything will be done in instantiateAllItems. Removal is done by declarativegeomap. + return; + // move changes are expressed as one remove + one insert, with the same moveId. // For simplicity, they will be treated as remove + insert. // Changes will be also ignored, as they represent only data changes, not layout changes diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp index b692bc76..f4cdc6bf 100644 --- a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp @@ -320,18 +320,9 @@ QDeclarativePolygonMapItem::QDeclarativePolygonMapItem(QQuickItem *parent) { setFlag(ItemHasContents, true); QObject::connect(&border_, SIGNAL(colorChanged(QColor)), - this, SLOT(handleBorderUpdated())); + this, SLOT(markSourceDirtyAndUpdate())); QObject::connect(&border_, SIGNAL(widthChanged(qreal)), - this, SLOT(handleBorderUpdated())); -} - -/*! - \internal -*/ -void QDeclarativePolygonMapItem::handleBorderUpdated() -{ - borderGeometry_.markSourceDirty(); - polishAndUpdate(); + this, SLOT(markSourceDirtyAndUpdate())); } QDeclarativePolygonMapItem::~QDeclarativePolygonMapItem() diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h b/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h index a68b6315..87d72307 100644 --- a/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h +++ b/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h @@ -120,7 +120,6 @@ protected: protected Q_SLOTS: void markSourceDirtyAndUpdate(); - void handleBorderUpdated(); virtual void afterViewportChanged(const QGeoMapViewportChangeEvent &event) override; private: diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp index b15dbc4d..88a766f5 100644 --- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp +++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp @@ -1087,6 +1087,7 @@ void QQuickGeoMapGestureArea::update() m_allPoints << m_touchPoints; if (m_allPoints.isEmpty() && !m_mousePoint.isNull()) m_allPoints << *m_mousePoint.data(); + std::sort(m_allPoints.begin(), m_allPoints.end(), [](const QTouchEvent::TouchPoint &tp1, const QTouchEvent::TouchPoint &tp2) { return tp1.id() < tp2.id(); }); touchPointStateMachine(); diff --git a/src/location/maps/qgeorouteparser.cpp b/src/location/maps/qgeorouteparser.cpp index 646902e0..51b839dd 100644 --- a/src/location/maps/qgeorouteparser.cpp +++ b/src/location/maps/qgeorouteparser.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE Private class implementations */ -QGeoRouteParserPrivate::QGeoRouteParserPrivate() : QObjectPrivate() +QGeoRouteParserPrivate::QGeoRouteParserPrivate() : QObjectPrivate(), trafficSide(QGeoRouteParser::RightHandTraffic) { } @@ -85,6 +85,20 @@ QUrl QGeoRouteParser::requestUrl(const QGeoRouteRequest &request, const QString return d->requestUrl(request, prefix); } +QGeoRouteParser::TrafficSide QGeoRouteParser::trafficSide() const +{ + Q_D(const QGeoRouteParser); + return d->trafficSide; +} + +void QGeoRouteParser::setTrafficSide(QGeoRouteParser::TrafficSide trafficSide) +{ + Q_D(QGeoRouteParser); + if (d->trafficSide == trafficSide) return; + d->trafficSide = trafficSide; + Q_EMIT trafficSideChanged(trafficSide); +} + QT_END_NAMESPACE diff --git a/src/location/maps/qgeorouteparser_p.h b/src/location/maps/qgeorouteparser_p.h index 33c3a4db..053dadb1 100644 --- a/src/location/maps/qgeorouteparser_p.h +++ b/src/location/maps/qgeorouteparser_p.h @@ -61,12 +61,25 @@ class Q_LOCATION_PRIVATE_EXPORT QGeoRouteParser : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QGeoRouteParser) - + Q_PROPERTY(TrafficSide trafficSide READ trafficSide WRITE setTrafficSide NOTIFY trafficSideChanged) + Q_ENUMS(TrafficSide) public: + enum TrafficSide { + RightHandTraffic, + LeftHandTraffic + }; virtual ~QGeoRouteParser(); QGeoRouteReply::Error parseReply(QList<QGeoRoute> &routes, QString &errorString, const QByteArray &reply) const; QUrl requestUrl(const QGeoRouteRequest &request, const QString &prefix) const; + TrafficSide trafficSide() const; + +public Q_SLOTS: + void setTrafficSide(TrafficSide trafficSide); + +Q_SIGNALS: + void trafficSideChanged(TrafficSide trafficSide); + protected: QGeoRouteParser(QGeoRouteParserPrivate &dd, QObject *parent = nullptr); diff --git a/src/location/maps/qgeorouteparser_p_p.h b/src/location/maps/qgeorouteparser_p_p.h index 63c773eb..c0080437 100644 --- a/src/location/maps/qgeorouteparser_p_p.h +++ b/src/location/maps/qgeorouteparser_p_p.h @@ -64,6 +64,8 @@ public: virtual QGeoRouteReply::Error parseReply(QList<QGeoRoute> &routes, QString &errorString, const QByteArray &reply) const = 0; virtual QUrl requestUrl(const QGeoRouteRequest &request, const QString &prefix) const = 0; + + QGeoRouteParser::TrafficSide trafficSide; }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeorouteparserosrmv4.cpp b/src/location/maps/qgeorouteparserosrmv4.cpp index bd36e7f3..24c920b0 100644 --- a/src/location/maps/qgeorouteparserosrmv4.cpp +++ b/src/location/maps/qgeorouteparserosrmv4.cpp @@ -86,7 +86,7 @@ static QList<QGeoCoordinate> parsePolyline(const QByteArray &data) return path; } -static QGeoManeuver::InstructionDirection osrmInstructionDirection(const QString &instructionCode) +static QGeoManeuver::InstructionDirection osrmInstructionDirection(const QString &instructionCode, QGeoRouteParser::TrafficSide trafficSide) { if (instructionCode == QLatin1String("0")) return QGeoManeuver::NoDirection; @@ -98,9 +98,15 @@ static QGeoManeuver::InstructionDirection osrmInstructionDirection(const QString return QGeoManeuver::DirectionRight; else if (instructionCode == QLatin1String("4")) return QGeoManeuver::DirectionHardRight; - else if (instructionCode == QLatin1String("5")) + else if (instructionCode == QLatin1String("5")) { + switch (trafficSide) { + case QGeoRouteParser::RightHandTraffic: + return QGeoManeuver::DirectionUTurnLeft; + case QGeoRouteParser::LeftHandTraffic: + return QGeoManeuver::DirectionUTurnRight; + } return QGeoManeuver::DirectionUTurnLeft; - else if (instructionCode == QLatin1String("6")) + } else if (instructionCode == QLatin1String("6")) return QGeoManeuver::DirectionHardLeft; else if (instructionCode == QLatin1String("7")) return QGeoManeuver::DirectionLeft; @@ -240,7 +246,7 @@ static QString osrmInstructionText(const QString &instructionCode, const QString } static QGeoRoute constructRoute(const QByteArray &geometry, const QJsonArray &instructions, - const QJsonObject &summary) + const QJsonObject &summary, QGeoRouteParser::TrafficSide trafficSide) { QGeoRoute route; @@ -272,7 +278,7 @@ static QGeoRoute constructRoute(const QByteArray &geometry, const QJsonArray &in segment.setDistance(segmentLength); QGeoManeuver maneuver; - maneuver.setDirection(osrmInstructionDirection(instructionCode)); + maneuver.setDirection(osrmInstructionDirection(instructionCode, trafficSide)); maneuver.setDistanceToNextInstruction(segmentLength); maneuver.setInstructionText(osrmInstructionText(instructionCode, wayname)); maneuver.setPosition(path.at(position)); @@ -349,7 +355,7 @@ QGeoRouteReply::Error QGeoRouteParserOsrmV4Private::parseReply(QList<QGeoRoute> QJsonArray routeInstructions = object.value(QStringLiteral("route_instructions")).toArray(); - QGeoRoute route = constructRoute(routeGeometry, routeInstructions, routeSummary); + QGeoRoute route = constructRoute(routeGeometry, routeInstructions, routeSummary, trafficSide); routes.append(route); @@ -365,7 +371,8 @@ QGeoRouteReply::Error QGeoRouteParserOsrmV4Private::parseReply(QList<QGeoRoute> for (int i = 0; i < alternativeSummaries.count(); ++i) { route = constructRoute(alternativeGeometries.at(i).toString().toLatin1(), alternativeInstructions.at(i).toArray(), - alternativeSummaries.at(i).toObject()); + alternativeSummaries.at(i).toObject(), + trafficSide); //routes.append(route); } } diff --git a/src/location/maps/qgeorouteparserosrmv5.cpp b/src/location/maps/qgeorouteparserosrmv5.cpp index 39910229..cc39158f 100644 --- a/src/location/maps/qgeorouteparserosrmv5.cpp +++ b/src/location/maps/qgeorouteparserosrmv5.cpp @@ -769,7 +769,7 @@ static QString instructionText(const QJsonObject &step, const QJsonObject &maneu return maneuverType + QLatin1String(" to/onto ") + wayName; } -static QGeoManeuver::InstructionDirection instructionDirection(const QJsonObject &maneuver) +static QGeoManeuver::InstructionDirection instructionDirection(const QJsonObject &maneuver, QGeoRouteParser::TrafficSide trafficSide) { QString modifier; if (maneuver.value(QLatin1String("modifier")).isString()) @@ -785,9 +785,15 @@ static QGeoManeuver::InstructionDirection instructionDirection(const QJsonObject return QGeoManeuver::DirectionHardRight; else if (modifier == QLatin1String("slight right")) return QGeoManeuver::DirectionLightRight; - else if (modifier == QLatin1String("uturn")) - return QGeoManeuver::DirectionUTurnLeft; // This should rather be country-specific. In UK, f.ex. one should rather UTurn Right - else if (modifier == QLatin1String("left")) + else if (modifier == QLatin1String("uturn")) { + switch (trafficSide) { + case QGeoRouteParser::RightHandTraffic: + return QGeoManeuver::DirectionUTurnLeft; + case QGeoRouteParser::LeftHandTraffic: + return QGeoManeuver::DirectionUTurnRight; + } + return QGeoManeuver::DirectionUTurnLeft; + } else if (modifier == QLatin1String("left")) return QGeoManeuver::DirectionLeft; else if (modifier == QLatin1String("sharp left")) return QGeoManeuver::DirectionHardLeft; @@ -855,7 +861,7 @@ QGeoRouteSegment QGeoRouteParserOsrmV5Private::parseStep(const QJsonObject &step QString geometry = step.value(QLatin1String("geometry")).toString(); QList<QGeoCoordinate> path = decodePolyline(geometry); - QGeoManeuver::InstructionDirection maneuverInstructionDirection = instructionDirection(maneuver); + QGeoManeuver::InstructionDirection maneuverInstructionDirection = instructionDirection(maneuver, trafficSide); QString maneuverInstructionText = instructionText(step, maneuver, maneuverInstructionDirection); diff --git a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp index e8db635f..29cf0167 100644 --- a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp +++ b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp @@ -238,7 +238,13 @@ QGeoRoutingManagerEngineMapbox::QGeoRoutingManagerEngineMapbox(const QVariantMap QGeoRouteParserOsrmV5 *parser = new QGeoRouteParserOsrmV5(this); parser->setExtension(new QGeoRouteParserOsrmV5ExtensionMapbox(m_accessToken, use_mapbox_text_instructions)); - + if (parameters.contains(QStringLiteral("mapbox.routing.traffic_side"))) { + QString trafficSide = parameters.value(QStringLiteral("mapbox.routing.traffic_side")).toString(); + if (trafficSide == QStringLiteral("right")) + parser->setTrafficSide(QGeoRouteParser::RightHandTraffic); + else if (trafficSide == QStringLiteral("left")) + parser->setTrafficSide(QGeoRouteParser::LeftHandTraffic); + } m_routeParser = parser; *error = QGeoServiceProvider::NoError; diff --git a/src/plugins/geoservices/mapbox/qplacesearchreplymapbox.cpp b/src/plugins/geoservices/mapbox/qplacesearchreplymapbox.cpp index a79af1cb..b2f2f043 100644 --- a/src/plugins/geoservices/mapbox/qplacesearchreplymapbox.cpp +++ b/src/plugins/geoservices/mapbox/qplacesearchreplymapbox.cpp @@ -188,19 +188,18 @@ void QPlaceSearchReplyMapbox::onReplyFinished() if (!categories.isEmpty()) { const QList<QPlaceCategory> placeCategories = placeResult.place().categories(); + bool categoryMatch = false; if (!placeCategories.isEmpty()) { - bool categoryMatch = false; for (const QPlaceCategory &placeCategory : placeCategories) { if (categories.contains(placeCategory)) { categoryMatch = true; break; } } - if (!categoryMatch) - continue; } + if (!categoryMatch) + continue; } - placeResult.setDistance(searchCenter.distanceTo(placeResult.place().location().coordinate())); results.append(placeResult); } diff --git a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp index 12db22a9..29a35aaa 100644 --- a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp +++ b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp @@ -67,6 +67,13 @@ QGeoRoutingManagerEngineOsm::QGeoRoutingManagerEngineOsm(const QVariantMap ¶ m_routeParser = new QGeoRouteParserOsrmV4(this); else m_routeParser = new QGeoRouteParserOsrmV5(this); + if (parameters.contains(QStringLiteral("osm.routing.traffic_side"))) { + QString trafficSide = parameters.value(QStringLiteral("mapbox.routing.traffic_side")).toString(); + if (trafficSide == QStringLiteral("right")) + m_routeParser->setTrafficSide(QGeoRouteParser::RightHandTraffic); + else if (trafficSide == QStringLiteral("left")) + m_routeParser->setTrafficSide(QGeoRouteParser::LeftHandTraffic); + } *error = QGeoServiceProvider::NoError; errorString->clear(); diff --git a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java index 1ea0c071..d819e627 100644 --- a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java +++ b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java @@ -114,7 +114,7 @@ public class QtPositioning implements LocationListener Log.w(TAG, "No locationManager available in QtPositioning"); return new int[0]; } - List<String> providers = locationManager.getAllProviders(); + List<String> providers = locationManager.getProviders(true); int retList[] = new int[providers.size()]; for (int i = 0; i < providers.size(); i++) { if (providers.get(i).equals(LocationManager.GPS_PROVIDER)) { @@ -521,10 +521,9 @@ public class QtPositioning implements LocationListener } } - - public static native void positionUpdated(Location update, int androidClassKey, boolean isSingleUpdate); public static native void locationProvidersDisabled(int androidClassKey); + public static native void locationProvidersChanged(int androidClassKey); public static native void satelliteUpdated(GpsSatellite[] update, int androidClassKey, boolean isSingleUpdate); @Override @@ -578,11 +577,13 @@ public class QtPositioning implements LocationListener @Override public void onProviderEnabled(String provider) { Log.d(TAG, "Enabled provider: " + provider); + locationProvidersChanged(nativeClassReference); } @Override public void onProviderDisabled(String provider) { Log.d(TAG, "Disabled provider: " + provider); + locationProvidersChanged(nativeClassReference); if (!expectedProvidersAvailable(expectedProviders)) locationProvidersDisabled(nativeClassReference); } diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp index 9bef8d36..0f358b42 100644 --- a/src/plugins/position/android/src/jnipositioning.cpp +++ b/src/plugins/position/android/src/jnipositioning.cpp @@ -51,8 +51,8 @@ #include "jnipositioning.h" -static JavaVM *javaVM = 0; -jclass positioningClass; +static JavaVM *javaVM = nullptr; +static jclass positioningClass; static jmethodID providerListMethodId; static jmethodID lastKnownPositionMethodId; @@ -78,10 +78,10 @@ namespace AndroidPositioning { AttachedJNIEnv() { attached = false; - if (javaVM && javaVM->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) { - if (javaVM->AttachCurrentThread(&jniEnv, NULL) < 0) { + if (javaVM && javaVM->GetEnv(reinterpret_cast<void**>(&jniEnv), JNI_VERSION_1_6) < 0) { + if (javaVM->AttachCurrentThread(&jniEnv, nullptr) < 0) { __android_log_print(ANDROID_LOG_ERROR, logTag, "AttachCurrentThread failed"); - jniEnv = 0; + jniEnv = nullptr; return; } attached = true; @@ -109,7 +109,7 @@ namespace AndroidPositioning { QGeoPositionInfoSourceAndroid *src = qobject_cast<QGeoPositionInfoSourceAndroid *>(obj); Q_ASSERT(src); do { - key = QRandomGenerator::global()->generate(); + key = qAbs(int(QRandomGenerator::global()->generate())); } while (idToPosSource()->contains(key)); idToPosSource()->insert(key, src); @@ -117,7 +117,7 @@ namespace AndroidPositioning { QGeoSatelliteInfoSourceAndroid *src = qobject_cast<QGeoSatelliteInfoSourceAndroid *>(obj); Q_ASSERT(src); do { - key = QRandomGenerator::global()->generate(); + key = qAbs(int(QRandomGenerator::global()->generate())); } while (idToSatSource()->contains(key)); idToSatSource()->insert(key, src); @@ -142,16 +142,15 @@ namespace AndroidPositioning { QGeoPositionInfoSource::PositioningMethods availableProviders() { - QGeoPositionInfoSource::PositioningMethods ret = - static_cast<QGeoPositionInfoSource::PositioningMethods>(0); + QGeoPositionInfoSource::PositioningMethods ret = QGeoPositionInfoSource::NoPositioningMethods; AttachedJNIEnv env; if (!env.jniEnv) return ret; jintArray jProviders = static_cast<jintArray>(env.jniEnv->CallStaticObjectMethod( positioningClass, providerListMethodId)); - jint *providers = env.jniEnv->GetIntArrayElements(jProviders, 0); - const uint size = env.jniEnv->GetArrayLength(jProviders); - for (uint i = 0; i < size; i++) { + jint *providers = env.jniEnv->GetIntArrayElements(jProviders, nullptr); + const int size = env.jniEnv->GetArrayLength(jProviders); + for (int i = 0; i < size; i++) { switch (providers[i]) { case PROVIDER_GPS: ret |= QGeoPositionInfoSource::SatellitePositioningMethods; @@ -182,17 +181,17 @@ namespace AndroidPositioning { const char *name, const char *sig) { - jmethodID id = 0; - int offset_name = qstrlen(name); - int offset_signal = qstrlen(sig); - QByteArray key(offset_name + offset_signal, Qt::Uninitialized); + jmethodID id = nullptr; + uint offset_name = qstrlen(name); + uint offset_signal = qstrlen(sig); + QByteArray key(int(offset_name + offset_signal), Qt::Uninitialized); memcpy(key.data(), name, offset_name); memcpy(key.data()+offset_name, sig, offset_signal); QHash<QByteArray, jmethodID>::iterator it = cachedMethodID->find(key); if (it == cachedMethodID->end()) { id = env->GetMethodID(clazz, name, sig); if (env->ExceptionCheck()) { - id = 0; + id = nullptr; #ifdef QT_DEBUG env->ExceptionDescribe(); #endif // QT_DEBUG @@ -235,22 +234,38 @@ namespace AndroidPositioning { jlong timestamp = jniEnv->CallLongMethod(location, mid); info.setTimestamp(QDateTime::fromMSecsSinceEpoch(timestamp, Qt::UTC)); - //accuracy + //horizontal accuracy mid = getCachedMethodID(jniEnv, thisClass, "hasAccuracy", "()Z"); attributeExists = jniEnv->CallBooleanMethod(location, mid); if (attributeExists) { mid = getCachedMethodID(jniEnv, thisClass, "getAccuracy", "()F"); jfloat accuracy = jniEnv->CallFloatMethod(location, mid); - info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy); + info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, qreal(accuracy)); } + //vertical accuracy + mid = getCachedMethodID(jniEnv, thisClass, "hasVerticalAccuracy", "()Z"); + if (mid) { + attributeExists = jniEnv->CallBooleanMethod(location, mid); + if (attributeExists) { + mid = getCachedMethodID(jniEnv, thisClass, "getVerticalAccuracyMeters", "()F"); + if (mid) { + jfloat accuracy = jniEnv->CallFloatMethod(location, mid); + info.setAttribute(QGeoPositionInfo::VerticalAccuracy, qreal(accuracy)); + } + } + } + + if (!mid) + jniEnv->ExceptionClear(); + //ground speed mid = getCachedMethodID(jniEnv, thisClass, "hasSpeed", "()Z"); attributeExists = jniEnv->CallBooleanMethod(location, mid); if (attributeExists) { mid = getCachedMethodID(jniEnv, thisClass, "getSpeed", "()F"); jfloat speed = jniEnv->CallFloatMethod(location, mid); - info.setAttribute(QGeoPositionInfo::GroundSpeed, speed); + info.setAttribute(QGeoPositionInfo::GroundSpeed, qreal(speed)); } //bearing @@ -259,7 +274,7 @@ namespace AndroidPositioning { if (attributeExists) { mid = getCachedMethodID(jniEnv, thisClass, "getBearing", "()F"); jfloat bearing = jniEnv->CallFloatMethod(location, mid); - info.setAttribute(QGeoPositionInfo::Direction, bearing); + info.setAttribute(QGeoPositionInfo::Direction, qreal(bearing)); } jniEnv->DeleteLocalRef(thisClass); @@ -288,7 +303,7 @@ namespace AndroidPositioning { //signal strength jmethodID mid = getCachedMethodID(jniEnv, thisClass, "getSnr", "()F"); jfloat snr = jniEnv->CallFloatMethod(element, mid); - info.setSignalStrength((int)snr); + info.setSignalStrength(int(snr)); //ignore any satellite with no signal whatsoever if (qFuzzyIsNull(snr)) @@ -307,12 +322,12 @@ namespace AndroidPositioning { //azimuth mid = getCachedMethodID(jniEnv, thisClass, "getAzimuth", "()F"); jfloat azimuth = jniEnv->CallFloatMethod(element, mid); - info.setAttribute(QGeoSatelliteInfo::Azimuth, azimuth); + info.setAttribute(QGeoSatelliteInfo::Azimuth, qreal(azimuth)); //elevation mid = getCachedMethodID(jniEnv, thisClass, "getElevation", "()F"); jfloat elevation = jniEnv->CallFloatMethod(element, mid); - info.setAttribute(QGeoSatelliteInfo::Elevation, elevation); + info.setAttribute(QGeoSatelliteInfo::Elevation, qreal(elevation)); //used in a fix mid = getCachedMethodID(jniEnv, thisClass, "usedInFix", "()Z"); @@ -339,7 +354,7 @@ namespace AndroidPositioning { jobject location = env.jniEnv->CallStaticObjectMethod(positioningClass, lastKnownPositionMethodId, fromSatellitePositioningMethodsOnly); - if (location == 0) + if (location == nullptr) return QGeoPositionInfo(); const QGeoPositionInfo info = positionInfoFromJavaLocation(env.jniEnv, location); @@ -513,6 +528,18 @@ static void locationProvidersDisabled(JNIEnv *env, jobject /*thiz*/, jint androi QMetaObject::invokeMethod(source, "locationProviderDisabled", Qt::AutoConnection); } +static void locationProvidersChanged(JNIEnv *env, jobject /*thiz*/, jint androidClassKey) +{ + Q_UNUSED(env); + QObject *source = AndroidPositioning::idToPosSource()->value(androidClassKey); + if (!source) { + qWarning("locationProvidersChanged: source == 0"); + return; + } + + QMetaObject::invokeMethod(source, "locationProvidersChanged", Qt::AutoConnection); +} + static void satelliteUpdated(JNIEnv *env, jobject /*thiz*/, jobjectArray satellites, jint androidClassKey, jboolean isSingleUpdate) { QList<QGeoSatelliteInfo> inUse; @@ -520,7 +547,7 @@ static void satelliteUpdated(JNIEnv *env, jobject /*thiz*/, jobjectArray satelli QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey); if (!source) { - qFatal("satelliteUpdated: source == 0"); + qWarning("satelliteUpdated: source == 0"); return; } @@ -549,7 +576,8 @@ if (!VAR) { \ static JNINativeMethod methods[] = { {"positionUpdated", "(Landroid/location/Location;IZ)V", (void *)positionUpdated}, {"locationProvidersDisabled", "(I)V", (void *) locationProvidersDisabled}, - {"satelliteUpdated", "([Landroid/location/GpsSatellite;IZ)V", (void *)satelliteUpdated} + {"satelliteUpdated", "([Landroid/location/GpsSatellite;IZ)V", (void *)satelliteUpdated}, + {"locationProvidersChanged", "(I)V", (void *) locationProvidersChanged} }; static bool registerNatives(JNIEnv *env) @@ -587,8 +615,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) __android_log_print(ANDROID_LOG_INFO, logTag, "Positioning start"); UnionJNIEnvToVoid uenv; - uenv.venv = NULL; - javaVM = 0; + uenv.venv = nullptr; + javaVM = nullptr; if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { __android_log_print(ANDROID_LOG_FATAL, logTag, "GetEnv failed"); diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android.cpp b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp index 59b8beab..38778ec4 100644 --- a/src/plugins/position/android/src/qgeopositioninfosource_android.cpp +++ b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp @@ -206,6 +206,11 @@ void QGeoPositionInfoSourceAndroid::locationProviderDisabled() setError(QGeoPositionInfoSource::ClosedError); } +void QGeoPositionInfoSourceAndroid::locationProvidersChanged() +{ + emit supportedPositioningMethodsChanged(); +} + void QGeoPositionInfoSourceAndroid::requestTimeout() { AndroidPositioning::stopUpdates(androidClassKeyForSingleRequest); diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android_p.h b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h index dbb27f83..61e107b1 100644 --- a/src/plugins/position/android/src/qgeopositioninfosource_android_p.h +++ b/src/plugins/position/android/src/qgeopositioninfosource_android_p.h @@ -79,6 +79,7 @@ public Q_SLOTS: void processSinglePositionUpdate(const QGeoPositionInfo& pInfo); void locationProviderDisabled(); + void locationProvidersChanged(); private Q_SLOTS: void requestTimeout(); diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp index 139a6b3d..b55d2ba3 100644 --- a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp +++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp @@ -179,7 +179,6 @@ int QGeoPositionInfoSourceWinRT::init() }); if (FAILED(hr)) { setError(QGeoPositionInfoSource::UnknownSourceError); - qErrnoWarning(hr, "Could not register status changed callback"); return -1; } @@ -342,15 +341,17 @@ bool QGeoPositionInfoSourceWinRT::startHandler() // registered. That could have helped in the single update case ComPtr<IAsyncOperation<Geoposition*>> op; hr = d->locator->GetGeopositionAsync(&op); + RETURN_HR_IF_FAILED("Could not start position operation"); hr = d->locator->add_PositionChanged(Callback<GeoLocatorPositionHandler>(this, &QGeoPositionInfoSourceWinRT::onPositionChanged).Get(), &d->positionToken); + RETURN_HR_IF_FAILED("Could not add position handler"); + return hr; }); if (FAILED(hr)) { setError(QGeoPositionInfoSource::UnknownSourceError); - qErrnoWarning(hr, "Could not add position handler"); return false; } diff --git a/src/positioning/qgeocoordinate.cpp b/src/positioning/qgeocoordinate.cpp index 80904d7c..f3d3ef9c 100644 --- a/src/positioning/qgeocoordinate.cpp +++ b/src/positioning/qgeocoordinate.cpp @@ -44,11 +44,28 @@ #include <QHash> #include <QDataStream> #include <QDebug> +#include <QMetaType> #include <qnumeric.h> #include <qmath.h> QT_BEGIN_NAMESPACE + +struct CoordinateStreamOperators +{ + CoordinateStreamOperators() + { +#ifndef QT_NO_DATASTREAM + qRegisterMetaTypeStreamOperators<QGeoCoordinate>(); +#endif +#ifndef QT_NO_DEBUG_STREAM + QMetaType::registerDebugStreamOperator<QGeoCoordinate>(); +#endif + } +}; +Q_GLOBAL_STATIC(CoordinateStreamOperators, initStreamOperators); + + static const double qgeocoordinate_EARTH_MEAN_RADIUS = 6371.0072; @@ -201,6 +218,9 @@ QGeoMercatorCoordinatePrivate::~QGeoMercatorCoordinatePrivate() QGeoCoordinate::QGeoCoordinate() : d(new QGeoCoordinatePrivate) { +#ifndef QT_NO_DATASTREAM + initStreamOperators(); +#endif } /*! @@ -215,6 +235,10 @@ QGeoCoordinate::QGeoCoordinate() QGeoCoordinate::QGeoCoordinate(double latitude, double longitude) : d(new QGeoCoordinatePrivate) { +#ifndef QT_NO_DATASTREAM + initStreamOperators(); +#endif + if (QLocationUtils::isValidLat(latitude) && QLocationUtils::isValidLong(longitude)) { d->lat = latitude; d->lng = longitude; @@ -236,6 +260,10 @@ QGeoCoordinate::QGeoCoordinate(double latitude, double longitude) QGeoCoordinate::QGeoCoordinate(double latitude, double longitude, double altitude) : d(new QGeoCoordinatePrivate) { +#ifndef QT_NO_DATASTREAM + initStreamOperators(); +#endif + if (QLocationUtils::isValidLat(latitude) && QLocationUtils::isValidLong(longitude)) { d->lat = latitude; d->lng = longitude; diff --git a/src/positioning/qgeopositioninfosource.cpp b/src/positioning/qgeopositioninfosource.cpp index cafb4f8a..2e126175 100644 --- a/src/positioning/qgeopositioninfosource.cpp +++ b/src/positioning/qgeopositioninfosource.cpp @@ -241,8 +241,10 @@ int QGeoPositionInfoSource::updateInterval() const If \a methods includes a method that is not supported by the source, the unsupported method will be ignored. - If \a methods does not include any methods supported by the source, the - preferred methods will be set to the set of methods which the source supports. + If \a methods does not include a single method available/supported by the source, the + preferred methods will be set to the set of methods which the source has available. + If the source has no method availabe (e.g. because its Location service is turned off + or it does not offer a Location service), the passed \a methods are accepted as they are. \b {Note:} When reimplementing this method, subclasses must call the base method implementation to ensure preferredPositioningMethods() returns the correct value. @@ -251,9 +253,13 @@ int QGeoPositionInfoSource::updateInterval() const */ void QGeoPositionInfoSource::setPreferredPositioningMethods(PositioningMethods methods) { - d->methods = methods & supportedPositioningMethods(); - if (d->methods == 0) { - d->methods = supportedPositioningMethods(); + if (supportedPositioningMethods() != QGeoPositionInfoSource::NoPositioningMethods) { + d->methods = methods & supportedPositioningMethods(); + if (d->methods == 0) { + d->methods = supportedPositioningMethods(); + } + } else { // avoid that turned of Location service blocks any changes to d->methods + d->methods = methods; } } @@ -355,9 +361,40 @@ QStringList QGeoPositionInfoSource::availableSources() /*! \fn virtual PositioningMethods QGeoPositionInfoSource::supportedPositioningMethods() const = 0; - Returns the positioning methods available to this source. - - \sa setPreferredPositioningMethods() + Returns the positioning methods available to this source. Availability is defined as being usable + at the time of calling this function. Therefore user settings like turned off location service or + limitations to Satellite-based position providers are reflected by this function. Runtime notifications + when the status changes can be obtained via \l supportedPositioningMethodsChanged(). + + Not all platforms distinguish the different positioning methods or communicate the current user + configuration of the device. The following table provides an overview of the current platform situation: + + \table + \header + \li Platform + \li Brief Description + \row + \li Android + \li Individual provider status and general Location service state are known and communicated + when location service is active. + \row + \li GeoClue + \li Hardcoced to always return AllPositioningMethods. + \row + \li GeoClue2 + \li Individual providers are not distinguishable but disabled Location services reflected. + \row + \li iOS/tvOS + \li Hardcoced to always return AllPositioningMethods. + \row + \li macOS + \li Hardcoced to always return AllPositioningMethods. + \row + \li Windows (UWP) + \li Individual providers are not distinguishable but disabled Location services reflected. + \endtable + + \sa supportedPositioningMethodsChanged(), setPreferredPositioningMethods() */ @@ -479,7 +516,10 @@ QStringList QGeoPositionInfoSource::availableSources() /*! \fn void QGeoPositionInfoSource::supportedPositioningMethodsChanged() - This signal is emitted after the supportedPositioningMethods change. + This signal is emitted when the supported positioning methods changed. The cause for a change could be + a user turning Location services on/off or restricting Location services to certain types (e.g. GPS only). + Note that changes to the supported positioning methods cannot be detected on all platforms. + \l supportedPositioningMethods() provides an overview of the current platform support. \since Qt 5.12 */ |