Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE] Data defined symbol layer visibility
Adds a data defined override to control a symbol layer's
visibility. Allows users to disable drawing certain symbol layers
for matching features.
  • Loading branch information
nyalldawson committed Oct 18, 2016
1 parent b8c2e68 commit a6148de
Show file tree
Hide file tree
Showing 17 changed files with 262 additions and 41 deletions.
9 changes: 6 additions & 3 deletions python/core/symbology-ng/qgssymbollayer.sip
Expand Up @@ -277,16 +277,19 @@ class QgsSymbolLayer
*/ */
void setPaintEffect( QgsPaintEffect* effect /Transfer/); void setPaintEffect( QgsPaintEffect* effect /Transfer/);


protected:
QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked = false );

/** Prepares all data defined property expressions for evaluation. This should /** Prepares all data defined property expressions for evaluation. This should
* be called prior to evaluating data defined properties. * be called prior to evaluating data defined properties.
* @param context symbol render context * @param context symbol render context
* @note added in QGIS 2.12 * @note added in QGIS 2.12
*/ */
virtual void prepareExpressions( const QgsSymbolRenderContext& context ); virtual void prepareExpressions( const QgsSymbolRenderContext& context );


//! Data defined layer enabled string
static const QString EXPR_LAYER_ENABLED;

protected:
QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked = false );

