Fixed (yet) another merge screw-up *sigh*
authorPekka Nissinen <pekka.nissinen@ixonos.com>
Thu, 29 Apr 2010 09:03:24 +0000 (12:03 +0300)
committerPekka Nissinen <pekka.nissinen@ixonos.com>
Thu, 29 Apr 2010 09:03:24 +0000 (12:03 +0300)
14 files changed:
src/map/mapcommon.h
src/map/mapengine.cpp
src/map/mapengine.h
src/map/mapfetcher.cpp
src/map/mapfetcher.h
src/map/mapscene.cpp
src/map/mapscene.h
src/map/maptile.cpp
src/map/maptile.h
src/map/mapview.cpp
src/map/mapview.h
src/situareservice/imagefetcher.h
src/src.pro
src/ui/mapviewscreen.cpp

index f7e8f4f..321a80c 100644 (file)
@@ -30,6 +30,7 @@ const int TILE_SIZE_Y = 256; ///< Tile image size in y direction
 
 const int MIN_MAP_ZOOM_LEVEL = 0; ///< Minimum zoom level
 const int MAX_MAP_ZOOM_LEVEL = 18; ///< Maximum zoom level
+const int MIN_VIEW_ZOOM_LEVEL = 2; ///< Minimum zoom level for MapView
 const int MIN_MAP_SCENE_NORMAL_LEVEL = MAX_MAP_ZOOM_LEVEL + 1;
 
 const int ZOOM_FPS = 30; ///< FPS for the zoom effect
index cc3fae0..98a8767 100644 (file)
@@ -36,12 +36,13 @@ 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)));
 
@@ -92,7 +93,7 @@ void MapEngine::parseURL(const QUrl &url, int &zoom, int &x, int &y)
 
 void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     int zoom = UNDEFINED;
     int x = UNDEFINED;
@@ -103,13 +104,15 @@ void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
     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_mapScene->addTile(mapTile, hashKey);
 
-        m_mapScene->removeStackedTiles(mapTile, viewRect());
+        m_mapScene->debugItemsCount();
+
+        m_mapScene->enqueueRemoveStackedTiles(mapTile);
    }
 }
 
@@ -138,19 +141,19 @@ void MapEngine::alignImmovableItems(QPoint viewTopLeft)
 {
     m_mapZoomPanel->setPos(viewTopLeft);
 
-//    qDebug() << __PRETTY_FUNCTION__ << "viewTopLeft:" << 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 (isCenterTileChanged(sceneCoordinate)) {
         getTiles(sceneCoordinate);
-        m_mapScene->removeOutOfViewTiles(viewRect());
+        m_mapScene->removeOutOfViewTiles();
     }
 }
 
@@ -165,14 +168,15 @@ bool MapEngine::isCenterTileChanged(QPoint sceneCoordinate)
 
 void MapEngine::getTiles(QPoint sceneCoordinate)
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
-    m_viewGrid = calculateTileGrid(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);
 
@@ -200,33 +204,40 @@ void MapEngine::getTiles(QPoint sceneCoordinate)
     }
 }
 
-QRect MapEngine::viewRect()
+void MapEngine::updateViewTilesSceneRect()
 {
-    QPoint topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewGrid.topLeft());
-    QPoint bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewGrid.bottomRight()
-                                                             + QPoint(1, 1));
-    return QRect(topLeft, bottomRight);
+    QPoint topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewTilesGrid.topLeft());
+    QPoint bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel,
+                                                            m_viewTilesGrid.bottomRight()
+                                                             + QPoint(1, 1)) - QPoint(1, 1);
+
+    m_mapScene->viewRectUpdated(QRect(topLeft, bottomRight));
 }
 
 void MapEngine::viewResized(const QSize &size)
 {
     m_viewSize = size;
     getTiles(m_sceneCoordinate);
-    m_mapScene->removeOutOfViewTiles(viewRect());
+    m_mapScene->removeOutOfViewTiles();
 }
 
