Skip to content

Commit a25b025

Browse files
committed
Export map level scale based dependencies in most vector symbology
1 parent d477d19 commit a25b025

26 files changed

+2909
-67
lines changed

doc/api_break.dox

+9
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,15 @@ in code which previously passed a null pointer to QgsVectorFileWriter.</li>
999999
<li>QgsWMSLegendNode has been renamed to QgsWmsLegendNode</li>
10001000
</ul>
10011001

1002+
\subsection qgis_api_break_3_0_QgsRenderer QgsRenderer
1003+
1004+
<ul>
1005+
<li>New virtual method <code>bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap props = QgsStringMap() )</code> accepts an
1006+
optional property map passing down layer level properties to the SLD encoders. If scale based visibility is enabled, it will contain the
1007+
<code>scaleMinDenom</code> and <code>scaleMaxDenom</code> properties.
1008+
</ul>
1009+
1010+
10021011

10031012
\section qgis_api_break_2_4 QGIS 2.4
10041013

python/core/qgsvectorlayer.sip

+1-2
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ class QgsVectorLayer : QgsMapLayer
709709
*/
710710
bool writeStyle( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const;
711711

712-
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const;
712+
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap& props ) const;
713713
bool readSld( const QDomNode& node, QString& errorMessage );
714714

715715
/**
@@ -1660,4 +1660,3 @@ class QgsVectorLayer : QgsMapLayer
16601660

16611661

16621662
};
1663-

python/core/symbology-ng/qgssymbollayerutils.sip

+31
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ class QgsSymbolLayerUtils
224224
static void createGeometryElement( QDomDocument &doc, QDomElement &element, const QString& geomFunc );
225225
static bool geometryFromSldElement( QDomElement &element, QString &geomFunc );
226226

227+
static bool createExpressionElement( QDomDocument &doc, QDomElement &element, const QString& function );
227228
static bool createFunctionElement( QDomDocument &doc, QDomElement &element, const QString& function );
228229
static bool functionFromSldElement( QDomElement &element, QString &function );
229230

@@ -444,4 +445,34 @@ class QgsSymbolLayerUtils
444445
*/
445446
static QList<double> prettyBreaks( double minimum, double maximum, int classes );
446447

448+
/** Rescales the given size based on the uomScale found in the props, if any is found, otherwise
449+
* returns the value un-modified
450+
* @note added in 3.0
451+
*/
452+
static double rescaleUom( double size, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props );
453+
454+
/** Rescales the given point based on the uomScale found in the props, if any is found, otherwise
455+
* returns a copy of the original point
456+
* @note added in 3.0
457+
*/
458+
static QPointF rescaleUom( const QPointF& point, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props ) /PyName=rescalePointUom/;
459+
460+
/** Rescales the given array based on the uomScale found in the props, if any is found, otherwise
461+
* returns a copy of the original point
462+
* @note added in 3.0
463+
*/
464+
static QVector<qreal> rescaleUom( const QVector<qreal>& array, QgsUnitTypes::RenderUnit unit, const QgsStringMap& props ) /PyName=rescaleArrayUom/;
465+
466+
/**
467+
* Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into the SE Rule element
468+
* @note added in 3.0
469+
*/
470+
static void applyScaleDependency( QDomDocument& doc, QDomElement& ruleElem, QgsStringMap& props );
471+
472+
/**
473+
* Merges the local scale limits, if any, with the ones already in the map, if any
474+
* @note added in 3.0
475+
*/
476+
static void mergeScaleDependencies( int mScaleMinDenom, int mScaleMaxDenom, QgsStringMap& props );
477+
447478
};

src/core/qgsmaplayer.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,13 @@ void QgsMapLayer::exportSldStyle( QDomDocument &doc, QString &errorMsg ) const
14481448
return;
14491449
}
14501450

1451-
if ( !vlayer->writeSld( namedLayerNode, myDocument, errorMsg ) )
1451+
QgsStringMap props;
1452+
if ( hasScaleBasedVisibility() )
1453+
{
1454+
props[ "scaleMinDenom" ] = QString::number( mMinScale );
1455+
props[ "scaleMaxDenom" ] = QString::number( mMaxScale );
1456+
}
1457+
if ( !vlayer->writeSld( namedLayerNode, myDocument, errorMsg, props ) )
14521458
{
14531459
errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
14541460
return;

src/core/qgsvectorlayer.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -1991,8 +1991,12 @@ bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
19911991
return true;
19921992
}
19931993

