403 changes: 403 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.cpp

Large diffs are not rendered by default.

135 changes: 135 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,141 @@ class CORE_EXPORT QgsSimpleFillSymbolLayerV2 : public QgsFillSymbolLayerV2
void applyDataDefinedSymbology( QgsSymbolV2RenderContext& context, QBrush& brush, QPen& pen, QPen& selPen );
};

class QgsVectorColorRampV2;

class CORE_EXPORT QgsGradientFillSymbolLayerV2 : public QgsFillSymbolLayerV2
{
public:

enum GradientColorType
{
SimpleTwoColor,
ColorRamp
};

enum GradientType
{
Linear,
Radial,
Conical
};

enum GradientCoordinateMode
{
Feature,
Viewport
};

enum GradientSpread
{
Pad,
Reflect,
Repeat
};

QgsGradientFillSymbolLayerV2( QColor color = DEFAULT_SIMPLEFILL_COLOR, QColor color2 = Qt::white,
GradientColorType gradientColorType = SimpleTwoColor, GradientType gradientType = Linear,
GradientCoordinateMode coordinateMode = Feature,
GradientSpread gradientSpread = Pad
);

virtual ~QgsGradientFillSymbolLayerV2();

// static stuff

static QgsSymbolLayerV2* create( const QgsStringMap& properties = QgsStringMap() );

// implemented from base classes

QString layerType() const;

void startRender( QgsSymbolV2RenderContext& context );

void stopRender( QgsSymbolV2RenderContext& context );

void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );

QgsStringMap properties() const;

QgsSymbolLayerV2* clone() const;

/**Type of gradient, eg linear or radial*/
GradientType gradientType() const { return mGradientType; };
void setGradientType( GradientType gradientType ) { mGradientType = gradientType; };

/**Gradient color mode, controls how gradient color stops are created*/
GradientColorType gradientColorType() const { return mGradientColorType; };
void setGradientColorType( GradientColorType gradientColorType ) { mGradientColorType = gradientColorType; };

/**Color ramp used for the gradient fill, only used if the gradient color type is set to ColorRamp*/
QgsVectorColorRampV2* colorRamp() { return mGradientRamp; };
void setColorRamp( QgsVectorColorRampV2* ramp );

/**Color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoColor*/
QColor color2() const { return mColor2; };
void setColor2( QColor color2 ) { mColor2 = color2; };

/**Coordinate mode for gradient. Controls how the gradient stops are positioned.*/
GradientCoordinateMode coordinateMode() const { return mCoordinateMode; };
void setCoordinateMode( GradientCoordinateMode coordinateMode ) { mCoordinateMode = coordinateMode; };

/**Gradient spread mode. Controls how the gradient behaves outside of the predefined stops*/
GradientSpread gradientSpread() const { return mGradientSpread; };
void setGradientSpread( GradientSpread gradientSpread ) { mGradientSpread = gradientSpread; };

/**Starting point of gradient fill, in the range [0,0] - [1,1]*/
void setReferencePoint1( QPointF referencePoint ) { mReferencePoint1 = referencePoint; };
QPointF referencePoint1() const { return mReferencePoint1; };

/**End point of gradient fill, in the range [0,0] - [1,1]*/
void setReferencePoint2( QPointF referencePoint ) { mReferencePoint2 = referencePoint; };
QPointF referencePoint2() const { return mReferencePoint2; };

/**Rotation angle for gradient fill. Can be used to rotate a gradient around its centre point*/
void setAngle( double angle ) { mAngle = angle; };
double angle() const { return mAngle; };

/**Offset for gradient fill*/
void setOffset( QPointF offset ) { mOffset = offset; };
QPointF offset() const { return mOffset; };

/**Units for gradient fill offset*/
void setOffsetUnit( QgsSymbolV2::OutputUnit unit ) { mOffsetUnit = unit; };
QgsSymbolV2::OutputUnit offsetUnit() const { return mOffsetUnit; };

protected:
QBrush mBrush;
QBrush mSelBrush;

GradientColorType mGradientColorType;
QColor mColor2;
QgsVectorColorRampV2* mGradientRamp;
GradientType mGradientType;
GradientCoordinateMode mCoordinateMode;
GradientSpread mGradientSpread;

QPointF mReferencePoint1;
QPointF mReferencePoint2;
double mAngle;

QPointF mOffset;
QgsSymbolV2::OutputUnit mOffsetUnit;

private:

//helper functions for data defined symbology
void applyDataDefinedSymbology( QgsSymbolV2RenderContext& context );

/**Applies the gradient to a brush*/
void applyGradient( const QgsSymbolV2RenderContext& context, QBrush& brush, const QColor& color, const QColor& color2,
const GradientColorType gradientColorType, QgsVectorColorRampV2 * gradientRamp, const GradientType gradientType,
const GradientCoordinateMode coordinateMode, const GradientSpread gradientSpread, const QPointF referencePoint1,
const QPointF referencePoint2, const double angle );

/**rotates a reference point by a specified angle around the point (0.5, 0.5)*/
QPointF rotateReferencePoint( const QPointF & refPoint, double angle );
};

