Skip to content

Commit

Permalink
After loading an ArcGIS Vector Tile Service layer, automatically load
Browse files Browse the repository at this point in the history
and set the default style and labels for the layer

Also populate the layer metadata with the available content from the
service definition (e.g. layer attribution)
  • Loading branch information
nyalldawson committed Sep 8, 2020
1 parent 9114e91 commit 6901d6f
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 14 deletions.
2 changes: 1 addition & 1 deletion python/core/auto_generated/qgsmaplayer.sip.in
Expand Up @@ -742,7 +742,7 @@ record in the users style table in their personal qgis.db)
.. versionadded:: 3.0
%End

QString loadDefaultMetadata( bool &resultFlag );
virtual QString loadDefaultMetadata( bool &resultFlag );
%Docstring
Retrieve the default metadata for this layer if one
exists (either as a .qmd file on disk or as a
Expand Down
16 changes: 12 additions & 4 deletions python/core/auto_generated/vectortile/qgsvectortilelayer.sip.in
Expand Up @@ -83,18 +83,26 @@ Constructs a new vector tile layer

virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) /Factory/;


virtual bool readXml( const QDomNode &layerNode, QgsReadWriteContext &context );


virtual bool writeXml( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const;

virtual bool readSymbology( const QDomNode &node, QString &errorMessage,
QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories );

virtual bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context,
StyleCategories categories = AllStyleCategories ) const;
virtual bool readSymbology( const QDomNode &node, QString &errorMessage,
QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories );

virtual bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context,
StyleCategories categories = AllStyleCategories ) const;

virtual void setTransformContext( const QgsCoordinateTransformContext &transformContext );

virtual QString loadDefaultStyle( bool &resultFlag /Out/ );

virtual QString loadDefaultMetadata( bool &resultFlag /Out/ );


virtual QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const ${SIP_FINAL};

virtual QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const ${SIP_FINAL};
Expand Down
10 changes: 10 additions & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -2057,6 +2057,9 @@ void QgisApp::handleDropUriList( const QgsMimeDataUtils::UriList &lst )
else if ( u.layerType == QLatin1String( "vector-tile" ) )
{
QgsVectorTileLayer *layer = new QgsVectorTileLayer( uri, u.name );
bool ok = false;
layer->loadDefaultStyle( ok );
layer->loadDefaultMetadata( ok );
addMapLayer( layer );
}
else if ( u.layerType == QLatin1String( "plugin" ) )
Expand Down Expand Up @@ -5653,6 +5656,13 @@ QgsVectorTileLayer *QgisApp::addVectorTileLayerPrivate( const QString &url, cons
// since the layer is bad, stomp on it
return nullptr;
}
bool ok = false;
QString error = layer->loadDefaultStyle( ok );
if ( !ok )
visibleMessageBar()->pushMessage( tr( "Error loading style" ), error, Qgis::Warning, messageTimeout() );
error = layer->loadDefaultMetadata( ok );
if ( !ok )
visibleMessageBar()->pushMessage( tr( "Error loading layer metadata" ), error, Qgis::Warning, messageTimeout() );

QgsProject::instance()->addMapLayer( layer.get() );
activateDeactivateLayerRelatedActions( activeLayer() );
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsmaplayer.h
Expand Up @@ -739,7 +739,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
* \returns a QString with any status messages
* \since QGIS 3.0
*/
QString loadDefaultMetadata( bool &resultFlag );
virtual QString loadDefaultMetadata( bool &resultFlag );

