Skip to content

Commit f4a0e74

Browse files
committedAug 16, 2018
Implement a QgsProviderRegistry decodeUri function + test
1 parent 4ab4b42 commit f4a0e74

File tree

8 files changed

+142
-7
lines changed

8 files changed

+142
-7
lines changed
 

‎python/core/auto_generated/qgsproviderregistry.sip.in

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Sets library directory where to search for plugins
7878
%Docstring
7979
Creates a new instance of a provider.
8080

81-
:param providerKey: identificator of the provider
81+
:param providerKey: identifier of the provider
8282
:param dataSource: string containing data source for the provider
8383
:param options: provider options
8484

@@ -89,9 +89,25 @@ Creates a new instance of a provider.
8989
%Docstring
9090
Returns the provider capabilities
9191

92-
:param providerKey: identificator of the provider
92+
:param providerKey: identifier of the provider
9393

9494
.. versionadded:: 2.6
95+
%End
96+
97+
QVariantMap decodeUri( const QString &providerKey, const QString &uri );
98+
%Docstring
99+
Returns the components (e.g. file path, layer name) of a provider uri
100+
101+
:param providerKey: identifier of the provider
102+
:param uri: uri string
103+
104+
:return: map containing components
105+
106+
.. note::
107+
108+
this function may not be supported by all providers, an empty map will be returned in such case
109+
110+
.. versionadded:: 3.4
95111
%End
96112

97113
QWidget *createSelectionWidget( const QString &providerKey,
@@ -109,7 +125,7 @@ responsible for deleting the returned widget.
109125
%Docstring
110126
Gets pointer to provider function
111127

112-
:param providerKey: identificator of the provider
128+
:param providerKey: identifier of the provider
113129
:param functionName: name of function
114130

115131
:return: pointer to function or NULL on error. If the provider uses direct provider

‎src/core/qgsproviderregistry.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ typedef QString databaseDrivers_t();
4343
typedef QString directoryDrivers_t();
4444
typedef QString protocolDrivers_t();
4545
typedef void initProviderFunction_t();
46+
typedef QVariantMap decodeUri_t( const QString &uri );
47+
4648
//typedef int dataCapabilities_t();
4749
//typedef QgsDataItem * dataItem_t(QString);
4850

@@ -438,6 +440,22 @@ QgsDataProvider *QgsProviderRegistry::createProvider( QString const &providerKey
438440
return dataProvider;
439441
} // QgsProviderRegistry::setDataProvider
440442

443+
QVariantMap QgsProviderRegistry::decodeUri( const QString &providerKey, const QString &uri )
444+
{
445+
std::unique_ptr< QLibrary > library( createProviderLibrary( providerKey ) );
446+
if ( !library )
447+
{
448+
return QVariantMap();
449+
}
450+
451+
decodeUri_t *decodeUri = reinterpret_cast< decodeUri_t *>( cast_to_fptr( library->resolve( "decodeUri" ) ) );
452+
if ( !decodeUri )
453+
{
454+
return QVariantMap();
455+
}
456+
return decodeUri( uri );
457+
}
458+
441459
int QgsProviderRegistry::providerCapabilities( const QString &providerKey ) const
442460
{
443461
std::unique_ptr< QLibrary > library( createProviderLibrary( providerKey ) );

‎src/core/qgsproviderregistry.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class CORE_EXPORT QgsProviderRegistry
9191

9292
/**
9393
* Creates a new instance of a provider.
94-
* \param providerKey identificator of the provider
94+
* \param providerKey identifier of the provider
9595
* \param dataSource string containing data source for the provider
9696
* \param options provider options
9797
* \returns new instance of provider or NULL on error
@@ -102,11 +102,21 @@ class CORE_EXPORT QgsProviderRegistry
102102

103103
/**
104104
* Returns the provider capabilities
105-
\param providerKey identificator of the provider
105+
\param providerKey identifier of the provider
106106
\since QGIS 2.6
107107
*/
108108
int providerCapabilities( const QString &providerKey ) const;
109109

110+
/**
111+
* Returns the components (e.g. file path, layer name) of a provider uri
112+
\param providerKey identifier of the provider
113+
\param uri uri string
114+
\returns map containing components
115+
\note this function may not be supported by all providers, an empty map will be returned in such case
116+
\since QGIS 3.4
117+
*/
118+
QVariantMap decodeUri( const QString &providerKey, const QString &uri );
119+
110120
/**
111121
* Returns a new widget for selecting layers from a provider.
112122
* Either the \a parent widget must be set or the caller becomes
@@ -119,7 +129,7 @@ class CORE_EXPORT QgsProviderRegistry
119129

120130
/**
121131
* Gets pointer to provider function
122-
* \param providerKey identificator of the provider
132+
* \param providerKey identifier of the provider
123133
* \param functionName name of function
124134
* \returns pointer to function or NULL on error. If the provider uses direct provider
125135
* function pointers instead of a library nullptr will be returned.

‎src/providers/gdal/qgsgdalprovider.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,6 +1974,30 @@ QStringList QgsGdalProvider::subLayers() const
19741974
return mSubLayers;
19751975
}
19761976

1977+
1978+
QGISEXTERN QVariantMap decodeUri( const QString &uri )
1979+
{
1980+
QString path = uri;
1981+
QString layerName;
1982+
1983+
QString vsiPrefix = qgsVsiPrefix( path );
1984+
if ( !path.isEmpty() )
1985+
path = path.mid( vsiPrefix.count() );
1986+
1987+
if ( path.indexOf( ':' ) != -1 )
1988+
{
1989+
QStringList parts = path.split( ':' );
1990+
path = parts[1];
1991+
if ( parts.count() > 2 )
1992+
layerName = parts[2];
1993+
}
1994+
1995+
QVariantMap uriComponents;
1996+
uriComponents.insert( QStringLiteral( "path" ), path );
1997+
uriComponents.insert( QStringLiteral( "layerName" ), layerName );
1998+
return uriComponents;
1999+
}
2000+
19772001
/**
19782002
* Class factory to return a pointer to a newly created
19792003
* QgsGdalProvider object

‎src/providers/ogr/qgsogrprovider.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,6 +3021,39 @@ QString createFilters( const QString &type )
30213021
}
30223022
}
30233023

3024+
QGISEXTERN QVariantMap decodeUri( const QString &uri )
3025+
{
3026+
QString path = uri;
3027+
QString layerName;
3028+
int layerId = -1;
3029+
3030+
int pipeIndex = path.indexOf( '|' );
3031+
if ( pipeIndex != -1 )
3032+
{
3033+
if ( path.indexOf( QLatin1String( "|layername=" ) ) != -1 )
3034+
{
3035+
QRegularExpression regex( QStringLiteral( "\\|layername=([^|]*)" ) );
3036+
layerName = regex.match( path ).captured( 1 );
3037+
}
3038+
else if ( path.indexOf( QLatin1String( "|layerid=" ) ) )
3039+
{
3040+
QRegularExpression regex( QStringLiteral( "\\|layerid=([^|]*)" ) );
3041+
layerId = regex.match( path ).captured( 1 ).toInt();
3042+
}
3043+
3044+
path = path.left( pipeIndex );
3045+
}
3046+
3047+
QString vsiPrefix = qgsVsiPrefix( path );
3048+
if ( !vsiPrefix.isEmpty() )
3049+
path = path.mid( vsiPrefix.count() );
3050+
3051+
QVariantMap uriComponents;
3052+
uriComponents.insert( QStringLiteral( "path" ), path );
3053+
uriComponents.insert( QStringLiteral( "layerName" ), layerName );
3054+
uriComponents.insert( QStringLiteral( "layerId" ), layerId > -1 ? layerId : QVariant() ) ;
3055+
return uriComponents;
3056+
}
30243057

30253058
QGISEXTERN QString fileVectorFilters()
30263059
{

‎src/providers/ogr/qgsogrprovider.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ class QgsOgrProvider : public QgsVectorDataProvider
9696
*/
9797
QString dataSourceUri( bool expandAuthConfig = false ) const override;
9898

99-
10099
QgsAbstractFeatureSource *featureSource() const override;
101100

102101
QgsCoordinateReferenceSystem crs() const override;

‎tests/src/providers/testqgsgdalprovider.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class TestQgsGdalProvider : public QObject
4444
void init() {}// will be called before each testfunction is executed.
4545
void cleanup() {}// will be called after every testfunction.
4646

47+
void decodeUri(); // test decode URI implementation
4748
void scaleDataType(); //test resultant data types for int raster with float scale (#11573)
4849
void warpedVrt(); //test loading raster which requires a warped vrt
4950
void noData();
@@ -82,6 +83,20 @@ void TestQgsGdalProvider::cleanupTestCase()
8283
}
8384
}
8485

