Skip to content

Commit

Permalink
[feature][symbology] Allow pen cap style to be set for ellipse marker…
Browse files Browse the repository at this point in the history
… symbol layers (#42289)
  • Loading branch information
nirvn committed Mar 17, 2021
1 parent 51339ef commit 09620ad
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 16 deletions.
30 changes: 30 additions & 0 deletions python/core/auto_generated/symbology/qgsellipsesymbollayer.sip.in
Expand Up @@ -75,6 +75,36 @@ Gets stroke join style.
Set stroke join style.

.. versionadded:: 2.16
%End

Qt::PenCapStyle penCapStyle() const;
%Docstring
Returns the marker's stroke cap style (e.g., flat, round, etc).

.. seealso:: :py:func:`setPenCapStyle`

.. seealso:: :py:func:`penJoinStyle`

.. seealso:: :py:func:`strokeColor`

.. seealso:: :py:func:`strokeStyle`

.. versionadded:: 3.20
%End

void setPenCapStyle( Qt::PenCapStyle style );
%Docstring
Sets the marker's stroke cap ``style`` (e.g., flat, round, etc).

.. seealso:: :py:func:`penCapStyle`

.. seealso:: :py:func:`penJoinStyle`

.. seealso:: :py:func:`setStrokeColor`

.. seealso:: :py:func:`setStrokeStyle`

.. versionadded:: 3.20
%End

void setStrokeWidth( double w );
Expand Down
56 changes: 43 additions & 13 deletions src/core/symbology/qgsellipsesymbollayer.cpp
Expand Up @@ -102,6 +102,10 @@ QgsSymbolLayer *QgsEllipseSymbolLayer::create( const QVariantMap &properties )
{
layer->setPenJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( properties[QStringLiteral( "joinstyle" )].toString() ) );
}
if ( properties.contains( QStringLiteral( "cap_style" ) ) )
{
layer->setPenCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( properties[QStringLiteral( "cap_style" )].toString() ) );
}
if ( properties.contains( QStringLiteral( "outline_width" ) ) )
{
layer->setStrokeWidth( properties[QStringLiteral( "outline_width" )].toDouble() );
Expand Down Expand Up @@ -179,9 +183,9 @@ void QgsEllipseSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext &
penColor.setAlphaF( penColor.alphaF() * context.opacity() );
mPen.setColor( penColor );

if ( mDataDefinedProperties.hasActiveProperties() )
bool ok;
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeWidth ) )
{
bool ok;
context.setOriginalValueVariable( mStrokeWidth );
QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyStrokeWidth, context.renderContext().expressionContext() );
if ( exprVal.isValid() )
Expand All @@ -194,44 +198,67 @@ void QgsEllipseSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext &
mSelPen.setWidthF( width );
}
}
}

if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeStyle ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle ) );
exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyStrokeStyle, context.renderContext().expressionContext() );
QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyStrokeStyle, context.renderContext().expressionContext() );
if ( exprVal.isValid() )
{
mPen.setStyle( QgsSymbolLayerUtils::decodePenStyle( exprVal.toString() ) );
mSelPen.setStyle( mPen.style() );
}
}

if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyJoinStyle ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle ) );
exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyJoinStyle, context.renderContext().expressionContext() );
QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyJoinStyle, context.renderContext().expressionContext() );
if ( exprVal.isValid() )
{
mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( exprVal.toString() ) );
mSelPen.setJoinStyle( mPen.joinStyle() );
}
}

if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyCapStyle ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePenCapStyle( mPenCapStyle ) );
QString style = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyCapStyle, context.renderContext().expressionContext(), QString(), &ok );
if ( ok )
{
mPen.setCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( style ) );
mSelPen.setCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( style ) );
}
}

if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyFillColor ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) );
QColor brushColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor );
brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
mBrush.setColor( brushColor );
}

if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeColor ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mStrokeColor ) );
QColor penColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mStrokeColor );
penColor.setAlphaF( penColor.alphaF() * context.opacity() );
mPen.setColor( penColor );
}

