QGIS API Documentation 3.39.0-Master (699c004a5df)
Loading...
Searching...
No Matches
qgssinglebandpseudocolorrenderer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgssinglebandpseudocolorrenderer.cpp
3 ------------------------------------
4 begin : January 2012
5 copyright : (C) 2012 by Marco Hugentobler
6 email : marco at sourcepole dot ch
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgscolorramp.h"
20#include "qgscolorrampshader.h"
21#include "qgsrastershader.h"
25
26#include <QDomDocument>
27#include <QDomElement>
28#include <QImage>
29
31 : QgsRasterRenderer( input, QStringLiteral( "singlebandpseudocolor" ) )
32 , mShader( shader )
33 , mBand( band )
34 , mClassificationMin( std::numeric_limits<double>::quiet_NaN() )
35 , mClassificationMax( std::numeric_limits<double>::quiet_NaN() )
36{
37}
38
40{
41 setInputBand( bandNo );
42}
43
45{
46 return mBand;
47}
48
50{
51 if ( !mInput )
52 {
53 mBand = band;
54 return true;
55 }
56 else if ( band > 0 && band <= mInput->bandCount() )
57 {
58 mBand = band;
59 return true;
60 }
61 return false;
62}
63
65{
66 mClassificationMin = min;
67 if ( auto *lShader = shader() )
68 {
69 QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( lShader->rasterShaderFunction() );
70 if ( colorRampShader )
71 {
72 colorRampShader->setMinimumValue( min );
73 }
74 }
75}
76
78{
79 mClassificationMax = max;
80 if ( auto *lShader = shader() )
81 {
82 QgsColorRampShader *colorRampShader = dynamic_cast<QgsColorRampShader *>( lShader->rasterShaderFunction() );
83 if ( colorRampShader )
84 {
85 colorRampShader->setMaximumValue( max );
86 }
87 }
88}
89
91{
92 QgsRasterShader *shader = nullptr;
93
94 if ( mShader )
95 {
96 shader = new QgsRasterShader( mShader->minimumValue(), mShader->maximumValue() );
97
98 // Shader function
99 const QgsColorRampShader *origColorRampShader = dynamic_cast<const QgsColorRampShader *>( mShader->rasterShaderFunction() );
100
101 if ( origColorRampShader )
102 {
103 QgsColorRampShader *colorRampShader = new QgsColorRampShader( *origColorRampShader );
104 shader->setRasterShaderFunction( colorRampShader );
105 }
106 }
108 renderer->copyCommonProperties( this );
109
110 return renderer;
111}
112
117
119{
120 mShader.reset( shader );
121}
122
123void QgsSingleBandPseudoColorRenderer::createShader( QgsColorRamp *colorRamp, Qgis::ShaderInterpolationMethod colorRampType, Qgis::ShaderClassificationMethod classificationMode, int classes, bool clip, const QgsRectangle &extent )
124{
125 if ( mBand == -1 || classificationMin() >= classificationMax() )
126 {
127 return;
128 }
129
130 QgsColorRampShader *colorRampShader = new QgsColorRampShader( classificationMin(), classificationMax(), colorRamp, colorRampType, classificationMode );
131 colorRampShader->classifyColorRamp( classes, mBand, extent, input() );
132 colorRampShader->setClip( clip );
133
134 QgsRasterShader *rasterShader = new QgsRasterShader();
135 rasterShader->setRasterShaderFunction( colorRampShader );
136 setShader( rasterShader );
137}
138
140{
141 if ( elem.isNull() )
142 {
143 return nullptr;
144 }
145
146 const int band = elem.attribute( QStringLiteral( "band" ), QStringLiteral( "-1" ) ).toInt();
147 QgsRasterShader *shader = nullptr;
148 const QDomElement rasterShaderElem = elem.firstChildElement( QStringLiteral( "rastershader" ) );
149 if ( !rasterShaderElem.isNull() )
150 {
151 shader = new QgsRasterShader();
152 shader->readXml( rasterShaderElem );
153 }
154
156 r->readXml( elem );
157
158 // TODO: add _readXML in superclass?
159 r->setClassificationMin( elem.attribute( QStringLiteral( "classificationMin" ), QStringLiteral( "NaN" ) ).toDouble() );
160 r->setClassificationMax( elem.attribute( QStringLiteral( "classificationMax" ), QStringLiteral( "NaN" ) ).toDouble() );
161
162 // Backward compatibility with serialization of QGIS 2.X era
163 const QString minMaxOrigin = elem.attribute( QStringLiteral( "classificationMinMaxOrigin" ) );
164 if ( !minMaxOrigin.isEmpty() )
165 {
166 if ( minMaxOrigin.contains( QLatin1String( "MinMax" ) ) )
167 {
169 }
170 else if ( minMaxOrigin.contains( QLatin1String( "CumulativeCut" ) ) )
171 {
173 }
174 else if ( minMaxOrigin.contains( QLatin1String( "StdDev" ) ) )
175 {
177 }
178 else
179 {
181 }
182
183 if ( minMaxOrigin.contains( QLatin1String( "FullExtent" ) ) )
184 {
186 }
187 else if ( minMaxOrigin.contains( QLatin1String( "SubExtent" ) ) )
188 {
190 }
191 else
192 {
194 }
195
196 if ( minMaxOrigin.contains( QLatin1String( "Estimated" ) ) )
197 {
199 }
200 else // if ( minMaxOrigin.contains( QLatin1String( "Exact" ) ) )
201 {
203 }
204 }
205
206 return r;
207}
208
209QgsRasterBlock *QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangle const &extent, int width, int height, QgsRasterBlockFeedback *feedback )
210{
211 Q_UNUSED( bandNo )
212
213 std::unique_ptr< QgsRasterBlock > outputBlock( new QgsRasterBlock() );
214 if ( !mInput || !mShader || !mShader->rasterShaderFunction() )
215 {
216 return outputBlock.release();
217 }
218
219
220 const std::shared_ptr< QgsRasterBlock > inputBlock( mInput->block( mBand, extent, width, height, feedback ) );
221 if ( !inputBlock || inputBlock->isEmpty() )
222 {
223 QgsDebugError( QStringLiteral( "No raster data!" ) );
224 return outputBlock.release();
225 }
226
227 //rendering is faster without considering user-defined transparency
228 const bool hasTransparency = usesTransparency();
229
230 std::shared_ptr< QgsRasterBlock > alphaBlock;
231 if ( mAlphaBand > 0 && mAlphaBand != mBand )
232 {
233 alphaBlock.reset( mInput->block( mAlphaBand, extent, width, height, feedback ) );
234 if ( !alphaBlock || alphaBlock->isEmpty() )
235 {
236 return outputBlock.release();
237 }
238 }
239 else if ( mAlphaBand == mBand )
240 {
241 alphaBlock = inputBlock;
242 }
243
244 if ( !outputBlock->reset( Qgis::DataType::ARGB32_Premultiplied, width, height ) )
245 {
246 return outputBlock.release();
247 }
248
249 const QRgb myDefaultColor = renderColorForNodataPixel();
250 QRgb *outputBlockData = outputBlock->colorData();
251 const QgsRasterShaderFunction *fcn = mShader->rasterShaderFunction();
252
253 const qgssize count = ( qgssize )width * height;
254 bool isNoData = false;
255 for ( qgssize i = 0; i < count; i++ )
256 {
257 const double val = inputBlock->valueAndNoData( i, isNoData );
258 if ( isNoData )
259 {
260 outputBlockData[i] = myDefaultColor;
261 continue;
262 }
263
264 int red, green, blue, alpha;
265 if ( !fcn->shade( val, &red, &green, &blue, &alpha ) )
266 {
267 outputBlockData[i] = myDefaultColor;
268 continue;
269 }
270
271 if ( alpha < 255 )
272 {
273 // Working with premultiplied colors, so multiply values by alpha
274 red *= ( alpha / 255.0 );
275 blue *= ( alpha / 255.0 );
276 green *= ( alpha / 255.0 );
277 }
278
279 if ( !hasTransparency )
280 {
281 outputBlockData[i] = qRgba( red, green, blue, alpha );
282 }
283 else
284 {
285 //opacity
286 double currentOpacity = mOpacity;
288 {
289 currentOpacity *= mRasterTransparency->opacityForValue( val );
290 }
291 if ( mAlphaBand > 0 )
292 {
293 const double alpha = alphaBlock->value( i );
294 if ( alpha == 0 )
295 {
296 outputBlock->setColor( i, myDefaultColor );
297 continue;
298 }
299 else
300 {
301 currentOpacity *= alpha / 255.0;
302 }
303 }
304
305 outputBlockData[i] = qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha );
306 }
307 }
308
309 return outputBlock.release();
310}
311
312void QgsSingleBandPseudoColorRenderer::writeXml( QDomDocument &doc, QDomElement &parentElem ) const
313{
314 if ( parentElem.isNull() )
315 {
316 return;
317 }
318
319 QDomElement rasterRendererElem = doc.createElement( QStringLiteral( "rasterrenderer" ) );
320 _writeXml( doc, rasterRendererElem );
321 rasterRendererElem.setAttribute( QStringLiteral( "band" ), mBand );
322 if ( mShader )
323 {
324 mShader->writeXml( doc, rasterRendererElem ); //todo: include color ramp items directly in this renderer
325 }
326 rasterRendererElem.setAttribute( QStringLiteral( "classificationMin" ), QgsRasterBlock::printValue( mClassificationMin ) );
327 rasterRendererElem.setAttribute( QStringLiteral( "classificationMax" ), QgsRasterBlock::printValue( mClassificationMax ) );
328
329 parentElem.appendChild( rasterRendererElem );
330}
331
332QList< QPair< QString, QColor > > QgsSingleBandPseudoColorRenderer::legendSymbologyItems() const
333{
334 QList< QPair< QString, QColor > > symbolItems;
335 if ( mShader )
336 {
337 QgsRasterShaderFunction *shaderFunction = mShader->rasterShaderFunction();
338 if ( shaderFunction )
339 {
340 shaderFunction->legendSymbologyItems( symbolItems );
341 }
342 }
343 return symbolItems;
344}
345
347{
348 QList<int> bandList;
349 if ( mBand != -1 )
350 {
351 bandList << mBand;
352 }
353 return bandList;
354}
355
356void QgsSingleBandPseudoColorRenderer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
357{
358 // create base structure
359 QgsRasterRenderer::toSld( doc, element, props );
360
361 // look for RasterSymbolizer tag
362 const QDomNodeList elements = element.elementsByTagName( QStringLiteral( "sld:RasterSymbolizer" ) );
363 if ( elements.size() == 0 )
364 return;
365
366 // there SHOULD be only one
367 QDomElement rasterSymbolizerElem = elements.at( 0 ).toElement();
368
369 // add Channel Selection tags
370 QDomElement channelSelectionElem = doc.createElement( QStringLiteral( "sld:ChannelSelection" ) );
371 rasterSymbolizerElem.appendChild( channelSelectionElem );
372
373 // for the mapped band
374 QDomElement channelElem = doc.createElement( QStringLiteral( "sld:GrayChannel" ) );
375 channelSelectionElem.appendChild( channelElem );
376
377 // set band
378 QDomElement sourceChannelNameElem = doc.createElement( QStringLiteral( "sld:SourceChannelName" ) );
379 sourceChannelNameElem.appendChild( doc.createTextNode( QString::number( mBand ) ) );
380 channelElem.appendChild( sourceChannelNameElem );
381
382 // add ColorMap tag
383 QDomElement colorMapElem = doc.createElement( QStringLiteral( "sld:ColorMap" ) );
384
385 // set type of ColorMap ramp [ramp, intervals, values]
386 // basing on interpolation algorithm of the raster shader
387 QString rampType = QStringLiteral( "ramp" );
388 const QgsColorRampShader *rampShader = dynamic_cast<const QgsColorRampShader *>( mShader->rasterShaderFunction() );
389 if ( !rampShader )
390 return;
391
392 switch ( rampShader->colorRampType() )
393 {
395 rampType = QStringLiteral( "values" );
396 break;
398 rampType = QStringLiteral( "intervals" );
399 break;
401 rampType = QStringLiteral( "ramp" );
402 break;
403 }
404
405 colorMapElem.setAttribute( QStringLiteral( "type" ), rampType );
406 if ( rampShader->colorRampItemList().size() >= 255 )
407 colorMapElem.setAttribute( QStringLiteral( "extended" ), QStringLiteral( "true" ) );
408 rasterSymbolizerElem.appendChild( colorMapElem );
409
410 // for each color set a ColorMapEntry tag nested into "sld:ColorMap" tag
411 // e.g. <ColorMapEntry color="#EEBE2F" quantity="-300" label="label" opacity="0"/>
412 const QList<QgsColorRampShader::ColorRampItem> classes = rampShader->colorRampItemList();
413 QList<QgsColorRampShader::ColorRampItem>::const_iterator classDataIt = classes.constBegin();
414 for ( ; classDataIt != classes.constEnd(); ++classDataIt )
415 {
416 QDomElement colorMapEntryElem = doc.createElement( QStringLiteral( "sld:ColorMapEntry" ) );
417 colorMapElem.appendChild( colorMapEntryElem );
418
419 // set colorMapEntryElem attributes
420 colorMapEntryElem.setAttribute( QStringLiteral( "color" ), classDataIt->color.name() );
421 colorMapEntryElem.setAttribute( QStringLiteral( "quantity" ), classDataIt->value );
422 colorMapEntryElem.setAttribute( QStringLiteral( "label" ), classDataIt->label );
423 if ( classDataIt->color.alphaF() != 1.0 )
424 {
425 colorMapEntryElem.setAttribute( QStringLiteral( "opacity" ), QString::number( classDataIt->color.alphaF() ) );
426 }
427 }
428}
429
431{
432 if ( const QgsColorRampShader *shader = dynamic_cast< const QgsColorRampShader * >( mShader->rasterShaderFunction() ) )
433 {
434 QgsStyleColorRampEntity entity( shader->sourceColorRamp() );
435 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) ) )
436 return false;
437 }
438
439 return true;
440}
441
442QList<QgsLayerTreeModelLegendNode *> QgsSingleBandPseudoColorRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
443{
444 if ( !mShader )
445 return QList<QgsLayerTreeModelLegendNode *>();
446
447 const QgsColorRampShader *rampShader = dynamic_cast<const QgsColorRampShader *>( mShader->rasterShaderFunction() );
448 if ( !rampShader )
449 return QList<QgsLayerTreeModelLegendNode *>();
450
451 QList<QgsLayerTreeModelLegendNode *> res;
452
453 const QString name = displayBandName( mBand );
454 if ( !name.isEmpty() )
455 {
456 res << new QgsSimpleLegendNode( nodeLayer, name );
457 }
458
459 switch ( rampShader->colorRampType() )
460 {
462 // for interpolated shaders we use a ramp legend node unless the settings flag
463 // to use the continuous legend is not set, in that case we fall through
464 if ( ! rampShader->legendSettings() || rampShader->legendSettings()->useContinuousLegend() )
465 {
466 if ( !rampShader->colorRampItemList().isEmpty() )
467 {
468 res << new QgsColorRampLegendNode( nodeLayer, rampShader->createColorRamp(),
469 rampShader->legendSettings() ? *rampShader->legendSettings() : QgsColorRampLegendNodeSettings(),
470 rampShader->minimumValue(), rampShader->maximumValue() );
471 }
472 break;
473 }
474 [[fallthrough]];
477 {
478 // for all others we use itemised lists
479 const QList< QPair< QString, QColor > > items = legendSymbologyItems();
480 res.reserve( items.size() );
481 for ( const QPair< QString, QColor > &item : items )
482 {
483 res << new QgsRasterSymbolLegendNode( nodeLayer, item.second, item.first );
484 }
485 break;
486 }
487 }
488 return res;
489}
490
495
QFlags< RasterRendererFlag > RasterRendererFlags
Flags which control behavior of raster renderers.
Definition qgis.h:1404
ShaderInterpolationMethod
Color ramp shader interpolation methods.
Definition qgis.h:1335
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
@ Linear
Interpolates the color between two class breaks linearly.
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
@ InternalLayerOpacityHandling
The renderer internally handles the raster layer's opacity, so the default layer level opacity handli...
ShaderClassificationMethod
Color ramp shader classification methods.
Definition qgis.h:1350
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Settings for a color ramp legend node.
bool useContinuousLegend() const
Returns true if a continuous gradient legend will be used.
A legend node which renders a color ramp.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Qgis::ShaderInterpolationMethod colorRampType() const
Returns the color ramp interpolation method.
const QgsColorRampLegendNodeSettings * legendSettings() const
Returns the color ramp shader legend settings.
QList< QgsColorRampShader::ColorRampItem > colorRampItemList() const
Returns the custom color map.
void setClip(bool clip)
Sets whether the shader should not render values out of range.
QgsColorRamp * createColorRamp() const
Creates a gradient color ramp from shader settings.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
Abstract base class for color ramps.
Layer tree node points to a map layer.
Feedback object tailored for raster block reading.
Raster data container.
static QString printValue(double value, bool localized=false)
Print double value with all necessary significant digits.
Base class for processing filters like renderers, reprojector, resampler etc.
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr)=0
Read block of data using given extent and size.
QString displayBandName(int bandNumber) const
Generates a friendly, descriptive name for the specified bandNumber.
QgsRasterInterface * mInput
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterInterface * input() const
Current input.
void setExtent(QgsRasterMinMaxOrigin::Extent extent)
Sets the extent.
@ Estimated
Approximated statistics.
void setLimits(QgsRasterMinMaxOrigin::Limits limits)
Sets the limits.
void setStatAccuracy(QgsRasterMinMaxOrigin::StatAccuracy accuracy)
Sets the statistics accuracy.
@ CurrentCanvas
Current extent of the canvas (at the time of computation) is used to compute statistics.
@ WholeRaster
Whole raster is used to compute statistics.
@ StdDev
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
@ MinMax
Real min-max values.
@ CumulativeCut
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ].
Raster renderer pipe that applies colors to a raster.
double mOpacity
Global alpha value (0-1)
int mAlphaBand
Read alpha value from band.
QRgb renderColorForNodataPixel() const
Returns the color for the renderer to use to represent nodata pixels.
const QgsRasterMinMaxOrigin & minMaxOrigin() const
Returns const reference to origin of min/max values.
void _writeXml(QDomDocument &doc, QDomElement &rasterRendererElem) const
Write upper class info into rasterrenderer element (called by writeXml method of subclasses)
int bandCount() const override
Gets number of bands.
QgsRasterMinMaxOrigin mMinMaxOrigin
Origin of min/max values.
QgsRasterTransparency * mRasterTransparency
Raster transparency per color or value. Overwrites global alpha value.
bool usesTransparency() const
void copyCommonProperties(const QgsRasterRenderer *other, bool copyMinMaxOrigin=true)
Copies common properties like opacity / transparency data from other renderer.
virtual void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
void readXml(const QDomElement &rendererElem) override
Sets base class members from xml. Usually called from create() methods of subclasses.
The raster shade function applies a shader to a pixel at render time - typically used to render grays...
virtual void legendSymbologyItems(QList< QPair< QString, QColor > > &symbolItems) const
Returns legend symbology items if provided by renderer.
double maximumValue() const
Returns the minimum value for the raster shader.
virtual bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlpha) const
Generates an new RGBA value based on one input value.
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
double minimumValue() const
Returns the maximum value for the raster shader.
Interface for all raster shaders.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads shader state from an XML element.
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
Implementation of legend node interface for displaying raster legend entries.
double opacityForValue(double value) const
Returns the opacity (as a value from 0 to 1) for a single value pixel.
A rectangle specified with double values.
Implementation of legend node interface for displaying arbitrary label with icon.
Raster renderer pipe for single band pseudocolor.
QgsSingleBandPseudoColorRenderer * clone() const override
Clone itself, create deep copy.
QList< QPair< QString, QColor > > legendSymbologyItems() const override
Returns symbology items if provided by renderer.
void writeXml(QDomDocument &doc, QDomElement &parentElem) const override
Write base class members to xml.
Q_DECL_DEPRECATED void setBand(int bandNo)
Sets the band used by the renderer.
void setShader(QgsRasterShader *shader)
Takes ownership of the shader.
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
QgsRasterShader * shader()
Returns the raster shader.
QList< int > usesBands() const override
Returns a list of band numbers used by the renderer.
bool setInputBand(int band) override
Attempts to set the input band for the renderer.
QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
Qgis::RasterRendererFlags flags() const override
Returns flags which dictate renderer behavior.
QgsSingleBandPseudoColorRenderer(QgsRasterInterface *input, int band=-1, QgsRasterShader *shader=nullptr)
Note: takes ownership of QgsRasterShader.
int inputBand() const override
Returns the input band for the renderer, or -1 if no input band is available.
static QgsRasterRenderer * create(const QDomElement &elem, QgsRasterInterface *input)
void createShader(QgsColorRamp *colorRamp=nullptr, Qgis::ShaderInterpolationMethod colorRampType=Qgis::ShaderInterpolationMethod::Linear, Qgis::ShaderClassificationMethod classificationMode=Qgis::ShaderClassificationMethod::Continuous, int classes=0, bool clip=false, const QgsRectangle &extent=QgsRectangle())
Creates a color ramp shader.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
bool canCreateRasterAttributeTable() const override
Returns true if the renderer is suitable for attribute table creation.
Q_DECL_DEPRECATED int band() const
Returns the band used by the renderer.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const override
Used from subclasses to create SLD Rule elements following SLD v1.0 specs.
A color ramp entity for QgsStyle databases.
Definition qgsstyle.h:1428
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition qgis.h:6429
#define QgsDebugError(str)
Definition qgslogger.h:38
Contains information relating to the style entity currently being visited.