Load upper level map images from the cache
[situare] / src / map / mapfetcher.h
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5        Jussi Laitinen - jussi.laitinen@ixonos.com
6        Sami Rämö - sami.ramo@ixonos.com
7
8    Situare is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License
10    version 2 as published by the Free Software Foundation.
11
12    Situare is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Situare; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
20    USA.
21 */
22
23 #ifndef MAPFETCHER_H
24 #define MAPFETCHER_H
25
26 #include <QtCore>
27 #include <QNetworkAccessManager>
28
29 class QNetworkReply;
30 class QUrl;
31
32 /**
33 * @brief MapFetcher handles requests to get map tiles.
34 *
35 * @author Jussi Laitinen jussi.laitinen@ixonos.com
36 * @author Sami Rämö sami.ramo@ixonos.com
37 */
38 class MapFetcher : public QObject
39 {
40     Q_OBJECT
41
42     /**
43     * @brief Type for download requests
44     *
45     * @typedef Request
46     */    
47     /**
48     * @brief Struct for download requests
49     *
50     * @struct _Request
51     */
52     typedef struct _Request {
53         bool cacheChecked; ///< Is this request already checked from the cache
54         QUrl url; ///< URL
55     } Request;
56
57 public:
58     /**
59     * @brief Constructor for MapFetcher.
60     *
61     * @param manager Network access manager
62     * @param parent parent object
63     */
64     MapFetcher(QNetworkAccessManager *manager, QObject *parent = 0);
65
66 /*******************************************************************************
67  * CLASS SPECIFIC MEMBER FUNCTIONS AND SLOTS
68  ******************************************************************************/
69 public:
70     /**
71     * @brief Set size of the download queue
72     *
73     * @param size New size
74     */
75     void setDownloadQueueSize(int size);
76
77 public slots:
78     /**
79     * @brief Enqueue fetching of map image
80     *
81     * Image fetching is triggered after events have been processed
82     * so the UI stays responsive.
83     *
84     * @param zoomLevel Zoom level
85     * @param x Tile x index
86     * @param y Tile y index
87     */
88     void enqueueFetchMapImage(int zoomLevel, int x, int y);
89
90 private:
91     /**
92     * @brief Build URL for donwloading single map tile from OpenStreetMap tile server
93     *
94     * @param zoomLevel Zoom level
95     * @param tileNumbers Tile x & y numbers
96     * @return URL for the required tile
97     */
98     QUrl buildURL(int zoomLevel, QPoint tileNumbers);
99
100     /**
101     * @brief Limit pending requests list size to m_pendingRequestsSize
102     *
103     */
104     void limitPendingRequestsListSize();
105
106     /**
107     * @brief Loads image from cache
108     *
109     * Tries to load requested, or upper zoom level image from the cache. Emits imageReveived signal
110     * if any image was found. If image found was from requested zoom level then expidation date is
111     * checked.
112     *
113     * @param url URL of the requested image
114     * @return True if requested zoom level image was found and was not expired. Otherwise false.
115     */
116     bool loadImageFromCache(const QUrl &url);
117
118     /**
119     * @brief Find first item based on criteria if the request is already checked from the cache
120     *
121     * If cacheChecked is true, then returns index of the first request which is already
122     * checked from the cache. If cacheChecked is false then returns first item which
123     * isn't checked from the cache. Returns -1 if the item is not found.
124     *
125     * @param cacheChecked Search criteria
126     * @return Index of the first matching request, or -1 if not found.
127     */
128     int newestRequestIndex(bool cacheChecked);
129
130     /**
131     * @brief Parse given URL to zoom, x and y values. Parsed values are
132     * placed in variables given as parameters.
133     *
134     * @param url url to parse
135     * @param [out] zoom zoom variable
136     * @param [out] x x variable
137     * @param [out] y y variable
138     */
139     void parseURL(const QUrl &url, int &zoom, int &x, int &y);
140
141     /**
142     * @brief Translate indexes to matching upper level map tile indexes
143     * @param[in,out] zoomLevel Zoom level
144     * @param[in,out] x x index
145     * @param[in,out] y y index
146     * @return true if translation succeeded, otherwise false
147     */
148     bool translateIndexesToUpperLevel(int &zoomLevel, int &x, int &y);
149
150 private slots:
151
152     /**
153     * @brief This slot is called when network manager has finished
154     * the download. Loads image and emits imageReceived signal with
155     * url and image. If there was a error in reply emits error-signal.
156     *
157     * @param reply
158     */
159     void downloadFinished(QNetworkReply *reply);
160
161     /**
162     * @brief Check next request if it is found from cache
163     *
164     * Next queued request, which is not already checked against cache, is taken
165     * from the queue and checked against cache. If not found from cache, then
166     * cache checked flag is set. New download is started if there aren't too
167     * many simultaneus downloads already running.
168     */
169     void checkNextRequestFromCache();
170
171     /**
172     * @brief This slot is called when next download is started. Takes url
173     * from queue, sends request and puts request to download queue.
174     */
175     void startNextDownload();
176
177 /*******************************************************************************
178  * SIGNALS
179  ******************************************************************************/
180 signals:    
181     /**
182     * @brief Signal which is emitted when a map tile
183     * is received from the server and loaded to pixmap.
184     *
185     * @param zoomLevel Zoom level
186     * @param x Tile x index
187     * @param y Tile y index
188     * @param image image pixmap
189     */
190     void mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image);
191
192     /**
193     * @brief Signal which is emitted when there is error
194     * in network reply.
195     *
196     * @param message error message
197     */
198     void error(const QString &message);
199
200 /*******************************************************************************
201  * DATA MEMBERS
202  ******************************************************************************/
203 private:
204     static const int MAX_PARALLEL_DOWNLOADS = 2; ///< Max simultaneous parallel downloads
205
206     QList<QNetworkReply*> m_currentDownloads; ///< List of current downloads
207     int m_pendingRequestsSize; ///< Max number of pending requests
208     bool m_fetchMapImagesTimerRunning; ///< is the singleshot timer already running
209     QNetworkAccessManager *m_manager; ///< Network access manager
210     QList<Request> m_pendingRequests; ///< List of map image fetching requests
211 };
212
213 #endif