Пример #1
0
    def testEditGeoJsonAddFieldAndThenAddFeatures(self):
        """ Test bugfix of https://issues.qgis.org/issues/18596 (adding a new field)"""

        datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json')
        with open(datasource, 'wt') as f:
            f.write("""{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""")

        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String)))
        self.assertTrue(vl.commitChanges())
        self.assertEqual(len(vl.dataProvider().fields()), 1 + 1)
        self.assertEqual([f.name() for f in vl.dataProvider().fields()], ['x', 'strfield'])

        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertIsNone(f['strfield'])
        self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield'])

        self.assertTrue(vl.startEditing())
        vl.changeAttributeValue(f.id(), 1, 'x')
        self.assertTrue(vl.commitChanges())
        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertEqual(f['strfield'], 'x')
        self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield'])

        # Completely reload file
        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertEqual(len(vl.fields()), 2)
def create_layer_bk(download_path, tmp_layer, indicator, indicator_name, data, year):

    tmp_data_provider = tmp_layer.dataProvider()
    tmp_layer.startEditing()
    tmp_feature = QgsFeature()

    # get world bank data
    # data = get_world_bank_data(indicator, year)

    # getting layer_name
    layer_name = indicator_name + " (" + year + ")"
    clean_layer_name = re.sub('\W+', '_', indicator_name) + "_" + year

    # creating output path
    # output_base_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "output")
    # if not os.path.exists(output_base_path):
    #     os.mkdir(output_base_path)

    # retrieving input shp
    # output_file = os.path.join(output_base_path, clean_layer_name + ".shp")
    output_file = os.path.join(download_path, clean_layer_name + ".shp")
    input_base_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources")

    # copy resource file to output
    # resource_files = glob.glob(os.path.join(input_base_path, "ne_110m_admin_0_*"))
    resource_files = glob.glob(os.path.join(input_base_path, "ne_110m_admin_0_*"))
    for resource_file in resource_files:
        base, extension = os.path.splitext(resource_file)
        copyfile(resource_file, os.path.join(download_path, clean_layer_name + extension))

    # Editing output_file
    layer = QgsVectorLayer(output_file, layer_name, "ogr")
    layer.startEditing()

    # TODO: add data check instead of the addedValue boolean?
    addedValue = False
    for feat in layer.getFeatures():
        if feat['iso_a2'] is not None:
            for d in data:
                code = d['country']['id']
                value = d['value']
                if code == feat['iso_a2']:
                    if value:
                        # TODO: automatize the index 5 of feat['iso_a2']
                        layer.changeAttributeValue(feat.id(), 5, float(value))
                        tmp_feature.setAttributes([float(value)])
                        # TODO add all togheter
                        tmp_data_provider.addFeatures([tmp_feature])
                        addedValue = True
                        break

    layer.commitChanges()
    return layer, addedValue
Пример #3
0
    def testGeopackageLargeFID(self):

        tmpfile = os.path.join(self.basetestpath, 'testGeopackageLargeFID.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString))
        ds = None

        vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')
        f = QgsFeature()
        f.setAttributes([1234567890123, None])
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.dataProvider().addFeatures([f]))
        self.assertTrue(vl.commitChanges())

        got = [feat for feat in vl.getFeatures()][0]
        self.assertEqual(got['fid'], 1234567890123)

        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.changeGeometry(1234567890123, QgsGeometry.fromWkt('Point (3 50)')))
        self.assertTrue(vl.changeAttributeValue(1234567890123, 1, 'foo'))
        self.assertTrue(vl.commitChanges())

        got = [feat for feat in vl.getFeatures()][0]
        self.assertEqual(got['str_field'], 'foo')
        got_geom = got.geometry()
        self.assertIsNotNone(got_geom)

        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.deleteFeature(1234567890123))
        self.assertTrue(vl.commitChanges())
Пример #4
0
    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']))
Пример #5
0
    def testDisablewalForSqlite3(self):
        ''' Test disabling walForSqlite3 setting '''
        QgsSettings().setValue("/qgis/walForSqlite3", False)

        tmpfile = os.path.join(self.basetestpath, 'testDisablewalForSqlite3.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('attr0', ogr.OFTInteger))
        lyr.CreateField(ogr.FieldDefn('attr1', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl = QgsVectorLayer(u'{}'.format(tmpfile), u'test', u'ogr')

        # Test that we are using default delete mode and not WAL
        ds = ogr.Open(tmpfile)
        lyr = ds.ExecuteSQL('PRAGMA journal_mode')
        f = lyr.GetNextFeature()
        res = f.GetField(0)
        ds.ReleaseResultSet(lyr)
        ds = None
        self.assertEqual(res, 'delete')

        self.assertTrue(vl.startEditing())
        feature = next(vl.getFeatures())
        self.assertTrue(vl.changeAttributeValue(feature.id(), 1, 1001))

        # Commit changes
        cbk = ErrorReceiver()
        vl.dataProvider().raiseError.connect(cbk.receiveError)
        self.assertTrue(vl.commitChanges())
        self.assertIsNone(cbk.msg)
        vl = None

        QgsSettings().setValue("/qgis/walForSqlite3", None)
Пример #6
0
    def testUpdateFeature(self):
        p = QgsProject()
        vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp")
        vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr")
        self.assertTrue(vector_layer.isValid())
        p.addMapLayer(vector_layer)

        l = QgsPrintLayout(p)
        atlas = l.atlas()
        atlas.setEnabled(True)
        atlas.setCoverageLayer(vector_layer)

        self.assertTrue(atlas.beginRender())
        self.assertTrue(atlas.first())
        self.assertEqual(atlas.currentFeatureNumber(), 0)
        self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie')
        self.assertEqual(l.reportContext().layer(), vector_layer)

        vector_layer.startEditing()
        self.assertTrue(vector_layer.changeAttributeValue(l.reportContext().feature().id(), 4, 'Nah, Canberra mate!'))
        self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie')
        l.atlas().refreshCurrentFeature()
        self.assertEqual(l.reportContext().feature()[4], 'Nah, Canberra mate!')
        vector_layer.rollBack()
Пример #7
0
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()
Пример #8
0
    def testProjectStorage(self):
        # New project without fileName
        p0 = QgsProject()
        self.assertTrue(p0.auxiliaryStorage().isValid())

        # Create new layers with key otherwise auxiliary layers are not
        # automacially created when added in project
        vl0 = createLayer()
        vl0Shp = writeShape(vl0, 'vl0.shp')

        vl1 = createLayer()
        vl1Shp = writeShape(vl1, 'vl1.shp')

        vl0 = QgsVectorLayer(vl0Shp, 'points', 'ogr')
        self.assertTrue(vl0.isValid())

        vl1 = QgsVectorLayer(vl1Shp, 'points', 'ogr')
        self.assertTrue(vl1.isValid())

        # Add layers to project and check underlying auxiliary layers
        p0.addMapLayers([vl0, vl1])

        self.assertTrue(vl0.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'pk'))
        self.assertTrue(
            vl1.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'num_char'))

        al0 = vl0.auxiliaryLayer()
        al1 = vl1.auxiliaryLayer()

        self.assertEqual(al0.joinInfo().targetFieldName(), 'pk')
        self.assertEqual(al1.joinInfo().targetFieldName(), 'num_char')

        # Add a field in auxiliary layers
        pdef0 = QgsPropertyDefinition('propname',
                                      QgsPropertyDefinition.DataTypeNumeric,
                                      '', '', 'ut')
        self.assertTrue(al0.addAuxiliaryField(pdef0))

        pdef1 = QgsPropertyDefinition('propname1',
                                      QgsPropertyDefinition.DataTypeString, '',
                                      '', 'ut')
        self.assertTrue(al1.addAuxiliaryField(pdef1))

        # Check auxiliary fields names
        af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, False)
        self.assertEqual(af0Name, 'ut_propname')
        af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, False)
        self.assertEqual(af1Name, 'ut_propname1')

        # Set value for auxiliary fields
        req = QgsFeatureRequest().setFilterExpression("name = 'Honey'")
        f = QgsFeature()
        vl0.getFeatures(req).nextFeature(f)
        self.assertTrue(f.isValid())
        af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, True)
        index0 = vl0.fields().indexOf(af0Name)
        vl0.changeAttributeValue(f.id(), index0, 333)

        req = QgsFeatureRequest().setFilterExpression("name = 'Apple'")
        f = QgsFeature()
        vl1.getFeatures(req).nextFeature(f)
        self.assertTrue(f.isValid())
        af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, True)
        index1 = vl1.fields().indexOf(af1Name)
        vl1.changeAttributeValue(f.id(), index0, 'myvalue')

        req = QgsFeatureRequest().setFilterExpression("name = 'Orange'")
        f = QgsFeature()
        vl1.getFeatures(req).nextFeature(f)
        self.assertTrue(f.isValid())
        vl1.changeAttributeValue(f.id(), index0, 'myvalue1')

        # Save the project in a zip file
        f = tmpPath() + '.qgz'
        p0.write(f)

        # Open the zip file with embedded auxiliary storage
        p1 = QgsProject()
        p1.read(f)

        # Check that auxiliary fields are well loaded in layers
        self.assertEqual(len(p1.mapLayers().values()), 2)

        for vl in p1.mapLayers().values():
            al = vl.auxiliaryLayer()
            self.assertEqual(len(al.auxiliaryFields()), 1)

            af = al.auxiliaryFields()[0]
            afPropDef = QgsAuxiliaryLayer.propertyDefinitionFromField(af)
            self.assertEqual(afPropDef.origin(), 'ut')

            if vl.auxiliaryLayer().joinInfo().targetFieldName() == 'pk':
                self.assertEqual(afPropDef.name(), 'propname')
                self.assertEqual(al.featureCount(), 1)

                req = QgsFeatureRequest().setFilterExpression("name = 'Honey'")
                f = QgsFeature()
                vl.getFeatures(req).nextFeature(f)
                self.assertTrue(f.isValid())
                self.assertEqual(f.attributes()[index0], 333.0)
            else:  # num_char
                self.assertEqual(al.featureCount(), 2)
                self.assertEqual(afPropDef.name(), 'propname1')

                req = QgsFeatureRequest().setFilterExpression("name = 'Apple'")
                f = QgsFeature()
                vl.getFeatures(req).nextFeature(f)
                self.assertTrue(f.isValid())
                self.assertEqual(f.attributes()[index1], 'myvalue')

                req = QgsFeatureRequest().setFilterExpression(
                    "name = 'Orange'")
                f = QgsFeature()
                vl.getFeatures(req).nextFeature(f)
                self.assertTrue(f.isValid())
                self.assertEqual(f.attributes()[index1], 'myvalue1')
