QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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" ) );
24  if ( expression.isEmpty() )
25  {
26  expression = QStringLiteral( "$geometry" );
27  }
29 
30  if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Marker" ) )
31  {
32  symbolLayer->setSubSymbol( QgsMarkerSymbol::createSimple( properties ) );
33  }
34  else if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Line" ) )
35  {
36  symbolLayer->setSubSymbol( QgsLineSymbol::createSimple( properties ) );
37  }
38  else
39  {
40  symbolLayer->setSubSymbol( QgsFillSymbol::createSimple( properties ) );
41  }
42  symbolLayer->restoreOldDataDefinedProperties( properties );
43 
44  return symbolLayer;
45 }
46 
47 QgsGeometryGeneratorSymbolLayer::QgsGeometryGeneratorSymbolLayer( const QString &expression )
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( QgsStringMap() ) );
66  mSymbol = mFillSymbol.get();
67  }
68  else if ( symbolType == QgsSymbol::Line )
69  {
70  if ( !mLineSymbol )
71  mLineSymbol.reset( QgsLineSymbol::createSimple( QgsStringMap() ) );
72  mSymbol = mLineSymbol.get();
73  }
74  else if ( symbolType == QgsSymbol::Marker )
75  {
76  if ( !mMarkerSymbol )
77  mMarkerSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
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  QgsGeometryGeneratorSymbolLayer *clone = new QgsGeometryGeneratorSymbolLayer( mExpression->expression() );
102 
103  if ( mFillSymbol )
104  clone->mFillSymbol.reset( mFillSymbol->clone() );
105  if ( mLineSymbol )
106  clone->mLineSymbol.reset( mLineSymbol->clone() );
107  if ( mMarkerSymbol )
108  clone->mMarkerSymbol.reset( mMarkerSymbol->clone() );
109 
110  clone->setSymbolType( mSymbolType );
111 
112  copyDataDefinedProperties( clone );
113  copyPaintEffect( clone );
114 
115  return clone;
116 }
117 
119 {
120  QgsStringMap props;
121  props.insert( QStringLiteral( "geometryModifier" ), mExpression->expression() );
122  switch ( mSymbolType )
123  {
124  case QgsSymbol::Marker:
125  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Marker" ) );
126  break;
127  case QgsSymbol::Line:
128  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Line" ) );
129  break;
130  default:
131  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Fill" ) );
132  break;
133  }
134  return props;
135 }
136 
138 {
139  if ( mSymbol )
140  mSymbol->drawPreviewIcon( context.renderContext().painter(), size );
141 }
142 
144 {
145  mExpression.reset( new QgsExpression( exp ) );
146 }
147 
149 {
150  switch ( symbol->type() )
151  {
152  case QgsSymbol::Marker:
153  mMarkerSymbol.reset( static_cast<QgsMarkerSymbol *>( symbol ) );
154  break;
155 
156  case QgsSymbol::Line:
157  mLineSymbol.reset( static_cast<QgsLineSymbol *>( symbol ) );
158  break;
159 
160  case QgsSymbol::Fill:
161  mFillSymbol.reset( static_cast<QgsFillSymbol *>( symbol ) );
162  break;
163 
164  default:
165  break;
166  }
167 
168  setSymbolType( symbol->type() );
169 
170  return true;
171 }
172 
174 {
175  return QgsSymbolLayer::usedAttributes( context )
176  + mSymbol->usedAttributes( context )
177  + mExpression->referencedColumns();
178 }
179 
181 {
182  // we treat geometry generator layers like they have data defined properties,
183  // since the WHOLE layer is based on expressions and requires the full expression
184  // context
185  return true;
186 }
187 
189 {
190  Q_UNUSED( symbol )
191  return true;
192 }
194 {
195  if ( context.feature() )
196  {
197  QgsExpressionContext &expressionContext = context.renderContext().expressionContext();
198 
199  QgsFeature f = expressionContext.feature();
200  QgsGeometry geom = mExpression->evaluate( &expressionContext ).value<QgsGeometry>();
201  f.setGeometry( geom );
202 
203  QgsExpressionContextScope *subSymbolExpressionContextScope = mSymbol->symbolRenderContext()->expressionContextScope();
204 
205  subSymbolExpressionContextScope->setFeature( f );
206 
207  mSymbol->renderFeature( f, context.renderContext(), -1, context.selected() );
208  }
209 }
210 
212 {
213  mSymbol->setColor( color );
214 }
QgsSymbol * subSymbol() override
Returns the symbol&#39;s sub symbol, if present.
Class for parsing and evaluation of expressions (formerly called "search strings").
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr)
Draws an icon of the symbol that occupies an area given by size using the specified painter...
Definition: qgssymbol.cpp:502
void drawPreviewIcon(QgsSymbolRenderContext &context, QSize size) override
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:62
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
Definition: qgssymbol.cpp:1299
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
Definition: qgssymbol.cpp:1310
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
virtual void render(QgsSymbolRenderContext &context)
Will render this symbol layer using the context.
void restoreOldDataDefinedProperties(const QgsStringMap &stringMap)
Restores older data defined properties from string map.
Line symbol.
Definition: qgssymbol.h:87
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QMap< QString, QString > QgsStringMap
Definition: qgis.h:694
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:431
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
SymbolType
Type of the symbol.
Definition: qgssymbol.h:84
QString layerType() const override
Returns a string that represents this layer type.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual QColor color() const
The fill color.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer&#39;s subsymbol. takes ownership of the passed symbol.
QgsStringMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setSymbolType(QgsSymbol::SymbolType symbolType)
Set the type of symbol which should be created.
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
Definition: qgssymbol.cpp:1175
QgsSymbolLayer(const QgsSymbolLayer &other)=delete
QgsSymbolLayer cannot be copied.
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.
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgssymbol.h:703
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style...
Definition: qgssymbol.h:759
QgsExpressionContext & expressionContext()
Gets the expression context.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties...
Marker symbol.
Definition: qgssymbol.h:86
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:718
Fill symbol.
Definition: qgssymbol.h:88
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
void setGeometryExpression(const QString &exp)
Set the expression to generate this geometry.
void setColor(const QColor &color) override
The fill color.
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:121
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:799
static QgsSymbolLayer * create(const QgsStringMap &properties)
bool isCompatibleWithSymbol(QgsSymbol *symbol) const override
Will always return true.
QgsSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
const QgsFeature * feature() const
Returns the current feature being rendered.
Definition: qgssymbol.h:784
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
QgsSymbol::SymbolType symbolType() const
Access the symbol type.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1288
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:456
Hybrid symbol.
Definition: qgssymbol.h:89
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:481
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
Definition: qgssymbol.cpp:1276