/**Base class for polygon renderers generating texture images*/
class CORE_EXPORT QgsImageFillSymbolLayer: public QgsFillSymbolLayerV2
{
Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ QgsSymbolLayerV2Registry::QgsSymbolLayerV2Registry()

addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SimpleFill", QObject::tr( "Simple fill" ), QgsSymbolV2::Fill,
QgsSimpleFillSymbolLayerV2::create, QgsSimpleFillSymbolLayerV2::createFromSld ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "GradientFill", QObject::tr( "Gradient fill" ), QgsSymbolV2::Fill,
QgsGradientFillSymbolLayerV2::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SVGFill", QObject::tr( "SVG fill" ), QgsSymbolV2::Fill,
QgsSVGFillSymbolLayer::create, QgsSVGFillSymbolLayer::createFromSld ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "CentroidFill", QObject::tr( "Centroid fill" ), QgsSymbolV2::Fill,
Expand Down
14 changes: 14 additions & 0 deletions src/core/symbology-ng/qgsvectorcolorrampv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,20 @@ void QgsVectorGradientColorRampV2::convertToDiscrete( bool discrete )
mDiscrete = discrete;
}

void QgsVectorGradientColorRampV2::addStopsToGradient( QGradient* gradient )
{
//copy color ramp stops to a QGradient
gradient->setColorAt( 0, mColor1 );
gradient->setColorAt( 1, mColor2 );

for ( QgsGradientStopsList::const_iterator it = mStops.begin();
it != mStops.end(); ++it )
{
gradient->setColorAt( it->offset , it->color );
}
}


//////////////


Expand Down
5 changes: 5 additions & 0 deletions src/core/symbology-ng/qgsvectorcolorrampv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define QGSVECTORCOLORRAMPV2_H

#include <QColor>
#include <QGradient>

#include "qgssymbollayerv2.h" // for QgsStringMap
#include "qgslogger.h"
Expand Down Expand Up @@ -91,6 +92,10 @@ class CORE_EXPORT QgsVectorGradientColorRampV2 : public QgsVectorColorRampV2
QgsStringMap info() const { return mInfo; }
void setInfo( const QgsStringMap& info ) { mInfo = info; }

/**copy color ramp stops to a QGradient
* @note added in 2.1 */
void addStopsToGradient( QGradient* gradient );

protected:
QColor mColor1, mColor2;
bool mDiscrete;
Expand Down
19 changes: 15 additions & 4 deletions src/gui/symbology-ng/qgscolorrampcombobox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
QSize QgsColorRampComboBox::rampIconSize( 50, 16 );

QgsColorRampComboBox::QgsColorRampComboBox( QWidget *parent ) :
QComboBox( parent ), mStyle( NULL ), mSourceColorRamp( NULL )
QComboBox( parent ), mStyle( NULL ), mSourceColorRamp( NULL ), mShowGradientOnly( false )
{
}

Expand All @@ -44,10 +44,13 @@ void QgsColorRampComboBox::populate( QgsStyleV2* style )
for ( QStringList::iterator it = rampNames.begin(); it != rampNames.end(); ++it )
{
QgsVectorColorRampV2* ramp = style->colorRamp( *it );
QIcon icon = QgsSymbolLayerV2Utils::colorRampPreviewIcon( ramp, rampIconSize );

addItem( icon, *it );
if ( !mShowGradientOnly || ramp->type() == "gradient" )
{
QIcon icon = QgsSymbolLayerV2Utils::colorRampPreviewIcon( ramp, rampIconSize );

addItem( icon, *it );
}
delete ramp;
}

Expand Down Expand Up @@ -82,7 +85,15 @@ void QgsColorRampComboBox::colorRampChanged( int index )
return;

// last item: "new color ramp..."
QString rampName = QgsStyleV2ManagerDialog::addColorRampStatic( this, mStyle );
QString rampName;
if ( !mShowGradientOnly )
{
rampName = QgsStyleV2ManagerDialog::addColorRampStatic( this, mStyle );
}
else
{
rampName = QgsStyleV2ManagerDialog::addColorRampStatic( this, mStyle, "Gradient" );
}
if ( rampName.isEmpty() )
return;

Expand Down
6 changes: 6 additions & 0 deletions src/gui/symbology-ng/qgscolorrampcombobox.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ class GUI_EXPORT QgsColorRampComboBox : public QComboBox

static QSize rampIconSize;

void setShowGradientOnly( bool gradientOnly ) { mShowGradientOnly = gradientOnly; };

public slots:
void colorRampChanged( int index );

protected:
QgsStyleV2* mStyle;
QgsVectorColorRampV2* mSourceColorRamp; // owns the copy

private:
bool mShowGradientOnly;

};

#endif // QGSCOLORRAMPCOMBOBOX_H
17 changes: 17 additions & 0 deletions src/gui/symbology-ng/qgsdatadefinedsymboldialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,20 @@ QString QgsDataDefinedSymbolDialog::verticalAnchorHelpText()
{
return tr( "'top'|'center'|'bottom'" );
}

QString QgsDataDefinedSymbolDialog::gradientTypeHelpText()
{
return tr( "'linear'|'radial'|'conical'" );
}

QString QgsDataDefinedSymbolDialog::gradientCoordModeHelpText()
{
return tr( "'feature'|'viewport'" );
}

QString QgsDataDefinedSymbolDialog::gradientSpreadHelpText()
{
return tr( "'pad'|'repeat'|'reflect'" );
}


3 changes: 3 additions & 0 deletions src/gui/symbology-ng/qgsdatadefinedsymboldialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class GUI_EXPORT QgsDataDefinedSymbolDialog: public QDialog, private Ui::QgsData
static QString fileNameHelpText();
static QString horizontalAnchorHelpText();
static QString verticalAnchorHelpText();
static QString gradientTypeHelpText();
static QString gradientCoordModeHelpText();
static QString gradientSpreadHelpText();

