Skip to content
Permalink
Browse files

[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
  • Loading branch information
nyalldawson committed Jul 13, 2016
1 parent 19dbd66 commit 93f2eec711f2d3e1593f497db581a7e6973cfcc9
@@ -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() ) );
@@ -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
@@ -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)
@@ -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.
Binary file not shown.

0 comments on commit 93f2eec

Please sign in to comment.
You can’t perform that action at this time.