48 QList<QgsAbstractLabelProvider *> lst;
59 , mMaximumScale( scaleMinDenom )
60 , mMinimumScale( scaleMaxDenom )
61 , mFilterExp( filterExp )
62 , mDescription( description )
63 , mElseRule( elseRule )
71 qDeleteAll( mChildren );
80 mSettings.reset( settings );
86 for (
Rule *
c : mChildren )
89 l +=
c->descendants();
94 void QgsRuleBasedLabeling::Rule::initFilter()
96 if ( mElseRule || mFilterExp.compare( QLatin1String(
"ELSE" ), Qt::CaseInsensitive ) == 0 )
99 mFilter.reset(
nullptr );
101 else if ( !mFilterExp.isEmpty() )
107 mFilter.reset(
nullptr );
111 void QgsRuleBasedLabeling::Rule::updateElseRules()
114 for (
Rule *rule : qgis::as_const( mChildren ) )
116 if ( rule->isElse() )
123 if ( mSettings && mSettings->format().containsAdvancedEffects() )
126 for (
Rule *rule : qgis::as_const( mChildren ) )
128 if ( rule->requiresAdvancedEffects() )
137 for (
const Rule *rule : qgis::as_const( mChildren ) )
139 if ( rule->settings() )
140 list << rule->ruleKey();
142 rule->subProviderIds( list );
149 mChildren.append( rule );
150 rule->mParent =
this;
156 mChildren.insert( i, rule );
157 rule->mParent =
this;
163 delete mChildren.at( i );
164 mChildren.removeAt( i );
172 if ( key == mRuleKey )
175 for (
Rule *rule : mChildren )
186 if ( key == mRuleKey )
189 for (
Rule *rule : qgis::as_const( mChildren ) )
201 Rule *newrule =
new Rule( s, mMaximumScale, mMinimumScale, mFilterExp, mDescription );
204 for (
Rule *rule : mChildren )
212 QDomElement settingsElem = ruleElem.firstChildElement( QStringLiteral(
"settings" ) );
213 if ( !settingsElem.isNull() )
216 settings->
readXml( settingsElem, context );
219 QString filterExp = ruleElem.attribute( QStringLiteral(
"filter" ) );
220 QString
description = ruleElem.attribute( QStringLiteral(
"description" ) );
221 int scaleMinDenom = ruleElem.attribute( QStringLiteral(
"scalemindenom" ), QStringLiteral(
"0" ) ).toInt();
222 int scaleMaxDenom = ruleElem.attribute( QStringLiteral(
"scalemaxdenom" ), QStringLiteral(
"0" ) ).toInt();
223 QString
ruleKey = ruleElem.attribute( QStringLiteral(
"key" ) );
224 Rule *rule =
new Rule( settings, scaleMinDenom, scaleMaxDenom, filterExp, description );
226 if ( !ruleKey.isEmpty() )
227 rule->mRuleKey = ruleKey;
229 rule->
setActive( ruleElem.attribute( QStringLiteral(
"active" ), QStringLiteral(
"1" ) ).toInt() );
231 QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral(
"rule" ) );
232 while ( !childRuleElem.isNull() )
234 Rule *childRule =
create( childRuleElem, context );
243 childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral(
"rule" ) );
251 QDomElement ruleElem = doc.createElement( QStringLiteral(
"rule" ) );
255 ruleElem.appendChild( mSettings->writeXml( doc, context ) );
257 if ( !mFilterExp.isEmpty() )
258 ruleElem.setAttribute( QStringLiteral(
"filter" ), mFilterExp );
260 ruleElem.setAttribute( QStringLiteral(
"scalemindenom" ), mMaximumScale );
262 ruleElem.setAttribute( QStringLiteral(
"scalemaxdenom" ), mMinimumScale );
263 if ( !mDescription.isEmpty() )
264 ruleElem.setAttribute( QStringLiteral(
"description" ), mDescription );
266 ruleElem.setAttribute( QStringLiteral(
"active" ), 0 );
267 ruleElem.setAttribute( QStringLiteral(
"key" ), mRuleKey );
269 for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
283 delete subProviders.value(
this,
nullptr );
284 subProviders[
this] = p;
288 for (
Rule *rule : qgis::as_const( mChildren ) )
290 rule->createSubProviders( layer, subProviders, provider );
299 if ( !p->
prepare( context, attributeNames ) )
301 subProviders.remove(
this );
308 attributeNames.unite( mFilter->referencedColumns() );
313 for (
Rule *rule : qgis::as_const( mChildren ) )
315 rule->prepare( context, attributeNames, subProviders );
321 if ( !isFilterOK( feature, context )
325 bool registered =
false;
328 if ( subProviders.contains(
this ) && mIsActive )
330 subProviders[
this]->registerFeature( feature, context, obstacleGeometry );
334 bool willRegisterSomething =
false;
337 for (
Rule *rule : qgis::as_const( mChildren ) )
340 if ( !rule->isElse() )
342 RegisterResult res = rule->registerFeature( feature, context, subProviders, obstacleGeometry );
345 registered |= willRegisterSomething;
350 if ( !willRegisterSomething )
352 for (
Rule *rule : qgis::as_const( mElseRules ) )
354 registered |= rule->registerFeature( feature, context, subProviders, obstacleGeometry ) !=
Filtered;
360 else if ( registered )
368 if ( ! mFilter || mElseRule )
376 bool QgsRuleBasedLabeling::Rule::isScaleOK(
double scale )
const 382 if ( !
qgsDoubleNear( mMaximumScale, 0.0 ) && mMaximumScale > scale )
384 if ( !
qgsDoubleNear( mMinimumScale, 0.0 ) && mMinimumScale < scale )
405 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
406 for (
int i = 0; i < origDescendants.count(); ++i )
407 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
429 QDomElement rulesElem = element.firstChildElement( QStringLiteral(
"rules" ) );
441 return QStringLiteral(
"rule-based" );
446 QDomElement elem = doc.createElement( QStringLiteral(
"labeling" ) );
447 elem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"rule-based" ) );
449 QDomElement rulesElem =
mRootRule->save( doc, context );
450 rulesElem.setTagName( QStringLiteral(
"rules" ) );
451 elem.appendChild( rulesElem );
479 return mRootRule->requiresAdvancedEffects();
500 for (
Rule *rule : rules )
506 QDomDocument doc = parent.ownerDocument();
508 QDomElement ruleElement = doc.createElement( QStringLiteral(
"se:Rule" ) );
509 parent.appendChild( ruleElement );
511 if ( !rule->filterExpression().isEmpty() )
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QgsStringMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
Class for parsing and evaluation of expressions (formerly called "search strings").
The class is used as a container of context for various read/write operations on other objects...
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.
bool requiresAdvancedEffects() const
Returns true if this rule or any of its children requires advanced composition effects to render...
QgsPalLayerSettings * settings() const
Returns the labeling settings.
Something was registered.
double rendererScale() const
Returns the renderer map scale.
QgsVectorLayerLabelProvider * provider(QgsVectorLayer *layer) const override
double maximumScale
The maximum map scale (i.e.
~QgsRuleBasedLabeling() override
void setSettings(QgsPalLayerSettings *settings, const QString &providerId=QString()) override
Set pal settings for a specific provider (takes ownership).
QgsRuleBasedLabeling::RuleToProviderMap mSubProviders
label providers are owned by labeling engine
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
bool requiresAdvancedEffects() const override
Returns true if drawing labels requires advanced effects like composition modes, which could prevent ...
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const override
Returns labeling configuration as XML element.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const
store labeling info to XML element
const QgsLabelingEngine * mEngine
Associated labeling engine.
void readXml(QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QgsStringMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void insertChild(int i, QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
RegisterResult
The result of registering a rule.
QgsRuleBasedLabeling::Rule * clone() const
clone this rule, return new instance
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
void registerFeature(const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry=QgsGeometry()) override
Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels...
QString description() const
A human readable description for this rule.
The QgsVectorLayerLabelProvider class implements a label provider for vector layers.
A geometry is the spatial representation of a feature.
bool drawLabels
Whether to draw labels for this layer.
QList< QgsAbstractLabelProvider * > subProviders() override
Returns subproviders.
RegisterResult registerFeature(const QgsFeature &feature, QgsRenderContext &context, RuleToProviderMap &subProviders, const QgsGeometry &obstacleGeometry=QgsGeometry())
register individual features
QString ruleKey() const
Unique rule identifier (for identification of rule within labeling, used as provider ID) ...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QMap< QgsRuleBasedLabeling::Rule *, QgsVectorLayerLabelProvider * > RuleToProviderMap
QMap< QString, QString > QgsStringMap
QgsRuleBasedLabeling::RuleList descendants() const
Returns all children, grand-children, grand-grand-children, grand-gra...
QList< QgsRuleBasedLabeling::Rule * > RuleList
void prepare(const QgsRenderContext &context, QSet< QString > &attributeNames, RuleToProviderMap &subProviders)
call prepare() on sub-providers and populate attributeNames
static QgsRuleBasedLabeling::Rule * create(const QDomElement &ruleElem, const QgsReadWriteContext &context)
Create a rule from an XML definition.
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
QgsMapLayer * layer() const
Returns the associated layer, or nullptr if no layer is associated with the provider.
QString type() const override
Unique type string of the labeling configuration implementation.
void appendChild(QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
QStringList subProviders() const override
Gets list of sub-providers within the layer's labeling.
bool prepare(const QgsRenderContext &context, QSet< QString > &attributeNames) override
Prepare for registration of features.
virtual bool prepare(const QgsRenderContext &context, QSet< QString > &attributeNames)
Prepare for registration of features.
std::unique_ptr< QgsRuleBasedLabeling > mRules
owned copy
std::unique_ptr< Rule > mRootRule
virtual QgsVectorLayerLabelProvider * createProvider(QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings)
create a label provider
void setSettings(QgsPalLayerSettings *settings)
Sets new settings (or nullptr). Deletes old settings if any.
QgsPalLayerSettings mSettings
Layer's labeling configuration.
QgsRuleBasedLabeling(QgsRuleBasedLabeling::Rule *root)
Constructs the labeling from given tree of rules (takes ownership)
const QgsRuleBasedLabeling::Rule * findRuleByKey(const QString &key) const
Try to find a rule given its unique key.
void setActive(bool state)
Sets if this rule is active.
QgsExpressionContext & expressionContext()
Gets the expression context.
static QgsRuleBasedLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Create the instance from a DOM element with saved configuration.
QgsRuleBasedLabeling * clone() const override
Returns a new copy of the object.
void setRuleKey(const QString &key)
Override the assigned rule key (should be used just internally by rule-based labeling) ...
QgsPalLayerSettings settings(const QString &providerId=QString()) const override
Gets associated label settings.
void subProviderIds(QStringList &list) const
append rule keys of descendants that contain valid settings (i.e.
Contains information about the context of a rendering operation.
bool scaleVisibility
Set to true to limit label visibility to a range of scales.
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
virtual void writeTextSymbolizer(QDomNode &parent, QgsPalLayerSettings &settings, const QgsStringMap &props) const
Writes a TextSymbolizer element contents based on the provided labeling settings. ...
QString providerId() const
Returns provider ID - useful in case there is more than one label provider within a layer (e...
void toSld(QDomNode &parent, const QgsStringMap &props) const override
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings.
void removeChildAt(int i)
delete child rule
QgsRuleBasedLabeling::Rule * rootRule()
Represents a vector layer which manages a vector based data sets.
void createSubProviders(QgsVectorLayer *layer, RuleToProviderMap &subProviders, QgsRuleBasedLabelProvider *provider)
add providers
QgsRuleBasedLabelProvider(const QgsRuleBasedLabeling &rules, QgsVectorLayer *layer, bool withFeatureLoop=true)
double minimumScale
The minimum map scale (i.e.