QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsxyzvectortiledataprovider.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsxyzvectortiledataprovider.cpp
3 --------------------------------------
4 Date : March 2020
5 Copyright : (C) 2020 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
18#include "moc_qgsxyzvectortiledataprovider.cpp"
19#include "qgsthreadingutils.h"
20#include "qgstiles.h"
21#include "qgsvectortileloader.h"
22#include "qgsvectortileutils.h"
25#include "qgsapplication.h"
26#include "qgsauthmanager.h"
27#include "qgsmessagelog.h"
29#include "qgslogger.h"
30#include <QIcon>
31#include <QNetworkRequest>
32
34
35QString QgsXyzVectorTileDataProvider::XYZ_DATA_PROVIDER_KEY = QStringLiteral( "xyzvectortiles" );
36QString QgsXyzVectorTileDataProvider::XYZ_DATA_PROVIDER_DESCRIPTION = QObject::tr( "XYZ Vector Tiles data provider" );
37
38//
39// QgsXyzVectorTileDataProviderBase
40//
41
42QgsXyzVectorTileDataProviderBase::QgsXyzVectorTileDataProviderBase( const QString &uri, const ProviderOptions &providerOptions, Qgis::DataProviderReadFlags flags )
43 : QgsVectorTileDataProvider( uri, providerOptions, flags )
44{
45 QgsDataSourceUri dsUri;
46 dsUri.setEncodedUri( uri );
47 mAuthCfg = dsUri.authConfigId();
48 mHeaders = dsUri.httpHeaders();
49}
50
51QgsXyzVectorTileDataProviderBase::QgsXyzVectorTileDataProviderBase( const QgsXyzVectorTileDataProviderBase &other )
53{
54 mAuthCfg = other.mAuthCfg;
55 mHeaders = other.mHeaders;
56}
57
58bool QgsXyzVectorTileDataProviderBase::supportsAsync() const
59{
60 return true;
61}
62
63QgsVectorTileRawData QgsXyzVectorTileDataProviderBase::readTile( const QgsTileMatrixSet &set, const QgsTileXYZ &id, QgsFeedback *feedback ) const
64{
65 return QgsVectorTileRawData( id, loadFromNetwork( id, set.tileMatrix( id.zoomLevel() ), sourcePath(), mAuthCfg, mHeaders, feedback ) );
66}
67
68QList<QgsVectorTileRawData> QgsXyzVectorTileDataProviderBase::readTiles( const QgsTileMatrixSet &set, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback, Qgis::RendererUsage usage ) const
69{
70 QList<QgsVectorTileRawData> rawTiles;
71 rawTiles.reserve( tiles.size() );
72 for ( QgsTileXYZ id : std::as_const( tiles ) )
73 {
74 QMap<QString, QByteArray> data;
75 const QgsStringMap sources = sourcePaths();
76 QgsStringMap::const_iterator it = sources.constBegin();
77 for ( ; it != sources.constEnd(); ++it )
78 {
79 if ( feedback && feedback->isCanceled() )
80 break;
81
82 const QByteArray rawData = loadFromNetwork( id, set.tileMatrix( id.zoomLevel() ), it.value(), mAuthCfg, mHeaders, feedback, usage );
83 if ( !rawData.isEmpty() )
84 {
85 data[it.key()] = rawData;
86 }
87 }
88 rawTiles.append( QgsVectorTileRawData( id, data ) );
89 }
90 return rawTiles;
91}
92
93QList<QNetworkRequest> QgsXyzVectorTileDataProviderBase::tileRequests( const QgsTileMatrixSet &set, const QgsTileXYZ &id, Qgis::RendererUsage usage ) const
94{
95 QList<QNetworkRequest> requests;
96
97 const QgsStringMap sourcesPaths = sourcePaths();
98
99 QgsStringMap::const_iterator it = sourcesPaths.constBegin();
100
101 for ( ; it != sourcesPaths.constEnd(); ++it )
102 {
103 QString urlTemplate = it.value();
104 QString layerName = it.key();
105
106 if ( urlTemplate.contains( QLatin1String( "{usage}" ) ) )
107 {
108 switch ( usage )
109 {
111 urlTemplate.replace( QLatin1String( "{usage}" ), QLatin1String( "view" ) );
112 break;
114 urlTemplate.replace( QLatin1String( "{usage}" ), QLatin1String( "export" ) );
115 break;
117 urlTemplate.replace( QLatin1String( "{usage}" ), QString() );
118 break;
119 }
120 }
121
122 const QString url = QgsVectorTileUtils::formatXYZUrlTemplate( urlTemplate, id, set.tileMatrix( id.zoomLevel() ) );
123
124 QNetworkRequest request( url );
125 QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsXyzVectorTileDataProvider" ) );
126 QgsSetRequestInitiatorId( request, id.toString() );
127
128 request.setAttribute( static_cast<QNetworkRequest::Attribute>( QgsVectorTileDataProvider::DATA_COLUMN ), id.column() );
129 request.setAttribute( static_cast<QNetworkRequest::Attribute>( QgsVectorTileDataProvider::DATA_ROW ), id.row() );
130 request.setAttribute( static_cast<QNetworkRequest::Attribute>( QgsVectorTileDataProvider::DATA_ZOOM ), id.zoomLevel() );
131 request.setAttribute( static_cast<QNetworkRequest::Attribute>( QgsVectorTileDataProvider::DATA_SOURCE_ID ), layerName );
132
133 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
134 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
135
136 mHeaders.updateNetworkRequest( request );
137
138 if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg ) )
139 {
140 QgsMessageLog::logMessage( tr( "network request update failed for authentication config" ), tr( "Network" ) );
141 }
142
143 requests << request;
144 }
145
146 return requests;
147}
148
149QByteArray QgsXyzVectorTileDataProviderBase::loadFromNetwork( const QgsTileXYZ &id, const QgsTileMatrix &tileMatrix, const QString &requestUrl, const QString &authid, const QgsHttpHeaders &headers, QgsFeedback *feedback, Qgis::RendererUsage usage )
150{
151 QString url = QgsVectorTileUtils::formatXYZUrlTemplate( requestUrl, id, tileMatrix );
152
153 if ( url.contains( QLatin1String( "{usage}" ) ) )
154 {
155 switch ( usage )
156 {
158 url.replace( QLatin1String( "{usage}" ), QLatin1String( "view" ) );
159 break;
161 url.replace( QLatin1String( "{usage}" ), QLatin1String( "export" ) );
162 break;
164 url.replace( QLatin1String( "{usage}" ), QString() );
165 break;
166 }
167 }
168
169 QNetworkRequest nr;
170 nr.setUrl( QUrl( url ) );
171
172 headers.updateNetworkRequest( nr );
173
175 req.setAuthCfg( authid );
176 QgsDebugMsgLevel( QStringLiteral( "Blocking request: " ) + url, 2 );
177 QgsBlockingNetworkRequest::ErrorCode errCode = req.get( nr, false, feedback );
178 if ( errCode != QgsBlockingNetworkRequest::NoError )
179 {
180 QgsDebugError( QStringLiteral( "Request failed: " ) + url );
181 return QByteArray();
182 }
183 QgsNetworkReplyContent reply = req.reply();
184 QgsDebugMsgLevel( QStringLiteral( "Request successful, content size %1" ).arg( reply.content().size() ), 2 );
185 return reply.content();
186}
187
188
189//
190// QgsXyzVectorTileDataProviderMetadata
191//
192
193
194QgsXyzVectorTileDataProviderMetadata::QgsXyzVectorTileDataProviderMetadata()
195 : QgsProviderMetadata( QgsXyzVectorTileDataProvider::XYZ_DATA_PROVIDER_KEY, QgsXyzVectorTileDataProvider::XYZ_DATA_PROVIDER_DESCRIPTION )
196{
197}
198
199QgsXyzVectorTileDataProvider *QgsXyzVectorTileDataProviderMetadata::createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, Qgis::DataProviderReadFlags flags )
200{
201 return new QgsXyzVectorTileDataProvider( uri, options, flags );
202}
203
204QIcon QgsXyzVectorTileDataProviderMetadata::icon() const
205{
206 return QgsApplication::getThemeIcon( QStringLiteral( "mIconVectorTileLayer.svg" ) );
207}
208
209QgsProviderMetadata::ProviderCapabilities QgsXyzVectorTileDataProviderMetadata::providerCapabilities() const
210{
211 return FileBasedUris;
212}
213
214QVariantMap QgsXyzVectorTileDataProviderMetadata::decodeUri( const QString &uri ) const
215{
216 QgsDataSourceUri dsUri;
217 dsUri.setEncodedUri( uri );
218
219 QVariantMap uriComponents;
220 uriComponents.insert( QStringLiteral( "type" ), QStringLiteral( "xyz" ) );
221
222 if ( uriComponents[ QStringLiteral( "type" ) ] == QLatin1String( "mbtiles" ) ||
223 ( uriComponents[ QStringLiteral( "type" ) ] == QLatin1String( "xyz" ) &&
224 !dsUri.param( QStringLiteral( "url" ) ).startsWith( QLatin1String( "http" ) ) ) )
225 {
226 uriComponents.insert( QStringLiteral( "path" ), dsUri.param( QStringLiteral( "url" ) ) );
227 }
228 else
229 {
230 uriComponents.insert( QStringLiteral( "url" ), dsUri.param( QStringLiteral( "url" ) ) );
231 if ( dsUri.hasParam( QStringLiteral( "urlName" ) ) )
232 uriComponents.insert( QStringLiteral( "urlName" ), dsUri.param( QStringLiteral( "urlName" ) ) );
233 }
234 int i = 2;
235 while ( true )
236 {
237 QString url = dsUri.param( QStringLiteral( "url_%2" ).arg( i ) );
238 QString urlName = dsUri.param( QStringLiteral( "urlName_%2" ).arg( i ) );
239 if ( url.isEmpty() || urlName.isEmpty() )
240 break;
241 uriComponents.insert( QStringLiteral( "urlName_%2" ).arg( i ), urlName );
242 uriComponents.insert( QStringLiteral( "url_%2" ).arg( i ), url );
243 i++;
244 }
245
246
247 if ( dsUri.hasParam( QStringLiteral( "zmin" ) ) )
248 uriComponents.insert( QStringLiteral( "zmin" ), dsUri.param( QStringLiteral( "zmin" ) ) );
249 if ( dsUri.hasParam( QStringLiteral( "zmax" ) ) )
250 uriComponents.insert( QStringLiteral( "zmax" ), dsUri.param( QStringLiteral( "zmax" ) ) );
251
252 dsUri.httpHeaders().updateMap( uriComponents );
253
254 if ( dsUri.hasParam( QStringLiteral( "styleUrl" ) ) )
255 uriComponents.insert( QStringLiteral( "styleUrl" ), dsUri.param( QStringLiteral( "styleUrl" ) ) );
256
257 const QString authcfg = dsUri.authConfigId();
258 if ( !authcfg.isEmpty() )
259 uriComponents.insert( QStringLiteral( "authcfg" ), authcfg );
260
261 return uriComponents;
262}
263
264QString QgsXyzVectorTileDataProviderMetadata::encodeUri( const QVariantMap &parts ) const
265{
266 QgsDataSourceUri dsUri;
267 dsUri.setParam( QStringLiteral( "type" ), QStringLiteral( "xyz" ) );
268 dsUri.setParam( QStringLiteral( "url" ), parts.value( parts.contains( QStringLiteral( "path" ) ) ? QStringLiteral( "path" ) : QStringLiteral( "url" ) ).toString() );
269 if ( parts.contains( QStringLiteral( "urlName" ) ) )
270 dsUri.setParam( QStringLiteral( "urlName" ), parts[ QStringLiteral( "urlName" ) ].toString() );
271
272 int i = 2;
273 while ( true )
274 {
275 QString urlNameKey = QStringLiteral( "urlName_%2" ).arg( i );
276 QString urlKey = QStringLiteral( "url_%2" ).arg( i );
277
278 if ( !parts.contains( urlNameKey ) || !parts.contains( urlKey ) )
279 break;
280 QString url = dsUri.param( QStringLiteral( "url_%2" ).arg( i ) );
281 QString urlName = dsUri.param( QStringLiteral( "urlName_%2" ).arg( i ) );
282 if ( url.isEmpty() || urlName.isEmpty() )
283 break;
284
285 dsUri.setParam( urlNameKey, parts[ urlNameKey ].toString() );
286 dsUri.setParam( urlKey, parts[ urlKey ].toString() );
287 i++;
288 }
289
290 if ( parts.contains( QStringLiteral( "zmin" ) ) )
291 dsUri.setParam( QStringLiteral( "zmin" ), parts[ QStringLiteral( "zmin" ) ].toString() );
292 if ( parts.contains( QStringLiteral( "zmax" ) ) )
293 dsUri.setParam( QStringLiteral( "zmax" ), parts[ QStringLiteral( "zmax" ) ].toString() );
294
295 dsUri.httpHeaders().setFromMap( parts );
296
297 if ( parts.contains( QStringLiteral( "styleUrl" ) ) )
298 dsUri.setParam( QStringLiteral( "styleUrl" ), parts[ QStringLiteral( "styleUrl" ) ].toString() );
299
300 if ( parts.contains( QStringLiteral( "authcfg" ) ) )
301 dsUri.setAuthConfigId( parts[ QStringLiteral( "authcfg" ) ].toString() );
302
303 return dsUri.encodedUri();
304}
305
306QString QgsXyzVectorTileDataProviderMetadata::absoluteToRelativeUri( const QString &uri, const QgsReadWriteContext &context ) const
307{
308 QgsDataSourceUri dsUri;
309 dsUri.setEncodedUri( uri );
310
311 QString sourcePath = dsUri.param( QStringLiteral( "url" ) );
312
313 const QUrl sourceUrl( sourcePath );
314 if ( sourceUrl.isLocalFile() )
315 {
316 // relative path will become "file:./x.txt"
317 const QString relSrcUrl = context.pathResolver().writePath( sourceUrl.toLocalFile() );
318 dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key
319 dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( relSrcUrl ).toString() );
320 return dsUri.encodedUri();
321 }
322
323 return uri;
324}
325
326QString QgsXyzVectorTileDataProviderMetadata::relativeToAbsoluteUri( const QString &uri, const QgsReadWriteContext &context ) const
327{
328 QgsDataSourceUri dsUri;
329 dsUri.setEncodedUri( uri );
330
331 QString sourcePath = dsUri.param( QStringLiteral( "url" ) );
332
333 const QUrl sourceUrl( sourcePath );
334 if ( sourceUrl.isLocalFile() ) // file-based URL? convert to relative path
335 {
336 const QString absSrcUrl = context.pathResolver().readPath( sourceUrl.toLocalFile() );
337 dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key
338 dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( absSrcUrl ).toString() );
339 return dsUri.encodedUri();
340 }
341
342 return uri;
343}
344
345QList<Qgis::LayerType> QgsXyzVectorTileDataProviderMetadata::supportedLayerTypes() const
346{
348}
349
350
351//
352// QgsXyzVectorTileDataProvider
353//
354
355QgsXyzVectorTileDataProvider::QgsXyzVectorTileDataProvider( const QString &uri, const ProviderOptions &providerOptions, Qgis::DataProviderReadFlags flags )
356 : QgsXyzVectorTileDataProviderBase( uri, providerOptions, flags )
357{
358 QgsDataSourceUri dsUri;
359 dsUri.setEncodedUri( uri );
360
361 const QString sourcePath = dsUri.param( QStringLiteral( "url" ) );
362 if ( !QgsVectorTileUtils::checkXYZUrlTemplate( sourcePath ) )
363 {
364 QgsDebugError( QStringLiteral( "Invalid format of URL for XYZ source: " ) + sourcePath );
365 mIsValid = false;
366 return;
367 }
368
369 int zMin = 0;
370 if ( dsUri.hasParam( QStringLiteral( "zmin" ) ) )
371 zMin = dsUri.param( QStringLiteral( "zmin" ) ).toInt();
372
373 int zMax = 14;
374 if ( dsUri.hasParam( QStringLiteral( "zmax" ) ) )
375 zMax = dsUri.param( QStringLiteral( "zmax" ) ).toInt();
376
377 mMatrixSet = QgsVectorTileMatrixSet::fromWebMercator( zMin, zMax );
378 mExtent = QgsRectangle( -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892 );
379
380 mIsValid = true;
381}
382
383QgsXyzVectorTileDataProvider::QgsXyzVectorTileDataProvider( const QgsXyzVectorTileDataProvider &other )
384 : QgsXyzVectorTileDataProviderBase( other )
385{
386 mIsValid = other.mIsValid;
387 mExtent = other.mExtent;
388 mMatrixSet = other.mMatrixSet;
389}
390
391Qgis::DataProviderFlags QgsXyzVectorTileDataProvider::flags() const
392{
394}
395
396QString QgsXyzVectorTileDataProvider::name() const
397{
399
400 return XYZ_DATA_PROVIDER_KEY;
401}
402
403QString QgsXyzVectorTileDataProvider::description() const
404{
406
407 return XYZ_DATA_PROVIDER_DESCRIPTION;
408}
409
410QgsVectorTileDataProvider *QgsXyzVectorTileDataProvider::clone() const
411{
413
414 return new QgsXyzVectorTileDataProvider( *this );
415}
416
417bool QgsXyzVectorTileDataProvider::isValid() const
418{
420
421 return mIsValid;
422}
423
424QgsRectangle QgsXyzVectorTileDataProvider::extent() const
425{
427
428 return mExtent;
429}
430
431QgsCoordinateReferenceSystem QgsXyzVectorTileDataProvider::crs() const
432{
434
435 return QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) );
436}
437
438const QgsVectorTileMatrixSet &QgsXyzVectorTileDataProvider::tileMatrixSet() const
439{
441
442 return mMatrixSet;
443}
444
445QString QgsXyzVectorTileDataProvider::sourcePath() const
446{
448
449 QgsDataSourceUri dsUri;
450 dsUri.setEncodedUri( dataSourceUri() );
451 return dsUri.param( QStringLiteral( "url" ) );
452}
453
454QgsStringMap QgsXyzVectorTileDataProvider::sourcePaths() const
455{
457
458 QgsDataSourceUri dsUri;
459 dsUri.setEncodedUri( dataSourceUri() );
460
461 QgsStringMap paths = { { dsUri.param( QStringLiteral( "urlName" ) ), dsUri.param( QStringLiteral( "url" ) ) } };
462
463 int i = 2;
464 while ( true )
465 {
466 QString url = dsUri.param( QStringLiteral( "url_%2" ).arg( i ) );
467 QString urlName = dsUri.param( QStringLiteral( "urlName_%2" ).arg( i ) );
468 if ( url.isEmpty() || urlName.isEmpty() )
469 break;
470
471 paths.insert( urlName, url );
472 i++;
473 }
474
475 return paths;
476}
477
479
480
481
QFlags< DataProviderFlag > DataProviderFlags
Data provider flags.
Definition qgis.h:2210
@ FastExtent2D
Provider's 2D extent retrieval via QgsDataProvider::extent() is always guaranteed to be trivial/fast ...
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:450
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
RendererUsage
Usage of the renderer.
Definition qgis.h:3259
@ Export
Renderer used for printing or exporting to a file.
@ View
Renderer used for displaying on screen.
@ Unknown
Renderer used for unknown usage.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkRequest with an authentication config.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
void setAuthCfg(const QString &authCfg)
Sets the authentication config id which should be used during the request.
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr, RequestFlags requestFlags=QgsBlockingNetworkRequest::RequestFlags())
Performs a "get" operation on the specified request.
@ NoError
No error was encountered.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get(), post(), head() or put() request has been mad...
This class represents a coordinate reference system (CRS).
Class for storing the component parts of a RDBMS data source URI (e.g.
QByteArray encodedUri() const
Returns the complete encoded URI as a byte array.
bool hasParam(const QString &key) const
Returns true if a parameter with the specified key exists.
int removeParam(const QString &key)
Removes a generic parameter by key.
void setEncodedUri(const QByteArray &uri)
Sets the complete encoded uri.
void setAuthConfigId(const QString &authcfg)
Sets the authentication configuration ID for the URI.
QgsHttpHeaders httpHeaders() const
Returns http headers.
QString param(const QString &key) const
Returns a generic parameter value corresponding to the specified key.
void setParam(const QString &key, const QString &value)
Sets a generic parameter value on the URI.
QString authConfigId() const
Returns any associated authentication configuration ID stored in the URI.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:53
This class implements simple http header management.
bool updateMap(QVariantMap &map) const
Updates a map by adding all the HTTP headers.
bool updateNetworkRequest(QNetworkRequest &request) const
Updates a request by adding all the HTTP headers.
void setFromMap(const QVariantMap &map)
Loads headers from the map.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Holds data provider key, description, and associated shared library file or function pointer informat...
QFlags< ProviderCapability > ProviderCapabilities
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Defines a set of tile matrices for multiple zoom levels.
Definition qgstiles.h:252
QgsTileMatrix tileMatrix(int zoom) const
Returns the tile matrix corresponding to the specified zoom.
Definition qgstiles.cpp:156
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
Definition qgstiles.h:136
Stores coordinates of a tile in a tile matrix set.
Definition qgstiles.h:40
Base class for vector tile layer data providers.
static int DATA_ZOOM
Role to set zoom attribute in the request so it can be retrieved later.
static int DATA_ROW
Role to set row attribute in the request so it can be retrieved later.
static int DATA_SOURCE_ID
Role to set source ID attribute in the request so it can be retrieved later.
static int DATA_COLUMN
Role to set column attribute in the request so it can be retrieved later.
Encapsulates properties of a vector tile matrix set, including tile origins and scaling information.
static QgsVectorTileMatrixSet fromWebMercator(int minimumZoom=0, int maximumZoom=14)
Returns a vector tile structure corresponding to the standard web mercator/GoogleCRS84Quad setup.
Keeps track of raw tile data from one or more sources that need to be decoded.
static bool checkXYZUrlTemplate(const QString &url)
Checks whether the URL template string is correct (contains {x}, {y} / {-y}, {z} placeholders)
static QString formatXYZUrlTemplate(const QString &url, QgsTileXYZ tile, const QgsTileMatrix &tileMatrix)
Returns formatted tile URL string replacing {x}, {y}, {z} placeholders (or {-y} instead of {y} for TM...
QMap< QString, QString > QgsStringMap
Definition qgis.h:6604
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
#define QgsDebugError(str)
Definition qgslogger.h:38
#define QgsSetRequestInitiatorClass(request, _class)
#define QgsSetRequestInitiatorId(request, str)
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Setting options for creating vector data providers.