34 #include <QDomDocument>
35 #include <QDomElement>
42 , mMaximumScale( scaleMinDenom )
43 , mMinimumScale( scaleMaxDenom )
44 , mFilterExp( filterExp )
46 , mDescription( description )
47 , mElseRule( elseRule )
50 mFilterExp = QStringLiteral(
"ELSE" );
52 mRuleKey = QUuid::createUuid().toString();
58 qDeleteAll( mChildren );
64 if ( mFilterExp.trimmed().compare( QLatin1String(
"ELSE" ), Qt::CaseInsensitive ) == 0 )
69 else if ( mFilterExp.trimmed().isEmpty() )
77 mFilter = qgis::make_unique< QgsExpression >( mFilterExp );
83 mChildren.append( rule );
90 mChildren.insert( i, rule );
97 mChildren.removeAll( rule );
104 delete mChildren.takeAt( i );
110 mChildren.removeAll( rule );
111 rule->mParent =
nullptr;
118 Rule *rule = mChildren.takeAt( i );
119 rule->mParent =
nullptr;
128 if ( key == mRuleKey )
131 const auto constMChildren = mChildren;
132 for (
Rule *rule : constMChildren )
141 void QgsRuleBasedRenderer::Rule::updateElseRules()
144 const auto constMChildren = mChildren;
145 for (
Rule *rule : constMChildren )
147 if ( rule->isElse() )
154 mFilterExp = QStringLiteral(
"ELSE" );
172 if ( !mChildren.empty() )
174 for (
const Rule *rule : mChildren )
177 if ( !rule->accept( visitor ) )
191 off.fill( QChar(
' ' ), indent );
192 QString symbolDump = ( mSymbol ? mSymbol->dump() : QStringLiteral(
"[]" ) );
193 QString msg = off + QStringLiteral(
"RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
194 .arg( mLabel ).arg( mMaximumScale ).arg( mMinimumScale )
195 .arg( mFilterExp, symbolDump );
198 const auto constMChildren = mChildren;
199 for (
Rule *rule : constMChildren )
201 lst.append( rule->dump( indent + 2 ) );
203 msg += lst.join( QLatin1Char(
'\n' ) );
212 attrs.unite(
mFilter->referencedColumns() );
214 attrs.unite( mSymbol->usedAttributes( context ) );
217 const auto constMChildren = mChildren;
218 for (
Rule *rule : constMChildren )
220 attrs.unite( rule->usedAttributes( context ) );
230 const auto constMChildren = mChildren;
231 for (
Rule *rule : constMChildren )
233 if ( rule->needsGeometry() )
244 lst.append( mSymbol.get() );
246 const auto constMChildren = mChildren;
247 for (
Rule *rule : constMChildren )
249 lst += rule->symbols( context );
256 mSymbol.reset( sym );
261 mFilterExp = filterExp;
268 if ( currentLevel != -1 )
270 lst <<
QgsLegendSymbolItem( mSymbol.get(), mLabel, mRuleKey,
true, mMaximumScale, mMinimumScale, currentLevel, mParent ? mParent->mRuleKey : QString() );
273 for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
284 if ( !
mFilter || mElseRule || ! context )
298 if ( !
qgsDoubleNear( mMaximumScale, 0.0 ) && mMaximumScale > scale )
300 if ( !
qgsDoubleNear( mMinimumScale, 0.0 ) && mMinimumScale < scale )
308 Rule *newrule =
new Rule( sym, mMaximumScale, mMinimumScale, mFilterExp, mLabel, mDescription );
311 const auto constMChildren = mChildren;
312 for (
Rule *rule : constMChildren )
319 QDomElement ruleElem = doc.createElement( QStringLiteral(
"rule" ) );
323 int symbolIndex = symbolMap.size();
324 symbolMap[QString::number( symbolIndex )] = mSymbol.get();
325 ruleElem.setAttribute( QStringLiteral(
"symbol" ), symbolIndex );
327 if ( !mFilterExp.isEmpty() )
328 ruleElem.setAttribute( QStringLiteral(
"filter" ), mFilterExp );
329 if ( mMaximumScale != 0 )
330 ruleElem.setAttribute( QStringLiteral(
"scalemindenom" ), mMaximumScale );
331 if ( mMinimumScale != 0 )
332 ruleElem.setAttribute( QStringLiteral(
"scalemaxdenom" ), mMinimumScale );
333 if ( !mLabel.isEmpty() )
334 ruleElem.setAttribute( QStringLiteral(
"label" ), mLabel );
335 if ( !mDescription.isEmpty() )
336 ruleElem.setAttribute( QStringLiteral(
"description" ), mDescription );
338 ruleElem.setAttribute( QStringLiteral(
"checkstate" ), 0 );
339 ruleElem.setAttribute( QStringLiteral(
"key" ), mRuleKey );
341 const auto constMChildren = mChildren;
342 for (
Rule *rule : constMChildren )
344 ruleElem.appendChild( rule->save( doc, symbolMap ) );
353 if (
symbols( context ).isEmpty() )
356 if ( !mFilterExp.isEmpty() )
358 QString
filter = props.value( QStringLiteral(
"filter" ), QString() ).toString();
360 filter += QLatin1String(
" AND " );
362 props[ QStringLiteral(
"filter" )] =
filter;
369 QDomElement ruleElem = doc.createElement( QStringLiteral(
"se:Rule" ) );
370 element.appendChild( ruleElem );
374 QDomElement nameElem = doc.createElement( QStringLiteral(
"se:Name" ) );
375 nameElem.appendChild( doc.createTextNode( mLabel ) );
376 ruleElem.appendChild( nameElem );
378 if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
380 QDomElement descrElem = doc.createElement( QStringLiteral(
"se:Description" ) );
381 if ( !mLabel.isEmpty() )
383 QDomElement titleElem = doc.createElement( QStringLiteral(
"se:Title" ) );
384 titleElem.appendChild( doc.createTextNode( mLabel ) );
385 descrElem.appendChild( titleElem );
387 if ( !mDescription.isEmpty() )
389 QDomElement abstractElem = doc.createElement( QStringLiteral(
"se:Abstract" ) );
390 abstractElem.appendChild( doc.createTextNode( mDescription ) );
391 descrElem.appendChild( abstractElem );
393 ruleElem.appendChild( descrElem );
396 if ( !props.value( QStringLiteral(
"filter" ), QString() ).toString().isEmpty() )
403 mSymbol->toSld( doc, ruleElem, props );
407 const auto constMChildren = mChildren;
408 for (
Rule *rule : constMChildren )
410 rule->toSld( doc, element, props );
416 mActiveChildren.clear();
429 mSymbol->startRender( context, fields );
433 QStringList subfilters;
434 const auto constMChildren = mChildren;
435 for (
Rule *rule : constMChildren )
438 if ( rule->startRender( context, fields, subfilter ) )
441 mActiveChildren.append( rule );
442 subfilters.append( subfilter );
450 if ( subfilters.length() > 1 || !subfilters.value( 0 ).isEmpty() )
452 if ( subfilters.contains( QStringLiteral(
"TRUE" ) ) )
454 sf = QStringLiteral(
"TRUE" );
465 else if ( subfilters.count() > 50 )
467 std::function<QString(
const QStringList & )>bt = [ &bt ](
const QStringList & subf )
469 if ( subf.count( ) == 1 )
473 else if ( subf.count( ) == 2 )
475 return subf.join( QLatin1String(
") OR (" ) ).prepend(
'(' ).append(
')' );
479 int midpos =
static_cast<int>( subf.length() / 2 );
480 return QStringLiteral(
"(%1) OR (%2)" ).arg( bt( subf.mid( 0, midpos ) ), bt( subf.mid( midpos ) ) );
483 sf = bt( subfilters );
487 sf = subfilters.join( QLatin1String(
") OR (" ) ).prepend(
'(' ).append(
')' );
499 if ( mSymbol || sf.isEmpty() )
500 filter = QStringLiteral(
"TRUE" );
506 else if ( !mFilterExp.trimmed().isEmpty() && !sf.isEmpty() )
507 filter = QStringLiteral(
"(%1) AND (%2)" ).arg( mFilterExp, sf );
508 else if ( !mFilterExp.trimmed().isEmpty() )
510 else if ( sf.isEmpty() )
511 filter = QStringLiteral(
"TRUE" );
522 QSet<int> symbolZLevelsSet;
528 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
530 symbolZLevelsSet.insert( mSymbol->symbolLayer( i )->renderingPass() );
535 QList<Rule *>::iterator it;
536 for ( it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
541 return symbolZLevelsSet;
548 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
550 int normLevel = zLevelsToNormLevels.value( mSymbol->symbolLayer( i )->renderingPass() );
551 mSymbolNormZLevels.insert( normLevel );
556 const auto constMActiveChildren = mActiveChildren;
557 for (
Rule *rule : constMActiveChildren )
559 rule->setNormZLevels( zLevelsToNormLevels );
566 if ( !isFilterOK( featToRender.
feat, &context ) )
569 bool rendered =
false;
572 if ( mSymbol && mIsActive )
575 const auto constMSymbolNormZLevels = mSymbolNormZLevels;
576 for (
int normZLevel : constMSymbolNormZLevels )
579 renderQueue[normZLevel].jobs.append(
new RenderJob( featToRender, mSymbol.get() ) );
584 bool willrendersomething =
false;
587 const auto constMChildren = mChildren;
588 for (
Rule *rule : constMChildren )
591 if ( !rule->isElse() )
593 RenderResult res = rule->renderFeature( featToRender, context, renderQueue );
595 willrendersomething |= ( res == Rendered || res == Inactive );
596 rendered |= ( res == Rendered );
601 if ( !willrendersomething )
603 const auto constMElseRules = mElseRules;
604 for (
Rule *rule : constMElseRules )
606 rendered |= rule->renderFeature( featToRender, context, renderQueue ) == Rendered;
609 if ( !mIsActive || ( mSymbol && !rendered ) )
619 if ( !isFilterOK( feature, context ) )
625 const auto constMActiveChildren = mActiveChildren;
626 for (
Rule *rule : constMActiveChildren )
628 if ( rule->isElse() )
630 if ( rule->children().isEmpty() )
632 RuleList lst = rulesForFeature( feature, context,
false );
633 lst.removeOne( rule );
642 return rule->willRenderFeature( feature, context );
645 else if ( rule->willRenderFeature( feature, context ) )
656 if ( !isFilterOK( feature, context ) )
659 lst.append( mSymbol.get() );
661 const auto constMActiveChildren = mActiveChildren;
662 for (
Rule *rule : constMActiveChildren )
664 lst += rule->symbolsForFeature( feature, context );
672 if ( !isFilterOK( feature, context ) )
674 lst.insert( mRuleKey );
676 const auto constMActiveChildren = mActiveChildren;
677 for (
Rule *rule : constMActiveChildren )
679 bool validKey =
false;
680 if ( rule->isElse() )
682 RuleList lst = rulesForFeature( feature, context,
false );
683 lst.removeOne( rule );
690 else if ( !rule->isElse( ) && rule->willRenderFeature( feature, context ) )
697 lst.unite( rule->legendKeysForFeature( feature, context ) );
706 if ( ! isFilterOK( feature, context ) || ( context && ! isScaleOK( context->
rendererScale() ) ) )
714 listChildren = mActiveChildren;
716 const auto constListChildren = listChildren;
717 for (
Rule *rule : constListChildren )
719 lst += rule->rulesForFeature( feature, context, onlyActive );
727 mSymbol->stopRender( context );
729 const auto constMActiveChildren = mActiveChildren;
730 for (
Rule *rule : constMActiveChildren )
732 rule->stopRender( context );
735 mActiveChildren.clear();
736 mSymbolNormZLevels.clear();
741 QString symbolIdx = ruleElem.attribute( QStringLiteral(
"symbol" ) );
743 if ( !symbolIdx.isEmpty() )
745 if ( symbolMap.contains( symbolIdx ) )
747 symbol = symbolMap.take( symbolIdx );
751 QgsDebugMsg(
"symbol for rule " + symbolIdx +
" not found!" );
755 QString filterExp = ruleElem.attribute( QStringLiteral(
"filter" ) );
756 QString label = ruleElem.attribute( QStringLiteral(
"label" ) );
757 QString description = ruleElem.attribute( QStringLiteral(
"description" ) );
758 int scaleMinDenom = ruleElem.attribute( QStringLiteral(
"scalemindenom" ), QStringLiteral(
"0" ) ).toInt();
759 int scaleMaxDenom = ruleElem.attribute( QStringLiteral(
"scalemaxdenom" ), QStringLiteral(
"0" ) ).toInt();
760 QString ruleKey = ruleElem.attribute( QStringLiteral(
"key" ) );
761 Rule *rule =
new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
763 if ( !ruleKey.isEmpty() )
764 rule->mRuleKey = ruleKey;
766 rule->
setActive( ruleElem.attribute( QStringLiteral(
"checkstate" ), QStringLiteral(
"1" ) ).toInt() );
768 QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral(
"rule" ) );
769 while ( !childRuleElem.isNull() )
771 Rule *childRule =
create( childRuleElem, symbolMap );
778 QgsDebugMsg( QStringLiteral(
"failed to init a child rule!" ) );
780 childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral(
"rule" ) );
792 l +=
c->descendants();
799 if ( ruleElem.localName() != QLatin1String(
"Rule" ) )
801 QgsDebugMsg( QStringLiteral(
"invalid element: Rule element expected, %1 found!" ).arg( ruleElem.tagName() ) );
805 QString label, description, filterExp;
806 int scaleMinDenom = 0, scaleMaxDenom = 0;
810 QDomElement childElem = ruleElem.firstChildElement();
811 while ( !childElem.isNull() )
813 if ( childElem.localName() == QLatin1String(
"Name" ) )
817 if ( label.isEmpty() )
818 label = childElem.firstChild().nodeValue();
820 else if ( childElem.localName() == QLatin1String(
"Description" ) )
823 QDomElement titleElem = childElem.firstChildElement( QStringLiteral(
"Title" ) );
824 if ( !titleElem.isNull() )
826 label = titleElem.firstChild().nodeValue();
829 QDomElement abstractElem = childElem.firstChildElement( QStringLiteral(
"Abstract" ) );
830 if ( !abstractElem.isNull() )
832 description = abstractElem.firstChild().nodeValue();
835 else if ( childElem.localName() == QLatin1String(
"Abstract" ) )
838 description = childElem.firstChild().nodeValue();
840 else if ( childElem.localName() == QLatin1String(
"Title" ) )
843 label = childElem.firstChild().nodeValue();
845 else if ( childElem.localName() == QLatin1String(
"Filter" ) )
850 if (
filter->hasParserError() )
856 filterExp =
filter->expression();
861 else if ( childElem.localName() == QLatin1String(
"MinScaleDenominator" ) )
864 int v = childElem.firstChild().nodeValue().toInt( &ok );
868 else if ( childElem.localName() == QLatin1String(
"MaxScaleDenominator" ) )
871 int v = childElem.firstChild().nodeValue().toInt( &ok );
875 else if ( childElem.localName().endsWith( QLatin1String(
"Symbolizer" ) ) )
881 childElem = childElem.nextSiblingElement();
886 if ( !layers.isEmpty() )
903 QgsDebugMsg( QStringLiteral(
"invalid geometry type: found %1" ).arg( geomType ) );
909 return new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
944 bool drawVertexMarker )
964 QList<int> symbolZLevels = qgis::setToList( symbolZLevelsSet );
965 std::sort( symbolZLevels.begin(), symbolZLevels.end() );
969 QMap<int, int> zLevelsToNormLevels;
970 int maxNormLevel = -1;
971 const auto constSymbolZLevels = symbolZLevels;
972 for (
int zLevel : constSymbolZLevels )
974 zLevelsToNormLevels[zLevel] = ++maxNormLevel;
976 QgsDebugMsgLevel( QStringLiteral(
"zLevel %1 -> %2" ).arg( zLevel ).arg( maxNormLevel ), 4 );
994 for (
const RenderLevel &level : constMRenderQueue )
998 for (
const RenderJob *job : qgis::as_const( level.jobs ) )
1005 for (
int i = 0; i < count; i++ )
1012 int flags = job->ftr.flags;
1054 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
1055 for (
int i = 0; i < origDescendants.count(); ++i )
1056 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
1079 rendererElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"RuleRenderer" ) );
1080 rendererElem.setAttribute( QStringLiteral(
"symbollevels" ), (
mUsingSymbolLevels ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1081 rendererElem.setAttribute( QStringLiteral(
"forceraster" ), (
mForceRaster ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1086 rulesElem.setTagName( QStringLiteral(
"rules" ) );
1087 rendererElem.appendChild( rulesElem );
1090 rendererElem.appendChild( symbolsElem );
1097 QDomElement
orderBy = doc.createElement( QStringLiteral(
"orderby" ) );
1099 rendererElem.appendChild(
orderBy );
1101 rendererElem.setAttribute( QStringLiteral(
"enableorderby" ), (
mOrderByEnabled ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1103 return rendererElem;
1114 return rule ? rule->
active() :
true;
1142 QDomElement symbolsElem = element.firstChildElement( QStringLiteral(
"symbols" ) );
1143 if ( symbolsElem.isNull() )
1148 QDomElement rulesElem = element.firstChildElement( QStringLiteral(
"rules" ) );
1165 Rule *root =
nullptr;
1167 QDomElement ruleElem = element.firstChildElement( QStringLiteral(
"Rule" ) );
1168 while ( !ruleElem.isNull() )
1175 root =
new Rule(
nullptr );
1180 ruleElem = ruleElem.nextSiblingElement( QStringLiteral(
"Rule" ) );
1208 const auto constCategories = r->
categories();
1213 if ( cat.value().type() == QVariant::Int )
1214 value = cat.value().toString();
1215 else if ( cat.value().type() == QVariant::Double )
1218 value = QString::number( cat.value().toDouble(),
'f', 4 );
1221 QString
filter = QStringLiteral(
"%1 = %2" ).arg( attr, value );
1238 else if ( !testExpr.
isField() )
1241 attr = QStringLiteral(
"(%1)" ).arg( attr );
1244 bool firstRange =
true;
1245 const auto constRanges = r->
ranges();
1250 QString
filter = QStringLiteral(
"%1 %2 %3 AND %1 <= %4" ).arg( attr, firstRange ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
1251 QString::number( rng.lowerValue(),
'f', 4 ),
1252 QString::number( rng.upperValue(),
'f', 4 ) );
1254 QString label = rng.label().isEmpty() ?
filter : rng.label();
1261 std::sort( scales.begin(), scales.end() );
1265 const auto constScales = scales;
1266 for (
int scale : constScales )
1270 if ( maxDenom != 0 && maxDenom <= scale )
1272 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, scale, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( scale ) ) );
1276 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, maxDenom, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( maxDenom ) ) );
1281 QString msg( QStringLiteral(
"Rule-based renderer:\n" ) );
1313 std::unique_ptr< QgsRuleBasedRenderer > r;
1314 if ( renderer->
type() == QLatin1String(
"RuleRenderer" ) )
1318 else if ( renderer->
type() == QLatin1String(
"singleSymbol" ) )
1321 if ( !singleSymbolRenderer )
1324 std::unique_ptr< QgsSymbol > origSymbol( singleSymbolRenderer->
symbol()->
clone() );
1325 r = qgis::make_unique< QgsRuleBasedRenderer >( origSymbol.release() );
1327 else if ( renderer->
type() == QLatin1String(
"categorizedSymbol" ) )
1330 if ( !categorizedRenderer )
1343 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = qgis::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1350 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = qgis::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1352 rule->setLabel( category.
label() );
1355 if ( category.
value().type() == QVariant::List )
1358 const QVariantList list = category.
value().toList();
1359 for (
const QVariant &v : list )
1362 if ( QVariant( v ).convert( QVariant::Double ) )
1364 values << v.toString();
1372 if ( values.empty() )
1374 expression = QStringLiteral(
"ELSE" );
1378 expression = QStringLiteral(
"%1 IN (%2)" ).arg( attr, values.join(
',' ) );
1384 if ( category.
value().convert( QVariant::Double ) )
1386 value = category.
value().toString();
1394 if ( value == QLatin1String(
"''" ) )
1396 expression = QStringLiteral(
"ELSE" );
1400 expression = QStringLiteral(
"%1 = %2" ).arg( attr, value );
1403 rule->setFilterExpression( expression );
1409 std::unique_ptr< QgsSymbol > origSymbol( category.
symbol()->
clone() );
1410 rule->setSymbol( origSymbol.release() );
1412 rootrule->appendChild( rule.release() );
1415 r = qgis::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1417 else if ( renderer->
type() == QLatin1String(
"graduatedSymbol" ) )
1420 if ( !graduatedRenderer )
1432 else if ( !testExpr.
isField() )
1435 attr = QStringLiteral(
"(%1)" ).arg( attr );
1438 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = qgis::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1442 for (
int i = 0; i < graduatedRenderer->
ranges().size(); ++i )
1444 range = graduatedRenderer->
ranges().value( i );
1445 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = qgis::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1446 rule->setLabel( range.
label() );
1449 expression = attr +
" >= " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1450 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1454 expression = attr +
" > " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1455 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1457 rule->setFilterExpression( expression );
1463 std::unique_ptr< QgsSymbol > symbol( range.
symbol()->
clone() );
1464 rule->setSymbol( symbol.release() );
1466 rootrule->appendChild( rule.release() );
1469 r = qgis::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1471 else if ( renderer->
type() == QLatin1String(
"pointDisplacement" ) || renderer->
type() == QLatin1String(
"pointCluster" ) )
1476 else if ( renderer->
type() == QLatin1String(
"invertedPolygonRenderer" ) )
1481 else if ( renderer->
type() == QLatin1String(
"mergedFeatureRenderer" ) )
1489 r->setOrderBy( renderer->
orderBy() );
1498 QString sizeExpression;
1499 switch ( symbol->
type() )
1505 if ( ! sizeScaleField.isEmpty() )
1507 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
1510 if ( ! rotationField.isEmpty() )
1517 if ( ! sizeScaleField.isEmpty() )
1524 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( lsl->
width() ).arg( sizeScaleField );
1533 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
const QgsCategoryList & categories() const
Returns a list of all categories recognized by the renderer.
QString classAttribute() const
Returns the class attribute for the renderer, which is the field name or expression string from the l...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
bool isField() const
Checks whether an expression consists only of a single field reference.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
static bool attemptReduceToInClause(const QStringList &expressions, QString &result)
Attempts to reduce a list of expressions to a single "field IN (val1, val2, ... )" type expression.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
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.
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
QgsPaintEffect * mPaintEffect
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
bool usingSymbolLevels() const
void setUsingSymbolLevels(bool usingSymbolLevels)
bool orderByEnabled() const
Returns whether custom ordering will be applied before features are processed by this renderer.
QgsFeatureRequest::OrderBy mOrderBy
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Container of fields for a vector layer.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
QString classAttribute() const
const QgsRangeList & ranges() const
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted,...
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
virtual double width() const
Returns the estimated width for the line symbol layer.
A line symbol type, for rendering LineString and MultiLineString geometries.
Abstract base class for marker symbol layers.
double size() const
Returns the symbol size.
A marker symbol type, for rendering Point and MultiPoint geometries.
QgsMergedFeatureRenderer is a polygon or line-only feature renderer used to renderer a set of feature...
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
The class is used as a container of context for various read/write operations on other objects.
Contains information about the context of a rendering operation.
double rendererScale() const
Returns the renderer map scale.
QgsExpressionContext & expressionContext()
Gets the expression context.
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
Represents an individual category (class) from a QgsCategorizedSymbolRenderer.
QgsSymbol * symbol() const
Returns the symbol which will be used to render this category.
QVariant value() const
Returns the value corresponding to this category.
QString label() const
Returns the label for this category, which is used to represent the category within legends and the l...
QgsSymbol * symbol() const
double upperValue() const
double lowerValue() const
This class keeps data about a rules for rule-based renderer.
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all child rules associated with the rule...
QgsRuleBasedRenderer::RuleList descendants() const
Returns all children, grand-children, grand-grand-children, grand-gra...
void setSymbol(QgsSymbol *sym)
Sets a new symbol (or nullptr). Deletes old symbol.
void removeChild(QgsRuleBasedRenderer::Rule *rule)
delete child rule
QgsRuleBasedRenderer::Rule * findRuleByKey(const QString &key)
Try to find a rule given its unique key.
void insertChild(int i, QgsRuleBasedRenderer::Rule *rule)
add child rule, take ownership, sets this as parent
QString ruleKey() const
Unique rule identifier (for identification of rule within renderer)
bool needsGeometry() const
Returns true if this rule or one of its children needs the geometry to be applied.
QgsRuleBasedRenderer::Rule * takeChild(QgsRuleBasedRenderer::Rule *rule)
take child rule out, set parent as nullptr
RenderResult
The result of rendering a rule.
@ Rendered
Something was rendered.
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 maximumScale() const
Returns the maximum map scale (i.e.
void setIsElse(bool iselse)
Sets if this rule is an ELSE rule.
QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext *context=nullptr)
tell which symbols will be used to render the feature
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext *context=nullptr)
Returns which legend keys match the feature.
QgsRuleBasedRenderer::Rule * clone() const
clone this rule, return new instance
bool willRenderFeature(const QgsFeature &feature, QgsRenderContext *context=nullptr)
only tell whether a feature will be rendered without actually rendering it
static QgsRuleBasedRenderer::Rule * create(QDomElement &ruleElem, QgsSymbolMap &symbolMap)
Create a rule from an XML definition.
void removeChildAt(int i)
delete child rule
void setActive(bool state)
Sets if this rule is active.
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.
bool isFilterOK(const QgsFeature &f, QgsRenderContext *context=nullptr) const
Check if a given feature shall be rendered by this rule.
QgsSymbolList symbols(const QgsRenderContext &context=QgsRenderContext()) const
bool isScaleOK(double scale) const
Check if this rule applies for a given scale.
void setNormZLevels(const QMap< int, int > &zLevelsToNormLevels)
assign normalized z-levels [0..N-1] for this rule's symbol for quick access during rendering
QDomElement save(QDomDocument &doc, QgsSymbolMap &symbolMap) const
void appendChild(QgsRuleBasedRenderer::Rule *rule)
add child rule, take ownership, sets this as parent
QgsRuleBasedRenderer::Rule * takeChildAt(int i)
take child rule out, set parent as nullptr
QSet< int > collectZLevels()
Gets all used z-levels from this rule and children.
double minimumScale() const
Returns the minimum map scale (i.e.
void stopRender(QgsRenderContext &context)
Stop a rendering process.
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.
QgsLegendSymbolList legendSymbolItems(int currentLevel=-1) const
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the attributes used to evaluate the expression of this rule.
void setFilterExpression(const QString &filterExp)
Set the expression used to check if a given feature shall be rendered with this rule.
static QgsRuleBasedRenderer::Rule * createFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType)
Create a rule from the SLD provided in element and for the specified geometry type.
QString dump(int indent=0) const
Dump for debug purpose.
void setRuleKey(const QString &key)
Override the assigned rule key (should be used just internally by rule-based renderer)
bool startRender(QgsRenderContext &context, const QgsFields &fields, QString &filter)
prepare the rule for rendering and its children (build active children array)
bool active() const
Returns if this rule is active.
void toSld(QDomDocument &doc, QDomElement &element, QVariantMap props) const
Saves the symbol layer as SLD.
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
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...
static QgsRuleBasedRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
creates a QgsRuleBasedRenderer from an existing renderer.
bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
void setLegendSymbolItem(const QString &key, QgsSymbol *symbol) override
Sets the symbol to be used for a legend symbol item.
void checkLegendSymbolItem(const QString &key, bool state=true) override
item in symbology was checked
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 ...
QList< QgsRuleBasedRenderer::RenderLevel > RenderQueue
Rendering queue: a list of rendering levels.
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
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
QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns list of symbols used for rendering the feature.
QString dump() const override
Returns debug information about this renderer.
QgsSymbolList originalSymbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
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...
bool willRenderFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns whether the renderer will render a feature or not.
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...
QList< QgsRuleBasedRenderer::Rule * > RuleList
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
Rule * mRootRule
the root node with hierarchical list of rules
~QgsRuleBasedRenderer() override
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
bool filterNeedsGeometry() const override
Returns true if this renderer requires the geometry to apply the filter.
QgsRuleBasedRenderer * clone() const override
Create a deep copy of this renderer.
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates a new rule-based renderer instance from XML.
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.
QgsLegendSymbolList legendSymbolItems() const override
Returns a list of symbology items for the legend.
QList< FeatureToRender > mCurrentFeatures
static QgsFeatureRenderer * createFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType)
QgsRuleBasedRenderer(QgsRuleBasedRenderer::Rule *root)
Constructs the renderer from given tree of rules (takes ownership)
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
QgsSymbol * symbol() const
Returns the symbol which will be rendered for every feature.
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 symbol entity for QgsStyle databases.
static bool createSymbolLayerListFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType, QgsSymbolLayerList &layers)
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 bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
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.
static void clearSymbolMap(QgsSymbolMap &symbols)
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 ...
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.
@ PropertyAngle
Symbol angle.
@ PropertySize
Symbol size.
@ PropertyStrokeWidth
Stroke width.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
SymbolType type() const
Returns the symbol's type.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
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)
QList< QgsLegendSymbolItem > QgsLegendSymbolList
#define QgsDebugMsgLevel(str, level)
#define RENDERER_TAG_NAME
QMap< QString, QgsSymbol * > QgsSymbolMap
QList< QgsSymbol * > QgsSymbolList
QList< QgsSymbolLayer * > QgsSymbolLayerList
Feature for rendering by a QgsRuleBasedRenderer.
A QgsRuleBasedRenderer rendering job, consisting of a feature to be rendered with a particular symbol...
Render level: a list of jobs to be drawn at particular level for a QgsRuleBasedRenderer.
Contains information relating to a node (i.e.
Contains information relating to the style entity currently being visited.