5

I want to clone my generated memory layer and apply different filters and symbology. The clone is visible in the layer tree, but doesn't show up in the canvas. What am I doing wrong?

uri = f'point?crs=EPSG:25832&field=id:integer&index=yes'
l_out = QgsVectorLayer(uri, 'new layer', 'memory')

x, y = 369000, 5616000
with edit(l_out):
    for i in range(10):
        f = QgsFeature(l_out.fields())
        g = QgsGeometry(QgsPoint(x, y))
        f.setGeometry(g)
        f.setAttributes([i])
        l_out.addFeature(f)
        x += 50
        y += 50

project = QgsProject.instance()
project.addMapLayer(l_out)

tree = project.layerTreeRoot()
group0 = tree.insertGroup(0, 'level 0')
group1 = group0.addGroup('level 1')

lcopy = project.addMapLayer(l_out.clone(), False)
nodecopy = group1.insertLayer(-1, lcopy)
1
  • If you use fix geometry it works. The first layer that is visible has memory://point?crs=EPSG:25832. The second before fixing has memory://memory?geometry=Point&crs=EPSG:25832, after fixing memory://Point?crs=EPSG:25832. you dont get any errors that had been fixed, not in qgis fixing and not in v.clean
    – Xeppit
    Commented Feb 18 at 22:02

1 Answer 1

6

There are several suggestions regarding your code:

  • adding the same layer l_out one more time to the project, even with the addToLegend = False does not make much sense to me. In the documentation for the addMapLayer() method, it says what Returns it possesses:

    nullptr if unable to add layer, otherwise pointer to newly added layer

    However, the type of the lcopy-variable is the QgsVectorLayer. On the another side, the insertLayer() method works with QgsMapLayer and QgsVectorLayer.

  • no need to create the nodecopy-object, simply proceed with:

    group1.insertLayer(-1, lcopy)
    
  • application of these methods i.e. isValid() and hasFeatures() can be useful to check if your QgsVectorLayer is solid:

    if l_out.isValid() and l_out.hasFeatures():
       ...
    

I can also suggest several workarounds:

  1. using the findLayer() method of the QgsLayerTreeGroup class:

    project = QgsProject.instance()
    project.addMapLayer(l_out)
    
    tree = project.layerTreeRoot()
    
    group0 = tree.insertGroup(0, 'level 0')
    group1 = group0.addGroup('level 1')
    
    layer = tree.findLayer(l_out.id()) # QgsLayerTreeLayer
    lcopy = layer.clone() # QgsLayerTreeLayer
    group1.insertChildNode(0, lcopy)
    
  2. proceeding without cloning:

    project = QgsProject.instance()
    project.addMapLayer(l_out)
    
    tree = project.layerTreeRoot()
    group0 = tree.insertGroup(0, 'level 0')
    group1 = group0.addGroup('level 1')
    
    group1.insertLayer(-1, l_out)
    
  3. applying the materialize() method:

     project = QgsProject.instance()
     project.addMapLayer(l_out)
    
     tree = project.layerTreeRoot()
     group0 = tree.insertGroup(0, 'level 0')
     group1 = group0.addGroup('level 1')
    
     lcopy = l_out.materialize(QgsFeatureRequest().setFilterFids(l_out.allFeatureIds())) # QgsVectorLayer
     group1.insertLayer(-1, lcopy)
    
2
  • Before editing this answer you suggested using layer.materialize(). That worked for me and so I could finish a projekt in time :). Your workaround with findLayer clones the complete layer tree node including the layer itself, that's appealing. As @Xeppit notes, my clone had the source prefix "memory?geometry=Point&" instead of "point?". I wonder if that syntax is valid or if this is a bug in clone().
    – Redoute
    Commented Feb 20 at 14:37
  • My error, findlayer().clone() clones the node, but not the layer: I can't set individual filters on the clones. So I have to stay with layer.materialize().
    – Redoute
    Commented Feb 20 at 16:02

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.