/**
* Retrieve a named metadata for this layer from a sqlite database.
Expand Down
88 changes: 88 additions & 0 deletions src/core/vectortile/qgsvectortilelayer.cpp
Expand Up @@ -292,6 +292,94 @@ void QgsVectorTileLayer::setTransformContext( const QgsCoordinateTransformContex
Q_UNUSED( transformContext )
}

QString QgsVectorTileLayer::loadDefaultStyle( bool &resultFlag )
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( mDataSource );
if ( mSourceType == QStringLiteral( "xyz" ) && dsUri.param( QStringLiteral( "serviceType" ) ) == QLatin1String( "arcgis" ) )
{
QNetworkRequest request = QNetworkRequest( QUrl( mArcgisLayerConfiguration.value( QStringLiteral( "serviceUri" ) ).toString()
+ '/' + mArcgisLayerConfiguration.value( QStringLiteral( "defaultStyles" ) ).toString() ) );

QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) );

QgsBlockingNetworkRequest networkRequest;
switch ( networkRequest.get( request ) )
{
case QgsBlockingNetworkRequest::NoError:
break;

case QgsBlockingNetworkRequest::NetworkError:
case QgsBlockingNetworkRequest::TimeoutError:
case QgsBlockingNetworkRequest::ServerExceptionError:
resultFlag = false;
return QObject::tr( "Error retrieving default style" );
}

const QgsNetworkReplyContent content = networkRequest.reply();
const QByteArray raw = content.content();

QgsMapBoxGlStyleConversionContext context;
// convert automatically from pixel sizes to millimeters, because pixel sizes
// are a VERY edge case in QGIS and don't play nice with hidpi map renders or print layouts
context.setTargetUnit( QgsUnitTypes::RenderMillimeters );
//assume source uses 96 dpi
context.setPixelSizeConversionFactor( 25.4 / 96.0 );

QgsMapBoxGlStyleConverter converter;
if ( converter.convert( raw, &context ) != QgsMapBoxGlStyleConverter::Success )
{
resultFlag = false;
return converter.errorMessage();
}

setRenderer( converter.renderer() );
setLabeling( converter.labeling() );
resultFlag = true;
return QString();
}
else
{
QgsMapLayer::loadDefaultStyle( resultFlag );
resultFlag = true;
return QString();
}
}

QString QgsVectorTileLayer::loadDefaultMetadata( bool &resultFlag )
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( mDataSource );
if ( mSourceType == QStringLiteral( "xyz" ) && dsUri.param( QStringLiteral( "serviceType" ) ) == QLatin1String( "arcgis" ) )
{
// populate default metadata
QgsLayerMetadata metadata;
metadata.setIdentifier( mArcgisLayerConfiguration.value( QStringLiteral( "serviceUri" ) ).toString() );
const QString parentIdentifier = mArcgisLayerConfiguration.value( QStringLiteral( "serviceItemId" ) ).toString();
if ( !parentIdentifier.isEmpty() )
{
metadata.setParentIdentifier( parentIdentifier );
}
metadata.setType( QStringLiteral( "dataset" ) );
metadata.setTitle( mArcgisLayerConfiguration.value( QStringLiteral( "name" ) ).toString() );
QString copyright = mArcgisLayerConfiguration.value( QStringLiteral( "copyrightText" ) ).toString();
if ( !copyright.isEmpty() )
metadata.setRights( QStringList() << copyright );
metadata.addLink( QgsAbstractMetadataBase::Link( tr( "Source" ), QStringLiteral( "WWW:LINK" ), mArcgisLayerConfiguration.value( QStringLiteral( "serviceUri" ) ).toString() ) );

setMetadata( metadata );

resultFlag = true;
return QString();
}
else
{
QgsMapLayer::loadDefaultMetadata( resultFlag );
resultFlag = true;
return QString();
}
}

QString QgsVectorTileLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
{
QgsDataSourceUri dsUri;
Expand Down
18 changes: 10 additions & 8 deletions src/core/vectortile/qgsvectortilelayer.h
Expand Up @@ -93,19 +93,21 @@ class CORE_EXPORT QgsVectorTileLayer : public QgsMapLayer

QgsVectorTileLayer *clone() const override SIP_FACTORY;

virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;
QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;

virtual bool readXml( const QDomNode &layerNode, QgsReadWriteContext &context ) override;
bool readXml( const QDomNode &layerNode, QgsReadWriteContext &context ) override;

virtual bool writeXml( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
bool writeXml( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const override;

virtual bool readSymbology( const QDomNode &node, QString &errorMessage,
QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories ) override;
bool readSymbology( const QDomNode &node, QString &errorMessage,
QgsReadWriteContext &context, StyleCategories categories = AllStyleCategories ) override;

virtual bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context,
StyleCategories categories = AllStyleCategories ) const override;
bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context,
StyleCategories categories = AllStyleCategories ) const override;

virtual void setTransformContext( const QgsCoordinateTransformContext &transformContext ) override;
void setTransformContext( const QgsCoordinateTransformContext &transformContext ) override;
QString loadDefaultStyle( bool &resultFlag SIP_OUT ) override;
QString loadDefaultMetadata( bool &resultFlag SIP_OUT ) override;

QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const FINAL;
QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const FINAL;
Expand Down

0 comments on commit 6901d6f

Please sign in to comment.