Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE][layouts] Allow control over the horizontal spacing before
legend group/subgroup/symbols

Gives flexibility to allow "nesting" legend groups/subgroups/symbols
and much greater control over legend item placement

Sponsored by SLYR
  • Loading branch information
nyalldawson committed Apr 24, 2020
1 parent 715f4c7 commit 36339c2
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 91 deletions.
32 changes: 26 additions & 6 deletions src/core/qgslegendrenderer.cpp
Expand Up @@ -653,8 +653,22 @@ QgsLegendRenderer::LegendComponent QgsLegendRenderer::drawSymbolItemInternal( Qg
Q_NOWARN_DEPRECATED_POP

ctx.top = top;

ctx.columnLeft = columnContext.left;
ctx.columnRight = columnContext.right;

switch ( mSettings.symbolAlignment() )
{
case Qt::AlignLeft:
default:
ctx.columnLeft += mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Left );
break;

case Qt::AlignRight:
ctx.columnRight -= mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Left );
break;
}

ctx.maxSiblingSymbolWidth = maxSiblingSymbolWidth;

if ( const QgsSymbolLegendNode *symbolNode = dynamic_cast< const QgsSymbolLegendNode * >( symbolItem ) )
Expand All @@ -675,6 +689,7 @@ QgsLegendRenderer::LegendComponent QgsLegendRenderer::drawSymbolItemInternal( Qg
// ideally we could (should?) expose all these margins as settings, and then adapt the below to respect the current symbol/text alignment
// and consider the correct margin sides...
double width = std::max( static_cast< double >( im.symbolSize.width() ), maxSiblingSymbolWidth )
+ mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Left )
+ mSettings.style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Right )
+ mSettings.style( QgsLegendStyle::SymbolLabel ).margin( QgsLegendStyle::Left )
+ im.labelSize.width();
Expand Down Expand Up @@ -719,23 +734,26 @@ QSizeF QgsLegendRenderer::drawLayerTitleInternal( QgsLayerTreeLayer *nodeLayer,
const QStringList lines = mSettings.evaluateItemText( titleString,
context ? context->expressionContext() : tempContext );
int i = 0;

const double sideMargin = mSettings.style( nodeLegendStyle( nodeLayer ) ).margin( QgsLegendStyle::Left );
for ( QStringList::ConstIterator layerItemPart = lines.constBegin(); layerItemPart != lines.constEnd(); ++layerItemPart )
{
y += mSettings.fontAscentMillimeters( layerFont );
if ( QPainter *destPainter = context && context->painter() ? context->painter() : painter )
{
double x = columnContext.left;
double x = columnContext.left + sideMargin;
if ( mSettings.style( nodeLegendStyle( nodeLayer ) ).alignment() != Qt::AlignLeft )
{
const double labelWidth = mSettings.textWidthMillimeters( layerFont, *layerItemPart );
if ( mSettings.style( nodeLegendStyle( nodeLayer ) ).alignment() == Qt::AlignRight )
x = columnContext.right - labelWidth;
x = columnContext.right - labelWidth - sideMargin;
else if ( mSettings.style( nodeLegendStyle( nodeLayer ) ).alignment() == Qt::AlignHCenter )
x = columnContext.left + ( columnContext.right - columnContext.left - labelWidth ) / 2;
}
mSettings.drawText( destPainter, x, y, *layerItemPart, layerFont );
}
qreal width = mSettings.textWidthMillimeters( layerFont, *layerItemPart );
qreal width = mSettings.textWidthMillimeters( layerFont, *layerItemPart ) + sideMargin *
( mSettings.style( nodeLegendStyle( nodeLayer ) ).alignment() == Qt::AlignHCenter ? 2 : 1 );
size.rwidth() = std::max( width, size.width() );
if ( layerItemPart != ( lines.end() - 1 ) )
{
Expand Down Expand Up @@ -773,6 +791,8 @@ QSizeF QgsLegendRenderer::drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup,

QgsExpressionContext tempContext;

const double sideMargin = mSettings.style( nodeLegendStyle( nodeGroup ) ).margin( QgsLegendStyle::Left );

const QStringList lines = mSettings.evaluateItemText( mLegendModel->data( idx, Qt::DisplayRole ).toString(),
context ? context->expressionContext() : tempContext );
for ( QStringList::ConstIterator groupPart = lines.constBegin(); groupPart != lines.constEnd(); ++groupPart )
Expand All @@ -781,18 +801,18 @@ QSizeF QgsLegendRenderer::drawGroupTitleInternal( QgsLayerTreeGroup *nodeGroup,

if ( QPainter *destPainter = context && context->painter() ? context->painter() : painter )
{
double x = columnContext.left;
double x = columnContext.left + sideMargin;
if ( mSettings.style( nodeLegendStyle( nodeGroup ) ).alignment() != Qt::AlignLeft )
{
const double labelWidth = mSettings.textWidthMillimeters( groupFont, *groupPart );
if ( mSettings.style( nodeLegendStyle( nodeGroup ) ).alignment() == Qt::AlignRight )
x = columnContext.right - labelWidth;
x = columnContext.right - labelWidth - sideMargin;
else if ( mSettings.style( nodeLegendStyle( nodeGroup ) ).alignment() == Qt::AlignHCenter )
x = columnContext.left + ( columnContext.right - columnContext.left - labelWidth ) / 2;
}
mSettings.drawText( destPainter, x, y, *groupPart, groupFont );
}
qreal width = mSettings.textWidthMillimeters( groupFont, *groupPart );
qreal width = mSettings.textWidthMillimeters( groupFont, *groupPart ) + sideMargin * ( mSettings.style( nodeLegendStyle( nodeGroup ) ).alignment() == Qt::AlignHCenter ? 2 : 1 );
size.rwidth() = std::max( width, size.width() );
if ( groupPart != ( lines.end() - 1 ) )
{
Expand Down
48 changes: 48 additions & 0 deletions src/gui/layout/qgslayoutlegendwidget.cpp
Expand Up @@ -91,9 +91,12 @@ QgsLayoutLegendWidget::QgsLayoutLegendWidget( QgsLayoutItemLegend *legend, QgsMa
connect( mTitleSpaceBottomSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
connect( mGroupSpaceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
connect( mSpaceBelowGroupHeadingSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
connect( mGroupSideSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
connect( mLayerSpaceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
connect( mSpaceBelowSubgroupHeadingSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
connect( mSubgroupSideSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
connect( mSymbolSpaceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
connect( mSymbolSideSpaceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
connect( mIconLabelSpaceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
connect( mFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutLegendWidget::mFontColorButton_colorChanged );
connect( mBoxSpaceSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
Expand Down Expand Up @@ -135,7 +138,10 @@ QgsLayoutLegendWidget::QgsLayoutLegendWidget( QgsLayoutItemLegend *legend, QgsMa
mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr( "Symbols on Right" ), QgsApplication::getThemeIcon( QStringLiteral( "/mIconArrangeSymbolsRight.svg" ) ) );

mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
mGroupSideSpinBox->setClearValue( 0 );
mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
mSubgroupSideSpinBox->setClearValue( 0 );
mSymbolSideSpaceSpinBox->setClearValue( 0 );

// setup icons
mAddToolButton->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
Expand Down Expand Up @@ -228,12 +234,15 @@ void QgsLayoutLegendWidget::setGuiElements()
mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
mTitleSpaceBottomSpinBox->setValue( mLegend->style( QgsLegendStyle::Title ).margin( QgsLegendStyle::Bottom ) );
mGroupSpaceSpinBox->setValue( mLegend->style( QgsLegendStyle::Group ).margin( QgsLegendStyle::Top ) );
mGroupSideSpinBox->setValue( mLegend->style( QgsLegendStyle::Group ).margin( QgsLegendStyle::Left ) );
mSpaceBelowGroupHeadingSpinBox->setValue( mLegend->style( QgsLegendStyle::Group ).margin( QgsLegendStyle::Bottom ) );
mLayerSpaceSpinBox->setValue( mLegend->style( QgsLegendStyle::Subgroup ).margin( QgsLegendStyle::Top ) );
mSpaceBelowSubgroupHeadingSpinBox->setValue( mLegend->style( QgsLegendStyle::Subgroup ).margin( QgsLegendStyle::Bottom ) );
mSubgroupSideSpinBox->setValue( mLegend->style( QgsLegendStyle::Subgroup ).margin( QgsLegendStyle::Left ) );
// We keep Symbol and SymbolLabel Top in sync for now
mSymbolSpaceSpinBox->setValue( mLegend->style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Top ) );
mIconLabelSpaceSpinBox->setValue( mLegend->style( QgsLegendStyle::SymbolLabel ).margin( QgsLegendStyle::Left ) );
mSymbolSideSpaceSpinBox->setValue( mLegend->style( QgsLegendStyle::Symbol ).margin( QgsLegendStyle::Left ) );
mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
mLineSpacingSpinBox->setValue( mLegend->lineSpacing() );
Expand Down Expand Up @@ -466,6 +475,42 @@ void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged( double space )
}
}

void QgsLayoutLegendWidget::spaceGroupSideChanged( double space )
{
if ( mLegend )
{
mLegend->beginCommand( tr( "Change Side of Group Space" ), QgsLayoutItem::UndoLegendGroupSpace );
mLegend->rstyle( QgsLegendStyle::Group ).setMargin( QgsLegendStyle::Left, space );
mLegend->adjustBoxSize();
mLegend->update();
mLegend->endCommand();
}
}

void QgsLayoutLegendWidget::spaceSubGroupSideChanged( double space )
{
if ( mLegend )
{
mLegend->beginCommand( tr( "Change Side of Subgroup Space" ), QgsLayoutItem::UndoLegendLayerSpace );
mLegend->rstyle( QgsLegendStyle::Subgroup ).setMargin( QgsLegendStyle::Left, space );
mLegend->adjustBoxSize();
mLegend->update();
mLegend->endCommand();
}
}

void QgsLayoutLegendWidget::spaceSymbolSideChanged( double space )
{
if ( mLegend )
{
mLegend->beginCommand( tr( "Change Side of Symbol Space" ), QgsLayoutItem::UndoLegendSymbolSpace );
mLegend->rstyle( QgsLegendStyle::Symbol ).setMargin( QgsLegendStyle::Left, space );
mLegend->adjustBoxSize();
mLegend->update();
mLegend->endCommand();
}
}

void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged( double d )
{
if ( mLegend )
Expand Down Expand Up @@ -1181,9 +1226,12 @@ void QgsLayoutLegendWidget::blockAllSignals( bool b )
mSymbolHeightSpinBox->blockSignals( b );
mGroupSpaceSpinBox->blockSignals( b );
mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
mGroupSideSpinBox->blockSignals( b );
mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
mSubgroupSideSpinBox->blockSignals( b );
mLayerSpaceSpinBox->blockSignals( b );
mSymbolSpaceSpinBox->blockSignals( b );
mSymbolSideSpaceSpinBox->blockSignals( b );
mIconLabelSpaceSpinBox->blockSignals( b );
mBoxSpaceSpinBox->blockSignals( b );
mColumnSpaceSpinBox->blockSignals( b );
Expand Down
5 changes: 5 additions & 0 deletions src/gui/layout/qgslayoutlegendwidget.h
Expand Up @@ -136,6 +136,11 @@ class GUI_EXPORT QgsLayoutLegendWidget: public QgsLayoutItemBaseWidget, private
void spaceBelowSubGroupHeadingChanged( double space );
void spaceBelowGroupHeadingChanged( double space );

void spaceGroupSideChanged( double space );
void spaceSubGroupSideChanged( double space );

void spaceSymbolSideChanged( double space );

private:
QgsLayoutLegendWidget() = delete;
void blockAllSignals( bool b );
Expand Down

0 comments on commit 36339c2

Please sign in to comment.