Branch data Line data Source code
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 : : 16 : : #include "qgsgeometrygeneratorsymbollayer.h" 17 : : #include "qgsgeometry.h" 18 : : 19 : 0 : QgsGeometryGeneratorSymbolLayer::~QgsGeometryGeneratorSymbolLayer() = default; 20 : : 21 : 0 : QgsSymbolLayer *QgsGeometryGeneratorSymbolLayer::create( const QVariantMap &properties ) 22 : : { 23 : 0 : QString expression = properties.value( QStringLiteral( "geometryModifier" ) ).toString(); 24 : 0 : if ( expression.isEmpty() ) 25 : : { 26 : 0 : expression = QStringLiteral( "$geometry" ); 27 : 0 : } 28 : 0 : QgsGeometryGeneratorSymbolLayer *symbolLayer = new QgsGeometryGeneratorSymbolLayer( expression ); 29 : : 30 : 0 : if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Marker" ) ) 31 : : { 32 : 0 : symbolLayer->setSubSymbol( QgsMarkerSymbol::createSimple( properties ) ); 33 : 0 : } 34 : 0 : else if ( properties.value( QStringLiteral( "SymbolType" ) ) == QLatin1String( "Line" ) ) 35 : : { 36 : 0 : symbolLayer->setSubSymbol( QgsLineSymbol::createSimple( properties ) ); 37 : 0 : } 38 : : else 39 : : { 40 : 0 : symbolLayer->setSubSymbol( QgsFillSymbol::createSimple( properties ) ); 41 : : } 42 : 0 : symbolLayer->restoreOldDataDefinedProperties( properties ); 43 : : 44 : 0 : return symbolLayer; 45 : 0 : } 46 : : 47 : 0 : QgsGeometryGeneratorSymbolLayer::QgsGeometryGeneratorSymbolLayer( const QString &expression ) 48 : 0 : : QgsSymbolLayer( QgsSymbol::Hybrid ) 49 : 0 : , mExpression( new QgsExpression( expression ) ) 50 : 0 : , mSymbolType( QgsSymbol::Marker ) 51 : 0 : { 52 : : 53 : 0 : } 54 : : 55 : 0 : QString QgsGeometryGeneratorSymbolLayer::layerType() const 56 : : { 57 : 0 : return QStringLiteral( "GeometryGenerator" ); 58 : : } 59 : : 60 : 0 : void QgsGeometryGeneratorSymbolLayer::setSymbolType( QgsSymbol::SymbolType symbolType ) 61 : : { 62 : 0 : if ( symbolType == QgsSymbol::Fill ) 63 : : { 64 : 0 : if ( !mFillSymbol ) 65 : 0 : mFillSymbol.reset( QgsFillSymbol::createSimple( QVariantMap() ) ); 66 : 0 : mSymbol = mFillSymbol.get(); 67 : 0 : } 68 : 0 : else if ( symbolType == QgsSymbol::Line ) 69 : : { 70 : 0 : if ( !mLineSymbol ) 71 : 0 : mLineSymbol.reset( QgsLineSymbol::createSimple( QVariantMap() ) ); 72 : 0 : mSymbol = mLineSymbol.get(); 73 : 0 : } 74 : 0 : else if ( symbolType == QgsSymbol::Marker ) 75 : : { 76 : 0 : if ( !mMarkerSymbol ) 77 : 0 : mMarkerSymbol.reset( QgsMarkerSymbol::createSimple( QVariantMap() ) ); 78 : 0 : mSymbol = mMarkerSymbol.get(); 79 : 0 : } 80 : : else 81 : : Q_ASSERT( false ); 82 : : 83 : 0 : mSymbolType = symbolType; 84 : 0 : } 85 : : 86 : 0 : void QgsGeometryGeneratorSymbolLayer::startRender( QgsSymbolRenderContext &context ) 87 : : { 88 : 0 : mExpression->prepare( &context.renderContext().expressionContext() ); 89 : : 90 : 0 : subSymbol()->startRender( context.renderContext() ); 91 : 0 : } 92 : : 93 : 0 : void QgsGeometryGeneratorSymbolLayer::stopRender( QgsSymbolRenderContext &context ) 94 : : { 95 : 0 : if ( mSymbol ) 96 : 0 : mSymbol->stopRender( context.renderContext() ); 97 : 0 : } 98 : : 99 : 0 : void QgsGeometryGeneratorSymbolLayer::startFeatureRender( const QgsFeature &, QgsRenderContext & ) 100 : : { 101 : 0 : mRenderingFeature = true; 102 : 0 : mHasRenderedFeature = false; 103 : 0 : } 104 : : 105 : 0 : void QgsGeometryGeneratorSymbolLayer::stopFeatureRender( const QgsFeature &, QgsRenderContext & ) 106 : : { 107 : 0 : mRenderingFeature = false; 108 : 0 : } 109 : : 110 : 0 : bool QgsGeometryGeneratorSymbolLayer::usesMapUnits() const 111 : : { 112 : 0 : if ( mFillSymbol ) 113 : 0 : return mFillSymbol->usesMapUnits(); 114 : 0 : else if ( mLineSymbol ) 115 : 0 : return mLineSymbol->usesMapUnits(); 116 : 0 : else if ( mMarkerSymbol ) 117 : 0 : return mMarkerSymbol->usesMapUnits(); 118 : 0 : return false; 119 : 0 : } 120 : 0 : 121 : 0 : QgsSymbolLayer *QgsGeometryGeneratorSymbolLayer::clone() const 122 : : { 123 : 0 : QgsGeometryGeneratorSymbolLayer *clone = new QgsGeometryGeneratorSymbolLayer( mExpression->expression() ); 124 : : 125 : 0 : if ( mFillSymbol ) 126 : 0 : clone->mFillSymbol.reset( mFillSymbol->clone() ); 127 : 0 : if ( mLineSymbol ) 128 : 0 : clone->mLineSymbol.reset( mLineSymbol->clone() ); 129 : 0 : if ( mMarkerSymbol ) 130 : 0 : clone->mMarkerSymbol.reset( mMarkerSymbol->clone() ); 131 : : 132 : 0 : clone->setSymbolType( mSymbolType ); 133 : : 134 : 0 : copyDataDefinedProperties( clone ); 135 : 0 : copyPaintEffect( clone ); 136 : : 137 : 0 : return clone; 138 : 0 : } 139 : : 140 : 0 : QVariantMap QgsGeometryGeneratorSymbolLayer::properties() const 141 : : { 142 : 0 : QVariantMap props; 143 : 0 : props.insert( QStringLiteral( "geometryModifier" ), mExpression->expression() ); 144 : 0 : switch ( mSymbolType ) 145 : : { 146 : : case QgsSymbol::Marker: 147 : 0 : props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Marker" ) ); 148 : 0 : break; 149 : : case QgsSymbol::Line: 150 : 0 : props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Line" ) ); 151 : 0 : break; 152 : : default: 153 : 0 : props.insert( QStringLiteral( "SymbolType" ), QStringLiteral( "Fill" ) ); 154 : 0 : break; 155 : : } 156 : 0 : return props; 157 : 0 : } 158 : : 159 : 0 : void QgsGeometryGeneratorSymbolLayer::drawPreviewIcon( QgsSymbolRenderContext &context, QSize size ) 160 : : { 161 : 0 : if ( mSymbol ) 162 : 0 : mSymbol->drawPreviewIcon( context.renderContext().painter(), size, nullptr, false, nullptr, context.patchShape() ); 163 : 0 : } 164 : : 165 : 0 : void QgsGeometryGeneratorSymbolLayer::setGeometryExpression( const QString &exp ) 166 : : { 167 : 0 : mExpression.reset( new QgsExpression( exp ) ); 168 : 0 : } 169 : : 170 : 0 : bool QgsGeometryGeneratorSymbolLayer::setSubSymbol( QgsSymbol *symbol ) 171 : : { 172 : 0 : switch ( symbol->type() ) 173 : : { 174 : : case QgsSymbol::Marker: 175 : 0 : mMarkerSymbol.reset( static_cast<QgsMarkerSymbol *>( symbol ) ); 176 : 0 : break; 177 : : 178 : : case QgsSymbol::Line: 179 : 0 : mLineSymbol.reset( static_cast<QgsLineSymbol *>( symbol ) ); 180 : 0 : break; 181 : : 182 : : case QgsSymbol::Fill: 183 : 0 : mFillSymbol.reset( static_cast<QgsFillSymbol *>( symbol ) ); 184 : 0 : break; 185 : : 186 : : default: 187 : 0 : break; 188 : : } 189 : : 190 : 0 : setSymbolType( symbol->type() ); 191 : : 192 : 0 : return true; 193 : : } 194 : : 195 : 0 : QSet<QString> QgsGeometryGeneratorSymbolLayer::usedAttributes( const QgsRenderContext &context ) const 196 : : { 197 : 0 : return QgsSymbolLayer::usedAttributes( context ) 198 : 0 : + mSymbol->usedAttributes( context ) 199 : 0 : + mExpression->referencedColumns(); 200 : 0 : } 201 : : 202 : 0 : bool QgsGeometryGeneratorSymbolLayer::hasDataDefinedProperties() const 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 : 0 : return true; 208 : : } 209 : : 210 : 0 : bool QgsGeometryGeneratorSymbolLayer::isCompatibleWithSymbol( QgsSymbol *symbol ) const 211 : : { 212 : : Q_UNUSED( symbol ) 213 : 0 : return true; 214 : : } 215 : 0 : void QgsGeometryGeneratorSymbolLayer::render( QgsSymbolRenderContext &context ) 216 : : { 217 : 0 : if ( mRenderingFeature && mHasRenderedFeature ) 218 : 0 : return; 219 : : 220 : 0 : if ( context.feature() ) 221 : : { 222 : 0 : QgsExpressionContext &expressionContext = context.renderContext().expressionContext(); 223 : : 224 : 0 : QgsFeature f = expressionContext.feature(); 225 : 0 : QgsGeometry geom = mExpression->evaluate( &expressionContext ).value<QgsGeometry>(); 226 : 0 : f.setGeometry( geom ); 227 : : 228 : 0 : QgsExpressionContextScope *subSymbolExpressionContextScope = mSymbol->symbolRenderContext()->expressionContextScope(); 229 : : 230 : 0 : subSymbolExpressionContextScope->setFeature( f ); 231 : : 232 : 0 : mSymbol->renderFeature( f, context.renderContext(), -1, context.selected() ); 233 : : 234 : 0 : if ( mRenderingFeature ) 235 : 0 : mHasRenderedFeature = true; 236 : 0 : } 237 : 0 : } 238 : : 239 : 0 : void QgsGeometryGeneratorSymbolLayer::setColor( const QColor &color ) 240 : : { 241 : 0 : mSymbol->setColor( color ); 242 : 0 : }