Merge pull request #4838 from aaime/textsymbolizer_sc

SLD label exports. fixes #8925
This commit is contained in:
Nyall Dawson 2017-07-26 21:09:19 +10:00 committed by GitHub
commit cf042dc5dd
11 changed files with 2695 additions and 60 deletions

View File

@ -76,6 +76,11 @@ Try to create instance of an implementation based on the XML data
:rtype: QgsAbstractVectorLayerLabeling
%End
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const;
%Docstring
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings
%End
private:
QgsAbstractVectorLayerLabeling( const QgsAbstractVectorLayerLabeling &rhs );
};
@ -105,6 +110,7 @@ Constructs simple labeling configuration with given initial settings
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const;
virtual bool requiresAdvancedEffects() const;
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const;
static QgsVectorLayerSimpleLabeling *create( const QDomElement &element, const QgsReadWriteContext &context );
%Docstring

View File

@ -481,6 +481,14 @@ Create ogr feature style string for pen
:rtype: bool
%End
static void createAnchorPointElement( QDomDocument &doc, QDomElement &element, QPointF anchor );
%Docstring
Creates a SE 1.1 anchor point element as a child of the specified element
\param doc The document
\param element The parent element
\param anchor An anchor specification, with values between 0 and 1
%End
static void createOnlineResourceElement( QDomDocument &doc, QDomElement &element, const QString &path, const QString &format );
static bool onlineResourceFromSldElement( QDomElement &element, QString &path, QString &format );
%Docstring

View File

@ -2205,11 +2205,6 @@ bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &error
{
Q_UNUSED( errorMessage );
// store the Name element
QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
nameNode.appendChild( doc.createTextNode( name() ) );
node.appendChild( nameNode );
QgsStringMap localProps = QgsStringMap( props );
if ( hasScaleBasedVisibility() )
{
@ -2218,7 +2213,27 @@ bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &error
if ( isSpatial() )
{
node.appendChild( mRenderer->writeSld( doc, name(), localProps ) );
// store the Name element
QDomElement nameNode = doc.createElement( "se:Name" );
nameNode.appendChild( doc.createTextNode( name() ) );
node.appendChild( nameNode );
QDomElement userStyleElem = doc.createElement( "UserStyle" );
node.appendChild( userStyleElem );
QDomElement nameElem = doc.createElement( "se:Name" );
nameElem.appendChild( doc.createTextNode( name() ) );
userStyleElem.appendChild( nameElem );
QDomElement featureTypeStyleElem = doc.createElement( "se:FeatureTypeStyle" );
userStyleElem.appendChild( featureTypeStyleElem );
mRenderer->toSld( doc, featureTypeStyleElem, localProps );
if ( labelsEnabled() )
{
mLabeling->toSld( featureTypeStyleElem, localProps );
}
}
return true;
}

View File

@ -17,6 +17,10 @@
#include "qgspallabeling.h"
#include "qgsrulebasedlabeling.h"
#include "qgsvectorlayer.h"
#include "qgssymbollayerutils.h"
#include "qgssymbollayer.h"
#include "qgsmarkersymbollayer.h"
#include "qgis.h"
QgsAbstractVectorLayerLabeling *QgsAbstractVectorLayerLabeling::create( const QDomElement &element, const QgsReadWriteContext &context )
@ -88,3 +92,457 @@ QgsVectorLayerSimpleLabeling *QgsVectorLayerSimpleLabeling::create( const QDomEl
return new QgsVectorLayerSimpleLabeling( QgsPalLayerSettings() );
}
QPointF quadOffsetToSldAnchor( QgsPalLayerSettings::QuadrantPosition quadrantPosition )
{
double quadOffsetX = 0.5, quadOffsetY = 0.5;
// adjust quadrant offset of labels
switch ( quadrantPosition )
{
case QgsPalLayerSettings::QuadrantAboveLeft:
quadOffsetX = 1;
quadOffsetY = 0;
break;
case QgsPalLayerSettings::QuadrantAbove:
quadOffsetX = 0.5;
quadOffsetY = 0;
break;
case QgsPalLayerSettings::QuadrantAboveRight:
quadOffsetX = 0;
quadOffsetY = 0;
break;
case QgsPalLayerSettings::QuadrantLeft:
quadOffsetX = 1;
quadOffsetY = 0.5;
break;
case QgsPalLayerSettings::QuadrantRight:
quadOffsetX = 0;
quadOffsetY = 0.5;
break;
case QgsPalLayerSettings::QuadrantBelowLeft:
quadOffsetX = 1;
quadOffsetY = 1;
break;
case QgsPalLayerSettings::QuadrantBelow:
quadOffsetX = 0.5;
quadOffsetY = 1;
break;
case QgsPalLayerSettings::QuadrantBelowRight:
quadOffsetX = 0;
quadOffsetY = 1.0;
break;
case QgsPalLayerSettings::QuadrantOver:
break;
}
return QPointF( quadOffsetX, quadOffsetY );
}
/*
* This is not a generic function encoder, just enough to encode the label case control functions
*/
void appendSimpleFunction( QDomDocument &doc, QDomElement &parent, const QString &name, const QString &attribute )
{
QDomElement function = doc.createElement( QStringLiteral( "ogc:Function" ) );
function.setAttribute( QStringLiteral( "name" ), name );
parent.appendChild( function );
QDomElement property = doc.createElement( QStringLiteral( "ogc:PropertyName" ) );
property.appendChild( doc.createTextNode( attribute ) );
function.appendChild( property );
}
std::unique_ptr<QgsMarkerSymbolLayer> backgroundToMarkerLayer( const QgsTextBackgroundSettings &settings )
{
std::unique_ptr<QgsMarkerSymbolLayer> layer;
switch ( settings.type() )
{
case QgsTextBackgroundSettings::ShapeSVG:
{
QgsSvgMarkerSymbolLayer *svg = new QgsSvgMarkerSymbolLayer( settings.svgFile() );
svg->setStrokeWidth( settings.strokeWidth() );
svg->setStrokeWidthUnit( settings.strokeWidthUnit() );
layer.reset( svg );
break;
}
case QgsTextBackgroundSettings::ShapeCircle:
case QgsTextBackgroundSettings::ShapeEllipse:
case QgsTextBackgroundSettings::ShapeRectangle:
case QgsTextBackgroundSettings::ShapeSquare:
{
QgsSimpleMarkerSymbolLayer *marker = new QgsSimpleMarkerSymbolLayer();
// default value
QgsSimpleMarkerSymbolLayerBase::Shape shape = shape = QgsSimpleMarkerSymbolLayerBase::Diamond;
switch ( settings.type() )
{
case QgsTextBackgroundSettings::ShapeCircle:
case QgsTextBackgroundSettings::ShapeEllipse:
shape = QgsSimpleMarkerSymbolLayerBase::Circle;
break;
case QgsTextBackgroundSettings::ShapeRectangle:
case QgsTextBackgroundSettings::ShapeSquare:
shape = QgsSimpleMarkerSymbolLayerBase::Square;
break;
case QgsTextBackgroundSettings::ShapeSVG:
break;
}
marker->setShape( shape );
marker->setStrokeWidth( settings.strokeWidth() );
marker->setStrokeWidthUnit( settings.strokeWidthUnit() );
layer.reset( marker );
}
}
layer->setEnabled( true );
// a marker does not have a size x and y, just a size (and it should be at least one)
QSizeF size = settings.size();
layer->setSize( qMax( 1., qMax( size.width(), size.height() ) ) );
layer->setSizeUnit( settings.sizeUnit() );
// fill and stroke
QColor fillColor = settings.fillColor();
QColor strokeColor = settings.strokeColor();
if ( settings.opacity() < 1 )
{
int alpha = qRound( settings.opacity() * 255 );
fillColor.setAlpha( alpha );
strokeColor.setAlpha( alpha );
}
layer->setFillColor( fillColor );
layer->setStrokeColor( strokeColor );
// rotation
if ( settings.rotationType() == QgsTextBackgroundSettings::RotationFixed )
{
layer->setAngle( settings.rotation() );
}
// offset
layer->setOffset( settings.offset() );
layer->setOffsetUnit( settings.offsetUnit() );
return layer;
}
void QgsVectorLayerSimpleLabeling::toSld( QDomNode &parent, const QgsStringMap &props ) const
{
if ( mSettings->drawLabels )
{
QDomDocument doc = parent.ownerDocument();
QDomElement ruleElement = doc.createElement( QStringLiteral( "se:Rule" ) );
parent.appendChild( ruleElement );
// scale dependencies
if ( mSettings->scaleVisibility )
{
QgsStringMap scaleProps = QgsStringMap();
scaleProps.insert( "scaleMinDenom", qgsDoubleToString( mSettings->minimumScale ) );
scaleProps.insert( "scaleMaxDenom", qgsDoubleToString( mSettings->maximumScale ) );
QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElement, scaleProps );
}
// text symbolizer
QDomElement textSymbolizerElement = doc.createElement( QStringLiteral( "se:TextSymbolizer" ) );
ruleElement.appendChild( textSymbolizerElement );
// label
QgsTextFormat format = mSettings->format();
QFont font = format.font();
QDomElement labelElement = doc.createElement( QStringLiteral( "se:Label" ) );
textSymbolizerElement.appendChild( labelElement );
if ( mSettings->isExpression )
{
labelElement.appendChild( doc.createComment( QStringLiteral( "SE Export for %1 not implemented yet" ).arg( mSettings->getLabelExpression()->dump() ) ) );
labelElement.appendChild( doc.createTextNode( "Placeholder" ) );
}
else
{
if ( font.capitalization() == QFont::AllUppercase )
{
appendSimpleFunction( doc, labelElement, QStringLiteral( "strToUpperCase" ), mSettings->fieldName );
}
else if ( font.capitalization() == QFont::AllLowercase )
{
appendSimpleFunction( doc, labelElement, QStringLiteral( "strToLowerCase" ), mSettings->fieldName );
}
else if ( font.capitalization() == QFont::Capitalize )
{
appendSimpleFunction( doc, labelElement, QStringLiteral( "strCapitalize" ), mSettings->fieldName );
}
else
{
QDomElement propertyNameElement = doc.createElement( QStringLiteral( "ogc:PropertyName" ) );
propertyNameElement.appendChild( doc.createTextNode( mSettings->fieldName ) );
labelElement.appendChild( propertyNameElement );
}
}
// font
QDomElement fontElement = doc.createElement( QStringLiteral( "se:Font" ) );
textSymbolizerElement.appendChild( fontElement );
fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-family" ), font.family() ) );
double fontSize = QgsSymbolLayerUtils::rescaleUom( format.size(), format.sizeUnit(), props );
fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-size" ), QString::number( fontSize ) ) );
if ( format.font().italic() )
{
fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-style" ), QStringLiteral( "italic" ) ) );
}
if ( format.font().bold() )
{
fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-weight" ), QStringLiteral( "bold" ) ) );
}
// label placement
QDomElement labelPlacement = doc.createElement( QStringLiteral( "se:LabelPlacement" ) );
textSymbolizerElement.appendChild( labelPlacement );
double maxDisplacement = 0;
double repeatDistance = 0;
switch ( mSettings->placement )
{
case QgsPalLayerSettings::OverPoint:
{
QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
labelPlacement.appendChild( pointPlacement );
// anchor point
QPointF anchor = quadOffsetToSldAnchor( mSettings->quadOffset );
QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, anchor );
// displacement
if ( mSettings->xOffset > 0 || mSettings->yOffset > 0 )
{
QgsUnitTypes::RenderUnit offsetUnit = mSettings->offsetUnits;
double dx = QgsSymbolLayerUtils::rescaleUom( mSettings->xOffset, offsetUnit, props );
double dy = QgsSymbolLayerUtils::rescaleUom( mSettings->yOffset, offsetUnit, props );
QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( dx, dy ) );
}
// rotation
if ( mSettings->angleOffset != 0 )
{
QDomElement rotation = doc.createElement( "se:Rotation" );
pointPlacement.appendChild( rotation );
rotation.appendChild( doc.createTextNode( QString::number( mSettings->angleOffset ) ) );
}
}
break;
case QgsPalLayerSettings::AroundPoint:
case QgsPalLayerSettings::OrderedPositionsAroundPoint:
{
QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
labelPlacement.appendChild( pointPlacement );
// SLD cannot do either, but let's do a best effort setting the distance using
// anchor point and displacement
QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, QPointF( 0, 0.5 ) );
QgsUnitTypes::RenderUnit distUnit = mSettings->distUnits;
double radius = QgsSymbolLayerUtils::rescaleUom( mSettings->dist, distUnit, props );
double offset = sqrt( radius * radius / 2 ); // make it start top/right
maxDisplacement = radius + 1; // lock the distance
QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( offset, offset ) );
}
break;
case QgsPalLayerSettings::Horizontal:
case QgsPalLayerSettings::Free:
{
// still a point placement (for "free" it's a fallback, there is no SLD equivalent)
QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
labelPlacement.appendChild( pointPlacement );
QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, QPointF( 0.5, 0.5 ) );
QgsUnitTypes::RenderUnit distUnit = mSettings->distUnits;
double dist = QgsSymbolLayerUtils::rescaleUom( mSettings->dist, distUnit, props );
QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( 0, dist ) );
break;
}
case QgsPalLayerSettings::Line:
case QgsPalLayerSettings::Curved:
case QgsPalLayerSettings::PerimeterCurved:
{
QDomElement linePlacement = doc.createElement( "se:LinePlacement" );
labelPlacement.appendChild( linePlacement );
// perpendicular distance if required
if ( mSettings->dist > 0 )
{
QgsUnitTypes::RenderUnit distUnit = mSettings->distUnits;
double dist = QgsSymbolLayerUtils::rescaleUom( mSettings->dist, distUnit, props );
QDomElement perpendicular = doc.createElement( "se:PerpendicularOffset" );
linePlacement.appendChild( perpendicular );
perpendicular.appendChild( doc.createTextNode( qgsDoubleToString( dist, 2 ) ) );
}
// repeat distance if required
if ( mSettings->repeatDistance > 0 )
{
QDomElement repeat = doc.createElement( "se:Repeat" );
linePlacement.appendChild( repeat );
repeat.appendChild( doc.createTextNode( QStringLiteral( "true" ) ) );
QDomElement gap = doc.createElement( "se:Gap" );
linePlacement.appendChild( gap );
repeatDistance = QgsSymbolLayerUtils::rescaleUom( mSettings->repeatDistance, mSettings->repeatDistanceUnit, props );
gap.appendChild( doc.createTextNode( qgsDoubleToString( repeatDistance, 2 ) ) );
}
// always generalized
QDomElement generalize = doc.createElement( "se:GeneralizeLine" );
linePlacement.appendChild( generalize );
generalize.appendChild( doc.createTextNode( QStringLiteral( "true" ) ) );
}
break;
}
// halo
QgsTextBufferSettings buffer = format.buffer();
if ( buffer.enabled() )
{
QDomElement haloElement = doc.createElement( QStringLiteral( "se:Halo" ) );
textSymbolizerElement.appendChild( haloElement );
QDomElement radiusElement = doc.createElement( QStringLiteral( "se:Radius" ) );
haloElement.appendChild( radiusElement );
// the SLD uses a radius, which is actually half of the link thickness the buffer size specifies
double radius = QgsSymbolLayerUtils::rescaleUom( buffer.size(), buffer.sizeUnit(), props ) / 2;
radiusElement.appendChild( doc.createTextNode( qgsDoubleToString( radius ) ) );
QDomElement fillElement = doc.createElement( QStringLiteral( "se:Fill" ) );
haloElement.appendChild( fillElement );
fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill" ), buffer.color().name() ) );
if ( buffer.opacity() != 1 )
{
fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill-opacity" ), QString::number( buffer.opacity() ) ) );
}
}
// fill
QDomElement fillElement = doc.createElement( QStringLiteral( "se:Fill" ) );
textSymbolizerElement.appendChild( fillElement );
fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill" ), format.color().name() ) );
if ( format.opacity() != 1 )
{
fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill-opacity" ), QString::number( format.opacity() ) ) );
}
// background graphic (not supported by SE 1.1, but supported by the GeoTools ecosystem as an extension)
QgsTextBackgroundSettings background = format.background();
if ( background.enabled() )
{
std::unique_ptr<QgsMarkerSymbolLayer> layer = backgroundToMarkerLayer( background );
layer->writeSldMarker( doc, textSymbolizerElement, props );
}
// priority and zIndex, the default values are 0 and 5 in qgis (and between 0 and 10),
// in the GeoTools ecosystem there is a single priority value set at 1000 by default
if ( mSettings->priority != 5 || mSettings->zIndex > 0 )
{
QDomElement priorityElement = doc.createElement( QStringLiteral( "se:Priority" ) );
textSymbolizerElement.appendChild( priorityElement );
int priority = 500 + 1000 * mSettings->zIndex + ( mSettings->priority - 5 ) * 100;
if ( mSettings->priority == 0 && mSettings->zIndex > 0 )
{
// small adjustment to make sure labels in z index n+1 are all above level n despite the priority value
priority += 1;
}
priorityElement.appendChild( doc.createTextNode( QString::number( priority ) ) );
}
// vendor options for text appearance
if ( font.underline() )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "underlineText" ), QStringLiteral( "true" ) );
textSymbolizerElement.appendChild( vo );
}
if ( font.strikeOut() )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "strikethroughText" ), QStringLiteral( "true" ) );
textSymbolizerElement.appendChild( vo );
}
// vendor options for text positioning
if ( maxDisplacement > 0 )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "maxDisplacement" ), qgsDoubleToString( maxDisplacement, 2 ) );
textSymbolizerElement.appendChild( vo );
}
if ( mSettings->placement == QgsPalLayerSettings::Curved || mSettings->placement == QgsPalLayerSettings::PerimeterCurved )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "followLine" ), QStringLiteral( "true" ) );
textSymbolizerElement.appendChild( vo );
if ( mSettings->maxCurvedCharAngleIn > 0 || mSettings->maxCurvedCharAngleOut > 0 )
{
// SLD has no notion for this, the GeoTools ecosystem can only do a single angle
double angle = qMin( qAbs( mSettings->maxCurvedCharAngleIn ), qAbs( mSettings->maxCurvedCharAngleOut ) );
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "maxAngleDelta" ), qgsDoubleToString( angle ) );
textSymbolizerElement.appendChild( vo );
}
}
if ( repeatDistance > 0 )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "repeat" ), qgsDoubleToString( repeatDistance, 2 ) );
textSymbolizerElement.appendChild( vo );
}
// miscellaneous options
if ( mSettings->displayAll )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "conflictResolution" ), QStringLiteral( "false" ) );
textSymbolizerElement.appendChild( vo );
}
if ( mSettings->upsidedownLabels == QgsPalLayerSettings::ShowAll )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "forceLeftToRight" ), QStringLiteral( "false" ) );
textSymbolizerElement.appendChild( vo );
}
if ( mSettings->mergeLines )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "group" ), QStringLiteral( "yes" ) );
textSymbolizerElement.appendChild( vo );
if ( mSettings->labelPerPart )
{
QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "labelAllGroup" ), QStringLiteral( "true" ) );
textSymbolizerElement.appendChild( vo );
}
}
// background symbol resize handling
if ( background.enabled() )
{
// enable resizing if needed
switch ( background.sizeType() )
{
case QgsTextBackgroundSettings::SizeBuffer:
{
QString resizeType;
if ( background.type() == QgsTextBackgroundSettings::ShapeRectangle || background.type() == QgsTextBackgroundSettings::ShapeEllipse )
{
resizeType = QStringLiteral( "stretch" );
}
else
{
resizeType = QStringLiteral( "proportional" );
}
QDomElement voResize = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "graphic-resize" ), resizeType );
textSymbolizerElement.appendChild( voResize );
// now hadle margin
QSizeF size = background.size();
if ( size.width() > 0 || size.height() > 0 )
{
double x = QgsSymbolLayerUtils::rescaleUom( size.width(), background.sizeUnit(), props );
double y = QgsSymbolLayerUtils::rescaleUom( size.height(), background.sizeUnit(), props );
// in case of ellipse qgis pads the size generously to make sure the text is inside the ellipse
// the following seems to do the trick and keep visual output similar
if ( background.type() == QgsTextBackgroundSettings::ShapeEllipse )
{
x += fontSize / 2;
y += fontSize;
}
QString resizeSpec = QString( "%1 %2" ).arg( qgsDoubleToString( x, 2 ) ).arg( qgsDoubleToString( y, 2 ) );
QDomElement voMargin = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "graphic-margin" ), resizeSpec );
textSymbolizerElement.appendChild( voMargin );
}
break;
}
case QgsTextBackgroundSettings::SizeFixed:
case QgsTextBackgroundSettings::SizePercent:
// nothing to do here
break;
}
}
}
}

