Undoed the parameter for user drag actions
[situare] / src / map / mapengine.cpp
index c993dfd..8c2a706 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <QtAlgorithms>
 #include <QDebug>
+#include <QGraphicsView>
 #include <QString>
 #include <QStringList>
 #include <QUrl>
@@ -33,6 +34,7 @@
 #include <QRect>
 
 #include "common.h"
+#include "coordinates/geocoordinate.h"
 #include "frienditemshandler.h"
 #include "gpslocationitem.h"
 #include "mapcommon.h"
@@ -129,21 +131,31 @@ QRect MapEngine::calculateTileGrid(SceneCoordinate coordinate)
     return QRect(topLeft, m_tilesGridSize);
 }
 
-void MapEngine::centerAndZoomTo(QRect rect)
+void MapEngine::centerAndZoomTo(QRect rect, bool useMargins)
 {
-    const int MARGIN_HORIZONTAL = 50;
-    const int MARGIN_VERTICAL = 5;
+    qDebug() << __PRETTY_FUNCTION__;
+
+    int marginHorizontal = 0;
+    int marginVertical = 0;
+
+    if (useMargins) {
+        marginHorizontal = 50;
+        marginVertical = 5;
+    }
 
     // calculate the usable size of the view
-    int viewUsableHeight = m_viewSize.height() - 2 * MARGIN_VERTICAL;
-    int viewUsableWidth = m_viewSize.width() - 2 * MARGIN_HORIZONTAL;
+    int viewUsableHeight = m_viewSize.height() - 2 * marginHorizontal;
+    int viewUsableWidth = m_viewSize.width() - 2 * marginVertical;
 
     // calculate how many levels must be zoomed out from the closest zoom level to get the rect
     // fit inside the usable view area
     int shift = 0;
     while ((rect.height() > (viewUsableHeight * (1 << shift)))
-           || (rect.width() > (viewUsableWidth * (1 << shift))))
+           || (rect.width() > (viewUsableWidth * (1 << shift)))) {
+
         shift++;
+    }
+
 
     scrollToPosition(SceneCoordinate(double(rect.center().x()), double(rect.center().y())));
 
@@ -176,6 +188,20 @@ QPoint MapEngine::convertSceneCoordinateToTileNumber(int zoomLevel, SceneCoordin
     return QPoint(x, y);
 }
 
+QRectF MapEngine::currentViewSceneRect() const
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    const QPoint ONE_PIXEL = QPoint(1, 1);
+
+    QGraphicsView *view = m_mapScene->views().first();
+    QPointF sceneTopLeft = view->mapToScene(0, 0);
+    QPoint viewBottomRight = QPoint(view->size().width(), view->size().height()) - ONE_PIXEL;
+    QPointF sceneBottomRight = view->mapToScene(viewBottomRight);
+
+    return QRectF(sceneTopLeft, sceneBottomRight);
+}
+
 void MapEngine::disableAutoCenteringIfRequired(SceneCoordinate coordinate)
 {
     if (isAutoCenteringEnabled()) {
@@ -199,7 +225,7 @@ void MapEngine::friendsPositionsUpdated()
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+    m_mapScene->spanItems(currentViewSceneRect());
 }
 
 void MapEngine::getTiles(SceneCoordinate coordinate)
@@ -233,14 +259,24 @@ void MapEngine::gpsPositionUpdate(GeoCoordinate position, qreal accuracy)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    m_gpsLocationItem->updatePosition(SceneCoordinate(position), accuracy);
-    m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+    m_gpsPosition = position;
 
+    // update GPS location item (but only if accuracy is a valid number)
+    if (!isnan(accuracy)) {
+        qreal resolution = MapScene::horizontalResolutionAtLatitude(position.latitude());
+        m_gpsLocationItem->updateItem(SceneCoordinate(position).toPointF(), accuracy, resolution);
+    }
+
+    m_mapScene->spanItems(currentViewSceneRect());
+
+    // do automatic centering (if enabled)
     if (m_autoCenteringEnabled) {
         m_lastAutomaticPosition = SceneCoordinate(position);
         m_scrollStartedByGps = true;
         scrollToPosition(m_lastAutomaticPosition);
     }
+
+    updateDirectionIndicator();
 }
 
 void MapEngine::init()
@@ -284,21 +320,6 @@ bool MapEngine::isCenterTileChanged(SceneCoordinate coordinate)
     return (centerTile != temp);
 }
 
-qreal MapEngine::sceneResolution()
-{
-    qDebug() << __PRETTY_FUNCTION__;
-
-    const int SHIFT = 200;
-
-    qreal scale = (1 << (OSM_MAX_ZOOM_LEVEL - m_zoomLevel));
-    GeoCoordinate centerCoordinate = centerGeoCoordinate();
-    SceneCoordinate shiftedSceneCoordinate(m_sceneCoordinate.x() + SHIFT * scale,
-                                           m_sceneCoordinate.y());
-    GeoCoordinate shiftedCoordinate(shiftedSceneCoordinate);
-    qreal dist = centerCoordinate.distanceTo(shiftedCoordinate);
-    return (dist / SHIFT);
-}
-
 void MapEngine::mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image)
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -353,7 +374,7 @@ void MapEngine::receiveOwnLocation(User *user)
         m_ownLocation->hide();
     }
 
