Skip to content

Commit

Permalink
Extra tweaks to legend column auto breaking when manual breaks are pr…
Browse files Browse the repository at this point in the history
…esent
  • Loading branch information
nyalldawson committed May 6, 2020
1 parent d574bf7 commit f09ec88
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/core/qgslegendrenderer.cpp
Expand Up @@ -439,6 +439,7 @@ int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups
// the target number of columns allowed is dictated by the number of forced column
// breaks OR the manually set column count (whichever is greater!)
const int targetNumberColumns = std::max( forcedColumnBreaks + 1, mSettings.columnCount() );
const int numberAutoPlacedBreaks = targetNumberColumns - forcedColumnBreaks - 1;

// We know height of each group and we have to split them into columns
// minimizing max column height. It is sort of bin packing problem, NP-hard.
Expand All @@ -450,11 +451,12 @@ int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups
int currentColumnGroupCount = 0; // number of groups in current column
double currentColumnHeight = 0;
double closedColumnsHeight = 0;
int autoPlacedBreaks = 0;

for ( int i = 0; i < componentGroups.size(); i++ )
{
// Recalc average height for remaining columns including current
double avgColumnHeight = ( totalHeight - closedColumnsHeight ) / ( targetNumberColumns - currentColumn );
double avgColumnHeight = ( totalHeight - closedColumnsHeight ) / ( numberAutoPlacedBreaks + 1 - autoPlacedBreaks );

LegendComponentGroup group = componentGroups.at( i );
double currentHeight = currentColumnHeight;
Expand All @@ -463,7 +465,8 @@ int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups
currentHeight += group.size.height();

bool canCreateNewColumn = ( currentColumnGroupCount > 0 ) // do not leave empty column
&& ( currentColumn < targetNumberColumns - 1 ); // must not exceed max number of columns
&& ( currentColumn < targetNumberColumns - 1 ) // must not exceed max number of columns
&& ( autoPlacedBreaks < numberAutoPlacedBreaks );

bool shouldCreateNewColumn = ( currentHeight - avgColumnHeight ) > group.size.height() / 2 // center of current group is over average height
&& currentColumnGroupCount > 0 // do not leave empty column
Expand All @@ -481,6 +484,8 @@ int QgsLegendRenderer::setColumns( QList<LegendComponentGroup> &componentGroups
{
// New column
currentColumn++;
if ( !group.placeColumnBreakBeforeGroup )
autoPlacedBreaks++;
currentColumnGroupCount = 0;
closedColumnsHeight += currentColumnHeight;
currentColumnHeight = group.size.height();
Expand Down
46 changes: 46 additions & 0 deletions tests/src/core/testqgslegendrenderer.cpp
Expand Up @@ -164,6 +164,8 @@ class TestQgsLegendRenderer : public QObject
void testColumnBreaks();
void testColumnBreaks2();
void testColumnBreaks3();
void testColumnBreaks4();
void testColumnBreaks5();
void testRasterStroke();
void testFilterByPolygon();
void testFilterByExpression();
Expand Down Expand Up @@ -985,6 +987,50 @@ void TestQgsLegendRenderer::testColumnBreaks3()
QVERIFY( _verifyImage( testName, mReport ) );
}

void TestQgsLegendRenderer::testColumnBreaks4()
{
QString testName = QStringLiteral( "legend_column_breaks4" );

QgsLayerTreeModel legendModel( mRoot );

QgsLayerTreeLayer *layer = legendModel.rootGroup()->findLayer( mVL3 );
QgsMapLayerLegendUtils::setLegendNodeColumnBreak( layer, 0, true );
legendModel.refreshLayerLegend( layer );

layer = legendModel.rootGroup()->findLayer( mRL );
QgsMapLayerLegendUtils::setLegendNodeColumnBreak( layer, 0, true );
legendModel.refreshLayerLegend( layer );

QgsLegendSettings settings;
settings.setColumnCount( 5 );
settings.setSplitLayer( true );
_setStandardTestFont( settings, QStringLiteral( "Bold" ) );
_renderLegend( testName, &legendModel, settings );
QVERIFY( _verifyImage( testName, mReport ) );
}

void TestQgsLegendRenderer::testColumnBreaks5()
{
QString testName = QStringLiteral( "legend_column_breaks5" );

QgsLayerTreeModel legendModel( mRoot );

QgsLayerTreeLayer *layer = legendModel.rootGroup()->findLayer( mVL3 );
QgsMapLayerLegendUtils::setLegendNodeColumnBreak( layer, 0, true );
legendModel.refreshLayerLegend( layer );

layer = legendModel.rootGroup()->findLayer( mRL );
QgsMapLayerLegendUtils::setLegendNodeColumnBreak( layer, 0, true );
legendModel.refreshLayerLegend( layer );

QgsLegendSettings settings;
settings.setColumnCount( 4 );
settings.setSplitLayer( false );
_setStandardTestFont( settings, QStringLiteral( "Bold" ) );
_renderLegend( testName, &legendModel, settings );
QVERIFY( _verifyImage( testName, mReport ) );
}

void TestQgsLegendRenderer::testRasterStroke()
{
QString testName = QStringLiteral( "legend_raster_border" );
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f09ec88

Please sign in to comment.