[FEATURE] Allow overriding the legend patch size on a per-item basis

Allows users to override the symbol patch size for individual legend
nodes, by double clicking the node

Width and height can be individually overridden, with the node falling
back to the default width or height when the override isn't set.

Sponsored by SLYR
This commit is contained in:
Nyall Dawson 2020-04-27 10:37:10 +10:00
parent 18547ec258
commit 0c64fd7907
15 changed files with 399 additions and 66 deletions

View File

@ -153,6 +153,30 @@ Sets the symbol patch ``shape`` to use when rendering the legend node symbol.
.. seealso:: :py:func:`patchShape`
.. versionadded:: 3.14
%End
QSizeF patchSize() const;
%Docstring
Returns the user (overridden) size for the legend node.
If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
symbol width or height from :py:class:`QgsLegendSettings`.
.. seealso:: :py:func:`setPatchSize`
.. versionadded:: 3.14
%End
void setPatchSize( QSizeF size );
%Docstring
Sets the user (overridden) ``size`` for the legend node.
If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
symbol width or height from :py:class:`QgsLegendSettings`.
.. seealso:: :py:func:`patchSize`
.. versionadded:: 3.14
%End

View File

@ -72,6 +72,30 @@ Sets some data associated with the item. Default implementation does nothing and
virtual QString userLabel() const;
virtual void setUserLabel( const QString &userLabel );
virtual QSizeF userPatchSize() const;
%Docstring
Returns the user (overridden) size for the legend node.
If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
symbol width or height from :py:class:`QgsLegendSettings`.
.. seealso:: :py:func:`setUserPatchSize`
.. versionadded:: 3.14
%End
virtual void setUserPatchSize( QSizeF size );
%Docstring
Sets the user (overridden) ``size`` for the legend node.
If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
symbol width or height from :py:class:`QgsLegendSettings`.
.. seealso:: :py:func:`userPatchSize`
.. versionadded:: 3.14
%End
virtual bool isScaleOK( double scale ) const;
virtual void invalidateMapBasedData();
@ -100,6 +124,8 @@ Default implementation does nothing. *
double maxSiblingSymbolWidth;
QgsLegendPatchShape patchShape;
QSizeF patchSize;
};
struct ItemMetrics

View File

@ -111,6 +111,30 @@ Returns the legend patch shape for the legend node belonging to ``nodeLayer`` at
.. seealso:: :py:func:`setLegendNodePatchShape`
.. versionadded:: 3.14
%End
static void setLegendNodeSymbolSize( QgsLayerTreeLayer *nodeLayer, int originalIndex, QSizeF size );
%Docstring
Sets the legend symbol ``size`` for the legend node belonging to ``nodeLayer`` at the specified ``originalIndex``.
If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
symbol width or height from :py:class:`QgsLegendSettings`.
.. seealso:: :py:func:`legendNodeSymbolSize`
.. versionadded:: 3.14
%End
static QSizeF legendNodeSymbolSize( QgsLayerTreeLayer *nodeLayer, int originalIndex );
%Docstring
Returns the legend node symbol size for the legend node belonging to ``nodeLayer`` at the specified ``originalIndex``.
If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
symbol width or height from :py:class:`QgsLegendSettings`.
.. seealso:: :py:func:`setLegendNodeSymbolSize`
.. versionadded:: 3.14
%End

View File

