Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsrulebasedrenderer.h - Rule-based renderer (symbology)
3 : : ---------------------
4 : : begin : May 2010
5 : : copyright : (C) 2010 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 : : #ifndef QGSRULEBASEDRENDERER_H
17 : : #define QGSRULEBASEDRENDERER_H
18 : :
19 : : #include "qgis_core.h"
20 : : #include "qgis_sip.h"
21 : : #include "qgsfields.h"
22 : : #include "qgsfeature.h"
23 : : #include "qgis.h"
24 : :
25 : : #include "qgsrenderer.h"
26 : :
27 : : class QgsExpression;
28 : :
29 : : class QgsCategorizedSymbolRenderer;
30 : : class QgsGraduatedSymbolRenderer;
31 : :
32 : : /**
33 : : * \ingroup core
34 : : * \brief Rule based renderer.
35 : : *
36 : : * When drawing a vector layer with rule-based renderer, it goes through
37 : : * the rules and draws features with symbols from rules that match.
38 : : */
39 : : class CORE_EXPORT QgsRuleBasedRenderer : public QgsFeatureRenderer
40 : : {
41 : : public:
42 : : // TODO: use QVarLengthArray instead of QList
43 : :
44 : : enum FeatureFlags
45 : : {
46 : : FeatIsSelected = 1,
47 : : FeatDrawMarkers = 2
48 : : };
49 : :
50 : : /**
51 : : * Feature for rendering by a QgsRuleBasedRenderer. Contains a QgsFeature and some flags.
52 : : * \ingroup core
53 : : */
54 : 0 : struct FeatureToRender
55 : : {
56 : 0 : FeatureToRender( const QgsFeature &_f, int _flags )
57 : 0 : : feat( _f )
58 : 0 : , flags( _flags )
59 : 0 : {}
60 : : QgsFeature feat;
61 : : int flags; // selected and/or draw markers
62 : : };
63 : :
64 : : /**
65 : : * A QgsRuleBasedRenderer rendering job, consisting of a feature to be rendered with a particular symbol.
66 : : * \ingroup core
67 : : */
68 : : struct RenderJob
69 : : {
70 : 0 : RenderJob( QgsRuleBasedRenderer::FeatureToRender &_ftr, QgsSymbol *_s )
71 : 0 : : ftr( _ftr )
72 : 0 : , symbol( _s )
73 : 0 : {}
74 : :
75 : : //! Feature to render
76 : : QgsRuleBasedRenderer::FeatureToRender &ftr;
77 : :
78 : : //! Symbol to render feature with (not owned by this object).
79 : : QgsSymbol *symbol = nullptr;
80 : :
81 : : private:
82 : : #ifdef SIP_RUN
83 : : RenderJob &operator=( const RenderJob & );
84 : : #endif
85 : : };
86 : :
87 : : /**
88 : : * Render level: a list of jobs to be drawn at particular level for a QgsRuleBasedRenderer.
89 : : * \ingroup core
90 : : */
91 : : struct RenderLevel
92 : : {
93 : 0 : explicit RenderLevel( int z ): zIndex( z ) {}
94 : 0 : ~RenderLevel() { qDeleteAll( jobs ); }
95 : : int zIndex;
96 : :
97 : : //! List of jobs to render, owned by this object.
98 : : QList<QgsRuleBasedRenderer::RenderJob *> jobs;
99 : :
100 : : QgsRuleBasedRenderer::RenderLevel &operator=( const QgsRuleBasedRenderer::RenderLevel &rh )
101 : : {
102 : : zIndex = rh.zIndex;
103 : : qDeleteAll( jobs );
104 : : jobs.clear();
105 : : for ( auto it = rh.jobs.constBegin(); it != rh.jobs.constEnd(); ++it )
106 : : {
107 : : jobs << new RenderJob( *( *it ) );
108 : : }
109 : : return *this;
110 : : }
111 : :
112 : 0 : RenderLevel( const QgsRuleBasedRenderer::RenderLevel &other )
113 : 0 : : zIndex( other.zIndex ), jobs()
114 : : {
115 : 0 : for ( auto it = other.jobs.constBegin(); it != other.jobs.constEnd(); ++it )
116 : : {
117 : 0 : jobs << new RenderJob( * ( *it ) );
118 : 0 : }
119 : 0 : }
120 : :
121 : : };
122 : :
123 : : //! Rendering queue: a list of rendering levels
124 : : typedef QList<QgsRuleBasedRenderer::RenderLevel> RenderQueue;
125 : :
126 : : class Rule;
127 : : typedef QList<QgsRuleBasedRenderer::Rule *> RuleList;
128 : :
129 : : /**
130 : : * \ingroup core
131 : : * \brief This class keeps data about a rules for rule-based renderer.
132 : : *
133 : : * A rule consists of a symbol, filter expression and range of scales.
134 : : * If filter is empty, it matches all features.
135 : : * If scale range has both values zero, it matches all scales.
136 : : * If one of the min/max scale denominators is zero, there is no lower/upper bound for scales.
137 : : * A rule matches if both filter and scale range match.
138 : : */
139 : : class CORE_EXPORT Rule
140 : : {
141 : : public:
142 : : //! The result of rendering a rule
143 : : enum RenderResult
144 : : {
145 : : Filtered = 0, //!< The rule does not apply
146 : : Inactive, //!< The rule is inactive
147 : : Rendered //!< Something was rendered
148 : : };
149 : :
150 : : //! Constructor takes ownership of the symbol
151 : : Rule( QgsSymbol *symbol SIP_TRANSFER, int maximumScale = 0, int minimumScale = 0, const QString &filterExp = QString(),
152 : : const QString &label = QString(), const QString &description = QString(), bool elseRule = false );
153 : : ~Rule();
154 : :
155 : : //! Rules cannot be copied
156 : : Rule( const Rule &rh ) = delete;
157 : : //! Rules cannot be copied
158 : : Rule &operator=( const Rule &rh ) = delete;
159 : :
160 : : /**
161 : : * Dump for debug purpose
162 : : * \param indent How many characters to indent. Will increase by two with every of the recursive calls
163 : : * \returns A string representing this rule
164 : : */
165 : : QString dump( int indent = 0 ) const;
166 : :
167 : : /**
168 : : * Returns the attributes used to evaluate the expression of this rule
169 : : * \returns A set of attribute names
170 : : */
171 : : QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
172 : :
173 : : /**
174 : : * Returns TRUE if this rule or one of its children needs the geometry to be applied.
175 : : */
176 : : bool needsGeometry() const;
177 : :
178 : : //! \note available in Python bindings as symbol2
179 : : QgsSymbolList symbols( const QgsRenderContext &context = QgsRenderContext() ) const;
180 : :
181 : : //! \since QGIS 2.6
182 : : QgsLegendSymbolList legendSymbolItems( int currentLevel = -1 ) const;
183 : :
184 : : /**
185 : : * Check if a given feature shall be rendered by this rule
186 : : *
187 : : * \param f The feature to test
188 : : * \param context The context in which the rendering happens
189 : : * \returns TRUE if the feature shall be rendered
190 : : */
191 : : bool isFilterOK( const QgsFeature &f, QgsRenderContext *context = nullptr ) const;
192 : :
193 : : /**
194 : : * Check if this rule applies for a given \a scale.
195 : : * The \a scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
196 : : * If set to 0, it will always return TRUE.
197 : : *
198 : : * \returns If the rule will be evaluated at this scale
199 : : */
200 : : bool isScaleOK( double scale ) const;
201 : :
202 : 0 : QgsSymbol *symbol() { return mSymbol.get(); }
203 : : QString label() const { return mLabel; }
204 : : bool dependsOnScale() const { return mMaximumScale != 0 || mMinimumScale != 0; }
205 : :
206 : : /**
207 : : * Returns the maximum map scale (i.e. most "zoomed in" scale) at which the rule will be active.
208 : : * The scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
209 : : * A scale of 0 indicates no maximum scale visibility.
210 : : * \see minimumScale()
211 : : * \see setMaximumScale()
212 : : * \since QGIS 3.0
213 : : */
214 : 0 : double maximumScale() const { return mMaximumScale; }
215 : :
216 : : /**
217 : : * Returns the minimum map scale (i.e. most "zoomed out" scale) at which the rule will be active.
218 : : * The scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
219 : : * A scale of 0 indicates no minimum scale visibility.
220 : : * \see maximumScale()
221 : : * \see setMinimumScale()
222 : : * \since QGIS 3.0
223 : : */
224 : 0 : double minimumScale() const { return mMinimumScale; }
225 : :
226 : : /**
227 : : * A filter that will check if this rule applies
228 : : * \returns An expression
229 : : */
230 : : QgsExpression *filter() const { return mFilter.get(); }
231 : :
232 : : /**
233 : : * A filter that will check if this rule applies
234 : : * \returns An expression
235 : : */
236 : : QString filterExpression() const { return mFilterExp; }
237 : :
238 : : /**
239 : : * A human readable description for this rule
240 : : *
241 : : * \returns Description
242 : : */
243 : : QString description() const { return mDescription; }
244 : :
245 : : /**
246 : : * Returns if this rule is active
247 : : *
248 : : * \returns TRUE if the rule is active
249 : : */
250 : 0 : bool active() const { return mIsActive; }
251 : :
252 : : /**
253 : : * Unique rule identifier (for identification of rule within renderer)
254 : : * \since QGIS 2.6
255 : : */
256 : 0 : QString ruleKey() const { return mRuleKey; }
257 : :
258 : : /**
259 : : * Override the assigned rule key (should be used just internally by rule-based renderer)
260 : : * \since QGIS 2.6
261 : : */
262 : 0 : void setRuleKey( const QString &key ) { mRuleKey = key; }
263 : :
264 : : //! Sets a new symbol (or NULLPTR). Deletes old symbol.
265 : : void setSymbol( QgsSymbol *sym SIP_TRANSFER );
266 : 0 : void setLabel( const QString &label ) { mLabel = label; }
267 : :
268 : : /**
269 : : * Sets the minimum map \a scale (i.e. most "zoomed out" scale) at which the rule will be active.
270 : : * The \a scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
271 : : * A \a scale of 0 indicates no minimum scale visibility.
272 : : * \see minimumScale()
273 : : * \see setMaximumScale()
274 : : */
275 : : void setMinimumScale( double scale ) { mMinimumScale = scale; }
276 : :
277 : : /**
278 : : * Sets the maximum map \a scale (i.e. most "zoomed in" scale) at which the rule will be active.
279 : : * The \a scale value indicates the scale denominator, e.g. 1000.0 for a 1:1000 map.
280 : : * A \a scale of 0 indicates no maximum scale visibility.
281 : : * \see maximumScale()
282 : : * \see setMinimumScale()
283 : : */
284 : : void setMaximumScale( double scale ) { mMaximumScale = scale; }
285 : :
286 : : /**
287 : : * Set the expression used to check if a given feature shall be rendered with this rule
288 : : *
289 : : * \param filterExp An expression
290 : : */
291 : : void setFilterExpression( const QString &filterExp );
292 : :
293 : : /**
294 : : * Set a human readable description for this rule
295 : : *
296 : : * \param description Description
297 : : */
298 : : void setDescription( const QString &description ) { mDescription = description; }
299 : :
300 : : /**
301 : : * Sets if this rule is active
302 : : * \param state Determines if the rule should be activated or deactivated
303 : : */
304 : 0 : void setActive( bool state ) { mIsActive = state; }
305 : :
306 : : //! clone this rule, return new instance
307 : : QgsRuleBasedRenderer::Rule *clone() const SIP_FACTORY;
308 : :
309 : : //! Saves the symbol layer as SLD
310 : : void toSld( QDomDocument &doc, QDomElement &element, QVariantMap props ) const;
311 : :
312 : : /**
313 : : * Create a rule from the SLD provided in element and for the specified geometry type.
314 : : */
315 : : static QgsRuleBasedRenderer::Rule *createFromSld( QDomElement &element, QgsWkbTypes::GeometryType geomType ) SIP_FACTORY;
316 : :
317 : : QDomElement save( QDomDocument &doc, QgsSymbolMap &symbolMap ) const;
318 : :
319 : : //! prepare the rule for rendering and its children (build active children array)
320 : : bool startRender( QgsRenderContext &context, const QgsFields &fields, QString &filter );
321 : :
322 : : //! Gets all used z-levels from this rule and children
323 : : QSet<int> collectZLevels();
324 : :
325 : : /**
326 : : * assign normalized z-levels [0..N-1] for this rule's symbol for quick access during rendering
327 : : * \note not available in Python bindings
328 : : */
329 : : void setNormZLevels( const QMap<int, int> &zLevelsToNormLevels ) SIP_SKIP;
330 : :
331 : : /**
332 : : * Render a given feature, will recursively call subclasses and only render if the constraints apply.
333 : : *
334 : : * \param featToRender The feature to render
335 : : * \param context The rendering context
336 : : * \param renderQueue The rendering queue to which the feature should be added
337 : : * \returns The result of the rendering. In explicit if the feature is added to the queue or
338 : : * the reason for not rendering the feature.
339 : : */
340 : : QgsRuleBasedRenderer::Rule::RenderResult renderFeature( QgsRuleBasedRenderer::FeatureToRender &featToRender, QgsRenderContext &context, QgsRuleBasedRenderer::RenderQueue &renderQueue );
341 : :
342 : : //! only tell whether a feature will be rendered without actually rendering it
343 : : bool willRenderFeature( const QgsFeature &feature, QgsRenderContext *context = nullptr );
344 : :
345 : : //! tell which symbols will be used to render the feature
346 : : QgsSymbolList symbolsForFeature( const QgsFeature &feature, QgsRenderContext *context = nullptr );
347 : :
348 : : /**
349 : : * Returns which legend keys match the feature
350 : : * \since QGIS 2.14
351 : : */
352 : : QSet< QString > legendKeysForFeature( const QgsFeature &feature, QgsRenderContext *context = nullptr );
353 : :
354 : : /**
355 : : * Returns the list of rules used to render the feature in a specific
356 : : * context.
357 : : *
358 : : * \param feature The feature for which rules have to be find
359 : : * \param context The rendering context
360 : : * \param onlyActive TRUE to search for active rules only, FALSE otherwise
361 : : */
362 : : QgsRuleBasedRenderer::RuleList rulesForFeature( const QgsFeature &feature, QgsRenderContext *context = nullptr, bool onlyActive = true );
363 : :
364 : : /**
365 : : * Stop a rendering process. Used to clean up the internal state of this rule
366 : : *
367 : : * \param context The rendering context
368 : : */
369 : : void stopRender( QgsRenderContext &context );
370 : :
371 : : /**
372 : : * Create a rule from an XML definition
373 : : *
374 : : * \param ruleElem The XML rule element
375 : : * \param symbolMap Symbol map
376 : : *
377 : : * \returns A new rule
378 : : */
379 : : static QgsRuleBasedRenderer::Rule *create( QDomElement &ruleElem, QgsSymbolMap &symbolMap ) SIP_FACTORY;
380 : :
381 : : /**
382 : : * Returns all children rules of this rule
383 : : *
384 : : * \returns A list of rules
385 : : */
386 : 0 : const QgsRuleBasedRenderer::RuleList &children() { return mChildren; }
387 : :
388 : : /**
389 : : * Returns all children, grand-children, grand-grand-children, grand-gra... you get it
390 : : *
391 : : * \returns A list of descendant rules
392 : : */
393 : : QgsRuleBasedRenderer::RuleList descendants() const;
394 : :
395 : : /**
396 : : * The parent rule
397 : : *
398 : : * \returns Parent rule
399 : : */
400 : : QgsRuleBasedRenderer::Rule *parent() { return mParent; }
401 : :
402 : : //! add child rule, take ownership, sets this as parent
403 : : void appendChild( QgsRuleBasedRenderer::Rule *rule SIP_TRANSFER );
404 : :
405 : : //! add child rule, take ownership, sets this as parent
406 : : void insertChild( int i, QgsRuleBasedRenderer::Rule *rule SIP_TRANSFER );
407 : :
408 : : //! delete child rule
409 : : void removeChild( QgsRuleBasedRenderer::Rule *rule );
410 : :
411 : : //! delete child rule
412 : : void removeChildAt( int i );
413 : :
414 : : //! take child rule out, set parent as NULLPTR
415 : : QgsRuleBasedRenderer::Rule *takeChild( QgsRuleBasedRenderer::Rule *rule ) SIP_TRANSFERBACK;
416 : :
417 : : //! take child rule out, set parent as NULLPTR
418 : : QgsRuleBasedRenderer::Rule *takeChildAt( int i ) SIP_TRANSFERBACK;
419 : :
420 : : /**
421 : : * Try to find a rule given its unique key
422 : : * \since QGIS 2.6
423 : : */
424 : : QgsRuleBasedRenderer::Rule *findRuleByKey( const QString &key );
425 : :
426 : : /**
427 : : * Sets if this rule is an ELSE rule
428 : : *
429 : : * \param iselse If TRUE, this rule is an ELSE rule
430 : : */
431 : : void setIsElse( bool iselse );
432 : :
433 : : /**
434 : : * Check if this rule is an ELSE rule
435 : : *
436 : : * \returns TRUE if this rule is an else rule
437 : : */
438 : 0 : bool isElse() const { return mElseRule; }
439 : :
440 : : /**
441 : : * Accepts the specified symbology \a visitor, causing it to visit all child rules associated
442 : : * with the rule.
443 : : *
444 : : * Returns TRUE if the visitor should continue visiting other objects, or FALSE if visiting
445 : : * should be canceled.
446 : : *
447 : : * \since QGIS 3.10
448 : : */
449 : : bool accept( QgsStyleEntityVisitorInterface *visitor ) const;
450 : :
451 : : protected:
452 : : void initFilter();
453 : :
454 : : private:
455 : : #ifdef SIP_RUN
456 : : Rule( const QgsRuleBasedRenderer::Rule &rh );
457 : : #endif
458 : :
459 : : Rule *mParent = nullptr; // parent rule (nullptr only for root rule)
460 : : std::unique_ptr< QgsSymbol > mSymbol;
461 : : double mMaximumScale = 0;
462 : : double mMinimumScale = 0;
463 : : QString mFilterExp, mLabel, mDescription;
464 : : bool mElseRule = false;
465 : : RuleList mChildren;
466 : : RuleList mElseRules;
467 : : bool mIsActive = true; // whether it is enabled or not
468 : :
469 : : QString mRuleKey; // string used for unique identification of rule within renderer
470 : :
471 : : // temporary
472 : : std::unique_ptr< QgsExpression > mFilter;
473 : : // temporary while rendering
474 : : QSet<int> mSymbolNormZLevels;
475 : : RuleList mActiveChildren;
476 : :
477 : : /**
478 : : * Check which child rules are else rules and update the internal list of else rules
479 : : *
480 : : */
481 : : void updateElseRules();
482 : : };
483 : :
484 : : /////
485 : :
486 : : //! Creates a new rule-based renderer instance from XML
487 : : static QgsFeatureRenderer *create( QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
488 : :
489 : : //! Constructs the renderer from given tree of rules (takes ownership)
490 : : QgsRuleBasedRenderer( QgsRuleBasedRenderer::Rule *root SIP_TRANSFER );
491 : : //! Constructor for convenience. Creates a root rule and adds a default rule with symbol (takes ownership)
492 : : QgsRuleBasedRenderer( QgsSymbol *defaultSymbol SIP_TRANSFER );
493 : :
494 : : ~QgsRuleBasedRenderer() override;
495 : :
496 : : //! Returns symbol for current feature. Should not be used individually: there could be more symbols for a feature
497 : : QgsSymbol *symbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const override;
498 : :
499 : : bool renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer = -1, bool selected = false, bool drawVertexMarker = false ) override SIP_THROW( QgsCsException );
500 : :
501 : : void startRender( QgsRenderContext &context, const QgsFields &fields ) override;
502 : :
503 : : void stopRender( QgsRenderContext &context ) override;
504 : :
505 : : QString filter( const QgsFields &fields = QgsFields() ) override;
506 : :
507 : : QSet<QString> usedAttributes( const QgsRenderContext &context ) const override;
508 : :
509 : : bool filterNeedsGeometry() const override;
510 : :
511 : : QgsRuleBasedRenderer *clone() const override SIP_FACTORY;
512 : :
513 : : void toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props = QVariantMap() ) const override;
514 : :
515 : : static QgsFeatureRenderer *createFromSld( QDomElement &element, QgsWkbTypes::GeometryType geomType ) SIP_FACTORY;
516 : :
517 : : QgsSymbolList symbols( QgsRenderContext &context ) const override;
518 : :
519 : : QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) override;
520 : : bool legendSymbolItemsCheckable() const override;
521 : : bool legendSymbolItemChecked( const QString &key ) override;
522 : : void checkLegendSymbolItem( const QString &key, bool state = true ) override;
523 : :
524 : : void setLegendSymbolItem( const QString &key, QgsSymbol *symbol SIP_TRANSFER ) override;
525 : : QgsLegendSymbolList legendSymbolItems() const override;
526 : : QString dump() const override;
527 : : bool willRenderFeature( const QgsFeature &feature, QgsRenderContext &context ) const override;
528 : : QgsSymbolList symbolsForFeature( const QgsFeature &feature, QgsRenderContext &context ) const override;
529 : : QgsSymbolList originalSymbolsForFeature( const QgsFeature &feature, QgsRenderContext &context ) const override;
530 : : QSet<QString> legendKeysForFeature( const QgsFeature &feature, QgsRenderContext &context ) const override;
531 : 0 : QgsFeatureRenderer::Capabilities capabilities() override { return MoreSymbolsPerFeature | Filter | ScaleDependent; }
532 : : bool accept( QgsStyleEntityVisitorInterface *visitor ) const override;
533 : :
534 : : /////
535 : :
536 : : QgsRuleBasedRenderer::Rule *rootRule() { return mRootRule; }
537 : :
538 : : //////
539 : :
540 : : //! take a rule and create a list of new rules based on the categories from categorized symbol renderer
541 : : static void refineRuleCategories( QgsRuleBasedRenderer::Rule *initialRule, QgsCategorizedSymbolRenderer *r );
542 : : //! take a rule and create a list of new rules based on the ranges from graduated symbol renderer
543 : : static void refineRuleRanges( QgsRuleBasedRenderer::Rule *initialRule, QgsGraduatedSymbolRenderer *r );
544 : : //! take a rule and create a list of new rules with intervals of scales given by the passed scale denominators
545 : : static void refineRuleScales( QgsRuleBasedRenderer::Rule *initialRule, QList<int> scales );
546 : :
547 : : /**
548 : : * Creates a new QgsRuleBasedRenderer from an existing \a renderer.
549 : : *
550 : : * Since QGIS 3.20, the optional \a layer parameter is required for conversions of some renderer types.
551 : : *
552 : : * \returns a new renderer if the conversion was possible, otherwise NULLPTR.
553 : : * \since QGIS 2.5
554 : : */
555 : : static QgsRuleBasedRenderer *convertFromRenderer( const QgsFeatureRenderer *renderer, QgsVectorLayer *layer = nullptr ) SIP_FACTORY;
556 : :
557 : : //! helper function to convert the size scale and rotation fields present in some other renderers to data defined symbology
558 : : static void convertToDataDefinedSymbology( QgsSymbol *symbol, const QString &sizeScaleField, const QString &rotationField = QString() );
559 : :
560 : : protected:
561 : : //! the root node with hierarchical list of rules
562 : : Rule *mRootRule = nullptr;
563 : :
564 : : // temporary
565 : : RenderQueue mRenderQueue;
566 : : QList<FeatureToRender> mCurrentFeatures;
567 : :
568 : : QString mFilter;
569 : :
570 : : private:
571 : : #ifdef SIP_RUN
572 : : QgsRuleBasedRenderer( const QgsRuleBasedRenderer & );
573 : : QgsRuleBasedRenderer &operator=( const QgsRuleBasedRenderer & );
574 : : #endif
575 : : };
576 : :
577 : : #endif // QGSRULEBASEDRENDERER_H
|