14

I am trying to add new layers into a specific group which I can get to work if I know the index, but how can I get Python to find the index of a group so it can load the new layer into the group wherever it is in the TOC?

qgis.utils.iface.legendInterface().moveLayer( layer, index )

3 Answers 3

31

[Updated to QGIS v3.x]

With the new layer list widget (aka legend, ToC or layer tree) added by Martin Dobias since QGIS v.2.4, you can follow this procedure from the QGIS Python console in order to add layers to a specific group (you won't need group indices anymore):

  1. Get the reference of the layer tree.

    root = QgsProject.instance().layerTreeRoot()

  2. Find the desired group (which could be a subgroup).

    mygroup = root.findGroup("streets_group") # We assume the group exists

  3. Create the layer object.

    mylayer = QgsVectorLayer("/Path/to/your/data.shp", "my layer", "ogr")

  4. Load it to the QgsProject (set the second parameter to False since you want to define a custom position for the layer).

    QgsProject.instance().addMapLayer(mylayer, False)

  5. Add the layer to the desired group.

    mygroup.addLayer(mylayer)

Source: QGIS Layer Tree API, Part 1 and Part 2, by Martin Dobias

0
7

Recently I stumbled upon the same problem. It's not a recent question anymore, but for anyone else having the same question, here's the trick.

toc = self.iface.legendInterface() # `toc`: table of contents
groups = toc.groups()

Now you have all groups listed in the groups variable. Based on the name of a group you can find the index, and move your new layer to the intended group based on the index:

groupIndex = groups.index(u'myGroup')
toc.moveLayer(newLayer, groupIndex)

This is more an extra, but in case the group myGroup would not exist, an error or exception will be thrown. You can handle that with try and except blocks.

# Do as what normally could/should be done...
try:
    groupIndex = groups.index(u'myGroup')
    toc.moveLayer(newLayer, groupIndex)
# Do this if the try didn't work...
except:
    groupIndex = toc.addGroup(u'myGroup', True)
    toc.moveLayer(newLayer, groupIndex)
4

I got tired of forgetting whatever the inputs to the various tree layer methods are so I made a function to handle all that for me. It takes whatever thing (group name, layer id, QgsMapLayer, or QgsLayerTreeNode) you want moved and moves it to a group, creating the group as needed. You can also pass in a group object, too, in case you forget that the group API only allows strings.

def move_to_group(thing, group, pos=0, expanded=False):
    """Move a layer tree node into a layer tree group.

    Parameter
    ---------

    thing : group name (str), layer id (str), qgis.core.QgsMapLayer, qgis.core.QgsLayerTreeNode

      Thing to move.  Can be a tree node (i.e. a layer or a group) or
      a map layer, the object or the string name/id.

    group : group name (str) or qgis.core.QgsLayerTreeGroup

      Group to move the thing to. If group does not already exist, it
      will be created.

    pos : int

      Position to insert into group. Default is 0.

    extended : bool

      Collapse or expand the thing moved. Default is False.

    Returns
    -------

    Tuple containing the moved thing and the group moved to.

    Note
    ----

    Moving destroys the original thing and creates a copy. It is the
    copy which is returned.

    """

    tree = qgis.core.QgsProject.instance().layerTreeRoot()

    # thing
    if isinstance(thing, str):
        try:  # group name
            node_object = tree.findGroup(thing)
        except:  # layer id
            node_object = tree.findLayer(thing)
    elif isinstance(thing, qgis.core.QgsMapLayer):
        node_object = tree.findLayer(thing)
    elif isinstance(thing, qgis.core.QgsLayerTreeNode):
        node_object = thing  # tree layer or group

    # group
    if isinstance(group, qgis.core.QgsLayerTreeGroup):
        group_name = group.name()
    else:  # group is str
        group_name = group

    group_object = tree.findGroup(group_name)

    if not group_object:
        group_object = tree.addGroup(group_name)

    # do the move
    node_object_clone = node_object.clone()
    node_object_clone.setExpanded(expanded)
    group_object.insertChildNode(pos, node_object_clone)

    parent = node_object.parent()
    parent.removeChildNode(node_object)

    return (node_object_clone, group_object)

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