Skip to content
Permalink
Browse files

Implement a QgsProviderRegistry decodeUri function + test

  • Loading branch information
nirvn committed Aug 16, 2018
1 parent 4ab4b42 commit f4a0e743fa3578ffaaa1d258622bf99ee4c49d06
@@ -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
@@ -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 ) );
@@ -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.
@@ -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
@@ -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()
{
@@ -96,7 +96,6 @@ class QgsOgrProvider : public QgsVectorDataProvider
*/
QString dataSourceUri( bool expandAuthConfig = false ) const override;


QgsAbstractFeatureSource *featureSource() const override;

QgsCoordinateReferenceSystem crs() const override;
@@ -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";
@@ -28,6 +28,7 @@
QgsField,
QgsFieldConstraints,
QgsGeometry,
QgsProviderRegistry,
QgsRectangle,
QgsSettings,
QgsVectorLayer,
@@ -95,6 +96,25 @@ def tearDownClass(cls):

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')

0 comments on commit f4a0e74

Please sign in to comment.
You can’t perform that action at this time.