Пример #9
0
    def testGeopackageTwoLayerEdition(self):
        ''' test https://issues.qgis.org/issues/17034 '''
        tmpfile = os.path.join(self.basetestpath,
                               'testGeopackageTwoLayerEdition.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)'))
        lyr.CreateFeature(f)
        f = None
        lyr = ds.CreateLayer('layer2', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 1)'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1",
                             u'layer1', u'ogr')
        vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2",
                             u'layer2', u'ogr')

        # Edit vl1, vl2 multiple times
        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(
            vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (2 2)')))
        self.assertTrue(
            vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (3 3)')))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeAttributeValue(1, 1, 100))
        self.assertTrue(vl2.changeAttributeValue(1, 1, 101))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(
            vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (4 4)')))
        self.assertTrue(
            vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (5 5)')))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        vl1 = None
        vl2 = None

        # Check everything is as expected after re-opening
        vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1",
                             u'layer1', u'ogr')
        vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2",
                             u'layer2', u'ogr')

        got = [feat for feat in vl1.getFeatures()][0]
        got_geom = got.geometry()
        self.assertEqual(got['attr'], 100)
        reference = QgsGeometry.fromWkt('Point (4 4)')
        self.assertEqual(
            got_geom.asWkb(), reference.asWkb(),
            'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))

        got = [feat for feat in vl2.getFeatures()][0]
        got_geom = got.geometry()
        self.assertEqual(got['attr'], 101)
        reference = QgsGeometry.fromWkt('Point (5 5)')
        self.assertEqual(
            got_geom.asWkb(), reference.asWkb(),
            'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))
Пример #10
0
 def on_click_Inici(self):
     global lbl_Cost
     global data
     global listFields
     global urlToLoad
     global TEMPORARY_PATH
 
     self.dlg.setEnabled(False)
     '''Tratamiento de errores'''
     llistaErrors = self.controlErrorsInput()
     if len(llistaErrors) > 0:
         llista = "Llista d'errors:\n\n"
         for i in range (0,len(llistaErrors)):
             llista += ("- "+llistaErrors[i] + '\n')
         QMessageBox.information(None, "Error", llista)
         self.dlg.setEnabled(True)
         return
     
     
     textBox = u'INICI DEL PROCÉS\n\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     campNom = ''
     campGeometria = ''
     campCod = ''
     campSrc = ''
     campLat = ''
     campLng = ''
     
     
     '''Obtención de Nom y Geometria'''
     if self.dlg.radio_ws.isChecked():
         campNom,campGeometria,campLat, campLng, campCod,campSrc=self.searchNomGeomCodSrcInFile()
         urlToLoad=self.dlg.combo_ws.currentText()
         #if(urlToLoad[-4:]=='.csv'):
         error = self.loadCSV(campNom, campGeometria, campCod,True)
         if (error=="Error"):
             self.dlg.setEnabled(True)
             return
 
     else:
         campNom = self.dlg.combo_nom.currentText()
         campCod=self.dlg.combo_cod.currentText()
         campSrc=self.dlg.combo_src.currentText()   
         if self.dlg.radio_geom.isChecked():
             campGeometria = self.dlg.combo_geom.currentText()
         elif self.dlg.radio_latlng.isChecked():
             campLat=self.dlg.combo_lat.currentText()
             campLng=self.dlg.combo_lng.currentText()
     
     '''Creación vector layer'''
     self.dlg.progressBar.setValue(60)
     textBox += u'Generant capa vectorial...\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     if campGeometria != '':
         file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s&wktField=%s&crs=%s' % (campCod,",", campGeometria,campSrc)
     elif campLat != '' and campLng != '':
         file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s&xField=%s&yField=%s&crs=%s' % (campCod,",", campLng, campLat,campSrc)
     else:
         file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s' % (campCod,",")  
     vlayergeom = QgsVectorLayer(file, self.dlg.txt_nomTaula.text(),'delimitedtext')
     try:
         vlayergeom = self.comprobarValidez(vlayergeom) #Sirve tanto para comprobar la corrección del CSV como para pasar el layer a memoria
     except Exception as ex:
         missatge="La geometria seleccionada no és correcte"
         print (missatge)
         template = "An exception of type {0} occurred. Arguments:\n{1!r}"
         message = template.format(type(ex).__name__, ex.args)
         print (message)
         QMessageBox.information(None, "Error", missatge)
         self.dlg.text_info.setText('')
         self.dlg.progressBar.setValue(0)
         self.dlg.setEnabled(True)
         return "Error"
     vlayergeom.setName(self.dlg.txt_nomTaula.text())
            
     self.dlg.progressBar.setValue(80)
     textBox += u'Adaptant camps...\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     
     '''Se renombra el campo de nombre y se añade un id'''
     vlayergeom.startEditing()
     fields = vlayergeom.fields()
     for x in range(len(fields)):
         if(campNom in fields[x].displayName()):
             vlayergeom.renameAttribute(x,'Nom')
             break;
     vlayergeom.addAttribute(QgsField('id', QVariant.Int))
     vlayergeom.commitChanges()
     
     '''Se autonumera el id'''
     features = vlayergeom.getFeatures()
     vlayergeom.startEditing()
     x=1
     for feature in features:
         vlayergeom.changeAttributeValue(feature.id(),self.getIndexOfField(vlayergeom,"id"),x)
         x=x+1
     vlayergeom.commitChanges()
        
     
     '''Se borran los campos no seleccionados''' 
     if not self.dlg.radio_ws.isChecked():
         llista_sel=[]    
         if (len(self.dlg.ListaCamps.selectedItems())>0):
             for item in self.dlg.ListaCamps.selectedItems():
                 llista_sel.append(item.text())
         
         vlayergeom.startEditing()
         for elem in listFields:
             if elem not in llista_sel:
                 vlayergeom.deleteAttribute(self.getIndexOfField(vlayergeom,elem))
         
         vlayergeom.commitChanges()
    
    
     '''Se representa en pantalla'''
     QgsProject.instance().addMapLayer(vlayergeom,False)
     root = QgsProject.instance().layerTreeRoot()
     myLayerNode=QgsLayerTreeLayer(vlayergeom)
     root.insertChildNode(0,myLayerNode)
     myLayerNode.setCustomProperty("showFeatureCount", True)
     
     
     if self.dlg.checkBox_save.isChecked():
         this_folder = os.path.dirname(os.path.abspath(__file__))   
         '''UPDATE'''
         file = open(this_folder+'/default_ws.txt') 
         cont=0
         strToWrite = ''
         for line in file:
             if (line.split('=',1)[1].replace('\n','')==self.dlg.txt_url.text()):
                 cont+=1
                 strToWrite+= line
             elif (cont==1):
                 cont+=1
                 strToWrite+= 'nom='+campNom+'\n'
             elif (cont==2):
                 cont+=1
                 if self.dlg.radio_geom.isChecked():
                     strToWrite+= 'geom='+campGeometria+'\n'
                 else:
                     strToWrite+='geom=\n'
             elif (cont==3):
                 cont+=1
                 if self.dlg.radio_latlng.isChecked():
                     strToWrite+= 'lat='+campLat+'\n'
                 else:
                     strToWrite+='lat=\n'
             elif (cont==4):
                 cont+=1
                 if self.dlg.radio_latlng.isChecked():
                     strToWrite+= 'lng='+campLng+'\n'
                 else:
                     strToWrite+='lng=\n'
             elif (cont==5):
                 cont+=1
                 strToWrite+= 'cod='+campCod+'\n'
             elif (cont==6):
                 cont+=1
                 strToWrite+= 'src='+campSrc+'\n'
             else:
                 strToWrite+=line
         file.close()
         file = open(this_folder+'/default_ws.txt', "w")
         file.write(strToWrite)
         file.close()    
         
         '''APEND'''
         if cont == 0:
             strToAppend = '\nurl='+self.dlg.txt_url.text()
             strToAppend += '\nnom='+campNom
             if self.dlg.radio_geom.isChecked():
                 strToAppend += '\ngeo='+campGeometria
             else:
                 strToAppend += '\ngeo='
             if self.dlg.radio_latlng.isChecked():
                 strToAppend += '\nlat='+campLat
                 strToAppend += '\nlng='+campLng
             else:
                 strToAppend += '\nlat='
                 strToAppend += '\nlng='
             strToAppend += '\ncod='+campCod
             strToAppend += '\nsrc='+campSrc
             file = open(this_folder+'/default_ws.txt', "a")
             file.write(strToAppend)
             file.close()
         
         
         self.file2Combo("default_ws.txt", self.dlg.combo_ws, 'Selecciona una opció')
         
     
     self.dlg.progressBar.setValue(100)
     textBox += u'\nProcés finalitzat.\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     self.dlg.setEnabled(True)
Пример #11
0
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())
        def _test(autoTransaction):
            """Test buffer methods within and without transactions

            - create a feature
            - save
            - retrieve the feature
            - change geom and attrs
            - test changes are seen in the buffer
            """

            def _check_feature(wkt):

                f = next(layer_a.getFeatures())
                self.assertEqual(f.geometry().asWkt().upper(), wkt)
                f = list(buffer.addedFeatures().values())[0]
                self.assertEqual(f.geometry().asWkt().upper(), wkt)

            ml = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test', 'memory')
            self.assertTrue(ml.isValid())

            d = QTemporaryDir()
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.driverName = 'GPKG'
            options.layerName = 'layer_a'
            err, _ = QgsVectorFileWriter.writeAsVectorFormatV2(ml, os.path.join(d.path(), 'transaction_test.gpkg'), QgsCoordinateTransformContext(), options)

            self.assertEqual(err, QgsVectorFileWriter.NoError)
            self.assertTrue(os.path.isfile(os.path.join(d.path(), 'transaction_test.gpkg')))

            options.layerName = 'layer_b'
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
            err, _ = QgsVectorFileWriter.writeAsVectorFormatV2(ml, os.path.join(d.path(), 'transaction_test.gpkg'), QgsCoordinateTransformContext(), options)

            layer_a = QgsVectorLayer(os.path.join(d.path(), 'transaction_test.gpkg|layername=layer_a'))

            self.assertTrue(layer_a.isValid())

            project = QgsProject()
            project.setAutoTransaction(autoTransaction)
            project.addMapLayers([layer_a])

            ###########################################
            # Tests with a new feature

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 123)
            f.setGeometry(QgsGeometry.fromWkt('point(7 45)'))
            self.assertTrue(layer_a.addFeatures([f]))

            _check_feature('POINT (7 45)')

            # Need to fetch the feature because its ID is NULL (-9223372036854775808)
            f = next(layer_a.getFeatures())

            self.assertEqual(len(buffer.addedFeatures()), 1)
            layer_a.undoStack().undo()
            self.assertEqual(len(buffer.addedFeatures()), 0)
            layer_a.undoStack().redo()
            self.assertEqual(len(buffer.addedFeatures()), 1)
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)

            # Now change attribute
            self.assertEqual(buffer.changedAttributeValues(), {})
            layer_a.changeAttributeValue(f.id(), 1, 321)

            self.assertEqual(len(buffer.addedFeatures()), 1)
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 321)

            layer_a.undoStack().undo()
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)

            # Change geometry
            f = next(layer_a.getFeatures())
            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)')))

            _check_feature('POINT (9 43)')
            self.assertEqual(buffer.changedGeometries(), {})

            layer_a.undoStack().undo()

            _check_feature('POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)')))
            _check_feature('POINT (9 43)')

            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(10 44)')))
            _check_feature('POINT (10 44)')

            # This is anothr surprise: geometry edits get collapsed into a single
            # one because they have the same hardcoded id
            layer_a.undoStack().undo()
            _check_feature('POINT (7 45)')

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Tests with the existing feature

            # Get the feature
            f = next(layer_a.getFeatures())
            self.assertTrue(f.isValid())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')

            self.assertTrue(layer_a.startEditing())
            layer_a.changeAttributeValue(f.id(), 1, 321)
            buffer = layer_a.editBuffer()
            self.assertEqual(buffer.changedAttributeValues(), {1: {1: 321}})
            layer_a.undoStack().undo()
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change geometry
            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)')))
            f = next(layer_a.getFeatures())
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (9 43)')
            self.assertEqual(buffer.changedGeometries()[1].asWkt().upper(), 'POINT (9 43)')
            layer_a.undoStack().undo()
            self.assertEqual(buffer.changedGeometries(), {})
            f = next(layer_a.getFeatures())

            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            # Delete an existing feature
            self.assertTrue(layer_a.deleteFeature(f.id()))
            with self.assertRaises(StopIteration):
                next(layer_a.getFeatures())
            self.assertEqual(buffer.deletedFeatureIds(), [f.id()])

            layer_a.undoStack().undo()
            self.assertTrue(layer_a.getFeature(f.id()).isValid())
            self.assertEqual(buffer.deletedFeatureIds(), [])

            ###########################################
            # Test delete

            # Delete a new feature
            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 555)
            f.setGeometry(QgsGeometry.fromWkt('point(8 46)'))
            self.assertTrue(layer_a.addFeatures([f]))
            f = [f for f in layer_a.getFeatures() if f.attribute('int') == 555][0]
            self.assertTrue(f.id() in buffer.addedFeatures())
            self.assertTrue(layer_a.deleteFeature(f.id()))
            self.assertFalse(f.id() in buffer.addedFeatures())
            self.assertFalse(f.id() in buffer.deletedFeatureIds())

            layer_a.undoStack().undo()
            self.assertTrue(f.id() in buffer.addedFeatures())

            ###########################################
            # Add attribute

            field = QgsField('attr1', QVariant.String)
            self.assertTrue(layer_a.addAttribute(field))
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [])

            layer_a.undoStack().redo()
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Remove attribute

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertNotEqual(attr_idx, -1)

            self.assertTrue(layer_a.deleteAttribute(attr_idx))
            self.assertEqual(buffer.deletedAttributeIds(), [2])
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            layer_a.undoStack().undo()
            self.assertEqual(buffer.deletedAttributeIds(), [])
            self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx)

            layer_a.undoStack().redo()
            self.assertEqual(buffer.deletedAttributeIds(), [2])
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            self.assertTrue(layer_a.rollBack())

            ###########################################
            # Rename attribute

            self.assertTrue(layer_a.startEditing())

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertNotEqual(attr_idx, -1)

            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)
            self.assertTrue(layer_a.renameAttribute(attr_idx, 'new_name'))
            self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx)

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx)
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)

            layer_a.undoStack().redo()
            self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx)
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
Пример #13
0
    def set_contour_properties(self, input_file):
        """Set the X, Y, RGB, ROMAN attributes of the contour layer.

        :param input_file: (Required) Name of the contour layer.
        :type input_file: str

        :raise: InvalidLayerError if anything is amiss with the layer.
        """
        LOGGER.debug('set_contour_properties requested for %s.' % input_file)
        layer = QgsVectorLayer(input_file, 'mmi-contours', "ogr")
        if not layer.isValid():
            raise InvalidLayerError(input_file)

        layer.startEditing()
        # Now loop through the db adding selected features to mem layer
        request = QgsFeatureRequest()
        fields = layer.dataProvider().fields()

        for feature in layer.getFeatures(request):
            if not feature.isValid():
                LOGGER.debug('Skipping feature')
                continue
            # Work out x and y
            line = feature.geometry().asPolyline()
            y = line[0].y()

            x_max = line[0].x()
            x_min = x_max
            for point in line:
                if point.y() < y:
                    y = point.y()
                x = point.x()
                if x < x_min:
                    x_min = x
                if x > x_max:
                    x_max = x
            x = x_min + ((x_max - x_min) / 2)

            # Get length
            length = feature.geometry().length()

            mmi_value = float(feature['MMI'])
            # We only want labels on the whole number contours
            if mmi_value != round(mmi_value):
                roman = ''
            else:
                roman = romanise(mmi_value)

            # RGB from http://en.wikipedia.org/wiki/Mercalli_intensity_scale
            rgb = mmi_colour(mmi_value)

            # Now update the feature
            feature_id = feature.id()
            layer.changeAttributeValue(
                feature_id, fields.indexFromName('X'), x)
            layer.changeAttributeValue(
                feature_id, fields.indexFromName('Y'), y)
            layer.changeAttributeValue(
                feature_id, fields.indexFromName('RGB'), rgb)
            layer.changeAttributeValue(
                feature_id, fields.indexFromName('ROMAN'), roman)
            layer.changeAttributeValue(
                feature_id, fields.indexFromName('ALIGN'), 'Center')
            layer.changeAttributeValue(
                feature_id, fields.indexFromName('VALIGN'), 'HALF')
            layer.changeAttributeValue(
                feature_id, fields.indexFromName('LEN'), length)

        layer.commitChanges()
