2

I am trying to write a simple script to copy the selected features from the active layer to a new memory layer. This would be equivalent to Edit -> Copy Features, Edit -> Paste Features As -> Temporary Scratch Layer.

The code I have so far is

#Get the type of the active layer
active_layer = iface.activeLayer()
geom_type = active_layer.geometryType()
if geom_type == QgsWkbTypes.PointGeometry:
    type_string = "Point"
elif geom_type == QgsWkbTypes.LineGeometry:
    type_string = "LineString"
elif geom_type == QgsWkbTypes.PolygonGeometry:
    type_string = "Polygon"
else:
    type_string = "unexpected"


#create a url from the layer type and the layer crs
crs = active_layer.sourceCrs();
url = type_string + '?' + crs.authid()

#create the new memory layer
new_layer = QgsVectorLayer(url, "copy", "memory")

#add the attributes of the active layer to the new memory layer`
attrs = active_layer.dataProvider().fields().toList()
new_layer.dataProvider().addAttributes(attrs)
new_layer.updateFields()

#copy the selecton from the active layer and paste to the new memory layer, add to TOC
iface.copySelectionToClipboard(active_layer)
iface.pasteFromClipboard(new_layer)
QgsProject.instance().addMapLayer(new_layer)

When executed the new layer is created, appears in the layer list, and the attribute table shows the appropriate fields. A pop-up at the top of the QGIS canvas says "n features were successfully pasted", but the attribute table of the new memory layer remains empty.

What key step(s) am I missing?

(This is just an exercise in trying to learn a bit about PyQGIS, so any other comments on approach are more than welcome).

3

I stumbled on a simpler two line method in the PyQGIS cookbook:

memory_layer = iface.activeLayer().materialize(QgsFeatureRequest().setFilterFids(iface.activeLayer().selectedFeatureIds()))
QgsProject.instance().addMapLayer(memory_layer)

This has the advantage that is copies any properties of the layer that might be getting missed in the code I was trying, such as a CRS that can't be represented by an EPSG code.

2

Use edit mode. Change the last seven lines as follows:

...
...

attrs = active_layer.dataProvider().fields().toList()    

with edit(new_layer):
    for attr in attrs:
        new_layer.addAttribute(attr)

    iface.copySelectionToClipboard(active_layer)
    iface.pasteFromClipboard(new_layer)

QgsProject.instance().addMapLayer(new_layer)
1
  • Thanks - that works. I wondered if I needed to put the layer in edit mode or something, but couldn't find anything. It doesn't appear to be necessary to add the attributes inside the with edit(...) block, the original code for that works fine.
    – Llaves
    Oct 18 '20 at 23:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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