-void MapEngine::viewZoomInFinished()
+void MapEngine::viewZoomFinished()
 {
     qDebug() << __PRETTY_FUNCTION__;
-    m_mapScene->removeOutOfViewTiles(viewRect());
+
+    if (m_zoomedIn) {
+        m_zoomedIn = false;
+        m_mapScene->removeOutOfViewTiles();
+    }
 }
 
 void MapEngine::zoomIn()
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     if (m_zoomLevel < MAX_MAP_ZOOM_LEVEL) {
         m_zoomLevel++;
+        m_zoomedIn = true;
         emit zoomLevelChanged(m_zoomLevel);
 
         m_mapScene->setTilesDrawingLevels(m_zoomLevel);
@@ -237,9 +248,9 @@ void MapEngine::zoomIn()
 
 void MapEngine::zoomOut()
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
-    if (m_zoomLevel > MIN_MAP_ZOOM_LEVEL) {
+    if (m_zoomLevel > MIN_VIEW_ZOOM_LEVEL) {
         m_zoomLevel--;
         emit zoomLevelChanged(m_zoomLevel);
 
@@ -278,7 +289,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();
index 30d9fc1..60b648e 100644 (file)
@@ -197,11 +197,12 @@ private:
     int tileMaxValue(int zoomLevel);
 
     /**
-    * @brief Returns the current view rect including margins
+    * @brief Updates the current view rect including margins
     *
-    * @return Current view rect
+    * Calculates tiles rect in scene based on m_viewTilesGrid and
+    * calls MapScene::viewRectUpdated()
     */
-    QRect viewRect();
+    void updateViewTilesSceneRect();
 
 private slots:
     /**
@@ -218,7 +219,7 @@ private slots:
     *
     * Does run removeOutOfViewTiles
     */
-    void viewZoomInFinished();
+    void viewZoomFinished();
 
     /**
     * @brief Slot for zooming in
@@ -267,8 +268,9 @@ private:
     QPoint m_centerTile; ///< Current center tile
     OwnLocationItem *m_ownLocation; ///< Item to show own location
     QPoint m_sceneCoordinate; ///< Current center coordinate
-    QRect m_viewGrid; ///< Current grid of tiles in view (includes margin)
+    QRect m_viewTilesGrid; ///< Current grid of tiles in view (includes margin)
     QSize m_viewSize; ///< Current view size
+    bool m_zoomedIn; ///< Flag for checking if zoomed in when zoom is finished
     int m_zoomLevel; ///< Current zoom level
 };
 
index 731a123..0df9c75 100644 (file)
@@ -3,6 +3,7 @@
    Copyright (C) 2010  Ixonos Plc. Authors:
 
        Jussi Laitinen - jussi.laitinen@ixonos.com
+       Sami Rämö - sami.ramo@ixonos.com
 
    Situare is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -33,6 +34,7 @@
 
 MapFetcher::MapFetcher(QNetworkAccessManager *manager, QObject *parent)
     : QObject(parent)
+    , m_isFetchMapImagesTimerRunning(false)
     , m_manager(manager)
 {
     QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
@@ -44,28 +46,58 @@ MapFetcher::MapFetcher(QNetworkAccessManager *manager, QObject *parent)
             downloadFinished(QNetworkReply*)));
 }
 
-void MapFetcher::fetchMapImage(const QUrl &url)
+void MapFetcher::enqueueFetchMapImage(QUrl url)
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
+
+    // check if new url is already in the list and move it to end
+    // or append new url if not found
+    int index;
+    if ((index = m_fetchMapImagesList.indexOf(url)) != -1)
+        m_fetchMapImagesList.move(index, m_fetchMapImagesList.size() - 1);
+    else
+        m_fetchMapImagesList << url;
+
+    // limit list size
+    if (m_fetchMapImagesList.size() > DOWNLOAD_QUEUE_SIZE)
+        m_fetchMapImagesList.removeFirst();
+
+    if (!m_isFetchMapImagesTimerRunning) {
+        m_isFetchMapImagesTimerRunning = true;
+        QTimer::singleShot(0, this, SLOT(fetchMapImage()));
+    }
+}
 
-    if (url.isEmpty() || !url.isValid())
-        return;
+void MapFetcher::fetchMapImage()
+{
+    qDebug() << __PRETTY_FUNCTION__;
 
-    if (loadImageFromCache(url))
-        return;
+    if (!m_fetchMapImagesList.isEmpty()) {
+        QUrl url = m_fetchMapImagesList.takeLast();
 
-    if (m_downloadQueue.size() >= DOWNLOAD_QUEUE_SIZE)
-        m_downloadQueue.dequeue();
+        if (!url.isEmpty() && url.isValid()) {
+            if (!loadImageFromCache(url)) {
+                if (m_downloadQueue.size() >= DOWNLOAD_QUEUE_SIZE)
+                    m_downloadQueue.dequeue();
 
-    m_downloadQueue.enqueue(url);
+                m_downloadQueue.enqueue(url);
+
+                if (m_currentDownloads.size() < MAX_PARALLEL_DOWNLOADS)
+                    startNextDownload();
+            }
+        }
+    }
 
-    if (m_currentDownloads.size() < MAX_PARALLEL_DOWNLOADS)
-        startNextDownload();
+    // schedule fetching of the next tile if the list is not empty
+    if (!m_fetchMapImagesList.isEmpty())
+        QTimer::singleShot(0, this, SLOT(fetchMapImage()));
+    else
+        m_isFetchMapImagesTimerRunning = false;
 }
 
 bool MapFetcher::loadImageFromCache(const QUrl &url)
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     bool imageFound = false;
 
@@ -102,7 +134,7 @@ bool MapFetcher::loadImageFromCache(const QUrl &url)
 
 void MapFetcher::startNextDownload()
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     if (m_downloadQueue.isEmpty())
         return;
@@ -118,7 +150,7 @@ void MapFetcher::startNextDownload()
 
 void MapFetcher::downloadFinished(QNetworkReply *reply)
 {
-    //qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     if (reply->error() == QNetworkReply::NoError) {
         QImage image;
index dbfef0d..bf1418f 100644 (file)
@@ -3,6 +3,7 @@
    Copyright (C) 2010  Ixonos Plc. Authors:
 
        Jussi Laitinen - jussi.laitinen@ixonos.com
+       Sami Rämö - sami.ramo@ixonos.com
 
    Situare is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -53,11 +54,14 @@ public:
  ******************************************************************************/
 public slots:
     /**
-    * @brief Fetch image from given URL.
+    * @brief Enqueue fetching of map image
     *
-    * @param url URL to image
+    * Image fetching is triggered after events have been processed
+    * so the UI stays responsive.
+    *
+    * @param url URL of the image to be fetched
     */
-    void fetchMapImage(const QUrl &url);
+    void enqueueFetchMapImage(QUrl url);
 
 private:
     /**
@@ -82,6 +86,13 @@ private slots:
     void downloadFinished(QNetworkReply *reply);
 
     /**
+    * @brief Fetch next map image.
+    *
+    * Next queued request is taken from the queue and fetching is started
+    */
+    void fetchMapImage();
+
+    /**
     * @brief This slot is called when next download is started. Takes url
     * from queue, sends request and puts request to download queue.
     */
@@ -117,6 +128,8 @@ private:
 
     QList<QNetworkReply*> m_currentDownloads; ///< List of current downloads
     QQueue<QUrl> m_downloadQueue;             ///< Queue of pending requests
+    QList<QUrl> m_fetchMapImagesList; ///< "Queue" for map image fetching requests
+    bool m_isFetchMapImagesTimerRunning; ///< is the singleshot timer already running
     QNetworkAccessManager *m_manager;       ///< Network access manager
 };
 
index 8889744..5c0fb59 100644 (file)
@@ -26,6 +26,8 @@
 
 MapScene::MapScene(QObject *parent)
     : QGraphicsScene(parent)
+    , m_isRemoveStackedTilesRunning(false)
+    , m_viewRect(QRect(0, 0, 0, 0))
 {
     const int maxTilesPerSide = (1 << MAX_MAP_ZOOM_LEVEL);
     const int maxPixelsX = maxTilesPerSide * TILE_SIZE_X;
@@ -39,20 +41,64 @@ void MapScene::addTile(MapTile *mapTile, QString hashKey)
     addItem(mapTile);
 }
 
+void MapScene::debugItemsCount()
+{
+#ifndef Q_WS_MAEMO_5
+    qDebug() << __PRETTY_FUNCTION__ << "ITEM ADDED:" << items().count();
+#endif // Q_WS_MAEMO_5
+}
+
+void MapScene::enqueueRemoveStackedTiles(MapTile *newTile)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_removeStackedTilesList << newTile;
+    if (!m_isRemoveStackedTilesRunning) {
+        m_isRemoveStackedTilesRunning = true;
+        QTimer::singleShot(0, this, SLOT(runNextStackedTilesRemoval()));
+    }
+}
+
 bool MapScene::isTileInScene(QString hashKey)
 {
     return m_mapTilesInScene.contains(hashKey);
 }
 
-void MapScene::removeOutOfViewTiles(QRect viewRect)
+void MapScene::runNextStackedTilesRemoval()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (!m_removeStackedTilesList.isEmpty()) {
+        MapTile *tile = m_removeStackedTilesList.takeFirst();
+        removeStackedTiles(tile);
+    }
+
+    // schedule removal of the next tile if the list is not empty
+    if (!m_removeStackedTilesList.isEmpty()) {
+        QTimer::singleShot(0, this, SLOT(runNextStackedTilesRemoval()));
+    }
+    else {
+        m_isRemoveStackedTilesRunning = false;
+#ifndef Q_WS_MAEMO_5
+    qDebug() << __PRETTY_FUNCTION__ << "STACKED END:" << items().count();
+#endif // Q_WS_MAEMO_5
+    }
+}
+
+void MapScene::removeOutOfViewTiles()
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
-    QList<QGraphicsItem *> viewTiles = items(viewRect, Qt::ContainsItemBoundingRect);
+    QList<QGraphicsItem *> viewTiles = items(m_viewRect, Qt::IntersectsItemBoundingRect);
     QList<QGraphicsItem *> allTiles = items();
 