Пример #14
0
    def testPktComposite(self):
        """
        Check that tables with PKs composed of many fields of different types are correctly read and written to
        """
        vl = QgsVectorLayer(
            '{} type=POINT estimatedmetadata=true key=\'"pk1","pk2"\' table="qgis_test"."tb_test_compound_pk" (geom)'
            .format(self.dbconn), "test_compound", "mssql")
        self.assertTrue(vl.isValid())

        fields = vl.fields()

        f = next(
            vl.getFeatures(QgsFeatureRequest().setFilterExpression(
                'pk1 = 1 AND pk2 = 2')))
        # first of all: we must be able to fetch a valid feature
        self.assertTrue(f.isValid())
        self.assertEqual(f['pk1'], 1)
        self.assertEqual(f['pk2'], 2)
        self.assertEqual(f['value'], 'test 2')

        # can we edit a field?
        vl.startEditing()
        vl.changeAttributeValue(f.id(), fields.indexOf('value'),
                                'Edited Test 2')
        self.assertTrue(vl.commitChanges())

        # Did we get it right? Let's create a new QgsVectorLayer and try to read back our changes:
        vl2 = QgsVectorLayer(
            '{} type=POINT estimatedmetadata=true table="qgis_test"."tb_test_compound_pk" (geom) key=\'"pk1","pk2"\' '
            .format(self.dbconn), "test_compound2", "mssql")
        self.assertTrue(vl2.isValid())
        f2 = next(
            vl2.getFeatures(QgsFeatureRequest().setFilterExpression(
                'pk1 = 1 AND pk2 = 2')))
        self.assertTrue(f2.isValid())

        # Then, making sure we really did change our value.
        self.assertEqual(f2['value'], 'Edited Test 2')

        # How about inserting a new field?
        f3 = QgsFeature(vl2.fields())
        f3['pk1'] = 4
        f3['pk2'] = -9223372036854775800
        f3['value'] = 'other test'
        vl.startEditing()
        res, f3 = vl.dataProvider().addFeatures([f3])
        self.assertTrue(res)
        self.assertTrue(vl.commitChanges())

        # can we catch it on another layer?
        f4 = next(
            vl2.getFeatures(QgsFeatureRequest().setFilterExpression(
                'pk2 = -9223372036854775800')))

        self.assertTrue(f4.isValid())
        expected_attrs = [4, -9223372036854775800, 'other test']
        self.assertEqual(f4.attributes(), expected_attrs)

        # Finally, let's delete one of the features.
        f5 = next(
            vl2.getFeatures(QgsFeatureRequest().setFilterExpression(
                'pk1 = 2 AND pk2 = 1')))
        vl2.startEditing()
        vl2.deleteFeatures([f5.id()])
        self.assertTrue(vl2.commitChanges())

        # did we really delete? Let's try to get the deleted feature from the first layer.
        f_iterator = vl.getFeatures(
            QgsFeatureRequest().setFilterExpression('pk1 = 2 AND pk2 = 1'))
        got_feature = True

        try:
            f6 = next(f_iterator)
            got_feature = f6.isValid()
        except StopIteration:
            got_feature = False

        self.assertFalse(got_feature)
Пример #15
0
    def testPktCompositeFloat(self):
        """
        Check that tables with PKs composed of many fields of different types are correctly read and written to
        """
        vl = QgsVectorLayer(
            '{} type=POINT key=\'"pk1","pk2","pk3"\' table="qgis_test"."tb_test_composite_float_pk" (geom)'
            .format(self.dbconn), "test_composite_float", "mssql")
        self.assertTrue(vl.isValid())

        fields = vl.fields()

        f = next(
            vl.getFeatures(
                QgsFeatureRequest().setFilterExpression('pk3 = 3.14159274')))
        # first of all: we must be able to fetch a valid feature
        self.assertTrue(f.isValid())
        self.assertEqual(f['pk1'], 1)
        self.assertEqual(f['pk2'], 2)

        self.assertEqual(round(f['pk3'], 6), round(3.14159274, 6))
        self.assertEqual(f['value'], 'test 2')

        # can we edit a field?
        vl.startEditing()
        vl.changeAttributeValue(f.id(), fields.indexOf('value'),
                                'Edited Test 2')
        self.assertTrue(vl.commitChanges())

        # Did we get it right? Let's create a new QgsVectorLayer and try to read back our changes:
        vl2 = QgsVectorLayer(
            '{} sslmode=disable srid=4326 key=\'"pk1","pk2","pk3"\' table="qgis_test"."tb_test_composite_float_pk" (geom)'
            .format(self.dbconn), "test_composite_float2", "mssql")
        self.assertTrue(vl2.isValid())
        f2 = next(
            vl.getFeatures(
                QgsFeatureRequest().setFilterExpression('pk3 = 3.14159274')))
        self.assertTrue(f2.isValid())

        # just making sure we have the correct feature
        # Only 6 decimals for PostgreSQL 11.
        self.assertEqual(round(f2['pk3'], 6), round(3.14159274, 6))

        # Then, making sure we really did change our value.
        self.assertEqual(f2['value'], 'Edited Test 2')

        # How about inserting a new field?
        f3 = QgsFeature(vl2.fields())
        f3['pk1'] = 4
        f3['pk2'] = -9223372036854775800
        f3['pk3'] = 7.29154
        f3['value'] = 'other test'
        vl.startEditing()
        res, f3 = vl.dataProvider().addFeatures([f3])
        self.assertTrue(res)
        self.assertTrue(vl.commitChanges())

        # can we catch it on another layer?
        f4 = next(
            vl2.getFeatures(QgsFeatureRequest().setFilterExpression(
                'pk2 = -9223372036854775800')))

        self.assertTrue(f4.isValid())
        expected_attrs = [4, -9223372036854775800, 7.29154, 'other test']
        gotten_attrs = [f4['pk1'], f4['pk2'], round(f4['pk3'], 5), f4['value']]
        self.assertEqual(gotten_attrs, expected_attrs)

        # Finally, let's delete one of the features.
        f5 = next(
            vl2.getFeatures(
                QgsFeatureRequest().setFilterExpression('pk3 = 7.29154')))
        vl2.startEditing()
        vl2.deleteFeatures([f5.id()])
        self.assertTrue(vl2.commitChanges())

        # did we really delete?
        f_iterator = vl.getFeatures(
            QgsFeatureRequest().setFilterExpression('pk3 = 7.29154'))
        got_feature = True

        try:
            f6 = next(f_iterator)
            got_feature = f6.isValid()
        except StopIteration:
            got_feature = False

        self.assertFalse(got_feature)
Пример #16
0
def set_contour_properties(contour_file_path):
    """Set the X, Y, RGB, ROMAN attributes of the contour layer.

    :param contour_file_path: Path of the contour layer.
    :type contour_file_path: str

    :raise: InvalidLayerError if anything is amiss with the layer.
    """
    LOGGER.debug(
        'Set_contour_properties requested for %s.' % contour_file_path)
    layer = QgsVectorLayer(contour_file_path, 'mmi-contours', "ogr")
    if not layer.isValid():
        raise InvalidLayerError(contour_file_path)

    layer.startEditing()
    # Now loop through the db adding selected features to mem layer
    request = QgsFeatureRequest()

    for feature in layer.getFeatures(request):
        if not feature.isValid():
            LOGGER.debug('Skipping feature')
            continue
        # Work out x and y
        line = feature.geometry().asPolyline()
        y = line[0].y()

        x_max = line[0].x()
        x_min = x_max
        for point in line:
            if point.y() < y:
                y = point.y()
            x = point.x()
            if x < x_min:
                x_min = x
            if x > x_max:
                x_max = x
        x = x_min + ((x_max - x_min) / 2)

        # Get length
        length = feature.geometry().length()

        mmi_value = float(feature[contour_mmi_field['field_name']])
        # We only want labels on the whole number contours
        if mmi_value != round(mmi_value):
            roman = ''
        else:
            roman = romanise(mmi_value)

        # RGB from http://en.wikipedia.org/wiki/Mercalli_intensity_scale
        rgb = mmi_colour(mmi_value)

        # Now update the feature
        feature_id = feature.id()
        layer.changeAttributeValue(
            feature_id, field_index_from_definition(layer, contour_x_field), x)
        layer.changeAttributeValue(
            feature_id, field_index_from_definition(layer, contour_y_field), y)
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_colour_field), rgb)
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_roman_field), roman)
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_halign_field), 'Center')
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_valign_field), 'HALF')
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_length_field), length)

    layer.commitChanges()