/** Saves all data defined properties to a string map. /** Saves all data defined properties to a string map.
* @param stringMap destination string map * @param stringMap destination string map
* @see restoreDataDefinedProperties * @see restoreDataDefinedProperties
Expand Down
2 changes: 1 addition & 1 deletion python/gui/symbology-ng/qgslayerpropertieswidget.sip
@@ -1,4 +1,4 @@
class QgsLayerPropertiesWidget : QgsPanelWidget class QgsLayerPropertiesWidget : QgsPanelWidget, QgsExpressionContextGenerator
{ {
%TypeHeaderCode %TypeHeaderCode
#include <qgslayerpropertieswidget.h> #include <qgslayerpropertieswidget.h>
Expand Down
1 change: 0 additions & 1 deletion src/core/symbology-ng/qgsellipsesymbollayer.cpp
Expand Up @@ -353,7 +353,6 @@ void QgsEllipseSymbolLayer::startRender( QgsSymbolRenderContext& context )
mPen.setJoinStyle( mPenJoinStyle ); mPen.setJoinStyle( mPenJoinStyle );
mPen.setWidthF( QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) ); mPen.setWidthF( QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) );
mBrush.setColor( mColor ); mBrush.setColor( mColor );
prepareExpressions( context );
} }


void QgsEllipseSymbolLayer::stopRender( QgsSymbolRenderContext & ) void QgsEllipseSymbolLayer::stopRender( QgsSymbolRenderContext & )
Expand Down
16 changes: 4 additions & 12 deletions src/core/symbology-ng/qgsfillsymbollayer.cpp
Expand Up @@ -258,7 +258,6 @@ void QgsSimpleFillSymbolLayer::startRender( QgsSymbolRenderContext& context )
mPen.setStyle( mBorderStyle ); mPen.setStyle( mBorderStyle );
mPen.setWidthF( QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), mBorderWidth, mBorderWidthUnit, mBorderWidthMapUnitScale ) ); mPen.setWidthF( QgsSymbolLayerUtils::convertToPainterUnits( context.renderContext(), mBorderWidth, mBorderWidthUnit, mBorderWidthMapUnitScale ) );
mPen.setJoinStyle( mPenJoinStyle ); mPen.setJoinStyle( mPenJoinStyle );
prepareExpressions( context );
} }


void QgsSimpleFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsSimpleFillSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down Expand Up @@ -838,9 +837,6 @@ void QgsGradientFillSymbolLayer::startRender( QgsSymbolRenderContext& context )
QColor selColor = context.renderContext().selectionColor(); QColor selColor = context.renderContext().selectionColor();
if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() ); if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() );
mSelBrush = QBrush( selColor ); mSelBrush = QBrush( selColor );

//update mBrush to use a gradient fill with specified properties
prepareExpressions( context );
} }


void QgsGradientFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsGradientFillSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down Expand Up @@ -1132,8 +1128,6 @@ void QgsShapeburstFillSymbolLayer::startRender( QgsSymbolRenderContext& context
QColor selColor = context.renderContext().selectionColor(); QColor selColor = context.renderContext().selectionColor();
if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() ); if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() );
mSelBrush = QBrush( selColor ); mSelBrush = QBrush( selColor );

prepareExpressions( context );
} }


void QgsShapeburstFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsShapeburstFillSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down Expand Up @@ -1996,8 +1990,6 @@ void QgsSVGFillSymbolLayer::startRender( QgsSymbolRenderContext& context )
{ {
mOutline->startRender( context.renderContext(), context.fields() ); mOutline->startRender( context.renderContext(), context.fields() );
} }

prepareExpressions( context );
} }


void QgsSVGFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsSVGFillSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down Expand Up @@ -2831,8 +2823,6 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolRenderContext& context
{ {
mFillLineSymbol->startRender( context.renderContext(), context.fields() ); mFillLineSymbol->startRender( context.renderContext(), context.fields() );
} }

prepareExpressions( context );
} }


void QgsLinePatternFillSymbolLayer::stopRender( QgsSymbolRenderContext & ) void QgsLinePatternFillSymbolLayer::stopRender( QgsSymbolRenderContext & )
Expand Down Expand Up @@ -3257,7 +3247,6 @@ void QgsPointPatternFillSymbolLayer::startRender( QgsSymbolRenderContext& contex
{ {
mOutline->startRender( context.renderContext(), context.fields() ); mOutline->startRender( context.renderContext(), context.fields() );
} }
prepareExpressions( context );
} }


void QgsPointPatternFillSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsPointPatternFillSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down Expand Up @@ -3451,6 +3440,8 @@ QgsSymbolLayer* QgsCentroidFillSymbolLayer::create( const QgsStringMap& properti
if ( properties.contains( "point_on_all_parts" ) ) if ( properties.contains( "point_on_all_parts" ) )
sl->setPointOnAllParts( properties["point_on_all_parts"].toInt() != 0 ); sl->setPointOnAllParts( properties["point_on_all_parts"].toInt() != 0 );


sl->restoreDataDefinedProperties( properties );

return sl; return sl;
} }


Expand Down Expand Up @@ -3533,6 +3524,7 @@ QgsStringMap QgsCentroidFillSymbolLayer::properties() const
QgsStringMap map; QgsStringMap map;
map["point_on_surface"] = QString::number( mPointOnSurface ); map["point_on_surface"] = QString::number( mPointOnSurface );
map["point_on_all_parts"] = QString::number( mPointOnAllParts ); map["point_on_all_parts"] = QString::number( mPointOnAllParts );
saveDataDefinedProperties( map );
return map; return map;
} }


Expand All @@ -3544,6 +3536,7 @@ QgsCentroidFillSymbolLayer* QgsCentroidFillSymbolLayer::clone() const
x->setSubSymbol( mMarker->clone() ); x->setSubSymbol( mMarker->clone() );
x->setPointOnSurface( mPointOnSurface ); x->setPointOnSurface( mPointOnSurface );
x->setPointOnAllParts( mPointOnAllParts ); x->setPointOnAllParts( mPointOnAllParts );
copyDataDefinedProperties( x );
copyPaintEffect( x ); copyPaintEffect( x );
return x; return x;
} }
Expand Down Expand Up @@ -3760,7 +3753,6 @@ void QgsRasterFillSymbolLayer::renderPolygon( const QPolygonF &points, QList<QPo


void QgsRasterFillSymbolLayer::startRender( QgsSymbolRenderContext &context ) void QgsRasterFillSymbolLayer::startRender( QgsSymbolRenderContext &context )
{ {
prepareExpressions( context );
applyPattern( mBrush, mImageFilePath, mWidth, mAlpha, context ); applyPattern( mBrush, mImageFilePath, mWidth, mAlpha, context );
} }


Expand Down
7 changes: 6 additions & 1 deletion src/core/symbology-ng/qgsgeometrygeneratorsymbollayer.cpp
Expand Up @@ -44,6 +44,7 @@ QgsSymbolLayer* QgsGeometryGeneratorSymbolLayer::create( const QgsStringMap& pro
{ {
symbolLayer->setSubSymbol( QgsFillSymbol::createSimple( properties ) ); symbolLayer->setSubSymbol( QgsFillSymbol::createSimple( properties ) );
} }
symbolLayer->restoreDataDefinedProperties( properties );


return symbolLayer; return symbolLayer;
} }
Expand Down Expand Up @@ -117,6 +118,7 @@ QgsSymbolLayer* QgsGeometryGeneratorSymbolLayer::clone() const


clone->setSymbolType( mSymbolType ); clone->setSymbolType( mSymbolType );


copyDataDefinedProperties( clone );
copyPaintEffect( clone ); copyPaintEffect( clone );


return clone; return clone;
Expand All @@ -138,6 +140,7 @@ QgsStringMap QgsGeometryGeneratorSymbolLayer::properties() const
props.insert( "SymbolType", "Fill" ); props.insert( "SymbolType", "Fill" );
break; break;
} }
saveDataDefinedProperties( props );


return props; return props;
} }
Expand Down Expand Up @@ -180,7 +183,9 @@ bool QgsGeometryGeneratorSymbolLayer::setSubSymbol( QgsSymbol* symbol )


QSet<QString> QgsGeometryGeneratorSymbolLayer::usedAttributes() const QSet<QString> QgsGeometryGeneratorSymbolLayer::usedAttributes() const
{ {
return mSymbol->usedAttributes() + mExpression->referencedColumns(); return QgsSymbolLayer::usedAttributes()
+ mSymbol->usedAttributes()
+ mExpression->referencedColumns();
} }


bool QgsGeometryGeneratorSymbolLayer::isCompatibleWithSymbol( QgsSymbol* symbol ) const bool QgsGeometryGeneratorSymbolLayer::isCompatibleWithSymbol( QgsSymbol* symbol ) const
Expand Down
6 changes: 0 additions & 6 deletions src/core/symbology-ng/qgslinesymbollayer.cpp
Expand Up @@ -228,9 +228,6 @@ void QgsSimpleLineSymbolLayer::startRender( QgsSymbolRenderContext& context )
if ( ! selectionIsOpaque ) if ( ! selectionIsOpaque )
selColor.setAlphaF( context.alpha() ); selColor.setAlphaF( context.alpha() );
mSelPen.setColor( selColor ); mSelPen.setColor( selColor );

//prepare expressions for data defined properties
prepareExpressions( context );
} }


void QgsSimpleLineSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsSimpleLineSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down Expand Up @@ -815,9 +812,6 @@ void QgsMarkerLineSymbolLayer::startRender( QgsSymbolRenderContext& context )
mMarker->setRenderHints( hints ); mMarker->setRenderHints( hints );


mMarker->startRender( context.renderContext(), context.fields() ); mMarker->startRender( context.renderContext(), context.fields() );

//prepare expressions for data defined properties
prepareExpressions( context );
} }


void QgsMarkerLineSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsMarkerLineSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down
4 changes: 0 additions & 4 deletions src/core/symbology-ng/qgsmarkersymbollayer.cpp
Expand Up @@ -160,8 +160,6 @@ void QgsSimpleMarkerSymbolLayerBase::startRender( QgsSymbolRenderContext &contex
else else
mPath = transform.map( mPath ); mPath = transform.map( mPath );


prepareExpressions( context );

QgsMarkerSymbolLayer::startRender( context ); QgsMarkerSymbolLayer::startRender( context );
} }


Expand Down Expand Up @@ -1909,7 +1907,6 @@ void QgsSvgMarkerSymbolLayer::startRender( QgsSymbolRenderContext& context )
{ {
QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions
Q_UNUSED( context ); Q_UNUSED( context );
prepareExpressions( context );
} }


void QgsSvgMarkerSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsSvgMarkerSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down Expand Up @@ -2574,7 +2571,6 @@ void QgsFontMarkerSymbolLayer::startRender( QgsSymbolRenderContext& context )
mChrWidth = mFontMetrics->width( mChr ); mChrWidth = mFontMetrics->width( mChr );
mChrOffset = QPointF( mChrWidth / 2.0, -mFontMetrics->ascent() / 2.0 ); mChrOffset = QPointF( mChrWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
mOrigSize = mSize; // save in case the size would be data defined mOrigSize = mSize; // save in case the size would be data defined
prepareExpressions( context );
} }


void QgsFontMarkerSymbolLayer::stopRender( QgsSymbolRenderContext& context ) void QgsFontMarkerSymbolLayer::stopRender( QgsSymbolRenderContext& context )
Expand Down
33 changes: 33 additions & 0 deletions src/core/symbology-ng/qgssymbol.cpp
Expand Up @@ -400,6 +400,7 @@ void QgsSymbol::startRender( QgsRenderContext& context, const QgsFields& fields
if ( !layer->enabled() ) if ( !layer->enabled() )
continue; continue;


layer->prepareExpressions( symbolContext );
layer->startRender( symbolContext ); layer->startRender( symbolContext );
} }
} }
Expand Down Expand Up @@ -610,6 +611,14 @@ void QgsSymbol::renderUsingLayer( QgsSymbolLayer* layer, QgsSymbolRenderContext&
{ {
Q_ASSERT( layer->type() == Hybrid ); Q_ASSERT( layer->type() == Hybrid );


if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) )
{
bool ok = false;
bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool();
if ( ok && !enabled )
return;
}

QgsGeometryGeneratorSymbolLayer* generatorLayer = static_cast<QgsGeometryGeneratorSymbolLayer*>( layer ); QgsGeometryGeneratorSymbolLayer* generatorLayer = static_cast<QgsGeometryGeneratorSymbolLayer*>( layer );


QgsPaintEffect* effect = generatorLayer->paintEffect(); QgsPaintEffect* effect = generatorLayer->paintEffect();
Expand Down Expand Up @@ -1403,6 +1412,14 @@ void QgsMarkerSymbol::renderPointUsingLayer( QgsMarkerSymbolLayer* layer, QPoint
{ {
static QPointF nullPoint( 0, 0 ); static QPointF nullPoint( 0, 0 );


if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) )
{
bool ok = false;
bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool();
if ( ok && !enabled )
return;
}

QgsPaintEffect* effect = layer->paintEffect(); QgsPaintEffect* effect = layer->paintEffect();
if ( effect && effect->enabled() ) if ( effect && effect->enabled() )
{ {
Expand Down Expand Up @@ -1676,6 +1693,14 @@ void QgsLineSymbol::renderPolyline( const QPolygonF& points, const QgsFeature* f


void QgsLineSymbol::renderPolylineUsingLayer( QgsLineSymbolLayer *layer, const QPolygonF &points, QgsSymbolRenderContext &context ) void QgsLineSymbol::renderPolylineUsingLayer( QgsLineSymbolLayer *layer, const QPolygonF &points, QgsSymbolRenderContext &context )
{ {
if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) )
{
bool ok = false;
bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool();
if ( ok && !enabled )
return;
}

QgsPaintEffect* effect = layer->paintEffect(); QgsPaintEffect* effect = layer->paintEffect();
if ( effect && effect->enabled() ) if ( effect && effect->enabled() )
{ {
Expand Down Expand Up @@ -1748,6 +1773,14 @@ void QgsFillSymbol::renderPolygon( const QPolygonF& points, QList<QPolygonF>* ri


void QgsFillSymbol::renderPolygonUsingLayer( QgsSymbolLayer* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolRenderContext& context ) void QgsFillSymbol::renderPolygonUsingLayer( QgsSymbolLayer* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolRenderContext& context )
{ {
if ( layer->hasDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED ) )
{
bool ok = false;
bool enabled = layer->evaluateDataDefinedProperty( QgsSymbolLayer::EXPR_LAYER_ENABLED, context, QVariant(), &ok ).toBool();
if ( ok && !enabled )
return;
}

QgsSymbol::SymbolType layertype = layer->type(); QgsSymbol::SymbolType layertype = layer->type();


QgsPaintEffect* effect = layer->paintEffect(); QgsPaintEffect* effect = layer->paintEffect();
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgssymbollayer.cpp
Expand Up @@ -89,6 +89,7 @@ const QString QgsSymbolLayer::EXPR_INTERVAL( "interval" );
const QString QgsSymbolLayer::EXPR_OFFSET_ALONG_LINE( "offset_along_line" ); const QString QgsSymbolLayer::EXPR_OFFSET_ALONG_LINE( "offset_along_line" );
const QString QgsSymbolLayer::EXPR_HORIZONTAL_ANCHOR_POINT( "horizontal_anchor_point" ); const QString QgsSymbolLayer::EXPR_HORIZONTAL_ANCHOR_POINT( "horizontal_anchor_point" );
const QString QgsSymbolLayer::EXPR_VERTICAL_ANCHOR_POINT( "vertical_anchor_point" ); const QString QgsSymbolLayer::EXPR_VERTICAL_ANCHOR_POINT( "vertical_anchor_point" );
const QString QgsSymbolLayer::EXPR_LAYER_ENABLED( "enabled" );


QgsDataDefined *QgsSymbolLayer::getDataDefinedProperty( const QString &property ) const QgsDataDefined *QgsSymbolLayer::getDataDefinedProperty( const QString &property ) const
{ {
Expand Down
17 changes: 10 additions & 7 deletions src/core/symbology-ng/qgssymbollayer.h
Expand Up @@ -278,6 +278,16 @@ class CORE_EXPORT QgsSymbolLayer
*/ */
void setPaintEffect( QgsPaintEffect* effect ); void setPaintEffect( QgsPaintEffect* effect );


