Skip to content

Commit 93f2eec

Browse files
committedJul 13, 2016
[composer] Fix initial size of legend is wrong if symbol size in
map units is used (fix #11921) On behalf of Faunalia, sponsored by ENEL
1 parent 19dbd66 commit 93f2eec

File tree

6 files changed

+103
-8
lines changed

6 files changed

+103
-8
lines changed
 

‎src/core/composer/qgscomposerlegend.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,10 @@ QgsComposerLegend::QgsComposerLegend( QgsComposition* composition )
4242
, mFilterOutAtlas( false )
4343
, mFilterAskedForUpdate( false )
4444
, mInAtlas( false )
45+
, mInitialMapScaleCalculated( false )
4546
{
4647
mLegendModel2 = new QgsLegendModelV2( QgsProject::instance()->layerTreeRoot() );
4748

48-
adjustBoxSize();
49-
5049
connect( &mLegendModel, SIGNAL( layersChanged() ), this, SLOT( synchronizeWithModel() ) );
5150

5251
connect( &composition->atlasComposition(), SIGNAL( renderEnded() ), this, SLOT( onAtlasEnded() ) );
@@ -115,12 +114,7 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem
115114
ms.setOutputDpi( dpi );
116115
mSettings.setMapScale( ms.scale() );
117116
}
118-
119-
drawBackground( painter );
120-
painter->save();
121-
//antialiasing on
122-
painter->setRenderHint( QPainter::Antialiasing, true );
123-
painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
117+
mInitialMapScaleCalculated = true;
124118

125119
QgsLegendRenderer legendRenderer( mLegendModel2, mSettings );
126120
legendRenderer.setLegendSize( rect().size() );
@@ -140,6 +134,12 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem
140134
setSceneRect( evalItemRect( targetRect, true ) );
141135
}
142136

137+
drawBackground( painter );
138+
painter->save();
139+
//antialiasing on
140+
painter->setRenderHint( QPainter::Antialiasing, true );
141+
painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
142+
143143
legendRenderer.drawLegend( painter );
144144

145145
painter->restore();
@@ -170,6 +170,15 @@ QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )
170170

171171
void QgsComposerLegend::adjustBoxSize()
172172
{
173+
if ( !mInitialMapScaleCalculated )
174+
{
175+
// this is messy - but until we have painted the item we have no knowledge of the current DPI
176+
// and so cannot correctly calculate the map scale. This results in incorrect size calculations
177+
// for marker symbols with size in map units, causing the legends to initially expand to huge
178+
// sizes if we attempt to calculate the box size first.
179+
return;
180+
}
181+
173182
QgsLegendRenderer legendRenderer( mLegendModel2, mSettings );
174183
QSizeF size = legendRenderer.minimumSize();
175184
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );

‎src/core/composer/qgscomposerlegend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
293293
void doUpdateFilterByMap();
294294

295295
bool mInAtlas;
296+
297+
//! Will be false until the associated map scale and DPI have been calculated
298+
bool mInitialMapScaleCalculated;
296299
};
297300

298301
#endif

‎tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ADD_PYTHON_TEST(PyQgsColorSchemeRegistry test_qgscolorschemeregistry.py)
2525
ADD_PYTHON_TEST(PyQgsComposerEffects test_qgscomposereffects.py)
2626
ADD_PYTHON_TEST(PyQgsComposerHtml test_qgscomposerhtml.py)
2727
ADD_PYTHON_TEST(PyQgsComposerLabel test_qgscomposerlabel.py)
28+
ADD_PYTHON_TEST(PyQgsComposerLegend test_qgscomposerlegend.py)
2829
ADD_PYTHON_TEST(PyQgsComposerMap test_qgscomposermap.py)
2930
ADD_PYTHON_TEST(PyQgsComposerMapGrid test_qgscomposermapgrid.py)
3031
ADD_PYTHON_TEST(PyQgsComposerPicture test_qgscomposerpicture.py)
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for QgsComposerLegend.
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = '(C) 2016 by Nyall Dawson'
10+
__date__ = '13/07/2016'
11+
__copyright__ = 'Copyright 2016, The QGIS Project'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
from qgis.PyQt.QtCore import QRectF
16+
from qgis.PyQt.QtGui import QColor
17+
18+
from qgis.core import (QgsComposerLegend,
19+
QgsComposerMap,
20+
QgsComposition,
21+
QgsMapSettings,
22+
QgsVectorLayer,
23+
QgsMapLayerRegistry,
24+
QgsMarkerSymbolV2,
25+
QgsSingleSymbolRendererV2
26+
)
27+
from qgis.testing import (start_app,
28+
unittest
29+
)
30+
from utilities import unitTestDataPath
31+
from qgscompositionchecker import QgsCompositionChecker
32+
import os
33+
34+
start_app()
35+
TEST_DATA_DIR = unitTestDataPath()
36+
37+
38+
class TestQgsComposerLegend(unittest.TestCase):
39+
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+
47+
def testInitialSizeSymbolMapUnits(self):
48+
"""Test initial size of legend with a symbol size in map units"""
49+
50+
marker_symbol = QgsMarkerSymbolV2.createSimple({'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit'})
51+
52+
self.point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol))
53+
54+
s = QgsMapSettings()
55+
s.setLayers([self.point_layer.id()])
56+
s.setCrsTransformEnabled(False)
57+
composition = QgsComposition(s)
58+
composition.setPaperSize(297, 210)
59+
60+
composer_map = QgsComposerMap(composition, 20, 20, 80, 80)
61+
composer_map.setFrameEnabled(True)
62+
composition.addComposerMap(composer_map)
63+
composer_map.setNewExtent(self.point_layer.extent())
64+
65+
legend = QgsComposerLegend(composition)
66+
legend.setSceneRect(QRectF(120, 20, 80, 80))
67+
legend.setFrameEnabled(True)
68+
legend.setFrameOutlineWidth(2)
69+
legend.setBackgroundColor(QColor(200, 200, 200))
70+
legend.setTitle('')
71+
composition.addComposerLegend(legend)
72+
legend.setComposerMap(composer_map)
73+
74+
checker = QgsCompositionChecker(
75+
'composer_legend_mapunits', composition)
76+
checker.setControlPathPrefix("composer_legend")
77+
result, message = checker.testComposition()
78+
self.assertTrue(result, message)
79+
80+
81+
if __name__ == '__main__':
82+
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.