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 )
PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Seth Loader
  • 151
  • 2
  • 5

3 Answers3

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

Germán Carrillo
  • 36,307
  • 5
  • 123
  • 178
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)
Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
kadéem
  • 565
  • 4
  • 14
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)

Lorem Ipsum
  • 279
  • 1
  • 7