Skip to content

Commit aa594f5

Browse files
committedOct 19, 2017
Also export rule based labelling. Follow up to #8925
1 parent fe780af commit aa594f5

File tree

8 files changed

+1648
-274
lines changed

8 files changed

+1648
-274
lines changed
 

‎python/core/qgsrulebasedlabeling.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ Create the instance from a DOM element with saved configuration
298298
%End
299299
virtual bool requiresAdvancedEffects() const;
300300

301+
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const;
301302

302303
protected:
303304
};

‎python/core/qgsvectorlayerlabeling.sip

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@ Try to create instance of an implementation based on the XML data
9292
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings
9393
%End
9494

95+
protected:
96+
97+
virtual void writeTextSymbolizer( QDomNode &parent, QgsPalLayerSettings &settings, const QgsStringMap &props ) const;
98+
%Docstring
99+
Writes a TextSymbolizer element contents based on the provided labeling settings
100+
writeTextSymbolizer
101+
@param parent the node that will have the text symbolizer element added to it
102+
@param settings the settings getting translated to a TextSymbolizer
103+
@param props a open ended set of properties that can drive/inform the SLD encoding
104+
%End
105+
95106
private:
96107
QgsAbstractVectorLayerLabeling( const QgsAbstractVectorLayerLabeling &rhs );
97108
};

‎src/core/qgsrulebasedlabeling.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* *
1414
***************************************************************************/
1515
#include "qgsrulebasedlabeling.h"
16-
16+
#include "qgssymbollayerutils.h"
1717

1818
QgsRuleBasedLabelProvider::QgsRuleBasedLabelProvider( const QgsRuleBasedLabeling &rules, QgsVectorLayer *layer, bool withFeatureLoop )
1919
: QgsVectorLayerLabelProvider( layer, QString(), withFeatureLoop, nullptr )
@@ -475,3 +475,44 @@ void QgsRuleBasedLabeling::setSettings( QgsPalLayerSettings *settings, const QSt
475475
return rule->setSettings( settings );
476476
}
477477
}
478+
479+
void QgsRuleBasedLabeling::toSld( QDomNode &parent, const QgsStringMap &props ) const
480+
{
481+
if ( !mRootRule )
482+
{
483+
return;
484+
}
485+
486+
const QgsRuleBasedLabeling::RuleList rules = mRootRule->children();
487+
for ( Rule *rule : rules )
488+
{
489+
QgsPalLayerSettings *settings = rule->settings();
490+
491+
if ( settings->drawLabels )
492+
{
493+
QDomDocument doc = parent.ownerDocument();
494+
495+
QDomElement ruleElement = doc.createElement( QStringLiteral( "se:Rule" ) );
496+
parent.appendChild( ruleElement );
497+
498+
if ( !rule->filterExpression().isEmpty() )
499+
{
500+
QgsSymbolLayerUtils::createFunctionElement( doc, ruleElement, rule->filterExpression() );
501+
}
502+
503+
// scale dependencies, the actual behavior is that the PAL settings min/max and
504+
// the rule min/max get intersected
505+
QgsStringMap localProps = QgsStringMap( props );
506+
QgsSymbolLayerUtils::mergeScaleDependencies( rule->maximumScale(), rule->minimumScale(), localProps );
507+
if ( settings->scaleVisibility )
508+
{
509+
QgsSymbolLayerUtils::mergeScaleDependencies( settings->maximumScale, settings->minimumScale, localProps );
510+
}
511+
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElement, localProps );
512+
513+
QgsAbstractVectorLayerLabeling::writeTextSymbolizer( ruleElement, *settings, props );
514+
}
515+
516+
}
517+
518+
}

‎src/core/qgsrulebasedlabeling.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
372372
*/
373373
virtual void setSettings( QgsPalLayerSettings *settings SIP_TRANSFER, const QString &providerId = QString() ) override;
374374
bool requiresAdvancedEffects() const override;
375+
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const override;
375376

376377
protected:
377378
Rule *mRootRule = nullptr;

‎src/core/qgsvectorlayerlabeling.cpp

Lines changed: 280 additions & 271 deletions
Large diffs are not rendered by default.

‎src/core/qgsvectorlayerlabeling.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ class CORE_EXPORT QgsAbstractVectorLayerLabeling
102102
parent.appendChild( doc.createComment( QStringLiteral( "SE Export for %1 not implemented yet" ).arg( type() ) ) );
103103
}
104104

