mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-09 00:08:52 -04:00
[sld] Don't try to write rules/categorizes without symbolizers
Only create rules/categorized categories/graduated ranges if the associated symbol could be converted to SLD, and is not an "empty" symbol. Otherwise we do not generate a rule, as SLD spec requires a Symbolizer element to be present.
This commit is contained in:
parent
52dd3047ac
commit
2abc9d92ca
@ -22,6 +22,7 @@ try:
|
|||||||
QgsSymbolLayerUtils.decodeBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeBrushStyle)
|
QgsSymbolLayerUtils.decodeBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeBrushStyle)
|
||||||
QgsSymbolLayerUtils.encodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.encodeSldBrushStyle)
|
QgsSymbolLayerUtils.encodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.encodeSldBrushStyle)
|
||||||
QgsSymbolLayerUtils.decodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeSldBrushStyle)
|
QgsSymbolLayerUtils.decodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeSldBrushStyle)
|
||||||
|
QgsSymbolLayerUtils.hasSldSymbolizer = staticmethod(QgsSymbolLayerUtils.hasSldSymbolizer)
|
||||||
QgsSymbolLayerUtils.decodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.decodeCoordinateReference)
|
QgsSymbolLayerUtils.decodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.decodeCoordinateReference)
|
||||||
QgsSymbolLayerUtils.encodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.encodeCoordinateReference)
|
QgsSymbolLayerUtils.encodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.encodeCoordinateReference)
|
||||||
QgsSymbolLayerUtils.decodeArrowHeadType = staticmethod(QgsSymbolLayerUtils.decodeArrowHeadType)
|
QgsSymbolLayerUtils.decodeArrowHeadType = staticmethod(QgsSymbolLayerUtils.decodeArrowHeadType)
|
||||||
|
@ -60,6 +60,13 @@ Contains utility functions for working with symbols and symbol layers.
|
|||||||
static QString encodeSldBrushStyle( Qt::BrushStyle style );
|
static QString encodeSldBrushStyle( Qt::BrushStyle style );
|
||||||
static Qt::BrushStyle decodeSldBrushStyle( const QString &str );
|
static Qt::BrushStyle decodeSldBrushStyle( const QString &str );
|
||||||
|
|
||||||
|
static bool hasSldSymbolizer( const QDomElement &element );
|
||||||
|
%Docstring
|
||||||
|
Returns ``True`` if a DOM ``element`` contains an SLD Symbolizer element.
|
||||||
|
|
||||||
|
.. versionadded:: 3.42
|
||||||
|
%End
|
||||||
|
|
||||||
static Qgis::SymbolCoordinateReference decodeCoordinateReference( const QString &string, bool *ok /Out/ = 0 );
|
static Qgis::SymbolCoordinateReference decodeCoordinateReference( const QString &string, bool *ok /Out/ = 0 );
|
||||||
%Docstring
|
%Docstring
|
||||||
Decodes a ``string`` representing a symbol coordinate reference mode.
|
Decodes a ``string`` representing a symbol coordinate reference mode.
|
||||||
|
@ -22,6 +22,7 @@ try:
|
|||||||
QgsSymbolLayerUtils.decodeBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeBrushStyle)
|
QgsSymbolLayerUtils.decodeBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeBrushStyle)
|
||||||
QgsSymbolLayerUtils.encodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.encodeSldBrushStyle)
|
QgsSymbolLayerUtils.encodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.encodeSldBrushStyle)
|
||||||
QgsSymbolLayerUtils.decodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeSldBrushStyle)
|
QgsSymbolLayerUtils.decodeSldBrushStyle = staticmethod(QgsSymbolLayerUtils.decodeSldBrushStyle)
|
||||||
|
QgsSymbolLayerUtils.hasSldSymbolizer = staticmethod(QgsSymbolLayerUtils.hasSldSymbolizer)
|
||||||
QgsSymbolLayerUtils.decodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.decodeCoordinateReference)
|
QgsSymbolLayerUtils.decodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.decodeCoordinateReference)
|
||||||
QgsSymbolLayerUtils.encodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.encodeCoordinateReference)
|
QgsSymbolLayerUtils.encodeCoordinateReference = staticmethod(QgsSymbolLayerUtils.encodeCoordinateReference)
|
||||||
QgsSymbolLayerUtils.decodeArrowHeadType = staticmethod(QgsSymbolLayerUtils.decodeArrowHeadType)
|
QgsSymbolLayerUtils.decodeArrowHeadType = staticmethod(QgsSymbolLayerUtils.decodeArrowHeadType)
|
||||||
|
@ -60,6 +60,13 @@ Contains utility functions for working with symbols and symbol layers.
|
|||||||
static QString encodeSldBrushStyle( Qt::BrushStyle style );
|
static QString encodeSldBrushStyle( Qt::BrushStyle style );
|
||||||
static Qt::BrushStyle decodeSldBrushStyle( const QString &str );
|
static Qt::BrushStyle decodeSldBrushStyle( const QString &str );
|
||||||
|
|
||||||
|
static bool hasSldSymbolizer( const QDomElement &element );
|
||||||
|
%Docstring
|
||||||
|
Returns ``True`` if a DOM ``element`` contains an SLD Symbolizer element.
|
||||||
|
|
||||||
|
.. versionadded:: 3.42
|
||||||
|
%End
|
||||||
|
|
||||||
static Qgis::SymbolCoordinateReference decodeCoordinateReference( const QString &string, bool *ok /Out/ = 0 );
|
static Qgis::SymbolCoordinateReference decodeCoordinateReference( const QString &string, bool *ok /Out/ = 0 );
|
||||||
%Docstring
|
%Docstring
|
||||||
Decodes a ``string`` representing a symbol coordinate reference mode.
|
Decodes a ``string`` representing a symbol coordinate reference mode.
|
||||||
|
@ -150,7 +150,6 @@ void QgsRendererCategory::toSld( QDomDocument &doc, QDomElement &element, QVaria
|
|||||||
}
|
}
|
||||||
|
|
||||||
QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
|
QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
|
||||||
element.appendChild( ruleElem );
|
|
||||||
|
|
||||||
QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
|
QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
|
||||||
nameElem.appendChild( doc.createTextNode( mLabel ) );
|
nameElem.appendChild( doc.createTextNode( mLabel ) );
|
||||||
@ -199,6 +198,14 @@ void QgsRendererCategory::toSld( QDomDocument &doc, QDomElement &element, QVaria
|
|||||||
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
|
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
|
||||||
|
|
||||||
mSymbol->toSld( doc, ruleElem, props );
|
mSymbol->toSld( doc, ruleElem, props );
|
||||||
|
if ( !QgsSymbolLayerUtils::hasSldSymbolizer( ruleElem ) )
|
||||||
|
{
|
||||||
|
// symbol could not be converted to SLD, or is an "empty" symbol. In this case we do not generate a rule, as
|
||||||
|
// SLD spec requires a Symbolizer element to be present
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.appendChild( ruleElem );
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
|
@ -138,7 +138,6 @@ void QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, QVariantM
|
|||||||
QString attrName = props[ QStringLiteral( "attribute" )].toString();
|
QString attrName = props[ QStringLiteral( "attribute" )].toString();
|
||||||
|
|
||||||
QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
|
QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
|
||||||
element.appendChild( ruleElem );
|
|
||||||
|
|
||||||
QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
|
QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
|
||||||
nameElem.appendChild( doc.createTextNode( mLabel ) );
|
nameElem.appendChild( doc.createTextNode( mLabel ) );
|
||||||
@ -160,6 +159,14 @@ void QgsRendererRange::toSld( QDomDocument &doc, QDomElement &element, QVariantM
|
|||||||
QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc );
|
QgsSymbolLayerUtils::createFunctionElement( doc, ruleElem, filterFunc );
|
||||||
|
|
||||||
mSymbol->toSld( doc, ruleElem, props );
|
mSymbol->toSld( doc, ruleElem, props );
|
||||||
|
if ( !QgsSymbolLayerUtils::hasSldSymbolizer( ruleElem ) )
|
||||||
|
{
|
||||||
|
// symbol could not be converted to SLD, or is an "empty" symbol. In this case we do not generate a rule, as
|
||||||
|
// SLD spec requires a Symbolizer element to be present
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.appendChild( ruleElem );
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////
|
//////////
|
||||||
|
@ -375,7 +375,6 @@ void QgsRuleBasedRenderer::Rule::toSld( QDomDocument &doc, QDomElement &element,
|
|||||||
if ( mSymbol )
|
if ( mSymbol )
|
||||||
{
|
{
|
||||||
QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
|
QDomElement ruleElem = doc.createElement( QStringLiteral( "se:Rule" ) );
|
||||||
element.appendChild( ruleElem );
|
|
||||||
|
|
||||||
//XXX: <se:Name> is the rule identifier, but our the Rule objects
|
//XXX: <se:Name> is the rule identifier, but our the Rule objects
|
||||||
// have no properties could be used as identifier. Use the label.
|
// have no properties could be used as identifier. Use the label.
|
||||||
@ -409,6 +408,13 @@ void QgsRuleBasedRenderer::Rule::toSld( QDomDocument &doc, QDomElement &element,
|
|||||||
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
|
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElem, props );
|
||||||
|
|
||||||
mSymbol->toSld( doc, ruleElem, props );
|
mSymbol->toSld( doc, ruleElem, props );
|
||||||
|
|
||||||
|
// Only create rules if symbol could be converted to SLD, and is not an "empty" symbol. Otherwise we do not generate a rule, as
|
||||||
|
// SLD spec requires a Symbolizer element to be present
|
||||||
|
if ( QgsSymbolLayerUtils::hasSldSymbolizer( ruleElem ) )
|
||||||
|
{
|
||||||
|
element.appendChild( ruleElem );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop into children rule list
|
// loop into children rule list
|
||||||
|
@ -391,6 +391,20 @@ Qt::BrushStyle QgsSymbolLayerUtils::decodeSldBrushStyle( const QString &str )
|
|||||||
return Qt::NoBrush;
|
return Qt::NoBrush;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QgsSymbolLayerUtils::hasSldSymbolizer( const QDomElement &element )
|
||||||
|
{
|
||||||
|
const QDomNodeList children = element.childNodes();
|
||||||
|
for ( int i = 0; i < children.size(); ++i )
|
||||||
|
{
|
||||||
|
const QDomElement childElement = children.at( i ).toElement();
|
||||||
|
if ( childElement.tagName() == QLatin1String( "se:LineSymbolizer" )
|
||||||
|
|| childElement.tagName() == QLatin1String( "se:PointSymbolizer" )
|
||||||
|
|| childElement.tagName() == QLatin1String( "se:PolygonSymbolizer" ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Qgis::SymbolCoordinateReference QgsSymbolLayerUtils::decodeCoordinateReference( const QString &string, bool *ok )
|
Qgis::SymbolCoordinateReference QgsSymbolLayerUtils::decodeCoordinateReference( const QString &string, bool *ok )
|
||||||
{
|
{
|
||||||
const QString compareString = string.trimmed();
|
const QString compareString = string.trimmed();
|
||||||
|
@ -94,6 +94,13 @@ class CORE_EXPORT QgsSymbolLayerUtils
|
|||||||
static QString encodeSldBrushStyle( Qt::BrushStyle style );
|
static QString encodeSldBrushStyle( Qt::BrushStyle style );
|
||||||
static Qt::BrushStyle decodeSldBrushStyle( const QString &str );
|
static Qt::BrushStyle decodeSldBrushStyle( const QString &str );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if a DOM \a element contains an SLD Symbolizer element.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.42
|
||||||
|
*/
|
||||||
|
static bool hasSldSymbolizer( const QDomElement &element );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes a \a string representing a symbol coordinate reference mode.
|
* Decodes a \a string representing a symbol coordinate reference mode.
|
||||||
*
|
*
|
||||||
|
@ -301,6 +301,7 @@ ADD_PYTHON_TEST(PyQgsRenderContext test_qgsrendercontext.py)
|
|||||||
ADD_PYTHON_TEST(PyQgsRenderedItemResults test_qgsrendereditemresults.py)
|
ADD_PYTHON_TEST(PyQgsRenderedItemResults test_qgsrendereditemresults.py)
|
||||||
ADD_PYTHON_TEST(PyQgsRenderer test_qgsrenderer.py)
|
ADD_PYTHON_TEST(PyQgsRenderer test_qgsrenderer.py)
|
||||||
ADD_PYTHON_TEST(PyQgsReport test_qgsreport.py)
|
ADD_PYTHON_TEST(PyQgsReport test_qgsreport.py)
|
||||||
|
ADD_PYTHON_TEST(PyQgsRuleBasedRenderer test_qgsrulebasedrenderer.py)
|
||||||
ADD_PYTHON_TEST(PyQgsScaleBarRendererRegistry test_qgsscalebarrendererregistry.py)
|
ADD_PYTHON_TEST(PyQgsScaleBarRendererRegistry test_qgsscalebarrendererregistry.py)
|
||||||
ADD_PYTHON_TEST(PyQgsScaleBarRenderers test_qgsscalebarrenderers.py)
|
ADD_PYTHON_TEST(PyQgsScaleBarRenderers test_qgsscalebarrenderers.py)
|
||||||
ADD_PYTHON_TEST(PyQgsScaleCalculator test_qgsscalecalculator.py)
|
ADD_PYTHON_TEST(PyQgsScaleCalculator test_qgsscalecalculator.py)
|
||||||
|
@ -935,6 +935,13 @@ class TestQgsCategorizedSymbolRenderer(QgisTestCase):
|
|||||||
symbol_f = createMarkerSymbol()
|
symbol_f = createMarkerSymbol()
|
||||||
renderer.addCategory(QgsRendererCategory(None, symbol_f, 'f', True, '4'))
|
renderer.addCategory(QgsRendererCategory(None, symbol_f, 'f', True, '4'))
|
||||||
|
|
||||||
|
# this category should NOT be included in the SLD, as it would otherwise result
|
||||||
|
# in an invalid se:rule with no symbolizer element
|
||||||
|
symbol_which_is_empty_in_sld = createFillSymbol()
|
||||||
|
symbol_which_is_empty_in_sld[0].setBrushStyle(Qt.NoBrush)
|
||||||
|
symbol_which_is_empty_in_sld[0].setStrokeStyle(Qt.NoPen)
|
||||||
|
renderer.addCategory(QgsRendererCategory(None, symbol_which_is_empty_in_sld, 'empty', True, '4'))
|
||||||
|
|
||||||
dom = QDomDocument()
|
dom = QDomDocument()
|
||||||
root = dom.createElement("FakeRoot")
|
root = dom.createElement("FakeRoot")
|
||||||
dom.appendChild(root)
|
dom.appendChild(root)
|
||||||
|
@ -24,6 +24,7 @@ from qgis.core import (
|
|||||||
QgsRendererRange,
|
QgsRendererRange,
|
||||||
QgsRendererRangeLabelFormat,
|
QgsRendererRangeLabelFormat,
|
||||||
QgsVectorLayer,
|
QgsVectorLayer,
|
||||||
|
QgsFillSymbol,
|
||||||
)
|
)
|
||||||
import unittest
|
import unittest
|
||||||
from qgis.testing import start_app, QgisTestCase
|
from qgis.testing import start_app, QgisTestCase
|
||||||
@ -44,6 +45,13 @@ def createMarkerSymbol():
|
|||||||
return symbol
|
return symbol
|
||||||
|
|
||||||
|
|
||||||
|
def createFillSymbol():
|
||||||
|
symbol = QgsFillSymbol.createSimple({
|
||||||
|
"color": "100,150,50"
|
||||||
|
})
|
||||||
|
return symbol
|
||||||
|
|
||||||
|
|
||||||
def createMemoryLayer(values):
|
def createMemoryLayer(values):
|
||||||
ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double",
|
ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double",
|
||||||
"test_data", "memory")
|
"test_data", "memory")
|
||||||
@ -563,6 +571,135 @@ class TestQgsGraduatedSymbolRenderer(QgisTestCase):
|
|||||||
self.assertTrue(ok)
|
self.assertTrue(ok)
|
||||||
self.assertEqual(exp, """(log("field_name") >= 15.5) AND (log("field_name") <= 16.5)""")
|
self.assertEqual(exp, """(log("field_name") >= 15.5) AND (log("field_name") <= 16.5)""")
|
||||||
|
|
||||||
|
def test_to_sld(self):
|
||||||
|
renderer = QgsGraduatedSymbolRenderer()
|
||||||
|
renderer.setClassAttribute('field_name')
|
||||||
|
|
||||||
|
symbol_a = createMarkerSymbol()
|
||||||
|
renderer.addClassRange(QgsRendererRange(1, 2, symbol_a, 'a', True, '0'))
|
||||||
|
symbol_b = createMarkerSymbol()
|
||||||
|
renderer.addClassRange(QgsRendererRange(5, 6, symbol_b, 'b', True, '1'))
|
||||||
|
symbol_c = createMarkerSymbol()
|
||||||
|
renderer.addClassRange(QgsRendererRange(15.5, 16.5, symbol_c, 'c', False, '2'))
|
||||||
|
|
||||||
|
# this category should NOT be included in the SLD, as it would otherwise result
|
||||||
|
# in an invalid se:rule with no symbolizer element
|
||||||
|
symbol_which_is_empty_in_sld = createFillSymbol()
|
||||||
|
symbol_which_is_empty_in_sld[0].setBrushStyle(Qt.NoBrush)
|
||||||
|
symbol_which_is_empty_in_sld[0].setStrokeStyle(Qt.NoPen)
|
||||||
|
renderer.addClassRange(
|
||||||
|
QgsRendererRange(25.5, 26.5, symbol_which_is_empty_in_sld, 'd', False, '2'))
|
||||||
|
|
||||||
|
dom = QDomDocument()
|
||||||
|
root = dom.createElement("FakeRoot")
|
||||||
|
dom.appendChild(root)
|
||||||
|
renderer.toSld(dom, root, {})
|
||||||
|
|
||||||
|
expected = """<FakeRoot>
|
||||||
|
<se:Rule>
|
||||||
|
<se:Name>a</se:Name>
|
||||||
|
<se:Description>
|
||||||
|
<se:Title>a</se:Title>
|
||||||
|
</se:Description>
|
||||||
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
<ogc:And>
|
||||||
|
<ogc:PropertyIsGreaterThanOrEqualTo>
|
||||||
|
<ogc:PropertyName>field_name</ogc:PropertyName>
|
||||||
|
<ogc:Literal>1</ogc:Literal>
|
||||||
|
</ogc:PropertyIsGreaterThanOrEqualTo>
|
||||||
|
<ogc:PropertyIsLessThanOrEqualTo>
|
||||||
|
<ogc:PropertyName>field_name</ogc:PropertyName>
|
||||||
|
<ogc:Literal>2</ogc:Literal>
|
||||||
|
</ogc:PropertyIsLessThanOrEqualTo>
|
||||||
|
</ogc:And>
|
||||||
|
</ogc:Filter>
|
||||||
|
<se:PointSymbolizer>
|
||||||
|
<se:Graphic>
|
||||||
|
<se:Mark>
|
||||||
|
<se:WellKnownName>square</se:WellKnownName>
|
||||||
|
<se:Fill>
|
||||||
|
<se:SvgParameter name="fill">#649632</se:SvgParameter>
|
||||||
|
</se:Fill>
|
||||||
|
<se:Stroke>
|
||||||
|
<se:SvgParameter name="stroke">#232323</se:SvgParameter>
|
||||||
|
<se:SvgParameter name="stroke-width">0.5</se:SvgParameter>
|
||||||
|
</se:Stroke>
|
||||||
|
</se:Mark>
|
||||||
|
<se:Size>11</se:Size>
|
||||||
|
</se:Graphic>
|
||||||
|
</se:PointSymbolizer>
|
||||||
|
</se:Rule>
|
||||||
|
<se:Rule>
|
||||||
|
<se:Name>b</se:Name>
|
||||||
|
<se:Description>
|
||||||
|
<se:Title>b</se:Title>
|
||||||
|
</se:Description>
|
||||||
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
<ogc:And>
|
||||||
|
<ogc:PropertyIsGreaterThan>
|
||||||
|
<ogc:PropertyName>field_name</ogc:PropertyName>
|
||||||
|
<ogc:Literal>5</ogc:Literal>
|
||||||
|
</ogc:PropertyIsGreaterThan>
|
||||||
|
<ogc:PropertyIsLessThanOrEqualTo>
|
||||||
|
<ogc:PropertyName>field_name</ogc:PropertyName>
|
||||||
|
<ogc:Literal>6</ogc:Literal>
|
||||||
|
</ogc:PropertyIsLessThanOrEqualTo>
|
||||||
|
</ogc:And>
|
||||||
|
</ogc:Filter>
|
||||||
|
<se:PointSymbolizer>
|
||||||
|
<se:Graphic>
|
||||||
|
<se:Mark>
|
||||||
|
<se:WellKnownName>square</se:WellKnownName>
|
||||||
|
<se:Fill>
|
||||||
|
<se:SvgParameter name="fill">#649632</se:SvgParameter>
|
||||||
|
</se:Fill>
|
||||||
|
<se:Stroke>
|
||||||
|
<se:SvgParameter name="stroke">#232323</se:SvgParameter>
|
||||||
|
<se:SvgParameter name="stroke-width">0.5</se:SvgParameter>
|
||||||
|
</se:Stroke>
|
||||||
|
</se:Mark>
|
||||||
|
<se:Size>11</se:Size>
|
||||||
|
</se:Graphic>
|
||||||
|
</se:PointSymbolizer>
|
||||||
|
</se:Rule>
|
||||||
|
<se:Rule>
|
||||||
|
<se:Name>c</se:Name>
|
||||||
|
<se:Description>
|
||||||
|
<se:Title>c</se:Title>
|
||||||
|
</se:Description>
|
||||||
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
<ogc:And>
|
||||||
|
<ogc:PropertyIsGreaterThan>
|
||||||
|
<ogc:PropertyName>field_name</ogc:PropertyName>
|
||||||
|
<ogc:Literal>15.5</ogc:Literal>
|
||||||
|
</ogc:PropertyIsGreaterThan>
|
||||||
|
<ogc:PropertyIsLessThanOrEqualTo>
|
||||||
|
<ogc:PropertyName>field_name</ogc:PropertyName>
|
||||||
|
<ogc:Literal>16.5</ogc:Literal>
|
||||||
|
</ogc:PropertyIsLessThanOrEqualTo>
|
||||||
|
</ogc:And>
|
||||||
|
</ogc:Filter>
|
||||||
|
<se:PointSymbolizer>
|
||||||
|
<se:Graphic>
|
||||||
|
<se:Mark>
|
||||||
|
<se:WellKnownName>square</se:WellKnownName>
|
||||||
|
<se:Fill>
|
||||||
|
<se:SvgParameter name="fill">#649632</se:SvgParameter>
|
||||||
|
</se:Fill>
|
||||||
|
<se:Stroke>
|
||||||
|
<se:SvgParameter name="stroke">#232323</se:SvgParameter>
|
||||||
|
<se:SvgParameter name="stroke-width">0.5</se:SvgParameter>
|
||||||
|
</se:Stroke>
|
||||||
|
</se:Mark>
|
||||||
|
<se:Size>11</se:Size>
|
||||||
|
</se:Graphic>
|
||||||
|
</se:PointSymbolizer>
|
||||||
|
</se:Rule>
|
||||||
|
</FakeRoot>
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(dom.toString(), expected)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
133
tests/src/python/test_qgsrulebasedrenderer.py
Normal file
133
tests/src/python/test_qgsrulebasedrenderer.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
"""QGIS Unit tests for QgsRuleBasedRenderer
|
||||||
|
|
||||||
|
.. note:: This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from qgis.PyQt.QtCore import Qt
|
||||||
|
from qgis.PyQt.QtXml import QDomDocument
|
||||||
|
from qgis.core import (
|
||||||
|
QgsMarkerSymbol,
|
||||||
|
QgsFillSymbol,
|
||||||
|
QgsRuleBasedRenderer
|
||||||
|
)
|
||||||
|
import unittest
|
||||||
|
from qgis.testing import start_app, QgisTestCase
|
||||||
|
|
||||||
|
start_app()
|
||||||
|
|
||||||
|
|
||||||
|
# ===========================================================
|
||||||
|
# Utility functions
|
||||||
|
|
||||||
|
|
||||||
|
def createMarkerSymbol():
|
||||||
|
symbol = QgsMarkerSymbol.createSimple({
|
||||||
|
"color": "100,150,50",
|
||||||
|
"name": "square",
|
||||||
|
"size": "3.0"
|
||||||
|
})
|
||||||
|
return symbol
|
||||||
|
|
||||||
|
|
||||||
|
def createFillSymbol():
|
||||||
|
symbol = QgsFillSymbol.createSimple({
|
||||||
|
"color": "100,150,50"
|
||||||
|
})
|
||||||
|
return symbol
|
||||||
|
|
||||||
|
|
||||||
|
class TestQgsRuleBasedSymbolRenderer(QgisTestCase):
|
||||||
|
|
||||||
|
def test_to_sld(self):
|
||||||
|
root_rule = QgsRuleBasedRenderer.Rule(None)
|
||||||
|
symbol_a = createMarkerSymbol()
|
||||||
|
root_rule.appendChild(
|
||||||
|
QgsRuleBasedRenderer.Rule(symbol_a, filterExp='"something"=1', label="label a", description="rule a")
|
||||||
|
)
|
||||||
|
symbol_b = createMarkerSymbol()
|
||||||
|
root_rule.appendChild(
|
||||||
|
QgsRuleBasedRenderer.Rule(symbol_b, filterExp='"something"=2', label="label b", description="rule b")
|
||||||
|
)
|
||||||
|
|
||||||
|
# this rule should NOT be included in the SLD, as it would otherwise result
|
||||||
|
# in an invalid se:rule with no symbolizer element
|
||||||
|
symbol_which_is_empty_in_sld = createFillSymbol()
|
||||||
|
symbol_which_is_empty_in_sld[0].setBrushStyle(Qt.NoBrush)
|
||||||
|
symbol_which_is_empty_in_sld[0].setStrokeStyle(Qt.NoPen)
|
||||||
|
root_rule.appendChild(
|
||||||
|
QgsRuleBasedRenderer.Rule(symbol_which_is_empty_in_sld, filterExp='"something"=3', label="label c", description="rule c"))
|
||||||
|
|
||||||
|
renderer = QgsRuleBasedRenderer(root_rule)
|
||||||
|
|
||||||
|
dom = QDomDocument()
|
||||||
|
root = dom.createElement("FakeRoot")
|
||||||
|
dom.appendChild(root)
|
||||||
|
renderer.toSld(dom, root, {})
|
||||||
|
|
||||||
|
expected = """<FakeRoot>
|
||||||
|
<se:Rule>
|
||||||
|
<se:Name>label a</se:Name>
|
||||||
|
<se:Description>
|
||||||
|
<se:Title>label a</se:Title>
|
||||||
|
<se:Abstract>rule a</se:Abstract>
|
||||||
|
</se:Description>
|
||||||
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
<ogc:PropertyIsEqualTo>
|
||||||
|
<ogc:PropertyName>something</ogc:PropertyName>
|
||||||
|
<ogc:Literal>1</ogc:Literal>
|
||||||
|
</ogc:PropertyIsEqualTo>
|
||||||
|
</ogc:Filter>
|
||||||
|
<se:PointSymbolizer>
|
||||||
|
<se:Graphic>
|
||||||
|
<se:Mark>
|
||||||
|
<se:WellKnownName>square</se:WellKnownName>
|
||||||
|
<se:Fill>
|
||||||
|
<se:SvgParameter name="fill">#649632</se:SvgParameter>
|
||||||
|
</se:Fill>
|
||||||
|
<se:Stroke>
|
||||||
|
<se:SvgParameter name="stroke">#232323</se:SvgParameter>
|
||||||
|
<se:SvgParameter name="stroke-width">0.5</se:SvgParameter>
|
||||||
|
</se:Stroke>
|
||||||
|
</se:Mark>
|
||||||
|
<se:Size>11</se:Size>
|
||||||
|
</se:Graphic>
|
||||||
|
</se:PointSymbolizer>
|
||||||
|
</se:Rule>
|
||||||
|
<se:Rule>
|
||||||
|
<se:Name>label b</se:Name>
|
||||||
|
<se:Description>
|
||||||
|
<se:Title>label b</se:Title>
|
||||||
|
<se:Abstract>rule b</se:Abstract>
|
||||||
|
</se:Description>
|
||||||
|
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
|
||||||
|
<ogc:PropertyIsEqualTo>
|
||||||
|
<ogc:PropertyName>something</ogc:PropertyName>
|
||||||
|
<ogc:Literal>2</ogc:Literal>
|
||||||
|
</ogc:PropertyIsEqualTo>
|
||||||
|
</ogc:Filter>
|
||||||
|
<se:PointSymbolizer>
|
||||||
|
<se:Graphic>
|
||||||
|
<se:Mark>
|
||||||
|
<se:WellKnownName>square</se:WellKnownName>
|
||||||
|
<se:Fill>
|
||||||
|
<se:SvgParameter name="fill">#649632</se:SvgParameter>
|
||||||
|
</se:Fill>
|
||||||
|
<se:Stroke>
|
||||||
|
<se:SvgParameter name="stroke">#232323</se:SvgParameter>
|
||||||
|
<se:SvgParameter name="stroke-width">0.5</se:SvgParameter>
|
||||||
|
</se:Stroke>
|
||||||
|
</se:Mark>
|
||||||
|
<se:Size>11</se:Size>
|
||||||
|
</se:Graphic>
|
||||||
|
</se:PointSymbolizer>
|
||||||
|
</se:Rule>
|
||||||
|
</FakeRoot>
|
||||||
|
"""
|
||||||
|
self.assertEqual(dom.toString(), expected)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user