Skip to content
Permalink
Browse files

Add possibility to set a minimum symbol size in layout legend. Minimu…

…m and maximum size are also valid for line widths
  • Loading branch information
mhugent committed Jun 29, 2020
1 parent 01a2fe2 commit 6ff2fe45ab3bf8c400e3b2c590ab725cdf58469d
@@ -201,7 +201,8 @@ Base class for graphical items within a :py:class:`QgsLayout`.
UndoLegendColumnCount,
UndoLegendSymbolWidth,
UndoLegendSymbolHeight,
UndoLegendMaxMarkerSymbolSize,
UndoLegendMaxSymbolSize,
UndoLegendMinSymbolSize,
UndoLegendWmsLegendWidth,
UndoLegendWmsLegendHeight,
UndoLegendTitleSpaceBottom,
@@ -304,15 +304,26 @@ Sets the legend symbol ``width``.
.. seealso:: :py:func:`symbolWidth`
%End

double maxMarkerSymbolSize() const;
double maxSymbolSize() const;
%Docstring
Returns the legend maximum marker symbol size (in mm). 0.0 means there is no maximum set
Returns the legend maximum symbol size (in mm). 0.0 means there is no maximum set
%End

void setMaxMarkerSymbolSize( double size );
void setMaxSymbolSize( double size );
%Docstring
set maximum symbol size for point markers
@param size maximum marker size (in mm) or 0.0 if no maximum
set maximum symbol size
@param size maximum size (in mm) or 0.0 if no maximum
%End

double minSymbolSize() const;
%Docstring
Returns the legend minimum symbol size (in mm). 0.0 means there is no minimum set
%End

void setMinSymbolSize( double size );
%Docstring
set minimum symbol size for symbol
@param size inimum size (in mm) or 0.0 if no minimum
%End


@@ -223,15 +223,26 @@ Sets the default symbol size (in millimeters) used for legend items.
.. seealso:: :py:func:`symbolSize`
%End

double maxMarkerSymbolSize() const;
double maxSymbolSize() const;
%Docstring
Returns the maximum marker symbol size in mm
Returns the maximum symbol size in mm
%End

void setMaxMarkerSymbolSize( double size );
void setMaxSymbolSize( double size );
%Docstring
Sets the maximum marker symbol size in mm
@param size maximum marker size in mm
Sets the maximum marker size in mm
@param size maximum size in mm
%End

double minSymbolSize() const;
%Docstring
Returns the minimum symbol size in mm
%End

void setMinSymbolSize( double size );
%Docstring
Sets the minimum symbol size in mm
@param size minimum size in mm
%End

void setSymbolAlignment( Qt::AlignmentFlag alignment );
@@ -1112,6 +1112,14 @@ will be scaled to maintain their current relative size to the whole symbol size.
.. seealso:: :py:func:`width`
%End

void setWidthUnit( QgsUnitTypes::RenderUnit unit );
%Docstring
Sets the width units for the whole symbol (including all symbol layers).

:param unit: size units
%End


double width() const;
%Docstring
Returns the estimated width for the whole symbol, which is the maximum width of
@@ -557,21 +557,23 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
double widthOffset = 0;
double heightOffset = 0;

std::unique_ptr<QgsMarkerSymbol> maxSizeMarkerSymbol;
double maxSymbolSize = settings.maxSymbolSize();
double minSymbolSize = settings.minSymbolSize();

std::unique_ptr<QgsMarkerSymbol> minMaxSizeMarkerSymbol;
if ( QgsMarkerSymbol *markerSymbol = dynamic_cast<QgsMarkerSymbol *>( s ) )
{
// allow marker symbol to occupy bigger area if necessary
double size = markerSymbol->size( *context ) / context->scaleFactor();

//If marker size exceeds max marker size, clone symbol and set max size in mm
double maxMarkerSymbolSize = settings.maxMarkerSymbolSize();
if ( maxMarkerSymbolSize > 0 && size > maxMarkerSymbolSize )
if ( ( maxSymbolSize > 0 && size > maxSymbolSize ) || ( minSymbolSize > 0 && size < minSymbolSize ) )
{
maxSizeMarkerSymbol.reset( dynamic_cast<QgsMarkerSymbol *>( s->clone() ) );
maxSizeMarkerSymbol->setSize( maxMarkerSymbolSize );
maxSizeMarkerSymbol->setSizeUnit( QgsUnitTypes::RenderMillimeters );
s = maxSizeMarkerSymbol.get();
size = maxMarkerSymbolSize;
minMaxSizeMarkerSymbol.reset( dynamic_cast<QgsMarkerSymbol *>( s->clone() ) );
minMaxSizeMarkerSymbol->setSize( size > maxSymbolSize ? maxSymbolSize : minSymbolSize );
minMaxSizeMarkerSymbol->setSizeUnit( QgsUnitTypes::RenderMillimeters );
s = minMaxSizeMarkerSymbol.get();
size = ( size > maxSymbolSize ) ? maxSymbolSize : minSymbolSize;
}

height = size;
@@ -586,6 +588,21 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
}
}