View File

@ -19,9 +19,9 @@
#include <QString>
#include <QStringList>
#include <QDomNode>
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgis.h"
class QDomDocument;
class QDomElement;
@ -76,6 +76,17 @@ class CORE_EXPORT QgsAbstractVectorLayerLabeling
//! Try to create instance of an implementation based on the XML data
static QgsAbstractVectorLayerLabeling *create( const QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
/**
* Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings
*/
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const
{
Q_UNUSED( parent )
Q_UNUSED( props )
QDomDocument doc = parent.ownerDocument();
parent.appendChild( doc.createComment( QStringLiteral( "SE Export for %1 not implemented yet" ).arg( type() ) ) );
}
private:
Q_DISABLE_COPY( QgsAbstractVectorLayerLabeling )
@ -105,6 +116,7 @@ class CORE_EXPORT QgsVectorLayerSimpleLabeling : public QgsAbstractVectorLayerLa
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const override;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const override;
bool requiresAdvancedEffects() const override;
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const override;
//! Create the instance from a DOM element with saved configuration
static QgsVectorLayerSimpleLabeling *create( const QDomElement &element, const QgsReadWriteContext &context );

View File

@ -2313,15 +2313,32 @@ void QgsSymbolLayerUtils::createDisplacementElement( QDomDocument &doc, QDomElem
element.appendChild( displacementElem );
QDomElement dispXElem = doc.createElement( QStringLiteral( "se:DisplacementX" ) );
dispXElem.appendChild( doc.createTextNode( qgsDoubleToString( offset.x() ) ) );
dispXElem.appendChild( doc.createTextNode( qgsDoubleToString( offset.x(), 2 ) ) );
QDomElement dispYElem = doc.createElement( QStringLiteral( "se:DisplacementY" ) );
dispYElem.appendChild( doc.createTextNode( qgsDoubleToString( offset.y() ) ) );
dispYElem.appendChild( doc.createTextNode( qgsDoubleToString( offset.y(), 2 ) ) );
displacementElem.appendChild( dispXElem );
displacementElem.appendChild( dispYElem );
}
void QgsSymbolLayerUtils::createAnchorPointElement( QDomDocument &doc, QDomElement &element, QPointF anchor )
{
// anchor is not tested for null, (0,0) is _not_ the default value (0.5, 0) is.
QDomElement anchorElem = doc.createElement( QStringLiteral( "se:AnchorPoint" ) );
element.appendChild( anchorElem );
QDomElement anchorXElem = doc.createElement( QStringLiteral( "se:AnchorPointX" ) );
anchorXElem.appendChild( doc.createTextNode( qgsDoubleToString( anchor.x() ) ) );
QDomElement anchorYElem = doc.createElement( QStringLiteral( "se:AnchorPointY" ) );
anchorYElem.appendChild( doc.createTextNode( qgsDoubleToString( anchor.y() ) ) );
anchorElem.appendChild( anchorXElem );
anchorElem.appendChild( anchorYElem );
}
bool QgsSymbolLayerUtils::displacementFromSldElement( QDomElement &element, QPointF &offset )
{
offset = QPointF( 0, 0 );
@ -2656,7 +2673,7 @@ QgsStringMap QgsSymbolLayerUtils::getSvgParameterList( QDomElement &element )
QDomElement QgsSymbolLayerUtils::createVendorOptionElement( QDomDocument &doc, const QString &name, const QString &value )
{
QDomElement nodeElem = doc.createElement( QStringLiteral( "VendorOption" ) );
QDomElement nodeElem = doc.createElement( QStringLiteral( "se:VendorOption" ) );
nodeElem.setAttribute( QStringLiteral( "name" ), name );
nodeElem.appendChild( doc.createTextNode( value ) );
return nodeElem;
@ -4028,8 +4045,26 @@ double QgsSymbolLayerUtils::rescaleUom( double size, QgsUnitTypes::RenderUnit un
scale = 1 / 0.28;
roundToUnit = true;
break;
// we don't have a good case for map units, as pixel values won't change based on zoom
default:
case QgsUnitTypes::RenderInches:
scale = 1 / 0.28 * 25.4;
roundToUnit = true;
break;
case QgsUnitTypes::RenderPoints:
scale = 90. /* dots per inch according to OGC SLD */ / 72. /* points per inch */;
roundToUnit = true;
break;
case QgsUnitTypes::RenderPixels:
// pixel is pixel
scale = 1;
break;
case QgsUnitTypes::RenderMapUnits:
case QgsUnitTypes::RenderMetersInMapUnits:
// already handed via uom
scale = 1;
break;
case QgsUnitTypes::RenderPercentage:
case QgsUnitTypes::RenderUnknownUnit:
// these do not make sense and should not really reach here
scale = 1;
}
}

View File

@ -332,6 +332,14 @@ class CORE_EXPORT QgsSymbolLayerUtils
static void createDisplacementElement( QDomDocument &doc, QDomElement &element, QPointF offset );
static bool displacementFromSldElement( QDomElement &element, QPointF &offset );
/**
* \brief Creates a SE 1.1 anchor point element as a child of the specified element
* \param doc The document
* \param element The parent element
* \param anchor An anchor specification, with values between 0 and 1
*/
static void createAnchorPointElement( QDomDocument &doc, QDomElement &element, QPointF anchor );
static void createOnlineResourceElement( QDomDocument &doc, QDomElement &element, const QString &path, const QString &format );
static bool onlineResourceFromSldElement( QDomElement &element, QString &path, QString &format );

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
test_qgssymbollayer_createsld.py
@ -25,15 +23,16 @@ __revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.PyQt.QtCore import Qt, QDir, QFile, QIODevice, QPointF
from qgis.PyQt.QtCore import Qt, QDir, QFile, QIODevice, QPointF, QSizeF
from qgis.PyQt.QtXml import QDomDocument
from qgis.PyQt.QtGui import QColor
from qgis.PyQt.QtGui import QColor, QFont
from qgis.core import (
QgsSimpleMarkerSymbolLayer, QgsSimpleMarkerSymbolLayerBase, QgsUnitTypes, QgsSvgMarkerSymbolLayer,
QgsFontMarkerSymbolLayer, QgsEllipseSymbolLayer, QgsSimpleLineSymbolLayer,
QgsMarkerLineSymbolLayer, QgsMarkerSymbol, QgsSimpleFillSymbolLayer, QgsSVGFillSymbolLayer,
QgsLinePatternFillSymbolLayer, QgsPointPatternFillSymbolLayer, QgsVectorLayer)
QgsLinePatternFillSymbolLayer, QgsPointPatternFillSymbolLayer, QgsVectorLayer, QgsVectorLayerSimpleLabeling,
QgsTextBufferSettings, QgsPalLayerSettings, QgsTextBackgroundSettings)
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath
@ -57,32 +56,6 @@ class TestQgsSymbolLayerCreateSld(unittest.TestCase):
self.assertStaticRotation(root, '50')
def assertStaticRotation(self, root, expectedValue, index=0):
# Check the rotation element is a literal, not a
rotation = root.elementsByTagName('se:Rotation').item(index)
literal = rotation.firstChild()
self.assertEqual("ogc:Literal", literal.nodeName())
self.assertEqual(expectedValue, literal.firstChild().nodeValue())
def assertStaticDisplacement(self, root, expectedDispX, expectedDispY):
displacement = root.elementsByTagName('se:Displacement').item(0)
self.assertIsNotNone(displacement)
dx = displacement.firstChild()
self.assertIsNotNone(dx)
self.assertEqual("se:DisplacementX", dx.nodeName())
self.assertSldNumber(expectedDispX, dx.firstChild().nodeValue())
dy = displacement.lastChild()
self.assertIsNotNone(dy)
self.assertEqual("se:DisplacementY", dy.nodeName())
self.assertSldNumber(expectedDispY, dy.firstChild().nodeValue())
def assertSldNumber(self, expected, stringValue):
value = float(stringValue)
self.assertFloatEquals(expected, value, 0.01)
def assertFloatEquals(self, expected, actual, tol):
self.assertLess(abs(expected - actual), tol)
def testSimpleMarkerUnitDefault(self):
symbol = QgsSimpleMarkerSymbolLayer(
QgsSimpleMarkerSymbolLayerBase.Star, color=QColor(255, 0, 0), strokeColor=QColor(0, 255, 0), size=10)
@ -98,14 +71,6 @@ class TestQgsSymbolLayerCreateSld(unittest.TestCase):
self.assertStrokeWidth(root, 2, 11)
self.assertStaticDisplacement(root, 18, 36)
def assertStrokeWidth(self, root, svgParameterIdx, expectedWidth):
strokeWidth = root.elementsByTagName(
'se:SvgParameter').item(svgParameterIdx)
svgParameterName = strokeWidth.attributes().namedItem('name')
self.assertEqual("stroke-width", svgParameterName.nodeValue())
self.assertSldNumber(
expectedWidth, strokeWidth.firstChild().nodeValue())
def testSimpleMarkerUnitPixels(self):
symbol = QgsSimpleMarkerSymbolLayer(
QgsSimpleMarkerSymbolLayerBase.Star, color=QColor(255, 0, 0), strokeColor=QColor(0, 255, 0), size=10)
@ -530,21 +495,666 @@ class TestQgsSymbolLayerCreateSld(unittest.TestCase):
gt = filter.firstChild()
expectedGtName = "ogc:PropertyIsGreaterThanOrEqualTo" if includeMin else "ogc:PropertyIsGreaterThan"
self.assertEquals(expectedGtName, gt.nodeName())
self.assertEqual(expectedGtName, gt.nodeName())
gtProperty = gt.firstChild()
self.assertEquals("ogc:PropertyName", gtProperty.nodeName())
self.assertEquals(attributeName, gtProperty.toElement().text())
self.assertEqual("ogc:PropertyName", gtProperty.nodeName())
self.assertEqual(attributeName, gtProperty.toElement().text())
gtValue = gt.childNodes().item(1)
self.assertEquals(min, gtValue.toElement().text())
self.assertEqual(min, gtValue.toElement().text())
lt = filter.childNodes().item(1)
expectedLtName = "ogc:PropertyIsLessThanOrEqualTo" if includeMax else "ogc:PropertyIsLessThan"
self.assertEquals(expectedLtName, lt.nodeName())
self.assertEqual(expectedLtName, lt.nodeName())
ltProperty = lt.firstChild()
self.assertEquals("ogc:PropertyName", ltProperty.nodeName())
self.assertEquals(attributeName, ltProperty.toElement().text())
self.assertEqual("ogc:PropertyName", ltProperty.nodeName())
self.assertEqual(attributeName, ltProperty.toElement().text())
ltValue = lt.childNodes().item(1)
self.assertEquals(max, ltValue.toElement().text())
self.assertEqual(max, ltValue.toElement().text())
def testSimpleLabeling(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
# Pick a local default font
fontFamily = QFont().family()
settings = layer.labeling().settings()
format = settings.format()
font = format.font()
font.setFamily(fontFamily)
font.setBold(False)
font.setItalic(False)
format.setFont(font)
settings.setFormat(format)
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Simple label text symbolizer" + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
self.assertPropertyName(ts, 'se:Label', 'NAME')
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual(fontFamily, self.assertSvgParameter(font, 'font-family').text())
self.assertEqual('11', self.assertSvgParameter(font, 'font-size').text())
fill = self.assertElement(ts, 'se:Fill', 0)
self.assertEqual('#000000', self.assertSvgParameter(fill, "fill").text())
self.assertIsNone(self.assertSvgParameter(fill, "fill-opacity", True))
def testLabelingUomMillimeter(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
self.updateLayerLabelingUnit(layer, QgsUnitTypes.RenderMillimeters)
dom, root = self.layerToSld(layer)
#print("Label sized in mm " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual('32', self.assertSvgParameter(font, 'font-size').text())
def testLabelingUomPixels(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
self.updateLayerLabelingUnit(layer, QgsUnitTypes.RenderPixels)
dom, root = self.layerToSld(layer)
# print("Label sized in pixels " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual('9', self.assertSvgParameter(font, 'font-size').text())
def testLabelingUomInches(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
self.updateLayerLabelingUnit(layer, QgsUnitTypes.RenderInches)
dom, root = self.layerToSld(layer)
# print("Label sized in inches " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual('816', self.assertSvgParameter(font, 'font-size').text())
def testTextStyle(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
# testing regular
self.updateLayerLabelingFontStyle(layer, False, False)
dom, root = self.layerToSld(layer)
# print("Simple label italic text" + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertIsNone(self.assertSvgParameter(font, 'font-weight', True))
self.assertIsNone(self.assertSvgParameter(font, 'font-style', True))
# testing bold
self.updateLayerLabelingFontStyle(layer, True, False)
dom, root = self.layerToSld(layer)
# print("Simple label bold text" + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual('bold', self.assertSvgParameter(font, 'font-weight').text())
self.assertIsNone(self.assertSvgParameter(font, 'font-style', True))
# testing italic
self.updateLayerLabelingFontStyle(layer, False, True)
dom, root = self.layerToSld(layer)
# print("Simple label italic text" + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual('italic', self.assertSvgParameter(font, 'font-style').text())
self.assertIsNone(self.assertSvgParameter(font, 'font-weight', True))
# testing bold italic
self.updateLayerLabelingFontStyle(layer, True, True)
dom, root = self.layerToSld(layer)
# print("Simple label bold and italic text" + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual('italic', self.assertSvgParameter(font, 'font-style').text())
self.assertEqual('bold', self.assertSvgParameter(font, 'font-weight').text())
# testing underline and strikethrough vendor options
self.updateLayerLabelingFontStyle(layer, False, False, True, True)
dom, root = self.layerToSld(layer)
# print("Simple label underline and strikethrough text" + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
font = self.assertElement(ts, 'se:Font', 0)
self.assertEqual('true', self.assertVendorOption(ts, 'underlineText').text())
self.assertEqual('true', self.assertVendorOption(ts, 'strikethroughText').text())
def testTextMixedCase(self):
self.assertCapitalizationFunction(QFont.MixedCase, None)
def testTextUppercase(self):
self.assertCapitalizationFunction(QFont.AllUppercase, "strToUpperCase")
def testTextLowercase(self):
self.assertCapitalizationFunction(QFont.AllLowercase, "strToLowerCase")
def testTextCapitalcase(self):
self.assertCapitalizationFunction(QFont.Capitalize, "strCapitalize")
def assertCapitalizationFunction(self, capitalization, expectedFunction):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
settings = layer.labeling().settings()
format = settings.format()
font = format.font()
font.setCapitalization(capitalization)
format.setFont(font)
settings.setFormat(format)
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Simple text with capitalization " + str(QFont.AllUppercase) + ": " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
label = self.assertElement(ts, "se:Label", 0)
if expectedFunction is None:
property = self.assertElement(label, "ogc:PropertyName", 0)
self.assertEqual("NAME", property.text())
else:
function = self.assertElement(label, "ogc:Function", 0)
self.assertEqual(expectedFunction, function.attribute("name"))
property = self.assertElement(function, "ogc:PropertyName", 0)
self.assertEqual("NAME", property.text())
def testLabelingTransparency(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
settings = layer.labeling().settings()
format = settings.format()
format.setOpacity(0.5)
settings.setFormat(format)
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Label with transparency " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
fill = self.assertElement(ts, 'se:Fill', 0)
self.assertEqual('#000000', self.assertSvgParameter(fill, "fill").text())
self.assertEqual('0.5', self.assertSvgParameter(fill, "fill-opacity").text())
def testLabelingBuffer(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
buffer = QgsTextBufferSettings()
buffer.setEnabled(True)
buffer.setSize(10)
buffer.setSizeUnit(QgsUnitTypes.RenderPixels)
buffer.setColor(QColor("Black"))
self.setLabelBufferSettings(layer, buffer)
dom, root = self.layerToSld(layer)
# print("Label with buffer 10 px " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
halo = self.assertElement(ts, 'se:Halo', 0)
# not full width, just radius here
self.assertEqual('5', self.assertElement(ts, 'se:Radius', 0).text())
haloFill = self.assertElement(halo, 'se:Fill', 0)
self.assertEqual('#000000', self.assertSvgParameter(haloFill, "fill").text())
def testLabelingBufferPointTranslucent(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
buffer = QgsTextBufferSettings()
buffer.setEnabled(True)
buffer.setSize(10)
buffer.setSizeUnit(QgsUnitTypes.RenderPoints)
buffer.setColor(QColor("Red"))
buffer.setOpacity(0.5)
self.setLabelBufferSettings(layer, buffer)
dom, root = self.layerToSld(layer)
# print("Label with buffer 10 points, red 50% transparent " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
halo = self.assertElement(ts, 'se:Halo', 0)
# not full width, just radius here
self.assertEqual('6.5', self.assertElement(ts, 'se:Radius', 0).text())
haloFill = self.assertElement(halo, 'se:Fill', 0)
self.assertEqual('#ff0000', self.assertSvgParameter(haloFill, "fill").text())
self.assertEqual('0.5', self.assertSvgParameter(haloFill, "fill-opacity").text())
def testLabelingLowPriority(self):
self.assertLabelingPriority(0, 0, '0')
def testLabelingDefaultPriority(self):
self.assertLabelingPriority(0, 5, None)
def testLabelingHighPriority(self):
self.assertLabelingPriority(0, 10, '1000')
def testLabelingZIndexLowPriority(self):
self.assertLabelingPriority(1, 0, '1001')
def testLabelingZIndexDefaultPriority(self):
self.assertLabelingPriority(1, 5, "1500")
def testLabelingZIndexHighPriority(self):
self.assertLabelingPriority(1, 10, '2000')
def assertLabelingPriority(self, zIndex, priority, expectedSldPriority):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
settings = layer.labeling().settings()
settings.zIndex = zIndex
settings.priority = priority
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Label with zIndex at " + str(zIndex) + " and priority at " + str(priority) + ": " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
priorityElement = self.assertElement(ts, "se:Priority", 0, True)
if expectedSldPriority is None:
self.assertIsNone(priorityElement)
else:
self.assertEqual(expectedSldPriority, priorityElement.text())
def testLabelingPlacementOverPointOffsetRotation(self):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
settings = layer.labeling().settings()
settings.placement = QgsPalLayerSettings.OverPoint
settings.xOffset = 5
settings.yOffset = 10
settings.offsetUnits = QgsUnitTypes.RenderMillimeters
settings.quadOffset = QgsPalLayerSettings.QuadrantOver
settings.angleOffset = 30
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Label with 'over point' placement " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
pointPlacement = self.assertPointPlacement(ts)
self.assertStaticDisplacement(pointPlacement, 18, 36)
self.assertStaticAnchorPoint(pointPlacement, 0.5, 0.5)
def testPointPlacementAboveLeft(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantAboveLeft, "AboveLeft", 1, 0)
def testPointPlacementAbove(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantAbove, "Above", 0.5, 0)
def testPointPlacementAboveRight(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantAboveRight, "AboveRight", 0, 0)
def testPointPlacementLeft(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantLeft, "Left", 1, 0.5)
def testPointPlacementRight(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantRight, "Right", 0, 0.5)
def testPointPlacementBelowLeft(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantBelowLeft, "BelowLeft", 1, 1)
def testPointPlacementBelow(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantBelow, "Below", 0.5, 1)
def testPointPlacementAboveRight(self):
self.assertLabelQuadrant(QgsPalLayerSettings.QuadrantBelowRight, "BelowRight", 0, 1)
def testPointPlacementCartoraphic(self):
self.assertPointPlacementDistance(QgsPalLayerSettings.OrderedPositionsAroundPoint)
def testPointPlacementCartoraphic(self):
self.assertPointPlacementDistance(QgsPalLayerSettings.AroundPoint)
def testLineParallelPlacement(self):
layer = QgsVectorLayer("LineString", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "lineLabel")
dom, root = self.layerToSld(layer)
# print("Label with parallel line placement " + dom.toString())
linePlacement = self.assertLinePlacement(root)
generalize = self.assertElement(linePlacement, 'se:GeneralizeLine', 0)
self.assertEqual("true", generalize.text())
def testLineParallelPlacementOffsetRepeat(self):
layer = QgsVectorLayer("LineString", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "lineLabel")
self.updateLinePlacementProperties(layer, QgsPalLayerSettings.Line, 2, 50)
dom, root = self.layerToSld(layer)
# print("Label with parallel line placement, perp. offset and repeat " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
linePlacement = self.assertLinePlacement(ts)
generalize = self.assertElement(linePlacement, 'se:GeneralizeLine', 0)
self.assertEqual("true", generalize.text())
offset = self.assertElement(linePlacement, 'se:PerpendicularOffset', 0)
self.assertEqual("7", offset.text())
repeat = self.assertElement(linePlacement, 'se:Repeat', 0)
self.assertEqual("true", repeat.text())
gap = self.assertElement(linePlacement, 'se:Gap', 0)
self.assertEqual("179", gap.text())
self.assertEqual("179", self.assertVendorOption(ts, "repeat").text())
def testLineCurvePlacementOffsetRepeat(self):
layer = QgsVectorLayer("LineString", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "lineLabel")
self.updateLinePlacementProperties(layer, QgsPalLayerSettings.Curved, 2, 50, 30, 40)
dom, root = self.layerToSld(layer)
# print("Label with curved line placement " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
linePlacement = self.assertLinePlacement(ts)
generalize = self.assertElement(linePlacement, 'se:GeneralizeLine', 0)
self.assertEqual("true", generalize.text())
offset = self.assertElement(linePlacement, 'se:PerpendicularOffset', 0)
self.assertEqual("7", offset.text())
repeat = self.assertElement(linePlacement, 'se:Repeat', 0)
self.assertEqual("true", repeat.text())
gap = self.assertElement(linePlacement, 'se:Gap', 0)
self.assertEqual("179", gap.text())
self.assertEqual("179", self.assertVendorOption(ts, "repeat").text())
self.assertEqual("true", self.assertVendorOption(ts, "followLine").text())
self.assertEqual("30", self.assertVendorOption(ts, "maxAngleDelta").text())
def testLineCurveMergeLines(self):
layer = QgsVectorLayer("LineString", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "lineLabel")
settings = layer.labeling().settings()
settings.placement = QgsPalLayerSettings.Curved
settings.mergeLines = True
settings.labelPerPart = True
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Label with curved line and line grouping " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
self.assertEqual("yes", self.assertVendorOption(ts, "group").text())
self.assertEqual("true", self.assertVendorOption(ts, "labelAllGroup").text())
def testLabelingPolygonFree(self):
layer = QgsVectorLayer("Polygon", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "polygonLabel")
settings = layer.labeling().settings()
settings.placement = QgsPalLayerSettings.Free
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Polygon label with 'Free' placement " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
pointPlacement = self.assertPointPlacement(ts)
self.assertIsNone(self.assertElement(ts, "se:Displacement", 0, True))
self.assertStaticAnchorPoint(pointPlacement, 0.5, 0.5)
def testLabelingPolygonPerimeterCurved(self):
layer = QgsVectorLayer("Polygon", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "polygonLabel")
self.updateLinePlacementProperties(layer, QgsPalLayerSettings.PerimeterCurved, 2, 50, 30, -40)
dom, root = self.layerToSld(layer)
# print("Polygon Label with curved perimeter line placement " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
linePlacement = self.assertLinePlacement(ts)
generalize = self.assertElement(linePlacement, 'se:GeneralizeLine', 0)
self.assertEqual("true", generalize.text())
offset = self.assertElement(linePlacement, 'se:PerpendicularOffset', 0)
self.assertEqual("7", offset.text())
repeat = self.assertElement(linePlacement, 'se:Repeat', 0)
self.assertEqual("true", repeat.text())
gap = self.assertElement(linePlacement, 'se:Gap', 0)
self.assertEqual("179", gap.text())
self.assertEqual("179", self.assertVendorOption(ts, "repeat").text())
self.assertEqual("true", self.assertVendorOption(ts, "followLine").text())
self.assertEqual("30", self.assertVendorOption(ts, "maxAngleDelta").text())
def testLabelScaleDependencies(self):
layer = QgsVectorLayer("Polygon", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "polygonLabel")
settings = layer.labeling().settings()
settings.scaleVisibility = True
settings.minimumScale = 1000000
settings.maximumScale = 10000000
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Labeling with scale dependencies " + dom.toString())
self.assertScaleDenominator(root, "1000000", "10000000", 1)
def testLabelShowAll(self):
layer = QgsVectorLayer("Polygon", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "polygonLabel")
settings = layer.labeling().settings()
settings.displayAll = True
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Labeling, showing all labels " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
self.assertVendorOption(ts, "conflictResolution", "false")
def testLabelUpsideDown(self):
layer = QgsVectorLayer("Polygon", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "polygonLabel")
settings = layer.labeling().settings()
settings.upsidedownLabels = QgsPalLayerSettings.ShowAll
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Labeling, showing upside down labels on lines " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
self.assertVendorOption(ts, "forceLeftToRight", "false")
def testLabelBackgroundSquareResize(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeSquare, 'square',
QgsTextBackgroundSettings.SizeBuffer, 'proportional')
def testLabelBackgroundRectangleResize(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeRectangle, 'square',
QgsTextBackgroundSettings.SizeBuffer, 'stretch')
def testLabelBackgroundCircleResize(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeCircle, 'circle',
QgsTextBackgroundSettings.SizeBuffer, 'proportional')
def testLabelBackgroundEllipseResize(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeEllipse, 'circle',
QgsTextBackgroundSettings.SizeBuffer, 'stretch')
def testLabelBackgroundSquareAbsolute(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeSquare, 'square',
QgsTextBackgroundSettings.SizeFixed, None)
def testLabelBackgroundRectangleAbsolute(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeRectangle, 'square',
QgsTextBackgroundSettings.SizeFixed, None)
def testLabelBackgroundCircleAbsolute(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeCircle, 'circle',
QgsTextBackgroundSettings.SizeFixed, None)
def testLabelBackgroundEllipseAbsolute(self):
self.assertLabelBackground(QgsTextBackgroundSettings.ShapeEllipse, 'circle',
QgsTextBackgroundSettings.SizeFixed, None)
def assertLabelBackground(self, backgroundType, expectedMarkName, sizeType, expectedResize):
layer = QgsVectorLayer("Polygon", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "polygonLabel")
settings = layer.labeling().settings()
background = QgsTextBackgroundSettings()
background.setEnabled(True)
background.setType(backgroundType)
background.setFillColor(QColor('yellow'))
background.setStrokeColor(QColor('black'))
background.setStrokeWidth(2)
background.setSize(QSizeF(10, 10))
background.setSizeType(sizeType)
format = settings.format()
format.setBackground(background)
settings.setFormat(format)
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Labeling, with background type " + str(backgroundType) + " and size type " + str(sizeType) + ": " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
graphic = self.assertElement(ts, "se:Graphic", 0)
self.assertEqual("36", self.assertElement(graphic, 'se:Size', 0).text())
self.assertWellKnownMark(graphic, 0, expectedMarkName, '#ffff00', '#000000', 7)
if expectedResize is None:
self.assertIsNone(expectedResize, self.assertVendorOption(ts, 'graphic-resize', True))
else:
self.assertEqual(expectedResize, self.assertVendorOption(ts, 'graphic-resize').text())
if sizeType == 0:
# check extra padding for proportional ellipse
if backgroundType == QgsTextBackgroundSettings.ShapeEllipse:
self.assertEqual("42.5 49", self.assertVendorOption(ts, 'graphic-margin').text())
else:
self.assertEqual("36 36", self.assertVendorOption(ts, 'graphic-margin').text())
else:
self.assertIsNone(self.assertVendorOption(ts, 'graphic-margin', True))
def updateLinePlacementProperties(self, layer, linePlacement, distance, repeat, maxAngleInternal=25, maxAngleExternal=-25):
settings = layer.labeling().settings()
settings.placement = linePlacement
settings.dist = distance
settings.repeatDistance = repeat
settings.maxCurvedCharAngleIn = maxAngleInternal
settings.maxCurvedCharAngleOut = maxAngleExternal
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
def assertPointPlacementDistance(self, placement):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
settings = layer.labeling().settings()
settings.placement = placement
settings.xOffset = 0
settings.yOffset = 0
settings.dist = 2
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Label with around point placement " + dom.toString())
ts = self.getTextSymbolizer(root, 1, 0)
pointPlacement = self.assertPointPlacement(ts)
self.assertStaticAnchorPoint(pointPlacement, 0, 0.5)
self.assertStaticDisplacement(pointPlacement, 4.95, 4.95)
def assertLabelQuadrant(self, quadrant, label, ax, ay):
layer = QgsVectorLayer("Point", "addfeat", "memory")
self.loadStyleWithCustomProperties(layer, "simpleLabel")
settings = layer.labeling().settings()
settings.placement = QgsPalLayerSettings.OverPoint
settings.xOffset = 0
settings.yOffset = 0
settings.quadOffset = quadrant
settings.angleOffset = 0
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
dom, root = self.layerToSld(layer)
# print("Label with " + label + " placement " + dom.toString())
self.assertStaticAnchorPoint(root, ax, ay)
def setLabelBufferSettings(self, layer, buffer):
settings = layer.labeling().settings()
format = settings.format()
format.setBuffer(buffer)
settings.setFormat(format)
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
def updateLayerLabelingFontStyle(self, layer, bold, italic, underline=False, strikeout=False):
settings = layer.labeling().settings()
format = settings.format()
font = format.font()
font.setBold(bold)
font.setItalic(italic)
font.setUnderline(underline)
font.setStrikeOut(strikeout)
format.setFont(font)
settings.setFormat(format)
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
def updateLayerLabelingUnit(self, layer, unit):
settings = layer.labeling().settings()
format = settings.format()
format.setSizeUnit(unit)
settings.setFormat(format)
layer.setLabeling(QgsVectorLayerSimpleLabeling(settings))
def loadStyleWithCustomProperties(self, layer, qmlFileName):
# load the style, only vector symbology
path = QDir.toNativeSeparators('%s/symbol_layer/%s.qml' % (unitTestDataPath(), qmlFileName))
# labeling is in custom properties, they need to be loaded separately
status = layer.loadNamedStyle(path)
doc = QDomDocument()
file = QFile(path)
file.open(QIODevice.ReadOnly)
doc.setContent(file, True)
file.close()
flag = layer.readCustomProperties(doc.documentElement())
def assertPointPlacement(self, textSymbolizer):
labelPlacement = self.assertElement(textSymbolizer, 'se:LabelPlacement', 0)
self.assertIsNone(self.assertElement(labelPlacement, 'se:LinePlacement', 0, True))
pointPlacement = self.assertElement(labelPlacement, 'se:PointPlacement', 0)
return pointPlacement
def assertLinePlacement(self, textSymbolizer):
labelPlacement = self.assertElement(textSymbolizer, 'se:LabelPlacement', 0)
self.assertIsNone(self.assertElement(labelPlacement, 'se:PointPlacement', 0, True))
linePlacement = self.assertElement(labelPlacement, 'se:LinePlacement', 0)
return linePlacement
def assertElement(self, container, elementName, index, allowMissing=False):
list = container.elementsByTagName(elementName)
if list.size() <= index:
if allowMissing:
return None
else:
self.fail('Expected to find at least ' + str(index + 1) + ' ' + elementName + ' in ' + container.nodeName() + ' but found ' + str(list.size()))
node = list.item(index)
self.assertTrue(node.isElement(), 'Found node but it''s not an element')
return node.toElement()
def getTextSymbolizer(self, root, ruleIndex, textSymbolizerIndex):
rule = self.assertElement(root, 'se:Rule', ruleIndex)
textSymbolizer = self.assertElement(rule, 'se:TextSymbolizer', textSymbolizerIndex)
return textSymbolizer
def assertPropertyName(self, root, containerProperty, expectedAttributeName):
container = root.elementsByTagName(containerProperty).item(0).toElement()
property = container.elementsByTagName("ogc:PropertyName").item(0).toElement()
self.assertEqual(expectedAttributeName, property.text())
def assertSvgParameter(self, container, expectedName, allowMissing=False):
list = container.elementsByTagName("se:SvgParameter")
for i in range(0, list.size()):
item = list.item(i)
if item.isElement and item.isElement() and item.toElement().attribute('name') == expectedName:
return item.toElement()
if allowMissing:
return None
else:
self.fail('Could not find a se:SvgParameter named ' + expectedName + ' in ' + container.nodeName())
def assertVendorOption(self, container, expectedName, allowMissing=False):
list = container.elementsByTagName("se:VendorOption")
for i in range(0, list.size()):
item = list.item(i)
if item.isElement and item.isElement() and item.toElement().attribute('name') == expectedName:
return item.toElement()
if allowMissing:
return None
else:
self.fail('Could not find a se:VendorOption named ' + expectedName + ' in ' + container.nodeName())
def assertScaleDenominator(self, root, expectedMinScale, expectedMaxScale, index=0):
rule = root.elementsByTagName('se:Rule').item(index).toElement()
@ -615,6 +1225,52 @@ class TestQgsSymbolLayerCreateSld(unittest.TestCase):
self.assertEqual('stroke-width', parameter.attribute('name'))
self.assertEqual(str(expectedStrokeWidth), parameter.text())
def assertStaticRotation(self, root, expectedValue, index=0):
# Check the rotation element is a literal, not a
rotation = root.elementsByTagName('se:Rotation').item(index)
literal = rotation.firstChild()
self.assertEqual("ogc:Literal", literal.nodeName())
self.assertEqual(expectedValue, literal.firstChild().nodeValue())
def assertStaticDisplacement(self, root, expectedAnchorX, expectedAnchorY):
displacement = root.elementsByTagName('se:Displacement').item(0)
self.assertIsNotNone(displacement)
dx = displacement.firstChild()
self.assertIsNotNone(dx)
self.assertEqual("se:DisplacementX", dx.nodeName())
self.assertSldNumber(expectedAnchorX, dx.firstChild().nodeValue())
dy = displacement.lastChild()
self.assertIsNotNone(dy)
self.assertEqual("se:DisplacementY", dy.nodeName())
self.assertSldNumber(expectedAnchorY, dy.firstChild().nodeValue())
def assertStaticAnchorPoint(self, root, expectedDispX, expectedDispY):
anchor = root.elementsByTagName('se:AnchorPoint').item(0)
self.assertIsNotNone(anchor)
ax = anchor.firstChild()
self.assertIsNotNone(ax)
self.assertEqual("se:AnchorPointX", ax.nodeName())
self.assertSldNumber(expectedDispX, ax.firstChild().nodeValue())
ay = anchor.lastChild()
self.assertIsNotNone(ay)
self.assertEqual("se:AnchorPointY", ay.nodeName())
self.assertSldNumber(expectedDispY, ay.firstChild().nodeValue())
def assertSldNumber(self, expected, stringValue):
value = float(stringValue)
self.assertFloatEquals(expected, value, 0.01)
def assertFloatEquals(self, expected, actual, tol):
self.assertLess(abs(expected - actual), tol, 'Expected %d but was %d' % (expected, actual))
def assertStrokeWidth(self, root, svgParameterIdx, expectedWidth):
strokeWidth = root.elementsByTagName(
'se:SvgParameter').item(svgParameterIdx)
svgParameterName = strokeWidth.attributes().namedItem('name')
self.assertEqual("stroke-width", svgParameterName.nodeValue())
self.assertSldNumber(
expectedWidth, strokeWidth.firstChild().nodeValue())
def symbolToSld(self, symbolLayer):
dom = QDomDocument()
root = dom.createElement("FakeRoot")

View File

@ -0,0 +1,242 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis simplifyAlgorithm="0" hasScaleBasedVisibilityFlag="0" maxScale="0" mincale="1e+08" simplifyDrawingHints="1" simplifyLocal="1" version="2.99.0-Master" readOnly="0" simplifyDrawingTol="1" simplifyMaxScale="1">
<renderer-v2 forceraster="0" enableorderby="0" symbollevels="0" type="singleSymbol">
<symbols>
<symbol name="0" alpha="1" type="line" clip_to_extent="1">
<layer locked="0" class="SimpleLine" pass="0" enabled="1">
<prop v="square" k="capstyle"/>
<prop v="5;2" k="customdash"/>
<prop v="3x:0,0,0,0,0,0" k="customdash_map_unit_scale"/>
<prop v="MM" k="customdash_unit"/>
<prop v="0" k="draw_inside_polygon"/>
<prop v="bevel" k="joinstyle"/>
<prop v="198,33,179,255" k="line_color"/>
<prop v="solid" k="line_style"/>
<prop v="0.26" k="line_width"/>
<prop v="MM" k="line_width_unit"/>
<prop v="0" k="offset"/>
<prop v="3x:0,0,0,0,0,0" k="offset_map_unit_scale"/>
<prop v="MM" k="offset_unit"/>
<prop v="0" k="use_custom_dash"/>
<prop v="3x:0,0,0,0,0,0" k="width_map_unit_scale"/>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale/>
</renderer-v2>
<labeling type="simple">
<settings>
<text-style namedStyle="Regular" fontSize="10" fontLetterSpacing="0" multilineHeight="1" fontWordSpacing="0" useSubstitutions="0" fontUnderline="0" previewBkgrdColor="#ffffff" isExpression="0" fontWeight="50" fontCapitals="0" fieldName="name" textColor="0,0,0,255" textOpacity="1" fontStrikeout="0" fontFamily="Noto Sans" fontSizeMapUnitScale="3x:0,0,0,0,0,0" blendMode="0" fontSizeUnit="Point" fontItalic="0">
<text-buffer bufferSize="1" bufferDraw="0" bufferColor="255,255,255,255" bufferJoinStyle="128" bufferSizeMapUnitScale="3x:0,0,0,0,0,0" bufferNoFill="1" bufferBlendMode="0" bufferSizeUnits="MM" bufferOpacity="1"/>
<background shapeRotation="0" shapeBorderWidthUnit="MM" shapeOffsetMapUnitScale="3x:0,0,0,0,0,0" shapeRadiiY="0" shapeBorderWidth="0" shapeRadiiUnit="MM" shapeBorderColor="128,128,128,255" shapeBorderWidthMapUnitScale="3x:0,0,0,0,0,0" shapeOffsetX="0" shapeOffsetY="0" shapeJoinStyle="64" shapeSizeX="0" shapeRadiiMapUnitScale="3x:0,0,0,0,0,0" shapeSizeY="0" shapeRotationType="0" shapeSizeUnit="MM" shapeBlendMode="0" shapeDraw="0" shapeSizeType="0" shapeRadiiX="0" shapeSVGFile="" shapeOffsetUnit="MM" shapeSizeMapUnitScale="3x:0,0,0,0,0,0" shapeFillColor="255,255,255,255" shapeType="0" shapeOpacity="1"/>
<shadow shadowOffsetAngle="135" shadowOffsetGlobal="1" shadowOffsetDist="1" shadowOffsetMapUnitScale="3x:0,0,0,0,0,0" shadowDraw="0" shadowUnder="0" shadowOpacity="0.7" shadowOffsetUnit="MM" shadowRadiusMapUnitScale="3x:0,0,0,0,0,0" shadowBlendMode="6" shadowRadiusAlphaOnly="0" shadowScale="100" shadowRadius="1.5" shadowRadiusUnit="MM" shadowColor="0,0,0,255"/>
<substitutions/>
</text-style>
<text-format placeDirectionSymbol="0" multilineAlign="4294967295" wrapChar="" rightDirectionSymbol=">" leftDirectionSymbol="&lt;" plussign="0" formatNumbers="0" reverseDirectionSymbol="0" addDirectionSymbol="0" decimals="3"/>
<placement rotationAngle="0" dist="0" priority="5" placement="2" placementFlags="10" labelOffsetInMapUnits="1" quadOffset="4" repeatDistanceUnit="1" distInMapUnits="0" centroidWhole="0" yOffset="0" centroidInside="0" maxCurvedCharAngleIn="25" repeatDistanceMapUnitScale="3x:0,0,0,0,0,0" distMapUnitScale="3x:0,0,0,0,0,0" maxCurvedCharAngleOut="-25" labelOffsetMapUnitScale="3x:0,0,0,0,0,0" xOffset="0" repeatDistance="0" predefinedPositionOrder="TR,TL,BR,BL,R,L,TSR,BSR" preserveRotation="1" fitInPolygonOnly="0" offsetType="0"/>
<rendering obstacle="1" zIndex="0" mergeLines="0" scaleVisibility="0" limitNumLabels="0" maxNumLabels="2000" drawLabels="1" scaleMax="0" fontLimitPixelSize="0" fontMinPixelSize="3" minFeatureSize="0" labelPerPart="0" obstacleFactor="1" displayAll="0" obstacleType="0" scaleMin="0" upsidedownLabels="0" fontMaxPixelSize="10000"/>
<dd_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</dd_properties>
</settings>
</labeling>
<customproperties>
<property value="0" key="embeddedWidgets/count"/>
<property key="variableNames"/>
<property key="variableValues"/>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<SingleCategoryDiagramRenderer sizeLegend="0" diagramType="Histogram" attributeLegend="1">
<DiagramCategory sizeType="MM" opacity="1" scaleBasedVisibility="0" width="15" backgroundColor="#ffffff" enabled="0" penAlpha="255" lineSizeScale="3x:0,0,0,0,0,0" penWidth="0" scaleDependency="Area" rotationOffset="270" lineSizeType="MM" labelPlacementMethod="XHeight" backgroundAlpha="255" barWidth="5" penColor="#000000" minScaleDenominator="0" sizeScale="3x:0,0,0,0,0,0" minimumSize="0" maxScaleDenominator="1e+08" diagramOrientation="Up" height="15">
<fontProperties style="" description="Noto Sans,9,-1,5,50,0,0,0,0,0"/>
</DiagramCategory>
<symbol name="sizeSymbol" alpha="1" type="marker" clip_to_extent="1">
<layer locked="0" class="SimpleMarker" pass="0" enabled="1">
<prop v="0" k="angle"/>
<prop v="255,0,0,255" k="color"/>
<prop v="1" k="horizontal_anchor_point"/>
<prop v="bevel" k="joinstyle"/>
<prop v="circle" k="name"/>
<prop v="0,0" k="offset"/>
<prop v="3x:0,0,0,0,0,0" k="offset_map_unit_scale"/>
<prop v="MM" k="offset_unit"/>
<prop v="0,0,0,255" k="outline_color"/>
<prop v="solid" k="outline_style"/>
<prop v="0" k="outline_width"/>
<prop v="3x:0,0,0,0,0,0" k="outline_width_map_unit_scale"/>
<prop v="MM" k="outline_width_unit"/>
<prop v="diameter" k="scale_method"/>
<prop v="2" k="size"/>
<prop v="3x:0,0,0,0,0,0" k="size_map_unit_scale"/>
<prop v="MM" k="size_unit"/>
<prop v="1" k="vertical_anchor_point"/>
<data_defined_properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</SingleCategoryDiagramRenderer>
<DiagramLayerSettings placement="2" obstacle="0" showAll="1" priority="0" dist="0" zIndex="0" linePlacementFlags="18">
<properties>
<Option type="Map">
<Option name="name" value="" type="QString"/>
<Option name="properties"/>
<Option name="type" value="collection" type="QString"/>
</Option>
</properties>
</DiagramLayerSettings>
<fieldConfiguration>
<field name="dissolve">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="scalerank">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="featurecla">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name_alt">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="rivernum">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="note">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
</fieldConfiguration>
<aliases>
<alias name="" field="dissolve" index="0"/>
<alias name="" field="scalerank" index="1"/>
<alias name="" field="featurecla" index="2"/>
<alias name="" field="name" index="3"/>
<alias name="" field="name_alt" index="4"/>
<alias name="" field="rivernum" index="5"/>
<alias name="" field="note" index="6"/>
</aliases>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<defaults>
<default field="dissolve" expression=""/>
<default field="scalerank" expression=""/>
<default field="featurecla" expression=""/>
<default field="name" expression=""/>
<default field="name_alt" expression=""/>
<default field="rivernum" expression=""/>
<default field="note" expression=""/>
</defaults>
<constraints>
<constraint field="dissolve" unique_strength="0" notnull_strength="0" exp_strength="0" constraints="0"/>
<constraint field="scalerank" unique_strength="0" notnull_strength="0" exp_strength="0" constraints="0"/>
<constraint field="featurecla" unique_strength="0" notnull_strength="0" exp_strength="0" constraints="0"/>
<constraint field="name" unique_strength="0" notnull_strength="0" exp_strength="0" constraints="0"/>
<constraint field="name_alt" unique_strength="0" notnull_strength="0" exp_strength="0" constraints="0"/>
<constraint field="rivernum" unique_strength="0" notnull_strength="0" exp_strength="0" constraints="0"/>
<constraint field="note" unique_strength="0" notnull_strength="0" exp_strength="0" constraints="0"/>
</constraints>
<constraintExpressions>
<constraint field="dissolve" desc="" exp=""/>
<constraint field="scalerank" desc="" exp=""/>
<constraint field="featurecla" desc="" exp=""/>
<constraint field="name" desc="" exp=""/>
<constraint field="name_alt" desc="" exp=""/>
<constraint field="rivernum" desc="" exp=""/>
<constraint field="note" desc="" exp=""/>
</constraintExpressions>
<attributeactions>
<defaultAction value="{00000000-0000-0000-0000-000000000000}" key="Canvas"/>
</attributeactions>
<attributetableconfig sortExpression="" actionWidgetStyle="dropDown" sortOrder="0">
<columns>
<column name="dissolve" hidden="0" type="field" width="-1"/>
<column name="scalerank" hidden="0" type="field" width="-1"/>
<column name="featurecla" hidden="0" type="field" width="-1"/>
<column name="name" hidden="0" type="field" width="-1"/>
<column name="name_alt" hidden="0" type="field" width="-1"/>
<column name="rivernum" hidden="0" type="field" width="-1"/>
<column name="note" hidden="0" type="field" width="-1"/>
<column hidden="1" type="actions" width="-1"/>
</columns>
</attributetableconfig>
<editform></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS forms can have a Python function that is called when the form is
opened.
Use this function to add extra logic to your forms.
Enter the name of the function in the "Python Init function"
field.
An example follows:
"""
from qgis.PyQt.QtWidgets import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<widgets/>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<expressionfields/>
<previewExpression>name</previewExpression>
<mapTip></mapTip>
<layerGeometryType>1</layerGeometryType>
</qgis>

View File

@ -0,0 +1,910 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="2.99.0-Master" simplifyDrawingHints="1" simplifyLocal="1" readOnly="0" mincale="1e+08" hasScaleBasedVisibilityFlag="0" maxScale="0" simplifyAlgorithm="0" simplifyDrawingTol="1" simplifyMaxScale="1">
<renderer-v2 symbollevels="0" forceraster="0" type="singleSymbol" enableorderby="0">
<symbols>
<symbol alpha="1" name="0" clip_to_extent="1" type="fill">
<layer pass="0" enabled="1" locked="0" class="SimpleFill">
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="color" v="143,107,163,255"/>
<prop k="joinstyle" v="bevel"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.26"/>
<prop k="outline_width_unit" v="MM"/>
<prop k="style" v="solid"/>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale/>
</renderer-v2>
<labeling type="simple">
<settings>
<text-style fontWeight="50" fieldName="name" blendMode="0" fontItalic="0" isExpression="0" fontStrikeout="0" fontSizeMapUnitScale="3x:0,0,0,0,0,0" fontSize="10" fontFamily="Noto Sans" previewBkgrdColor="#ffffff" useSubstitutions="0" fontUnderline="0" textOpacity="1" textColor="0,0,0,255" fontSizeUnit="Point" fontWordSpacing="0" fontCapitals="0" namedStyle="Regular" multilineHeight="1" fontLetterSpacing="0">
<text-buffer bufferColor="255,255,255,255" bufferSize="1" bufferSizeUnits="MM" bufferBlendMode="0" bufferOpacity="1" bufferSizeMapUnitScale="3x:0,0,0,0,0,0" bufferNoFill="1" bufferJoinStyle="128" bufferDraw="0"/>
<background shapeRotationType="0" shapeType="0" shapeSizeX="0" shapeOpacity="1" shapeRadiiMapUnitScale="3x:0,0,0,0,0,0" shapeRadiiY="0" shapeSizeMapUnitScale="3x:0,0,0,0,0,0" shapeBlendMode="0" shapeOffsetY="0" shapeRotation="0" shapeOffsetMapUnitScale="3x:0,0,0,0,0,0" shapeOffsetX="0" shapeOffsetUnit="MM" shapeFillColor="255,255,255,255" shapeBorderWidthMapUnitScale="3x:0,0,0,0,0,0" shapeBorderColor="128,128,128,255" shapeSVGFile="" shapeRadiiUnit="MM" shapeDraw="0" shapeSizeType="0" shapeBorderWidthUnit="MM" shapeSizeY="0" shapeRadiiX="0" shapeBorderWidth="0" shapeJoinStyle="64" shapeSizeUnit="MM"/>
<shadow shadowOffsetGlobal="1" shadowRadiusUnit="MM" shadowBlendMode="6" shadowOffsetDist="1" shadowOffsetAngle="135" shadowUnder="0" shadowOffsetMapUnitScale="3x:0,0,0,0,0,0" shadowScale="100" shadowRadius="1.5" shadowRadiusMapUnitScale="3x:0,0,0,0,0,0" shadowColor="0,0,0,255" shadowOpacity="0.7" shadowDraw="0" shadowOffsetUnit="MM" shadowRadiusAlphaOnly="0"/>
<substitutions/>
</text-style>
<text-format reverseDirectionSymbol="0" placeDirectionSymbol="0" multilineAlign="4294967295" plussign="0" rightDirectionSymbol=">" formatNumbers="0" leftDirectionSymbol="&lt;" decimals="3" wrapChar="" addDirectionSymbol="0"/>
<placement offsetType="0" priority="5" dist="0" repeatDistanceUnit="1" labelOffsetInMapUnits="1" predefinedPositionOrder="TR,TL,BR,BL,R,L,TSR,BSR" repeatDistanceMapUnitScale="3x:0,0,0,0,0,0" distInMapUnits="0" preserveRotation="1" yOffset="0" labelOffsetMapUnitScale="3x:0,0,0,0,0,0" centroidInside="0" rotationAngle="0" distMapUnitScale="3x:0,0,0,0,0,0" maxCurvedCharAngleOut="-25" maxCurvedCharAngleIn="25" placementFlags="10" repeatDistance="0" xOffset="0" placement="0" fitInPolygonOnly="0" quadOffset="4" centroidWhole="0"/>
<rendering drawLabels="1" labelPerPart="0" obstacleFactor="1" scaleVisibility="0" scaleMax="0" mergeLines="0" scaleMin="0" minFeatureSize="0" obstacle="1" fontMaxPixelSize="10000" zIndex="0" fontMinPixelSize="3" obstacleType="0" fontLimitPixelSize="0" limitNumLabels="0" upsidedownLabels="0" maxNumLabels="2000" displayAll="0"/>
<dd_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</dd_properties>
</settings>
</labeling>
<customproperties>
<property key="embeddedWidgets/count" value="0"/>
<property key="variableNames"/>
<property key="variableValues"/>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
<DiagramCategory rotationOffset="270" barWidth="5" scaleDependency="Area" penWidth="0" minimumSize="0" height="15" penAlpha="255" sizeType="MM" enabled="0" lineSizeScale="3x:0,0,0,0,0,0" minScaleDenominator="0" maxScaleDenominator="1e+08" sizeScale="3x:0,0,0,0,0,0" scaleBasedVisibility="0" width="15" diagramOrientation="Up" labelPlacementMethod="XHeight" lineSizeType="MM" backgroundAlpha="255" penColor="#000000" backgroundColor="#ffffff" opacity="1">
<fontProperties description="Noto Sans,9,-1,5,50,0,0,0,0,0" style=""/>
</DiagramCategory>
<symbol alpha="1" name="sizeSymbol" clip_to_extent="1" type="marker">
<layer pass="0" enabled="1" locked="0" class="SimpleMarker">
<prop k="angle" v="0"/>
<prop k="color" v="255,0,0,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0"/>
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="MM"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="2"/>
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="size_unit" v="MM"/>
<prop k="vertical_anchor_point" v="1"/>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</SingleCategoryDiagramRenderer>
<DiagramLayerSettings obstacle="0" priority="0" linePlacementFlags="18" dist="0" zIndex="0" showAll="1" placement="0">
<properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</properties>
</DiagramLayerSettings>
<fieldConfiguration>
<field name="scalerank">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="featurecla">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="labelrank">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="sovereignt">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="sov_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="adm0_dif">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="level">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="type">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="admin">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="adm0_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="geou_dif">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="geounit">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="gu_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="su_dif">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="subunit">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="su_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="brk_diff">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name_long">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="brk_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="brk_name">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="brk_group">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="abbrev">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="postal">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="formal_en">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="formal_fr">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="note_adm0">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="note_brk">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name_sort">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name_alt">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="mapcolor7">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="mapcolor8">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="mapcolor9">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="mapcolor13">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="pop_est">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="gdp_md_est">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="pop_year">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="lastcensus">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="gdp_year">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="economy">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="income_grp">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="wikipedia">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="fips_10">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="iso_a2">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="iso_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="iso_n3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="un_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="wb_a2">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="wb_a3">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="woe_id">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="adm0_a3_is">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="adm0_a3_us">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="adm0_a3_un">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="adm0_a3_wb">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="continent">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="region_un">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="subregion">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="region_wb">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="name_len">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="long_len">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="abbrev_len">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="tiny">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="homepart">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
</fieldConfiguration>
<aliases>
<alias field="scalerank" name="" index="0"/>
<alias field="featurecla" name="" index="1"/>
<alias field="labelrank" name="" index="2"/>
<alias field="sovereignt" name="" index="3"/>
<alias field="sov_a3" name="" index="4"/>
<alias field="adm0_dif" name="" index="5"/>
<alias field="level" name="" index="6"/>
<alias field="type" name="" index="7"/>
<alias field="admin" name="" index="8"/>
<alias field="adm0_a3" name="" index="9"/>
<alias field="geou_dif" name="" index="10"/>
<alias field="geounit" name="" index="11"/>
<alias field="gu_a3" name="" index="12"/>
<alias field="su_dif" name="" index="13"/>
<alias field="subunit" name="" index="14"/>
<alias field="su_a3" name="" index="15"/>
<alias field="brk_diff" name="" index="16"/>
<alias field="name" name="" index="17"/>
<alias field="name_long" name="" index="18"/>
<alias field="brk_a3" name="" index="19"/>
<alias field="brk_name" name="" index="20"/>
<alias field="brk_group" name="" index="21"/>
<alias field="abbrev" name="" index="22"/>
<alias field="postal" name="" index="23"/>
<alias field="formal_en" name="" index="24"/>
<alias field="formal_fr" name="" index="25"/>
<alias field="note_adm0" name="" index="26"/>
<alias field="note_brk" name="" index="27"/>
<alias field="name_sort" name="" index="28"/>
<alias field="name_alt" name="" index="29"/>
<alias field="mapcolor7" name="" index="30"/>
<alias field="mapcolor8" name="" index="31"/>
<alias field="mapcolor9" name="" index="32"/>
<alias field="mapcolor13" name="" index="33"/>
<alias field="pop_est" name="" index="34"/>
<alias field="gdp_md_est" name="" index="35"/>
<alias field="pop_year" name="" index="36"/>
<alias field="lastcensus" name="" index="37"/>
<alias field="gdp_year" name="" index="38"/>
<alias field="economy" name="" index="39"/>
<alias field="income_grp" name="" index="40"/>
<alias field="wikipedia" name="" index="41"/>
<alias field="fips_10" name="" index="42"/>
<alias field="iso_a2" name="" index="43"/>
<alias field="iso_a3" name="" index="44"/>
<alias field="iso_n3" name="" index="45"/>
<alias field="un_a3" name="" index="46"/>
<alias field="wb_a2" name="" index="47"/>
<alias field="wb_a3" name="" index="48"/>
<alias field="woe_id" name="" index="49"/>
<alias field="adm0_a3_is" name="" index="50"/>
<alias field="adm0_a3_us" name="" index="51"/>
<alias field="adm0_a3_un" name="" index="52"/>
<alias field="adm0_a3_wb" name="" index="53"/>
<alias field="continent" name="" index="54"/>
<alias field="region_un" name="" index="55"/>
<alias field="subregion" name="" index="56"/>
<alias field="region_wb" name="" index="57"/>
<alias field="name_len" name="" index="58"/>
<alias field="long_len" name="" index="59"/>
<alias field="abbrev_len" name="" index="60"/>
<alias field="tiny" name="" index="61"/>
<alias field="homepart" name="" index="62"/>
</aliases>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<defaults>
<default field="scalerank" expression=""/>
<default field="featurecla" expression=""/>
<default field="labelrank" expression=""/>
<default field="sovereignt" expression=""/>
<default field="sov_a3" expression=""/>
<default field="adm0_dif" expression=""/>
<default field="level" expression=""/>
<default field="type" expression=""/>
<default field="admin" expression=""/>
<default field="adm0_a3" expression=""/>
<default field="geou_dif" expression=""/>
<default field="geounit" expression=""/>
<default field="gu_a3" expression=""/>
<default field="su_dif" expression=""/>
<default field="subunit" expression=""/>
<default field="su_a3" expression=""/>
<default field="brk_diff" expression=""/>
<default field="name" expression=""/>
<default field="name_long" expression=""/>
<default field="brk_a3" expression=""/>
<default field="brk_name" expression=""/>
<default field="brk_group" expression=""/>
<default field="abbrev" expression=""/>
<default field="postal" expression=""/>
<default field="formal_en" expression=""/>
<default field="formal_fr" expression=""/>
<default field="note_adm0" expression=""/>
<default field="note_brk" expression=""/>
<default field="name_sort" expression=""/>
<default field="name_alt" expression=""/>
<default field="mapcolor7" expression=""/>
<default field="mapcolor8" expression=""/>
<default field="mapcolor9" expression=""/>
<default field="mapcolor13" expression=""/>
<default field="pop_est" expression=""/>
<default field="gdp_md_est" expression=""/>
<default field="pop_year" expression=""/>
<default field="lastcensus" expression=""/>
<default field="gdp_year" expression=""/>
<default field="economy" expression=""/>
<default field="income_grp" expression=""/>
<default field="wikipedia" expression=""/>
<default field="fips_10" expression=""/>
<default field="iso_a2" expression=""/>
<default field="iso_a3" expression=""/>
<default field="iso_n3" expression=""/>
<default field="un_a3" expression=""/>
<default field="wb_a2" expression=""/>
<default field="wb_a3" expression=""/>
<default field="woe_id" expression=""/>
<default field="adm0_a3_is" expression=""/>
<default field="adm0_a3_us" expression=""/>
<default field="adm0_a3_un" expression=""/>
<default field="adm0_a3_wb" expression=""/>
<default field="continent" expression=""/>
<default field="region_un" expression=""/>
<default field="subregion" expression=""/>
<default field="region_wb" expression=""/>
<default field="name_len" expression=""/>
<default field="long_len" expression=""/>
<default field="abbrev_len" expression=""/>
<default field="tiny" expression=""/>
<default field="homepart" expression=""/>
</defaults>
<constraints>
<constraint field="scalerank" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="featurecla" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="labelrank" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="sovereignt" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="sov_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="adm0_dif" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="level" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="type" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="admin" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="adm0_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="geou_dif" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="geounit" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="gu_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="su_dif" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="subunit" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="su_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="brk_diff" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="name" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="name_long" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="brk_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="brk_name" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="brk_group" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="abbrev" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="postal" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="formal_en" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="formal_fr" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="note_adm0" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="note_brk" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="name_sort" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="name_alt" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="mapcolor7" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="mapcolor8" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="mapcolor9" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="mapcolor13" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="pop_est" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="gdp_md_est" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="pop_year" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="lastcensus" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="gdp_year" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="economy" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="income_grp" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="wikipedia" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="fips_10" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="iso_a2" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="iso_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="iso_n3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="un_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="wb_a2" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="wb_a3" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="woe_id" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="adm0_a3_is" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="adm0_a3_us" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="adm0_a3_un" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="adm0_a3_wb" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="continent" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="region_un" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="subregion" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="region_wb" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="name_len" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="long_len" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="abbrev_len" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="tiny" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
<constraint field="homepart" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
</constraints>
<constraintExpressions>
<constraint field="scalerank" desc="" exp=""/>
<constraint field="featurecla" desc="" exp=""/>
<constraint field="labelrank" desc="" exp=""/>
<constraint field="sovereignt" desc="" exp=""/>
<constraint field="sov_a3" desc="" exp=""/>
<constraint field="adm0_dif" desc="" exp=""/>
<constraint field="level" desc="" exp=""/>
<constraint field="type" desc="" exp=""/>
<constraint field="admin" desc="" exp=""/>
<constraint field="adm0_a3" desc="" exp=""/>
<constraint field="geou_dif" desc="" exp=""/>
<constraint field="geounit" desc="" exp=""/>
<constraint field="gu_a3" desc="" exp=""/>
<constraint field="su_dif" desc="" exp=""/>
<constraint field="subunit" desc="" exp=""/>
<constraint field="su_a3" desc="" exp=""/>
<constraint field="brk_diff" desc="" exp=""/>
<constraint field="name" desc="" exp=""/>
<constraint field="name_long" desc="" exp=""/>
<constraint field="brk_a3" desc="" exp=""/>
<constraint field="brk_name" desc="" exp=""/>
<constraint field="brk_group" desc="" exp=""/>
<constraint field="abbrev" desc="" exp=""/>
<constraint field="postal" desc="" exp=""/>
<constraint field="formal_en" desc="" exp=""/>
<constraint field="formal_fr" desc="" exp=""/>
<constraint field="note_adm0" desc="" exp=""/>
<constraint field="note_brk" desc="" exp=""/>
<constraint field="name_sort" desc="" exp=""/>
<constraint field="name_alt" desc="" exp=""/>
<constraint field="mapcolor7" desc="" exp=""/>
<constraint field="mapcolor8" desc="" exp=""/>
<constraint field="mapcolor9" desc="" exp=""/>
<constraint field="mapcolor13" desc="" exp=""/>
<constraint field="pop_est" desc="" exp=""/>
<constraint field="gdp_md_est" desc="" exp=""/>
<constraint field="pop_year" desc="" exp=""/>
<constraint field="lastcensus" desc="" exp=""/>
<constraint field="gdp_year" desc="" exp=""/>
<constraint field="economy" desc="" exp=""/>
<constraint field="income_grp" desc="" exp=""/>
<constraint field="wikipedia" desc="" exp=""/>
<constraint field="fips_10" desc="" exp=""/>
<constraint field="iso_a2" desc="" exp=""/>
<constraint field="iso_a3" desc="" exp=""/>
<constraint field="iso_n3" desc="" exp=""/>
<constraint field="un_a3" desc="" exp=""/>
<constraint field="wb_a2" desc="" exp=""/>
<constraint field="wb_a3" desc="" exp=""/>
<constraint field="woe_id" desc="" exp=""/>
<constraint field="adm0_a3_is" desc="" exp=""/>
<constraint field="adm0_a3_us" desc="" exp=""/>
<constraint field="adm0_a3_un" desc="" exp=""/>
<constraint field="adm0_a3_wb" desc="" exp=""/>
<constraint field="continent" desc="" exp=""/>
<constraint field="region_un" desc="" exp=""/>
<constraint field="subregion" desc="" exp=""/>
<constraint field="region_wb" desc="" exp=""/>
<constraint field="name_len" desc="" exp=""/>
<constraint field="long_len" desc="" exp=""/>
<constraint field="abbrev_len" desc="" exp=""/>
<constraint field="tiny" desc="" exp=""/>
<constraint field="homepart" desc="" exp=""/>
</constraintExpressions>
<attributeactions>
<defaultAction key="Canvas" value="{00000000-0000-0000-0000-000000000000}"/>
</attributeactions>
<attributetableconfig actionWidgetStyle="dropDown" sortOrder="0" sortExpression="">
<columns>
<column name="scalerank" type="field" hidden="0" width="-1"/>
<column name="featurecla" type="field" hidden="0" width="-1"/>
<column name="labelrank" type="field" hidden="0" width="-1"/>
<column name="sovereignt" type="field" hidden="0" width="-1"/>
<column name="sov_a3" type="field" hidden="0" width="-1"/>
<column name="adm0_dif" type="field" hidden="0" width="-1"/>
<column name="level" type="field" hidden="0" width="-1"/>
<column name="type" type="field" hidden="0" width="-1"/>
<column name="admin" type="field" hidden="0" width="-1"/>
<column name="adm0_a3" type="field" hidden="0" width="-1"/>
<column name="geou_dif" type="field" hidden="0" width="-1"/>
<column name="geounit" type="field" hidden="0" width="-1"/>
<column name="gu_a3" type="field" hidden="0" width="-1"/>
<column name="su_dif" type="field" hidden="0" width="-1"/>
<column name="subunit" type="field" hidden="0" width="-1"/>
<column name="su_a3" type="field" hidden="0" width="-1"/>
<column name="brk_diff" type="field" hidden="0" width="-1"/>
<column name="name" type="field" hidden="0" width="-1"/>
<column name="name_long" type="field" hidden="0" width="-1"/>
<column name="brk_a3" type="field" hidden="0" width="-1"/>
<column name="brk_name" type="field" hidden="0" width="-1"/>
<column name="brk_group" type="field" hidden="0" width="-1"/>
<column name="abbrev" type="field" hidden="0" width="-1"/>
<column name="postal" type="field" hidden="0" width="-1"/>
<column name="formal_en" type="field" hidden="0" width="-1"/>
<column name="formal_fr" type="field" hidden="0" width="-1"/>
<column name="note_adm0" type="field" hidden="0" width="-1"/>
<column name="note_brk" type="field" hidden="0" width="-1"/>
<column name="name_sort" type="field" hidden="0" width="-1"/>
<column name="name_alt" type="field" hidden="0" width="-1"/>
<column name="mapcolor7" type="field" hidden="0" width="-1"/>
<column name="mapcolor8" type="field" hidden="0" width="-1"/>
<column name="mapcolor9" type="field" hidden="0" width="-1"/>
<column name="mapcolor13" type="field" hidden="0" width="-1"/>
<column name="pop_est" type="field" hidden="0" width="-1"/>
<column name="gdp_md_est" type="field" hidden="0" width="-1"/>
<column name="pop_year" type="field" hidden="0" width="-1"/>
<column name="lastcensus" type="field" hidden="0" width="-1"/>
<column name="gdp_year" type="field" hidden="0" width="-1"/>
<column name="economy" type="field" hidden="0" width="-1"/>
<column name="income_grp" type="field" hidden="0" width="-1"/>
<column name="wikipedia" type="field" hidden="0" width="-1"/>
<column name="fips_10" type="field" hidden="0" width="-1"/>
<column name="iso_a2" type="field" hidden="0" width="-1"/>
<column name="iso_a3" type="field" hidden="0" width="-1"/>
<column name="iso_n3" type="field" hidden="0" width="-1"/>
<column name="un_a3" type="field" hidden="0" width="-1"/>
<column name="wb_a2" type="field" hidden="0" width="-1"/>
<column name="wb_a3" type="field" hidden="0" width="-1"/>
<column name="woe_id" type="field" hidden="0" width="-1"/>
<column name="adm0_a3_is" type="field" hidden="0" width="-1"/>
<column name="adm0_a3_us" type="field" hidden="0" width="-1"/>
<column name="adm0_a3_un" type="field" hidden="0" width="-1"/>
<column name="adm0_a3_wb" type="field" hidden="0" width="-1"/>
<column name="continent" type="field" hidden="0" width="-1"/>
<column name="region_un" type="field" hidden="0" width="-1"/>
<column name="subregion" type="field" hidden="0" width="-1"/>
<column name="region_wb" type="field" hidden="0" width="-1"/>
<column name="name_len" type="field" hidden="0" width="-1"/>
<column name="long_len" type="field" hidden="0" width="-1"/>
<column name="abbrev_len" type="field" hidden="0" width="-1"/>
<column name="tiny" type="field" hidden="0" width="-1"/>
<column name="homepart" type="field" hidden="0" width="-1"/>
<column type="actions" hidden="1" width="-1"/>
</columns>
</attributetableconfig>
<editform></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS forms can have a Python function that is called when the form is
opened.
Use this function to add extra logic to your forms.
Enter the name of the function in the "Python Init function"
field.
An example follows:
"""
from qgis.PyQt.QtWidgets import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<widgets/>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<expressionfields/>
<previewExpression>name</previewExpression>
<mapTip></mapTip>
<layerGeometryType>2</layerGeometryType>
</qgis>

View File

@ -0,0 +1,285 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="2.18.0" simplifyAlgorithm="0" minimumScale="0" maximumScale="1e+08" simplifyDrawingHints="0" minLabelScale="0" maxLabelScale="1e+08" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
<edittypes>
<edittype widgetv2type="TextEdit" name="ID">
<widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
</edittype>
<edittype widgetv2type="TextEdit" name="AUTHORITY">
<widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
</edittype>
<edittype widgetv2type="TextEdit" name="NAME">
<widgetv2config IsMultiline="0" fieldEditable="1" constraint="" UseHtml="0" labelOnTop="0" constraintDescription="" notNull="0"/>
</edittype>
</edittypes>
<renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
<symbols>
<symbol alpha="1" clip_to_extent="1" type="marker" name="0">
<layer pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="160,80,26,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0"/>
<prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="MM"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="5"/>
<prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="size_unit" v="MM"/>
<prop k="vertical_anchor_point" v="1"/>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale scalemethod="diameter"/>
</renderer-v2>
<labeling type="simple"/>
<customproperties>
<property key="embeddedWidgets/count" value="0"/>
<property key="labeling" value="pal"/>
<property key="labeling/addDirectionSymbol" value="false"/>
<property key="labeling/angleOffset" value="0"/>
<property key="labeling/blendMode" value="0"/>
<property key="labeling/bufferBlendMode" value="0"/>
<property key="labeling/bufferColorA" value="255"/>
<property key="labeling/bufferColorB" value="255"/>
<property key="labeling/bufferColorG" value="255"/>
<property key="labeling/bufferColorR" value="255"/>
<property key="labeling/bufferDraw" value="false"/>
<property key="labeling/bufferJoinStyle" value="128"/>
<property key="labeling/bufferNoFill" value="false"/>
<property key="labeling/bufferSize" value="1"/>
<property key="labeling/bufferSizeInMapUnits" value="false"/>
<property key="labeling/bufferSizeMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/bufferTransp" value="0"/>
<property key="labeling/centroidInside" value="false"/>
<property key="labeling/centroidWhole" value="false"/>
<property key="labeling/decimals" value="3"/>
<property key="labeling/displayAll" value="false"/>
<property key="labeling/dist" value="0"/>
<property key="labeling/distInMapUnits" value="false"/>
<property key="labeling/distMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/drawLabels" value="true"/>
<property key="labeling/enabled" value="true"/>
<property key="labeling/fieldName" value="NAME"/>
<property key="labeling/fitInPolygonOnly" value="false"/>
<property key="labeling/fontCapitals" value="0"/>
<property key="labeling/fontFamily" value="Liberation Mono"/>
<property key="labeling/fontItalic" value="true"/>
<property key="labeling/fontLetterSpacing" value="0"/>
<property key="labeling/fontLimitPixelSize" value="false"/>
<property key="labeling/fontMaxPixelSize" value="10000"/>
<property key="labeling/fontMinPixelSize" value="3"/>
<property key="labeling/fontSize" value="9"/>
<property key="labeling/fontSizeInMapUnits" value="false"/>
<property key="labeling/fontSizeMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/fontStrikeout" value="false"/>
<property key="labeling/fontUnderline" value="false"/>
<property key="labeling/fontWeight" value="75"/>
<property key="labeling/fontWordSpacing" value="0"/>
<property key="labeling/formatNumbers" value="false"/>
<property key="labeling/isExpression" value="false"/>
<property key="labeling/labelOffsetInMapUnits" value="true"/>
<property key="labeling/labelOffsetMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/labelPerPart" value="false"/>
<property key="labeling/leftDirectionSymbol" value="&lt;"/>
<property key="labeling/limitNumLabels" value="false"/>
<property key="labeling/maxCurvedCharAngleIn" value="25"/>
<property key="labeling/maxCurvedCharAngleOut" value="-25"/>
<property key="labeling/maxNumLabels" value="2000"/>
<property key="labeling/mergeLines" value="false"/>
<property key="labeling/minFeatureSize" value="0"/>
<property key="labeling/multilineAlign" value="3"/>
<property key="labeling/multilineHeight" value="1"/>
<property key="labeling/namedStyle" value="Regular"/>
<property key="labeling/obstacle" value="true"/>
<property key="labeling/obstacleFactor" value="1"/>
<property key="labeling/obstacleType" value="0"/>
<property key="labeling/offsetType" value="0"/>
<property key="labeling/placeDirectionSymbol" value="0"/>
<property key="labeling/placement" value="1"/>
<property key="labeling/placementFlags" value="10"/>
<property key="labeling/plussign" value="false"/>
<property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
<property key="labeling/preserveRotation" value="true"/>
<property key="labeling/previewBkgrdColor" value="#ffffff"/>
<property key="labeling/priority" value="5"/>
<property key="labeling/quadOffset" value="7"/>
<property key="labeling/repeatDistance" value="0"/>
<property key="labeling/repeatDistanceMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/repeatDistanceUnit" value="1"/>
<property key="labeling/reverseDirectionSymbol" value="false"/>
<property key="labeling/rightDirectionSymbol" value=">"/>
<property key="labeling/scaleMax" value="10000000"/>
<property key="labeling/scaleMin" value="1"/>
<property key="labeling/scaleVisibility" value="false"/>
<property key="labeling/shadowBlendMode" value="6"/>
<property key="labeling/shadowColorB" value="0"/>
<property key="labeling/shadowColorG" value="0"/>
<property key="labeling/shadowColorR" value="0"/>
<property key="labeling/shadowDraw" value="false"/>
<property key="labeling/shadowOffsetAngle" value="135"/>
<property key="labeling/shadowOffsetDist" value="1"/>
<property key="labeling/shadowOffsetGlobal" value="true"/>
<property key="labeling/shadowOffsetMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/shadowOffsetUnits" value="1"/>
<property key="labeling/shadowRadius" value="1.5"/>
<property key="labeling/shadowRadiusAlphaOnly" value="false"/>
<property key="labeling/shadowRadiusMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/shadowRadiusUnits" value="1"/>
<property key="labeling/shadowScale" value="100"/>
<property key="labeling/shadowTransparency" value="30"/>
<property key="labeling/shadowUnder" value="0"/>
<property key="labeling/shapeBlendMode" value="0"/>
<property key="labeling/shapeBorderColorA" value="255"/>
<property key="labeling/shapeBorderColorB" value="128"/>
<property key="labeling/shapeBorderColorG" value="128"/>
<property key="labeling/shapeBorderColorR" value="128"/>
<property key="labeling/shapeBorderWidth" value="0"/>
<property key="labeling/shapeBorderWidthMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/shapeBorderWidthUnits" value="1"/>
<property key="labeling/shapeDraw" value="false"/>
<property key="labeling/shapeFillColorA" value="255"/>
<property key="labeling/shapeFillColorB" value="255"/>
<property key="labeling/shapeFillColorG" value="255"/>
<property key="labeling/shapeFillColorR" value="255"/>
<property key="labeling/shapeJoinStyle" value="64"/>
<property key="labeling/shapeOffsetMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/shapeOffsetUnits" value="1"/>
<property key="labeling/shapeOffsetX" value="0"/>
<property key="labeling/shapeOffsetY" value="0"/>
<property key="labeling/shapeRadiiMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/shapeRadiiUnits" value="1"/>
<property key="labeling/shapeRadiiX" value="0"/>
<property key="labeling/shapeRadiiY" value="0"/>
<property key="labeling/shapeRotation" value="0"/>
<property key="labeling/shapeRotationType" value="0"/>
<property key="labeling/shapeSVGFile" value=""/>
<property key="labeling/shapeSizeMapUnitScale" value="0,0,0,0,0,0"/>
<property key="labeling/shapeSizeType" value="0"/>
<property key="labeling/shapeSizeUnits" value="1"/>
<property key="labeling/shapeSizeX" value="0"/>
<property key="labeling/shapeSizeY" value="0"/>
<property key="labeling/shapeTransparency" value="0"/>
<property key="labeling/shapeType" value="0"/>
<property key="labeling/substitutions" value="&lt;substitutions/>"/>
<property key="labeling/textColorA" value="255"/>
<property key="labeling/textColorB" value="0"/>
<property key="labeling/textColorG" value="0"/>
<property key="labeling/textColorR" value="0"/>
<property key="labeling/textTransp" value="0"/>
<property key="labeling/upsidedownLabels" value="0"/>
<property key="labeling/useSubstitutions" value="false"/>
<property key="labeling/wrapChar" value=""/>
<property key="labeling/xOffset" value="0"/>
<property key="labeling/yOffset" value="0"/>
<property key="labeling/zIndex" value="0"/>
<property key="variableNames" value="_fields_"/>
<property key="variableValues" value=""/>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerTransparency>0</layerTransparency>
<displayfield>NAME</displayfield>
<label>0</label>
<labelattributes>
<label fieldname="" text="Etichetta"/>
<family fieldname="" name="Liberation Mono"/>
<size fieldname="" units="pt" value="12"/>
<bold fieldname="" on="0"/>
<italic fieldname="" on="0"/>
<underline fieldname="" on="0"/>
<strikeout fieldname="" on="0"/>
<color fieldname="" red="0" blue="0" green="0"/>
<x fieldname=""/>
<y fieldname=""/>
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
<angle fieldname="" value="0" auto="0"/>
<alignment fieldname="" value="center"/>
<buffercolor fieldname="" red="255" blue="255" green="255"/>
<buffersize fieldname="" units="pt" value="1"/>
<bufferenabled fieldname="" on=""/>
<multilineenabled fieldname="" on=""/>
<selectedonly on=""/>
</labelattributes>
<SingleCategoryDiagramRenderer diagramType="Histogram" sizeLegend="0" attributeLegend="1">
<DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" sizeScale="0,0,0,0,0,0" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="0,0,0,0,0,0" sizeType="MM" lineSizeType="MM" minScaleDenominator="inf">
<fontProperties description="Liberation Mono,9,-1,5,50,0,0,0,0,0" style=""/>
</DiagramCategory>
<symbol alpha="1" clip_to_extent="1" type="marker" name="sizeSymbol">
<layer pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="255,0,0,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0"/>
<prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="MM"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="2"/>
<prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="size_unit" v="MM"/>
<prop k="vertical_anchor_point" v="1"/>
</layer>
</symbol>
</SingleCategoryDiagramRenderer>
<DiagramLayerSettings yPosColumn="-1" showColumn="-1" linePlacementFlags="10" placement="0" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
<annotationform></annotationform>
<aliases>
<alias field="ID" index="0" name=""/>
<alias field="AUTHORITY" index="1" name=""/>
<alias field="NAME" index="2" name=""/>
</aliases>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<attributeactions default="-1"/>
<attributetableconfig actionWidgetStyle="dropDown" sortExpression="" sortOrder="2359551">
<columns>
<column width="-1" hidden="0" type="field" name="ID"/>
<column width="-1" hidden="0" type="field" name="AUTHORITY"/>
<column width="-1" hidden="0" type="field" name="NAME"/>
<column width="-1" hidden="1" type="actions"/>
</columns>
</attributetableconfig>
<editform></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS forms can have a Python function that is called when the form is
opened.
Use this function to add extra logic to your forms.
Enter the name of the function in the "Python Init function"
field.
An example follows:
"""
from qgis.PyQt.QtWidgets import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<widgets/>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<layerGeometryType>0</layerGeometryType>
</qgis>