Merge branch 'map' of https://vcs.maemo.org/git/situare into map
[situare] / src / map / mapengine.cpp
index 590045c..ca52db5 100644 (file)
@@ -4,6 +4,7 @@
 
        Sami Rämö - sami.ramo@ixonos.com
        Jussi Laitinen - jussi.laitinen@ixonos.com
+       Pekka Nissinen - pekka.nissinen@ixonos.com
 
    Situare is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -20,8 +21,6 @@
    USA.
 */
 
-#include <QtCore>
-#include <QtGlobal>
 #include <QDebug>
 #include <QString>
 #include <QStringList>
@@ -37,14 +36,23 @@ MapEngine::MapEngine(QObject *parent)
     : QObject(parent)
     , m_centerTile(QPoint(UNDEFINED, UNDEFINED))
     , m_viewSize(QSize(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT))
+    , m_zoomedIn(false)
     , m_zoomLevel(DEFAULT_ZOOM_LEVEL)
 {
     m_mapScene = new MapScene(this);
 
     m_mapFetcher = new MapFetcher(new QNetworkAccessManager(this), this);
-    connect(this, SIGNAL(fetchImage(QUrl)), m_mapFetcher, SLOT(fetchMapImage(QUrl)));
+    connect(this, SIGNAL(fetchImage(QUrl)), m_mapFetcher, SLOT(enqueueFetchMapImage(QUrl)));
     connect(m_mapFetcher, SIGNAL(mapImageReceived(QUrl,QPixmap)), this,
             SLOT(mapImageReceived(QUrl, QPixmap)));
+
+    m_mapZoomPanel = new MapZoomPanel(NULL, MAP_ZOOM_PANEL_POSITION_X, MAP_ZOOM_PANEL_POSITION_Y);
+    m_mapScene->addItem(m_mapZoomPanel);
+    connect(m_mapZoomPanel, SIGNAL(zoomInPressed()), this, SLOT(zoomIn()));
+    connect(m_mapZoomPanel, SIGNAL(zoomOutPressed()), this, SLOT(zoomOut()));
+
+    m_ownLocation = new OwnLocationItem();
+    m_mapScene->addItem(m_ownLocation);
 }
 
 void MapEngine::init()
@@ -74,37 +82,37 @@ void MapEngine::parseURL(const QUrl &url, int &zoom, int &x, int &y)
 
     int size = pathParts.size();
 
-    if (size < 3)
-        return;
-
-    zoom = (pathParts.at(size-3)).toInt();
-    x = (pathParts.at(size-2)).toInt();
-    QString yString = pathParts.at(size-1);
-    yString.chop(4);
-    y = yString.toInt();
+    if (size >= 3) {
+        zoom = (pathParts.at(size-3)).toInt();
+        x = (pathParts.at(size-2)).toInt();
+        QString yString = pathParts.at(size-1);
+        yString.chop(4);
+        y = yString.toInt();
+    }
 }
 
 void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     int zoom = UNDEFINED;
     int x = UNDEFINED;
     int y = UNDEFINED;
 
     parseURL(url, zoom, x, y);
-
-    if (!m_mapTilesInScene.contains(tilePath(zoom, x, y))) {
+    QString hashKey = tilePath(zoom, x, y);
+    if (!m_mapScene->isTileInScene(hashKey)) {
 
         MapTile *mapTile = new MapTile();
-        mapTile->setZoomLevel(zoom);
+        mapTile->setZoomLevel(zoom, m_zoomLevel);
         mapTile->setTileNumber(QPoint(x, y));
         mapTile->setPixmap(pixmap);
 
-        m_mapTilesInScene.insert(tilePath(zoom, x, y), mapTile);
-        m_mapScene->addMapTile(mapTile);
+        m_mapScene->addTile(mapTile, hashKey);
+
+        m_mapScene->debugItemsCount();
 
-        removeStackedTiles(mapTile);
+        m_mapScene->enqueueRemoveStackedTiles(mapTile);
    }
 }
 
@@ -118,7 +126,7 @@ int MapEngine::tileMaxValue(int zoomLevel)
     return (1 << zoomLevel) - 1;
 }
 
-QRect MapEngine::calculateGrid(QPoint sceneCoordinate)
+QRect MapEngine::calculateTileGrid(QPoint sceneCoordinate)
 {
     QPoint tileCoordinate = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
     int gridWidth = (m_viewSize.width()/TILE_SIZE_X + 1) + (GRID_PADDING*2);
@@ -126,23 +134,32 @@ QRect MapEngine::calculateGrid(QPoint sceneCoordinate)
     int topLeftX = tileCoordinate.x() - (gridWidth/2);
     int topLeftY = tileCoordinate.y() - (gridHeight/2);
 
+    m_mapFetcher->setDownloadQueueSize(gridWidth * gridHeight);
+
     return QRect(topLeftX, topLeftY, gridWidth, gridHeight);
 }
 
