1

I'm generating a map print layout programmatically with PyQGIS. The print layout contains 2 map items, the 'Main map' and 'Inset'. I want the inset to show 'Layer 1', 'Layer 2' and 'Layer 3' (with Layer 3 at the bottom), while the Main map will show all layers, except 'Layer 1' and 'Layer 2'.

I have tried setting the inset layers visibility then locking the layers and styles:

    map_item = layout.itemById('Inset')
    layers= self.project.mapLayers()
    insetLayers=[]
    for layerID, l in layers.items():
       if l.name() == 'Layer 3':
            self.project.layerTreeRoot().findLayer(l.id()).setItemVisibilityChecked(True)
            insetLayers.insert(0, l)
       elif l.name() in ['Layer 1', 'Layer 2']:
            self.project.layerTreeRoot().findLayer(l.id()).setItemVisibilityChecked(True)
            insetLayers.append(l)
    map_item.setLayers(insetLayers)
    map_item.setKeepLayerSet(True)
    map_item.setKeepLayerStyles(True)
    map_item.refresh()
    for l in layers.values():
         if l.name() in ['Layer 1','Layer 2']:
             self.project.layerTreeRoot().findLayer(l.id()).setItemVisibilityChecked(False)
         else:
             self.project.layerTreeRoot().findLayer(l.id()).setItemVisibilityChecked(True)

This code locked the inset layers correctly, but 'Layer 1' and 'Layer 2' were showing only their labels, not their features. This could potentially be because 'Layer 3' is above them, but 'Layer 3' is at the bottom of the layers list.

I think this could be solved by setting a data defined override for the layers being displayed, but I'm having trouble doing this. I can set the override expression in QGIS here:

QGIS print layout layers screenshot

but I can't figure how to do this in PyQGIS. I have tried:

map_item = layout.itemById('Inset')
expression = 'Layer 1|Layer 2|Layer 3'
property_expression = QgsProperty(expression)
map_item.setLayers(property_expression)
map_item.refresh()

1 Answer 1

0

The order of the layers in layout map is defined by the order of items in insetLayers list. Your code always put 'Layer 3' on the top - insetLayers.insert(0, l).

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