Пример #17
0
    def testTypeValidation(self):
        """Test that incompatible types in attributes raise errors"""

        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer',
            'test', 'memory')
        self.assertTrue(vl.isValid())
        invalid = QgsFeature(vl.fields())
        invalid.setAttribute('int', 'A string')
        invalid.setGeometry(QgsGeometry.fromWkt('point(9 45)'))
        self.assertTrue(vl.startEditing())
        # Validation happens on commit
        self.assertTrue(vl.addFeatures([invalid]))
        self.assertFalse(vl.commitChanges())
        self.assertTrue(vl.rollBack())
        self.assertFalse(vl.hasFeatures())

        # Add a valid feature
        valid = QgsFeature(vl.fields())
        valid.setAttribute('int', 123)
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid]))
        self.assertTrue(vl.commitChanges())
        self.assertEqual(vl.featureCount(), 1)

        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        # Add both
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer',
            'test', 'memory')
        self.assertEqual(vl.featureCount(), 0)
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid, invalid]))
        self.assertFalse(vl.commitChanges())
        self.assertEqual(vl.featureCount(), 2)
        self.assertTrue(vl.rollBack())
        self.assertEqual(vl.featureCount(), 0)

        # Add both swapped
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer',
            'test', 'memory')
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([invalid, valid]))
        self.assertFalse(vl.commitChanges())
        self.assertEqual(vl.featureCount(), 2)
        self.assertTrue(vl.rollBack())
        self.assertEqual(vl.featureCount(), 0)

        # Change attribute value
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer',
            'test', 'memory')
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid]))
        self.assertTrue(vl.commitChanges())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.changeAttributeValue(1, 0, 'A string'))
        self.assertFalse(vl.commitChanges())
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 'A string')
        self.assertTrue(vl.rollBack())

        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        # Change attribute values
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer',
            'test', 'memory')
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid]))
        self.assertTrue(vl.commitChanges())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.changeAttributeValues(1, {0: 'A string'}))
        self.assertFalse(vl.commitChanges())
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 'A string')
        self.assertTrue(vl.rollBack())

        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        ##############################################
        # Test direct data provider calls

        # No rollback (old behavior)
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer',
            'test', 'memory')
        dp = vl.dataProvider()
        self.assertFalse(dp.addFeatures([valid, invalid])[0])
        self.assertEqual([f.attributes() for f in dp.getFeatures()], [[123]])
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        # Roll back
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=int:integer',
            'test', 'memory')
        dp = vl.dataProvider()
        self.assertFalse(dp.addFeatures([valid, invalid], QgsFeatureSink.RollBackOnErrors)[0])
        self.assertFalse(dp.hasFeatures())

        # Expected behavior for changeAttributeValues is to always roll back
        self.assertTrue(dp.addFeatures([valid])[0])
        self.assertFalse(dp.changeAttributeValues({1: {0: 'A string'}}))
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)
Пример #18
0
def link_irrig_swat(self):
    APEXMOD_path_dict = self.dirs_and_paths()
    # self.layer = QgsProject.instance().mapLayersByName("mf_grid (MODFLOW)")[0]
    # input1 = QgsProject.instance().mapLayersByName("mf_grid (MODFLOW)")[0]
    # provider = self.layer.dataProvider()
    # # Find *.wel file and read number of grid cells
    # for filename in glob.glob(str(APEXMOD_path_dict['MODFLOW'])+"/*.wel"):
    #     with open(filename, "r") as f:
    #         data = []
    #         for line in f.readlines():
    #             if not line.startswith("#"):
    #                 data.append(line.replace('\n', '').split())
    # wel_row = []
    # wel_col = []
    # nWell = int(data[0][0])
    # # Skip two lines in Riv package and get row and col
    # for i in range(2, nWell+2):
    #     wel_row.append(int(data[i][1]))
    #     wel_col.append(int(data[i][2]))

    # # Find grid cells according to the well package
    # feats = self.layer.getFeatures()
    # wel_matched = []

    # for f in feats:
    #     rowNo = f.attribute("row")
    #     colNo = f.attribute("col")
    #     for i in range(len(wel_row)):
    #         if ((rowNo == wel_row[i]) and (colNo == wel_col[i])):
    #             wel_matched.append(f.id())
    # self.layer.selectByIds(wel_matched)

    output_dir = APEXMOD_path_dict['Scenarios']
    name_ext = "irrig_swat_grid.shp"
    irrig_swat_grid = os.path.join(output_dir, name_ext)

    # Create layer field
    layer_swat_col = QgsVectorLayer(irrig_swat_grid,
                                    '{0}'.format("irrig_swat_grid"), 'ogr')
    lyrProvider = layer_swat_col.dataProvider()
    if lyrProvider.fields().indexFromName('layer') == -1:
        lyr_field = QgsField('layer', QVariant.Int)
        lyrProvider.addAttributes([lyr_field])
        layer_swat_col.updateFields()

        # Get the index numbers of the fields
        lyrIdx = lyrProvider.fields().indexFromName('layer')

        # Get features (Find out a way to change attribute values using another field)
        feats = layer_swat_col.getFeatures()
        layer_swat_col.startEditing()

        # add layer number
        for f in feats:
            layer_swat_col.changeAttributeValue(f.id(), lyrIdx, 1)
        layer_swat_col.commitChanges()

    # Join sub and hru id
    n3_ext = "irrig_swat_grid_s.shp"
    irrig_swat_grid_s = os.path.join(output_dir, n3_ext)
    # QgsVectorFileWriter.deleteShapeFile(irrig_mf_s)
    sub_shp = QgsProject.instance().mapLayersByName("sub (SWAT)")[0]
    processing.run("qgis:joinattributesbylocation", irrig_swat_grid, sub_shp,
                   ['intersects'], 0, 0, "sum,mean,min,max,median", 0,
                   irrig_swat_grid_s)

    # Join sub id
    n4_ext = "irrig_swat_grid_f.shp"
    irrig_swat_grid_f = os.path.join(output_dir, n4_ext)
    # QgsVectorFileWriter.deleteShapeFile(irrig_mf_f)
    hru_shp = QgsProject.instance().mapLayersByName("hru (SWAT)")[0]
    processing.run("qgis:joinattributesbylocation", irrig_swat_grid_s, hru_shp,
                   ['intersects'], 0, 0, "sum,mean,min,max,median", 0,
                   irrig_swat_grid_f)

    layer_swat = QgsVectorLayer(irrig_swat_grid_f, '{0}'.format("irrig_swat"),
                                'ogr')
    QgsProject.instance().addMapLayer(layer_swat, False)
    root = QgsProject.instance().layerTreeRoot()
    p_swat_tree = root.findGroup("Pumping from SWAT")
    p_swat_tree.insertChildNode(0, QgsLayerTreeLayer(layer_swat))
    self.dlg.lineEdit_irrig_swat_grids.setText(irrig_swat_grid_f)

    # delete unnecessary fields
    input2 = QgsProject.instance().mapLayersByName("irrig_swat")[0]
    fields = input2.dataProvider()
    fdname = [
        fields.indexFromName(field.name()) for field in fields.fields()
        if not (
            field.name() == 'Subbasin' or field.name() == 'row' or field.name(
            ) == 'col' or field.name() == 'HRU_ID' or field.name() == 'layer')
    ]

    fields.deleteAttributes(fdname)
    input2.updateFields()
    msgBox.setWindowTitle("Created!")
    msgBox.setText(
        "'irrig_swat.shp' file has been created!\n" +
        "If you have multiple HRUs for a well, open its Attribute table and modify it."
    )
    msgBox.exec_()
    def download_data(self):

        # Get user selection
        group_code = self.cbGroups.itemData(self.cbGroups.currentIndex())
        domain_code = self.cbDomains.itemData(self.cbDomains.currentIndex())
        element_code = self.cbElements.itemData(self.cbElements.currentIndex())
        item_code = self.cbItems.itemData(self.cbItems.currentIndex())
        download_folder = self.download_folder.text()

        # Check selection
        if group_code is None:
            self.bar.pushMessage(None, self.tr('Please select a group'), level=QgsMessageBar.CRITICAL)
        elif domain_code is None:
            self.bar.pushMessage(None, self.tr('Please select a domain'), level=QgsMessageBar.CRITICAL)
        elif element_code is None:
            self.bar.pushMessage(None, self.tr('Please select an element'), level=QgsMessageBar.CRITICAL)
        elif item_code is None:
            self.bar.pushMessage(None, self.tr('Please select an item'), level=QgsMessageBar.CRITICAL)
        elif download_folder is None or len(download_folder) == 0:
            self.bar.pushMessage(None, self.tr('Please select a download folder'), level=QgsMessageBar.CRITICAL)
        else:
            # Get data
            data = get_data(domain_code, element_code, item_code)
            # Notify the user
            self.bar.pushMessage(None, self.tr('Downloaded rows: ') + str(len(data)), level=QgsMessageBar.INFO)
            # Layer name
            layer_name = self.cbItems.currentText().replace(' ', '_') + '_' + self.cbElements.currentText().replace(' ', '_')
            folder_name = os.path.join(download_folder, group_code, domain_code)
            if not os.path.exists(folder_name):
                os.makedirs(folder_name)
            # Copy template layer
            output_file = copy_layer(folder_name, layer_name)
            layer = QgsVectorLayer(output_file, 'layer_name', 'ogr')
            # Add all the years to the layer
            feature_idx = 64
            year_to_be_shown = 2014
            number_of_nulls = 0
            for year in range(2014, 1960, -1):
                progress = (1 + (feature_idx - 64)) * 1.86
                self.progress.setValue(progress)
                self.progress_label.setText('<b>' + self.tr('Progress') + ': ' + '</b> ' + self.tr('Adding Year ') + str(year))
                year_data = self.get_year_data(data, year)
                layer.dataProvider().addAttributes([QgsField(str(year), QVariant.Double)])
                if len(year_data) > 0:
                    layer.startEditing()
                    for feature in layer.getFeatures():
                        if feature['FAOSTAT'] is not None:
                            feature_code = str(feature['FAOSTAT'])
                            for d in year_data:
                                data_code = str(d['code'])
                                if data_code == feature_code:
                                    value = d['value']
                                    layer.changeAttributeValue(feature.id(), (feature_idx), float(value))
                                    tmp_feature = QgsFeature()
                                    tmp_feature.setAttributes([float(value)])
                                    layer.dataProvider().addFeatures([tmp_feature])
                                    if value is None:
                                        number_of_nulls += 1
                    layer.commitChanges()
                else:
                    year_to_be_shown -= 1
                feature_idx += 1
            # Add layer to canvas
            if self.add_to_canvas.isChecked():
                renderer = self.create_join_renderer(layer, str(year_to_be_shown), 11, QgsGraduatedSymbolRendererV2.Pretty)
                l = QgsVectorLayer(output_file, layer_name + '(' + str(year_to_be_shown) + ')', 'ogr')
                r = renderer.clone()
                r.setClassAttribute(str(year_to_be_shown))
                l.setRendererV2(r)
                QgsMapLayerRegistry.instance().addMapLayer(l)
                self.iface.legendInterface().setLayerVisible(l, True)
            # Close pop-up
            self.dlg.close()
Пример #20
0
    def download_data(self):

        # Get user selection
        group_code = self.cbGroups.itemData(self.cbGroups.currentIndex())
        domain_code = self.cbDomains.itemData(self.cbDomains.currentIndex())
        element_code = self.cbElements.itemData(self.cbElements.currentIndex())
        item_code = self.cbItems.itemData(self.cbItems.currentIndex())
        download_folder = self.download_folder.text()

        # Check selection
        if group_code is None:
            self.bar.pushMessage(None,
                                 self.tr('Please select a group'),
                                 level=QgsMessageBar.CRITICAL)
        elif domain_code is None:
            self.bar.pushMessage(None,
                                 self.tr('Please select a domain'),
                                 level=QgsMessageBar.CRITICAL)
        elif element_code is None:
            self.bar.pushMessage(None,
                                 self.tr('Please select an element'),
                                 level=QgsMessageBar.CRITICAL)
        elif item_code is None:
            self.bar.pushMessage(None,
                                 self.tr('Please select an item'),
                                 level=QgsMessageBar.CRITICAL)
        elif download_folder is None or len(download_folder) == 0:
            self.bar.pushMessage(None,
                                 self.tr('Please select a download folder'),
                                 level=QgsMessageBar.CRITICAL)
        else:
            # Get data
            data = get_data(domain_code, element_code, item_code)
            # Notify the user
            self.bar.pushMessage(None,
                                 self.tr('Downloaded rows: ') + str(len(data)),
                                 level=QgsMessageBar.INFO)
            # Layer name
            layer_name = self.cbItems.currentText().replace(
                ' ', '_') + '_' + self.cbElements.currentText().replace(
                    ' ', '_')
            folder_name = os.path.join(download_folder, group_code,
                                       domain_code)
            if not os.path.exists(folder_name):
                os.makedirs(folder_name)
            # Copy template layer
            output_file = copy_layer(folder_name, layer_name)
            layer = QgsVectorLayer(output_file, 'layer_name', 'ogr')
            # Add all the years to the layer
            feature_idx = 64
            year_to_be_shown = 2014
            number_of_nulls = 0
            for year in range(2014, 1960, -1):
                progress = (1 + (feature_idx - 64)) * 1.86
                self.progress.setValue(progress)
                self.progress_label.setText('<b>' + self.tr('Progress') +
                                            ': ' + '</b> ' +
                                            self.tr('Adding Year ') +
                                            str(year))
                year_data = self.get_year_data(data, year)
                layer.dataProvider().addAttributes(
                    [QgsField(str(year), QVariant.Double)])
                if len(year_data) > 0:
                    layer.startEditing()
                    for feature in layer.getFeatures():
                        if feature['FAOSTAT'] is not None:
                            feature_code = str(feature['FAOSTAT'])
                            for d in year_data:
                                data_code = str(d['code'])
                                if data_code == feature_code:
                                    value = d['value']
                                    layer.changeAttributeValue(
                                        feature.id(), (feature_idx),
                                        float(value))
                                    tmp_feature = QgsFeature()
                                    tmp_feature.setAttributes([float(value)])
                                    layer.dataProvider().addFeatures(
                                        [tmp_feature])
                                    if value is None:
                                        number_of_nulls += 1
                    layer.commitChanges()
                else:
                    year_to_be_shown -= 1
                feature_idx += 1
            # Add layer to canvas
            if self.add_to_canvas.isChecked():
                renderer = self.create_join_renderer(
                    layer, str(year_to_be_shown), 11,
                    QgsGraduatedSymbolRendererV2.Pretty)
                l = QgsVectorLayer(
                    output_file,
                    layer_name + '(' + str(year_to_be_shown) + ')', 'ogr')
                r = renderer.clone()
                r.setClassAttribute(str(year_to_be_shown))
                l.setRendererV2(r)
                QgsMapLayerRegistry.instance().addMapLayer(l)
                self.iface.legendInterface().setLayerVisible(l, True)
            # Close pop-up
            self.dlg.close()