private slots:
void expressionButtonClicked();
Expand Down
1 change: 1 addition & 0 deletions src/gui/symbology-ng/qgslayerpropertieswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static void _initWidgetFunctions()
_initWidgetFunction( "VectorField", QgsVectorFieldSymbolLayerWidget::create );

_initWidgetFunction( "SimpleFill", QgsSimpleFillSymbolLayerV2Widget::create );
_initWidgetFunction( "GradientFill", QgsGradientFillSymbolLayerV2Widget::create );
_initWidgetFunction( "SVGFill", QgsSVGFillSymbolLayerWidget::create );
_initWidgetFunction( "CentroidFill", QgsCentroidFillSymbolLayerV2Widget::create );
_initWidgetFunction( "LinePatternFill", QgsLinePatternFillSymbolLayerWidget::create );
Expand Down
295 changes: 295 additions & 0 deletions src/gui/symbology-ng/qgssymbollayerv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,301 @@ void QgsSimpleFillSymbolLayerV2Widget::on_mDataDefinedPropertiesButton_clicked()

///////////

QgsGradientFillSymbolLayerV2Widget::QgsGradientFillSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent )
: QgsSymbolLayerV2Widget( parent, vl )
{
mLayer = NULL;

setupUi( this );

cboGradientColorRamp->setShowGradientOnly( true );
cboGradientColorRamp->populate( QgsStyleV2::defaultStyle() );

connect( btnChangeColor, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor( const QColor& ) ) );
connect( btnChangeColor2, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor2( const QColor& ) ) );
connect( cboGradientColorRamp, SIGNAL( currentIndexChanged( int ) ) , this, SLOT( applyColorRamp() ) );
connect( cboGradientType, SIGNAL( currentIndexChanged( int ) ), this, SLOT( setGradientType( int ) ) );
connect( cboCoordinateMode, SIGNAL( currentIndexChanged( int ) ), this, SLOT( setCoordinateMode( int ) ) );
connect( cboGradientSpread, SIGNAL( currentIndexChanged( int ) ), this, SLOT( setGradientSpread( int ) ) );
connect( radioTwoColor, SIGNAL( toggled( bool ) ), this, SLOT( colorModeChanged() ) );
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( offsetChanged() ) );
connect( spinOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( offsetChanged() ) );
connect( spinRefPoint1X, SIGNAL( valueChanged( double ) ), this, SLOT( referencePointChanged() ) );
connect( spinRefPoint1Y, SIGNAL( valueChanged( double ) ), this, SLOT( referencePointChanged() ) );
connect( spinRefPoint2X, SIGNAL( valueChanged( double ) ), this, SLOT( referencePointChanged() ) );
connect( spinRefPoint2Y, SIGNAL( valueChanged( double ) ), this, SLOT( referencePointChanged() ) );
}

void QgsGradientFillSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
{
if ( layer->layerType() != "GradientFill" )
return;

// layer type is correct, we can do the cast
mLayer = static_cast<QgsGradientFillSymbolLayerV2*>( layer );

// set values
btnChangeColor->setColor( mLayer->color() );
btnChangeColor->setColorDialogOptions( QColorDialog::ShowAlphaChannel );
btnChangeColor2->setColor( mLayer->color2() );
btnChangeColor2->setColorDialogOptions( QColorDialog::ShowAlphaChannel );

if ( mLayer->gradientColorType() == QgsGradientFillSymbolLayerV2::SimpleTwoColor )
{
radioTwoColor->setChecked( true );
cboGradientColorRamp->setEnabled( false );
}
else
{
radioColorRamp->setChecked( true );
btnChangeColor->setEnabled( false );
btnChangeColor2->setEnabled( false );
}

// set source color ramp
if ( mLayer->colorRamp() )
{
cboGradientColorRamp->blockSignals( true );
cboGradientColorRamp->setSourceColorRamp( mLayer->colorRamp() );
cboGradientColorRamp->blockSignals( false );
}

cboGradientType->blockSignals( true );
switch ( mLayer->gradientType() )
{
case QgsGradientFillSymbolLayerV2::Linear:
cboGradientType->setCurrentIndex( 0 );
break;
case QgsGradientFillSymbolLayerV2::Radial:
cboGradientType->setCurrentIndex( 1 );
break;
case QgsGradientFillSymbolLayerV2::Conical:
cboGradientType->setCurrentIndex( 2 );
break;
}
cboGradientType->blockSignals( false );

cboCoordinateMode->blockSignals( true );
switch ( mLayer->coordinateMode() )
{
case QgsGradientFillSymbolLayerV2::Viewport:
cboCoordinateMode->setCurrentIndex( 1 );
break;
case QgsGradientFillSymbolLayerV2::Feature:
default:
cboCoordinateMode->setCurrentIndex( 0 );
break;
}
cboCoordinateMode->blockSignals( false );

cboGradientSpread->blockSignals( true );
switch ( mLayer->gradientSpread() )
{
case QgsGradientFillSymbolLayerV2::Pad:
cboGradientSpread->setCurrentIndex( 0 );
break;
case QgsGradientFillSymbolLayerV2::Repeat:
cboGradientSpread->setCurrentIndex( 1 );
break;
case QgsGradientFillSymbolLayerV2::Reflect:
cboGradientSpread->setCurrentIndex( 2 );
break;
}
cboGradientSpread->blockSignals( false );

spinRefPoint1X->blockSignals( true );
spinRefPoint1X->setValue( mLayer->referencePoint1().x() );
spinRefPoint1X->blockSignals( false );
spinRefPoint1Y->blockSignals( true );
spinRefPoint1Y->setValue( mLayer->referencePoint1().y() );
spinRefPoint1Y->blockSignals( false );
spinRefPoint2X->blockSignals( true );
spinRefPoint2X->setValue( mLayer->referencePoint2().x() );
spinRefPoint2X->blockSignals( false );
spinRefPoint2Y->blockSignals( true );
spinRefPoint2Y->setValue( mLayer->referencePoint2().y() );
spinRefPoint2Y->blockSignals( false );

spinOffsetX->blockSignals( true );
spinOffsetX->setValue( mLayer->offset().x() );
spinOffsetX->blockSignals( false );
spinOffsetY->blockSignals( true );
spinOffsetY->setValue( mLayer->offset().y() );
spinOffsetY->blockSignals( false );
mSpinAngle->blockSignals( true );
mSpinAngle->setValue( mLayer->angle() );
mSpinAngle->blockSignals( false );

mOffsetUnitComboBox->blockSignals( true );
mOffsetUnitComboBox->setCurrentIndex( mLayer->offsetUnit() );
mOffsetUnitComboBox->blockSignals( false );
}

