38 #include <QDomDocument>
39 #include <QDomElement>
46 , mMaximumScale( scaleMinDenom )
47 , mMinimumScale( scaleMaxDenom )
48 , mFilterExp( filterExp )
50 , mDescription( description )
51 , mElseRule( elseRule )
54 mFilterExp = QStringLiteral(
"ELSE" );
56 mRuleKey = QUuid::createUuid().toString();
62 qDeleteAll( mChildren );
68 if ( mFilterExp.trimmed().compare( QLatin1String(
"ELSE" ), Qt::CaseInsensitive ) == 0 )
73 else if ( mFilterExp.trimmed().isEmpty() )
81 mFilter = std::make_unique< QgsExpression >( mFilterExp );
87 mChildren.append( rule );
94 mChildren.insert( i, rule );
101 mChildren.removeAll( rule );
108 delete mChildren.takeAt( i );
114 mChildren.removeAll( rule );
115 rule->mParent =
nullptr;
122 Rule *rule = mChildren.takeAt( i );
123 rule->mParent =
nullptr;
132 if ( key == mRuleKey )
135 const auto constMChildren = mChildren;
136 for (
Rule *rule : constMChildren )
145 void QgsRuleBasedRenderer::Rule::updateElseRules()
148 const auto constMChildren = mChildren;
149 for (
Rule *rule : constMChildren )
151 if ( rule->isElse() )
158 mFilterExp = QStringLiteral(
"ELSE" );
176 if ( !mChildren.empty() )
178 for (
const Rule *rule : mChildren )
181 if ( !rule->accept( visitor ) )
195 off.fill( QChar(
' ' ), indent );
196 QString symbolDump = ( mSymbol ? mSymbol->dump() : QStringLiteral(
"[]" ) );
197 QString msg = off + QStringLiteral(
"RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
198 .arg( mLabel ).arg( mMaximumScale ).arg( mMinimumScale )
199 .arg( mFilterExp, symbolDump );
202 const auto constMChildren = mChildren;
203 for (
Rule *rule : constMChildren )
205 lst.append( rule->dump( indent + 2 ) );
207 msg += lst.join( QLatin1Char(
'\n' ) );
216 attrs.unite(
mFilter->referencedColumns() );
218 attrs.unite( mSymbol->usedAttributes( context ) );
221 const auto constMChildren = mChildren;
222 for (
Rule *rule : constMChildren )
224 attrs.unite( rule->usedAttributes( context ) );
234 const auto constMChildren = mChildren;
235 for (
Rule *rule : constMChildren )
237 if ( rule->needsGeometry() )
248 lst.append( mSymbol.get() );
250 const auto constMChildren = mChildren;
251 for (
Rule *rule : constMChildren )
253 lst += rule->symbols( context );
260 mSymbol.reset( sym );
265 mFilterExp = filterExp;
272 if ( currentLevel != -1 )
274 lst <<
QgsLegendSymbolItem( mSymbol.get(), mLabel, mRuleKey,
true, mMaximumScale, mMinimumScale, currentLevel, mParent ? mParent->mRuleKey : QString() );
277 for ( RuleList::const_iterator it = mChildren.constBegin(); it != mChildren.constEnd(); ++it )
288 if ( !
mFilter || mElseRule || ! context )
302 if ( !
qgsDoubleNear( mMaximumScale, 0.0 ) && mMaximumScale > scale )
304 if ( !
qgsDoubleNear( mMinimumScale, 0.0 ) && mMinimumScale < scale )
312 Rule *newrule =
new Rule( sym, mMaximumScale, mMinimumScale, mFilterExp, mLabel, mDescription );
315 const auto constMChildren = mChildren;
316 for (
Rule *rule : constMChildren )
323 QDomElement ruleElem = doc.createElement( QStringLiteral(
"rule" ) );
327 int symbolIndex = symbolMap.size();
328 symbolMap[QString::number( symbolIndex )] = mSymbol.get();
329 ruleElem.setAttribute( QStringLiteral(
"symbol" ), symbolIndex );
331 if ( !mFilterExp.isEmpty() )
332 ruleElem.setAttribute( QStringLiteral(
"filter" ), mFilterExp );
333 if ( mMaximumScale != 0 )
334 ruleElem.setAttribute( QStringLiteral(
"scalemindenom" ), mMaximumScale );
335 if ( mMinimumScale != 0 )
336 ruleElem.setAttribute( QStringLiteral(
"scalemaxdenom" ), mMinimumScale );
337 if ( !mLabel.isEmpty() )
338 ruleElem.setAttribute( QStringLiteral(
"label" ), mLabel );
339 if ( !mDescription.isEmpty() )
340 ruleElem.setAttribute( QStringLiteral(
"description" ), mDescription );
342 ruleElem.setAttribute( QStringLiteral(
"checkstate" ), 0 );
343 ruleElem.setAttribute( QStringLiteral(
"key" ), mRuleKey );
345 const auto constMChildren = mChildren;
346 for (
Rule *rule : constMChildren )
348 ruleElem.appendChild( rule->save( doc, symbolMap ) );
357 if (
symbols( context ).isEmpty() )
360 if ( !mFilterExp.isEmpty() )
362 QString
filter = props.value( QStringLiteral(
"filter" ), QString() ).toString();
364 filter += QLatin1String(
" AND " );
366 props[ QStringLiteral(
"filter" )] =
filter;
373 QDomElement ruleElem = doc.createElement( QStringLiteral(
"se:Rule" ) );
374 element.appendChild( ruleElem );
378 QDomElement nameElem = doc.createElement( QStringLiteral(
"se:Name" ) );
379 nameElem.appendChild( doc.createTextNode( mLabel ) );
380 ruleElem.appendChild( nameElem );
382 if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
384 QDomElement descrElem = doc.createElement( QStringLiteral(
"se:Description" ) );
385 if ( !mLabel.isEmpty() )
387 QDomElement titleElem = doc.createElement( QStringLiteral(
"se:Title" ) );
388 titleElem.appendChild( doc.createTextNode( mLabel ) );
389 descrElem.appendChild( titleElem );
391 if ( !mDescription.isEmpty() )
393 QDomElement abstractElem = doc.createElement( QStringLiteral(
"se:Abstract" ) );
394 abstractElem.appendChild( doc.createTextNode( mDescription ) );
395 descrElem.appendChild( abstractElem );
397 ruleElem.appendChild( descrElem );
400 if ( !props.value( QStringLiteral(
"filter" ), QString() ).toString().isEmpty() )
407 mSymbol->toSld( doc, ruleElem, props );
411 const auto constMChildren = mChildren;
412 for (
Rule *rule : constMChildren )
414 rule->toSld( doc, element, props );
420 mActiveChildren.clear();
433 mSymbol->startRender( context, fields );
437 QStringList subfilters;
438 const auto constMChildren = mChildren;
439 for (
Rule *rule : constMChildren )
442 if ( rule->startRender( context, fields, subfilter ) )
445 mActiveChildren.append( rule );
446 subfilters.append( subfilter );
454 if ( subfilters.length() > 1 || !subfilters.value( 0 ).isEmpty() )
456 if ( subfilters.contains( QStringLiteral(
"TRUE" ) ) )
458 sf = QStringLiteral(
"TRUE" );
469 else if ( subfilters.count() > 50 )
471 std::function<QString(
const QStringList & )>bt = [ &bt ](
const QStringList & subf )
473 if ( subf.count( ) == 1 )
477 else if ( subf.count( ) == 2 )
479 return subf.join( QLatin1String(
") OR (" ) ).prepend(
'(' ).append(
')' );
483 int midpos =
static_cast<int>( subf.length() / 2 );
484 return QStringLiteral(
"(%1) OR (%2)" ).arg( bt( subf.mid( 0, midpos ) ), bt( subf.mid( midpos ) ) );
487 sf = bt( subfilters );
491 sf = subfilters.join( QLatin1String(
") OR (" ) ).prepend(
'(' ).append(
')' );
503 if ( mSymbol || sf.isEmpty() )
504 filter = QStringLiteral(
"TRUE" );
510 else if ( !mFilterExp.trimmed().isEmpty() && !sf.isEmpty() )
511 filter = QStringLiteral(
"(%1) AND (%2)" ).arg( mFilterExp, sf );
512 else if ( !mFilterExp.trimmed().isEmpty() )
514 else if ( sf.isEmpty() )
515 filter = QStringLiteral(
"TRUE" );
526 QSet<int> symbolZLevelsSet;
532 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
534 symbolZLevelsSet.insert( mSymbol->symbolLayer( i )->renderingPass() );
539 QList<Rule *>::iterator it;
540 for ( it = mActiveChildren.begin(); it != mActiveChildren.end(); ++it )
545 return symbolZLevelsSet;
552 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
554 int normLevel = zLevelsToNormLevels.value( mSymbol->symbolLayer( i )->renderingPass() );
555 mSymbolNormZLevels.insert( normLevel );
560 const auto constMActiveChildren = mActiveChildren;
561 for (
Rule *rule : constMActiveChildren )
563 rule->setNormZLevels( zLevelsToNormLevels );
570 if ( !isFilterOK( featToRender.
feat, &context ) )
573 bool rendered =
false;
576 if ( mSymbol && mIsActive )
579 const auto constMSymbolNormZLevels = mSymbolNormZLevels;
580 for (
int normZLevel : constMSymbolNormZLevels )
583 renderQueue[normZLevel].jobs.append(
new RenderJob( featToRender, mSymbol.get() ) );
588 bool matchedAChild =
false;
591 const auto constMChildren = mChildren;
592 for (
Rule *rule : constMChildren )
595 if ( !rule->isElse() )
597 const RenderResult res = rule->renderFeature( featToRender, context, renderQueue );
599 matchedAChild |= ( res == Rendered || res == Inactive );
600 rendered |= ( res == Rendered );
605 if ( !matchedAChild )
607 const auto constMElseRules = mElseRules;
608 for (
Rule *rule : constMElseRules )
610 const RenderResult res = rule->renderFeature( featToRender, context, renderQueue );
611 matchedAChild |= ( res == Rendered || res == Inactive );
612 rendered |= res == Rendered;
615 if ( !mIsActive || ( mSymbol && !rendered ) || ( matchedAChild && !rendered ) )
625 if ( !isFilterOK( feature, context ) )
631 const auto constMActiveChildren = mActiveChildren;
632 for (
Rule *rule : constMActiveChildren )
634 if ( rule->isElse() )
636 if ( rule->children().isEmpty() )
638 RuleList lst = rulesForFeature( feature, context,
false );
639 lst.removeOne( rule );
648 return rule->willRenderFeature( feature, context );
651 else if ( rule->willRenderFeature( feature, context ) )
662 if ( !isFilterOK( feature, context ) )
665 lst.append( mSymbol.get() );
667 const auto constMActiveChildren = mActiveChildren;
668 for (
Rule *rule : constMActiveChildren )
670 lst += rule->symbolsForFeature( feature, context );
678 if ( !isFilterOK( feature, context ) )
680 lst.insert( mRuleKey );
682 const auto constMActiveChildren = mActiveChildren;
683 for (
Rule *rule : constMActiveChildren )
685 bool validKey =
false;
686 if ( rule->isElse() )
688 RuleList lst = rulesForFeature( feature, context,
false );
689 lst.removeOne( rule );
696 else if ( !rule->isElse( ) && rule->willRenderFeature( feature, context ) )
703 lst.unite( rule->legendKeysForFeature( feature, context ) );
712 if ( ! isFilterOK( feature, context ) || ( context && ! isScaleOK( context->
rendererScale() ) ) )
720 listChildren = mActiveChildren;
722 const auto constListChildren = listChildren;
723 for (
Rule *rule : constListChildren )
725 lst += rule->rulesForFeature( feature, context, onlyActive );
733 mSymbol->stopRender( context );
735 const auto constMActiveChildren = mActiveChildren;
736 for (
Rule *rule : constMActiveChildren )
738 rule->stopRender( context );
741 mActiveChildren.clear();
742 mSymbolNormZLevels.clear();
747 QString symbolIdx = ruleElem.attribute( QStringLiteral(
"symbol" ) );
749 if ( !symbolIdx.isEmpty() )
751 if ( symbolMap.contains( symbolIdx ) )
753 symbol = symbolMap.take( symbolIdx );
757 QgsDebugMsg(
"symbol for rule " + symbolIdx +
" not found!" );
761 QString filterExp = ruleElem.attribute( QStringLiteral(
"filter" ) );
762 QString label = ruleElem.attribute( QStringLiteral(
"label" ) );
763 QString description = ruleElem.attribute( QStringLiteral(
"description" ) );
764 int scaleMinDenom = ruleElem.attribute( QStringLiteral(
"scalemindenom" ), QStringLiteral(
"0" ) ).toInt();
765 int scaleMaxDenom = ruleElem.attribute( QStringLiteral(
"scalemaxdenom" ), QStringLiteral(
"0" ) ).toInt();
766 QString ruleKey = ruleElem.attribute( QStringLiteral(
"key" ) );
767 Rule *rule =
new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
769 if ( !ruleKey.isEmpty() )
770 rule->mRuleKey = ruleKey;
772 rule->
setActive( ruleElem.attribute( QStringLiteral(
"checkstate" ), QStringLiteral(
"1" ) ).toInt() );
774 QDomElement childRuleElem = ruleElem.firstChildElement( QStringLiteral(
"rule" ) );
775 while ( !childRuleElem.isNull() )
777 Rule *childRule =
create( childRuleElem, symbolMap );
784 QgsDebugMsg( QStringLiteral(
"failed to init a child rule!" ) );
786 childRuleElem = childRuleElem.nextSiblingElement( QStringLiteral(
"rule" ) );
798 l +=
c->descendants();
805 if ( ruleElem.localName() != QLatin1String(
"Rule" ) )
807 QgsDebugMsg( QStringLiteral(
"invalid element: Rule element expected, %1 found!" ).arg( ruleElem.tagName() ) );
811 QString label, description, filterExp;
812 int scaleMinDenom = 0, scaleMaxDenom = 0;
816 QDomElement childElem = ruleElem.firstChildElement();
817 while ( !childElem.isNull() )
819 if ( childElem.localName() == QLatin1String(
"Name" ) )
823 if ( label.isEmpty() )
824 label = childElem.firstChild().nodeValue();
826 else if ( childElem.localName() == QLatin1String(
"Description" ) )
829 QDomElement titleElem = childElem.firstChildElement( QStringLiteral(
"Title" ) );
830 if ( !titleElem.isNull() )
832 label = titleElem.firstChild().nodeValue();
835 QDomElement abstractElem = childElem.firstChildElement( QStringLiteral(
"Abstract" ) );
836 if ( !abstractElem.isNull() )
838 description = abstractElem.firstChild().nodeValue();
841 else if ( childElem.localName() == QLatin1String(
"Abstract" ) )
844 description = childElem.firstChild().nodeValue();
846 else if ( childElem.localName() == QLatin1String(
"Title" ) )
849 label = childElem.firstChild().nodeValue();
851 else if ( childElem.localName() == QLatin1String(
"Filter" ) )
856 if (
filter->hasParserError() )
862 filterExp =
filter->expression();
867 else if ( childElem.localName() == QLatin1String(
"MinScaleDenominator" ) )
870 int v = childElem.firstChild().nodeValue().toInt( &ok );
874 else if ( childElem.localName() == QLatin1String(
"MaxScaleDenominator" ) )
877 int v = childElem.firstChild().nodeValue().toInt( &ok );
881 else if ( childElem.localName().endsWith( QLatin1String(
"Symbolizer" ) ) )
887 childElem = childElem.nextSiblingElement();
892 if ( !layers.isEmpty() )
909 QgsDebugMsg( QStringLiteral(
"invalid geometry type: found %1" ).arg( geomType ) );
915 return new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
950 bool drawVertexMarker )
970 QList<int> symbolZLevels = qgis::setToList( symbolZLevelsSet );
971 std::sort( symbolZLevels.begin(), symbolZLevels.end() );
975 QMap<int, int> zLevelsToNormLevels;
976 int maxNormLevel = -1;
977 const auto constSymbolZLevels = symbolZLevels;
978 for (
int zLevel : constSymbolZLevels )
980 zLevelsToNormLevels[zLevel] = ++maxNormLevel;
982 QgsDebugMsgLevel( QStringLiteral(
"zLevel %1 -> %2" ).arg( zLevel ).arg( maxNormLevel ), 4 );
1000 for (
const RenderLevel &level : constMRenderQueue )
1004 for (
const RenderJob *job : std::as_const( level.jobs ) )
1011 for (
int i = 0; i < count; i++ )
1018 int flags = job->ftr.flags;
1060 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
1061 for (
int i = 0; i < origDescendants.count(); ++i )
1062 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
1084 rendererElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"RuleRenderer" ) );
1089 rulesElem.setTagName( QStringLiteral(
"rules" ) );
1090 rendererElem.appendChild( rulesElem );
1093 rendererElem.appendChild( symbolsElem );
1097 return rendererElem;
1108 return rule ? rule->
active() :
true;
1125 std::function<QString(
Rule *rule )> ruleToExpression;
1126 ruleToExpression = [&ruleToExpression](
Rule * rule ) -> QString
1132 QStringList otherRules;
1133 const QList<QgsRuleBasedRenderer::Rule *> siblings = rule->
parent()->
children();
1134 for (
Rule *sibling : siblings )
1136 if ( sibling == rule )
1139 const QString siblingExpression = ruleToExpression( sibling );
1140 if ( siblingExpression.isEmpty() )
1141 return QStringLiteral(
"FALSE" );
1143 otherRules.append( siblingExpression );
1146 if ( otherRules.empty() )
1147 return QStringLiteral(
"TRUE" );
1150 otherRules.size() > 1
1151 ? QStringLiteral(
"NOT ((%1))" ).arg( otherRules.join( QLatin1String(
") OR (" ) ) )
1152 : QStringLiteral(
"NOT (%1)" ).arg( otherRules.at( 0 ) )
1157 QStringList ruleParts;
1162 ruleParts.append( QStringLiteral(
"@map_scale <= %1" ).arg( rule->
minimumScale() ) );
1165 ruleParts.append( QStringLiteral(
"@map_scale >= %1" ).arg( rule->
maximumScale() ) );
1167 if ( !ruleParts.empty() )
1170 ruleParts.size() > 1
1171 ? QStringLiteral(
"(%1)" ).arg( ruleParts.join( QLatin1String(
") AND (" ) ) )
1185 const QString ruleFilter = ruleToExpression( rule );
1186 if ( !ruleFilter.isEmpty() )
1187 parts.append( ruleFilter );
1193 return parts.empty() ? QStringLiteral(
"TRUE" )
1194 : ( parts.size() > 1
1195 ? QStringLiteral(
"(%1)" ).arg( parts.join( QLatin1String(
") AND (" ) ) )
1217 QDomElement symbolsElem = element.firstChildElement( QStringLiteral(
"symbols" ) );
1218 if ( symbolsElem.isNull() )
1223 QDomElement rulesElem = element.firstChildElement( QStringLiteral(
"rules" ) );
1240 Rule *root =
nullptr;
1242 QDomElement ruleElem = element.firstChildElement( QStringLiteral(
"Rule" ) );
1243 while ( !ruleElem.isNull() )
1250 root =
new Rule(
nullptr );
1255 ruleElem = ruleElem.nextSiblingElement( QStringLiteral(
"Rule" ) );
1283 const auto constCategories = r->
categories();
1288 if ( cat.value().isNull() )
1290 else if ( cat.value().type() == QVariant::Int )
1291 value = cat.value().toString();
1292 else if ( cat.value().type() == QVariant::Double )
1295 value = QString::number( cat.value().toDouble(),
'f', 4 );
1298 const QString
filter = QStringLiteral(
"%1 %2 %3" ).arg( attr, cat.value().isNull() ? QStringLiteral(
"IS" ) : QStringLiteral(
"=" ), value );
1299 const QString label = !cat.label().isEmpty() ? cat.label() :
1300 cat.value().isValid() ? value : QString();
1316 else if ( !testExpr.
isField() )
1319 attr = QStringLiteral(
"(%1)" ).arg( attr );
1322 bool firstRange =
true;
1323 const auto constRanges = r->
ranges();
1328 QString
filter = QStringLiteral(
"%1 %2 %3 AND %1 <= %4" ).arg( attr, firstRange ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
1329 QString::number( rng.lowerValue(),
'f', 4 ),
1330 QString::number( rng.upperValue(),
'f', 4 ) );
1332 QString label = rng.label().isEmpty() ?
filter : rng.label();
1339 std::sort( scales.begin(), scales.end() );
1343 const auto constScales = scales;
1344 for (
int scale : constScales )
1348 if ( maxDenom != 0 && maxDenom <= scale )
1350 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, scale, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( scale ) ) );
1354 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, maxDenom, QString(), QStringLiteral(
"%1 - %2" ).arg( oldScale ).arg( maxDenom ) ) );
1359 QString msg( QStringLiteral(
"Rule-based renderer:\n" ) );
1391 std::unique_ptr< QgsRuleBasedRenderer > r;
1392 if ( renderer->
type() == QLatin1String(
"RuleRenderer" ) )
1396 else if ( renderer->
type() == QLatin1String(
"singleSymbol" ) )
1399 if ( !singleSymbolRenderer )
1402 std::unique_ptr< QgsSymbol > origSymbol( singleSymbolRenderer->
symbol()->
clone() );
1403 r = std::make_unique< QgsRuleBasedRenderer >( origSymbol.release() );
1405 else if ( renderer->
type() == QLatin1String(
"categorizedSymbol" ) )
1408 if ( !categorizedRenderer )
1413 bool isField =
false;
1423 if ( isField && !attr.contains(
'\"' ) )
1429 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = std::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1436 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = std::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1438 rule->setLabel( category.
label() );
1441 if ( category.
value().type() == QVariant::List )
1444 const QVariantList list = category.
value().toList();
1445 for (
const QVariant &v : list )
1448 if ( QVariant( v ).convert( QVariant::Double ) )
1450 values << v.toString();
1458 if ( values.empty() )
1460 expression = QStringLiteral(
"ELSE" );
1464 expression = QStringLiteral(
"%1 IN (%2)" ).arg( attr, values.join(
',' ) );
1470 if ( category.
value().convert( QVariant::Double ) )
1472 value = category.
value().toString();
1480 if ( value == QLatin1String(
"''" ) )
1482 expression = QStringLiteral(
"ELSE" );
1486 expression = QStringLiteral(
"%1 = %2" ).arg( attr, value );
1489 rule->setFilterExpression( expression );
1495 std::unique_ptr< QgsSymbol > origSymbol( category.
symbol()->
clone() );
1496 rule->setSymbol( origSymbol.release() );
1498 rootrule->appendChild( rule.release() );
1501 r = std::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1503 else if ( renderer->
type() == QLatin1String(
"graduatedSymbol" ) )
1506 if ( !graduatedRenderer )
1512 bool isField =
false;
1522 if ( isField && !attr.contains(
'\"' ) )
1527 else if ( !isField )
1530 attr = QStringLiteral(
"(%1)" ).arg( attr );
1533 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = std::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1537 for (
int i = 0; i < graduatedRenderer->
ranges().size(); ++i )
1539 range = graduatedRenderer->
ranges().value( i );
1540 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = std::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1541 rule->setLabel( range.
label() );
1544 expression = attr +
" >= " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1545 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1549 expression = attr +
" > " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1550 attr +
" <= " + QString::number( range.
upperValue(),
'f' );
1552 rule->setFilterExpression( expression );
1558 std::unique_ptr< QgsSymbol > symbol( range.
symbol()->
clone() );
1559 rule->setSymbol( symbol.release() );
1561 rootrule->appendChild( rule.release() );
1564 r = std::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1566 else if ( renderer->
type() == QLatin1String(
"pointDisplacement" ) || renderer->
type() == QLatin1String(
"pointCluster" ) )
1571 else if ( renderer->
type() == QLatin1String(
"invertedPolygonRenderer" ) )
1576 else if ( renderer->
type() == QLatin1String(
"mergedFeatureRenderer" ) )
1581 else if ( renderer->
type() == QLatin1String(
"embeddedSymbol" ) && layer )
1585 std::unique_ptr< QgsRuleBasedRenderer::Rule > rootrule = std::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1592 while ( it.
nextFeature( feature ) && rootrule->children().size() < 500 )
1596 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = std::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1597 rule->setFilterExpression( QStringLiteral(
"$id=%1" ).arg( feature.
id() ) );
1598 rule->setLabel( QString::number( feature.
id() ) );
1600 rootrule->appendChild( rule.release() );
1604 std::unique_ptr< QgsRuleBasedRenderer::Rule > rule = std::make_unique< QgsRuleBasedRenderer::Rule >(
nullptr );
1605 rule->setFilterExpression( QStringLiteral(
"ELSE" ) );
1606 rule->setLabel( QObject::tr(
"All other features" ) );
1608 rootrule->appendChild( rule.release() );
1610 r = std::make_unique< QgsRuleBasedRenderer >( rootrule.release() );
1623 QString sizeExpression;
1624 switch ( symbol->
type() )
1630 if ( ! sizeScaleField.isEmpty() )
1632 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
1635 if ( ! rotationField.isEmpty() )
1642 if ( ! sizeScaleField.isEmpty() )
1649 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( lsl->
width() ).arg( sizeScaleField );
1658 sizeExpression = QStringLiteral(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );