From 6ad353740399ac752da83a6d6d6c23fd3740d286 Mon Sep 17 00:00:00 2001 From: nirvn Date: Sat, 2 Apr 2016 11:17:33 +0700 Subject: [PATCH] [FEATURE] add outline join style settings to simple markers (fixes #3797) --- .../symbology-ng/qgsmarkersymbollayerv2.sip | 25 ++++++++++++- .../symbology-ng/qgsmarkersymbollayerv2.cpp | 32 ++++++++++++---- .../symbology-ng/qgsmarkersymbollayerv2.h | 27 +++++++++++++- .../symbology-ng/qgssymbollayerv2widget.cpp | 11 ++++++ src/gui/symbology-ng/qgssymbollayerv2widget.h | 1 + src/ui/symbollayer/widget_simplemarker.ui | 37 +++++++++++++++++-- 6 files changed, 121 insertions(+), 12 deletions(-) diff --git a/python/core/symbology-ng/qgsmarkersymbollayerv2.sip b/python/core/symbology-ng/qgsmarkersymbollayerv2.sip index 1aa110fd18c..c6a2abe5e42 100644 --- a/python/core/symbology-ng/qgsmarkersymbollayerv2.sip +++ b/python/core/symbology-ng/qgsmarkersymbollayerv2.sip @@ -5,12 +5,24 @@ class QgsSimpleMarkerSymbolLayerV2 : QgsMarkerSymbolLayerV2 %End public: + /** Constructor for QgsSimpleMarkerSymbolLayerV2. + * @param name symbol name, should be one of "square", "rectangle", "diamond", + * "pentagon", "triangle", "equilateral_triangle", "star", "regular_star", "arrow", + * "circle", "cross", "cross2", "line", "x", "arrowhead", "filled_arrowhead" + * @param color fill color for symbol + * @param borderColor border color for symbol + * @param size symbol size (in mm) + * @param angle symbol rotation angle + * @param scaleMethod scaling method for data defined scaling + * @param penJoinStyle join style for outline pen + */ QgsSimpleMarkerSymbolLayerV2( const QString& name = DEFAULT_SIMPLEMARKER_NAME, const QColor& color = DEFAULT_SIMPLEMARKER_COLOR, const QColor& borderColor = DEFAULT_SIMPLEMARKER_BORDERCOLOR, double size = DEFAULT_SIMPLEMARKER_SIZE, double angle = DEFAULT_SIMPLEMARKER_ANGLE, - QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD ); + QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD, + Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEFILL_JOINSTYLE ); // static stuff @@ -41,9 +53,20 @@ class QgsSimpleMarkerSymbolLayerV2 : QgsMarkerSymbolLayerV2 QColor borderColor() const; void setBorderColor( const QColor& color ); + /** Get outline join style. + * @note added in 2.4 */ Qt::PenStyle outlineStyle() const; + /** Set outline join style. + * @note added in 2.4 */ void setOutlineStyle( Qt::PenStyle outlineStyle ); + /** Get outline join style. + * @note added in 2.16 */ + Qt::PenJoinStyle penJoinStyle() const; + /** Set outline join style. + * @note added in 2.16 */ + void setPenJoinStyle( Qt::PenJoinStyle style ); + /** Get outline color. * @note added in 2.1 */ QColor outlineColor() const; diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index 4f849c4530f..91e2c08cb7f 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -48,8 +48,9 @@ static void _fixQPictureDPI( QPainter* p ) ////// -QgsSimpleMarkerSymbolLayerV2::QgsSimpleMarkerSymbolLayerV2( const QString& name, const QColor& color, const QColor& borderColor, double size, double angle, QgsSymbolV2::ScaleMethod scaleMethod ) - : mOutlineStyle( Qt::SolidLine ), mOutlineWidth( 0 ), mOutlineWidthUnit( QgsSymbolV2::MM ) +QgsSimpleMarkerSymbolLayerV2::QgsSimpleMarkerSymbolLayerV2( const QString& name, const QColor& color, const QColor& borderColor, double size, double angle, QgsSymbolV2::ScaleMethod scaleMethod, + Qt::PenJoinStyle penJoinStyle ) + : mOutlineStyle( Qt::SolidLine ), mOutlineWidth( 0 ), mOutlineWidthUnit( QgsSymbolV2::MM ), mPenJoinStyle( penJoinStyle ) { mName = name; mColor = color; @@ -68,6 +69,7 @@ QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::create( const QgsStringMap& prop QString name = DEFAULT_SIMPLEMARKER_NAME; QColor color = DEFAULT_SIMPLEMARKER_COLOR; QColor borderColor = DEFAULT_SIMPLEMARKER_BORDERCOLOR; + Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE; double size = DEFAULT_SIMPLEMARKER_SIZE; double angle = DEFAULT_SIMPLEMARKER_ANGLE; QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD; @@ -89,6 +91,10 @@ QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::create( const QgsStringMap& prop { borderColor = QgsSymbolLayerV2Utils::decodeColor( props["line_color"] ); } + if ( props.contains( "joinstyle" ) ) + { + penJoinStyle = QgsSymbolLayerV2Utils::decodePenJoinStyle( props["joinstyle"] ); + } if ( props.contains( "size" ) ) size = props["size"].toDouble(); if ( props.contains( "angle" ) ) @@ -96,7 +102,7 @@ QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::create( const QgsStringMap& prop if ( props.contains( "scale_method" ) ) scaleMethod = QgsSymbolLayerV2Utils::decodeScaleMethod( props["scale_method"] ); - QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size, angle, scaleMethod ); + QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size, angle, scaleMethod, penJoinStyle ); if ( props.contains( "offset" ) ) m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) ); if ( props.contains( "offset_unit" ) ) @@ -168,6 +174,7 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex mBrush = QBrush( brushColor ); mPen = QPen( penColor ); mPen.setStyle( mOutlineStyle ); + mPen.setJoinStyle( mPenJoinStyle ); mPen.setWidthF( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) ); QColor selBrushColor = context.renderContext().selectionColor(); @@ -190,8 +197,8 @@ void QgsSimpleMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& contex // - drawing to screen (not printer) mUsingCache = !hasDataDefinedRotation && !hasDataDefinedSize && !context.renderContext().forceVectorOutput() && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_NAME ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR_BORDER ) - && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE ) && - !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE ); + && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE ) + && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE ) && !hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE ); // use either QPolygonF or QPainterPath for drawing // 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 double scaledSize = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mSize, mSizeUnit, mSizeMapUnitScale ); // calculate necessary image size for the cache - double pw = (( qgsDoubleNear( mPen.widthF(), 0.0 ) ? 1 : mPen.widthF() ) + 1 ) / 2 * 2; // make even (round up); handle cosmetic pen + double pw = qRound((( qgsDoubleNear( mPen.widthF(), 0.0 ) ? 1 : mPen.widthF() * 4 ) + 1 ) ) / 2 * 2; // make even (round up); handle cosmetic pen int imageSize = ( static_cast< int >( scaledSize ) + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width double center = imageSize / 2.0; @@ -560,6 +567,16 @@ void QgsSimpleMarkerSymbolLayerV2::renderPoint( QPointF point, QgsSymbolV2Render mSelPen.setStyle( QgsSymbolLayerV2Utils::decodePenStyle( outlineStyle ) ); } } + if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE ) ) + { + context.setOriginalValueVariable( QgsSymbolLayerV2Utils::encodePenJoinStyle( mPenJoinStyle ) ); + QString style = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_JOIN_STYLE, context, QVariant(), &ok ).toString(); + if ( ok ) + { + mPen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( style ) ); + mSelPen.setJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( style ) ); + } + } p->setBrush( context.selected() ? mSelBrush : mBrush ); p->setPen( context.selected() ? mSelPen : mPen ); @@ -664,6 +681,7 @@ QgsStringMap QgsSimpleMarkerSymbolLayerV2::properties() const map["outline_width"] = QString::number( mOutlineWidth ); map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit ); map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale ); + map["joinstyle"] = QgsSymbolLayerV2Utils::encodePenJoinStyle( mPenJoinStyle ); map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint ); map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint ); @@ -675,7 +693,7 @@ QgsStringMap QgsSimpleMarkerSymbolLayerV2::properties() const QgsSimpleMarkerSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::clone() const { - QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( mName, mColor, mBorderColor, mSize, mAngle, mScaleMethod ); + QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( mName, mColor, mBorderColor, mSize, mAngle, mScaleMethod, mPenJoinStyle ); m->setOffset( mOffset ); m->setSizeUnit( mSizeUnit ); m->setSizeMapUnitScale( mSizeMapUnitScale ); diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index 76780a8d614..0229d5a6bf2 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -22,6 +22,7 @@ #define DEFAULT_SIMPLEMARKER_NAME "circle" #define DEFAULT_SIMPLEMARKER_COLOR QColor(255,0,0) #define DEFAULT_SIMPLEMARKER_BORDERCOLOR QColor(0,0,0) +#define DEFAULT_SIMPLEMARKER_JOINSTYLE Qt::BevelJoin #define DEFAULT_SIMPLEMARKER_SIZE DEFAULT_POINT_SIZE #define DEFAULT_SIMPLEMARKER_ANGLE 0 @@ -34,12 +35,24 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2 { public: + /** Constructor for QgsSimpleMarkerSymbolLayerV2. + * @param name symbol name, should be one of "square", "rectangle", "diamond", + * "pentagon", "triangle", "equilateral_triangle", "star", "regular_star", "arrow", + * "circle", "cross", "cross2", "line", "x", "arrowhead", "filled_arrowhead" + * @param color fill color for symbol + * @param borderColor border color for symbol + * @param size symbol size (in mm) + * @param angle symbol rotation angle + * @param scaleMethod scaling method for data defined scaling + * @param penJoinStyle join style for outline pen + */ QgsSimpleMarkerSymbolLayerV2( const QString& name = DEFAULT_SIMPLEMARKER_NAME, const QColor& color = DEFAULT_SIMPLEMARKER_COLOR, const QColor& borderColor = DEFAULT_SIMPLEMARKER_BORDERCOLOR, double size = DEFAULT_SIMPLEMARKER_SIZE, double angle = DEFAULT_SIMPLEMARKER_ANGLE, - QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD ); + QgsSymbolV2::ScaleMethod scaleMethod = DEFAULT_SCALE_METHOD, + Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE ); // static stuff @@ -70,9 +83,20 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2 QColor borderColor() const { return mBorderColor; } void setBorderColor( const QColor& color ) { mBorderColor = color; } + /** Get outline join style. + * @note added in 2.4 */ Qt::PenStyle outlineStyle() const { return mOutlineStyle; } + /** Set outline join style. + * @note added in 2.4 */ void setOutlineStyle( Qt::PenStyle outlineStyle ) { mOutlineStyle = outlineStyle; } + /** Get outline join style. + * @note added in 2.16 */ + Qt::PenJoinStyle penJoinStyle() const { return mPenJoinStyle; } + /** Set outline join style. + * @note added in 2.16 */ + void setPenJoinStyle( Qt::PenJoinStyle style ) { mPenJoinStyle = style; } + /** Get outline color. * @note added in 2.1 */ QColor outlineColor() const override { return borderColor(); } @@ -122,6 +146,7 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2 double mOutlineWidth; QgsSymbolV2::OutputUnit mOutlineWidthUnit; QgsMapUnitScale mOutlineWidthMapUnitScale; + Qt::PenJoinStyle mPenJoinStyle; QPen mPen; QBrush mBrush; QPolygonF mPolygon; diff --git a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp index a840de90bd0..f65789df600 100644 --- a/src/gui/symbology-ng/qgssymbollayerv2widget.cpp +++ b/src/gui/symbology-ng/qgssymbollayerv2widget.cpp @@ -455,6 +455,7 @@ QgsSimpleMarkerSymbolLayerV2Widget::QgsSimpleMarkerSymbolLayerV2Widget( const Qg connect( lstNames, SIGNAL( currentRowChanged( int ) ), this, SLOT( setName() ) ); connect( btnChangeColorBorder, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColorBorder( const QColor& ) ) ); connect( btnChangeColorFill, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( setColorFill( const QColor& ) ) ); + connect( cboJoinStyle, SIGNAL( currentIndexChanged( int ) ), this, SLOT( penJoinStyleChanged() ) ); connect( spinSize, SIGNAL( valueChanged( double ) ), this, SLOT( setSize() ) ); connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setAngle() ) ); connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) ); @@ -503,6 +504,9 @@ void QgsSimpleMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer mOutlineWidthSpinBox->blockSignals( true ); mOutlineWidthSpinBox->setValue( mLayer->outlineWidth() ); mOutlineWidthSpinBox->blockSignals( false ); + cboJoinStyle->blockSignals( true ); + cboJoinStyle->setPenJoinStyle( mLayer->penJoinStyle() ); + cboJoinStyle->blockSignals( false ); // without blocking signals the value gets changed because of slot setOffset() spinOffsetX->blockSignals( true ); @@ -542,6 +546,7 @@ void QgsSimpleMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer registerDataDefinedButton( mBorderColorDDBtn, "color_border", QgsDataDefinedButton::String, QgsDataDefinedButton::colorAlphaDesc() ); registerDataDefinedButton( mOutlineWidthDDBtn, "outline_width", QgsDataDefinedButton::Double, QgsDataDefinedButton::doublePosDesc() ); registerDataDefinedButton( mOutlineStyleDDBtn, "outline_style", QgsDataDefinedButton::String, QgsDataDefinedButton::lineStyleDesc() ); + registerDataDefinedButton( mJoinStyleDDBtn, "join_style", QgsDataDefinedButton::String, QgsDataDefinedButton::penJoinStyleDesc() ); registerDataDefinedButton( mSizeDDBtn, "size", QgsDataDefinedButton::Double, QgsDataDefinedButton::doublePosDesc() ); registerDataDefinedButton( mAngleDDBtn, "angle", QgsDataDefinedButton::Double, QgsDataDefinedButton::double180RotDesc() ); registerDataDefinedButton( mOffsetDDBtn, "offset", QgsDataDefinedButton::String, QgsDataDefinedButton::doubleXYDesc() ); @@ -574,6 +579,12 @@ void QgsSimpleMarkerSymbolLayerV2Widget::setColorFill( const QColor& color ) emit changed(); } +void QgsSimpleMarkerSymbolLayerV2Widget::penJoinStyleChanged() +{ + mLayer->setPenJoinStyle( cboJoinStyle->penJoinStyle() ); + emit changed(); +} + void QgsSimpleMarkerSymbolLayerV2Widget::setSize() { mLayer->setSize( spinSize->value() ); diff --git a/src/gui/symbology-ng/qgssymbollayerv2widget.h b/src/gui/symbology-ng/qgssymbollayerv2widget.h index 6ce300af9a9..a2a3f60e60a 100644 --- a/src/gui/symbology-ng/qgssymbollayerv2widget.h +++ b/src/gui/symbology-ng/qgssymbollayerv2widget.h @@ -201,6 +201,7 @@ class GUI_EXPORT QgsSimpleMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Wid private slots: void updateAssistantSymbol(); + void penJoinStyleChanged(); private: diff --git a/src/ui/symbollayer/widget_simplemarker.ui b/src/ui/symbollayer/widget_simplemarker.ui index 28b92a5bc7f..f1b6d23c833 100644 --- a/src/ui/symbollayer/widget_simplemarker.ui +++ b/src/ui/symbollayer/widget_simplemarker.ui @@ -70,7 +70,7 @@ - + @@ -295,7 +295,7 @@ - + Outline width @@ -323,6 +323,30 @@ + + + + Join style + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + + + ... + + + + + @@ -491,6 +515,11 @@
qgsunitselectionwidget.h
1 + + QgsPenJoinStyleComboBox + QComboBox +
qgspenstylecombobox.h
+
QgsPenStyleComboBox QComboBox @@ -507,9 +536,11 @@ mSizeUnitWidget mOutlineStyleComboBox mOutlineStyleDDBtn + cboJoinStyle + mJoinStyleDDBtn mOutlineWidthSpinBox mOutlineWidthDDBtn - mOutlineWidthUnitWidget + mOutlineWidthUnitWidget spinAngle mAngleDDBtn spinOffsetX