4. Accéder à la table des matières (TOC)

Indication

Les extraits de code sur cette page nécessitent les importations suivantes si vous êtes en dehors de la console pyqgis :

from qgis.core import (
    QgsProject,
    QgsVectorLayer,
)

Vous pouvez utiliser différentes classes pour accéder à toutes les couches chargées dans la table des matières et les utiliser pour récupérer des informations :

4.1. The QgsProject class

Vous pouvez utiliser QgsProject pour récupérer des informations sur la table des matières et toutes les couches chargées.

Vous devez créer une instance de QgsProject et utiliser ses méthodes pour obtenir les couches chargées.

La principale méthode est mapLayers(). Elle retournera un dictionnaire des couches chargées :

layers = QgsProject.instance().mapLayers()
print(layers)
{'countries_89ae1b0f_f41b_4f42_bca4_caf55ddbe4b6': <QgsVectorLayer: 'countries' (ogr)>}

Les clés du dictionnaire sont les ids uniques des couches, tandis que les valeurs sont les objets correspondants.

Il est désormais facile d’obtenir toute autre information sur les couches :

1# list of layer names using list comprehension
2l = [layer.name() for layer in QgsProject.instance().mapLayers().values()]
3# dictionary with key = layer name and value = layer object
4layers_list = {}
5for l in QgsProject.instance().mapLayers().values():
6  layers_list[l.name()] = l
7
8print(layers_list)
{'countries': <QgsVectorLayer: 'countries' (ogr)>}

Vous pouvez également interroger la TOC en utilisant le nom de la couche :

country_layer = QgsProject.instance().mapLayersByName("countries")[0]

Note

Une liste avec toutes les couches correspondantes est retournée, donc nous indexons avec [0] pour obtenir la première couche avec ce nom.

4.2. QgsLayerTreeGroup class

L’arbre à couches est une structure arborescente classique constituée de nœuds. Il existe actuellement deux types de nœuds : les nœuds de groupe (QgsLayerTreeGroup) et les nœuds de couche (QgsLayerTreeLayer).

Note

Pour plus d’informations, vous pouvez lire ces messages de Martin Dobias sur son blog : Part 1 Part 2 Part 3

On peut accéder facilement à l’arbre des couches du projet avec la méthode layerTreeRoot() de la classe QgsProject :

root = QgsProject.instance().layerTreeRoot()

root est un nœud de groupe et a des enfants :

root.children()

Une liste des enfants directs est renvoyée. Les enfants du sous-groupe doivent être consultés par leur propre parent direct.

Nous pouvons récupérer un des enfants :

child0 = root.children()[0]
print(child0)
<QgsLayerTreeLayer: countries>

Les couches peuvent également être récupérées en utilisant leur id (unique) :

ids = root.findLayerIds()
# access the first layer of the ids list
root.findLayer(ids[0])

Et les groupes peuvent également être recherchés en utilisant leurs noms :

root.findGroup('Group Name')

QgsLayerTreeGroup a de nombreuses autres méthodes utiles qui peuvent être utilisées pour obtenir plus d’informations sur la TOC :

# list of all the checked layers in the TOC
checked_layers = root.checkedLayers()
print(checked_layers)
[<QgsVectorLayer: 'countries' (ogr)>]

Maintenant, ajoutons quelques couches à l’arbre des couches du projet. Il y a deux façons de le faire :

  1. Ajout explicite en utilisant les fonctions addLayer() ou insertLayer() :

    1# create a temporary layer
    2layer1 = QgsVectorLayer("path_to_layer", "Layer 1", "memory")
    3# add the layer to the legend, last position
    4root.addLayer(layer1)
    5# add the layer at given position
    6root.insertLayer(5, layer1)
    
  2. Ajout implicite : puisque l’arbre des couches du projet est connecté au registre des couches, il suffit d’ajouter une couche au registre des couches de la carte :

    QgsProject.instance().addMapLayer(layer1)
    

Vous pouvez facilement passer de QgsVectorLayer à QgsLayerTreeLayer :

node_layer = root.findLayer(country_layer.id())
print("Layer node:", node_layer)
print("Map layer:", node_layer.layer())
Layer node: <QgsLayerTreeLayer: countries>
Map layer: <QgsVectorLayer: 'countries' (ogr)>

Les groupes peuvent être ajoutés avec la méthode addGroup(). Dans l’exemple ci-dessous, le premier ajoutera un groupe à la fin de la table des matières, tandis que pour le second, vous pouvez ajouter un autre groupe à l’intérieur d’un groupe existant :

node_group1 = root.addGroup('Simple Group')
# add a sub-group to Simple Group
node_subgroup1 = node_group1.addGroup("I'm a sub group")

Pour déplacer les nœuds et les groupes, il existe de nombreuses méthodes utiles.

Le déplacement d’un nœud existant se fait en trois étapes :

  1. le clonage du nœud existant

  2. le déplacement du nœud cloné vers la position souhaitée

  3. en supprimant le nœud d’origine

1# clone the group
2cloned_group1 = node_group1.clone()
3# move the node (along with sub-groups and layers) to the top
4root.insertChildNode(0, cloned_group1)
5# remove the original node
6root.removeChildNode(node_group1)

Il est un peu plus compliqué de déplacer une couche dans la légende :

 1# get a QgsVectorLayer
 2vl = QgsProject.instance().mapLayersByName("countries")[0]
 3# create a QgsLayerTreeLayer object from vl by its id
 4myvl = root.findLayer(vl.id())
 5# clone the myvl QgsLayerTreeLayer object
 6myvlclone = myvl.clone()
 7# get the parent. If None (layer is not in group) returns ''
 8parent = myvl.parent()
 9# move the cloned layer to the top (0)
10parent.insertChildNode(0, myvlclone)
11# remove the original myvl
12root.removeChildNode(myvl)

ou le déplacer vers un groupe existant :

 1# get a QgsVectorLayer
 2vl = QgsProject.instance().mapLayersByName("countries")[0]
 3# create a QgsLayerTreeLayer object from vl by its id
 4myvl = root.findLayer(vl.id())
 5# clone the myvl QgsLayerTreeLayer object
 6myvlclone = myvl.clone()
 7# create a new group
 8group1 = root.addGroup("Group1")
 9# get the parent. If None (layer is not in group) returns ''
10parent = myvl.parent()
11# move the cloned layer to the top (0)
12group1.insertChildNode(0, myvlclone)
13# remove the QgsLayerTreeLayer from its parent
14parent.removeChildNode(myvl)

Quelques autres méthodes qui peuvent être utilisées pour modifier les groupes et les couches :

 1node_group1 = root.findGroup("Group1")
 2# change the name of the group
 3node_group1.setName("Group X")
 4node_layer2 = root.findLayer(country_layer.id())
 5# change the name of the layer
 6node_layer2.setName("Layer X")
 7# change the visibility of a layer
 8node_group1.setItemVisibilityChecked(True)
 9node_layer2.setItemVisibilityChecked(False)
10# expand/collapse the group view
11node_group1.setExpanded(True)
12node_group1.setExpanded(False)