Implement a QgsProviderRegistry decodeUri function + test

This commit is contained in:
nirvn 2018-08-16 11:19:57 +07:00 committed by Mathieu Pellerin
parent 4ab4b42d27
commit f4a0e743fa
8 changed files with 142 additions and 7 deletions

View File

@ -78,7 +78,7 @@ Sets library directory where to search for plugins
%Docstring
Creates a new instance of a provider.
:param providerKey: identificator of the provider
:param providerKey: identifier of the provider
:param dataSource: string containing data source for the provider
:param options: provider options
@ -89,9 +89,25 @@ Creates a new instance of a provider.
%Docstring
Returns the provider capabilities
:param providerKey: identificator of the provider
:param providerKey: identifier of the provider
.. versionadded:: 2.6
%End
QVariantMap decodeUri( const QString &providerKey, const QString &uri );
%Docstring
Returns the components (e.g. file path, layer name) of a provider uri
:param providerKey: identifier of the provider
:param uri: uri string
:return: map containing components
.. note::
this function may not be supported by all providers, an empty map will be returned in such case
.. versionadded:: 3.4
%End
QWidget *createSelectionWidget( const QString &providerKey,
@ -109,7 +125,7 @@ responsible for deleting the returned widget.
%Docstring
Gets pointer to provider function
:param providerKey: identificator of the provider
:param providerKey: identifier of the provider
:param functionName: name of function
:return: pointer to function or NULL on error. If the provider uses direct provider

View File

@ -43,6 +43,8 @@ typedef QString databaseDrivers_t();
typedef QString directoryDrivers_t();
typedef QString protocolDrivers_t();
typedef void initProviderFunction_t();
typedef QVariantMap decodeUri_t( const QString &uri );
//typedef int dataCapabilities_t();
//typedef QgsDataItem * dataItem_t(QString);
@ -438,6 +440,22 @@ QgsDataProvider *QgsProviderRegistry::createProvider( QString const &providerKey
return dataProvider;
} // QgsProviderRegistry::setDataProvider
QVariantMap QgsProviderRegistry::decodeUri( const QString &providerKey, const QString &uri )
{
std::unique_ptr< QLibrary > library( createProviderLibrary( providerKey ) );
if ( !library )
{
return QVariantMap();
}
decodeUri_t *decodeUri = reinterpret_cast< decodeUri_t *>( cast_to_fptr( library->resolve( "decodeUri" ) ) );
if ( !decodeUri )
{
return QVariantMap();
}
return decodeUri( uri );
}
int QgsProviderRegistry::providerCapabilities( const QString &providerKey ) const
{
std::unique_ptr< QLibrary > library( createProviderLibrary( providerKey ) );

View File

@ -91,7 +91,7 @@ class CORE_EXPORT QgsProviderRegistry
/**
* Creates a new instance of a provider.
* \param providerKey identificator of the provider
* \param providerKey identifier of the provider
* \param dataSource string containing data source for the provider
* \param options provider options
* \returns new instance of provider or NULL on error
@ -102,11 +102,21 @@ class CORE_EXPORT QgsProviderRegistry
/**
* Returns the provider capabilities
\param providerKey identificator of the provider
\param providerKey identifier of the provider
\since QGIS 2.6
*/
int providerCapabilities( const QString &providerKey ) const;
/**
* Returns the components (e.g. file path, layer name) of a provider uri
\param providerKey identifier of the provider
\param uri uri string
\returns map containing components
\note this function may not be supported by all providers, an empty map will be returned in such case
\since QGIS 3.4
*/
QVariantMap decodeUri( const QString &providerKey, const QString &uri );
/**
* Returns a new widget for selecting layers from a provider.
* Either the \a parent widget must be set or the caller becomes
@ -119,7 +129,7 @@ class CORE_EXPORT QgsProviderRegistry
/**
* Gets pointer to provider function
* \param providerKey identificator of the provider
* \param providerKey identifier of the provider
* \param functionName name of function
* \returns pointer to function or NULL on error. If the provider uses direct provider
* function pointers instead of a library nullptr will be returned.

View File

@ -1974,6 +1974,30 @@ QStringList QgsGdalProvider::subLayers() const
return mSubLayers;
}
QGISEXTERN QVariantMap decodeUri( const QString &uri )
{
QString path = uri;
QString layerName;
QString vsiPrefix = qgsVsiPrefix( path );
if ( !path.isEmpty() )
path = path.mid( vsiPrefix.count() );
if ( path.indexOf( ':' ) != -1 )
{
QStringList parts = path.split( ':' );
path = parts[1];
if ( parts.count() > 2 )
layerName = parts[2];
}
QVariantMap uriComponents;
uriComponents.insert( QStringLiteral( "path" ), path );
uriComponents.insert( QStringLiteral( "layerName" ), layerName );
return uriComponents;
}
/**
* Class factory to return a pointer to a newly created
* QgsGdalProvider object

View File

@ -3021,6 +3021,39 @@ QString createFilters( const QString &type )
}
}
QGISEXTERN QVariantMap decodeUri( const QString &uri )
{
QString path = uri;
QString layerName;
int layerId = -1;
int pipeIndex = path.indexOf( '|' );
if ( pipeIndex != -1 )
{
if ( path.indexOf( QLatin1String( "|layername=" ) ) != -1 )
{
QRegularExpression regex( QStringLiteral( "\\|layername=([^|]*)" ) );
layerName = regex.match( path ).captured( 1 );
}
else if ( path.indexOf( QLatin1String( "|layerid=" ) ) )
{
QRegularExpression regex( QStringLiteral( "\\|layerid=([^|]*)" ) );
layerId = regex.match( path ).captured( 1 ).toInt();
}
path = path.left( pipeIndex );
}
QString vsiPrefix = qgsVsiPrefix( path );
if ( !vsiPrefix.isEmpty() )
path = path.mid( vsiPrefix.count() );
QVariantMap uriComponents;
uriComponents.insert( QStringLiteral( "path" ), path );
uriComponents.insert( QStringLiteral( "layerName" ), layerName );
uriComponents.insert( QStringLiteral( "layerId" ), layerId > -1 ? layerId : QVariant() ) ;
return uriComponents;
}
QGISEXTERN QString fileVectorFilters()
{

View File

@ -96,7 +96,6 @@ class QgsOgrProvider : public QgsVectorDataProvider
*/
QString dataSourceUri( bool expandAuthConfig = false ) const override;
QgsAbstractFeatureSource *featureSource() const override;
QgsCoordinateReferenceSystem crs() const override;

View File

@ -44,6 +44,7 @@ class TestQgsGdalProvider : public QObject
void init() {}// will be called before each testfunction is executed.
void cleanup() {}// will be called after every testfunction.
void decodeUri(); // test decode URI implementation
void scaleDataType(); //test resultant data types for int raster with float scale (#11573)
void warpedVrt(); //test loading raster which requires a warped vrt
void noData();
@ -82,6 +83,20 @@ void TestQgsGdalProvider::cleanupTestCase()
}
}
void TestQgsGdalProvider::decodeUri()
{
QString uri = QStringLiteral( "/home/to/path/raster.tif" );
QVariantMap components;
components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri );
QCOMPARE( components[QStringLiteral( "path" )].toString(), uri );
uri = QStringLiteral( "gpkg:/home/to/path/my_file.gpkg:layer_name" );
components = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), uri );
QCOMPARE( components[QStringLiteral( "path" )].toString(), QStringLiteral( "/home/to/path/my_file.gpkg" ) );
QCOMPARE( components[QStringLiteral( "layerName" )].toString(), QStringLiteral( "layer_name" ) );
}
void TestQgsGdalProvider::scaleDataType()
{
QString rasterWithOffset = QStringLiteral( TEST_DATA_DIR ) + "/int_raster_with_scale.tif";

View File

@ -28,6 +28,7 @@ from qgis.core import (QgsFeature,
QgsField,
QgsFieldConstraints,
QgsGeometry,
QgsProviderRegistry,
QgsRectangle,
QgsSettings,
QgsVectorLayer,
@ -95,6 +96,25 @@ class TestPyQgsOGRProviderGpkg(unittest.TestCase):
QgsSettings().clear()
def testDecodeUri(self):
filename = '/home/to/path/my_file.gpkg'
registry = QgsProviderRegistry.instance()
uri = filename
components = registry.decodeUri('ogr', uri)
self.assertEqual(components["path"], filename)
uri = '{}|layername=test'.format(filename)
components = registry.decodeUri('ogr', uri)
self.assertEqual(components["path"], filename)
self.assertEqual(components["layerName"], 'test')
uri = '{}|layerid=0'.format(filename)
components = registry.decodeUri('ogr', uri)
self.assertEqual(components["path"], filename)
self.assertEqual(components["layerId"], 0)
def testSingleToMultiPolygonPromotion(self):
tmpfile = os.path.join(self.basetestpath, 'testSingleToMultiPolygonPromotion.gpkg')