Skip to content

Commit 6ad3537

Browse files
committed
[FEATURE] add outline join style settings to simple markers
(fixes #3797)
1 parent 99d5e42 commit 6ad3537

File tree

6 files changed

+121
-12
lines changed

6 files changed

+121
-12
lines changed

python/core/symbology-ng/qgsmarkersymbollayerv2.sip

+24-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,24 @@ class QgsSimpleMarkerSymbolLayerV2 : QgsMarkerSymbolLayerV2
55
%End
66

77
public:
8+
/** Constructor for QgsSimpleMarkerSymbolLayerV2.
9+
* @param name symbol name, should be one of "square", "rectangle", "diamond",
10+
* "pentagon", "triangle", "equilateral_triangle", "star", "regular_star", "arrow",
11+
* "circle", "cross", "cross2", "line", "x", "arrowhead", "filled_arrowhead"
12+
* @param color fill color for symbol
13+
* @param borderColor border color for symbol
14+
* @param size symbol size (in mm)
15+
* @param angle symbol rotation angle
16+
* @param scaleMethod scaling method for data defined scaling
17+
* @param penJoinStyle join style for outline pen
18+
*/
819
QgsSimpleMarkerSymbolLayerV2( const QString& name = DEFAULT_SIMPLEMARKER_NAME,
920
const QColor& color = DEFAULT_SIMPLEMARKER_COLOR,
1021
const QColor& borderColor = DEFAULT_SIMPLEMARKER_BORDERCOLOR,
1122
double size = DEFAULT_SIMPLEMARKER_SIZE,
1223
double angle = DEFAULT_SIMPLEMARKER_ANGLE,
13-
QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD );
24+
QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD,
25+
Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEFILL_JOINSTYLE );
1426

1527
// static stuff
1628

@@ -41,9 +53,20 @@ class QgsSimpleMarkerSymbolLayerV2 : QgsMarkerSymbolLayerV2
4153
QColor borderColor() const;
4254
void setBorderColor( const QColor& color );
4355

56+
/** Get outline join style.
57+
* @note added in 2.4 */
4458
Qt::PenStyle outlineStyle() const;
59+
/** Set outline join style.
60+
* @note added in 2.4 */
4561
void setOutlineStyle( Qt::PenStyle outlineStyle );
4662

63+
/** Get outline join style.
64+
* @note added in 2.16 */
65+
Qt::PenJoinStyle penJoinStyle() const;
66+
/** Set outline join style.
67+
* @note added in 2.16 */
68+
void setPenJoinStyle( Qt::PenJoinStyle style );
69+
4770
/** Get outline color.
4871
* @note added in 2.1 */
4972
QColor outlineColor() const;

src/core/symbology-ng/qgsmarkersymbollayerv2.cpp

+25-7
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ static void _fixQPictureDPI( QPainter* p )
4848

4949
//////
5050

51-
QgsSimpleMarkerSymbolLayerV2::QgsSimpleMarkerSymbolLayerV2( const QString& name, const QColor& color, const QColor& borderColor, double size, double angle, QgsSymbolV2::ScaleMethod scaleMethod )
52-
: mOutlineStyle( Qt::SolidLine ), mOutlineWidth( 0 ), mOutlineWidthUnit( QgsSymbolV2::MM )
51+
QgsSimpleMarkerSymbolLayerV2::QgsSimpleMarkerSymbolLayerV2( const QString& name, const QColor& color, const QColor& borderColor, double size, double angle, QgsSymbolV2::ScaleMethod scaleMethod,
52+
Qt::PenJoinStyle penJoinStyle )
53+
: mOutlineStyle( Qt::SolidLine ), mOutlineWidth( 0 ), mOutlineWidthUnit( QgsSymbolV2::MM ), mPenJoinStyle( penJoinStyle )
5354
{
5455
mName = name;
5556
mColor = color;
@@ -68,6 +69,7 @@ QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::create( const QgsStringMap& prop
6869
QString name = DEFAULT_SIMPLEMARKER_NAME;
6970
QColor color = DEFAULT_SIMPLEMARKER_COLOR;
7071
QColor borderColor = DEFAULT_SIMPLEMARKER_BORDERCOLOR;
72+
Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE;
7173
double size = DEFAULT_SIMPLEMARKER_SIZE;
7274
double angle = DEFAULT_SIMPLEMARKER_ANGLE;
7375
QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD;
@@ -89,14 +91,18 @@ QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::create( const QgsStringMap& prop
8991
{
9092
borderColor = QgsSymbolLayerV2Utils::decodeColor( props["line_color"] );
9193
}
94+
if ( props.contains( "joinstyle" ) )
95+
{
96+
penJoinStyle = QgsSymbolLayerV2Utils::decodePenJoinStyle( props["joinstyle"] );
97+
}
9298
if ( props.contains( "size" ) )
9399
size = props["size"].toDouble();
94100
if ( props.contains( "angle" ) )
95101
angle = props["angle"].toDouble();
96102
if ( props.contains( "scale_method" ) )
97103
scaleMethod = QgsSymbolLayerV2Utils::decodeScaleMethod( props["scale_method"] );
98104

99-
QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size, angle, scaleMethod );
105+
QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size, angle, scaleMethod, penJoinStyle );
100106
if ( props.contains( "offset" ) )
101107
m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
102108
if ( props.contains( "offset_unit" ) )
@@ -168,6 +174,7 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex
168174
mBrush = QBrush( brushColor );
169175
mPen = QPen( penColor );
170176
mPen.setStyle( mOutlineStyle );
177+
mPen.setJoinStyle( mPenJoinStyle );
171178
mPen.setWidthF( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) );
172179