-//    qDebug() << __PRETTY_FUNCTION__ << "All tiles:" << allTiles.count();
-//    qDebug() << __PRETTY_FUNCTION__ << "Tiles in view area:" << viewTiles.count();
+#ifndef Q_WS_MAEMO_5
+    qDebug() << __PRETTY_FUNCTION__ << "OUT OF VIEW START:" << items().count();
+#endif // Q_WS_MAEMO_5
+
+
+    qDebug() << __PRETTY_FUNCTION__ << "All tiles:" << allTiles.count();
+    qDebug() << __PRETTY_FUNCTION__ << "Tiles in view area:" << viewTiles.count();
 
     //Remove tiles which are in view from allTiles
     foreach (QGraphicsItem *tile, viewTiles)
@@ -65,61 +111,49 @@ void MapScene::removeOutOfViewTiles(QRect viewRect)
         if (tileToRemove)
             removeTile(tileToRemove);
     }
+
+#ifndef Q_WS_MAEMO_5
+    qDebug() << __PRETTY_FUNCTION__ << "OUT OF VIEW END:" << items().count();
+#endif // Q_WS_MAEMO_5
+
 }
 
-void MapScene::removeStackedTiles(MapTile *newTile, QRect viewRect)
+void MapScene::removeStackedTiles(MapTile *newTile)
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     QRectF newTileSceneRect = newTile->sceneBoundingRect();
 
     //Loop all items under new tile
