summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@theqtcompany.com>2015-05-20 09:32:41 +0200
committerAlex Blasche <alexander.blasche@theqtcompany.com>2015-05-26 13:23:38 +0000
commita78198c12374724857f33fd8c7771984d4b7ae4e (patch)
tree4aca4a07d381be3537eb2063997da26dbd3e8070
parentbeadca0d5377136c18abdf8efabe47cf396598ff (diff)
downloadqtlocation-a78198c12374724857f33fd8c7771984d4b7ae4e.tar.gz
Add visible region support to Map
Change-Id: I340f1ad3a623a04a1846c5a57ad2bbcb9e253556 Reviewed-by: Michal Klocek <michal.klocek@theqtcompany.com> Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
-rw-r--r--examples/location/planespotter/planespotter.qml10
-rw-r--r--src/imports/location/qdeclarativegeomap.cpp128
-rw-r--r--src/imports/location/qdeclarativegeomap_p.h12
3 files changed, 136 insertions, 14 deletions
diff --git a/examples/location/planespotter/planespotter.qml b/examples/location/planespotter/planespotter.qml
index 59b8b00b..91d9e056 100644
--- a/examples/location/planespotter/planespotter.qml
+++ b/examples/location/planespotter/planespotter.qml
@@ -185,15 +185,7 @@ Window {
}
//! [CppPlane2]
- onWidthChanged: {
- if (width > 0)
- mapOfEurope.fitViewportToGeoShape(viewOfEurope)
- }
-
- onHeightChanged: {
- if (height > 0)
- mapOfEurope.fitViewportToGeoShape(viewOfEurope)
- }
+ visibleRegion: viewOfEurope
}
Rectangle {
diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp
index 3924a476..a8cdd25d 100644
--- a/src/imports/location/qdeclarativegeomap.cpp
+++ b/src/imports/location/qdeclarativegeomap.cpp
@@ -180,7 +180,8 @@ QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent)
m_error(QGeoServiceProvider::NoError),
m_zoomLevel(8.0),
m_componentCompleted(false),
- m_mappingManagerInitialized(false)
+ m_mappingManagerInitialized(false),
+ m_pendingFitViewport(false)
{
setAcceptHoverEvents(false);
setAcceptedMouseButtons(Qt::LeftButton);
@@ -692,6 +693,113 @@ QGeoCoordinate QDeclarativeGeoMap::center() const
return m_center;
}
+
+/*!
+ \qmlproperty geoshape QtLocation::Map::visibleRegion
+
+ This property holds the region which occupies the viewport of
+ the map. 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 the screen. This implies that
+ reading this property back shortly after having been set the
+ returned area is equal or larger than the set area.
+
+ Setting this property implicitly changes the \l center and
+ \l zoomLevel of the map. Any previously set value to those
+ properties will be overridden.
+
+ This property does not provide any change notifications.
+
+ \since 5.5
+*/
+void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape)
+{
+ if (shape == m_region)
+ return;
+
+ m_region = shape;
+ if (!shape.isValid()) {
+ // shape invalidated -> nothing to fit anymore
+ m_pendingFitViewport = false;
+ return;
+ }
+
+ if (!width() || !height()) {
+ m_pendingFitViewport = true;
+ return;
+ }
+
+ fitViewportToGeoShape();
+}
+
+QGeoShape QDeclarativeGeoMap::visibleRegion() const
+{
+ if (!width() || !height())
+ return QGeoShape();
+
+ QGeoCoordinate tl = m_map->itemPositionToCoordinate(QDoubleVector2D(0, 0));
+ QGeoCoordinate br = m_map->itemPositionToCoordinate(QDoubleVector2D(width(), height()));
+
+ return QGeoRectangle(tl, br);
+}
+
+void QDeclarativeGeoMap::fitViewportToGeoShape()
+{
+ double bboxWidth;
+ double bboxHeight;
+ QGeoCoordinate centerCoordinate;
+
+ switch (m_region.type()) {
+ case QGeoShape::RectangleType:
+ {
+ QGeoRectangle rect = m_region;
+ 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 = m_region;
+ 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));
+}
+
/*!
\internal
*/
@@ -1035,11 +1143,28 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF
m_map->resize(newGeometry.width(), newGeometry.height());
QQuickItem::geometryChanged(newGeometry, oldGeometry);
+
+ /*!
+ The fitViewportTo*() functions depend on a valid map geometry.
+ If they were called prior to the first resize they cause
+ the zoomlevel to jump to 0 (showing the world). Therefore the
+ calls were queued up until now.
+
+ Multiple fitViewportTo*() calls replace each other.
+ */
+ if (m_pendingFitViewport && width() && height()) {
+ fitViewportToGeoShape();
+ m_pendingFitViewport = false;
+ }
+
}
+// TODO Remove this function -> BC break
/*!
\qmlmethod 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
@@ -1112,6 +1237,7 @@ void QDeclarativeGeoMap::fitViewportToGeoShape(const QVariant &variantShape)
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));
}
diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h
index a36f2991..93f9426b 100644
--- a/src/imports/location/qdeclarativegeomap_p.h
+++ b/src/imports/location/qdeclarativegeomap_p.h
@@ -44,10 +44,7 @@
#include <QtQuick/QQuickItem>
#include <QtCore/QPointer>
#include <QtCore/QMutex>
-
-
-
-
+#include <QtPositioning/qgeoshape.h>
QT_BEGIN_NAMESPACE
@@ -70,6 +67,7 @@ class QDeclarativeGeoMap : public QQuickItem
Q_PROPERTY(QList<QObject *> mapItems READ mapItems NOTIFY mapItemsChanged)
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_INTERFACES(QQmlParserStatus)
public:
@@ -95,6 +93,9 @@ public:
void setCenter(const QGeoCoordinate &center);
QGeoCoordinate center() const;
+ void setVisibleRegion(const QGeoShape &shape);
+ QGeoShape visibleRegion() const;
+
QQmlListProperty<QDeclarativeGeoMapType> supportedMapTypes();
Q_INVOKABLE void removeMapItem(QDeclarativeGeoMapItemBase *item);
@@ -161,6 +162,7 @@ private:
void setupMapView(QDeclarativeGeoMapItemView *view);
void populateMap();
void fitViewportToMapItemsRefine(bool refine);
+ void fitViewportToGeoShape();
bool isInteractive();
private:
@@ -181,6 +183,8 @@ private:
qreal m_zoomLevel;
bool m_componentCompleted;
bool m_mappingManagerInitialized;
+ QGeoShape m_region;
+ bool m_pendingFitViewport;
friend class QDeclarativeGeoMapItem;
friend class QDeclarativeGeoMapItemView;