30 #include <QDomDocument> 31 #include <QDomElement> 36 : mParent( NULL ), mSymbol( symbol )
37 , mScaleMinDenom( scaleMinDenom ), mScaleMaxDenom( scaleMaxDenom )
38 , mFilterExp( filterExp ), mLabel( label ), mDescription( description )
39 , mElseRule( elseRule )
43 mRuleKey = QUuid::createUuid().toString();
147 off.fill( QChar(
' ' ), offset );
149 QString msg = off + QString(
"RULE %1 - scale [%2,%3] - filter %4 - symbol %5\n" )
156 lst.append( rule->
dump( offset + 2 ) );
158 msg += lst.join(
"\n" );
203 if (
mSymbol && ( ruleFilter.isEmpty() ||
mLabel == ruleFilter ) )
209 if ( scaleDenominator == -1 || rule->
isScaleOK( scaleDenominator ) )
220 if ( currentLevel != -1 )
225 for ( RuleList::const_iterator it =
mChildren.constBegin(); it !=
mChildren.constEnd(); ++it )
240 return res.toInt() != 0;
269 QDomElement ruleElem = doc.createElement(
"rule" );
273 int symbolIndex = symbolMap.size();
274 symbolMap[QString::number( symbolIndex )] =
mSymbol;
275 ruleElem.setAttribute(
"symbol", symbolIndex );
278 ruleElem.setAttribute(
"filter",
mFilterExp );
284 ruleElem.setAttribute(
"label",
mLabel );
288 ruleElem.setAttribute(
"checkstate", 0 );
289 ruleElem.setAttribute(
"key",
mRuleKey );
307 if ( !props.value(
"filter",
"" ).isEmpty() )
308 props[
"filter" ] +=
" AND ";
315 int parentScaleMinDenom = props.value(
"scaleMinDenom",
"0" ).toInt( &ok );
316 if ( !ok || parentScaleMinDenom <= 0 )
319 props[
"scaleMinDenom" ] = QString::number( qMax( parentScaleMinDenom,
mScaleMinDenom ) );
325 int parentScaleMaxDenom = props.value(
"scaleMaxDenom",
"0" ).toInt( &ok );
326 if ( !ok || parentScaleMaxDenom <= 0 )
329 props[
"scaleMaxDenom" ] = QString::number( qMin( parentScaleMaxDenom,
mScaleMaxDenom ) );
334 QDomElement ruleElem = doc.createElement(
"se:Rule" );
335 element.appendChild( ruleElem );
339 QDomElement nameElem = doc.createElement(
"se:Name" );
340 nameElem.appendChild( doc.createTextNode(
mLabel ) );
341 ruleElem.appendChild( nameElem );
345 QDomElement descrElem = doc.createElement(
"se:Description" );
348 QDomElement titleElem = doc.createElement(
"se:Title" );
349 titleElem.appendChild( doc.createTextNode(
mLabel ) );
350 descrElem.appendChild( titleElem );
354 QDomElement abstractElem = doc.createElement(
"se:Abstract" );
355 abstractElem.appendChild( doc.createTextNode(
mDescription ) );
356 descrElem.appendChild( abstractElem );
358 ruleElem.appendChild( descrElem );
361 if ( !props.value(
"filter",
"" ).isEmpty() )
366 if ( !props.value(
"scaleMinDenom",
"" ).isEmpty() )
368 QDomElement scaleMinDenomElem = doc.createElement(
"se:MinScaleDenominator" );
369 scaleMinDenomElem.appendChild( doc.createTextNode( props.value(
"scaleMinDenom",
"" ) ) );
370 ruleElem.appendChild( scaleMinDenomElem );
373 if ( !props.value(
"scaleMaxDenom",
"" ).isEmpty() )
375 QDomElement scaleMaxDenomElem = doc.createElement(
"se:MaxScaleDenominator" );
376 scaleMaxDenomElem.appendChild( doc.createTextNode( props.value(
"scaleMaxDenom",
"" ) ) );
377 ruleElem.appendChild( scaleMaxDenomElem );
386 ( *it )->toSld( doc, element, props );
423 QSet<int> symbolZLevelsSet;
436 QList<Rule*>::iterator it;
442 return symbolZLevelsSet;
470 bool rendered =
false;
479 renderQueue[normZLevel].jobs.append(
new RenderJob( featToRender,
mSymbol ) );
484 bool willrendersomething =
false;
495 willrendersomething |= rule->
renderFeature( featToRender, context, renderQueue );
496 rendered |= willrendersomething;
500 if ( !willrendersomething )
504 rendered |= rule->
renderFeature( featToRender, context, renderQueue );
577 QString symbolIdx = ruleElem.attribute(
"symbol" );
579 if ( !symbolIdx.isEmpty() )
581 if ( symbolMap.contains( symbolIdx ) )
583 symbol = symbolMap.take( symbolIdx );
587 QgsDebugMsg(
"symbol for rule " + symbolIdx +
" not found!" );
591 QString filterExp = ruleElem.attribute(
"filter" );
592 QString
label = ruleElem.attribute(
"label" );
593 QString
description = ruleElem.attribute(
"description" );
594 int scaleMinDenom = ruleElem.attribute(
"scalemindenom",
"0" ).toInt();
595 int scaleMaxDenom = ruleElem.attribute(
"scalemaxdenom",
"0" ).toInt();
596 QString
ruleKey = ruleElem.attribute(
"key" );
597 Rule* rule =
new Rule( symbol, scaleMinDenom, scaleMaxDenom, filterExp, label, description );
599 if ( !ruleKey.isEmpty() )
602 rule->
setCheckState( ruleElem.attribute(
"checkstate",
"1" ).toInt() );
604 QDomElement childRuleElem = ruleElem.firstChildElement(
"rule" );
605 while ( !childRuleElem.isNull() )
607 Rule* childRule =
create( childRuleElem, symbolMap );
616 childRuleElem = childRuleElem.nextSiblingElement(
"rule" );
624 if ( ruleElem.localName() !=
"Rule" )
626 QgsDebugMsg( QString(
"invalid element: Rule element expected, %1 found!" ).arg( ruleElem.tagName() ) );
635 QDomElement childElem = ruleElem.firstChildElement();
636 while ( !childElem.isNull() )
638 if ( childElem.localName() ==
"Name" )
642 if ( label.isEmpty() )
643 label = childElem.firstChild().nodeValue();
645 else if ( childElem.localName() ==
"Description" )
648 QDomElement titleElem = childElem.firstChildElement(
"Title" );
649 if ( !titleElem.isNull() )
651 label = titleElem.firstChild().nodeValue();
654 QDomElement abstractElem = childElem.firstChildElement(
"Abstract" );
655 if ( !abstractElem.isNull() )
657 description = abstractElem.firstChild().nodeValue();
660 else if ( childElem.localName() ==
"Abstract" )
663 description = childElem.firstChild().nodeValue();
665 else if ( childElem.localName() ==
"Title" )
668 label = childElem.firstChild().nodeValue();
670 else if ( childElem.localName() ==
"Filter" )
686 else if ( childElem.localName() ==
"MinScaleDenominator" )
689 int v = childElem.firstChild().nodeValue().toInt( &ok );
693 else if ( childElem.localName() ==
"MaxScaleDenominator" )
696 int v = childElem.firstChild().nodeValue().toInt( &ok );
700 else if ( childElem.localName().endsWith(
"Symbolizer" ) )
706 childElem = childElem.nextSiblingElement();
711 if ( layers.size() > 0 )
728 QgsDebugMsg( QString(
"invalid geometry type: found %1" ).arg( geomType ) );
734 return new Rule( symbol, scaleMinDenom,
scaleMaxDenom, filterExp, label, description );
768 bool drawVertexMarker )
786 QList<int> symbolZLevels = symbolZLevelsSet.toList();
787 qSort( symbolZLevels );
791 QMap<int, int> zLevelsToNormLevels;
792 int maxNormLevel = -1;
793 foreach (
int zLevel, symbolZLevels )
795 zLevelsToNormLevels[zLevel] = ++maxNormLevel;
797 QgsDebugMsg( QString(
"zLevel %1 -> %2" ).arg( zLevel ).arg( maxNormLevel ) );
820 for (
int i = 0; i < count; i++ )
847 return attrs.values();
859 Q_ASSERT( origDescendants.count() == clonedDescendants.count() );
860 for (
int i = 0; i < origDescendants.count(); ++i )
861 clonedDescendants[i]->setRuleKey( origDescendants[i]->ruleKey() );
883 rendererElem.setAttribute(
"type",
"RuleRenderer" );
889 rulesElem.setTagName(
"rules" );
890 rendererElem.appendChild( rulesElem );
893 rendererElem.appendChild( symbolsElem );
902 for ( QgsLegendSymbolList::iterator it = items.begin(); it != items.end(); ++it )
904 QPair<QString, QgsSymbolV2*> pair = *it;
906 lst << qMakePair( pair.first, pix );
943 QDomElement symbolsElem = element.firstChildElement(
"symbols" );
944 if ( symbolsElem.isNull() )
949 QDomElement rulesElem = element.firstChildElement(
"rules" );
968 QDomElement ruleElem = element.firstChildElement(
"Rule" );
969 while ( !ruleElem.isNull() )
976 root =
new Rule( 0 );
981 ruleElem = ruleElem.nextSiblingElement(
"Rule" );
1004 if ( cat.
value().type() == QVariant::Int )
1005 value = cat.
value().toString();
1006 else if ( cat.
value().type() == QVariant::Double )
1009 value = QString::number( cat.
value().toDouble(),
'f', 4 );
1012 QString filter = QString(
"%1 = %2" ).arg( attr ).arg( value );
1013 QString label = filter;
1025 QString filter = QString(
"%1 >= %2 AND %1 <= %3" ).arg( attr )
1026 .arg( QString::number( rng.
lowerValue(),
'f', 4 ) )
1027 .arg( QString::number( rng.
upperValue(),
'f', 4 ) );
1028 QString label = filter;
1039 foreach (
int scale, scales )
1043 if ( maxDenom != 0 && maxDenom <= scale )
1045 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, scale, QString(), QString(
"%1 - %2" ).arg( oldScale ).arg( scale ) ) );
1049 initialRule->
appendChild(
new Rule( symbol->
clone(), oldScale, maxDenom, QString(), QString(
"%1 - %2" ).arg( oldScale ).arg( maxDenom ) ) );
1054 QString msg(
"Rule-based renderer:\n" );
1076 if ( renderer->
type() ==
"RuleRenderer" )
1081 if ( renderer->
type() ==
"singleSymbol" )
1084 if ( !singleSymbolRenderer )
1092 if ( renderer->
type() ==
"categorizedSymbol" )
1095 if ( !categorizedRenderer )
1103 for (
int i = 0; i < categorizedRenderer->
categories().size(); ++i )
1105 category = categorizedRenderer->
categories().value( i );
1112 if ( QVariant( category.
value() ).convert( QVariant::Double ) )
1114 value = category.
value().toString();
1118 value =
"'" + category.
value().toString() +
"'";
1122 if ( value ==
"''" )
1124 expression =
"ELSE";
1128 expression = categorizedRenderer->
classAttribute() +
" = " + value;
1146 if ( renderer->
type() ==
"graduatedSymbol" )
1150 if ( !graduatedRenderer )
1157 for (
int i = 0; i < graduatedRenderer->
ranges().size();++i )
1159 range = graduatedRenderer->
ranges().value( i );
1164 expression = graduatedRenderer->
classAttribute() +
" >= " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1169 expression = graduatedRenderer->
classAttribute() +
" > " + QString::number( range.
lowerValue(),
'f' ) +
" AND " + \
1189 if ( renderer->
type() ==
"pointDisplacement" )
1192 if ( pointDisplacementRenderer )
1195 if ( renderer->
type() ==
"invertedPolygonRenderer" )
1198 if ( invertedPolygonRenderer )
1207 QString sizeExpression;
1208 switch ( symbol->
type() )
1214 if ( ! sizeScaleField.isNull() )
1216 sizeExpression = QString(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
1219 if ( ! rotationField.isNull() )
1226 if ( ! sizeScaleField.isNull() )
1233 sizeExpression = QString(
"%1*(%2)" ).arg( lsl->
width() ).arg( sizeScaleField );
1242 sizeExpression = QString(
"%1*(%2)" ).arg( msl->
size() ).arg( sizeScaleField );
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props)
QMap< QString, QgsSymbolV2 * > QgsSymbolV2Map
Class for parsing and evaluation of expressions (formerly called "search strings").
QString description() const
QgsSymbolV2List symbolsForFeature(QgsFeature &feat)
tell which symbols will be used to render the feature
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
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QStringList referencedColumns() const
Get list of columns referenced by the expression.
QgsSymbolV2 * symbol() const
const QgsCategoryList & categories() const
static QString quotedColumnRef(QString name)
return quoted column reference (in double quotes)
virtual double width() const
QList< QgsSymbolV2 * > QgsSymbolV2List
virtual QgsSymbolV2List symbols() override
for symbol levels
QSet< int > collectZLevels()
get all used z-levels from this rule and children
const QString expression() const
Alias for dump()
static QgsFeatureRendererV2 * create(QDomElement &element)
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
QSet< int > mSymbolNormZLevels
QSet< QString > usedAttributes() const
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
static void convertToDataDefinedSymbology(QgsSymbolV2 *symbol, QString sizeScaleField, QString rotationField)
helper function to convert the size scale and rotation fields present in some other renderers to data...
QString classAttribute() const
double rendererScale() const
virtual QgsSymbolV2 * clone() const =0
virtual QgsFeatureRendererV2 * clone() const override
static QgsFeatureRendererV2 * createFromSld(QDomElement &element, QGis::GeometryType geomType)
void setLabel(QString label)
bool isScaleOK(double scale) const
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()
RuleList rulesForFeature(QgsFeature &feat)
tell which rules will be used to render the feature
Container of fields for a vector layer.
void removeChild(Rule *rule)
delete child rule
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
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, QString rule="") override
return a list of item text / symbol
QMap< QString, QString > QgsStringMap
void removeChildAt(int i)
delete child rule
virtual void checkLegendSymbolItem(QString key, bool state=true) override
item in symbology was checked
QString rotationField() const override
return rotation field name (or empty string if not set or not supported by renderer) ...
void renderFeatureWithSymbol(QgsFeature &feature, QgsSymbolV2 *symbol, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker)
virtual QString rotationField() const
return rotation field name (or empty string if not set or not supported by renderer) ...
void setCheckState(bool state)
double upperValue() const
static bool createSymbolLayerV2ListFromSld(QDomElement &element, QGis::GeometryType geomType, QgsSymbolLayerV2List &layers)
void stopRender(QgsRenderContext &context)
virtual QgsSymbolV2List originalSymbolsForFeature(QgsFeature &feat) override
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
virtual QgsFeatureRendererV2 * clone() const =0
virtual QDomElement save(QDomDocument &doc) override
store renderer info to XML element
Rule(QgsSymbolV2 *symbol, int scaleMinDenom=0, int scaleMaxDenom=0, QString filterExp=QString(), QString label=QString(), QString description=QString(), bool elseRule=false)
Constructor takes ownership of the symbol.
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 ...
int scaleMinDenom() const
void takeChild(Rule *rule)
take child rule out, set parent as null
virtual void stopRender(QgsRenderContext &context) override
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted...
void startRender(QgsRenderContext &context, const QgsFields *fields=0)
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, QString function)
void appendChild(Rule *rule)
add child rule, take ownership, sets this as parent
static QDomElement saveSymbols(QgsSymbolV2Map &symbols, QString tagName, QDomDocument &doc)
static Rule * create(QDomElement &ruleElem, QgsSymbolV2Map &symbolMap)
QString rotationField() const override
return rotation field name (or empty string if not set or not supported by renderer) ...
QgsSymbolV2 * symbol() const
QDomElement save(QDomDocument &doc, QgsSymbolV2Map &symbolMap)
bool isFilterOK(QgsFeature &f) const
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) ...
QgsExpression * filter() const
virtual void toSld(QDomDocument &doc, QDomElement &element) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
virtual QgsLegendSymbologyList legendSymbologyItems(QSize iconSize) override
return a list of symbology items for the legend
QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, QString rule="")
QString ruleKey() const
Unique rule identifier (for identification of rule within renderer)
QList< RenderJob * > jobs
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
virtual bool willRenderFeature(QgsFeature &feat) override
return whether the renderer will render a feature or not.
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 ...
QString dump(int offset=0) const
Rule * takeChildAt(int i)
take child rule out, set parent as null
bool renderFeature(FeatureToRender &featToRender, QgsRenderContext &context, RenderQueue &renderQueue)
RuleList descendants() const
QList< QPair< QString, QPixmap > > QgsLegendSymbologyList
virtual bool legendSymbolItemChecked(QString key) override
items of symbology items in legend is checked
QgsFeatureRendererV2 * embeddedRenderer() const
QgsLegendSymbolListV2 legendSymbolItemsV2(int currentLevel=-1) const
int renderingPass() const
virtual QString layerType() const =0
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
QString rotationField() const override
return rotation field name (or empty string if not set or not supported by renderer) ...
int scaleMaxDenom() const
QString sizeScaleField() const
Contains information about the context of a rendering operation.
const QgsFeatureRendererV2 * embeddedRenderer() const
void stopRender(QgsRenderContext &context)
double lowerValue() const
QList< QgsSymbolLayerV2 * > QgsSymbolLayerV2List
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)
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
QSet< QString > usedAttributes()
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.
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
static QgsRuleBasedRendererV2 * convertFromRenderer(const QgsFeatureRendererV2 *renderer)
creates a QgsRuleBasedRendererV2 from an existing renderer.
QList< QgsLegendSymbolItemV2 > QgsLegendSymbolListV2
QList< RenderLevel > RenderQueue
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
virtual QgsSymbolV2 * symbolForFeature(QgsFeature &feature) override
return symbol for current feature. Should not be used individually: there could be more symbols for a...
static QPixmap symbolPreviewPixmap(QgsSymbolV2 *symbol, QSize size, QgsRenderContext *customContext=0)
bool willRenderFeature(QgsFeature &feat)
only tell whether a feature will be rendered without actually rendering it
QList< QPair< QString, QgsSymbolV2 * > > QgsLegendSymbolList
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...
void setFilterExpression(QString filterExp)
QgsSymbolV2 * symbol() const
QList< FeatureToRender > mCurrentFeatures
QgsSymbolV2List symbols()
Rule * findRuleByKey(QString key)
Try to find a rule given its unique key.
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...
virtual QgsSymbolV2List symbolsForFeature(QgsFeature &feat) override
return list of symbols used for rendering the feature.
virtual void setDataDefinedProperty(const QString &property, const QString &expressionString)