summaryrefslogtreecommitdiff
path: root/src/location/declarativemaps/qdeclarativegeomap.cpp
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2018-06-19 16:33:44 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2018-07-26 13:38:02 +0000
commiteca7cc8a260538fcccde97fe59d9580250600bf1 (patch)
tree6a87cc4391b1e0dbf65ee011d0314cfae4c8b19f /src/location/declarativemaps/qdeclarativegeomap.cpp
parentd6fc6ba0f84c4cda0ccc2e1250da4a68441dd6ba (diff)
downloadqtlocation-eca7cc8a260538fcccde97fe59d9580250600bf1.tar.gz
Introduce Map.visibleArea
This will allow moving the visible map area to a subregion of the viewport, allowing to maintain the desired visible region visible when overlaying controls on top of the map. Task-number: QTBUG-68966 Change-Id: Idf4b30f7c1e4062e5e1c0ddc01a31bc856c0bc0c Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/location/declarativemaps/qdeclarativegeomap.cpp')
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap.cpp107
1 files changed, 79 insertions, 28 deletions
diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp
index faa25916..d201b6ab 100644
--- a/src/location/declarativemaps/qdeclarativegeomap.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomap.cpp
@@ -333,6 +333,7 @@ void QDeclarativeGeoMap::initialize()
bool bearingHasChanged = false;
bool tiltHasChanged = false;
bool fovHasChanged = false;
+ bool visibleAreaHasChanged = false;
QGeoCoordinate center = m_cameraData.center();
@@ -354,6 +355,10 @@ void QDeclarativeGeoMap::initialize()
tiltHasChanged = true;
}
+ m_map->setVisibleArea(m_visibleArea);
+ if (m_map->visibleArea() != m_visibleArea)
+ visibleAreaHasChanged = true;
+
m_cameraData.setFieldOfView(qBound(m_cameraCapabilities.minimumFieldOfView(),
fov,
m_cameraCapabilities.maximumFieldOfView()));
@@ -362,8 +367,9 @@ void QDeclarativeGeoMap::initialize()
// set latitude boundary check
m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+ m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(m_cameraData);
- center.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
+ center.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
if (center != m_cameraData.center()) {
centerHasChanged = true;
@@ -389,6 +395,10 @@ void QDeclarativeGeoMap::initialize()
if (fovHasChanged)
emit fieldOfViewChanged(m_cameraData.fieldOfView());
+ if (visibleAreaHasChanged)
+ emit visibleAreaChanged();
+ connect(m_map, &QGeoMap::visibleAreaChanged, this, &QDeclarativeGeoMap::visibleAreaChanged);
+
emit mapReadyChanged(true);
if (m_copyrights) // To not update during initialize()
@@ -915,8 +925,9 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel, bool overzoom)
zoomLevel,
overzoom ? 30 : maximumZoomLevel()));
m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+ m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(m_cameraData);
QGeoCoordinate coord = m_cameraData.center();
- coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
+ coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
if (coord != m_cameraData.center()) {
centerHasChanged = true;
m_cameraData.setCenter(coord);
@@ -1231,7 +1242,7 @@ void QDeclarativeGeoMap::setCenter(const QGeoCoordinate &center)
if (m_initialized) {
QGeoCoordinate coord(center);
- coord.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
+ coord.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
m_cameraData.setCenter(coord);
m_map->setCameraData(m_cameraData);
} else {
@@ -1364,6 +1375,42 @@ QColor QDeclarativeGeoMap::color() const
}
/*!
+ \qmlproperty rect QtLocation::Map::visibleArea
+
+ This property holds the visible area inside the Map QML element.
+ It is a rect whose coordinates are relative to the Map element.
+ Its size will be clamped to the size of the Map element.
+ A null visibleArea means that the whole Map is visible.
+
+ \since 5.12
+*/
+QRectF QDeclarativeGeoMap::visibleArea() const
+{
+ if (m_initialized)
+ return m_map->visibleArea();
+ return m_visibleArea;
+}
+
+void QDeclarativeGeoMap::setVisibleArea(const QRectF &visibleArea)
+{
+ const QRectF oldVisibleArea = QDeclarativeGeoMap::visibleArea();
+ if (visibleArea == oldVisibleArea)
+ return;
+
+ if (!visibleArea.isValid() && !visibleArea.isEmpty()) // values < 0
+ return;
+
+ if (m_initialized) {
+ m_map->setVisibleArea(visibleArea);
+ } else {
+ m_visibleArea = visibleArea;
+ const QRectF newVisibleArea = QDeclarativeGeoMap::visibleArea();
+ if (newVisibleArea != oldVisibleArea)
+ emit visibleAreaChanged();
+ }
+}
+
+/*!
\qmlproperty bool QtLocation::Map::mapReady
This property holds whether the map has been successfully initialized and is ready to be used.
@@ -1378,6 +1425,17 @@ bool QDeclarativeGeoMap::mapReady() const
return m_initialized;
}
+QMargins QDeclarativeGeoMap::mapMargins() const
+{
+ const QRectF va = m_map->visibleArea();
+ if (va.isEmpty())
+ return QMargins();
+ return QMargins( va.x()
+ , va.y()
+ , width() - va.width() - va.x()
+ , height() - va.height() - va.y());
+}
+
// TODO: offer the possibility to specify the margins.
void QDeclarativeGeoMap::fitViewportToGeoShape()
{
@@ -1385,34 +1443,24 @@ void QDeclarativeGeoMap::fitViewportToGeoShape()
// This case remains handled here, and not inside QGeoMap*::fitViewportToGeoRectangle,
// in order to honor animations on center and zoomLevel
const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
- const int margins = 10;
- if (!m_map || !m_visibleRegion.isValid() || width() <= margins || height() <= margins)
- return;
+ const int borderSize = 10;
+ const QMargins borders(borderSize, borderSize, borderSize, borderSize);
- QDoubleVector2D topLeftPoint = p.geoToMapProjection(m_visibleRegion.topLeft());
- QDoubleVector2D bottomRightPoint = p.geoToMapProjection(m_visibleRegion.bottomRight());
- if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline
- bottomRightPoint.setX(bottomRightPoint.x() + 1.0);
+ if (!m_map || !m_visibleRegion.isValid())
+ return;
- // find center of the bounding box
- QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5;
- center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x());
- QGeoCoordinate centerCoordinate = p.mapProjectionToGeo(center);
+ const QMargins margins = borders + mapMargins();
+ const QPair<QGeoCoordinate, qreal> fitData = p.fitViewportToGeoRectangle(m_visibleRegion,
+ margins);
+ if (!fitData.first.isValid())
+ return;
// position camera to the center of bounding box
- setProperty("center", QVariant::fromValue(centerCoordinate)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property
-
- // if the shape is empty we just change center position, not zoom
- double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * m_map->mapWidth();
- double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * m_map->mapHeight();
+ setProperty("center", QVariant::fromValue(fitData.first)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property
- if (bboxHeight == 0.0 && bboxWidth == 0.0)
+ if (!qIsFinite(fitData.second))
return;
-
- double zoomRatio = qMax(bboxWidth / (width() - margins),
- bboxHeight / (height() - margins));
- zoomRatio = std::log(zoomRatio) / std::log(2.0);
- double newZoom = qMax<double>(minimumZoomLevel(), zoomLevel() - zoomRatio);
+ double newZoom = qMax<double>(minimumZoomLevel(), fitData.second);
setProperty("zoomLevel", QVariant::fromValue(newZoom)); // not using setZoomLevel(newZoom) to honor a possible animation set on the zoomLevel property
} else if (m_map->capabilities() & QGeoMap::SupportsFittingViewportToGeoRectangle) {
// Animations cannot be honored in this case, as m_map act as a black box
@@ -2067,11 +2115,14 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF
setMinimumZoomLevel(m_map->minimumZoom(), false);
// Update the center latitudinal threshold
- double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
- if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude) {
+ const double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+ const double minimumCenterLatitudeAtZoom = m_map->minimumCenterLatitudeAtZoom(m_cameraData);
+ if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude
+ || minimumCenterLatitudeAtZoom != m_minimumViewportLatitude) {
m_maximumViewportLatitude = maximumCenterLatitudeAtZoom;
+ m_minimumViewportLatitude = minimumCenterLatitudeAtZoom;
QGeoCoordinate coord = m_cameraData.center();
- coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
+ coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
if (coord != m_cameraData.center()) {
m_cameraData.setCenter(coord);