2

I have a QGIS project with multiple layouts (in total about 30) in my layout manager. I used of the "Follow map theme" then "Lock layers" options in the Map item properties to make sure that each layout is displaying the correct layer. However after I am done making all the layouts I would like to make sure that they are displaying the correct layers.

Is there a way in QGIS to verify which layer is being displayed in the layout? Making all the layouts manually is prone to error. This option is absolutely necessary to make big map making projects possible.

I am also open to using the Python API to do this.


I have made some progress:

project = QgsProject.instance()
manager = project.layoutManager()
layouts = manager.layouts
layout = layouts[0]
items = layout.items()

#find map object
for item in items:
    if isinstance(item, qgis._core.QgsLayoutItemMap):
        map_object = item

#Here need to find map object somehow
layers = map_object.layers

The above will extract the layers as QgsVectorLayer or QgsRasterLayer objects. Unfortunately this is not enough, I would also like to extract the position of the QgsVectorLayer in the layer tree. I found out how to go down a layer tree from this post. However when I get down to the object of interest it returns it as a QgsLayerTreeLayer.

It is possible to extract the underlying layer from the tree layer by doing this:

layer_from_layer_tree = tree_layer.layer()

And it is apparently possible to also do this:

layer_from_layer_tree==layer_from_map_layout
>>> True

But I am not sure if this is the recommended way to compare two layer objects, and if objects which are not equal will return False.

In any case, I think it is very convoluted. Verifying which layers are in your layout should be a basic functionality available directly in the GUI.

1 Answer 1

1

Here's a script I came up with to do this:

project = QgsProject.instance()
manager = project.layoutManager()
layouts = manager.layouts()


for layout in layouts:

    items = layout.items()

    #find map object
    for item in items:
        if isinstance(item, qgis._core.QgsLayoutItemMap):
            map_object = item

    #Here need to find map object somehow
    layers = map_object.layers()
    print('LAYOUT NAME: ', layout.name())

    for layer in layers:
        root=project.layerTreeRoot()
        for node in root.children():
            for subnode in node.children():
                for layer_tree_object in subnode.children():
                    layer_from_layer_tree = layer_tree_object.layer()
                    layer_from_map_object = layer

                    if layer_from_layer_tree == layer_from_map_object:

                        print('GROUP NAME: ', node.name())
                        print('SUBGROUP NAME: ', subnode.name())
                        print('LAYER NAME: ', layer_from_layer_tree.name())
                        print('\n')

In my case I am using groups and subgroups in my layer tree manager so I need to navigate through the .children() objects. In your case, it may be different. It all depends on the layout. At the end of the day it will be necessary to extract the layer objects from within the layer tree manager and within the map object in your layout, then compare the two.

I am still quite annoyed that such a simple check requires such an extensive use of the API.

1
  • That's what apis for, you could do a plugin from this and share it, then it's part of the gui ;-) Commented Jun 26, 2019 at 7:49

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