-    m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+    m_mapScene->spanItems(currentViewSceneRect());
 }
 
 QGraphicsScene* MapEngine::scene()
@@ -397,6 +418,9 @@ void MapEngine::setAutoCentering(bool enabled)
     qDebug() << __PRETTY_FUNCTION__;
 
     m_autoCenteringEnabled = enabled;
+
+    if (!m_autoCenteringEnabled && m_gpsLocationItem->isVisible())
+        updateDirectionIndicator();
 }
 
 void MapEngine::setCenterPosition(SceneCoordinate coordinate)
@@ -422,8 +446,10 @@ void MapEngine::setCenterPosition(SceneCoordinate coordinate)
         m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
     }
 
-    m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
-    emit newMapResolution(sceneResolution());
+    m_mapScene->spanItems(currentViewSceneRect());
+    emit newMapResolution(viewResolution());
+
+    updateDirectionIndicator();
 }
 
 void MapEngine::setGPSEnabled(bool enabled)
@@ -439,22 +465,11 @@ void MapEngine::setRoute(Route &route)
 
     m_route = route;
 
-    qDebug() << __PRETTY_FUNCTION__ << "from:" << m_route.startPointName();
-    qDebug() << __PRETTY_FUNCTION__ << "to:" << m_route.endPointName();
-    qDebug() << __PRETTY_FUNCTION__ << "distance:" << m_route.totalDistance();
-    qDebug() << __PRETTY_FUNCTION__ << "estimated time:" << m_route.totalTime();
-
-    foreach (GeoCoordinate point, m_route.geometryPoints())
-        qDebug() << __PRETTY_FUNCTION__ << "geometry point:" << point;
-
-    foreach (RouteSegment segment, m_route.segments()) {
-        qDebug() << __PRETTY_FUNCTION__ << "segment:" << segment.instruction();
-    }
-
     // delete old route track (if exists)
     if (m_mapRouteItem) {
         m_mapScene->removeItem(m_mapRouteItem);
         delete m_mapRouteItem;
+        m_mapRouteItem = 0;
     }
 
     // create new route track
@@ -494,6 +509,34 @@ void MapEngine::setTilesGridSize(const QSize &viewSize)
     m_tilesGridSize.setWidth(gridWidth);
 }
 
+void MapEngine::showMapArea(const GeoCoordinate &swBound, const GeoCoordinate &neBound)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    QRect area;
+    area.setTopRight(SceneCoordinate(neBound).toPointF().toPoint());
+    area.setBottomLeft(SceneCoordinate(swBound).toPointF().toPoint());
+
+    centerAndZoomTo(area, false);
+}
+
+void MapEngine::updateDirectionIndicator()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    qreal distance = m_gpsPosition.distanceTo(m_sceneCoordinate);
+
+    qreal direction = m_sceneCoordinate.azimuthTo(SceneCoordinate(m_gpsPosition));
+
+    // direction indicator triangle should be drawn only if the gps location item is not currently
+    // visible on the view
+    bool drawDirectionIndicatorTriangle = true;
+    if (currentViewSceneRect().contains(m_gpsLocationItem->pos()))
+        drawDirectionIndicatorTriangle = false;
+
+    emit directionIndicatorValuesUpdate(direction, distance, drawDirectionIndicatorTriangle);
+}
+
 void MapEngine::updateViewTilesSceneRect()
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -529,10 +572,21 @@ void MapEngine::viewResized(const QSize &size)
     m_mapScene->setSceneVerticalOverlap(m_viewSize.height(), m_zoomLevel);
 }
 
+qreal MapEngine::viewResolution()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    qreal scale = (1 << (OSM_MAX_ZOOM_LEVEL - m_zoomLevel));
+
+    return MapScene::horizontalResolutionAtLatitude(centerGeoCoordinate().latitude()) * scale;
+}
+
 void MapEngine::viewZoomFinished()
 {
     qDebug() << __PRETTY_FUNCTION__;
 
+    updateDirectionIndicator();
+
     if (m_zoomedIn) {
         m_zoomedIn = false;
         m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
@@ -551,8 +605,8 @@ void MapEngine::zoomed()
     m_mapScene->setZoomLevel(m_zoomLevel);
     getTiles(m_sceneCoordinate);
     m_mapScene->setSceneVerticalOverlap(m_viewSize.height(), m_zoomLevel);
-    m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
-    emit newMapResolution(sceneResolution());
+    m_mapScene->spanItems(currentViewSceneRect());
+    emit newMapResolution(viewResolution());
 }
 
 void MapEngine::zoomIn()