std::unique_ptr<QgsLineSymbol> minMaxSizeLineSymbol;
if ( QgsLineSymbol *lineSymbol = dynamic_cast<QgsLineSymbol *>( s ) )
{
double width = lineSymbol->width( *context ) / context->scaleFactor();
if ( ( maxSymbolSize > 0 && width > maxSymbolSize ) || ( minSymbolSize > 0 && width < minSymbolSize ) )
{
minMaxSizeLineSymbol.reset( dynamic_cast<QgsLineSymbol *>( s->clone() ) );
minMaxSizeLineSymbol->setWidth( width > maxSymbolSize ? maxSymbolSize : minSymbolSize );
minMaxSizeLineSymbol->setWidthUnit( QgsUnitTypes::RenderMillimeters );
s = minMaxSizeLineSymbol.get();
width = ( width > maxSymbolSize ) ? maxSymbolSize : minSymbolSize;
}
height = width;
}

if ( ctx && ctx->painter )
{
double currentYCoord = ctx->top + ( itemHeight - desiredHeight ) / 2;
@@ -252,7 +252,8 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
UndoLegendColumnCount, //!< Legend column count
UndoLegendSymbolWidth, //!< Legend symbol width
UndoLegendSymbolHeight, //!< Legend symbol height
UndoLegendMaxMarkerSymbolSize, //!< Max marker symbol size
UndoLegendMaxSymbolSize, //!< Legend maximum symbol size
UndoLegendMinSymbolSize, //!< Legend minimum symbol size
UndoLegendWmsLegendWidth, //!< Legend WMS width
UndoLegendWmsLegendHeight, //!< Legend WMS height
UndoLegendTitleSpaceBottom, //!< Legend title space
@@ -394,14 +394,24 @@ void QgsLayoutItemLegend::setSymbolWidth( double w )
mSettings.setSymbolSize( QSizeF( w, mSettings.symbolSize().height() ) );
}

double QgsLayoutItemLegend::maxMarkerSymbolSize() const
double QgsLayoutItemLegend::maxSymbolSize() const
{
return mSettings.maxMarkerSymbolSize();
return mSettings.maxSymbolSize();
}

void QgsLayoutItemLegend::setMaxMarkerSymbolSize( double size )
void QgsLayoutItemLegend::setMaxSymbolSize( double size )
{
mSettings.setMaxMarkerSymbolSize( size );
mSettings.setMaxSymbolSize( size );
}

double QgsLayoutItemLegend::minSymbolSize() const
{
return mSettings.minSymbolSize();
}

void QgsLayoutItemLegend::setMinSymbolSize( double size )
{
mSettings.setMinSymbolSize( size );
}