Пример #21
0
def processing(options, f, progressBar, progressMessage):
    '''
    Select trees which are on the contour of the forest and isolated trees.
    '''
    # Export Grid contour and isolated to crowns values
    forestSelectedPath = options['dst'] + 'tif/' + f + \
        '_forest_selected.tif'
    crownsPath = options['dst'] + 'shp/' + f + '_crowns.shp'
    # crownsStatsPath = options['dst'] + 'shp/' + f + '_crowns_stats.shp'
    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("gridstatisticsforpolygons started\n")
    fileTxt.close()

    crowns = QgsVectorLayer(crownsPath, "crowns", "ogr")
    inputStatRaster = QgsRasterLayer(forestSelectedPath, "forestSelected")
    z_stat = QgsZonalStatistics(crowns, inputStatRaster, '_', 1,
                                QgsZonalStatistics.Max)

    result_z_stat = z_stat.calculateStatistics(QgsFeedback())

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("gridstatisticsforpolygons passed\n")
    fileTxt.close()
    # crowns = QgsVectorLayer(crownsStatsPath, 'Crowns stats', 'ogr')
    crowns.selectByExpression('"_max"=1.0')
    selected_array = crowns.getValues("N", True)
    crowns.invertSelection()
    unselected_array = crowns.getValues("N", True)
    unselected_crowns_ids = crowns.getValues("$id", True)
    unselected_top_ids = crowns.getValues('"N" - 1', True)
    crowns.dataProvider().deleteFeatures(unselected_crowns_ids[0])

    treetopsPath = options['dst'] + 'shp/' + f + '_treetops.shp'
    treetops = QgsVectorLayer(treetopsPath, 'Tree tops', 'ogr')

    treetops.dataProvider().deleteFeatures(unselected_top_ids[0])

    treetopsSelectedPath = options['dst'] + 'shp/' + f + \
        '_treetops_selected.shp'
    crownsSelectedPath = options['dst'] + 'shp/' + f + '_crowns_selected.shp'
    treetopsTrianglesPath = options['dst'] + 'shp/' + f + \
        '_treetops_triangles.shp'

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("advancedpythonfieldcalculator started\n")
    fileTxt.close()

    treetops.dataProvider().addAttributes([QgsField('N', QVariant.Int)])
    treetops.updateFields()
    treetops.startEditing()
    for treetop in treetops.getFeatures():
        treetops.changeAttributeValue(treetop.id(),
                                      treetop.fieldNameIndex('N'),
                                      treetop.id())
    treetops.commitChanges()

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("joinattributesbylocation started\n")
    fileTxt.close()

    # Adapted from https://github.com/qgis/QGIS-Processing
    # TODO: replace by native QGIS c++ algo when available...

    crowns.dataProvider().addAttributes([QgsField('tid', QVariant.Int)])
    crowns.updateFields()
    crowns.startEditing()
    fcount = crowns.featureCount()
    counter = 0
    for crown in crowns.getFeatures():
        counter += 1
        progressBar.setValue(100 + int(counter * (600 / fcount)))
        progressMessage.setText('Joining crown ' + str(counter) + '/' +
                                str(fcount))
        request = QgsFeatureRequest()
        request.setFilterRect(crown.geometry().boundingBox())
        dp = treetops.dataProvider()
        for r in dp.getFeatures(request):
            if crown.geometry().intersects(r.geometry()):
                crowns.changeAttributeValue(crown.id(),
                                            crown.fieldNameIndex('tid'),
                                            r.id())
    crowns.commitChanges()

    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("delaunaytriangulation started\n")
    fileTxt.close()

    # delaunay triangulation Adapted from official Python plugin
    # TODO: replace by native QGIS c++ algo when available...

    fields = QgsFields()
    fields.append(QgsField('POINTA', QVariant.Double, '', 24, 15))
    fields.append(QgsField('POINTB', QVariant.Double, '', 24, 15))
    fields.append(QgsField('POINTC', QVariant.Double, '', 24, 15))
    crs = QgsCoordinateReferenceSystem('EPSG:2056')
    triangleFile = QgsVectorFileWriter(treetopsTrianglesPath, 'utf-8', fields,
                                       QgsWkbTypes.Polygon, crs,
                                       'ESRI Shapefile')

    pts = []
    ptDict = {}
    ptNdx = -1
    c = voronoi.Context()
    features = treetops.getFeatures()
    total = 100.0 / treetops.featureCount() if treetops.featureCount() else 0
    progressMessage.setText('Starting triangulation...')
    for current, inFeat in enumerate(features):
        geom = QgsGeometry(inFeat.geometry())
        if geom.isNull():
            continue
        if geom.isMultipart():
            points = geom.asMultiPoint()
        else:
            points = [geom.asPoint()]
        for n, point in enumerate(points):
            x = point.x()
            y = point.y()
            pts.append((x, y))
            ptNdx += 1
            ptDict[ptNdx] = (inFeat.id(), n)
    progressMessage.setText('Triangulation step 1 ok')

    if len(pts) < 3:
        raise QgsProcessingException(
            'Input file should contain at least 3 points. Choose '
            'another file and try again.')

    uniqueSet = set(item for item in pts)
    ids = [pts.index(item) for item in uniqueSet]
    sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet])
    c.triangulate = True
    voronoi.voronoi(sl, c)
    triangles = c.triangles
    feat = QgsFeature()

    total = 100.0 / len(triangles) if triangles else 1
    for current, triangle in enumerate(triangles):

        indices = list(triangle)
        indices.append(indices[0])
        polygon = []

        attrs = []
        step = 0
        for index in indices:
            fid, n = ptDict[ids[index]]
            request = QgsFeatureRequest().setFilterFid(fid)
            inFeat = next(treetops.getFeatures(request))
            geom = QgsGeometry(inFeat.geometry())
            point = QgsPoint(geom.asPoint())

            polygon.append(point)
            if step <= 3:
                attrs.append(ids[index])
            step += 1

        linestring = QgsLineString(polygon)
        poly = QgsPolygon()
        poly.setExteriorRing(linestring)
        feat.setAttributes(attrs)
        geometry = QgsGeometry().fromWkt(poly.asWkt())
        feat.setGeometry(geometry)
        triangleFile.addFeature(feat)
    progressMessage.setText('Triangulation terminated')

    #  Remove triangles with perimeter higher than threshold
    triangles = QgsVectorLayer(treetopsTrianglesPath, 'triangles', 'ogr')
    maxPeri = str(options['MaxTrianglePerimeter'])
    triangles.selectByExpression('$perimeter > ' + maxPeri)
    triangles_to_delete_ids = triangles.getValues("$id", True)
    triangles.dataProvider().deleteFeatures(triangles_to_delete_ids[0])

    outputDir = options["dst"]
    fileTxt = open(outputDir + "/log.txt", "a")
    fileTxt.write("treeSelector passed\n")
    fileTxt.close()
    progressMessage.setText('Starting convexhull computing...')
