Skip to content

Commit 0f037da

Browse files
authored
Merge pull request #8649 from qgis/expression_function_decode_uri
Expression function `decode_uri`
2 parents 56ca46e + 0896548 commit 0f037da

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "decode_uri",
3+
"type": "function",
4+
"description": "Takes a layer and decodes the uri of the underlying data provider. It depends on the dataprovider, which data is available.",
5+
"arguments": [ {"arg":"layer","description":"The layer for which the uri should be decoded."},
6+
{"arg":"part","description":"The part of the uri to return. If unspecified, a map with all uri parts will be returned.","optional":true} ],
7+
"examples": [ { "expression":"decode_uri(@layer)", "returns":"{'layerId': '0', 'layerName': '', 'path': '/home/qgis/shapefile.shp'}"},
8+
{ "expression":"decode_uri(@layer)", "returns":"{'layerId': NULL, 'layerName': 'layer', 'path': '/home/qgis/geopackage.gpkg'}"},
9+
{ "expression":"decode_uri(@layer, 'path')", "returns":"'C:\\\\my_data\\\\qgis\\\\shape.shp'"}
10+
]
11+
}
12+

resources/function_help/json/layer_property

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Returns a matching layer property or metadata value.",
55
"arguments": [
66
{"arg":"layer", "description":"a string, representing either a layer name or layer ID"},
7-
{"arg":"property", "description":"a string corresponding to the property to return. Valid options are:<br /><ul><li>name: layer name</li><li>id: layer ID</li><li>title: metadata title string</li><li>abstract: metadata abstract string</li><li>keywords: metadata keywords</li><li>data_url: metadata URL</li><li>attribution: metadata attribution string</li><li>attribution_url: metadata attribution URL</li><li>source: layer source</li><li>min_scale: minimum display scale for layer</li><li>max_scale: maximum display scale for layer</li><li>crs: layer CRS</li><li>crs_definition: layer CRS full definition</li><li>crs_description: layer CRS description</li><li>extent: layer extent (as a geometry object)</li><li>type: layer type, e.g., Vector or Raster</li><li>storage_type: storage format (vector layers only)</li><li>geometry_type: geometry type, e.g., Point (vector layers only)</li><li>feature_count: approximate feature count for layer (vector layers only)</li></ul>"}
7+
{"arg":"property", "description":"a string corresponding to the property to return. Valid options are:<br /><ul><li>name: layer name</li><li>id: layer ID</li><li>title: metadata title string</li><li>abstract: metadata abstract string</li><li>keywords: metadata keywords</li><li>data_url: metadata URL</li><li>attribution: metadata attribution string</li><li>attribution_url: metadata attribution URL</li><li>source: layer source</li><li>min_scale: minimum display scale for layer</li><li>max_scale: maximum display scale for layer</li><li>crs: layer CRS</li><li>crs_definition: layer CRS full definition</li><li>crs_description: layer CRS description</li><li>extent: layer extent (as a geometry object)</li><li>type: layer type, e.g., Vector or Raster</li><li>storage_type: storage format (vector layers only)</li><li>geometry_type: geometry type, e.g., Point (vector layers only)</li><li>feature_count: approximate feature count for layer (vector layers only)</li><li>path: File path to the layer data source. Only available for file based layers.</li></ul>"}
88
],
99
"examples": [
1010
{ "expression":"layer_property('streets','title')", "returns":"'Basemap Streets'"},

src/core/expression/qgsexpressionfunction.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "qgsfieldformatterregistry.h"
4747
#include "qgsfieldformatter.h"
4848
#include "qgsvectorlayerfeatureiterator.h"
49+
#include "qgsproviderregistry.h"
4950

5051
const QString QgsExpressionFunction::helpText() const
5152
{
@@ -4024,12 +4025,49 @@ static QVariant fcnGetLayerProperty( const QVariantList &values, const QgsExpres
40244025
return QgsWkbTypes::geometryDisplayString( vLayer->geometryType() );
40254026
else if ( QString::compare( layerProperty, QStringLiteral( "feature_count" ), Qt::CaseInsensitive ) == 0 )
40264027
return QVariant::fromValue( vLayer->featureCount() );
4028+
else if ( QString::compare( layerProperty, QStringLiteral( "path" ), Qt::CaseInsensitive ) == 0 )
4029+
{
4030+
if ( vLayer->dataProvider() )
4031+
{
4032+
const QVariantMap decodedUri = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->dataProvider()->dataSourceUri() );
4033+
return decodedUri.value( QStringLiteral( "path" ) );
4034+
}
4035+
}
40274036
}
40284037
}
40294038

