6

I'm trying to group a large number of layers together based on a common portion of name string. They are a mix of polygons and points. I would like to create individual groups by using part of the layer's name. Anyone have any ideas? I was looking to build a plugin but I am unable to (due to my coding abilities).

I attached a picture to show what I'm looking for as the end result. I have projects with a large amount of information that needs to be grouped.

enter image description here

2
  • Are you trying to do this programmatically? If not, can you edit your question to explain how it differs from gis.stackexchange.com/questions/120599/…?
    – Chris W
    Commented Apr 6, 2015 at 20:49
  • Yes. Im trying to find a way to group layers based on their name. Thus creating multipule groups.
    – Tyler
    Commented Apr 6, 2015 at 20:57

2 Answers 2

9

You can do it in three steps: Get group names, create groups, and move layers.

For testing purposes, I've replicated your sample scenario:

enter image description here

Run the following code snippet in your QGIS Python console:

# 1. Get group names and list of layer ids
root = QgsProject.instance().layerTreeRoot()
dictGroups={}
for layer in root.findLayers():
  if QgsLayerTree.isLayer(layer):
    prefix="Site "+layer.layerName().split("_")[0] # Adjust this to fit your needs
    if not prefix in dictGroups:
      dictGroups[prefix]=[]
    dictGroups[prefix].append(layer.layerId())

# 2. Create groups
for key in dictGroups:
  root.addGroup(key)

# 3. Move layers
for key in dictGroups:
  parent = root.findGroup(key)
  for id in dictGroups[key]:
    layer = root.findLayer(id)
    clone = layer.clone()
    parent.insertChildNode(0, clone)
    root.removeChildNode(layer)

You should get something like this:

enter image description here

0
2

I'm only adding a little extra here but I hope the explination may help others.

I spent a long time wrapping my head around nodes vs layers.

It seems that the Layers are the "heavy weight" underlying objects, and the nodes are used to represent the arrangement in the tree. (https://qgis.org/api/classQgsLayerTreeNode.html#details)

I offer the below code with couple of advantages over the accepted post (and I would't have gotten here with out the accepted answer, so THANK YOU to Germán Carrillo):

  1. It manipulates the tree rather than any layers. (Actually, just double-checked the docs - findLayer does actually return a LayerTreeNode (as a LayerTreeLayer), so stays in the "node" realm. Sometimes shortening names can lead to misdirection...)
  2. It gets the selected nodes and only forms them into a sub-group. (This was my own personal use-case, not necessarily what the OP asked for.)
  3. Keeps object (node) references rather than collecting and the re-looking up QGIS layer id's.
  4. Uses addChildNode rather than insertChildNode(0,..., in order to preserve the order of the nodes in the new group.
  5. Deliberately using an extra loop so I could verify correct working before deleting the original nodes. (The last three loops can actually be combined.)

#

v = iface.layerTreeView()
# v.collapseAllNodes()
nodes = v.selectedNodes()
parent = nodes[0].parent()

groups = {}
for n in nodes: 
    key = n.name()[:1]
    if not key in groups:
        groups[key]=[]
    groups[key].append(n)

new_groups = {}
for key in groups:
    grp_name = key+'00'
    grp = parent.addGroup(grp_name)
    new_groups[key] = grp

for key in groups:
    new_group = new_groups[key]
    for n in groups[key]:
        clone = n.clone()
        new_group.addChildNode(clone)

for key in groups:
    for n in groups[key]:
        parent.removeChildNode(n)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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