QGIS API Documentation  3.19.0-Master (c022ae99b5)
qgsvectortilelayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectortilelayer.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 
16 #include "qgsvectortilelayer.h"
17 
18 #include "qgslogger.h"
20 #include "qgsmbtiles.h"
23 #include "qgsvectortilelabeling.h"
24 #include "qgsvectortileloader.h"
25 #include "qgsvectortileutils.h"
27 
28 #include "qgsdatasourceuri.h"
32 #include "qgsjsonutils.h"
33 #include "qgspainting.h"
34 #include "qgsmaplayerfactory.h"
35 
36 #include <QUrl>
37 #include <QUrlQuery>
38 
39 QgsVectorTileLayer::QgsVectorTileLayer( const QString &uri, const QString &baseName )
41 {
42  mDataSource = uri;
43 
44  setValid( loadDataSource() );
45 
46  // set a default renderer
50 }
51 
52 bool QgsVectorTileLayer::loadDataSource()
53 {
54  QgsDataSourceUri dsUri;
55  dsUri.setEncodedUri( mDataSource );
56 
57  mSourceType = dsUri.param( QStringLiteral( "type" ) );
58  mSourcePath = dsUri.param( QStringLiteral( "url" ) );
59  if ( mSourceType == QLatin1String( "xyz" ) && dsUri.param( QStringLiteral( "serviceType" ) ) == QLatin1String( "arcgis" ) )
60  {
61  if ( !setupArcgisVectorTileServiceConnection( mSourcePath, dsUri ) )
62  return false;
63  }
64  else if ( mSourceType == QLatin1String( "xyz" ) )
65  {
66  if ( !QgsVectorTileUtils::checkXYZUrlTemplate( mSourcePath ) )
67  {
68  QgsDebugMsg( QStringLiteral( "Invalid format of URL for XYZ source: " ) + mSourcePath );
69  return false;
70  }
71 
72  // online tiles
73  mSourceMinZoom = 0;
74  mSourceMaxZoom = 14;
75 
76  if ( dsUri.hasParam( QStringLiteral( "zmin" ) ) )
77  mSourceMinZoom = dsUri.param( QStringLiteral( "zmin" ) ).toInt();
78  if ( dsUri.hasParam( QStringLiteral( "zmax" ) ) )
79  mSourceMaxZoom = dsUri.param( QStringLiteral( "zmax" ) ).toInt();
80 
81  setExtent( QgsRectangle( -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892 ) );
82  }
83  else if ( mSourceType == QLatin1String( "mbtiles" ) )
84  {
85  QgsMbTiles reader( mSourcePath );
86  if ( !reader.open() )
87  {
88  QgsDebugMsg( QStringLiteral( "failed to open MBTiles file: " ) + mSourcePath );
89  return false;
90  }
91 
92  QString format = reader.metadataValue( QStringLiteral( "format" ) );
93  if ( format != QLatin1String( "pbf" ) )
94  {
95  QgsDebugMsg( QStringLiteral( "Cannot open MBTiles for vector tiles. Format = " ) + format );
96  return false;
97  }
98 
99  QgsDebugMsgLevel( QStringLiteral( "name: " ) + reader.metadataValue( QStringLiteral( "name" ) ), 2 );
100  bool minZoomOk, maxZoomOk;
101  int minZoom = reader.metadataValue( QStringLiteral( "minzoom" ) ).toInt( &minZoomOk );
102  int maxZoom = reader.metadataValue( QStringLiteral( "maxzoom" ) ).toInt( &maxZoomOk );
103  if ( minZoomOk )
104  mSourceMinZoom = minZoom;
105  if ( maxZoomOk )
106  mSourceMaxZoom = maxZoom;
107  QgsDebugMsgLevel( QStringLiteral( "zoom range: %1 - %2" ).arg( mSourceMinZoom ).arg( mSourceMaxZoom ), 2 );
108 
109  QgsRectangle r = reader.extent();
110  QgsCoordinateTransform ct( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ),
111  QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) ), transformContext() );
112  r = ct.transformBoundingBox( r );
113  setExtent( r );
114  }
115  else
116  {
117  QgsDebugMsg( QStringLiteral( "Unknown source type: " ) + mSourceType );
118  return false;
119  }
120 
121  setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) ) );
122  return true;
123 }
124 
125 bool QgsVectorTileLayer::setupArcgisVectorTileServiceConnection( const QString &uri, const QgsDataSourceUri &dataSourceUri )
126 {
127  QUrl url( uri );
128  // some services don't default to json format, while others do... so let's explicitly request it!
129  // (refs https://github.com/qgis/QGIS/issues/4231)
130  QUrlQuery query;
131  query.addQueryItem( QStringLiteral( "f" ), QStringLiteral( "pjson" ) );
132  url.setQuery( query );
133 
134  QNetworkRequest request = QNetworkRequest( url );
135 
136  QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) )
137 
138  QgsBlockingNetworkRequest networkRequest;
139  switch ( networkRequest.get( request ) )
140  {
142  break;
143 
147  return false;
148  }
149 
150  const QgsNetworkReplyContent content = networkRequest.reply();
151  const QByteArray raw = content.content();
152 
153  // Parse data
154  QJsonParseError err;
155  QJsonDocument doc = QJsonDocument::fromJson( raw, &err );
156  if ( doc.isNull() )
157  {
158  return false;
159  }
160  mArcgisLayerConfiguration = doc.object().toVariantMap();
161  if ( mArcgisLayerConfiguration.contains( QStringLiteral( "error" ) ) )
162  {
163  return false;
164  }
165 
166  mArcgisLayerConfiguration.insert( QStringLiteral( "serviceUri" ), uri );
167  mSourcePath = uri + '/' + mArcgisLayerConfiguration.value( QStringLiteral( "tiles" ) ).toList().value( 0 ).toString();
168  if ( !QgsVectorTileUtils::checkXYZUrlTemplate( mSourcePath ) )
169  {
170  QgsDebugMsg( QStringLiteral( "Invalid format of URL for XYZ source: " ) + mSourcePath );
171  return false;
172  }
173 
174  // if hardcoded zoom limits aren't specified, take them from the server
175  if ( !dataSourceUri.hasParam( QStringLiteral( "zmin" ) ) )
176  mSourceMinZoom = 0;
177  else
178  mSourceMinZoom = dataSourceUri.param( QStringLiteral( "zmin" ) ).toInt();
179 
180  if ( !dataSourceUri.hasParam( QStringLiteral( "zmax" ) ) )
181  mSourceMaxZoom = mArcgisLayerConfiguration.value( QStringLiteral( "maxzoom" ) ).toInt();
182  else
183  mSourceMaxZoom = dataSourceUri.param( QStringLiteral( "zmax" ) ).toInt();
184 
185  setExtent( QgsRectangle( -20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892 ) );
186 
187  return true;
188 }
189 
191 
192 
194 {
195  QgsVectorTileLayer *layer = new QgsVectorTileLayer( source(), name() );
196  layer->setRenderer( renderer() ? renderer()->clone() : nullptr );
197  return layer;
198 }
199 
201 {
202  return new QgsVectorTileLayerRenderer( this, rendererContext );
203 }
204 
205 bool QgsVectorTileLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext &context )
206 {
207  setValid( loadDataSource() );
208 
209  QString errorMsg;
210  if ( !readSymbology( layerNode, errorMsg, context ) )
211  return false;
212 
213  readStyleManager( layerNode );
214  return true;
215 }
216 
217 bool QgsVectorTileLayer::writeXml( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const
218 {
219  QDomElement mapLayerNode = layerNode.toElement();
220  mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::VectorTileLayer ) );
221 
222  writeStyleManager( layerNode, doc );
223 
224  QString errorMsg;
225  return writeSymbology( layerNode, doc, errorMsg, context );
226 }
227 
228 bool QgsVectorTileLayer::readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
229 {
230  QDomElement elem = node.toElement();
231 
232  readCommonStyle( elem, context, categories );
233 
234  const QDomElement elemRenderer = elem.firstChildElement( QStringLiteral( "renderer" ) );
235  if ( elemRenderer.isNull() )
236  {
237  errorMessage = tr( "Missing <renderer> tag" );
238  return false;
239  }
240  const QString rendererType = elemRenderer.attribute( QStringLiteral( "type" ) );
241 
242  if ( categories.testFlag( Symbology ) )
243  {
244  QgsVectorTileRenderer *r = nullptr;
245  if ( rendererType == QLatin1String( "basic" ) )
247  else
248  {
249  errorMessage = tr( "Unknown renderer type: " ) + rendererType;
250  return false;
251  }
252 
253  r->readXml( elemRenderer, context );
254  setRenderer( r );
255  }
256 
257  if ( categories.testFlag( Labeling ) )
258  {
259  setLabeling( nullptr );
260  const QDomElement elemLabeling = elem.firstChildElement( QStringLiteral( "labeling" ) );
261  if ( !elemLabeling.isNull() )
262  {
263  const QString labelingType = elemLabeling.attribute( QStringLiteral( "type" ) );
264  QgsVectorTileLabeling *labeling = nullptr;
265  if ( labelingType == QLatin1String( "basic" ) )
267  else
268  {
269  errorMessage = tr( "Unknown labeling type: " ) + rendererType;
270  }
271 
272  if ( labeling )
273  {
274  labeling->readXml( elemLabeling, context );
276  }
277  }
278  }
279 
280  if ( categories.testFlag( Symbology ) )
281  {
282  // get and set the blend mode if it exists
283  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
284  if ( !blendModeNode.isNull() )
285  {
286  QDomElement e = blendModeNode.toElement();
287  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
288  }
289  }
290 
291  // get and set the layer transparency
292  if ( categories.testFlag( Rendering ) )
293  {
294  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
295  if ( !layerOpacityNode.isNull() )
296  {
297  QDomElement e = layerOpacityNode.toElement();
298  setOpacity( e.text().toDouble() );
299  }
300  }
301 
302  return true;
303 }
304 
305 bool QgsVectorTileLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
306 {
307  Q_UNUSED( errorMessage )
308  QDomElement elem = node.toElement();
309 
310  writeCommonStyle( elem, doc, context, categories );
311 
312  if ( mRenderer )
313  {
314  QDomElement elemRenderer = doc.createElement( QStringLiteral( "renderer" ) );
315  elemRenderer.setAttribute( QStringLiteral( "type" ), mRenderer->type() );
316  if ( categories.testFlag( Symbology ) )
317  {
318  mRenderer->writeXml( elemRenderer, context );
319  }
320  elem.appendChild( elemRenderer );
321  }
322 
323  if ( mLabeling && categories.testFlag( Labeling ) )
324  {
325  QDomElement elemLabeling = doc.createElement( QStringLiteral( "labeling" ) );
326  elemLabeling.setAttribute( QStringLiteral( "type" ), mLabeling->type() );
327  mLabeling->writeXml( elemLabeling, context );
328  elem.appendChild( elemLabeling );
329  }
330 
331  if ( categories.testFlag( Symbology ) )
332  {
333  // add the blend mode field
334  QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
335  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
336  blendModeElem.appendChild( blendModeText );
337  node.appendChild( blendModeElem );
338  }
339 
340  // add the layer opacity
341  if ( categories.testFlag( Rendering ) )
342  {
343  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
344  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
345  layerOpacityElem.appendChild( layerOpacityText );
346  node.appendChild( layerOpacityElem );
347  }
348 
349  return true;
350 }
351 
353 {
354  Q_UNUSED( transformContext )
356 }
357 
358 QString QgsVectorTileLayer::loadDefaultStyle( bool &resultFlag )
359 {
360  QString error;
361  QStringList warnings;
362  resultFlag = loadDefaultStyle( error, warnings );
363  return error;
364 }
365 
366 bool QgsVectorTileLayer::loadDefaultStyle( QString &error, QStringList &warnings )
367 {
368  QgsDataSourceUri dsUri;
369  dsUri.setEncodedUri( mDataSource );
370 
371  QString styleUrl;
372  if ( !dsUri.param( QStringLiteral( "styleUrl" ) ).isEmpty() )
373  {
374  styleUrl = dsUri.param( QStringLiteral( "styleUrl" ) );
375  }
376  else if ( mSourceType == QLatin1String( "xyz" ) && dsUri.param( QStringLiteral( "serviceType" ) ) == QLatin1String( "arcgis" ) )
377  {
378  // for ArcMap VectorTileServices we default to the defaultStyles URL from the layer configuration
379  styleUrl = mArcgisLayerConfiguration.value( QStringLiteral( "serviceUri" ) ).toString()
380  + '/' + mArcgisLayerConfiguration.value( QStringLiteral( "defaultStyles" ) ).toString();
381  }
382 
383  if ( !styleUrl.isEmpty() )
384  {
385  QNetworkRequest request = QNetworkRequest( QUrl( styleUrl ) );
386 
387  QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) );
388 
389  QgsBlockingNetworkRequest networkRequest;
390  switch ( networkRequest.get( request ) )
391  {
393  break;
394 
398  error = QObject::tr( "Error retrieving default style" );
399  return false;
400  }
401 
402  const QgsNetworkReplyContent content = networkRequest.reply();
403  const QVariantMap styleDefinition = QgsJsonUtils::parseJson( content.content() ).toMap();
404 
406  // convert automatically from pixel sizes to millimeters, because pixel sizes
407  // are a VERY edge case in QGIS and don't play nice with hidpi map renders or print layouts
409  //assume source uses 96 dpi
410  context.setPixelSizeConversionFactor( 25.4 / 96.0 );
411 
412  if ( styleDefinition.contains( QStringLiteral( "sprite" ) ) )
413  {
414  // retrieve sprite definition
415  QString spriteUriBase;
416  if ( styleDefinition.value( QStringLiteral( "sprite" ) ).toString().startsWith( QLatin1String( "http" ) ) )
417  {
418  spriteUriBase = styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
419  }
420  else
421  {
422  spriteUriBase = styleUrl + '/' + styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
423  }
424 
425  for ( int resolution = 2; resolution > 0; resolution-- )
426  {
427  QNetworkRequest request = QNetworkRequest( QUrl( spriteUriBase + QStringLiteral( "%1.json" ).arg( resolution > 1 ? QStringLiteral( "@%1x" ).arg( resolution ) : QString() ) ) );
428  QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) )
429  QgsBlockingNetworkRequest networkRequest;
430  switch ( networkRequest.get( request ) )
431  {
433  {
434  const QgsNetworkReplyContent content = networkRequest.reply();
435  const QVariantMap spriteDefinition = QgsJsonUtils::parseJson( content.content() ).toMap();
436 
437  // retrieve sprite images
438  QNetworkRequest request = QNetworkRequest( QUrl( spriteUriBase + QStringLiteral( "%1.png" ).arg( resolution > 1 ? QStringLiteral( "@%1x" ).arg( resolution ) : QString() ) ) );
439 
440  QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) )
441 
442  QgsBlockingNetworkRequest networkRequest;
443  switch ( networkRequest.get( request ) )
444  {
446  {
447  const QgsNetworkReplyContent imageContent = networkRequest.reply();
448  QImage spriteImage( QImage::fromData( imageContent.content() ) );
449  context.setSprites( spriteImage, spriteDefinition );
450  break;
451  }
452 
456  break;
457  }
458 
459  break;
460  }
461 
465  break;
466  }
467 
468  if ( !context.spriteDefinitions().isEmpty() )
469  break;
470  }
471  }
472 
473  QgsMapBoxGlStyleConverter converter;
474  if ( converter.convert( styleDefinition, &context ) != QgsMapBoxGlStyleConverter::Success )
475  {
476  warnings = converter.warnings();
477  error = converter.errorMessage();
478  return false;
479  }
480 
481  setRenderer( converter.renderer() );
482  setLabeling( converter.labeling() );
483  warnings = converter.warnings();
484  return true;
485  }
486  else
487  {
488  bool resultFlag = false;
489  error = QgsMapLayer::loadDefaultStyle( resultFlag );
490  return resultFlag;
491  }
492 }
493 
494 QString QgsVectorTileLayer::loadDefaultMetadata( bool &resultFlag )
495 {
496  QgsDataSourceUri dsUri;
497  dsUri.setEncodedUri( mDataSource );
498  if ( mSourceType == QLatin1String( "xyz" ) && dsUri.param( QStringLiteral( "serviceType" ) ) == QLatin1String( "arcgis" ) )
499  {
500  // populate default metadata
502  metadata.setIdentifier( mArcgisLayerConfiguration.value( QStringLiteral( "serviceUri" ) ).toString() );
503  const QString parentIdentifier = mArcgisLayerConfiguration.value( QStringLiteral( "serviceItemId" ) ).toString();
504  if ( !parentIdentifier.isEmpty() )
505  {
506  metadata.setParentIdentifier( parentIdentifier );
507  }
508  metadata.setType( QStringLiteral( "dataset" ) );
509  metadata.setTitle( mArcgisLayerConfiguration.value( QStringLiteral( "name" ) ).toString() );
510  QString copyright = mArcgisLayerConfiguration.value( QStringLiteral( "copyrightText" ) ).toString();
511  if ( !copyright.isEmpty() )
512  metadata.setRights( QStringList() << copyright );
513  metadata.addLink( QgsAbstractMetadataBase::Link( tr( "Source" ), QStringLiteral( "WWW:LINK" ), mArcgisLayerConfiguration.value( QStringLiteral( "serviceUri" ) ).toString() ) );
514 
516 
517  resultFlag = true;
518  return QString();
519  }
520  else
521  {
522  QgsMapLayer::loadDefaultMetadata( resultFlag );
523  resultFlag = true;
524  return QString();
525  }
526 }
527 
528 QString QgsVectorTileLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
529 {
530  QgsDataSourceUri dsUri;
531  dsUri.setEncodedUri( source );
532 
533  QString sourceType = dsUri.param( QStringLiteral( "type" ) );
534  QString sourcePath = dsUri.param( QStringLiteral( "url" ) );
535  if ( sourceType == QLatin1String( "xyz" ) )
536  {
537  QUrl sourceUrl( sourcePath );
538  if ( sourceUrl.isLocalFile() )
539  {
540  // relative path will become "file:./x.txt"
541  QString relSrcUrl = context.pathResolver().writePath( sourceUrl.toLocalFile() );
542  dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key
543  dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( relSrcUrl ).toString() );
544  return dsUri.encodedUri();
545  }
546  }
547  else if ( sourceType == QLatin1String( "mbtiles" ) )
548  {
550  dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key
551  dsUri.setParam( QStringLiteral( "url" ), sourcePath );
552  return dsUri.encodedUri();
553  }
554 
555  return source;
556 }
557 
558 QString QgsVectorTileLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
559 {
560  Q_UNUSED( provider )
561 
562  QgsDataSourceUri dsUri;
563  dsUri.setEncodedUri( source );
564 
565  QString sourceType = dsUri.param( QStringLiteral( "type" ) );
566  QString sourcePath = dsUri.param( QStringLiteral( "url" ) );
567  if ( sourceType == QLatin1String( "xyz" ) )
568  {
569  QUrl sourceUrl( sourcePath );
570  if ( sourceUrl.isLocalFile() ) // file-based URL? convert to relative path
571  {
572  QString absSrcUrl = context.pathResolver().readPath( sourceUrl.toLocalFile() );
573  dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key
574  dsUri.setParam( QStringLiteral( "url" ), QUrl::fromLocalFile( absSrcUrl ).toString() );
575  return dsUri.encodedUri();
576  }
577  }
578  else if ( sourceType == QLatin1String( "mbtiles" ) )
579  {
581  dsUri.removeParam( QStringLiteral( "url" ) ); // needed because setParam() would insert second "url" key
582  dsUri.setParam( QStringLiteral( "url" ), sourcePath );
583  return dsUri.encodedUri();
584  }
585 
586  return source;
587 }
588 
590 {
591  QgsLayerMetadataFormatter htmlFormatter( metadata() );
592 
593  QString info = QStringLiteral( "<html><head></head>\n<body>\n" );
594 
595  info += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" ) %
596  QStringLiteral( "<table class=\"list-view\">\n" ) %
597 
598  // name
599  QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Name" ) % QStringLiteral( "</td><td>" ) % name() % QStringLiteral( "</td></tr>\n" );
600 
601  info += QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "URI" ) % QStringLiteral( "</td><td>" ) % source() % QStringLiteral( "</td></tr>\n" );
602  info += QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Source type" ) % QStringLiteral( "</td><td>" ) % sourceType() % QStringLiteral( "</td></tr>\n" );
603 
604  const QString url = sourcePath();
605  info += QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Source path" ) % QStringLiteral( "</td><td>%1" ).arg( QStringLiteral( "<a href=\"%1\">%2</a>" ).arg( QUrl( url ).toString(), sourcePath() ) ) + QStringLiteral( "</td></tr>\n" );
606 
607  info += QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Zoom levels" ) % QStringLiteral( "</td><td>" ) % QStringLiteral( "%1 - %2" ).arg( sourceMinZoom() ).arg( sourceMaxZoom() ) % QStringLiteral( "</td></tr>\n" );
608 
609  info += QLatin1String( "</table>\n<br><br>" );
610 
611  // CRS
612  info += crsHtmlMetadata();
613 
614  // Identification section
615  info += QStringLiteral( "<h1>" ) % tr( "Identification" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
616  htmlFormatter.identificationSectionHtml() %
617  QStringLiteral( "<br><br>\n" ) %
618 
619  // extent section
620  QStringLiteral( "<h1>" ) % tr( "Extent" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
621  htmlFormatter.extentSectionHtml( ) %
622  QStringLiteral( "<br><br>\n" ) %
623 
624  // Start the Access section
625  QStringLiteral( "<h1>" ) % tr( "Access" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
626  htmlFormatter.accessSectionHtml( ) %
627  QStringLiteral( "<br><br>\n" ) %
628 
629 
630  // Start the contacts section
631  QStringLiteral( "<h1>" ) % tr( "Contacts" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
632  htmlFormatter.contactsSectionHtml( ) %
633  QStringLiteral( "<br><br>\n" ) %
634 
635  // Start the links section
636  QStringLiteral( "<h1>" ) % tr( "References" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
637  htmlFormatter.linksSectionHtml( ) %
638  QStringLiteral( "<br><br>\n" ) %
639 
640  // Start the history section
641  QStringLiteral( "<h1>" ) % tr( "History" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
642  htmlFormatter.historySectionHtml( ) %
643  QStringLiteral( "<br><br>\n" ) %
644 
645  QStringLiteral( "\n</body>\n</html>\n" );
646 
647  return info;
648 }
649 
651 {
652  QgsTileMatrix tileMatrix = QgsTileMatrix::fromWebMercator( tileID.zoomLevel() );
653  QgsTileRange tileRange( tileID.column(), tileID.column(), tileID.row(), tileID.row() );
654 
655  QgsDataSourceUri dsUri;
656  dsUri.setEncodedUri( mDataSource );
657  const QString authcfg = dsUri.authConfigId();
658  const QString referer = dsUri.param( QStringLiteral( "referer" ) );
659 
660  QList<QgsVectorTileRawData> rawTiles = QgsVectorTileLoader::blockingFetchTileRawData( mSourceType, mSourcePath, tileMatrix, QPointF(), tileRange, authcfg, referer );
661  if ( rawTiles.isEmpty() )
662  return QByteArray();
663  return rawTiles.first().data;
664 }
665 
667 {
668  mRenderer.reset( r );
669  triggerRepaint();
670 }
671 
673 {
674  return mRenderer.get();
675 }
676 
678 {
679  mLabeling.reset( labeling );
680  triggerRepaint();
681 }
682 
684 {
685  return mLabeling.get();
686 }
void setType(const QString &type)
Sets the type (nature) of the resource.
void setParentIdentifier(const QString &parentIdentifier)
Sets a reference, URI, URL or some other mechanism to identify the parent resource that this resource...
void setTitle(const QString &title)
Sets the human readable title (name) of the resource, typically displayed in search results.
void setIdentifier(const QString &identifier)
Sets the reference, URI, URL or some other mechanism to identify the resource.
void addLink(const QgsAbstractMetadataBase::Link &link)
Adds an individual link to the existing links.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "get" operation on the specified request.
@ 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.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get() or post() request has been made.
This class represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
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.
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.
static QVariant parseJson(const std::string &jsonString)
Converts JSON jsonString to a QVariant, in case of parsing error an invalid QVariant is returned.
Class for metadata formatter.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
A structured metadata store for a map layer.
void setRights(const QStringList &rights)
Sets a list of rights (attribution or copyright strings) associated with the resource.
Context for a MapBox GL style conversion operation.
void setPixelSizeConversionFactor(double sizeConversionFactor)
Sets the pixel size conversion factor, used to scale the original pixel sizes when converting styles.
void setSprites(const QImage &image, const QVariantMap &definitions)
Sets the sprite image and definitions JSON to use during conversion.
void setTargetUnit(QgsUnitTypes::RenderUnit targetUnit)
Sets the target unit type.
QVariantMap spriteDefinitions() const
Returns the sprite definitions to use during conversion.
Handles conversion of MapBox GL styles to QGIS vector tile renderers and labeling settings.
QgsVectorTileRenderer * renderer() const
Returns a new instance of a vector tile renderer representing the converted style,...
QgsVectorTileLabeling * labeling() const
Returns a new instance of a vector tile labeling representing the converted style,...
Result convert(const QVariantMap &style, QgsMapBoxGlStyleConversionContext *context=nullptr)
Converts a JSON style map, and returns the resultant status of the conversion.
@ Success
Conversion was successful.
QString errorMessage() const
Returns a descriptive error message if an error was encountered during the style conversion,...
QStringList warnings() const
Returns a list of user-friendly warnings generated during the conversion, e.g.
static QString typeToString(QgsMapLayerType type)
Converts a map layer type to a string value.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for all map layer types.
Definition: qgsmaplayer.h:85
QString name
Definition: qgsmaplayer.h:88
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any). To be called by subclasses.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager's configuration (if exists). To be called by subclasses.
QString source() const
Returns the source for the layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:90
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
virtual QgsError error() const
Gets current status error.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1675
virtual QString loadDefaultMetadata(bool &resultFlag)
Retrieve the default metadata for this layer if one exists (either as a .qmd file on disk or as a rec...
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
double opacity
Definition: qgsmaplayer.h:94
@ Symbology
Symbology.
Definition: qgsmaplayer.h:170
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:179
@ Labeling
Labeling.
Definition: qgsmaplayer.h:172
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Utility class for reading and writing MBTiles files (which are SQLite3 databases).
Definition: qgsmbtiles.h:39
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
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.
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.
Definition: qgsrectangle.h:42
Contains information about the context of a rendering operation.
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
Definition: qgstiles.h:103
static QgsTileMatrix fromWebMercator(int mZoomLevel)
Returns a tile matrix for the usual web mercator.
Definition: qgstiles.cpp:20
Range of tiles in a tile matrix to be rendered.
Definition: qgstiles.h:66
Stores coordinates of a tile in a tile matrix set.
Definition: qgstiles.h:33
int zoomLevel() const
Returns tile's zoom level (Z)
Definition: qgstiles.h:46
int column() const
Returns tile's column index (X)
Definition: qgstiles.h:42
int row() const
Returns tile's row index (Y)
Definition: qgstiles.h:44
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
Basic labeling configuration for vector tile layers.
The default vector tile renderer implementation.
static QList< QgsVectorTileBasicRendererStyle > simpleStyleWithRandomColors()
Returns a list of styles to render all layers, using random colors.
Base class for labeling configuration classes for vector tile layers.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads labeling properties from given XML element.
This class provides map rendering functionality for vector tile layers.
Implements a map layer that is dedicated to rendering of vector tiles.
QByteArray getRawTile(QgsTileXYZ tileID)
Fetches raw tile data for the give tile coordinates.
bool readXml(const QDomNode &layerNode, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const override
Write the style for the layer into the docment provided.
void setRenderer(QgsVectorTileRenderer *r)
Sets renderer for the map layer.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const FINAL
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
QString sourceType() const
Returns type of the data source.
bool writeXml(QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files.
void setLabeling(QgsVectorTileLabeling *labeling)
Sets labeling for the map layer.
QgsVectorTileLabeling * labeling() const
Returns currently assigned labeling.
~QgsVectorTileLayer() override
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) override
Read the symbology for the current layer from the DOM node supplied.
int sourceMinZoom() const
Returns minimum zoom level at which source has any valid tiles (negative = unconstrained)
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
QString loadDefaultStyle(bool &resultFlag) override
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const FINAL
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
QgsVectorTileLayer(const QString &path=QString(), const QString &baseName=QString())
Constructs a new vector tile layer.
int sourceMaxZoom() const
Returns maximum zoom level at which source has any valid tiles (negative = unconstrained)
QgsVectorTileRenderer * renderer() const
Returns currently assigned renderer.
QString loadDefaultMetadata(bool &resultFlag) override
Retrieve the default metadata for this layer if one exists (either as a .qmd file on disk or as a rec...
QString sourcePath() const
Returns URL/path of the data source (syntax different to each data source type)
void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
QgsVectorTileLayer * clone() const override
Returns a new instance equivalent to this one except for the id which is still unique.
static QList< QgsVectorTileRawData > blockingFetchTileRawData(const QString &sourceType, const QString &sourcePath, const QgsTileMatrix &tileMatrix, const QPointF &viewCenter, const QgsTileRange &range, const QString &authid, const QString &referer)
Returns raw tile data for the specified range of tiles. Blocks the caller until all tiles are fetched...
Abstract base class for all vector tile renderer implementations.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads renderer's properties from given XML element.
static bool checkXYZUrlTemplate(const QString &url)
Checks whether the URL template string is correct (contains {x}, {y} / {-y}, {z} placeholders)
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:69
@ VectorTileLayer
Added in 3.14.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
#define QgsSetRequestInitiatorClass(request, _class)