[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
This commit is contained in:
Nyall Dawson 2016-07-12 16:32:00 +10:00
parent 19dbd66ff1
commit 93f2eec711
6 changed files with 103 additions and 8 deletions

View File

@ -42,11 +42,10 @@ QgsComposerLegend::QgsComposerLegend( QgsComposition* composition )
, mFilterOutAtlas( false )
, mFilterAskedForUpdate( false )
, mInAtlas( false )
, mInitialMapScaleCalculated( false )
{
mLegendModel2 = new QgsLegendModelV2( QgsProject::instance()->layerTreeRoot() );
adjustBoxSize();
connect( &mLegendModel, SIGNAL( layersChanged() ), this, SLOT( synchronizeWithModel() ) );
connect( &composition->atlasComposition(), SIGNAL( renderEnded() ), this, SLOT( onAtlasEnded() ) );
@ -115,12 +114,7 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem
ms.setOutputDpi( dpi );
mSettings.setMapScale( ms.scale() );
}
drawBackground( painter );
painter->save();
//antialiasing on
painter->setRenderHint( QPainter::Antialiasing, true );
painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
mInitialMapScaleCalculated = true;
QgsLegendRenderer legendRenderer( mLegendModel2, mSettings );
legendRenderer.setLegendSize( rect().size() );
@ -140,6 +134,12 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem
setSceneRect( evalItemRect( targetRect, true ) );
}
drawBackground( painter );
painter->save();
//antialiasing on
painter->setRenderHint( QPainter::Antialiasing, true );
painter->setPen( QPen( QColor( 0, 0, 0 ) ) );
legendRenderer.drawLegend( painter );
painter->restore();
@ -170,6 +170,15 @@ QSizeF QgsComposerLegend::paintAndDetermineSize( QPainter* painter )
void QgsComposerLegend::adjustBoxSize()
{
if ( !mInitialMapScaleCalculated )
{
// this is messy - but until we have painted the item we have no knowledge of the current DPI
// and so cannot correctly calculate the map scale. This results in incorrect size calculations
// for marker symbols with size in map units, causing the legends to initially expand to huge
// sizes if we attempt to calculate the box size first.
return;
}
QgsLegendRenderer legendRenderer( mLegendModel2, mSettings );
QSizeF size = legendRenderer.minimumSize();
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ) );

View File

@ -293,6 +293,9 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
void doUpdateFilterByMap();
bool mInAtlas;
//! Will be false until the associated map scale and DPI have been calculated
bool mInitialMapScaleCalculated;
};
#endif

View File

@ -25,6 +25,7 @@ ADD_PYTHON_TEST(PyQgsColorSchemeRegistry test_qgscolorschemeregistry.py)
ADD_PYTHON_TEST(PyQgsComposerEffects test_qgscomposereffects.py)
ADD_PYTHON_TEST(PyQgsComposerHtml test_qgscomposerhtml.py)
ADD_PYTHON_TEST(PyQgsComposerLabel test_qgscomposerlabel.py)
ADD_PYTHON_TEST(PyQgsComposerLegend test_qgscomposerlegend.py)
ADD_PYTHON_TEST(PyQgsComposerMap test_qgscomposermap.py)
ADD_PYTHON_TEST(PyQgsComposerMapGrid test_qgscomposermapgrid.py)
ADD_PYTHON_TEST(PyQgsComposerPicture test_qgscomposerpicture.py)

View File

@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsComposerLegend.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = '(C) 2016 by Nyall Dawson'
__date__ = '13/07/2016'
__copyright__ = 'Copyright 2016, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.PyQt.QtCore import QRectF
from qgis.PyQt.QtGui import QColor
from qgis.core import (QgsComposerLegend,
QgsComposerMap,
QgsComposition,
QgsMapSettings,
QgsVectorLayer,
QgsMapLayerRegistry,
QgsMarkerSymbolV2,
QgsSingleSymbolRendererV2
)
from qgis.testing import (start_app,
unittest
)
from utilities import unitTestDataPath
from qgscompositionchecker import QgsCompositionChecker
import os
start_app()
TEST_DATA_DIR = unitTestDataPath()
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"""
marker_symbol = QgsMarkerSymbolV2.createSimple({'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit'})
self.point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol))
s = QgsMapSettings()
s.setLayers([self.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())
legend = QgsComposerLegend(composition)
legend.setSceneRect(QRectF(120, 20, 80, 80))
legend.setFrameEnabled(True)
legend.setFrameOutlineWidth(2)
legend.setBackgroundColor(QColor(200, 200, 200))
legend.setTitle('')
composition.addComposerLegend(legend)
legend.setComposerMap(composer_map)
checker = QgsCompositionChecker(
'composer_legend_mapunits', composition)
checker.setControlPathPrefix("composer_legend")
result, message = checker.testComposition()
self.assertTrue(result, message)
if __name__ == '__main__':
unittest.main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB