QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 #include "qgsmarkersymbol.h"
19 #include "qgslinesymbol.h"
20 #include "qgsfillsymbol.h"
21 
23 
25 {
26  QString expression = properties.value( QStringLiteral( "geometryModifier" ) ).toString();
27  if ( expression.isEmpty() )
28  {
29  expression = QStringLiteral( "$geometry" );
30  }
32 
33  if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Marker" ) )
34  {
36  }
37  else if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Line" ) )
38  {
40  }
41  else
42  {
44  }
46 
47  return symbolLayer;
48 }
49 
50 QgsGeometryGeneratorSymbolLayer::QgsGeometryGeneratorSymbolLayer( const QString &expression )
51  : QgsSymbolLayer( Qgis::SymbolType::Hybrid )
52  , mExpression( new QgsExpression( expression ) )
53  , mSymbolType( Qgis::SymbolType::Marker )
54 {
55 
56 }
57 
59 {
60  return QStringLiteral( "GeometryGenerator" );
61 }
62 
64 {
66  {
67  if ( !mFillSymbol )
68  mFillSymbol.reset( QgsFillSymbol::createSimple( QVariantMap() ) );
69  mSymbol = mFillSymbol.get();
70  }
71  else if ( symbolType == Qgis::SymbolType::Line )
72  {
73  if ( !mLineSymbol )
74  mLineSymbol.reset( QgsLineSymbol::createSimple( QVariantMap() ) );
75  mSymbol = mLineSymbol.get();
76  }
78  {
79  if ( !mMarkerSymbol )
80  mMarkerSymbol.reset( QgsMarkerSymbol::createSimple( QVariantMap() ) );
81  mSymbol = mMarkerSymbol.get();
82  }
83  else
84  Q_ASSERT( false );
85 
86  mSymbolType = symbolType;
87 }
88 
90 {
91  mExpression->prepare( &context.renderContext().expressionContext() );
92 
93  subSymbol()->startRender( context.renderContext() );
94 }
95 
97 {
98  if ( mSymbol )
99  mSymbol->stopRender( context.renderContext() );
100 }
101 
103 {
104  mRenderingFeature = true;
105  mHasRenderedFeature = false;
106 }
107 
109 {
110  mRenderingFeature = false;
111 }
112 
114 {
115  if ( mFillSymbol )
116  return mFillSymbol->usesMapUnits();
117  else if ( mLineSymbol )
118  return mLineSymbol->usesMapUnits();
119  else if ( mMarkerSymbol )
120  return mMarkerSymbol->usesMapUnits();
121  return false;
122 }
123 
125 {
126  QgsGeometryGeneratorSymbolLayer *clone = new QgsGeometryGeneratorSymbolLayer( mExpression->expression() );
127 
128  if ( mFillSymbol )
129  clone->mFillSymbol.reset( mFillSymbol->clone() );
130  if ( mLineSymbol )
131  clone->mLineSymbol.reset( mLineSymbol->clone() );
132  if ( mMarkerSymbol )
133  clone->mMarkerSymbol.reset( mMarkerSymbol->clone() );
134 
135  clone->setSymbolType( mSymbolType );
136 
139 
140  return clone;
141 }
142 
144 {
145  QVariantMap props;
146  props.insert( QStringLiteral( "geometryModifier" ), mExpression->expression() );
147  switch ( mSymbolType )
148  {
150  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Marker" ) );
151  break;
153  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Line" ) );
154  break;
155  default:
156  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Fill" ) );
157  break;
158  }
159  return props;
160 }
161 
163 {
164  if ( mSymbol )
165  mSymbol->drawPreviewIcon( context.renderContext().painter(), size, nullptr, false, nullptr, context.patchShape() );
166 }
167 
169 {
170  mExpression.reset( new QgsExpression( exp ) );
171 }
172 
174 {
175  switch ( symbol->type() )
176  {
178  mMarkerSymbol.reset( static_cast<QgsMarkerSymbol *>( symbol ) );
179  break;
180 
182  mLineSymbol.reset( static_cast<QgsLineSymbol *>( symbol ) );
183  break;
184 
186  mFillSymbol.reset( static_cast<QgsFillSymbol *>( symbol ) );
187  break;
188 
189  default:
190  break;
191  }
192 
193  setSymbolType( symbol->type() );
194 
195  return true;
196 }
197 
199 {
200  return QgsSymbolLayer::usedAttributes( context )
201  + mSymbol->usedAttributes( context )
202  + mExpression->referencedColumns();
203 }
204 
206 {
207  // we treat geometry generator layers like they have data defined properties,
208  // since the WHOLE layer is based on expressions and requires the full expression
209  // context
210  return true;
211 }
212 
214 {
215  Q_UNUSED( symbol )
216  return true;
217 }
219 {
220  if ( mRenderingFeature && mHasRenderedFeature )
221  return;
222 
223  if ( context.feature() )
224  {
225  QgsExpressionContext &expressionContext = context.renderContext().expressionContext();
226 
227  QgsFeature f = expressionContext.feature();
228  QgsGeometry geom = mExpression->evaluate( &expressionContext ).value<QgsGeometry>();
229  f.setGeometry( geom );
230 
231  QgsExpressionContextScope *subSymbolExpressionContextScope = mSymbol->symbolRenderContext()->expressionContextScope();
232 
233  subSymbolExpressionContextScope->setFeature( f );
234 
235  mSymbol->renderFeature( f, context.renderContext(), -1, context.selected() );
236 
237  if ( mRenderingFeature )
238  mHasRenderedFeature = true;
239  }
240 }
241 
242 void QgsGeometryGeneratorSymbolLayer::setColor( const QColor &color )
243 {
244  mSymbol->setColor( color );
245 }
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:62
SymbolType
Symbol types.
Definition: qgis.h:168
@ Marker
Marker symbol.
@ Line
Line symbol.
@ Fill
Fill symbol.
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 unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:145
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:30
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
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.
void setSymbolType(Qgis::SymbolType symbolType)
Set the type of symbol which should be created.
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.
Qgis::SymbolType symbolType() const
Access the symbol type.
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.
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: qgslinesymbol.h:30
static QgsLineSymbol * createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
A marker symbol type, for rendering Point and MultiPoint geometries.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
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.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
const QgsFeature * feature() const
Returns the current feature being rendered.
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
const QgsLegendPatchShape * patchShape() const
Returns the symbol patch shape, to use if rendering symbol preview icons.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:38
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
Definition: qgssymbol.cpp:1433
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:516
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:562
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:903
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:802
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:541
Qgis::SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:97
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:489