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
qgeotileproviderosm.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
6#include <QtCore/QJsonDocument>
7#include <QtCore/QJsonObject>
8#include <QDebug>
9
11
12static const int maxValidZoom = 30;
13static const QDateTime defaultTs = QDateTime::fromString(QStringLiteral("2016-06-01T00:00:00"), Qt::ISODate);
14
15static void setSSL(QGeoMapType &mapType, bool isHTTPS)
16{
17 QVariantMap metadata = mapType.metadata();
18 metadata["isHTTPS"] = isHTTPS;
19
20 mapType = QGeoMapType(mapType.style(), mapType.name(), mapType.description(), mapType.mobile(),
21 mapType.night(), mapType.mapId(), mapType.pluginName(), mapType.cameraCapabilities(),
22 metadata);
23}
24
26 const QList<TileProvider *> &providers,
27 const QGeoCameraCapabilities &cameraCapabilities)
28 : m_nm(nm),
29 m_provider(nullptr),
30 m_mapType(mapType),
31 m_status(Idle),
32 m_cameraCapabilities(cameraCapabilities)
33{
34 for (int i = 0; i < providers.size(); ++i) {
35 TileProvider *p = providers[i];
36 if (!m_provider)
39 }
40
41 if (!m_provider || m_provider->isValid())
43
46
48}
49
53
55{
56 if (m_status != Resolved || !m_provider)
57 return QUrl();
58 return m_provider->tileAddress(x, y, z);
59}
60
62{
63 if (m_status != Resolved || !m_provider)
64 return QString();
65 return m_provider->mapCopyRight();
66}
67
74
81
83{
84 if (m_status != Resolved || !m_provider)
85 return QString();
86 return m_provider->format();
87}
88
90{
91 if (m_status != Resolved || !m_provider)
92 return 0;
94}
95
97{
98 if (m_status != Resolved || !m_provider)
99 return 20;
101}
102
104{
105 if (!m_provider)
106 return false;
107 return m_provider->isHighDpi();
108}
109
111{
112 if (!m_provider)
113 return QDateTime();
114 return m_provider->timestamp();
115}
116
121
123{
124 return m_mapType;
125}
126
128{
129 if (m_status != Resolved || !m_provider)
130 return false;
131 return m_provider->isValid();
132}
133
135{
136 return (m_status == Resolved);
137}
138
150
152{
153 if (m_provider && m_provider->isValid())
154 return;
155 bool found = false;
157 if (p->isValid() && !found) {
158 m_provider = p;
160 found = true;
161 }
162 p->disconnect(this);
163 }
165}
166
168{
169 Q_UNUSED(provider);
170 // provider and m_provider are the same, at this point. m_status is Resolving.
173}
174
176{
177 Q_UNUSED(provider);
178 // provider and m_provider are the same at this point. m_status is Resolving.
179 if (!m_provider || m_provider->isInvalid()) {
180 m_provider = nullptr;
182 if (m_providerId >= m_providerList.size() -1) { // no hope left
183 emit resolutionError(this);
184 return;
185 }
186 // Advance the pointer in the provider list, and possibly start resolution on the next in the list.
187 for (int i = m_providerId + 1; i < m_providerList.size(); ++i) {
188 m_providerId = i;
190 if (!p->isInvalid()) {
191 m_provider = p;
192 if (!p->isValid()) {
193 m_status = Idle;
194#if 0 // leaving triggering the retry to the tile fetcher, instead of constantly spinning it in here.
197#endif
199 }
200 break;
201 }
202 }
203 if (!m_provider)
204 emit resolutionError(this);
205 } else if (m_provider->isValid()) {
208 } else { // still not resolved. But network error is recoverable.
209 m_status = Idle;
210#if 0 // leaving triggering the retry to the tile fetcher
212#endif
213 }
214}
215
229
231{
232 if (!provider)
233 return;
234 std::unique_ptr<TileProvider> p(provider);
235 if (provider->status() == TileProvider::Invalid)
236 return; // if the provider is already resolved and invalid, no point in adding it.
237
238 provider = p.release();
239 provider->setNetworkManager(m_nm);
240 provider->setParent(this);
241 m_providerList.append(provider);
242 if (!m_provider)
243 m_provider = provider;
244}
245
246
247/*
248 Class TileProvder
249*/
250
251static void sort2(int &a, int &b)
252{
253 if (a > b) {
254 int temp=a;
255 a=b;
256 b=temp;
257 }
258}
259
260TileProvider::TileProvider() : m_status(Invalid), m_nm(nullptr), m_timestamp(defaultTs), m_highDpi(false)
261{
262
263}
264
265TileProvider::TileProvider(const QUrl &urlRedirector, bool highDpi)
266: m_status(Idle), m_urlRedirector(urlRedirector), m_nm(nullptr), m_timestamp(defaultTs), m_highDpi(highDpi)
267{
270}
271
273 const QString &format,
274 const QString &copyRightMap,
275 const QString &copyRightData,
276 bool highDpi,
277 int minimumZoomLevel,
278 int maximumZoomLevel)
279: m_status(Invalid), m_nm(nullptr), m_urlTemplate(urlTemplate),
280 m_format(format), m_copyRightMap(copyRightMap), m_copyRightData(copyRightData),
281 m_minimumZoomLevel(minimumZoomLevel), m_maximumZoomLevel(maximumZoomLevel), m_timestamp(defaultTs), m_highDpi(highDpi)
282{
284}
285
289
316
318{
319 switch (error) {
330 // Errors we don't expect to recover from in the near future, which
331 // prevent accessing the redirection info but not the actual providers.
333 default:
334 //qWarning() << "QGeoTileProviderOsm network error:" << error;
335 break;
336 }
337}
338
340{
341 QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
343
344 switch (m_status) {
345 case Resolving:
346 m_status = Idle;
347 case Idle: // should not happen
348 case Invalid: // should not happen
349 break;
350 case Valid: // should not happen
352 return;
353 }
354
355 QObject errorEmitter;
356 QMetaObject::Connection errorEmitterConnection =
357 connect(&errorEmitter, &QObject::destroyed, this, [this](){ this->resolutionError(this); });
358
359 if (reply->error() != QNetworkReply::NoError) {
361 return;
362 }
364
365 /*
366 * The content of a provider information file must be in JSON format, containing
367 * (as of Qt 5.6.2) the following fields:
368 *
369 * {
370 * "Enabled" : bool, (optional)
371 * "UrlTemplate" : "<url template>", (mandatory)
372 * "ImageFormat" : "<image format>", (mandatory)
373 * "MapCopyRight" : "<copyright>", (mandatory)
374 * "DataCopyRight" : "<copyright>", (mandatory)
375 * "StyleCopyRight" : "<copyright>", (optional)
376 * "MinimumZoomLevel" : <minimumZoomLevel>, (optional)
377 * "MaximumZoomLevel" : <maximumZoomLevel>, (optional)
378 * "Timestamp" : <timestamp>, (optional)
379 * }
380 *
381 * Enabled is optional, and allows to temporarily disable a tile provider if it becomes
382 * unavailable, without making the osm plugin fire requests to it. Default is true.
383 *
384 * MinimumZoomLevel and MaximumZoomLevel are also optional, and allow to prevent invalid tile
385 * requests to the providers, if they do not support the specific ZL. Default is 0 and 20,
386 * respectively.
387 *
388 * UrlTemplate is required, and is the tile url template, with %x, %y and %z as
389 * placeholders for the actual parameters.
390 * Example:
391 * http://localhost:8080/maps/%z/%x/%y.png
392 *
393 * ImageFormat is required, and is the format of the tile.
394 * Examples:
395 * "png", "jpg"
396 *
397 * MapCopyRight is required and is the string that will be displayed in the "Map (c)" part
398 * of the on-screen copyright notice. Can be an empty string.
399 * Example:
400 * "<a href='http://www.mapquest.com/'>MapQuest</a>"
401 *
402 * DataCopyRight is required and is the string that will be displayed in the "Data (c)" part
403 * of the on-screen copyright notice. Can be an empty string.
404 * Example:
405 * "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
406 *
407 * StyleCopyRight is optional and is the string that will be displayed in the optional "Style (c)" part
408 * of the on-screen copyright notice.
409 *
410 * Timestamp is optional, and if set will cause QtLocation to clear the content of the cache older
411 * than this timestamp. The purpose is to prevent mixing tiles from different providers in the cache
412 * upon provider change. The value must be a string in ISO 8601 format (see Qt::ISODate)
413 */
414
417 if (error.error != QJsonParseError::NoError) {
418 qWarning() << "QGeoTileProviderOsm: Error parsing redirection data: "<<error.errorString() << "at "<<m_urlRedirector;
419 return;
420 }
421 if (!d.isObject()) {
422 qWarning() << "QGeoTileProviderOsm: Invalid redirection data" << "at "<<m_urlRedirector;
423 return;
424 }
425 const QJsonObject json = d.object();
426 const QJsonValue urlTemplate = json.value(QLatin1String("UrlTemplate"));
427 const QJsonValue imageFormat = json.value(QLatin1String("ImageFormat"));
428 const QJsonValue copyRightMap = json.value(QLatin1String("MapCopyRight"));
429 const QJsonValue copyRightData = json.value(QLatin1String("DataCopyRight"));
430 if ( urlTemplate == QJsonValue::Undefined
431 || imageFormat == QJsonValue::Undefined
432 || copyRightMap == QJsonValue::Undefined
433 || copyRightData == QJsonValue::Undefined
434 || !urlTemplate.isString()
435 || !imageFormat.isString()
436 || !copyRightMap.isString()
437 || !copyRightData.isString()) {
438 qWarning() << "QGeoTileProviderOsm: Incomplete redirection data" << "at "<<m_urlRedirector;
439 return;
440 }
441
442 m_urlTemplate = urlTemplate.toString();
443 m_format = imageFormat.toString();
444 m_copyRightMap = copyRightMap.toString();
445 m_copyRightData = copyRightData.toString();
446
447 const QJsonValue enabled = json.value(QLatin1String("Enabled"));
448 if (enabled.isBool() && ! enabled.toBool()) {
449 qWarning() << "QGeoTileProviderOsm: Tileserver disabled" << "at "<<m_urlRedirector;
450 return;
451 }
452
453 const QJsonValue copyRightStyle = json.value(QLatin1String("StyleCopyRight"));
454 if (copyRightStyle != QJsonValue::Undefined && copyRightStyle.isString())
455 m_copyRightStyle = copyRightStyle.toString();
456
459 const QJsonValue minZoom = json.value(QLatin1String("MinimumZoomLevel"));
460 if (minZoom.isDouble())
461 m_minimumZoomLevel = qBound(0, int(minZoom.toDouble()), maxValidZoom);
462 const QJsonValue maxZoom = json.value(QLatin1String("MaximumZoomLevel"));
463 if (maxZoom.isDouble())
464 m_maximumZoomLevel = qBound(0, int(maxZoom.toDouble()), maxValidZoom);
465
466 const QJsonValue ts = json.value(QLatin1String("Timestamp"));
467 if (ts.isString())
468 m_timestamp = QDateTime::fromString(ts.toString(), Qt::ISODate);
469
471 if (isValid()) {
472 QObject::disconnect(errorEmitterConnection);
474 }
475}
476
486
488{
490 return;
491
492 if (m_format.isEmpty())
493 return;
494
495 if (m_minimumZoomLevel < 0 || m_minimumZoomLevel > 30)
496 return;
497
498 if (m_maximumZoomLevel < 0 || m_maximumZoomLevel > 30 || m_maximumZoomLevel < m_minimumZoomLevel)
499 return;
500
501 // Currently supporting only %x, %y and &z
502 int offset[3];
504 if (offset[0] < 0)
505 return;
506
508 if (offset[1] < 0)
509 return;
510
512 if (offset[2] < 0)
513 return;
514
515 int sortedOffsets[3];
516 std::copy(offset, offset + 3, sortedOffsets);
517 sort2(sortedOffsets[0] ,sortedOffsets[1]);
518 sort2(sortedOffsets[1] ,sortedOffsets[2]);
519 sort2(sortedOffsets[0] ,sortedOffsets[1]);
520
521 int min = sortedOffsets[0];
522 int max = sortedOffsets[2];
523 int mid = sortedOffsets[1];
524
525 // Initing LUT
526 for (int i=0; i<3; i++) {
527 if (offset[0] == sortedOffsets[i])
528 paramsLUT[i] = 0;
529 else if (offset[1] == sortedOffsets[i])
530 paramsLUT[i] = 1;
531 else
532 paramsLUT[i] = 2;
533 }
534
535 m_urlPrefix = m_urlTemplate.mid(0 , min);
536 m_urlSuffix = m_urlTemplate.mid(max + 2, m_urlTemplate.size() - max - 2);
537
538 paramsSep[0] = m_urlTemplate.mid(min + 2, mid - min - 2);
539 paramsSep[1] = m_urlTemplate.mid(mid + 2, max - mid - 2);
540 m_status = Valid;
541}
542
544{
545 return m_status == Valid;
546}
547
549{
550 return m_status == Invalid;
551}
552
554{
555 return (m_status == Valid || m_status == Invalid);
556}
557
562
567
572
574{
575 return m_format;
576}
577
579{
580 return m_minimumZoomLevel;
581}
582
584{
585 return m_maximumZoomLevel;
586}
587
589{
590 return m_timestamp;
591}
592
594{
595 return m_highDpi;
596}
597
599{
600 return m_urlTemplate.startsWith(QStringLiteral("https"));
601}
602
604{
605 m_copyRightStyle = copyright;
606}
607
609{
611}
612
613QUrl TileProvider::tileAddress(int x, int y, int z) const
614{
615 if (z < m_minimumZoomLevel || z > m_maximumZoomLevel)
616 return QUrl();
617 int params[3] = { x, y, z};
618 QString url;
619 url += m_urlPrefix;
621 url += paramsSep[0];
623 url += paramsSep[1];
625 url += m_urlSuffix;
626 return QUrl(url);
627}
628
633
638
639
\inmodule QtCore\reentrant
Definition qdatetime.h:283
void setMaximumZoomLevel(double maximumZoomLevel)
void setMinimumZoomLevel(double minimumZoomLevel)
QML_STRUCTURED_VALUEMapStyle style
QVariantMap metadata
QByteArray pluginName() const
int mapId() const
QString description
QGeoCameraCapabilities cameraCapabilities
QGeoTileProviderOsm(QNetworkAccessManager *nm, const QGeoMapType &mapType, const QList< TileProvider * > &providers, const QGeoCameraCapabilities &cameraCapabilities)
QNetworkAccessManager * m_nm
void onResolutionFinished(TileProvider *provider)
QString dataCopyRight() const
const QGeoMapType & mapType() const
QGeoCameraCapabilities m_cameraCapabilities
QGeoCameraCapabilities cameraCapabilities() const
QDateTime timestamp() const
void onResolutionError(TileProvider *provider)
QList< TileProvider * > m_providerList
void addProvider(TileProvider *provider)
void resolutionFinished(const QGeoTileProviderOsm *provider)
QString styleCopyRight() const
void resolutionError(const QGeoTileProviderOsm *provider)
QUrl tileAddress(int x, int y, int z) const
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
\inmodule QtCore\reentrant
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
QJsonValue value(const QString &key) const
Returns a QJsonValue representing the value for the key key.
\inmodule QtCore\reentrant
Definition qjsonvalue.h:25
bool isString() const
Returns true if the value contains a string.
Definition qjsonvalue.h:75
bool isDouble() const
Returns true if the value contains a double.
Definition qjsonvalue.h:74
double toDouble(double defaultValue=0) const
Converts the value to a double and returns it.
QString toString() const
Converts the value to a QString and returns it.
qsizetype size() const noexcept
Definition qlist.h:397
void append(parameter_type t)
Definition qlist.h:458
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
The QNetworkAccessManager class allows the application to send network requests and receive replies.
QNetworkReply * get(const QNetworkRequest &request)
Posts a request to obtain the contents of the target request and returns a new QNetworkReply object o...
The QNetworkReply class contains the data and headers for a request sent with QNetworkAccessManager.
void errorOccurred(QNetworkReply::NetworkError)
NetworkError error() const
Returns the error that was found during the processing of this request.
NetworkError
Indicates all possible error conditions found during the processing of the request.
@ ContentOperationNotPermittedError
@ OperationNotImplementedError
@ AuthenticationRequiredError
void finished()
This signal is emitted when the reply has finished processing.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
void setHeader(KnownHeaders header, const QVariant &value)
Sets the value of the known header header to be value, overriding any previously set headers.
void setAttribute(Attribute code, const QVariant &value)
Sets the attribute associated with code code to be value value.
void setUrl(const QUrl &url)
Sets the URL this network request is referring to be url.
\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
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2658
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
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
\inmodule QtCore
Definition qurl.h:94
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1882
int minimumZoomLevel() const
void handleError(QNetworkReply::NetworkError error)
void onNetworkReplyError(QNetworkReply::NetworkError error)
int maximumZoomLevel() const
QString styleCopyRight() const
QString dataCopyRight() const
void resolutionFinished(TileProvider *provider)
bool isResolved() const
Status status() const
void setStyleCopyRight(const QString &copyright)
void setNetworkManager(QNetworkAccessManager *nm)
QString mapCopyRight() const
QUrl tileAddress(int x, int y, int z) const
QNetworkAccessManager * m_nm
QString format() const
const QDateTime & timestamp() const
void resolutionError(TileProvider *provider)
void setTimestamp(const QDateTime &timestamp)
Combined button and popup list for selecting options.
@ ISODate
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
DBusConnection const char DBusError * error
static void sort2(int &a, int &b)
static const QDateTime defaultTs
static void setSSL(QGeoMapType &mapType, bool isHTTPS)
static QT_BEGIN_NAMESPACE const int maxValidZoom
#define qWarning
Definition qlogging.h:166
@ Invalid
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLboolean GLboolean GLboolean b
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLint y
void ** params
GLfloat GLfloat p
[1]
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define emit
#define Q_UNUSED(x)
QUrl url("example.com")
[constructor-url-reference]
QObject::connect nullptr
QNetworkRequest request(url)
QNetworkReply * reply
\inmodule QtCore\reentrant
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962