1994-
19951994
bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1995+
{
1996+
return writeSld( node, doc, errorMessage, QgsStringMap() );
1997+
}
1998+
1999+
bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap props ) const
19962000
{
19972001
Q_UNUSED( errorMessage );
19982002

@@ -2001,9 +2005,15 @@ bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& error
20012005
nameNode.appendChild( doc.createTextNode( name() ) );
20022006
node.appendChild( nameNode );
20032007

2008+
QgsStringMap localProps = QgsStringMap( props );
2009+
if ( hasScaleBasedVisibility() )
2010+
{
2011+
QgsSymbolLayerUtils::mergeScaleDependencies( minimumScale(), maximumScale(), localProps );
2012+
}
2013+
20042014
if ( hasGeometryType() )
20052015
{
2006-
node.appendChild( mRenderer->writeSld( doc, name() ) );
2016+
node.appendChild( mRenderer->writeSld( doc, name(), localProps ) );
20072017
}
20082018
return true;
20092019
}

src/core/qgsvectorlayer.h

+11
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,17 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
803803
bool writeStyle( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const override;
804804

805805
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const;
806+
807+
/**
808+
* Writes the symbology of the layer into the document provided in SLD 1.1 format
809+
* @param node the node that will have the style element added to it.
810+
* @param doc the document that will have the QDomNode added.
811+
* @param errorMessage reference to string that will be updated with any error messages
812+
* @param props a open ended set of properties that can drive/inform the SLD encoding
813+
* @return true in case of success
814+
*/
815+
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap props = QgsStringMap() ) const;
816+
806817
bool readSld( const QDomNode& node, QString& errorMessage ) override;
807818

808819
/**

src/core/symbology-ng/qgscategorizedsymbolrenderer.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ void QgsRendererCategory::toSld( QDomDocument &doc, QDomElement &element, QgsStr
141141
mValue.toString().replace( '\'', "''" ) );
142142
QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc );
143143

144+
// add the mix/max scale denoms if we got any from the callers
145+
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
146+
144147
mSymbol->toSld( doc, ruleElem, props );
145148
}
146149

@@ -517,9 +520,8 @@ QgsCategorizedSymbolRenderer* QgsCategorizedSymbolRenderer::clone() const
517520
return r;
518521
}
519522

520-
void QgsCategorizedSymbolRenderer::toSld( QDomDocument &doc, QDomElement &element ) const
523+
void QgsCategorizedSymbolRenderer::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
521524
{
522-
QgsStringMap props;
523525
props[ "attribute" ] = mAttrName;
524526
if ( mRotation.data() )
525527
props[ "angle" ] = mRotation->expression();

src/core/symbology-ng/qgscategorizedsymbolrenderer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class CORE_EXPORT QgsCategorizedSymbolRenderer : public QgsFeatureRenderer
9999

100100
virtual QgsCategorizedSymbolRenderer* clone() const override;
101101

102-
virtual void toSld( QDomDocument& doc, QDomElement &element ) const override;
102+
virtual void toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props = QgsStringMap() ) const override;
103103

104104
//! returns bitwise OR-ed capabilities of the renderer
105105
virtual Capabilities capabilities() override { return SymbolLevels | RotationField | Filter; }

src/core/symbology-ng/qgsgraduatedsymbolrenderer.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -560,9 +560,8 @@ QgsGraduatedSymbolRenderer* QgsGraduatedSymbolRenderer::clone() const
560560
return r;
561561
}
562562

563-
void QgsGraduatedSymbolRenderer::toSld( QDomDocument& doc, QDomElement &element ) const
563+
void QgsGraduatedSymbolRenderer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
564564
{
565-
QgsStringMap props;
566565
props[ "attribute" ] = mAttrName;
567566
props[ "method" ] = graduatedMethodStr( mGraduatedMethod );
568567
if ( mRotation.data() )

src/core/symbology-ng/qgsgraduatedsymbolrenderer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class CORE_EXPORT QgsGraduatedSymbolRenderer : public QgsFeatureRenderer
152152

153153
virtual QgsGraduatedSymbolRenderer* clone() const override;
154154

155-
virtual void toSld( QDomDocument& doc, QDomElement &element ) const override;
155+
virtual void toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props = QgsStringMap() ) const override;
156156

157157
//! returns bitwise OR-ed capabilities of the renderer
158158
virtual Capabilities capabilities() override { return SymbolLevels | RotationField | Filter; }

src/core/symbology-ng/qgslinesymbollayer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,7 @@ void QgsMarkerLineSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, c
14501450
if ( !gap.isEmpty() )
14511451
{
14521452
QDomElement gapElem = doc.createElement( "se:Gap" );
1453-
QgsSymbolLayerUtils::createFunctionElement( doc, gapElem, gap );
1453+
QgsSymbolLayerUtils::createExpressionElement( doc, gapElem, gap );
14541454
graphicStrokeElem.appendChild( gapElem );
14551455
}
14561456

src/core/symbology-ng/qgspointdisplacementrenderer.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ QgsPointDisplacementRenderer* QgsPointDisplacementRenderer::clone() const
8787
return r;
8888
}
8989

90-
void QgsPointDisplacementRenderer::toSld( QDomDocument& doc, QDomElement &element ) const
90+
void QgsPointDisplacementRenderer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
9191
{
92-
mRenderer->toSld( doc, element );
92+
mRenderer->toSld( doc, element, props );
9393
}
9494

9595

src/core/symbology-ng/qgspointdisplacementrenderer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsFeatureRenderer
4646

4747
QgsPointDisplacementRenderer* clone() const override;
4848

49-
virtual void toSld( QDomDocument& doc, QDomElement &element ) const override;
49+
virtual void toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props = QgsStringMap() ) const override;
5050

5151
/** Reimplemented from QgsFeatureRenderer*/
5252
bool renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool selected = false, bool drawVertexMarker = false ) override;