@ -18,6 +18,7 @@
#include "qgslayertreeutils.h"
#include "qgsmaplayer.h"
#include "qgsproject.h"
#include "qgssymbollayerutils.h"
QgsLayerTreeLayer::QgsLayerTreeLayer( QgsMapLayer *layer )
@ -40,6 +41,7 @@ QgsLayerTreeLayer::QgsLayerTreeLayer( const QgsLayerTreeLayer &other )
, mRef( other.mRef )
, mLayerName( other.mLayerName )
, mPatchShape( other.mPatchShape )
, mPatchSize( other.mPatchSize )
{
attachToLayer();
}
@ -130,6 +132,8 @@ QgsLayerTreeLayer *QgsLayerTreeLayer::readXml( QDomElement &element, const QgsRe
nodeLayer->setPatchShape( patch );
}
nodeLayer->setPatchSize( QgsSymbolLayerUtils::decodeSize( element.attribute( QStringLiteral( "patch_size" ) ) ) );
return nodeLayer;
}
@ -164,6 +168,7 @@ void QgsLayerTreeLayer::writeXml( QDomElement &parentElement, const QgsReadWrite
mPatchShape.writeXml( patchElem, doc, context );
elem.appendChild( patchElem );
}
elem.setAttribute( QStringLiteral( "patch_size" ), QgsSymbolLayerUtils::encodeSize( mPatchSize ) );
writeCommonXml( elem );

View File

