Skip to content

Commit 665df5f

Browse files
authored
Merge pull request #3436 from aaime/scaledep
Export map level scale based dependencies in most vector symbology
2 parents 4a52351 + a25b025 commit 665df5f

26 files changed

+2909
-67
lines changed

doc/api_break.dox

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

1031+
\subsection qgis_api_break_3_0_QgsRenderer QgsRenderer
1032+
1033+
<ul>
1034+
<li>New virtual method <code>bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap props = QgsStringMap() )</code> accepts an
1035+
optional property map passing down layer level properties to the SLD encoders. If scale based visibility is enabled, it will contain the
1036+
<code>scaleMinDenom</code> and <code>scaleMaxDenom</code> properties.
1037+
</ul>
1038+
1039+
10311040

10321041
\section qgis_api_break_2_4 QGIS 2.4
10331042

python/core/qgsvectorlayer.sip

+1-2
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ class QgsVectorLayer : QgsMapLayer
723723
*/
724724
bool writeStyle( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const;
725725

726-
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const;
726+
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap& props ) const;
727727
bool readSld( const QDomNode& node, QString& errorMessage );
728728

729729
/**
@@ -1710,4 +1710,3 @@ class QgsVectorLayer : QgsMapLayer
17101710

17111711

17121712
};
1713-

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
@@ -2042,8 +2042,12 @@ bool QgsVectorLayer::readSld( const QDomNode& node, QString& errorMessage )
20422042
return true;
20432043
}
20442044

2045-
20462045
bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
2046+
{
2047+
return writeSld( node, doc, errorMessage, QgsStringMap() );
2048+
}
2049+
2050+
bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap props ) const
20472051
{
20482052
Q_UNUSED( errorMessage );
20492053

@@ -2052,9 +2056,15 @@ bool QgsVectorLayer::writeSld( QDomNode& node, QDomDocument& doc, QString& error
20522056
nameNode.appendChild( doc.createTextNode( name() ) );
20532057
node.appendChild( nameNode );
20542058

2059+
QgsStringMap localProps = QgsStringMap( props );
2060+
if ( hasScaleBasedVisibility() )
2061+
{
2062+
QgsSymbolLayerUtils::mergeScaleDependencies( minimumScale(), maximumScale(), localProps );
2063+
}
2064+
20552065
if ( hasGeometryType() )
20562066
{
2057-
node.appendChild( mRenderer->writeSld( doc, name() ) );
2067+
node.appendChild( mRenderer->writeSld( doc, name(), localProps ) );
20582068
}
20592069
return true;
20602070
}

src/core/qgsvectorlayer.h

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

819819
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const;
820+
821+
/**
822+
* Writes the symbology of the layer into the document provided in SLD 1.1 format
823+
* @param node the node that will have the style element added to it.
824+
* @param doc the document that will have the QDomNode added.
825+
* @param errorMessage reference to string that will be updated with any error messages
826+
* @param props a open ended set of properties that can drive/inform the SLD encoding
827+
* @return true in case of success
828+
*/
829+
bool writeSld( QDomNode& node, QDomDocument& doc, QString& errorMessage, QgsStringMap props = QgsStringMap() ) const;
830+
820831
bool readSld( const QDomNode& node, QString& errorMessage ) override;
821832

822833
/**

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
@@ -328,10 +328,11 @@ QgsFeatureRenderer* QgsFeatureRenderer::loadSld( const QDomNode &node, QgsWkbTyp
328328

329329
QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QgsVectorLayer &layer ) const
330330
{
331-
return writeSld( doc, layer.name() );
331+
QgsStringMap props;
332+
return writeSld( doc, layer.name(), props );
332333
}
333334

334-
QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QString& styleName ) const
335+
QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QString& styleName, QgsStringMap props ) const
335336
{
336337
QDomElement userStyleElem = doc.createElement( "UserStyle" );
337338

@@ -340,7 +341,7 @@ QDomElement QgsFeatureRenderer::writeSld( QDomDocument& doc, const QString& styl
340341
userStyleElem.appendChild( nameElem );
341342

342343
QDomElement featureTypeStyleElem = doc.createElement( "se:FeatureTypeStyle" );
343-
toSld( doc, featureTypeStyleElem );
344+
toSld( doc, featureTypeStyleElem, props );
344345
userStyleElem.appendChild( featureTypeStyleElem );
345346

346347
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)