Skip to content

Commit

Permalink
[FEATURE] Data defined properties for font marker
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 21, 2015
1 parent 87f2370 commit 1e3b820
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 75 deletions.
3 changes: 3 additions & 0 deletions python/gui/symbology-ng/qgssymbollayerv2widget.sip
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class QgsSimpleMarkerSymbolLayerV2Widget : QgsSymbolLayerV2Widget

public:
QgsSimpleMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent /TransferThis/ = NULL );
~QgsSimpleMarkerSymbolLayerV2Widget();

static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) /Factory/;

Expand Down Expand Up @@ -226,6 +227,7 @@ class QgsSvgMarkerSymbolLayerV2Widget : QgsSymbolLayerV2Widget

public:
QgsSvgMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent /TransferThis/ = NULL );
~QgsSvgMarkerSymbolLayerV2Widget();

static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) /Factory/;

Expand Down Expand Up @@ -346,6 +348,7 @@ class QgsFontMarkerSymbolLayerV2Widget : QgsSymbolLayerV2Widget

public:
QgsFontMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent /TransferThis/ = NULL );
~QgsFontMarkerSymbolLayerV2Widget();

static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) /Factory/;

Expand Down
88 changes: 78 additions & 10 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,9 @@ QgsSymbolLayerV2* QgsFontMarkerSymbolLayerV2::create( const QgsStringMap& props
{
m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
}

m->restoreDataDefinedProperties( props );

return m;
}

Expand All @@ -1701,8 +1704,8 @@ void QgsFontMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context
mFont.setPixelSize( mSize * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mSizeUnit, mSizeMapUnitScale ) );
QFontMetrics fm( mFont );
mChrOffset = QPointF( fm.width( mChr ) / 2, -fm.ascent() / 2 );

mOrigSize = mSize; // save in case the size would be data defined
prepareExpressions( context.fields(), context.renderContext().rendererScale() );
}

void QgsFontMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
Expand All @@ -1716,29 +1719,89 @@ void QgsFontMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2R
if ( !p )
return;

QColor penColor = context.selected() ? context.renderContext().selectionColor() : mColor;
penColor.setAlphaF( mColor.alphaF() * context.alpha() );
QColor penColor = mColor;
bool ok;
if ( hasDataDefinedProperty( "color" ) )
{
QString colorString = evaluateDataDefinedProperty( "color", context.feature(), QVariant(), &ok ).toString();
if ( ok )
penColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
}
penColor = context.selected() ? context.renderContext().selectionColor() : penColor;
penColor.setAlphaF( penColor.alphaF() * context.alpha() );

p->setPen( penColor );
p->setFont( mFont );

p->save();

double scaledSize = mSize;

bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || hasDataDefinedProperty( "size" );

ok = true;
if ( hasDataDefinedProperty( "size" ) )
{
scaledSize = evaluateDataDefinedProperty( "size", context.feature(), mSize, &ok ).toDouble();
}

if ( hasDataDefinedSize && ok )
{
switch ( mScaleMethod )
{
case QgsSymbolV2::ScaleArea:
scaledSize = sqrt( scaledSize );
break;
case QgsSymbolV2::ScaleDiameter:
break;
}
}

//offset
double offsetX = 0;
double offsetY = 0;
markerOffset( context, offsetX, offsetY );
markerOffset( context, scaledSize, scaledSize , offsetX, offsetY );
QPointF outputOffset( offsetX, offsetY );
if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
outputOffset = _rotatedOffset( outputOffset, mAngle + mLineAngle );

double angle = mAngle + mLineAngle;
if ( hasDataDefinedProperty( "angle" ) )
{
angle = evaluateDataDefinedProperty( "angle", context.feature(), mAngle ).toDouble() + mLineAngle;
}

bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || hasDataDefinedProperty( "angle" );
if ( hasDataDefinedRotation )
{
// For non-point markers, "dataDefinedRotation" means following the
// shape (shape-data defined). For them, "field-data defined" does
// not work at all. TODO: if "field-data defined" ever gets implemented
// we'll need a way to distinguish here between the two, possibly
// using another flag in renderHints()
const QgsFeature* f = context.feature();
if ( f )
{
const QgsGeometry *g = f->constGeometry();
if ( g && g->type() == QGis::Point )
{
const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
angle += m2p.mapRotation();
}
}
}

if ( angle )
outputOffset = _rotatedOffset( outputOffset, angle );
p->translate( point + outputOffset );

if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale )
if ( !qgsDoubleNear( scaledSize, mOrigSize ) )
{
double s = mSize / mOrigSize;
double s = scaledSize / mOrigSize;
p->scale( s, s );
}

if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
p->rotate( mAngle + mLineAngle );
bool rotated = !qgsDoubleNear( angle, 0 );
if ( rotated )
p->rotate( angle );

