QGIS API Documentation  2.99.0-Master (9caa722)
qgsrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrenderer.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsrenderer.h"
17 #include "qgssymbol.h"
18 #include "qgssymbollayerutils.h"
19 #include "qgsrulebasedrenderer.h"
20 
21 #include "qgssinglesymbolrenderer.h" // for default renderer
22 
23 #include "qgsrendererregistry.h"
24 
25 #include "qgsrendercontext.h"
26 #include "qgsclipper.h"
27 #include "qgsgeometry.h"
28 #include "qgsgeometrycollection.h"
29 #include "qgsfeature.h"
30 #include "qgslogger.h"
31 #include "qgsvectorlayer.h"
32 #include "qgspainteffect.h"
33 #include "qgseffectstack.h"
34 #include "qgspainteffectregistry.h"
35 #include "qgswkbptr.h"
36 #include "qgspoint.h"
37 #include "qgsproperty.h"
38 
39 #include <QDomElement>
40 #include <QDomDocument>
41 #include <QPolygonF>
42 
43 QPointF QgsFeatureRenderer::_getPoint( QgsRenderContext &context, const QgsPoint &point )
44 {
45  return QgsSymbol::_getPoint( context, point );
46 }
47 
49 {
50  if ( !destRenderer || !mPaintEffect )
51  return;
52 
53  destRenderer->setPaintEffect( mPaintEffect->clone() );
54  destRenderer->mOrderBy = mOrderBy;
55  destRenderer->mOrderByEnabled = mOrderByEnabled;
56 }
57 
59  : mType( type )
60  , mUsingSymbolLevels( false )
63  , mForceRaster( false )
64  , mOrderByEnabled( false )
65 {
67  mPaintEffect->setEnabled( false );
68 }
69 
71 {
72  delete mPaintEffect;
73 }
74 
76 {
77  return new QgsSingleSymbolRenderer( QgsSymbol::defaultSymbol( geomType ) );
78 }
79 
81 {
82  return symbolForFeature( feature, context );
83 }
84 
86 {
87  Q_UNUSED( feature );
88  Q_UNUSED( context );
89  return QSet< QString >();
90 }
91 
93 {
94  return false;
95 }
96 
97 bool QgsFeatureRenderer::renderFeature( QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
98 {
99  QgsSymbol *symbol = symbolForFeature( feature, context );
100  if ( !symbol )
101  return false;
102 
103  renderFeatureWithSymbol( feature, symbol, context, layer, selected, drawVertexMarker );
104  return true;
105 }
106 
107 void QgsFeatureRenderer::renderFeatureWithSymbol( QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
108 {
109  symbol->renderFeature( feature, context, layer, selected, drawVertexMarker, mCurrentVertexMarkerType, mCurrentVertexMarkerSize );
110 }
111 
113 {
114  return QStringLiteral( "UNKNOWN RENDERER\n" );
115 }
116 
117 QgsFeatureRenderer *QgsFeatureRenderer::load( QDomElement &element, const QgsReadWriteContext &context )
118 {
119  // <renderer-v2 type=""> ... </renderer-v2>
120 
121  if ( element.isNull() )
122  return nullptr;
123 
124  // load renderer
125  QString rendererType = element.attribute( QStringLiteral( "type" ) );
126 
128  if ( !m )
129  return nullptr;
130 
131  QgsFeatureRenderer *r = m->createRenderer( element, context );
132  if ( r )
133  {
134  r->setUsingSymbolLevels( element.attribute( QStringLiteral( "symbollevels" ), QStringLiteral( "0" ) ).toInt() );
135  r->setForceRasterRender( element.attribute( QStringLiteral( "forceraster" ), QStringLiteral( "0" ) ).toInt() );
136 
137  //restore layer effect
138  QDomElement effectElem = element.firstChildElement( QStringLiteral( "effect" ) );
139  if ( !effectElem.isNull() )
140  {
141  r->setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
142  }
143 
144  // restore order by
145  QDomElement orderByElem = element.firstChildElement( QStringLiteral( "orderby" ) );
146  r->mOrderBy.load( orderByElem );
147  r->setOrderByEnabled( element.attribute( QStringLiteral( "enableorderby" ), QStringLiteral( "0" ) ).toInt() );
148  }
149  return r;
150 }
151 
152 QDomElement QgsFeatureRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
153 {
154  Q_UNUSED( context );
155  // create empty renderer element
156  QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
157  rendererElem.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? "1" : "0" ) );
158 
160  mPaintEffect->saveProperties( doc, rendererElem );
161 
162  if ( !mOrderBy.isEmpty() )
163  {
164  QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
165  mOrderBy.save( orderBy );
166  rendererElem.appendChild( orderBy );
167  }
168  rendererElem.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? "1" : "0" ) );
169  return rendererElem;
170 }
171 
172 QgsFeatureRenderer *QgsFeatureRenderer::loadSld( const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage )
173 {
174  QDomElement element = node.toElement();
175  if ( element.isNull() )
176  return nullptr;
177 
178  // get the UserStyle element
179  QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
180  if ( userStyleElem.isNull() )
181  {
182  // UserStyle element not found, nothing will be rendered
183  errorMessage = QStringLiteral( "Info: UserStyle element not found." );
184  return nullptr;
185  }
186 
187  // get the FeatureTypeStyle element
188  QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
189  if ( featTypeStyleElem.isNull() )
190  {
191  errorMessage = QStringLiteral( "Info: FeatureTypeStyle element not found." );
192  return nullptr;
193  }
194 
195  // use the RuleRenderer when more rules are present or the rule
196  // has filters or min/max scale denominators set,
197  // otherwise use the SingleSymbol renderer
198  bool needRuleRenderer = false;
199  int ruleCount = 0;
200 
201  QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
202  while ( !ruleElem.isNull() )
203  {
204  ruleCount++;
205 
206  // more rules present, use the RuleRenderer
207  if ( ruleCount > 1 )
208  {
209  QgsDebugMsg( "more Rule elements found: need a RuleRenderer" );
210  needRuleRenderer = true;
211  break;
212  }
213 
214  QDomElement ruleChildElem = ruleElem.firstChildElement();
215  while ( !ruleChildElem.isNull() )
216  {
217  // rule has filter or min/max scale denominator, use the RuleRenderer
218  if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
219  ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
220  ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
221  {
222  QgsDebugMsg( "Filter or Min/MaxScaleDenominator element found: need a RuleRenderer" );
223  needRuleRenderer = true;
224  break;
225  }
226 
227  ruleChildElem = ruleChildElem.nextSiblingElement();
228  }
229 
230  if ( needRuleRenderer )
231  {
232  break;
233  }
234 
235  ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
236  }
237 
238  QString rendererType;
239  if ( needRuleRenderer )
240  {
241  rendererType = QStringLiteral( "RuleRenderer" );
242  }
243  else
244  {
245  rendererType = QStringLiteral( "singleSymbol" );
246  }
247  QgsDebugMsg( QString( "Instantiating a '%1' renderer..." ).arg( rendererType ) );
248 
249  // create the renderer and return it
251  if ( !m )
252  {
253  errorMessage = QStringLiteral( "Error: Unable to get metadata for '%1' renderer." ).arg( rendererType );
254  return nullptr;
255  }
256 
257  QgsFeatureRenderer *r = m->createRendererFromSld( featTypeStyleElem, geomType );
258  return r;
259 }
260 
261 QDomElement QgsFeatureRenderer::writeSld( QDomDocument &doc, const QString &styleName, const QgsStringMap &props ) const
262 {
263  QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
264 
265  QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
266  nameElem.appendChild( doc.createTextNode( styleName ) );
267  userStyleElem.appendChild( nameElem );
268 
269  QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
270  toSld( doc, featureTypeStyleElem, props );
271  userStyleElem.appendChild( featureTypeStyleElem );
272 
273  return userStyleElem;
274 }
275 
277 {
278  return false;
279 }
280 
282 {
283  Q_UNUSED( key );
284  return false;
285 }
286 
287 void QgsFeatureRenderer::checkLegendSymbolItem( const QString &key, bool state )
288 {
289  Q_UNUSED( key );
290  Q_UNUSED( state );
291 }
292 
293 void QgsFeatureRenderer::setLegendSymbolItem( const QString &key, QgsSymbol *symbol )
294 {
295  Q_UNUSED( key );
296  delete symbol;
297 }
298 
300 {
301  return QgsLegendSymbolList();
302 }
303 
305 {
308 }
309 
311 {
312  return nullptr != symbolForFeature( feat, context );
313 }
314 
316 {
317  QgsVectorLayer::drawVertexMarker( pt.x(), pt.y(), *context.painter(),
320 }
321 
323 {
324  Q_FOREACH ( QPointF pt, pts )
325  renderVertexMarker( pt, context );
326 }
327 
328 void QgsFeatureRenderer::renderVertexMarkerPolygon( QPolygonF &pts, QList<QPolygonF> *rings, QgsRenderContext &context )
329 {
330  Q_FOREACH ( QPointF pt, pts )
331  renderVertexMarker( pt, context );
332 
333  if ( rings )
334  {
335  Q_FOREACH ( const QPolygonF &ring, *rings )
336  {
337  Q_FOREACH ( QPointF pt, ring )
338  renderVertexMarker( pt, context );
339  }
340  }
341 }
342 
344 {
345  QgsSymbolList lst;
346  QgsSymbol *s = symbolForFeature( feat, context );
347  if ( s ) lst.append( s );
348  return lst;
349 }
350 
352 {
353  QgsSymbolList lst;
354  QgsSymbol *s = originalSymbolForFeature( feat, context );
355  if ( s ) lst.append( s );
356  return lst;
357 }
358 
360 {
361  return mPaintEffect;
362 }
363 
365 {
366  delete mPaintEffect;
367  mPaintEffect = effect;
368 }
369 
371 {
372  return mOrderBy;
373 }
374 
376 {
377  mOrderBy = orderBy;
378 }
379 
381 {
382  return mOrderByEnabled;
383 }
384 
386 {
387  mOrderByEnabled = enabled;
388 }
389 
391 {
392  if ( symbol->type() == QgsSymbol::Marker )
393  {
394  QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( symbol );
395  if ( QgsSymbol::ScaleArea == QgsSymbol::ScaleMethod( method ) )
396  {
397  s->setDataDefinedSize( QgsProperty::fromExpression( "coalesce(sqrt(" + QString::number( s->size() ) + " * (" + field + ")),0)" ) );
398  }
399  else
400  {
401  s->setDataDefinedSize( QgsProperty::fromExpression( "coalesce(" + QString::number( s->size() ) + " * (" + field + "),0)" ) );
402  }
404  }
405  else if ( symbol->type() == QgsSymbol::Line )
406  {
407  QgsLineSymbol *s = static_cast<QgsLineSymbol *>( symbol );
408  s->setDataDefinedWidth( QgsProperty::fromExpression( "coalesce(" + QString::number( s->width() ) + " * (" + field + "),0)" ) );
409  }
410 }
411 
412 void QgsFeatureRenderer::convertSymbolRotation( QgsSymbol *symbol, const QString &field )
413 {
414  if ( symbol->type() == QgsSymbol::Marker )
415  {
416  QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( symbol );
418  ? QString::number( s->angle() ) + " + "
419  : QString() ) + field );
420  s->setDataDefinedAngle( dd );
421  }
422 }
virtual bool willRenderFeature(QgsFeature &feat, QgsRenderContext &context)
Returns whether the renderer will render a feature or not.
The class is used as a container of context for various read/write operations on other objects...
virtual QgsSymbolList originalSymbolsForFeature(QgsFeature &feat, QgsRenderContext &context)
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
virtual QgsLegendSymbolList legendSymbolItems() const
Returns a list of symbology items for the legend.
void setEnabled(const bool enabled)
Sets whether the effect is enabled.
void setVertexMarkerAppearance(int type, int size)
set type and size of editing vertex markers for subsequent rendering
QList< QgsLegendSymbolItem > QgsLegendSymbolList
QgsFeatureRequest::OrderBy mOrderBy
Definition: qgsrenderer.h:472
Calculate scale by the diameter.
Definition: qgssymbol.h:96
virtual void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgsrenderer.h:275
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
virtual QgsFeatureRenderer * createRendererFromSld(QDomElement &elem, QgsWkbTypes::GeometryType geomType)
QgsFeatureRequest::OrderBy orderBy() const
Get the order in which features shall be processed by this renderer.
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context)
store renderer info to XML element
VertexMarkerType
Editing vertex markers.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual QgsSymbol * originalSymbolForFeature(QgsFeature &feature, QgsRenderContext &context)
Return symbol for feature.
Definition: qgsrenderer.cpp:80
static QPointF _getPoint(QgsRenderContext &context, const QgsPoint &point)
Creates a point in screen coordinates from a QgsPoint in map coordinates.
Definition: qgssymbol.h:320
Base class for visual effects which can be applied to QPicture drawings.
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
void renderVertexMarkerPolyline(QPolygonF &pts, QgsRenderContext &context)
render editing vertex marker for a polyline
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:49
void CORE_EXPORT load(const QDomElement &elem)
Deserialize from XML.
void setUsingSymbolLevels(bool usingSymbolLevels)
Definition: qgsrenderer.h:250
void setDataDefinedAngle(const QgsProperty &property)
Set data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1136
QgsPaintEffect * mPaintEffect
Definition: qgsrenderer.h:458
Line symbol.
Definition: qgssymbol.h:85
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:61
static QPointF _getPoint(QgsRenderContext &context, const QgsPoint &point)
Creates a point in screen coordinates from a wkb string in map coordinates.
Definition: qgsrenderer.cpp:43
QMap< QString, QString > QgsStringMap
Definition: qgis.h:366
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application&#39;s paint effect registry, used for managing paint effects. ...
virtual QgsPaintEffect * clone() const =0
Duplicates an effect by creating a deep copy of the effect.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the renderer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the renderer.
QList< QgsSymbol * > QgsSymbolList
Definition: qgsrenderer.h:43
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
return new default symbol for specified geometry type
Definition: qgssymbol.cpp:254
QString type() const
Definition: qgsrenderer.h:124
virtual QgsSymbolList symbolsForFeature(QgsFeature &feat, QgsRenderContext &context)
Returns list of symbols used for rendering the feature.
static QgsPaintEffect * defaultStack()
Returns a new effect stack consisting of a sensible selection of default effects. ...
void setForceRasterRender(bool forceRaster)
Sets whether the renderer should be rendered to a raster destination.
Definition: qgsrenderer.h:366
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
Calculate scale by the area.
Definition: qgssymbol.h:95
double width() const
Definition: qgssymbol.cpp:1549
virtual QgsFeatureRenderer * createRenderer(QDomElement &elem, const QgsReadWriteContext &context)=0
Return new instance of the renderer given the DOM element.
virtual ~QgsFeatureRenderer()
Definition: qgsrenderer.cpp:70
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, int currentVertexMarkerType=0, int currentVertexMarkerSize=0)
Render a feature.
Definition: qgssymbol.cpp:676
QgsRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
static void convertSymbolSizeScale(QgsSymbol *symbol, QgsSymbol::ScaleMethod method, const QString &field)
virtual bool legendSymbolItemChecked(const QString &key)
items of symbology items in legend is checked
void setScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Definition: qgssymbol.cpp:1401
ScaleMethod
Scale method.
Definition: qgssymbol.h:93
A store for object properties.
Definition: qgsproperty.h:189
static void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y. (Useful to assist vertex editing.)
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:36
bool orderByEnabled() const
Returns whether custom ordering will be applied before features are processed by this renderer...
virtual void checkLegendSymbolItem(const QString &key, bool state=true)
item in symbology was checked
virtual void setLegendSymbolItem(const QString &key, QgsSymbol *symbol)
Sets the symbol to be used for a legend symbol item.
void setDataDefinedWidth(const QgsProperty &property)
Set data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1568
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
void renderVertexMarkerPolygon(QPolygonF &pts, QList< QPolygonF > *rings, QgsRenderContext &context)
render editing vertex marker for a polygon
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:136
static void convertSymbolRotation(QgsSymbol *symbol, const QString &field)
Marker symbol.
Definition: qgssymbol.h:84
virtual QgsSymbol * symbolForFeature(QgsFeature &feature, QgsRenderContext &context)=0
To be overridden.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
SymbolType type() const
Definition: qgssymbol.h:112
double size() const
Returns the size for the whole symbol, which is the maximum size of all marker symbol layers in the s...
Definition: qgssymbol.cpp:1233
int mCurrentVertexMarkerSize
The current size of editing marker.
Definition: qgsrenderer.h:456
static QgsFeatureRenderer * loadSld(const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
Stores metadata about one renderer class.
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
Definition: qgsrenderer.cpp:48
virtual QDomElement writeSld(QDomDocument &doc, const QString &styleName, const QgsStringMap &props=QgsStringMap()) const
create the SLD UserStyle element following the SLD v1.1 specs with the given name ...
virtual QSet< QString > legendKeysForFeature(QgsFeature &feature, QgsRenderContext &context)
Return legend keys matching a specified feature.
Definition: qgsrenderer.cpp:85
virtual bool legendSymbolItemsCheckable() const
items of symbology items in legend should be checkable
void setDataDefinedSize(const QgsProperty &property)
Set data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1310
int mCurrentVertexMarkerType
The current type of editing marker.
Definition: qgsrenderer.h:454
void renderFeatureWithSymbol(QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker)
static QgsFeatureRenderer * defaultRenderer(QgsWkbTypes::GeometryType geomType)
return a new renderer - used by default in vector layers
Definition: qgsrenderer.cpp:75
virtual bool filterNeedsGeometry() const
Returns true if this renderer requires the geometry to apply the filter.
Definition: qgsrenderer.cpp:92
Represents a vector layer which manages a vector based data sets.
QgsFeatureRenderer(const QString &type)
Definition: qgsrenderer.cpp:58
void setOrderByEnabled(bool enabled)
Sets whether custom ordering should be applied before features are processed by this renderer...
static QgsRendererRegistry * rendererRegistry()
Returns the application&#39;s renderer registry, used for managing vector layer renderers.
double angle() const
Returns the marker angle for the whole symbol.
Definition: qgssymbol.cpp:1113
virtual bool renderFeature(QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false)
Render a feature using this renderer in the given context.
Definition: qgsrenderer.cpp:97
Represents a list of OrderByClauses, with the most important first and the least important last...
void renderVertexMarker(QPointF pt, QgsRenderContext &context)
render editing vertex marker at specified point
virtual QString dump() const
Returns debug information about this renderer.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.