Skip to content

Commit

Permalink
[processing] Add method to encode and decode a combined provider key …
Browse files Browse the repository at this point in the history
…and uri

to a single string

We need this to allow processing inputs to load non gdal/ogr/mdal sources, such
as being able to directly read postgis layers without loading them into a project first
  • Loading branch information
nyalldawson committed Mar 26, 2020
1 parent 4b197da commit 320fecc
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 0 deletions.
22 changes: 22 additions & 0 deletions python/core/auto_generated/processing/qgsprocessingutils.sip.in
Expand Up @@ -90,6 +90,28 @@ value.
.. seealso:: :py:func:`compatibleRasterLayers`

.. seealso:: :py:func:`compatibleVectorLayers`
%End

static QString encodeProviderKeyAndUri( const QString &providerKey, const QString &uri );
%Docstring
Encodes a provider key and layer ``uri`` to a single string, for use with
decodeProviderKeyAndUri()

.. versionadded:: 3.14
%End

static bool decodeProviderKeyAndUri( const QString &string, QString &providerKey /Out/, QString &uri /Out/ );
%Docstring
Decodes a provider key and layer ``uri`` from an encoded string, for use with
encodeProviderKeyAndUri()

:param string: encoded string, as returned by encodeProviderKeyAndUri()
:param uri: decoded layer uri

:return: - ``True`` if ``string`` was successfully decoded
- providerKey: ID key for corresponding data provider

.. versionadded:: 3.14
%End

enum class LayerHint
Expand Down
19 changes: 19 additions & 0 deletions src/core/processing/qgsprocessingutils.cpp
Expand Up @@ -133,6 +133,25 @@ QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project,
return layers;
}

QString QgsProcessingUtils::encodeProviderKeyAndUri( const QString &providerKey, const QString &uri )
{
return QStringLiteral( "%1://%2" ).arg( providerKey, uri );
}

bool QgsProcessingUtils::decodeProviderKeyAndUri( const QString &string, QString &providerKey, QString &uri )
{
QRegularExpression re( QStringLiteral( "^(\\w+?):\\/\\/(.+)$" ) );
const QRegularExpressionMatch match = re.match( string );
if ( !match.hasMatch() )
return false;

providerKey = match.captured( 1 );
uri = match.captured( 2 );

// double check that provider is valid
return QgsProviderRegistry::instance()->providerMetadata( providerKey );
}

QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMapLayerStore *store, QgsProcessingUtils::LayerHint typeHint )
{
if ( !store || string.isEmpty() )
Expand Down
21 changes: 21 additions & 0 deletions src/core/processing/qgsprocessingutils.h
Expand Up @@ -105,6 +105,27 @@ class CORE_EXPORT QgsProcessingUtils
*/
static QList< QgsMapLayer * > compatibleLayers( QgsProject *project, bool sort = true );

/**
* Encodes a provider key and layer \a uri to a single string, for use with
* decodeProviderKeyAndUri()
*
* \since QGIS 3.14
*/
static QString encodeProviderKeyAndUri( const QString &providerKey, const QString &uri );

/**
* Decodes a provider key and layer \a uri from an encoded string, for use with
* encodeProviderKeyAndUri()
*
* \param string encoded string, as returned by encodeProviderKeyAndUri()
* \param providerKey ID key for corresponding data provider
* \param uri decoded layer uri
* \returns TRUE if \a string was successfully decoded
*
* \since QGIS 3.14
*/
static bool decodeProviderKeyAndUri( const QString &string, QString &providerKey SIP_OUT, QString &uri SIP_OUT );

/**
* Layer type hints.
* \since QGIS 3.4
Expand Down
23 changes: 23 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -518,6 +518,7 @@ class TestQgsProcessing: public QObject
void providerById();
void removeProvider();
void compatibleLayers();
void encodeDecodeUriProvider();
void normalizeLayerSource();
void context();
void mapLayers();
Expand Down Expand Up @@ -860,6 +861,28 @@ void TestQgsProcessing::compatibleLayers()
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" << "V4" << "v1" << "v3" << "vvvv4" << "MX" << "mA" );
}

void TestQgsProcessing::encodeDecodeUriProvider()
{
QString provider;
QString uri;
QCOMPARE( QgsProcessingUtils::encodeProviderKeyAndUri( QStringLiteral( "ogr" ), QStringLiteral( "/home/me/test.shp" ) ), QStringLiteral( "ogr:///home/me/test.shp" ) );
QVERIFY( QgsProcessingUtils::decodeProviderKeyAndUri( QStringLiteral( "ogr:///home/me/test.shp" ), provider, uri ) );
QCOMPARE( provider, QStringLiteral( "ogr" ) );
QCOMPARE( uri, QStringLiteral( "/home/me/test.shp" ) );
QCOMPARE( QgsProcessingUtils::encodeProviderKeyAndUri( QStringLiteral( "ogr" ), QStringLiteral( "http://mysourcem/a.json" ) ), QStringLiteral( "ogr://http://mysourcem/a.json" ) );
QVERIFY( QgsProcessingUtils::decodeProviderKeyAndUri( QStringLiteral( "ogr://http://mysourcem/a.json" ), provider, uri ) );
QCOMPARE( provider, QStringLiteral( "ogr" ) );
QCOMPARE( uri, QStringLiteral( "http://mysourcem/a.json" ) );
QCOMPARE( QgsProcessingUtils::encodeProviderKeyAndUri( QStringLiteral( "postgres" ), QStringLiteral( "host=blah blah etc" ) ), QStringLiteral( "postgres://host=blah blah etc" ) );
QVERIFY( QgsProcessingUtils::decodeProviderKeyAndUri( QStringLiteral( "postgres://host=blah blah etc" ), provider, uri ) );
QCOMPARE( provider, QStringLiteral( "postgres" ) );
QCOMPARE( uri, QStringLiteral( "host=blah blah etc" ) );

// should reject non valid providers
QVERIFY( !QgsProcessingUtils::decodeProviderKeyAndUri( QStringLiteral( "asdasda://host=blah blah etc" ), provider, uri ) );
QVERIFY( !QgsProcessingUtils::decodeProviderKeyAndUri( QStringLiteral( "http://mysourcem/a.json" ), provider, uri ) );
}

void TestQgsProcessing::normalizeLayerSource()
{
QCOMPARE( QgsProcessingUtils::normalizeLayerSource( "data\\layers\\test.shp" ), QString( "data/layers/test.shp" ) );
Expand Down

0 comments on commit 320fecc

Please sign in to comment.