From 7ee5e32211bcb237e2c6a95e44625a2204586fcc Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 15 May 2023 08:40:41 +1000 Subject: [PATCH] Add flag to indicate that vector tile provider matrix set should always be used for the layer (as opposed to any previously stored matrix sets) For some vector tile data providers this is more appropriate -- specifically for those with tilemap information where we MUST ensure that the tilemap matches the data source or missing tiles may be present. (If we store the matrix set information in projects then loading older projects may mean that a stored tilemap is out-of-sync with the actual data source's current tilemap). --- python/core/auto_additions/qgis.py | 7 +++++++ python/core/auto_generated/qgis.sip.in | 10 ++++++++++ src/core/qgis.h | 20 +++++++++++++++++++ .../vectortile/qgsvectortiledataprovider.cpp | 5 +++++ .../vectortile/qgsvectortiledataprovider.h | 6 ++++++ src/core/vectortile/qgsvectortilelayer.cpp | 17 +++++++++++----- 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index 35a11011583..8e2262cae31 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -3614,6 +3614,13 @@ Qgis.FeatureSymbologyExport.__doc__ = 'Options for exporting features considerin # -- Qgis.FeatureSymbologyExport.baseClass = Qgis # monkey patching scoped based enum +Qgis.VectorTileProviderFlag.AlwaysUseTileMatrixSetFromProvider.__doc__ = "Vector tile layer must always use the tile matrix set from the data provider, and should never store, restore or override the definition of this matrix set." +Qgis.VectorTileProviderFlag.__doc__ = 'Flags for vector tile data providers.\n\n.. versionadded:: 3.32\n\n' + '* ``AlwaysUseTileMatrixSetFromProvider``: ' + Qgis.VectorTileProviderFlag.AlwaysUseTileMatrixSetFromProvider.__doc__ +# -- +Qgis.VectorTileProviderFlag.baseClass = Qgis +Qgis.VectorTileProviderFlags.baseClass = Qgis +VectorTileProviderFlags = Qgis # dirty hack since SIP seems to introduce the flags in module +# monkey patching scoped based enum Qgis.VectorTileProviderCapability.ReadLayerMetadata.__doc__ = "Provider can read layer metadata from data store. See QgsDataProvider.layerMetadata()" Qgis.VectorTileProviderCapability.__doc__ = 'Enumeration with capabilities that vector tile data providers might implement.\n\n.. versionadded:: 3.32\n\n' + '* ``ReadLayerMetadata``: ' + Qgis.VectorTileProviderCapability.ReadLayerMetadata.__doc__ # -- diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index b55d7bcc128..62a3104d99a 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -2047,6 +2047,14 @@ The development version PerSymbolLayer }; + enum class VectorTileProviderFlag + { + AlwaysUseTileMatrixSetFromProvider, + }; + + typedef QFlags VectorTileProviderFlags; + + enum class VectorTileProviderCapability { ReadLayerMetadata, @@ -2217,6 +2225,8 @@ QFlags operator|(Qgis::DatabaseProv QFlags operator|(Qgis::VectorFileWriterCapability f1, QFlags f2); +QFlags operator|(Qgis::VectorTileProviderFlag f1, QFlags f2); + QFlags operator|(Qgis::VectorTileProviderCapability f1, QFlags f2); diff --git a/src/core/qgis.h b/src/core/qgis.h index b095f47fe64..9e59969283b 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -3553,6 +3553,25 @@ class CORE_EXPORT Qgis }; Q_ENUM( FeatureSymbologyExport ) + /** + * Flags for vector tile data providers. + * + * \since QGIS 3.32 + */ + enum class VectorTileProviderFlag : int + { + AlwaysUseTileMatrixSetFromProvider = 1 << 1, //!< Vector tile layer must always use the tile matrix set from the data provider, and should never store, restore or override the definition of this matrix set. + }; + Q_ENUM( VectorTileProviderFlag ) + + /** + * Vector tile data provider flags. + * + * \since QGIS 3.32 + */ + Q_DECLARE_FLAGS( VectorTileProviderFlags, VectorTileProviderFlag ) + Q_FLAG( VectorTileProviderFlags ) + /** * Enumeration with capabilities that vector tile data providers might implement. * \since QGIS 3.32 @@ -3745,6 +3764,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::LabelLinePlacementFlags ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::LabelPolygonPlacementFlags ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::DatabaseProviderConnectionCapabilities2 ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::VectorFileWriterCapabilities ) +Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::VectorTileProviderFlags ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::VectorTileProviderCapabilities ) // hack to workaround warnings when casting void pointers diff --git a/src/core/vectortile/qgsvectortiledataprovider.cpp b/src/core/vectortile/qgsvectortiledataprovider.cpp index 09306351358..7a97b2a4a9f 100644 --- a/src/core/vectortile/qgsvectortiledataprovider.cpp +++ b/src/core/vectortile/qgsvectortiledataprovider.cpp @@ -32,6 +32,11 @@ QgsVectorTileDataProvider::QgsVectorTileDataProvider( const QgsVectorTileDataPro setTransformContext( other.transformContext() ); } +Qgis::VectorTileProviderFlags QgsVectorTileDataProvider::providerFlags() const +{ + return Qgis::VectorTileProviderFlags(); +} + Qgis::VectorTileProviderCapabilities QgsVectorTileDataProvider::providerCapabilities() const { return Qgis::VectorTileProviderCapabilities(); diff --git a/src/core/vectortile/qgsvectortiledataprovider.h b/src/core/vectortile/qgsvectortiledataprovider.h index 97a7a6d9445..fca04a3746d 100644 --- a/src/core/vectortile/qgsvectortiledataprovider.h +++ b/src/core/vectortile/qgsvectortiledataprovider.h @@ -58,6 +58,12 @@ class CORE_EXPORT QgsVectorTileDataProvider : public QgsDataProvider */ QgsVectorTileDataProvider &operator=( const QgsVectorTileDataProvider &other ) = delete; + /** + * Returns flags reflecting the behavior of the data provider. + * \since QGIS 3.32 + */ + virtual Qgis::VectorTileProviderFlags providerFlags() const; + /** * Returns flags containing the supported capabilities of the data provider. * \since QGIS 3.32 diff --git a/src/core/vectortile/qgsvectortilelayer.cpp b/src/core/vectortile/qgsvectortilelayer.cpp index 6ceb6d37407..5df38fe38d0 100644 --- a/src/core/vectortile/qgsvectortilelayer.cpp +++ b/src/core/vectortile/qgsvectortilelayer.cpp @@ -154,12 +154,15 @@ bool QgsVectorTileLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext setValid( loadDataSource() ); - const QDomElement matrixSetElement = layerNode.firstChildElement( QStringLiteral( "matrixSet" ) ); - if ( !matrixSetElement.isNull() ) + if ( !mDataProvider || !( qobject_cast< QgsVectorTileDataProvider * >( mDataProvider.get() )->providerFlags() & Qgis::VectorTileProviderFlag::AlwaysUseTileMatrixSetFromProvider ) ) { - mMatrixSet.readXml( matrixSetElement, context ); - setCrs( mMatrixSet.crs() ); + const QDomElement matrixSetElement = layerNode.firstChildElement( QStringLiteral( "matrixSet" ) ); + if ( !matrixSetElement.isNull() ) + { + mMatrixSet.readXml( matrixSetElement, context ); + } } + setCrs( mMatrixSet.crs() ); QString errorMsg; if ( !readSymbology( layerNode, errorMsg, context ) ) @@ -176,7 +179,11 @@ bool QgsVectorTileLayer::writeXml( QDomNode &layerNode, QDomDocument &doc, const QDomElement mapLayerNode = layerNode.toElement(); mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( Qgis::LayerType::VectorTile ) ); - mapLayerNode.appendChild( mMatrixSet.writeXml( doc, context ) ); + if ( !mDataProvider || !( qobject_cast< QgsVectorTileDataProvider * >( mDataProvider.get() )->providerFlags() & Qgis::VectorTileProviderFlag::AlwaysUseTileMatrixSetFromProvider ) ) + { + mapLayerNode.appendChild( mMatrixSet.writeXml( doc, context ) ); + } + // add provider node if ( mDataProvider )