Skip to content

Commit

Permalink
[composer] Fix setting legend content by map not resizing legend
Browse files Browse the repository at this point in the history
When a legend was set to filter content by map, it wasn't
consistently being resized to fit the legend contents. This caused
issues for atlas exports where legends could grow but never
shrink.

Fix #14707

On behalf of Faunalia, sponsored by ENEL
  • Loading branch information
nyalldawson committed Jul 13, 2016
1 parent 93f2eec commit 4f31ab6
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 13 deletions.
16 changes: 14 additions & 2 deletions src/core/composer/qgscomposerlegend.cpp
Expand Up @@ -43,6 +43,7 @@ QgsComposerLegend::QgsComposerLegend( QgsComposition* composition )
, mFilterAskedForUpdate( false )
, mInAtlas( false )
, mInitialMapScaleCalculated( false )
, mForceResize( false )
{
mLegendModel2 = new QgsLegendModelV2( QgsProject::instance()->layerTreeRoot() );

Expand All @@ -66,6 +67,8 @@ QgsComposerLegend::QgsComposerLegend()
, mFilterOutAtlas( false )
, mFilterAskedForUpdate( false )
, mInAtlas( false )
, mInitialMapScaleCalculated( false )
, mForceResize( false )
{

}
Expand Down Expand Up @@ -117,11 +120,18 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem
mInitialMapScaleCalculated = true;

QgsLegendRenderer legendRenderer( mLegendModel2, mSettings );
legendRenderer.setLegendSize( rect().size() );
legendRenderer.setLegendSize( mForceResize ? QSize() : rect().size() );

//adjust box if width or height is too small
QSizeF size = legendRenderer.minimumSize();
if ( size.height() > rect().height() || size.width() > rect().width() )
if ( mForceResize )
{
mForceResize = false;
//set new rect, respecting position mode and data defined size/position
QRectF targetRect = QRectF( pos().x(), pos().y(), size.width(), size.height() );
setSceneRect( evalItemRect( targetRect, true ) );
}
else if ( size.height() > rect().height() || size.width() > rect().width() )
{
//need to resize box
QRectF targetRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
Expand Down Expand Up @@ -673,6 +683,8 @@ void QgsComposerLegend::doUpdateFilterByMap()
}
else
mLegendModel2->setLegendFilterByMap( nullptr );

mForceResize = true;
}

void QgsComposerLegend::setLegendFilterOutAtlas( bool doFilter )
Expand Down
3 changes: 3 additions & 0 deletions src/core/composer/qgscomposerlegend.h
Expand Up @@ -296,6 +296,9 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem

//! Will be false until the associated map scale and DPI have been calculated
bool mInitialMapScaleCalculated;

//! Will be true if the legend size should be totally reset at next paint
bool mForceResize;
};

#endif
Expand Down
60 changes: 49 additions & 11 deletions tests/src/python/test_qgscomposerlegend.py
Expand Up @@ -22,7 +22,8 @@
QgsVectorLayer,
QgsMapLayerRegistry,
QgsMarkerSymbolV2,
QgsSingleSymbolRendererV2
QgsSingleSymbolRendererV2,
QgsRectangle
)
from qgis.testing import (start_app,
unittest
Expand All @@ -37,30 +38,27 @@

class TestQgsComposerLegend(unittest.TestCase):

def __init__(self, methodName):
"""Run once on class initialization."""
unittest.TestCase.__init__(self, methodName)
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
self.point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
QgsMapLayerRegistry.instance().addMapLayers([self.point_layer])

def testInitialSizeSymbolMapUnits(self):
"""Test initial size of legend with a symbol size in map units"""

point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
QgsMapLayerRegistry.instance().addMapLayers([point_layer])

marker_symbol = QgsMarkerSymbolV2.createSimple({'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit'})

self.point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol))
point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol))

s = QgsMapSettings()
s.setLayers([self.point_layer.id()])
s.setLayers([point_layer.id()])
s.setCrsTransformEnabled(False)
composition = QgsComposition(s)
composition.setPaperSize(297, 210)

composer_map = QgsComposerMap(composition, 20, 20, 80, 80)
composer_map.setFrameEnabled(True)
composition.addComposerMap(composer_map)
composer_map.setNewExtent(self.point_layer.extent())
composer_map.setNewExtent(point_layer.extent())

legend = QgsComposerLegend(composition)
legend.setSceneRect(QRectF(120, 20, 80, 80))
Expand All @@ -77,6 +75,46 @@ def testInitialSizeSymbolMapUnits(self):
result, message = checker.testComposition()
self.assertTrue(result, message)

QgsMapLayerRegistry.instance().removeMapLayers([point_layer])

def testResizeWithMapContent(self):
"""Test test legend resizes to match map content"""

point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
QgsMapLayerRegistry.instance().addMapLayers([point_layer])

s = QgsMapSettings()
s.setLayers([point_layer.id()])
s.setCrsTransformEnabled(False)
composition = QgsComposition(s)
composition.setPaperSize(297, 210)

composer_map = QgsComposerMap(composition, 20, 20, 80, 80)
composer_map.setFrameEnabled(True)
composition.addComposerMap(composer_map)
composer_map.setNewExtent(point_layer.extent())

legend = QgsComposerLegend(composition)
legend.setSceneRect(QRectF(120, 20, 80, 80))
legend.setFrameEnabled(True)
legend.setFrameOutlineWidth(2)
legend.setBackgroundColor(QColor(200, 200, 200))
legend.setTitle('')
legend.setLegendFilterByMapEnabled(True)
composition.addComposerLegend(legend)
legend.setComposerMap(composer_map)

composer_map.setNewExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))

checker = QgsCompositionChecker(
'composer_legend_size_content', composition)
checker.setControlPathPrefix("composer_legend")
result, message = checker.testComposition()
self.assertTrue(result, message)

QgsMapLayerRegistry.instance().removeMapLayers([point_layer])


if __name__ == '__main__':
unittest.main()
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 4f31ab6

Please sign in to comment.