if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyName ) )
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyName ) )
{
QString symbolName = mSymbolName;
context.setOriginalValueVariable( mSymbolName );
QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyName, context.renderContext().expressionContext() );
if ( exprVal.isValid() )
{
QString symbolName = mSymbolName;
context.setOriginalValueVariable( mSymbolName );
exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyName, context.renderContext().expressionContext() );
if ( exprVal.isValid() )
{
symbolName = exprVal.toString();
}
preparePath( symbolName, context, &scaledWidth, &scaledHeight, context.feature() );
symbolName = exprVal.toString();
}
preparePath( symbolName, context, &scaledWidth, &scaledHeight, context.feature() );
}

//offset and rotation
Expand Down Expand Up @@ -321,6 +348,7 @@ void QgsEllipseSymbolLayer::startRender( QgsSymbolRenderContext &context )
mPen.setColor( mStrokeColor );
mPen.setStyle( mStrokeStyle );
mPen.setJoinStyle( mPenJoinStyle );
mPen.setCapStyle( mPenCapStyle );
mPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
mBrush.setColor( mColor );

Expand Down Expand Up @@ -353,6 +381,7 @@ QgsEllipseSymbolLayer *QgsEllipseSymbolLayer::clone() const
m->setOffsetMapUnitScale( mOffsetMapUnitScale );
m->setStrokeStyle( mStrokeStyle );
m->setPenJoinStyle( mPenJoinStyle );
m->setPenCapStyle( mPenCapStyle );
m->setStrokeWidth( mStrokeWidth );
m->setColor( color() );
m->setStrokeColor( mStrokeColor );
Expand Down Expand Up @@ -513,6 +542,7 @@ QVariantMap QgsEllipseSymbolLayer::properties() const
map[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
map[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
map[QStringLiteral( "joinstyle" )] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
map[QStringLiteral( "cap_style" )] = QgsSymbolLayerUtils::encodePenCapStyle( mPenCapStyle );
map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
map[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
Expand Down
21 changes: 21 additions & 0 deletions src/core/symbology/qgsellipsesymbollayer.h
Expand Up @@ -75,6 +75,26 @@ class CORE_EXPORT QgsEllipseSymbolLayer: public QgsMarkerSymbolLayer
*/
void setPenJoinStyle( Qt::PenJoinStyle style ) { mPenJoinStyle = style; }

/**
* Returns the marker's stroke cap style (e.g., flat, round, etc).
* \see setPenCapStyle()
* \see penJoinStyle()
* \see strokeColor()
* \see strokeStyle()
* \since QGIS 3.20
*/
Qt::PenCapStyle penCapStyle() const { return mPenCapStyle; }

/**
* Sets the marker's stroke cap \a style (e.g., flat, round, etc).
* \see penCapStyle()
* \see penJoinStyle()
* \see setStrokeColor()
* \see setStrokeStyle()
* \since QGIS 3.20
*/
void setPenCapStyle( Qt::PenCapStyle style ) { mPenCapStyle = style; }

void setStrokeWidth( double w ) { mStrokeWidth = w; }
double strokeWidth() const { return mStrokeWidth; }

Expand Down Expand Up @@ -156,6 +176,7 @@ class CORE_EXPORT QgsEllipseSymbolLayer: public QgsMarkerSymbolLayer
QColor mStrokeColor;
Qt::PenStyle mStrokeStyle = Qt::SolidLine;
Qt::PenJoinStyle mPenJoinStyle = DEFAULT_ELLIPSE_JOINSTYLE;
Qt::PenCapStyle mPenCapStyle = Qt::SquareCap;
double mStrokeWidth = 0;
QgsUnitTypes::RenderUnit mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
QgsMapUnitScale mStrokeWidthMapUnitScale;
Expand Down
10 changes: 10 additions & 0 deletions src/gui/symbology/qgsellipsesymbollayerwidget.cpp
Expand Up @@ -97,6 +97,7 @@ QgsEllipseSymbolLayerWidget::QgsEllipseSymbolLayerWidget( QgsVectorLayer *vl, QW
connect( spinOffsetX, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsEllipseSymbolLayerWidget::setOffset );
connect( spinOffsetY, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsEllipseSymbolLayerWidget::setOffset );
connect( cboJoinStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEllipseSymbolLayerWidget::penJoinStyleChanged );
connect( cboCapStyle, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEllipseSymbolLayerWidget::penCapStyleChanged );
}

void QgsEllipseSymbolLayerWidget::setSymbolLayer( QgsSymbolLayer *layer )
Expand Down Expand Up @@ -137,6 +138,7 @@ void QgsEllipseSymbolLayerWidget::setSymbolLayer( QgsSymbolLayer *layer )
mHorizontalAnchorComboBox->setCurrentIndex( mLayer->horizontalAnchorPoint() );
mVerticalAnchorComboBox->setCurrentIndex( mLayer->verticalAnchorPoint() );
cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
cboCapStyle->setPenCapStyle( mLayer->penCapStyle() );
blockComboSignals( false );

registerDataDefinedButton( mSymbolWidthDDBtn, QgsSymbolLayer::PropertyWidth );
Expand All @@ -147,6 +149,7 @@ void QgsEllipseSymbolLayerWidget::setSymbolLayer( QgsSymbolLayer *layer )
registerDataDefinedButton( mStrokeColorDDBtn, QgsSymbolLayer::PropertyStrokeColor );
registerDataDefinedButton( mStrokeStyleDDBtn, QgsSymbolLayer::PropertyStrokeStyle );
registerDataDefinedButton( mJoinStyleDDBtn, QgsSymbolLayer::PropertyJoinStyle );
registerDataDefinedButton( mCapStyleDDBtn, QgsSymbolLayer::PropertyCapStyle );
registerDataDefinedButton( mShapeDDBtn, QgsSymbolLayer::PropertyName );
registerDataDefinedButton( mOffsetDDBtn, QgsSymbolLayer::PropertyOffset );
registerDataDefinedButton( mHorizontalAnchorDDBtn, QgsSymbolLayer::PropertyHorizontalAnchor );
Expand Down Expand Up @@ -287,6 +290,12 @@ void QgsEllipseSymbolLayerWidget::penJoinStyleChanged()
emit changed();
}

void QgsEllipseSymbolLayerWidget::penCapStyleChanged()
{
mLayer->setPenCapStyle( cboCapStyle->penCapStyle() );
emit changed();
}

void QgsEllipseSymbolLayerWidget::blockComboSignals( bool block )
{
mSymbolWidthUnitWidget->blockSignals( block );
Expand All @@ -299,6 +308,7 @@ void QgsEllipseSymbolLayerWidget::blockComboSignals( bool block )
mSymbolHeightUnitWidget->blockSignals( block );
mOffsetUnitWidget->blockSignals( block );
cboJoinStyle->blockSignals( block );
cboCapStyle->blockSignals( block );
}

void QgsEllipseSymbolLayerWidget::mHorizontalAnchorComboBox_currentIndexChanged( int index )
Expand Down
1 change: 1 addition & 0 deletions src/gui/symbology/qgsellipsesymbollayerwidget.h
Expand Up @@ -73,6 +73,7 @@ class GUI_EXPORT QgsEllipseSymbolLayerWidget: public QgsSymbolLayerWidget, priva
void mVerticalAnchorComboBox_currentIndexChanged( int index );

void penJoinStyleChanged();
void penCapStyleChanged();

void setOffset();
};
Expand Down
27 changes: 27 additions & 0 deletions src/ui/symbollayer/widget_ellipse.ui
Expand Up @@ -219,6 +219,26 @@
</item>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cap style</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QgsPenCapStyleComboBox" name="cboCapStyle"/>
</item>
<item row="9" column="2">
<widget class="QgsPropertyOverrideButton" name="mCapStyleDDBtn">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
Expand Down Expand Up @@ -591,6 +611,11 @@
<extends>QComboBox</extends>
<header>qgspenstylecombobox.h</header>
</customwidget>
<customwidget>
<class>QgsPenCapStyleComboBox</class>
<extends>QComboBox</extends>
<header>qgspenstylecombobox.h</header>
</customwidget>
<customwidget>
<class>QgsPenStyleComboBox</class>
<extends>QComboBox</extends>
Expand All @@ -614,6 +639,8 @@
<tabstop>mStrokeWidthDDBtn</tabstop>
<tabstop>cboJoinStyle</tabstop>
<tabstop>mJoinStyleDDBtn</tabstop>
<tabstop>cboCapStyle</tabstop>
<tabstop>mCapStyleDDBtn</tabstop>
<tabstop>mRotationSpinBox</tabstop>
<tabstop>mRotationDDBtn</tabstop>
<tabstop>spinOffsetX</tabstop>
Expand Down
21 changes: 18 additions & 3 deletions tests/src/core/testqgsellipsemarker.cpp
Expand Up @@ -58,6 +58,7 @@ class TestQgsEllipseMarkerSymbol : public QObject
void ellipseMarkerSymbolBevelJoin();
void ellipseMarkerSymbolMiterJoin();
void ellipseMarkerSymbolRoundJoin();
void ellipseMarkerSymbolCapStyle();
void selected();
void bounds();
void opacityWithDataDefinedColor();
Expand Down Expand Up @@ -158,7 +159,7 @@ void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolSize()

void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolBevelJoin()
{
mReport += QLatin1String( "<h2>Ellipse marker symbol layer test</h2>\n" );
mReport += QLatin1String( "<h2>Ellipse marker bevel join style</h2>\n" );

mEllipseMarkerLayer->setFillColor( Qt::blue );
mEllipseMarkerLayer->setStrokeColor( Qt::black );
Expand All @@ -172,7 +173,7 @@ void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolBevelJoin()

void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolMiterJoin()
{
mReport += QLatin1String( "<h2>Ellipse marker symbol layer test</h2>\n" );
mReport += QLatin1String( "<h2>Ellipse marker miter join style</h2>\n" );

mEllipseMarkerLayer->setFillColor( Qt::blue );
mEllipseMarkerLayer->setStrokeColor( Qt::black );
Expand All @@ -186,7 +187,7 @@ void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolMiterJoin()

void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolRoundJoin()
{
mReport += QLatin1String( "<h2>Ellipse marker symbol layer test</h2>\n" );
mReport += QLatin1String( "<h2>Ellipse marker round join style</h2>\n" );

mEllipseMarkerLayer->setFillColor( Qt::blue );
mEllipseMarkerLayer->setStrokeColor( Qt::black );
Expand All @@ -198,6 +199,20 @@ void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolRoundJoin()
QVERIFY( imageCheck( "ellipsemarker_roundjoin" ) );
}

void TestQgsEllipseMarkerSymbol::ellipseMarkerSymbolCapStyle()
{
mReport += QLatin1String( "<h2>Ellipse marker round cap style</h2>\n" );

mEllipseMarkerLayer->setColor( Qt::blue );
mEllipseMarkerLayer->setStrokeColor( Qt::black );
mEllipseMarkerLayer->setSymbolName( QStringLiteral( "cross" ) );
mEllipseMarkerLayer->setSymbolWidth( 35 );
mEllipseMarkerLayer->setSymbolHeight( 15 );
mEllipseMarkerLayer->setStrokeWidth( 3 );
mEllipseMarkerLayer->setPenCapStyle( Qt::RoundCap );
QVERIFY( imageCheck( "ellipsemarker_roundcap" ) );
}

void TestQgsEllipseMarkerSymbol::selected()
{
mEllipseMarkerLayer->setFillColor( Qt::blue );
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 09620ad

Please sign in to comment.