Split vector tile classes into separate files

This commit is contained in:
Nyall Dawson 2023-03-16 10:18:25 +10:00
parent 50f3420bce
commit aadfbab40f
18 changed files with 874 additions and 608 deletions

View File

@ -9,8 +9,6 @@
class QgsVectorTileLayer : QgsMapLayer
{
%Docstring(signature="appended")
@ -281,8 +279,6 @@ Emitted whenever the selected features in the layer are changed.
};
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -890,11 +890,14 @@ set(QGIS_CORE_SRCS
vector/qgsvectorlayerundopassthroughcommand.cpp
vector/qgsvectorlayerutils.cpp
vectortile/qgsarcgisvectortileservicedataprovider.cpp
vectortile/qgsmapboxglstyleconverter.cpp
vectortile/qgsmbtilesvectortiledataprovider.cpp
vectortile/qgsvectortilebasiclabeling.cpp
vectortile/qgsvectortilebasicrenderer.cpp
vectortile/qgsvectortileconnection.cpp
vectortile/qgsvectortiledataitems.cpp
vectortile/qgsvectortiledataprovider.cpp
vectortile/qgsvectortilelabeling.cpp
vectortile/qgsvectortilelayer.cpp
vectortile/qgsvectortilelayerrenderer.cpp
@ -907,6 +910,8 @@ set(QGIS_CORE_SRCS
vectortile/qgsvectortileutils.cpp
vectortile/qgsvectortilewriter.cpp
vectortile/qgsvtpktiles.cpp
vectortile/qgsvtpkvectortiledataprovider.cpp
vectortile/qgsxyzvectortiledataprovider.cpp
${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp
@ -1899,11 +1904,14 @@ set(QGIS_CORE_HDRS
vector/qgsvectorlayerundopassthroughcommand.h
vector/qgsvectorlayerutils.h
vectortile/qgsarcgisvectortileservicedataprovider.h
vectortile/qgsmapboxglstyleconverter.h
vectortile/qgsmbtilesvectortiledataprovider.h
vectortile/qgsvectortilebasiclabeling.h
vectortile/qgsvectortilebasicrenderer.h
vectortile/qgsvectortileconnection.h
vectortile/qgsvectortiledataitems.h
vectortile/qgsvectortiledataprovider.h
vectortile/qgsvectortilelabeling.h
vectortile/qgsvectortilelayer.h
vectortile/qgsvectortilelayerrenderer.h
@ -1917,6 +1925,8 @@ set(QGIS_CORE_HDRS
vectortile/qgsvectortileutils.h
vectortile/qgsvectortilewriter.h
vectortile/qgsvtpktiles.h
vectortile/qgsvtpkvectortiledataprovider.h
vectortile/qgsxyzvectortiledataprovider.h
)
set(QGIS_CORE_PRIVATE_HDRS

View File

@ -0,0 +1,53 @@
/***************************************************************************
qgsarcgisvectortileservicedataprovider.cpp
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsarcgisvectortileservicedataprovider.h"
#include "qgsthreadingutils.h"
///@cond PRIVATE
QgsArcGisVectorTileServiceDataProvider::QgsArcGisVectorTileServiceDataProvider( const QString &uri, const QString &sourcePath, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsXyzVectorTileDataProvider( uri, providerOptions, flags )
, mSourcePath( sourcePath )
{
}
QgsVectorTileDataProvider *QgsArcGisVectorTileServiceDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsArcGisVectorTileServiceDataProvider( dataSourceUri(), mSourcePath, options, mReadFlags );
}
QString QgsArcGisVectorTileServiceDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return mSourcePath;
}
bool QgsArcGisVectorTileServiceDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
///@endcond

View File

@ -0,0 +1,47 @@
/***************************************************************************
qgsarcgisvectortileservicedataprovider.h
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSARCGISVECTORTILESERVICEDATAPROVIDER_H
#define QGSARCGISVECTORTILESERVICEDATAPROVIDER_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsxyzvectortiledataprovider.h"
#define SIP_NO_FILE
///@cond PRIVATE
class CORE_EXPORT QgsArcGisVectorTileServiceDataProvider : public QgsXyzVectorTileDataProvider
{
Q_OBJECT
public:
QgsArcGisVectorTileServiceDataProvider( const QString &uri,
const QString &sourcePath,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
private:
QString mSourcePath;
};
///@endcond
#endif // QGSARCGISVECTORTILESERVICEDATAPROVIDER_H

View File

@ -0,0 +1,127 @@
/***************************************************************************
qgsmbtilesvectortiledataprovider.cpp
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsmbtilesvectortiledataprovider.h"
#include "qgsthreadingutils.h"
#include "qgsmbtiles.h"
#include "qgstiles.h"
#include "qgsvectortileloader.h"
#include "qgsziputils.h"
#include "qgslogger.h"
///@cond PRIVATE
QgsMbTilesVectorTileDataProvider::QgsMbTilesVectorTileDataProvider( const QString &uri, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsVectorTileDataProvider( uri, providerOptions, flags )
{
}
QgsVectorTileDataProvider *QgsMbTilesVectorTileDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsMbTilesVectorTileDataProvider( dataSourceUri(), options, mReadFlags );
}
QString QgsMbTilesVectorTileDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
return dsUri.param( QStringLiteral( "url" ) );
}
bool QgsMbTilesVectorTileDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
QgsCoordinateReferenceSystem QgsMbTilesVectorTileDataProvider::crs() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) );
}
QByteArray QgsMbTilesVectorTileDataProvider::readTile( const QgsTileMatrix &, const QgsTileXYZ &id, QgsFeedback *feedback ) const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsMbTiles mbReader( dsUri.param( QStringLiteral( "url" ) ) );
mbReader.open();
return loadFromMBTiles( mbReader, id, feedback );
}
QList<QgsVectorTileRawData> QgsMbTilesVectorTileDataProvider::readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback ) const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsMbTiles mbReader( dsUri.param( QStringLiteral( "url" ) ) );
mbReader.open();
QList<QgsVectorTileRawData> rawTiles;
rawTiles.reserve( tiles.size() );
for ( QgsTileXYZ id : std::as_const( tiles ) )
{
if ( feedback && feedback->isCanceled() )
break;
const QByteArray rawData = loadFromMBTiles( mbReader, id, feedback );
if ( !rawData.isEmpty() )
{
rawTiles.append( QgsVectorTileRawData( id, rawData ) );
}
}
return rawTiles;
}
QByteArray QgsMbTilesVectorTileDataProvider::loadFromMBTiles( QgsMbTiles &mbTileReader, const QgsTileXYZ &id, QgsFeedback *feedback )
{
// MBTiles uses TMS specs with Y starting at the bottom while XYZ uses Y starting at the top
const int rowTMS = static_cast<int>( pow( 2, id.zoomLevel() ) - id.row() - 1 );
QByteArray gzippedTileData = mbTileReader.tileData( id.zoomLevel(), id.column(), rowTMS );
if ( gzippedTileData.isEmpty() )
{
return QByteArray();
}
if ( feedback && feedback->isCanceled() )
return QByteArray();
QByteArray data;
if ( !QgsZipUtils::decodeGzip( gzippedTileData, data ) )
{
QgsDebugMsg( QStringLiteral( "Failed to decompress tile " ) + id.toString() );
return QByteArray();
}
QgsDebugMsgLevel( QStringLiteral( "Tile blob size %1 -> uncompressed size %2" ).arg( gzippedTileData.size() ).arg( data.size() ), 2 );
return data;
}
///@endcond

View File

@ -0,0 +1,54 @@
/***************************************************************************
qgsmbtilesvectortiledataprovider.h
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSMBTILESVECTORTILEDATAPROVIDER_H
#define QGSMBTILESVECTORTILEDATAPROVIDER_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsvectortiledataprovider.h"
class QgsMbTiles;
#define SIP_NO_FILE
///@cond PRIVATE
class CORE_EXPORT QgsMbTilesVectorTileDataProvider : public QgsVectorTileDataProvider
{
Q_OBJECT
public:
QgsMbTilesVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
QgsCoordinateReferenceSystem crs() const override;
QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const override;
QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const override;
private:
//! Returns raw tile data for a single tile loaded from MBTiles file
static QByteArray loadFromMBTiles( QgsMbTiles &mbTileReader, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr );
};
///@endcond
#endif // QGSMBTILESVECTORTILEDATAPROVIDER_H

View File

@ -0,0 +1,75 @@
/***************************************************************************
qgsvectortiledataprovider.cpp
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsvectortiledataprovider.h"
#include "qgsthreadingutils.h"
#include <QNetworkRequest>
QgsVectorTileDataProvider::QgsVectorTileDataProvider(
const QString &uri,
const ProviderOptions &options,
QgsDataProvider::ReadFlags flags )
: QgsDataProvider( uri, options, flags )
{}
QString QgsVectorTileDataProvider::name() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QStringLiteral( "vectortile" );
}
QString QgsVectorTileDataProvider::description() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QString();
}
QgsRectangle QgsVectorTileDataProvider::extent() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsRectangle();
}
bool QgsVectorTileDataProvider::renderInPreview( const PreviewContext &context )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
// Vector tiles by design are very CPU light to render, so we are much more permissive here compared
// with other layer types. (Generally if a vector tile layer has taken more than a few milliseconds to render it's
// a result of network requests, and the tile manager class handles these gracefully for us)
return context.lastRenderingTimeMs <= 1000;
}
bool QgsVectorTileDataProvider::supportsAsync() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return false;
}
QNetworkRequest QgsVectorTileDataProvider::tileRequest( const QgsTileMatrix &, const QgsTileXYZ &, Qgis::RendererUsage ) const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QNetworkRequest();
}
///@endcond

View File

@ -0,0 +1,89 @@
/***************************************************************************
qgsvectortiledataprovider.h
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSVECTORTILEDATAPROVIDER_H
#define QGSVECTORTILEDATAPROVIDER_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsdataprovider.h"
class QgsTileMatrix;
class QgsTileXYZ;
class QgsVectorTileRawData;
#define SIP_NO_FILE
/**
* Base class for vector tile layer data providers.
*
* \note Not available in Python bindings
*
* \since QGIS 3.22
*/
class CORE_EXPORT QgsVectorTileDataProvider : public QgsDataProvider
{
Q_OBJECT
public:
/**
* Constructor for QgsVectorTileDataProvider, with the specified \a uri.
*/
QgsVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QString name() const override;
QString description() const override;
QgsRectangle extent() const override;
bool renderInPreview( const QgsDataProvider::PreviewContext &context ) override;
/**
* Returns the source path for the data.
*/
virtual QString sourcePath() const = 0;
/**
* Returns a clone of the data provider.
*/
virtual QgsVectorTileDataProvider *clone() const = 0 SIP_FACTORY;
/**
* Returns TRUE if the provider supports async tile reading.
*
* The default implementation returns FALSE.
*/
virtual bool supportsAsync() const;
/**
* Returns raw tile data for a single tile.
*/
virtual QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const = 0;
/**
* Returns raw tile data for a range of tiles.
*/
virtual QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &tileMatrix, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const = 0;
/**
* Returns a network request for a tile.
*
* The default implementation returns an invalid request.
*/
virtual QNetworkRequest tileRequest( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, Qgis::RendererUsage usage ) const;
};
#endif // QGSVECTORTILEDATAPROVIDER_H

View File

@ -22,10 +22,8 @@
#include "qgsvectortilebasiclabeling.h"
#include "qgsvectortilebasicrenderer.h"
#include "qgsvectortilelabeling.h"
#include "qgsvectortileloader.h"
#include "qgsvectortileutils.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsdatasourceuri.h"
#include "qgslayermetadataformatter.h"
#include "qgsblockingnetworkrequest.h"
@ -39,10 +37,11 @@
#include "qgsvectortilemvtdecoder.h"
#include "qgsthreadingutils.h"
#include "qgsproviderregistry.h"
#include "qgsziputils.h"
#include "qgsapplication.h"
#include "qgsmessagelog.h"
#include "qgsauthmanager.h"
#include "qgsvectortiledataprovider.h"
#include "qgsmbtilesvectortiledataprovider.h"
#include "qgsarcgisvectortileservicedataprovider.h"
#include "qgsxyzvectortiledataprovider.h"
#include "qgsvtpkvectortiledataprovider.h"
#include <QUrl>
#include <QUrlQuery>
@ -1317,416 +1316,3 @@ void QgsVectorTileLayer::removeSelection()
}
//
// QgsVectorTileDataProvider
//
///@cond PRIVATE
QgsVectorTileDataProvider::QgsVectorTileDataProvider( const QString &uri,
const ProviderOptions &options,
QgsDataProvider::ReadFlags flags )
: QgsDataProvider( uri, options, flags )
{}
QString QgsVectorTileDataProvider::name() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QStringLiteral( "vectortile" );
}
QString QgsVectorTileDataProvider::description() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QString();
}
QgsRectangle QgsVectorTileDataProvider::extent() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsRectangle();
}
bool QgsVectorTileDataProvider::renderInPreview( const PreviewContext &context )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
// Vector tiles by design are very CPU light to render, so we are much more permissive here compared
// with other layer types. (Generally if a vector tile layer has taken more than a few milliseconds to render it's
// a result of network requests, and the tile manager class handles these gracefully for us)
return context.lastRenderingTimeMs <= 1000;
}
bool QgsVectorTileDataProvider::supportsAsync() const
{
return false;
}
QNetworkRequest QgsVectorTileDataProvider::tileRequest( const QgsTileMatrix &, const QgsTileXYZ &, Qgis::RendererUsage ) const
{
return QNetworkRequest();
}
//
// QgsXyzVectorTileDataProvider
//
QgsXyzVectorTileDataProvider::QgsXyzVectorTileDataProvider( const QString &uri, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsVectorTileDataProvider( uri, providerOptions, flags )
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( uri );
mAuthCfg = dsUri.authConfigId();
mHeaders = dsUri.httpHeaders();
}
QgsVectorTileDataProvider *QgsXyzVectorTileDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsXyzVectorTileDataProvider( dataSourceUri(), options, mReadFlags );
}
QString QgsXyzVectorTileDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
return dsUri.param( QStringLiteral( "url" ) );
}
bool QgsXyzVectorTileDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
QgsCoordinateReferenceSystem QgsXyzVectorTileDataProvider::crs() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) );
}
bool QgsXyzVectorTileDataProvider::supportsAsync() const
{
return true;
}
QByteArray QgsXyzVectorTileDataProvider::readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback ) const
{
return loadFromNetwork( id, tileMatrix, sourcePath(), mAuthCfg, mHeaders, feedback );
}
QList<QgsVectorTileRawData> QgsXyzVectorTileDataProvider::readTiles( const QgsTileMatrix &tileMatrix, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback ) const
{
QList<QgsVectorTileRawData> rawTiles;
rawTiles.reserve( tiles.size() );
const QString source = sourcePath();
for ( QgsTileXYZ id : std::as_const( tiles ) )
{
if ( feedback && feedback->isCanceled() )
break;
const QByteArray rawData = loadFromNetwork( id, tileMatrix, source, mAuthCfg, mHeaders, feedback );
if ( !rawData.isEmpty() )
{
rawTiles.append( QgsVectorTileRawData( id, rawData ) );
}
}
return rawTiles;
}
QNetworkRequest QgsXyzVectorTileDataProvider::tileRequest( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, Qgis::RendererUsage usage ) const
{
QString urlTemplate = sourcePath();
if ( urlTemplate.contains( QLatin1String( "{usage}" ) ) )
{
switch ( usage )
{
case Qgis::RendererUsage::View:
urlTemplate.replace( QLatin1String( "{usage}" ), QLatin1String( "view" ) );
break;
case Qgis::RendererUsage::Export:
urlTemplate.replace( QLatin1String( "{usage}" ), QLatin1String( "export" ) );
break;
case Qgis::RendererUsage::Unknown:
urlTemplate.replace( QLatin1String( "{usage}" ), QString() );
break;
}
}
const QString url = QgsVectorTileUtils::formatXYZUrlTemplate( urlTemplate, id, tileMatrix );
QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsXyzVectorTileDataProvider" ) );
QgsSetRequestInitiatorId( request, id.toString() );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ), id.column() );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ), id.row() );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), id.zoomLevel() );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mHeaders.updateNetworkRequest( request );
if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg ) )
{
QgsMessageLog::logMessage( tr( "network request update failed for authentication config" ), tr( "Network" ) );
}
return request;
}
QByteArray QgsXyzVectorTileDataProvider::loadFromNetwork( const QgsTileXYZ &id, const QgsTileMatrix &tileMatrix, const QString &requestUrl, const QString &authid, const QgsHttpHeaders &headers, QgsFeedback *feedback )
{
QString url = QgsVectorTileUtils::formatXYZUrlTemplate( requestUrl, id, tileMatrix );
QNetworkRequest nr;
nr.setUrl( QUrl( url ) );
headers.updateNetworkRequest( nr );
QgsBlockingNetworkRequest req;
req.setAuthCfg( authid );
QgsDebugMsgLevel( QStringLiteral( "Blocking request: " ) + url, 2 );
QgsBlockingNetworkRequest::ErrorCode errCode = req.get( nr, false, feedback );
if ( errCode != QgsBlockingNetworkRequest::NoError )
{
QgsDebugMsg( QStringLiteral( "Request failed: " ) + url );
return QByteArray();
}
QgsNetworkReplyContent reply = req.reply();
QgsDebugMsgLevel( QStringLiteral( "Request successful, content size %1" ).arg( reply.content().size() ), 2 );
return reply.content();
}
//
// QgsMbTilesVectorTileDataProvider
//
QgsMbTilesVectorTileDataProvider::QgsMbTilesVectorTileDataProvider( const QString &uri, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsVectorTileDataProvider( uri, providerOptions, flags )
{
}
QgsVectorTileDataProvider *QgsMbTilesVectorTileDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsMbTilesVectorTileDataProvider( dataSourceUri(), options, mReadFlags );
}
QString QgsMbTilesVectorTileDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
return dsUri.param( QStringLiteral( "url" ) );
}
bool QgsMbTilesVectorTileDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
QgsCoordinateReferenceSystem QgsMbTilesVectorTileDataProvider::crs() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) );
}
QByteArray QgsMbTilesVectorTileDataProvider::readTile( const QgsTileMatrix &, const QgsTileXYZ &id, QgsFeedback *feedback ) const
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsMbTiles mbReader( dsUri.param( QStringLiteral( "url" ) ) );
mbReader.open();
return loadFromMBTiles( mbReader, id, feedback );
}
QList<QgsVectorTileRawData> QgsMbTilesVectorTileDataProvider::readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback ) const
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsMbTiles mbReader( dsUri.param( QStringLiteral( "url" ) ) );
mbReader.open();
QList<QgsVectorTileRawData> rawTiles;
rawTiles.reserve( tiles.size() );
for ( QgsTileXYZ id : std::as_const( tiles ) )
{
if ( feedback && feedback->isCanceled() )
break;
const QByteArray rawData = loadFromMBTiles( mbReader, id, feedback );
if ( !rawData.isEmpty() )
{
rawTiles.append( QgsVectorTileRawData( id, rawData ) );
}
}
return rawTiles;
}
QByteArray QgsMbTilesVectorTileDataProvider::loadFromMBTiles( QgsMbTiles &mbTileReader, const QgsTileXYZ &id, QgsFeedback *feedback )
{
// MBTiles uses TMS specs with Y starting at the bottom while XYZ uses Y starting at the top
const int rowTMS = static_cast<int>( pow( 2, id.zoomLevel() ) - id.row() - 1 );
QByteArray gzippedTileData = mbTileReader.tileData( id.zoomLevel(), id.column(), rowTMS );
if ( gzippedTileData.isEmpty() )
{
return QByteArray();
}
if ( feedback && feedback->isCanceled() )
return QByteArray();
QByteArray data;
if ( !QgsZipUtils::decodeGzip( gzippedTileData, data ) )
{
QgsDebugMsg( QStringLiteral( "Failed to decompress tile " ) + id.toString() );
return QByteArray();
}
QgsDebugMsgLevel( QStringLiteral( "Tile blob size %1 -> uncompressed size %2" ).arg( gzippedTileData.size() ).arg( data.size() ), 2 );
return data;
}
//
// QgsVtpkVectorTileDataProvider
//
QgsVtpkVectorTileDataProvider::QgsVtpkVectorTileDataProvider( const QString &uri, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsVectorTileDataProvider( uri, providerOptions, flags )
{
}
QgsVectorTileDataProvider *QgsVtpkVectorTileDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsVtpkVectorTileDataProvider( dataSourceUri(), options, mReadFlags );
}
QString QgsVtpkVectorTileDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
return dsUri.param( QStringLiteral( "url" ) );
}
bool QgsVtpkVectorTileDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
QgsCoordinateReferenceSystem QgsVtpkVectorTileDataProvider::crs() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) );
}
QByteArray QgsVtpkVectorTileDataProvider::readTile( const QgsTileMatrix &, const QgsTileXYZ &id, QgsFeedback *feedback ) const
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsVtpkTiles reader( dsUri.param( QStringLiteral( "url" ) ) );
reader.open();
return loadFromVtpk( reader, id, feedback );
}
QList<QgsVectorTileRawData> QgsVtpkVectorTileDataProvider::readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback ) const
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsVtpkTiles reader( dsUri.param( QStringLiteral( "url" ) ) );
reader.open();
QList<QgsVectorTileRawData> rawTiles;
rawTiles.reserve( tiles.size() );
for ( QgsTileXYZ id : std::as_const( tiles ) )
{
if ( feedback && feedback->isCanceled() )
break;
const QByteArray rawData = loadFromVtpk( reader, id, feedback );
if ( !rawData.isEmpty() )
{
rawTiles.append( QgsVectorTileRawData( id, rawData ) );
}
}
return rawTiles;
}
QByteArray QgsVtpkVectorTileDataProvider::loadFromVtpk( QgsVtpkTiles &vtpkTileReader, const QgsTileXYZ &id, QgsFeedback * )
{
const QByteArray tileData = vtpkTileReader.tileData( id.zoomLevel(), id.column(), id.row() );
if ( tileData.isEmpty() )
{
return QByteArray();
}
return tileData;
}
//
// QgsArcGisVectorTileServiceDataProvider
//
QgsArcGisVectorTileServiceDataProvider::QgsArcGisVectorTileServiceDataProvider( const QString &uri, const QString &sourcePath, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsXyzVectorTileDataProvider( uri, providerOptions, flags )
, mSourcePath( sourcePath )
{
}
QgsVectorTileDataProvider *QgsArcGisVectorTileServiceDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsArcGisVectorTileServiceDataProvider( dataSourceUri(), mSourcePath, options, mReadFlags );
}
QString QgsArcGisVectorTileServiceDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return mSourcePath;
}
bool QgsArcGisVectorTileServiceDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
///@endcond