void QgsLayoutItemLegend::setSymbolAlignment( Qt::AlignmentFlag alignment )
@@ -536,7 +546,8 @@ bool QgsLayoutItemLegend::writePropertiesToElement( QDomElement &legendElem, QDo

legendElem.setAttribute( QStringLiteral( "symbolWidth" ), QString::number( mSettings.symbolSize().width() ) );
legendElem.setAttribute( QStringLiteral( "symbolHeight" ), QString::number( mSettings.symbolSize().height() ) );
legendElem.setAttribute( QStringLiteral( "maxMarkerSymbolSize" ), QString::number( mSettings.maxMarkerSymbolSize() ) );
legendElem.setAttribute( QStringLiteral( "maxSymbolSize" ), QString::number( mSettings.maxSymbolSize() ) );
legendElem.setAttribute( QStringLiteral( "minSymbolSize" ), QString::number( mSettings.minSymbolSize() ) );

legendElem.setAttribute( QStringLiteral( "symbolAlignment" ), mSettings.symbolAlignment() );

@@ -632,7 +643,8 @@ bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem
mSettings.setSymbolSize( QSizeF( itemElem.attribute( QStringLiteral( "symbolWidth" ), QStringLiteral( "7.0" ) ).toDouble(), itemElem.attribute( QStringLiteral( "symbolHeight" ), QStringLiteral( "14.0" ) ).toDouble() ) );
mSettings.setSymbolAlignment( static_cast< Qt::AlignmentFlag >( itemElem.attribute( QStringLiteral( "symbolAlignment" ), QString::number( Qt::AlignLeft ) ).toInt() ) );

mSettings.setMaxMarkerSymbolSize( itemElem.attribute( QStringLiteral( "maxMarkerSymbolSize" ), QStringLiteral( "0.0" ) ).toDouble() );
mSettings.setMaxSymbolSize( itemElem.attribute( QStringLiteral( "maxSymbolSize" ), QStringLiteral( "0.0" ) ).toDouble() );
mSettings.setMinSymbolSize( itemElem.attribute( QStringLiteral( "minSymbolSize" ), QStringLiteral( "0.0" ) ).toDouble() );

mSettings.setWmsLegendSize( QSizeF( itemElem.attribute( QStringLiteral( "wmsLegendWidth" ), QStringLiteral( "50" ) ).toDouble(), itemElem.attribute( QStringLiteral( "wmsLegendHeight" ), QStringLiteral( "25" ) ).toDouble() ) );
mSettings.setLineSpacing( itemElem.attribute( QStringLiteral( "lineSpacing" ), QStringLiteral( "1.0" ) ).toDouble() );
@@ -319,15 +319,26 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
void setSymbolWidth( double width );

/**
* Returns the legend maximum marker symbol size (in mm). 0.0 means there is no maximum set
* Returns the legend maximum symbol size (in mm). 0.0 means there is no maximum set
*/
double maxMarkerSymbolSize() const;
double maxSymbolSize() const;

/**
* @brief set maximum symbol size for point markers
* @param size maximum marker size (in mm) or 0.0 if no maximum
* @brief set maximum symbol size
* @param size maximum size (in mm) or 0.0 if no maximum
*/
void setMaxMarkerSymbolSize( double size );
void setMaxSymbolSize( double size );

/**
* Returns the legend minimum symbol size (in mm). 0.0 means there is no minimum set
*/
double minSymbolSize() const;

/**
* @brief set minimum symbol size for symbol
* @param size inimum size (in mm) or 0.0 if no minimum
*/
void setMinSymbolSize( double size );


/**
@@ -235,15 +235,26 @@ class CORE_EXPORT QgsLegendSettings
void setSymbolSize( QSizeF s ) {mSymbolSize = s;}

/**
* Returns the maximum marker symbol size in mm
* Returns the maximum symbol size in mm
*/
double maxMarkerSymbolSize() const {return mMaxMarkerSymbolSize; }
double maxSymbolSize() const {return mMaxSymbolSize; }

/**
* Sets the maximum marker symbol size in mm
* @param size maximum marker size in mm
* Sets the maximum marker size in mm
* @param size maximum size in mm
*/
void setMaxMarkerSymbolSize( double size ) { mMaxMarkerSymbolSize = size;}
void setMaxSymbolSize( double size ) { mMaxSymbolSize = size;}

/**
* Returns the minimum symbol size in mm
*/
double minSymbolSize() const {return mMinSymbolSize; }

/**
* Sets the minimum symbol size in mm
* @param size minimum size in mm
*/
void setMinSymbolSize( double size ) { mMinSymbolSize = size;}

/**
* Sets the \a alignment for placement of legend symbols.
@@ -491,7 +502,10 @@ class CORE_EXPORT QgsLegendSettings
QSizeF mSymbolSize;

//! Maximum marker symbol size (in mm)
double mMaxMarkerSymbolSize = 0.0;
double mMaxSymbolSize = 0.0;

//! Minimum marker symbol size (in mm)
double mMinSymbolSize = 0.0;

//! Width and height of WMS legendGraphic pixmap
QSizeF mWmsLegendSize;
@@ -1943,6 +1943,19 @@ void QgsLineSymbol::setWidth( double w )
}
}

void QgsLineSymbol::setWidthUnit( QgsUnitTypes::RenderUnit unit )
{
const auto constLLayers = mLayers;
for ( QgsSymbolLayer *layer : constLLayers )
{
if ( layer->type() != QgsSymbol::Line )
continue;

QgsLineSymbolLayer *lineLayer = static_cast<QgsLineSymbolLayer *>( layer );
lineLayer->setWidthUnit( unit );
}
}

double QgsLineSymbol::width() const
{
double maxWidth = 0;
@@ -1139,6 +1139,13 @@ class CORE_EXPORT QgsLineSymbol : public QgsSymbol
*/
void setWidth( double width );

/**
* Sets the width units for the whole symbol (including all symbol layers).
* \param unit size units
*/
void setWidthUnit( QgsUnitTypes::RenderUnit unit );


/**
* Returns the estimated width for the whole symbol, which is the maximum width of
* all marker symbol layers in the symbol.
@@ -86,7 +86,8 @@ QgsLayoutLegendWidget::QgsLayoutLegendWidget( QgsLayoutItemLegend *legend, QgsMa
connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled, this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
connect( mSymbolWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
connect( mSymbolHeightSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
connect( mMaxMarkerSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mMaxMarkerSizeSpinBox_valueChanged );
connect( mMaxSymbolSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
connect( mMinSymbolSizeSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
connect( mWmsLegendWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
connect( mWmsLegendHeightSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
connect( mTitleSpaceBottomSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
@@ -231,7 +232,8 @@ void QgsLayoutLegendWidget::setGuiElements()
mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
mMaxMarkerSizeSpinBox->setValue( mLegend->maxMarkerSymbolSize() );
mMaxSymbolSizeSpinBox->setValue( mLegend->maxSymbolSize() );
mMinSymbolSizeSpinBox->setValue( mLegend->minSymbolSize() );
mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
mTitleSpaceBottomSpinBox->setValue( mLegend->style( QgsLegendStyle::Title ).margin( QgsLegendStyle::Bottom ) );
@@ -405,12 +407,24 @@ void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged( double d )
}
}

void QgsLayoutLegendWidget::mMaxMarkerSizeSpinBox_valueChanged( double d )
void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged( double d )
{
if ( mLegend )
{
mLegend->beginCommand( tr( "Change Legend Maximum Marker Size" ), QgsLayoutItem::UndoLegendMaxMarkerSymbolSize );
mLegend->setMaxMarkerSymbolSize( d );
mLegend->beginCommand( tr( "Change Legend Maximum Symbol Size" ), QgsLayoutItem::UndoLegendMaxSymbolSize );
mLegend->setMaxSymbolSize( d );
mLegend->adjustBoxSize();
mLegend->update();
mLegend->endCommand();
}
}

void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged( double d )
{
if ( mLegend )
{
mLegend->beginCommand( tr( "Change Legend Minimum Symbol Size" ), QgsLayoutItem::UndoLegendMinSymbolSize );
mLegend->setMinSymbolSize( d );
mLegend->adjustBoxSize();
mLegend->update();
mLegend->endCommand();
@@ -1235,7 +1249,8 @@ void QgsLayoutLegendWidget::blockAllSignals( bool b )
mEqualColumnWidthCheckBox->blockSignals( b );
mSymbolWidthSpinBox->blockSignals( b );
mSymbolHeightSpinBox->blockSignals( b );
mMaxMarkerSizeSpinBox->blockSignals( b );
mMaxSymbolSizeSpinBox->blockSignals( b );
mMinSymbolSizeSpinBox->blockSignals( b );
mGroupSpaceSpinBox->blockSignals( b );
mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
mGroupSideSpinBox->blockSignals( b );
@@ -76,7 +76,8 @@ class GUI_EXPORT QgsLayoutLegendWidget: public QgsLayoutItemBaseWidget, private
void mEqualColumnWidthCheckBox_toggled( bool checked );
void mSymbolWidthSpinBox_valueChanged( double d );
void mSymbolHeightSpinBox_valueChanged( double d );
void mMaxMarkerSizeSpinBox_valueChanged( double d );
void mMaxSymbolSizeSpinBox_valueChanged( double d );
void mMinSymbolSizeSpinBox_valueChanged( double d );
void mWmsLegendWidthSpinBox_valueChanged( double d );
void mWmsLegendHeightSpinBox_valueChanged( double d );
void mTitleSpaceBottomSpinBox_valueChanged( double d );

0 comments on commit 6ff2fe4

Please sign in to comment.
You can’t perform that action at this time.