Skip to content

Commit 4f31ab6

Browse files
committedJul 13, 2016
[composer] Fix setting legend content by map not resizing legend
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
1 parent 93f2eec commit 4f31ab6

File tree

5 files changed

+66
-13
lines changed

5 files changed

+66
-13
lines changed
 

‎src/core/composer/qgscomposerlegend.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ QgsComposerLegend::QgsComposerLegend( QgsComposition* composition )
4343
, mFilterAskedForUpdate( false )
4444
, mInAtlas( false )
4545
, mInitialMapScaleCalculated( false )
46+
, mForceResize( false )
4647
{
4748
mLegendModel2 = new QgsLegendModelV2( QgsProject::instance()->layerTreeRoot() );
4849

@@ -66,6 +67,8 @@ QgsComposerLegend::QgsComposerLegend()
6667
, mFilterOutAtlas( false )
6768
, mFilterAskedForUpdate( false )
6869
, mInAtlas( false )
70+
, mInitialMapScaleCalculated( false )
71+
, mForceResize( false )
6972
{
7073

7174
}
@@ -117,11 +120,18 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem
117120
mInitialMapScaleCalculated = true;
118121

119122
QgsLegendRenderer legendRenderer( mLegendModel2, mSettings );
120-
legendRenderer.setLegendSize( rect().size() );
123+
legendRenderer.setLegendSize( mForceResize ? QSize() : rect().size() );
121124

122125
//adjust box if width or height is too small
123126
QSizeF size = legendRenderer.minimumSize();
124-
if ( size.height() > rect().height() || size.width() > rect().width() )
127+
if ( mForceResize )
128+
{
129+
mForceResize = false;
130+
//set new rect, respecting position mode and data defined size/position
131+
QRectF targetRect = QRectF( pos().x(), pos().y(), size.width(), size.height() );
132+
setSceneRect( evalItemRect( targetRect, true ) );
133+
}
134+
else if ( size.height() > rect().height() || size.width() > rect().width() )
125135
{
126136
//need to resize box
127137
QRectF targetRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
@@ -673,6 +683,8 @@ void QgsComposerLegend::doUpdateFilterByMap()
673683
}
674684
else
675685
mLegendModel2->setLegendFilterByMap( nullptr );
686+
687+
mForceResize = true;
676688
}
677689

678690
void QgsComposerLegend::setLegendFilterOutAtlas( bool doFilter )

‎src/core/composer/qgscomposerlegend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
296296

297297
//! Will be false until the associated map scale and DPI have been calculated
298298
bool mInitialMapScaleCalculated;
299+
300+
//! Will be true if the legend size should be totally reset at next paint
301+
bool mForceResize;
299302
};
300303

301304
#endif

‎tests/src/python/test_qgscomposerlegend.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
QgsVectorLayer,
2323
QgsMapLayerRegistry,
2424
QgsMarkerSymbolV2,
25-
QgsSingleSymbolRendererV2
25+
QgsSingleSymbolRendererV2,
26+
QgsRectangle
2627
)
2728
from qgis.testing import (start_app,
2829
unittest
@@ -37,30 +38,27 @@
3738

3839
class TestQgsComposerLegend(unittest.TestCase):
3940

40-
def __init__(self, methodName):
41-
"""Run once on class initialization."""
42-
unittest.TestCase.__init__(self, methodName)
43-
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
44-
self.point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
45-
QgsMapLayerRegistry.instance().addMapLayers([self.point_layer])
46-
4741
def testInitialSizeSymbolMapUnits(self):
4842
"""Test initial size of legend with a symbol size in map units"""
4943

44+
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
45+
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
46+
QgsMapLayerRegistry.instance().addMapLayers([point_layer])
47+
5048
marker_symbol = QgsMarkerSymbolV2.createSimple({'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit'})
5149

52-
self.point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol))
50+
point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol))
5351

5452
s = QgsMapSettings()
55-
s.setLayers([self.point_layer.id()])
53+
s.setLayers([point_layer.id()])
5654
s.setCrsTransformEnabled(False)
5755
composition = QgsComposition(s)
5856
composition.setPaperSize(297, 210)
5957

6058
composer_map = QgsComposerMap(composition, 20, 20, 80, 80)
6159
composer_map.setFrameEnabled(True)
6260
composition.addComposerMap(composer_map)
63-
composer_map.setNewExtent(self.point_layer.extent())
61+
composer_map.setNewExtent(point_layer.extent())
6462

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

78+
QgsMapLayerRegistry.instance().removeMapLayers([point_layer])
79+
80+
def testResizeWithMapContent(self):
81+
"""Test test legend resizes to match map content"""
82+
83+
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
84+
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
85+
QgsMapLayerRegistry.instance().addMapLayers([point_layer])
86+
87+
s = QgsMapSettings()
88+
s.setLayers([point_layer.id()])
89+
s.setCrsTransformEnabled(False)
90+
composition = QgsComposition(s)
91+
composition.setPaperSize(297, 210)
92+
93+
composer_map = QgsComposerMap(composition, 20, 20, 80, 80)
94+
composer_map.setFrameEnabled(True)
95+
composition.addComposerMap(composer_map)
96+
composer_map.setNewExtent(point_layer.extent())
97+
98+
legend = QgsComposerLegend(composition)
99+
legend.setSceneRect(QRectF(120, 20, 80, 80))
100+
legend.setFrameEnabled(True)
101+
legend.setFrameOutlineWidth(2)
102+
legend.setBackgroundColor(QColor(200, 200, 200))
103+
legend.setTitle('')
104+
legend.setLegendFilterByMapEnabled(True)
105+
composition.addComposerLegend(legend)
106+
legend.setComposerMap(composer_map)
107+
108+
composer_map.setNewExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))
109+
110+
checker = QgsCompositionChecker(
111+
'composer_legend_size_content', composition)
112+
checker.setControlPathPrefix("composer_legend")
113+
result, message = checker.testComposition()
114+
self.assertTrue(result, message)
115+
116+
QgsMapLayerRegistry.instance().removeMapLayers([point_layer])
117+
80118

81119
if __name__ == '__main__':
82120
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.