Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgeotilerequestmanager.cpp
Go to the documentation of this file.
1// Copyright (C) 2015 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
9
10#include <QtCore/QPointer>
11#include <QtCore/QTimer>
12
13QT_BEGIN_NAMESPACE
14
15class RetryFuture;
16
18{
19public:
20 explicit QGeoTileRequestManagerPrivate(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine);
22
23 QGeoTiledMap *m_map;
25
26 QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > requestTiles(const QSet<QGeoTileSpec> &tiles);
27 void tileError(const QGeoTileSpec &tile, const QString &errorString);
28
32
33 void tileFetched(const QGeoTileSpec &spec);
34};
35
36QGeoTileRequestManager::QGeoTileRequestManager(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine)
37 : d_ptr(new QGeoTileRequestManagerPrivate(map, engine))
38{
39
40}
41
42QGeoTileRequestManager::~QGeoTileRequestManager()
43{
44
45}
46
47QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > QGeoTileRequestManager::requestTiles(const QSet<QGeoTileSpec> &tiles)
48{
49 return d_ptr->requestTiles(tiles);
50}
51
52void QGeoTileRequestManager::tileFetched(const QGeoTileSpec &spec)
53{
54 d_ptr->tileFetched(spec);
55}
56
57QSharedPointer<QGeoTileTexture> QGeoTileRequestManager::tileTexture(const QGeoTileSpec &spec)
58{
59 if (d_ptr->m_engine)
60 return d_ptr->m_engine->getTileTexture(spec);
61 else
62 return QSharedPointer<QGeoTileTexture>();
63}
64
65void QGeoTileRequestManager::tileError(const QGeoTileSpec &tile, const QString &errorString)
66{
67 d_ptr->tileError(tile, errorString);
68}
69
70QGeoTileRequestManagerPrivate::QGeoTileRequestManagerPrivate(QGeoTiledMap *map,QGeoTiledMappingManagerEngine *engine)
71 : m_map(map),
73{
74}
75
79
81{
82 QSet<QGeoTileSpec> cancelTiles = m_requested - tiles;
83 QSet<QGeoTileSpec> requestTiles = tiles - m_requested;
84 QSet<QGeoTileSpec> cached;
85// int tileSize = tiles.size();
86// int newTiles = requestTiles.size();
87
88 typedef QSet<QGeoTileSpec>::const_iterator iter;
89
90 QMap<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > cachedTex;
91
92 // remove tiles in cache from request tiles
93 if (!m_engine.isNull()) {
94 iter i = requestTiles.constBegin();
95 iter end = requestTiles.constEnd();
96 for (; i != end; ++i) {
97 QGeoTileSpec tile = *i;
98 QSharedPointer<QGeoTileTexture> tex = m_engine->getTileTexture(tile);
99 if (tex) {
100 if (!tex->image.isNull())
101 cachedTex.insert(tile, tex);
102 cached.insert(tile);
103 } else {
104 // Try to use textures from lower zoom levels, but still request the proper tile
105 QGeoTileSpec spec = tile;
106 const int endRange = qMax(0, tile.zoom() - 4); // Using up to 4 zoom levels up. 4 is arbitrary.
107 for (int z = tile.zoom() - 1; z >= endRange; z--) {
108 int denominator = 1 << (tile.zoom() - z);
109 spec.setZoom(z);
110 spec.setX(tile.x() / denominator);
111 spec.setY(tile.y() / denominator);
112 QSharedPointer<QGeoTileTexture> t = m_engine->getTileTexture(spec);
113 if (t && !t->image.isNull()) {
114 cachedTex.insert(tile, t);
115 break;
116 }
117 }
118 }
119 }
120 }
121
122 requestTiles -= cached;
123
124 m_requested -= cancelTiles;
125 m_requested += requestTiles;
126
127// qDebug() << "required # tiles: " << tileSize << ", new tiles: " << newTiles << ", total server requests: " << requested_.size();
128
129 if (!requestTiles.isEmpty() || !cancelTiles.isEmpty()) {
130 if (!m_engine.isNull()) {
131// qDebug() << "new server requests: " << requestTiles.size() << ", server cancels: " << cancelTiles.size();
132 m_engine->updateTileRequests(m_map, requestTiles, cancelTiles);
133
134 // Remove any cancelled tiles from the error retry hash to avoid
135 // re-using the numbers for a totally different request cycle.
136 iter i = cancelTiles.constBegin();
137 iter end = cancelTiles.constEnd();
138 for (; i != end; ++i) {
139 m_retries.remove(*i);
140 m_futures.remove(*i);
141 }
142 }
143 }
144
145 return cachedTex;
146}
147
148void QGeoTileRequestManagerPrivate::tileFetched(const QGeoTileSpec &spec)
149{
150 m_map->updateTile(spec);
151 m_requested.remove(spec);
152 m_retries.remove(spec);
153 m_futures.remove(spec);
154}
155
156// Represents a tile that needs to be retried after a certain period of time
157class RetryFuture : public QObject
158{
160public:
162
163public Q_SLOTS:
164 void retry();
165
166private:
167 QGeoTileSpec m_tile;
168 QGeoTiledMap *m_map;
169 QPointer<QGeoTiledMappingManagerEngine> m_engine;
170};
171
172RetryFuture::RetryFuture(const QGeoTileSpec &tile, QGeoTiledMap *map, QGeoTiledMappingManagerEngine* engine, QObject *parent)
173 : QObject(parent), m_tile(tile), m_map(map), m_engine(engine)
174{}
175
176void RetryFuture::retry()
177{
178 QSet<QGeoTileSpec> requestTiles;
179 QSet<QGeoTileSpec> cancelTiles;
180 requestTiles.insert(m_tile);
181 if (!m_engine.isNull())
182 m_engine->updateTileRequests(m_map, requestTiles, cancelTiles);
183}
184
185void QGeoTileRequestManagerPrivate::tileError(const QGeoTileSpec &tile, const QString &errorString)
186{
187 if (m_requested.contains(tile)) {
188 int count = m_retries.value(tile, 0);
189 m_retries.insert(tile, count + 1);
190
191 if (count >= 5) {
192 qWarning("QGeoTileRequestManager: Failed to fetch tile (%d,%d,%d) 5 times, giving up. "
193 "Last error message was: '%s'",
194 tile.x(), tile.y(), tile.zoom(), qPrintable(errorString));
195 m_requested.remove(tile);
196 m_retries.remove(tile);
197 m_futures.remove(tile);
198
199 } else {
200 // Exponential time backoff when retrying
201 int delay = (1 << count) * 500;
202
203 QSharedPointer<RetryFuture> future(new RetryFuture(tile,m_map,m_engine));
204 m_futures.insert(tile, future);
205
206 QTimer::singleShot(delay, future.data(), &RetryFuture::retry);
207 // Passing .data() to singleShot is ok -- Qt will clean up the
208 // connection if the target qobject is deleted
209 }
210 }
211}
212
213QT_END_NAMESPACE
214
215#include "qgeotilerequestmanager.moc"
QMap< QGeoTileSpec, QSharedPointer< QGeoTileTexture > > requestTiles(const QSet< QGeoTileSpec > &tiles)
void tileError(const QGeoTileSpec &tile, const QString &errorString)
void tileFetched(const QGeoTileSpec &spec)
QGeoTileRequestManagerPrivate(QGeoTiledMap *map, QGeoTiledMappingManagerEngine *engine)
QHash< QGeoTileSpec, int > m_retries
QPointer< QGeoTiledMappingManagerEngine > m_engine
QHash< QGeoTileSpec, QSharedPointer< RetryFuture > > m_futures