74bd5e756989c35a7c0ca58e4583baf6d8dd80cd
[situare] / src / map / mapengine.h
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5        Sami Rämö - sami.ramo@ixonos.com
6        Jussi Laitinen - jussi.laitinen@ixonos.com
7        Pekka Nissinen - pekka.nissinen@ixonos.com
8        Ville Tiensuu - ville.tiensuu@ixonos.com
9        Henri Lampela - henri.lampela@ixonos.com
10
11    Situare is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License
13    version 2 as published by the Free Software Foundation.
14
15    Situare is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with Situare; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
23    USA.
24 */
25
26 #ifndef MAPENGINE_H
27 #define MAPENGINE_H
28
29 #include <QtCore>
30
31 #include "routing/route.h"
32 #include "coordinates/geocoordinate.h"
33 #include "coordinates/scenecoordinate.h"
34
35 class QGraphicsScene;
36
37 class FriendItemsHandler;
38 class GPSLocationItem;
39 class MapFetcher;
40 class MapRouteItem;
41 class MapScene;
42 class MapScroller;
43 class MapTile;
44 class OwnLocationItem;
45 class User;
46
47 /**
48  * @brief Map engine
49  *
50  * Logic for controlling map functionality. Does also include static methods for
51  * converting coordinates.
52  *
53  * NOTE: MapEngine must have a view attached before using it!
54  *
55  * @author Sami Rämö - sami.ramo (at) ixonos.com
56  * @author Jussi Laitinen - jussi.laitinen (at) ixonos.com
57  * @author Pekka Nissinen - pekka.nissinen (at) ixonos.com
58  * @author Ville Tiensuu - ville.tiensuu (at) ixonos.com
59  */
60 class MapEngine : public QObject
61 {
62     Q_OBJECT
63
64 public:
65     /**
66      * @brief Constructor
67      *
68      * @param parent Parent
69      */
70     MapEngine(QObject *parent = 0);
71
72     /**
73      * @brief Destructor
74      * Saves view of the map to settings file
75      */
76     ~MapEngine();
77
78 /*******************************************************************************
79  * MEMBER FUNCTIONS AND SLOTS
80  ******************************************************************************/
81 public:
82     /**
83      * @brief Coordinates of the current center point
84      *
85      * @return Current coordinates
86      */
87     GeoCoordinate centerGeoCoordinate();
88
89     /**
90      * @brief Convert MapScene coordinate to tile x & y numbers.
91      *
92      * @param zoomLevel ZoomLevel
93      * @param coordinate MapScene coordinate
94      * @return tile x & y numbers
95      */
96     static QPoint convertSceneCoordinateToTileNumber(int zoomLevel, SceneCoordinate coordinate);
97
98     /**
99      * @brief Set initial values for the map
100      *
101      * Set initial location and zoom level from the settings, if available, or use the default
102      * values set in the constructor. Signals locationChanged() and zoomLevelChanged() are emitted,
103      * so init should be called after those signals are connected.
104      */
105     void init();
106
107     /**
108      * @brief Return given value translated between min and max
109      *
110      * If given value is not inside the given range (min <= value <= max), then the allowed range
111      * is adder or subtracted until the value does fit in the range.
112      *
113      * @param value Value to be normalized
114      * @param min Minimum allowed value
115      * @param max Maximum allowed value
116      * @return value which is moved to be inside the given limits
117      */
118     static int normalize(int value, int min, int max);
119
120     /**
121      * @brief Getter for scene
122      *
123      * @return QGraphicsScene
124      */
125     QGraphicsScene* scene();
126
127     /**
128      * @brief Sets new zoom level
129      *
130      * @return newZoomLevel value that is set to new zoom level
131      */
132     void setZoomLevel(const int newZoomLevel);
133
134 public slots:
135     /**
136      * @brief Center smoothly to given latitude and longitude coordinates.
137      *
138      * @param coordinate Latitude & longitude coordinates for location
139      */
140     void centerToCoordinates(GeoCoordinate coordinate);
141
142     /**
143      * @brief Slot to catch user own location data
144      *
145      * @param user User info
146      */
147     void receiveOwnLocation(User *user);
148
149     /**
150      * @brief Set auto centering.
151      *
152      * @param enabled true if enabled, false otherwise
153      */
154     void setAutoCentering(bool enabled);
155
156     /**
157      * @brief Slot for enabling / disabling GPS
158      *
159      * GPS location item is disabled or enabled based on GPS state
160      *
161      * @param enabled True is GPS is enabled, otherwise false
162      */
163     void setGPSEnabled(bool enabled);
164
165     /**
166      * @brief Slot for view resizing.
167      *
168      * @param size view size
169      */
170     void viewResized(const QSize &size);
171
172 private:
173     /**
174      * @brief Calculate grid of tile coordinates from current scene coordinate.
175      *
176      * Grid size is calculated from view size and scene's current center coordinate.
177      *
178      * @param coordinate scene's current center coordinate
179      * @return QRect grid of tile coordinates
180      */
181     QRect calculateTileGrid(SceneCoordinate coordinate);
182
183     /**
184     * @brief Center and zoom to given rect
185     *
186     * Map is centered to center point of the rect and zoomed so that whole rect is visible
187     * as big as possible.
188     *
189     * @param rect Target rect
190     * @param useMargins true if margins should be added to rect, false otherwise
191     */
192     void centerAndZoomTo(QRect rect, bool useMargins = true);
193
194     /**
195     * @brief Returns the rect of the current scene area drawn on the view
196     *
197     * @returns Rect of the current scene area drawn on the view
198     */
199     QRectF currentViewSceneRect() const;
200
201     /**
202      * @brief Request disabling of auto centering if centered too far from the real location.
203      *
204      * @param coordinate scene's center coordinate
205      */
206     void disableAutoCenteringIfRequired(SceneCoordinate coordinate);
207
208     /**
209      * @brief Get new tiles.
210      *
211      * Calculates which tiles has to be fetched. Does emit fetchImage for tiles which
212      * aren't already in the scene.
213      * @param coordinate scene's center coordinate
214      */
215     void getTiles(SceneCoordinate coordinate);
216
217     /**
218      * @brief Check if auto centering is enabled
219      *
220      * @return true if enabled, false otherwise
221      */
222     bool isAutoCenteringEnabled();
223
224     /**
225      * @brief Check if center tile has changed.
226      *
227      * @param coordinate scene's center coordinate
228      * @return bool true if center tile changed, false otherwise
229      */
230     bool isCenterTileChanged(SceneCoordinate coordinate);
231
232     /**
233      * @brief Set size of tiles grid based on view size
234      *
235      * @param viewSize Current view size
236      */
237     void setTilesGridSize(const QSize &viewSize);
238
239     /**
240      * @brief Updates direction and distance values to indicator button
241      *
242      * Calculate and update direction and distance values and send those to indicator button
243      */
244     void updateDirectionIndicator();
245
246     /**
247      * @brief Updates the current view rect including margins
248      *
249      * Calculates tiles rect in scene based on m_viewTilesGrid and
250      * calls MapScene::viewRectUpdated()
251      */
252     void updateViewTilesSceneRect();
253
254     /**
255      * @brief Calculate scale at the map center of the map in meters/pixel
256      *
257      * @return qreal Scale of the map in meters/pixel
258      */
259     qreal viewResolution();
260
261     /**
262      * @brief This method is ran always when the map is zoomed
263      *
264      * This method is the right place for all actions which must be done when ever map is zoomed.
265      */
266     void zoomed();
267
268 private slots:
269     /**
270      * @brief This slot is called after friend items position have been updated
271      *
272      * Does run MapScene::spanItems()
273      */
274     void friendsPositionsUpdated();
275
276     /**
277      * @brief Slot for GPS position updates
278      *
279      * GPS location item is updated and map centered to new location (if automatic
280      * centering is enabled).
281      *
282      * @param position New coordinates from GPS
283      * @param accuracy Accuracy of the GPS fix
284      */
285     void gpsPositionUpdate(GeoCoordinate position, qreal accuracy);
286
287     /**
288      * @brief Slot for received map tile images
289      *
290      * Does receive map tile images from MapFetcher. Calls MapScene::addTile() for creating and adding
291      * the actual MapTile object to the MapScene.
292      *
293      * Tile is added also to outside the world horizontal limits, if required, for spanning the map.
294      *
295      * @param zoomLevel Zoom level
296      * @param x Tile x index
297      * @param y Tile y index
298      * @param image Received pixmap
299      */
300     void mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image);
301
302     /**
303      * @brief Called when MapScroller state is changed
304      *
305      * Does check if the smooth scroll effect was interrupted and should the auto centering
306      * feature to be disabled.
307      *
308      * @param newState New state
309      */
310     void scrollerStateChanged(QAbstractAnimation::State newState);
311
312     /**
313      * @brief Scroll smoothly to given scene position
314      *
315      * @param coordinate Target position in the scene
316      */
317     void scrollToPosition(SceneCoordinate coordinate);
318
319     /**
320      * @brief Set center point in the scene
321      *
322      * Does emit locationChanged signal.
323      * @param coordinate Scene coordinates for new position
324      */
325     void setCenterPosition(SceneCoordinate coordinate, bool isUserDragAction = false);
326
327     /**
328      * @brief Builds and sets route, also centers it
329      *
330      * @param route Route route information
331      */
332     void setRoute(Route &route);
333
334     /**
335     * @brief Shows map area defined by bounds.
336     *
337     * Calls centerAndZoomTo() with area defined by bounds.
338     * @param swBound south-west bound of location item
339     * @param neBound north-east bound of location item
340     */
341     void showMapArea(const GeoCoordinate &swBound, const GeoCoordinate &neBound);
342
343     /**
344      * @brief Slot for actions after view zoom is finished
345      *
346      * Does run removeOutOfViewTiles
347      */
348     void viewZoomFinished();
349
350     /**
351      * @brief Slot for zooming in
352      */
353     void zoomIn();
354
355     /**
356      * @brief Slot for zooming out
357      */
358     void zoomOut();
359
360 /*******************************************************************************
361  * SIGNALS
362  ******************************************************************************/
363 signals:
364     /**
365     * @brief Signal when direction and distance from current map center point to current GPS
366     *        location is changed
367     *
368     * @param direction Direction in degrees
369     * @param distance Distance in meters
370     * @param draw Should the indicator triangle be drawn or not
371     */
372     void directionIndicatorValuesUpdate(qreal direction, qreal distance, bool draw);
373
374     /**
375     * @brief Signals error
376     *
377     * @param context error context
378     * @param error error code
379     */
380     void error(const int context, const int error);
381
382     /**
383      * @brief Signal for image fetching.
384      *
385      * @param zoomLevel Zoom level
386      * @param x Tile x index
387      * @param y Tile y index
388      */
389     void fetchImage(int zoomLevel, int x, int y);
390
391     /**
392     * @brief Signal when friend image is ready
393     *
394     * @param user Friend
395     */
396     void friendImageReady(User *user);
397
398     /**
399      * @brief Signal when friend list locations are fetched
400      *
401      * @param friendsList Friends list data
402      */
403     void friendsLocationsReady(QList<User *> &friendsList);
404
405     /**
406      * @brief Request view centering to new locaiton
407      *
408      * @param coordinate New scene coordinates
409      */
410     void locationChanged(SceneCoordinate coordinate, bool isUserDragAction);
411
412     /**
413      * @brief Signal is emitted when location item is clicked.
414      *
415      * @param userIDs list of friends user IDs in the group
416      */
417     void locationItemClicked(const QList<QString> &userIDs);
418
419     /**
420      * @brief Signal to notify map scrolling.
421      */
422     void mapScrolledManually();
423
424     /**
425      * @brief Signal to notify when map is zoomed in to the maxmimum.
426      */
427     void maxZoomLevelReached();
428
429     /**
430      * @brief Signal to notify when map is zoomed out to the minimum.
431      */
432     void minZoomLevelReached();
433
434     /**
435      * @brief Signal to pass the scale of the map to map scale
436      */
437     void newMapResolution(qreal scale);
438
439     /**
440      * @brief Request view changing zoom level
441      *
442      * @param newZoomLevel New zoom level
443      */
444     void zoomLevelChanged(int newZoomLevel);
445
446 /*******************************************************************************
447  * DATA MEMBERS
448  ******************************************************************************/
449 private:
450     bool m_autoCenteringEnabled;    ///< Auto centering enabled
451     bool m_scrollStartedByGps;      ///< Smooth scroll is started by GPS?
452     bool m_smoothScrollRunning;     ///< Smooth scroll is running?
453     bool m_zoomedIn;                ///< Flag for checking if zoomed in when zoom is finished
454
455     int m_zoomLevel;                ///< Current zoom level
456
457     QPoint m_centerTile;            ///< Current center tile
458     SceneCoordinate m_lastAutomaticPosition; ///< Last automatically set position in scene coordinate
459     SceneCoordinate m_sceneCoordinate;       ///< Current center coordinate
460
461     QRect m_viewTilesGrid;          ///< Current grid of tiles in view (includes margin)
462
463     QSize m_tilesGridSize;          ///< Current size of the tiles grid
464     QSize m_viewSize;               ///< Current view size
465
466     FriendItemsHandler *m_friendItemsHandler;   ///< Handler for friend and group items
467     GeoCoordinate m_gpsPosition;                ///< Latest GPS position
468     GPSLocationItem *m_gpsLocationItem;         ///< Item pointing current location from GPS
469     MapFetcher *m_mapFetcher;                   ///< Fetcher for map tiles
470     MapRouteItem *m_mapRouteItem;               ///< Map route item
471     MapScene *m_mapScene;                       ///< Scene for map tiles
472     MapScroller *m_scroller;                    ///< Kinetic scroller
473     OwnLocationItem *m_ownLocation;             ///< Item to show own location
474     Route m_route;                              ///< Current route data
475 };
476
477 #endif // MAPENGINE_H