From 385acae48c4834a55cd9322d90faf5bc8d2fe95b Mon Sep 17 00:00:00 2001 From: Alessandro Pasotti Date: Wed, 4 Mar 2020 16:25:50 +0100 Subject: [PATCH] PG raster: reset renderer when filter changes --- .../raster/qgsrasterlayer.sip.in | 1 + src/core/raster/qgsrasterlayer.cpp | 169 +++++++++--------- src/core/raster/qgsrasterlayer.h | 4 + .../python/test_provider_postgresraster.py | 11 ++ 4 files changed, 105 insertions(+), 80 deletions(-) diff --git a/python/core/auto_generated/raster/qgsrasterlayer.sip.in b/python/core/auto_generated/raster/qgsrasterlayer.sip.in index d3cc2f70ecc..8535d548715 100644 --- a/python/core/auto_generated/raster/qgsrasterlayer.sip.in +++ b/python/core/auto_generated/raster/qgsrasterlayer.sip.in @@ -447,6 +447,7 @@ Emitted when the layer's subset string has changed. virtual QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const; + }; diff --git a/src/core/raster/qgsrasterlayer.cpp b/src/core/raster/qgsrasterlayer.cpp index ba548f621ec..52264a9376c 100644 --- a/src/core/raster/qgsrasterlayer.cpp +++ b/src/core/raster/qgsrasterlayer.cpp @@ -815,6 +815,7 @@ void QgsRasterLayer::setDataProvider( QString const &provider, const QgsDataProv QgsDebugMsgLevel( QStringLiteral( "exiting." ), 4 ); + } void QgsRasterLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag ) @@ -1142,97 +1143,105 @@ void QgsRasterLayer::refreshContrastEnhancement( const QgsRectangle &extent ) void QgsRasterLayer::refreshRendererIfNeeded( QgsRasterRenderer *rasterRenderer, const QgsRectangle &extent ) { - if ( !( mDataProvider && - mLastRectangleUsedByRefreshContrastEnhancementIfNeeded != extent && - rasterRenderer->minMaxOrigin().limits() != QgsRasterMinMaxOrigin::None && - rasterRenderer->minMaxOrigin().extent() == QgsRasterMinMaxOrigin::UpdatedCanvas ) ) - return; - - QgsSingleBandGrayRenderer *singleBandRenderer = nullptr; - QgsMultiBandColorRenderer *multiBandRenderer = nullptr; - QgsSingleBandPseudoColorRenderer *sbpcr = nullptr; - const QgsContrastEnhancement *ce = nullptr; - if ( ( singleBandRenderer = dynamic_cast( rasterRenderer ) ) ) + if ( mDataProvider && + mLastRectangleUsedByRefreshContrastEnhancementIfNeeded != extent && + rasterRenderer->minMaxOrigin().limits() != QgsRasterMinMaxOrigin::None && + rasterRenderer->minMaxOrigin().extent() == QgsRasterMinMaxOrigin::UpdatedCanvas ) { - ce = singleBandRenderer->contrastEnhancement(); + refreshRenderer( rasterRenderer, extent ); } - else if ( ( multiBandRenderer = dynamic_cast( rasterRenderer ) ) ) - { - ce = multiBandRenderer->redContrastEnhancement(); - } - else if ( ( sbpcr = dynamic_cast( rasterRenderer ) ) ) - { - mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent; - double min; - double max; - computeMinMax( sbpcr->band(), - rasterRenderer->minMaxOrigin(), - rasterRenderer->minMaxOrigin().limits(), extent, - SAMPLE_SIZE, min, max ); - sbpcr->setClassificationMin( min ); - sbpcr->setClassificationMax( max ); +} - if ( sbpcr->shader() ) +void QgsRasterLayer::refreshRenderer( QgsRasterRenderer *rasterRenderer, const QgsRectangle &extent ) +{ + if ( mDataProvider ) + { + QgsSingleBandGrayRenderer *singleBandRenderer = nullptr; + QgsMultiBandColorRenderer *multiBandRenderer = nullptr; + QgsSingleBandPseudoColorRenderer *sbpcr = nullptr; + const QgsContrastEnhancement *ce = nullptr; + if ( ( singleBandRenderer = dynamic_cast( rasterRenderer ) ) ) { - QgsColorRampShader *colorRampShader = dynamic_cast( sbpcr->shader()->rasterShaderFunction() ); - if ( colorRampShader ) + ce = singleBandRenderer->contrastEnhancement(); + } + else if ( ( multiBandRenderer = dynamic_cast( rasterRenderer ) ) ) + { + ce = multiBandRenderer->redContrastEnhancement(); + } + else if ( ( sbpcr = dynamic_cast( rasterRenderer ) ) ) + { + mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent; + double min; + double max; + computeMinMax( sbpcr->band(), + rasterRenderer->minMaxOrigin(), + rasterRenderer->minMaxOrigin().limits(), extent, + SAMPLE_SIZE, min, max ); + sbpcr->setClassificationMin( min ); + sbpcr->setClassificationMax( max ); + + if ( sbpcr->shader() ) { - colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() ); + QgsColorRampShader *colorRampShader = dynamic_cast( sbpcr->shader()->rasterShaderFunction() ); + if ( colorRampShader ) + { + colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() ); + } } + + QgsSingleBandPseudoColorRenderer *r = dynamic_cast( renderer() ); + r->setClassificationMin( min ); + r->setClassificationMax( max ); + + if ( r->shader() ) + { + QgsColorRampShader *colorRampShader = dynamic_cast( r->shader()->rasterShaderFunction() ); + if ( colorRampShader ) + { + colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() ); + } + } + + emit repaintRequested(); + emit styleChanged(); + emit rendererChanged(); + return; } - QgsSingleBandPseudoColorRenderer *r = dynamic_cast( renderer() ); - r->setClassificationMin( min ); - r->setClassificationMax( max ); - - if ( r->shader() ) + if ( ce && + ce->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement ) { - QgsColorRampShader *colorRampShader = dynamic_cast( r->shader()->rasterShaderFunction() ); - if ( colorRampShader ) + mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent; + + setContrastEnhancement( ce->contrastEnhancementAlgorithm(), + rasterRenderer->minMaxOrigin().limits(), + extent, + SAMPLE_SIZE, + true, + rasterRenderer ); + + // Update main renderer so that the legends get updated + if ( singleBandRenderer ) + static_cast( renderer() )->setContrastEnhancement( new QgsContrastEnhancement( * singleBandRenderer->contrastEnhancement() ) ); + else if ( multiBandRenderer ) { - colorRampShader->classifyColorRamp( sbpcr->band(), extent, rasterRenderer->input() ); + if ( multiBandRenderer->redContrastEnhancement() ) + { + static_cast( renderer() )->setRedContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->redContrastEnhancement() ) ); + } + if ( multiBandRenderer->greenContrastEnhancement() ) + { + static_cast( renderer() )->setGreenContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->greenContrastEnhancement() ) ); + } + if ( multiBandRenderer->blueContrastEnhancement() ) + { + static_cast( renderer() )->setBlueContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->blueContrastEnhancement() ) ); + } } + + emit styleChanged(); + emit rendererChanged(); } - - emit repaintRequested(); - emit styleChanged(); - emit rendererChanged(); - return; - } - - if ( ce && - ce->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement ) - { - mLastRectangleUsedByRefreshContrastEnhancementIfNeeded = extent; - - setContrastEnhancement( ce->contrastEnhancementAlgorithm(), - rasterRenderer->minMaxOrigin().limits(), - extent, - SAMPLE_SIZE, - true, - rasterRenderer ); - - // Update main renderer so that the legends get updated - if ( singleBandRenderer ) - static_cast( renderer() )->setContrastEnhancement( new QgsContrastEnhancement( * singleBandRenderer->contrastEnhancement() ) ); - else if ( multiBandRenderer ) - { - if ( multiBandRenderer->redContrastEnhancement() ) - { - static_cast( renderer() )->setRedContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->redContrastEnhancement() ) ); - } - if ( multiBandRenderer->greenContrastEnhancement() ) - { - static_cast( renderer() )->setGreenContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->greenContrastEnhancement() ) ); - } - if ( multiBandRenderer->blueContrastEnhancement() ) - { - static_cast( renderer() )->setBlueContrastEnhancement( new QgsContrastEnhancement( *multiBandRenderer->blueContrastEnhancement() ) ); - } - } - - emit styleChanged(); - emit rendererChanged(); } } @@ -1275,8 +1284,8 @@ bool QgsRasterLayer::setSubsetString( const QString &subset ) if ( res ) { setExtent( mDataProvider->extent() ); + refreshRenderer( renderer(), extent() ); emit subsetStringChanged(); - triggerRepaint(); } return res; diff --git a/src/core/raster/qgsrasterlayer.h b/src/core/raster/qgsrasterlayer.h index 5d1eaecd125..bf2090b979e 100644 --- a/src/core/raster/qgsrasterlayer.h +++ b/src/core/raster/qgsrasterlayer.h @@ -481,6 +481,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer bool writeXml( QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context ) const override; QString encodedSource( const QString &source, const QgsReadWriteContext &context ) const override; QString decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const override; + private: //! \brief Initialize default values void init(); @@ -501,6 +502,9 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer bool generateLookupTableFlag, QgsRasterRenderer *rasterRenderer ); + //! Refresh renderer + void refreshRenderer( QgsRasterRenderer *rasterRenderer, const QgsRectangle &extent ); + void computeMinMax( int band, const QgsRasterMinMaxOrigin &mmo, QgsRasterMinMaxOrigin::Limits limits, diff --git a/tests/src/python/test_provider_postgresraster.py b/tests/src/python/test_provider_postgresraster.py index f1b704ed824..464f65d6d3b 100644 --- a/tests/src/python/test_provider_postgresraster.py +++ b/tests/src/python/test_provider_postgresraster.py @@ -281,6 +281,11 @@ class TestPyQgsPostgresRasterProvider(unittest.TestCase): self.assertEqual(int(stats.minimumValue), 136) self.assertEqual(int(stats.maximumValue), 169) + ce = rl.renderer().contrastEnhancement() + min_max = int(ce.minimumValue()), int(ce.maximumValue()) + self.assertEqual(min_max, (136, 169)) + + # Change filter: self.assertTrue(rl.setSubsetString('"pk" = 1')) block = rl.dataProvider().block(1, rl.extent(), 2, 2) data = [] @@ -294,6 +299,12 @@ class TestPyQgsPostgresRasterProvider(unittest.TestCase): self.assertEqual(int(stats.minimumValue), 136) self.assertEqual(int(stats.maximumValue), 153) + # Check that the renderer has been updated + ce = rl.renderer().contrastEnhancement() + new_min_max = int(ce.minimumValue()), int(ce.maximumValue()) + self.assertNotEqual(new_min_max, min_max) + self.assertEqual(new_min_max, (136, 153)) + # Set invalid filter self.assertFalse(rl.setSubsetString('"pk_wrong" = 1')) block = rl.dataProvider().block(1, rl.extent(), 2, 2)