diff --git a/python/PyQt6/core/auto_additions/qgsmaplayerutils.py b/python/PyQt6/core/auto_additions/qgsmaplayerutils.py index 2474a53a66e..e2b7a7ddfb7 100644 --- a/python/PyQt6/core/auto_additions/qgsmaplayerutils.py +++ b/python/PyQt6/core/auto_additions/qgsmaplayerutils.py @@ -5,3 +5,4 @@ QgsMapLayerUtils.layerSourceMatchesPath = staticmethod(QgsMapLayerUtils.layerSou QgsMapLayerUtils.updateLayerSourcePath = staticmethod(QgsMapLayerUtils.updateLayerSourcePath) QgsMapLayerUtils.sortLayersByType = staticmethod(QgsMapLayerUtils.sortLayersByType) QgsMapLayerUtils.launderLayerName = staticmethod(QgsMapLayerUtils.launderLayerName) +QgsMapLayerUtils.isOpenStreetMapLayer = staticmethod(QgsMapLayerUtils.isOpenStreetMapLayer) diff --git a/python/PyQt6/core/auto_generated/qgsmaplayerutils.sip.in b/python/PyQt6/core/auto_generated/qgsmaplayerutils.sip.in index cbe0a0ea74a..062c4c4483b 100644 --- a/python/PyQt6/core/auto_generated/qgsmaplayerutils.sip.in +++ b/python/PyQt6/core/auto_generated/qgsmaplayerutils.sip.in @@ -78,6 +78,13 @@ Specifically this method: - Removes any characters which are not alphanumeric or '_'. .. versionadded:: 3.28 +%End + + static bool isOpenStreetMapLayer( QgsMapLayer *layer ); +%Docstring +Returns ``True`` if the layer is served by OpenStreetMap server. + +.. versionadded:: 3.40 %End }; diff --git a/python/core/auto_additions/qgsmaplayerutils.py b/python/core/auto_additions/qgsmaplayerutils.py index 2474a53a66e..e2b7a7ddfb7 100644 --- a/python/core/auto_additions/qgsmaplayerutils.py +++ b/python/core/auto_additions/qgsmaplayerutils.py @@ -5,3 +5,4 @@ QgsMapLayerUtils.layerSourceMatchesPath = staticmethod(QgsMapLayerUtils.layerSou QgsMapLayerUtils.updateLayerSourcePath = staticmethod(QgsMapLayerUtils.updateLayerSourcePath) QgsMapLayerUtils.sortLayersByType = staticmethod(QgsMapLayerUtils.sortLayersByType) QgsMapLayerUtils.launderLayerName = staticmethod(QgsMapLayerUtils.launderLayerName) +QgsMapLayerUtils.isOpenStreetMapLayer = staticmethod(QgsMapLayerUtils.isOpenStreetMapLayer) diff --git a/python/core/auto_generated/qgsmaplayerutils.sip.in b/python/core/auto_generated/qgsmaplayerutils.sip.in index cbe0a0ea74a..062c4c4483b 100644 --- a/python/core/auto_generated/qgsmaplayerutils.sip.in +++ b/python/core/auto_generated/qgsmaplayerutils.sip.in @@ -78,6 +78,13 @@ Specifically this method: - Removes any characters which are not alphanumeric or '_'. .. versionadded:: 3.28 +%End + + static bool isOpenStreetMapLayer( QgsMapLayer *layer ); +%Docstring +Returns ``True`` if the layer is served by OpenStreetMap server. + +.. versionadded:: 3.40 %End }; diff --git a/src/analysis/processing/qgsalgorithmrasterize.cpp b/src/analysis/processing/qgsalgorithmrasterize.cpp index 27666d6bc32..918400b6fc3 100644 --- a/src/analysis/processing/qgsalgorithmrasterize.cpp +++ b/src/analysis/processing/qgsalgorithmrasterize.cpp @@ -25,6 +25,7 @@ #include "qgsalgorithmrasterize.h" #include "qgsprocessingparameters.h" #include "qgsprovidermetadata.h" +#include "qgsmaplayerutils.h" #include "qgsmapthemecollection.h" #include "qgsrasterfilewriter.h" #include "qgsmaprenderercustompainterjob.h" @@ -154,63 +155,59 @@ QVariantMap QgsRasterizeAlgorithm::processAlgorithm( const QVariantMap ¶mete int64_t totalTiles = 0; for ( auto &layer : std::as_const( mMapLayers ) ) { - if ( QgsRasterLayer *rasterLayer = qobject_cast( ( layer.get() ) ) ) + if ( QgsMapLayerUtils::isOpenStreetMapLayer( layer.get() ) ) { - if ( const QgsProviderMetadata *metadata = rasterLayer->providerMetadata() ) + if ( QgsRasterLayer *rasterLayer = qobject_cast( ( layer.get() ) ) ) { - QVariantMap details = metadata->decodeUri( rasterLayer->source() ); - if ( details.contains( QStringLiteral( "url" ) ) && QUrl( details[QStringLiteral( "url" )].toString() ).host() == QStringLiteral( "tile.openstreetmap.org" ) ) + const QList< double > resolutions = rasterLayer->dataProvider()->nativeResolutions(); + if ( resolutions.isEmpty() ) { - const QList< double > resolutions = rasterLayer->dataProvider()->nativeResolutions(); - if ( resolutions.isEmpty() ) + continue; + } + + if ( totalTiles == 0 ) + { + const QgsCoordinateTransform ct( context.project()->crs(), rasterLayer->crs(), context.transformContext() ); + QgsRectangle extentLayer; + try { + extentLayer = ct.transform( extent ); + } + catch ( QgsCsException & ) + { + totalTiles = -1; continue; } - if ( totalTiles == 0 ) + const double mapUnitsPerPixelLayer = extentLayer.width() / width; + int i; + for ( i = 0; i < resolutions.size() && resolutions.at( i ) < mapUnitsPerPixelLayer; i++ ) { - const QgsCoordinateTransform ct( context.project()->crs(), rasterLayer->crs(), context.transformContext() ); - QgsRectangle extentLayer; - try - { - extentLayer = ct.transform( extent ); - } - catch ( QgsCsException & ) - { - totalTiles = -1; - continue; - } - - const double mapUnitsPerPixelLayer = extentLayer.width() / width; - int i; - for ( i = 0; i < resolutions.size() && resolutions.at( i ) < mapUnitsPerPixelLayer; i++ ) - { - } - - if ( i == resolutions.size() || - ( i > 0 && resolutions.at( i ) - mapUnitsPerPixelLayer > mapUnitsPerPixelLayer - resolutions.at( i - 1 ) ) ) - { - i--; - } - - const int nbTilesWidth = std::ceil( extentLayer.width() / resolutions.at( i ) / 256 ); - const int nbTilesHeight = std::ceil( extentLayer.height() / resolutions.at( i ) / 256 ); - totalTiles = static_cast( nbTilesWidth ) * nbTilesHeight; } - feedback->pushInfo( QStringLiteral( "%1" ).arg( totalTiles ) ); - if ( totalTiles > 5000 ) + if ( i == resolutions.size() || + ( i > 0 && resolutions.at( i ) - mapUnitsPerPixelLayer > mapUnitsPerPixelLayer - resolutions.at( i - 1 ) ) ) { - // Prevent bulk downloading of tiles from openstreetmap.org as per OSMF tile usage policy - feedback->pushFormattedMessage( QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( rasterLayer->name(), QStringLiteral( "" ), QStringLiteral( "" ) ), - QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( rasterLayer->name(), QString(), QString() ) ); + i--; + } - layer->deleteLater(); - std::vector>::iterator position = std::find( mMapLayers.begin(), mMapLayers.end(), layer ); - if ( position != mMapLayers.end() ) - { - mMapLayers.erase( position ); - } + const int nbTilesWidth = std::ceil( extentLayer.width() / resolutions.at( i ) / 256 ); + const int nbTilesHeight = std::ceil( extentLayer.height() / resolutions.at( i ) / 256 ); + totalTiles = static_cast( nbTilesWidth ) * nbTilesHeight; + } + feedback->pushInfo( QStringLiteral( "%1" ).arg( totalTiles ) ); + + if ( totalTiles > 5000 ) + { + // Prevent bulk downloading of tiles from openstreetmap.org as per OSMF tile usage policy + feedback->pushFormattedMessage( QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( rasterLayer->name(), QStringLiteral( "" ), QStringLiteral( "" ) ), + QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( rasterLayer->name(), QString(), QString() ) ); + + layer->deleteLater(); + std::vector>::iterator position = std::find( mMapLayers.begin(), mMapLayers.end(), layer ); + if ( position != mMapLayers.end() ) + { + mMapLayers.erase( position ); } } } diff --git a/src/analysis/processing/qgsalgorithmxyztiles.cpp b/src/analysis/processing/qgsalgorithmxyztiles.cpp index 2685d34a8d1..3359e51bf9d 100644 --- a/src/analysis/processing/qgsalgorithmxyztiles.cpp +++ b/src/analysis/processing/qgsalgorithmxyztiles.cpp @@ -22,6 +22,7 @@ #include "qgslayertree.h" #include "qgslayertreelayer.h" #include "qgsexpressioncontextutils.h" +#include "qgsmaplayerutils.h" #include "qgsprovidermetadata.h" ///@cond PRIVATE @@ -192,17 +193,13 @@ void QgsXyzTilesBaseAlgorithm::checkLayersUsagePolicy( QgsProcessingFeedback *fe { for ( QgsMapLayer *layer : std::as_const( mLayers ) ) { - if ( const QgsProviderMetadata *metadata = layer->providerMetadata() ) + if ( QgsMapLayerUtils::isOpenStreetMapLayer( layer ) ) { - QVariantMap details = metadata->decodeUri( layer->source() ); - if ( details.contains( QStringLiteral( "url" ) ) && QUrl( details[QStringLiteral( "url" )].toString() ).host() == QStringLiteral( "tile.openstreetmap.org" ) ) - { - // Prevent bulk downloading of tiles from openstreetmap.org as per OSMF tile usage policy - feedback->pushFormattedMessage( QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( layer->name(), QStringLiteral( "" ), QStringLiteral( "" ) ), - QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( layer->name(), QString(), QString() ) ); - mLayers.removeAll( layer ); - delete layer; - } + // Prevent bulk downloading of tiles from openstreetmap.org as per OSMF tile usage policy + feedback->pushFormattedMessage( QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( layer->name(), QStringLiteral( "" ), QStringLiteral( "" ) ), + QObject::tr( "Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" ).arg( layer->name(), QString(), QString() ) ); + mLayers.removeAll( layer ); + delete layer; } } } diff --git a/src/core/qgsmaplayerutils.cpp b/src/core/qgsmaplayerutils.cpp index 68b19fbf86e..69281ccf4d6 100644 --- a/src/core/qgsmaplayerutils.cpp +++ b/src/core/qgsmaplayerutils.cpp @@ -166,3 +166,20 @@ QString QgsMapLayerUtils::launderLayerName( const QString &name ) return laundered; } + +bool QgsMapLayerUtils::isOpenStreetMapLayer( QgsMapLayer *layer ) +{ + if ( layer->providerType() == QStringLiteral( "wms" ) ) + { + if ( const QgsProviderMetadata *metadata = layer->providerMetadata() ) + { + QVariantMap details = metadata->decodeUri( layer->source() ); + QUrl url( details.value( QStringLiteral( "url" ) ).toString() ); + if ( url.host().endsWith( QStringLiteral( ".openstreetmap.org" ) ) || url.host().endsWith( QStringLiteral( ".osm.org" ) ) ) + { + return true; + } + } + } + return false; +} diff --git a/src/core/qgsmaplayerutils.h b/src/core/qgsmaplayerutils.h index 3708cc9cbda..5606cbaa9ec 100644 --- a/src/core/qgsmaplayerutils.h +++ b/src/core/qgsmaplayerutils.h @@ -94,6 +94,13 @@ class CORE_EXPORT QgsMapLayerUtils */ static QString launderLayerName( const QString &name ); + /** + * Returns TRUE if the layer is served by OpenStreetMap server. + * + * \since QGIS 3.40 + */ + static bool isOpenStreetMapLayer( QgsMapLayer *layer ); + }; #endif // QGSMAPLAYERUTILS_H