33 #include <QDomDocument>
34 #include <QDomElement>
39 : mParent( NULL ), mSymbol( symbol )
40 , mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom )
41 , mFilterExp( filterExp ), mLabel( label ), mDescription( description )
42 , mElseRule( elseRule )
54 qDeleteAll( mChildren );
60 if ( mElseRule || mFilterExp.compare(
"ELSE", Qt::CaseInsensitive ) == 0 )
65 else if ( !mFilterExp.isEmpty() )
78 mChildren.append( rule );
85 mChildren.insert( i, rule );
92 mChildren.removeAll( rule );
99 Rule* rule = mChildren[i];
100 mChildren.removeAt( i );
107 mChildren.removeAll( rule );
114 Rule* rule = mChildren.takeAt( i );
124 if ( key == mRuleKey )
127 Q_FOREACH (
Rule* rule, mChildren )
139 Q_FOREACH (
Rule* rule, mChildren )
151 QString symbolDump = ( mSymbol ? mSymbol->dump() :
QString(
"[]" ) );
152 QString msg = off +
QString(
"RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
153 .
arg( mLabel ).
arg( mScaleMinDenom ).
arg( mScaleMaxDenom )
154 .
arg( mFilterExp, symbolDump );
157 Q_FOREACH (
Rule* rule, mChildren )
161 msg += lst.
join(
"\n" );
172 attrs.
unite( mSymbol->usedAttributes() );
192 lst += rule->
symbols( context );
206 if ( mSymbol && ( ruleFilter.
isEmpty() || mLabel == ruleFilter ) )
207 lst << qMakePair( mLabel, mSymbol );
212 if ( scaleDenominator == -1 || rule->
isScaleOK( scaleDenominator ) )
223 if ( currentLevel != -1 )
225 lst <<
QgsLegendSymbolItemV2( mSymbol, mLabel, mRuleKey,
true, mScaleMinDenom, mScaleMaxDenom, currentLevel, mParent ? mParent->mRuleKey :
QString() );
244 return res.
toInt() != 0;
251 if ( mScaleMinDenom == 0 && mScaleMaxDenom == 0 )
253 if ( mScaleMinDenom != 0 && mScaleMinDenom > scale )
255 if ( mScaleMaxDenom != 0 && mScaleMaxDenom < scale )
263 Rule* newrule =
new Rule( sym, mScaleMinDenom, mScaleMaxDenom, mFilterExp, mLabel, mDescription );
266 Q_FOREACH (
Rule* rule, mChildren )
277 int symbolIndex = symbolMap.
size();
281 if ( !mFilterExp.isEmpty() )
283 if ( mScaleMinDenom != 0 )
284 ruleElem.
setAttribute(
"scalemindenom", mScaleMinDenom );
285 if ( mScaleMaxDenom != 0 )
286 ruleElem.
setAttribute(
"scalemaxdenom", mScaleMaxDenom );
287 if ( !mLabel.isEmpty() )
289 if ( !mDescription.isEmpty() )
307 if (
symbols( context ).isEmpty() )
310 if ( !mFilterExp.isEmpty() )
312 if ( !props.
value(
"filter",
"" ).isEmpty() )
313 props[
"filter" ] +=
" AND ";
314 props[
"filter" ] += mFilterExp;
317 if ( mScaleMinDenom != 0 )
320 int parentScaleMinDenom = props.
value(
"scaleMinDenom",
"0" ).toInt( &ok );
321 if ( !ok || parentScaleMinDenom <= 0 )
324 props[
"scaleMinDenom" ] =
QString::number( qMax( parentScaleMinDenom, mScaleMinDenom ) );
327 if ( mScaleMaxDenom != 0 )
330 int parentScaleMaxDenom = props.
value(
"scaleMaxDenom",
"0" ).toInt( &ok );
331 if ( !ok || parentScaleMaxDenom <= 0 )
334 props[
"scaleMaxDenom" ] =
QString::number( qMin( parentScaleMaxDenom, mScaleMaxDenom ) );
348 if ( !mLabel.isEmpty() || !mDescription.isEmpty() )
351 if ( !mLabel.isEmpty() )
357 if ( !mDescription.isEmpty() )
366 if ( !props.
value(
"filter",
"" ).isEmpty() )
371 if ( !props.
value(
"scaleMinDenom",
"" ).isEmpty() )
378 if ( !props.
value(
"scaleMaxDenom",
"" ).isEmpty() )
385 mSymbol->toSld( doc, ruleElem, props );
391 ( *it )->toSld( doc, element, props );
403 mActiveChildren.clear();
416 mSymbol->startRender( context, &fields );
425 if ( rule->
startRender( context, fields , subfilter ) )
428 mActiveChildren.append( rule );
429 subfilters.
append( subfilter );
437 if ( subfilters.
length() > 1 || subfilters.
value( 0 ).trimmed().length() > 0 )
451 else if ( mFilterExp.trimmed().length() && sf.
trimmed().
length() )
452 filter =
QString(
"(%1) AND (%2)" ).
arg( mFilterExp, sf );
453 else if ( mFilterExp.trimmed().length() )
473 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
475 symbolZLevelsSet.
insert( mSymbol->symbolLayer( i )->renderingPass() );
481 for ( it = mActiveChildren.
begin(); it != mActiveChildren.
end(); ++it )
486 return symbolZLevelsSet;
493 for (
int i = 0; i < mSymbol->symbolLayerCount(); i++ )
495 int normLevel = zLevelsToNormLevels.
value( mSymbol->symbolLayer( i )->renderingPass() );
496 mSymbolNormZLevels.insert( normLevel );
511 if ( !isFilterOK( featToRender.
feat, &context ) )
514 bool rendered =
false;
517 if ( mSymbol && mIsActive )
520 Q_FOREACH (
int normZLevel, mSymbolNormZLevels )
523 renderQueue[normZLevel].jobs.
append(
new RenderJob( featToRender, mSymbol ) );
528 bool willrendersomething =
false;
531 Q_FOREACH (
Rule* rule, mChildren )
538 willrendersomething |= ( res == Rendered || res == Inactive );
539 rendered |= ( res == Rendered );
544 if ( !willrendersomething )
546 Q_FOREACH (
Rule* rule, mElseRules )
548 rendered |= rule->
renderFeature( featToRender, context, renderQueue ) == Rendered;
561 if ( !isFilterOK( feat, context ) )
578 if ( !isFilterOK( feat, context ) )
594 if ( !isFilterOK( feat, context ) )
611 mSymbol->stopRender( context );
619 mActiveChildren.clear();
620 mSymbolNormZLevels.clear();
629 if ( symbolMap.
contains( symbolIdx ) )
631 symbol = symbolMap.
take( symbolIdx );
635 QgsDebugMsg(
"symbol for rule " + symbolIdx +
" not found!" );
642 int scaleMinDenom = ruleElem.
attribute(
"scalemindenom",
"0" ).
toInt();
643 int scaleMaxDenom = ruleElem.
attribute(
"scalemaxdenom",
"0" ).
toInt();
645 Rule* rule =
new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
653 while ( !childRuleElem.
isNull() )
655 Rule* childRule =
create( childRuleElem, symbolMap );
678 QString label, description, filterExp;
679 int scaleMinDenom = 0, scaleMaxDenom = 0;
684 while ( !childElem.
isNull() )
693 else if ( childElem.
localName() ==
"Description" )
697 if ( !titleElem.
isNull() )
703 if ( !abstractElem.
isNull() )
708 else if ( childElem.
localName() ==
"Abstract" )
713 else if ( childElem.
localName() ==
"Title" )
718 else if ( childElem.
localName() ==
"Filter" )
734 else if ( childElem.
localName() ==
"MinScaleDenominator" )
741 else if ( childElem.
localName() ==
"MaxScaleDenominator" )
759 if ( layers.
size() > 0 )
782 return new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
816 bool drawVertexMarker )
835 qSort( symbolZLevels );
840 int maxNormLevel = -1;
841 Q_FOREACH (
int zLevel, symbolZLevels )
843 zLevelsToNormLevels[zLevel] = ++maxNormLevel;
869 for (
int i = 0; i < count; i++ )
913 Q_ASSERT( origDescendants.
count() == clonedDescendants.
count() );
914 for (
int i = 0; i < origDescendants.
count(); ++i )
915 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
965 lst << qMakePair( pair.first, pix );
1003 if ( symbolsElem.
isNull() )
1028 while ( !ruleElem.
isNull() )
1035 root =
new Rule( 0 );
1072 if ( cat.
value().
type() == QVariant::Int )
1074 else if ( cat.
value().
type() == QVariant::Double )
1097 else if ( !testExpr.
isField() )
1103 bool firstRange =
true;
1123 Q_FOREACH (
int scale, scales )
1127 if ( maxDenom != 0 && maxDenom <= scale )
1138 QString msg(
"Rule-based renderer:\n" );
1160 if ( renderer->
type() ==
"RuleRenderer" )
1165 if ( renderer->
type() ==
"singleSymbol" )
1168 if ( !singleSymbolRenderer )
1176 if ( renderer->
type() ==
"categorizedSymbol" )
1179 if ( !categorizedRenderer )
1187 for (
int i = 0; i < categorizedRenderer->
categories().
size(); ++i )
1196 if (
QVariant( category.
value() ).convert( QVariant::Double ) )
1206 if ( value ==
"''" )
1208 expression =
"ELSE";
1212 expression = categorizedRenderer->
classAttribute() +
" = " + value;
1230 if ( renderer->
type() ==
"graduatedSymbol" )
1234 if ( !graduatedRenderer )
1241 for (
int i = 0; i < graduatedRenderer->
ranges().
size();++i )
1273 if ( renderer->
type() ==
"pointDisplacement" )
1276 if ( pointDisplacementRenderer )
1279 if ( renderer->
type() ==
"invertedPolygonRenderer" )
1282 if ( invertedPolygonRenderer )
1292 switch ( symbol->
type() )
1298 if ( ! sizeScaleField.
isEmpty() )
1300 sizeExpression =
QString(
"%1*(%2)" ).
arg( msl->
size() ).arg( sizeScaleField );
1303 if ( ! rotationField.
isEmpty() )
1310 if ( ! sizeScaleField.
isEmpty() )
1317 sizeExpression =
QString(
"%1*(%2)" ).
arg( lsl->
width() ).arg( sizeScaleField );
1326 sizeExpression =
QString(
"%1*(%2)" ).
arg( msl->
size() ).arg( sizeScaleField );
QString dump(int indent=0) const
Dump for debug purpose.
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props)
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 ...
QgsSymbolV2List symbolsForFeature(QgsFeature &feat, QgsRenderContext *context=0)
tell which symbols will be used to render the feature
#define RENDERER_TAG_NAME
QString & append(QChar ch)
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)
return quoted column reference (in double quotes)
virtual double width() const
QString & fill(QChar ch, int size)
QSet< int > collectZLevels()
get all used z-levels from this rule and children
QDomNode appendChild(const QDomNode &newChild)
const QString expression() const
Alias for dump()
static QgsFeatureRendererV2 * create(QDomElement &element)
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.
QString classAttribute() const
QString & prepend(QChar ch)
QgsSymbolV2List symbols(const QgsRenderContext &context=QgsRenderContext())
double rendererScale() const
virtual QgsSymbolV2 * clone() const =0
virtual QgsFeatureRendererV2 * clone() const override
bool willRenderFeature(QgsFeature &feat, QgsRenderContext *context=0)
only tell whether a feature will be rendered without actually rendering it
static QgsFeatureRendererV2 * createFromSld(QDomElement &element, QGis::GeometryType geomType)
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
bool isFilterOK(QgsFeature &f, QgsRenderContext *context=0) const
Check if a given feature shall be rendered by this rule.
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
RuleList rulesForFeature(QgsFeature &feat, QgsRenderContext *context=0)
tell which rules will be used to render the feature
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
bool isElse()
Check if this rule is an ELSE rule.
QMap< QString, QString > QgsStringMap
QgsPaintEffect * mPaintEffect
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)
void setCheckState(bool state)
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
QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="")
int scaleMinDenom() const
int toInt(bool *ok) const
void takeChild(Rule *rule)
take child rule out, set parent as null
QList< T > values() const
virtual void stopRender(QgsRenderContext &context) override
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted...
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
QDomElement save(QDomDocument &doc, QgsSymbolV2Map &symbolMap)
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
used from subclasses to create SLD Rule elements following 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)
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
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...
QgsFeatureRendererV2 * embeddedRenderer() const
QDomText createTextNode(const QString &value)
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
QgsExpressionContext & expressionContext()
Gets the expression context.
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.
const QgsFeatureRendererV2 * embeddedRenderer() const
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.
void copyPaintEffect(QgsFeatureRendererV2 *destRenderer) const
Copies paint effect of this renderer to another renderer.
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.
double lowerValue() const
const QgsRangeList & ranges() const
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)
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.
QSet< QString > usedAttributes()
Return the attributes used to evaluate the expression of this rule.
static QString quotedString(QString text)
return quoted string (in single quotes)
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const override
Return a list of symbology items for the legend.
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
double toDouble(bool *ok) const
static QgsRuleBasedRendererV2 * convertFromRenderer(const QgsFeatureRendererV2 *renderer)
creates a QgsRuleBasedRendererV2 from an existing renderer.
QgsSymbolLayerV2 * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
virtual QString filter() override
If a renderer does not require all the features this method may be overridden and return an expressio...
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)
static QPixmap symbolPreviewPixmap(QgsSymbolV2 *symbol, QSize size, QgsRenderContext *customContext=0)
QString parserErrorString() const
Returns parser error.
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
QList< FeatureToRender > mCurrentFeatures
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.