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 <QtCore/QTimerEvent>
38
39#include "qgeomappingmanagerengine_p.h"
40#include "qgeotilefetcher_p.h"
41#include "qgeotilefetcher_p_p.h"
42#include "qgeotiledmapreply_p.h"
43#include "qgeotilespec_p.h"
44#include "qgeotiledmap_p.h"
45
46#include <algorithm>
47#include <iterator>
48
49QT_BEGIN_NAMESPACE
50
51QGeoTileFetcher::QGeoTileFetcher(QGeoMappingManagerEngine *parent)
52: QObject(*new QGeoTileFetcherPrivate(), parent)
53{
54 Q_D(QGeoTileFetcher);
55
56 d->enabled_ = true;
57 d->engine_ = parent;
58}
59
60QGeoTileFetcher::QGeoTileFetcher(QGeoTileFetcherPrivate &dd, QGeoMappingManagerEngine *parent)
61: QObject(dd,parent)
62{
63 Q_D(QGeoTileFetcher);
64 d->enabled_ = true;
65 d->engine_ = parent;
66}
67
68QGeoTileFetcher::~QGeoTileFetcher()
69{
70}
71
72void QGeoTileFetcher::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded,
73 const QSet<QGeoTileSpec> &tilesRemoved)
74{
75 Q_D(QGeoTileFetcher);
76
77 QMutexLocker ml(&d->queueMutex_);
78
79 cancelTileRequests(tiles: tilesRemoved);
80
81 std::copy(first: tilesAdded.cbegin(), last: tilesAdded.cend(), result: std::back_inserter(x&: d->queue_));
82
83 if (d->enabled_ && initialized() && !d->queue_.isEmpty() && !d->timer_.isActive())
84 d->timer_.start(msec: 0, obj: this);
85}
86
87void QGeoTileFetcher::cancelTileRequests(const QSet<QGeoTileSpec> &tiles)
88{
89 Q_D(QGeoTileFetcher);
90
91 typedef QSet<QGeoTileSpec>::const_iterator tile_iter;
92 // No need to lock: called only in updateTileRequests
93 tile_iter tile = tiles.constBegin();
94 tile_iter end = tiles.constEnd();
95 for (; tile != end; ++tile) {
96 QGeoTiledMapReply *reply = d->invmap_.value(akey: *tile, adefaultValue: 0);
97 if (reply) {
98 d->invmap_.remove(akey: *tile);
99 reply->abort();
100 if (reply->isFinished())
101 reply->deleteLater();
102 }
103 d->queue_.removeAll(t: *tile);
104 }
105}
106
107void QGeoTileFetcher::requestNextTile()
108{
109 Q_D(QGeoTileFetcher);
110
111 QMutexLocker ml(&d->queueMutex_);
112
113 if (!d->enabled_)
114 return;
115
116 if (d->queue_.isEmpty())
117 return;
118
119 QGeoTileSpec ts = d->queue_.takeFirst();
120 if (d->queue_.isEmpty())
121 d->timer_.stop();
122
123 // Check against min/max zoom to prevent sending requests for not existing objects
124 const QGeoCameraCapabilities & cameraCaps = d->engine_->cameraCapabilities(mapId: ts.mapId());
125 // the ZL in QGeoTileSpec is relative to the native tile size of the provider.
126 // It gets denormalized in QGeoTiledMap.
127 if (ts.zoom() < cameraCaps.minimumZoomLevel() || ts.zoom() > cameraCaps.maximumZoomLevel() || !fetchingEnabled())
128 return;
129
130 QGeoTiledMapReply *reply = getTileImage(spec: ts);
131 if (!reply)
132 return;
133
134 if (reply->isFinished()) {
135 handleReply(reply, spec: ts);
136 } else {
137 connect(sender: reply,
138 SIGNAL(finished()),
139 receiver: this,
140 SLOT(finished()),
141 Qt::QueuedConnection);
142
143 d->invmap_.insert(akey: ts, avalue: reply);
144 }
145}
146
147void QGeoTileFetcher::finished()
148{
149 Q_D(QGeoTileFetcher);
150
151 QMutexLocker ml(&d->queueMutex_);
152
153 QGeoTiledMapReply *reply = qobject_cast<QGeoTiledMapReply *>(object: sender());
154 if (!reply)
155 return;
156
157 QGeoTileSpec spec = reply->tileSpec();
158
159 if (!d->invmap_.contains(akey: spec)) {
160 reply->deleteLater();
161 return;
162 }
163
164 d->invmap_.remove(akey: spec);
165
166 handleReply(reply, spec);
167}
168
169void QGeoTileFetcher::timerEvent(QTimerEvent *event)
170{
171 Q_D(QGeoTileFetcher);
172 if (event->timerId() != d->timer_.timerId()) {
173 QObject::timerEvent(event);
174 return;
175 }
176
177 QMutexLocker ml(&d->queueMutex_);
178 if (d->queue_.isEmpty() || !initialized()) {
179 d->timer_.stop();
180 return;
181 }
182 ml.unlock();
183
184 requestNextTile();
185}
186
187bool QGeoTileFetcher::initialized() const
188{
189 return true;
190}
191
192bool QGeoTileFetcher::fetchingEnabled() const
193{
194 return true;
195}
196
197void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec)
198{
199 Q_D(QGeoTileFetcher);
200
201 if (!d->enabled_) {
202 reply->deleteLater();
203 return;
204 }
205
206 if (reply->error() == QGeoTiledMapReply::NoError) {
207 emit tileFinished(spec, bytes: reply->mapImageData(), format: reply->mapImageFormat());
208 } else {
209 emit tileError(spec, errorString: reply->errorString());
210 }
211
212 reply->deleteLater();
213}
214
215/*******************************************************************************
216*******************************************************************************/
217
218QGeoTileFetcherPrivate::QGeoTileFetcherPrivate()
219: QObjectPrivate(), enabled_(false), engine_(0)
220{
221}
222
223QGeoTileFetcherPrivate::~QGeoTileFetcherPrivate()
224{
225}
226
227QT_END_NAMESPACE
228

source code of qtlocation/src/location/maps/qgeotilefetcher.cpp