Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
13QGeoFileTileCacheOsm::QGeoFileTileCacheOsm(const QList<QGeoTileProviderOsm *> &providers,
14 const QString &offlineDirectory,
15 const QString &directory, QObject *parent)
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
38
39QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::get(const QGeoTileSpec &spec)
40{
41 QSharedPointer<QGeoTileTexture> tt = getFromMemory(spec);
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())
82 QDir::root().mkpath(directory_);
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));
103 if (fi.lastModified() > m_maxMapIdTimestamps[spec.mapId()])
104 m_maxMapIdTimestamps[spec.mapId()] = fi.lastModified();
105 }
106
107 // Base class ::init()
109
112}
113
114QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::getFromOfflineStorage(const QGeoTileSpec &spec)
115{
116 if (!m_offlineData)
117 return QSharedPointer<QGeoTileTexture>();
118
119 int providerId = spec.mapId() - 1;
120 if (providerId < 0 || providerId >= m_providers.size())
121 return QSharedPointer<QGeoTileTexture>();
122
123 const QString fileName = tileSpecToFilename(spec, QStringLiteral("*"), providerId);
125 if (!validTiles.size())
126 return QSharedPointer<QGeoTileTexture>();
127
128 QFile file(m_offlineDirectory.absoluteFilePath(validTiles.first()));
130 return QSharedPointer<QGeoTileTexture>();
131 QByteArray bytes = file.readAll();
132 file.close();
133
135 if (!image.loadFromData(bytes)) {
136 handleError(spec, QLatin1String("Problem with tile image"));
137 return QSharedPointer<QGeoTileTexture>();
138 }
139
140 addToMemoryCache(spec, bytes, QString());
141 return addToTextureCache(spec, image);
142}
143
145{
146 QList<QGeoTileSpec> keys;
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:20
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:1365
static QDir root()
Returns the root directory.
Definition qdir.h:224
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qdir.cpp:1715
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:23
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
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
qsizetype size() const noexcept
Definition qlist.h:397
void resize(qsizetype size)
Definition qlist.h:403
NetworkError
Indicates all possible error conditions found during the processing of the request.
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
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:8218
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
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:8084
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:165
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]
QStringList keys
QString dir
[11]
QStringList files
[8]
\inmodule QtCore \reentrant
Definition qchar.h:18