Merge branch 'master' into map
authorPekka Nissinen <pekka.nissinen@ixonos.com>
Wed, 28 Apr 2010 07:16:22 +0000 (10:16 +0300)
committerPekka Nissinen <pekka.nissinen@ixonos.com>
Wed, 28 Apr 2010 07:16:22 +0000 (10:16 +0300)
Conflicts:
src/images.qrc
src/map/mapfetcher.cpp

19 files changed:
doc/map/map_class_diagram.dia [new file with mode: 0644]
res/images/zoom_in.png [new file with mode: 0755]
res/images/zoom_out.png [new file with mode: 0755]
src/map/mapbutton.cpp [new file with mode: 0644]
src/map/mapbutton.h [new file with mode: 0644]
src/map/mapcommon.h
src/map/mapengine.cpp
src/map/mapengine.h
src/map/mapfetcher.cpp
src/map/mapscene.cpp
src/map/mapscene.h
src/map/mapview.cpp
src/map/mapview.h
src/map/mapzoompanel.cpp [new file with mode: 0644]
src/map/mapzoompanel.h [new file with mode: 0644]
src/resources/zoom_in.png [new file with mode: 0644]
src/resources/zoom_out.png [new file with mode: 0644]
src/src.pro
src/ui/mapviewscreen.cpp

diff --git a/doc/map/map_class_diagram.dia b/doc/map/map_class_diagram.dia
new file mode 100644 (file)
index 0000000..a255926
Binary files /dev/null and b/doc/map/map_class_diagram.dia differ
diff --git a/res/images/zoom_in.png b/res/images/zoom_in.png
new file mode 100755 (executable)
index 0000000..0c8fd51
Binary files /dev/null and b/res/images/zoom_in.png differ
diff --git a/res/images/zoom_out.png b/res/images/zoom_out.png
new file mode 100755 (executable)
index 0000000..8b45cb5
Binary files /dev/null and b/res/images/zoom_out.png differ
diff --git a/src/map/mapbutton.cpp b/src/map/mapbutton.cpp
new file mode 100644 (file)
index 0000000..4c73cc3
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+   Situare - A location system for Facebook
+   Copyright (C) 2010  Ixonos Plc. Authors:
+
+       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
+   version 2 as published by the Free Software Foundation.
+
+   Situare is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Situare; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+   USA.
+*/
+
+#include <QDebug>
+#include <QPixmap>
+
+#include "mapbutton.h"
+#include "mapcommon.h"
+
+MapButton::MapButton(QString fileName)
+    : m_buttonMode(QIcon::Normal),
+    m_buttonWidth(MAP_ZOOM_PANEL_BUTTON_SIZE),
+    m_buttonHeight(MAP_ZOOM_PANEL_BUTTON_SIZE)
+{
+    QPixmap pixmap(fileName);
+
+    // Temporary (lazy fix) solution to get the buttons larger
+    addPixmap(pixmap.scaled(m_buttonWidth, m_buttonHeight, Qt::KeepAspectRatio, Qt::FastTransformation));
+}
+
+void MapButton::draw(QPainter *painter, int x, int y)
+{
+    paint(painter, x, y, m_buttonWidth, m_buttonHeight, NULL, m_buttonMode);
+}
+
+void MapButton::setMode(QIcon::Mode mode)
+{
+    m_buttonMode = mode;
+}
diff --git a/src/map/mapbutton.h b/src/map/mapbutton.h
new file mode 100644 (file)
index 0000000..137e340
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+   Situare - A location system for Facebook
+   Copyright (C) 2010  Ixonos Plc. Authors:
+
+       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
+   version 2 as published by the Free Software Foundation.
+
+   Situare is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Situare; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+   USA.
+*/
+
+#ifndef MAPBUTTON_H
+#define MAPBUTTON_H
+
+#include <QIcon>
+#include <QString>
+#include <QPainter>
+
+class MapButton : public QIcon
+{
+public:
+    MapButton(QString fileName);
+    void draw(QPainter *painter, int x, int y);
+    void setMode(QIcon::Mode mode);
+
+private:
+    QIcon::Mode m_buttonMode;
+    int m_buttonWidth;
+    int m_buttonHeight;
+};
+
+#endif // MAPBUTTON_H
index 2ebb115..6435843 100644 (file)
@@ -35,6 +35,12 @@ const int MIN_MAP_SCENE_NORMAL_LEVEL = MAX_MAP_ZOOM_LEVEL + 1;
 const int ZOOM_FPS = 30; ///< FPS for the zoom effect
 const qreal ZOOM_TIME = 250; ///< Length of the zoom effect (ms)
 