+void MapEngine::alignImmovableItems(QPoint viewTopLeft)
+{
+    m_mapZoomPanel->setPos(viewTopLeft);
+
+    qDebug() << __PRETTY_FUNCTION__ << "viewTopLeft:" << viewTopLeft;
+}
+
 void MapEngine::setLocation(QPoint sceneCoordinate)
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     m_sceneCoordinate = sceneCoordinate;
     emit locationChanged(m_sceneCoordinate);
 
-    if (centerTileChanged(sceneCoordinate)) {
-        calculateNewTiles(sceneCoordinate);
-        removeOldTiles();
+    if (isCenterTileChanged(sceneCoordinate)) {
+        getTiles(sceneCoordinate);
+        m_mapScene->removeOutOfViewTiles();
     }
 }
 
-bool MapEngine::centerTileChanged(QPoint sceneCoordinate)
+bool MapEngine::isCenterTileChanged(QPoint sceneCoordinate)
 {
     QPoint centerTile = convertSceneCoordinateToTileNumber(m_zoomLevel, sceneCoordinate);
     QPoint temp = m_centerTile;
@@ -151,16 +168,17 @@ bool MapEngine::centerTileChanged(QPoint sceneCoordinate)
     return (centerTile != temp);
 }
 
-void MapEngine::calculateNewTiles(QPoint sceneCoordinate)
+void MapEngine::getTiles(QPoint sceneCoordinate)
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
-    m_viewGrid = calculateGrid(sceneCoordinate);
+    m_viewTilesGrid = calculateTileGrid(sceneCoordinate);
+    updateViewTilesSceneRect();
 
-    int topLeftX = m_viewGrid.topLeft().x();
-    int topLeftY = m_viewGrid.topLeft().y();
-    int bottomRightX = m_viewGrid.bottomRight().x();
-    int bottomRightY = m_viewGrid.bottomRight().y();
+    int topLeftX = m_viewTilesGrid.topLeft().x();
+    int topLeftY = m_viewTilesGrid.topLeft().y();
+    int bottomRightX = m_viewTilesGrid.bottomRight().x();
+    int bottomRightY = m_viewTilesGrid.bottomRight().y();
 
     int tileMaxVal = tileMaxValue(m_zoomLevel);
 
@@ -182,156 +200,66 @@ void MapEngine::calculateNewTiles(QPoint sceneCoordinate)
 
             QUrl url = buildURL(m_zoomLevel, QPoint(tileX, tileY));
 
-            if (!m_mapTilesInScene.contains(tilePath(m_zoomLevel, tileX, tileY)))
+            if (!m_mapScene->isTileInScene(tilePath(m_zoomLevel, tileX, tileY)))
                 emit fetchImage(url);
         }
     }
 }
 
-void MapEngine::removeTile(MapTile *tile)
+void MapEngine::updateViewTilesSceneRect()
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    QPoint topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewTilesGrid.topLeft());
+    QPoint bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel,
+                                                            m_viewTilesGrid.bottomRight()
+                                                             + QPoint(1, 1)) - QPoint(1, 1);
 
-    if (tile) {
-       m_mapTilesInScene.remove(tilePath(tile->zoomLevel(), tile->tileNumber().x(),
-                                         tile->tileNumber().y()));
-       m_mapScene->removeItem(tile);
-       delete tile;
-    }
+    m_mapScene->viewRectUpdated(QRect(topLeft, bottomRight));
 }
 
-void MapEngine::removeOldTiles()
+void MapEngine::viewResized(const QSize &size)
 {
-    //qDebug() << __PRETTY_FUNCTION__;
-
-    QPointF topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewGrid.topLeft());
-    QPointF bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewGrid.bottomRight()
-                                                             + QPoint(1, 1));
-    qreal width = bottomRight.x() - topLeft.x();
-    qreal height = bottomRight.y() - topLeft.y();
-
-    QList<QGraphicsItem *> viewTiles = m_mapScene->items(topLeft.x(), topLeft.y(), width, height,
-                                                         Qt::ContainsItemBoundingRect);
-    QList<QGraphicsItem *> allTiles = m_mapScene->items();
-
-    foreach (QGraphicsItem *tile, viewTiles)
-        allTiles.removeOne(tile);
-
-    QHashIterator<QString, MapTile *> i(m_mapTilesInScene);
-
-     while (i.hasNext()) {
-         i.next();
-         if (allTiles.contains(i.value()) && m_mapTilesInScene.contains(i.key())) {
-             MapTile *tile = i.value();
-             removeTile(tile);
-         }
-     }
+    m_viewSize = size;
+    getTiles(m_sceneCoordinate);
+    m_mapScene->removeOutOfViewTiles();
 }
 