-    QList<QGraphicsItem *> collidingTiles = newTile->collidingItems(Qt::IntersectsItemBoundingRect);
-//    qDebug() << __PRETTY_FUNCTION__ << "Colliding tiles before:" << collidingTiles.count();
-    foreach (QGraphicsItem *collidingTile, collidingTiles) {
-
-
-        QRectF collidingTileSceneRect = collidingTile->sceneBoundingRect();
-
-        // remove tile if it is obscured by new tile
-        if (newTileSceneRect.contains(collidingTileSceneRect)) {
-            MapTile *tile = dynamic_cast<MapTile *>(collidingTile);
-            if (tile)
-                removeTile(tile);
-        }
-        else {
-            // remove tile if it is obscured in the view area
-            QRect collidingTileViewableArea =
-                    collidingTileSceneRect.intersected(viewRect).toRect();
-            if (collidingTile->isObscured(collidingTileViewableArea)) {
-                qDebug() << __PRETTY_FUNCTION__ << "Deleting obscured item";
-                MapTile *tile = dynamic_cast<MapTile *>(collidingTile);
-                if (tile)
-                    removeTile(tile);
-            }
+    QList<QGraphicsItem *> collidingItems = newTile->collidingItems(Qt::IntersectsItemBoundingRect);
+    foreach (QGraphicsItem *collidingItem, collidingItems) {
+        MapTile *collidingTile = dynamic_cast<MapTile *>(collidingItem);
+        if (collidingTile) {
+             // remove tile if it is fully obscured by new tile
+            QRectF collidingTileSceneRect = collidingTile->sceneBoundingRect();
+            if (newTileSceneRect.contains(collidingTileSceneRect))
+                removeTile(collidingTile);
         }
     }
-//    qDebug() << __PRETTY_FUNCTION__ << "All tiles after:"
-//             << newTile->collidingItems(Qt::IntersectsItemBoundingRect).count();
 }
 
-
 void MapScene::removeTile(MapTile *tile)
 {
-//    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << __PRETTY_FUNCTION__;
 
     if (tile) {
         m_mapTilesInScene.remove(MapEngine::tilePath(tile->zoomLevel(),
                                                      tile->tileNumber().x(),
                                                      tile->tileNumber().y()));
-       removeItem(tile);
-       delete tile;
+        removeItem(tile);
+        m_removeStackedTilesList.removeAll(tile);
+        delete tile;
     }
 }
 
 void MapScene::setTilesDrawingLevels(int zoomLevel)
 {
-//    qDebug() << __PRETTY_FUNCTION__ << "m_zoomLevel:" << m_zoomLevel;
+    qDebug() << __PRETTY_FUNCTION__ << "zoomLevel:" << zoomLevel;
 
     QList<QGraphicsItem *> allItems = items();
 
@@ -129,3 +163,8 @@ void MapScene::setTilesDrawingLevels(int zoomLevel)
             item->setSceneLevel(zoomLevel);
     }
 }