173180
QColor selBrushColor = context.renderContext().selectionColor();
@@ -190,8 +197,8 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex
190197
// - drawing to screen (not printer)
191198
mUsingCache = !hasDataDefinedRotation && !hasDataDefinedSize && !context.renderContext().forceVectorOutput()
192199
&& !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_NAME ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR_BORDER )
193-
&& !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE ) &&
194-
!hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE );
200+
&& !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE )
201+
&& !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE );
195202

196203
// use either QPolygonF or QPainterPath for drawing
197204
// TODO: find out whether drawing directly doesn't bring overhead - if not, use it for all shapes
@@ -259,7 +266,7 @@ bool QgsSimpleMarkerSymbolLayerV2::prepareCache( QgsSymbolV2RenderContext& conte
259266
double scaledSize = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mSize, mSizeUnit, mSizeMapUnitScale );
260267

261268
// calculate necessary image size for the cache
262-
double pw = (( qgsDoubleNear( mPen.widthF(), 0.0 ) ? 1 : mPen.widthF() ) + 1 ) / 2 * 2; // make even (round up); handle cosmetic pen
269+
double pw = qRound((( qgsDoubleNear( mPen.widthF(), 0.0 ) ? 1 : mPen.widthF() * 4 ) + 1 ) ) / 2 * 2; // make even (round up); handle cosmetic pen
263270
int imageSize = ( static_cast< int >( scaledSize ) + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width
264271
double center = imageSize / 2.0;
265272

@@ -560,6 +567,16 @@ void QgsSimpleMarkerSymbolLayerV2::renderPoint( QPointF point, QgsSymbolV2Render
560567
mSelPen.setStyle( QgsSymbolLayerV2Utils::decodePenStyle( outlineStyle ) );
561568
}
562569
}
570+
if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE ) )
571+
{
572+
context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodePenJoinStyle( mPenJoinStyle ) );
573+
QString style = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE, context, QVariant(), &ok ).toString();
574+
if ( ok )
575+
{
576+
mPen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( style ) );
577+
mSelPen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( style ) );
578+
}
579+
}
563580

564581
p->setBrush( context.selected() ? mSelBrush : mBrush );
565582
p->setPen( context.selected() ? mSelPen : mPen );
@@ -664,6 +681,7 @@ QgsStringMap QgsSimpleMarkerSymbolLayerV2::properties() const
664681
map["outline_width"] = QString::number( mOutlineWidth );
665682
map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
666683
map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
684+
map["joinstyle"] = QgsSymbolLayerV2Utils::encodePenJoinStyle( mPenJoinStyle );
667685
map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
668686
map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
669687

@@ -675,7 +693,7 @@ QgsStringMap QgsSimpleMarkerSymbolLayerV2::properties() const
675693