-void MapEngine::removeStackedTiles(MapTile *newTile)
+void MapEngine::viewZoomFinished()
 {
-    //qDebug() << __PRETTY_FUNCTION__;
-
-    QRectF newTileSceneRect = newTile->mapRectToScene(newTile->boundingRect());
-    QList<QGraphicsItem *> collidingTiles = newTile->collidingItems(Qt::IntersectsItemBoundingRect);
-
-    //Loop all items under new tile
-    foreach (QGraphicsItem *collidingTile, collidingTiles) {
-
-        QRectF collidingTileSceneRect = collidingTile->sceneBoundingRect();
-
-        //If new tile covers the tile under, remove the tile
-        if (newTileSceneRect.contains(collidingTileSceneRect)) {
-            MapTile *tile = dynamic_cast<MapTile *>(collidingTile);
-            removeTile(tile);
-        }
-
-        else {
-            //Get tiles below removal candidate
-            QList<QGraphicsItem *> stackedTiles = m_mapScene->items(collidingTileSceneRect,
-                                                                    Qt::ContainsItemBoundingRect);
-
-            QRectF combined = combineTiles(collidingTile, stackedTiles);
-
-            //If combined tiles below removal candidate covers removal candidate, remove it
-            if (combined.contains(collidingTileSceneRect)) {
-                MapTile *tile = dynamic_cast<MapTile *>(collidingTile);
-                removeTile(tile);
-            }
-        }
-    }
-}
+    qDebug() << __PRETTY_FUNCTION__;
 
-QRectF MapEngine::combineTiles(QGraphicsItem *parentTile,
-                               const QList<QGraphicsItem*> &stackedTiles)
-{
-    QRectF combined;
-    int count = 0;
-
-    foreach (QGraphicsItem *stackedTile, stackedTiles) {
-        if (stackedTile != parentTile) {
-            count++;
-            QRectF stackedTileSceneRect = stackedTile->sceneBoundingRect();
-            combined = combined.united(stackedTileSceneRect);
-        }
+    if (m_zoomedIn) {
+        m_zoomedIn = false;
+        m_mapScene->removeOutOfViewTiles();
     }
-
-    if (count < 4)
-        combined = QRectF();
-
-    return combined;
-}
-
-void MapEngine::viewResized(const QSize &size)
-{
-    m_viewSize = size;
-    calculateNewTiles(m_sceneCoordinate);
-    removeOldTiles();
 }
 
 void MapEngine::zoomIn()
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    if (m_zoomLevel >= MAX_MAP_ZOOM_LEVEL)
-        return;
+    if (m_zoomLevel < MAX_MAP_ZOOM_LEVEL) {
+        m_zoomLevel++;
+        m_zoomedIn = true;
+        emit zoomLevelChanged(m_zoomLevel);
 
-    m_zoomLevel++;
-    emit zoomLevelChanged(m_zoomLevel);
-
-    setTilesDrawingLevels();
+        m_mapScene->setTilesDrawingLevels(m_zoomLevel);
 
-    calculateNewTiles(m_sceneCoordinate);
-    QTimer::singleShot(500, this, SLOT(removeOldTiles()));
+        getTiles(m_sceneCoordinate);
+    }
 }
 
 void MapEngine::zoomOut()
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    if (m_zoomLevel <= MIN_MAP_ZOOM_LEVEL)
-        return;
+    if (m_zoomLevel > MIN_VIEW_ZOOM_LEVEL) {
+        m_zoomLevel--;
+        emit zoomLevelChanged(m_zoomLevel);
 
-    m_zoomLevel--;
-    emit zoomLevelChanged(m_zoomLevel);
-
-    setTilesDrawingLevels();
-
-    calculateNewTiles(m_sceneCoordinate);
-}
-
-void MapEngine::setTilesDrawingLevels()
-{
-    //qDebug() << __PRETTY_FUNCTION__ << "m_zoomLevel:" << m_zoomLevel;
-
-    QList<QGraphicsItem *> items = m_mapScene->items();
+        m_mapScene->setTilesDrawingLevels(m_zoomLevel);
 
-    for (int i = 0; i < items.size(); ++i) {
-        MapTile *item = dynamic_cast<MapTile *>(items.at(i));
-        if (item)
-            item->setSceneLevel(m_zoomLevel);
+        getTiles(m_sceneCoordinate);
     }
-
 }
 
 QString MapEngine::tilePath(int zoomLevel, int x, int y)
@@ -343,11 +271,6 @@ QString MapEngine::tilePath(int zoomLevel, int x, int y)
     return tilePathString;
 }
 
-void MapEngine::scalingFactorChanged(qreal scaleFactor)
-{
-    qDebug() << __PRETTY_FUNCTION__;
-}
-
 QPoint MapEngine::convertSceneCoordinateToTileNumber(int zoomLevel, QPoint sceneCoordinate)
 {
     int pow = 1 << (MAX_MAP_ZOOM_LEVEL - zoomLevel);
@@ -368,7 +291,7 @@ QPoint MapEngine::convertTileNumberToSceneCoordinate(int zoomLevel, QPoint tileN
 
 QPoint MapEngine::convertLatLonToSceneCoordinate(QPointF latLonCoordinate)
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     qreal longitude = latLonCoordinate.x();
     qreal latitude = latLonCoordinate.y();