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
: 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)));
void MapEngine::mapImageReceived(const QUrl &url, const QPixmap &pixmap)
{
- //qDebug() << __PRETTY_FUNCTION__;
+ qDebug() << __PRETTY_FUNCTION__;
int zoom = UNDEFINED;
int x = UNDEFINED;
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);
}
}
{
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();
}
}
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);
}
}
-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);
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);
QPoint MapEngine::convertLatLonToSceneCoordinate(QPointF latLonCoordinate)
{
-// qDebug() << __PRETTY_FUNCTION__;
+ qDebug() << __PRETTY_FUNCTION__;
qreal longitude = latLonCoordinate.x();
qreal latitude = latLonCoordinate.y();
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:
/**
*
* Does run removeOutOfViewTiles
*/
- void viewZoomInFinished();
+ void viewZoomFinished();
/**
* @brief Slot for zooming in
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
};
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
MapFetcher::MapFetcher(QNetworkAccessManager *manager, QObject *parent)
: QObject(parent)
+ , m_isFetchMapImagesTimerRunning(false)
, m_manager(manager)
{
QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
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;
void MapFetcher::startNextDownload()
{
- //qDebug() << __PRETTY_FUNCTION__;
+ qDebug() << __PRETTY_FUNCTION__;
if (m_downloadQueue.isEmpty())
return;
void MapFetcher::downloadFinished(QNetworkReply *reply)
{
- //qDebug() << __PRETTY_FUNCTION__;
+ qDebug() << __PRETTY_FUNCTION__;
if (reply->error() == QNetworkReply::NoError) {
QImage image;
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
******************************************************************************/
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:
/**
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.
*/
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
};
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;
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)
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();
item->setSceneLevel(zoomLevel);
}
}
+
+void MapScene::viewRectUpdated(QRect viewRect)
+{
+ m_viewRect = viewRect;
+}
*/
class MapScene : public QGraphicsScene
{
+ Q_OBJECT
public:
/**
* @brief Constructor
*/
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
*
/**
* @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.
*/
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
, m_zoomLevel(UNDEFINED)
{
setPos(UNDEFINED, UNDEFINED);
+ setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
}
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);
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()
(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);
/**
* @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
#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());
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());
}
#define MAPVIEW_H
#include <QGraphicsView>
+#include <QPropertyAnimation>
/**
* @brief Map view widget
{
Q_OBJECT
+ /**
+ * @brief View scaling
+ *
+ * @property viewScale
+ */
+ Q_PROPERTY(qreal viewScale READ viewScale WRITE setViewScale)
+
public:
/**
* @brief Constructor
*/
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
******************************************************************************/
*/
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
******************************************************************************/
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
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
* 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
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)
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