33 #include <QDomDocument> 34 #include <QDomElement> 41 , mMaximumScale( scaleMinDenom )
42 , mMinimumScale( scaleMaxDenom )
43 , mFilterExp( filterExp )
45 , mDescription( description )
46 , mElseRule( elseRule )
49 mFilterExp = QStringLiteral(
"ELSE" );
51 mRuleKey = QUuid::createUuid().toString();
57 qDeleteAll( mChildren );
63 if ( mFilterExp.trimmed().compare( QLatin1String(
"ELSE" ), Qt::CaseInsensitive ) == 0 )
68 else if ( mFilterExp.trimmed().isEmpty() )
76 mFilter = qgis::make_unique< QgsExpression >( mFilterExp );
82 mChildren.append( rule );
89 mChildren.insert( i, rule );
96 mChildren.removeAll( rule );
103 delete mChildren.takeAt( i );
109 mChildren.removeAll( rule );
110 rule->mParent =
nullptr;
117 Rule *rule = mChildren.takeAt( i );
118 rule->mParent =
nullptr;
127 if ( key == mRuleKey )
130 Q_FOREACH (
Rule *rule, mChildren )
139 void QgsRuleBasedRenderer::Rule::updateElseRules()
142 Q_FOREACH (
Rule *rule, mChildren )
151 mFilterExp = QStringLiteral(
"ELSE" );
160 off.fill( QChar(
' ' ), indent );
161 QString symbolDump = ( mSymbol ? mSymbol->dump() : QStringLiteral(
"[]" ) );
162 QString msg = off + QStringLiteral(
"RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
163 .arg( mLabel ).arg( mMaximumScale ).arg( mMinimumScale )
164 .arg( mFilterExp, symbolDump );
167 Q_FOREACH (
Rule *rule, mChildren )
169 lst.append( rule->
dump( indent + 2 ) );
171 msg += lst.join( QStringLiteral(
"\n" ) );
180 attrs.unite( mFilter->referencedColumns() );
182 attrs.unite( mSymbol->usedAttributes( context ) );
185 Q_FOREACH (
Rule *rule, mChildren )
194 if ( mFilter && mFilter->needsGeometry() )
197 Q_FOREACH (
Rule *rule, mChildren )
210 lst.append( mSymbol.get() );
212 Q_FOREACH (
Rule *rule, mChildren )
214 lst += rule->
symbols( context );
221 mSymbol.reset( sym );
226 mFilterExp = filterExp;
233 if ( currentLevel != -1 )
235 lst <<
QgsLegendSymbolItem( mSymbol.get(), mLabel, mRuleKey,
true, mMaximumScale, mMinimumScale, currentLevel, mParent ? mParent->mRuleKey : QString() );
238 for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
249 if ( ! mFilter || mElseRule || ! context )
263 if ( !
qgsDoubleNear( mMaximumScale, 0.0 ) && mMaximumScale > scale )
265 if ( !
qgsDoubleNear( mMinimumScale, 0.0 ) && mMinimumScale < scale )
272 QgsSymbol *sym = mSymbol ? mSymbol->clone() :
nullptr;
273 Rule *newrule =
new Rule( sym, mMaximumScale, mMinimumScale, mFilterExp, mLabel, mDescription );
276 Q_FOREACH (
Rule *rule, mChildren )
283 QDomElement ruleElem = doc.createElement( QStringLiteral(
"rule" ) );
287 int symbolIndex = symbolMap.size();
288 symbolMap[QString::number( symbolIndex )] = mSymbol.get();
289 ruleElem.setAttribute( QStringLiteral(
"symbol" ), symbolIndex );
291 if ( !mFilterExp.isEmpty() )
292 ruleElem.setAttribute( QStringLiteral(
"filter" ), mFilterExp );
293 if ( mMaximumScale != 0 )
294 ruleElem.setAttribute( QStringLiteral(
"scalemindenom" ), mMaximumScale );
295 if ( mMinimumScale != 0 )
296 ruleElem.setAttribute( QStringLiteral(
"scalemaxdenom" ), mMinimumScale );
297 if ( !mLabel.isEmpty() )
298 ruleElem.setAttribute( QStringLiteral(
"label" ), mLabel );
299 if ( !mDescription.isEmpty() )
300 ruleElem.setAttribute( QStringLiteral(
"description" ), mDescription );
302 ruleElem.setAttribute( QStringLiteral(
"checkstate" ), 0 );
303 ruleElem.setAttribute( QStringLiteral(
"key" ), mRuleKey );
305 Q_FOREACH (
Rule *rule, mChildren )
307 ruleElem.appendChild( rule->
save( doc, symbolMap ) );
316 if (
symbols( context ).isEmpty() )
319 if ( !mFilterExp.isEmpty() )
321 if ( !props.value( QStringLiteral(
"filter" ), QString() ).isEmpty() )
322 props[ QStringLiteral(
"filter" )] += QLatin1String(
" AND " );
323 props[ QStringLiteral(
"filter" )] += mFilterExp;
330 QDomElement ruleElem = doc.createElement( QStringLiteral(
"se:Rule" ) );
331 element.appendChild( ruleElem );
335 QDomElement nameElem = doc.createElement( QStringLiteral(
"se:Name" ) );
336 nameElem.appendChild( doc.createTextNode( mLabel ) );
337 ruleElem.appendChild( nameElem );
339 if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
341 QDomElement descrElem = doc.createElement( QStringLiteral(
"se:Description" ) );
342 if ( !mLabel.isEmpty() )
344 QDomElement titleElem = doc.createElement( QStringLiteral(
"se:Title" ) );
345 titleElem.appendChild( doc.createTextNode( mLabel ) );
346 descrElem.appendChild( titleElem );
348 if ( !mDescription.isEmpty() )
350 QDomElement abstractElem = doc.createElement( QStringLiteral(
"se:Abstract" ) );
351 abstractElem.appendChild( doc.createTextNode( mDescription ) );
352 descrElem.appendChild( abstractElem );
354 ruleElem.appendChild( descrElem );
357 if ( !props.value( QStringLiteral(
"filter" ), QString() ).isEmpty() )
364 mSymbol->toSld( doc, ruleElem, props );
368 Q_FOREACH (
Rule *rule, mChildren )
370 rule->
toSld( doc, element, props );
376 mActiveChildren.clear();
389 mSymbol->startRender( context, fields );
393 QStringList subfilters;
394 Q_FOREACH (
Rule *rule, mChildren )
397 if ( rule->
startRender( context, fields, subfilter ) )
400 mActiveChildren.append( rule );
401 subfilters.append( subfilter );
409 if ( subfilters.length() > 1 || !subfilters.value( 0 ).isEmpty() )
411 if ( subfilters.contains( QStringLiteral(
"TRUE" ) ) )
413 sf = QStringLiteral(
"TRUE" );
417 else if ( subfilters.count() > 50 )
419 std::function<QString( const QStringList & )>bt = [ &bt ](
const QStringList & subf )
421 if ( subf.count( ) == 1 )
425 else if ( subf.count( ) == 2 )
427 return subf.join( QStringLiteral(
") OR (" ) ).prepend(
'(' ).append(
')' );
431 int midpos =
static_cast<int>( subf.length() / 2 );
432 return QStringLiteral(
"(%1) OR (%2)" ).arg( bt( subf.mid( 0, midpos ) ) ).arg( bt( subf.mid( midpos ) ) );
435 sf = bt( subfilters );
439 sf = subfilters.join( QStringLiteral(
") OR (" ) ).prepend(
'(' ).append(
')' );
450 if ( mSymbol || sf.isEmpty() )
451 filter = QStringLiteral(
"TRUE" );
457 else if ( !mFilterExp.trimmed().isEmpty() && !sf.isEmpty() )
458 filter = QStringLiteral(
"(%1) AND (%2)" ).arg( mFilterExp, sf );
459 else if ( !mFilterExp.trimmed().isEmpty() )
461 else if ( sf.isEmpty() )
462 filter = QStringLiteral(
"TRUE" );
466 filter = filter.trimmed();
473 QSet<int> symbolZLevelsSet;
479 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
481 symbolZLevelsSet.insert( mSymbol->symbolLayer( i )->renderingPass() );
486 QList<Rule *>::iterator it;
487 for ( it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
492 return symbolZLevelsSet;
499 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
501 int normLevel = zLevelsToNormLevels.value( mSymbol->symbolLayer( i )->renderingPass() );
502 mSymbolNormZLevels.insert( normLevel );
507 Q_FOREACH (
Rule *rule, mActiveChildren )
519 bool rendered =
false;
522 if ( mSymbol && mIsActive )
525 Q_FOREACH (
int normZLevel, mSymbolNormZLevels )
528 renderQueue[normZLevel].jobs.append(
new RenderJob( featToRender, mSymbol.get() ) );
533 bool willrendersomething =
false;
536 Q_FOREACH (
Rule *rule, mChildren )
549 if ( !willrendersomething )
551 Q_FOREACH (
Rule *rule, mElseRules )
556 if ( !mIsActive || ( mSymbol && !rendered ) )
572 Q_FOREACH (
Rule *rule, mActiveChildren )
579 lst.removeOne( rule );
605 lst.append( mSymbol.get() );
607 Q_FOREACH (
Rule *rule, mActiveChildren )
619 lst.insert( mRuleKey );
621 Q_FOREACH (
Rule *rule, mActiveChildren )
623 bool validKey =
false;
627 lst.removeOne( rule );
658 listChildren = mActiveChildren;
660 Q_FOREACH (
Rule *rule, listChildren )
670 mSymbol->stopRender( context );
672 Q_FOREACH (
Rule *rule, mActiveChildren )
677 mActiveChildren.clear();
678 mSymbolNormZLevels.clear();
683 QString symbolIdx = ruleElem.attribute( QStringLiteral(
"symbol" ) );
685 if ( !symbolIdx.isEmpty() )
687 if ( symbolMap.contains( symbolIdx ) )
689 symbol = symbolMap.take( symbolIdx );
693 QgsDebugMsg(
"symbol for rule " + symbolIdx +
" not found!" );
697 QString filterExp = ruleElem.attribute( QStringLiteral(
"filter" ) );
698 QString
label = ruleElem.attribute( QStringLiteral(
"label" ) );
699 QString
description = ruleElem.attribute( QStringLiteral(
"description" ) );
700 int scaleMinDenom = ruleElem.attribute( QStringLiteral(
"scalemindenom" ), QStringLiteral(
"0" ) ).toInt();
701 int scaleMaxDenom = ruleElem.attribute( QStringLiteral(
"scalemaxdenom" ), QStringLiteral(
"0" ) ).toInt();
702 QString
ruleKey = ruleElem.attribute( QStringLiteral(
"key" ) );
703 Rule *rule =
new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
705 if ( !ruleKey.isEmpty() )
706 rule->mRuleKey = ruleKey;
708 rule->
setActive( ruleElem.attribute( QStringLiteral(
"checkstate" ), QStringLiteral(
"1" ) ).toInt() );
710 QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral(
"rule" ) );
711 while ( !childRuleElem.isNull() )
713 Rule *childRule =
create( childRuleElem, symbolMap );
720 QgsDebugMsg( QStringLiteral(
"failed to init a child rule!" ) );
722 childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral(
"rule" ) );
734 l +=
c->descendants();
741 if ( ruleElem.localName() != QLatin1String(
"Rule" ) )
743 QgsDebugMsg( QStringLiteral(
"invalid element: Rule element expected, %1 found!" ).arg( ruleElem.tagName() ) );
748 int scaleMinDenom = 0, scaleMaxDenom = 0;
752 QDomElement childElem = ruleElem.firstChildElement();
753 while ( !childElem.isNull() )
755 if ( childElem.localName() == QLatin1String(
"Name" ) )
759 if ( label.isEmpty() )
760 label = childElem.firstChild().nodeValue();
762 else if ( childElem.localName() == QLatin1String(
"Description" ) )
765 QDomElement titleElem = childElem.firstChildElement( QStringLiteral(
"Title" ) );
766 if ( !titleElem.isNull() )
768 label = titleElem.firstChild().nodeValue();
771 QDomElement abstractElem = childElem.firstChildElement( QStringLiteral(
"Abstract" ) );
772 if ( !abstractElem.isNull() )
774 description = abstractElem.firstChild().nodeValue();
777 else if ( childElem.localName() == QLatin1String(
"Abstract" ) )
780 description = childElem.firstChild().nodeValue();
782 else if ( childElem.localName() == QLatin1String(
"Title" ) )
785 label = childElem.firstChild().nodeValue();
787 else if ( childElem.localName() == QLatin1String(
"Filter" ) )
803 else if ( childElem.localName() == QLatin1String(
"MinScaleDenominator" ) )
806 int v = childElem.firstChild().nodeValue().toInt( &ok );
810 else if ( childElem.localName() == QLatin1String(
"MaxScaleDenominator" ) )
813 int v = childElem.firstChild().nodeValue().toInt( &ok );
817 else if ( childElem.localName().endsWith( QLatin1String(
"Symbolizer" ) ) )
823 childElem = childElem.nextSiblingElement();
828 if ( !layers.isEmpty() )
845 QgsDebugMsg( QStringLiteral(
"invalid geometry type: found %1" ).arg( geomType ) );
851 return new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
886 bool drawVertexMarker )
906 QList<int> symbolZLevels = symbolZLevelsSet.toList();
907 std::sort( symbolZLevels.begin(), symbolZLevels.end() );
911 QMap<int, int> zLevelsToNormLevels;
912 int maxNormLevel = -1;
913 Q_FOREACH (
int zLevel, symbolZLevels )
915 zLevelsToNormLevels[zLevel] = ++maxNormLevel;
917 QgsDebugMsgLevel( QStringLiteral(
"zLevel %1 -> %2" ).arg( zLevel ).arg( maxNormLevel ), 4 );
943 for (
int i = 0; i < count; i++ )
991 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
992 for (
int i = 0; i < origDescendants.count(); ++i )
993 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
1016 rendererElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"RuleRenderer" ) );
1017 rendererElem.setAttribute( QStringLiteral(
"symbollevels" ), (
mUsingSymbolLevels ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1018 rendererElem.setAttribute( QStringLiteral(
"forceraster" ), (
mForceRaster ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1023 rulesElem.setTagName( QStringLiteral(
"rules" ) );
1024 rendererElem.appendChild( rulesElem );
1027 rendererElem.appendChild( symbolsElem );
1034 QDomElement
orderBy = doc.createElement( QStringLiteral(
"orderby" ) );
1036 rendererElem.appendChild( orderBy );
1038 rendererElem.setAttribute( QStringLiteral(
"enableorderby" ), (
mOrderByEnabled ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1040 return rendererElem;
1051 return rule ? rule->
active() :
true;
1079 QDomElement symbolsElem = element.firstChildElement( QStringLiteral(
"symbols" ) );
1080 if ( symbolsElem.isNull() )
1085 QDomElement rulesElem = element.firstChildElement( QStringLiteral(
"rules" ) );
1102 Rule *root =
nullptr;
1104 QDomElement ruleElem = element.firstChildElement( QStringLiteral(
"Rule" ) );
1105 while ( !ruleElem.isNull() )
1112 root =
new Rule(
nullptr );
1117 ruleElem = ruleElem.nextSiblingElement( QStringLiteral(
"Rule" ) );
1149 if ( cat.
value().type() == QVariant::Int )
1150 value = cat.
value().toString();
1151 else if ( cat.
value().type() == QVariant::Double )
1154 value = QString::number( cat.
value().toDouble(),
'f', 4 );
1157 QString
filter = QStringLiteral(
"%1 = %2" ).arg( attr, value );
1174 else if ( !testExpr.
isField() )
1177 attr = QStringLiteral(
"(%1)" ).arg( attr );
1180 bool firstRange =
true;
1185 QString
filter = QStringLiteral(
"%1 %2 %3 AND %1 <= %4" ).arg( attr, firstRange ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
1187 QString::number( rng.
upperValue(),
'f', 4 ) );
1196 std::sort( scales.begin(), scales.end() );
1200 Q_FOREACH (
int scale, scales )
1204 if ( maxDenom != 0 && maxDenom <= scale )
1206 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, scale, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( scale ) ) );
1210 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, maxDenom, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( maxDenom ) ) );
1215 QString msg( QStringLiteral(
"Rule-based renderer:\n" ) );
1242 std::unique_ptr< QgsRuleBasedRenderer > r;
1243 if ( renderer->
type() == QLatin1String(
"RuleRenderer" ) )
1245 r.reset( dynamic_cast<QgsRuleBasedRenderer *>( renderer->
clone() ) );
1247 else if ( renderer->
type() == QLatin1String(
"singleSymbol" ) )
1250 if ( !singleSymbolRenderer )
1253 std::unique_ptr< QgsSymbol > origSymbol( singleSymbolRenderer->
symbol()->
clone() );
1254 r = qgis::make_unique< QgsRuleBasedRenderer >( origSymbol.release() );
1256 else if ( renderer->
type() == QLatin1String(
"categorizedSymbol" ) )
1259 if ( !categorizedRenderer )
1272 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1279 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1284 if ( category.
value().type() == QVariant::List )
1287 const QVariantList list = category.
value().toList();
1288 for (
const QVariant &v : list )
1291 if ( QVariant( v ).convert( QVariant::Double ) )
1293 values << v.toString();
1301 if ( values.empty() )
1303 expression = QStringLiteral(
"ELSE" );
1307 expression = QStringLiteral(
"%1 IN (%2)" ).arg( attr, values.join(
',' ) );
1313 if ( category.
value().convert( QVariant::Double ) )
1315 value = category.
value().toString();
1323 if ( value == QLatin1String(
"''" ) )
1325 expression = QStringLiteral(
"ELSE" );
1329 expression = QStringLiteral(
"%1 = %2" ).arg( attr, value );
1332 rule->setFilterExpression( expression );
1338 std::unique_ptr< QgsSymbol > origSymbol( category.
symbol()->
clone() );
1339 rule->setSymbol( origSymbol.release() );
1341 rootrule->appendChild( rule.release() );
1344 r = qgis::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1346 else if ( renderer->
type() == QLatin1String(
"graduatedSymbol" ) )
1349 if ( !graduatedRenderer )
1361 else if ( !testExpr.
isField() )
1364 attr = QStringLiteral(
"(%1)" ).arg( attr );
1367 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1371 for (
int i = 0; i < graduatedRenderer->
ranges().size(); ++i )
1373 range = graduatedRenderer->
ranges().value( i );
1374 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1375 rule->setLabel( range.
label() );
1378 expression = attr +
" >= " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1379 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1383 expression = attr +
" > " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1384 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1386 rule->setFilterExpression( expression );
1392 std::unique_ptr< QgsSymbol > symbol( range.
symbol()->
clone() );
1393 rule->setSymbol( symbol.release() );
1395 rootrule->appendChild( rule.release() );
1398 r = qgis::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1400 else if ( renderer->
type() == QLatin1String(
"pointDisplacement" ) || renderer->
type() == QLatin1String(
"pointCluster" ) )
1403 if ( pointDistanceRenderer )
1406 else if ( renderer->
type() == QLatin1String(
"invertedPolygonRenderer" ) )
1409 if ( invertedPolygonRenderer )
1424 QString sizeExpression;
1425 switch ( symbol->
type() )
1431 if ( ! sizeScaleField.isEmpty() )
1433 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
1436 if ( ! rotationField.isEmpty() )
1443 if ( ! sizeScaleField.isEmpty() )
1450 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( lsl->
width() ).arg( sizeScaleField );
1459 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
QgsRuleBasedRenderer(QgsRuleBasedRenderer::Rule *root)
Constructs the renderer from given tree of rules (takes ownership)
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
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.
QString label() const
Returns the label for this category, which is used to represent the category within legends and the l...
Class for parsing and evaluation of expressions (formerly called "search strings").
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
The class is used as a container of context for various read/write operations on other objects...
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the attributes used to evaluate the expression of this rule.
double rendererScale() const
Returns the renderer map scale.
QDomElement save(QDomDocument &doc, QgsSymbolMap &symbolMap) const
QgsSymbolList originalSymbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
QList< QgsLegendSymbolItem > QgsLegendSymbolList
bool filterNeedsGeometry() const override
Returns true if this renderer requires the geometry to apply the filter.
QgsFeatureRequest::OrderBy mOrderBy
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
QgsRuleBasedRenderer::RuleList descendants() const
Returns all children, grand-children, grand-grand-children, grand-gra...
Represents an individual category (class) from a QgsCategorizedSymbolRenderer.
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Abstract base class for all rendered symbols.
QgsRuleBasedRenderer::Rule * takeChild(QgsRuleBasedRenderer::Rule *rule)
take child rule out, set parent as null
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
QList< QgsRuleBasedRenderer::RenderLevel > RenderQueue
Rendering queue: a list of rendering levels.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QgsStringMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
const QgsRuleBasedRenderer::RuleList & children()
Returns all children rules of this rule.
bool renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override
Render a feature using this renderer in the given context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
static void convertToDataDefinedSymbology(QgsSymbol *symbol, const QString &sizeScaleField, const QString &rotationField=QString())
helper function to convert the size scale and rotation fields present in some other renderers to data...
This class keeps data about a rules for rule-based renderer.
QString ruleKey() const
Unique rule identifier (for identification of rule within renderer)
QgsSymbol * symbol() const
Returns the symbol which will be used to render this category.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
void setRuleKey(const QString &key)
Override the assigned rule key (should be used just internally by rule-based renderer) ...
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
QString classAttribute() const
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
QgsLegendSymbolList legendSymbolItems() const override
Returns a list of symbology items for the legend.
QString classAttribute() const
Returns the class attribute for the renderer, which is the field name or expression string from the l...
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
QgsRuleBasedRenderer::FeatureToRender & ftr
Feature to render.
Container of fields for a vector layer.
#define RENDERER_TAG_NAME
void setUsingSymbolLevels(bool usingSymbolLevels)
void checkLegendSymbolItem(const QString &key, bool state=true) override
item in symbology was checked
QSet< int > collectZLevels()
Gets all used z-levels from this rule and children.
Rule * mRootRule
the root node with hierarchical list of rules
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QList< FeatureToRender > mCurrentFeatures
static void clearSymbolMap(QgsSymbolMap &symbols)
double maximumScale() const
Returns the maximum map scale (i.e.
bool willRenderFeature(const QgsFeature &feature, QgsRenderContext *context=nullptr)
only tell whether a feature will be rendered without actually rendering it
QgsPaintEffect * mPaintEffect
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
void setNormZLevels(const QMap< int, int > &zLevelsToNormLevels)
assign normalized z-levels [0..N-1] for this rule's symbol for quick access during rendering ...
QString description() const
A human readable description for this rule.
QString parserErrorString() const
Returns parser error.
QMap< QString, QString > QgsStringMap
virtual double width() const
Returns the estimated width for the line symbol layer.
A marker symbol type, for rendering Point and MultiPoint geometries.
bool isElse() const
Check if this rule is an ELSE rule.
A line symbol type, for rendering LineString and MultiLineString geometries.
bool startRender(QgsRenderContext &context, const QgsFields &fields, QString &filter)
prepare the rule for rendering and its children (build active children array)
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
bool active() const
Returns if this rule is active.
QList< QgsRuleBasedRenderer::Rule * > RuleList
QString dump(int indent=0) const
Dump for debug purpose.
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
double lowerValue() const
int renderingPass() const
RenderResult
The result of rendering a rule.
QList< QgsSymbol * > QgsSymbolList
bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
static QgsFeatureRenderer * createFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType)
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted...
#define QgsDebugMsgLevel(str, level)
const QgsCategoryList & categories() const
Returns a list of all categories recognized by the renderer.
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates a new rule-based renderer instance from XML.
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
QgsRuleBasedRenderer::RuleList rulesForFeature(const QgsFeature &feature, QgsRenderContext *context=nullptr, bool onlyActive=true)
Returns the list of rules used to render the feature in a specific context.
double size() const
Returns the symbol size.
void renderFeatureWithSymbol(const QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker)
Render the feature with the symbol using context.
QgsSymbolList symbols(const QgsRenderContext &context=QgsRenderContext()) const
A QgsRuleBasedRenderer rendering job, consisting of a feature to be rendered with a particular symbol...
void removeChild(QgsRuleBasedRenderer::Rule *rule)
delete child rule
QgsExpression * filter() const
A filter that will check if this rule applies.
~QgsRuleBasedRenderer() override
QList< QgsSymbolLayer * > QgsSymbolLayerList
When drawing a vector layer with rule-based renderer, it goes through the rules and draws features wi...
QList< QgsRuleBasedRenderer::RenderJob * > jobs
List of jobs to render, owned by this object.
bool isFilterOK(const QgsFeature &f, QgsRenderContext *context=nullptr) const
Check if a given feature shall be rendered by this rule.
QgsSymbol * symbol() const
double minimumScale() const
Returns the minimum map scale (i.e.
void insertChild(int i, QgsRuleBasedRenderer::Rule *rule)
add child rule, take ownership, sets this as parent
Render level: a list of jobs to be drawn at particular level for a QgsRuleBasedRenderer.
bool isScaleOK(double scale) const
Check if this rule applies for a given scale.
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
QgsSymbolLayer * symbolLayer(int layer)
Returns a specific symbol layer contained in the symbol.
bool orderByEnabled() const
Returns whether custom ordering will be applied before features are processed by this renderer...
void stopRender(QgsRenderContext &context)
Stop a rendering process.
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
QgsRuleBasedRenderer::Rule * takeChildAt(int i)
take child rule out, set parent as null
void setSymbol(QgsSymbol *sym)
Sets a new symbol (or NULL). Deletes old symbol.
QVariant value() const
Returns the value corresponding to this category.
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns symbol for current feature. Should not be used individually: there could be more symbols for ...
QString expression() const
Returns the original, unmodified expression string.
QgsExpressionContext & expressionContext()
Gets the expression context.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
static void refineRuleRanges(QgsRuleBasedRenderer::Rule *initialRule, QgsGraduatedSymbolRenderer *r)
take a rule and create a list of new rules based on the ranges from graduated symbol renderer ...
void setActive(bool state)
Sets if this rule is active.
QgsRuleBasedRenderer::Rule * clone() const
clone this rule, return new instance
QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext *context=nullptr)
tell which symbols will be used to render the feature
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Contains information about the context of a rendering operation.
Abstract base class for marker symbol layers.
void setIsElse(bool iselse)
Sets if this rule is an ELSE rule.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
bool usingSymbolLevels() const
QgsSymbol * symbol
Symbol to render feature with (not owned by this object).
SymbolType type() const
Returns the symbol's type.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
static QgsRuleBasedRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
creates a QgsRuleBasedRenderer from an existing renderer.
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
bool isField() const
Checks whether an expression consists only of a single field reference.
double upperValue() const
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
QMap< QString, QgsSymbol *> QgsSymbolMap
bool needsGeometry() const
Returns true if this rule or one of its chilren needs the geometry to be applied. ...
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns list of symbols used for rendering the feature.
bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
Rule(QgsSymbol *symbol, int maximumScale=0, int minimumScale=0, const QString &filterExp=QString(), const QString &label=QString(), const QString &description=QString(), bool elseRule=false)
Constructor takes ownership of the symbol.
QgsRuleBasedRenderer * clone() const override
Create a deep copy of this renderer.
QgsLegendSymbolList legendSymbolItems(int currentLevel=-1) const
QgsRuleBasedRenderer::Rule::RenderResult renderFeature(QgsRuleBasedRenderer::FeatureToRender &featToRender, QgsRenderContext &context, QgsRuleBasedRenderer::RenderQueue &renderQueue)
Render a given feature, will recursively call subclasses and only render if the constraints apply...
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static void refineRuleCategories(QgsRuleBasedRenderer::Rule *initialRule, QgsCategorizedSymbolRenderer *r)
take a rule and create a list of new rules based on the categories from categorized symbol renderer ...
bool willRenderFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns whether the renderer will render a feature or not.
QString filter(const QgsFields &fields=QgsFields()) override
If a renderer does not require all the features this method may be overridden and return an expressio...
void setFilterExpression(const QString &filterExp)
Set the expression used to check if a given feature shall be rendered with this rule.
Feature for rendering by a QgsRuleBasedRenderer.
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
static void refineRuleScales(QgsRuleBasedRenderer::Rule *initialRule, QList< int > scales)
take a rule and create a list of new rules with intervals of scales given by the passed scale denomin...
void removeChildAt(int i)
delete child rule
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
static QgsRuleBasedRenderer::Rule * create(QDomElement &ruleElem, QgsSymbolMap &symbolMap)
Create a rule from an XML definition.
QgsRuleBasedRenderer::Rule * findRuleByKey(const QString &key)
Try to find a rule given its unique key.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
const QgsRangeList & ranges() const
void setLabel(const QString &label)
Sets the label for this category, which is used to represent the category within legends and the laye...
static bool createSymbolLayerListFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType, QgsSymbolLayerList &layers)
QgsSymbol * symbol() const
Returns the symbol which will be rendered for every feature.
void setLegendSymbolItem(const QString &key, QgsSymbol *symbol) override
Sets the symbol to be used for a legend symbol item.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
void appendChild(QgsRuleBasedRenderer::Rule *rule)
add child rule, take ownership, sets this as parent
static QgsRuleBasedRenderer::Rule * createFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType)
Create a rule from the SLD provided in element and for the specified geometry type.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
QString dump() const override
Returns debug information about this renderer.
virtual QString layerType() const =0
Returns a string that represents this layer type.
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext *context=nullptr)
Returns which legend keys match the feature.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.