Skip to content

Commit

Permalink
When querying sublayers for all providers using
Browse files Browse the repository at this point in the history
QgsProviderRegistry::querySublayers, if there is a preferred providers
for a particular uri then ONLY return sublayers from these providers
instead of iterating over all providers

This cleans up the case that two providers can technically handle
a uri, but where we definitely only want ONE of them to handle that
uri. Specifically, while the OGR provider can technically open
JSON files so reports that it can handle ept.json files, we only
ever want to use the EPT point cloud provider for these as we know
for certain that they are point cloud uris, not vector layers.
  • Loading branch information
nyalldawson committed Jul 23, 2021
1 parent e57193d commit c74f42c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/core/providers/qgsproviderregistry.cpp
Expand Up @@ -906,6 +906,10 @@ QList<QgsProviderSublayerDetails> QgsProviderRegistry::querySublayers( const QSt
QList<QgsProviderSublayerDetails> res;
for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
{
// if we should defer this uri for other providers, do so
if ( shouldDeferUriForOtherProviders( uri, it->first ) )
continue;

res.append( it->second->querySublayers( uri, flags, feedback ) );
if ( feedback && feedback->isCanceled() )
break;
Expand Down
27 changes: 23 additions & 4 deletions tests/src/python/test_qgsproviderregistry.py
Expand Up @@ -131,6 +131,29 @@ def testUnusableUriDetails(self):
self.assertIn('LAZ', details.warning)

def testSublayerDetails(self):
ept_provider_metadata = QgsProviderRegistry.instance().providerMetadata('ept')
ogr_provider_metadata = QgsProviderRegistry.instance().providerMetadata('ogr')

if ept_provider_metadata is not None:
# test querying a uri which should be blocklisted
self.assertFalse(QgsProviderRegistry.instance().querySublayers(unitTestDataPath() + '/point_clouds/ept/sunshine-coast/ept-build.json'))

if ept_provider_metadata is not None and ogr_provider_metadata is not None:
# test querying a uri which is technically capable of being opened by two providers, but which one provider is preferred
# in this case we are testing a ept.json file, which should ALWAYS be treated as a ept point cloud layer even though
# the OGR provider CAN technically open json files

# when we directly query ogr provider metadata it should report sublayers for the json file...
self.assertEqual([l.providerKey() for l in ogr_provider_metadata.querySublayers(
unitTestDataPath() + '/point_clouds/ept/sunshine-coast/ept.json', Qgis.SublayerQueryFlags(Qgis.SublayerQueryFlag.FastScan))], ['ogr'])

# ...and when we query ept provider metadata directly it should also report sublayers for ept.json files...
self.assertEqual([l.providerKey() for l in ept_provider_metadata.querySublayers(
unitTestDataPath() + '/point_clouds/ept/sunshine-coast/ept.json', Qgis.SublayerQueryFlags(Qgis.SublayerQueryFlag.FastScan))], ['ept'])

# ... but when we query the provider registry itself, it should ONLY report the ept provider sublayers
self.assertEqual([l.providerKey() for l in QgsProviderRegistry.instance().querySublayers(unitTestDataPath() + '/point_clouds/ept/sunshine-coast/ept.json', Qgis.SublayerQueryFlags(Qgis.SublayerQueryFlag.FastScan))], ['ept'])

provider1 = TestProviderMetadata('p1')
provider2 = TestProviderMetadata('p2')

Expand All @@ -142,10 +165,6 @@ def testSublayerDetails(self):
self.assertCountEqual([p.providerKey() for p in QgsProviderRegistry.instance().querySublayers('test_uri')],
['p1', 'p2'])

if QgsProviderRegistry.instance().providerMetadata('ept'):
# test querying a uri which should be blocklisted
self.assertFalse(QgsProviderRegistry.instance().querySublayers(unitTestDataPath() + '/point_clouds/ept/sunshine-coast/ept-build.json'))


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

0 comments on commit c74f42c

Please sign in to comment.