40304039
return QVariant();
40314040
}
40324041

4042+
static QVariant fcnDecodeUri( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
4043+
{
4044+
QgsMapLayer *layer = QgsExpressionUtils::getMapLayer( values.at( 0 ), parent );
4045+
if ( !layer )
4046+
{
4047+
parent->setEvalErrorString( QObject::tr( "Cannot find layer %1" ).arg( values.at( 0 ).toString() ) );
4048+
return QVariant();
4049+
}
4050+
4051+
if ( !layer->dataProvider() )
4052+
{
4053+
parent->setEvalErrorString( QObject::tr( "Layer %1 has invalid data provider" ).arg( layer->name() ) );
4054+
return QVariant();
4055+
}
4056+
4057+
const QString uriPart = values.at( 1 ).toString();
4058+
4059+
const QVariantMap decodedUri = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->dataProvider()->dataSourceUri() );
4060+
4061+
if ( !uriPart.isNull() )
4062+
{
4063+
return decodedUri.value( values.at( 1 ).toString() );
4064+
}
4065+
else
4066+
{
4067+
return decodedUri;
4068+
}
4069+
}
4070+
40334071
static QVariant fcnGetRasterBandStat( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
40344072
{
40354073
QString layerIdOrName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
@@ -4906,6 +4944,11 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
49064944
// **General** functions
49074945
sFunctions
49084946
<< new QgsStaticExpressionFunction( QStringLiteral( "layer_property" ), 2, fcnGetLayerProperty, QStringLiteral( "General" ) )
4947+
<< new QgsStaticExpressionFunction( QStringLiteral( "decode_uri" ),
4948+
QgsExpressionFunction::ParameterList()
4949+
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
4950+
<< QgsExpressionFunction::Parameter( QStringLiteral( "part" ), true ),
4951+
fcnDecodeUri, QStringLiteral( "Map Layers" ) )
49094952
<< new QgsStaticExpressionFunction( QStringLiteral( "raster_statistic" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
49104953
<< QgsExpressionFunction::Parameter( QStringLiteral( "band" ) )
49114954
<< QgsExpressionFunction::Parameter( QStringLiteral( "statistic" ) ), fcnGetRasterBandStat, QStringLiteral( "Rasters" ) );

tests/src/core/testqgsexpression.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,8 @@ class TestQgsExpression: public QObject
12661266
QTest::newRow( "layer_property storage_type" ) << QStringLiteral( "layer_property('%1','storage_type')" ).arg( mPointsLayer->name() ) << false << QVariant( "ESRI Shapefile" );
12671267
QTest::newRow( "layer_property geometry_type" ) << QStringLiteral( "layer_property('%1','geometry_type')" ).arg( mPointsLayer->name() ) << false << QVariant( "Point" );
12681268

1269+
QTest::newRow( "decode_uri shp path" ) << QStringLiteral( "array_last(string_to_array(replace(decode_uri('%1', 'path'), '\\\\', '/'), '/'))" ).arg( mPointsLayer->name() ) << false << QVariant( "points.shp" );
1270+
12691271
// raster_statistic tests
12701272
QTest::newRow( "raster_statistic no layer" ) << "raster_statistic('',1,'min')" << false << QVariant();
12711273
QTest::newRow( "raster_statistic bad layer" ) << "raster_statistic('bad',1,'min')" << false << QVariant();

0 commit comments

Comments
 (0)