Пример #22
0
    def testShpZipSupport(self):
        ''' Test support for multi layer compressed shapefiles (.shp.zip) '''

        if int(osgeo.gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(
                3, 1, 0):
            return

        tmpfile = os.path.join(self.basetestpath, 'testShpZipSupport.shp.zip')
        ds = osgeo.ogr.GetDriverByName('ESRI Shapefile').CreateDataSource(
            tmpfile)
        lyr = ds.CreateLayer('layer1', geom_type=osgeo.ogr.wkbPoint)
        lyr.CreateField(osgeo.ogr.FieldDefn('attr', osgeo.ogr.OFTInteger))
        f = osgeo.ogr.Feature(lyr.GetLayerDefn())
        f.SetField('attr', 1)
        f.SetGeometry(osgeo.ogr.CreateGeometryFromWkt('POINT(0 0)'))
        lyr.CreateFeature(f)
        f = None
        lyr = ds.CreateLayer('layer2', geom_type=osgeo.ogr.wkbMultiLineString)
        lyr.CreateField(osgeo.ogr.FieldDefn('attr', osgeo.ogr.OFTInteger))
        f = osgeo.ogr.Feature(lyr.GetLayerDefn())
        f.SetField('attr', 2)
        f.SetGeometry(osgeo.ogr.CreateGeometryFromWkt('LINESTRING(0 0,1 1)'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl1 = QgsVectorLayer(tmpfile + '|layername=layer1', 'test', 'ogr')
        vl2 = QgsVectorLayer(tmpfile + '|layername=layer2', 'test', 'ogr')
        self.assertTrue(vl1.isValid())
        self.assertTrue(vl2.isValid())
        self.assertEqual(vl1.wkbType(), QgsWkbTypes.Point)
        self.assertEqual(vl2.wkbType(), QgsWkbTypes.MultiLineString)
        f1 = next(vl1.getFeatures())
        f2 = next(vl2.getFeatures())
        assert f1['attr'] == 1
        self.assertEqual(f1.geometry().constGet().asWkt(), 'Point (0 0)')
        assert f2['attr'] == 2
        self.assertEqual(f2.geometry().constGet().asWkt(),
                         'MultiLineString ((0 0, 1 1))')

        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeAttributeValue(f1.id(), 0, -1))
        self.assertTrue(vl2.changeAttributeValue(f2.id(), 0, -2))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        f = next(vl1.getFeatures())
        assert f['attr'] == -1

        f = next(vl2.getFeatures())
        assert f['attr'] == -2

        # Check DataItem
        registry = QgsApplication.dataItemProviderRegistry()
        ogrprovider = next(provider for provider in registry.providers()
                           if provider.name() == 'OGR')
        item = ogrprovider.createDataItem(tmpfile, None)
        children = item.createChildren()
        self.assertEqual(len(children), 2)
        uris = sorted([children[i].uri() for i in range(2)])
        self.assertIn('testShpZipSupport.shp.zip|layername=layer1', uris[0])
        self.assertIn('testShpZipSupport.shp.zip|layername=layer2', uris[1])

        gdalprovider = next(provider for provider in registry.providers()
                            if provider.name() == 'GDAL')
        item = gdalprovider.createDataItem(tmpfile, None)
        assert not item
Пример #23
0
        def _test(autoTransaction):
            """Test buffer methods within and without transactions

            - create a feature
            - save
            - retrieve the feature
            - change geom and attrs
            - test changes are seen in the buffer
            """
            def _check_feature(wkt):

                f = next(layer_a.getFeatures())
                self.assertEqual(f.geometry().asWkt().upper(), wkt)
                f = list(buffer.addedFeatures().values())[0]
                self.assertEqual(f.geometry().asWkt().upper(), wkt)

            ml = QgsVectorLayer(
                'Point?crs=epsg:4326&field=int:integer&field=int2:integer',
                'test', 'memory')
            self.assertTrue(ml.isValid())

            d = QTemporaryDir()
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.driverName = 'GPKG'
            options.layerName = 'layer_a'
            err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
                ml, os.path.join(d.path(), 'transaction_test.gpkg'),
                QgsCoordinateTransformContext(), options)

            self.assertEqual(err, QgsVectorFileWriter.NoError)
            self.assertTrue(os.path.isfile(newFileName))

            layer_a = QgsVectorLayer(newFileName + '|layername=layer_a')

            self.assertTrue(layer_a.isValid())

            project = QgsProject()
            project.setAutoTransaction(autoTransaction)
            project.addMapLayers([layer_a])

            ###########################################
            # Tests with a new feature

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 123)
            f.setGeometry(QgsGeometry.fromWkt('point(7 45)'))
            self.assertTrue(layer_a.addFeatures([f]))

            _check_feature('POINT (7 45)')

            # Need to fetch the feature because its ID is NULL (-9223372036854775808)
            f = next(layer_a.getFeatures())

            self.assertEqual(len(buffer.addedFeatures()), 1)
            layer_a.undoStack().undo()
            self.assertEqual(len(buffer.addedFeatures()), 0)
            layer_a.undoStack().redo()
            self.assertEqual(len(buffer.addedFeatures()), 1)
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)

            # Now change attribute
            self.assertEqual(buffer.changedAttributeValues(), {})
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValue(f.id(), 1, 321)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])

            self.assertEqual(len(buffer.addedFeatures()), 1)
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 321)

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123])
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)

            # Change multiple attributes
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValues(f.id(), {1: 321, 2: 456})
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])
            self.assertEqual(spy_attribute_changed[1], [f.id(), 2, 456])
            buffer = layer_a.editBuffer()
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            # This is because QgsVectorLayerUndoCommandChangeAttribute plural
            if not autoTransaction:
                layer_a.undoStack().undo()
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.attribute('int2'), None)
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(
                spy_attribute_changed[1 if autoTransaction else 0],
                [f.id(), 2, None])
            self.assertEqual(
                spy_attribute_changed[0 if autoTransaction else 1],
                [f.id(), 1, 123])

            # Change geometry
            f = next(layer_a.getFeatures())
            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            self.assertTrue(len(spy_geometry_changed), 1)
            self.assertEqual(spy_geometry_changed[0][0], f.id())
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(9 43)').asWkt())

            _check_feature('POINT (9 43)')
            self.assertEqual(buffer.changedGeometries(), {})

            layer_a.undoStack().undo()

            _check_feature('POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            _check_feature('POINT (9 43)')

            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(10 44)')))
            _check_feature('POINT (10 44)')

            # This is another surprise: geometry edits get collapsed into a single
            # one because they have the same hardcoded id
            layer_a.undoStack().undo()
            _check_feature('POINT (7 45)')

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Tests with the existing feature

            # Get the feature
            f = next(layer_a.getFeatures())
            self.assertTrue(f.isValid())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')

            # Change single attribute
            self.assertTrue(layer_a.startEditing())
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValue(f.id(), 1, 321)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])
            buffer = layer_a.editBuffer()
            self.assertEqual(buffer.changedAttributeValues(), {1: {1: 321}})

            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute(1), 321)

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute(1), 123)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123])
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change attributes
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValues(f.id(), {1: 111, 2: 654})
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(spy_attribute_changed[0], [1, 1, 111])
            self.assertEqual(spy_attribute_changed[1], [1, 2, 654])
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attributes(), [1, 111, 654])
            self.assertEqual(buffer.changedAttributeValues(),
                             {1: {
                                 1: 111,
                                 2: 654
                             }})

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            # This is because QgsVectorLayerUndoCommandChangeAttribute plural
            if not autoTransaction:
                layer_a.undoStack().undo()
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(
                spy_attribute_changed[0 if autoTransaction else 1],
                [1, 1, 123])
            self.assertEqual(
                spy_attribute_changed[1 if autoTransaction else 0],
                [1, 2, None])
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attributes(), [1, 123, None])
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change geometry
            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            self.assertEqual(spy_geometry_changed[0][0], 1)
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(9 43)').asWkt())

            f = next(layer_a.getFeatures())
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (9 43)')
            self.assertEqual(buffer.changedGeometries()[1].asWkt().upper(),
                             'POINT (9 43)')

            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            layer_a.undoStack().undo()
            self.assertEqual(spy_geometry_changed[0][0], 1)
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(7 45)').asWkt())
            self.assertEqual(buffer.changedGeometries(), {})
            f = next(layer_a.getFeatures())

            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            # Delete an existing feature
            self.assertTrue(layer_a.deleteFeature(f.id()))
            with self.assertRaises(StopIteration):
                next(layer_a.getFeatures())
            self.assertEqual(buffer.deletedFeatureIds(), [f.id()])

            layer_a.undoStack().undo()
            self.assertTrue(layer_a.getFeature(f.id()).isValid())
            self.assertEqual(buffer.deletedFeatureIds(), [])

            ###########################################
            # Test delete

            # Delete a new feature
            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 555)
            f.setGeometry(QgsGeometry.fromWkt('point(8 46)'))
            self.assertTrue(layer_a.addFeatures([f]))
            f = [
                f for f in layer_a.getFeatures() if f.attribute('int') == 555
            ][0]
            self.assertTrue(f.id() in buffer.addedFeatures())
            self.assertTrue(layer_a.deleteFeature(f.id()))
            self.assertFalse(f.id() in buffer.addedFeatures())
            self.assertFalse(f.id() in buffer.deletedFeatureIds())

            layer_a.undoStack().undo()
            self.assertTrue(f.id() in buffer.addedFeatures())

            ###########################################
            # Add attribute

            field = QgsField('attr1', QVariant.String)
            self.assertTrue(layer_a.addAttribute(field))
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [])

            layer_a.undoStack().redo()
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Remove attribute

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertNotEqual(attr_idx, -1)

            self.assertTrue(layer_a.deleteAttribute(attr_idx))
            self.assertEqual(buffer.deletedAttributeIds(), [attr_idx])
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            layer_a.undoStack().undo()
            self.assertEqual(buffer.deletedAttributeIds(), [])
            self.assertEqual(layer_a.fields().lookupField(field.name()),
                             attr_idx)

            # This is totally broken at least on OGR/GPKG: the rollback
            # does not restore the original fields
            if False:

                layer_a.undoStack().redo()
                self.assertEqual(buffer.deletedAttributeIds(), [attr_idx])
                self.assertEqual(layer_a.fields().lookupField(field.name()),
                                 -1)

                # Rollback!
                self.assertTrue(layer_a.rollBack())

                self.assertIn('attr1', layer_a.dataProvider().fields().names())
                self.assertIn('attr1', layer_a.fields().names())
                self.assertEqual(layer_a.fields().names(),
                                 layer_a.dataProvider().fields().names())

                attr_idx = layer_a.fields().lookupField(field.name())
                self.assertNotEqual(attr_idx, -1)

                self.assertTrue(layer_a.startEditing())
                attr_idx = layer_a.fields().lookupField(field.name())
                self.assertNotEqual(attr_idx, -1)

            ###########################################
            # Rename attribute

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)
            self.assertTrue(layer_a.renameAttribute(attr_idx, 'new_name'))
            self.assertEqual(layer_a.fields().lookupField('new_name'),
                             attr_idx)

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()),
                             attr_idx)
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)

            layer_a.undoStack().redo()
            self.assertEqual(layer_a.fields().lookupField('new_name'),
                             attr_idx)
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            #############################################
            # Try hard to make this fail for transactions
            if autoTransaction:
                self.assertTrue(layer_a.commitChanges())
                self.assertTrue(layer_a.startEditing())
                f = next(layer_a.getFeatures())

                # Do
                for i in range(10):
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.changeAttributeValue(f.id(), 2, i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0], [f.id(), 2, i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: i
                                      }})
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), i)

                # Undo/redo
                for i in range(9):

                    # Undo
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().undo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 8 - i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: 8 - i
                                      }})

                    # Redo
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().redo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 9 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 9 - i])

                    # Undo again
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().undo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 8 - i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: 8 - i
                                      }})

                    # Last check
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)

                self.assertEqual(buffer.changedAttributeValues(),
                                 {f.id(): {
                                      2: 0
                                  }})
                layer_a.undoStack().undo()
                buffer = layer_a.editBuffer()
                self.assertEqual(buffer.changedAttributeValues(), {})
                f = next(layer_a.getFeatures())
                self.assertEqual(f.attribute(2), None)
Пример #24
0
    def create_path_with_scratch_layer(self, path_links):
        # Create TSP route
        crs = self.link_layer.dataProvider().crs().authid()
        vl = QgsVectorLayer(f"LineString?crs={crs}", 'TSP Solution', "memory")
        pr = vl.dataProvider()

        # add fields
        pr.addAttributes(self.link_layer.dataProvider().fields())
        vl.updateFields(
        )  # tell the vector layer to fetch changes from the provider

        idx = self.link_layer.dataProvider().fieldNameIndex('link_id')
        self.link_features = {}
        for feat in self.link_layer.getFeatures():
            link_id = feat.attributes()[idx]
            self.link_features[link_id] = feat

        # add a feature
        all_links = []
        for k in path_links:
            fet = self.link_features[k]
            all_links.append(fet)

        # add all links to the temp layer
        pr.addFeatures(all_links)

        # add layer to the map
        QgsProject.instance().addMapLayer(vl)

        symbol = vl.renderer().symbol()
        symbol.setWidth(1.6)
        qgis.utils.iface.mapCanvas().refresh()

        # Create TSP stops
        crs = self.node_layer.dataProvider().crs().authid()
        nl = QgsVectorLayer(f"Point?crs={crs}", 'TSP Stops', "memory")
        pn = nl.dataProvider()

        # add fields
        pn.addAttributes(self.node_layer.dataProvider().fields())
        nl.updateFields(
        )  # tell the vector layer to fetch changes from the provider

        idx = self.node_layer.dataProvider().fieldNameIndex('node_id')
        self.node_features = {}
        for feat in self.node_layer.getFeatures():
            node_id = feat.attributes()[idx]
            self.node_features[node_id] = feat

        # add the feature
        stop_nodes = []
        seq = {}
        for i, k in enumerate(self.worker_thread.node_sequence[:-1]):
            fet = self.node_features[k]
            stop_nodes.append(fet)
            seq[k] = i + 1

        # add all links to the temp layer
        pn.addFeatures(stop_nodes)

        # Goes back and adds the order of visitation for each node
        pn.addAttributes([QgsField('sequence', QVariant.Int)])
        nl.updateFields()
        sdx = nl.dataProvider().fieldNameIndex('sequence')

        nl.startEditing()
        for feat in nl.getFeatures():
            node_id = feat.attributes()[idx]
            nl.changeAttributeValue(feat.id(), sdx, seq[node_id])

        nl.commitChanges()

        # add layer to the map
        QgsProject.instance().addMapLayer(nl)
        symbol = QgsMarkerSymbol.createSimple({'name': 'star', 'color': 'red'})
        symbol.setSize(6)
        nl.renderer().setSymbol(symbol)

        qgis.utils.iface.mapCanvas().refresh()
Пример #25
0
    def testGeopackageTwoLayerEdition(self):
        ''' test https://issues.qgis.org/issues/17034 '''
        tmpfile = os.path.join(self.basetestpath, 'testGeopackageTwoLayerEdition.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)'))
        lyr.CreateFeature(f)
        f = None
        lyr = ds.CreateLayer('layer2', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 1)'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr')
        vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2", u'layer2', u'ogr')

        # Edit vl1, vl2 multiple times
        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (2 2)')))
        self.assertTrue(vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (3 3)')))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeAttributeValue(1, 1, 100))
        self.assertTrue(vl2.changeAttributeValue(1, 1, 101))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (4 4)')))
        self.assertTrue(vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (5 5)')))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        vl1 = None
        vl2 = None

        # Check everything is as expected after re-opening
        vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr')
        vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2", u'layer2', u'ogr')

        got = [feat for feat in vl1.getFeatures()][0]
        got_geom = got.geometry()
        self.assertEqual(got['attr'], 100)
        reference = QgsGeometry.fromWkt('Point (4 4)')
        self.assertEqual(got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))

        got = [feat for feat in vl2.getFeatures()][0]
        got_geom = got.geometry()
        self.assertEqual(got['attr'], 101)
        reference = QgsGeometry.fromWkt('Point (5 5)')
        self.assertEqual(got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))