+static const int MAP_ZOOM_PANEL_POSITION_X = 10; ///< Horizontal position of zoom panel
+static const int MAP_ZOOM_PANEL_POSITION_Y = 10; ///< Vertical position of zoom panel
+static const int MAP_ZOOM_PANEL_LEVEL = MIN_MAP_SCENE_NORMAL_LEVEL
+                                        + MAX_MAP_ZOOM_LEVEL + 2; ///< Zepth of zoom panel (Z-axis)
+static const int MAP_ZOOM_PANEL_BUTTON_SIZE = 48; ///< Size of a zoom panel button
+
 const qreal MAX_LATITUDE = 85.05112877980659237802;  ///< Maximum latitude value
 const qreal MIN_LATITUDE = -MAX_LATITUDE; ///< Minimum latitude value
 const qreal MIN_LONGITUDE = -180.0;  ///< Minimum longitude value
index f05a470..4617284 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
@@ -43,6 +44,11 @@ MapEngine::MapEngine(QObject *parent)
     connect(this, SIGNAL(fetchImage(QUrl)), m_mapFetcher, SLOT(fetchMapImage(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()));
 }
 
 void MapEngine::init()
@@ -91,17 +97,16 @@ void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
 
     parseURL(url, zoom, x, y);
     QString hashKey = tilePath(zoom, x, y);
-    if (!m_mapTilesInScene.contains(hashKey)) {
+    if (!m_mapScene->isTileInScene(hashKey)) {
 
         MapTile *mapTile = new MapTile();
         mapTile->setZoomLevel(zoom);
         mapTile->setTileNumber(QPoint(x, y));
         mapTile->setPixmap(pixmap);
 
-        m_mapTilesInScene.insert(hashKey, mapTile);
-        m_mapScene->addMapTile(mapTile);
+        m_mapScene->addTile(mapTile, hashKey);
 
-        removeStackedTiles(mapTile);
+        m_mapScene->removeStackedTiles(mapTile, viewRect());
    }
 }
 
@@ -126,16 +131,23 @@ QRect MapEngine::calculateTileGrid(QPoint sceneCoordinate)
     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 (isCenterTileChanged(sceneCoordinate)) {
         getTiles(sceneCoordinate);
-        removeTilesOutOfView();
+        m_mapScene->removeOutOfViewTiles(viewRect());
     }
 }
 
@@ -179,154 +191,61 @@ void MapEngine::getTiles(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)
+QRect MapEngine::viewRect()
 {
-    //qDebug() << __PRETTY_FUNCTION__;
-
-    if (tile) {
-       m_mapTilesInScene.remove(tilePath(tile->zoomLevel(), tile->tileNumber().x(),
-                                         tile->tileNumber().y()));
-       m_mapScene->removeItem(tile);
-       delete tile;
-    }
-}
-
-void MapEngine::removeTilesOutOfView()
-{
-    //qDebug() << __PRETTY_FUNCTION__;
-
     QPoint topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel, m_viewGrid.topLeft());
     QPoint 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();
-
-    //Remove tiles which are in view from allTiles
-    foreach (QGraphicsItem *tile, viewTiles)
-        allTiles.removeOne(tile);
-
-    //Remove tiles out of view
-    foreach (QGraphicsItem *tile, allTiles) {
-        MapTile *tileToRemove = dynamic_cast<MapTile *>(tile);
-        removeTile(tileToRemove);
-    }
-}
-
-void MapEngine::removeStackedTiles(MapTile *newTile)
-{
-    //qDebug() << __PRETTY_FUNCTION__;
-
-    QRectF newTileSceneRect = newTile->sceneBoundingRect();
-    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);
-            }
-        }
-    }
-}
-
-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 (count < 4)
-        combined = QRectF();
-
-    return combined;
+    return QRect(topLeft, bottomRight);
 }
 
 void MapEngine::viewResized(const QSize &size)
 {
     m_viewSize = size;
     getTiles(m_sceneCoordinate);
-    removeTilesOutOfView();
+    m_mapScene->removeOutOfViewTiles(viewRect());
 }
 
-void MapEngine::zoomIn()
+void MapEngine::viewZoomInFinished()
 {
     qDebug() << __PRETTY_FUNCTION__;
+    m_mapScene->removeOutOfViewTiles(viewRect());
+}
+
+void MapEngine::zoomIn()
+{
+//    qDebug() << __PRETTY_FUNCTION__;
 
     if (m_zoomLevel < MAX_MAP_ZOOM_LEVEL) {
         m_zoomLevel++;
         emit zoomLevelChanged(m_zoomLevel);
 
-        setTilesDrawingLevels();
+        m_mapScene->setTilesDrawingLevels(m_zoomLevel);
 
         getTiles(m_sceneCoordinate);
-
-        // remove unused tiles after zooming is done
-        QTimer::singleShot(ZOOM_TIME*2, this, SLOT(removeTilesOutOfView()));
     }
 }
 
 void MapEngine::zoomOut()
 {
-    qDebug() << __PRETTY_FUNCTION__;
+//    qDebug() << __PRETTY_FUNCTION__;
 
     if (m_zoomLevel > MIN_MAP_ZOOM_LEVEL) {
         m_zoomLevel--;
         emit zoomLevelChanged(m_zoomLevel);
 
-        setTilesDrawingLevels();
+        m_mapScene->setTilesDrawingLevels(m_zoomLevel);
 
         getTiles(m_sceneCoordinate);
     }
 }
 
-void MapEngine::setTilesDrawingLevels()
-{
-    //qDebug() << __PRETTY_FUNCTION__ << "m_zoomLevel:" << m_zoomLevel;
-
-    QList<QGraphicsItem *> items = m_mapScene->items();
-
-    for (int i = 0; i < items.size(); ++i) {
-        MapTile *item = dynamic_cast<MapTile *>(items.at(i));
-        if (item)
-            item->setSceneLevel(m_zoomLevel);
-    }
-
-}
-
 QString MapEngine::tilePath(int zoomLevel, int x, int y)
 {
     QString tilePathString(QString::number(zoomLevel) + "/");
@@ -336,12 +255,6 @@ QString MapEngine::tilePath(int zoomLevel, int x, int y)
     return tilePathString;
 }
 
