I am working on a plugin for QGIS (2.12). It uses data stored in an Spatialite database. When the user creates a new feature, the plugin should:
- update the feature attribute table (the popup form is disabled)
- update another (non-geometry) table in the database
- if the polygon overlaps any existing polygons:
- update the polygon geometry using the difference method
The modifications do not need any user input, and can happen in 'real-time' or following a commitChanges(), but the user should remain in (or be returned to) an editing session.
What is the best strategy for this? Should I use the provider, the vector layer functions, the iface.vectorLayerTools?
So far, I have not had much success. I have a class that is created on the layer.editingStarted() signal that listens for changes to geometry. It includes the following:
def __init__(self, iface, vlayer, db): self.vlayer = vlayer self.edit_buffer = vlayer.editBuffer() def connect_signals self.edit_buffer.featureAdded.connect(self.feature_added) self.edit_buffer.geometryChanged.connect(self.geometry_changed) self.vlayer.beforeCommitChanges.connect(self.disconnect_eb_signals) self.vlayer.committedFeaturesAdded.connect(self.committed_add)
I first tried to use the edit buffer's
featureAdded() signal e.g.
def feature_added(self, fid): self.vlayer.beginEditCommand('Update attributes') self.vlayer.changeAttributeValue(fid, 1, 'new_value') self.vlayer.endEditCommand()
Using the temporary fids given to the pre-commit features prevented making the changes to the other tables, which needed to reference them. Also, this method caused QGIS to crash/segmentation fault if the Undo command was used (on Linux, and with Undo, Redo on Windows).
Is this a bug, or am I just approaching this in the wrong way?
I have also tried using the
commitedFeaturesAdded() signal. This solved the undo/redo issues and allowed me to update the attribute table directly in the database via SQL commands, after the feature was created with the final fid. However, now when I try to change the geometry and check for intersection/overlap again I get stuck in a loop of newly committed features.
Finally, I tried calculating the modified geometry, exporting as Wkt and using GeomFromText to update the
vlayer table directly. In this case, the SQL is run without error, but the geometry doesn't seem to be updated.