diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index 9201ed37590..f0dfda08d7d 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -1279,6 +1279,14 @@ Qgis.RasterRendererFlag.baseClass = Qgis Qgis.RasterRendererFlags.baseClass = Qgis RasterRendererFlags = Qgis # dirty hack since SIP seems to introduce the flags in module # monkey patching scoped based enum +Qgis.RasterRendererCapability.UsesMultipleBands.__doc__ = "The renderer utilizes multiple raster bands for color data (note that alpha bands are not considered for this capability)" +Qgis.RasterRendererCapability.__doc__ = "Raster renderer capabilities.\n\n.. versionadded:: 3.48\n\n" + '* ``UsesMultipleBands``: ' + Qgis.RasterRendererCapability.UsesMultipleBands.__doc__ +# -- +Qgis.RasterRendererCapability.baseClass = Qgis +Qgis.RasterRendererCapabilities = lambda flags=0: Qgis.RasterRendererCapability(flags) +Qgis.RasterRendererCapabilities.baseClass = Qgis +RasterRendererCapabilities = Qgis # dirty hack since SIP seems to introduce the flags in module +# monkey patching scoped based enum Qgis.RasterAttributeTableFieldUsage.Generic.__doc__ = "Field usage Generic" Qgis.RasterAttributeTableFieldUsage.PixelCount.__doc__ = "Field usage PixelCount" Qgis.RasterAttributeTableFieldUsage.Name.__doc__ = "Field usage Name" diff --git a/python/PyQt6/core/auto_generated/qgis.sip.in b/python/PyQt6/core/auto_generated/qgis.sip.in index 2557d927de0..eadc3ec4f53 100644 --- a/python/PyQt6/core/auto_generated/qgis.sip.in +++ b/python/PyQt6/core/auto_generated/qgis.sip.in @@ -691,6 +691,14 @@ The development version + enum class RasterRendererCapability /BaseType=IntFlag/ + { + UsesMultipleBands, + }; + + typedef QFlags RasterRendererCapabilities; + + enum class RasterAttributeTableFieldUsage /BaseType=IntEnum/ { Generic, @@ -2859,6 +2867,8 @@ QFlags operator|(Qgis::ProjectReadFlag f1, QFlags operator|(Qgis::RasterRendererFlag f1, QFlags f2); +QFlags operator|(Qgis::RasterRendererCapability f1, QFlags f2); + QFlags operator|(Qgis::RasterTemporalCapabilityFlag f1, QFlags f2); QFlags operator|(Qgis::RelationshipCapability f1, QFlags f2); diff --git a/python/PyQt6/core/auto_generated/raster/qgsrasterrendererregistry.sip.in b/python/PyQt6/core/auto_generated/raster/qgsrasterrendererregistry.sip.in new file mode 100644 index 00000000000..eeb73ec78d7 --- /dev/null +++ b/python/PyQt6/core/auto_generated/raster/qgsrasterrendererregistry.sip.in @@ -0,0 +1,72 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/raster/qgsrasterrendererregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + + +class QgsRasterRendererRegistry +{ +%Docstring(signature="appended") +Registry for raster renderers. + +:py:class:`QgsRasterRendererRegistry` is not usually directly created, but rather accessed through +:py:func:`QgsApplication.rasterRendererRegistry()`. + +.. note:: + + Exposed to Python bindings in QGIS 3.38 +%End + +%TypeHeaderCode +#include "qgsrasterrendererregistry.h" +%End + public: + + QgsRasterRendererRegistry(); +%Docstring +Constructor for QgsRasterRendererRegistry. + +QgsRasterRendererRegistry is not usually directly created, but rather accessed through +:py:func:`QgsApplication.rasterRendererRegistry()`. + +The registry is pre-populated with standard raster renderers. +%End + + + + + QStringList renderersList() const; +%Docstring +Returns a list of the names of registered renderers. +%End + + + Qgis::RasterRendererCapabilities rendererCapabilities( const QString &rendererName ) const; +%Docstring +Returns the capabilities for the renderer with the specified name. + +.. versionadded:: 3.38 +%End + + QgsRasterRenderer *defaultRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle, QgsRasterDataProvider *provider ) const /Factory/; +%Docstring +Creates a default renderer for a raster drawing style (considering user options such as default contrast enhancement). +Caller takes ownership. +%End + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/raster/qgsrasterrendererregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/PyQt6/core/core_auto.sip b/python/PyQt6/core/core_auto.sip index 0f1a068e200..71eb28b16c0 100644 --- a/python/PyQt6/core/core_auto.sip +++ b/python/PyQt6/core/core_auto.sip @@ -642,6 +642,7 @@ %Include auto_generated/raster/qgsrasterpyramid.sip %Include auto_generated/raster/qgsrasterrange.sip %Include auto_generated/raster/qgsrasterrenderer.sip +%Include auto_generated/raster/qgsrasterrendererregistry.sip %Include auto_generated/raster/qgsrasterrendererutils.sip %Include auto_generated/raster/qgsrasterresamplefilter.sip %Include auto_generated/raster/qgsrasterresampler.sip diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index 7481285da9d..8de9a1a5d29 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -1253,6 +1253,13 @@ Qgis.RasterRendererFlag.baseClass = Qgis Qgis.RasterRendererFlags.baseClass = Qgis RasterRendererFlags = Qgis # dirty hack since SIP seems to introduce the flags in module # monkey patching scoped based enum +Qgis.RasterRendererCapability.UsesMultipleBands.__doc__ = "The renderer utilizes multiple raster bands for color data (note that alpha bands are not considered for this capability)" +Qgis.RasterRendererCapability.__doc__ = "Raster renderer capabilities.\n\n.. versionadded:: 3.48\n\n" + '* ``UsesMultipleBands``: ' + Qgis.RasterRendererCapability.UsesMultipleBands.__doc__ +# -- +Qgis.RasterRendererCapability.baseClass = Qgis +Qgis.RasterRendererCapabilities.baseClass = Qgis +RasterRendererCapabilities = Qgis # dirty hack since SIP seems to introduce the flags in module +# monkey patching scoped based enum Qgis.RasterAttributeTableFieldUsage.Generic.__doc__ = "Field usage Generic" Qgis.RasterAttributeTableFieldUsage.PixelCount.__doc__ = "Field usage PixelCount" Qgis.RasterAttributeTableFieldUsage.Name.__doc__ = "Field usage Name" diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index cb1e8df0340..830419e8222 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -691,6 +691,14 @@ The development version + enum class RasterRendererCapability + { + UsesMultipleBands, + }; + + typedef QFlags RasterRendererCapabilities; + + enum class RasterAttributeTableFieldUsage { Generic, @@ -2859,6 +2867,8 @@ QFlags operator|(Qgis::ProjectReadFlag f1, QFlags operator|(Qgis::RasterRendererFlag f1, QFlags f2); +QFlags operator|(Qgis::RasterRendererCapability f1, QFlags f2); + QFlags operator|(Qgis::RasterTemporalCapabilityFlag f1, QFlags f2); QFlags operator|(Qgis::RelationshipCapability f1, QFlags f2); diff --git a/python/core/auto_generated/raster/qgsrasterrendererregistry.sip.in b/python/core/auto_generated/raster/qgsrasterrendererregistry.sip.in new file mode 100644 index 00000000000..eeb73ec78d7 --- /dev/null +++ b/python/core/auto_generated/raster/qgsrasterrendererregistry.sip.in @@ -0,0 +1,72 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/raster/qgsrasterrendererregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + + +class QgsRasterRendererRegistry +{ +%Docstring(signature="appended") +Registry for raster renderers. + +:py:class:`QgsRasterRendererRegistry` is not usually directly created, but rather accessed through +:py:func:`QgsApplication.rasterRendererRegistry()`. + +.. note:: + + Exposed to Python bindings in QGIS 3.38 +%End + +%TypeHeaderCode +#include "qgsrasterrendererregistry.h" +%End + public: + + QgsRasterRendererRegistry(); +%Docstring +Constructor for QgsRasterRendererRegistry. + +QgsRasterRendererRegistry is not usually directly created, but rather accessed through +:py:func:`QgsApplication.rasterRendererRegistry()`. + +The registry is pre-populated with standard raster renderers. +%End + + + + + QStringList renderersList() const; +%Docstring +Returns a list of the names of registered renderers. +%End + + + Qgis::RasterRendererCapabilities rendererCapabilities( const QString &rendererName ) const; +%Docstring +Returns the capabilities for the renderer with the specified name. + +.. versionadded:: 3.38 +%End + + QgsRasterRenderer *defaultRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle, QgsRasterDataProvider *provider ) const /Factory/; +%Docstring +Creates a default renderer for a raster drawing style (considering user options such as default contrast enhancement). +Caller takes ownership. +%End + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/raster/qgsrasterrendererregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/core/core_auto.sip b/python/core/core_auto.sip index 0f1a068e200..71eb28b16c0 100644 --- a/python/core/core_auto.sip +++ b/python/core/core_auto.sip @@ -642,6 +642,7 @@ %Include auto_generated/raster/qgsrasterpyramid.sip %Include auto_generated/raster/qgsrasterrange.sip %Include auto_generated/raster/qgsrasterrenderer.sip +%Include auto_generated/raster/qgsrasterrendererregistry.sip %Include auto_generated/raster/qgsrasterrendererutils.sip %Include auto_generated/raster/qgsrasterresamplefilter.sip %Include auto_generated/raster/qgsrasterresampler.sip diff --git a/src/core/qgis.h b/src/core/qgis.h index 7a690087ec9..2f2f10b7aa3 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -1163,6 +1163,25 @@ class CORE_EXPORT Qgis Q_ENUM( RasterRendererFlag ) Q_FLAG( RasterRendererFlags ) + /** + * Raster renderer capabilities. + * + * \since QGIS 3.48 + */ + enum class RasterRendererCapability : int SIP_ENUM_BASETYPE( IntFlag ) + { + UsesMultipleBands = 1 << 0, //!< The renderer utilizes multiple raster bands for color data (note that alpha bands are not considered for this capability) + }; + Q_ENUM( RasterRendererCapability ) + + /** + * Raster renderer capabilities. + * + * \since QGIS 3.38 + */ + Q_DECLARE_FLAGS( RasterRendererCapabilities, RasterRendererCapability ) + Q_FLAG( RasterRendererCapabilities ) + /** * \brief The RasterAttributeTableFieldUsage enum represents the usage of a Raster Attribute Table field. * \note Directly mapped from GDALRATFieldUsage enum values. @@ -4977,6 +4996,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::ProfileGeneratorFlags ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::ProjectCapabilities ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::ProjectReadFlags ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::RasterRendererFlags ) +Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::RasterRendererCapabilities ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::RasterTemporalCapabilityFlags ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::RelationshipCapabilities ) Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::RenderContextFlags ) diff --git a/src/core/raster/qgsrasterrendererregistry.cpp b/src/core/raster/qgsrasterrendererregistry.cpp index 7fdcca9b229..772b362d5e2 100644 --- a/src/core/raster/qgsrasterrendererregistry.cpp +++ b/src/core/raster/qgsrasterrendererregistry.cpp @@ -35,9 +35,10 @@ QgsRasterRendererRegistryEntry::QgsRasterRendererRegistryEntry( const QString &name, const QString &visibleName, QgsRasterRendererCreateFunc rendererFunction, - QgsRasterRendererWidgetCreateFunc widgetFunction ) + QgsRasterRendererWidgetCreateFunc widgetFunction, Qgis::RasterRendererCapabilities capabilities ) : name( name ) , visibleName( visibleName ) + , capabilities( capabilities ) , rendererCreateFunction( rendererFunction ) , widgetCreateFunction( widgetFunction ) { @@ -52,7 +53,8 @@ QgsRasterRendererRegistry::QgsRasterRendererRegistry() { // insert items in a particular order, which is returned in renderersList() insert( QgsRasterRendererRegistryEntry( QStringLiteral( "multibandcolor" ), QObject::tr( "Multiband color" ), - QgsMultiBandColorRenderer::create, nullptr ) ); + QgsMultiBandColorRenderer::create, nullptr, + Qgis::RasterRendererCapability::UsesMultipleBands ) ); insert( QgsRasterRendererRegistryEntry( QStringLiteral( "paletted" ), QObject::tr( "Paletted/Unique values" ), QgsPalettedRasterRenderer::create, nullptr ) ); insert( QgsRasterRendererRegistryEntry( QStringLiteral( "singlebandgray" ), QObject::tr( "Singleband gray" ), QgsSingleBandGrayRenderer::create, nullptr ) ); @@ -109,6 +111,16 @@ QList< QgsRasterRendererRegistryEntry > QgsRasterRendererRegistry::entries() con return result; } +Qgis::RasterRendererCapabilities QgsRasterRendererRegistry::rendererCapabilities( const QString &rendererName ) const +{ + const QHash< QString, QgsRasterRendererRegistryEntry >::const_iterator it = mEntries.constFind( rendererName ); + if ( it != mEntries.constEnd() ) + { + return it.value().capabilities; + } + return Qgis::RasterRendererCapabilities(); +} + QgsRasterRenderer *QgsRasterRendererRegistry::defaultRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle, QgsRasterDataProvider *provider ) const { if ( !provider || provider->bandCount() < 1 ) diff --git a/src/core/raster/qgsrasterrendererregistry.h b/src/core/raster/qgsrasterrendererregistry.h index 8230221d440..424b2a94596 100644 --- a/src/core/raster/qgsrasterrendererregistry.h +++ b/src/core/raster/qgsrasterrendererregistry.h @@ -18,11 +18,6 @@ #ifndef QGSRASTERRENDERERREGISTRY_H #define QGSRASTERRENDERERREGISTRY_H - -#define SIP_NO_FILE - - - #include "qgis_core.h" #include "qgis.h" #include @@ -36,17 +31,26 @@ class QgsRasterRendererWidget; class QgsRasterDataProvider; class QgsRectangle; +#ifndef SIP_RUN typedef QgsRasterRenderer *( *QgsRasterRendererCreateFunc )( const QDomElement &, QgsRasterInterface *input ); typedef QgsRasterRendererWidget *( *QgsRasterRendererWidgetCreateFunc )( QgsRasterLayer *, const QgsRectangle &extent ); /** * \ingroup core * \brief Registry for raster renderer entries. + * + * \note Not available in Python bindings */ struct CORE_EXPORT QgsRasterRendererRegistryEntry { + + /** + * Constructor for QgsRasterRendererRegistryEntry. + * + * Since QGIS 3.38, the \a capabilities argument can be used to specify renderer capabilities. + */ QgsRasterRendererRegistryEntry( const QString &name, const QString &visibleName, QgsRasterRendererCreateFunc rendererFunction, - QgsRasterRendererWidgetCreateFunc widgetFunction ); + QgsRasterRendererWidgetCreateFunc widgetFunction, Qgis::RasterRendererCapabilities capabilities = Qgis::RasterRendererCapabilities() ); /** * Constructor for QgsRasterRendererRegistryEntry. @@ -54,11 +58,21 @@ struct CORE_EXPORT QgsRasterRendererRegistryEntry QgsRasterRendererRegistryEntry() = default; QString name; QString visibleName; //visible (and translatable) name + + /** + * Renderer capabilities. + * + * \since QGIS 3.38 + */ + Qgis::RasterRendererCapabilities capabilities; + QIcon icon(); QgsRasterRendererCreateFunc rendererCreateFunction = nullptr ; //pointer to create function QgsRasterRendererWidgetCreateFunc widgetCreateFunction = nullptr ; //pointer to create function for renderer widget }; +#endif + /** * \ingroup core * \brief Registry for raster renderers. @@ -66,25 +80,67 @@ struct CORE_EXPORT QgsRasterRendererRegistryEntry * QgsRasterRendererRegistry is not usually directly created, but rather accessed through * QgsApplication::rasterRendererRegistry(). * - * \note not available in Python bindings + * \note Exposed to Python bindings in QGIS 3.38 */ class CORE_EXPORT QgsRasterRendererRegistry { public: + /** + * Constructor for QgsRasterRendererRegistry. + * + * QgsRasterRendererRegistry is not usually directly created, but rather accessed through + * QgsApplication::rasterRendererRegistry(). + * + * The registry is pre-populated with standard raster renderers. + */ QgsRasterRendererRegistry(); - void insert( const QgsRasterRendererRegistryEntry &entry ); - void insertWidgetFunction( const QString &rendererName, QgsRasterRendererWidgetCreateFunc func ); - bool rendererData( const QString &rendererName, QgsRasterRendererRegistryEntry &data ) const; + /** + * Inserts a new \a entry into the registry. + * + * \note Not available in Python bindings + */ + void insert( const QgsRasterRendererRegistryEntry &entry ) SIP_SKIP; + + /** + * Sets the widget creation function for a renderer. + * + * \note Not available in Python bindings + */ + void insertWidgetFunction( const QString &rendererName, QgsRasterRendererWidgetCreateFunc func ) SIP_SKIP; + + /** + * Retrieves renderer data from the registry. + * + * \note Not available in Python bindings + */ + bool rendererData( const QString &rendererName, QgsRasterRendererRegistryEntry &data ) const SIP_SKIP; + + /** + * Returns a list of the names of registered renderers. + */ QStringList renderersList() const; - QList< QgsRasterRendererRegistryEntry > entries() const; + + /** + * Returns the list of registered renderers. + * + * \note Not available in Python bindings + */ + QList< QgsRasterRendererRegistryEntry > entries() const SIP_SKIP; + + /** + * Returns the capabilities for the renderer with the specified name. + * + * \since QGIS 3.38 + */ + Qgis::RasterRendererCapabilities rendererCapabilities( const QString &rendererName ) const; /** * Creates a default renderer for a raster drawing style (considering user options such as default contrast enhancement). * Caller takes ownership. */ - QgsRasterRenderer *defaultRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle, QgsRasterDataProvider *provider ) const; + QgsRasterRenderer *defaultRendererForDrawingStyle( Qgis::RasterDrawingStyle drawingStyle, QgsRasterDataProvider *provider ) const SIP_FACTORY; private: QHash< QString, QgsRasterRendererRegistryEntry > mEntries; diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 2943264d74e..916a6c27b18 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -264,6 +264,7 @@ ADD_PYTHON_TEST(PyQgsRasterColorRampShader test_qgsrastercolorrampshader.py) ADD_PYTHON_TEST(PyQgsRasterLineSymbolLayer test_qgsrasterlinesymbollayer.py) ADD_PYTHON_TEST(PyQgsRasterPipe test_qgsrasterpipe.py) ADD_PYTHON_TEST(PyQgsRasterRange test_qgsrasterrange.py) +ADD_PYTHON_TEST(PyQgsRasterRendererRegistry test_qgsrasterrendererregistry.py) ADD_PYTHON_TEST(PyQgsRasterRendererUtils test_qgsrasterrendererutils.py) ADD_PYTHON_TEST(PyQgsRasterResampler test_qgsrasterresampler.py) ADD_PYTHON_TEST(PyQgsRasterTransparency test_qgsrastertransparency.py) diff --git a/tests/src/python/test_qgsrasterrendererregistry.py b/tests/src/python/test_qgsrasterrendererregistry.py new file mode 100644 index 00000000000..b57ba82d835 --- /dev/null +++ b/tests/src/python/test_qgsrasterrendererregistry.py @@ -0,0 +1,51 @@ +"""QGIS Unit tests for QgsRasterRendererRegistry + +.. note:: 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. +""" +from qgis.core import ( + Qgis, + QgsRasterRendererRegistry +) +import unittest +from qgis.testing import start_app, QgisTestCase + +from utilities import unitTestDataPath + +# Convenience instances in case you may need them +# not used in this test +start_app() +TEST_DATA_DIR = unitTestDataPath() + + +class TestQgsRasterRendererRegistry(QgisTestCase): + + def test_registered(self): + """ + Test that standard renderers are registered + """ + registry = QgsRasterRendererRegistry() + self.assertIn('multibandcolor', registry.renderersList()) + self.assertIn('singlebandgray', registry.renderersList()) + self.assertIn('singlebandpseudocolor', registry.renderersList()) + self.assertIn('singlebandcolordata', registry.renderersList()) + self.assertIn('hillshade', registry.renderersList()) + self.assertIn('paletted', registry.renderersList()) + self.assertIn('contour', registry.renderersList()) + + def test_capabilities(self): + """ + Test retrieving renderer capabilities + """ + registry = QgsRasterRendererRegistry() + self.assertFalse(registry.rendererCapabilities('not a renderer')) + self.assertEqual(registry.rendererCapabilities('multibandcolor'), + Qgis.RasterRendererCapability.UsesMultipleBands) + self.assertEqual(registry.rendererCapabilities('singlebandgray'), + Qgis.RasterRendererCapabilities()) + + +if __name__ == '__main__': + unittest.main()