1

I am working on a QGIS plugin. The database for the plugin is a GeoPackage. Part of the plugin includes the ability to import features from outside databases by clicking a button.

The problem I am having is that all the attributes that I am mapping from outside data to the plugin GeoPackage db are getting copied but the geometry is not.

The first thing I tried was:

new_model_feature = QgsFeature(model_fields)
new_model_feature.setGeometry(source_feature.geometry())

That did not work. Then I tried:

new_model_feature = QgsFeature(model_fields)
source_geometry = QgsGeometry().fromWkb(source_feature.geometry().asWkb())
new_model_feature.setGeometry(source_geometry)

Nothing seems to be able to set the geometry correctly in the new feature. Again, attributes copy (code not shown) but not geometry. What am I missing here? I open the attribute table in the GeoPackage and everything looks normal. I set up my GeoPackage layer like this:

QgsVectorLayer('MultiLineString', 'Pipes', 'memory')

Other things I have tried don't seem to make a difference either:

  • Change the geometry type of the plugin layer
  • Export the external layer to shapefile before trying to import

Also, I have tried exploring the geometry by printing the WKT to console and get something like this:

MultiLineString ((2274935.15752089023590088 6929719.31379280984401703, 2274938.08763313293457031 6929258.37376980483531952))

which seems normal.

Any ideas?

I would really rather not deconstruct the WKT into components and then rebuild since that would be incredibly slow since, in my current project I am using the plugin for, the source data has hundreds of thousands of features I am trying to import and then keep synchronized over time.

EDIT:

Based on your comments @bugmenot123, I changed to edit session but I still can't get it to work. Here is the whole method:

def sync_source(self, source_info):
    # use OGR specific exceptions   https://gis.stackexchange.com/questions/372385/converting-an-esri-gdb-to-gpkg-using-pyqgis
    ogr.UseExceptions()
    # get the driver
    driver = ogr.GetDriverByName("OpenFileGDB")
    try:
        gdb = driver.Open(source_info['SOURCE_LOCATION'], 0)
    except Exception as e:
        print(e)
    imported_features = []
    source_num = source_info['DATA_SOURCE']
    model_layername = source_info['MODEL_LAYER']
    model_layer = self.project.werqs_db.layer_objects[model_layername]
    model_fields = model_layer.fields()
    source_layer_name = source_info['TABLE_NAME']
    source_layer_uri = f'{source_info["SOURCE_LOCATION"]}|layername={source_layer_name}'
    source_layer = QgsVectorLayer(source_layer_uri, source_layer_name, 'ogr')
    # BUILD UID LISTS
    source_UID_field = source_info['TABLE_UID_FIELD']
    source_layer_UIDs = set([])
    for source_feature in source_layer.getFeatures():  # source_layer_request
        source_UID = source_feature[source_UID_field]
        if source_UID in self.source_UIDs:  # duplicate, track but don't use
            self.source_duplicate_UIDs.append(source_UID)
        source_layer_UIDs.add(source_UID)
    import_UIDs = []
    # WORK ON IMPORTS
    model_layer.startEditing()
    features_to_import = []
    for source_feature in source_layer.getFeatures():
        source_UID = source_feature[source_UID_field]
        if source_UID in import_UIDs and source_UID not in self.source_duplicate_UIDs:
            imported_features.append(source_feature)
            new_model_feature = QgsFeature(model_fields)
            new_model_feature.setGeometry(source_feature.geometry())
            new_model_feature['UID'] = source_UID
            features_to_import.append(new_model_feature)
    QgsMessageLog.logMessage(f'there are {len(features_to_import)} features that are attempting addition', 'WaterwerQs Plugin', Qgis.Info)
    model_layer.addFeatures(features_to_import)
    model_layer.commitChanges()
    model_layer.updateExtents()
    self.iface.mapCanvas().refreshAllLayers()
5
  • Where exactly do you judge if it worked or not? Is new_model_feature.geometry() not the correct geometry after you setGeometryd it? Feb 1, 2023 at 17:45
  • The features don't show up in the map. Feb 1, 2023 at 18:48
  • model_layer_data_provider = model_layer.dataProvider() model_layer_data_provider.addFeatures(features_to_import) model_layer.commitChanges() model_layer.updateExtents() self.iface.mapCanvas().refreshAllLayers() Feb 1, 2023 at 18:50
  • Does not help either Feb 1, 2023 at 18:51
  • Why do you not add the feature directly via qgis.org/pyqgis/master/core/… or qgis.org/pyqgis/master/core/… but using the low-level qgis.org/pyqgis/master/core/… ? What does the return code say? Are you in edit mode? Your code sample is very sparse. Feb 1, 2023 at 19:05

2 Answers 2

2

You seem to be missing an active edit mode and you might have an easier time using the high-level QgsVectorLayer methods instead of the low-level QgsVectorDataProvider.

Here is an example that should hopefully work, adjust the layer names:

source_layer = QgsProject.instance().mapLayersByName("a")[0]
target_layer = QgsProject.instance().mapLayersByName("b")[0]

source_feature = next(source_layer.getFeatures())

new_feature = QgsFeature()
new_feature.setGeometry(source_feature.geometry())

with edit(target_layer):
    success = target_layer.addFeature(new_feature)
if not success:
    print("Error...")
0

This was a symbology issue that I missed. No wonder it did not make sense.

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.