676694
QgsSimpleMarkerSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::clone() const
677695
{
678-
QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( mName, mColor, mBorderColor, mSize, mAngle, mScaleMethod );
696+
QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( mName, mColor, mBorderColor, mSize, mAngle, mScaleMethod, mPenJoinStyle );
679697
m->setOffset( mOffset );
680698
m->setSizeUnit( mSizeUnit );
681699
m->setSizeMapUnitScale( mSizeMapUnitScale );

src/core/symbology-ng/qgsmarkersymbollayerv2.h

+26-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#define DEFAULT_SIMPLEMARKER_NAME "circle"
2323
#define DEFAULT_SIMPLEMARKER_COLOR QColor(255,0,0)
2424
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR QColor(0,0,0)
25+
#define DEFAULT_SIMPLEMARKER_JOINSTYLE Qt::BevelJoin
2526
#define DEFAULT_SIMPLEMARKER_SIZE DEFAULT_POINT_SIZE
2627
#define DEFAULT_SIMPLEMARKER_ANGLE 0
2728

@@ -34,12 +35,24 @@
3435
class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
3536
{
3637
public:
38+
/** Constructor for QgsSimpleMarkerSymbolLayerV2.
39+
* @param name symbol name, should be one of "square", "rectangle", "diamond",
40+
* "pentagon", "triangle", "equilateral_triangle", "star", "regular_star", "arrow",
41+
* "circle", "cross", "cross2", "line", "x", "arrowhead", "filled_arrowhead"
42+
* @param color fill color for symbol
43+
* @param borderColor border color for symbol
44+
* @param size symbol size (in mm)
45+
* @param angle symbol rotation angle
46+
* @param scaleMethod scaling method for data defined scaling
47+
* @param penJoinStyle join style for outline pen
48+
*/
3749
QgsSimpleMarkerSymbolLayerV2( const QString& name = DEFAULT_SIMPLEMARKER_NAME,
3850
const QColor& color = DEFAULT_SIMPLEMARKER_COLOR,
3951
const QColor& borderColor = DEFAULT_SIMPLEMARKER_BORDERCOLOR,
4052
double size = DEFAULT_SIMPLEMARKER_SIZE,
4153
double angle = DEFAULT_SIMPLEMARKER_ANGLE,
42-
QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD );
54+
QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD,
55+
Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE );
4356

4457
// static stuff
4558

@@ -70,9 +83,20 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
7083
QColor borderColor() const { return mBorderColor; }
7184
void setBorderColor( const QColor& color ) { mBorderColor = color; }
7285

86+
/** Get outline join style.
87+
* @note added in 2.4 */
7388
Qt::PenStyle outlineStyle() const { return mOutlineStyle; }
89+
/** Set outline join style.
90+
* @note added in 2.4 */
7491
void setOutlineStyle( Qt::PenStyle outlineStyle ) { mOutlineStyle = outlineStyle; }
7592

93+
/** Get outline join style.
94+
* @note added in 2.16 */
95+
Qt::PenJoinStyle penJoinStyle() const { return mPenJoinStyle; }
96+
/** Set outline join style.
97+
* @note added in 2.16 */
98+
void setPenJoinStyle( Qt::PenJoinStyle style ) { mPenJoinStyle = style; }
99+
76100
/** Get outline color.
77101
* @note added in 2.1 */
78102
QColor outlineColor() const override { return borderColor(); }
@@ -122,6 +146,7 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
122146
double mOutlineWidth;
123147
QgsSymbolV2::OutputUnit mOutlineWidthUnit;
124148
QgsMapUnitScale mOutlineWidthMapUnitScale;
149+
Qt::PenJoinStyle mPenJoinStyle;
125150
QPen mPen;
126151
QBrush mBrush;
127152
QPolygonF mPolygon;

src/gui/symbology-ng/qgssymbollayerv2widget.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ QgsSimpleMarkerSymbolLayerV2Widget::QgsSimpleMarkerSymbolLayerV2Widget( const Qg
455455
connect( lstNames, SIGNAL( currentRowChanged( int ) ), this, SLOT( setName() ) );
456456
connect( btnChangeColorBorder, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColorBorder( const QColor& ) ) );
457457
connect( btnChangeColorFill, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColorFill( const QColor& ) ) );
458+
connect( cboJoinStyle, SIGNAL( currentIndexChanged( int ) ), this, SLOT( penJoinStyleChanged() ) );
458459
connect( spinSize, SIGNAL( valueChanged( double ) ), this, SLOT( setSize() ) );
459460
connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setAngle() ) );
460461
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
@@ -503,6 +504,9 @@ void QgsSimpleMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer
503504
mOutlineWidthSpinBox->blockSignals( true );
504505
mOutlineWidthSpinBox->setValue( mLayer->outlineWidth() );
505506
mOutlineWidthSpinBox->blockSignals( false );
507+
cboJoinStyle->blockSignals( true );
508+
cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() );
509+
cboJoinStyle->blockSignals( false );
506510

