QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgsgeometrygeneratorsymbollayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometrygeneratorsymbollayer.cpp
3  ---------------------
4  begin : November 2015
5  copyright : (C) 2015 by Matthias Kuhn
6  email : matthias at opengis dot ch
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 
17 #include "qgsgeometry.h"
18 
20 
22 {
23  QString expression = properties.value( QStringLiteral( "geometryModifier" ) ).toString();
24  if ( expression.isEmpty() )
25  {
26  expression = QStringLiteral( "$geometry" );
27  }
29 
30  if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Marker" ) )
31  {
33  }
34  else if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Line" ) )
35  {
37  }
38  else
39  {
41  }
43 
44  return symbolLayer;
45 }
46 
47 QgsGeometryGeneratorSymbolLayer::QgsGeometryGeneratorSymbolLayer( const QString &expression )
48  : QgsSymbolLayer( QgsSymbol::Hybrid )
49  , mExpression( new QgsExpression( expression ) )
50  , mSymbolType( QgsSymbol::Marker )
51 {
52 
53 }
54 
56 {
57  return QStringLiteral( "GeometryGenerator" );
58 }
59 
61 {
62  if ( symbolType == QgsSymbol::Fill )
63  {
64  if ( !mFillSymbol )
65  mFillSymbol.reset( QgsFillSymbol::createSimple( QVariantMap() ) );
66  mSymbol = mFillSymbol.get();
67  }
68  else if ( symbolType == QgsSymbol::Line )
69  {
70  if ( !mLineSymbol )
71  mLineSymbol.reset( QgsLineSymbol::createSimple( QVariantMap() ) );
72  mSymbol = mLineSymbol.get();
73  }
74  else if ( symbolType == QgsSymbol::Marker )
75  {
76  if ( !mMarkerSymbol )
77  mMarkerSymbol.reset( QgsMarkerSymbol::createSimple( QVariantMap() ) );
78  mSymbol = mMarkerSymbol.get();
79  }
80  else
81  Q_ASSERT( false );
82 
83  mSymbolType = symbolType;
84 }
85 
87 {
88  mExpression->prepare( &context.renderContext().expressionContext() );
89 
90  subSymbol()->startRender( context.renderContext() );
91 }
92 
94 {
95  if ( mSymbol )
96  mSymbol->stopRender( context.renderContext() );
97 }
98 
100 {
101  mRenderingFeature = true;
102  mHasRenderedFeature = false;
103 }
104 
106 {
107  mRenderingFeature = false;
108 }
109 
111 {
112  if ( mFillSymbol )
113  return mFillSymbol->usesMapUnits();
114  else if ( mLineSymbol )
115  return mLineSymbol->usesMapUnits();
116  else if ( mMarkerSymbol )
117  return mMarkerSymbol->usesMapUnits();
118  return false;
119 }
120 
122 {
123  QgsGeometryGeneratorSymbolLayer *clone = new QgsGeometryGeneratorSymbolLayer( mExpression->expression() );
124 
125  if ( mFillSymbol )
126  clone->mFillSymbol.reset( mFillSymbol->clone() );
127  if ( mLineSymbol )
128  clone->mLineSymbol.reset( mLineSymbol->clone() );
129  if ( mMarkerSymbol )
130  clone->mMarkerSymbol.reset( mMarkerSymbol->clone() );
131 
132  clone->setSymbolType( mSymbolType );
133 
136 
137  return clone;
138 }
139 
141 {
142  QVariantMap props;
143  props.insert( QStringLiteral( "geometryModifier" ), mExpression->expression() );
144  switch ( mSymbolType )
145  {
146  case QgsSymbol::Marker:
147  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Marker" ) );
148  break;
149  case QgsSymbol::Line:
150  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Line" ) );
151  break;
152  default:
153  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Fill" ) );
154  break;
155  }
156  return props;
157 }
158 
160 {
161  if ( mSymbol )
162  mSymbol->drawPreviewIcon( context.renderContext().painter(), size, nullptr, false, nullptr, context.patchShape() );
163 }
164 
166 {
167  mExpression.reset( new QgsExpression( exp ) );
168 }
169 
171 {
172  switch ( symbol->type() )
173  {
174  case QgsSymbol::Marker:
175  mMarkerSymbol.reset( static_cast<QgsMarkerSymbol *>( symbol ) );
176  break;
177 
178  case QgsSymbol::Line:
179  mLineSymbol.reset( static_cast<QgsLineSymbol *>( symbol ) );
180  break;
181 
182  case QgsSymbol::Fill:
183  mFillSymbol.reset( static_cast<QgsFillSymbol *>( symbol ) );
184  break;
185 
186  default:
187  break;
188  }
189 
190  setSymbolType( symbol->type() );
191 
192  return true;
193 }
194 
196 {
197  return QgsSymbolLayer::usedAttributes( context )
198  + mSymbol->usedAttributes( context )
199  + mExpression->referencedColumns();
200 }
201 
203 {
204  // we treat geometry generator layers like they have data defined properties,
205  // since the WHOLE layer is based on expressions and requires the full expression
206  // context
207  return true;
208 }
209 
211 {
212  Q_UNUSED( symbol )
213  return true;
214 }
216 {
217  if ( mRenderingFeature && mHasRenderedFeature )
218  return;
219 
220  if ( context.feature() )
221  {
222  QgsExpressionContext &expressionContext = context.renderContext().expressionContext();
223 
224  QgsFeature f = expressionContext.feature();
225  QgsGeometry geom = mExpression->evaluate( &expressionContext ).value<QgsGeometry>();
226  f.setGeometry( geom );
227 
228  QgsExpressionContextScope *subSymbolExpressionContextScope = mSymbol->symbolRenderContext()->expressionContextScope();
229 
230  subSymbolExpressionContextScope->setFeature( f );
231 
232  mSymbol->renderFeature( f, context.renderContext(), -1, context.selected() );
233 
234  if ( mRenderingFeature )
235  mHasRenderedFeature = true;
236  }
237 }
238 
239 void QgsGeometryGeneratorSymbolLayer::setColor( const QColor &color )
240 {
241  mSymbol->setColor( color );
242 }
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
Class for parsing and evaluation of expressions (formerly called "search strings").
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:144
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1307
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Definition: qgssymbol.cpp:1578
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void drawPreviewIcon(QgsSymbolRenderContext &context, QSize size) override
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setGeometryExpression(const QString &exp)
Set the expression to generate this geometry.
QgsSymbol::SymbolType symbolType() const
Access the symbol type.
QString layerType() const override
Returns a string that represents this layer type.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
bool isCompatibleWithSymbol(QgsSymbol *symbol) const override
Will always return true.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setSymbolType(QgsSymbol::SymbolType symbolType)
Set the type of symbol which should be created.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
void setColor(const QColor &color) override
The fill color.
static QgsSymbolLayer * create(const QVariantMap &properties)
Creates the symbol layer.
virtual void render(QgsSymbolRenderContext &context)
Will render this symbol layer using the context.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
QgsSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:1204
static QgsLineSymbol * createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
Definition: qgssymbol.cpp:1567
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:1004
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1556
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
virtual QColor color() const
The fill color.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
Definition: qgssymbol.h:850
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgssymbol.h:794
const QgsFeature * feature() const
Returns the current feature being rendered.
Definition: qgssymbol.h:875
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
Definition: qgssymbol.cpp:1534
const QgsLegendPatchShape * patchShape() const
Returns the symbol patch shape, to use if rendering symbol preview icons.
Definition: qgssymbol.cpp:1544
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:65
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
Definition: qgssymbol.cpp:1417
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:507
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *patchShape=nullptr)
Draws an icon of the symbol that occupies an area given by size using the specified painter.
Definition: qgssymbol.cpp:553
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, int currentVertexMarkerType=0, double currentVertexMarkerSize=0.0) SIP_THROW(QgsCsException)
Render a feature.
Definition: qgssymbol.cpp:890
SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:138
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:789
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:532
SymbolType
Type of the symbol.
Definition: qgssymbol.h:87
@ Line
Line symbol.
Definition: qgssymbol.h:89
@ Fill
Fill symbol.
Definition: qgssymbol.h:90
@ Marker
Marker symbol.
Definition: qgssymbol.h:88
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:480