0

I am working on a QGIS plugin in python. In this plugin I load two layers. These layers are polygons which represent administrative boundaries. My plugin load also several print layout in a Qgis project. In these print layout there is a legend. I would like that in the legend of the composer it is displayed only the layers that are visible in the map of the composer. The problem is that my administrative boundaries are represented as a polygon and therefore the layer is always present in my map while the administrative boundaries are not visible in the map if I use the option "Show features only inside the linked map". How can I do not to display the layers of the administrative boundaries in the legend if they are not visible in the extent of the map ? I tried this code.

project = QgsProject.instance()
root = QgsProject.instance().layerTreeRoot()
groupe_admin = root.addGroup("Limites administratives")
        
dep_layer = QgsVectorLayer('C:/dep.shp', 'DEPARTEMENT', 'ogr')
reg_layer = QgsVectorLayer('C:/reg.shp', 'REGIONS', 'ogr')
QgsProject.instance().addMapLayer(dep_layer, False)
QgsProject.instance().addMapLayer(reg_layer, False)
groupe_admin.addLayer(dep_layer)
groupe_admin.addLayer(reg_layer)
processing.run("qgis:polygonstolines", {'INPUT': dep_layer, 'OUTPUT': 'C:/dep_lignes.shp'})
processing.run("qgis:polygonstolines", {'INPUT': reg_layer, 'OUTPUT': 'C:/reg_lignes.shp'})
depL_layer = QgsVectorLayer('C:/dep_lignes.shp', 'DEP', 'ogr')
regL_layer = QgsVectorLayer('C:/reg_lignes.shp', 'REG', 'ogr')
QgsProject.instance().addMapLayer(depL_layer, False)
QgsProject.instance().addMapLayer(regL_layer, False)

layout = QgsPrintLayout(project)
document = QDomDocument()
template_file = open('C:/Users/Thysma/Documents/Stage/Composeurs/A4 PT.qpt')
template_content = template_file.read()
template_file.close()
document.setContent(template_content)
layout.loadFromTemplate(document, QgsReadWriteContext())
project.layoutManager().addLayout(layout)
map = layout.itemById("map")

processing.run("qgis:extenttolayer", {'INPUT': map.extent(), 'OUTPUT': 'C:/emprise_carte.shp'})
layout_map_layer = QgsVectorLayer('C:/emprise_carte.shp', 'Emprise Carte', 'ogr')
processing.run("qgis:selectbylocation", {'INPUT': depL_layer,
                                         'PREDICATE': 0,
                                         'INTERSECT': layout_map_layer,
                                         'METHOD': 0})

depL_feat = depL_layer.selectedFeatureCount()
if depL_feat == 0:
    depL_layer.removeSelection()
    depL_feat = 0
    legend = [i for i in layout.items() if isinstance(i, QgsLayoutItemLegend)][0]
    legend.setAutoUpdateModel(False)
    rootGroup_admin = 
    legend.model().rootGroup().findGroup('Limitesadministratives')
    rootGroup_admin.removeLayer(dep_layer)
    legend.adjustBoxSize()
    layout.refresh()



enter image description here

3
  • Your problem seems to be that the layer is present, you just don't see any of the borders - so you need to check if the outline of the polygon intersects the bounds of the map.
    – Ian Turton
    Commented Apr 23, 2021 at 8:05
  • Does converting administrative boundary layers into line geometry work for you? Commented Apr 23, 2021 at 8:06
  • Yes Ian ! I already thought about this idea but I don't know how to do it... Commented Apr 23, 2021 at 8:20

2 Answers 2

1

You can set the map extent based on your line layer like this :

ms = QgsMapSettings()
context = QgsRenderContext.fromMapSettings(ms)
ms.setLayers([line_layer])
rect = QgsRectangle(ms.fullExtent())
rect.scale(1.2)
ms.setExtent(rect)
map.setExtent(rect)
layout.addLayoutItem(map)

Then when you add the legend you can compare the extent of your layers with your map extent, if your map extent contains you layer extent then the layer will be in the legend. Like in this code :

layers = [layer for layer in QgsProject.instance().mapLayers().values()]    
legend = QgsLayoutItemLegend(layout)
layerTree = QgsLayerTree()
for layer in layers :
    if rect.contains(layer.extent()):
        layerTree.addLayer(layer)
legend.model().setRootGroup(layerTree)
layout.addLayoutItem(legend)

With those 2 layers in my project : enter image description here

I obtain something like this :

enter image description here

0

A solution I have tested in QGIS :

  1. Produce a line layer with the tool polygonstolines
  2. In your legend add this layer and errase the department and region layer.
  3. Activate the filter to show legend only for item inside atlas item (see capture under)

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.