From 6ae1c696d85de4fcfb8861c88a5b8ed6f1fa3384 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sami=20R=C3=A4m=C3=B6?= Date: Mon, 21 Jun 2010 14:34:36 +0300 Subject: [PATCH] Implemented smooth centering feature --- src/engine/engine.cpp | 16 +++++----- src/map/mapengine.cpp | 54 ++++++++++++++++++++------------- src/map/mapengine.h | 38 +++++++++++++---------- src/map/mapscroller.cpp | 7 ----- src/map/mapscroller.h | 2 +- src/map/mapview.cpp | 1 + tests/map/mapengine/testmapengine.cpp | 36 +++++++++++++--------- 7 files changed, 87 insertions(+), 67 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index f087fa9..78be25f 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -49,7 +49,7 @@ SituareEngine::SituareEngine(QMainWindow *parent) m_userMoved(false), m_automaticUpdateIntervalTimer(0), m_lastUpdatedGPSPosition(QPointF()) -{ +{ qDebug() << __PRETTY_FUNCTION__; m_ui = new MainWindow; m_ui->updateItemVisibility(); @@ -209,7 +209,7 @@ void SituareEngine::enableAutomaticLocationUpdate(bool enabled, int updateInterv void SituareEngine::error(const int error) { - qDebug() << __PRETTY_FUNCTION__; + qDebug() << __PRETTY_FUNCTION__; switch(error) { @@ -428,7 +428,7 @@ void SituareEngine::setFirstStartZoomLevel(QPointF latLonCoordinate, qreal accur Q_UNUSED(latLonCoordinate); Q_UNUSED(accuracy); - if (m_autoCenteringEnabled) // autocentering is disabled when map is scrolled + if (m_autoCenteringEnabled) // autocentering is disabled when map is scrolled m_mapEngine->setZoomLevel(DEFAULT_ZOOM_LEVEL_WHEN_GPS_IS_AVAILABLE); disconnect(m_gps, SIGNAL(position(QPointF,qreal)), @@ -477,7 +477,7 @@ void SituareEngine::signalsFromGPS() void SituareEngine::signalsFromMainWindow() { - qDebug() << __PRETTY_FUNCTION__; + qDebug() << __PRETTY_FUNCTION__; connect(m_ui, SIGNAL(error(int)), this, SLOT(error(int))); @@ -496,7 +496,7 @@ void SituareEngine::signalsFromMainWindow() // signals from map view connect(m_ui, SIGNAL(mapViewScrolled(QPoint)), - m_mapEngine, SLOT(setLocation(QPoint))); + m_mapEngine, SLOT(setCenterPosition(QPoint))); connect(m_ui, SIGNAL(mapViewResized(QSize)), m_mapEngine, SLOT(viewResized(QSize))); @@ -529,18 +529,18 @@ void SituareEngine::signalsFromMainWindow() this, SLOT(requestUpdateLocation(QString,bool))); connect(m_ui, SIGNAL(enableAutomaticLocationUpdate(bool, int)), - this, SLOT(enableAutomaticLocationUpdate(bool, int))); + this, SLOT(enableAutomaticLocationUpdate(bool, int))); // signals from user info tab connect(m_ui, SIGNAL(refreshUserData()), this, SLOT(refreshUserData())); connect(m_ui, SIGNAL(findUser(QPointF)), - m_mapEngine, SLOT(setViewLocation(QPointF))); + m_mapEngine, SLOT(centerToCoordinates(QPointF))); // signals from friend list tab connect(m_ui, SIGNAL(findFriend(QPointF)), - m_mapEngine, SLOT(setViewLocation(QPointF))); + m_mapEngine, SLOT(centerToCoordinates(QPointF))); } void SituareEngine::signalsFromMapEngine() diff --git a/src/map/mapengine.cpp b/src/map/mapengine.cpp index ca6d33e..6df3d06 100644 --- a/src/map/mapengine.cpp +++ b/src/map/mapengine.cpp @@ -45,6 +45,8 @@ #include "mapengine.h" +const int SMOOTH_CENTERING_TIME_MS = 1000; + MapEngine::MapEngine(QObject *parent) : QObject(parent), m_autoCenteringEnabled(false), @@ -90,7 +92,7 @@ MapEngine::MapEngine(QObject *parent) m_scroller = &MapScroller::getInstance(); connect(m_scroller, SIGNAL(coordinateUpdated(QPoint)), - this, SLOT(setLocation(QPoint))); + this, SLOT(setCenterPosition(QPoint))); } MapEngine::~MapEngine() @@ -123,6 +125,17 @@ QPointF MapEngine::centerGeoCoordinate() return convertSceneCoordinateToLatLon(m_zoomLevel, m_sceneCoordinate); } +void MapEngine::centerToCoordinates(QPointF latLonCoordinate) +{ + qDebug() << __PRETTY_FUNCTION__; + + QPoint scenePosition = convertLatLonToSceneCoordinate(latLonCoordinate); + + m_lastManualPosition = scenePosition; + + scrollToPosition(scenePosition); +} + QPoint MapEngine::convertLatLonToSceneCoordinate(QPointF latLonCoordinate) { qDebug() << __PRETTY_FUNCTION__; @@ -244,7 +257,7 @@ void MapEngine::gpsPositionUpdate(QPointF position, qreal accuracy) m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize); if (m_autoCenteringEnabled) - setViewLocation(position); + centerToCoordinates(position); } qreal MapEngine::greatCircleDistance(QPointF firstLocation, QPointF secondLocation) @@ -282,7 +295,7 @@ void MapEngine::init() } emit zoomLevelChanged(m_zoomLevel); - setViewLocation(QPointF(startLocation.x(), startLocation.y())); + centerToCoordinates(QPointF(startLocation.x(), startLocation.y())); } bool MapEngine::isAutoCenteringEnabled() @@ -380,6 +393,16 @@ QGraphicsScene* MapEngine::scene() return m_mapScene; } +void MapEngine::scrollToPosition(QPoint scenePosition) +{ + m_scroller->stop(); + m_scroller->setEasingCurve(QEasingCurve::InOutQuart); + m_scroller->setDuration(SMOOTH_CENTERING_TIME_MS); + m_scroller->setStartValue(m_sceneCoordinate); + m_scroller->setEndValue(scenePosition); + m_scroller->start(); +} + void MapEngine::setAutoCentering(bool enabled) { m_autoCenteringEnabled = enabled; @@ -390,24 +413,24 @@ void MapEngine::setGPSEnabled(bool enabled) m_gpsLocationItem->setEnabled(enabled); } -void MapEngine::setLocation(QPoint sceneCoordinate) +void MapEngine::setCenterPosition(QPoint scenePosition) { qDebug() << __PRETTY_FUNCTION__; // jump to opposite side of the world if world horizontal limit is exceeded - sceneCoordinate.setX(normalize(sceneCoordinate.x(), MAP_MIN_PIXEL_X, MAP_MAX_PIXEL_X)); + scenePosition.setX(normalize(scenePosition.x(), MAP_MIN_PIXEL_X, MAP_MAX_PIXEL_X)); // don't allow vertical scene coordinates go out of the map - sceneCoordinate.setY(qBound(MAP_MIN_PIXEL_Y, sceneCoordinate.y(), MAP_MAX_PIXEL_Y)); + scenePosition.setY(qBound(MAP_MIN_PIXEL_Y, scenePosition.y(), MAP_MAX_PIXEL_Y)); - if (disableAutoCentering(sceneCoordinate)) + if (disableAutoCentering(scenePosition)) emit mapScrolledManually(); - m_sceneCoordinate = sceneCoordinate; + m_sceneCoordinate = scenePosition; emit locationChanged(m_sceneCoordinate); - if (isCenterTileChanged(sceneCoordinate)) { - getTiles(sceneCoordinate); + if (isCenterTileChanged(scenePosition)) { + getTiles(scenePosition); m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel); } @@ -445,17 +468,6 @@ void MapEngine::setTilesGridSize(const QSize &viewSize) m_tilesGridSize.setWidth(gridWidth); } -void MapEngine::setViewLocation(QPointF latLonCoordinate) -{ - qDebug() << __PRETTY_FUNCTION__; - - QPoint sceneCoordinate = convertLatLonToSceneCoordinate(latLonCoordinate); - - m_lastManualPosition = sceneCoordinate; - - setLocation(sceneCoordinate); -} - int MapEngine::tileMaxIndex(int zoomLevel) { qDebug() << __PRETTY_FUNCTION__; diff --git a/src/map/mapengine.h b/src/map/mapengine.h index 810f25f..ba505f0 100644 --- a/src/map/mapengine.h +++ b/src/map/mapengine.h @@ -180,6 +180,13 @@ public: public slots: /** + * @brief Center smoothly to given latitude and longitude coordinates. + * + * @param latLonCoordinate Latitude & longitude coordinates for location + */ + void centerToCoordinates(QPointF latLonCoordinate); + + /** * @brief Slot to catch user own location data * * @param user User info @@ -203,22 +210,6 @@ public slots: void setGPSEnabled(bool enabled); /** - * @brief Slot for setting current view location - * - * Emits locationChanged signal. - * @param sceneCoordinate Scene coordinates for new position - */ - void setLocation(QPoint sceneCoordinate); - - /** - * @brief Helper for setting view location based on latitude and longitude - * coordinates - * - * @param latLonCoordinate Latitude & longitude coordinates for location - */ - void setViewLocation(QPointF latLonCoordinate); - - /** * @brief Calculate maximum value for tile in this zoom level. * * @param zoomLevel zoom level @@ -340,6 +331,21 @@ private slots: void mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image); /** + * @brief Scroll smoothly to given scene position + * + * @param scenePosition Target position in the scene + */ + void scrollToPosition(QPoint scenePosition); + + /** + * @brief Set center point in the scene + * + * Does emit locationChanged signal. + * @param scenePosition Scene coordinates for new position + */ + void setCenterPosition(QPoint scenePosition); + + /** * @brief Slot for actions after view zoom is finished * * Does run removeOutOfViewTiles diff --git a/src/map/mapscroller.cpp b/src/map/mapscroller.cpp index d7ad402..d458c91 100644 --- a/src/map/mapscroller.cpp +++ b/src/map/mapscroller.cpp @@ -24,13 +24,6 @@ #include "mapscroller.h" -MapScroller::MapScroller() -{ - qDebug() << __PRETTY_FUNCTION__; - - setEasingCurve(QEasingCurve::OutCirc); -} - MapScroller& MapScroller::getInstance() { qDebug() << __PRETTY_FUNCTION__; diff --git a/src/map/mapscroller.h b/src/map/mapscroller.h index acd6644..6f44401 100644 --- a/src/map/mapscroller.h +++ b/src/map/mapscroller.h @@ -42,7 +42,7 @@ private: /** * @brief Constructor in not accessible because class is using singleton design pattern. */ - MapScroller(); + MapScroller() {} /** * @brief Destructor in not accessible because class is using singleton design pattern. diff --git a/src/map/mapview.cpp b/src/map/mapview.cpp index 6b38ff4..471e28b 100644 --- a/src/map/mapview.cpp +++ b/src/map/mapview.cpp @@ -130,6 +130,7 @@ void MapView::mouseReleaseEvent(QMouseEvent *event) QPointF effectSceneDistance = effectViewDistance * (1 << (MAX_MAP_ZOOM_LEVEL - m_zoomLevel)); + m_scroller->setEasingCurve(QEasingCurve::OutCirc); m_scroller->setDuration(KINETIC_SCROLL_TIME_MS); m_scroller->setStartValue(m_scenePosition); m_scroller->setEndValue(m_scenePosition + effectSceneDistance.toPoint()); diff --git a/tests/map/mapengine/testmapengine.cpp b/tests/map/mapengine/testmapengine.cpp index 269e845..3cdb973 100644 --- a/tests/map/mapengine/testmapengine.cpp +++ b/tests/map/mapengine/testmapengine.cpp @@ -43,6 +43,9 @@ private slots: void zoomOutRemovedTilesCount(); void zoomInRemovedTilesCount(); void usingLastLocation(); + +signals: + void setCenterPosition(QPoint); // a way to call a private slot }; /** @@ -88,20 +91,21 @@ void TestMapEngine::setLocationNewTilesCount() { MapEngine engine; engine.viewResized(QSize(800, 480)); + connect(this, SIGNAL(setCenterPosition(QPoint)), &engine, SLOT(setCenterPosition(QPoint))); QSignalSpy fetchImageSpy(&engine, SIGNAL(fetchImage(int,int,int))); QTest::qWait(1000); fetchImageSpy.clear(); // first test, scene is empty so all tiles should be downloaded - engine.setLocation(QPoint(1220*16, 1220*16)); + emit setCenterPosition(QPoint(1220*16, 1220*16)); QTest::qWait(1000); QCOMPARE(fetchImageSpy.count(), 5*4); fetchImageSpy.clear(); // move one tile to east and south, only most right one column and most bottom one row tiles // should be downloaded - engine.setLocation(QPoint((1220+TILE_SIZE_X)*16, (1220+TILE_SIZE_Y)*16)); + emit setCenterPosition(QPoint((1220+TILE_SIZE_X)*16, (1220+TILE_SIZE_Y)*16)); QTest::qWait(1000); QCOMPARE(fetchImageSpy.count(), 4 + 4); fetchImageSpy.clear(); @@ -111,18 +115,19 @@ void TestMapEngine::setLocationRemovedTilesCount() { MapEngine engine; engine.viewResized(QSize(800, 480)); + connect(this, SIGNAL(setCenterPosition(QPoint)), &engine, SLOT(setCenterPosition(QPoint))); const int maxItemsCount = 40; - engine.setLocation(QPoint(1220*16, 1220*16)); + emit setCenterPosition(QPoint(1220*16, 1220*16)); QTest::qWait(1000); - engine.setLocation(QPoint(2220*16, 2220*16)); + emit setCenterPosition(QPoint(2220*16, 2220*16)); QTest::qWait(1000); QVERIFY(engine.scene()->items().count() <= maxItemsCount); - engine.setLocation(QPoint(520*16, 2220*16)); + emit setCenterPosition(QPoint(520*16, 2220*16)); QTest::qWait(1000); - engine.setLocation(QPoint(2220*16, 520*16)); + emit setCenterPosition(QPoint(2220*16, 520*16)); QTest::qWait(1000); QVERIFY(engine.scene()->items().count() <= maxItemsCount); @@ -132,17 +137,18 @@ void TestMapEngine::zoomInRemovedTilesCount() { MapEngine engine; engine.viewResized(QSize(800, 480)); + connect(this, SIGNAL(setCenterPosition(QPoint)), &engine, SLOT(setCenterPosition(QPoint))); const int maxItemsCount = 40; - engine.setLocation(QPoint(1220*16, 1220*16)); + emit setCenterPosition(QPoint(1220*16, 1220*16)); QTest::qWait(1000); QTest::qWait(1000); QVERIFY(engine.scene()->items().count() <= maxItemsCount); - engine.setLocation(QPoint(520*16, 2220*16)); + emit setCenterPosition(QPoint(520*16, 2220*16)); QTest::qWait(1000); - engine.setLocation(QPoint(2220*16, 520*16)); + emit setCenterPosition(QPoint(2220*16, 520*16)); QTest::qWait(1000); QVERIFY(engine.scene()->items().count() <= maxItemsCount); @@ -152,18 +158,19 @@ void TestMapEngine::zoomOutRemovedTilesCount() { MapEngine engine; engine.viewResized(QSize(800, 480)); + connect(this, SIGNAL(setCenterPosition(QPoint)), &engine, SLOT(setCenterPosition(QPoint))); const int maxItemsCount = 40; - engine.setLocation(QPoint(1220*16, 1220.23*16)); + emit setCenterPosition(QPoint(1220*16, 1220.23*16)); QTest::qWait(1000); - engine.setLocation(QPoint(2220*16, 2220.23*16)); + emit setCenterPosition(QPoint(2220*16, 2220.23*16)); QTest::qWait(1000); QVERIFY(engine.scene()->items().count() <= maxItemsCount); - engine.setLocation(QPoint(520*16, 2220*16)); + emit setCenterPosition(QPoint(520*16, 2220*16)); QTest::qWait(1000); - engine.setLocation(QPoint(2220*16, 520*16)); + emit setCenterPosition(QPoint(2220*16, 520*16)); QTest::qWait(1000); QVERIFY(engine.scene()->items().count() <= maxItemsCount); @@ -174,6 +181,7 @@ void TestMapEngine::usingLastLocation() // Create mapengine and start monitoring zoomLevelChanged-signal MapEngine *mapengine = new MapEngine; QSignalSpy mapEngineSpy(mapengine, SIGNAL(zoomLevelChanged(int))); + connect(this, SIGNAL(setCenterPosition(QPoint)), mapengine, SLOT(setCenterPosition(QPoint))); QVERIFY (mapEngineSpy.isValid()); QCOMPARE (mapEngineSpy.count(), 0); @@ -204,7 +212,7 @@ void TestMapEngine::usingLastLocation() // Call set location with know parameter to get location changed // Store new location and zoomlevel to settings - mapengine->setLocation(NEW_TEST_SCENECOORDINATE); + emit setCenterPosition(NEW_TEST_SCENECOORDINATE); delete mapengine; // Read settings and verify that zoomlevel is correct -- 1.7.9.5