Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qgeofiletilecacheosm.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 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:critical reason:filesystem-manipulation
4
5
#
include
"qgeofiletilecacheosm.h"
6
#
include
<
QtLocation
/
private
/
qgeotilespec_p
.
h
>
7
#
include
<
QDir
>
8
#
include
<
QDirIterator
>
9
#
include
<
QPair
>
10
#
include
<
QDateTime
>
11
12
QT_BEGIN_NAMESPACE
13
14
QGeoFileTileCacheOsm::QGeoFileTileCacheOsm(
const
QList<QGeoTileProviderOsm *> &providers,
15
const
QString &offlineDirectory,
16
const
QString &directory, QObject *parent)
17
: QGeoFileTileCache(directory, parent),
18
m_offlineDirectory(offlineDirectory),
19
m_offlineData(
false
),
20
m_providers(providers)
21
{
22
m_highDpi.resize(providers.size());
23
if
(!offlineDirectory.isEmpty()) {
24
m_offlineDirectory = QDir(offlineDirectory);
25
if
(m_offlineDirectory.exists())
26
m_offlineData =
true
;
27
}
28
for
(
int
i = 0; i < providers.size(); i++) {
29
providers[i]->setParent(
this
);
30
m_highDpi[i] = providers[i]->isHighDpi();
31
connect(providers[i], &QGeoTileProviderOsm::resolutionFinished,
this
, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
32
connect(providers[i], &QGeoTileProviderOsm::resolutionError,
this
, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
33
}
34
}
35
36
QGeoFileTileCacheOsm
::~
QGeoFileTileCacheOsm
()
37
{
38
}
39
40
QSharedPointer
<
QGeoTileTexture
>
QGeoFileTileCacheOsm
::
get
(
const
QGeoTileSpec &spec)
41
{
42
QSharedPointer<QGeoTileTexture> tt = getFromMemory(spec);
43
if
(tt)
44
return
tt;
45
if
((tt = getFromOfflineStorage(spec)))
46
return
tt;
47
return
getFromDisk(spec);
48
}
49
50
void
QGeoFileTileCacheOsm
::onProviderResolutionFinished(
const
QGeoTileProviderOsm
*provider)
51
{
52
clearObsoleteTiles
(
provider
)
;
53
Q_UNUSED(provider);
54
for
(
int
i = 0; i < m_providers.size(); i++) {
55
if
(m_providers[i]->isHighDpi() != m_highDpi[i]) {
// e.g., HiDpi was requested but only LoDpi is available
56
int
mapId = m_providers[i]->mapType().mapId();
57
m_highDpi[i] = m_providers[i]->isHighDpi();
58
59
// reload cache for mapId i
60
dropTiles
(
mapId
)
;
61
loadTiles
(
mapId
)
;
62
63
// send signal to clear scene in all maps created through this provider that use the reloaded tiles
64
emit mapDataUpdated(mapId);
65
}
66
}
67
}
68
69
// On resolution error the provider is removed.
70
// This happens ONLY if there is no enabled hardcoded fallback for the mapId.
71
// Hardcoded fallbacks also have a timestamp, that can get updated with Qt releases.
72
void
QGeoFileTileCacheOsm
::
onProviderResolutionError
(
const
QGeoTileProviderOsm
*provider, QNetworkReply::NetworkError error)
73
{
74
Q_UNUSED(error);
75
clearObsoleteTiles
(
provider
)
;
// this still removes tiles who happen to be older than qgeotileproviderosm.cpp defaultTs
76
}
77
78
// init() is always called before the provider resolution starts
79
void
QGeoFileTileCacheOsm
::
init
()
80
{
81
if
(directory_.isEmpty())
82
directory_ = baseLocationCacheDirectory();
83
QDir::root().mkpath(directory_);
84
85
// find max mapId
86
int
max = 0;
87
for
(
auto
p: std::as_const(m_providers))
88
if
(p->mapType().mapId() > max)
89
max = p->mapType().mapId();
90
// Create a mapId to maxTimestamp LUT..
91
m_maxMapIdTimestamps.resize(max+1);
// initializes to invalid QDateTime
92
93
// .. by finding the newest file in each tileset (tileset = mapId).
94
QDir dir(directory_);
95
QStringList formats;
96
formats << QLatin1String(
"*.*"
);
97
const
QStringList files = dir.entryList(formats, QDir::Files);
98
99
for
(
const
QString &tileFileName : files) {
100
QGeoTileSpec spec = filenameToTileSpec(tileFileName);
101
if
(spec.zoom() == -1)
102
continue
;
103
QFileInfo fi(dir.filePath(tileFileName));
104
if
(fi.lastModified() > m_maxMapIdTimestamps[spec.mapId()])
105
m_maxMapIdTimestamps[spec.mapId()] = fi.lastModified();
106
}
107
108
// Base class ::init()
109
QGeoFileTileCache::init();
110
111
for
(QGeoTileProviderOsm * p: std::as_const(m_providers))
112
clearObsoleteTiles(p);
113
}
114
115
QSharedPointer
<
QGeoTileTexture
>
QGeoFileTileCacheOsm
::
getFromOfflineStorage
(
const
QGeoTileSpec &spec)
116
{
117
if
(!m_offlineData)
118
return
QSharedPointer<QGeoTileTexture>();
119
120
int
providerId = spec.mapId() - 1;
121
if
(providerId < 0 || providerId >= m_providers.size())
122
return
QSharedPointer<QGeoTileTexture>();
123
124
const
QString fileName = tileSpecToFilename(spec, QStringLiteral(
"*"
), providerId);
125
QStringList validTiles = m_offlineDirectory.entryList({fileName});
126
if
(!validTiles.size())
127
return
QSharedPointer<QGeoTileTexture>();
128
129
QFile file(m_offlineDirectory.absoluteFilePath(validTiles.first()));
130
if
(!file.open(QIODevice::ReadOnly))
131
return
QSharedPointer<QGeoTileTexture>();
132
QByteArray bytes = file.readAll();
133
file.close();
134
135
QImage image;
136
if
(!image.loadFromData(bytes)) {
137
handleError(spec, QLatin1String(
"Problem with tile image"
));
138
return
QSharedPointer<QGeoTileTexture>();
139
}
140
141
addToMemoryCache(spec, bytes, QString());
142
return
addToTextureCache(spec, image);
143
}
144
145
void
QGeoFileTileCacheOsm
::
dropTiles
(
int
mapId)
146
{
147
{
148
const
QList<QGeoTileSpec> keys = textureCache_.keys();
149
for
(
const
QGeoTileSpec &k : keys)
150
if
(k.mapId() == mapId)
151
textureCache_.remove(k);
152
}
153
154
{
155
const
QList<QGeoTileSpec> keys = memoryCache_.keys();
156
for
(
const
QGeoTileSpec &k : keys)
157
if
(k.mapId() == mapId)
158
memoryCache_.remove(k);
159
}
160
161
{
162
const
QList<QGeoTileSpec> keys = diskCache_.keys();
163
for
(
const
QGeoTileSpec &k : keys)
164
if
(k.mapId() == mapId)
165
diskCache_.remove(k);
166
}
167
}
168
169
void
QGeoFileTileCacheOsm
::
loadTiles
(
int
mapId)
170
{
171
QStringList formats;
172
formats << QLatin1String(
"*.*"
);
173
174
QDir dir(directory_);
175
QStringList files = dir.entryList(formats, QDir::Files);
176
177
for
(
int
i = 0; i < files.size(); ++i) {
178
QGeoTileSpec spec = filenameToTileSpec(files.at(i));
179
if
(spec.zoom() == -1 || spec.mapId() != mapId)
180
continue
;
181
QString filename = dir.filePath(files.at(i));
182
addToDiskCache(spec, filename);
183
}
184
}
185
186
QString
QGeoFileTileCacheOsm
::
tileSpecToFilename
(
const
QGeoTileSpec &spec,
const
QString &format,
const
QString &directory)
const
187
{
188
int
providerId = spec.mapId() - 1;
189
if
(providerId < 0 || providerId >= m_providers.size())
190
return
QString();
191
192
QDir dir = QDir(directory);
193
return
dir.filePath(tileSpecToFilename(spec, format, providerId));
194
}
195
196
QString
QGeoFileTileCacheOsm
::
tileSpecToFilename
(
const
QGeoTileSpec &spec,
const
QString &format,
int
providerId)
const
197
{
198
QString filename = spec.plugin();
199
filename += QLatin1String(
"-"
);
200
filename += (m_providers[providerId]->isHighDpi()) ? QLatin1Char(
'h'
) : QLatin1Char(
'l'
);
201
filename += QLatin1String(
"-"
);
202
filename += QString::number(spec.mapId());
203
filename += QLatin1String(
"-"
);
204
filename += QString::number(spec.zoom());
205
filename += QLatin1String(
"-"
);
206
filename += QString::number(spec.x());
207
filename += QLatin1String(
"-"
);
208
filename += QString::number(spec.y());
209
210
//Append version if real version number to ensure backwards compatibility and eviction of old tiles
211
if
(spec.version() != -1) {
212
filename += QLatin1String(
"-"
);
213
filename += QString::number(spec.version());
214
}
215
216
filename += QLatin1String(
"."
);
217
filename += format;
218
return
filename;
219
}
220
221
QGeoTileSpec
QGeoFileTileCacheOsm
::
filenameToTileSpec
(
const
QString &filename)
const
222
{
223
QGeoTileSpec emptySpec;
224
225
QStringList parts = filename.split(
'.'
);
226
227
if
(parts.length() != 2)
228
return
emptySpec;
229
230
QString name = parts.at(0);
231
QStringList fields = name.split(
'-'
);
232
233
int
length = fields.length();
234
if
(length != 6 && length != 7)
235
return
emptySpec;
236
237
QList<
int
> numbers;
238
239
bool
ok =
false
;
240
for
(
int
i = 2; i < length; ++i) {
241
ok =
false
;
242
int
value = fields.at(i).toInt(&ok);
243
if
(!ok)
244
return
emptySpec;
245
numbers.append(value);
246
}
247
248
if
(numbers.at(0) > m_providers.size())
249
return
emptySpec;
250
251
bool
highDpi = m_providers[numbers.at(0) - 1]->isHighDpi();
252
if
(highDpi && fields.at(1) != QLatin1Char(
'h'
))
253
return
emptySpec;
254
else
if
(!highDpi && fields.at(1) != QLatin1Char(
'l'
))
255
return
emptySpec;
256
257
//File name without version, append default
258
if
(numbers.length() < 5)
259
numbers.append(-1);
260
261
return
QGeoTileSpec(fields.at(0),
262
numbers.at(0),
263
numbers.at(1),
264
numbers.at(2),
265
numbers.at(3),
266
numbers.at(4));
267
}
268
269
void
QGeoFileTileCacheOsm
::
clearObsoleteTiles
(
const
QGeoTileProviderOsm
*p)
270
{
271
// process initialized providers, and connect the others
272
273
if
(p
->
isResolved
(
)
) {
274
if
(m_maxMapIdTimestamps[p->mapType().mapId()].isValid() &&
// there are tiles in the cache
275
p->timestamp() > m_maxMapIdTimestamps[p->mapType().mapId()]) {
// and they are older than the provider
276
qInfo() <<
"provider for "
<< p->mapType().name() <<
" timestamp: "
<< p->timestamp()
277
<<
" -- data last modified: "
<< m_maxMapIdTimestamps[p->mapType().mapId()] <<
". Clearing."
;
278
clearMapId(p->mapType().mapId());
279
m_maxMapIdTimestamps[p->mapType().mapId()] = p->timestamp();
// don't do it again.
280
}
281
}
else
{
282
connect(p, &QGeoTileProviderOsm::resolutionFinished,
283
this
, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
284
#
if
0
// If resolution fails, better not try to remove anything. Beside, on error, resolutionFinished is also emitted.
285
connect(p, &QGeoTileProviderOsm::resolutionError,
286
this
, &QGeoFileTileCacheOsm::onProviderResolutionError);
287
#
endif
288
}
289
}
290
291
QT_END_NAMESPACE
QGeoFileTileCacheOsm
Definition
qgeofiletilecacheosm.h:17
QGeoFileTileCacheOsm::onProviderResolutionError
void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
Definition
qgeofiletilecacheosm.cpp:72
QGeoFileTileCacheOsm::getFromOfflineStorage
QSharedPointer< QGeoTileTexture > getFromOfflineStorage(const QGeoTileSpec &spec)
Definition
qgeofiletilecacheosm.cpp:115
QGeoFileTileCacheOsm::tileSpecToFilename
QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const override
Definition
qgeofiletilecacheosm.cpp:186
QGeoFileTileCacheOsm::init
void init() override
Definition
qgeofiletilecacheosm.cpp:79
QGeoFileTileCacheOsm::dropTiles
void dropTiles(int mapId)
Definition
qgeofiletilecacheosm.cpp:145
QGeoFileTileCacheOsm::filenameToTileSpec
QGeoTileSpec filenameToTileSpec(const QString &filename) const override
Definition
qgeofiletilecacheosm.cpp:221
QGeoFileTileCacheOsm::tileSpecToFilename
QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, int providerId) const
Definition
qgeofiletilecacheosm.cpp:196
QGeoFileTileCacheOsm::loadTiles
void loadTiles(int mapId)
Definition
qgeofiletilecacheosm.cpp:169
QGeoFileTileCacheOsm::get
QSharedPointer< QGeoTileTexture > get(const QGeoTileSpec &spec) override
Definition
qgeofiletilecacheosm.cpp:40
QGeoFileTileCacheOsm::clearObsoleteTiles
void clearObsoleteTiles(const QGeoTileProviderOsm *p)
Definition
qgeofiletilecacheosm.cpp:269
QGeoFileTileCacheOsm::~QGeoFileTileCacheOsm
~QGeoFileTileCacheOsm()
Definition
qgeofiletilecacheosm.cpp:36
QGeoTileProviderOsm
Definition
qgeotileproviderosm.h:101
QGeoTileProviderOsm::isResolved
bool isResolved() const
Definition
qgeotileproviderosm.cpp:135
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtlocation
src
plugins
geoservices
osm
qgeofiletilecacheosm.cpp
Generated on
for Qt by
1.18.0