From c3b967d171220b3c32ba88eb4986a255c31db932 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 24 Oct 2020 16:37:53 +1000 Subject: [PATCH 1/4] Make setting point cloud layer data source follow expected behavior for map layers Will make it possible to repair point cloud layer sources --- .../pointcloud/qgspointcloudlayer.sip.in | 4 ++ src/core/pointcloud/qgspointcloudlayer.cpp | 61 ++++++++++--------- src/core/pointcloud/qgspointcloudlayer.h | 11 ++-- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/python/core/auto_generated/pointcloud/qgspointcloudlayer.sip.in b/python/core/auto_generated/pointcloud/qgspointcloudlayer.sip.in index 8dc146f727a4..d81807236686 100644 --- a/python/core/auto_generated/pointcloud/qgspointcloudlayer.sip.in +++ b/python/core/auto_generated/pointcloud/qgspointcloudlayer.sip.in @@ -39,6 +39,8 @@ Constructor for LayerOptions with optional ``transformContext``. QgsCoordinateTransformContext transformContext; + bool loadDefaultStyle; + bool skipCrsValidation; }; @@ -83,6 +85,8 @@ QgsPointCloudLayer cannot be copied. virtual QString loadDefaultStyle( bool &resultFlag /Out/ ); + virtual void setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag = false ); + private: QgsPointCloudLayer( const QgsPointCloudLayer &rhs ); diff --git a/src/core/pointcloud/qgspointcloudlayer.cpp b/src/core/pointcloud/qgspointcloudlayer.cpp index 35b0c71e257a..8aed3387eb89 100644 --- a/src/core/pointcloud/qgspointcloudlayer.cpp +++ b/src/core/pointcloud/qgspointcloudlayer.cpp @@ -29,19 +29,11 @@ QgsPointCloudLayer::QgsPointCloudLayer( const QString &path, const QgsPointCloudLayer::LayerOptions &options ) : QgsMapLayer( QgsMapLayerType::PointCloudLayer, baseName, path ) { - Q_UNUSED( options ) - bool ok = false; if ( !path.isEmpty() && !providerLib.isEmpty() ) { QgsDataProvider::ProviderOptions providerOptions { options.transformContext }; - QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags(); - if ( mReadFlags & QgsMapLayer::FlagTrustLayerMetadata ) - { - flags |= QgsDataProvider::FlagTrustDataSource; - } - ok = loadDataSource( providerLib, providerOptions, flags ); + setDataSource( path, baseName, providerLib, providerOptions, options.loadDefaultStyle ); } - setValid( ok ); } QgsPointCloudLayer::~QgsPointCloudLayer() = default; @@ -80,17 +72,15 @@ bool QgsPointCloudLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext { // create provider QDomNode pkeyNode = layerNode.namedItem( QStringLiteral( "provider" ) ); - QString providerKey = pkeyNode.toElement().text(); - QgsDataProvider::ProviderOptions providerOptions { context.transformContext() }; - QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags(); - if ( mReadFlags & QgsMapLayer::FlagTrustLayerMetadata ) + mProviderKey = pkeyNode.toElement().text(); + + if ( !( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) ) { - flags |= QgsDataProvider::FlagTrustDataSource; + QgsDataProvider::ProviderOptions providerOptions { context.transformContext() }; + setDataSource( mDataSource, mLayerName, mProviderKey, providerOptions, false ); } - // TODO: support QgsMapLayer::FlagDontResolveLayers ? - bool ok = loadDataSource( providerKey, providerOptions, flags ); - setValid( ok ); - if ( !ok ) + + if ( !isValid() ) { return false; } @@ -156,17 +146,30 @@ QString QgsPointCloudLayer::loadDefaultStyle( bool &resultFlag ) return QString(); } - -bool QgsPointCloudLayer::loadDataSource( const QString &providerLib, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags ) +void QgsPointCloudLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag ) { - QString dataSource = mDataSource; - mProviderKey = providerLib; + Q_UNUSED( loadDefaultStyleFlag ) + + if ( mDataProvider ) + disconnect( mDataProvider.get(), &QgsPointCloudDataProvider::dataChanged, this, &QgsPointCloudLayer::dataChanged ); + + setName( baseName ); + mProviderKey = provider; + mDataSource = dataSource; - mDataProvider.reset( qobject_cast( QgsProviderRegistry::instance()->createProvider( providerLib, dataSource, options, flags ) ) ); + QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags(); + if ( mReadFlags & QgsMapLayer::FlagTrustLayerMetadata ) + { + flags |= QgsDataProvider::FlagTrustDataSource; + } + + mDataProvider.reset( qobject_cast( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options, flags ) ) ); if ( !mDataProvider ) { - QgsDebugMsgLevel( QStringLiteral( "Unable to get point cloud data provider" ), 2 ); - return false; + QgsDebugMsg( QStringLiteral( "Unable to get point cloud data provider" ) ); + setValid( false ); + emit dataSourceChanged(); + return; } mDataProvider->setParent( this ); @@ -175,13 +178,15 @@ bool QgsPointCloudLayer::loadDataSource( const QString &providerLib, const QgsDa setValid( mDataProvider->isValid() ); if ( !isValid() ) { - QgsDebugMsgLevel( QStringLiteral( "Invalid point cloud provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 ); - return false; + QgsDebugMsg( QStringLiteral( "Invalid point cloud provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ) ); + emit dataSourceChanged(); + return; } setCrs( mDataProvider->crs() ); connect( mDataProvider.get(), &QgsPointCloudDataProvider::dataChanged, this, &QgsPointCloudLayer::dataChanged ); - return true; + emit dataSourceChanged(); + triggerRepaint(); } diff --git a/src/core/pointcloud/qgspointcloudlayer.h b/src/core/pointcloud/qgspointcloudlayer.h index 8dd5725c63fd..da76ff3547f4 100644 --- a/src/core/pointcloud/qgspointcloudlayer.h +++ b/src/core/pointcloud/qgspointcloudlayer.h @@ -54,8 +54,14 @@ class CORE_EXPORT QgsPointCloudLayer : public QgsMapLayer : transformContext( transformContext ) {} + /** + * Coordinate transform context + */ QgsCoordinateTransformContext transformContext; + //! Set to TRUE if the default layer style should be loaded + bool loadDefaultStyle = true; + /** * Controls whether the layer is allowed to have an invalid/unknown CRS. * @@ -105,13 +111,10 @@ class CORE_EXPORT QgsPointCloudLayer : public QgsMapLayer void setTransformContext( const QgsCoordinateTransformContext &transformContext ) override; QString loadDefaultStyle( bool &resultFlag SIP_OUT ) override; + void setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag = false ) override; private: - bool loadDataSource( const QString &providerLib, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags ); - /** - * Returns TRUE if the provider is in read-only mode - */ bool isReadOnly() const override {return true;} #ifdef SIP_RUN From c1b6c9642d44e18e3b8bae30a4169cf0530813b4 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 24 Oct 2020 16:38:38 +1000 Subject: [PATCH 2/4] Fix cloning point cloud layers --- src/core/pointcloud/qgspointcloudlayer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/pointcloud/qgspointcloudlayer.cpp b/src/core/pointcloud/qgspointcloudlayer.cpp index 8aed3387eb89..68991b8afbb4 100644 --- a/src/core/pointcloud/qgspointcloudlayer.cpp +++ b/src/core/pointcloud/qgspointcloudlayer.cpp @@ -40,7 +40,12 @@ QgsPointCloudLayer::~QgsPointCloudLayer() = default; QgsPointCloudLayer *QgsPointCloudLayer::clone() const { - QgsPointCloudLayer *layer = new QgsPointCloudLayer( source(), name() ); + LayerOptions options; + options.loadDefaultStyle = false; + options.transformContext = transformContext(); + options.skipCrsValidation = true; + + QgsPointCloudLayer *layer = new QgsPointCloudLayer( source(), name(), mProviderKey, options ); QgsMapLayer::clone( layer ); return layer; } From 7ccc1790eba7837f2ea94e32a39991fbff822af2 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 24 Oct 2020 16:40:50 +1000 Subject: [PATCH 3/4] Point cloud layer data sources can be changed via menu --- src/app/qgsapplayertreeviewmenuprovider.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/qgsapplayertreeviewmenuprovider.cpp b/src/app/qgsapplayertreeviewmenuprovider.cpp index d440cdc1452c..6483ee36fa2e 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.cpp +++ b/src/app/qgsapplayertreeviewmenuprovider.cpp @@ -145,6 +145,7 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu() QgsMapLayer *layer = QgsLayerTree::toLayer( node )->layer(); QgsRasterLayer *rlayer = qobject_cast( layer ); QgsVectorLayer *vlayer = qobject_cast( layer ); + QgsPointCloudLayer *pcLayer = qobject_cast( layer ); if ( layer && layer->isSpatial() ) { @@ -270,8 +271,8 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu() menu->addAction( tr( "&Filter…" ), QgisApp::instance(), qgis::overload<>::of( &QgisApp::layerSubsetString ) ); } - // change data source is only supported for vectors and rasters - if ( vlayer || rlayer ) + // change data source is only supported for vectors and rasters, point clouds + if ( vlayer || rlayer || pcLayer ) { QAction *a = new QAction( layer->isValid() ? tr( "Change Data Source…" ) : tr( "Repair Data Source…" ), menu ); From 7831901ce3ff472cd569aedfb47651656cc06da7 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 24 Oct 2020 16:42:29 +1000 Subject: [PATCH 4/4] Fix build --- src/app/qgsapplayertreeviewmenuprovider.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/qgsapplayertreeviewmenuprovider.cpp b/src/app/qgsapplayertreeviewmenuprovider.cpp index 6483ee36fa2e..57c0b449f9e2 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.cpp +++ b/src/app/qgsapplayertreeviewmenuprovider.cpp @@ -43,6 +43,7 @@ #include "qgssymbollayerutils.h" #include "qgsxmlutils.h" #include "qgsmessagebar.h" +#include "qgspointcloudlayer.h" QgsAppLayerTreeViewMenuProvider::QgsAppLayerTreeViewMenuProvider( QgsLayerTreeView *view, QgsMapCanvas *canvas )