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 const auto constMChildren = mChildren;
131 for (
Rule *rule : constMChildren )
140 void QgsRuleBasedRenderer::Rule::updateElseRules()
143 const auto constMChildren = mChildren;
144 for (
Rule *rule : constMChildren )
146 if ( rule->isElse() )
153 mFilterExp = QStringLiteral(
"ELSE" );
162 off.fill( QChar(
' ' ), indent );
163 QString symbolDump = ( mSymbol ? mSymbol->dump() : QStringLiteral(
"[]" ) );
164 QString msg = off + QStringLiteral(
"RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
165 .arg( mLabel ).arg( mMaximumScale ).arg( mMinimumScale )
166 .arg( mFilterExp, symbolDump );
169 const auto constMChildren = mChildren;
170 for (
Rule *rule : constMChildren )
172 lst.append( rule->dump( indent + 2 ) );
174 msg += lst.join( QStringLiteral(
"\n" ) );
183 attrs.unite( mFilter->referencedColumns() );
185 attrs.unite( mSymbol->usedAttributes( context ) );
188 const auto constMChildren = mChildren;
189 for (
Rule *rule : constMChildren )
191 attrs.unite( rule->usedAttributes( context ) );
198 if ( mFilter && mFilter->needsGeometry() )
201 const auto constMChildren = mChildren;
202 for (
Rule *rule : constMChildren )
204 if ( rule->needsGeometry() )
215 lst.append( mSymbol.get() );
217 const auto constMChildren = mChildren;
218 for (
Rule *rule : constMChildren )
220 lst += rule->symbols( context );
227 mSymbol.reset( sym );
232 mFilterExp = filterExp;
239 if ( currentLevel != -1 )
241 lst <<
QgsLegendSymbolItem( mSymbol.get(), mLabel, mRuleKey,
true, mMaximumScale, mMinimumScale, currentLevel, mParent ? mParent->mRuleKey : QString() );
244 for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
255 if ( ! mFilter || mElseRule || ! context )
269 if ( !
qgsDoubleNear( mMaximumScale, 0.0 ) && mMaximumScale > scale )
271 if ( !
qgsDoubleNear( mMinimumScale, 0.0 ) && mMinimumScale < scale )
278 QgsSymbol *sym = mSymbol ? mSymbol->clone() :
nullptr;
279 Rule *newrule =
new Rule( sym, mMaximumScale, mMinimumScale, mFilterExp, mLabel, mDescription );
282 const auto constMChildren = mChildren;
283 for (
Rule *rule : constMChildren )
290 QDomElement ruleElem = doc.createElement( QStringLiteral(
"rule" ) );
294 int symbolIndex = symbolMap.size();
295 symbolMap[QString::number( symbolIndex )] = mSymbol.get();
296 ruleElem.setAttribute( QStringLiteral(
"symbol" ), symbolIndex );
298 if ( !mFilterExp.isEmpty() )
299 ruleElem.setAttribute( QStringLiteral(
"filter" ), mFilterExp );
300 if ( mMaximumScale != 0 )
301 ruleElem.setAttribute( QStringLiteral(
"scalemindenom" ), mMaximumScale );
302 if ( mMinimumScale != 0 )
303 ruleElem.setAttribute( QStringLiteral(
"scalemaxdenom" ), mMinimumScale );
304 if ( !mLabel.isEmpty() )
305 ruleElem.setAttribute( QStringLiteral(
"label" ), mLabel );
306 if ( !mDescription.isEmpty() )
307 ruleElem.setAttribute( QStringLiteral(
"description" ), mDescription );
309 ruleElem.setAttribute( QStringLiteral(
"checkstate" ), 0 );
310 ruleElem.setAttribute( QStringLiteral(
"key" ), mRuleKey );
312 const auto constMChildren = mChildren;
313 for (
Rule *rule : constMChildren )
315 ruleElem.appendChild( rule->save( doc, symbolMap ) );
324 if (
symbols( context ).isEmpty() )
327 if ( !mFilterExp.isEmpty() )
329 if ( !props.value( QStringLiteral(
"filter" ), QString() ).isEmpty() )
330 props[ QStringLiteral(
"filter" )] += QLatin1String(
" AND " );
331 props[ QStringLiteral(
"filter" )] += mFilterExp;
338 QDomElement ruleElem = doc.createElement( QStringLiteral(
"se:Rule" ) );
339 element.appendChild( ruleElem );
343 QDomElement nameElem = doc.createElement( QStringLiteral(
"se:Name" ) );
344 nameElem.appendChild( doc.createTextNode( mLabel ) );
345 ruleElem.appendChild( nameElem );
347 if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
349 QDomElement descrElem = doc.createElement( QStringLiteral(
"se:Description" ) );
350 if ( !mLabel.isEmpty() )
352 QDomElement titleElem = doc.createElement( QStringLiteral(
"se:Title" ) );
353 titleElem.appendChild( doc.createTextNode( mLabel ) );
354 descrElem.appendChild( titleElem );
356 if ( !mDescription.isEmpty() )
358 QDomElement abstractElem = doc.createElement( QStringLiteral(
"se:Abstract" ) );
359 abstractElem.appendChild( doc.createTextNode( mDescription ) );
360 descrElem.appendChild( abstractElem );
362 ruleElem.appendChild( descrElem );
365 if ( !props.value( QStringLiteral(
"filter" ), QString() ).isEmpty() )
372 mSymbol->toSld( doc, ruleElem, props );
376 const auto constMChildren = mChildren;
377 for (
Rule *rule : constMChildren )
379 rule->toSld( doc, element, props );
385 mActiveChildren.clear();
398 mSymbol->startRender( context, fields );
402 QStringList subfilters;
403 const auto constMChildren = mChildren;
404 for (
Rule *rule : constMChildren )
407 if ( rule->startRender( context, fields, subfilter ) )
410 mActiveChildren.append( rule );
411 subfilters.append( subfilter );
419 if ( subfilters.length() > 1 || !subfilters.value( 0 ).isEmpty() )
421 if ( subfilters.contains( QStringLiteral(
"TRUE" ) ) )
423 sf = QStringLiteral(
"TRUE" );
427 else if ( subfilters.count() > 50 )
429 std::function<QString( const QStringList & )>bt = [ &bt ](
const QStringList & subf )
431 if ( subf.count( ) == 1 )
435 else if ( subf.count( ) == 2 )
437 return subf.join( QStringLiteral(
") OR (" ) ).prepend(
'(' ).append(
')' );
441 int midpos =
static_cast<int>( subf.length() / 2 );
442 return QStringLiteral(
"(%1) OR (%2)" ).arg( bt( subf.mid( 0, midpos ) ) ).arg( bt( subf.mid( midpos ) ) );
445 sf = bt( subfilters );
449 sf = subfilters.join( QStringLiteral(
") OR (" ) ).prepend(
'(' ).append(
')' );
460 if ( mSymbol || sf.isEmpty() )
461 filter = QStringLiteral(
"TRUE" );
467 else if ( !mFilterExp.trimmed().isEmpty() && !sf.isEmpty() )
468 filter = QStringLiteral(
"(%1) AND (%2)" ).arg( mFilterExp, sf );
469 else if ( !mFilterExp.trimmed().isEmpty() )
471 else if ( sf.isEmpty() )
472 filter = QStringLiteral(
"TRUE" );
476 filter = filter.trimmed();
483 QSet<int> symbolZLevelsSet;
489 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
491 symbolZLevelsSet.insert( mSymbol->symbolLayer( i )->renderingPass() );
496 QList<Rule *>::iterator it;
497 for ( it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
502 return symbolZLevelsSet;
509 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
511 int normLevel = zLevelsToNormLevels.value( mSymbol->symbolLayer( i )->renderingPass() );
512 mSymbolNormZLevels.insert( normLevel );
517 const auto constMActiveChildren = mActiveChildren;
518 for (
Rule *rule : constMActiveChildren )
520 rule->setNormZLevels( zLevelsToNormLevels );
530 bool rendered =
false;
533 if ( mSymbol && mIsActive )
536 const auto constMSymbolNormZLevels = mSymbolNormZLevels;
537 for (
int normZLevel : constMSymbolNormZLevels )
540 renderQueue[normZLevel].jobs.append(
new RenderJob( featToRender, mSymbol.get() ) );
545 bool willrendersomething =
false;
548 const auto constMChildren = mChildren;
549 for (
Rule *rule : constMChildren )
552 if ( !rule->isElse() )
554 RenderResult res = rule->renderFeature( featToRender, context, renderQueue );
562 if ( !willrendersomething )
564 const auto constMElseRules = mElseRules;
565 for (
Rule *rule : constMElseRules )
567 rendered |= rule->renderFeature( featToRender, context, renderQueue ) ==
Rendered;
570 if ( !mIsActive || ( mSymbol && !rendered ) )
586 const auto constMActiveChildren = mActiveChildren;
587 for (
Rule *rule : constMActiveChildren )
589 if ( rule->isElse() )
591 if ( rule->children().isEmpty() )
594 lst.removeOne( rule );
603 return rule->willRenderFeature( feature, context );
606 else if ( rule->willRenderFeature( feature, context ) )
620 lst.append( mSymbol.get() );
622 const auto constMActiveChildren = mActiveChildren;
623 for (
Rule *rule : constMActiveChildren )
625 lst += rule->symbolsForFeature( feature, context );
635 lst.insert( mRuleKey );
637 const auto constMActiveChildren = mActiveChildren;
638 for (
Rule *rule : constMActiveChildren )
640 bool validKey =
false;
641 if ( rule->isElse() )
644 lst.removeOne( rule );
651 else if ( !rule->isElse( ) && rule->willRenderFeature( feature, context ) )
658 lst.unite( rule->legendKeysForFeature( feature, context ) );
675 listChildren = mActiveChildren;
677 const auto constListChildren = listChildren;
678 for (
Rule *rule : constListChildren )
680 lst += rule->rulesForFeature( feature, context, onlyActive );
688 mSymbol->stopRender( context );
690 const auto constMActiveChildren = mActiveChildren;
691 for (
Rule *rule : constMActiveChildren )
693 rule->stopRender( context );
696 mActiveChildren.clear();
697 mSymbolNormZLevels.clear();
702 QString symbolIdx = ruleElem.attribute( QStringLiteral(
"symbol" ) );
704 if ( !symbolIdx.isEmpty() )
706 if ( symbolMap.contains( symbolIdx ) )
708 symbol = symbolMap.take( symbolIdx );
712 QgsDebugMsg(
"symbol for rule " + symbolIdx +
" not found!" );
716 QString filterExp = ruleElem.attribute( QStringLiteral(
"filter" ) );
717 QString
label = ruleElem.attribute( QStringLiteral(
"label" ) );
718 QString
description = ruleElem.attribute( QStringLiteral(
"description" ) );
719 int scaleMinDenom = ruleElem.attribute( QStringLiteral(
"scalemindenom" ), QStringLiteral(
"0" ) ).toInt();
720 int scaleMaxDenom = ruleElem.attribute( QStringLiteral(
"scalemaxdenom" ), QStringLiteral(
"0" ) ).toInt();
721 QString
ruleKey = ruleElem.attribute( QStringLiteral(
"key" ) );
722 Rule *rule =
new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
724 if ( !ruleKey.isEmpty() )
725 rule->mRuleKey = ruleKey;
727 rule->
setActive( ruleElem.attribute( QStringLiteral(
"checkstate" ), QStringLiteral(
"1" ) ).toInt() );
729 QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral(
"rule" ) );
730 while ( !childRuleElem.isNull() )
732 Rule *childRule =
create( childRuleElem, symbolMap );
739 QgsDebugMsg( QStringLiteral(
"failed to init a child rule!" ) );
741 childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral(
"rule" ) );
753 l +=
c->descendants();
760 if ( ruleElem.localName() != QLatin1String(
"Rule" ) )
762 QgsDebugMsg( QStringLiteral(
"invalid element: Rule element expected, %1 found!" ).arg( ruleElem.tagName() ) );
767 int scaleMinDenom = 0, scaleMaxDenom = 0;
771 QDomElement childElem = ruleElem.firstChildElement();
772 while ( !childElem.isNull() )
774 if ( childElem.localName() == QLatin1String(
"Name" ) )
778 if ( label.isEmpty() )
779 label = childElem.firstChild().nodeValue();
781 else if ( childElem.localName() == QLatin1String(
"Description" ) )
784 QDomElement titleElem = childElem.firstChildElement( QStringLiteral(
"Title" ) );
785 if ( !titleElem.isNull() )
787 label = titleElem.firstChild().nodeValue();
790 QDomElement abstractElem = childElem.firstChildElement( QStringLiteral(
"Abstract" ) );
791 if ( !abstractElem.isNull() )
793 description = abstractElem.firstChild().nodeValue();
796 else if ( childElem.localName() == QLatin1String(
"Abstract" ) )
799 description = childElem.firstChild().nodeValue();
801 else if ( childElem.localName() == QLatin1String(
"Title" ) )
804 label = childElem.firstChild().nodeValue();
806 else if ( childElem.localName() == QLatin1String(
"Filter" ) )
822 else if ( childElem.localName() == QLatin1String(
"MinScaleDenominator" ) )
825 int v = childElem.firstChild().nodeValue().toInt( &ok );
829 else if ( childElem.localName() == QLatin1String(
"MaxScaleDenominator" ) )
832 int v = childElem.firstChild().nodeValue().toInt( &ok );
836 else if ( childElem.localName().endsWith( QLatin1String(
"Symbolizer" ) ) )
842 childElem = childElem.nextSiblingElement();
847 if ( !layers.isEmpty() )
864 QgsDebugMsg( QStringLiteral(
"invalid geometry type: found %1" ).arg( geomType ) );
870 return new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
905 bool drawVertexMarker )
925 QList<int> symbolZLevels = symbolZLevelsSet.toList();
926 std::sort( symbolZLevels.begin(), symbolZLevels.end() );
930 QMap<int, int> zLevelsToNormLevels;
931 int maxNormLevel = -1;
932 const auto constSymbolZLevels = symbolZLevels;
933 for (
int zLevel : constSymbolZLevels )
935 zLevelsToNormLevels[zLevel] = ++maxNormLevel;
937 QgsDebugMsgLevel( QStringLiteral(
"zLevel %1 -> %2" ).arg( zLevel ).arg( maxNormLevel ), 4 );
955 for (
const RenderLevel &level : constMRenderQueue )
959 for (
const RenderJob *job : qgis::as_const( level.jobs ) )
966 for (
int i = 0; i < count; i++ )
973 int flags = job->ftr.flags;
1015 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
1016 for (
int i = 0; i < origDescendants.count(); ++i )
1017 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
1040 rendererElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"RuleRenderer" ) );
1041 rendererElem.setAttribute( QStringLiteral(
"symbollevels" ), (
mUsingSymbolLevels ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1042 rendererElem.setAttribute( QStringLiteral(
"forceraster" ), (
mForceRaster ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1047 rulesElem.setTagName( QStringLiteral(
"rules" ) );
1048 rendererElem.appendChild( rulesElem );
1051 rendererElem.appendChild( symbolsElem );
1058 QDomElement
orderBy = doc.createElement( QStringLiteral(
"orderby" ) );
1060 rendererElem.appendChild( orderBy );
1062 rendererElem.setAttribute( QStringLiteral(
"enableorderby" ), (
mOrderByEnabled ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1064 return rendererElem;
1075 return rule ? rule->
active() :
true;
1103 QDomElement symbolsElem = element.firstChildElement( QStringLiteral(
"symbols" ) );
1104 if ( symbolsElem.isNull() )
1109 QDomElement rulesElem = element.firstChildElement( QStringLiteral(
"rules" ) );
1126 Rule *root =
nullptr;
1128 QDomElement ruleElem = element.firstChildElement( QStringLiteral(
"Rule" ) );
1129 while ( !ruleElem.isNull() )
1136 root =
new Rule(
nullptr );
1141 ruleElem = ruleElem.nextSiblingElement( QStringLiteral(
"Rule" ) );
1169 const auto constCategories = r->
categories();
1174 if ( cat.value().type() == QVariant::Int )
1175 value = cat.value().toString();
1176 else if ( cat.value().type() == QVariant::Double )
1179 value = QString::number( cat.value().toDouble(),
'f', 4 );
1182 QString
filter = QStringLiteral(
"%1 = %2" ).arg( attr, value );
1199 else if ( !testExpr.
isField() )
1202 attr = QStringLiteral(
"(%1)" ).arg( attr );
1205 bool firstRange =
true;
1206 const auto constRanges = r->
ranges();
1211 QString
filter = QStringLiteral(
"%1 %2 %3 AND %1 <= %4" ).arg( attr, firstRange ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
1212 QString::number( rng.lowerValue(),
'f', 4 ),
1213 QString::number( rng.upperValue(),
'f', 4 ) );
1222 std::sort( scales.begin(), scales.end() );
1226 const auto constScales = scales;
1227 for (
int scale : constScales )
1231 if ( maxDenom != 0 && maxDenom <= scale )
1233 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, scale, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( scale ) ) );
1237 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, maxDenom, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( maxDenom ) ) );
1242 QString msg( QStringLiteral(
"Rule-based renderer:\n" ) );
1269 std::unique_ptr< QgsRuleBasedRenderer > r;
1270 if ( renderer->
type() == QLatin1String(
"RuleRenderer" ) )
1272 r.reset( dynamic_cast<QgsRuleBasedRenderer *>( renderer->
clone() ) );
1274 else if ( renderer->
type() == QLatin1String(
"singleSymbol" ) )
1277 if ( !singleSymbolRenderer )
1280 std::unique_ptr< QgsSymbol > origSymbol( singleSymbolRenderer->
symbol()->
clone() );
1281 r = qgis::make_unique< QgsRuleBasedRenderer >( origSymbol.release() );
1283 else if ( renderer->
type() == QLatin1String(
"categorizedSymbol" ) )
1286 if ( !categorizedRenderer )
1299 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1306 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1311 if ( category.
value().type() == QVariant::List )
1314 const QVariantList list = category.
value().toList();
1315 for (
const QVariant &v : list )
1318 if ( QVariant( v ).convert( QVariant::Double ) )
1320 values << v.toString();
1328 if ( values.empty() )
1330 expression = QStringLiteral(
"ELSE" );
1334 expression = QStringLiteral(
"%1 IN (%2)" ).arg( attr, values.join(
',' ) );
1340 if ( category.
value().convert( QVariant::Double ) )
1342 value = category.
value().toString();
1350 if ( value == QLatin1String(
"''" ) )
1352 expression = QStringLiteral(
"ELSE" );
1356 expression = QStringLiteral(
"%1 = %2" ).arg( attr, value );
1359 rule->setFilterExpression( expression );
1365 std::unique_ptr< QgsSymbol > origSymbol( category.
symbol()->
clone() );
1366 rule->setSymbol( origSymbol.release() );
1368 rootrule->appendChild( rule.release() );
1371 r = qgis::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1373 else if ( renderer->
type() == QLatin1String(
"graduatedSymbol" ) )
1376 if ( !graduatedRenderer )
1388 else if ( !testExpr.
isField() )
1391 attr = QStringLiteral(
"(%1)" ).arg( attr );
1394 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1398 for (
int i = 0; i < graduatedRenderer->
ranges().size(); ++i )
1400 range = graduatedRenderer->
ranges().value( i );
1401 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = qgis::make_unique< QgsRuleBasedRenderer::Rule >( nullptr );
1402 rule->setLabel( range.
label() );
1405 expression = attr +
" >= " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1406 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1410 expression = attr +
" > " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1411 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1413 rule->setFilterExpression( expression );
1419 std::unique_ptr< QgsSymbol > symbol( range.
symbol()->
clone() );
1420 rule->setSymbol( symbol.release() );
1422 rootrule->appendChild( rule.release() );
1425 r = qgis::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1427 else if ( renderer->
type() == QLatin1String(
"pointDisplacement" ) || renderer->
type() == QLatin1String(
"pointCluster" ) )
1430 if ( pointDistanceRenderer )
1433 else if ( renderer->
type() == QLatin1String(
"invertedPolygonRenderer" ) )
1436 if ( invertedPolygonRenderer )
1451 QString sizeExpression;
1452 switch ( symbol->
type() )
1458 if ( ! sizeScaleField.isEmpty() )
1460 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
1463 if ( ! rotationField.isEmpty() )
1470 if ( ! sizeScaleField.isEmpty() )
1477 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( lsl->
width() ).arg( sizeScaleField );
1486 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 nullptr
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.
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.
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
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.
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.
void renderFeatureWithSymbol(const QgsFeature &feature, QgsSymbol *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker) SIP_THROW(QgsCsException)
Render the feature with the symbol using context.
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
Specifies the rendering pass in which this symbol layer should be rendered.
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.
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...
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 nullptr
void setSymbol(QgsSymbol *sym)
Sets a new symbol (or nullptr). 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
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
bool renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override SIP_THROW(QgsCsException)
Render a feature using this renderer in the given context.
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.