+
+void MapScene::viewRectUpdated(QRect viewRect)
+{
+    m_viewRect = viewRect;
+}
index 7c6c446..3096c61 100644 (file)
@@ -33,6 +33,7 @@
 */
 class MapScene : public QGraphicsScene
 {
+    Q_OBJECT
 public:
     /**
     * @brief Constructor
@@ -54,6 +55,17 @@ public:
     */
     void addTile(MapTile *mapTile, QString hashKey);
 
+    void debugItemsCount();
+
+    /**
+    * @brief Enqueue stacked tiles removal request
+    *
+    * Removal is triggered after events have been processed so the UI
+    * stays more responsive
+    * @param newTile New tile, which area under it is inspected
+    */
+    void enqueueRemoveStackedTiles(MapTile *newTile);
+
     /**
     * @brief Returns if tile mathcing hash key is already in the scene
     *
@@ -65,20 +77,22 @@ public:
     /**
     * @brief Remove tiles which are out of view bounds.
     *
-    * @param viewRect Current view rect
     */
-    void removeOutOfViewTiles(QRect viewRect);
+    void removeOutOfViewTiles();
 
     /**
     * @brief Remove tiles which are stacked.
     *
-    * Iterate through tiles which are under this map tile and remove obscured
-    * tiles.
+    * Iterate through tiles which are under this map tile and remove tiles which
+    * are fully obscured by this new tile. Tiles which are only partially
+    * obscured by this new tile are not checked, and thus deleted, because of
+    * the required complexity of the algorithm and processing power. Those tiles
+    * will be removed when they go out of the view area caused by scrolling or
+    * zooming in enough.
     *
     * @param newTile new tile covering old tiles
-    * @param viewRect Current view rect
     */
-    void removeStackedTiles(MapTile *newTile, QRect viewRect);
+    void removeStackedTiles(MapTile *newTile);
 
     /**
     * @brief Remove tile.
@@ -96,11 +110,33 @@ public:
     */
     void setTilesDrawingLevels(int zoomLevel);
 
+    /**
+    * @brief Save new view rect
+    *
+    * View rect must be saved to local scope whenever it changes because
+    * it is used by removal algorithms and some of the algorithms are run
+    * delayed so the actual view rect may change before the cleanup
+    * algorithm is run.
+    *
+    * @param viewRect New view rect
+    */
+    void viewRectUpdated(QRect viewRect);
+
+private slots:
+    /**
+    * @brief Slot for running next queued removal of stacked tiles
+    *
+    */
+    void runNextStackedTilesRemoval();
+
 /*******************************************************************************
  * DATA MEMBERS
  ******************************************************************************/
 private:
+    bool m_isRemoveStackedTilesRunning; ///< Is singleshot timer already running
     QHash<QString, MapTile *> m_mapTilesInScene;  ///< List of map tiles in map scene
+    QList<MapTile *> m_removeStackedTilesList; ///< "Queue" for stacked tiles removal requests
+    QRect m_viewRect; ///< Current viewable area
 };
 
 #endif // MAPSCENE_H