@ -159,6 +159,28 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
*/
void setPatchShape( const QgsLegendPatchShape &shape );
/**
* Returns the user (overridden) size for the legend node.
*
* If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
* symbol width or height from QgsLegendSettings.
*
* \see setPatchSize()
* \since QGIS 3.14
*/
QSizeF patchSize() const { return mPatchSize; }
/**
* Sets the user (overridden) \a size for the legend node.
*
* If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
* symbol width or height from QgsLegendSettings.
*
* \see patchSize()
* \since QGIS 3.14
*/
void setPatchSize( QSizeF size ) { mPatchSize = size; }
signals:
/**
@ -210,6 +232,7 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
#endif
QgsLegendPatchShape mPatchShape;
QSizeF mPatchSize;
};

View File

@ -59,6 +59,13 @@ bool QgsLayerTreeModelLegendNode::setData( const QVariant &value, int role )
return false;
}
QSizeF QgsLayerTreeModelLegendNode::userPatchSize() const
{
if ( mEmbeddedInParent )
return mLayerNode->patchSize();
return mUserSize;
}
QgsLayerTreeModelLegendNode::ItemMetrics QgsLayerTreeModelLegendNode::draw( const QgsLegendSettings &settings, ItemContext *ctx )
{
@ -68,7 +75,7 @@ QgsLayerTreeModelLegendNode::ItemMetrics QgsLayerTreeModelLegendNode::draw( cons
// itemHeight here is not really item height, it is only for symbol
// vertical alignment purpose, i.e. OK take single line height
// if there are more lines, those run under the symbol
double itemHeight = std::max( static_cast< double >( settings.symbolSize().height() ), textHeight );
double itemHeight = std::max( static_cast< double >( ctx && ctx->patchSize.height() > 0 ? ctx->patchSize.height() : settings.symbolSize().height() ), textHeight );
ItemMetrics im;
im.symbolSize = drawSymbol( settings, ctx, itemHeight );
@ -88,6 +95,15 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings &setting
if ( symbolIcon.isNull() )
return QSizeF();
QSizeF size = settings.symbolSize();
if ( ctx )
{
if ( ctx->patchSize.width() > 0 )
size.setWidth( ctx->patchSize.width( ) );
if ( ctx->patchSize.height() > 0 )
size.setHeight( ctx->patchSize.height( ) );
}
if ( ctx && ctx->painter )
{
switch ( settings.symbolAlignment() )
@ -96,21 +112,21 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings &setting
default:
symbolIcon.paint( ctx->painter,
static_cast< int >( ctx->columnLeft ),
static_cast< int >( ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2 ),
static_cast< int >( settings.symbolSize().width() ),
static_cast< int >( settings.symbolSize().height() ) );
static_cast< int >( ctx->top + ( itemHeight - size.height() ) / 2 ),
static_cast< int >( size.width() ),
static_cast< int >( size.height() ) );
break;
case Qt::AlignRight:
symbolIcon.paint( ctx->painter,
static_cast< int >( ctx->columnRight - settings.symbolSize().width() ),
static_cast< int >( ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2 ),
static_cast< int >( settings.symbolSize().width() ),
static_cast< int >( settings.symbolSize().height() ) );
static_cast< int >( ctx->columnRight - size.width() ),
static_cast< int >( ctx->top + ( itemHeight - size.height() ) / 2 ),
static_cast< int >( size.width() ),
static_cast< int >( size.height() ) );
break;
}
}
return settings.symbolSize();
return size;
}
void QgsLayerTreeModelLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const
@ -531,8 +547,10 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
}
//Consider symbol size for point markers
double height = settings.symbolSize().height();
double width = settings.symbolSize().width();
const double desiredHeight = ctx && ctx->patchSize.height() > 0 ? ctx->patchSize.height() : settings.symbolSize().height();
const double desiredWidth = ctx && ctx->patchSize.width() > 0 ? ctx->patchSize.width() : settings.symbolSize().width();
double height = desiredHeight;
double width = desiredWidth;
//Center small marker symbols
double widthOffset = 0;
@ -544,19 +562,19 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
double size = markerSymbol->size( *context ) / context->scaleFactor();
height = size;
width = size;
if ( width < settings.symbolSize().width() )
if ( width < desiredWidth )
{
widthOffset = ( settings.symbolSize().width() - width ) / 2.0;
widthOffset = ( desiredWidth - width ) / 2.0;
}
if ( height < settings.symbolSize().height() )
if ( height < desiredHeight )
{
heightOffset = ( settings.symbolSize().height() - height ) / 2.0;
heightOffset = ( desiredHeight - height ) / 2.0;
}
}
if ( ctx && ctx->painter )
{
double currentYCoord = ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2;
double currentYCoord = ctx->top + ( itemHeight - desiredHeight ) / 2;
QPainter *p = ctx->painter;
//setup painter scaling to dots so that raster symbology is drawn to scale
@ -621,8 +639,8 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
p->restore();
}
return QSizeF( std::max( width + 2 * widthOffset, static_cast< double >( settings.symbolSize().width() ) ),
std::max( height + 2 * heightOffset, static_cast< double >( settings.symbolSize().height() ) ) );
return QSizeF( std::max( width + 2 * widthOffset, static_cast< double >( desiredWidth ) ),
std::max( height + 2 * heightOffset, static_cast< double >( desiredHeight ) ) );
}
void QgsSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const
@ -858,6 +876,22 @@ QVariant QgsRasterSymbolLegendNode::data( int role ) const
QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const
{
QSizeF size = settings.symbolSize();
double offsetX = 0;
if ( ctx )
{
if ( ctx->patchSize.width() > 0 )
{
if ( ctx->patchSize.width() < size.width() )
offsetX = ( size.width() - ctx->patchSize.width() ) / 2.0;
size.setWidth( ctx->patchSize.width() );
}
if ( ctx->patchSize.height() > 0 )
{
size.setHeight( ctx->patchSize.height() );
}
}
if ( ctx && ctx->painter )
{
QColor itemColor = mColor;
@ -885,17 +919,17 @@ QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings,
{
case Qt::AlignLeft:
default:
ctx->painter->drawRect( QRectF( ctx->columnLeft, ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2,
settings.symbolSize().width(), settings.symbolSize().height() ) );
ctx->painter->drawRect( QRectF( ctx->columnLeft + offsetX, ctx->top + ( itemHeight - size.height() ) / 2,
size.width(), size.height() ) );
break;
case Qt::AlignRight:
ctx->painter->drawRect( QRectF( ctx->columnRight - settings.symbolSize().width(), ctx->top + ( itemHeight - settings.symbolSize().height() ) / 2,
settings.symbolSize().width(), settings.symbolSize().height() ) );
ctx->painter->drawRect( QRectF( ctx->columnRight - size.width() - offsetX, ctx->top + ( itemHeight - size.height() ) / 2,
size.width(), size.height() ) );
break;
}
}
return settings.symbolSize();
return size;
}
void QgsRasterSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const

View File

@ -87,6 +87,28 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
virtual QString userLabel() const { return mUserLabel; }
virtual void setUserLabel( const QString &userLabel ) { mUserLabel = userLabel; }
/**
* Returns the user (overridden) size for the legend node.
*
* If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
* symbol width or height from QgsLegendSettings.
*
* \see setUserPatchSize()
* \since QGIS 3.14
*/
virtual QSizeF userPatchSize() const;
/**
* Sets the user (overridden) \a size for the legend node.
*
* If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
* symbol width or height from QgsLegendSettings.
*
* \see userPatchSize()
* \since QGIS 3.14
*/
virtual void setUserPatchSize( QSizeF size ) { mUserSize = size; }
virtual bool isScaleOK( double scale ) const { Q_UNUSED( scale ) return true; }
/**
@ -152,6 +174,15 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
* \since QGIS 3.14
*/
QgsLegendPatchShape patchShape;
/**
* Symbol patch size to render for the node.
*
* If either the width or height are zero, then the default width/height from QgsLegendSettings::symbolSize() should be used instead.
*
* \since QGIS 3.14
*/
QSizeF patchSize;
};
struct ItemMetrics
@ -229,6 +260,7 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
bool mEmbeddedInParent;
QString mUserLabel;
QgsLegendPatchShape mPatchShape;
QSizeF mUserSize;
};
#include "qgslegendsymbolitem.h"