View File

@ -18,21 +18,15 @@
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsmaplayer.h"
#include "qgsvectortilematrixset.h"
#include "qgsfeatureid.h"
class QgsVectorTileLabeling;
class QgsVectorTileRenderer;
class QgsVectorTileRawData;
class QgsVectorTileDataProvider;
class QgsTileXYZ;
class QgsVectorTileLabeling;
class QgsFeature;
class QgsGeometry;
class QgsSelectionContext;
class QgsMbTiles;
/**
* \ingroup core
@ -317,160 +311,6 @@ class CORE_EXPORT QgsVectorTileLayer : public QgsMapLayer
bool loadDefaultStyleAndSubLayersPrivate( QString &error, QStringList &warnings, QList< QgsMapLayer * > *subLayers );
};
#ifndef SIP_RUN
///@cond PRIVATE
/**
* A minimal data provider for vector tile layers.
*
* \since QGIS 3.22
*/
class QgsVectorTileDataProvider : public QgsDataProvider
{
Q_OBJECT
public:
QgsVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QString name() const override;
QString description() const override;
QgsRectangle extent() const override;
bool renderInPreview( const QgsDataProvider::PreviewContext &context ) override;
//! Renders the source path for the data
virtual QString sourcePath() const = 0;
//! Returns a clone of the data provider
virtual QgsVectorTileDataProvider *clone() const = 0 SIP_FACTORY;
/**
* Returns TRUE if the provider supports async tile reading.
*
* The default implementation returns FALSE.
*/
virtual bool supportsAsync() const;
//! Returns raw tile data for a single tile
virtual QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const = 0;
//! Returns raw tile data for a range of tiles
virtual QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const = 0;
/**
* Returns a network request for a tile.
*
* The default implementation returns an invalid request.
*/
virtual QNetworkRequest tileRequest( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, Qgis::RendererUsage usage ) const;
};
class QgsXyzVectorTileDataProvider : public QgsVectorTileDataProvider
{
Q_OBJECT
public:
QgsXyzVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
QgsCoordinateReferenceSystem crs() const override;
bool supportsAsync() const override;
QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const override;
QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const override;
QNetworkRequest tileRequest( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, Qgis::RendererUsage usage ) const override;
protected:
QString mAuthCfg;
QgsHttpHeaders mHeaders;
private:
//! Returns raw tile data for a single tile, doing a HTTP request. Block the caller until tile data are downloaded.
static QByteArray loadFromNetwork( const QgsTileXYZ &id,
const QgsTileMatrix &tileMatrix,
const QString &requestUrl,
const QString &authid,
const QgsHttpHeaders &headers,
QgsFeedback *feedback = nullptr );
};
class QgsMbTilesVectorTileDataProvider : public QgsVectorTileDataProvider
{
Q_OBJECT
public:
QgsMbTilesVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
QgsCoordinateReferenceSystem crs() const override;
QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const override;
QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const override;
private:
//! Returns raw tile data for a single tile loaded from MBTiles file
static QByteArray loadFromMBTiles( QgsMbTiles &mbTileReader, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr );
};
class QgsVtpkTiles;
class QgsVtpkVectorTileDataProvider : public QgsVectorTileDataProvider
{
Q_OBJECT
public:
QgsVtpkVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
QgsCoordinateReferenceSystem crs() const override;
QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const override;
QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const override;
private:
//! Returns raw tile data for a single tile loaded from VTPK file
static QByteArray loadFromVtpk( QgsVtpkTiles &vtpkTileReader, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr );
};
class QgsArcGisVectorTileServiceDataProvider : public QgsXyzVectorTileDataProvider
{
Q_OBJECT
public:
QgsArcGisVectorTileServiceDataProvider( const QString &uri,
const QString &sourcePath,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
private:
QString mSourcePath;
};
///@endcond
#endif
#endif // QGSVECTORTILELAYER_H

View File

@ -14,24 +14,21 @@
***************************************************************************/
#include "qgsvectortilelayerrenderer.h"
#include <QElapsedTimer>
#include <QThread>
#include "qgsexpressioncontextutils.h"
#include "qgsfeedback.h"
#include "qgslogger.h"
#include "qgsvectortilebasicrenderer.h"
#include "qgsvectortilemvtdecoder.h"
#include "qgsvectortilelayer.h"
#include "qgsvectortileloader.h"
#include "qgsvectortileutils.h"
#include "qgslabelingengine.h"
#include "qgsvectortilelabeling.h"
#include "qgsmapclippingutils.h"
#include "qgsrendercontext.h"
#include "qgsvectortiledataprovider.h"
#include <QElapsedTimer>
#include <QThread>
QgsVectorTileLayerRenderer::QgsVectorTileLayerRenderer( QgsVectorTileLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id(), &context )

View File

@ -19,15 +19,15 @@
#define SIP_NO_FILE
#include "qgsmaplayerrenderer.h"
#include "qgsvectortilerenderer.h"
#include "qgsmapclippingregion.h"
#include "qgsvectortilematrixset.h"
class QgsVectorTileLayer;
class QgsVectorTileRawData;
class QgsVectorTileLabelProvider;
class QgsVectorTileDataProvider;
#include "qgsvectortilerenderer.h"
#include "qgsmapclippingregion.h"
#include "qgsvectortilematrixset.h"
/**
* \ingroup core

View File

@ -14,17 +14,16 @@
***************************************************************************/
#include "qgsvectortileloader.h"
#include <QEventLoop>
#include "qgslogger.h"
#include "qgsvectortileutils.h"
#include "qgsapplication.h"
#include "qgsvectortilelayer.h"
#include "qgsvectortiledataprovider.h"
#include "qgsfeedback.h"
#include "qgstiledownloadmanager.h"
#include <QEventLoop>
QgsVectorTileLoader::QgsVectorTileLoader( const QgsVectorTileDataProvider *provider, const QgsTileMatrix &tileMatrix, const QgsTileRange &range, const QPointF &viewCenter, QgsFeedback *feedback, Qgis::RendererUsage usage )
: mEventLoop( new QEventLoop )
, mFeedback( feedback )

View File

@ -20,9 +20,13 @@
#include "qgstiles.h"
class QByteArray;
class QgsFeedback;
class QgsTileDownloadManagerReply;
class QgsVectorTileDataProvider;
class QByteArray;
class QNetworkReply;
class QEventLoop;
/**
* \ingroup core
@ -44,14 +48,6 @@ class QgsVectorTileRawData
};
class QNetworkReply;
class QEventLoop;
class QgsVtpkTiles;
class QgsTileDownloadManagerReply;
class QgsVectorTileDataProvider;
/**
* \ingroup core
* \brief The loader class takes care of loading raw vector tile data from a tile source.

View File

@ -0,0 +1,110 @@
/***************************************************************************
qgsvtpkvectortiledataprovider.cpp
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsvtpkvectortiledataprovider.h"
#include "qgsthreadingutils.h"
#include "qgsvtpktiles.h"
#include "qgsvectortileloader.h"
///@cond PRIVATE
QgsVtpkVectorTileDataProvider::QgsVtpkVectorTileDataProvider( const QString &uri, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsVectorTileDataProvider( uri, providerOptions, flags )
{
}
QgsVectorTileDataProvider *QgsVtpkVectorTileDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsVtpkVectorTileDataProvider( dataSourceUri(), options, mReadFlags );
}
QString QgsVtpkVectorTileDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
return dsUri.param( QStringLiteral( "url" ) );
}
bool QgsVtpkVectorTileDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
QgsCoordinateReferenceSystem QgsVtpkVectorTileDataProvider::crs() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) );
}
QByteArray QgsVtpkVectorTileDataProvider::readTile( const QgsTileMatrix &, const QgsTileXYZ &id, QgsFeedback *feedback ) const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsVtpkTiles reader( dsUri.param( QStringLiteral( "url" ) ) );
reader.open();
return loadFromVtpk( reader, id, feedback );
}
QList<QgsVectorTileRawData> QgsVtpkVectorTileDataProvider::readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback ) const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
QgsVtpkTiles reader( dsUri.param( QStringLiteral( "url" ) ) );
reader.open();
QList<QgsVectorTileRawData> rawTiles;
rawTiles.reserve( tiles.size() );
for ( QgsTileXYZ id : std::as_const( tiles ) )
{
if ( feedback && feedback->isCanceled() )
break;
const QByteArray rawData = loadFromVtpk( reader, id, feedback );
if ( !rawData.isEmpty() )
{
rawTiles.append( QgsVectorTileRawData( id, rawData ) );
}
}
return rawTiles;
}
QByteArray QgsVtpkVectorTileDataProvider::loadFromVtpk( QgsVtpkTiles &vtpkTileReader, const QgsTileXYZ &id, QgsFeedback * )
{
const QByteArray tileData = vtpkTileReader.tileData( id.zoomLevel(), id.column(), id.row() );
if ( tileData.isEmpty() )
{
return QByteArray();
}
return tileData;
}
///@endcond

View File

@ -0,0 +1,54 @@
/***************************************************************************
qgsvtpkvectortiledataprovider.h
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSVTPKVECTORTILEDATAPROVIDER_H
#define QGSVTPKVECTORTILEDATAPROVIDER_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsvectortiledataprovider.h"
#define SIP_NO_FILE
///@cond PRIVATE
class QgsVtpkTiles;
class QgsVtpkVectorTileDataProvider : public QgsVectorTileDataProvider
{
Q_OBJECT
public:
QgsVtpkVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
QgsCoordinateReferenceSystem crs() const override;
QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const override;
QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const override;
private:
//! Returns raw tile data for a single tile loaded from VTPK file
static QByteArray loadFromVtpk( QgsVtpkTiles &vtpkTileReader, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr );
};
///@endcond
#endif // QGSVTPKVECTORTILEDATAPROVIDER_H

View File

@ -0,0 +1,170 @@
/***************************************************************************
qgsxyzvectortiledataprovider.cpp
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsxyzvectortiledataprovider.h"
#include "qgsthreadingutils.h"
#include "qgstiles.h"
#include "qgsvectortileloader.h"
#include "qgsvectortileutils.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsapplication.h"
#include "qgsauthmanager.h"
#include "qgsmessagelog.h"
#include "qgsblockingnetworkrequest.h"
#include "qgslogger.h"
#include <QNetworkRequest>
///@cond PRIVATE
QgsXyzVectorTileDataProvider::QgsXyzVectorTileDataProvider( const QString &uri, const ProviderOptions &providerOptions, ReadFlags flags )
: QgsVectorTileDataProvider( uri, providerOptions, flags )
{
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( uri );
mAuthCfg = dsUri.authConfigId();
mHeaders = dsUri.httpHeaders();
}
QgsVectorTileDataProvider *QgsXyzVectorTileDataProvider::clone() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
ProviderOptions options;
options.transformContext = transformContext();
return new QgsXyzVectorTileDataProvider( dataSourceUri(), options, mReadFlags );
}
QString QgsXyzVectorTileDataProvider::sourcePath() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QgsDataSourceUri dsUri;
dsUri.setEncodedUri( dataSourceUri() );
return dsUri.param( QStringLiteral( "url" ) );
}
bool QgsXyzVectorTileDataProvider::isValid() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return true;
}
QgsCoordinateReferenceSystem QgsXyzVectorTileDataProvider::crs() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
return QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) );
}
bool QgsXyzVectorTileDataProvider::supportsAsync() const
{
return true;
}
QByteArray QgsXyzVectorTileDataProvider::readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback ) const
{
return loadFromNetwork( id, tileMatrix, sourcePath(), mAuthCfg, mHeaders, feedback );
}
QList<QgsVectorTileRawData> QgsXyzVectorTileDataProvider::readTiles( const QgsTileMatrix &tileMatrix, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback ) const
{
QList<QgsVectorTileRawData> rawTiles;
rawTiles.reserve( tiles.size() );
const QString source = sourcePath();
for ( QgsTileXYZ id : std::as_const( tiles ) )
{
if ( feedback && feedback->isCanceled() )
break;
const QByteArray rawData = loadFromNetwork( id, tileMatrix, source, mAuthCfg, mHeaders, feedback );
if ( !rawData.isEmpty() )
{
rawTiles.append( QgsVectorTileRawData( id, rawData ) );
}
}
return rawTiles;
}
QNetworkRequest QgsXyzVectorTileDataProvider::tileRequest( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, Qgis::RendererUsage usage ) const
{
QString urlTemplate = sourcePath();
if ( urlTemplate.contains( QLatin1String( "{usage}" ) ) )
{
switch ( usage )
{
case Qgis::RendererUsage::View:
urlTemplate.replace( QLatin1String( "{usage}" ), QLatin1String( "view" ) );
break;
case Qgis::RendererUsage::Export:
urlTemplate.replace( QLatin1String( "{usage}" ), QLatin1String( "export" ) );
break;
case Qgis::RendererUsage::Unknown:
urlTemplate.replace( QLatin1String( "{usage}" ), QString() );
break;
}
}
const QString url = QgsVectorTileUtils::formatXYZUrlTemplate( urlTemplate, id, tileMatrix );
QNetworkRequest request( url );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsXyzVectorTileDataProvider" ) );
QgsSetRequestInitiatorId( request, id.toString() );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ), id.column() );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ), id.row() );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), id.zoomLevel() );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mHeaders.updateNetworkRequest( request );
if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg ) )
{
QgsMessageLog::logMessage( tr( "network request update failed for authentication config" ), tr( "Network" ) );
}
return request;
}
QByteArray QgsXyzVectorTileDataProvider::loadFromNetwork( const QgsTileXYZ &id, const QgsTileMatrix &tileMatrix, const QString &requestUrl, const QString &authid, const QgsHttpHeaders &headers, QgsFeedback *feedback )
{
QString url = QgsVectorTileUtils::formatXYZUrlTemplate( requestUrl, id, tileMatrix );
QNetworkRequest nr;
nr.setUrl( QUrl( url ) );
headers.updateNetworkRequest( nr );
QgsBlockingNetworkRequest req;
req.setAuthCfg( authid );
QgsDebugMsgLevel( QStringLiteral( "Blocking request: " ) + url, 2 );
QgsBlockingNetworkRequest::ErrorCode errCode = req.get( nr, false, feedback );
if ( errCode != QgsBlockingNetworkRequest::NoError )
{
QgsDebugMsg( QStringLiteral( "Request failed: " ) + url );
return QByteArray();
}
QgsNetworkReplyContent reply = req.reply();
QgsDebugMsgLevel( QStringLiteral( "Request successful, content size %1" ).arg( reply.content().size() ), 2 );
return reply.content();
}
///@endcond

View File

@ -0,0 +1,63 @@
/***************************************************************************
qgsxyzvectortiledataprovider.h
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSXYZVECTORTILEDATAPROVIDER_H
#define QGSXYZVECTORTILEDATAPROVIDER_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsvectortiledataprovider.h"
#define SIP_NO_FILE
///@cond PRIVATE
class CORE_EXPORT QgsXyzVectorTileDataProvider : public QgsVectorTileDataProvider
{
Q_OBJECT
public:
QgsXyzVectorTileDataProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags );
QgsVectorTileDataProvider *clone() const override;
QString sourcePath() const override;
bool isValid() const override;
QgsCoordinateReferenceSystem crs() const override;
bool supportsAsync() const override;
QByteArray readTile( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, QgsFeedback *feedback = nullptr ) const override;
QList<QgsVectorTileRawData> readTiles( const QgsTileMatrix &, const QVector<QgsTileXYZ> &tiles, QgsFeedback *feedback = nullptr ) const override;
QNetworkRequest tileRequest( const QgsTileMatrix &tileMatrix, const QgsTileXYZ &id, Qgis::RendererUsage usage ) const override;
protected:
QString mAuthCfg;
QgsHttpHeaders mHeaders;
private:
//! Returns raw tile data for a single tile, doing a HTTP request. Block the caller until tile data are downloaded.
static QByteArray loadFromNetwork( const QgsTileXYZ &id,
const QgsTileMatrix &tileMatrix,
const QString &requestUrl,
const QString &authid,
const QgsHttpHeaders &headers,
QgsFeedback *feedback = nullptr );
};
///@endcond
#endif // QGSXYZVECTORTILEDATAPROVIDER_H