Skip to content

Commit

Permalink
Refine API for QgsProviderRegistry tests for preferred provider
Browse files Browse the repository at this point in the history
for a URI to better handle ties, add direct method to determine
whether a particular provider should defer handling of a certain
URI to another (better equipped) provider
  • Loading branch information
nyalldawson committed Nov 5, 2020
1 parent 4dd8f27 commit 8abe4a1
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 15 deletions.
30 changes: 25 additions & 5 deletions python/core/auto_generated/qgsproviderregistry.sip.in
Expand Up @@ -281,20 +281,40 @@ Returns list of available providers by their keys
Returns metadata of the provider or ``None`` if not found
%End

QgsProviderMetadata *preferredProviderForUri( const QString &uri ) const;
QList< QgsProviderMetadata *> preferredProvidersForUri( const QString &uri ) const;
%Docstring
Returns the metadata for the preferred provider for opening the specified ``uri``.
Returns the metadata for the preferred provider(s) for opening the specified ``uri``.

The preferred provider is determined by comparing the priority returned by
:py:func:`QgsProviderMetadata.priorityForUri()` for all registered providers, and selecting
the provider with the largest non-zero priority.

A ``None`` may be returned, which indicates that no providers are available which
An empty list may be returned, which indicates that no providers are available which
returned a non-zero priority for the specified URI.

In the case that multiple providers returned the same priority for the URI then
either of these providers will be returned. In this case the :py:func:`QgsProviderMetadata.priorityForUri()`
implementation for the providers should be refined to avoid ties.
all of these providers will be returned.

.. seealso:: :py:func:`shouldDeferUriForOtherProviders`

.. versionadded:: 3.18
%End

bool shouldDeferUriForOtherProviders( const QString &uri, const QString &providerKey ) const;
%Docstring
Returns ``True`` if the provider with matching ``providerKey`` should defer handling of
the specified ``uri`` to another provider.

This method tests whether any providers are listed as the preferred provider for ``uri``
(see :py:func:`~QgsProviderRegistry.preferredProvidersForUri`), and if so tests whether the specified provider is
included in that preferred providers list. Returns ``True`` only if the specified provider
is calculated as one of the preferred providers for the URI.

In the case that there is no registered preferred provider for the URI then ``False`` will be
returned, and the provider must use another metric to determine whether it should
handle the URI.

.. seealso:: :py:func:`preferredProvidersForUri`

.. versionadded:: 3.18
%End
Expand Down
17 changes: 14 additions & 3 deletions src/core/qgsproviderregistry.cpp
Expand Up @@ -746,18 +746,29 @@ QgsProviderMetadata *QgsProviderRegistry::providerMetadata( const QString &provi
return findMetadata_( mProviders, providerKey );
}

QgsProviderMetadata *QgsProviderRegistry::preferredProviderForUri( const QString &uri ) const
QList< QgsProviderMetadata * > QgsProviderRegistry::preferredProvidersForUri( const QString &uri ) const
{
QgsProviderMetadata *res = nullptr;
QList< QgsProviderMetadata * > res;
int maxPriority = 0;
for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
{
const int thisProviderPriority = it->second->priorityForUri( uri );
if ( thisProviderPriority > maxPriority )
{
res.clear();
maxPriority = thisProviderPriority;
res = it->second;
}
if ( thisProviderPriority == maxPriority )
res.append( it->second );
}
return res;
}

bool QgsProviderRegistry::shouldDeferUriForOtherProviders( const QString &uri, const QString &providerKey ) const
{
const QList< QgsProviderMetadata * > providers = preferredProvidersForUri( uri );
if ( providers.empty() )
return false;

return !providers.contains( QgsProviderRegistry::instance()->providerMetadata( providerKey ) );
}
28 changes: 23 additions & 5 deletions src/core/qgsproviderregistry.h
Expand Up @@ -283,22 +283,40 @@ class CORE_EXPORT QgsProviderRegistry
QgsProviderMetadata *providerMetadata( const QString &providerKey ) const;

/**
* Returns the metadata for the preferred provider for opening the specified \a uri.
* Returns the metadata for the preferred provider(s) for opening the specified \a uri.
*
* The preferred provider is determined by comparing the priority returned by
* QgsProviderMetadata::priorityForUri() for all registered providers, and selecting
* the provider with the largest non-zero priority.
*
* A NULLPTR may be returned, which indicates that no providers are available which
* An empty list may be returned, which indicates that no providers are available which
* returned a non-zero priority for the specified URI.
*
* In the case that multiple providers returned the same priority for the URI then
* either of these providers will be returned. In this case the QgsProviderMetadata::priorityForUri()
* implementation for the providers should be refined to avoid ties.
* all of these providers will be returned.
*
* \see shouldDeferUriForOtherProviders()
* \since QGIS 3.18
*/
QgsProviderMetadata *preferredProviderForUri( const QString &uri ) const;
QList< QgsProviderMetadata *> preferredProvidersForUri( const QString &uri ) const;

/**
* Returns TRUE if the provider with matching \a providerKey should defer handling of
* the specified \a uri to another provider.
*
* This method tests whether any providers are listed as the preferred provider for \a uri
* (see preferredProvidersForUri()), and if so tests whether the specified provider is
* included in that preferred providers list. Returns TRUE only if the specified provider
* is calculated as one of the preferred providers for the URI.
*
* In the case that there is no registered preferred provider for the URI then FALSE will be
* returned, and the provider must use another metric to determine whether it should
* handle the URI.
*
* \see preferredProvidersForUri()
* \since QGIS 3.18
*/
bool shouldDeferUriForOtherProviders( const QString &uri, const QString &providerKey ) const;

/**
* Returns a file filter string for supported vector files.
Expand Down
7 changes: 5 additions & 2 deletions tests/src/providers/testqgseptprovider.cpp
Expand Up @@ -112,8 +112,11 @@ void TestQgsEptProvider::decodeUri()
void TestQgsEptProvider::preferredUri()
{
// test that EPT is the preferred provider for ept.json uris
QCOMPARE( QgsProviderRegistry::instance()->preferredProviderForUri( QStringLiteral( "/home/test/ept.json" ) )->key(), QStringLiteral( "ept" ) );
QCOMPARE( QgsProviderRegistry::instance()->preferredProviderForUri( QStringLiteral( "/home/test/EPT.JSON" ) )->key(), QStringLiteral( "ept" ) );
QCOMPARE( QgsProviderRegistry::instance()->preferredProvidersForUri( QStringLiteral( "/home/test/ept.json" ) ), QList< QgsProviderMetadata * >() << QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "ept" ) ) );
QCOMPARE( QgsProviderRegistry::instance()->preferredProvidersForUri( QStringLiteral( "/home/test/EPT.JSON" ) ), QList< QgsProviderMetadata * >() << QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "ept" ) ) );

QVERIFY( !QgsProviderRegistry::instance()->shouldDeferUriForOtherProviders( QStringLiteral( "/home/test/ept.json" ), QStringLiteral( "ept" ) ) );
QVERIFY( QgsProviderRegistry::instance()->shouldDeferUriForOtherProviders( QStringLiteral( "/home/test/ept.json" ), QStringLiteral( "ogr" ) ) );
}


Expand Down
5 changes: 5 additions & 0 deletions tests/src/python/test_qgsproviderregistry.py
Expand Up @@ -61,6 +61,11 @@ def testCreateProvider(self):

self.assertIsNone(QgsProviderRegistry.instance().createProvider('asdasdasdasdasd', ''))

def testShouldDeferUriForOtherProviders(self):
self.assertTrue(QgsProviderRegistry.instance().shouldDeferUriForOtherProviders('/home/nyall/ept.json', 'ogr'))
self.assertFalse(QgsProviderRegistry.instance().shouldDeferUriForOtherProviders('/home/nyall/ept.json', 'ept'))
self.assertFalse(QgsProviderRegistry.instance().shouldDeferUriForOtherProviders('/home/nyall/my.json', 'ogr'))


if __name__ == '__main__':
unittest.main()

0 comments on commit 8abe4a1

Please sign in to comment.