3

How can I remove multiple layers from legend in the MapComposer without removing them from the canvas and without having to specified their group ?

In the code below I have to add group = root_group.findGroup("group_name_1") to remove the layers belonging to this group but I would like to find a way to remove the layers without having to indicate their group name... Is it possible ?

layers_to_remove = []

legend = [i for i in layout.items() if isinstance(i, QgsLayoutItemLegend)][0]
root_group = legend.model().rootGroup()  
group = root_group.findGroup("group_name_1")  
legend.setAutoUpdateModel(False)
for layer in layers_to_remove:
    root_group.removeLayer(layer)  
2
  • All layers have unique names? Commented Dec 21, 2022 at 11:00
  • Yes they only have unique names !
    – Linda
    Commented Dec 21, 2022 at 11:22

1 Answer 1

5

You can find the group dynamically by getting the name of the layer's parent in the layer tree:

# reference to the project
p = QgsProject.instance()

# names of layers to remove from legend
layers_to_remove = ['layer1', 'layer2']

# the layer tree
root = p.layerTreeRoot()

# layout manager
manager = p.layoutManager()

# first layout (can also use manager.layoutByName() )
layout = manager.layouts()[0]

# get legend
legend = [i for i in layout.items() if isinstance(i, QgsLayoutItemLegend)][0]

# disable auto-update
legend.setAutoUpdateModel(False)

# legend model
model = legend.model()

# the root legend group
root_group = model.rootGroup()

# loop through layer names
for layer_name in layers_to_remove:
    # find layer in project
    layer = p.mapLayersByName(layer_name)[0]
    
    # get layer tree layer instance of layer
    layertreelayer = root.findLayer(layer.id())
    
    # get the parent of the layer tree layer (layer tree root, or group)
    parent = layertreelayer.parent()
    
    # if the parent is a group and has a name, find it and remove the layer
    if isinstance(parent, QgsLayerTreeGroup) and parent.name():
        group = root_group.findGroup(parent.name())
        group.removeLayer(layer)
    # remove layers that are not in a group
    else:
        root_group.removeLayer(layer)
        
# update legend
legend.adjustBoxSize()
layout.refresh()

Note: there will need to be some extra logic (e.g. recursion) added to deal with sub-groups.

9
  • Hi Matt ! Qgis says "AttributeError: 'NoneType' object has no attribute 'removeLayer'". The "group" variable does not seem to be recognized !
    – Linda
    Commented Dec 22, 2022 at 9:06
  • What does parent.name() return?
    – Matt
    Commented Dec 22, 2022 at 9:42
  • with print(parent.name()) : The group names of the layers to be removed
    – Linda
    Commented Dec 22, 2022 at 9:45
  • Are any of your groups subgroups (a group within a group)? With 'first level' groups the script works flawlessly when I test it.
    – Matt
    Commented Dec 22, 2022 at 10:38
  • 1
    Well discovered :) although that doesn't make a difference for me (QGIS 3.28.1). Layer/group visibility can be unchecked but they still react to the script. I'm glad you got it working.
    – Matt
    Commented Dec 22, 2022 at 11:04

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.