def __createMemoryLayer(self, layer_name, gtype, geometries, attributes, fNames, fTypes): """ Create a memory layer from parameters :param layer_name: name for the layer :param gtype: geometry type of the layer :param geometries: objects geometries :param attributes: objects attributes :param fNames: fields names :param fTypes: fields types """ layerList = QgsMapLayerRegistry.instance().mapLayersByName(layer_name) if layerList: QgsMapLayerRegistry.instance().removeMapLayers([layerList[0].id()]) epsg = self.canvas().mapRenderer().destinationCrs().authid() fieldsParam = "" for i in range(len(fNames)): fieldsParam += "&field=" + fNames[i] + ":" + fTypes[i] layer = QgsVectorLayer(gtype + "?crs=" + epsg + fieldsParam + "&index=yes", layer_name, "memory") QgsMapLayerRegistry.instance().addMapLayer(layer) layer.startEditing() for i in range(len(geometries)): feature = QgsFeature() feature.setGeometry(QgsGeometry().fromWkt(geometries[i])) fields = layer.pendingFields() feature.setFields(fields) for j in range(len(fNames)): feature.setAttribute(fNames[j], attributes[i][j]) layer.addFeature(feature) layer.commitChanges()
def create_release_as_points(): releases_point_layer = QgsVectorLayer( "Point?" "crs=epsg:3857&" "field=id:integer&" "field=name:string(20)&" "field=version:string(20)&" "field=ltr:bool&" "field=start:date&" "field=end:date&" "index=yes", "Release points", "memory") releases_point_layer.loadNamedStyle( os.path.join(FOLDER, 'qml', 'release_points.qml')) QgsProject.instance().addMapLayer(releases_point_layer, False) for i, release in enumerate(RELEASES): with edit(releases_point_layer): int_rel = i + 1 start_x = int_rel feat = QgsFeature() feat.setAttributes([ int_rel, release['name'], release['version'], release['ltr'], release['start'], release['end'] ]) feat.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(start_x * 100, start_x * 100))) releases_point_layer.addFeature(feat) return releases_point_layer
def getmap(self): if self.canvas: settings = self.canvas.mapSettings() layers = settings.layers() if GPS.isConnected: try: gpslayer = QgsMapLayerRegistry.instance().mapLayersByName("__gps_layer")[0] except IndexError: gpslayer = QgsVectorLayer("Point", "__gps_layer", "memory") symbol = QgsMarkerSymbolV2.createSimple({'name': 'circle', 'color': 'blue', "size": '5'}) gpslayer.rendererV2().setSymbol(symbol) QgsMapLayerRegistry.instance().addMapLayer(gpslayer, False) layers.append(gpslayer.id()) settings.setLayers(layers) map_pos = QgsPoint(GPS.gpsinfo("longitude"), GPS.gpsinfo("latitude")) # map_pos = QgsPoint(115.72589,-32.29597) geom = QgsGeometry.fromPoint(map_pos) feature = QgsFeature() feature.setGeometry(geom) gpslayer.startEditing() gpslayer.addFeature(feature) # gpslayer.commitChanges() self.renderjob = QgsMapRendererParallelJob(settings) self.renderjob.finished.connect(self.rendermap) self.renderjob.start()
def getmap(self): if self.canvas: settings = self.canvas.mapSettings() layers = settings.layers() if GPS.isConnected: try: gpslayer = QgsMapLayerRegistry.instance().mapLayersByName( "__gps_layer")[0] except IndexError: gpslayer = QgsVectorLayer("Point", "__gps_layer", "memory") symbol = QgsMarkerSymbolV2.createSimple({ 'name': 'circle', 'color': 'blue', "size": '5' }) gpslayer.rendererV2().setSymbol(symbol) QgsMapLayerRegistry.instance().addMapLayer(gpslayer, False) layers.append(gpslayer.id()) settings.setLayers(layers) map_pos = QgsPoint(GPS.gpsinfo("longitude"), GPS.gpsinfo("latitude")) # map_pos = QgsPoint(115.72589,-32.29597) geom = QgsGeometry.fromPoint(map_pos) feature = QgsFeature() feature.setGeometry(geom) gpslayer.startEditing() gpslayer.addFeature(feature) # gpslayer.commitChanges() self.renderjob = QgsMapRendererParallelJob(settings) self.renderjob.finished.connect(self.rendermap) self.renderjob.start()
def centroid(self): """ Create a centroid for all layers on the input layer. Everything is put into a new temporary scratch memory layer. """ # Get the layer from the combobox layer = self.layerComboBox.currentData() # Create a new scratch layer based on the original layer uri = "Point?crs={authid}&index=yes".format( authid=layer.crs().authid()) layer_name = "Centroid ({layername})".format(layername=layer.name()) new_layer = QgsVectorLayer(uri, layer_name, "memory") new_layer.startEditing() # Add all attribute definitions from the source layer for field in layer.fields(): new_layer.addAttribute(field) # Process all features for feature in layer.getFeatures(): # Here is the important call: create a centroid geom = feature.geometry().centroid() feature.setGeometry(geom) new_layer.addFeature(feature) # Save the features to the memory layer new_layer.commitChanges() QgsProject.instance().addMapLayer(new_layer)
def test_extent(self): options = QgsGroupLayer.LayerOptions(QgsCoordinateTransformContext()) group_layer = QgsGroupLayer('test', options) self.assertTrue(group_layer.isValid()) layer1 = QgsVectorLayer('Point?crs=epsg:3111', 'Point', 'memory') f = QgsFeature() f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2478778, 2487236))) layer1.startEditing() layer1.addFeature(f) layer1.commitChanges() group_layer.setChildLayers([layer1]) extent = group_layer.extent() self.assertAlmostEqual(extent.xMinimum(), 2478778, -2) self.assertAlmostEqual(extent.xMaximum(), 2478778, -2) self.assertAlmostEqual(extent.yMinimum(), 2487236, -2) self.assertAlmostEqual(extent.yMaximum(), 2487236, -2) layer2 = QgsVectorLayer('Point?crs=epsg:4326', 'Point', 'memory') f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(142.178, -35.943))) layer2.startEditing() layer2.addFeature(f) layer2.commitChanges() group_layer.setChildLayers([layer1, layer2]) extent = group_layer.extent() self.assertAlmostEqual(extent.xMinimum(), 2245407, -2) self.assertEqual(extent.xMaximum(), 2478778) self.assertEqual(extent.yMinimum(), 2487236) self.assertAlmostEqual(extent.yMaximum(), 2613508, -2)
def create_reservoirs_lay(geoms=None, ids=None, elevs=None, elevs_corr=None, crs=None): url = 'Point' if crs is not None: url += '?crs=' + crs.authid() reservoirs_lay = QgsVectorLayer(url, Parameters.reservoirs_vlay_name, 'memory') reservoirs_lay_dp = reservoirs_lay.dataProvider() reservoirs_lay_dp.addAttributes(Reservoir.fields) reservoirs_lay.updateFields() if geoms is not None: for n in range(len(geoms)): reservoir_ft = QgsFeature() reservoir_ft.setGeometry(geoms[n]) reservoir_id = ids[n] if ids is not None else None elev = elevs[n] if elevs is not None else None deltaz = elevs_corr[n] if elevs_corr is not None else None reservoir_ft.setAttribute(Reservoir.field_name_eid, reservoir_id) reservoir_ft.setAttribute(Reservoir.field_name_elev, elev) reservoir_ft.setAttribute(Reservoir.field_name_delta_z, deltaz) reservoirs_lay.addFeature(reservoir_ft) return reservoirs_lay
def create_release_as_lines(): releases_line_layer = QgsVectorLayer( "LineString?" "crs=epsg:3857&" "field=id:integer&" "field=name:string(20)&" "field=version:string(20)&" "field=ltr:bool&" "index=yes", "Release lines", "memory") with edit(releases_line_layer): for i, release in enumerate(RELEASES): int_rel = i + 1 start_x = int_rel * 100 end_x = 400 if release['ltr'] else 100 feat = QgsFeature() feat.setAttributes( [int_rel, release['name'], release['version'], release['ltr']]) feat.setGeometry( QgsGeometry.fromPolyline([ QgsPoint(start_x, start_x), QgsPoint(start_x + end_x, start_x) ])) releases_line_layer.addFeature(feat) releases_line_layer.loadNamedStyle( os.path.join(FOLDER, 'qml', 'release_lines.qml')) QgsProject.instance().addMapLayer(releases_line_layer, False) return releases_line_layer
def test_AddFeatureNullFid(self): """Test gpkg feature with NULL fid can be added""" tmpfile = os.path.join(self.basetestpath, 'testGeopackageSplitFeatures.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPolygon) lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString)) ds = None layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') # Check that pk field has unique constraint fields = layer.fields() pkfield = fields.at(0) self.assertTrue(pkfield.constraints().constraints() & QgsFieldConstraints.ConstraintUnique) # Test add feature with default Fid (NULL) layer.startEditing() f = QgsFeature() feat = QgsFeature(layer.fields()) feat.setGeometry( QgsGeometry.fromWkt('Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))')) feat.setAttribute(1, 'test_value') layer.addFeature(feat) self.assertTrue(layer.commitChanges()) self.assertEqual(layer.featureCount(), 1)
def _qgs_memory_layer(self, style, features=None): """ Create QgsVectorLayer with memory backend and load features into it """ result = QgsVectorLayer(style.parent.geometry_type, None, 'memory') provider = result.dataProvider() # Setup layer fields fldmap = {} for fld in style.parent.fields: provider.addAttributes( [QgsField(fld.keyname, *FIELD_TYPE_TO_QGIS[fld.datatype])]) fldmap[fld.keyname] = len(fldmap) qgsfields = provider.fields() result.updateFields() # Load style from qml file result.loadNamedStyle(self.env.file_storage.filename( style.qml_fileobj)) # Disable read only flag when it was set via qml file result.setReadOnly(False) # Load features into layers if needed if features is not None: result.startEditing() for feat in features: qgsfeat = QgsFeature(qgsfields) fattrs = [None] * len(fldmap) for k, v in feat.fields.iteritems(): if v is None: continue elif isinstance(v, date): v = QDate(v.year, v.month, v.day) elif isinstance(v, time): v = QTime(v.hour, v.minute, v.second) elif isinstance(v, datetime): v = QDateTime(v.year, v.month, v.day, v.hour, v.minute, v.second) fattrs[fldmap[k]] = v qgsfeat.setAttributes(fattrs) # Method fromWkb() is much faster constructor fromWkt() # TODO: QGIS 3 have constructor fromWkb() qgsgeom = QgsGeometry() qgsgeom.fromWkb(feat.geom.wkb) qgsfeat.setGeometry(qgsgeom) result.addFeature(qgsfeat) result.commitChanges() result.setCrs(QgsCoordinateReferenceSystem(style.parent.srs.id)) return result
def insert_scenario(layer: QgsVectorLayer, name: str) -> int: """ Insert the new scenario and get its ID. """ feature = QgsFeature(layer.fields()) feature.setAttribute('nom', name) with edit(layer): layer.addFeature(feature) request = QgsFeatureRequest() request.setLimit(1) request.addOrderBy('id', False) feature = QgsFeature() layer.getFeatures(request).nextFeature(feature) return feature['id']
def create_bar_date(): bar_today_layer = QgsVectorLayer( "Point?" "crs=epsg:3857&" "field=id:integer&" "index=yes", "Bar", "memory") QgsProject.instance().addMapLayer(bar_today_layer, False) bar_today_layer.loadNamedStyle(os.path.join(FOLDER, 'qml', 'bar.qml')) with edit(bar_today_layer): feat = QgsFeature() feat.setAttributes([1]) feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0, 0))) bar_today_layer.addFeature(feat) return bar_today_layer
class DrawPointsAction(BaseAction): """Esta accion es la encargada de crear una capa de secciones y una capa de eje que el usuario podrá cargar después""" # TODO: Fix harcoded names def __init__(self): self.hidro_layer = None self.gen_sec = None def pre(self): # Verifica que la capa de hidrografía exista self.hidro_layer = manager.get_layer('hidrografia') self.gen_sec = manager.get_layer('secciones') if self.hidro_layer is None: raise LayerNotFound('hidrografia') # Este error se genera para preguntarle al usuario que desea hacer. if self.gen_sec is not None: raise PreviousGeneratedLayerFound('secciones') def pro(self): # Crea la capa en la que se van a agregar los nuevos puntos # Obtener crs de la capa de hidrografia crs = self.hidro_layer.crs().authid() self.gen_sec = QgsVectorLayer('Point?crs=' + crs, 'secciones', 'memory') manager.add_layers([self.gen_sec]) def pos(self, points): """ Habilita la edición de la capa, y dibuja los puntos en caso de ser necesario. :param option: Opción elegida por el usuario de importar los puntos o dibujarlos. :type option: bool :param points: En caso de que option sea True, los puntos serán una lista de puntos :type points: list """ self.gen_sec.startEditing() if points: for x, y in points: feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPoint(QgsPoint(x, y))) self.gen_sec.addFeature(feature) self.gen_sec.commitChanges()
def create_tanks_lay(geoms=None, ids=None, curves=None, diameters=None, elevs=None, elevs_corr=None, levels_init=None, levels_max=None, levels_min=None, vols_min=None, crs=None): url = 'Point' if crs is not None: url += '?crs=' + crs.authid() tanks_lay = QgsVectorLayer(url, Parameters.tanks_vlay_name, 'memory') tanks_lay_dp = tanks_lay.dataProvider() tanks_lay_dp.addAttributes(Tank.fields) tanks_lay.updateFields() if geoms is not None: for n in range(len(geoms)): tanks_ft = QgsFeature() tanks_ft.setGeometry(geoms[n]) tank_id = ids[n] if ids is not None else None curve = curves[n] if curves is not None else None diameter = diameters[n] if diameters is not None else None elev = elevs[n] if elevs is not None else None deltaz = elevs_corr[n] if elevs_corr is not None else None level_init = levels_init[n] if levels_init is not None else None level_max = levels_max[n] if levels_max is not None else None level_min = levels_min[n] if levels_min is not None else None vol_min = vols_min[n] if vols_min is not None else None tanks_ft.setAttribute(Tank.field_name_eid, tank_id) tanks_ft.setAttribute(Tank.field_name_curve, curve) tanks_ft.setAttribute(Tank.field_name_diameter, diameter) tanks_ft.setAttribute(Tank.field_name_elev, elev) tanks_ft.setAttribute(Tank.field_name_delta_z, deltaz) tanks_ft.setAttribute(Tank.field_name_level_init, level_init) tanks_ft.setAttribute(Tank.field_name_level_max, level_max) tanks_ft.setAttribute(Tank.field_name_level_min, level_min) tanks_ft.setAttribute(Tank.field_name_vol_min, vol_min) tanks_lay.addFeature(tanks_ft) return tanks_lay
def testNull(self): """ Asserts that 0, '' and NULL are treated as different values on insert """ vl = QgsVectorLayer(self.dbconn + ' sslmode=disable key=\'gid\' table="qgis_test"."constraints" sql=', 'test1', 'postgres') self.assertTrue(vl.isValid()) QgsProject.instance().addMapLayer(vl) tg = QgsTransactionGroup() tg.addLayer(vl) vl.startEditing() def onError(message): """We should not get here. If we do, fail and say why""" self.assertFalse(True, message) vl.raiseError.connect(onError) f = QgsFeature(vl.fields()) f['gid'] = 100 f['val'] = 0 f['name'] = '' self.assertTrue(vl.addFeature(f)) feature = next(vl.getFeatures('"gid" = 100')) self.assertEqual(f['val'], feature['val']) self.assertEqual(f['name'], feature['name'])
def testTransactionGroupExpressionFields(self): """Test issue GH #39230, this is not really specific to GPKG""" project = QgsProject() project.setAutoTransaction(True) tmpfile = os.path.join( self.basetestpath, 'tempGeoPackageTransactionExpressionFields.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint) lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT (1 1)')) f.SetField('str_field', 'one') lyr.CreateFeature(f) del lyr del ds vl = QgsVectorLayer(tmpfile + '|layername=test', 'test', 'ogr') f = QgsField('expression_field', QVariant.Int) idx = vl.addExpressionField('123', f) self.assertEqual(vl.fields().fieldOrigin(idx), QgsFields.OriginExpression) project.addMapLayers([vl]) feature = next(vl.getFeatures()) feature.setAttributes([None, 'two', 123]) self.assertTrue(vl.startEditing()) self.assertTrue(vl.addFeature(feature)) self.assertFalse(vl.dataProvider().hasErrors())
def create_current_date(): current_date_layer = QgsVectorLayer( "Point?" "crs=epsg:3857&" "field=id:integer&" "index=yes", "Current date", "memory") QgsProject.instance().addMapLayer(current_date_layer, False) current_date_layer.loadNamedStyle( os.path.join(FOLDER, 'qml', 'current_date.qml')) with edit(current_date_layer): feat = QgsFeature() feat.setAttributes([1]) feat.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(((SIZE + 5) / 2) * 100, -100))) current_date_layer.addFeature(feat) return current_date_layer
def testNull(self): """ Asserts that 0, '' and NULL are treated as different values on insert """ vl = QgsVectorLayer( self.dbconn + ' sslmode=disable key=\'gid\' table="qgis_test"."constraints" sql=', 'test1', 'postgres') self.assertTrue(vl.isValid()) QgsProject.instance().addMapLayer(vl) tg = QgsTransactionGroup() tg.addLayer(vl) vl.startEditing() def onError(message): """We should not get here. If we do, fail and say why""" self.assertFalse(True, message) vl.raiseError.connect(onError) f = QgsFeature(vl.fields()) f['gid'] = 100 f['val'] = 0 f['name'] = '' self.assertTrue(vl.addFeature(f)) feature = next(vl.getFeatures('"gid" = 100')) self.assertEqual(f['val'], feature['val']) self.assertEqual(f['name'], feature['name'])
def test_insert_pk_escaping(self): """ Test that inserting features works with complex pk name see https://github.com/qgis/QGIS/issues/42290 """ md = QgsProviderRegistry.instance().providerMetadata('mssql') conn = md.createConnection(self.dbconn, {}) conn.execSql('DROP TABLE IF EXISTS qgis_test.test_complex_pk_name') conn.execSql( 'CREATE TABLE qgis_test.test_complex_pk_name ([test-field] int)') uri = '{} table="qgis_test"."test_complex_pk_name" sql='.format( self.dbconn) vl = QgsVectorLayer(uri, '', 'mssql') self.assertTrue(vl.isValid()) self.assertEqual(vl.primaryKeyAttributes(), [0]) vl.startEditing() f = QgsFeature(vl.fields()) f.setAttributes([1]) self.assertTrue(vl.addFeature(f)) self.assertTrue(vl.commitChanges()) vl = QgsVectorLayer(uri, '', 'mssql') features = list(vl.getFeatures()) self.assertEqual([f['test-field'] for f in features], [1])
def make_grid_layer(polys, crs, _type_grid): result_layer = QgsVectorLayer( "Polygon?crs={}&field=ID:integer".format(crs.authid()), "{}_grid".format(_type_grid), "memory") result_layer.startEditing() result_layer.setCrs(crs) for ix, geom in enumerate(polys): new_geom = QgsGeometry.fromPolygonXY([[ QgsPointXY(*geom[ix_ring][ix_coords]) for ix_coords in range(len(geom[ix_ring])) ] for ix_ring in range(len(geom))]) feature = QgsFeature() feature.setGeometry(new_geom) feature.setAttributes([QVariant(ix)]) result_layer.addFeature(feature, QgsFeatureSink.FastInsert) result_layer.commitChanges() return result_layer
def centroid(self): layer = self.layerComboBox.currentData() uri = 'Point?crs={authid}&index=yes'.format(authid=layer.crs().authid()) new_layer = QgsVectorLayer(uri, 'centroid', 'memory') QgsProject.instance().addMapLayer(new_layer) # segunda parte new_layer.startEditing() for field in layer.fields(): new_layer.addAttribute(field) for feature in layer.getFeatures(): geom = feature.geometry().centroid() feature.setGeometry(geom) new_layer.addFeature(feature) new_layer.commitChanges()
def testEditSubsetString(self): tmpfile = os.path.join(self.basetestpath, 'testEditSubsetString.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbMultiPolygon) lyr.CreateField(ogr.FieldDefn('foo', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'bar' lyr.CreateFeature(f) f = None f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'baz' lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}|layerid=0'.format(tmpfile), 'test', 'ogr') self.assertEqual(vl.dataProvider().featureCount(), 2) # Test adding features vl.setSubsetString("foo = 'baz'") self.assertTrue(vl.startEditing()) feature = QgsFeature(vl.fields()) feature['foo'] = 'abc' vl.addFeature(feature) vl.commitChanges() vl.setSubsetString(None) self.assertEqual(vl.dataProvider().featureCount(), 3) # Test deleting a feature vl.setSubsetString("foo = 'baz'") self.assertTrue(vl.startEditing()) vl.deleteFeature(1) vl.commitChanges() vl.setSubsetString(None) self.assertEqual(vl.dataProvider().featureCount(), 2) # Test editing a feature vl.setSubsetString("foo = 'baz'") self.assertTrue(vl.startEditing()) vl.changeAttributeValue(2, 1, 'xx') vl.commitChanges() vl.setSubsetString(None) self.assertEqual(set((feat['foo'] for feat in vl.getFeatures())), set(['xx', 'abc']))
class DrawAxisAction(BaseAction): # TODO: Fix harcoded names def __init__(self): self.hidro_layer = None self.gen_sec = None self.gen_eje = None def pre(self): # Verifica que la capa de hidrografía exista self.hidro_layer = manager.get_layer('hidrografia') self.gen_sec = manager.get_layer('secciones') self.gen_eje = manager.get_layer('ejes') if self.hidro_layer is None: raise LayerNotFound('hidrografia') if self.gen_sec is None: raise LayerNotFound('secciones') # Este error se genera para preguntarle al usuario que desea hacer. if self.gen_eje is not None: raise PreviousGeneratedLayerFound('ejes') def pro(self): # Obtener crs de la capa de hidrografia crs = self.hidro_layer.crs().authid() self.gen_eje = QgsVectorLayer('LineString?crs=' + crs, 'ejes', 'memory') manager.add_layers([self.gen_eje]) self.gen_sec.commitChanges() def pos(self): self.gen_eje.startEditing() points = [] for feat in self.gen_sec.getFeatures(): points.append(feat.geometry().asPoint()) # print points feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolyline(points)) self.gen_eje.addFeature(feature) self.gen_eje.commitChanges()
def buffer(self): layer = self.layerComboBox.currentData() uri = 'Polygon?crs={authid}&index=yes'.format(authid=layer.crs().authid()) new_layer = QgsVectorLayer(uri, 'buffer', 'memory') QgsProject.instance().addMapLayer(new_layer) # segunda parte buffer_size = self.spinBox.value() new_layer.startEditing() for field in layer.fields(): new_layer.addAttribute(field) for feature in layer.getFeatures(): geom = feature.geometry().buffer(buffer_size, 5) feature.setGeometry(geom) new_layer.addFeature(feature) new_layer.commitChanges()
def create_pipes_lay(geoms=None, ids=None, demands=None, diameters=None, lengths=None, roughnesses=None, statuses=None, minor_losses=None, crs=None): url = 'LineString' if crs is not None: url += '?crs=' + crs.authid() pipes_lay = QgsVectorLayer(url, Parameters.pipes_vlay_name, 'memory') pipes_lay_dp = pipes_lay.dataProvider() pipes_lay_dp.addAttributes(Pipe.fields) pipes_lay_dp.addAttributes(QPipe.fields) pipes_lay.updateFields() if geoms is not None: for n in range(len(geoms)): pipe_ft = QgsFeature() pipe_ft.setGeometry(geoms[n]) pipe_id = ids[n] if ids is not None else None demand = demands[n] if demands is not None else None diameter = diameters[n] if diameters is not None else None length = lengths[n] if lengths is not None else None roughness = roughnesses[n] if roughnesses is not None else None status = statuses[n] if statuses is not None else None minor_loss = minor_losses[ n] if minor_losses is not None else None pipe_ft.setAttribute(Pipe.field_name_eid, pipe_id) pipe_ft.setAttribute(Pipe.field_name_diameter, diameter) pipe_ft.setAttribute(Pipe.field_name_length, length) pipe_ft.setAttribute(Pipe.field_name_roughness, roughness) pipe_ft.setAttribute(Pipe.field_name_status, status) pipe_ft.setAttribute(Pipe.field_name_minor_loss, minor_loss) pipes_lay.addFeature(pipe_ft) return pipes_lay
def taskFinished(self, data): self.dialog.runButton.setEnabled(True) self.dialog.cancel_button.setEnabled(False) self.sendDialogLog('process has been completed', self.greenColor) self.task.terminate() if self.dialog.addLayersWithError.isChecked(): failPoints = data[0] failMultilines = data[1] if len(failPoints) != 0 or len(failMultilines) != 0: for l2rem in QgsProject.instance().mapLayersByName( 'AJBL_error_target_points'): QgsProject.instance().removeMapLayer(l2rem) epsg = self.targetLayer.sourceCrs().authid() layer = QgsVectorLayer(f'Point?crs={epsg}', 'AJBL_error_target_points', 'memory') QgsProject.instance().addMapLayer(layer, False) layerTree = self.iface.layerTreeCanvasBridge().rootGroup() layerTree.insertChildNode(0, QgsLayerTreeLayer(layer)) layer.dataProvider().addAttributes( [QgsField('Fail', QVariant.String)]) for f in failPoints: layer.startEditing() feature = QgsFeature() feature.setGeometry(f[0].geometry()) feature.setAttributes([f[1]]) layer.addFeature(feature) layer.commitChanges() for f in failMultilines: layer.startEditing() feature = QgsFeature() feature.setGeometry(f[0].geometry()) feature.setAttributes([f[1]]) layer.addFeature(feature) layer.commitChanges() layer.reload()
def run(self): """ Just show/dock Widget/Plugin """ layer = QgsVectorLayer("LineString", "Examplelayer", "memory") layer.startEditing() layer.addAttribute(QgsField("id", QVariant.Int)) layer.addAttribute(QgsField("Length", QVariant.Double)) qfeature = QgsFeature() qfeature.setGeometry( QgsGeometry.fromPolyline([QgsPoint(0, 0), QgsPoint(1, 1)])) qfeature.setAttributes([1, 1.414]) layer.addFeature(qfeature) layer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer(layer)
def buildQgsVectorLayer(string_geomtype, string_layername, crs, feature_list, list_qgsfield): #create new vector layer from self.crs vector_layer = QgsVectorLayer(string_geomtype, string_layername, "memory") #set crs from class vector_layer.setCrs(crs) #set fields provider = vector_layer.dataProvider() provider.addAttributes(list_qgsfield) #[QgsField('fid',QVariant.Int),QgsField("origin_point_id", QVariant.Double),QgsField("iso", QVariant.Int)] vector_layer.updateFields() #fill layer with geom and attrs vector_layer.startEditing() for feat in feature_list: vector_layer.addFeature(feat, True) vector_layer.commitChanges() return vector_layer
def create_junctions_lay(geoms=None, ids=None, demands=None, elevs=None, deltazs=None, patterns=None, emitters=None, crs=None): url = 'Point' if crs is not None: url += '?crs=' + crs.authid() junctions_lay = QgsVectorLayer(url, Parameters.junctions_vlay_name, 'memory') junctions_lay_dp = junctions_lay.dataProvider() junctions_lay_dp.addAttributes(Junction.fields) junctions_lay_dp.addAttributes(QJunction.fields) junctions_lay.updateFields() if geoms is not None: for n in range(len(geoms)): junctions_ft = QgsFeature() junctions_ft.setGeometry(geoms[n]) junction_id = ids[n] if ids is not None else None demand = demands[n] if demands is not None else None elev = elevs[n] if elevs is not None else None deltaz = deltazs[n] if deltazs is not None else None pattern = patterns[n] if patterns is not None else None emitter = emitters[n] if emitters is not None else None junctions_ft.setAttribute(Junction.field_name_eid, junction_id) junctions_ft.setAttribute(Junction.field_name_elev, elev) junctions_ft.setAttribute(Junction.field_name_delta_z, deltaz) junctions_ft.setAttribute(Junction.field_name_pattern, pattern) junctions_ft.setAttribute(Junction.field_name_emitter_coeff, emitter) junctions_lay.addFeature(junctions_ft) return junctions_lay
def cost_route(self, route, feedback): """Extract the route with the highest cost from network point to layer""" longest_route = QgsVectorLayer(route.source(), 'Longest route', 'memory') # better work on a duplicate here to not mess things up with selections dupl = self.duplicate_layer(route, feedback) dupl.removeSelection() # need the field's index for retrieval, not the name field_map = dupl.dataProvider().fieldNameMap() maximum = dupl.maximumValue(field_map['cost']) request = QgsFeatureRequest(QgsExpression("cost=%s" % maximum)) longest_route.startEditing() for feature in dupl.getFeatures(request): longest_route.addFeature(feature) longest_route.commitChanges() return (maximum, longest_route)
def testTransactionRollback(self): """Test issue https://github.com/qgis/QGIS/issues/48171#issuecomment-1132709901""" d = QTemporaryDir() path = d.path() source_fields = QgsFields() source_fields.append(QgsField('int', QVariant.Int)) vl = QgsMemoryProviderUtils.createMemoryLayer('test', source_fields) f = QgsFeature() f.setAttributes([1]) vl.dataProvider().addFeature(f) tmpfile = os.path.join(path, 'testTransactionRollback.sqlite') options = { 'driverName': 'SpatiaLite', 'layerName': 'test' } err = QgsVectorLayerExporter.exportLayer(vl, tmpfile, "ogr", vl.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) vl = QgsVectorLayer( 'dbname=\'{}\' table="test" () sql='.format(tmpfile), 'test', 'spatialite') self.assertTrue(vl.isValid()) p = QgsProject.instance() p.setTransactionMode(Qgis.TransactionMode.AutomaticGroups) self.assertTrue(p.addMapLayer(vl)) cache = QgsVectorLayerCache(vl, 100) am = QgsAttributeTableModel(cache) am.loadLayer() self.assertEqual(am.rowCount(), 1) self.assertTrue(vl.startEditing()) vl.beginEditCommand('edit1') f = QgsFeature() f.setAttributes([2]) self.assertTrue(vl.addFeature(f)) self.assertEqual(am.rowCount(), 2) self.assertEqual(len([f for f in vl.getFeatures()]), 2) vl.endEditCommand() self.assertTrue(vl.rollBack()) self.assertEqual(len([f for f in vl.getFeatures()]), 1) self.assertEqual(am.rowCount(), 1)
def addPointToLayer(self, x, y, z): x = float(x) y = float(y) z = float(z) name = 'Obliczone wysokości - GUGiK NMT' layers = QgsProject.instance().mapLayersByName(name) if not layers: layer = QgsVectorLayer( 'PointZ?crs=epsg:2180&field=x:double&field=y:double&field=z:double', name, 'memory') QgsProject.instance().addMapLayer(layer, False) layerTree = self.iface.layerTreeCanvasBridge().rootGroup() layerTree.insertChildNode(0, QgsLayerTreeLayer(layer)) treeRoot = QgsProject.instance().layerTreeRoot() if treeRoot.hasCustomLayerOrder(): order = treeRoot.customLayerOrder() order.insert( 0, order.pop( order.index( QgsProject.instance().mapLayersByName(name)[0]))) treeRoot.setCustomLayerOrder(order) layer.loadNamedStyle( os.path.join(self.plugin_dir, 'layer_style.qml'), True) else: layer = layers[0] feature = QgsFeature() point = QgsGeometry(QgsPoint(x, y, z)) feature.setGeometry(point) feature.setAttributes([x, y, z]) layer.startEditing() layer.addFeature(feature) layer.commitChanges() layer.reload()
def test_AddFeatureNullFid(self): """Test gpkg feature with NULL fid can be added""" tmpfile = os.path.join(self.basetestpath, 'testGeopackageSplitFeatures.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPolygon) lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString)) ds = None layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') # Check that pk field has unique constraint fields = layer.fields() pkfield = fields.at(0) self.assertTrue(pkfield.constraints().constraints() & QgsFieldConstraints.ConstraintUnique) # Test add feature with default Fid (NULL) layer.startEditing() f = QgsFeature() feat = QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromWkt('Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))')) feat.setAttribute(1, 'test_value') layer.addFeature(feat) self.assertTrue(layer.commitChanges()) self.assertEqual(layer.featureCount(), 1)
def testEdit(self): """Test `with edit(layer):` code""" ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory") # Data as list of x, y, id, value self.assertTrue(ml.isValid()) fields = ml.fields() # Check insert with edit(ml): feat = QgsFeature(fields) feat['id'] = 1 feat['value'] = 0.9 self.assertTrue(ml.addFeature(feat)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 0.9) # Check update with edit(ml): f = next(ml.getFeatures()) f['value'] = 9.9 self.assertTrue(ml.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) # Check for rollBack after exceptions with self.assertRaises(NameError): with edit(ml): f = next(ml.getFeatures()) f['value'] = 3.8 crashycrash() # NOQA self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) self.assertEqual(next(ml.getFeatures())['value'], 9.9) # Check for `as` with edit(ml) as l: f = next(l.getFeatures()) f['value'] = 10 self.assertTrue(l.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 10) # Check that we get a QgsEditError exception when the commit fails with self.assertRaises(QgsEditError): with edit(ml) as l: l.rollBack()
class mesh_canvas(QgsMapCanvas): def __init__(self,iface,tile_name,tile_credit,tile_url,tile_zmin,tile_zmax,tile_bbox): QgsMapCanvas.__init__(self) self.iface = iface self.setWheelAction(QgsMapCanvas.WheelZoom,1) self.setDestinationCrs(self.iface.mapCanvas().mapSettings().destinationCrs()) self.setCrsTransformEnabled(True) self.iface.mapCanvas().destinationCrsChanged.connect(self.onCrsChanged) self.iface.mapCanvas().extentsChanged.connect(self.onExtentsChanged) self.iface.mapCanvas().scaleChanged.connect(self.onScaleChanged) layerdef = TileLayerDefinition(tile_name, tile_credit, tile_url, zmin=tile_zmin, zmax=tile_zmax, bbox=tile_bbox) creditVisibility=True plugin = plugins.get("TileLayerPlugin") self.chirin_layer = TileLayer(plugin,layerdef, creditVisibility) QgsMapLayerRegistry.instance().addMapLayer(self.chirin_layer,False) self.meshPolyLayer = QgsVectorLayer("polygon?crs=postgis:4612",u"地域メッシュインデックス","memory") renderer = self.meshPolyLayer.rendererV2() renderer.symbols()[0].symbolLayers()[0].setFillColor(QtGui.QColor(0,0,0,0)) renderer.symbols()[0].symbolLayers()[0].setBorderWidth(0.1) self.meshPolyLayer.label().setLabelField(0,0) self.meshPolyLayer.startEditing() self.meshPolyLayer.addAttribute(QgsField("meshC",QtCore.QVariant.String)) self.meshPolyLayer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer(self.meshPolyLayer,False) main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.Trs_laln = QgsCoordinateTransform(main_crs,QgsCoordinateReferenceSystem(4612)) self.redraw_mesh() layers = [] layers.append(QgsMapCanvasLayer(self.meshPolyLayer)) layers.append(QgsMapCanvasLayer(self.chirin_layer)) self.setLayerSet(layers) self.setExtent( self.iface.mapCanvas().extent() ) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.resize(self.iface.mapCanvas().size()/2) def onCrsChanged(self): main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.setDestinationCrs(main_crs) def onExtentsChanged(self): self.setExtent( self.iface.mapCanvas().extent() ) self.redraw_mesh() self.refresh() def onScaleChanged(self): self.resize(self.iface.mapCanvas().size()/2) def PPopend(self): self.iface.mapCanvas().extentsChanged.disconnect() self.iface.mapCanvas().scaleChanged.disconnect() def res_mesh_index(self,latitude,longitude): x1d = math.floor(longitude - 100) x2d = math.floor((longitude - x1d - 100 ) * 8 ) x3d = math.floor((longitude - x1d - 100 - x2d/8.0 )*80 ) y1d = math.floor(latitude*1.5) y2d = math.floor((latitude*1.5 - y1d ) * 8 ) y3d = math.floor((latitude*1.5 - y1d - y2d/8.0 )*80 ) return (x1d,x2d,x3d,y1d,y2d,y3d) def res_extent_mesh(self): main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.Trs_laln.setSourceCrs(main_crs) my_rect = self.iface.mapCanvas().extent() laln_rect = self.Trs_laln.transform(my_rect) x_min = laln_rect.xMinimum() x_max = laln_rect.xMaximum() y_min = laln_rect.yMinimum() y_max = laln_rect.yMaximum() Lx1d,Lx2d,Lx3d,Ly1d,Ly2d,Ly3d = self.res_mesh_index(y_min, x_min) Rx1d,Rx2d,Rx3d,Uy1d,Uy2d,Uy3d = self.res_mesh_index(y_max, x_max) x_range = x_max - x_min y_range = y_max - y_min return {"Lx1d":Lx1d,"Lx2d":Lx2d,"Lx3d":Lx3d, "Rx1d":Rx1d,"Rx2d":Rx2d,"Rx3d":Rx3d, "Ly1d":Ly1d,"Ly2d":Ly2d,"Ly3d":Ly3d, "Uy1d":Uy1d,"Uy2d":Uy2d,"Uy3d":Uy3d, "xRange":x_range,"yRange":y_range} def draw_m1d(self): x = self.e_mesh["Lx1d"] -1 while x <= self.e_mesh["Rx1d"] + 1: y = self.e_mesh["Ly1d"] while y <= self.e_mesh["Uy1d"]: f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1)/1.5), QgsPoint(x+101,(y+1)/1.5),QgsPoint(x+101,y/1.5)]])) m1d_str = str(int(y)) + str(int(x)) f.setAttribute("meshC",m1d_str) self.meshPolyLayer.addFeature(f) y += 1 x += 1 def draw_m2d(self): x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 - 1 / 8.0 while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + 1 / 8.0: x1d = math.floor(x) x2d = math.floor((x-x1d)*8) y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 - 1 / 8.0 while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] + 1 / 8.0: y1d = math.floor(y) y2d = math.floor((y-y1d)*8) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/8.0)/1.5), QgsPoint(x+100+1/8.0,(y+1/8.0)/1.5),QgsPoint(x+100+1/8.0,y/1.5)]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) mesh_str = m1d_str + m2d_str f.setAttribute("meshC",mesh_str) self.meshPolyLayer.addFeature(f) y += 1/8.0 x += 1/8.0 def draw_m3d(self): x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 + self.e_mesh["Lx3d"] / 80.0 - 1 / 80.0 while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + self.e_mesh["Rx3d"] / 80.0 + 1 / 80.0: x1d = math.floor(x) x2d = math.floor((x-x1d)*8) x3d = math.floor((x-x1d-x2d/8.0)*80) y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 + self.e_mesh["Ly3d"] / 80.0 - 1 / 80.0 while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] / 8.0 + self.e_mesh["Uy3d"] / 80.0 + 1 / 80.0: y1d = math.floor(y) y2d = math.floor((y-y1d)*8) y3d = math.floor((y-y1d-y2d/8.0)*80) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/80.0)/1.5), QgsPoint(x+100+1/80.0,(y+1/80.0)/1.5),QgsPoint(x+100+1/80.0,y/1.5)]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) m3d_str = str(int(y3d)) + str(int(x3d)) mesh_str = m1d_str + m2d_str + m3d_str f.setAttribute("meshC",mesh_str) self.meshPolyLayer.addFeature(f) y += 1/80.0 x += 1/80.0 def draw_m5x(self): x = self.e_mesh["Lx1d"] - 1 while x <= self.e_mesh["Rx1d"]+1: x1d = math.floor(x) x2d = math.floor((x-x1d)*8) x5x = math.floor((x-x1d-x2d/8.0)*16) y = self.e_mesh["Ly1d"] - 1 while y <= self.e_mesh["Uy1d"]+1: y1d = math.floor(y) y2d = math.floor((y-y1d)*8) y5x = math.floor((y-y1d-y2d/8.0)*16) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/16.0)/1.5), QgsPoint(x+100+1/16.0,(y+1/16.0)/1.5),QgsPoint(x+100+1/16.0,y/1.5)]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) m5x_str = str(int(x5x+y5x*2+1)) mesh_str = m1d_str + "-" + m2d_str + "-" + m5x_str f.setAttribute("meshC",mesh_str) self.meshPolyLayer.addFeature(f) y += 1/16.0 x += 1/16.0 def redraw_mesh(self): self.e_mesh = self.res_extent_mesh() if self.e_mesh["xRange"] < 50: self.meshPolyLayer.startEditing() self.meshPolyLayer.selectAll() self.meshPolyLayer.deleteSelectedFeatures() if self.e_mesh["xRange"] > 2.0: self.draw_m1d() elif self.e_mesh["xRange"] > 1.0/8.0: self.draw_m2d() else: self.draw_m3d() self.meshPolyLayer.commitChanges() self.meshPolyLayer.enableLabels(self.e_mesh["xRange"] <= 8.0) def closeEvent(self,event): QgsMapLayerRegistry.instance().removeMapLayers( [ self.meshPolyLayer.id(), self.chirin_layer.id() ]) self.iface.mapCanvas().destinationCrsChanged.disconnect() self.iface.mapCanvas().extentsChanged.disconnect() self.iface.mapCanvas().scaleChanged.disconnect()
def on_btnRun_clicked(self): if self.inputfile == '': QMessageBox.critical(self,'Map Creator', 'Please specify input coordinate file.') return if self.outputfile == '': QMessageBox.critical(self,'Map Creator', 'Please specify output shapefile.') return self.setCursor(Qt.WaitCursor) #Open coordinate input file f = open(self.inputfile, 'r') lines = f.readlines() f.close() header = lines[0].split(',')[0] totfeat = len(lines) - 1 lines.pop(0) lines.reverse() #Create vector layer basename = os.path.basename(self.outputfile) vlayer = QgsVectorLayer("Polygon", basename, "memory") vprovider = vlayer.dataProvider() fld = QgsField(header,QVariant.String) flds = QgsFields() flds.append(fld) vprovider.addAttributes([fld]) vlayer.startEditing() hull = [] for cnt, line in enumerate(lines): line = line.rstrip().split(',') numcoords = int((len(line) - 1) / 2) hull[:] = [] geom = QgsGeometry() feat = QgsFeature() feat.setFields(flds) for i in range(numcoords): hull.append(QgsPoint(float(line[i*2+1]),float(line[i*2+2]))) geom = geom.fromMultiPoint(hull) geom = geom.convexHull() feat.setGeometry(geom) feat.setAttribute(header,str(line[0])) result = vlayer.addFeature(feat) if not result: self.setCursor(Qt.ArrowCursor) QMessageBox.critical(self,'Map Creator', 'Processing error.') return self.ui.ProgressBar.setValue(float(cnt+1)/float(totfeat) * 100.0) QApplication.processEvents() vlayer.commitChanges() vlayer.updateExtents() #Write the output shapefile if os.path.exists(self.outputfile): QgsVectorFileWriter.deleteShapeFile(self.outputfile) result = QgsVectorFileWriter.writeAsVectorFormat(vlayer, self.outputfile, 'utf-8', vlayer.crs()) if result != QgsVectorFileWriter.NoError: QMessageBox.critical(self,'Map Creator','Error creating shapefile.') else: #Ask to add shapfile to map name = QFileInfo(self.outputfile).completeBaseName() result = QMessageBox.question(self,'Map Creator', 'Add shapefile to map?', QMessageBox.Yes, QMessageBox.No) if result == QMessageBox.Yes: self.iface.addVectorLayer(self.outputfile, name, 'ogr') self.setCursor(Qt.ArrowCursor)
class CsvLayer(): """ Pretend we are a data provider """ dirty = False doing_attr_update = False def __init__(self, csv_path): """ Initialize the layer by reading the CSV file, creating a memory layer, and adding records to it """ # Save the path to the file soe we can update it in response to edits self.csv_path = csv_path self.csv_file = open(csv_path, 'rb') self.reader = csv.reader(self.csv_file) self.header = self.reader.next() logger(str(self.header)) # Get sample sample = self.reader.next() self.field_sample = dict(zip(self.header, sample)) logger("sample %s" % str(self.field_sample)) field_name_types = {} # create dict of fieldname:type for key in self.field_sample.keys(): if self.field_sample[key].isdigit(): field_type = 'integer' else: try: float(self.field_sample[key]) field_type = 'real' except ValueError: field_type = 'string' field_name_types[key] = field_type logger(str(field_name_types)) # Build up the URI needed to create memory layer self.uri = self.uri = "Point?crs=epsg:4326" for fld in self.header: self.uri += '&field={}:{}'.format(fld, field_name_types[fld]) logger(self.uri) # Create the layer self.lyr = QgsVectorLayer(self.uri, 'cities.csv', 'memory') self.add_records() # done with the csv file self.csv_file.close() # Make connections self.lyr.editingStarted.connect(self.editing_started) self.lyr.editingStopped.connect(self.editing_stopped) self.lyr.committedAttributeValuesChanges.connect(self.attributes_changed) self.lyr.committedFeaturesAdded.connect(self.features_added) self.lyr.committedFeaturesRemoved.connect(self.features_removed) self.lyr.geometryChanged.connect(self.geometry_changed) # Add the layer the map QgsMapLayerRegistry.instance().addMapLayer(self.lyr) def add_records(self): """ Add records to the memory layer by reading the CSV file """ # Return to beginning of csv file self.csv_file.seek(0) # Skip the header self.reader.next() self.lyr.startEditing() for row in self.reader: flds = dict(zip(self.header, row)) # logger("This row: %s" % flds) feature = QgsFeature() geometry = QgsGeometry.fromPoint( QgsPoint(float(flds['X']), float(flds['Y']))) feature.setGeometry(geometry) # for key in flds: # logger("setting attribute for |%s|" % key) # feature.setAttribute(feature.fieldNameIndex(key), flds[key]) feature.setAttributes(row) self.lyr.addFeature(feature, True) self.lyr.commitChanges() def editing_started(self): """ Connect to the edit buffer so we can capture geometry and attribute changes """ self.lyr.editBuffer().committedAttributeValuesChanges.connect( self.attributes_changed) def editing_stopped(self): """ Update the CSV file if changes were committed """ if self.dirty: logger("Updating the CSV") features = self.lyr.getFeatures() tempfile = NamedTemporaryFile(mode='w', delete=False) writer = csv.writer(tempfile, delimiter=',') # write the header writer.writerow(self.header) for feature in features: row = [] for fld in self.header: row.append(feature[feature.fieldNameIndex(fld)]) writer.writerow(row) tempfile.close() shutil.move(tempfile.name, self.csv_path) self.dirty = False def attributes_changed(self, layer, changes): """ Attribute values changed; set the dirty flag """ if not self.doing_attr_update: logger("attributes changed") self.dirty = True def features_added(self, layer, features): """ Features added; update the X and Y attributes for each and set the dirty flag """ logger("features added") for feature in features: self.geometry_changed(feature.id(), feature.geometry()) self.dirty = True def features_removed(self, layer, feature_ids): """ Features removed; set the dirty flag """ logger("features removed") self.dirty = True def geometry_changed(self, fid, geom): """ Geometry for a feature changed; update the X and Y attributes for each """ feature = self.lyr.getFeatures(QgsFeatureRequest(fid)).next() pt = geom.asPoint() logger("Updating feature {} ({}) X and Y attributes to: {}".format( fid, feature['NAME'], pt.toString())) self.lyr.changeAttributeValue(fid, feature.fieldNameIndex('X'), pt.x()) self.lyr.changeAttributeValue(fid, feature.fieldNameIndex('Y'), pt.y())
class AutoFieldsTests( unittest.TestCase ): @classmethod def setUpClass( self ): self.msg = MessageManager( 'debug', None ) self.msg.show( "Info! SetUp started", 'info', True ) #Initialize QGIS app app = QgsApplication([], True) QgsApplication.setPrefixPath("/usr", True) QgsApplication.initQgis() #Configure QSettings (organization and application name) self.settings = QSettings("GeoTux", "QGIS-Plugin-Test") #Load layer, add field f1, and add layer to Registry baseDir = os.path.dirname( os.path.realpath( __file__ ) ) self.layerPath = os.path.join( baseDir, 'test_data', 'test_points.shp' ) self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) self.layer.dataProvider().addAttributes([QgsField('f1', QVariant.Double)]) self.layer.updateFields() QgsMapLayerRegistry.instance().addMapLayer( self.layer ) #Instantiate AutoFieldManager self.autoFieldManager = AutoFieldManager( self.msg, None, '/AutoFieldsTest', 'GeoTux', 'QGIS-Plugin-Test' ) def readStoredSettings( self, layer, fieldName ): """ Helper function to get a dictionary of stored QSettings for an AutoField """ dictTmpProperties = {} autoFieldId = self.autoFieldManager.buildAutoFieldId( layer, fieldName ) self.settings.beginGroup('/AutoFieldsTest/data/' + autoFieldId) dictTmpProperties['layer'] = self.settings.value( "layer", "", type=str ) dictTmpProperties['field'] = self.settings.value( "field", u"", type=unicode ) dictTmpProperties['expression'] = self.settings.value( "expression", u"", type=unicode ) dictTmpProperties['layer2'] = self.settings.value( "layer2", "", type=str ) dictTmpProperties['field2'] = self.settings.value( "field2", "", type=str ) dictTmpProperties['enabled'] = self.settings.value( "enabled", False, type=bool ) self.settings.endGroup() return dictTmpProperties def test01CreateEnabledAutoField( self ): """ QSettings should be properly stored, AutoField should be enabled """ self.msg.show( "Info! Test 1 started", 'info', True ) self.autoFieldManager.createAutoField( layer=self.layer, fieldName=u'f1', expression=u'$x' ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) dictExpectedProperties = { 'layer':self.layerPath, 'field':u'f1', 'expression':u'$x', 'layer2':"", 'field2':"", 'enabled':True } self.assertEqual( dictTmpProperties, dictExpectedProperties ) def test02AvoidTwoAutoFieldsOnSameField( self ): """ AutoField should not be created if another one already exists on the same field.""" self.msg.show( "Info! Test 2 started", 'info', True ) res = self.autoFieldManager.createAutoField( layer=self.layer, fieldName=u'f1', expression=u'$y' ) self.assertFalse( res ) def test03EditAutoFieldLayer( self ): """ AutoField value should be updated if a feature is added. Note: It cannot handle the case when writing directly to the provider, as QGIS doesn't have a SIGNAL for that. self.layer.dataProvider().addFeatures( [ tmpFeature ] ) """ self.msg.show( "Info! Test 3 started", 'info', True ) tmpFeature = QgsFeature( self.layer.pendingFields() ) tmpFeature.setGeometry( QgsGeometry.fromPoint( QgsPoint(-74.4, 4.5) ) ) # Either 1: self.layer.startEditing() self.layer.addFeature( tmpFeature ) self.layer.commitChanges() # Or 2: #with edit( self.layer ): # self.layer.addFeature( tmpFeature ) addedFeature = self.layer.getFeatures().next() self.assertEquals( addedFeature['f1'], -74.4 ) def test04ChangeAttributeValue( self ): """ AutoField value should be updated if another AutoField value is changed """ self.msg.show( "Info! Test 4 started", 'info', True ) self.autoFieldManager.createAutoField( layer=self.layer, fieldName=u'modified', expression=u'\'now: \' + to_string("f1")' ) self.layer.startEditing() self.layer.changeAttributeValue( 0, self.layer.fieldNameIndex( u'id' ), 1 ) self.layer.commitChanges() feature = self.layer.getFeatures().next() self.assertEquals( feature['modified'], 'now: -74.4' ) def test05FieldRemovedThenDisableAutoField( self ): """ AutoField should be disabled if its base field is removed """ self.msg.show( "Info! Test 5 started", 'info', True ) fieldIndex = self.layer.fieldNameIndex( u'f1' ) self.layer.startEditing() self.layer.deleteAttribute( fieldIndex ) self.layer.commitChanges() dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertFalse( dictTmpProperties['enabled'] ) def test06MissingFieldAddedThenEnableAutoField( self ): """ AutoField should be enabled if missing field is added """ self.msg.show( "Info! Test 6 started", 'info', True ) self.layer.startEditing() self.layer.addAttribute( QgsField( 'f1', QVariant.Double, len=10, prec=2 ) ) self.layer.commitChanges() dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertTrue( dictTmpProperties['enabled'] ) def test07LayerRemovedThenDisableAutoField( self ): """ AutoField should be disabled if its base layer is removed """ self.msg.show( "Info! Test 7 started", 'info', True ) QgsMapLayerRegistry.instance().removeMapLayer( self.layer.id() ) # removeMapLayer deletes the underlying object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertFalse( dictTmpProperties['enabled'] ) def test08MissingLayerAddedThenEnableAutoField( self ): """ AutoField should be enabled if missing layer is added """ self.msg.show( "Info! Test 8 started", 'info', True ) # test07 deletes the layer object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) QgsMapLayerRegistry.instance().addMapLayer( self.layer ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertTrue( dictTmpProperties['enabled'] ) def test09RemoveAutoField( self ): """ QSettings should be deleted for the removed AutoField """ self.msg.show( "Info! Test 9 started", 'info', True ) # test07 deletes the layer object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) autoFieldId = self.autoFieldManager.buildAutoFieldId( self.layer, u'f1') self.autoFieldManager.removeAutoField( autoFieldId ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertEqual( dictTmpProperties, {'layer':"",'field':"",'expression':"",'layer2':"",'field2':"",'enabled':False} ) @classmethod def tearDownClass( self ): self.msg.show( "Info! TearDown started", 'info', True ) # test07 deletes the layer object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) #Remove AutoField modified autoFieldId = self.autoFieldManager.buildAutoFieldId( self.layer, u'modified' ) self.autoFieldManager.removeAutoField( autoFieldId ) #Delete field f1 fieldIndex = self.layer.fieldNameIndex('f1') self.layer.dataProvider().deleteAttributes( [fieldIndex] ) self.layer.updateFields() #Delete features from test layer fIds = self.layer.allFeatureIds() self.layer.dataProvider().deleteFeatures( fIds ) #Remove layer from Registry QgsMapLayerRegistry.instance().removeMapLayer( self.layer.id() ) self.msg.show( "Info! TearDown finished", 'info', True ) QgsApplication.exitQgis()