p->drawText( -mChrOffset, mChr );
p->restore();
Expand All @@ -1759,6 +1822,10 @@ QgsStringMap QgsFontMarkerSymbolLayerV2::properties() const
props["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
props["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
props["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );

//data define properties
saveDataDefinedProperties( props );

return props;
}

Expand All @@ -1772,6 +1839,7 @@ QgsSymbolLayerV2* QgsFontMarkerSymbolLayerV2::clone() const
m->setSizeMapUnitScale( mSizeMapUnitScale );
m->setHorizontalAnchorPoint( mHorizontalAnchorPoint );
m->setVerticalAnchorPoint( mVerticalAnchorPoint );
copyDataDefinedProperties( m );
copyPaintEffect( m );
return m;
}
Expand Down
32 changes: 32 additions & 0 deletions src/gui/symbology-ng/qgssymbollayerv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2501,13 +2501,24 @@ QgsFontMarkerSymbolLayerV2Widget::QgsFontMarkerSymbolLayerV2Widget( const QgsVec
spinOffsetX->setClearValue( 0.0 );
spinOffsetY->setClearValue( 0.0 );

//make a temporary symbol for the size assistant preview
mAssistantPreviewSymbol = new QgsMarkerSymbolV2();

mSizeDDBtn->setAssistant( new QgsSizeScaleWidget( mVectorLayer, mAssistantPreviewSymbol ) );

connect( cboFont, SIGNAL( currentFontChanged( const QFont & ) ), this, SLOT( setFontFamily( const QFont& ) ) );
connect( spinSize, SIGNAL( valueChanged( double ) ), this, SLOT( setSize( double ) ) );
connect( btnColor, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColor( const QColor& ) ) );
connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setAngle( double ) ) );
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
connect( spinOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
connect( widgetChar, SIGNAL( characterSelected( const QChar & ) ), this, SLOT( setCharacter( const QChar & ) ) );
connect( this, SIGNAL( changed() ), this, SLOT( updateAssistantSymbol() ) );
}

QgsFontMarkerSymbolLayerV2Widget::~QgsFontMarkerSymbolLayerV2Widget()
{
delete mAssistantPreviewSymbol;
}

void QgsFontMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
Expand Down Expand Up @@ -2557,6 +2568,15 @@ void QgsFontMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
mVerticalAnchorComboBox->setCurrentIndex( mLayer->verticalAnchorPoint() );
mHorizontalAnchorComboBox->blockSignals( false );
mVerticalAnchorComboBox->blockSignals( false );

registerDataDefinedButton( mSizeDDBtn, "size", QgsDataDefinedButton::Double, QgsDataDefinedButton::doublePosDesc() );
registerDataDefinedButton( mRotationDDBtn, "angle", QgsDataDefinedButton::Double, QgsDataDefinedButton::double180RotDesc() );
registerDataDefinedButton( mColorDDBtn, "color", QgsDataDefinedButton::String, QgsDataDefinedButton::colorAlphaDesc() );
registerDataDefinedButton( mOffsetDDBtn, "offset", QgsDataDefinedButton::String, QgsDataDefinedButton::doubleXYDesc() );
registerDataDefinedButton( mHorizontalAnchorDDBtn, "horizontal_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::horizontalAnchorDesc() );
registerDataDefinedButton( mVerticalAnchorDDBtn, "vertical_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::verticalAnchorDesc() );

updateAssistantSymbol();
}

QgsSymbolLayerV2* QgsFontMarkerSymbolLayerV2Widget::symbolLayer()
Expand Down Expand Up @@ -2640,6 +2660,18 @@ void QgsFontMarkerSymbolLayerV2Widget::on_mVerticalAnchorComboBox_currentIndexCh
}
}

void QgsFontMarkerSymbolLayerV2Widget::updateAssistantSymbol()
{
for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
{
mAssistantPreviewSymbol->deleteSymbolLayer( i );
}
mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
QgsDataDefined* ddSize = mLayer->getDataDefinedProperty( "size" );
if ( ddSize )
mAssistantPreviewSymbol->setDataDefinedSize( *ddSize );
}

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


Expand Down
10 changes: 10 additions & 0 deletions src/gui/symbology-ng/qgssymbollayerv2widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,8 @@ class GUI_EXPORT QgsFontMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Widge
public:
QgsFontMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent = NULL );

~QgsFontMarkerSymbolLayerV2Widget();

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

// from base class
Expand All @@ -518,6 +520,14 @@ class GUI_EXPORT QgsFontMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Widge
QgsFontMarkerSymbolLayerV2* mLayer;
CharacterWidget* widgetChar;

private slots:

void updateAssistantSymbol();

private:

QgsMarkerSymbolV2* mAssistantPreviewSymbol;

};

//////////
Expand Down
Loading

0 comments on commit 1e3b820

Please sign in to comment.