I'm writing a standalone application using QGIS API to export maps automatically as pdf.

When I'm building my QgsComposition, I have an issue:

I have already built a list with the layers I want to show on the map (not all the layers from the original project), but my QgsComposerLegend shows all the layers.

First, I tried this:

    legend = QgsComposerLegend(c)

And the result:

enter image description here

But the layer set is not the one I want.

I found this post: Filter MapComposer legend to only show layers visible on the map

I adapted its code to mine and I have this:

enter image description here

With the code:

    legend = QgsComposerLegend(c)
    layerGroup = QgsLayerTreeGroup()
    for layer in layers:
        layerGroup.insertLayer(0, layer)

The issue is that I would keep the initial tree organization, and just suppress the layers I don't want.

I tried using the QgsLayerTreeGroup methods this way:

    legend = QgsComposerLegend(c)
    layersToRemove = []
    for layer in legend.modelV2().rootGroup().findLayers():
        if layer.layer() not in layers:
    for layer in layerToRemove:
        # print(layer.id())

But I have the same result as the first code... I don't understand why, but the layers are not removed from the tree... Any idea ?

1 Answer 1


OK I managed to solve the problem...

To set my layerTree in the legend, I tried to modify directly the layerTreeRoot of the project (I work with a copy of the original project, the layers are never deleted...)

I have built a recursive function to check if each layer in the tree is in my list, and if not, I remove it.

The main code now looks like this:

    legend = QgsComposerLegend(c)
    root = buildLegendLayerTree(project.layerTreeRoot(), layers)

With the following definition for the function:

    def buildLegendLayerTree(root, layers):
        for child in root.children():
            if child.nodeType()==0: # if the child is a group node, not a layer
                child = buildLegendLayerTree(child, layers)
            else: # if it is a layer
                if child.layer() not in layers:

And now I have the result I expected :)

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.