index 0bae905..5d3128b 100644 (file)
@@ -31,6 +31,7 @@ MapTile::MapTile()
     , m_zoomLevel(UNDEFINED)
 {    
     setPos(UNDEFINED, UNDEFINED);
+    setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
 }
 
 int MapTile::zoomLevel()
@@ -38,12 +39,12 @@ int MapTile::zoomLevel()
     return m_zoomLevel;
 }
 
-void MapTile::setZoomLevel(int zoomLevel)
+void MapTile::setZoomLevel(int tileZoomLevel, int currentViewZoomLevel)
 {
-    m_zoomLevel = zoomLevel;
+    m_zoomLevel = tileZoomLevel;
     setPosition();
 
-    setZValue(static_cast<qreal>(MIN_MAP_SCENE_NORMAL_LEVEL + zoomLevel));
+    setSceneLevel(currentViewZoomLevel);
 
     qreal zoomFactor = static_cast<qreal>(1 << (MAX_MAP_ZOOM_LEVEL - m_zoomLevel));
     setScale(zoomFactor);
@@ -59,9 +60,9 @@ void MapTile::setSceneLevel(int currentZoomLevel)
     else
         setZValue(static_cast<qreal>(MIN_MAP_SCENE_NORMAL_LEVEL + m_zoomLevel));
 
-//    qDebug() << __PRETTY_FUNCTION__ << "Tile:" << m_tileNumber
-//                                    << "m_zoomLevel" << m_zoomLevel
-//                                    << "zValue:" << zValue();
+    qDebug() << __PRETTY_FUNCTION__ << "Tile:" << m_tileNumber
+                                    << "m_zoomLevel" << m_zoomLevel
+                                    << "zValue:" << zValue();
 }
 
 QPoint MapTile::tileNumber()
@@ -84,7 +85,7 @@ void MapTile::setPosition()
         (m_tileNumber.y() >= 0) && (m_tileNumber.y() <= maxTileNumber)) {
 
         setPos(MapEngine::convertTileNumberToSceneCoordinate(m_zoomLevel, m_tileNumber));
-        //qDebug() << __PRETTY_FUNCTION__ << "tile position:" << pos();
+        qDebug() << __PRETTY_FUNCTION__ << "tile position:" << pos();
     }
     else {
         setPos(UNDEFINED, UNDEFINED);
index 7e40cce..097d827 100644 (file)
@@ -63,9 +63,12 @@ public:
     /**
     * @brief Setter for zoom level
     *
-    * @param zoomLevel Zoom level
+    * Does also set the zValue.
+    *
+    * @param tileZoomLevel Zoom level of the tile
+    * @param currentViewZoomLevel Current view zoom level
     */
-    void setZoomLevel(int zoomLevel);
+    void setZoomLevel(int tileZoomLevel, int currentViewZoomLevel);
 
     /**
     * @brief Getter for tile number
index 9f6ba4c..47770c1 100644 (file)
 #include <QDebug>
 #include <QMouseEvent>
 
-#ifndef Q_WS_MAEMO_5
-//   #include <QGLWidget>
-#endif // Q_WS_MAEMO_5
-
 #include "mapcommon.h"
 #include "mapview.h"
 
 MapView::MapView(QWidget *parent)
     : QGraphicsView(parent)
-    , m_timerID(NULL)
 {
-/**
-  * Use OpenGL for desktop to gain some performance in map view.
-  * OpenGL can't be used in scratchbox.
-  */
-#ifndef Q_WS_MAEMO_5
-  //  setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer)));
-#endif // !Q_WS_MAEMO_5
-
     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+    m_zoomAnimation = new QPropertyAnimation(this, "viewScale", this);
+    connect(m_zoomAnimation, SIGNAL(finished()), this, SIGNAL(viewZoomFinished()));
 }
 
 void MapView::setZoomLevel(int zoomLevel)
 {
-    m_zoomTargetScale = pow(2, zoomLevel - MAX_MAP_ZOOM_LEVEL);
-    m_zoomScaleDelta = (m_zoomTargetScale - currentScale()) / (ZOOM_FPS * (ZOOM_TIME / 1000));
+    m_zoomAnimation->stop();
+    m_zoomAnimation->setDuration(ZOOM_TIME);
+    m_zoomAnimation->setStartValue(viewScale());
+    m_zoomAnimation->setEndValue(pow(2, zoomLevel - MAX_MAP_ZOOM_LEVEL));
 
-    if (m_timerID)
-        killTimer(m_timerID);
-
-    m_timerID = startTimer(1000/ZOOM_FPS);
+    m_zoomAnimation->start();
 }
 