Пример #26
0
    def generate_guide_file(self):
        """Generates the guide file, if CheckBPlanned.isChecked then add_to_db
        is called. Finalising with calling on the cleanup function."""
        path = self.path[:self.path.index('tmp_files123')]
        file_name = path + 'guide_file_{f}_{g}.shp'.format(
            f=check_text(self.dlg.CBFieldList.currentText()),
            g=datetime.date(datetime.today()).isoformat())
        if os.path.isfile(file_name):
            msgBox = QMessageBox()
            msgBox.setText(
                self.
                tr('You have already created a guide file for this field today, do you want to replace it?'
                   ))
            msgBox.addButton(QPushButton(self.tr('Yes')), QMessageBox.YesRole)
            msgBox.addButton(QPushButton(self.tr('No')), QMessageBox.NoRole)
            res = msgBox.exec_()
            if res == 1:
                return
            try:
                for ending in ['dbf', 'prj', 'shp', 'shx']:
                    os.remove(file_name[:-3] + ending)
            except PermissionError:
                QMessageBox.information(
                    None, self.tr('Error'),
                    self.
                    tr('The file could not automatically be removed, please try to do it manually and create the guide file again'
                       ))
                return
        params = {
            'INPUT': self.path + "raster_output.tif",
            'BAND': 1,
            'OUTPUT': file_name,
            'FIELD': 'indexValue'
        }
        alg_name = 'gdal:polygonize'
        try:
            processing.run(alg_name, params)
            vl = QgsVectorLayer(file_name, 'ferti_layert', 'ogr')
            vl.startEditing()
            ferti_field = QgsField('Fertilizin', QVariant.Int)
            vl.dataProvider().addAttributes([ferti_field])
            vl.updateFields()
            idx = vl.dataProvider().fieldNameIndex('Fertilizin')

            for f in vl.getFeatures():
                val = f.attributes()[0]
                if type(val) is not int:
                    break
                ferti = int(np.interp(val, self.x_values, self.y_values))
                vl.changeAttributeValue(f.id(), idx, ferti)
            vl.commitChanges()
            del vl
            self.file_name = file_name
            if self.dlg.CheckBPlanned.isChecked():
                self.add_to_db()
            self.cleanup()
        except QgsProcessingException:
            QMessageBox.information(
                None, self.tr("Error:"),
                self.
                tr('Currently QGIS does not allow you to have any non English '
                   'character in the directory path or filename'))
            return
Пример #27
0
    def testProjectStorage(self):
        # New project without fileName
        p0 = QgsProject()
        self.assertTrue(p0.auxiliaryStorage().isValid())

        # Create new layers with key otherwise auxiliary layers are not
        # automacially created when added in project
        vl0 = createLayer()
        vl0Shp = writeShape(vl0, 'vl0.shp')

        vl1 = createLayer()
        vl1Shp = writeShape(vl1, 'vl1.shp')

        vl0 = QgsVectorLayer(vl0Shp, 'points', 'ogr')
        self.assertTrue(vl0.isValid())

        vl1 = QgsVectorLayer(vl1Shp, 'points', 'ogr')
        self.assertTrue(vl1.isValid())

        # Add layers to project and check underlying auxiliary layers
        p0.addMapLayers([vl0, vl1])

        self.assertTrue(vl0.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'pk'))
        self.assertTrue(vl1.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'num_char'))

        al0 = vl0.auxiliaryLayer()
        al1 = vl1.auxiliaryLayer()

        self.assertEqual(al0.joinInfo().targetFieldName(), 'pk')
        self.assertEqual(al1.joinInfo().targetFieldName(), 'num_char')

        # Add a field in auxiliary layers
        pdef0 = QgsPropertyDefinition('propname', QgsPropertyDefinition.DataTypeNumeric, '', '', 'ut')
        self.assertTrue(al0.addAuxiliaryField(pdef0))

        pdef1 = QgsPropertyDefinition('propname1', QgsPropertyDefinition.DataTypeString, '', '', 'ut')
        self.assertTrue(al1.addAuxiliaryField(pdef1))

        # Check auxiliary fields names
        af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, False)
        self.assertEqual(af0Name, 'ut_propname')
        af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, False)
        self.assertEqual(af1Name, 'ut_propname1')

        # Set value for auxiliary fields
        req = QgsFeatureRequest().setFilterExpression("name = 'Honey'")
        f = QgsFeature()
        vl0.getFeatures(req).nextFeature(f)
        self.assertTrue(f.isValid())
        af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, True)
        index0 = vl0.fields().indexOf(af0Name)
        vl0.changeAttributeValue(f.id(), index0, 333)

        req = QgsFeatureRequest().setFilterExpression("name = 'Apple'")
        f = QgsFeature()
        vl1.getFeatures(req).nextFeature(f)
        self.assertTrue(f.isValid())
        af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, True)
        index1 = vl1.fields().indexOf(af1Name)
        vl1.changeAttributeValue(f.id(), index0, 'myvalue')

        req = QgsFeatureRequest().setFilterExpression("name = 'Orange'")
        f = QgsFeature()
        vl1.getFeatures(req).nextFeature(f)
        self.assertTrue(f.isValid())
        vl1.changeAttributeValue(f.id(), index0, 'myvalue1')

        # Save the project in a zip file
        f = tmpPath() + '.qgz'
        p0.write(f)

        # Open the zip file with embedded auxiliary storage
        p1 = QgsProject()
        p1.read(f)

        # Check that auxiliary fields are well loaded in layers
        self.assertEqual(len(p1.mapLayers().values()), 2)

        for vl in p1.mapLayers().values():
            al = vl.auxiliaryLayer()
            self.assertEqual(len(al.auxiliaryFields()), 1)

            af = al.auxiliaryFields()[0]
            afPropDef = QgsAuxiliaryLayer.propertyDefinitionFromField(af)
            self.assertEqual(afPropDef.origin(), 'ut')

            if vl.auxiliaryLayer().joinInfo().targetFieldName() == 'pk':
                self.assertEqual(afPropDef.name(), 'propname')
                self.assertEqual(al.featureCount(), 1)

                req = QgsFeatureRequest().setFilterExpression("name = 'Honey'")
                f = QgsFeature()
                vl.getFeatures(req).nextFeature(f)
                self.assertTrue(f.isValid())
                self.assertEqual(f.attributes()[index0], 333.0)
            else: # num_char
                self.assertEqual(al.featureCount(), 2)
                self.assertEqual(afPropDef.name(), 'propname1')

                req = QgsFeatureRequest().setFilterExpression("name = 'Apple'")
                f = QgsFeature()
                vl.getFeatures(req).nextFeature(f)
                self.assertTrue(f.isValid())
                self.assertEqual(f.attributes()[index1], 'myvalue')

                req = QgsFeatureRequest().setFilterExpression("name = 'Orange'")
                f = QgsFeature()
                vl.getFeatures(req).nextFeature(f)
                self.assertTrue(f.isValid())
                self.assertEqual(f.attributes()[index1], 'myvalue1')
Пример #28
0
def set_contour_properties(contour_file_path):
    """Set the X, Y, RGB, ROMAN attributes of the contour layer.

    :param contour_file_path: Path of the contour layer.
    :type contour_file_path: str

    :raise: InvalidLayerError if anything is amiss with the layer.
    """
    LOGGER.debug('Set_contour_properties requested for %s.' %
                 contour_file_path)
    layer = QgsVectorLayer(contour_file_path, 'mmi-contours', "ogr")
    if not layer.isValid():
        raise InvalidLayerError(contour_file_path)

    layer.startEditing()
    # Now loop through the db adding selected features to mem layer
    request = QgsFeatureRequest()

    for feature in layer.getFeatures(request):
        if not feature.isValid():
            LOGGER.debug('Skipping feature')
            continue
        # Work out x and y
        line = feature.geometry().asPolyline()
        y = line[0].y()

        x_max = line[0].x()
        x_min = x_max
        for point in line:
            if point.y() < y:
                y = point.y()
            x = point.x()
            if x < x_min:
                x_min = x
            if x > x_max:
                x_max = x
        x = x_min + ((x_max - x_min) / 2)

        # Get length
        length = feature.geometry().length()

        mmi_value = float(feature[contour_mmi_field['field_name']])
        # We only want labels on the whole number contours
        if mmi_value != round(mmi_value):
            roman = ''
        else:
            roman = romanise(mmi_value)

        # RGB from http://en.wikipedia.org/wiki/Mercalli_intensity_scale
        rgb = mmi_colour(mmi_value)

        # Now update the feature
        feature_id = feature.id()
        layer.changeAttributeValue(
            feature_id, field_index_from_definition(layer, contour_x_field), x)
        layer.changeAttributeValue(
            feature_id, field_index_from_definition(layer, contour_y_field), y)
        layer.changeAttributeValue(
            feature_id, field_index_from_definition(layer,
                                                    contour_colour_field), rgb)
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_roman_field), roman)
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_halign_field), 'Center')
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_valign_field), 'HALF')
        layer.changeAttributeValue(
            feature_id,
            field_index_from_definition(layer, contour_length_field), length)

    layer.commitChanges()
Пример #29
0
def loadCSVLayer(gpsPath, logger, messageBar, dateFormat, mainWindow, messageBox):
    fields = ['date', 'time', 'x', 'y', 'altitude']
    userfields = []
    with open(gpsPath, 'rb') as csvfile:
        reader = csv.reader(csvfile, delimiter=',')
        i = 0
        for row in reader:
            if i == 0: #header row
                #check for x
                for f in fields:
                    Fre = re.search(f, str(row), re.I)
                    if Fre:
                        userfields.append(Fre.group())
                    else:
                        # hang an error
                        logger.error('CSV column names import error. Failed on: %s' % f)
                        messageBox.critical(mainWindow, "Column Name Error", "Missing column: %s\n\nPlease reformat csv file. Column headers should include: 'date', 'time', 'x', 'y', 'altitude'" %(f))
            else:
                pass
            i += 1

        if i < 10:
            messageBox.warning(mainWindow, "Friendly Import Warning", "This track is pretty short, which if fine. However, some of the track smoothing and tour automation won't work great because it is geared for longer tracks. Give it a try anyway and let us know if you encounter an error or serious problem at https://github.com/EdFarrell/MilkMachine/issues" )

    if len(userfields) == 5:
        logger.info('headers %s' % userfields)
        messageBar.pushMessage("Success", "User file column headers good: {0}".format(gpsPath), level=QgsMessageBar.INFO, duration=5)

        #http://qgis.org/api/classQgsVectorLayer.html
        layername = gpsPath.split(".")[0].split('/')[-1]
        #crs = QgsCoordinateReferenceSystem(4326).toProj4()
        crs = 'EPSG:4326'
        uri = "file:/" + gpsPath + "?delimiter=%s&xField=%s&yField=%s&crs=%s" % (",", "x", "y", crs)
        logger.info('uri: %s' % uri)
        Qlayer = QgsVectorLayer(uri, layername, "delimitedtext")

        # check the rest of the fields. required are date, time, and z
        fdict = field_indices(Qlayer)
        logger.info('fdict : %s' %(fdict))

        # save the kml layer as
        shapepath = gpsPath.split(".")[0] + '.shp'
        shapepath_line = gpsPath.split(".")[0] + '_line.shp'
        #shapepath_dup = gpsPath.split(".")[0] + '_duplicate.shp'

        QgsVectorFileWriter.writeAsVectorFormat(Qlayer, shapepath, "utf-8", None, "ESRI Shapefile")  # working copy
        #bring the shapefile back in, and render it on the map
        shaper = QgsVectorLayer(shapepath, layername, "ogr")
        shaper.dataProvider().addAttributes( [QgsField("datetime",QVariant.String), QgsField("camera",QVariant.String), QgsField("flyto",QVariant.String), QgsField("iconstyle", QVariant.String), QgsField("labelstyle", QVariant.String), QgsField("model", QVariant.String), QgsField("lookat", QVariant.String) , QgsField("symbtour", QVariant.String)])
        shaper.updateFields()

        fields = field_indices(shaper)
        # calculate the datetime field
        # idx = fields['datetime']  #feature.attributes()[idx]
        fid_dt = []
        # model_altitude = []
        try:
            for f in shaper.getFeatures():
                # currentatt = f.attributes()[fields['datetime']]  # this should be fields['Name']
                pointdate = f.attributes()[fields['date']]  #2014/06/06
                pointtime = f.attributes()[fields['time']]

                # format for microseconds
                sec_pieces = pointtime.split(':')[2].split('.')
                if len(sec_pieces) == 1:
                    microsec = 0
                elif len(sec_pieces) == 2:
                    microsec = int(float('0.' + sec_pieces[1]) * 1000000)

                #['mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy/mm/dd']
                if dateFormat == 'mm/dd/yyyy':
                    current_dt = datetime.datetime(int(pointdate.split('/')[2]), int(pointdate.split('/')[0]), int(pointdate.split('/')[1]), int(pointtime.split(':')[0]), int(pointtime.split(':')[1]), int(pointtime.split(':')[2]), microsec)
                elif dateFormat == 'dd/mm/yyyy':
                    current_dt = datetime.datetime(int(pointdate.split('/')[2]), int(pointdate.split('/')[1]), int(pointdate.split('/')[0]), int(pointtime.split(':')[0]), int(pointtime.split(':')[1]), int(pointtime.split(':')[2]), microsec)
                elif dateFormat == 'yyyy/mm/dd':
                    current_dt = datetime.datetime(int(pointdate.split('/')[0]), int(pointdate.split('/')[1]), int(pointdate.split('/')[2]), int(pointtime.split(':')[0]), int(pointtime.split(':')[1]), int(pointtime.split(':')[2]), microsec)

                fid_dt.append([f.id(), current_dt.strftime("%Y/%m/%d %H:%M:%S %f")])

            shaper.startEditing()
            shaper.beginEditCommand('datetime')
            for i,v in enumerate(fid_dt):
                shaper.changeAttributeValue(v[0],fields['datetime'], v[1])
            shaper.endEditCommand()
            shaper.commitChanges()

            return shaper
        except:
            logger.error('Error writing time to datetime column, user presented with messagebox')
            logger.exception(traceback.format_exc())
            messageBox.critical(mainWindow,"Date & Time Import Error", "An error occured while converting the 'date' and 'time' fields into a Python datetime object. Please make sure that your specified the correct date format, and the time format is HH:MM:SS. If your seconds are fractional, then please express this as SS.xxxxxx")