View File

@ -674,8 +674,9 @@ QgsLegendRenderer::LegendComponent QgsLegendRenderer::drawSymbolItemInternal( Qg
if ( const QgsSymbolLegendNode *symbolNode = dynamic_cast< const QgsSymbolLegendNode * >( symbolItem ) )
ctx.patchShape = symbolNode->patchShape();
QgsLayerTreeModelLegendNode::ItemMetrics im = symbolItem->draw( mSettings, context ? &ctx
: ( painter ? &ctx : nullptr ) );
ctx.patchSize = symbolItem->userPatchSize();
QgsLayerTreeModelLegendNode::ItemMetrics im = symbolItem->draw( mSettings, &ctx );
if ( layerScope )
delete context->expressionContext().popScope();

View File

@ -24,7 +24,7 @@
#include "qgsrenderer.h"
#include "qgsvectorlayer.h"
#include "qgsdiagramrenderer.h"
#include "qgssymbollayerutils.h"
QgsMapLayerLegend::QgsMapLayerLegend( QObject *parent )
: QObject( parent )
@ -168,6 +168,23 @@ QgsLegendPatchShape QgsMapLayerLegendUtils::legendNodePatchShape( QgsLayerTreeLa
return shape;
}
void QgsMapLayerLegendUtils::setLegendNodeSymbolSize( QgsLayerTreeLayer *nodeLayer, int originalIndex, QSizeF size )
{
if ( size.isValid() )
nodeLayer->setCustomProperty( "legend/symbol-size-" + QString::number( originalIndex ), QgsSymbolLayerUtils::encodeSize( size ) );
else
nodeLayer->removeCustomProperty( "legend/symbol-size-" + QString::number( originalIndex ) );
}
QSizeF QgsMapLayerLegendUtils::legendNodeSymbolSize( QgsLayerTreeLayer *nodeLayer, int originalIndex )
{
const QString size = nodeLayer->customProperty( "legend/symbol-size-" + QString::number( originalIndex ) ).toString();
if ( size.isEmpty() )
return QSizeF();
else
return QgsSymbolLayerUtils::decodeSize( size );
}
void QgsMapLayerLegendUtils::applyLayerNodeProperties( QgsLayerTreeLayer *nodeLayer, QList<QgsLayerTreeModelLegendNode *> &nodes )
{
// handle user labels
@ -185,6 +202,12 @@ void QgsMapLayerLegendUtils::applyLayerNodeProperties( QgsLayerTreeLayer *nodeLa
symbolNode->setPatchShape( shape );
}
const QSizeF userSize = QgsMapLayerLegendUtils::legendNodeSymbolSize( nodeLayer, i );
if ( userSize.isValid() )
{
legendNode->setUserPatchSize( userSize );
}
i++;
}

View File

@ -119,6 +119,28 @@ class CORE_EXPORT QgsMapLayerLegendUtils
*/
static QgsLegendPatchShape legendNodePatchShape( QgsLayerTreeLayer *nodeLayer, int originalIndex );
/**
* Sets the legend symbol \a size for the legend node belonging to \a nodeLayer at the specified \a originalIndex.
*
* If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
* symbol width or height from QgsLegendSettings.
*
* \see legendNodeSymbolSize()
* \since QGIS 3.14
*/
static void setLegendNodeSymbolSize( QgsLayerTreeLayer *nodeLayer, int originalIndex, QSizeF size );
/**
* Returns the legend node symbol size for the legend node belonging to \a nodeLayer at the specified \a originalIndex.
*
* If either the width or height are non-zero, they will be used when rendering the legend node instead of the default
* symbol width or height from QgsLegendSettings.
*
* \see setLegendNodeSymbolSize()
* \since QGIS 3.14
*/
static QSizeF legendNodeSymbolSize( QgsLayerTreeLayer *nodeLayer, int originalIndex );
//! update according to layer node's custom properties (order of items, user labels for items)
static void applyLayerNodeProperties( QgsLayerTreeLayer *nodeLayer, QList<QgsLayerTreeModelLegendNode *> &nodes );
};

