Skip to content

Commit 7031bc3

Browse files
committedMar 24, 2023
Show VTPK files in browser
Implement required methods in vtpk provider metadata so that VTPK files are shown in the browser panel as valid vector tile layer sources. Allows for easy addition of vtpk sources to projects, and easy fixing of broken vtpk layer paths
1 parent 5c813af commit 7031bc3

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed
 

‎src/core/vectortile/qgsvtpkvectortiledataprovider.cpp

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
#include "qgsvectortileloader.h"
2020
#include "qgsapplication.h"
2121
#include "qgslogger.h"
22+
#include "qgsprovidersublayerdetails.h"
23+
#include "qgsproviderutils.h"
2224

2325
#include <QIcon>
26+
#include <QFileInfo>
2427

2528
///@cond PRIVATE
2629

@@ -225,6 +228,13 @@ QgsVtpkVectorTileDataProviderMetadata::QgsVtpkVectorTileDataProviderMetadata()
225228
{
226229
}
227230

231+
QgsProviderMetadata::ProviderMetadataCapabilities QgsVtpkVectorTileDataProviderMetadata::capabilities() const
232+
{
233+
return ProviderMetadataCapability::LayerTypesForUri
234+
| ProviderMetadataCapability::PriorityForUri
235+
| ProviderMetadataCapability::QuerySublayers;
236+
}
237+
228238
QgsVtpkVectorTileDataProvider *QgsVtpkVectorTileDataProviderMetadata::createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
229239
{
230240
return new QgsVtpkVectorTileDataProvider( uri, options, flags );
@@ -240,13 +250,71 @@ QgsProviderMetadata::ProviderCapabilities QgsVtpkVectorTileDataProviderMetadata:
240250
return FileBasedUris;
241251
}
242252

253+
QList<QgsProviderSublayerDetails> QgsVtpkVectorTileDataProviderMetadata::querySublayers( const QString &uri, Qgis::SublayerQueryFlags, QgsFeedback * ) const
254+
{
255+
QString fileName;
256+
const QFileInfo fi( uri );
257+
if ( fi.isFile() )
258+
{
259+
fileName = uri;
260+
}
261+
else
262+
{
263+
const QVariantMap parts = decodeUri( uri );
264+
fileName = parts.value( QStringLiteral( "path" ) ).toString();
265+
}
266+
267+
if ( fileName.isEmpty() )
268+
return {};
269+
270+
if ( QFileInfo( fileName ).suffix().compare( QLatin1String( "vtpk" ), Qt::CaseInsensitive ) == 0 )
271+
{
272+
QVariantMap parts;
273+
parts.insert( QStringLiteral( "path" ), fileName );
274+
275+
QgsProviderSublayerDetails details;
276+
details.setUri( encodeUri( parts ) );
277+
details.setProviderKey( key() );
278+
details.setType( Qgis::LayerType::VectorTile );
279+
details.setName( QgsProviderUtils::suggestLayerNameFromFilePath( fileName ) );
280+
return {details};
281+
}
282+
else
283+
{
284+
return {};
285+
}
286+
}
287+
288+
int QgsVtpkVectorTileDataProviderMetadata::priorityForUri( const QString &uri ) const
289+
{
290+
if ( validLayerTypesForUri( uri ).contains( Qgis::LayerType::VectorTile ) )
291+
return 100;
292+
293+
return 0;
294+
}
295+
296+
QList<Qgis::LayerType> QgsVtpkVectorTileDataProviderMetadata::validLayerTypesForUri( const QString &uri ) const
297+
{
298+
const QFileInfo fi( uri );
299+
if ( fi.isFile() && fi.suffix().compare( QLatin1String( "vtpk" ), Qt::CaseInsensitive ) == 0 )
300+
{
301+
return { Qgis::LayerType::VectorTile };
302+
}
303+
304+
const QVariantMap parts = decodeUri( uri );
305+
if ( parts.value( QStringLiteral( "path" ) ).toString().endsWith( ".vtpk", Qt::CaseSensitivity::CaseInsensitive ) )
306+
return { Qgis::LayerType::VectorTile };
307+
308+
return {};
309+
}
310+
243311
QVariantMap QgsVtpkVectorTileDataProviderMetadata::decodeUri( const QString &uri ) const
244312
{
245313
QgsDataSourceUri dsUri;
246314
dsUri.setEncodedUri( uri );
247315

248316
QVariantMap uriComponents;
249-
uriComponents.insert( QStringLiteral( "type" ), dsUri.param( QStringLiteral( "type" ) ) );
317+
uriComponents.insert( QStringLiteral( "type" ), QStringLiteral( "vtpk" ) );
250318
uriComponents.insert( QStringLiteral( "path" ), dsUri.param( QStringLiteral( "url" ) ) );
251319

252320
return uriComponents;
@@ -255,7 +323,7 @@ QVariantMap QgsVtpkVectorTileDataProviderMetadata::decodeUri( const QString &uri
255323
QString QgsVtpkVectorTileDataProviderMetadata::encodeUri( const QVariantMap &parts ) const
256324
{
257325
QgsDataSourceUri dsUri;
258-
dsUri.setParam( QStringLiteral( "type" ), parts.value( QStringLiteral( "type" ) ).toString() );
326+
dsUri.setParam( QStringLiteral( "type" ), QStringLiteral( "vtpk" ) );
259327
dsUri.setParam( QStringLiteral( "url" ), parts.value( parts.contains( QStringLiteral( "path" ) ) ? QStringLiteral( "path" ) : QStringLiteral( "url" ) ).toString() );
260328
return dsUri.encodedUri();
261329
}

‎src/core/vectortile/qgsvtpkvectortiledataprovider.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,13 @@ class QgsVtpkVectorTileDataProviderMetadata : public QgsProviderMetadata
8585
Q_OBJECT
8686
public:
8787
QgsVtpkVectorTileDataProviderMetadata();
88+
QgsProviderMetadata::ProviderMetadataCapabilities capabilities() const override;
8889
QgsVtpkVectorTileDataProvider *createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ) override;
8990
QIcon icon() const override;
9091
ProviderCapabilities providerCapabilities() const override;
92+
QList< QgsProviderSublayerDetails > querySublayers( const QString &uri, Qgis::SublayerQueryFlags flags = Qgis::SublayerQueryFlags(), QgsFeedback *feedback = nullptr ) const override;
93+
int priorityForUri( const QString &uri ) const override;
94+
QList< Qgis::LayerType > validLayerTypesForUri( const QString &uri ) const override;
9195
QVariantMap decodeUri( const QString &uri ) const override;
9296
QString encodeUri( const QVariantMap &parts ) const override;
9397
QString absoluteToRelativeUri( const QString &uri, const QgsReadWriteContext &context ) const override;

‎tests/src/core/testqgsvectortilelayer.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "qgsmarkersymbollayer.h"
3535
#include "qgsprovidermetadata.h"
3636
#include "qgsproviderregistry.h"
37+
#include "qgsprovidersublayerdetails.h"
3738

3839
/**
3940
* \ingroup UnitTests
@@ -67,6 +68,7 @@ class TestQgsVectorTileLayer : public QgsTest
6768
void test_relativePathsXyz();
6869
void test_absoluteRelativeUriXyz();
6970

71+
void testVtpkProviderMetadata();
7072
void test_relativePathsVtpk();
7173
void test_absoluteRelativeUriVtpk();
7274

@@ -315,6 +317,43 @@ void TestQgsVectorTileLayer::test_absoluteRelativeUriXyz()
315317
QCOMPARE( vectorTileMetadata->relativeToAbsoluteUri( relativeUri, context ), absoluteUri );
316318
}
317319

320+
void TestQgsVectorTileLayer::testVtpkProviderMetadata()
321+
{
322+
QgsProviderMetadata *vectorTileMetadata = QgsProviderRegistry::instance()->providerMetadata( "vtpkvectortiles" );
323+
QVERIFY( vectorTileMetadata );
324+
325+
// not vtpk uris
326+
QCOMPARE( vectorTileMetadata->priorityForUri( QString() ), 0 );
327+
QCOMPARE( vectorTileMetadata->validLayerTypesForUri( QString() ), {} );
328+
329+
QCOMPARE( vectorTileMetadata->priorityForUri( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/points.shp" ) ), 0 );
330+
QVERIFY( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/points.shp" ) ).isEmpty() );
331+
QVERIFY( vectorTileMetadata->querySublayers( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/points.shp" ) ).isEmpty() );
332+
333+
QCOMPARE( vectorTileMetadata->priorityForUri( QStringLiteral( "type=vtpk&url=%1/points.shp" ).arg( TEST_DATA_DIR ) ), 0 );
334+
QVERIFY( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( "type=vtpk&url=%1/points.shp" ).arg( TEST_DATA_DIR ) ).isEmpty() );
335+
QVERIFY( vectorTileMetadata->querySublayers( QStringLiteral( "type=vtpk&url=%1/points.shp" ).arg( TEST_DATA_DIR ) ).isEmpty() );
336+
337+
// vtpk uris
338+
QCOMPARE( vectorTileMetadata->priorityForUri( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/testvtpk.vtpk" ) ), 100 );
339+
QCOMPARE( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/testvtpk.vtpk" ) ), {Qgis::LayerType::VectorTile} );
340+
QList< QgsProviderSublayerDetails > sublayers = vectorTileMetadata->querySublayers( QStringLiteral( TEST_DATA_DIR ) + QStringLiteral( "/testvtpk.vtpk" ) );
341+
QCOMPARE( sublayers.size(), 1 );
342+
QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "vtpkvectortiles" ) );
343+
QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "testvtpk" ) );
344+
QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) );
345+
QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile );
346+
347+
QCOMPARE( vectorTileMetadata->priorityForUri( QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) ), 100 );
348+
QCOMPARE( vectorTileMetadata->validLayerTypesForUri( QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) ), {Qgis::LayerType::VectorTile} );
349+
sublayers = vectorTileMetadata->querySublayers( QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) );
350+
QCOMPARE( sublayers.size(), 1 );
351+
QCOMPARE( sublayers.at( 0 ).providerKey(), QStringLiteral( "vtpkvectortiles" ) );
352+
QCOMPARE( sublayers.at( 0 ).name(), QStringLiteral( "testvtpk" ) );
353+
QCOMPARE( sublayers.at( 0 ).uri(), QStringLiteral( "type=vtpk&url=%1/testvtpk.vtpk" ).arg( TEST_DATA_DIR ) );
354+
QCOMPARE( sublayers.at( 0 ).type(), Qgis::LayerType::VectorTile );
355+
}
356+
318357
void TestQgsVectorTileLayer::test_relativePathsVtpk()
319358
{
320359
QgsReadWriteContext contextRel;

0 commit comments

Comments
 (0)
Please sign in to comment.