29#include <QJsonParseError>
30#include <QJsonDocument>
35QString QgsArcGisVectorTileServiceDataProvider::ARCGIS_VT_SERVICE_DATA_PROVIDER_KEY = QStringLiteral(
"arcgisvectortileservice" );
36QString QgsArcGisVectorTileServiceDataProvider::ARCGIS_VT_SERVICE_DATA_PROVIDER_DESCRIPTION = QObject::tr(
"ArcGIS Vector Tile Service data provider" );
39QgsArcGisVectorTileServiceDataProvider::QgsArcGisVectorTileServiceDataProvider(
const QString &uri,
const ProviderOptions &providerOptions, ReadFlags flags )
40 : QgsXyzVectorTileDataProviderBase( uri, providerOptions, flags )
42 mIsValid = setupArcgisVectorTileServiceConnection();
48 mLayerMetadata.setIdentifier( mArcgisLayerConfiguration.value( QStringLiteral(
"serviceUri" ) ).toString() );
49 const QString parentIdentifier = mArcgisLayerConfiguration.value( QStringLiteral(
"serviceItemId" ) ).toString();
50 if ( !parentIdentifier.isEmpty() )
52 mLayerMetadata.setParentIdentifier( parentIdentifier );
54 mLayerMetadata.setType( QStringLiteral(
"dataset" ) );
55 mLayerMetadata.setTitle( mArcgisLayerConfiguration.value( QStringLiteral(
"name" ) ).toString() );
56 const QString copyright = mArcgisLayerConfiguration.value( QStringLiteral(
"copyrightText" ) ).toString();
57 if ( !copyright.isEmpty() )
58 mLayerMetadata.setRights( QStringList() << copyright );
59 mLayerMetadata.addLink(
QgsAbstractMetadataBase::Link( tr(
"Source" ), QStringLiteral(
"WWW:LINK" ), mArcgisLayerConfiguration.value( QStringLiteral(
"serviceUri" ) ).toString() ) );
62QgsArcGisVectorTileServiceDataProvider::QgsArcGisVectorTileServiceDataProvider(
const QgsArcGisVectorTileServiceDataProvider &other )
63 : QgsXyzVectorTileDataProviderBase( other )
65 mIsValid = other.mIsValid;
66 mExtent = other.mExtent;
67 mMatrixSet = other.mMatrixSet;
68 mSourcePath = other.mSourcePath;
69 mArcgisLayerConfiguration = other.mArcgisLayerConfiguration;
70 mArcgisStyleConfiguration = other.mArcgisStyleConfiguration;
72 mLayerMetadata = other.mLayerMetadata;
75Qgis::VectorTileProviderFlags QgsArcGisVectorTileServiceDataProvider::providerFlags()
const
80Qgis::VectorTileProviderCapabilities QgsArcGisVectorTileServiceDataProvider::providerCapabilities()
const
85QString QgsArcGisVectorTileServiceDataProvider::name()
const
89 return ARCGIS_VT_SERVICE_DATA_PROVIDER_KEY;
92QString QgsArcGisVectorTileServiceDataProvider::description()
const
96 return ARCGIS_VT_SERVICE_DATA_PROVIDER_DESCRIPTION;
103 return new QgsArcGisVectorTileServiceDataProvider( *
this );
106QString QgsArcGisVectorTileServiceDataProvider::sourcePath()
const
113bool QgsArcGisVectorTileServiceDataProvider::isValid()
const
120QgsRectangle QgsArcGisVectorTileServiceDataProvider::extent()
const
141QgsLayerMetadata QgsArcGisVectorTileServiceDataProvider::layerMetadata()
const
145 return mLayerMetadata;
148QVariantMap QgsArcGisVectorTileServiceDataProvider::styleDefinition()
const
152 return mArcgisStyleConfiguration;
155QString QgsArcGisVectorTileServiceDataProvider::styleUrl()
const
160 return mArcgisLayerConfiguration.value( QStringLiteral(
"serviceUri" ) ).toString()
161 +
'/' + mArcgisLayerConfiguration.value( QStringLiteral(
"defaultStyles" ) ).toString();
164QString QgsArcGisVectorTileServiceDataProvider::htmlMetadata()
const
168 if ( !mTileMapUrl.isEmpty() )
169 metadata += QStringLiteral(
"<tr><td class=\"highlight\">" ) % tr(
"Tilemap" ) % QStringLiteral(
"</td><td><a href=\"%1\">%1</a>" ).arg( mTileMapUrl ) % QStringLiteral(
"</td></tr>\n" );
174bool QgsArcGisVectorTileServiceDataProvider::setupArcgisVectorTileServiceConnection()
180 QString tileServiceUri = dsUri.param( QStringLiteral(
"url" ) );
182 QUrl url( tileServiceUri );
186 query.addQueryItem( QStringLiteral(
"f" ), QStringLiteral(
"pjson" ) );
187 url.setQuery( query );
189 QNetworkRequest request = QNetworkRequest( url );
194 switch ( networkRequest.get( request ) )
206 const QByteArray raw = content.
content();
210 const QJsonDocument doc = QJsonDocument::fromJson( raw, &err );
216 mArcgisLayerConfiguration = doc.object().toVariantMap();
217 if ( mArcgisLayerConfiguration.contains( QStringLiteral(
"error" ) ) )
222 if ( !mArcgisLayerConfiguration.value( QStringLiteral(
"tiles" ) ).isValid() )
225 const QString sourceUri = mArcgisLayerConfiguration.value( QStringLiteral(
"sources" ) ).toMap().value( QStringLiteral(
"esri" ) ).toMap().value( QStringLiteral(
"url" ) ).toString();
226 if ( !sourceUri.isEmpty() )
228 QUrl url( sourceUri );
232 query.addQueryItem( QStringLiteral(
"f" ), QStringLiteral(
"pjson" ) );
233 url.setQuery( query );
235 QNetworkRequest request = QNetworkRequest( url );
240 switch ( networkRequest.get( request ) )
252 const QByteArray raw = content.
content();
256 const QJsonDocument doc = QJsonDocument::fromJson( raw, &err );
262 tileServiceUri = sourceUri;
265 mArcgisStyleConfiguration = mArcgisLayerConfiguration;
266 mArcgisLayerConfiguration = doc.object().toVariantMap();
267 if ( mArcgisLayerConfiguration.contains( QStringLiteral(
"error" ) ) )
276 const QString tileMapEndpoint = mArcgisLayerConfiguration.value( QStringLiteral(
"tileMap" ) ).toString();
277 if ( !tileMapEndpoint.isEmpty() )
279 mTileMapUrl = tileServiceUri +
'/' + tileMapEndpoint;
280 QUrl tilemapUrl( mTileMapUrl );
281 tilemapUrl.setQuery( query );
283 QNetworkRequest tileMapRequest = QNetworkRequest( tilemapUrl );
287 switch ( tileMapNetworkRequest.get( tileMapRequest ) )
299 const QByteArray tileMapRaw = tileMapContent.
content();
301 const QJsonDocument tileMapDoc = QJsonDocument::fromJson( tileMapRaw, &err );
302 if ( !tileMapDoc.isNull() )
304 tileMap = tileMapDoc.object().toVariantMap();
308 mSourcePath = tileServiceUri +
'/' + mArcgisLayerConfiguration.value( QStringLiteral(
"tiles" ) ).toList().value( 0 ).toString();
311 QgsDebugError( QStringLiteral(
"Invalid format of URL for XYZ source: " ) + tileServiceUri );
315 mArcgisLayerConfiguration.insert( QStringLiteral(
"serviceUri" ), tileServiceUri );
317 mMatrixSet.fromEsriJson( mArcgisLayerConfiguration, tileMap );
318 mCrs = mMatrixSet.crs();
321 if ( dsUri.hasParam( QStringLiteral(
"zmin" ) ) )
322 mMatrixSet.dropMatricesOutsideZoomRange( dsUri.param( QStringLiteral(
"zmin" ) ).toInt(), 99 );
324 if ( dsUri.hasParam( QStringLiteral(
"zmax" ) ) )
325 mMatrixSet.dropMatricesOutsideZoomRange( 0, dsUri.param( QStringLiteral(
"zmax" ) ).toInt() );
327 const QVariantMap fullExtent = mArcgisLayerConfiguration.value( QStringLiteral(
"fullExtent" ) ).toMap();
328 if ( !fullExtent.isEmpty() )
331 fullExtent.value( QStringLiteral(
"xmin" ) ).toDouble(),
332 fullExtent.value( QStringLiteral(
"ymin" ) ).toDouble(),
333 fullExtent.value( QStringLiteral(
"xmax" ) ).toDouble(),
334 fullExtent.value( QStringLiteral(
"ymax" ) ).toDouble()
341 mExtent = extentTransform.transformBoundingBox( fullExtentRect );
345 QgsDebugError( QStringLiteral(
"Could not transform layer fullExtent to layer CRS" ) );
354 mExtent = extentTransform.transformBoundingBox(
QgsRectangle( -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892 ) );
358 QgsDebugError( QStringLiteral(
"Could not transform layer extent to layer CRS" ) );
370QgsArcGisVectorTileServiceDataProviderMetadata::QgsArcGisVectorTileServiceDataProviderMetadata()
371 :
QgsProviderMetadata( QgsArcGisVectorTileServiceDataProvider::ARCGIS_VT_SERVICE_DATA_PROVIDER_KEY,
372 QgsArcGisVectorTileServiceDataProvider::ARCGIS_VT_SERVICE_DATA_PROVIDER_DESCRIPTION )
376QIcon QgsArcGisVectorTileServiceDataProviderMetadata::icon()
const
381QgsProviderMetadata::ProviderCapabilities QgsArcGisVectorTileServiceDataProviderMetadata::providerCapabilities()
const
383 return QgsProviderMetadata::ProviderCapabilities();
386QgsArcGisVectorTileServiceDataProvider *QgsArcGisVectorTileServiceDataProviderMetadata::createProvider(
const QString &uri,
const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
388 return new QgsArcGisVectorTileServiceDataProvider( uri, options, flags );
391QVariantMap QgsArcGisVectorTileServiceDataProviderMetadata::decodeUri(
const QString &uri )
const
396 QVariantMap uriComponents;
397 uriComponents.insert( QStringLiteral(
"type" ), QStringLiteral(
"xyz" ) );
398 uriComponents.insert( QStringLiteral(
"serviceType" ), QStringLiteral(
"arcgis" ) );
399 uriComponents.insert( QStringLiteral(
"url" ), dsUri.
param( QStringLiteral(
"url" ) ) );
401 if ( dsUri.
hasParam( QStringLiteral(
"zmin" ) ) )
402 uriComponents.insert( QStringLiteral(
"zmin" ), dsUri.
param( QStringLiteral(
"zmin" ) ) );
403 if ( dsUri.
hasParam( QStringLiteral(
"zmax" ) ) )
404 uriComponents.insert( QStringLiteral(
"zmax" ), dsUri.
param( QStringLiteral(
"zmax" ) ) );
408 if ( dsUri.
hasParam( QStringLiteral(
"styleUrl" ) ) )
409 uriComponents.insert( QStringLiteral(
"styleUrl" ), dsUri.
param( QStringLiteral(
"styleUrl" ) ) );
412 if ( !authcfg.isEmpty() )
413 uriComponents.insert( QStringLiteral(
"authcfg" ), authcfg );
415 return uriComponents;
418QString QgsArcGisVectorTileServiceDataProviderMetadata::encodeUri(
const QVariantMap &parts )
const
421 dsUri.
setParam( QStringLiteral(
"type" ), QStringLiteral(
"xyz" ) );
422 dsUri.
setParam( QStringLiteral(
"serviceType" ), QStringLiteral(
"arcgis" ) );
423 dsUri.
setParam( QStringLiteral(
"url" ), parts.value( QStringLiteral(
"url" ) ).toString() );
425 if ( parts.contains( QStringLiteral(
"zmin" ) ) )
426 dsUri.
setParam( QStringLiteral(
"zmin" ), parts[ QStringLiteral(
"zmin" ) ].toString() );
427 if ( parts.contains( QStringLiteral(
"zmax" ) ) )
428 dsUri.
setParam( QStringLiteral(
"zmax" ), parts[ QStringLiteral(
"zmax" ) ].toString() );
432 if ( parts.contains( QStringLiteral(
"styleUrl" ) ) )
433 dsUri.
setParam( QStringLiteral(
"styleUrl" ), parts[ QStringLiteral(
"styleUrl" ) ].toString() );
435 if ( parts.contains( QStringLiteral(
"authcfg" ) ) )
436 dsUri.
setAuthConfigId( parts[ QStringLiteral(
"authcfg" ) ].toString() );
441QString QgsArcGisVectorTileServiceDataProviderMetadata::absoluteToRelativeUri(
const QString &uri,
const QgsReadWriteContext & )
const
448QString QgsArcGisVectorTileServiceDataProviderMetadata::relativeToAbsoluteUri(
const QString &uri,
const QgsReadWriteContext & )
const
455QList<Qgis::LayerType> QgsArcGisVectorTileServiceDataProviderMetadata::supportedLayerTypes()
const
@ ReadLayerMetadata
Provider can read layer metadata from data store. See QgsDataProvider::layerMetadata()
@ AlwaysUseTileMatrixSetFromProvider
Vector tile layer must always use the tile matrix set from the data provider, and should never store,...
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsCoordinateReferenceSystem convertSpatialReference(const QVariantMap &spatialReferenceMap)
Converts a spatial reference JSON definition to a QgsCoordinateReferenceSystem value.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
@ NetworkError
A network error occurred.
@ ServerExceptionError
An exception was raised by the server.
@ NoError
No error was encountered.
@ TimeoutError
Timeout was reached before a reply was received.
This class represents a coordinate reference system (CRS).
Custom exception class for Coordinate Reference System related exceptions.
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.
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.
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
Base class for vector tile layer data providers.
Encapsulates properties of a vector tile matrix set, including tile origins and scaling information.
static bool checkXYZUrlTemplate(const QString &url)
Checks whether the URL template string is correct (contains {x}, {y} / {-y}, {z} placeholders)
#define QgsDebugError(str)
#define QgsSetRequestInitiatorClass(request, _class)
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Setting options for creating vector data providers.