86+
void TestQgsGdalProvider::decodeUri()
87+
{
88+
QString uri = QStringLiteral( "/home/to/path/raster.tif" );
89+
QVariantMap components;
90+
91+
components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri );
92+
QCOMPARE( components[QStringLiteral( "path" )].toString(), uri );
93+
94+
uri = QStringLiteral( "gpkg:/home/to/path/my_file.gpkg:layer_name" );
95+
components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri );
96+
QCOMPARE( components[QStringLiteral( "path" )].toString(), QStringLiteral( "/home/to/path/my_file.gpkg" ) );
97+
QCOMPARE( components[QStringLiteral( "layerName" )].toString(), QStringLiteral( "layer_name" ) );
98+
}
99+
85100
void TestQgsGdalProvider::scaleDataType()
86101
{
87102
QString rasterWithOffset = QStringLiteral( TEST_DATA_DIR ) + "/int_raster_with_scale.tif";

‎tests/src/python/test_provider_ogr_gpkg.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
QgsField,
2929
QgsFieldConstraints,
3030
QgsGeometry,
31+
QgsProviderRegistry,
3132
QgsRectangle,
3233
QgsSettings,
3334
QgsVectorLayer,
@@ -95,6 +96,25 @@ def tearDownClass(cls):
9596

9697
QgsSettings().clear()
9798

99+
def testDecodeUri(self):
100+
101+
filename = '/home/to/path/my_file.gpkg'
102+
103+
registry = QgsProviderRegistry.instance()
104+
uri = filename
105+
components = registry.decodeUri('ogr', uri)
106+
self.assertEqual(components["path"], filename)
107+
108+
uri = '{}|layername=test'.format(filename)
109+
components = registry.decodeUri('ogr', uri)
110+
self.assertEqual(components["path"], filename)
111+
self.assertEqual(components["layerName"], 'test')
112+
113+
uri = '{}|layerid=0'.format(filename)
114+
components = registry.decodeUri('ogr', uri)
115+
self.assertEqual(components["path"], filename)
116+
self.assertEqual(components["layerId"], 0)
117+
98118
def testSingleToMultiPolygonPromotion(self):
99119

100120
tmpfile = os.path.join(self.basetestpath, 'testSingleToMultiPolygonPromotion.gpkg')

0 commit comments

Comments
 (0)
Please sign in to comment.