507511
// without blocking signals the value gets changed because of slot setOffset()
508512
spinOffsetX->blockSignals( true );
@@ -542,6 +546,7 @@ void QgsSimpleMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer
542546
registerDataDefinedButton( mBorderColorDDBtn, "color_border", QgsDataDefinedButton::String, QgsDataDefinedButton::colorAlphaDesc() );
543547
registerDataDefinedButton( mOutlineWidthDDBtn, "outline_width", QgsDataDefinedButton::Double, QgsDataDefinedButton::doublePosDesc() );
544548
registerDataDefinedButton( mOutlineStyleDDBtn, "outline_style", QgsDataDefinedButton::String, QgsDataDefinedButton::lineStyleDesc() );
549+
registerDataDefinedButton( mJoinStyleDDBtn, "join_style", QgsDataDefinedButton::String, QgsDataDefinedButton::penJoinStyleDesc() );
545550
registerDataDefinedButton( mSizeDDBtn, "size", QgsDataDefinedButton::Double, QgsDataDefinedButton::doublePosDesc() );
546551
registerDataDefinedButton( mAngleDDBtn, "angle", QgsDataDefinedButton::Double, QgsDataDefinedButton::double180RotDesc() );
547552
registerDataDefinedButton( mOffsetDDBtn, "offset", QgsDataDefinedButton::String, QgsDataDefinedButton::doubleXYDesc() );
@@ -574,6 +579,12 @@ void QgsSimpleMarkerSymbolLayerV2Widget::setColorFill( const QColor& color )
574579
emit changed();
575580
}
576581

582+
void QgsSimpleMarkerSymbolLayerV2Widget::penJoinStyleChanged()
583+
{
584+
mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() );
585+
emit changed();
586+
}
587+
577588
void QgsSimpleMarkerSymbolLayerV2Widget::setSize()
578589
{
579590
mLayer->setSize( spinSize->value() );

src/gui/symbology-ng/qgssymbollayerv2widget.h

+1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ class GUI_EXPORT QgsSimpleMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Wid
201201
private slots:
202202

203203
void updateAssistantSymbol();
204+
void penJoinStyleChanged();
204205

205206
private:
206207

src/ui/symbollayer/widget_simplemarker.ui

+34-3
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
</item>
7171
</layout>
7272
</item>
73-
<item row="6" column="1">
73+
<item row="7" column="1">
7474
<layout class="QHBoxLayout" name="horizontalLayout_4">
7575
<item>
7676
<widget class="QgsDoubleSpinBox" name="mOutlineWidthSpinBox">
@@ -295,7 +295,7 @@
295295
</property>
296296
</widget>
297297
</item>
298-
<item row="6" column="0">
298+
<item row="7" column="0">
299299
<widget class="QLabel" name="mOutlineWidthLabel">
300300
<property name="text">
301301
<string>Outline width</string>
@@ -323,6 +323,30 @@
323323
</property>
324324
</widget>
325325
</item>
326+
<item row="6" column="0">
327+
<widget class="QLabel" name="label_8">
328+
<property name="text">
329+
<string>Join style</string>
330+
</property>
331+
<property name="alignment">
332+
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
333+
</property>
334+
</widget>
335+
</item>
336+
<item row="6" column="1">
337+
<layout class="QHBoxLayout" name="horizontalLayout_7">
338+
<item>
339+
<widget class="QgsPenJoinStyleComboBox" name="cboJoinStyle"/>
340+
</item>
341+
<item>
342+
<widget class="QgsDataDefinedButton" name="mJoinStyleDDBtn">
343+
<property name="text">
344+
<string>...</string>
345+
</property>
346+
</widget>
347+
</item>
348+
</layout>
349+
</item>
326350
<item row="0" column="1">
327351
<layout class="QHBoxLayout" name="horizontalLayout_2">
328352
<item>
@@ -491,6 +515,11 @@
491515
<header>qgsunitselectionwidget.h</header>
492516
<container>1</container>
493517
</customwidget>
518+
<customwidget>
519+
<class>QgsPenJoinStyleComboBox</class>
520+
<extends>QComboBox</extends>
521+
<header>qgspenstylecombobox.h</header>
522+
</customwidget>
494523
<customwidget>
495524
<class>QgsPenStyleComboBox</class>
496525
<extends>QComboBox</extends>
@@ -507,9 +536,11 @@
507536
<tabstop>mSizeUnitWidget</tabstop>
508537
<tabstop>mOutlineStyleComboBox</tabstop>
509538
<tabstop>mOutlineStyleDDBtn</tabstop>
539+
<tabstop>cboJoinStyle</tabstop>
540+
<tabstop>mJoinStyleDDBtn</tabstop>
510541
<tabstop>mOutlineWidthSpinBox</tabstop>
511542
<tabstop>mOutlineWidthDDBtn</tabstop>
512-
<tabstop>mOutlineWidthUnitWidget</tabstop>
543+
<tabstop>mOutlineWidthUnitWidget</tabstop>
513544
<tabstop>spinAngle</tabstop>
514545
<tabstop>mAngleDDBtn</tabstop>
515546
<tabstop>spinOffsetX</tabstop>

0 commit comments

Comments
 (0)