PyQGIS Layer Group – Adding Layer to Group and Subgroup and Assigning Color in PyQGIS

pyqgispython

So I have this script which works great:

import time
import processing
from os.path import join, normpath

start_tot = time.time()

path = normpath('C:\\Users\\hejhej\\Dropbox\\Documents\\')

ext = ".shp"

layers = ["a", "b", "c"] 

municipalities = ["1", "2", "3"]

for layer in layers:

    start = time.time()    

    for value in municipalities:

    
        input_layer = join(path, layer + ext)
        input_municipality = join(path, value + ext)

        alg_params1 = {
            'INPUT' : input_layer,
            'OVERLAY' : input_municipality,
            'OUTPUT' : 'memory:'
            }

        res1 = processing.run("native:clip", alg_params1)['OUTPUT']

        output_layer = join(path, layer + "_" + value + ext)

        alg_params2 = {
            'INPUT' : res1,
            'OUTPUT' : output_layer
            }
    
        res2 = processing.run("native:multiparttosingleparts", alg_params2)  
    
        iface.addVectorLayer(output_layer, 'counties', 'ogr')

        end = time.time()
        print("Elapsed time for", layer+"_"+value, ":", end-start, "seconds.")

end_tot = time.time()
print()
print("Total time elapsed:", (end_tot-start_tot)/60, "minutes.")

Which I give full credit to @taras

I would like to upgrade this fine script by making the script put the various layers into the correct group and sub group as well as give each layer its designated colour, instead of having to do this manually afterwards.

I guess the nesting (nested lists/dictionaries) is something I can sort out myself, once I have the correct lines in place for the other stuff.

How would I make all the newly created layers to be red and to end up in a subgroup called "luke" which is in a group called "lucky"?

I have been looking at solutions such as Adding layer to group using PyQGIS for grouping and Changing color of vector layer using PyQGIS for colouring, but I can't quite figure it out myself.

edit:

This is now how the script has evolved:

import time
import processing
from os.path import join, normpath

start_tot = time.time()

root = QgsProject.instance().layerTreeRoot()

path = normpath('C:\\Users\\tlind\\Dropbox\\Documents\\')

ext = ".shp"

layers = ["1", "2", "3"] 

municipalities = ["a", "b", "c"]

for layer in layers:

    start = time.time()    

    for value in municipalities:

    
        input_layer = join(path, layer + ext)
        input_municipality = join(path, value + ext)

        alg_params1 = {
            'INPUT' : input_layer,
            'OVERLAY' : input_municipality,
            'OUTPUT' : 'memory:'
            }

        res1 = processing.run("native:clip", alg_params1)['OUTPUT']

        output_layer = join(path, layer + "_" + value + ext)

        alg_params2 = {
            'INPUT' : res1,
            'OUTPUT' : output_layer
            }
    
        res2 = processing.run("native:multiparttosingleparts", alg_params2)  
    
        vlayer = iface.addVectorLayer(output_layer, "", "ogr")
    
        vlayer.renderer().symbol().setColor(QColor("blue"))
        vlayer.triggerRepaint() 
        iface.layerTreeView().refreshLayerSymbology(vlayer.id())
    
        moving = QgsProject.instance().mapLayersByName(layer+"_"+value)[0]
        mylayer = root.findLayer(moving.id())
        myClone = mylayer.clone()
        parent = mylayer.parent()

        group = root.findGroup("kalmar")
        subgroup = group.findGroup(value)
        subgroup.insertChildNode(0, myClone)

        parent.removeChildNode(mylayer)

        end = time.time()
        print("Elapsed time for", layer+"_"+value, ":", end-start, "seconds.")

end_tot = time.time()
print()
print("Total time elapsed:", (end_tot-start_tot)/60, "minutes.")

I've managed to reach a step where everything is working as it should be, although I want to go deeper. What I want now may be outside PyQGIS and actually just some standard Python feature, but I would like to give different colours to the layers depending on the "layers" array.

Is there anyone who has any bright ideas?

Best Answer

Please limit the scope of your post to one specific question to fit the 'one question - best answer' model of GIS SE (feel free to post further questions about your other issues).

I will address your first question: Adding a layer to group and subgroup

Creating a subgroup is as easy as creating a top-level group in the root, as you have already done. Incidentally, by using QgsVectorLayer instead of iface.addVectorLayer, you can skip the cloning part. The symbology etc can still be manipulated on the layer object before it is added to the canvas.

root = QgsProject.instance().layerTreeRoot()

# add a group to the layer tree root
# the first argument is the position at which to insert the group, 0 being top
group = root.insertGroup(0, 'lucky')

# create a group 'luke' inside the group named 'lucky'
subgroup = group.insertGroup(0, 'luke')

# create an instance of the layer, but it is not yet added to the canvas
vlayer = QgsVectorLayer(output_layer, 'my layer name', 'ogr')

# configure symbology of vlayer here

# add the layer to the (sub)group
subgroup.addLayer(vlayer)
Related Question