QgsSymbolLayerV2* QgsGradientFillSymbolLayerV2Widget::symbolLayer()
{
return mLayer;
}

void QgsGradientFillSymbolLayerV2Widget::setColor( const QColor& color )
{
mLayer->setColor( color );
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::setColor2( const QColor& color )
{
mLayer->setColor2( color );
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::colorModeChanged()
{
if ( radioTwoColor->isChecked() )
{
mLayer->setGradientColorType( QgsGradientFillSymbolLayerV2::SimpleTwoColor );
}
else
{
mLayer->setGradientColorType( QgsGradientFillSymbolLayerV2::ColorRamp );
}
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::applyColorRamp()
{
QgsVectorColorRampV2* ramp = cboGradientColorRamp->currentColorRamp();
if ( ramp == NULL )
return;

mLayer->setColorRamp( ramp );
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::setGradientType( int index )
{
switch ( index )
{
case 0:
mLayer->setGradientType( QgsGradientFillSymbolLayerV2::Linear );
break;
case 1:
mLayer->setGradientType( QgsGradientFillSymbolLayerV2::Radial );
break;
case 2:
mLayer->setGradientType( QgsGradientFillSymbolLayerV2::Conical );
break;
}
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::setCoordinateMode( int index )
{

switch ( index )
{
case 0:
mLayer->setCoordinateMode( QgsGradientFillSymbolLayerV2::Feature );
break;
case 1:
mLayer->setCoordinateMode( QgsGradientFillSymbolLayerV2::Viewport );
break;
}

emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::setGradientSpread( int index )
{
switch ( index )
{
case 0:
mLayer->setGradientSpread( QgsGradientFillSymbolLayerV2::Pad );
break;
case 1:
mLayer->setGradientSpread( QgsGradientFillSymbolLayerV2::Repeat );
break;
case 2:
mLayer->setGradientSpread( QgsGradientFillSymbolLayerV2::Reflect );
break;
}

emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::offsetChanged()
{
mLayer->setOffset( QPointF( spinOffsetX->value(), spinOffsetY->value() ) );
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::referencePointChanged()
{
mLayer->setReferencePoint1( QPointF( spinRefPoint1X->value(), spinRefPoint1Y->value() ) );
mLayer->setReferencePoint2( QPointF( spinRefPoint2X->value(), spinRefPoint2Y->value() ) );
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::on_mSpinAngle_valueChanged( double value )
{
mLayer->setAngle( value );
emit changed();
}

void QgsGradientFillSymbolLayerV2Widget::on_mOffsetUnitComboBox_currentIndexChanged( int index )
{
if ( mLayer )
{
mLayer->setOffsetUnit(( QgsSymbolV2::OutputUnit ) index );
emit changed();
}
}

void QgsGradientFillSymbolLayerV2Widget::on_mDataDefinedPropertiesButton_clicked()
{
if ( !mLayer )
{
return;
}

QList< QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry > dataDefinedProperties;
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "color", tr( "Color" ), mLayer->dataDefinedPropertyString( "color" ), QgsDataDefinedSymbolDialog::colorHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "color2", tr( "Color 2" ), mLayer->dataDefinedPropertyString( "color2" ), QgsDataDefinedSymbolDialog::colorHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "angle", tr( "Angle" ), mLayer->dataDefinedPropertyString( "angle" ),
QgsDataDefinedSymbolDialog::doubleHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "gradient_type", tr( "Gradient type" ), mLayer->dataDefinedPropertyString( "gradient_type" ), QgsDataDefinedSymbolDialog::gradientTypeHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "coordinate_mode", tr( "Coordinate mode" ), mLayer->dataDefinedPropertyString( "coordinate_mode" ), QgsDataDefinedSymbolDialog::gradientCoordModeHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "spread", tr( "Spread" ), mLayer->dataDefinedPropertyString( "spread" ),
QgsDataDefinedSymbolDialog::gradientSpreadHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "reference1_x", tr( "Reference Point 1 (x)" ), mLayer->dataDefinedPropertyString( "reference1_x" ),
QgsDataDefinedSymbolDialog::doubleHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "reference1_y", tr( "Reference Point 1 (y)" ), mLayer->dataDefinedPropertyString( "reference1_y" ),
QgsDataDefinedSymbolDialog::doubleHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "reference2_x", tr( "Reference Point 2 (x)" ), mLayer->dataDefinedPropertyString( "reference2_x" ),
QgsDataDefinedSymbolDialog::doubleHelpText() );
dataDefinedProperties << QgsDataDefinedSymbolDialog::DataDefinedSymbolEntry( "reference2_y", tr( "Reference Point 2 (y)" ), mLayer->dataDefinedPropertyString( "reference2_y" ),
QgsDataDefinedSymbolDialog::doubleHelpText() );

QgsDataDefinedSymbolDialog d( dataDefinedProperties, mVectorLayer );
if ( d.exec() == QDialog::Accepted )
{
//empty all existing properties first
mLayer->removeDataDefinedProperties();

QMap<QString, QString> properties = d.dataDefinedProperties();
QMap<QString, QString>::const_iterator it = properties.constBegin();
for ( ; it != properties.constEnd(); ++it )
{
if ( !it.value().isEmpty() )
{
mLayer->setDataDefinedProperty( it.key(), it.value() );
}
}
emit changed();
}
}

///////////

QgsMarkerLineSymbolLayerV2Widget::QgsMarkerLineSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent )
: QgsSymbolLayerV2Widget( parent, vl )
{
Expand Down
38 changes: 38 additions & 0 deletions src/gui/symbology-ng/qgssymbollayerv2widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,44 @@ class GUI_EXPORT QgsSimpleFillSymbolLayerV2Widget : public QgsSymbolLayerV2Widge
};


///////////

#include "ui_widget_gradientfill.h"

class QgsGradientFillSymbolLayerV2;

class GUI_EXPORT QgsGradientFillSymbolLayerV2Widget : public QgsSymbolLayerV2Widget, private Ui::WidgetGradientFill
{
Q_OBJECT

public:
QgsGradientFillSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent = NULL );

static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) { return new QgsGradientFillSymbolLayerV2Widget( vl ); }

// from base class
virtual void setSymbolLayer( QgsSymbolLayerV2* layer );
virtual QgsSymbolLayerV2* symbolLayer();

public slots:
void setColor( const QColor& color );
void setColor2( const QColor& color );
void applyColorRamp();
void setGradientType( int index );
void setCoordinateMode( int index );
void setGradientSpread( int index );
void offsetChanged();
void referencePointChanged();
void on_mOffsetUnitComboBox_currentIndexChanged( int index );
void on_mDataDefinedPropertiesButton_clicked();
void colorModeChanged();
void on_mSpinAngle_valueChanged( double value );

protected:
QgsGradientFillSymbolLayerV2* mLayer;
};


///////////

#include "ui_widget_markerline.h"
Expand Down
437 changes: 437 additions & 0 deletions src/ui/symbollayer/widget_gradientfill.ui

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions tests/src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,5 @@ ADD_QGIS_TEST(rectangletest testqgsrectangle.cpp)
ADD_QGIS_TEST(composerscalebartest testqgscomposerscalebar.cpp )
ADD_QGIS_TEST(ogcutilstest testqgsogcutils.cpp)
ADD_QGIS_TEST(vectorlayercachetest testqgsvectorlayercache.cpp )
ADD_QGIS_TEST(gradienttest testqgsgradients.cpp )

273 changes: 273 additions & 0 deletions tests/src/core/testqgsgradients.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
/***************************************************************************
testqgsgradients.cpp
--------------------------------------
Date : 20 Jan 2008
Copyright : (C) 2008 by Tim Sutton
Email : tim @ linfiniti.com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QtTest>
#include <QObject>
#include <QString>
#include <QStringList>
#include <QObject>
#include <QApplication>
#include <QFileInfo>
#include <QDir>
#include <QDesktopServices>

#include <iostream>
//qgis includes...
#include <qgsmaprenderer.h>
#include <qgsmaplayer.h>
#include <qgsvectorlayer.h>
#include <qgsapplication.h>
#include <qgsproviderregistry.h>
#include <qgsmaplayerregistry.h>
#include <qgssymbolv2.h>
#include <qgssinglesymbolrendererv2.h>
#include <qgsfillsymbollayerv2.h>
#include <qgsvectorcolorrampv2.h>
//qgis test includes
#include "qgsrenderchecker.h"

/** \ingroup UnitTests
* This is a unit test for gradient fill types.
*/
class TestQgsGradients: public QObject
{
Q_OBJECT;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init() {};// will be called before each testfunction is executed.
void cleanup() {};// will be called after every testfunction.

void gradientSymbol();
void gradientSymbolColors();
void gradientSymbolRamp();
void gradientSymbolRadial();
void gradientSymbolConical();
void gradientSymbolViewport();
void gradientSymbolReferencePoints();
void gradientSymbolReflectSpread();
void gradientSymbolRepeatSpread();
void gradientSymbolRotate();
void gradientSymbolFromQml();
private:
bool mTestHasError;
bool setQml( QString theType );
bool imageCheck( QString theType );
QgsMapRenderer * mpMapRenderer;
QgsVectorLayer * mpPolysLayer;
QgsGradientFillSymbolLayerV2* mGradientFill;
QgsFillSymbolV2* mFillSymbol;
QgsSingleSymbolRendererV2* mSymbolRenderer;
QString mTestDataDir;
QString mReport;
};


void TestQgsGradients::initTestCase()
{
mTestHasError = false;
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
QgsApplication::showSettings();

//create some objects that will be used in all tests...
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
mTestDataDir = myDataDir + QDir::separator();

//
//create a poly layer that will be used in all tests...
//
QString myPolysFileName = mTestDataDir + "polys.shp";
QFileInfo myPolyFileInfo( myPolysFileName );
mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(),
myPolyFileInfo.completeBaseName(), "ogr" );
// Register the layer with the registry
QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << mpPolysLayer );

//setup gradient fill
mGradientFill = new QgsGradientFillSymbolLayerV2();
mFillSymbol = new QgsFillSymbolV2();
mFillSymbol->changeSymbolLayer( 0, mGradientFill );
mSymbolRenderer = new QgsSingleSymbolRendererV2( mFillSymbol );
mpPolysLayer->setRendererV2( mSymbolRenderer );

// We only need maprender instead of mapcanvas
// since maprender does not require a qui
// and is more light weight
//
mpMapRenderer = new QgsMapRenderer();
QStringList myLayers;
myLayers << mpPolysLayer->id();
mpMapRenderer->setLayerSet( myLayers );
mReport += "<h1>Gradient Renderer Tests</h1>\n";

}
void TestQgsGradients::cleanupTestCase()
{
QString myReportFile = QDir::tempPath() + QDir::separator() + "qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
}

void TestQgsGradients::gradientSymbol()
{
mReport += "<h2>Gradient symbol renderer test</h2>\n";
mGradientFill->setColor( QColor( "red" ) );
mGradientFill->setColor2( QColor( "blue" ) );
mGradientFill->setGradientType( QgsGradientFillSymbolLayerV2::Linear );
mGradientFill->setGradientColorType( QgsGradientFillSymbolLayerV2::SimpleTwoColor );
mGradientFill->setCoordinateMode( QgsGradientFillSymbolLayerV2::Feature );
mGradientFill->setGradientSpread( QgsGradientFillSymbolLayerV2::Pad );
mGradientFill->setReferencePoint1( QPointF( 0, 0 ) );
mGradientFill->setReferencePoint2( QPointF( 1, 1 ) );
QVERIFY( imageCheck( "gradient" ) );
}

void TestQgsGradients::gradientSymbolColors()
{
mReport += "<h2>Gradient symbol renderer color test</h2>\n";
mGradientFill->setColor( QColor( "green" ) );
mGradientFill->setColor2( QColor( "white" ) );
QVERIFY( imageCheck( "gradient_colors" ) );
mGradientFill->setColor( QColor( "red" ) );
mGradientFill->setColor2( QColor( "blue" ) );
}

void TestQgsGradients::gradientSymbolRamp()
{
QgsVectorGradientColorRampV2* gradientRamp = new QgsVectorGradientColorRampV2( QColor( Qt::red ), QColor( Qt::blue ) );
QgsGradientStopsList stops;
stops.append( QgsGradientStop( 0.5, QColor( Qt::white ) ) );
gradientRamp->setStops( stops );

mGradientFill->setColorRamp( gradientRamp );
mGradientFill->setGradientColorType( QgsGradientFillSymbolLayerV2::ColorRamp );
QVERIFY( imageCheck( "gradient_ramp" ) );
mGradientFill->setGradientColorType( QgsGradientFillSymbolLayerV2::SimpleTwoColor );
}

void TestQgsGradients::gradientSymbolRadial()
{
mReport += "<h2>Gradient symbol renderer radial test</h2>\n";
mGradientFill->setGradientType( QgsGradientFillSymbolLayerV2::Radial );
QVERIFY( imageCheck( "gradient_radial" ) );
mGradientFill->setGradientType( QgsGradientFillSymbolLayerV2::Linear );
}

void TestQgsGradients::gradientSymbolConical()
{
mReport += "<h2>Gradient symbol renderer conical test</h2>\n";
mGradientFill->setGradientType( QgsGradientFillSymbolLayerV2::Conical );
mGradientFill->setReferencePoint1( QPointF( 0.5, 0.5 ) );
QVERIFY( imageCheck( "gradient_conical" ) );
mGradientFill->setReferencePoint1( QPointF( 0, 0 ) );
mGradientFill->setGradientType( QgsGradientFillSymbolLayerV2::Linear );
}

void TestQgsGradients::gradientSymbolViewport()
{
mReport += "<h2>Gradient symbol renderer viewport test</h2>\n";
mGradientFill->setCoordinateMode( QgsGradientFillSymbolLayerV2::Viewport );
QVERIFY( imageCheck( "gradient_viewport" ) );
mGradientFill->setCoordinateMode( QgsGradientFillSymbolLayerV2::Feature );
}

void TestQgsGradients::gradientSymbolReferencePoints()
{
mReport += "<h2>Gradient symbol renderer reference points test</h2>\n";
mGradientFill->setReferencePoint1( QPointF( 0.5, 0.4 ) );
mGradientFill->setReferencePoint2( QPointF( 0, 0.2 ) );
QVERIFY( imageCheck( "gradient_refpoints" ) );
mGradientFill->setReferencePoint1( QPointF( 0, 0 ) );
mGradientFill->setReferencePoint2( QPointF( 1, 1 ) );
}

void TestQgsGradients::gradientSymbolReflectSpread()
{
mReport += "<h2>Gradient symbol renderer reflect spread test</h2>\n";
mGradientFill->setReferencePoint2( QPointF( 0.5, 0.5 ) );
mGradientFill->setGradientSpread( QgsGradientFillSymbolLayerV2::Reflect );
QVERIFY( imageCheck( "gradient_reflect" ) );
mGradientFill->setGradientSpread( QgsGradientFillSymbolLayerV2::Pad );
mGradientFill->setReferencePoint2( QPointF( 1, 1 ) );
}

void TestQgsGradients::gradientSymbolRepeatSpread()
{
mReport += "<h2>Gradient symbol renderer repeat spread test</h2>\n";
mGradientFill->setReferencePoint2( QPointF( 0.5, 0.5 ) );
mGradientFill->setGradientSpread( QgsGradientFillSymbolLayerV2::Repeat );
QVERIFY( imageCheck( "gradient_repeat" ) );
mGradientFill->setGradientSpread( QgsGradientFillSymbolLayerV2::Pad );
mGradientFill->setReferencePoint2( QPointF( 1, 1 ) );
}

void TestQgsGradients::gradientSymbolRotate()
{
mReport += "<h2>Gradient symbol renderer rotate test</h2>\n";
mGradientFill->setAngle( 90 );
QVERIFY( imageCheck( "gradient_rotate" ) );
mGradientFill->setAngle( 0 );
}

void TestQgsGradients::gradientSymbolFromQml()
{
mReport += "<h2>Gradient symbol from QML test</h2>\n";
QVERIFY( setQml( "gradient" ) );
QVERIFY( imageCheck( "gradient_from_qml" ) );
}



//
// Private helper functions not called directly by CTest
//

bool TestQgsGradients::setQml( QString theType )
{
//load a qml style and apply to our layer
//the style will correspond to the renderer
//type we are testing
QString myFileName = mTestDataDir + "polys_" + theType + "_symbol.qml";
bool myStyleFlag = false;
QString error = mpPolysLayer->loadNamedStyle( myFileName, myStyleFlag );
if ( !myStyleFlag )
{
qDebug( "%s", error.toLocal8Bit().constData() );
}
return myStyleFlag;
}

bool TestQgsGradients::imageCheck( QString theTestType )
{
//use the QgsRenderChecker test utility class to
//ensure the rendered output matches our control image
mpMapRenderer->setExtent( mpPolysLayer->extent() );
QgsRenderChecker myChecker;
myChecker.setControlName( "expected_" + theTestType );
myChecker.setMapRenderer( mpMapRenderer );
bool myResultFlag = myChecker.runTest( theTestType );
mReport += myChecker.report();
return myResultFlag;
}

QTEST_MAIN( TestQgsGradients )
#include "moc_testqgsgradients.cxx"
82 changes: 82 additions & 0 deletions tests/src/python/test_qgssymbollayerv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@
import qgis
from PyQt4.QtCore import *
from PyQt4.QtXml import QDomDocument
from PyQt4.QtGui import QColor

from qgis.core import (
QgsCentroidFillSymbolLayerV2,
QgsEllipseSymbolLayerV2,
QgsFillSymbolLayerV2,
QgsFontMarkerSymbolLayerV2,
QgsGradientFillSymbolLayerV2,
QgsImageFillSymbolLayer,
QgsLinePatternFillSymbolLayer,
QgsLineSymbolLayerV2,
Expand All @@ -47,6 +49,8 @@
QgsSvgMarkerSymbolLayerV2,
QgsSymbolLayerV2,
QgsVectorFieldSymbolLayer,
QgsSymbolV2,
QgsVectorGradientColorRampV2
)
from utilities import (unitTestDataPath,
getQgisTestApp,
Expand Down Expand Up @@ -86,6 +90,14 @@ def testBinding(self):
mMessage = 'Expected "%s" got "%s"' % (mExpectedType, mType)
assert mExpectedType == mType, mMessage

try:
mType = type(QgsGradientFillSymbolLayerV2)
except:
mType = None
mExpectedType = pyqtWrapperType
mMessage = 'Expected "%s" got "%s"' % (mExpectedType, mType)
assert mExpectedType == mType, mMessage

try:
mType = type(QgsImageFillSymbolLayer)
except:
Expand Down Expand Up @@ -237,6 +249,76 @@ def testQgsSimpleFillSymbolLayerV2(self):
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

def testQgsGradientFillSymbolLayerV2(self):
'''Test setting and getting QgsGradientFillSymbolLayerV2 properties.
'''
mGradientLayer = QgsGradientFillSymbolLayerV2()

mExpectedValue = type(QgsGradientFillSymbolLayerV2())
mValue = type(mGradientLayer)
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QgsGradientFillSymbolLayerV2.Radial
mGradientLayer.setGradientType( mExpectedValue )
mValue = mGradientLayer.gradientType()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QgsGradientFillSymbolLayerV2.ColorRamp
mGradientLayer.setGradientColorType( mExpectedValue )
mValue = mGradientLayer.gradientColorType()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QColor('#55aaff')
mGradientLayer.setColor2( mExpectedValue )
mValue = mGradientLayer.color2()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QgsGradientFillSymbolLayerV2.Viewport
mGradientLayer.setCoordinateMode( mExpectedValue )
mValue = mGradientLayer.coordinateMode()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QgsGradientFillSymbolLayerV2.Reflect
mGradientLayer.setGradientSpread( mExpectedValue )
mValue = mGradientLayer.gradientSpread()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QPointF(0.5, 0.8)
mGradientLayer.setReferencePoint1( mExpectedValue )
mValue = mGradientLayer.referencePoint1()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QPointF(0.2, 0.4)
mGradientLayer.setReferencePoint2( mExpectedValue )
mValue = mGradientLayer.referencePoint2()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = 90
mGradientLayer.setAngle( mExpectedValue )
mValue = mGradientLayer.angle()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QPointF(10, 20)
mGradientLayer.setOffset( mExpectedValue )
mValue = mGradientLayer.offset()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

mExpectedValue = QgsSymbolV2.MapUnit
mGradientLayer.setOffsetUnit( mExpectedValue )
mValue = mGradientLayer.offsetUnit()
mMessage = 'Expected "%s" got "%s"' % (mExpectedValue,mValue)
assert mExpectedValue == mValue, mMessage

def testQgsCentroidFillSymbolLayerV2(self):
'''
Create a new style from a .sld file and match test
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
182 changes: 182 additions & 0 deletions tests/testdata/polys_gradient_symbol.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="2.1.0-Master" minimumScale="1" maximumScale="1e+08" minLabelScale="1" maxLabelScale="1e+08" hasScaleBasedVisibilityFlag="0" scaleBasedLabelVisibilityFlag="0">
<renderer-v2 symbollevels="0" type="singleSymbol">
<symbols>
<symbol alpha="1" type="fill" name="0">
<layer pass="0" class="GradientFill" locked="0">
<prop k="angle" v="0"/>
<prop k="color1" v="0,0,255,255"/>
<prop k="color2" v="0,255,0,255"/>
<prop k="color_type" v="0"/>
<prop k="coordinate_mode" v="0"/>
<prop k="discrete" v="0"/>
<prop k="gradient_color" v="52,60,170,255"/>
<prop k="gradient_color2" v="0,170,0,255"/>
<prop k="offset" v="0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="reference_point1" v="0,0"/>
<prop k="reference_point2" v="1,1"/>
<prop k="spread" v="0"/>
<prop k="type" v="0"/>
</layer>
</symbol>
</symbols>
<rotation field=""/>
<sizescale field="" scalemethod="area"/>
</renderer-v2>
<customproperties>
<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="64"/>
<property key="labeling/bufferNoFill" value="false"/>
<property key="labeling/bufferSize" value="1"/>
<property key="labeling/bufferSizeInMapUnits" value="false"/>
<property key="labeling/bufferTransp" value="0"/>
<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/enabled" value="false"/>
<property key="labeling/fieldName" value=""/>
<property key="labeling/fontBold" value="true"/>
<property key="labeling/fontCapitals" value="0"/>
<property key="labeling/fontFamily" value="Ubuntu"/>
<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="11"/>
<property key="labeling/fontSizeInMapUnits" value="false"/>
<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/labelPerPart" value="false"/>
<property key="labeling/leftDirectionSymbol" value="&lt;"/>
<property key="labeling/limitNumLabels" value="false"/>
<property key="labeling/maxCurvedCharAngleIn" value="20"/>
<property key="labeling/maxCurvedCharAngleOut" value="-20"/>
<property key="labeling/maxNumLabels" value="2000"/>
<property key="labeling/mergeLines" value="false"/>
<property key="labeling/minFeatureSize" value="0"/>
<property key="labeling/multilineAlign" value="0"/>
<property key="labeling/multilineHeight" value="1"/>
<property key="labeling/namedStyle" value="Bold Italic"/>
<property key="labeling/obstacle" value="true"/>
<property key="labeling/placeDirectionSymbol" value="0"/>
<property key="labeling/placement" value="0"/>
<property key="labeling/placementFlags" value="0"/>
<property key="labeling/plussign" value="false"/>
<property key="labeling/preserveRotation" value="true"/>
<property key="labeling/previewBkgrdColor" value="#ffffff"/>
<property key="labeling/priority" value="5"/>
<property key="labeling/quadOffset" value="4"/>
<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/shadowOffsetUnits" value="1"/>
<property key="labeling/shadowRadius" value="1.5"/>
<property key="labeling/shadowRadiusAlphaOnly" value="false"/>
<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/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/shapeOffsetUnits" value="1"/>
<property key="labeling/shapeOffsetX" value="0"/>
<property key="labeling/shapeOffsetY" value="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/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/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/wrapChar" value=""/>
<property key="labeling/xOffset" value="0"/>
<property key="labeling/yOffset" value="0"/>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerTransparency>0</layerTransparency>
<displayfield>Name</displayfield>
<label>0</label>
<labelattributes>
<label fieldname="" text="Label"/>
<family fieldname="" name="Lucida Grande"/>
<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>
<edittypes>
<edittype labelontop="0" editable="1" type="0" name="Name"/>
<edittype labelontop="0" editable="1" type="0" name="Value"/>
</edittypes>
<editform></editform>
<editforminit></editforminit>
<featformsuppress>0</featformsuppress>
<annotationform></annotationform>
<editorlayout>generatedlayout</editorlayout>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<attributeactions/>
</qgis>