105+
protected:
106+
107+
/**
108+
* Writes a TextSymbolizer element contents based on the provided labeling settings
109+
* @brief writeTextSymbolizer
110+
* @param parent the node that will have the text symbolizer element added to it
111+
* @param settings the settings getting translated to a TextSymbolizer
112+
* @param props a open ended set of properties that can drive/inform the SLD encoding
113+
*/
114+
virtual void writeTextSymbolizer( QDomNode &parent, QgsPalLayerSettings &settings, const QgsStringMap &props ) const;
115+
105116
private:
106117
Q_DISABLE_COPY( QgsAbstractVectorLayerLabeling )
107118

‎tests/src/python/test_qgssymbollayer_createsld.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -915,8 +915,9 @@ def testLabelScaleDependencies(self):
915915
self.loadStyleWithCustomProperties(layer, "polygonLabel")
916916
settings = layer.labeling().settings()
917917
settings.scaleVisibility = True
918-
settings.minimumScale = 1000000
919-
settings.maximumScale = 10000000
918+
# Careful: min scale -> large scale denomin
919+
settings.minimumScale = 10000000
920+
settings.maximumScale = 1000000
920921
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
921922

922923
dom, root = self.layerToSld(layer)
@@ -1018,6 +1019,39 @@ def assertLabelBackground(self, backgroundType, expectedMarkName, sizeType, expe
10181019
else:
10191020
self.assertIsNone(self.assertVendorOption(ts, 'graphic-margin', True))
10201021

1022+
def testRuleBasedLabels(self):
1023+
layer = QgsVectorLayer("Point", "addfeat", "memory")
1024+
self.loadStyleWithCustomProperties(layer, "ruleLabel")
1025+
1026+
dom, root = self.layerToSld(layer)
1027+
# print("Rule based labeling: " + dom.toString())
1028+
1029+
# three rules, one with the point symbol, one with the first rule based label,
1030+
# one with the second rule based label
1031+
rule1 = self.getRule(root, 0)
1032+
self.assertElement(rule1, 'se:PointSymbolizer', 0)
1033+
1034+
rule2 = self.getRule(root, 1)
1035+
self.assertScaleDenominator(root, '100000', '10000000', 1)
1036+
tsRule2 = self.assertElement(rule2, 'se:TextSymbolizer', 0)
1037+
gt = rule2.elementsByTagName("Filter").item(0).firstChild()
1038+
self.assertEqual("ogc:PropertyIsGreaterThan", gt.nodeName())
1039+
gtProperty = gt.toElement().firstChild()
1040+
self.assertEqual("ogc:PropertyName", gtProperty.nodeName())
1041+
self.assertEqual("POP_MAX", gtProperty.toElement().text())
1042+
gtValue = gt.childNodes().item(1)
1043+
self.assertEqual("1000000", gtValue.toElement().text())
1044+
1045+
rule3 = self.getRule(root, 2)
1046+
tsRule3 = self.assertElement(rule3, 'se:TextSymbolizer', 0)
1047+
lt = rule3.elementsByTagName("Filter").item(0).firstChild()
1048+
self.assertEqual("ogc:PropertyIsLessThan", lt.nodeName())
1049+
ltProperty = lt.toElement().firstChild()
1050+
self.assertEqual("ogc:PropertyName", ltProperty.nodeName())
1051+
self.assertEqual("POP_MAX", ltProperty.toElement().text())
1052+
ltValue = gt.childNodes().item(1)
1053+
self.assertEqual("1000000", gtValue.toElement().text())
1054+
10211055
def updateLinePlacementProperties(self, layer, linePlacement, distance, repeat, maxAngleInternal=25, maxAngleExternal=-25):
10221056
settings = layer.labeling().settings()
10231057
settings.placement = linePlacement
@@ -1124,6 +1158,10 @@ def assertElement(self, container, elementName, index, allowMissing=False):
11241158
self.assertTrue(node.isElement(), 'Found node but it''s not an element')
11251159
return node.toElement()
11261160

1161+
def getRule(self, root, ruleIndex):
1162+
rule = self.assertElement(root, 'se:Rule', ruleIndex)
1163+
return rule
1164+
11271165
def getTextSymbolizer(self, root, ruleIndex, textSymbolizerIndex):
11281166
rule = self.assertElement(root, 'se:Rule', ruleIndex)
11291167
textSymbolizer = self.assertElement(rule, 'se:TextSymbolizer', textSymbolizerIndex)

‎tests/testdata/symbol_layer/ruleLabel.qml

Lines changed: 1262 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.