QGIS API Documentation 4.3.0-Master (e0370aa57ef)
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 QgsLabelFeatureDetails &details )
51{
52 // will register the feature to relevant sub-providers
53 return std::get< 1 >( mRules->rootRule()->registerFeature( feature, context, mSubProviders, details ) );
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
261std::unique_ptr<QgsRuleBasedLabeling::Rule> QgsRuleBasedLabeling::Rule::clone( bool resetRuleKey ) const
262{
263 QgsPalLayerSettings *s = mSettings.get() ? new QgsPalLayerSettings( *mSettings ) : nullptr;
264 auto newrule = std::make_unique<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 ).release() );
272
273 return newrule;
274}
275
276std::unique_ptr<QgsRuleBasedLabeling::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 auto rule = std::make_unique<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 std::unique_ptr<Rule> childRule = create( childRuleElem, context );
306 if ( childRule )
307 {
308 rule->appendChild( childRule.release() );
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(), [this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item ) { return item.first == this; } );
355
356 if ( it != subProviders.end() )
357 {
358 delete it->second;
359 subProviders.erase( it );
360 }
361
362 subProviders.push_back( { this, p } );
363 }
364
365 // call recursively
366 for ( Rule *rule : std::as_const( mChildren ) )
367 {
368 rule->createSubProviders( layer, subProviders, provider );
369 }
370}
371
372void QgsRuleBasedLabeling::Rule::prepare( QgsRenderContext &context, QSet<QString> &attributeNames, QgsRuleBasedLabeling::RuleToProviderVec &subProviders )
373{
374 if ( mSettings )
375 {
376 auto it = std::find_if( subProviders.begin(), subProviders.end(), [this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item ) { return item.first == this; } );
377
378 if ( it != subProviders.end() )
379 {
380 QgsVectorLayerLabelProvider *p = it->second;
381 if ( !p->prepare( context, attributeNames ) )
382 {
383 subProviders.erase( it );
384 delete p;
385 }
386 }
387 }
388
389 if ( mFilter )
390 {
391 attributeNames.unite( mFilter->referencedColumns() );
392 mFilter->prepare( &context.expressionContext() );
393 }
394
395 // call recursively
396 for ( Rule *rule : std::as_const( mChildren ) )
397 {
398 rule->prepare( context, attributeNames, subProviders );
399 }
400}
401
402std::tuple< QgsRuleBasedLabeling::Rule::RegisterResult, QList< QgsLabelFeature * > > QgsRuleBasedLabeling::Rule::registerFeature(
403 const QgsFeature &feature, QgsRenderContext &context, QgsRuleBasedLabeling::RuleToProviderVec &subProviders, const QgsLabelFeatureDetails &details
404)
405{
406 QList< QgsLabelFeature * > labels;
407 if ( !isFilterOK( feature, context ) || !isScaleOK( context.rendererScale() ) )
408 {
409 return { Filtered, labels };
410 }
411
412 bool registered = false;
413
414 // do we have active subprovider for the rule?
415 auto it = std::find_if( subProviders.begin(), subProviders.end(), [this]( const std::pair<QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider *> &item ) { return item.first == this; } );
416
417 if ( it != subProviders.end() && mIsActive )
418 {
419 labels.append( it->second->registerFeature( feature, context, details ) );
420 registered = true;
421 }
422
423 bool matchedAChild = false;
424
425 // call recursively
426 for ( Rule *rule : std::as_const( mChildren ) )
427 {
428 // Don't process else rules yet
429 if ( !rule->isElse() )
430 {
431 RegisterResult res;
432 QList< QgsLabelFeature * > added;
433 std::tie( res, added ) = rule->registerFeature( feature, context, subProviders, details );
434 labels.append( added );
435 // consider inactive items as "matched" so the else rule will ignore them
436 matchedAChild |= ( res == Registered || res == Inactive );
437 registered |= matchedAChild;
438 }
439 }
440
441 // If none of the rules passed then we jump into the else rules and process them.
442 if ( !matchedAChild )
443 {
444 for ( Rule *rule : std::as_const( mElseRules ) )
445 {
446 RegisterResult res;
447 QList< QgsLabelFeature * > added;
448 std::tie( res, added ) = rule->registerFeature( feature, context, subProviders, details );
449 matchedAChild |= ( res == Registered || res == Inactive );
450 registered |= res != Filtered;
451 labels.append( added );
452 }
453 }
454
455 if ( !mIsActive || ( matchedAChild && !registered ) )
456 return { Inactive, labels };
457 else if ( registered )
458 return { Registered, labels };
459 else
460 return { Filtered, labels };
461}
462
463bool QgsRuleBasedLabeling::Rule::isFilterOK( const QgsFeature &f, QgsRenderContext &context ) const
464{
465 if ( !mFilter || mElseRule )
466 return true;
467
468 context.expressionContext().setFeature( f );
469 QVariant res = mFilter->evaluate( &context.expressionContext() );
470 return res.toBool();
471}
472
473bool QgsRuleBasedLabeling::Rule::isScaleOK( double scale ) const
474{
475 if ( qgsDoubleNear( scale, 0.0 ) ) // so that we can count features in classes without scale context
476 return true;
477 if ( qgsDoubleNear( mMaximumScale, 0.0 ) && qgsDoubleNear( mMinimumScale, 0.0 ) )
478 return true;
479
480 // maxScale is inclusive ( < --> no label )
481 if ( !qgsDoubleNear( mMaximumScale, 0.0 ) && QgsScaleUtils::lessThanMaximumScale( scale, mMaximumScale ) )
482 return false;
483
484 // minScale is exclusive ( >= --> no label )
485 if ( !qgsDoubleNear( mMinimumScale, 0.0 ) && QgsScaleUtils::equalToOrGreaterThanMinimumScale( scale, mMinimumScale ) )
486 return false;
487 return true;
488}
489
491
495
497{
498 std::unique_ptr<Rule> rootRule = mRootRule->clone();
499
500 // normally with clone() the individual rules get new keys (UUID), but here we want to keep
501 // the tree of rules intact, so that other components that may use the rule keys work nicely (e.g. map themes)
502 rootRule->setRuleKey( mRootRule->ruleKey() );
503 RuleList origDescendants = mRootRule->descendants();
504 RuleList clonedDescendants = rootRule->descendants();
505 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
506 for ( int i = 0; i < origDescendants.count(); ++i )
507 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
508
509 return new QgsRuleBasedLabeling( rootRule.release() );
510}
511
514
519
521{
522 return mRootRule.get();
523}
524
525
526std::unique_ptr<QgsRuleBasedLabeling> QgsRuleBasedLabeling::create( const QDomElement &element, const QgsReadWriteContext &context ) // cppcheck-suppress duplInheritedMember
527{
528 QDomElement rulesElem = element.firstChildElement( u"rules"_s );
529
530 std::unique_ptr<Rule> root = Rule::create( rulesElem, context );
531 if ( !root )
532 return nullptr;
533
534 return std::make_unique<QgsRuleBasedLabeling>( root.release() );
535}
536
538{
539 return u"rule-based"_s;
540}
541
542QDomElement QgsRuleBasedLabeling::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
543{
544 QDomElement elem = doc.createElement( u"labeling"_s );
545 elem.setAttribute( u"type"_s, u"rule-based"_s );
546
547 QDomElement rulesElem = mRootRule->save( doc, context );
548 rulesElem.setTagName( u"rules"_s ); // instead of just "rule"
549 elem.appendChild( rulesElem );
550
551 return elem;
552}
553
555{
556 return new QgsRuleBasedLabelProvider( *this, layer, false );
557}
558
560{
561 QStringList lst;
562 mRootRule->subProviderIds( lst );
563 return lst;
564}
565
566QgsPalLayerSettings QgsRuleBasedLabeling::settings( const QString &providerId ) const
567{
568 const Rule *rule = mRootRule->findRuleByKey( providerId );
569 if ( rule && rule->settings() )
570 return *rule->settings();
571
572 return QgsPalLayerSettings();
573}
574
576{
577 return mRootRule->accept( visitor );
578}
579
581{
582 return mRootRule->requiresAdvancedEffects();
583}
584
586{
587 return mRootRule->hasNonDefaultCompositionMode();
588}
589
591{
592 if ( settings )
593 {
594 Rule *rule = mRootRule->findRuleByKey( providerId );
595 if ( rule && rule->settings() )
596 rule->setSettings( settings );
597 }
598}
599
600void QgsRuleBasedLabeling::toSld( QDomNode &parent, const QVariantMap &properties ) const
601{
602 QgsSldExportContext context;
603 context.setExtraProperties( properties );
604 toSld( parent, context );
605}
606
607bool QgsRuleBasedLabeling::toSld( QDomNode &parent, QgsSldExportContext &context ) const
608{
609 if ( !mRootRule )
610 {
611 return false;
612 }
613
614 const QgsRuleBasedLabeling::RuleList rules = mRootRule->children();
615 for ( Rule *rule : rules )
616 {
617 QgsPalLayerSettings *settings = rule->settings();
618
619 if ( settings && settings->drawLabels )
620 {
621 QDomDocument doc = parent.ownerDocument();
622
623 QDomElement ruleElement = doc.createElement( u"se:Rule"_s );
624 parent.appendChild( ruleElement );
625
626 if ( !rule->filterExpression().isEmpty() )
627 {
628 QgsSymbolLayerUtils::createFunctionElement( doc, ruleElement, rule->filterExpression(), context );
629 }
630
631 // scale dependencies, the actual behavior is that the PAL settings min/max and
632 // the rule min/max get intersected
633 const QVariantMap oldProps = context.extraProperties();
634 QVariantMap localProps = oldProps;
635 QgsSymbolLayerUtils::mergeScaleDependencies( rule->maximumScale(), rule->minimumScale(), localProps );
636 if ( settings->scaleVisibility )
637 {
638 QgsSymbolLayerUtils::mergeScaleDependencies( settings->maximumScale, settings->minimumScale, localProps );
639 }
640 QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElement, localProps );
641 context.setExtraProperties( localProps );
643 context.setExtraProperties( oldProps );
644 }
645 }
646 return true;
647}
648
649void QgsRuleBasedLabeling::multiplyOpacity( double opacityFactor )
650{
651 if ( !mRootRule )
652 {
653 return;
654 }
655
656 const QgsRuleBasedLabeling::RuleList rules = mRootRule->children();
657 for ( Rule *rule : rules )
658 {
659 QgsPalLayerSettings *settings = rule->settings();
660
661 if ( settings && settings->drawLabels )
662 {
663 QgsTextFormat format { settings->format() };
664 format.multiplyOpacity( opacityFactor );
665 settings->setFormat( format );
666 }
667 }
668}
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
Encapsulates details for an individual feature to label.
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.
QList< QgsLabelFeature * > registerFeature(const QgsFeature &feature, QgsRenderContext &context, const QgsLabelFeatureDetails &details=QgsLabelFeatureDetails()) override
Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels.
std::unique_ptr< QgsRuleBasedLabeling > mRules
owned copy
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 createSubProviders(QgsVectorLayer *layer, RuleToProviderVec &subProviders, QgsRuleBasedLabelProvider *provider)
add providers
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.
static std::unique_ptr< QgsRuleBasedLabeling::Rule > create(const QDomElement &ruleElem, const QgsReadWriteContext &context, bool reuseId=true)
Create a rule from an XML definition.
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
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
std::unique_ptr< QgsRuleBasedLabeling::Rule > clone(bool resetRuleKey=true) const
clone this rule
std::tuple< RegisterResult, QList< QgsLabelFeature * > > registerFeature(const QgsFeature &feature, QgsRenderContext &context, RuleToProviderVec &subProviders, const QgsLabelFeatureDetails &details)
Register individual features.
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
static std::unique_ptr< QgsRuleBasedLabeling > create(const QDomElement &element, const QgsReadWriteContext &context)
Create the instance from a DOM element with saved configuration.
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
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:1547
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.
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:7795
Contains information relating to a node (i.e.
Contains information relating to the style entity currently being visited.