Пример #30
0
class ReorderProcess():
    """Along line point reordering

    according to given destination"""
    def __init__(self, exutoire, point_reseau):
        """Set all informations needed to order the network"""

        self.exutoire_layer = exutoire
        self.point_reseau_layer = point_reseau
        self.crs = QgsCoordinateReferenceSystem(
            self.point_reseau_layer.crs().authid())

        # Create ouput
        self.output = QgsVectorLayer("Point", "point", "memory")
        self.output.setCrs(self.crs)

        # Add fields
        name_T_id = "T_id"
        name_L_id = "L_id"
        name_P_id = "P_id"
        name_nat = "nature"
        provider = self.output.dataProvider()
        caps = provider.capabilities()
        if caps & QgsVectorDataProvider.AddAttributes:
            res = provider.addAttributes([
                QgsField(name_T_id, QVariant.String),
                QgsField(name_L_id, QVariant.String),
                QgsField(name_P_id, QVariant.String),
                QgsField(name_nat, QVariant.String)
            ])
            self.output.updateFields()
        # Save field index
        self.index_nat = self.point_reseau_layer.fieldNameIndex('nature')
        self.index_pid = self.point_reseau_layer.fieldNameIndex('P_id')
        self.index_order = self.point_reseau_layer.fieldNameIndex('order')
        self.l_done = []

    def reorder(self, pt, count_order):

        feat = QgsFeature(self.output.pendingFields())
        pt_geom = pt.geometry()
        feat.setGeometry(pt_geom)

        tid = pt.attribute("T_id")
        lid = pt.attribute("L_id")
        ppid = pt.attribute("P_id")
        nat = pt.attribute("nature")

        if nat == 'start':
            self.output.startEditing()
            feat.setAttributes([tid, str(count_order), ppid, nat])
            print 'reorder: %s' % ([tid, lid, ppid, nat, str(count_order)])
            self.output.dataProvider().addFeatures([feat])
            self.output.commitChanges()
            self.output.updateExtents()
            while nat != 'end':
                expr = QgsExpression('L_id = %s and P_id = %s' %
                                     (lid, str(int(ppid) + 1)))
                req = QgsFeatureRequest(expr)
                n_pt_it = self.point_reseau_layer.getFeatures(req)
                n_pt = n_pt_it.next()
                n_pt_it = None

                feat = QgsFeature(self.output.pendingFields())
                n_pt_geom = n_pt.geometry()
                feat.setGeometry(n_pt_geom)

                tid = n_pt.attribute("T_id")
                lid = n_pt.attribute("L_id")
                ppid = n_pt.attribute("P_id")
                nat = n_pt.attribute("nature")

                self.output.startEditing()
                feat.setAttributes([tid, str(count_order), ppid, nat])
                print[tid, lid, ppid, nat, str(count_order)]
                self.output.dataProvider().addFeatures([feat])
                self.output.commitChanges()
                self.output.updateExtents()
        else:
            pid = 0
            self.output.startEditing()
            feat.setAttributes([tid, str(count_order), str(pid), 'start'])
            print[tid, lid, str(pid), 'start', str(count_order)]
            self.output.dataProvider().addFeatures([feat])
            self.output.commitChanges()
            self.output.updateExtents()
            nat = None
            feat = None
            while nat != 'start':
                ppid = str(int(ppid) - 1)
                expr = QgsExpression('L_id = %s and P_id = %s' % (lid, ppid))
                req = QgsFeatureRequest(expr)
                n_pt_it = self.point_reseau_layer.getFeatures(req)
                n_pt = n_pt_it.next()
                n_pt_it = None

                feat = QgsFeature(self.output.pendingFields())
                n_pt_geom = n_pt.geometry()
                feat.setGeometry(n_pt_geom)

                tid = n_pt.attribute("T_id")
                nat = n_pt.attribute("nature")
                if nat != 'start':
                    pid += 1
                    self.output.startEditing()
                    feat.setAttributes([tid, str(count_order), str(pid), nat])
                    print[tid, lid, str(pid), nat, str(count_order)]
                    self.output.dataProvider().addFeatures([feat])
                    self.output.commitChanges()
                    self.output.updateExtents()
                    feat = None
                else:
                    pid += 1
                    self.output.startEditing()
                    feat.setAttributes(
                        [tid, str(count_order),
                         str(pid), 'end'])
                    print[tid, lid, str(pid), 'end', str(count_order)]
                    self.output.dataProvider().addFeatures([feat])
                    self.output.commitChanges()
                    self.output.updateExtents()
                    feat = None

    def executeReorder(self):

        count_order = 0
        # loop over exutoire features to process several network
        for exutoire in self.exutoire_layer.getFeatures():
            exutoire_geom = exutoire.geometry().buffer(1, 4).boundingBox()
            # Select the start point that intersects the outlet
            req = QgsFeatureRequest().setFilterRect(exutoire_geom)
            pts_reseau_sortie = self.point_reseau_layer.getFeatures(req)
            for pt_sortie in pts_reseau_sortie:
                count_order += 1
                L_id = pt_sortie.attribute("L_id")
                # Reorder the points of the first line of the network
                self.reorder(pt_sortie, count_order)
                nat = 'end'
                string = "L_id = %s AND nature = '%s'" % (count_order, nat)
                print string
                expr = QgsExpression(string)
                reque = QgsFeatureRequest(expr)
                # Select the last point of the first line
                pt_end_it = self.output.getFeatures(reque)
                pt_end = pt_end_it.next()
                pt_end_it = None
                # Make a buffer around the point to define a boundingBox
                pt_end_geom = pt_end.geometry().buffer(1, 4).boundingBox()
                req = QgsFeatureRequest(
                    QgsExpression("L_id != %s" %
                                  (str(L_id)))).setFilterRect(pt_end_geom)
                # Select the next points
                next_ls = self.point_reseau_layer.getFeatures(req)
                self.l_done.append(L_id)
                list_next = []
                # Fill next_ls list with the next features
                for next_l in next_ls:
                    list_next.append(next_l)
                # While there is features in list_next, reorder process continues
                while len(list_next) != 0:
                    current_list = list_next
                    list_next = []
                    # Loop over the next features
                    for next_pt in current_list:
                        # Get line id
                        L_id = next_pt.attribute("L_id")
                        print L_id
                        # if the line has not been already reorder
                        if L_id not in self.l_done:
                            count_order += 1
                            #then reorder
                            self.reorder(next_pt, count_order)
                            string = "L_id = %s AND nature='%s'" % (
                                count_order, nat)
                            print string
                            expr = QgsExpression(string)
                            req = QgsFeatureRequest(QgsExpression(expr))
                            pt_end_it = self.output.getFeatures(req)
                            pt_end = pt_end_it.next()
                            pt_end_it = None
                            pt_end_geom = pt_end.geometry().buffer(
                                1, 4).boundingBox()
                            # Find the next feature
                            reque = QgsFeatureRequest(
                                QgsExpression(
                                    "L_id != %s" %
                                    (L_id))).setFilterRect(pt_end_geom)
                            next_ls = self.point_reseau_layer.getFeatures(
                                reque)
                            self.l_done.append(L_id)
                            # Fill next_ls list again and loop
                            for next_l in next_ls:
                                list_next.append(next_l)
                    print len(list_next)

        expr = QgsExpression("nature = 'end'")
        req = QgsFeatureRequest(expr)
        end_pts = self.output.getFeatures(req)
        change_dict = {}
        change_list = []
        rm_ids = []
        #clean lines that aren't a cross border anymore because a small part has been removed
        for end_pt in end_pts:
            end_pt_geom = end_pt.geometry().buffer(1, 4).boundingBox()
            end_pt_id = end_pt.id()
            end_lid = end_pt.attribute("L_id")
            end_pid = end_pt.attribute("P_id")
            expr = QgsExpression("L_id != '%s'" % (end_lid))
            req = QgsFeatureRequest(expr).setFilterRect(end_pt_geom)
            int_pts = []
            for int_pt in self.output.getFeatures(req):
                lid_int_pt = int_pt.attribute("L_id")
                int_pts.append(int_pt)
            if len(int_pts) == 1:
                rm_ids.append(end_pt_id)
                if int(end_lid) in change_dict:
                    change_dict[int(lid_int_pt)] = change_dict[int(end_lid)]
                else:
                    change_dict[int(lid_int_pt)] = int(end_lid)
        print change_dict
        change_dict = sorted(change_dict.items(), key=lambda t: t[0])
        for ch_tuple in change_dict:
            print ch_tuple[0]
            end_lid = str(ch_tuple[1])
            end_pid = None
            for end_pt in self.output.getFeatures(
                    QgsFeatureRequest(
                        QgsExpression("L_id = '%s' and nature = '%s'" %
                                      (end_lid, "end")))):
                if end_pid is None:
                    end_pid = end_pt.attribute("P_id")
                elif int(end_pid) < int(end_pt.attribute("P_id")):
                    end_pid = end_pt.attribute("P_id")
            expr = QgsExpression("L_id = '%s'" % (str(ch_tuple[0])))
            req = QgsFeatureRequest(expr)
            for ch_pt in self.output.getFeatures(req):
                ch_pt_id = ch_pt.id()
                if ch_pt.attribute("nature") == "start":
                    rm_ids.append(ch_pt_id)
                else:
                    ch_tid = ch_pt.attribute("T_id")
                    ch_nature = ch_pt.attribute("nature")
                    self.output.startEditing()
                    self.output.changeAttributeValue(ch_pt_id, 1, end_lid)
                    self.output.changeAttributeValue(ch_pt_id, 2, end_pid)
                    self.output.commitChanges()
                    end_pid = int(end_pid) + 1
        self.output.startEditing()
        self.output.deleteFeatures(rm_ids)
        self.output.commitChanges()

        return self.output, self.crs