-void MapEngine::scalingFactorChanged(qreal scaleFactor)
-{
-    qDebug() << __PRETTY_FUNCTION__;
-    Q_UNUSED(scaleFactor);
-}
-
 QPoint MapEngine::convertSceneCoordinateToTileNumber(int zoomLevel, QPoint sceneCoordinate)
 {
     int pow = 1 << (MAX_MAP_ZOOM_LEVEL - zoomLevel);
index 9e202f5..4b156ab 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
@@ -29,6 +30,7 @@
 #include "mapfetcher.h"
 #include "mapscene.h"
 #include "maptile.h"
+#include "mapzoompanel.h"
 
 /**
 * @brief Map engine
@@ -37,6 +39,7 @@
 * converting coordinates.
 * @author Sami Rämö - sami.ramo (at) ixonos.com
 * @author Jussi Laitinen - jussi.laitinen (at) ixonos.com
+* @author Pekka Nissinen - pekka.nissinen (at) ixonos.com
 */
 class MapEngine : public QObject
 {
@@ -50,8 +53,9 @@ public:
     MapEngine(QObject *parent = 0);
 
 /*******************************************************************************
- * CLASS SPECIFIC MEMBER FUNCTIONS AND SLOTS
+ * MEMBER FUNCTIONS AND SLOTS
  ******************************************************************************/
+public:
     /**
     * @brief Convert latitude and longitude to scene coordinates.
     *
@@ -102,8 +106,25 @@ public:
     */
     QGraphicsScene* scene();
 
+    /**
+    * @brief Return tile path created from tile values.
+    *
+    * @param zoomLevel tile's zoom level
+    * @param x tile's x value
+    * @param y tile's y value
+    * @return QString tile path
+    */
+    static QString tilePath(int zoomLevel, int x, int y);
+
 public slots:
     /**
+    * @brief Slot for immovable scene items position correction
+    *
+    * @param viewTopLeft Scene coordinate of the viewport top left corner
+    */
+    void alignImmovableItems(QPoint viewTopLeft);
+
+    /**
     * @brief Slot for setting current view location
     *
     * Emits locationChanged signal.
@@ -141,7 +162,8 @@ private:
     /**
     * @brief Get new tiles.
     *
-    * Calculates which tiles has to be fetched.
+    * Calculates which tiles has to be fetched. Does emit fetchImage for tiles which
+    * aren't already in the scene.
     * @param sceneCoordinate scene's center coordinate
     */
     void getTiles(QPoint sceneCoordinate);
@@ -155,15 +177,6 @@ private:
     bool isCenterTileChanged(QPoint sceneCoordinate);
 
     /**
-    * @brief Combine tiles' rectangles to one rectangle.
-    *
-    * @param parentTile parent tile not to combine
-    * @param stackedTiles tiles to combine
-    * @return QRectF resulting rectangle
-    */
-    QRectF combineTiles(QGraphicsItem *parentTile, const QList<QGraphicsItem*> &stackedTiles);
-
-    /**
     * @brief Parse given URL to zoom, x and y values. Parsed values are
     * placed in variables given as parameters.
     *
@@ -175,31 +188,6 @@ private:
     void parseURL(const QUrl &url, int &zoom, int &x, int &y);
 
     /**
-    * @brief Remove tiles which are stacked.
-    *
-    * Iterate through tiles which are under this map tile and remove obscured
-    * tiles.
-    *
-    * @param newTile new tile covering old tiles
-    */
-    void removeStackedTiles(MapTile *newTile);
-
-    /**
-    * @brief Remove tile.
-    *
-    * Removes tile from scene and list of current tiles in scene.
-    * @param tile MapTile to remove
-    */
-    void removeTile(MapTile *tile);
-
-    /**
-    * @brief Set drawing order of all tiles in the scene
-    *
-    * Check MapTile::setSceneLevel for more information.
-    */
-    void setTilesDrawingLevels();
-
-    /**
     * @brief Calculate maximum value for tile in this zoom level.
     *
     * @param zoomLevel zoom level
@@ -208,14 +196,11 @@ private:
     int tileMaxValue(int zoomLevel);
 
     /**
-    * @brief Return tile path created from tile values.
+    * @brief Returns the current view rect including margins
     *
-    * @param zoomLevel tile's zoom level
-    * @param x tile's x value
-    * @param y tile's y value
-    * @return QString tile path
+    * @return Current view rect
     */
-    QString tilePath(int zoomLevel, int x, int y);
+    QRect viewRect();
 
 private slots:
     /**
@@ -228,18 +213,11 @@ private slots:
     void mapImageReceived(const QUrl &url, const QPixmap &pixmap);
 
     /**
-    * @brief Remove tiles which are out of view bounds.
-    */
-    void removeTilesOutOfView();
-
-    /**
-    * @brief Slot for view scaling factor change events
+    * @brief Slot for actions after view zoom is finished
     *
-    * Can be used to trigger scaling of zoom buttons, friend indicators and other
-    * MapScene elements which should retain their visual size
-    * @param scaleFactor view's scale factor
+    * Does run removeOutOfViewTiles
     */
-    void scalingFactorChanged(qreal scaleFactor);
+    void viewZoomInFinished();
 
     /**
     * @brief Slot for zooming in
@@ -282,13 +260,13 @@ signals:
  * DATA MEMBERS
  ******************************************************************************/
 private:
-    QPoint m_centerTile;    ///< Current center tile
     MapFetcher *m_mapFetcher; ///< Fetcher for map tiles
     MapScene *m_mapScene; ///< Scene for map tiles
-    QHash<QString, MapTile *> m_mapTilesInScene;  ///< List of map tiles in map scene
-    QPoint m_sceneCoordinate;  ///< Current center coordinate
-    QRect m_viewGrid; ///< Current grid of tiles in view
-    QSize m_viewSize;   ///< Current view size
+    MapZoomPanel *m_mapZoomPanel; ///< Toolbar for zoom buttons
+    QPoint m_centerTile; ///< Current center tile
+    QPoint m_sceneCoordinate; ///< Current center coordinate
+    QRect m_viewGrid; ///< Current grid of tiles in view (includes margin)
+    QSize m_viewSize; ///< Current view size
     int m_zoomLevel; ///< Current zoom level
 };
 
index 731a123..5818906 100644 (file)
@@ -75,7 +75,11 @@ bool MapFetcher::loadImageFromCache(const QUrl &url)
 
         QNetworkCacheMetaData metaData = cache->metaData(url);
 
+<<<<<<< HEAD:src/map/mapfetcher.cpp
+        if (metaData.expirationDate().isValid()) {
+=======
         if ((metaData.expirationDate().isValid()) && (url.isValid())) {
+>>>>>>> master:src/map/mapfetcher.cpp
 
             if (metaData.expirationDate() < QDateTime::currentDateTime()) {
                 cache->remove(url);
@@ -83,7 +87,11 @@ bool MapFetcher::loadImageFromCache(const QUrl &url)
             }
         }
 
+<<<<<<< HEAD:src/map/mapfetcher.cpp
+        QIODevice *cacheImage = m_manager->cache()->data(url);
+=======
         QIODevice *cacheImage = cache->data(url);
+>>>>>>> master:src/map/mapfetcher.cpp
 
         if (cacheImage) {
             QImage image;
index f7b55ba..8889744 100644 (file)
@@ -33,7 +33,99 @@ MapScene::MapScene(QObject *parent)
     setSceneRect(0, 0, maxPixelsX, maxPixelsY);
 }
 
-void MapScene::addMapTile(MapTile *mapTile)
+void MapScene::addTile(MapTile *mapTile, QString hashKey)
 {
+    m_mapTilesInScene.insert(hashKey, mapTile);
     addItem(mapTile);
 }
+
+bool MapScene::isTileInScene(QString hashKey)
+{
+    return m_mapTilesInScene.contains(hashKey);
+}
+
+void MapScene::removeOutOfViewTiles(QRect viewRect)
+{
+//    qDebug() << __PRETTY_FUNCTION__;
+
+    QList<QGraphicsItem *> viewTiles = items(viewRect, Qt::ContainsItemBoundingRect);
+    QList<QGraphicsItem *> allTiles = items();
+
+//    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)
+        allTiles.removeOne(tile);
+
+
+    //Remove tiles out of view
+    foreach (QGraphicsItem *tile, allTiles) {
+        MapTile *tileToRemove = dynamic_cast<MapTile *>(tile);
+        if (tileToRemove)
+            removeTile(tileToRemove);
+    }
+}
+
+void MapScene::removeStackedTiles(MapTile *newTile, QRect viewRect)
+{
+//    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);
+            }
+        }
+    }
+//    qDebug() << __PRETTY_FUNCTION__ << "All tiles after:"
+//             << newTile->collidingItems(Qt::IntersectsItemBoundingRect).count();
+}
+
+
+void MapScene::removeTile(MapTile *tile)
+{
+//    qDebug() << __PRETTY_FUNCTION__;
+
+    if (tile) {
+        m_mapTilesInScene.remove(MapEngine::tilePath(tile->zoomLevel(),
+                                                     tile->tileNumber().x(),
+                                                     tile->tileNumber().y()));
+       removeItem(tile);
+       delete tile;
+    }
+}
+
+void MapScene::setTilesDrawingLevels(int zoomLevel)
+{
+//    qDebug() << __PRETTY_FUNCTION__ << "m_zoomLevel:" << m_zoomLevel;
+
+    QList<QGraphicsItem *> allItems = items();
+
+    for (int i = 0; i < allItems.size(); ++i) {
+        MapTile *item = dynamic_cast<MapTile *>(allItems.at(i));
+        if (item)
+            item->setSceneLevel(zoomLevel);
+    }
+}
index 4ba5896..7c6c446 100644 (file)
@@ -43,14 +43,64 @@ public:
     MapScene(QObject *parent = 0);
 
 /*******************************************************************************
- * CLASS SPECIFIC MEMBER FUNCTIONS AND SLOTS
+ * MEMBER FUNCTIONS AND SLOTS
  ******************************************************************************/
