Skip to content

Commit

Permalink
[composer] Fix initial size of legend is wrong if symbol size in
Browse files Browse the repository at this point in the history
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 93f2eec
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 8 deletions.
25 changes: 17 additions & 8 deletions src/core/composer/qgscomposerlegend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() ) );
Expand Down Expand Up @@ -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() );
Expand All @@ -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();
Expand Down Expand Up @@ -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() ) );
Expand Down
3 changes: 3 additions & 0 deletions src/core/composer/qgscomposerlegend.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
82 changes: 82 additions & 0 deletions tests/src/python/test_qgscomposerlegend.py
Original file line number Diff line number Diff line change
@@ -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()
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
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 93f2eec

Please sign in to comment.