View File

@ -1001,6 +1001,7 @@ void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
}
nodeLayer->setPatchShape( QgsLegendPatchShape() );
nodeLayer->setPatchSize( QSizeF() );
mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
@ -1437,7 +1438,23 @@ QgsLayoutLegendNodeWidget::QgsLayoutLegendNodeWidget( QgsLayoutItemLegend *legen
else
{
currentLabel = QgsLayerTree::toGroup( mNode )->name();
}
mWidthSpinBox->setClearValue( 0, tr( "Default" ) );
mHeightSpinBox->setClearValue( 0, tr( "Default" ) );
mWidthSpinBox->setVisible( mLegendNode || mLayer );
mHeightSpinBox->setVisible( mLegendNode || mLayer );
mPatchWidthLabel->setVisible( mLegendNode || mLayer );
mPatchHeightLabel->setVisible( mLegendNode || mLayer );
if ( mLegendNode )
{
mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
}
else if ( mLayer )
{
mWidthSpinBox->setValue( mLayer->patchSize().width() );
mHeightSpinBox->setValue( mLayer->patchSize().height() );
}
QgsLegendPatchShape patchShape;
@ -1489,6 +1506,9 @@ QgsLayoutLegendNodeWidget::QgsLayoutLegendNodeWidget( QgsLayoutItemLegend *legen
connect( mLabelEdit, &QPlainTextEdit::textChanged, this, &QgsLayoutLegendNodeWidget::labelChanged );
connect( mPatchShapeButton, &QgsLegendPatchShapeButton::changed, this, &QgsLayoutLegendNodeWidget::patchChanged );
connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsLayoutLegendNodeWidget::insertExpression );
connect( mWidthSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendNodeWidget::sizeChanged );
connect( mHeightSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendNodeWidget::sizeChanged );
}
void QgsLayoutLegendNodeWidget::labelChanged()
@ -1591,4 +1611,30 @@ void QgsLayoutLegendNodeWidget::insertExpression()
}
}
void QgsLayoutLegendNodeWidget::sizeChanged( double )
{
mLegend->beginCommand( tr( "Edit Legend Item" ) );
const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
if ( mLegendNode )
{
QgsMapLayerLegendUtils::setLegendNodeSymbolSize( mLayer, mOriginalLegendNodeIndex, size );
mLegend->model()->refreshLayerLegend( mLayer );
}
else if ( mLayer )
{
mLayer->setPatchSize( size );
const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer, false );
for ( QgsLayerTreeModelLegendNode *node : layerLegendNodes )
{
QgsMapLayerLegendUtils::setLegendNodeSymbolSize( mLayer, _originalLegendNodeIndex( node ), size );
}
mLegend->model()->refreshLayerLegend( mLayer );
}
mLegend->adjustBoxSize();
mLegend->updateFilterByMap();
mLegend->endCommand();
}
///@endcond