+public:
     /**
     * @brief Add MapTile item to scene
     *
     * @param mapTile Map tile item to be added
+    * @param hashKey Hash key for the tile
     */
-    void addMapTile(MapTile *mapTile);
+    void addTile(MapTile *mapTile, QString hashKey);
+
+    /**
+    * @brief Returns if tile mathcing hash key is already in the scene
+    *
+    * @param hashKey
+    * @return True if tile was in the scene, otherwise false
+    */
+    bool isTileInScene(QString hashKey);
+
+    /**
+    * @brief Remove tiles which are out of view bounds.
+    *
+    * @param viewRect Current view rect
+    */
+    void removeOutOfViewTiles(QRect viewRect);
+
+    /**
+    * @brief Remove tiles which are stacked.
+    *
+    * Iterate through tiles which are under this map tile and remove obscured
+    * tiles.
+    *
+    * @param newTile new tile covering old tiles
+    * @param viewRect Current view rect
+    */
+    void removeStackedTiles(MapTile *newTile, QRect viewRect);
+
+    /**
+    * @brief Remove tile.
+    *
+    * Removes tile from scene and list of current tiles in scene.
+    * @param tile MapTile to remove
+    */
+    void removeTile(MapTile *tile);
+
+    /**
+    * @brief Set drawing order of all tiles in the scene
+    *
+    * Check MapTile::setSceneLevel for more information.
+    * @param zoomLevel Current zoom level
+    */
+    void setTilesDrawingLevels(int zoomLevel);
+
+/*******************************************************************************
+ * DATA MEMBERS
+ ******************************************************************************/
+private:
+    QHash<QString, MapTile *> m_mapTilesInScene;  ///< List of map tiles in map scene
 };
 
 #endif // MAPSCENE_H
