Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix interplay of legend atlas filtering and multiple map
extent filtering
  • Loading branch information
nyalldawson committed Mar 30, 2023
1 parent efa9765 commit ab6c1c5
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/core/layout/qgslayoutitemlegend.cpp
Expand Up @@ -1137,6 +1137,8 @@ void QgsLayoutItemLegend::doUpdateFilterByMap()
filterGeometry = QgsGeometry::fromQPolygonF( ( *linkedFilterMaps.constBegin() )->visibleExtentPolygon() );
}

const QgsGeometry atlasGeometry = mInAtlas ? mLayout->reportContext().currentGeometry( ms.destinationCrs() ) : QgsGeometry();

QgsLayerTreeFilterSettings filterSettings( ms );

if ( !linkedFilterMaps.empty() )
Expand All @@ -1162,6 +1164,11 @@ void QgsLayoutItemLegend::doUpdateFilterByMap()
const QList< QgsMapLayer * > layersForMap = map->layersToRender();
for ( QgsMapLayer *layer : layersForMap )
{
if ( !atlasGeometry.isNull() )
{
mapExtent = mapExtent.intersection( atlasGeometry );
}

filterSettings.addVisibleExtentForLayer( layer, QgsReferencedGeometry( mapExtent, ms.destinationCrs() ) );
}
}
Expand Down
101 changes: 100 additions & 1 deletion tests/src/python/test_qgslayoutlegend.py
Expand Up @@ -44,7 +44,9 @@
QgsRuleBasedRenderer,
QgsSingleSymbolRenderer,
QgsVectorLayer,
QgsReadWriteContext
QgsReadWriteContext,
QgsFeature,
QgsGeometry
)
from qgis.testing import start_app, unittest

Expand Down Expand Up @@ -1118,6 +1120,103 @@ def test_filter_by_map_content_rendering_different_layers(self):
TestQgsLayoutItemLegend.report += checker.report()
self.assertTrue(result, message)

def test_filter_by_map_content_rendering_different_layers_in_atlas(self):
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
point_layer = QgsVectorLayer(point_path, 'points', 'ogr')

point_layer2 = QgsVectorLayer(point_path, 'points2', 'ogr')

root_rule = QgsRuleBasedRenderer.Rule(None)
marker_symbol = QgsMarkerSymbol.createSimple(
{'color': '#ff0000', 'outline_style': 'no', 'size': '8'})

marker_symbol = QgsMarkerSymbol.createSimple(
{'color': '#00ffff', 'outline_style': 'no', 'size': '4'})
one_rule = QgsRuleBasedRenderer.Rule(marker_symbol,
filterExp='"Pilots" = 1',
label='1')
root_rule.appendChild(one_rule)
marker_symbol = QgsMarkerSymbol.createSimple(
{'color': '#ff8888', 'outline_style': 'no', 'size': '4'})
two_rule = QgsRuleBasedRenderer.Rule(marker_symbol,
filterExp='"Pilots" = 2',
label='2')
root_rule.appendChild(two_rule)
marker_symbol = QgsMarkerSymbol.createSimple(
{'color': '#8888ff', 'outline_style': 'no', 'size': '4'})
three_rule = QgsRuleBasedRenderer.Rule(marker_symbol,
filterExp='"Pilots" = 3',
label='3')
root_rule.appendChild(three_rule)

renderer = QgsRuleBasedRenderer(root_rule)
point_layer.setRenderer(renderer)

marker_symbol = QgsMarkerSymbol.createSimple(
{'color': '#003366', 'outline_style': 'no', 'size': '8'})
point_layer2.setRenderer(QgsSingleSymbolRenderer(marker_symbol))

p = QgsProject()
p.addMapLayers([point_layer, point_layer2])

layout = QgsLayout(p)
layout.initializeDefaults()

map = QgsLayoutItemMap(layout)
map.attemptSetSceneRect(QRectF(19, 17, 100, 165))
map.setFrameEnabled(True)
map.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
map.setLayers([point_layer])
map.zoomToExtent(QgsRectangle(-108.52403736600929562, 22.4408089916287814, -97.776639147740255, 29.00866345834875304))
map.setMapRotation(45)

layout.addLayoutItem(map)

map2 = QgsLayoutItemMap(layout)
map2.attemptSetSceneRect(QRectF(150, 117, 100, 165))
map2.setFrameEnabled(True)
map2.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
map2.setLayers([point_layer2])
map2.setExtent(QgsRectangle(-12309930, 3091263, -11329181, 3977074))

layout.addLayoutItem(map2)

legend = QgsLayoutItemLegend(layout)
legend.setLegendFilterByMapEnabled(True)
legend.setLinkedMap(map2)
legend.setFilterByMapItems([map])
layout.addLayoutItem(legend)
legend.setTitle("Legend")
legend.attemptSetSceneRect(QRectF(220, 20, 20, 20))
legend.setFrameEnabled(True)
legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
legend.setBackgroundColor(QColor(200, 200, 200))
legend.setTitle('')

legend.setStyleFont(QgsLegendStyle.Title, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.Group, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.Subgroup, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.Symbol, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.SymbolLabel,
QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setLegendFilterOutAtlas(True)

atlas_layer = QgsVectorLayer(
"Polygon?field=fldtxt:string&field=fldint:integer",
"addfeat", "memory")
layout.reportContext().setLayer(atlas_layer)
f = QgsFeature()
f.setGeometry(QgsGeometry.fromWkt('Polygon ((-115.422 42.22, -118.202 36.246, -103.351 22.06, -102.314 22.682, -116.542 37.159, -113.348 41.846, -98.747 39.98, -93.313 47.281, -94.225 47.861, -99.95 41.39, -114.51 43.34, -115.422 42.22))'))
layout.reportContext().setFeature(f)
legend.refresh()

checker = QgsLayoutChecker(
'legend_multiple_filter_maps_different_layers_atlas', layout)
checker.setControlPathPrefix("composer_legend")
result, message = checker.testLayout()
TestQgsLayoutItemLegend.report += checker.report()
self.assertTrue(result, message)


if __name__ == '__main__':
unittest.main()
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 ab6c1c5

Please sign in to comment.