QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
qgsrulebasedlabeling.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrulebasedlabeling.cpp
3 ---------------------
4 begin : September 2015
5 copyright : (C) 2015 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 ***************************************************************************/
16
17#include "qgsscaleutils.h"
18#include "qgssldexportcontext.h"
20#include "qgssymbollayerutils.h"
21
22#include <QString>
23
24using namespace Qt::StringLiterals;
25
27 : QgsVectorLayerLabelProvider( layer, QString(), withFeatureLoop, nullptr )
28{
29 mRules.reset( rules.clone() );
30 mRules->rootRule()->createSubProviders( layer, mSubProviders, this );
31}
32
37
38bool QgsRuleBasedLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
39{
40 for ( const auto &subprovider : std::as_const( mSubProviders ) )
41 {
42 subprovider.second->setEngine( mEngine );
43 }
44
45 // populate sub-providers
46 mRules->rootRule()->prepare( context, attributeNames, mSubProviders );
47 return true;
48}
49
50QList<QgsLabelFeature *> QgsRuleBasedLabelProvider::registerFeature( const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
51{
52 // will register the feature to relevant sub-providers
53 return std::get< 1 >( mRules->rootRule()->registerFeature( feature, context, mSubProviders, obstacleGeometry, symbol ) );
54}
55
56QList<QgsAbstractLabelProvider *> QgsRuleBasedLabelProvider::subProviders()
57{
58 QList<QgsAbstractLabelProvider *> lst;
59 for ( const auto &subprovider : std::as_const( mSubProviders ) )
60 {
61 lst << subprovider.second;
62 }
63 return lst;
64}
65
66
68
69QgsRuleBasedLabeling::Rule::Rule( QgsPalLayerSettings *settings, double scaleMinDenom, double scaleMaxDenom, const QString &filterExp, const QString &description, bool elseRule )
70 : mSettings( settings )
71 , mMaximumScale( scaleMinDenom )
72 , mMinimumScale( scaleMaxDenom )
73 , mFilterExp( filterExp )
74 , mDescription( description )
75 , mElseRule( elseRule )
76{
77 if ( mElseRule )
78 mFilterExp = u"ELSE"_s;
79
80 initFilter();
81}
82
84{
85 qDeleteAll( mChildren );
86 // do NOT delete parent
87}
88
90{
91 if ( mSettings.get() == settings )
92 return;
93
94 mSettings.reset( settings );
95}
96
98{
99 RuleList l;
100 for ( Rule *c : mChildren )
101 {
102 l += c;
103 l += c->descendants();
104 }
105 return l;
106}
107
108void QgsRuleBasedLabeling::Rule::initFilter()
109{
110 if ( mFilterExp.trimmed().compare( "ELSE"_L1, Qt::CaseInsensitive ) == 0 )
111 {
112 mElseRule = true;
113 mFilter.reset( );
114 }
115 else if ( mFilterExp.trimmed().isEmpty() )
116 {
117 mElseRule = false;
118 mFilter.reset();
119 }
120 else
121 {
122 mElseRule = false;
123 mFilter = std::make_unique< QgsExpression >( mFilterExp );
124 }
125}
126
127void QgsRuleBasedLabeling::Rule::updateElseRules()
128{
129 mElseRules.clear();
130 for ( Rule *rule : std::as_const( mChildren ) )
131 {
132 if ( rule->isElse() )
133 mElseRules << rule;
134 }
135}
136
138{
139 if ( mSettings && mSettings->format().containsAdvancedEffects() )
140 return true;
141
142 for ( Rule *rule : std::as_const( mChildren ) )
143 {
144 if ( rule->requiresAdvancedEffects() )
145 return true;
146 }
147
148 return false;
149}
150
152{
153 if ( mSettings &&
154 ( mSettings->dataDefinedProperties().isActive( QgsPalLayerSettings::Property::FontBlendMode )
155 || mSettings->dataDefinedProperties().isActive( QgsPalLayerSettings::Property::ShapeBlendMode )
156 || mSettings->dataDefinedProperties().isActive( QgsPalLayerSettings::Property::BufferBlendMode )
157 || mSettings->dataDefinedProperties().isActive( QgsPalLayerSettings::Property::ShadowBlendMode )
158 || mSettings->format().hasNonDefaultCompositionMode() ) )
159 return true;
160
161 for ( Rule *rule : std::as_const( mChildren ) )
162 {
163 if ( rule->hasNonDefaultCompositionMode() )
164 return true;
165 }
166
167 return false;
168}
169
171{
172 // NOTE: if visitEnter returns false it means "don't visit the rule", not "abort all further visitations"
174 return true;
175
176 if ( mSettings )
177 {
178 QgsStyleLabelSettingsEntity entity( *mSettings );
179 if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity ) ) )
180 return false;
181 }
182
183 if ( !mChildren.empty() )
184 {
185 for ( const Rule *rule : mChildren )
186 {
187 if ( !rule->accept( visitor ) )
188 return false;
189 }
190 }
191
192 if ( mParent && !visitor->visitExit( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::SymbolRule, mRuleKey, mDescription ) ) )
193 return false;
194
195 return true;
196}
197
198void QgsRuleBasedLabeling::Rule::subProviderIds( QStringList &list ) const
199{
200 for ( const Rule *rule : std::as_const( mChildren ) )
201 {
202 if ( rule->settings() )
203 list << rule->ruleKey();
204
205 rule->subProviderIds( list );
206 }
207}
208
209
211{
212 mChildren.append( rule );
213 rule->mParent = this;
214 updateElseRules();
215}
216
218{
219 mChildren.insert( i, rule );
220 rule->mParent = this;
221 updateElseRules();
222}
223
225{
226 delete mChildren.at( i );
227 mChildren.removeAt( i );
228 updateElseRules();
229}
230
232{
233 // we could use a hash / map for search if this will be slow...
234
235 if ( key == mRuleKey )
236 return this;
237
238 for ( Rule *rule : mChildren )
239 {
240 const Rule *r = rule->findRuleByKey( key );
241 if ( r )
242 return r;
243 }
244 return nullptr;
245}
246
248{
249 if ( key == mRuleKey )
250 return this;
251
252 for ( Rule *rule : std::as_const( mChildren ) )
253 {
254 Rule *r = rule->findRuleByKey( key );
255 if ( r )
256 return r;
257 }
258 return nullptr;
259}
260
262{
263 QgsPalLayerSettings *s = mSettings.get() ? new QgsPalLayerSettings( *mSettings ) : nullptr;
264 Rule *newrule = new Rule( s, mMaximumScale, mMinimumScale, mFilterExp, mDescription );
265 newrule->setActive( mIsActive );
266 if ( !resetRuleKey )
267 newrule->setRuleKey( ruleKey() );
268
269 // clone children
270 for ( Rule *rule : mChildren )
271 newrule->appendChild( rule->clone( resetRuleKey ) );
272
273 return newrule;
274}
275
276QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::create( const QDomElement &ruleElem, const QgsReadWriteContext &context, bool reuseId )
277{
278 QgsPalLayerSettings *settings = nullptr;
279 QDomElement settingsElem = ruleElem.firstChildElement( u"settings"_s );
280 if ( !settingsElem.isNull() )
281 {
283 settings->readXml( settingsElem, context );
284 }
285
286 QString filterExp = ruleElem.attribute( u"filter"_s );
287 QString description = ruleElem.attribute( u"description"_s );
288 int scaleMinDenom = ruleElem.attribute( u"scalemindenom"_s, u"0"_s ).toInt();
289 int scaleMaxDenom = ruleElem.attribute( u"scalemaxdenom"_s, u"0"_s ).toInt();
290 QString ruleKey;
291 if ( reuseId )
292 ruleKey = ruleElem.attribute( u"key"_s );
293 else
294 ruleKey = QUuid::createUuid().toString();
295 Rule *rule = new Rule( settings, scaleMinDenom, scaleMaxDenom, filterExp, description );
296
297 if ( !ruleKey.isEmpty() )
298 rule->mRuleKey = ruleKey;
299
300 rule->setActive( ruleElem.attribute( u"active"_s, u"1"_s ).toInt() );
301
302 QDomElement childRuleElem = ruleElem.firstChildElement( u"rule"_s );
303 while ( !childRuleElem.isNull() )
304 {
305 Rule *childRule = create( childRuleElem, context );
306 if ( childRule )
307 {
308 rule->appendChild( childRule );
309 }
310 else
311 {
312 //QgsDebugError( u"failed to init a child rule!"_s );
313 }
314 childRuleElem = childRuleElem.nextSiblingElement( u"rule"_s );
315 }
316
317 return rule;
318}
319
320QDomElement QgsRuleBasedLabeling::Rule::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
321{
322 QDomElement ruleElem = doc.createElement( u"rule"_s );
323
324 if ( mSettings )
325 {
326 ruleElem.appendChild( mSettings->writeXml( doc, context ) );
327 }
328 if ( !mFilterExp.isEmpty() )
329 ruleElem.setAttribute( u"filter"_s, mFilterExp );
330 if ( !qgsDoubleNear( mMaximumScale, 0 ) )
331 ruleElem.setAttribute( u"scalemindenom"_s, mMaximumScale );
332 if ( !qgsDoubleNear( mMinimumScale, 0 ) )
333 ruleElem.setAttribute( u"scalemaxdenom"_s, mMinimumScale );
334 if ( !mDescription.isEmpty() )
335 ruleElem.setAttribute( u"description"_s, mDescription );
336 if ( !mIsActive )
337 ruleElem.setAttribute( u"active"_s, 0 );
338 ruleElem.setAttribute( u"key"_s, mRuleKey );
339
340 for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
341 {
342 Rule *rule = *it;
343 ruleElem.appendChild( rule->save( doc, context ) );
344 }
345 return ruleElem;
346}
347
349{
350 if ( mSettings )
351 {
352 // add provider!
353 QgsVectorLayerLabelProvider *p = provider->createProvider( layer, mRuleKey, false, mSettings.get() );
354 auto it = std::find_if( subProviders.begin(), subProviders.end(),
355 [this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item )
356 {
357 return item.first == this;
358 } );
359
360 if ( it != subProviders.end() )
361 {
362 delete it->second;
363 subProviders.erase( it );
364 }
365
366 subProviders.push_back( {this, p} );
367 }
368
369 // call recursively
370 for ( Rule *rule : std::as_const( mChildren ) )
371 {
372 rule->createSubProviders( layer, subProviders, provider );
373 }
374}
375
376void QgsRuleBasedLabeling::Rule::prepare( QgsRenderContext &context, QSet<QString> &attributeNames, QgsRuleBasedLabeling::RuleToProviderVec &subProviders )
377{
378 if ( mSettings )
379 {
380 auto it = std::find_if( subProviders.begin(), subProviders.end(),
381 [this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item )
382 {
383 return item.first == this;
384 } );
385
386 if ( it != subProviders.end() )
387 {
388 QgsVectorLayerLabelProvider *p = it->second;
389 if ( !p->prepare( context, attributeNames ) )
390 {
391 subProviders.erase( it );
392 delete p;
393 }
394 }
395 }
396
397 if ( mFilter )
398 {
399 attributeNames.unite( mFilter->referencedColumns() );
400 mFilter->prepare( &context.expressionContext() );
401 }
402
403 // call recursively
404 for ( Rule *rule : std::as_const( mChildren ) )
405 {
406 rule->prepare( context, attributeNames, subProviders );
407 }
408}
409
410std::tuple< QgsRuleBasedLabeling::Rule::RegisterResult, QList< QgsLabelFeature * > > QgsRuleBasedLabeling::Rule::registerFeature( const QgsFeature &feature, QgsRenderContext &context, QgsRuleBasedLabeling::RuleToProviderVec &subProviders, const QgsGeometry &obstacleGeometry, const QgsSymbol *symbol )
411{
412 QList< QgsLabelFeature * > labels;
413 if ( !isFilterOK( feature, context )
414 || !isScaleOK( context.rendererScale() ) )
415 {
416 return { Filtered, labels };
417 }
418
419 bool registered = false;
420
421 // do we have active subprovider for the rule?
422 auto it = std::find_if( subProviders.begin(), subProviders.end(),
423 [this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item )
424 {
425 return item.first == this;
426 } );
427
428 if ( it != subProviders.end() && mIsActive )
429 {
430 labels.append( it->second->registerFeature( feature, context, obstacleGeometry, symbol ) );
431 registered = true;
432 }
433
434 bool matchedAChild = false;
435
436 // call recursively
437 for ( Rule *rule : std::as_const( mChildren ) )
438 {
439 // Don't process else rules yet
440 if ( !rule->isElse() )
441 {
442 RegisterResult res;
443 QList< QgsLabelFeature * > added;
444 std::tie( res, added ) = rule->registerFeature( feature, context, subProviders, obstacleGeometry );
445 labels.append( added );
446 // consider inactive items as "matched" so the else rule will ignore them
447 matchedAChild |= ( res == Registered || res == Inactive );
448 registered |= matchedAChild;
449 }
450 }
451
452 // If none of the rules passed then we jump into the else rules and process them.
453 if ( !matchedAChild )
454 {
455 for ( Rule *rule : std::as_const( mElseRules ) )
456 {
457 RegisterResult res;
458 QList< QgsLabelFeature * > added;
459 std::tie( res, added ) = rule->registerFeature( feature, context, subProviders, obstacleGeometry, symbol ) ;
460 matchedAChild |= ( res == Registered || res == Inactive );
461 registered |= res != Filtered;
462 labels.append( added );
463 }
464 }
465
466 if ( !mIsActive || ( matchedAChild && !registered ) )
467 return { Inactive, labels };
468 else if ( registered )
469 return { Registered, labels };
470 else
471 return { Filtered, labels };
472}
473
474bool QgsRuleBasedLabeling::Rule::isFilterOK( const QgsFeature &f, QgsRenderContext &context ) const
475{
476 if ( ! mFilter || mElseRule )
477 return true;
478
479 context.expressionContext().setFeature( f );
480 QVariant res = mFilter->evaluate( &context.expressionContext() );
481 return res.toBool();
482}
483
484bool QgsRuleBasedLabeling::Rule::isScaleOK( double scale ) const
485{
486 if ( qgsDoubleNear( scale, 0.0 ) ) // so that we can count features in classes without scale context
487 return true;
488 if ( qgsDoubleNear( mMaximumScale, 0.0 ) && qgsDoubleNear( mMinimumScale, 0.0 ) )
489 return true;
490
491 // maxScale is inclusive ( < --> no label )
492 if ( !qgsDoubleNear( mMaximumScale, 0.0 ) && QgsScaleUtils::lessThanMaximumScale( scale, mMaximumScale ) )
493 return false;
494
495 // minScale is exclusive ( >= --> no label )
496 if ( !qgsDoubleNear( mMinimumScale, 0.0 ) && QgsScaleUtils::equalToOrGreaterThanMinimumScale( scale, mMinimumScale ) )
497 return false;
498 return true;
499}
500
502
507
509{
510 Rule *rootRule = mRootRule->clone();
511
512 // normally with clone() the individual rules get new keys (UUID), but here we want to keep
513 // the tree of rules intact, so that other components that may use the rule keys work nicely (e.g. map themes)
514 rootRule->setRuleKey( mRootRule->ruleKey() );
515 RuleList origDescendants = mRootRule->descendants();
516 RuleList clonedDescendants = rootRule->descendants();
517 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
518 for ( int i = 0; i < origDescendants.count(); ++i )
519 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
520
521 return new QgsRuleBasedLabeling( rootRule );
522}
523
527
532
534{
535 return mRootRule.get();
536}
537
538
539QgsRuleBasedLabeling *QgsRuleBasedLabeling::create( const QDomElement &element, const QgsReadWriteContext &context ) // cppcheck-suppress duplInheritedMember
540{
541 QDomElement rulesElem = element.firstChildElement( u"rules"_s );
542
543 Rule *root = Rule::create( rulesElem, context );
544 if ( !root )
545 return nullptr;
546
548 return rl;
549}
550
552{
553 return u"rule-based"_s;
554}
555
556QDomElement QgsRuleBasedLabeling::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
557{
558 QDomElement elem = doc.createElement( u"labeling"_s );
559 elem.setAttribute( u"type"_s, u"rule-based"_s );
560
561 QDomElement rulesElem = mRootRule->save( doc, context );
562 rulesElem.setTagName( u"rules"_s ); // instead of just "rule"
563 elem.appendChild( rulesElem );
564
565 return elem;
566}
567
569{
570 return new QgsRuleBasedLabelProvider( *this, layer, false );
571}
572
574{
575 QStringList lst;
576 mRootRule->subProviderIds( lst );
577 return lst;
578}
579
580QgsPalLayerSettings QgsRuleBasedLabeling::settings( const QString &providerId ) const
581{
582 const Rule *rule = mRootRule->findRuleByKey( providerId );
583 if ( rule && rule->settings() )
584 return *rule->settings();
585
586 return QgsPalLayerSettings();
587}
588
590{
591 return mRootRule->accept( visitor );
592}
593
595{
596 return mRootRule->requiresAdvancedEffects();
597}
598
600{
601 return mRootRule->hasNonDefaultCompositionMode();
602}
603
605{
606 if ( settings )
607 {
608 Rule *rule = mRootRule->findRuleByKey( providerId );
609 if ( rule && rule->settings() )
610 rule->setSettings( settings );
611 }
612}
613
614void QgsRuleBasedLabeling::toSld( QDomNode &parent, const QVariantMap &properties ) const
615{
616 QgsSldExportContext context;
617 context.setExtraProperties( properties );
618 toSld( parent, context );
619}
620
621bool QgsRuleBasedLabeling::toSld( QDomNode &parent, QgsSldExportContext &context ) const
622{
623 if ( !mRootRule )
624 {
625 return false;
626 }
627
628 const QgsRuleBasedLabeling::RuleList rules = mRootRule->children();
629 for ( Rule *rule : rules )
630 {
631 QgsPalLayerSettings *settings = rule->settings();
632
633 if ( settings && settings->drawLabels )
634 {
635 QDomDocument doc = parent.ownerDocument();
636
637 QDomElement ruleElement = doc.createElement( u"se:Rule"_s );
638 parent.appendChild( ruleElement );
639
640 if ( !rule->filterExpression().isEmpty() )
641 {
642 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElement, rule->filterExpression(), context );
643 }
644
645 // scale dependencies, the actual behavior is that the PAL settings min/max and
646 // the rule min/max get intersected
647 const QVariantMap oldProps = context.extraProperties();
648 QVariantMap localProps = oldProps;
649 QgsSymbolLayerUtils::mergeScaleDependencies( rule->maximumScale(), rule->minimumScale(), localProps );
650 if ( settings->scaleVisibility )
651 {
652 QgsSymbolLayerUtils::mergeScaleDependencies( settings->maximumScale, settings->minimumScale, localProps );
653 }
654 QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElement, localProps );
655 context.setExtraProperties( localProps );
657 context.setExtraProperties( oldProps );
658 }
659 }
660 return true;
661}
662
663void QgsRuleBasedLabeling::multiplyOpacity( double opacityFactor )
664{
665 if ( !mRootRule )
666 {
667 return;
668 }
669
670 const QgsRuleBasedLabeling::RuleList rules = mRootRule->children();
671 for ( Rule *rule : rules )
672 {
673 QgsPalLayerSettings *settings = rule->settings();
674
675 if ( settings && settings->drawLabels )
676 {
677 QgsTextFormat format { settings->format() };
678 format.multiplyOpacity( opacityFactor );
679 settings->setFormat( format );
680 }
681
682 }
683}
const QgsLabelingEngine * mEngine
Associated labeling engine.
QgsMapLayer * layer() const
Returns the associated layer, or nullptr if no layer is associated with the provider.
QString providerId() const
Returns provider ID - useful in case there is more than one label provider within a layer (e....
virtual Q_DECL_DEPRECATED void writeTextSymbolizer(QDomNode &parent, QgsPalLayerSettings &settings, const QVariantMap &props) const
Writes a TextSymbolizer element contents based on the provided labeling settings.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
A geometry is the spatial representation of a feature.
Contains settings for how a map layer will be labeled.
A container for the context for various read/write operations on objects.
Contains information about the context of a rendering operation.
double rendererScale() const
Returns the renderer map scale.
QgsExpressionContext & expressionContext()
Gets the expression context.
Label provider for rule based labeling.
bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames) override
Prepare for registration of features.
std::unique_ptr< QgsRuleBasedLabeling > mRules
owned copy
QList< QgsLabelFeature * > registerFeature(const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr) override
Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels.
QgsRuleBasedLabelProvider(const QgsRuleBasedLabeling &rules, QgsVectorLayer *layer, bool withFeatureLoop=true)
std::vector< std::pair< QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider * > > mSubProviders
label providers are owned by labeling engine
virtual QgsVectorLayerLabelProvider * createProvider(QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings)
create a label provider
QList< QgsAbstractLabelProvider * > subProviders() override
Returns subproviders.
A child rule for QgsRuleBasedLabeling.
void setRuleKey(const QString &key)
Override the assigned rule key (should be used just internally by rule-based labeling).
void createSubProviders(QgsVectorLayer *layer, RuleToProviderVec &subProviders, QgsRuleBasedLabelProvider *provider)
add providers
std::tuple< RegisterResult, QList< QgsLabelFeature * > > registerFeature(const QgsFeature &feature, QgsRenderContext &context, RuleToProviderVec &subProviders, const QgsGeometry &obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr)
Register individual features.
void prepare(QgsRenderContext &context, QSet< QString > &attributeNames, RuleToProviderVec &subProviders)
call prepare() on sub-providers and populate attributeNames
QgsPalLayerSettings * settings() const
Returns the labeling settings.
RegisterResult
The result of registering a rule.
@ Inactive
The rule is inactive.
@ Filtered
The rule does not apply.
@ Registered
Something was registered.
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all child rules associated with the rule...
bool hasNonDefaultCompositionMode() const
Returns true if this rule or any of its children requires a non-default composition mode.
void subProviderIds(QStringList &list) const
append rule keys of descendants that contain valid settings (i.e.
bool requiresAdvancedEffects() const
Returns true if this rule or any of its children requires advanced composition effects to render.
void removeChildAt(int i)
delete child rule
void setActive(bool state)
Sets if this rule is active.
static QgsRuleBasedLabeling::Rule * create(const QDomElement &ruleElem, const QgsReadWriteContext &context, bool reuseId=true)
Create a rule from an XML definition.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const
store labeling info to XML element
void setSettings(QgsPalLayerSettings *settings)
Sets new settings (or nullptr). Deletes old settings if any.
QgsRuleBasedLabeling::RuleList descendants() const
Returns all children, grand-children, grand-grand-children, grand-gra... you get it.
Rule(QgsPalLayerSettings *settings, double maximumScale=0, double minimumScale=0, const QString &filterExp=QString(), const QString &description=QString(), bool elseRule=false)
takes ownership of settings, settings may be nullptr
void insertChild(int i, QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
QgsRuleBasedLabeling::Rule * clone(bool resetRuleKey=true) const
clone this rule
QString ruleKey() const
Unique rule identifier (for identification of rule within labeling, used as provider ID).
const QgsRuleBasedLabeling::Rule * findRuleByKey(const QString &key) const
Try to find a rule given its unique key.
void appendChild(QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
QString description() const
A human readable description for this rule.
Rule based labeling for a vector layer.
QList< QgsRuleBasedLabeling::Rule * > RuleList
std::unique_ptr< Rule > mRootRule
Q_DECL_DEPRECATED void toSld(QDomNode &parent, const QVariantMap &properties) const override
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings.
QStringList subProviders() const override
Gets list of sub-providers within the layer's labeling.
QgsRuleBasedLabeling(QgsRuleBasedLabeling::Rule *root)
Constructs the labeling from given tree of rules (takes ownership).
QgsVectorLayerLabelProvider * provider(QgsVectorLayer *layer) const override
static QgsRuleBasedLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Create the instance from a DOM element with saved configuration.
void setSettings(QgsPalLayerSettings *settings, const QString &providerId=QString()) override
Set pal settings for a specific provider (takes ownership).
QgsPalLayerSettings settings(const QString &providerId=QString()) const override
Gets associated label settings.
QString type() const override
Unique type string of the labeling configuration implementation.
QgsRuleBasedLabeling * clone() const override
Returns a new copy of the object.
void multiplyOpacity(double opacityFactor) override
Multiply opacity by opacityFactor.
QgsRuleBasedLabeling::Rule * rootRule()
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const override
Returns labeling configuration as XML element.
bool hasNonDefaultCompositionMode() const override
Returns true the labeling requires a non-default composition mode.
bool requiresAdvancedEffects() const override
Returns true if drawing labels requires advanced effects like composition modes, which could prevent ...
static bool equalToOrGreaterThanMinimumScale(const double scale, const double minScale)
Returns whether the scale is equal to or greater than the minScale, taking non-round numbers into acc...
static bool lessThanMaximumScale(const double scale, const double maxScale)
Returns whether the scale is less than the maxScale, taking non-round numbers into account.
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void setExtraProperties(const QVariantMap &properties)
Sets the open ended set of properties that can drive/inform the SLD encoding.
QVariantMap extraProperties() const
Returns the open ended set of properties that can drive/inform the SLD encoding.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A label settings entity for QgsStyle databases.
Definition qgsstyle.h:1491
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
static Q_DECL_DEPRECATED bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates an OGC function element.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
Container for all settings relating to text rendering.
void multiplyOpacity(double opacityFactor)
Multiply opacity by opacityFactor.
Implements a label provider for vector layers.
virtual bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames)
Prepare for registration of features.
QgsVectorLayerLabelProvider(QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings, const QString &layerName=QString())
Convenience constructor to initialize the provider from given vector layer.
const QgsPalLayerSettings & settings() const
Returns the layer's settings.
Represents a vector layer which manages a vector based dataset.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6935
Contains information relating to a node (i.e.
Contains information relating to the style entity currently being visited.