index cf8c27c..15de9cb 100644 (file)
@@ -61,6 +61,7 @@ void MapView::setZoomLevel(int zoomLevel)
 void MapView::timerEvent(QTimerEvent *event)
 {
     if (event->timerId() == m_timerID) {
+        bool finished = false;
         qreal scaleFactor = currentScale();
 
 //        qDebug() << __PRETTY_FUNCTION__
@@ -70,6 +71,7 @@ void MapView::timerEvent(QTimerEvent *event)
         if (fabs(m_zoomTargetScale - scaleFactor) <= fabs(m_zoomScaleDelta)) {
             scaleFactor = m_zoomTargetScale;
             killTimer(event->timerId());
+            finished = true;
         }
         else {
             scaleFactor += m_zoomScaleDelta;
@@ -81,8 +83,11 @@ void MapView::timerEvent(QTimerEvent *event)
 
         QTransform transform;
         transform.scale(scaleFactor, scaleFactor);
-        emit scalingFactorChanged(scaleFactor);
         setTransform(transform);
+       emit viewContentChanged(mapToScene(viewport()->x(), viewport()->y()).toPoint());
+
+        if (finished && m_zoomScaleDelta > 0)
+            emit viewZoomInFinished();
     }
 }
 
@@ -97,18 +102,20 @@ 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());
 }
 
 void MapView::mousePressEvent(QMouseEvent *event)
 {
+    QGraphicsView::mousePressEvent(event);
+
     m_mousePosition = mapToScene(event->pos()).toPoint();
     m_scenePosition = mapToScene(width() / 2 - 1, height() / 2 - 1).toPoint();
 }
 