-void MapView::timerEvent(QTimerEvent *event)
+qreal MapView::currentScale()
 {
-    if (event->timerId() == m_timerID) {
-        bool finished = false;
-        qreal scaleFactor = currentScale();
-
-//        qDebug() << __PRETTY_FUNCTION__
-//                 << "abs(m_zoomTargetScale - scaleFactor)" << fabs(m_zoomTargetScale - scaleFactor)
-//                 << "abs(m_zoomScaleDelta)" << fabs(m_zoomScaleDelta);
-
-        if (fabs(m_zoomTargetScale - scaleFactor) <= fabs(m_zoomScaleDelta)) {
-            scaleFactor = m_zoomTargetScale;
-            killTimer(event->timerId());
-            finished = true;
-        }
-        else {
-            scaleFactor += m_zoomScaleDelta;
-        }
-
-//        qDebug() << __PRETTY_FUNCTION__ << "currentScale:" << currentScale()
-//                                        << "m_zoomScaleDelta" << m_zoomScaleDelta
-//                                        << "scaleFactor:" << scaleFactor;
-
-        QTransform transform;
-        transform.scale(scaleFactor, scaleFactor);
-        setTransform(transform);
-       emit viewContentChanged(mapToScene(viewport()->x(), viewport()->y()).toPoint());
-
-        if (finished && m_zoomScaleDelta > 0)
-            emit viewZoomInFinished();
-    }
+    QTransform currentTransform = transform();
+    return currentTransform.m11();
 }
 
-qreal MapView::currentScale()
+qreal MapView::viewScale()
 {
     QTransform currentTransform = transform();
     return currentTransform.m11();
 }
 
