33 #include <QDomDocument>
34 #include <QDomElement>
41 , mScaleMinDenom( scaleMinDenom )
42 , mScaleMaxDenom( scaleMaxDenom )
43 , mFilterExp( filterExp )
45 , mDescription( description )
46 , mElseRule( elseRule )
61 qDeleteAll( mChildren );
67 if ( mFilterExp.trimmed().compare(
"ELSE", Qt::CaseInsensitive ) == 0 )
73 else if ( mFilterExp.trimmed().isEmpty() )
89 mChildren.append( rule );
96 mChildren.insert( i, rule );
103 mChildren.removeAll( rule );
110 delete mChildren.takeAt( i );
116 mChildren.removeAll( rule );
124 Rule* rule = mChildren.takeAt( i );
134 if ( key == mRuleKey )
137 Q_FOREACH (
Rule* rule, mChildren )
149 Q_FOREACH (
Rule* rule, mChildren )
169 QString symbolDump = ( mSymbol ? mSymbol->dump() :
QString(
"[]" ) );
170 QString msg = off +
QString(
"RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
171 .
arg( mLabel ).
arg( mScaleMinDenom ).
arg( mScaleMaxDenom )
172 .
arg( mFilterExp, symbolDump );
175 Q_FOREACH (
Rule* rule, mChildren )
179 msg += lst.
join(
"\n" );
190 attrs.
unite( mSymbol->usedAttributes() );
193 Q_FOREACH (
Rule* rule, mChildren )
206 Q_FOREACH (
Rule* rule, mChildren )
208 lst += rule->
symbols( context );
221 mFilterExp = filterExp;
228 if ( mSymbol && ( ruleFilter.
isEmpty() || mLabel == ruleFilter ) )
229 lst << qMakePair( mLabel, mSymbol );
231 Q_FOREACH (
Rule* rule, mChildren )
244 if ( currentLevel != -1 )
246 lst <<
QgsLegendSymbolItemV2( mSymbol, mLabel, mRuleKey,
true, mScaleMinDenom, mScaleMaxDenom, currentLevel, mParent ? mParent->mRuleKey :
QString() );
265 return res.
toInt() != 0;
272 if ( mScaleMinDenom == 0 && mScaleMaxDenom == 0 )
274 if ( mScaleMinDenom != 0 && mScaleMinDenom > scale )
276 if ( mScaleMaxDenom != 0 && mScaleMaxDenom < scale )
284 Rule* newrule =
new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
287 Q_FOREACH (
Rule* rule, mChildren )
298 int symbolIndex = symbolMap.
size();
302 if ( !mFilterExp.isEmpty() )
304 if ( mScaleMinDenom != 0 )
305 ruleElem.
setAttribute(
"scalemindenom", mScaleMinDenom );
306 if ( mScaleMaxDenom != 0 )
307 ruleElem.
setAttribute(
"scalemaxdenom", mScaleMaxDenom );
308 if ( !mLabel.isEmpty() )
310 if ( !mDescription.isEmpty() )
316 Q_FOREACH (
Rule* rule, mChildren )
327 if (
symbols( context ).isEmpty() )
331 if ( !mFilterExp.isEmpty() )
333 if ( !locProps.
value(
"filter",
"" ).isEmpty() )
334 locProps[
"filter" ] +=
" AND ";
335 locProps[
"filter" ] += mFilterExp;
351 if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
354 if ( !mLabel.isEmpty() )
360 if ( !mDescription.isEmpty() )
369 if ( !locProps.
value(
"filter",
"" ).isEmpty() )
376 mSymbol->toSld( doc, ruleElem, locProps );
380 Q_FOREACH (
Rule* rule, mChildren )
382 rule->
toSld( doc, element, locProps );
394 mActiveChildren.clear();
407 mSymbol->startRender( context, &fields );
412 Q_FOREACH (
Rule* rule, mChildren )
415 if ( rule->
startRender( context, fields , subfilter ) )
418 mActiveChildren.
append( rule );
419 subfilters.
append( subfilter );
427 if ( subfilters.
length() > 1 || !subfilters.
value( 0 ).isEmpty() )
429 if ( subfilters.
contains(
"TRUE" ) )
449 else if ( !mFilterExp.trimmed().isEmpty() && !sf.
isEmpty() )
450 filter =
QString(
"(%1) AND (%2)" ).
arg( mFilterExp, sf );
451 else if ( !mFilterExp.trimmed().isEmpty() )
471 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
473 symbolZLevelsSet.
insert( mSymbol->symbolLayer( i )->renderingPass() );
479 for ( it = mActiveChildren.
begin(); it != mActiveChildren.
end(); ++it )
484 return symbolZLevelsSet;
491 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
493 int normLevel = zLevelsToNormLevels.
value( mSymbol->symbolLayer( i )->renderingPass() );
494 mSymbolNormZLevels.insert( normLevel );
499 Q_FOREACH (
Rule* rule, mActiveChildren )
508 if ( !isFilterOK( featToRender.
feat, &context ) )
511 bool rendered =
false;
514 if ( mSymbol && mIsActive )
517 Q_FOREACH (
int normZLevel, mSymbolNormZLevels )
520 renderQueue[normZLevel].jobs.
append(
new RenderJob( featToRender, mSymbol ) );
525 bool willrendersomething =
false;
528 Q_FOREACH (
Rule* rule, mChildren )
535 willrendersomething |= ( res == Rendered || res == Inactive );
536 rendered |= ( res == Rendered );
541 if ( !willrendersomething )
543 Q_FOREACH (
Rule* rule, mElseRules )
545 rendered |= rule->
renderFeature( featToRender, context, renderQueue ) == Rendered;
548 if ( !mIsActive || ( mSymbol && !rendered ) )
558 if ( !isFilterOK( feat, context ) )
563 Q_FOREACH (
Rule* rule, mActiveChildren )
574 if ( !isFilterOK( feat, context ) )
579 Q_FOREACH (
Rule* rule, mActiveChildren )
589 if ( !isFilterOK( feat, context ) )
593 Q_FOREACH (
Rule* rule, mActiveChildren )
603 if ( !isFilterOK( feat, context ) )
609 Q_FOREACH (
Rule* rule, mActiveChildren )
619 mSymbol->stopRender( context );
621 Q_FOREACH (
Rule* rule, mActiveChildren )
626 mActiveChildren.clear();
627 mSymbolNormZLevels.clear();
636 if ( symbolMap.
contains( symbolIdx ) )
638 symbol = symbolMap.
take( symbolIdx );
642 QgsDebugMsg(
"symbol for rule " + symbolIdx +
" not found!" );
649 int scaleMinDenom = ruleElem.
attribute(
"scalemindenom",
"0" ).
toInt();
650 int scaleMaxDenom = ruleElem.
attribute(
"scalemaxdenom",
"0" ).
toInt();
652 Rule* rule =
new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
660 while ( !childRuleElem.
isNull() )
662 Rule* childRule =
create( childRuleElem, symbolMap );
685 QString label, description, filterExp;
686 int scaleMinDenom = 0, scaleMaxDenom = 0;
691 while ( !childElem.
isNull() )
700 else if ( childElem.
localName() ==
"Description" )
704 if ( !titleElem.
isNull() )
710 if ( !abstractElem.
isNull() )
715 else if ( childElem.
localName() ==
"Abstract" )
720 else if ( childElem.
localName() ==
"Title" )
725 else if ( childElem.
localName() ==
"Filter" )
741 else if ( childElem.
localName() ==
"MinScaleDenominator" )
748 else if ( childElem.
localName() ==
"MaxScaleDenominator" )
789 return new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
823 bool drawVertexMarker )
842 qSort( symbolZLevels );
847 int maxNormLevel = -1;
848 Q_FOREACH (
int zLevel, symbolZLevels )
850 zLevelsToNormLevels[zLevel] = ++maxNormLevel;
876 for (
int i = 0; i < count; i++ )
920 Q_ASSERT( origDescendants.
count() == clonedDescendants.
count() );
921 for (
int i = 0; i < origDescendants.
count(); ++i )
922 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
985 lst << qMakePair( pair.first, pix );
998 return rule ? rule->
active() :
true;
1032 if ( symbolsElem.
isNull() )
1054 Rule* root =
nullptr;
1057 while ( !ruleElem.
isNull() )
1064 root =
new Rule(
nullptr );
1101 if ( cat.
value().
type() == QVariant::Int )
1103 else if ( cat.
value().
type() == QVariant::Double )
1126 else if ( !testExpr.
isField() )
1132 bool firstRange =
true;
1152 Q_FOREACH (
int scale, scales )
1156 if ( maxDenom != 0 && maxDenom <= scale )
1167 QString msg(
"Rule-based renderer:\n" );
1194 if ( renderer->
type() ==
"RuleRenderer" )
1199 if ( renderer->
type() ==
"singleSymbol" )
1202 if ( !singleSymbolRenderer )
1210 if ( renderer->
type() ==
"categorizedSymbol" )
1213 if ( !categorizedRenderer )
1231 for (
int i = 0; i < categorizedRenderer->
categories().
size(); ++i )
1240 if (
QVariant( category.
value() ).convert( QVariant::Double ) )
1250 if ( value ==
"''" )
1252 expression =
"ELSE";
1256 expression =
QString(
"%1 = %2" ).
arg( attr, value );
1274 if ( renderer->
type() ==
"graduatedSymbol" )
1277 if ( !graduatedRenderer )
1289 else if ( !testExpr.
isField() )
1299 for (
int i = 0; i < graduatedRenderer->
ranges().
size();++i )
1331 if ( renderer->
type() ==
"pointDisplacement" )
1334 if ( pointDisplacementRenderer )
1337 if ( renderer->
type() ==
"invertedPolygonRenderer" )
1340 if ( invertedPolygonRenderer )
1350 switch ( symbol->
type() )
1356 if ( ! sizeScaleField.
isEmpty() )
1358 sizeExpression =
QString(
"%1*(%2)" ).
arg( msl->
size() ).arg( sizeScaleField );
1361 if ( ! rotationField.
isEmpty() )
1368 if ( ! sizeScaleField.
isEmpty() )
1375 sizeExpression =
QString(
"%1*(%2)" ).
arg( lsl->
width() ).arg( sizeScaleField );
1384 sizeExpression =
QString(
"%1*(%2)" ).
arg( msl->
size() ).arg( sizeScaleField );
QString dump(int indent=0) const
Dump for debug purpose.
static QDomElement saveSymbols(QgsSymbolV2Map &symbols, const QString &tagName, QDomDocument &doc)
Class for parsing and evaluation of expressions (formerly called "search strings").
void setLabel(const QString &label)
static QgsSymbolV2Map loadSymbols(QDomElement &element)
void setNormZLevels(const QMap< int, int > &zLevelsToNormLevels)
assign normalized z-levels [0..N-1] for this rule's symbol for quick access during rendering ...
#define RENDERER_TAG_NAME
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
QString & append(QChar ch)
virtual 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 hasParserError() const
Returns true if an error occurred when parsing the input expression.
QgsSymbolV2 * symbol() const
A container class for data source field mapping or expression.
const QgsCategoryList & categories() const
bool contains(const Key &key) const
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
virtual double width() const
QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="") const
QString & fill(QChar ch, int size)
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, const QgsStringMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
QgsFeatureRequest::OrderBy orderBy() const
Get the order in which features shall be processed by this renderer.
QSet< int > collectZLevels()
get all used z-levels from this rule and children
QDomNode appendChild(const QDomNode &newChild)
static QgsFeatureRendererV2 * create(QDomElement &element)
virtual QSet< QString > legendKeysForFeature(QgsFeature &feature, QgsRenderContext &context) override
Return legend keys matching a specified feature.
QString attribute(const QString &name, const QString &defValue) const
void setTagName(const QString &name)
QString nodeValue() const
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setActive(bool state)
Sets if this rule is active.
QString classAttribute() const
QString & prepend(QChar ch)
double rendererScale() const
bool isFilterOK(QgsFeature &f, QgsRenderContext *context=nullptr) const
Check if a given feature shall be rendered by this rule.
virtual QgsSymbolV2 * clone() const =0
static QgsFeatureRendererV2 * createFromSld(QDomElement &element, QGis::GeometryType geomType)
QgsSymbolV2List symbols(const QgsRenderContext &context=QgsRenderContext()) const
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
bool contains(const QString &str, Qt::CaseSensitivity cs) const
bool isScaleOK(double scale) const
Check if this rule applies for a given scale.
QDomElement nextSiblingElement(const QString &tagName) const
Q_DECL_DEPRECATED bool startRender(QgsRenderContext &context, const QgsFields &fields)
Prepare the rule for rendering and its children (build active children array)
Rule * clone() const
clone this rule, return new instance
~QgsRuleBasedRendererV2()
Container of fields for a vector layer.
void removeChild(Rule *rule)
delete child rule
static void mergeScaleDependencies(int mScaleMinDenom, int mScaleMaxDenom, QgsStringMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
virtual void setLegendSymbolItem(const QString &key, QgsSymbolV2 *symbol) override
Sets the symbol to be used for a legend symbol item.
QString join(const QString &separator) const
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
virtual bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
void setIsElse(bool iselse)
Sets if this rule is an ELSE rule.
bool isElse()
Check if this rule is an ELSE rule.
QMap< QString, QString > QgsStringMap
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
QgsPaintEffect * mPaintEffect
Rule * takeChild(Rule *rule)
take child rule out, set parent as null
void removeChildAt(int i)
delete child rule
virtual QgsSymbolV2List originalSymbolsForFeature(QgsFeature &feat, QgsRenderContext &context) override
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
virtual bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
Rule * findRuleByKey(const QString &key)
Try to find a rule given its unique key.
void renderFeatureWithSymbol(QgsFeature &feature, QgsSymbolV2 *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker)
double upperValue() const
virtual void checkLegendSymbolItem(const QString &key, bool state=true) override
item in symbology was checked
static bool createSymbolLayerV2ListFromSld(QDomElement &element, QGis::GeometryType geomType, QgsSymbolLayerV2List &layers)
void stopRender(QgsRenderContext &context)
Stop a rendering process.
virtual QgsFeatureRendererV2 * clone() const =0
QString number(int n, int base)
int count(const T &value) const
virtual QDomElement save(QDomDocument &doc) override
store renderer info to XML element
void append(const T &value)
static void refineRuleCategories(Rule *initialRule, QgsCategorizedSymbolRendererV2 *r)
take a rule and create a list of new rules based on the categories from categorized symbol renderer ...
QString localName() const
const QgsFeatureRendererV2 * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
int scaleMinDenom() const
int toInt(bool *ok) const
QList< T > values() const
virtual void stopRender(QgsRenderContext &context) override
Needs to be called when a render cycle has finished to clean up.
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted...
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const
Creates a DOM element representing the rule in SLD format.
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const
void appendChild(Rule *rule)
add child rule, take ownership, sets this as parent
static Rule * create(QDomElement &ruleElem, QgsSymbolV2Map &symbolMap)
Create a rule from an XML definition.
RenderResult renderFeature(FeatureToRender &featToRender, QgsRenderContext &context, RenderQueue &renderQueue)
Render a given feature, will recursively call subclasses and only render if the constraints apply...
QgsSymbolV2 * symbol() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QSet< QString > legendKeysForFeature(QgsFeature &feat, QgsRenderContext *context=nullptr)
Returns which legend keys match the feature.
int symbolLayerCount()
Returns total number of symbol layers contained in the symbol.
This class keeps data about a rules for rule-based renderer.
void setRuleKey(const QString &key)
Override the assigned rule key (should be used just internally by rule-based renderer) ...
virtual void toSld(QDomDocument &doc, QDomElement &element) const override
Writes the SLD element following the SLD v1.1 specs.
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
bool isField() const
Checks whether an expression consists only of a single field reference.
virtual QgsLegendSymbologyList legendSymbologyItems(QSize iconSize) override
return a list of symbology items for the legend
QString ruleKey() const
Unique rule identifier (for identification of rule within renderer)
bool willRenderFeature(QgsFeature &feat, QgsRenderContext *context=nullptr)
only tell whether a feature will be rendered without actually rendering it
QList< RenderJob * > jobs
virtual Q_DECL_DEPRECATED QgsSymbolV2List symbols()
For symbol levels.
Rule * mRootRule
the root node with hierarchical list of rules
virtual bool renderFeature(QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override
Render a feature using this renderer in the given context.
static void refineRuleRanges(Rule *initialRule, QgsGraduatedSymbolRendererV2 *r)
take a rule and create a list of new rules based on the ranges from graduated symbol renderer ...
Rule * takeChildAt(int i)
take child rule out, set parent as null
RuleList descendants() const
Returns all children, grand-children, grand-grand-children, grand-gra...
QDomText createTextNode(const QString &value)
QgsSymbolV2List symbolsForFeature(QgsFeature &feat, QgsRenderContext *context=nullptr)
tell which symbols will be used to render the feature
void updateElseRules()
Check which child rules are else rules and update the internal list of else rules.
QgsLegendSymbolListV2 legendSymbolItemsV2(int currentLevel=-1) const
int renderingPass() const
virtual QString layerType() const =0
Returns a string that represents this layer type.
QgsExpressionContext & expressionContext()
Gets the expression context.
void copyRendererData(QgsFeatureRendererV2 *destRenderer) const
Clones generic renderer data to another renderer.
A renderer that automatically displaces points with the same position.
virtual QgsSymbolV2 * subSymbol()
QgsRuleBasedRendererV2(QgsRuleBasedRendererV2::Rule *root)
Constructs the renderer from given tree of rules (takes ownership)
void setUsingSymbolLevels(bool usingSymbolLevels)
virtual QString dump() const override
for debugging
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
int scaleMaxDenom() const
QString sizeScaleField() const
Contains information about the context of a rendering operation.
virtual QgsSymbolV2List symbolsForFeature(QgsFeature &feat, QgsRenderContext &context) override
return list of symbols used for rendering the feature.
virtual QgsSymbolV2 * symbolForFeature(QgsFeature &feature, QgsRenderContext &context) override
return symbol for current feature. Should not be used individually: there could be more symbols for a...
QDomNode firstChild() const
static void convertToDataDefinedSymbology(QgsSymbolV2 *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...
RenderResult
The result of rendering a rule.
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
QSet< T > & unite(const QSet< T > &other)
Rule(QgsSymbolV2 *symbol, int scaleMinDenom=0, int scaleMaxDenom=0, const QString &filterExp=QString(), const QString &label=QString(), const QString &description=QString(), bool elseRule=false)
Constructor takes ownership of the symbol.
static QPixmap symbolPreviewPixmap(QgsSymbolV2 *symbol, QSize size, QgsRenderContext *customContext=nullptr)
double lowerValue() const
const QgsRangeList & ranges() const
QgsFeatureRequest::OrderBy mOrderBy
QString sizeScaleField() const
When drawing a vector layer with rule-based renderer, it goes through the rules and draws features wi...
static Rule * createFromSld(QDomElement &element, QGis::GeometryType geomType)
RuleList rulesForFeature(QgsFeature &feat, QgsRenderContext *context=nullptr)
tell which rules will be used to render the feature
QDomElement firstChildElement(const QString &tagName) const
bool usingSymbolLevels() const
QString sizeScaleField() const
static QgsExpression * expressionFromOgcFilter(const QDomElement &element)
Parse XML with OGC filter into QGIS expression.
virtual void startRender(QgsRenderContext &context, const QgsFields &fields) override
Needs to be called when a new render cycle is started.
virtual QgsRuleBasedRendererV2 * clone() const override
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const override
Return a list of symbology items for the legend.
QString expression() const
Return the original, unmodified expression string.
QList< T > toList() const
QString classAttribute() const
static void clearSymbolMap(QgsSymbolV2Map &symbols)
void setSymbol(QgsSymbolV2 *sym)
set a new symbol (or NULL). Deletes old symbol.
virtual QList< QString > usedAttributes() override
Returns a set of attributes required for this renderer.
double toDouble(bool *ok) const
static QgsRuleBasedRendererV2 * convertFromRenderer(const QgsFeatureRendererV2 *renderer)
creates a QgsRuleBasedRendererV2 from an existing renderer.
QSet< QString > usedAttributes() const
Return the attributes used to evaluate the expression of this rule.
QgsSymbolLayerV2 * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
void insertChild(int i, Rule *rule)
add child rule, take ownership, sets this as parent
void setFilterExpression(const QString &filterExp)
Set the expression used to check if a given feature shall be rendered with this rule.
QDomElement createElement(const QString &tagName)
QString parserErrorString() const
Returns parser error.
bool active() const
Returns if this rule is active.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QgsSymbolV2 * symbol() const
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="") override
return a list of item text / symbol
const QgsFeatureRendererV2 * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
QList< FeatureToRender > mCurrentFeatures
QDomElement save(QDomDocument &doc, QgsSymbolV2Map &symbolMap) const
virtual bool willRenderFeature(QgsFeature &feat, QgsRenderContext &context) override
return whether the renderer will render a feature or not.
static void refineRuleScales(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...
const T value(const Key &key) const
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.