-
 void MapView::centerToSceneCoordinates(QPoint sceneCoordinate)
 {
 //    qDebug() << __PRETTY_FUNCTION__ << "sceneCoordinate" << sceneCoordinate;
@@ -117,6 +124,7 @@ void MapView::centerToSceneCoordinates(QPoint sceneCoordinate)
 
 void MapView::resizeEvent(QResizeEvent *event)
 {
-    //qDebug() << "Resize event: " << event->size();
+//    qDebug() << "Resize event: " << event->size();
     emit viewResized(event->size());
+    emit viewContentChanged(mapToScene(viewport()->x(), viewport()->y()).toPoint());
 }
index 7ad9005..7f13f52 100644 (file)
@@ -32,6 +32,7 @@
 class MapView : public QGraphicsView
 {
     Q_OBJECT
+
 public:
     /**
     * @brief Constructor
@@ -108,15 +109,6 @@ private:
  ******************************************************************************/
 signals:
     /**
-    * @brief Signal for view scale factor change events
-    *
-    * Can be used to trigger scaling of zoom buttons, friend indicators and other
-    * MapScene elements which should retain their visual size
-    * @param scaleFactor view's scale factor
-    */
-    void scalingFactorChanged(qreal scaleFactor);
-
-    /**
     * @brief Signal for view resize events.
     *
     * Signal is emitted when view has been resized.
@@ -132,6 +124,20 @@ signals:
     */
     void viewScrolled(QPoint sceneCoordinate);
 
+    /**
+    * @brief Signal for informing that zooming in is finished
+    *
+    */
+    void viewZoomInFinished();
+
+    /**
+    * @brief Signal for updating view content
+    *
+    * Signal is emitted when view content needs an update.
+    * @param viewTopLeft Scene coordinate of the viewport top left corner
+    */
+    void viewContentChanged(QPoint viewTopLeft);
+
 /*******************************************************************************
  * DATA MEMBERS
  ******************************************************************************/
diff --git a/src/map/mapzoompanel.cpp b/src/map/mapzoompanel.cpp
new file mode 100644 (file)
index 0000000..361f7d4
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+   Situare - A location system for Facebook
+   Copyright (C) 2010  Ixonos Plc. Authors:
+
+       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
+   version 2 as published by the Free Software Foundation.
+
+   Situare is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Situare; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+   USA.
+*/
+
+#include <QDebug>
+
+#include "mapcommon.h"
+#include "mapzoompanel.h"
+
+MapZoomPanel::MapZoomPanel(QGraphicsItem *parent, int x, int y) : QGraphicsItem(parent)
+{
+    m_x = x;
+    m_y = y;
+    m_width = MAP_ZOOM_PANEL_BUTTON_SIZE;
+    m_height = MAP_ZOOM_PANEL_BUTTON_SIZE * 2;
+
+    m_zoomInBtn = new MapButton(":/resources/zoom_in.png");
+    m_zoomOutBtn = new MapButton(":/resources/zoom_out.png");
+
+    setFlag(QGraphicsItem::ItemIgnoresTransformations);
+    setZValue(static_cast<qreal>(MAP_ZOOM_PANEL_LEVEL));
+}
+
+QRectF MapZoomPanel::boundingRect() const
+{
+    return QRectF(m_x, m_y, m_width, m_height);
+}
+
+void MapZoomPanel::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    Q_UNUSED(option);
+    Q_UNUSED(widget);
+
+    m_zoomInBtn->draw(painter, m_x, m_y);
+    m_zoomOutBtn->draw(painter, m_x, m_y + MAP_ZOOM_PANEL_BUTTON_SIZE);
+}
+
+void MapZoomPanel::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    if ( event->pos().y() < (m_y + MAP_ZOOM_PANEL_BUTTON_SIZE) )
+        m_zoomInBtn->setMode(QIcon::Selected);
+    else
+        m_zoomOutBtn->setMode(QIcon::Selected);
+
+    update();
+
+//    qDebug() << __PRETTY_FUNCTION__;
+}
+
+void MapZoomPanel::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    Q_UNUSED(event);
+
+    m_zoomInBtn->setMode(QIcon::Normal);
+    m_zoomOutBtn->setMode(QIcon::Normal);
+
+    if ( event->pos().y() < (m_y + MAP_ZOOM_PANEL_BUTTON_SIZE) )
+        emit zoomInPressed();
+    else
+        emit zoomOutPressed();
+
+    update();
+
+//    qDebug() << __PRETTY_FUNCTION__;
+}
diff --git a/src/map/mapzoompanel.h b/src/map/mapzoompanel.h
new file mode 100644 (file)
index 0000000..c136ad3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+   Situare - A location system for Facebook
+   Copyright (C) 2010  Ixonos Plc. Authors:
+
+       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
+   version 2 as published by the Free Software Foundation.
+
+   Situare is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Situare; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+   USA.
+*/
+
+#ifndef MAPZOOMPANEL_H
+#define MAPZOOMPANEL_H
+
+#include <QRectF>
+#include <QWidget>
+#include <QPainter>
+#include <QGraphicsItem>
+#include <QStyleOptionGraphicsItem>
+#include <QGraphicsSceneMouseEvent>
+
+#include "mapbutton.h"
+
+class MapZoomPanel : public QObject, public QGraphicsItem
+{
+    Q_OBJECT
+
+public:
+    MapZoomPanel(QGraphicsItem *parent = 0, int x = 0, int y = 0);
+    QRectF boundingRect() const;
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+protected:
+    void mousePressEvent(QGraphicsSceneMouseEvent *event);
+    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+signals:
+    void zoomInPressed();
+    void zoomOutPressed();
+
+private:
+    MapButton *m_zoomInBtn;
+    MapButton *m_zoomOutBtn;
+
+    qreal m_x;
+    qreal m_y;
+    qreal m_width;
+    qreal m_height;
+};
+
+#endif // MAPZOOMPANEL_H
diff --git a/src/resources/zoom_in.png b/src/resources/zoom_in.png
new file mode 100644 (file)
index 0000000..c2a84fc
Binary files /dev/null and b/src/resources/zoom_in.png differ
diff --git a/src/resources/zoom_out.png b/src/resources/zoom_out.png
new file mode 100644 (file)
index 0000000..ba6ffbc
Binary files /dev/null and b/src/resources/zoom_out.png differ
index 97140ac..0392109 100644 (file)
@@ -19,6 +19,8 @@ SOURCES += main.cpp \
     map/mapscene.cpp \
     map/maptile.cpp \
     map/mapfetcher.cpp \
