QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 {
21  delete mMarkerSymbol;
22  delete mLineSymbol;
23  delete mFillSymbol;
24 }
25 
27 {
28  QString expression = properties.value( QStringLiteral( "geometryModifier" ) );
29  if ( expression.isEmpty() )
30  {
31  expression = QStringLiteral( "$geometry" );
32  }
34 
35  if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Marker" ) )
36  {
37  symbolLayer->setSubSymbol( QgsMarkerSymbol::createSimple( properties ) );
38  }
39  else if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Line" ) )
40  {
41  symbolLayer->setSubSymbol( QgsLineSymbol::createSimple( properties ) );
42  }
43  else
44  {
45  symbolLayer->setSubSymbol( QgsFillSymbol::createSimple( properties ) );
46  }
47  symbolLayer->restoreOldDataDefinedProperties( properties );
48 
49  return symbolLayer;
50 }
51 
52 QgsGeometryGeneratorSymbolLayer::QgsGeometryGeneratorSymbolLayer( const QString &expression )
54  , mExpression( new QgsExpression( expression ) )
55  , mSymbolType( QgsSymbol::Marker )
56 {
57 
58 }
59 
61 {
62  return QStringLiteral( "GeometryGenerator" );
63 }
64 
66 {
67  if ( symbolType == QgsSymbol::Fill )
68  {
69  if ( !mFillSymbol )
70  mFillSymbol = QgsFillSymbol::createSimple( QgsStringMap() );
71  mSymbol = mFillSymbol;
72  }
73  else if ( symbolType == QgsSymbol::Line )
74  {
75  if ( !mLineSymbol )
76  mLineSymbol = QgsLineSymbol::createSimple( QgsStringMap() );
77  mSymbol = mLineSymbol;
78  }
79  else if ( symbolType == QgsSymbol::Marker )
80  {
81  if ( !mMarkerSymbol )
82  mMarkerSymbol = QgsMarkerSymbol::createSimple( QgsStringMap() );
83  mSymbol = mMarkerSymbol;
84  }
85  else
86  Q_ASSERT( false );
87 
88  mSymbolType = symbolType;
89 }
90 
92 {
93  mExpression->prepare( &context.renderContext().expressionContext() );
94 
95  subSymbol()->startRender( context.renderContext() );
96 }
97 
99 {
100  if ( mSymbol )
101  mSymbol->stopRender( context.renderContext() );
102 }
103 
105 {
106  QgsGeometryGeneratorSymbolLayer *clone = new QgsGeometryGeneratorSymbolLayer( mExpression->expression() );
107 
108  if ( mFillSymbol )
109  clone->mFillSymbol = mFillSymbol->clone();
110  if ( mLineSymbol )
111  clone->mLineSymbol = mLineSymbol->clone();
112  if ( mMarkerSymbol )
113  clone->mMarkerSymbol = mMarkerSymbol->clone();
114 
115  clone->setSymbolType( mSymbolType );
116 
117  copyDataDefinedProperties( clone );
118  copyPaintEffect( clone );
119 
120  return clone;
121 }
122 
124 {
125  QgsStringMap props;
126  props.insert( QStringLiteral( "geometryModifier" ), mExpression->expression() );
127  switch ( mSymbolType )
128  {
129  case QgsSymbol::Marker:
130  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Marker" ) );
131  break;
132  case QgsSymbol::Line:
133  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Line" ) );
134  break;
135  default:
136  props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Fill" ) );
137  break;
138  }
139  return props;
140 }
141 
143 {
144  if ( mSymbol )
145  mSymbol->drawPreviewIcon( context.renderContext().painter(), size );
146 }
147 
149 {
150  mExpression.reset( new QgsExpression( exp ) );
151 }
152 
154 {
155  switch ( symbol->type() )
156  {
157  case QgsSymbol::Marker:
158  mMarkerSymbol = static_cast<QgsMarkerSymbol *>( symbol );
159  break;
160 
161  case QgsSymbol::Line:
162  mLineSymbol = static_cast<QgsLineSymbol *>( symbol );
163  break;
164 
165  case QgsSymbol::Fill:
166  mFillSymbol = static_cast<QgsFillSymbol *>( symbol );
167  break;
168 
169  default:
170  break;
171  }
172 
173  setSymbolType( symbol->type() );
174 
175  return true;
176 }
177 
179 {
180  return QgsSymbolLayer::usedAttributes( context )
181  + mSymbol->usedAttributes( context )
182  + mExpression->referencedColumns();
183 }
184 
186 {
187  // we treat geometry generator layers like they have data defined properties,
188  // since the WHOLE layer is based on expressions and requires the full expression
189  // context
190  return true;
191 }
192 
194 {
195  Q_UNUSED( symbol )
196  return true;
197 }
199 {
200  if ( context.feature() )
201  {
202  QgsExpressionContext &expressionContext = context.renderContext().expressionContext();
203 
204  QgsFeature f = expressionContext.feature();
205  QgsGeometry geom = mExpression->evaluate( &expressionContext ).value<QgsGeometry>();
206  f.setGeometry( geom );
207 
208  QgsExpressionContextScope *subSymbolExpressionContextScope = mSymbol->symbolRenderContext()->expressionContextScope();
209 
210  subSymbolExpressionContextScope->setFeature( f );
211 
212  mSymbol->renderFeature( f, context.renderContext(), -1, context.selected() );
213  }
214 }
215 
217 {
218  mSymbol->setColor( color );
219 }
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(QgsSymbolRenderContext &context, QSize size) override
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
Definition: qgssymbol.cpp:1139
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
Definition: qgssymbol.cpp:1150
void startRender(QgsSymbolRenderContext &context) override
void stopRender(QgsSymbolRenderContext &context) override
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
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:86
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:577
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:732
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:920
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:404
QgsSymbol::SymbolType symbolType() const
Access the symbol type.
QgsSymbolLayer(QgsSymbol::SymbolType type, bool locked=false)
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:83
QString layerType() const override
Returns a string that represents this layer type.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1952
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
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 drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr)
Draws an icon of the symbol that occupies an area given by size using the specified painter...
Definition: qgssymbol.cpp:470
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
void setSymbolType(QgsSymbol::SymbolType symbolType)
Set the type of symbol which should be created.
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
Definition: qgssymbol.cpp:1063
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:572
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:85
Fill symbol.
Definition: qgssymbol.h:87
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.
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:734
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.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbol.h:628
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:120
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1003
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1128
bool selected() const
Definition: qgssymbol.h:611
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:654
virtual QColor color() const
The fill color.
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:426
Hybrid symbol.
Definition: qgssymbol.h:88
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1590
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1828
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:450
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
Definition: qgssymbol.cpp:1116