Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsrenderer.cpp
3 : : ---------------------
4 : : begin : November 2009
5 : : copyright : (C) 2009 by Martin Dobias
6 : : email : wonder dot sk at gmail dot com
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 "qgsrenderer.h"
17 : : #include "qgssymbol.h"
18 : : #include "qgssymbollayerutils.h"
19 : : #include "qgsrulebasedrenderer.h"
20 : :
21 : : #include "qgssinglesymbolrenderer.h" // for default renderer
22 : :
23 : : #include "qgsrendererregistry.h"
24 : :
25 : : #include "qgsrendercontext.h"
26 : : #include "qgsclipper.h"
27 : : #include "qgsgeometry.h"
28 : : #include "qgsgeometrycollection.h"
29 : : #include "qgsfeature.h"
30 : : #include "qgslogger.h"
31 : : #include "qgsvectorlayer.h"
32 : : #include "qgspainteffect.h"
33 : : #include "qgseffectstack.h"
34 : : #include "qgspainteffectregistry.h"
35 : : #include "qgswkbptr.h"
36 : : #include "qgspoint.h"
37 : : #include "qgsproperty.h"
38 : : #include "qgsapplication.h"
39 : :
40 : : #include <QDomElement>
41 : : #include <QDomDocument>
42 : : #include <QPolygonF>
43 : : #include <QThread>
44 : :
45 : 0 : QPointF QgsFeatureRenderer::_getPoint( QgsRenderContext &context, const QgsPoint &point )
46 : : {
47 : 0 : return QgsSymbol::_getPoint( context, point );
48 : : }
49 : :
50 : 0 : void QgsFeatureRenderer::copyRendererData( QgsFeatureRenderer *destRenderer ) const
51 : : {
52 : 0 : if ( !destRenderer || !mPaintEffect )
53 : 0 : return;
54 : :
55 : 0 : destRenderer->setPaintEffect( mPaintEffect->clone() );
56 : 0 : destRenderer->mOrderBy = mOrderBy;
57 : 0 : destRenderer->mOrderByEnabled = mOrderByEnabled;
58 : 0 : }
59 : :
60 : 78 : QgsFeatureRenderer::QgsFeatureRenderer( const QString &type )
61 : 78 : : mType( type )
62 : 78 : , mUsingSymbolLevels( false )
63 : 78 : , mCurrentVertexMarkerType( QgsVectorLayer::Cross )
64 : 78 : , mCurrentVertexMarkerSize( 2 )
65 : 78 : , mForceRaster( false )
66 : 78 : , mOrderByEnabled( false )
67 : 78 : {
68 : 78 : mPaintEffect = QgsPaintEffectRegistry::defaultStack();
69 : 78 : mPaintEffect->setEnabled( false );
70 : 78 : }
71 : :
72 : 62 : QgsFeatureRenderer::~QgsFeatureRenderer()
73 : 62 : {
74 : 62 : delete mPaintEffect;
75 : 62 : }
76 : :
77 : 78 : QgsFeatureRenderer *QgsFeatureRenderer::defaultRenderer( QgsWkbTypes::GeometryType geomType )
78 : : {
79 : 78 : return new QgsSingleSymbolRenderer( QgsSymbol::defaultSymbol( geomType ) );
80 : 0 : }
81 : :
82 : 0 : QgsSymbol *QgsFeatureRenderer::originalSymbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
83 : : {
84 : 0 : return symbolForFeature( feature, context );
85 : : }
86 : :
87 : 0 : QSet< QString > QgsFeatureRenderer::legendKeysForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
88 : : {
89 : 0 : Q_UNUSED( feature )
90 : 0 : Q_UNUSED( context )
91 : 0 : return QSet< QString >();
92 : : }
93 : :
94 : 0 : void QgsFeatureRenderer::startRender( QgsRenderContext &, const QgsFields & )
95 : : {
96 : : #ifdef QGISDEBUG
97 : : if ( !mThread )
98 : : {
99 : : mThread = QThread::currentThread();
100 : : }
101 : : else
102 : : {
103 : : Q_ASSERT_X( mThread == QThread::currentThread(), "QgsFeatureRenderer::startRender", "startRender called in a different thread - use a cloned renderer instead" );
104 : : }
105 : : #endif
106 : 0 : }
107 : :
108 : 0 : void QgsFeatureRenderer::stopRender( QgsRenderContext & )
109 : : {
110 : : #ifdef QGISDEBUG
111 : : Q_ASSERT_X( mThread == QThread::currentThread(), "QgsFeatureRenderer::stopRender", "stopRender called in a different thread - use a cloned renderer instead" );
112 : : #endif
113 : 0 : }
114 : :
115 : 0 : bool QgsFeatureRenderer::usesEmbeddedSymbols() const
116 : : {
117 : 0 : return false;
118 : : }
119 : :
120 : 0 : bool QgsFeatureRenderer::filterNeedsGeometry() const
121 : : {
122 : 0 : return false;
123 : : }
124 : :
125 : 0 : bool QgsFeatureRenderer::renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
126 : : {
127 : : #ifdef QGISDEBUG
128 : : Q_ASSERT_X( mThread == QThread::currentThread(), "QgsFeatureRenderer::renderFeature", "renderFeature called in a different thread - use a cloned renderer instead" );
129 : : #endif
130 : :
131 : 0 : QgsSymbol *symbol = symbolForFeature( feature, context );
132 : 0 : if ( !symbol )
133 : 0 : return false;
134 : :
135 : 0 : renderFeatureWithSymbol( feature, symbol, context, layer, selected, drawVertexMarker );
136 : 0 : return true;
137 : 0 : }
138 : :
139 : 0 : void QgsFeatureRenderer::renderFeatureWithSymbol( const QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
140 : : {
141 : 0 : symbol->renderFeature( feature, context, layer, selected, drawVertexMarker, mCurrentVertexMarkerType, mCurrentVertexMarkerSize );
142 : 0 : }
143 : :
144 : 0 : QString QgsFeatureRenderer::dump() const
145 : : {
146 : 0 : return QStringLiteral( "UNKNOWN RENDERER\n" );
147 : : }
148 : :
149 : 0 : QgsSymbolList QgsFeatureRenderer::symbols( QgsRenderContext &context ) const
150 : : {
151 : 0 : Q_UNUSED( context )
152 : 0 : return QgsSymbolList();
153 : : }
154 : :
155 : 0 : QgsFeatureRenderer *QgsFeatureRenderer::load( QDomElement &element, const QgsReadWriteContext &context )
156 : : {
157 : : // <renderer-v2 type=""> ... </renderer-v2>
158 : :
159 : 0 : if ( element.isNull() )
160 : 0 : return nullptr;
161 : :
162 : : // load renderer
163 : 0 : QString rendererType = element.attribute( QStringLiteral( "type" ) );
164 : :
165 : 0 : QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( rendererType );
166 : 0 : if ( !m )
167 : 0 : return nullptr;
168 : :
169 : 0 : QgsFeatureRenderer *r = m->createRenderer( element, context );
170 : 0 : if ( r )
171 : : {
172 : 0 : r->setUsingSymbolLevels( element.attribute( QStringLiteral( "symbollevels" ), QStringLiteral( "0" ) ).toInt() );
173 : 0 : r->setForceRasterRender( element.attribute( QStringLiteral( "forceraster" ), QStringLiteral( "0" ) ).toInt() );
174 : :
175 : : //restore layer effect
176 : 0 : QDomElement effectElem = element.firstChildElement( QStringLiteral( "effect" ) );
177 : 0 : if ( !effectElem.isNull() )
178 : : {
179 : 0 : r->setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
180 : 0 : }
181 : :
182 : : // restore order by
183 : 0 : QDomElement orderByElem = element.firstChildElement( QStringLiteral( "orderby" ) );
184 : 0 : r->mOrderBy.load( orderByElem );
185 : 0 : r->setOrderByEnabled( element.attribute( QStringLiteral( "enableorderby" ), QStringLiteral( "0" ) ).toInt() );
186 : 0 : }
187 : 0 : return r;
188 : 0 : }
189 : :
190 : 0 : QDomElement QgsFeatureRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
191 : : {
192 : 0 : Q_UNUSED( context )
193 : : // create empty renderer element
194 : 0 : QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
195 : 0 : rendererElem.setAttribute( QStringLiteral( "forceraster" ), ( mForceRaster ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
196 : :
197 : 0 : if ( mPaintEffect && !QgsPaintEffectRegistry::isDefaultStack( mPaintEffect ) )
198 : 0 : mPaintEffect->saveProperties( doc, rendererElem );
199 : :
200 : 0 : if ( !mOrderBy.isEmpty() )
201 : : {
202 : 0 : QDomElement orderBy = doc.createElement( QStringLiteral( "orderby" ) );
203 : 0 : mOrderBy.save( orderBy );
204 : 0 : rendererElem.appendChild( orderBy );
205 : 0 : }
206 : 0 : rendererElem.setAttribute( QStringLiteral( "enableorderby" ), ( mOrderByEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ) );
207 : 0 : return rendererElem;
208 : 0 : }
209 : :
210 : 0 : QgsFeatureRenderer *QgsFeatureRenderer::loadSld( const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage )
211 : : {
212 : 0 : QDomElement element = node.toElement();
213 : 0 : if ( element.isNull() )
214 : 0 : return nullptr;
215 : :
216 : : // get the UserStyle element
217 : 0 : QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
218 : 0 : if ( userStyleElem.isNull() )
219 : : {
220 : : // UserStyle element not found, nothing will be rendered
221 : 0 : errorMessage = QStringLiteral( "Info: UserStyle element not found." );
222 : 0 : return nullptr;
223 : : }
224 : :
225 : : // get the FeatureTypeStyle element
226 : 0 : QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
227 : 0 : if ( featTypeStyleElem.isNull() )
228 : : {
229 : 0 : errorMessage = QStringLiteral( "Info: FeatureTypeStyle element not found." );
230 : 0 : return nullptr;
231 : : }
232 : :
233 : : // create empty FeatureTypeStyle element to merge Rule's from all FeatureTypeStyle's
234 : 0 : QDomElement mergedFeatTypeStyle = featTypeStyleElem.cloneNode( false ).toElement();
235 : :
236 : : // use the RuleRenderer when more rules are present or the rule
237 : : // has filters or min/max scale denominators set,
238 : : // otherwise use the SingleSymbol renderer
239 : 0 : bool needRuleRenderer = false;
240 : 0 : int ruleCount = 0;
241 : :
242 : 0 : while ( !featTypeStyleElem.isNull() )
243 : : {
244 : 0 : QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
245 : 0 : while ( !ruleElem.isNull() )
246 : : {
247 : : // test rule children element to check if we need to create RuleRenderer
248 : : // and if the rule has a symbolizer
249 : 0 : bool hasRendererSymbolizer = false;
250 : 0 : bool hasRuleRenderer = false;
251 : 0 : QDomElement ruleChildElem = ruleElem.firstChildElement();
252 : 0 : while ( !ruleChildElem.isNull() )
253 : : {
254 : : // rule has filter or min/max scale denominator, use the RuleRenderer
255 : 0 : if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
256 : 0 : ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
257 : 0 : ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
258 : : {
259 : 0 : hasRuleRenderer = true;
260 : 0 : }
261 : : // rule has a renderer symbolizer, not a text symbolizer
262 : 0 : else if ( ruleChildElem.localName().endsWith( QLatin1String( "Symbolizer" ) ) &&
263 : 0 : ruleChildElem.localName() != QLatin1String( "TextSymbolizer" ) )
264 : : {
265 : 0 : QgsDebugMsgLevel( QStringLiteral( "Symbolizer element found and not a TextSymbolizer" ), 2 );
266 : 0 : hasRendererSymbolizer = true;
267 : 0 : }
268 : :
269 : 0 : ruleChildElem = ruleChildElem.nextSiblingElement();
270 : : }
271 : :
272 : 0 : if ( hasRendererSymbolizer )
273 : : {
274 : 0 : ruleCount++;
275 : :
276 : : // append a clone of all Rules to the merged FeatureTypeStyle element
277 : 0 : mergedFeatTypeStyle.appendChild( ruleElem.cloneNode().toElement() );
278 : :
279 : 0 : if ( hasRuleRenderer )
280 : : {
281 : 0 : QgsDebugMsgLevel( QStringLiteral( "Filter or Min/MaxScaleDenominator element found: need a RuleRenderer" ), 2 );
282 : 0 : needRuleRenderer = true;
283 : 0 : }
284 : 0 : }
285 : :
286 : : // more rules present, use the RuleRenderer
287 : 0 : if ( ruleCount > 1 )
288 : : {
289 : 0 : QgsDebugMsgLevel( QStringLiteral( "more Rule elements found: need a RuleRenderer" ), 2 );
290 : 0 : needRuleRenderer = true;
291 : 0 : }
292 : :
293 : 0 : ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
294 : 0 : }
295 : 0 : featTypeStyleElem = featTypeStyleElem.nextSiblingElement( QStringLiteral( "FeatureTypeStyle" ) );
296 : 0 : }
297 : :
298 : 0 : QString rendererType;
299 : 0 : if ( needRuleRenderer )
300 : : {
301 : 0 : rendererType = QStringLiteral( "RuleRenderer" );
302 : 0 : }
303 : : else
304 : : {
305 : 0 : rendererType = QStringLiteral( "singleSymbol" );
306 : : }
307 : 0 : QgsDebugMsgLevel( QStringLiteral( "Instantiating a '%1' renderer..." ).arg( rendererType ), 2 );
308 : :
309 : : // create the renderer and return it
310 : 0 : QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( rendererType );
311 : 0 : if ( !m )
312 : : {
313 : 0 : errorMessage = QStringLiteral( "Error: Unable to get metadata for '%1' renderer." ).arg( rendererType );
314 : 0 : return nullptr;
315 : : }
316 : :
317 : 0 : QgsFeatureRenderer *r = m->createRendererFromSld( mergedFeatTypeStyle, geomType );
318 : 0 : return r;
319 : 0 : }
320 : :
321 : 0 : QDomElement QgsFeatureRenderer::writeSld( QDomDocument &doc, const QString &styleName, const QVariantMap &props ) const
322 : : {
323 : 0 : QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
324 : :
325 : 0 : QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
326 : 0 : nameElem.appendChild( doc.createTextNode( styleName ) );
327 : 0 : userStyleElem.appendChild( nameElem );
328 : :
329 : 0 : QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
330 : 0 : toSld( doc, featureTypeStyleElem, props );
331 : 0 : userStyleElem.appendChild( featureTypeStyleElem );
332 : :
333 : 0 : return userStyleElem;
334 : 0 : }
335 : :
336 : 0 : bool QgsFeatureRenderer::legendSymbolItemsCheckable() const
337 : : {
338 : 0 : return false;
339 : : }
340 : :
341 : 0 : bool QgsFeatureRenderer::legendSymbolItemChecked( const QString &key )
342 : : {
343 : 0 : Q_UNUSED( key )
344 : 0 : return false;
345 : : }
346 : :
347 : 0 : void QgsFeatureRenderer::checkLegendSymbolItem( const QString &key, bool state )
348 : : {
349 : 0 : Q_UNUSED( key )
350 : : Q_UNUSED( state )
351 : 0 : }
352 : :
353 : 0 : void QgsFeatureRenderer::setLegendSymbolItem( const QString &key, QgsSymbol *symbol )
354 : : {
355 : 0 : Q_UNUSED( key )
356 : 0 : delete symbol;
357 : 0 : }
358 : :
359 : 0 : QgsLegendSymbolList QgsFeatureRenderer::legendSymbolItems() const
360 : : {
361 : 0 : return QgsLegendSymbolList();
362 : : }
363 : :
364 : 0 : void QgsFeatureRenderer::setVertexMarkerAppearance( int type, double size )
365 : : {
366 : 0 : mCurrentVertexMarkerType = type;
367 : 0 : mCurrentVertexMarkerSize = size;
368 : 0 : }
369 : :
370 : 0 : bool QgsFeatureRenderer::willRenderFeature( const QgsFeature &feature, QgsRenderContext &context ) const
371 : : {
372 : 0 : return nullptr != symbolForFeature( feature, context );
373 : : }
374 : :
375 : 0 : void QgsFeatureRenderer::renderVertexMarker( QPointF pt, QgsRenderContext &context )
376 : : {
377 : 0 : int markerSize = context.convertToPainterUnits( mCurrentVertexMarkerSize, QgsUnitTypes::RenderMillimeters );
378 : 0 : QgsSymbolLayerUtils::drawVertexMarker( pt.x(), pt.y(), *context.painter(),
379 : 0 : static_cast< QgsSymbolLayerUtils::VertexMarkerType >( mCurrentVertexMarkerType ),
380 : 0 : markerSize );
381 : 0 : }
382 : :
383 : 0 : void QgsFeatureRenderer::renderVertexMarkerPolyline( QPolygonF &pts, QgsRenderContext &context )
384 : : {
385 : 0 : const auto constPts = pts;
386 : 0 : for ( QPointF pt : constPts )
387 : 0 : renderVertexMarker( pt, context );
388 : 0 : }
389 : :
390 : 0 : void QgsFeatureRenderer::renderVertexMarkerPolygon( QPolygonF &pts, QList<QPolygonF> *rings, QgsRenderContext &context )
391 : : {
392 : 0 : const auto constPts = pts;
393 : 0 : for ( QPointF pt : constPts )
394 : 0 : renderVertexMarker( pt, context );
395 : :
396 : 0 : if ( rings )
397 : : {
398 : 0 : const auto constRings = *rings;
399 : 0 : for ( const QPolygonF &ring : constRings )
400 : : {
401 : 0 : const auto constRing = ring;
402 : 0 : for ( QPointF pt : constRing )
403 : 0 : renderVertexMarker( pt, context );
404 : 0 : }
405 : 0 : }
406 : 0 : }
407 : :
408 : 0 : QgsSymbolList QgsFeatureRenderer::symbolsForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
409 : : {
410 : 0 : QgsSymbolList lst;
411 : 0 : QgsSymbol *s = symbolForFeature( feature, context );
412 : 0 : if ( s ) lst.append( s );
413 : 0 : return lst;
414 : 0 : }
415 : :
416 : 0 : void QgsFeatureRenderer::modifyRequestExtent( QgsRectangle &extent, QgsRenderContext &context )
417 : : {
418 : 0 : Q_UNUSED( extent )
419 : 0 : Q_UNUSED( context )
420 : 0 : }
421 : :
422 : 0 : QgsSymbolList QgsFeatureRenderer::originalSymbolsForFeature( const QgsFeature &feature, QgsRenderContext &context ) const
423 : : {
424 : 0 : QgsSymbolList lst;
425 : 0 : QgsSymbol *s = originalSymbolForFeature( feature, context );
426 : 0 : if ( s ) lst.append( s );
427 : 0 : return lst;
428 : 0 : }
429 : :
430 : 0 : QgsPaintEffect *QgsFeatureRenderer::paintEffect() const
431 : : {
432 : 0 : return mPaintEffect;
433 : : }
434 : :
435 : 0 : void QgsFeatureRenderer::setPaintEffect( QgsPaintEffect *effect )
436 : : {
437 : 0 : delete mPaintEffect;
438 : 0 : mPaintEffect = effect;
439 : 0 : }
440 : :
441 : 0 : QgsFeatureRequest::OrderBy QgsFeatureRenderer::orderBy() const
442 : : {
443 : 0 : return mOrderBy;
444 : : }
445 : :
446 : 0 : void QgsFeatureRenderer::setOrderBy( const QgsFeatureRequest::OrderBy &orderBy )
447 : : {
448 : 0 : mOrderBy = orderBy;
449 : 0 : }
450 : :
451 : 0 : bool QgsFeatureRenderer::orderByEnabled() const
452 : : {
453 : 0 : return mOrderByEnabled;
454 : : }
455 : :
456 : 0 : void QgsFeatureRenderer::setOrderByEnabled( bool enabled )
457 : : {
458 : 0 : mOrderByEnabled = enabled;
459 : 0 : }
460 : :
461 : 0 : void QgsFeatureRenderer::setEmbeddedRenderer( QgsFeatureRenderer *subRenderer )
462 : : {
463 : 0 : delete subRenderer;
464 : 0 : }
465 : :
466 : 0 : const QgsFeatureRenderer *QgsFeatureRenderer::embeddedRenderer() const
467 : : {
468 : 0 : return nullptr;
469 : : }
470 : :
471 : 0 : bool QgsFeatureRenderer::accept( QgsStyleEntityVisitorInterface * ) const
472 : : {
473 : 0 : return true;
474 : : }
475 : :
476 : 0 : void QgsFeatureRenderer::convertSymbolSizeScale( QgsSymbol *symbol, QgsSymbol::ScaleMethod method, const QString &field )
477 : : {
478 : 0 : if ( symbol->type() == QgsSymbol::Marker )
479 : : {
480 : 0 : QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( symbol );
481 : 0 : if ( QgsSymbol::ScaleArea == QgsSymbol::ScaleMethod( method ) )
482 : : {
483 : 0 : s->setDataDefinedSize( QgsProperty::fromExpression( "coalesce(sqrt(" + QString::number( s->size() ) + " * (" + field + ")),0)" ) );
484 : 0 : }
485 : : else
486 : : {
487 : 0 : s->setDataDefinedSize( QgsProperty::fromExpression( "coalesce(" + QString::number( s->size() ) + " * (" + field + "),0)" ) );
488 : : }
489 : 0 : s->setScaleMethod( QgsSymbol::ScaleDiameter );
490 : 0 : }
491 : 0 : else if ( symbol->type() == QgsSymbol::Line )
492 : : {
493 : 0 : QgsLineSymbol *s = static_cast<QgsLineSymbol *>( symbol );
494 : 0 : s->setDataDefinedWidth( QgsProperty::fromExpression( "coalesce(" + QString::number( s->width() ) + " * (" + field + "),0)" ) );
495 : 0 : }
496 : 0 : }
497 : :
498 : 0 : void QgsFeatureRenderer::convertSymbolRotation( QgsSymbol *symbol, const QString &field )
499 : : {
500 : 0 : if ( symbol->type() == QgsSymbol::Marker )
501 : : {
502 : 0 : QgsMarkerSymbol *s = static_cast<QgsMarkerSymbol *>( symbol );
503 : 0 : QgsProperty dd = QgsProperty::fromExpression( ( s->angle()
504 : 0 : ? QString::number( s->angle() ) + " + "
505 : 0 : : QString() ) + field );
506 : 0 : s->setDataDefinedAngle( dd );
507 : 0 : }
508 : 0 : }
509 : :
510 : 0 : QgsSymbol *QgsSymbolLevelItem::symbol() const
511 : : {
512 : 0 : return mSymbol;
513 : : }
514 : :
515 : 0 : int QgsSymbolLevelItem::layer() const
516 : : {
517 : 0 : return mLayer;
518 : : }
|