+    map/mapzoompanel.cpp \
+    map/mapbutton.cpp \
     ui/pixmap.cpp \
     ui/infotab.cpp \
     ui/updatelocation/updatelocationdialog.cpp \
@@ -33,6 +35,8 @@ HEADERS += ui/mainwindow.h \
     map/maptile.h \
     map/mapfetcher.h \
     map/mapcommon.h \
+    map/mapzoompanel.h \
+    map/mapbutton.h \
     ui/pixmap.h \
     ui/infotab.h \
     ui/updatelocation/updatelocationdialog.h \
index cc7b7da..de749a8 100644 (file)
@@ -37,26 +37,27 @@ MapViewScreen::MapViewScreen(QWidget *parent)
             mapView, SLOT(centerToSceneCoordinates(QPoint)));
     connect(mapEngine, SIGNAL(zoomLevelChanged(int)), mapView, SLOT(setZoomLevel(int)));
     connect(mapView, SIGNAL(viewResized(QSize)), mapEngine, SLOT(viewResized(QSize)));
-    connect(mapView, SIGNAL(scalingFactorChanged(qreal)),
-            mapEngine, SLOT(scalingFactorChanged(qreal)));
+    connect(mapView, SIGNAL(viewContentChanged(QPoint)),
+            mapEngine, SLOT(alignImmovableItems(QPoint)));
+    connect(mapView, SIGNAL(viewZoomInFinished()), mapEngine, SLOT(viewZoomInFinished()));
 
     QHBoxLayout *mapViewLayout = new QHBoxLayout;
     //DEBUG
-    QVBoxLayout *mapControlLayout = new QVBoxLayout;
-    QWidget *mapControl = new QWidget(this);
-    mapControl->setLayout(mapControlLayout);
-    search = new QPushButton("Search", this);
-    zoomOut = new QPushButton("-", this);
-    zoomIn = new QPushButton("+", this);
-    mapControlLayout->addWidget(&latLine);
-    mapControlLayout->addWidget(&lonLine);
-    mapControlLayout->addWidget(search);
-    mapControlLayout->addWidget(zoomIn);
-    mapControlLayout->addWidget(zoomOut);
-    mapViewLayout->addWidget(mapControl);
-    connect(search, SIGNAL(clicked()), this, SLOT(searchMap()));
-    connect(zoomIn, SIGNAL(clicked()), mapEngine, SLOT(zoomIn()));
-    connect(zoomOut, SIGNAL(clicked()), mapEngine, SLOT(zoomOut()));
+//    QVBoxLayout *mapControlLayout = new QVBoxLayout;
+//    QWidget *mapControl = new QWidget(this);
+//    mapControl->setLayout(mapControlLayout);
+//    search = new QPushButton("Search", this);
+//    zoomOut = new QPushButton("-", this);
+//    zoomIn = new QPushButton("+", this);
+//    mapControlLayout->addWidget(&latLine);
+//    mapControlLayout->addWidget(&lonLine);
+//    mapControlLayout->addWidget(search);
+//    mapControlLayout->addWidget(zoomIn);
+//    mapControlLayout->addWidget(zoomOut);
+//    mapViewLayout->addWidget(mapControl);
+//    connect(search, SIGNAL(clicked()), this, SLOT(searchMap()));
+//    connect(zoomIn, SIGNAL(clicked()), mapEngine, SLOT(zoomIn()));
+//    connect(zoomOut, SIGNAL(clicked()), mapEngine, SLOT(zoomOut()));
     //DEBUG
     mapViewLayout->addWidget(mapView);
     setLayout(mapViewLayout);