1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtLocation module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL3$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or later as published by the Free |
28 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
29 | ** the packaging of this file. Please review the following information to |
30 | ** ensure the GNU General Public License version 2.0 requirements will be |
31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
32 | ** |
33 | ** $QT_END_LICENSE$ |
34 | ** |
35 | ****************************************************************************/ |
36 | |
37 | #include "qgeotiledmappingmanagerengine_p.h" |
38 | #include "qgeotiledmappingmanagerengine_p_p.h" |
39 | #include "qgeotilefetcher_p.h" |
40 | |
41 | |
42 | #include "qgeotiledmap_p.h" |
43 | #include "qgeotilerequestmanager_p.h" |
44 | #include "qgeofiletilecache_p.h" |
45 | #include "qgeotilespec_p.h" |
46 | |
47 | #include <QTimer> |
48 | #include <QLocale> |
49 | #include <QDir> |
50 | #include <QStandardPaths> |
51 | |
52 | QT_BEGIN_NAMESPACE |
53 | |
54 | QGeoTiledMappingManagerEngine::QGeoTiledMappingManagerEngine(QObject *parent) |
55 | : QGeoMappingManagerEngine(parent), |
56 | m_prefetchStyle(QGeoTiledMap::PrefetchTwoNeighbourLayers), |
57 | d_ptr(new QGeoTiledMappingManagerEnginePrivate) |
58 | { |
59 | } |
60 | |
61 | /*! |
62 | Destroys this mapping manager. |
63 | */ |
64 | QGeoTiledMappingManagerEngine::~QGeoTiledMappingManagerEngine() |
65 | { |
66 | delete d_ptr; |
67 | } |
68 | |
69 | /*! |
70 | Sets the tile fetcher. Takes ownership of the QObject. |
71 | */ |
72 | void QGeoTiledMappingManagerEngine::setTileFetcher(QGeoTileFetcher *fetcher) |
73 | { |
74 | Q_D(QGeoTiledMappingManagerEngine); |
75 | |
76 | if (d->fetcher_) |
77 | d->fetcher_->deleteLater(); |
78 | fetcher->setParent(this); |
79 | d->fetcher_ = fetcher; |
80 | |
81 | qRegisterMetaType<QGeoTileSpec>(); |
82 | |
83 | connect(sender: d->fetcher_, |
84 | SIGNAL(tileFinished(QGeoTileSpec,QByteArray,QString)), |
85 | receiver: this, |
86 | SLOT(engineTileFinished(QGeoTileSpec,QByteArray,QString)), |
87 | Qt::QueuedConnection); |
88 | connect(sender: d->fetcher_, |
89 | SIGNAL(tileError(QGeoTileSpec,QString)), |
90 | receiver: this, |
91 | SLOT(engineTileError(QGeoTileSpec,QString)), |
92 | Qt::QueuedConnection); |
93 | |
94 | engineInitialized(); |
95 | } |
96 | |
97 | QGeoTileFetcher *QGeoTiledMappingManagerEngine::tileFetcher() |
98 | { |
99 | Q_D(QGeoTiledMappingManagerEngine); |
100 | return d->fetcher_; |
101 | } |
102 | |
103 | QGeoMap *QGeoTiledMappingManagerEngine::createMap() |
104 | { |
105 | return NULL; |
106 | } |
107 | |
108 | void QGeoTiledMappingManagerEngine::releaseMap(QGeoTiledMap *map) |
109 | { |
110 | d_ptr->mapHash_.remove(akey: map); |
111 | |
112 | QHash<QGeoTileSpec, QSet<QGeoTiledMap *> > newTileHash = d_ptr->tileHash_; |
113 | typedef QHash<QGeoTileSpec, QSet<QGeoTiledMap *> >::const_iterator h_iter; |
114 | h_iter hi = d_ptr->tileHash_.constBegin(); |
115 | h_iter hend = d_ptr->tileHash_.constEnd(); |
116 | for (; hi != hend; ++hi) { |
117 | QSet<QGeoTiledMap *> maps = hi.value(); |
118 | if (maps.contains(value: map)) { |
119 | maps.remove(value: map); |
120 | if (maps.isEmpty()) |
121 | newTileHash.remove(akey: hi.key()); |
122 | else |
123 | newTileHash.insert(akey: hi.key(), avalue: maps); |
124 | } |
125 | } |
126 | d_ptr->tileHash_ = newTileHash; |
127 | } |
128 | |
129 | void QGeoTiledMappingManagerEngine::updateTileRequests(QGeoTiledMap *map, |
130 | const QSet<QGeoTileSpec> &tilesAdded, |
131 | const QSet<QGeoTileSpec> &tilesRemoved) |
132 | { |
133 | Q_D(QGeoTiledMappingManagerEngine); |
134 | |
135 | typedef QSet<QGeoTileSpec>::const_iterator tile_iter; |
136 | |
137 | // add and remove tiles from tileset for this map |
138 | |
139 | QSet<QGeoTileSpec> oldTiles = d->mapHash_.value(akey: map); |
140 | |
141 | tile_iter rem = tilesRemoved.constBegin(); |
142 | tile_iter remEnd = tilesRemoved.constEnd(); |
143 | for (; rem != remEnd; ++rem) { |
144 | oldTiles.remove(value: *rem); |
145 | } |
146 | |
147 | tile_iter add = tilesAdded.constBegin(); |
148 | tile_iter addEnd = tilesAdded.constEnd(); |
149 | for (; add != addEnd; ++add) { |
150 | oldTiles.insert(value: *add); |
151 | } |
152 | |
153 | d->mapHash_.insert(akey: map, avalue: oldTiles); |
154 | |
155 | // add and remove map from mapset for the tiles |
156 | |
157 | QSet<QGeoTileSpec> reqTiles; |
158 | QSet<QGeoTileSpec> cancelTiles; |
159 | |
160 | rem = tilesRemoved.constBegin(); |
161 | for (; rem != remEnd; ++rem) { |
162 | QSet<QGeoTiledMap *> mapSet = d->tileHash_.value(akey: *rem); |
163 | mapSet.remove(value: map); |
164 | if (mapSet.isEmpty()) { |
165 | cancelTiles.insert(value: *rem); |
166 | d->tileHash_.remove(akey: *rem); |
167 | } else { |
168 | d->tileHash_.insert(akey: *rem, avalue: mapSet); |
169 | } |
170 | } |
171 | |
172 | add = tilesAdded.constBegin(); |
173 | for (; add != addEnd; ++add) { |
174 | QSet<QGeoTiledMap *> mapSet = d->tileHash_.value(akey: *add); |
175 | if (mapSet.isEmpty()) { |
176 | reqTiles.insert(value: *add); |
177 | } |
178 | mapSet.insert(value: map); |
179 | d->tileHash_.insert(akey: *add, avalue: mapSet); |
180 | } |
181 | |
182 | cancelTiles -= reqTiles; |
183 | |
184 | QMetaObject::invokeMethod(obj: d->fetcher_, member: "updateTileRequests" , |
185 | type: Qt::QueuedConnection, |
186 | Q_ARG(QSet<QGeoTileSpec>, reqTiles), |
187 | Q_ARG(QSet<QGeoTileSpec>, cancelTiles)); |
188 | } |
189 | |
190 | void QGeoTiledMappingManagerEngine::engineTileFinished(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format) |
191 | { |
192 | Q_D(QGeoTiledMappingManagerEngine); |
193 | |
194 | QSet<QGeoTiledMap *> maps = d->tileHash_.value(akey: spec); |
195 | |
196 | typedef QSet<QGeoTiledMap *>::const_iterator map_iter; |
197 | |
198 | map_iter map = maps.constBegin(); |
199 | map_iter mapEnd = maps.constEnd(); |
200 | for (; map != mapEnd; ++map) { |
201 | QSet<QGeoTileSpec> tileSet = d->mapHash_.value(akey: *map); |
202 | tileSet.remove(value: spec); |
203 | if (tileSet.isEmpty()) |
204 | d->mapHash_.remove(akey: *map); |
205 | else |
206 | d->mapHash_.insert(akey: *map, avalue: tileSet); |
207 | } |
208 | |
209 | d->tileHash_.remove(akey: spec); |
210 | tileCache()->insert(spec, bytes, format, areas: d->cacheHint_); |
211 | |
212 | map = maps.constBegin(); |
213 | mapEnd = maps.constEnd(); |
214 | for (; map != mapEnd; ++map) { |
215 | (*map)->requestManager()->tileFetched(spec); |
216 | } |
217 | } |
218 | |
219 | void QGeoTiledMappingManagerEngine::engineTileError(const QGeoTileSpec &spec, const QString &errorString) |
220 | { |
221 | Q_D(QGeoTiledMappingManagerEngine); |
222 | |
223 | QSet<QGeoTiledMap *> maps = d->tileHash_.value(akey: spec); |
224 | typedef QSet<QGeoTiledMap *>::const_iterator map_iter; |
225 | map_iter map = maps.constBegin(); |
226 | map_iter mapEnd = maps.constEnd(); |
227 | for (; map != mapEnd; ++map) { |
228 | QSet<QGeoTileSpec> tileSet = d->mapHash_.value(akey: *map); |
229 | |
230 | tileSet.remove(value: spec); |
231 | if (tileSet.isEmpty()) |
232 | d->mapHash_.remove(akey: *map); |
233 | else |
234 | d->mapHash_.insert(akey: *map, avalue: tileSet); |
235 | } |
236 | d->tileHash_.remove(akey: spec); |
237 | |
238 | for (map = maps.constBegin(); map != mapEnd; ++map) { |
239 | (*map)->requestManager()->tileError(tile: spec, errorString); |
240 | } |
241 | |
242 | emit tileError(spec, errorString); |
243 | } |
244 | |
245 | void QGeoTiledMappingManagerEngine::setTileSize(const QSize &tileSize) |
246 | { |
247 | Q_D(QGeoTiledMappingManagerEngine); |
248 | d->tileSize_ = tileSize; |
249 | } |
250 | |
251 | void QGeoTiledMappingManagerEngine::setTileVersion(int version) |
252 | { |
253 | Q_D(QGeoTiledMappingManagerEngine); |
254 | if (d->m_tileVersion != version) { |
255 | d->m_tileVersion = version; |
256 | emit tileVersionChanged(); |
257 | } |
258 | } |
259 | |
260 | QSize QGeoTiledMappingManagerEngine::tileSize() const |
261 | { |
262 | Q_D(const QGeoTiledMappingManagerEngine); |
263 | return d->tileSize_; |
264 | } |
265 | |
266 | int QGeoTiledMappingManagerEngine::tileVersion() const |
267 | { |
268 | Q_D(const QGeoTiledMappingManagerEngine); |
269 | return d->m_tileVersion; |
270 | } |
271 | |
272 | QAbstractGeoTileCache::CacheAreas QGeoTiledMappingManagerEngine::cacheHint() const |
273 | { |
274 | Q_D(const QGeoTiledMappingManagerEngine); |
275 | return d->cacheHint_; |
276 | } |
277 | |
278 | void QGeoTiledMappingManagerEngine::setCacheHint(QAbstractGeoTileCache::CacheAreas cacheHint) |
279 | { |
280 | Q_D(QGeoTiledMappingManagerEngine); |
281 | d->cacheHint_ = cacheHint; |
282 | } |
283 | |
284 | /*! |
285 | Sets the tile cache. Takes ownership of the QObject. |
286 | */ |
287 | void QGeoTiledMappingManagerEngine::setTileCache(QAbstractGeoTileCache *cache) |
288 | { |
289 | Q_D(QGeoTiledMappingManagerEngine); |
290 | Q_ASSERT_X(!d->tileCache_, Q_FUNC_INFO, "This should be called only once" ); |
291 | cache->setParent(this); |
292 | d->tileCache_ = cache; |
293 | d->tileCache_->init(); |
294 | } |
295 | |
296 | QAbstractGeoTileCache *QGeoTiledMappingManagerEngine::tileCache() |
297 | { |
298 | Q_D(QGeoTiledMappingManagerEngine); |
299 | if (!d->tileCache_) { |
300 | QString cacheDirectory; |
301 | if (!managerName().isEmpty()) |
302 | cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + managerName(); |
303 | d->tileCache_ = new QGeoFileTileCache(cacheDirectory); |
304 | d->tileCache_->init(); |
305 | } |
306 | return d->tileCache_; |
307 | } |
308 | |
309 | QSharedPointer<QGeoTileTexture> QGeoTiledMappingManagerEngine::getTileTexture(const QGeoTileSpec &spec) |
310 | { |
311 | return d_ptr->tileCache_->get(spec); |
312 | } |
313 | |
314 | /******************************************************************************* |
315 | *******************************************************************************/ |
316 | |
317 | QGeoTiledMappingManagerEnginePrivate::QGeoTiledMappingManagerEnginePrivate() |
318 | : m_tileVersion(-1), |
319 | cacheHint_(QAbstractGeoTileCache::AllCaches), |
320 | tileCache_(0), |
321 | fetcher_(0) |
322 | { |
323 | } |
324 | |
325 | QGeoTiledMappingManagerEnginePrivate::~QGeoTiledMappingManagerEnginePrivate() |
326 | { |
327 | } |
328 | |
329 | QT_END_NAMESPACE |
330 | |