View File

@ -193,6 +193,7 @@ class GUI_EXPORT QgsLayoutLegendNodeWidget: public QgsPanelWidget, private Ui::Q
void labelChanged();
void patchChanged();
void insertExpression();
void sizeChanged( double );
private:

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>282</height>
<width>351</width>
<height>381</height>
</rect>
</property>
<property name="windowTitle">
@ -26,17 +26,7 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QPlainTextEdit" name="mLabelEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -49,43 +39,89 @@
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="mInsertExpressionButton">
<property name="text">
<string>Insert an Expression…</string>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Patch</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1">
<item row="0" column="0">
<widget class="QLabel" name="mPatchShapeLabel">
<property name="text">
<string>Shape</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsLegendPatchShapeButton" name="mPatchShapeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Customize</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mPatchWidthLabel">
<property name="text">
<string>Width (mm)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsDoubleSpinBox" name="mWidthSpinBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mPatchHeightLabel">
<property name="text">
<string>Height (mm)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsDoubleSpinBox" name="mHeightSpinBox"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsLegendPatchShapeButton" name="mPatchShapeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Customize</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mPatchShapeLabel">
<property name="text">
<string>Patch shape</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Label</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="mLabelEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="mInsertExpressionButton">
<property name="text">
<string>Insert an Expression…</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsPanelWidget</class>
<extends>QWidget</extends>
@ -98,6 +134,13 @@
<header>qgslegendpatchshapebutton.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mLabelEdit</tabstop>
<tabstop>mInsertExpressionButton</tabstop>
<tabstop>mPatchShapeButton</tabstop>
<tabstop>mWidthSpinBox</tabstop>
<tabstop>mHeightSpinBox</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -132,6 +132,7 @@ class TestQgsLegendRenderer : public QObject
void testBasic();
void testMultiline();
void testOverrideSize();
void testSpacing();
void testEffects();
void testBigMarker();
@ -340,6 +341,34 @@ void TestQgsLegendRenderer::testMultiline()
QVERIFY( _verifyImage( testName, mReport ) );
}
void TestQgsLegendRenderer::testOverrideSize()
{
QString testName = QStringLiteral( "legend_override_size" );
QgsLayerTreeModel legendModel( mRoot );
legendModel.findLegendNode( mVL1->id(), QString() );
QgsLayerTreeLayer *layer = legendModel.rootGroup()->findLayer( mVL1 );
layer->setPatchSize( QSizeF( 30, 0 ) );
QgsLayerTreeModelLegendNode *embeddedNode = legendModel.legendNodeEmbeddedInParent( layer );
embeddedNode->setUserLabel( QString() );
layer = legendModel.rootGroup()->findLayer( mVL3 );
QgsMapLayerLegendUtils::setLegendNodeSymbolSize( layer, 1, QSizeF( 0, 30 ) );
legendModel.refreshLayerLegend( layer );
layer = legendModel.rootGroup()->findLayer( mRL );
QgsMapLayerLegendUtils::setLegendNodeSymbolSize( layer, 0, QSizeF( 50, 30 ) );
legendModel.refreshLayerLegend( layer );
QgsLegendSettings settings;
_setStandardTestFont( settings, QStringLiteral( "Bold" ) );
_renderLegend( testName, &legendModel, settings );
QVERIFY( _verifyImage( testName, mReport ) );
}
void TestQgsLegendRenderer::testSpacing()
{
QgsMarkerSymbol *sym = new QgsMarkerSymbol();

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB