Qt 6.x
The Qt SDK
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
5#include <QtLocation/private/qgeotilespec_p.h>
6#include <QDir>
7#include <QDirIterator>
8#include <QPair>
9#include <QDateTime>
10
12
14 const QString &offlineDirectory,
17 m_offlineDirectory(offlineDirectory),
18 m_offlineData(false),
19 m_providers(providers)
20{
21 m_highDpi.resize(providers.size());
22 if (!offlineDirectory.isEmpty()) {
23 m_offlineDirectory = QDir(offlineDirectory);
25 m_offlineData = true;
26 }
27 for (int i = 0; i < providers.size(); i++) {
28 providers[i]->setParent(this);
29 m_highDpi[i] = providers[i]->isHighDpi();
32 }
33}
34
36{
37}
38
40{
42 if (tt)
43 return tt;
44 if ((tt = getFromOfflineStorage(spec)))
45 return tt;
46 return getFromDisk(spec);
47}
48
50{
51 clearObsoleteTiles(provider);
52 Q_UNUSED(provider);
53 for (int i = 0; i < m_providers.size(); i++) {
54 if (m_providers[i]->isHighDpi() != m_highDpi[i]) { // e.g., HiDpi was requested but only LoDpi is available
55 int mapId = m_providers[i]->mapType().mapId();
56 m_highDpi[i] = m_providers[i]->isHighDpi();
57
58 // reload cache for mapId i
59 dropTiles(mapId);
60 loadTiles(mapId);
61
62 // send signal to clear scene in all maps created through this provider that use the reloaded tiles
63 emit mapDataUpdated(mapId);
64 }
65 }
66}
67
68// On resolution error the provider is removed.
69// This happens ONLY if there is no enabled hardcoded fallback for the mapId.
70// Hardcoded fallbacks also have a timestamp, that can get updated with Qt releases.
72{
74 clearObsoleteTiles(provider); // this still removes tiles who happen to be older than qgeotileproviderosm.cpp defaultTs
75}
76
77// init() is always called before the provider resolution starts
79{
80 if (directory_.isEmpty())
83
84 // find max mapId
85 int max = 0;
86 for (auto p: m_providers)
87 if (p->mapType().mapId() > max)
88 max = p->mapType().mapId();
89 // Create a mapId to maxTimestamp LUT..
90 m_maxMapIdTimestamps.resize(max+1); // initializes to invalid QDateTime
91
92 // .. by finding the newest file in each tileset (tileset = mapId).
95 formats << QLatin1String("*.*");
97
98 for (const QString &tileFileName : files) {
99 QGeoTileSpec spec = filenameToTileSpec(tileFileName);
100 if (spec.zoom() == -1)
101 continue;
102 QFileInfo fi(dir.filePath(tileFileName));
105 }
106
107 // Base class ::init()
109
112}
113
115{
116 if (!m_offlineData)
118
119 int providerId = spec.mapId() - 1;
120 if (providerId < 0 || providerId >= m_providers.size())
122
123 const QString fileName = tileSpecToFilename(spec, QStringLiteral("*"), providerId);
125 if (!validTiles.size())
127
128 QFile file(m_offlineDirectory.absoluteFilePath(validTiles.first()));
131 QByteArray bytes = file.readAll();
132 file.close();
133
135 if (!image.loadFromData(bytes)) {
136 handleError(spec, QLatin1String("Problem with tile image"));
138 }
139
140 addToMemoryCache(spec, bytes, QString());
141 return addToTextureCache(spec, image);
142}
143
145{
148 for (const QGeoTileSpec &k : keys)
149 if (k.mapId() == mapId)
151
153 for (const QGeoTileSpec &k : keys)
154 if (k.mapId() == mapId)
156
157 keys = diskCache_.keys();
158 for (const QGeoTileSpec &k : keys)
159 if (k.mapId() == mapId)
161}
162
164{
166 formats << QLatin1String("*.*");
167
170
171 for (int i = 0; i < files.size(); ++i) {
173 if (spec.zoom() == -1 || spec.mapId() != mapId)
174 continue;
175 QString filename = dir.filePath(files.at(i));
176 addToDiskCache(spec, filename);
177 }
178}
179
181{
182 int providerId = spec.mapId() - 1;
183 if (providerId < 0 || providerId >= m_providers.size())
184 return QString();
185
187 return dir.filePath(tileSpecToFilename(spec, format, providerId));
188}
189
191{
192 QString filename = spec.plugin();
193 filename += QLatin1String("-");
194 filename += (m_providers[providerId]->isHighDpi()) ? QLatin1Char('h') : QLatin1Char('l');
195 filename += QLatin1String("-");
196 filename += QString::number(spec.mapId());
197 filename += QLatin1String("-");
198 filename += QString::number(spec.zoom());
199 filename += QLatin1String("-");
200 filename += QString::number(spec.x());
201 filename += QLatin1String("-");
202 filename += QString::number(spec.y());
203
204 //Append version if real version number to ensure backwards compatibility and eviction of old tiles
205 if (spec.version() != -1) {
206 filename += QLatin1String("-");
207 filename += QString::number(spec.version());
208 }
209
210 filename += QLatin1String(".");
211 filename += format;
212 return filename;
213}
214
216{
217 QGeoTileSpec emptySpec;
218
219 QStringList parts = filename.split('.');
220
221 if (parts.length() != 2)
222 return emptySpec;
223
224 QString name = parts.at(0);
225 QStringList fields = name.split('-');
226
227 int length = fields.length();
228 if (length != 6 && length != 7)
229 return emptySpec;
230
231 QList<int> numbers;
232
233 bool ok = false;
234 for (int i = 2; i < length; ++i) {
235 ok = false;
236 int value = fields.at(i).toInt(&ok);
237 if (!ok)
238 return emptySpec;
239 numbers.append(value);
240 }
241
242 if (numbers.at(0) > m_providers.size())
243 return emptySpec;
244
245 bool highDpi = m_providers[numbers.at(0) - 1]->isHighDpi();
246 if (highDpi && fields.at(1) != QLatin1Char('h'))
247 return emptySpec;
248 else if (!highDpi && fields.at(1) != QLatin1Char('l'))
249 return emptySpec;
250
251 //File name without version, append default
252 if (numbers.length() < 5)
253 numbers.append(-1);
254
255 return QGeoTileSpec(fields.at(0),
256 numbers.at(0),
257 numbers.at(1),
258 numbers.at(2),
259 numbers.at(3),
260 numbers.at(4));
261}
262
264{
265 // process initialized providers, and connect the others
266
267 if (p->isResolved()) {
268 if (m_maxMapIdTimestamps[p->mapType().mapId()].isValid() && // there are tiles in the cache
269 p->timestamp() > m_maxMapIdTimestamps[p->mapType().mapId()]) { // and they are older than the provider
270 qInfo() << "provider for " << p->mapType().name() << " timestamp: " << p->timestamp()
271 << " -- data last modified: " << m_maxMapIdTimestamps[p->mapType().mapId()] << ". Clearing.";
272 clearMapId(p->mapType().mapId());
273 m_maxMapIdTimestamps[p->mapType().mapId()] = p->timestamp(); // don't do it again.
274 }
275 } else {
278#if 0 // If resolution fails, better not try to remove anything. Beside, on error, resolutionFinished is also emitted.
281#endif
282 }
283}
284
static QString baseLocationCacheDirectory()
virtual void handleError(const QGeoTileSpec &spec, const QString &errorString)
\inmodule QtCore
Definition qbytearray.h:57
void remove(const Key &key, bool force=false)
Definition qcache3q_p.h:378
QList< Key > keys() const
Definition qcache3q_p.h:392
\inmodule QtCore
Definition qdir.h:19
QStringList entryList(Filters filters=NoFilter, SortFlags sort=NoSort) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qdir.cpp:1364
static QDir root()
Returns the root directory.
Definition qdir.h:221
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qdir.cpp:1715
bool mkpath(const QString &dirPath) const
Creates the directory path dirPath.
Definition qdir.cpp:1579
QString absoluteFilePath(const QString &fileName) const
Returns the absolute path name of a file in the directory.
Definition qdir.cpp:809
@ Files
Definition qdir.h:22
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QDateTime lastModified() const
Returns the date and time when the file was last modified.
Definition qfileinfo.h:156
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
QList< QDateTime > m_maxMapIdTimestamps
QSharedPointer< QGeoTileTexture > getFromOfflineStorage(const QGeoTileSpec &spec)
QList< QGeoTileProviderOsm * > m_providers
void mapDataUpdated(int mapId)
QGeoTileSpec filenameToTileSpec(const QString &filename) const override
QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, int providerId) const
QGeoFileTileCacheOsm(const QList< QGeoTileProviderOsm * > &providers, const QString &offlineDirectory=QString(), const QString &directory=QString(), QObject *parent=nullptr)
QSharedPointer< QGeoTileTexture > get(const QGeoTileSpec &spec) override
void clearObsoleteTiles(const QGeoTileProviderOsm *p)
void onProviderResolutionFinished(const QGeoTileProviderOsm *provider)
QCache3Q< QGeoTileSpec, QGeoCachedTileMemory > memoryCache_
QSharedPointer< QGeoTileTexture > getFromDisk(const QGeoTileSpec &spec)
QSharedPointer< QGeoTileTexture > addToTextureCache(const QGeoTileSpec &spec, const QImage &image)
QCache3Q< QGeoTileSpec, QGeoTileTexture > textureCache_
void addToMemoryCache(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format)
QString directory() const
void clearMapId(int mapId)
QCache3Q< QGeoTileSpec, QGeoCachedTileDisk, QCache3QTileEvictionPolicy > diskCache_
QSharedPointer< QGeoCachedTileDisk > addToDiskCache(const QGeoTileSpec &spec, const QString &filename)
QSharedPointer< QGeoTileTexture > getFromMemory(const QGeoTileSpec &spec)
void resolutionFinished(const QGeoTileProviderOsm *provider)
void resolutionError(const QGeoTileProviderOsm *provider)
int x() const
int version() const
int zoom() const
int mapId() const
QString plugin() const
int y() const
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
\inmodule QtGui
Definition qimage.h:37
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
qsizetype length() const noexcept
Definition qlist.h:388
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void resize(qsizetype size)
Definition qlist.h:392
void append(parameter_type t)
Definition qlist.h:441
NetworkError
Indicates all possible error conditions found during the processing of the request.
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
EGLint EGLint * formats
Combined button and popup list for selecting options.
Definition image.cpp:4
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qInfo
Definition qlogging.h:161
GLenum GLuint GLenum GLsizei length
GLuint name
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat p
[1]
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define emit
#define Q_UNUSED(x)
QFile file
[0]
QFileInfo fi("c:/temp/foo")
[newstuff]
QStringList keys
QString dir
[11]
QStringList files
[8]
\inmodule QtCore \reentrant
Definition qchar.h:17
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent