From d68a428f6e85481c5810bc7d8c816a6a1def5ddf Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Mon, 8 Apr 2024 09:34:33 +0700 Subject: [PATCH] Address review --- .../qgsrastersinglecolorrenderer.sip.in | 16 +++-- .../qgsrastersinglecolorrenderer.sip.in | 16 +++-- .../raster/qgsrastersinglecolorrenderer.cpp | 58 ++++++++++++++----- .../raster/qgsrastersinglecolorrenderer.h | 13 +++-- .../qgsrastersinglecolorrendererwidget.cpp | 18 +++--- .../qgsrastersinglecolorrendererwidget.h | 3 - .../qgsrastersinglecolorrendererwidgetbase.ui | 19 +++++- tests/src/python/CMakeLists.txt | 2 +- .../test_qgsrastersinglecolorrenderer.py | 5 +- 9 files changed, 106 insertions(+), 44 deletions(-) diff --git a/python/PyQt6/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in b/python/PyQt6/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in index fa3084087dc..c3163903506 100644 --- a/python/PyQt6/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in +++ b/python/PyQt6/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in @@ -14,7 +14,7 @@ class QgsRasterSingleColorRenderer: QgsRasterRenderer { %Docstring(signature="appended") -Raster single color renderer pipe. +Raster renderer which renders all data pixels using a single color. .. versionadded:: 3.38 %End @@ -24,7 +24,7 @@ Raster single color renderer pipe. %End public: - QgsRasterSingleColorRenderer( QgsRasterInterface *input, QColor color ); + QgsRasterSingleColorRenderer( QgsRasterInterface *input, int band, const QColor &color ); %Docstring Creates a single ``color`` renderer %End @@ -49,16 +49,24 @@ Creates an instance of the renderer based on definition from XML (used by the re QColor color() const; %Docstring Returns the single color used by the renderer. + +.. seealso:: :py:func:`setColor` %End - void setColor( QColor &color ); + void setColor( const QColor &color ); %Docstring -Sets the single color used by the renderer. +Sets the single ``color`` used by the renderer. + +.. seealso:: :py:func:`color` %End virtual void writeXml( QDomDocument &doc, QDomElement &parentElem ) const; + virtual int inputBand() const; + + virtual bool setInputBand( int band ); + virtual QList usesBands() const; diff --git a/python/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in b/python/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in index fa3084087dc..c3163903506 100644 --- a/python/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in +++ b/python/core/auto_generated/raster/qgsrastersinglecolorrenderer.sip.in @@ -14,7 +14,7 @@ class QgsRasterSingleColorRenderer: QgsRasterRenderer { %Docstring(signature="appended") -Raster single color renderer pipe. +Raster renderer which renders all data pixels using a single color. .. versionadded:: 3.38 %End @@ -24,7 +24,7 @@ Raster single color renderer pipe. %End public: - QgsRasterSingleColorRenderer( QgsRasterInterface *input, QColor color ); + QgsRasterSingleColorRenderer( QgsRasterInterface *input, int band, const QColor &color ); %Docstring Creates a single ``color`` renderer %End @@ -49,16 +49,24 @@ Creates an instance of the renderer based on definition from XML (used by the re QColor color() const; %Docstring Returns the single color used by the renderer. + +.. seealso:: :py:func:`setColor` %End - void setColor( QColor &color ); + void setColor( const QColor &color ); %Docstring -Sets the single color used by the renderer. +Sets the single ``color`` used by the renderer. + +.. seealso:: :py:func:`color` %End virtual void writeXml( QDomDocument &doc, QDomElement &parentElem ) const; + virtual int inputBand() const; + + virtual bool setInputBand( int band ); + virtual QList usesBands() const; diff --git a/src/core/raster/qgsrastersinglecolorrenderer.cpp b/src/core/raster/qgsrastersinglecolorrenderer.cpp index 7237dc9b35d..1c6f0f2bdc3 100644 --- a/src/core/raster/qgsrastersinglecolorrenderer.cpp +++ b/src/core/raster/qgsrastersinglecolorrenderer.cpp @@ -22,15 +22,16 @@ #include #include -QgsRasterSingleColorRenderer::QgsRasterSingleColorRenderer( QgsRasterInterface *input, QColor color ) +QgsRasterSingleColorRenderer::QgsRasterSingleColorRenderer( QgsRasterInterface *input, int band, const QColor &color ) : QgsRasterRenderer( input, QStringLiteral( "singlecolor" ) ) + , mInputBand( band ) , mColor( color ) { } QgsRasterSingleColorRenderer *QgsRasterSingleColorRenderer::clone() const { - QgsRasterSingleColorRenderer *renderer = new QgsRasterSingleColorRenderer( nullptr, mColor ); + QgsRasterSingleColorRenderer *renderer = new QgsRasterSingleColorRenderer( nullptr, mInputBand, mColor ); renderer->copyCommonProperties( this ); return renderer; } @@ -48,23 +49,24 @@ QgsRasterRenderer *QgsRasterSingleColorRenderer::create( const QDomElement &elem } const QColor color = QgsColorUtils::colorFromString( elem.attribute( QStringLiteral( "color" ), QStringLiteral( "0,0,0" ) ) ); - QgsRasterSingleColorRenderer *r = new QgsRasterSingleColorRenderer( input, color ); + const int band = elem.attribute( QStringLiteral( "band" ), QStringLiteral( "1" ) ).toInt(); + QgsRasterSingleColorRenderer *r = new QgsRasterSingleColorRenderer( input, band, color ); r->readXml( elem ); return r; } -QgsRasterBlock *QgsRasterSingleColorRenderer::block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback ) +QgsRasterBlock *QgsRasterSingleColorRenderer::block( int, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback ) { QgsDebugMsgLevel( QStringLiteral( "width = %1 height = %2" ).arg( width ).arg( height ), 4 ); std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() ); - if ( !mInput ) + if ( !mInput || mInputBand == -1 ) { return outputBlock.release(); } - const std::shared_ptr< QgsRasterBlock > inputBlock( mInput->block( bandNo, extent, width, height, feedback ) ); + const std::shared_ptr< QgsRasterBlock > inputBlock( mInput->block( mInputBand, extent, width, height, feedback ) ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugError( QStringLiteral( "No raster data!" ) ); @@ -82,14 +84,17 @@ QgsRasterBlock *QgsRasterSingleColorRenderer::block( int bandNo, const QgsRectan return outputBlock.release(); } - const QRgb myDefaultColor = renderColorForNodataPixel(); + const QRgb defaultColor = renderColorForNodataPixel(); + const QRgb rendererColor = qRgba( mColor.red(), mColor.green(), mColor.blue(), mColor.alpha() ); + bool isNoData = false; - for ( qgssize i = 0; i < ( qgssize )width * height; i++ ) + const qgssize blockSize = static_cast< qgssize >( width ) * height; + for ( qgssize i = 0; i < blockSize; i++ ) { double value = inputBlock->valueAndNoData( i, isNoData ); if ( isNoData ) { - outputBlock->setColor( i, myDefaultColor ); + outputBlock->setColor( i, defaultColor ); continue; } @@ -103,7 +108,7 @@ QgsRasterBlock *QgsRasterSingleColorRenderer::block( int bandNo, const QgsRectan const double alpha = alphaBlock->value( i ); if ( alpha == 0 ) { - outputBlock->setColor( i, myDefaultColor ); + outputBlock->setColor( i, defaultColor ); continue; } else @@ -114,7 +119,7 @@ QgsRasterBlock *QgsRasterSingleColorRenderer::block( int bandNo, const QgsRectan if ( qgsDoubleNear( currentAlpha, 1.0 ) ) { - outputBlock->setColor( i, qRgba( mColor.red(), mColor.green(), mColor.blue(), mColor.alpha() ) ); + outputBlock->setColor( i, rendererColor ); } else { @@ -128,7 +133,7 @@ QgsRasterBlock *QgsRasterSingleColorRenderer::block( int bandNo, const QgsRectan return outputBlock.release(); } -void QgsRasterSingleColorRenderer::setColor( QColor &color ) +void QgsRasterSingleColorRenderer::setColor( const QColor &color ) { mColor = color;; } @@ -149,16 +154,37 @@ void QgsRasterSingleColorRenderer::writeXml( QDomDocument &doc, QDomElement &par _writeXml( doc, rasterRendererElem ); rasterRendererElem.setAttribute( QStringLiteral( "color" ), QgsColorUtils::colorToString( mColor ) ); + rasterRendererElem.setAttribute( QStringLiteral( "band" ), QgsColorUtils::colorToString( mInputBand ) ); parentElem.appendChild( rasterRendererElem ); } +int QgsRasterSingleColorRenderer::inputBand() const +{ + return mInputBand; +} + +bool QgsRasterSingleColorRenderer::setInputBand( int band ) +{ + if ( !mInput ) + { + mInputBand = band; + return true; + } + else if ( band > 0 && band <= mInput->bandCount() ) + { + mInputBand = band; + return true; + } + return false; +} + QList QgsRasterSingleColorRenderer::usesBands() const { - QList bandList; - for ( int i = 0; i <= bandCount(); i++ ) + QList bands; + if ( mInputBand != -1 ) { - bandList << i; + bands << mInputBand; } - return bandList; + return bands; } diff --git a/src/core/raster/qgsrastersinglecolorrenderer.h b/src/core/raster/qgsrastersinglecolorrenderer.h index 9dfc653e40a..50f7fa94df2 100644 --- a/src/core/raster/qgsrastersinglecolorrenderer.h +++ b/src/core/raster/qgsrastersinglecolorrenderer.h @@ -28,7 +28,7 @@ class QDomElement; /** * \ingroup core - * \brief Raster single color renderer pipe. + * \brief Raster renderer which renders all data pixels using a single color. * \since QGIS 3.38 */ class CORE_EXPORT QgsRasterSingleColorRenderer: public QgsRasterRenderer @@ -36,7 +36,7 @@ class CORE_EXPORT QgsRasterSingleColorRenderer: public QgsRasterRenderer public: //! Creates a single \a color renderer - QgsRasterSingleColorRenderer( QgsRasterInterface *input, QColor color ); + QgsRasterSingleColorRenderer( QgsRasterInterface *input, int band, const QColor &color ); //! QgsRasterSingleColorRenderer cannot be copied. Use clone() instead. QgsRasterSingleColorRenderer( const QgsRasterSingleColorRenderer & ) = delete; @@ -53,16 +53,20 @@ class CORE_EXPORT QgsRasterSingleColorRenderer: public QgsRasterRenderer /** * Returns the single color used by the renderer. + * \see setColor() */ QColor color() const; /** - * Sets the single color used by the renderer. + * Sets the single \a color used by the renderer. + * \see color() */ - void setColor( QColor &color ); + void setColor( const QColor &color ); void writeXml( QDomDocument &doc, QDomElement &parentElem ) const override; + int inputBand() const override; + bool setInputBand( int band ) override; QList usesBands() const override; private: @@ -71,6 +75,7 @@ class CORE_EXPORT QgsRasterSingleColorRenderer: public QgsRasterRenderer const QgsRasterSingleColorRenderer &operator=( const QgsRasterSingleColorRenderer & ); #endif + int mInputBand = -1; QColor mColor; }; diff --git a/src/gui/raster/qgsrastersinglecolorrendererwidget.cpp b/src/gui/raster/qgsrastersinglecolorrendererwidget.cpp index 333f3f38480..eef41fb1396 100644 --- a/src/gui/raster/qgsrastersinglecolorrendererwidget.cpp +++ b/src/gui/raster/qgsrastersinglecolorrendererwidget.cpp @@ -33,7 +33,10 @@ QgsRasterSingleColorRendererWidget::QgsRasterSingleColorRendererWidget( QgsRaste return; } - connect( mColor, &QgsColorButton::colorChanged, this, &QgsRasterSingleColorRendererWidget::colorChanged ); + mBandComboBox->setLayer( layer ); + + connect( mBandComboBox, &QgsRasterBandComboBox::bandChanged, this, [ = ]( int ) { emit widgetChanged(); } ); + connect( mColorButton, &QgsColorButton::colorChanged, this, [ = ]( const QColor & ) { emit widgetChanged(); } ); setFromRenderer( layer->renderer() ); } @@ -52,24 +55,21 @@ QgsRasterRenderer *QgsRasterSingleColorRendererWidget::renderer() return nullptr; } - QgsRasterSingleColorRenderer *renderer = new QgsRasterSingleColorRenderer( provider, mColor->color() ); + QgsRasterSingleColorRenderer *renderer = new QgsRasterSingleColorRenderer( provider, mBandComboBox->currentBand(), mColorButton->color() ); return renderer; } -void QgsRasterSingleColorRendererWidget::colorChanged( const QColor & ) -{ - emit widgetChanged(); -} - void QgsRasterSingleColorRendererWidget::setFromRenderer( const QgsRasterRenderer *r ) { const QgsRasterSingleColorRenderer *scr = dynamic_cast( r ); if ( scr ) { - mColor->setColor( scr->color() ); + mBandComboBox->setBand( scr->inputBand() ); + mColorButton->setColor( scr->color() ); } else { - mColor->setColor( QColor( 0, 0, 0 ) ); + mBandComboBox->setBand( 1 ); + mColorButton->setColor( QColor( 0, 0, 0 ) ); } } diff --git a/src/gui/raster/qgsrastersinglecolorrendererwidget.h b/src/gui/raster/qgsrastersinglecolorrendererwidget.h index 3ebd16f8515..55dc343d2f6 100644 --- a/src/gui/raster/qgsrastersinglecolorrendererwidget.h +++ b/src/gui/raster/qgsrastersinglecolorrendererwidget.h @@ -46,9 +46,6 @@ class GUI_EXPORT QgsRasterSingleColorRendererWidget: public QgsRasterRendererWid */ void setFromRenderer( const QgsRasterRenderer *r ); - private slots: - void colorChanged( const QColor &color ); - }; #endif // QGSRASTERSINGLECOLORRENDERERWIDGET_H diff --git a/src/ui/qgsrastersinglecolorrendererwidgetbase.ui b/src/ui/qgsrastersinglecolorrendererwidgetbase.ui index 7b974f8c79c..b8b1276227d 100644 --- a/src/ui/qgsrastersinglecolorrendererwidgetbase.ui +++ b/src/ui/qgsrastersinglecolorrendererwidgetbase.ui @@ -29,14 +29,24 @@ + + + Band + + + + + + + Color - - + + 0 @@ -80,6 +90,11 @@ QToolButton
qgscolorbutton.h
+ + QgsRasterBandComboBox + QComboBox +
qgsrasterbandcombobox.h
+
diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 0a818a94dac..7b1402a7b32 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -291,7 +291,7 @@ ADD_PYTHON_TEST(PyQgsSingleBandColorDataRenderer test_qgssinglebandcolordatarend ADD_PYTHON_TEST(PyQgsSingleBandGrayRenderer test_qgssinglebandgrayrenderer.py) ADD_PYTHON_TEST(PyQgsSingleBandPseudoColorRenderer test_qgssinglebandpseudocolorrenderer.py) ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py) -ADD_PYTHON_TEST(PyQgsRasterSingleColorRenderer test_rasterqgssinglecolorrenderer.py) +ADD_PYTHON_TEST(PyQgsRasterSingleColorRenderer test_qgsrastersinglecolorrenderer.py) ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py) ADD_PYTHON_TEST(PyQgsSphere test_qgssphere.py) ADD_PYTHON_TEST(PyQgsSvgCache test_qgssvgcache.py) diff --git a/tests/src/python/test_qgsrastersinglecolorrenderer.py b/tests/src/python/test_qgsrastersinglecolorrenderer.py index 9c2d8d56f08..6ef5a3a420d 100644 --- a/tests/src/python/test_qgsrastersinglecolorrenderer.py +++ b/tests/src/python/test_qgsrastersinglecolorrenderer.py @@ -36,8 +36,11 @@ class TestQgsRasterSingleBandGrayRenderer(QgisTestCase): self.assertTrue(layer.isValid(), f'Raster not loaded: {path}') renderer = QgsRasterSingleColorRenderer(layer.dataProvider(), - QColor(255, 0, 0)) + 1, + QColor(255, 0, 0)) + self.assertEqual(renderer.inputBand(), 1) + self.assertEqual(renderer.usesBands(), [1]) self.assertEqual(renderer.color(), QColor(255, 0, 0)) renderer.setColor(QColor(0, 255, 0)) self.assertEqual(renderer.color(), QColor(0, 255, 0))