src/core/symbology-ng/qgsrenderer.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,11 @@ QgsFeatureRenderer* QgsFeatureRenderer::loadSld( const QDomNode &node, QgsWkbTyp
340340

341341
QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QgsVectorLayer &layer ) const
342342
{
343-
return writeSld( doc, layer.name() );
343+
QgsStringMap props;
344+
return writeSld( doc, layer.name(), props );
344345
}
345346

346-
QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QString& styleName ) const
347+
QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QString& styleName, QgsStringMap props ) const
347348
{
348349
QDomElement userStyleElem = doc.createElement( "UserStyle" );
349350

@@ -352,7 +353,7 @@ QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QString& styl
352353
userStyleElem.appendChild( nameElem );
353354

354355
QDomElement featureTypeStyleElem = doc.createElement( "se:FeatureTypeStyle" );
355-
toSld( doc, featureTypeStyleElem );
356+
toSld( doc, featureTypeStyleElem, props );
356357
userStyleElem.appendChild( featureTypeStyleElem );
357358

358359
return userStyleElem;

src/core/symbology-ng/qgsrenderer.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ class CORE_EXPORT QgsFeatureRenderer
263263
Q_DECL_DEPRECATED virtual QDomElement writeSld( QDomDocument& doc, const QgsVectorLayer &layer ) const;
264264
//! create the SLD UserStyle element following the SLD v1.1 specs with the given name
265265
//! @note added in 2.8
266-
virtual QDomElement writeSld( QDomDocument& doc, const QString& styleName ) const;
266+
virtual QDomElement writeSld( QDomDocument& doc, const QString& styleName, QgsStringMap props = QgsStringMap() ) const;
267267

268268
/** Create a new renderer according to the information contained in
269269
* the UserStyle element of a SLD style document
@@ -278,8 +278,11 @@ class CORE_EXPORT QgsFeatureRenderer
278278
static QgsFeatureRenderer* loadSld( const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage );
279279

280280
//! used from subclasses to create SLD Rule elements following SLD v1.1 specs
281-
virtual void toSld( QDomDocument& doc, QDomElement &element ) const
282-
{ element.appendChild( doc.createComment( QString( "FeatureRendererV2 %1 not implemented yet" ).arg( type() ) ) ); }
281+
virtual void toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props = QgsStringMap() ) const
282+
{
283+
element.appendChild( doc.createComment( QString( "FeatureRendererV2 %1 not implemented yet" ).arg( type() ) ) );
284+
( void ) props; // warning avoidance
285+
}
283286

284287
//! return a list of symbology items for the legend
285288
virtual QgsLegendSymbologyList legendSymbologyItems( QSize iconSize );

src/core/symbology-ng/qgsrulebasedrenderer.cpp

+4-34
Original file line numberDiff line numberDiff line change
@@ -348,25 +348,7 @@ void QgsRuleBasedRenderer::Rule::toSld( QDomDocument& doc, QDomElement &element,
348348
props[ "filter" ] += mFilterExp;
349349
}
350350

351-
if ( mScaleMinDenom != 0 )
352-
{
353-
bool ok;
354-
int parentScaleMinDenom = props.value( "scaleMinDenom", "0" ).toInt( &ok );
355-
if ( !ok || parentScaleMinDenom <= 0 )
356-
props[ "scaleMinDenom" ] = QString::number( mScaleMinDenom );
357-
else
358-
props[ "scaleMinDenom" ] = QString::number( qMax( parentScaleMinDenom, mScaleMinDenom ) );
359-
}
360-
361-
if ( mScaleMaxDenom != 0 )
362-
{
363-
bool ok;
364-
int parentScaleMaxDenom = props.value( "scaleMaxDenom", "0" ).toInt( &ok );
365-
if ( !ok || parentScaleMaxDenom <= 0 )
366-
props[ "scaleMaxDenom" ] = QString::number( mScaleMaxDenom );
367-
else
368-
props[ "scaleMaxDenom" ] = QString::number( qMin( parentScaleMaxDenom, mScaleMaxDenom ) );
369-
}
351+
QgsSymbolLayerUtils::mergeScaleDependencies( mScaleMinDenom, mScaleMaxDenom, props );
370352

371353
if ( mSymbol )
372354
{
@@ -402,19 +384,7 @@ void QgsRuleBasedRenderer::Rule::toSld( QDomDocument& doc, QDomElement &element,
402384
QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, props.value( "filter", "" ) );
403385
}
404386

405-
if ( !props.value( "scaleMinDenom", "" ).isEmpty() )
406-
{
407-
QDomElement scaleMinDenomElem = doc.createElement( "se:MinScaleDenominator" );
408-
scaleMinDenomElem.appendChild( doc.createTextNode( props.value( "scaleMinDenom", "" ) ) );
409-
ruleElem.appendChild( scaleMinDenomElem );
410-
}
411-
412-
if ( !props.value( "scaleMaxDenom", "" ).isEmpty() )
413-
{
414-
QDomElement scaleMaxDenomElem = doc.createElement( "se:MaxScaleDenominator" );
415-
scaleMaxDenomElem.appendChild( doc.createTextNode( props.value( "scaleMaxDenom", "" ) ) );
416-
ruleElem.appendChild( scaleMaxDenomElem );
417-
}
387+
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
418388

419389
mSymbol->toSld( doc, ruleElem, props );
420390
}
@@ -977,9 +947,9 @@ QgsRuleBasedRenderer* QgsRuleBasedRenderer::clone() const
977947
return r;
978948
}
979949

980-
void QgsRuleBasedRenderer::toSld( QDomDocument& doc, QDomElement &element ) const
950+
void QgsRuleBasedRenderer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
981951
{
982-
mRootRule->toSld( doc, element, QgsStringMap() );
952+
mRootRule->toSld( doc, element, props );
983953
}
984954

985955
// TODO: ideally this function should be removed in favor of legendSymbol(ogy)Items

src/core/symbology-ng/qgsrulebasedrenderer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ class CORE_EXPORT QgsRuleBasedRenderer : public QgsFeatureRenderer
441441

442442
virtual QgsRuleBasedRenderer* clone() const override;
443443

444-
virtual void toSld( QDomDocument& doc, QDomElement &element ) const override;
444+
virtual void toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props = QgsStringMap() ) const override;
445445

446446
static QgsFeatureRenderer* createFromSld( QDomElement& element, QgsWkbTypes::GeometryType geomType );
447447

src/core/symbology-ng/qgssinglesymbolrenderer.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,8 @@ QgsSingleSymbolRenderer* QgsSingleSymbolRenderer::clone() const
205205
return r;
206206
}
207207

208-
void QgsSingleSymbolRenderer::toSld( QDomDocument& doc, QDomElement &element ) const
208+
void QgsSingleSymbolRenderer::toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const
209209
{
210-
QgsStringMap props;
211210
if ( mRotation.data() )
212211
props[ "angle" ] = mRotation->expression();
213212
if ( mSizeScale.data() )
@@ -220,6 +219,8 @@ void QgsSingleSymbolRenderer::toSld( QDomDocument& doc, QDomElement &element ) c
220219
nameElem.appendChild( doc.createTextNode( "Single symbol" ) );
221220
ruleElem.appendChild( nameElem );
222221

222+
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
223+
223224
if ( mSymbol.data() ) mSymbol->toSld( doc, ruleElem, props );
224225
}
225226

src/core/symbology-ng/qgssinglesymbolrenderer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class CORE_EXPORT QgsSingleSymbolRenderer : public QgsFeatureRenderer
6161

6262
virtual QgsSingleSymbolRenderer* clone() const override;
6363

64-
virtual void toSld( QDomDocument& doc, QDomElement &element ) const override;
64+
virtual void toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props = QgsStringMap() ) const override;
6565
static QgsFeatureRenderer* createFromSld( QDomElement& element, QgsWkbTypes::GeometryType geomType );
6666

6767
//! returns bitwise OR-ed capabilities of the renderer

0 commit comments

Comments
 (0)