+void MapView::setViewScale(qreal viewScale)
+{
+    QTransform transform;
+    transform.scale(viewScale, viewScale);
+    setTransform(transform);
+    emit viewContentChanged(mapToScene(viewport()->x(), viewport()->y()).toPoint());
+}
+
 void MapView::mouseMoveEvent(QMouseEvent *event)
 {
     m_scenePosition += m_mousePosition - mapToScene(event->pos()).toPoint();
 
     emit viewScrolled(m_scenePosition);
-//    qDebug() << __PRETTY_FUNCTION__ << "m_scenePosition:" << m_scenePosition;
+    qDebug() << __PRETTY_FUNCTION__ << "m_scenePosition:" << m_scenePosition;
 
     m_mousePosition = mapToScene(event->pos()).toPoint();
     emit viewContentChanged(mapToScene(viewport()->x(), viewport()->y()).toPoint());
@@ -118,13 +88,13 @@ void MapView::mousePressEvent(QMouseEvent *event)
 
 void MapView::centerToSceneCoordinates(QPoint sceneCoordinate)
 {
-//    qDebug() << __PRETTY_FUNCTION__ << "sceneCoordinate" << sceneCoordinate;
+    qDebug() << __PRETTY_FUNCTION__ << "sceneCoordinate" << sceneCoordinate;
     centerOn(sceneCoordinate);
 }
 
 void MapView::resizeEvent(QResizeEvent *event)
 {
-//    qDebug() << "Resize event: " << event->size();
+    qDebug() << __PRETTY_FUNCTION__ << event->size();
     emit viewResized(event->size());
     emit viewContentChanged(mapToScene(viewport()->x(), viewport()->y()).toPoint());
 }
index 7f13f52..a5651dc 100644 (file)
@@ -23,6 +23,7 @@
 #define MAPVIEW_H
 
 #include <QGraphicsView>
+#include <QPropertyAnimation>
 
 /**
 * @brief Map view widget
@@ -33,6 +34,13 @@ class MapView : public QGraphicsView
 {
     Q_OBJECT
 
+    /**
+    * @brief View scaling
+    *
+    * @property viewScale
+    */
+    Q_PROPERTY(qreal viewScale READ viewScale WRITE setViewScale)
+
 public:
     /**
     * @brief Constructor
@@ -71,13 +79,6 @@ private:
     */
     void mousePressEvent(QMouseEvent *event);
 
-    /**
-    * @brief Event handler for timer events, used for smooth zoom effect
-    *
-    * @param event
-    */
-    void timerEvent(QTimerEvent *event);
-
 /*******************************************************************************
  * MEMBER FUNCTIONS AND SLOTS
  ******************************************************************************/
@@ -104,6 +105,20 @@ private:
     */
     qreal currentScale();
 
+    /**
+    * @brief Set new view scale
+    *
+    * @param viewScale New scaling factor
+    */
+    void setViewScale(qreal viewScale);
+
+    /**
+    * @brief Get current view scale
+    *
+    * @return Current view scaling factor
+    */
+    qreal viewScale();
+
 /*******************************************************************************
  * SIGNALS
  ******************************************************************************/
@@ -125,10 +140,10 @@ signals:
     void viewScrolled(QPoint sceneCoordinate);
 
     /**
-    * @brief Signal for informing that zooming in is finished
+    * @brief Signal for informing that zooming animation is finished
     *
     */
-    void viewZoomInFinished();
+    void viewZoomFinished();
 
     /**
     * @brief Signal for updating view content
@@ -144,9 +159,7 @@ signals:
 private:
     QPoint m_mousePosition; ///< Previous mouse event position
     QPoint m_scenePosition; ///< New center position
-    int m_timerID; ///< ID number of the timer used for smooth zoom effect
-    qreal m_zoomScaleDelta; ///< Scaling factor delta for smooth zoom transition effect
-    qreal m_zoomTargetScale; ///< Scaling factor of the target zoom level
+    QPropertyAnimation *m_zoomAnimation; ///< Zoom animation
 };
 
 #endif // MAPVIEW_H
index 08087ab..53d075c 100644 (file)
@@ -101,7 +101,6 @@ signals:
  * DATA MEMBERS
  ******************************************************************************/
 private:
-
     QList<QNetworkReply*> m_currentDownloads; ///< List of current downloads
     QQueue<QUrl> m_downloadQueue;             ///< Queue of pending requests
     QNetworkAccessManager *m_manager;       ///< Network access manager
index 9afb198..044d8ee 100644 (file)
@@ -63,13 +63,7 @@ HEADERS += ui/mainwindow.h \
 QT += network \
     webkit
 
-# use don't use OpenGL when building in scratchbox
 !maemo5 { 
-#    QT += opengl
-    message(OpenGL built in)
-    message(Make sure you have OpenGL development headers installed)
-    message(install headers with: sudo apt-get install libgl-dev libglu-dev)
-
     message(QJson built in)
     message(Make sure you have QJson development headers installed)
     message(install headers with: sudo apt-get install libqjson-dev)
index b2e6b92..cf11954 100644 (file)
@@ -39,7 +39,7 @@ MapViewScreen::MapViewScreen(QWidget *parent)
     connect(mapView, SIGNAL(viewResized(QSize)), mapEngine, SLOT(viewResized(QSize)));
     connect(mapView, SIGNAL(viewContentChanged(QPoint)),
             mapEngine, SLOT(alignImmovableItems(QPoint)));
-    connect(mapView, SIGNAL(viewZoomInFinished()), mapEngine, SLOT(viewZoomInFinished()));
+    connect(mapView, SIGNAL(viewZoomFinished()), mapEngine, SLOT(viewZoomFinished()));
 
     QHBoxLayout *mapViewLayout = new QHBoxLayout;
     //DEBUG