summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-02-08 03:07:36 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2020-02-08 03:07:36 +0100
commit4cfed13377ababcfaa7dacb055bcd3dd0f2cf7d4 (patch)
treead28212aacfd9b127c7e46fba13ab0431b66e288
parentc91ad6b13417a1a77e092ede6dee6f40cee6d535 (diff)
parent614d67be158e3ef8443c1b7f3126303cfcf4becc (diff)
downloadqtlocation-4cfed13377ababcfaa7dacb055bcd3dd0f2cf7d4.tar.gz
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: If5c3274ecf7e19b55ca54db21405d2908d8b14ae
-rw-r--r--dist/changes-5.14.120
-rw-r--r--src/plugins/position/android/src/jnipositioning.cpp60
-rw-r--r--src/plugins/position/android/src/jnipositioning.h2
-rw-r--r--src/positioning/positioning.pro4
-rw-r--r--src/positioning/qgeopath.cpp24
-rw-r--r--src/positioning/qgeopath_p.h1
-rw-r--r--src/positioning/qgeopolygon.cpp78
-rw-r--r--tests/auto/declarative_geoshape/tst_locationsingleton.qml4
8 files changed, 139 insertions, 54 deletions
diff --git a/dist/changes-5.14.1 b/dist/changes-5.14.1
new file mode 100644
index 00000000..d0086381
--- /dev/null
+++ b/dist/changes-5.14.1
@@ -0,0 +1,20 @@
+Qt 5.14.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.14.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.14 series is binary compatible with the 5.13.x series.
+Applications compiled for 5.13 will continue to run with 5.14.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+ - This release contains only minor code improvements.
diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp
index 4812e307..05b25d98 100644
--- a/src/plugins/position/android/src/jnipositioning.cpp
+++ b/src/plugins/position/android/src/jnipositioning.cpp
@@ -44,7 +44,6 @@
#include <QtGlobal>
#include <QtCore/private/qjnihelpers_p.h>
#include <android/log.h>
-#include <jni.h>
#include <QGeoPositionInfo>
#include "qgeopositioninfosource_android_p.h"
#include "qgeosatelliteinfosource_android_p.h"
@@ -351,6 +350,9 @@ namespace AndroidPositioning {
if (!env.jniEnv)
return QGeoPositionInfo();
+ if (!requestionPositioningPermissions(env.jniEnv))
+ return {};
+
jobject location = env.jniEnv->CallStaticObjectMethod(positioningClass,
lastKnownPositionMethodId,
fromSatellitePositioningMethodsOnly);
@@ -383,19 +385,8 @@ namespace AndroidPositioning {
QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
if (source) {
- // Android v23+ requires runtime permission check and requests
- QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION"));
-
- if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) {
- const QHash<QString, QtAndroidPrivate::PermissionsResult> results =
- QtAndroidPrivate::requestPermissionsSync(env.jniEnv, QStringList() << permission);
- if (!results.contains(permission)
- || results[permission] == QtAndroidPrivate::PermissionsResult::Denied)
- {
- qWarning() << "Position retrieval not possible due to missing permission (ACCESS_FINE_LOCATION)";
- return QGeoPositionInfoSource::AccessError;
- }
- }
+ if (!requestionPositioningPermissions(env.jniEnv))
+ return QGeoPositionInfoSource::AccessError;
int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startUpdatesMethodId,
androidClassKey,
@@ -434,19 +425,8 @@ namespace AndroidPositioning {
QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
if (source) {
- // Android v23+ requires runtime permission check and requests
- QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION"));
-
- if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) {
- const QHash<QString, QtAndroidPrivate::PermissionsResult> results =
- QtAndroidPrivate::requestPermissionsSync(env.jniEnv, QStringList() << permission);
- if (!results.contains(permission)
- || results[permission] == QtAndroidPrivate::PermissionsResult::Denied)
- {
- qWarning() << "Position update not possible due to missing permission (ACCESS_FINE_LOCATION)";
- return QGeoPositionInfoSource::AccessError;
- }
- }
+ if (!requestionPositioningPermissions(env.jniEnv))
+ return QGeoPositionInfoSource::AccessError;
int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, requestUpdateMethodId,
androidClassKey,
@@ -473,6 +453,9 @@ namespace AndroidPositioning {
QGeoSatelliteInfoSourceAndroid *source = AndroidPositioning::idToSatSource()->value(androidClassKey);
if (source) {
+ if (!requestionPositioningPermissions(env.jniEnv))
+ return QGeoSatelliteInfoSource::AccessError;
+
int interval = source->updateInterval();
if (isSingleRequest)
interval = requestTimeout;
@@ -492,8 +475,29 @@ namespace AndroidPositioning {
}
return QGeoSatelliteInfoSource::UnknownSourceError;
}
-}
+ bool requestionPositioningPermissions(JNIEnv *env)
+ {
+ using namespace QtAndroidPrivate;
+
+ if (androidSdkVersion() < 23)
+ return true;
+
+ // Android v23+ requires runtime permission check and requests
+ QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION"));
+
+ if (checkPermission(permission) == PermissionsResult::Denied) {
+ const QHash<QString, PermissionsResult> results =
+ requestPermissionsSync(env, QStringList() << permission);
+ if (!results.contains(permission) || results[permission] == PermissionsResult::Denied) {
+ qWarning() << "Position data not available due to missing permission " << permission;
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
static void positionUpdated(JNIEnv *env, jobject /*thiz*/, jobject location, jint androidClassKey, jboolean isSingleUpdate)
{
diff --git a/src/plugins/position/android/src/jnipositioning.h b/src/plugins/position/android/src/jnipositioning.h
index 0de6a5aa..0c051b8c 100644
--- a/src/plugins/position/android/src/jnipositioning.h
+++ b/src/plugins/position/android/src/jnipositioning.h
@@ -40,6 +40,7 @@
#ifndef JNIPOSITIONING_H
#define JNIPOSITIONING_H
+#include <jni.h>
#include <QGeoPositionInfoSource>
#include <QGeoSatelliteInfoSource>
@@ -58,6 +59,7 @@ namespace AndroidPositioning
QGeoSatelliteInfoSource::Error startSatelliteUpdates(int androidClassKey,
bool isSingleRequest,
int updateRequestTimeout);
+ bool requestionPositioningPermissions(JNIEnv *env);
}
#endif // JNIPOSITIONING_H
diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro
index 06e2d531..65350909 100644
--- a/src/positioning/positioning.pro
+++ b/src/positioning/positioning.pro
@@ -11,8 +11,10 @@ OTHER_FILES += configure.json doc/src/*.qdoc doc/src/plugins/*.qdoc # show .qd
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
jar/QtPositioning.jar:org.qtproject.qt5.android.positioning.QtPositioning
-ANDROID_PERMISSIONS = \
+ANDROID_PERMISSIONS += \
android.permission.ACCESS_FINE_LOCATION
+ANDROID_FEATURES += \
+ android.hardware.location.gps
ANDROID_LIB_DEPENDENCIES = \
plugins/position/libplugins_position_qtposition_android.so
MODULE_WINRT_CAPABILITIES_DEVICE += \
diff --git a/src/positioning/qgeopath.cpp b/src/positioning/qgeopath.cpp
index 1225d7c8..b6513bc7 100644
--- a/src/positioning/qgeopath.cpp
+++ b/src/positioning/qgeopath.cpp
@@ -475,6 +475,9 @@ bool QGeoPathPrivate::lineContains(const QGeoCoordinate &coordinate) const
// If the mercator x value of a coordinate of the line, or the coordinate parameter, is less
// than mercator(m_bbox).x, add that to the conversion.
+ if (m_bboxDirty)
+ const_cast<QGeoPathPrivate &>(*this).computeBoundingBox();
+
double lineRadius = qMax(width() * 0.5, 0.2); // minimum radius: 20cm
if (!m_path.size())
@@ -482,23 +485,21 @@ bool QGeoPathPrivate::lineContains(const QGeoCoordinate &coordinate) const
else if (m_path.size() == 1)
return (m_path[0].distanceTo(coordinate) <= lineRadius);
- double leftBoundMercator = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
-
QDoubleVector2D p = QWebMercator::coordToMercator(coordinate);
- if (p.x() < leftBoundMercator)
- p.setX(p.x() + leftBoundMercator); // unwrap X
+ if (p.x() < m_leftBoundWrapped)
+ p.setX(p.x() + m_leftBoundWrapped); // unwrap X
QDoubleVector2D a;
QDoubleVector2D b;
if (m_path.size()) {
a = QWebMercator::coordToMercator(m_path[0]);
- if (a.x() < leftBoundMercator)
- a.setX(a.x() + leftBoundMercator); // unwrap X
+ if (a.x() < m_leftBoundWrapped)
+ a.setX(a.x() + m_leftBoundWrapped); // unwrap X
}
for (int i = 1; i < m_path.size(); i++) {
b = QWebMercator::coordToMercator(m_path[i]);
- if (b.x() < leftBoundMercator)
- b.setX(b.x() + leftBoundMercator); // unwrap X
+ if (b.x() < m_leftBoundWrapped)
+ b.setX(b.x() + m_leftBoundWrapped); // unwrap X
if (b == a)
continue;
@@ -513,7 +514,7 @@ bool QGeoPathPrivate::lineContains(const QGeoCoordinate &coordinate) const
if (candidate.x() > 1.0)
- candidate.setX(candidate.x() - leftBoundMercator); // wrap X
+ candidate.setX(candidate.x() - m_leftBoundWrapped); // wrap X
QGeoCoordinate closest = QWebMercator::mercatorToCoord(candidate);
@@ -600,6 +601,7 @@ void QGeoPathPrivate::translate(double degreesLatitude, double degreesLongitude)
p.setLongitude(QLocationUtils::wrapLong(p.longitude() + degreesLongitude));
}
m_bbox.translate(degreesLatitude, degreesLongitude);
+ m_leftBoundWrapped = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
}
QGeoRectangle QGeoPathPrivate::boundingGeoRectangle() const
@@ -673,6 +675,7 @@ void QGeoPathPrivate::computeBoundingBox()
double m_minX, m_maxX, m_minLati, m_maxLati;
m_bboxDirty = false;
computeBBox(m_path, m_deltaXs, m_minX, m_maxX, m_minLati, m_maxLati, m_bbox);
+ m_leftBoundWrapped = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
}
QGeoPathPrivateEager::QGeoPathPrivateEager()
@@ -715,6 +718,7 @@ void QGeoPathPrivateEager::translate(double degreesLatitude, double degreesLongi
m_bbox.translate(degreesLatitude, degreesLongitude);
m_minLati += degreesLatitude;
m_maxLati += degreesLatitude;
+ m_leftBoundWrapped = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
}
void QGeoPathPrivateEager::addCoordinate(const QGeoCoordinate &coordinate)
@@ -729,11 +733,13 @@ void QGeoPathPrivateEager::addCoordinate(const QGeoCoordinate &coordinate)
void QGeoPathPrivateEager::QGeoPathPrivateEager::computeBoundingBox()
{
computeBBox(m_path, m_deltaXs, m_minX, m_maxX, m_minLati, m_maxLati, m_bbox);
+ m_leftBoundWrapped = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
}
void QGeoPathPrivateEager::QGeoPathPrivateEager::updateBoundingBox()
{
updateBBox(m_path, m_deltaXs, m_minX, m_maxX, m_minLati, m_maxLati, m_bbox);
+ m_leftBoundWrapped = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
}
QGeoPathEager::QGeoPathEager() : QGeoPath()
diff --git a/src/positioning/qgeopath_p.h b/src/positioning/qgeopath_p.h
index be73994f..6dd17b09 100644
--- a/src/positioning/qgeopath_p.h
+++ b/src/positioning/qgeopath_p.h
@@ -220,6 +220,7 @@ public:
QList<QGeoCoordinate> m_path;
qreal m_width = 0;
QGeoRectangle m_bbox; // cached
+ double m_leftBoundWrapped; // cached
bool m_bboxDirty = false;
};
diff --git a/src/positioning/qgeopolygon.cpp b/src/positioning/qgeopolygon.cpp
index e8fdda76..301759df 100644
--- a/src/positioning/qgeopolygon.cpp
+++ b/src/positioning/qgeopolygon.cpp
@@ -39,6 +39,8 @@
#include "qgeopolygon.h"
#include "qgeopolygon_p.h"
+#include "qgeopath_p.h"
+#include "qgeocircle.h"
#include "qgeocoordinate.h"
#include "qnumeric.h"
@@ -135,6 +137,41 @@ QGeoPolygon::QGeoPolygon(const QGeoPolygon &other)
initPolygonConversions();
}
+static void calculatePeripheralPoints(QList<QGeoCoordinate> &path,
+ const QGeoCircle &circle,
+ int steps)
+{
+ const QGeoCoordinate &center = circle.center();
+ const qreal distance = circle.radius();
+ // Calculate points based on great-circle distance
+ // Calculation is the same as GeoCoordinate's atDistanceAndAzimuth function
+ // but tweaked here for computing multiple points
+
+ // pre-calculations
+ steps = qMax(steps, 3);
+ qreal centerLon = center.longitude();
+ qreal latRad = QLocationUtils::radians(center.latitude());
+ qreal lonRad = QLocationUtils::radians(centerLon);
+ qreal cosLatRad = std::cos(latRad);
+ qreal sinLatRad = std::sin(latRad);
+ qreal ratio = (distance / QLocationUtils::earthMeanRadius());
+ qreal cosRatio = std::cos(ratio);
+ qreal sinRatio = std::sin(ratio);
+ qreal sinLatRad_x_cosRatio = sinLatRad * cosRatio;
+ qreal cosLatRad_x_sinRatio = cosLatRad * sinRatio;
+ for (int i = 0; i < steps; ++i) {
+ qreal azimuthRad = 2 * M_PI * i / steps;
+ qreal resultLatRad = std::asin(sinLatRad_x_cosRatio
+ + cosLatRad_x_sinRatio * std::cos(azimuthRad));
+ qreal resultLonRad = lonRad + std::atan2(std::sin(azimuthRad) * cosLatRad_x_sinRatio,
+ cosRatio - sinLatRad * std::sin(resultLatRad));
+ qreal lat2 = QLocationUtils::degrees(resultLatRad);
+ qreal lon2 = QLocationUtils::wrapLong(QLocationUtils::degrees(resultLonRad));
+
+ path << QGeoCoordinate(lat2, lon2, center.altitude());
+ }
+}
+
/*!
Constructs a new geo polygon from the contents of \a other.
*/
@@ -142,8 +179,22 @@ QGeoPolygon::QGeoPolygon(const QGeoShape &other)
: QGeoShape(other)
{
initPolygonConversions();
- if (type() != QGeoShape::PolygonType)
- d_ptr = new QGeoPolygonPrivate();
+ if (type() != QGeoShape::PolygonType) {
+ QGeoPolygonPrivate *poly = new QGeoPolygonPrivate();
+ if (type() == QGeoShape::CircleType) {
+ const QGeoCircle &circle = static_cast<const QGeoCircle &>(other);
+ QList<QGeoCoordinate> perimeter;
+ calculatePeripheralPoints(perimeter, circle, 128);
+ poly->setPath(perimeter);
+ } else if (type() == QGeoShape::RectangleType) {
+ const QGeoRectangle &rect = static_cast<const QGeoRectangle &>(other);
+ QList<QGeoCoordinate> perimeter;
+ perimeter << rect.topLeft() << rect.topRight()
+ << rect.bottomRight() << rect.bottomLeft();
+ poly->setPath(perimeter);
+ }
+ d_ptr = poly;
+ }
}
/*!
@@ -504,10 +555,11 @@ void QGeoPolygonPrivate::translate(double degreesLatitude, double degreesLongitu
// Need min/maxLati, so update bbox
QVector<double> m_deltaXs;
double m_minX, m_maxX, m_minLati, m_maxLati;
- m_bboxDirty = false;
+ m_bboxDirty = false; // Updated in translatePoly
computeBBox(m_path, m_deltaXs, m_minX, m_maxX, m_minLati, m_maxLati, m_bbox);
-
translatePoly(m_path, m_holesList, m_bbox, degreesLatitude, degreesLongitude, m_maxLati, m_minLati);
+ m_leftBoundWrapped = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
+ m_clipperDirty = true;
}
bool QGeoPolygonPrivate::operator==(const QGeoShapePrivate &other) const
@@ -557,10 +609,11 @@ bool QGeoPolygonPrivate::polygonContains(const QGeoCoordinate &coordinate) const
const_cast<QGeoPolygonPrivate *>(this)->updateClipperPath(); // this one updates bbox too if needed
QDoubleVector2D coord = QWebMercator::coordToMercator(coordinate);
- double tlx = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
- if (coord.x() < tlx)
+
+ if (coord.x() < m_leftBoundWrapped)
coord.setX(coord.x() + 1.0);
+
IntPoint intCoord = QClipperUtils::toIntPoint(coord);
if (!c2t::clip2tri::pointInPolygon(intCoord, m_clipperPath))
return false;
@@ -570,12 +623,7 @@ bool QGeoPolygonPrivate::polygonContains(const QGeoCoordinate &coordinate) const
// ToDo: cache these
QGeoPolygon holePolygon;
holePolygon.setPath(holePath);
- // QGeoPath holeBoundary;
- // holeBoundary.setPath(holePath);
-
- if (holePolygon.contains(coordinate)
- // && !(holeBoundary.contains(coordinate))
- )
+ if (holePolygon.contains(coordinate))
return false;
}
return true;
@@ -591,11 +639,11 @@ void QGeoPolygonPrivate::updateClipperPath()
if (m_bboxDirty)
computeBoundingBox();
m_clipperDirty = false;
- double tlx = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
+
QList<QDoubleVector2D> preservedPath;
for (const QGeoCoordinate &c : m_path) {
QDoubleVector2D crd = QWebMercator::coordToMercator(c);
- if (crd.x() < tlx)
+ if (crd.x() < m_leftBoundWrapped)
crd.setX(crd.x() + 1.0);
preservedPath << crd;
}
@@ -625,6 +673,7 @@ QGeoShapePrivate *QGeoPolygonPrivateEager::clone() const
void QGeoPolygonPrivateEager::translate(double degreesLatitude, double degreesLongitude)
{
translatePoly(m_path, m_holesList, m_bbox, degreesLatitude, degreesLongitude, m_maxLati, m_minLati);
+ m_clipperDirty = true;
}
void QGeoPolygonPrivateEager::markDirty()
@@ -645,6 +694,7 @@ void QGeoPolygonPrivateEager::addCoordinate(const QGeoCoordinate &coordinate)
void QGeoPolygonPrivateEager::computeBoundingBox()
{
computeBBox(m_path, m_deltaXs, m_minX, m_maxX, m_minLati, m_maxLati, m_bbox);
+ m_leftBoundWrapped = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
}
void QGeoPolygonPrivateEager::updateBoundingBox()
diff --git a/tests/auto/declarative_geoshape/tst_locationsingleton.qml b/tests/auto/declarative_geoshape/tst_locationsingleton.qml
index 096a72e9..b58eedfd 100644
--- a/tests/auto/declarative_geoshape/tst_locationsingleton.qml
+++ b/tests/auto/declarative_geoshape/tst_locationsingleton.qml
@@ -222,11 +222,11 @@ Item {
polygon = QtPositioning.shapeToPolygon(QtPositioning.circle())
verify(!polygon.isValid)
polygon = QtPositioning.shapeToPolygon(QtPositioning.circle(tl, 10000))
- verify(!polygon.isValid)
+ verify(polygon.isValid) // fixed, polygon copy constructor can now initialize from a circle.
polygon = QtPositioning.shapeToPolygon(QtPositioning.rectangle())
verify(!polygon.isValid)
polygon = QtPositioning.shapeToPolygon(QtPositioning.rectangle(tl, br))
- verify(!polygon.isValid)
+ verify(polygon.isValid) // fixed, polygon copy constructor can now initialize from a rectangle.
polygon = QtPositioning.shapeToPolygon(QtPositioning.polygon())
verify(!polygon.isValid)