/** Prepares all data defined property expressions for evaluation. This should
* be called prior to evaluating data defined properties.
* @param context symbol render context
* @note added in QGIS 2.12
*/
virtual void prepareExpressions( const QgsSymbolRenderContext& context );

//! Data defined layer enabled string
static const QString EXPR_LAYER_ENABLED;

protected: protected:
QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked = false ); QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked = false );


Expand All @@ -299,13 +309,6 @@ class CORE_EXPORT QgsSymbolLayer
static const bool selectFillBorder = false; // Fill symbol layer also selects border symbology static const bool selectFillBorder = false; // Fill symbol layer also selects border symbology
static const bool selectFillStyle = false; // Fill symbol uses symbol layer style.. static const bool selectFillStyle = false; // Fill symbol uses symbol layer style..


/** Prepares all data defined property expressions for evaluation. This should
* be called prior to evaluating data defined properties.
* @param context symbol render context
* @note added in QGIS 2.12
*/
virtual void prepareExpressions( const QgsSymbolRenderContext& context );

/** Saves all data defined properties to a string map. /** Saves all data defined properties to a string map.
* @param stringMap destination string map * @param stringMap destination string map
* @see restoreDataDefinedProperties * @see restoreDataDefinedProperties
Expand Down

0 comments on commit a6148de

Please sign in to comment.