mirror of
https://github.com/qgis/QGIS.git
synced 2025-05-09 00:03:46 -04:00
2260 lines
85 KiB
Python
2260 lines
85 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""QGIS Unit tests for QgsVectorLayer.
|
|
|
|
.. note:: This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
"""
|
|
__author__ = 'Tim Sutton'
|
|
__date__ = '20/08/2012'
|
|
__copyright__ = 'Copyright 2012, The QGIS Project'
|
|
# This will get replaced with a git SHA1 when you do a git archive
|
|
__revision__ = '$Format:%H$'
|
|
|
|
import qgis # NOQA
|
|
|
|
import os
|
|
|
|
from qgis.PyQt.QtCore import QVariant, Qt
|
|
from qgis.PyQt.QtGui import QPainter
|
|
from qgis.PyQt.QtXml import QDomDocument
|
|
|
|
from qgis.core import (QgsWkbTypes,
|
|
QgsAction,
|
|
QgsEditorWidgetSetup,
|
|
QgsVectorLayer,
|
|
QgsRectangle,
|
|
QgsFeature,
|
|
QgsFeatureRequest,
|
|
QgsGeometry,
|
|
QgsPoint,
|
|
QgsField,
|
|
QgsFieldConstraints,
|
|
QgsFields,
|
|
QgsVectorLayerJoinInfo,
|
|
QgsSymbol,
|
|
QgsSingleSymbolRenderer,
|
|
QgsCoordinateReferenceSystem,
|
|
QgsReadWriteContext,
|
|
QgsProject,
|
|
QgsUnitTypes,
|
|
QgsAggregateCalculator,
|
|
QgsPointV2,
|
|
QgsExpressionContext,
|
|
QgsExpressionContextScope,
|
|
QgsExpressionContextUtils,
|
|
QgsLineSymbol,
|
|
QgsMapLayerStyle,
|
|
QgsMapLayerDependency,
|
|
QgsPalLayerSettings,
|
|
QgsVectorLayerSimpleLabeling,
|
|
QgsSingleCategoryDiagramRenderer,
|
|
QgsDiagramLayerSettings,
|
|
QgsTextFormat)
|
|
from qgis.testing import start_app, unittest
|
|
from utilities import unitTestDataPath
|
|
start_app()
|
|
|
|
|
|
def createEmptyLayer():
|
|
layer = QgsVectorLayer("Point", "addfeat", "memory")
|
|
assert layer.pendingFeatureCount() == 0
|
|
return layer
|
|
|
|
|
|
def createEmptyLayerWithFields():
|
|
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory")
|
|
assert layer.pendingFeatureCount() == 0
|
|
return layer
|
|
|
|
|
|
def createLayerWithOnePoint():
|
|
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
|
|
"addfeat", "memory")
|
|
pr = layer.dataProvider()
|
|
f = QgsFeature()
|
|
f.setAttributes(["test", 123])
|
|
f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
|
|
assert pr.addFeatures([f])
|
|
assert layer.pendingFeatureCount() == 1
|
|
return layer
|
|
|
|
|
|
def createLayerWithTwoPoints():
|
|
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
|
|
"addfeat", "memory")
|
|
pr = layer.dataProvider()
|
|
f = QgsFeature()
|
|
f.setAttributes(["test", 123])
|
|
f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["test2", 457])
|
|
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
|
|
assert pr.addFeatures([f, f2])
|
|
assert layer.pendingFeatureCount() == 2
|
|
return layer
|
|
|
|
|
|
def createLayerWithFivePoints():
|
|
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
|
|
"addfeat", "memory")
|
|
pr = layer.dataProvider()
|
|
f = QgsFeature()
|
|
f.setAttributes(["test", 123])
|
|
f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["test2", 457])
|
|
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(200, 200)))
|
|
f3 = QgsFeature()
|
|
f3.setAttributes(["test2", 888])
|
|
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(300, 200)))
|
|
f4 = QgsFeature()
|
|
f4.setAttributes(["test3", -1])
|
|
f4.setGeometry(QgsGeometry.fromPoint(QgsPoint(400, 300)))
|
|
f5 = QgsFeature()
|
|
f5.setAttributes(["test4", 0])
|
|
f5.setGeometry(QgsGeometry.fromPoint(QgsPoint(0, 0)))
|
|
assert pr.addFeatures([f, f2, f3, f4, f5])
|
|
assert layer.featureCount() == 5
|
|
return layer
|
|
|
|
|
|
def createJoinLayer():
|
|
joinLayer = QgsVectorLayer(
|
|
"Point?field=x:string&field=y:integer&field=z:integer",
|
|
"joinlayer", "memory")
|
|
pr = joinLayer.dataProvider()
|
|
f1 = QgsFeature()
|
|
f1.setAttributes(["foo", 123, 321])
|
|
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 1)))
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["bar", 456, 654])
|
|
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(2, 2)))
|
|
f3 = QgsFeature()
|
|
f3.setAttributes(["qar", 457, 111])
|
|
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(2, 2)))
|
|
f4 = QgsFeature()
|
|
f4.setAttributes(["a", 458, 19])
|
|
f4.setGeometry(QgsGeometry.fromPoint(QgsPoint(2, 2)))
|
|
assert pr.addFeatures([f1, f2, f3, f4])
|
|
assert joinLayer.pendingFeatureCount() == 4
|
|
return joinLayer
|
|
|
|
|
|
def dumpFeature(f):
|
|
print("--- FEATURE DUMP ---")
|
|
print(("valid: %d | id: %d" % (f.isValid(), f.id())))
|
|
geom = f.geometry()
|
|
if geom:
|
|
print(("geometry wkb: %d" % geom.wkbType()))
|
|
else:
|
|
print("no geometry")
|
|
print(("attrs: %s" % str(f.attributes())))
|
|
|
|
|
|
def formatAttributes(attrs):
|
|
return repr([str(a) for a in attrs])
|
|
|
|
|
|
def dumpEditBuffer(layer):
|
|
editBuffer = layer.editBuffer()
|
|
if not editBuffer:
|
|
print("NO EDITING!")
|
|
return
|
|
print("ADDED:")
|
|
for fid, f in editBuffer.addedFeatures().items():
|
|
print(("%d: %s | %s" % (
|
|
f.id(), formatAttributes(f.attributes()),
|
|
f.geometry().exportToWkt())))
|
|
print("CHANGED GEOM:")
|
|
for fid, geom in editBuffer.changedGeometries().items():
|
|
print(("%d | %s" % (f.id(), f.geometry().exportToWkt())))
|
|
|
|
|
|
class TestQgsVectorLayer(unittest.TestCase):
|
|
|
|
def test_FeatureCount(self):
|
|
myPath = os.path.join(unitTestDataPath(), 'lines.shp')
|
|
myLayer = QgsVectorLayer(myPath, 'Lines', 'ogr')
|
|
myCount = myLayer.featureCount()
|
|
self.assertEqual(myCount, 6)
|
|
|
|
# ADD FEATURE
|
|
|
|
def test_AddFeature(self):
|
|
layer = createEmptyLayerWithFields()
|
|
feat = QgsFeature(layer.fields())
|
|
feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 2)))
|
|
|
|
def checkAfter():
|
|
self.assertEqual(layer.pendingFeatureCount(), 1)
|
|
|
|
# check select+nextFeature
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(1, 2))
|
|
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2.geometry().asPoint(), QgsPoint(1, 2))
|
|
|
|
def checkBefore():
|
|
self.assertEqual(layer.pendingFeatureCount(), 0)
|
|
|
|
# check select+nextFeature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
checkBefore()
|
|
|
|
# try to add feature without editing mode
|
|
self.assertFalse(layer.addFeature(feat))
|
|
|
|
# add feature
|
|
layer.startEditing()
|
|
|
|
# try adding feature with incorrect number of fields
|
|
bad_feature = QgsFeature()
|
|
self.assertFalse(layer.addFeature(bad_feature))
|
|
|
|
# add good feature
|
|
self.assertTrue(layer.addFeature(feat))
|
|
|
|
checkAfter()
|
|
self.assertEqual(layer.dataProvider().featureCount(), 0)
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
|
|
checkAfter()
|
|
self.assertEqual(layer.dataProvider().featureCount(), 1)
|
|
|
|
# ADD FEATURES
|
|
|
|
def test_AddFeatures(self):
|
|
layer = createEmptyLayerWithFields()
|
|
feat1 = QgsFeature(layer.fields())
|
|
feat1.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 2)))
|
|
feat2 = QgsFeature(layer.fields())
|
|
feat2.setGeometry(QgsGeometry.fromPoint(QgsPoint(11, 12)))
|
|
|
|
def checkAfter():
|
|
self.assertEqual(layer.pendingFeatureCount(), 2)
|
|
|
|
# check select+nextFeature
|
|
it = layer.getFeatures()
|
|
f1 = next(it)
|
|
self.assertEqual(f1.geometry().asPoint(), QgsPoint(1, 2))
|
|
f2 = next(it)
|
|
self.assertEqual(f2.geometry().asPoint(), QgsPoint(11, 12))
|
|
|
|
# check feature at id
|
|
f1_1 = next(layer.getFeatures(QgsFeatureRequest(f1.id())))
|
|
self.assertEqual(f1_1.geometry().asPoint(), QgsPoint(1, 2))
|
|
f2_1 = next(layer.getFeatures(QgsFeatureRequest(f2.id())))
|
|
self.assertEqual(f2_1.geometry().asPoint(), QgsPoint(11, 12))
|
|
|
|
def checkBefore():
|
|
self.assertEqual(layer.pendingFeatureCount(), 0)
|
|
|
|
# check select+nextFeature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
checkBefore()
|
|
|
|
# try to add feature without editing mode
|
|
self.assertFalse(layer.addFeatures([feat1, feat2]))
|
|
|
|
# add feature
|
|
layer.startEditing()
|
|
|
|
# try adding feature with incorrect number of fields
|
|
bad_feature = QgsFeature()
|
|
self.assertFalse(layer.addFeatures([bad_feature]))
|
|
|
|
# add good features
|
|
self.assertTrue(layer.addFeatures([feat1, feat2]))
|
|
|
|
checkAfter()
|
|
self.assertEqual(layer.dataProvider().featureCount(), 0)
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
|
|
checkAfter()
|
|
self.assertEqual(layer.dataProvider().featureCount(), 2)
|
|
# DELETE FEATURE
|
|
|
|
def test_DeleteFeature(self):
|
|
layer = createLayerWithOnePoint()
|
|
fid = 1
|
|
|
|
def checkAfter():
|
|
self.assertEqual(layer.pendingFeatureCount(), 0)
|
|
|
|
# check select+nextFeature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
# check feature at id
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures(QgsFeatureRequest(fid)))
|
|
|
|
def checkBefore():
|
|
self.assertEqual(layer.pendingFeatureCount(), 1)
|
|
|
|
# check select+nextFeature
|
|
fi = layer.getFeatures()
|
|
f = next(fi)
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(100, 200))
|
|
with self.assertRaises(StopIteration):
|
|
next(fi)
|
|
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(fid)))
|
|
self.assertEqual(f2.id(), fid)
|
|
|
|
checkBefore()
|
|
|
|
# try to delete feature without editing mode
|
|
self.assertFalse(layer.deleteFeature(fid))
|
|
|
|
# delete feature
|
|
layer.startEditing()
|
|
self.assertTrue(layer.deleteFeature(fid))
|
|
|
|
checkAfter()
|
|
|
|
# make sure calling it twice does not work
|
|
self.assertFalse(layer.deleteFeature(fid))
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertEqual(layer.dataProvider().featureCount(), 1)
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
|
|
checkAfter()
|
|
self.assertEqual(layer.dataProvider().featureCount(), 0)
|
|
|
|
def test_DeleteFeatureAfterAddFeature(self):
|
|
|
|
layer = createEmptyLayer()
|
|
feat = QgsFeature()
|
|
feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 2)))
|
|
|
|
def checkBefore():
|
|
self.assertEqual(layer.pendingFeatureCount(), 0)
|
|
|
|
# check select+nextFeature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
def checkAfter1():
|
|
self.assertEqual(layer.pendingFeatureCount(), 1)
|
|
|
|
def checkAfter2():
|
|
checkBefore() # should be the same state: no features
|
|
|
|
checkBefore()
|
|
|
|
# add feature
|
|
layer.startEditing()
|
|
self.assertTrue(layer.addFeature(feat))
|
|
checkAfter1()
|
|
fid = feat.id()
|
|
self.assertTrue(layer.deleteFeature(fid))
|
|
checkAfter2()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkAfter1()
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter1()
|
|
layer.undoStack().redo()
|
|
checkAfter2()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
checkAfter2()
|
|
|
|
self.assertEqual(layer.dataProvider().featureCount(), 0)
|
|
|
|
# CHANGE ATTRIBUTE
|
|
|
|
def test_ChangeAttribute(self):
|
|
layer = createLayerWithOnePoint()
|
|
fid = 1
|
|
|
|
def checkAfter():
|
|
# check select+nextFeature
|
|
fi = layer.getFeatures()
|
|
f = next(fi)
|
|
self.assertEqual(f[0], "good")
|
|
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2[0], "good")
|
|
|
|
def checkBefore():
|
|
# check select+nextFeature
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f[0], "test")
|
|
|
|
checkBefore()
|
|
|
|
# try to change attribute without editing mode
|
|
self.assertFalse(layer.changeAttributeValue(fid, 0, "good"))
|
|
|
|
# change attribute
|
|
layer.startEditing()
|
|
self.assertTrue(layer.changeAttributeValue(fid, 0, "good"))
|
|
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
checkAfter()
|
|
|
|
def test_ChangeAttributeAfterAddFeature(self):
|
|
layer = createLayerWithOnePoint()
|
|
layer.dataProvider().deleteFeatures([1]) # no need for this feature
|
|
|
|
newF = QgsFeature()
|
|
newF.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 1)))
|
|
newF.setAttributes(["hello", 42])
|
|
|
|
def checkAfter():
|
|
self.assertEqual(len(layer.pendingFields()), 2)
|
|
# check feature
|
|
fi = layer.getFeatures()
|
|
f = next(fi)
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 2)
|
|
self.assertEqual(attrs[0], "hello")
|
|
self.assertEqual(attrs[1], 12)
|
|
|
|
with self.assertRaises(StopIteration):
|
|
next(fi)
|
|
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2[0], "hello")
|
|
self.assertEqual(f2[1], 12)
|
|
|
|
def checkBefore():
|
|
# check feature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
checkBefore()
|
|
|
|
layer.startEditing()
|
|
layer.beginEditCommand("AddFeature + ChangeAttribute")
|
|
self.assertTrue(layer.addFeature(newF))
|
|
self.assertTrue(layer.changeAttributeValue(newF.id(), 1, 12))
|
|
layer.endEditCommand()
|
|
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
checkAfter()
|
|
|
|
# print "COMMIT ERRORS:"
|
|
# for item in list(layer.commitErrors()): print item
|
|
|
|
# CHANGE GEOMETRY
|
|
|
|
def test_ChangeGeometry(self):
|
|
layer = createLayerWithOnePoint()
|
|
fid = 1
|
|
|
|
def checkAfter():
|
|
# check select+nextFeature
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(300, 400))
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2.geometry().asPoint(), QgsPoint(300, 400))
|
|
|
|
def checkBefore():
|
|
# check select+nextFeature
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(100, 200))
|
|
|
|
# try to change geometry without editing mode
|
|
self.assertFalse(layer.changeGeometry(fid, QgsGeometry.fromPoint(QgsPoint(300, 400))))
|
|
|
|
checkBefore()
|
|
|
|
# change geometry
|
|
layer.startEditing()
|
|
layer.beginEditCommand("ChangeGeometry")
|
|
self.assertTrue(layer.changeGeometry(fid, QgsGeometry.fromPoint(QgsPoint(300, 400))))
|
|
layer.endEditCommand()
|
|
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
checkAfter()
|
|
|
|
def test_ChangeGeometryAfterChangeAttribute(self):
|
|
layer = createLayerWithOnePoint()
|
|
fid = 1
|
|
|
|
def checkAfter():
|
|
# check select+nextFeature
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(300, 400))
|
|
self.assertEqual(f[0], "changed")
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2.geometry().asPoint(), QgsPoint(300, 400))
|
|
self.assertEqual(f2[0], "changed")
|
|
|
|
def checkBefore():
|
|
# check select+nextFeature
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(100, 200))
|
|
self.assertEqual(f[0], "test")
|
|
|
|
checkBefore()
|
|
|
|
# change geometry
|
|
layer.startEditing()
|
|
layer.beginEditCommand("ChangeGeometry + ChangeAttribute")
|
|
self.assertTrue(layer.changeAttributeValue(fid, 0, "changed"))
|
|
self.assertTrue(layer.changeGeometry(fid, QgsGeometry.fromPoint(QgsPoint(300, 400))))
|
|
layer.endEditCommand()
|
|
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
checkAfter()
|
|
|
|
def test_ChangeGeometryAfterAddFeature(self):
|
|
layer = createLayerWithOnePoint()
|
|
layer.dataProvider().deleteFeatures([1]) # no need for this feature
|
|
|
|
newF = QgsFeature()
|
|
newF.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 1)))
|
|
newF.setAttributes(["hello", 42])
|
|
|
|
def checkAfter():
|
|
self.assertEqual(len(layer.pendingFields()), 2)
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(2, 2))
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2.geometry().asPoint(), QgsPoint(2, 2))
|
|
|
|
def checkBefore():
|
|
# check feature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
checkBefore()
|
|
|
|
layer.startEditing()
|
|
layer.beginEditCommand("AddFeature+ChangeGeometry")
|
|
self.assertTrue(layer.addFeature(newF))
|
|
self.assertTrue(layer.changeGeometry(newF.id(), QgsGeometry.fromPoint(QgsPoint(2, 2))))
|
|
layer.endEditCommand()
|
|
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
self.assertTrue(layer.commitChanges())
|
|
checkAfter()
|
|
|
|
# print "COMMIT ERRORS:"
|
|
# for item in list(layer.commitErrors()): print item
|
|
|
|
# ADD ATTRIBUTE
|
|
|
|
def test_AddAttribute(self):
|
|
layer = createLayerWithOnePoint()
|
|
fld1 = QgsField("fld1", QVariant.Int, "integer")
|
|
#fld2 = QgsField("fld2", QVariant.Int, "integer")
|
|
|
|
def checkBefore():
|
|
# check fields
|
|
flds = layer.pendingFields()
|
|
self.assertEqual(len(flds), 2)
|
|
self.assertEqual(flds[0].name(), "fldtxt")
|
|
self.assertEqual(flds[1].name(), "fldint")
|
|
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 2)
|
|
self.assertEqual(attrs[0], "test")
|
|
self.assertEqual(attrs[1], 123)
|
|
|
|
def checkAfter():
|
|
# check fields
|
|
flds = layer.pendingFields()
|
|
self.assertEqual(len(flds), 3)
|
|
self.assertEqual(flds[0].name(), "fldtxt")
|
|
self.assertEqual(flds[1].name(), "fldint")
|
|
self.assertEqual(flds[2].name(), "fld1")
|
|
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 3)
|
|
self.assertEqual(attrs[0], "test")
|
|
self.assertEqual(attrs[1], 123)
|
|
self.assertTrue(attrs[2] is None)
|
|
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2[0], "test")
|
|
self.assertEqual(f2[1], 123)
|
|
self.assertTrue(f2[2] is None)
|
|
|
|
# for nt in layer.dataProvider().nativeTypes():
|
|
# print (nt.mTypeDesc, nt.mTypeName, nt.mType, nt.mMinLen,
|
|
# nt.mMaxLen, nt.mMinPrec, nt.mMaxPrec)
|
|
self.assertTrue(layer.dataProvider().supportedType(fld1))
|
|
|
|
# without editing mode
|
|
self.assertFalse(layer.addAttribute(fld1))
|
|
|
|
layer.startEditing()
|
|
|
|
checkBefore()
|
|
|
|
self.assertTrue(layer.addAttribute(fld1))
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
layer.commitChanges()
|
|
checkAfter()
|
|
|
|
def test_AddAttributeAfterAddFeature(self):
|
|
layer = createLayerWithOnePoint()
|
|
layer.dataProvider().deleteFeatures([1]) # no need for this feature
|
|
|
|
newF = QgsFeature()
|
|
newF.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 1)))
|
|
newF.setAttributes(["hello", 42])
|
|
|
|
fld1 = QgsField("fld1", QVariant.Int, "integer")
|
|
|
|
def checkBefore():
|
|
self.assertEqual(len(layer.pendingFields()), 2)
|
|
# check feature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
def checkAfter():
|
|
self.assertEqual(len(layer.pendingFields()), 3)
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 3)
|
|
self.assertEqual(attrs[0], "hello")
|
|
self.assertEqual(attrs[1], 42)
|
|
self.assertTrue(attrs[2] is None)
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(f2[0], "hello")
|
|
self.assertEqual(f2[1], 42)
|
|
self.assertTrue(f2[2] is None)
|
|
|
|
layer.startEditing()
|
|
|
|
checkBefore()
|
|
|
|
layer.beginEditCommand("AddFeature + AddAttribute")
|
|
self.assertTrue(layer.addFeature(newF))
|
|
self.assertTrue(layer.addAttribute(fld1))
|
|
layer.endEditCommand()
|
|
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
layer.commitChanges()
|
|
checkAfter()
|
|
|
|
# print "COMMIT ERRORS:"
|
|
# for item in list(layer.commitErrors()): print item
|
|
|
|
def test_AddAttributeAfterChangeValue(self):
|
|
pass # not interesting to test...?
|
|
|
|
def test_AddAttributeAfterDeleteAttribute(self):
|
|
pass # maybe it would be good to test
|
|
|
|
# DELETE ATTRIBUTE
|
|
|
|
def test_DeleteAttribute(self):
|
|
layer = createLayerWithOnePoint()
|
|
layer.dataProvider().addAttributes(
|
|
[QgsField("flddouble", QVariant.Double, "double")])
|
|
layer.dataProvider().changeAttributeValues(
|
|
{1: {2: 5.5}})
|
|
|
|
# without editing mode
|
|
self.assertFalse(layer.deleteAttribute(0))
|
|
|
|
def checkBefore():
|
|
flds = layer.pendingFields()
|
|
self.assertEqual(len(flds), 3)
|
|
self.assertEqual(flds[0].name(), "fldtxt")
|
|
self.assertEqual(flds[1].name(), "fldint")
|
|
self.assertEqual(flds[2].name(), "flddouble")
|
|
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 3)
|
|
self.assertEqual(attrs[0], "test")
|
|
self.assertEqual(attrs[1], 123)
|
|
self.assertEqual(attrs[2], 5.5)
|
|
|
|
layer.startEditing()
|
|
|
|
checkBefore()
|
|
|
|
self.assertTrue(layer.deleteAttribute(0))
|
|
|
|
def checkAfterOneDelete():
|
|
flds = layer.pendingFields()
|
|
# for fld in flds: print "FLD", fld.name()
|
|
self.assertEqual(len(flds), 2)
|
|
self.assertEqual(flds[0].name(), "fldint")
|
|
self.assertEqual(flds[1].name(), "flddouble")
|
|
self.assertEqual(layer.pendingAllAttributesList(), [0, 1])
|
|
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 2)
|
|
self.assertEqual(attrs[0], 123)
|
|
self.assertEqual(attrs[1], 5.5)
|
|
|
|
checkAfterOneDelete()
|
|
|
|
# delete last attribute
|
|
self.assertTrue(layer.deleteAttribute(0))
|
|
|
|
def checkAfterTwoDeletes():
|
|
self.assertEqual(layer.pendingAllAttributesList(), [0])
|
|
flds = layer.pendingFields()
|
|
# for fld in flds: print "FLD", fld.name()
|
|
self.assertEqual(len(flds), 1)
|
|
self.assertEqual(flds[0].name(), "flddouble")
|
|
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 1)
|
|
self.assertEqual(attrs[0], 5.5)
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(len(f2.attributes()), 1)
|
|
self.assertEqual(f2[0], 5.5)
|
|
|
|
checkAfterTwoDeletes()
|
|
layer.undoStack().undo()
|
|
checkAfterOneDelete()
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfterOneDelete()
|
|
layer.undoStack().redo()
|
|
checkAfterTwoDeletes()
|
|
|
|
self.assertTrue(layer.commitChanges()) # COMMIT!
|
|
checkAfterTwoDeletes()
|
|
|
|
def test_DeleteAttributeAfterAddAttribute(self):
|
|
layer = createLayerWithOnePoint()
|
|
fld1 = QgsField("fld1", QVariant.Int, "integer")
|
|
|
|
def checkAfter(): # layer should be unchanged
|
|
flds = layer.pendingFields()
|
|
self.assertEqual(len(flds), 2)
|
|
self.assertEqual(flds[0].name(), "fldtxt")
|
|
self.assertEqual(flds[1].name(), "fldint")
|
|
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 2)
|
|
self.assertEqual(attrs[0], "test")
|
|
self.assertEqual(attrs[1], 123)
|
|
# check feature at id
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(len(f2.attributes()), 2)
|
|
self.assertEqual(f2[0], "test")
|
|
self.assertEqual(f2[1], 123)
|
|
|
|
checkAfter()
|
|
|
|
layer.startEditing()
|
|
|
|
layer.beginEditCommand("AddAttribute + DeleteAttribute")
|
|
self.assertTrue(layer.addAttribute(fld1))
|
|
self.assertTrue(layer.deleteAttribute(2))
|
|
layer.endEditCommand()
|
|
|
|
checkAfter()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkAfter()
|
|
layer.undoStack().redo()
|
|
checkAfter()
|
|
|
|
layer.commitChanges()
|
|
checkAfter()
|
|
|
|
def test_DeleteAttributeAfterAddFeature(self):
|
|
layer = createLayerWithOnePoint()
|
|
layer.dataProvider().deleteFeatures([1]) # no need for this feature
|
|
|
|
newF = QgsFeature()
|
|
newF.setGeometry(QgsGeometry.fromPoint(QgsPoint(1, 1)))
|
|
newF.setAttributes(["hello", 42])
|
|
|
|
def checkBefore():
|
|
self.assertEqual(len(layer.pendingFields()), 2)
|
|
# check feature
|
|
with self.assertRaises(StopIteration):
|
|
next(layer.getFeatures())
|
|
|
|
def checkAfter1():
|
|
self.assertEqual(len(layer.pendingFields()), 2)
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 2)
|
|
self.assertEqual(attrs[0], "hello")
|
|
self.assertEqual(attrs[1], 42)
|
|
|
|
def checkAfter2():
|
|
self.assertEqual(len(layer.pendingFields()), 1)
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 1)
|
|
self.assertEqual(attrs[0], 42)
|
|
|
|
layer.startEditing()
|
|
|
|
checkBefore()
|
|
|
|
layer.addFeature(newF)
|
|
checkAfter1()
|
|
layer.deleteAttribute(0)
|
|
checkAfter2()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkAfter1()
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter1()
|
|
layer.undoStack().redo()
|
|
checkAfter2()
|
|
|
|
layer.commitChanges()
|
|
checkAfter2()
|
|
|
|
def test_DeleteAttributeAfterChangeValue(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
def checkBefore():
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 2)
|
|
self.assertEqual(attrs[0], "test")
|
|
self.assertEqual(attrs[1], 123)
|
|
|
|
def checkAfter1():
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 2)
|
|
self.assertEqual(attrs[0], "changed")
|
|
self.assertEqual(attrs[1], 123)
|
|
|
|
def checkAfter2():
|
|
# check feature
|
|
f = next(layer.getFeatures())
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 1)
|
|
self.assertEqual(attrs[0], 123)
|
|
|
|
layer.startEditing()
|
|
|
|
checkBefore()
|
|
|
|
self.assertTrue(layer.changeAttributeValue(1, 0, "changed"))
|
|
checkAfter1()
|
|
self.assertTrue(layer.deleteAttribute(0))
|
|
checkAfter2()
|
|
|
|
# now try undo/redo
|
|
layer.undoStack().undo()
|
|
checkAfter1()
|
|
layer.undoStack().undo()
|
|
checkBefore()
|
|
layer.undoStack().redo()
|
|
checkAfter1()
|
|
layer.undoStack().redo()
|
|
checkAfter2()
|
|
|
|
layer.commitChanges()
|
|
checkAfter2()
|
|
|
|
# RENAME ATTRIBUTE
|
|
|
|
def test_RenameAttribute(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
# without editing mode
|
|
self.assertFalse(layer.renameAttribute(0, 'renamed'))
|
|
|
|
def checkFieldNames(names):
|
|
flds = layer.fields()
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(flds.count(), len(names))
|
|
self.assertEqual(f.fields().count(), len(names))
|
|
|
|
for idx, expected_name in enumerate(names):
|
|
self.assertEqual(flds[idx].name(), expected_name)
|
|
self.assertEqual(f.fields().at(idx).name(), expected_name)
|
|
|
|
layer.startEditing()
|
|
|
|
checkFieldNames(['fldtxt', 'fldint'])
|
|
|
|
self.assertFalse(layer.renameAttribute(-1, 'fldtxt2'))
|
|
self.assertFalse(layer.renameAttribute(10, 'fldtxt2'))
|
|
self.assertFalse(layer.renameAttribute(0, 'fldint')) # duplicate name
|
|
|
|
self.assertTrue(layer.renameAttribute(0, 'fldtxt2'))
|
|
checkFieldNames(['fldtxt2', 'fldint'])
|
|
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt2', 'fldint'])
|
|
|
|
# change two fields
|
|
self.assertTrue(layer.renameAttribute(1, 'fldint2'))
|
|
checkFieldNames(['fldtxt2', 'fldint2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt2', 'fldint'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt2', 'fldint'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt2', 'fldint2'])
|
|
|
|
# two renames
|
|
self.assertTrue(layer.renameAttribute(0, 'fldtxt3'))
|
|
checkFieldNames(['fldtxt3', 'fldint2'])
|
|
self.assertTrue(layer.renameAttribute(0, 'fldtxt4'))
|
|
checkFieldNames(['fldtxt4', 'fldint2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt3', 'fldint2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt2', 'fldint2'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt3', 'fldint2'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt4', 'fldint2'])
|
|
|
|
def test_RenameAttributeAfterAdd(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
def checkFieldNames(names):
|
|
flds = layer.fields()
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(flds.count(), len(names))
|
|
self.assertEqual(f.fields().count(), len(names))
|
|
|
|
for idx, expected_name in enumerate(names):
|
|
self.assertEqual(flds[idx].name(), expected_name)
|
|
self.assertEqual(f.fields().at(idx).name(), expected_name)
|
|
|
|
layer.startEditing()
|
|
|
|
checkFieldNames(['fldtxt', 'fldint'])
|
|
self.assertTrue(layer.renameAttribute(1, 'fldint2'))
|
|
checkFieldNames(['fldtxt', 'fldint2'])
|
|
#add an attribute
|
|
self.assertTrue(layer.addAttribute(QgsField("flddouble", QVariant.Double, "double")))
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble'])
|
|
# rename it
|
|
self.assertTrue(layer.renameAttribute(2, 'flddouble2'))
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2'])
|
|
self.assertTrue(layer.addAttribute(QgsField("flddate", QVariant.Date, "date")))
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2', 'flddate'])
|
|
self.assertTrue(layer.renameAttribute(2, 'flddouble3'))
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate'])
|
|
self.assertTrue(layer.renameAttribute(3, 'flddate2'))
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate2'])
|
|
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2', 'flddate'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint'])
|
|
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt', 'fldint2'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2', 'flddate'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate'])
|
|
layer.undoStack().redo()
|
|
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate2'])
|
|
|
|
def test_RenameAttributeAndDelete(self):
|
|
layer = createLayerWithOnePoint()
|
|
layer.dataProvider().addAttributes(
|
|
[QgsField("flddouble", QVariant.Double, "double")])
|
|
layer.updateFields()
|
|
|
|
def checkFieldNames(names):
|
|
flds = layer.fields()
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(flds.count(), len(names))
|
|
self.assertEqual(f.fields().count(), len(names))
|
|
|
|
for idx, expected_name in enumerate(names):
|
|
self.assertEqual(flds[idx].name(), expected_name)
|
|
self.assertEqual(f.fields().at(idx).name(), expected_name)
|
|
|
|
layer.startEditing()
|
|
|
|
checkFieldNames(['fldtxt', 'fldint', 'flddouble'])
|
|
self.assertTrue(layer.renameAttribute(0, 'fldtxt2'))
|
|
checkFieldNames(['fldtxt2', 'fldint', 'flddouble'])
|
|
self.assertTrue(layer.renameAttribute(2, 'flddouble2'))
|
|
checkFieldNames(['fldtxt2', 'fldint', 'flddouble2'])
|
|
|
|
#delete an attribute
|
|
self.assertTrue(layer.deleteAttribute(0))
|
|
checkFieldNames(['fldint', 'flddouble2'])
|
|
# rename remaining
|
|
self.assertTrue(layer.renameAttribute(0, 'fldint2'))
|
|
checkFieldNames(['fldint2', 'flddouble2'])
|
|
self.assertTrue(layer.renameAttribute(1, 'flddouble3'))
|
|
checkFieldNames(['fldint2', 'flddouble3'])
|
|
#delete an attribute
|
|
self.assertTrue(layer.deleteAttribute(0))
|
|
checkFieldNames(['flddouble3'])
|
|
self.assertTrue(layer.renameAttribute(0, 'flddouble4'))
|
|
checkFieldNames(['flddouble4'])
|
|
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['flddouble3'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldint2', 'flddouble3'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldint2', 'flddouble2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldint', 'flddouble2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt2', 'fldint', 'flddouble2'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt2', 'fldint', 'flddouble'])
|
|
layer.undoStack().undo()
|
|
checkFieldNames(['fldtxt', 'fldint', 'flddouble'])
|
|
|
|
#layer.undoStack().redo()
|
|
#checkFieldNames(['fldtxt2', 'fldint'])
|
|
#layer.undoStack().redo()
|
|
#checkFieldNames(['fldint'])
|
|
|
|
def test_RenameExpressionField(self):
|
|
layer = createLayerWithOnePoint()
|
|
exp_field_idx = layer.addExpressionField('1+1', QgsField('math_is_hard', QVariant.Int))
|
|
|
|
#rename and check
|
|
self.assertTrue(layer.renameAttribute(exp_field_idx, 'renamed'))
|
|
self.assertEqual(layer.fields()[exp_field_idx].name(), 'renamed')
|
|
f = next(layer.getFeatures())
|
|
self.assertEqual(f.fields()[exp_field_idx].name(), 'renamed')
|
|
|
|
def test_fields(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
flds = layer.pendingFields()
|
|
self.assertEqual(flds.indexFromName("fldint"), 1)
|
|
self.assertEqual(flds.indexFromName("fldXXX"), -1)
|
|
|
|
def test_getFeatures(self):
|
|
|
|
layer = createLayerWithOnePoint()
|
|
|
|
f = QgsFeature()
|
|
fi = layer.getFeatures()
|
|
self.assertTrue(fi.nextFeature(f))
|
|
self.assertTrue(f.isValid())
|
|
self.assertEqual(f.id(), 1)
|
|
self.assertEqual(f.geometry().asPoint(), QgsPoint(100, 200))
|
|
self.assertEqual(f["fldtxt"], "test")
|
|
self.assertEqual(f["fldint"], 123)
|
|
|
|
self.assertFalse(fi.nextFeature(f))
|
|
|
|
layer2 = createLayerWithFivePoints()
|
|
|
|
# getFeature(fid)
|
|
feat = layer2.getFeature(4)
|
|
self.assertTrue(feat.isValid())
|
|
self.assertEqual(feat['fldtxt'], 'test3')
|
|
self.assertEqual(feat['fldint'], -1)
|
|
feat = layer2.getFeature(10)
|
|
self.assertFalse(feat.isValid())
|
|
|
|
# getFeatures(expression)
|
|
it = layer2.getFeatures("fldint <= 0")
|
|
fids = [f.id() for f in it]
|
|
self.assertEqual(set(fids), set([4, 5]))
|
|
|
|
# getFeatures(fids)
|
|
it = layer2.getFeatures([1, 2])
|
|
fids = [f.id() for f in it]
|
|
self.assertEqual(set(fids), set([1, 2]))
|
|
|
|
# getFeatures(rect)
|
|
it = layer2.getFeatures(QgsRectangle(99, 99, 201, 201))
|
|
fids = [f.id() for f in it]
|
|
self.assertEqual(set(fids), set([1, 2]))
|
|
|
|
def test_join(self):
|
|
|
|
joinLayer = createJoinLayer()
|
|
joinLayer2 = createJoinLayer()
|
|
QgsProject.instance().addMapLayers([joinLayer, joinLayer2])
|
|
|
|
layer = createLayerWithOnePoint()
|
|
|
|
join = QgsVectorLayerJoinInfo()
|
|
join.setTargetFieldName("fldint")
|
|
join.setJoinLayer(joinLayer)
|
|
join.setJoinFieldName("y")
|
|
join.setUsingMemoryCache(True)
|
|
|
|
layer.addJoin(join)
|
|
|
|
join2 = QgsVectorLayerJoinInfo()
|
|
join2.setTargetFieldName("fldint")
|
|
join2.setJoinLayer(joinLayer2)
|
|
join2.setJoinFieldName("y")
|
|
join2.setUsingMemoryCache(True)
|
|
join2.setPrefix("custom-prefix_")
|
|
|
|
layer.addJoin(join2)
|
|
|
|
flds = layer.pendingFields()
|
|
self.assertEqual(len(flds), 6)
|
|
self.assertEqual(flds[2].name(), "joinlayer_x")
|
|
self.assertEqual(flds[3].name(), "joinlayer_z")
|
|
self.assertEqual(flds[4].name(), "custom-prefix_x")
|
|
self.assertEqual(flds[5].name(), "custom-prefix_z")
|
|
self.assertEqual(flds.fieldOrigin(0), QgsFields.OriginProvider)
|
|
self.assertEqual(flds.fieldOrigin(2), QgsFields.OriginJoin)
|
|
self.assertEqual(flds.fieldOrigin(3), QgsFields.OriginJoin)
|
|
self.assertEqual(flds.fieldOriginIndex(0), 0)
|
|
self.assertEqual(flds.fieldOriginIndex(2), 0)
|
|
self.assertEqual(flds.fieldOriginIndex(3), 2)
|
|
|
|
f = QgsFeature()
|
|
fi = layer.getFeatures()
|
|
self.assertTrue(fi.nextFeature(f))
|
|
attrs = f.attributes()
|
|
self.assertEqual(len(attrs), 6)
|
|
self.assertEqual(attrs[0], "test")
|
|
self.assertEqual(attrs[1], 123)
|
|
self.assertEqual(attrs[2], "foo")
|
|
self.assertEqual(attrs[3], 321)
|
|
self.assertFalse(fi.nextFeature(f))
|
|
|
|
f2 = next(layer.getFeatures(QgsFeatureRequest(f.id())))
|
|
self.assertEqual(len(f2.attributes()), 6)
|
|
self.assertEqual(f2[2], "foo")
|
|
self.assertEqual(f2[3], 321)
|
|
|
|
def test_JoinStats(self):
|
|
""" test calculating min/max/uniqueValues on joined field """
|
|
joinLayer = createJoinLayer()
|
|
layer = createLayerWithTwoPoints()
|
|
QgsProject.instance().addMapLayers([joinLayer, layer])
|
|
|
|
join = QgsVectorLayerJoinInfo()
|
|
join.setTargetFieldName("fldint")
|
|
join.setJoinLayer(joinLayer)
|
|
join.setJoinFieldName("y")
|
|
join.setUsingMemoryCache(True)
|
|
layer.addJoin(join)
|
|
|
|
# stats on joined fields should only include values present by join
|
|
self.assertEqual(layer.minimumValue(3), 111)
|
|
self.assertEqual(layer.maximumValue(3), 321)
|
|
self.assertEqual(set(layer.uniqueValues(3)), set([111, 321]))
|
|
|
|
def testUniqueValue(self):
|
|
""" test retrieving unique values """
|
|
layer = createLayerWithFivePoints()
|
|
|
|
# test layer with just provider features
|
|
self.assertEqual(set(layer.uniqueValues(1)), set([123, 457, 888, -1, 0]))
|
|
|
|
# add feature with new value
|
|
layer.startEditing()
|
|
f1 = QgsFeature()
|
|
f1.setAttributes(["test2", 999])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
|
|
# should be included in unique values
|
|
self.assertEqual(set(layer.uniqueValues(1)), set([123, 457, 888, -1, 0, 999]))
|
|
# add it again, should be no change
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["test2", 999])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
self.assertEqual(set(layer.uniqueValues(1)), set([123, 457, 888, -1, 0, 999]))
|
|
# add another feature
|
|
f3 = QgsFeature()
|
|
f3.setAttributes(["test2", 9999])
|
|
self.assertTrue(layer.addFeature(f3))
|
|
self.assertEqual(set(layer.uniqueValues(1)), set([123, 457, 888, -1, 0, 999, 9999]))
|
|
|
|
# change an attribute value to a new unique value
|
|
f1_id = next(layer.getFeatures()).id()
|
|
self.assertTrue(layer.changeAttributeValue(f1_id, 1, 481523))
|
|
# note - this isn't 100% accurate, since 123 no longer exists - but it avoids looping through all features
|
|
self.assertEqual(set(layer.uniqueValues(1)), set([123, 457, 888, -1, 0, 999, 9999, 481523]))
|
|
|
|
def testUniqueStringsMatching(self):
|
|
""" test retrieving unique strings matching subset """
|
|
layer = QgsVectorLayer("Point?field=fldtxt:string", "addfeat", "memory")
|
|
pr = layer.dataProvider()
|
|
f = QgsFeature()
|
|
f.setAttributes(["apple"])
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["orange"])
|
|
f3 = QgsFeature()
|
|
f3.setAttributes(["pear"])
|
|
f4 = QgsFeature()
|
|
f4.setAttributes(["BanaNa"])
|
|
f5 = QgsFeature()
|
|
f5.setAttributes(["ApriCot"])
|
|
assert pr.addFeatures([f, f2, f3, f4, f5])
|
|
assert layer.featureCount() == 5
|
|
|
|
# test layer with just provider features
|
|
self.assertEqual(set(layer.uniqueStringsMatching(0, 'N')), set(['orange', 'BanaNa']))
|
|
|
|
# add feature with new value
|
|
layer.startEditing()
|
|
f1 = QgsFeature()
|
|
f1.setAttributes(["waterMelon"])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
|
|
# should be included in unique values
|
|
self.assertEqual(set(layer.uniqueStringsMatching(0, 'N')), set(['orange', 'BanaNa', 'waterMelon']))
|
|
# add it again, should be no change
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["waterMelon"])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
self.assertEqual(set(layer.uniqueStringsMatching(0, 'N')), set(['orange', 'BanaNa', 'waterMelon']))
|
|
self.assertEqual(set(layer.uniqueStringsMatching(0, 'aN')), set(['orange', 'BanaNa']))
|
|
# add another feature
|
|
f3 = QgsFeature()
|
|
f3.setAttributes(["pineapple"])
|
|
self.assertTrue(layer.addFeature(f3))
|
|
self.assertEqual(set(layer.uniqueStringsMatching(0, 'n')), set(['orange', 'BanaNa', 'waterMelon', 'pineapple']))
|
|
|
|
# change an attribute value to a new unique value
|
|
f = QgsFeature()
|
|
f1_id = next(layer.getFeatures()).id()
|
|
self.assertTrue(layer.changeAttributeValue(f1_id, 0, 'coconut'))
|
|
# note - this isn't 100% accurate, since orange no longer exists - but it avoids looping through all features
|
|
self.assertEqual(set(layer.uniqueStringsMatching(0, 'n')), set(['orange', 'BanaNa', 'waterMelon', 'pineapple', 'coconut']))
|
|
|
|
def testMinValue(self):
|
|
""" test retrieving minimum values """
|
|
layer = createLayerWithFivePoints()
|
|
|
|
# test layer with just provider features
|
|
self.assertEqual(layer.minimumValue(1), -1)
|
|
|
|
# add feature with new value
|
|
layer.startEditing()
|
|
f1 = QgsFeature()
|
|
f1.setAttributes(["test2", -999])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
|
|
# should be new minimum value
|
|
self.assertEqual(layer.minimumValue(1), -999)
|
|
# add it again, should be no change
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["test2", -999])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
self.assertEqual(layer.minimumValue(1), -999)
|
|
# add another feature
|
|
f3 = QgsFeature()
|
|
f3.setAttributes(["test2", -1000])
|
|
self.assertTrue(layer.addFeature(f3))
|
|
self.assertEqual(layer.minimumValue(1), -1000)
|
|
|
|
# change an attribute value to a new minimum value
|
|
f1_id = next(layer.getFeatures()).id()
|
|
self.assertTrue(layer.changeAttributeValue(f1_id, 1, -1001))
|
|
self.assertEqual(layer.minimumValue(1), -1001)
|
|
|
|
def testMaxValue(self):
|
|
""" test retrieving maximum values """
|
|
layer = createLayerWithFivePoints()
|
|
|
|
# test layer with just provider features
|
|
self.assertEqual(layer.maximumValue(1), 888)
|
|
|
|
# add feature with new value
|
|
layer.startEditing()
|
|
f1 = QgsFeature()
|
|
f1.setAttributes(["test2", 999])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
|
|
# should be new maximum value
|
|
self.assertEqual(layer.maximumValue(1), 999)
|
|
# add it again, should be no change
|
|
f2 = QgsFeature()
|
|
f2.setAttributes(["test2", 999])
|
|
self.assertTrue(layer.addFeature(f1))
|
|
self.assertEqual(layer.maximumValue(1), 999)
|
|
# add another feature
|
|
f3 = QgsFeature()
|
|
f3.setAttributes(["test2", 1000])
|
|
self.assertTrue(layer.addFeature(f3))
|
|
self.assertEqual(layer.maximumValue(1), 1000)
|
|
|
|
# change an attribute value to a new maximum value
|
|
f1_id = next(layer.getFeatures()).id()
|
|
self.assertTrue(layer.changeAttributeValue(f1_id, 1, 1001))
|
|
self.assertEqual(layer.maximumValue(1), 1001)
|
|
|
|
def test_InvalidOperations(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
layer.startEditing()
|
|
|
|
# ADD FEATURE
|
|
|
|
newF1 = QgsFeature()
|
|
self.assertFalse(layer.addFeature(newF1)) # need attributes like the layer has)
|
|
|
|
# DELETE FEATURE
|
|
|
|
self.assertFalse(layer.deleteFeature(-333))
|
|
# we do not check for existence of the feature id if it's
|
|
# not newly added feature
|
|
#self.assertFalse(layer.deleteFeature(333))
|
|
|
|
# CHANGE GEOMETRY
|
|
|
|
self.assertFalse(layer.changeGeometry(
|
|
-333, QgsGeometry.fromPoint(QgsPoint(1, 1))))
|
|
|
|
# CHANGE VALUE
|
|
|
|
self.assertFalse(layer.changeAttributeValue(-333, 0, 1))
|
|
self.assertFalse(layer.changeAttributeValue(1, -1, 1))
|
|
|
|
# ADD ATTRIBUTE
|
|
|
|
self.assertFalse(layer.addAttribute(QgsField()))
|
|
|
|
# DELETE ATTRIBUTE
|
|
|
|
self.assertFalse(layer.deleteAttribute(-1))
|
|
|
|
def onBlendModeChanged(self, mode):
|
|
self.blendModeTest = mode
|
|
|
|
def test_setBlendMode(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.blendModeTest = 0
|
|
layer.blendModeChanged.connect(self.onBlendModeChanged)
|
|
layer.setBlendMode(QPainter.CompositionMode_Screen)
|
|
|
|
self.assertEqual(self.blendModeTest, QPainter.CompositionMode_Screen)
|
|
self.assertEqual(layer.blendMode(), QPainter.CompositionMode_Screen)
|
|
|
|
def test_setFeatureBlendMode(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.blendModeTest = 0
|
|
layer.featureBlendModeChanged.connect(self.onBlendModeChanged)
|
|
layer.setFeatureBlendMode(QPainter.CompositionMode_Screen)
|
|
|
|
self.assertEqual(self.blendModeTest, QPainter.CompositionMode_Screen)
|
|
self.assertEqual(layer.featureBlendMode(), QPainter.CompositionMode_Screen)
|
|
|
|
def test_ExpressionField(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
cnt = layer.pendingFields().count()
|
|
|
|
idx = layer.addExpressionField('5', QgsField('test', QVariant.LongLong))
|
|
|
|
fet = next(layer.getFeatures())
|
|
self.assertEqual(fet[idx], 5)
|
|
# check fields
|
|
self.assertEqual(layer.fields().count(), cnt + 1)
|
|
self.assertEqual(fet.fields(), layer.fields())
|
|
|
|
# retrieve single feature and check fields
|
|
fet = next(layer.getFeatures(QgsFeatureRequest().setFilterFid(1)))
|
|
self.assertEqual(fet.fields(), layer.fields())
|
|
|
|
layer.updateExpressionField(idx, '9')
|
|
|
|
self.assertEqual(next(layer.getFeatures())[idx], 9)
|
|
|
|
layer.removeExpressionField(idx)
|
|
|
|
self.assertEqual(layer.pendingFields().count(), cnt)
|
|
|
|
def test_ExpressionFieldEllipsoidLengthCalculation(self):
|
|
#create a temporary layer
|
|
temp_layer = QgsVectorLayer("LineString?crs=epsg:3111&field=pk:int", "vl", "memory")
|
|
self.assertTrue(temp_layer.isValid())
|
|
f1 = QgsFeature(temp_layer.dataProvider().fields(), 1)
|
|
f1.setAttribute("pk", 1)
|
|
f1.setGeometry(QgsGeometry.fromPolyline([QgsPoint(2484588, 2425722), QgsPoint(2482767, 2398853)]))
|
|
temp_layer.dataProvider().addFeatures([f1])
|
|
|
|
# set project CRS and ellipsoid
|
|
srs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId)
|
|
QgsProject.instance().setCrs(srs)
|
|
QgsProject.instance().setEllipsoid("WGS84")
|
|
QgsProject.instance().setDistanceUnits(QgsUnitTypes.DistanceMeters)
|
|
|
|
idx = temp_layer.addExpressionField('$length', QgsField('length', QVariant.Double)) # NOQA
|
|
|
|
# check value
|
|
f = next(temp_layer.getFeatures())
|
|
expected = 26932.156
|
|
self.assertAlmostEqual(f['length'], expected, 3)
|
|
|
|
# change project length unit, check calculation respects unit
|
|
QgsProject.instance().setDistanceUnits(QgsUnitTypes.DistanceFeet)
|
|
f = next(temp_layer.getFeatures())
|
|
expected = 88360.0918635
|
|
self.assertAlmostEqual(f['length'], expected, 3)
|
|
|
|
def test_ExpressionFieldEllipsoidAreaCalculation(self):
|
|
#create a temporary layer
|
|
temp_layer = QgsVectorLayer("Polygon?crs=epsg:3111&field=pk:int", "vl", "memory")
|
|
self.assertTrue(temp_layer.isValid())
|
|
f1 = QgsFeature(temp_layer.dataProvider().fields(), 1)
|
|
f1.setAttribute("pk", 1)
|
|
f1.setGeometry(QgsGeometry.fromPolygon([[QgsPoint(2484588, 2425722), QgsPoint(2482767, 2398853), QgsPoint(2520109, 2397715), QgsPoint(2520792, 2425494), QgsPoint(2484588, 2425722)]]))
|
|
temp_layer.dataProvider().addFeatures([f1])
|
|
|
|
# set project CRS and ellipsoid
|
|
srs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId)
|
|
QgsProject.instance().setCrs(srs)
|
|
QgsProject.instance().setEllipsoid("WGS84")
|
|
QgsProject.instance().setAreaUnits(QgsUnitTypes.AreaSquareMeters)
|
|
|
|
idx = temp_layer.addExpressionField('$area', QgsField('area', QVariant.Double)) # NOQA
|
|
|
|
# check value
|
|
f = next(temp_layer.getFeatures())
|
|
expected = 1009089817.0
|
|
self.assertAlmostEqual(f['area'], expected, delta=1.0)
|
|
|
|
# change project area unit, check calculation respects unit
|
|
QgsProject.instance().setAreaUnits(QgsUnitTypes.AreaSquareMiles)
|
|
f = next(temp_layer.getFeatures())
|
|
expected = 389.6117565069
|
|
self.assertAlmostEqual(f['area'], expected, 3)
|
|
|
|
def test_ExpressionFilter(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
idx = layer.addExpressionField('5', QgsField('test', QVariant.LongLong)) # NOQA
|
|
|
|
features = layer.getFeatures(QgsFeatureRequest().setFilterExpression('"test" = 6'))
|
|
|
|
assert(len(list(features)) == 0)
|
|
|
|
features = layer.getFeatures(QgsFeatureRequest().setFilterExpression('"test" = 5'))
|
|
|
|
assert(len(list(features)) == 1)
|
|
|
|
def testSelectByIds(self):
|
|
""" Test selecting by ID"""
|
|
layer = QgsVectorLayer(os.path.join(unitTestDataPath(), 'points.shp'), 'Points', 'ogr')
|
|
|
|
# SetSelection
|
|
layer.selectByIds([1, 3, 5, 7], QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([1, 3, 5, 7]))
|
|
# check that existing selection is cleared
|
|
layer.selectByIds([2, 4, 6], QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 4, 6]))
|
|
|
|
# AddToSelection
|
|
layer.selectByIds([3, 5], QgsVectorLayer.AddToSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 3, 4, 5, 6]))
|
|
layer.selectByIds([1], QgsVectorLayer.AddToSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([1, 2, 3, 4, 5, 6]))
|
|
|
|
# IntersectSelection
|
|
layer.selectByIds([1, 3, 5, 6], QgsVectorLayer.IntersectSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([1, 3, 5, 6]))
|
|
layer.selectByIds([1, 2, 5, 6], QgsVectorLayer.IntersectSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([1, 5, 6]))
|
|
|
|
# RemoveFromSelection
|
|
layer.selectByIds([2, 6, 7], QgsVectorLayer.RemoveFromSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([1, 5]))
|
|
layer.selectByIds([1, 5], QgsVectorLayer.RemoveFromSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([]))
|
|
|
|
def testSelectByExpression(self):
|
|
""" Test selecting by expression """
|
|
layer = QgsVectorLayer(os.path.join(unitTestDataPath(), 'points.shp'), 'Points', 'ogr')
|
|
|
|
# SetSelection
|
|
layer.selectByExpression('"Class"=\'B52\' and "Heading" > 10 and "Heading" <70', QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([10, 11]))
|
|
# check that existing selection is cleared
|
|
layer.selectByExpression('"Class"=\'Biplane\'', QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([1, 5, 6, 7, 8]))
|
|
# SetSelection no matching
|
|
layer.selectByExpression('"Class"=\'A380\'', QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([]))
|
|
|
|
# AddToSelection
|
|
layer.selectByExpression('"Importance"=3', QgsVectorLayer.AddToSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([0, 2, 3, 4, 14]))
|
|
layer.selectByExpression('"Importance"=4', QgsVectorLayer.AddToSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([0, 2, 3, 4, 13, 14]))
|
|
|
|
# IntersectSelection
|
|
layer.selectByExpression('"Heading"<100', QgsVectorLayer.IntersectSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([0, 2, 3, 4]))
|
|
layer.selectByExpression('"Cabin Crew"=1', QgsVectorLayer.IntersectSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 3]))
|
|
|
|
# RemoveFromSelection
|
|
layer.selectByExpression('"Heading"=85', QgsVectorLayer.RemoveFromSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([3]))
|
|
layer.selectByExpression('"Heading"=95', QgsVectorLayer.RemoveFromSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([]))
|
|
|
|
def testSelectByRect(self):
|
|
""" Test selecting by rectangle """
|
|
layer = QgsVectorLayer(os.path.join(unitTestDataPath(), 'points.shp'), 'Points', 'ogr')
|
|
|
|
# SetSelection
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 45), QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 3, 7, 10, 11, 15]))
|
|
# check that existing selection is cleared
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 37), QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 3, 10, 15]))
|
|
# SetSelection no matching
|
|
layer.selectByRect(QgsRectangle(112, 30, 115, 45), QgsVectorLayer.SetSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([]))
|
|
|
|
# AddToSelection
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 37), QgsVectorLayer.AddToSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 3, 10, 15]))
|
|
layer.selectByRect(QgsRectangle(-112, 37, -94, 45), QgsVectorLayer.AddToSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 3, 7, 10, 11, 15]))
|
|
|
|
# IntersectSelection
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 37), QgsVectorLayer.IntersectSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 3, 10, 15]))
|
|
layer.selectByIds([2, 10, 13])
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 37), QgsVectorLayer.IntersectSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([2, 10]))
|
|
|
|
# RemoveFromSelection
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 45), QgsVectorLayer.SetSelection)
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 37), QgsVectorLayer.RemoveFromSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([7, 11]))
|
|
layer.selectByRect(QgsRectangle(-112, 30, -94, 45), QgsVectorLayer.RemoveFromSelection)
|
|
self.assertEqual(set(layer.selectedFeatureIds()), set([]))
|
|
|
|
def testAggregate(self):
|
|
""" Test aggregate calculation """
|
|
layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory")
|
|
pr = layer.dataProvider()
|
|
|
|
int_values = [4, 2, 3, 2, 5, None, 8]
|
|
features = []
|
|
for i in int_values:
|
|
f = QgsFeature()
|
|
f.setFields(layer.fields())
|
|
f.setAttributes([i])
|
|
features.append(f)
|
|
assert pr.addFeatures(features)
|
|
|
|
tests = [[QgsAggregateCalculator.Count, 6],
|
|
[QgsAggregateCalculator.Sum, 24],
|
|
[QgsAggregateCalculator.Mean, 4],
|
|
[QgsAggregateCalculator.StDev, 2.0816],
|
|
[QgsAggregateCalculator.StDevSample, 2.2803],
|
|
[QgsAggregateCalculator.Min, 2],
|
|
[QgsAggregateCalculator.Max, 8],
|
|
[QgsAggregateCalculator.Range, 6],
|
|
[QgsAggregateCalculator.Median, 3.5],
|
|
[QgsAggregateCalculator.CountDistinct, 5],
|
|
[QgsAggregateCalculator.CountMissing, 1],
|
|
[QgsAggregateCalculator.FirstQuartile, 2],
|
|
[QgsAggregateCalculator.ThirdQuartile, 5.0],
|
|
[QgsAggregateCalculator.InterQuartileRange, 3.0]
|
|
]
|
|
|
|
for t in tests:
|
|
val, ok = layer.aggregate(t[0], 'fldint')
|
|
self.assertTrue(ok)
|
|
if isinstance(t[1], int):
|
|
self.assertEqual(val, t[1])
|
|
else:
|
|
self.assertAlmostEqual(val, t[1], 3)
|
|
|
|
# test with parameters
|
|
layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory")
|
|
pr = layer.dataProvider()
|
|
|
|
string_values = ['this', 'is', 'a', 'test']
|
|
features = []
|
|
for s in string_values:
|
|
f = QgsFeature()
|
|
f.setFields(layer.fields())
|
|
f.setAttributes([s])
|
|
features.append(f)
|
|
assert pr.addFeatures(features)
|
|
params = QgsAggregateCalculator.AggregateParameters()
|
|
params.delimiter = ' '
|
|
val, ok = layer.aggregate(QgsAggregateCalculator.StringConcatenate, 'fldstring', params)
|
|
self.assertTrue(ok)
|
|
self.assertEqual(val, 'this is a test')
|
|
|
|
def onLayerTransparencyChanged(self, tr):
|
|
self.transparencyTest = tr
|
|
|
|
def test_setLayerTransparency(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.transparencyTest = 0
|
|
layer.layerTransparencyChanged.connect(self.onLayerTransparencyChanged)
|
|
layer.setLayerTransparency(50)
|
|
self.assertEqual(self.transparencyTest, 50)
|
|
self.assertEqual(layer.layerTransparency(), 50)
|
|
|
|
def onRendererChanged(self):
|
|
self.rendererChanged = True
|
|
|
|
def test_setRenderer(self):
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.rendererChanged = False
|
|
layer.rendererChanged.connect(self.onRendererChanged)
|
|
|
|
r = QgsSingleSymbolRenderer(QgsSymbol.defaultSymbol(QgsWkbTypes.PointGeometry))
|
|
layer.setRenderer(r)
|
|
self.assertTrue(self.rendererChanged)
|
|
self.assertEqual(layer.renderer(), r)
|
|
|
|
def testGetSetAliases(self):
|
|
""" test getting and setting aliases """
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.assertFalse(layer.attributeAlias(0))
|
|
self.assertFalse(layer.attributeAlias(1))
|
|
self.assertFalse(layer.attributeAlias(2))
|
|
|
|
layer.setFieldAlias(0, "test")
|
|
self.assertEqual(layer.attributeAlias(0), "test")
|
|
self.assertFalse(layer.attributeAlias(1))
|
|
self.assertFalse(layer.attributeAlias(2))
|
|
self.assertEqual(layer.fields().at(0).alias(), "test")
|
|
|
|
layer.setFieldAlias(1, "test2")
|
|
self.assertEqual(layer.attributeAlias(0), "test")
|
|
self.assertEqual(layer.attributeAlias(1), "test2")
|
|
self.assertFalse(layer.attributeAlias(2))
|
|
self.assertEqual(layer.fields().at(0).alias(), "test")
|
|
self.assertEqual(layer.fields().at(1).alias(), "test2")
|
|
|
|
layer.setFieldAlias(1, None)
|
|
self.assertEqual(layer.attributeAlias(0), "test")
|
|
self.assertFalse(layer.attributeAlias(1))
|
|
self.assertFalse(layer.attributeAlias(2))
|
|
self.assertEqual(layer.fields().at(0).alias(), "test")
|
|
self.assertFalse(layer.fields().at(1).alias())
|
|
|
|
layer.removeFieldAlias(0)
|
|
self.assertFalse(layer.attributeAlias(0))
|
|
self.assertFalse(layer.attributeAlias(1))
|
|
self.assertFalse(layer.attributeAlias(2))
|
|
self.assertFalse(layer.fields().at(0).alias())
|
|
self.assertFalse(layer.fields().at(1).alias())
|
|
|
|
def testSaveRestoreAliases(self):
|
|
""" test saving and restoring aliases from xml"""
|
|
layer = createLayerWithOnePoint()
|
|
|
|
# no default expressions
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer2 = createLayerWithOnePoint()
|
|
self.assertTrue(layer2.readXml(elem, QgsReadWriteContext()))
|
|
self.assertFalse(layer2.attributeAlias(0))
|
|
self.assertFalse(layer2.attributeAlias(1))
|
|
|
|
# set some aliases
|
|
layer.setFieldAlias(0, "test")
|
|
layer.setFieldAlias(1, "test2")
|
|
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer3 = createLayerWithOnePoint()
|
|
self.assertTrue(layer3.readXml(elem, QgsReadWriteContext()))
|
|
self.assertEqual(layer3.attributeAlias(0), "test")
|
|
self.assertEqual(layer3.attributeAlias(1), "test2")
|
|
self.assertEqual(layer3.fields().at(0).alias(), "test")
|
|
self.assertEqual(layer3.fields().at(1).alias(), "test2")
|
|
|
|
def testGetSetDefaults(self):
|
|
""" test getting and setting default expressions """
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.assertFalse(layer.defaultValueExpression(0))
|
|
self.assertFalse(layer.defaultValueExpression(1))
|
|
self.assertFalse(layer.defaultValueExpression(2))
|
|
|
|
layer.setDefaultValueExpression(0, "'test'")
|
|
self.assertEqual(layer.defaultValueExpression(0), "'test'")
|
|
self.assertFalse(layer.defaultValueExpression(1))
|
|
self.assertFalse(layer.defaultValueExpression(2))
|
|
self.assertEqual(layer.fields().at(0).defaultValueExpression(), "'test'")
|
|
|
|
layer.setDefaultValueExpression(1, "2+2")
|
|
self.assertEqual(layer.defaultValueExpression(0), "'test'")
|
|
self.assertEqual(layer.defaultValueExpression(1), "2+2")
|
|
self.assertFalse(layer.defaultValueExpression(2))
|
|
self.assertEqual(layer.fields().at(0).defaultValueExpression(), "'test'")
|
|
self.assertEqual(layer.fields().at(1).defaultValueExpression(), "2+2")
|
|
|
|
def testSaveRestoreDefaults(self):
|
|
""" test saving and restoring default expressions from xml"""
|
|
layer = createLayerWithOnePoint()
|
|
|
|
# no default expressions
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer2 = createLayerWithOnePoint()
|
|
self.assertTrue(layer2.readXml(elem, QgsReadWriteContext()))
|
|
self.assertFalse(layer2.defaultValueExpression(0))
|
|
self.assertFalse(layer2.defaultValueExpression(1))
|
|
|
|
# set some default expressions
|
|
layer.setDefaultValueExpression(0, "'test'")
|
|
layer.setDefaultValueExpression(1, "2+2")
|
|
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer3 = createLayerWithOnePoint()
|
|
self.assertTrue(layer3.readXml(elem, QgsReadWriteContext()))
|
|
self.assertEqual(layer3.defaultValueExpression(0), "'test'")
|
|
self.assertEqual(layer3.defaultValueExpression(1), "2+2")
|
|
self.assertEqual(layer3.fields().at(0).defaultValueExpression(), "'test'")
|
|
self.assertEqual(layer3.fields().at(1).defaultValueExpression(), "2+2")
|
|
|
|
def testEvaluatingDefaultExpressions(self):
|
|
""" tests calculation of default values"""
|
|
layer = createLayerWithOnePoint()
|
|
layer.setDefaultValueExpression(0, "'test'")
|
|
layer.setDefaultValueExpression(1, "2+2")
|
|
self.assertEqual(layer.defaultValue(0), 'test')
|
|
self.assertEqual(layer.defaultValue(1), 4)
|
|
|
|
# using feature
|
|
layer.setDefaultValueExpression(1, '$id * 2')
|
|
feature = QgsFeature(4)
|
|
feature.setValid(True)
|
|
feature.setFields(layer.fields())
|
|
# no feature:
|
|
self.assertFalse(layer.defaultValue(1))
|
|
# with feature:
|
|
self.assertEqual(layer.defaultValue(0, feature), 'test')
|
|
self.assertEqual(layer.defaultValue(1, feature), 8)
|
|
|
|
# using feature geometry
|
|
layer.setDefaultValueExpression(1, '$x * 2')
|
|
feature.setGeometry(QgsGeometry(QgsPointV2(6, 7)))
|
|
self.assertEqual(layer.defaultValue(1, feature), 12)
|
|
|
|
# using contexts
|
|
scope = QgsExpressionContextScope()
|
|
scope.setVariable('var1', 16)
|
|
context = QgsExpressionContext()
|
|
context.appendScope(scope)
|
|
layer.setDefaultValueExpression(1, '$id + @var1')
|
|
self.assertEqual(layer.defaultValue(1, feature, context), 20)
|
|
|
|
# if no scope passed, should use a default constructed one including layer variables
|
|
QgsExpressionContextUtils.setLayerVariable(layer, 'var2', 4)
|
|
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), 'var3', 8)
|
|
layer.setDefaultValueExpression(1, 'to_int(@var2) + to_int(@var3) + $id')
|
|
self.assertEqual(layer.defaultValue(1, feature), 16)
|
|
|
|
# bad expression
|
|
layer.setDefaultValueExpression(1, 'not a valid expression')
|
|
self.assertFalse(layer.defaultValue(1))
|
|
|
|
def testGetSetConstraints(self):
|
|
""" test getting and setting field constraints """
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.assertFalse(layer.fieldConstraints(0))
|
|
self.assertFalse(layer.fieldConstraints(1))
|
|
self.assertFalse(layer.fieldConstraints(2))
|
|
|
|
layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertEqual(layer.fieldConstraints(0), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertFalse(layer.fieldConstraints(1))
|
|
self.assertFalse(layer.fieldConstraints(2))
|
|
self.assertEqual(layer.fields().at(0).constraints().constraints(), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintOrigin(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintStrength(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintStrengthHard)
|
|
|
|
layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintNotNull)
|
|
layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique)
|
|
self.assertEqual(layer.fieldConstraints(0), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertEqual(layer.fieldConstraints(1), QgsFieldConstraints.ConstraintNotNull | QgsFieldConstraints.ConstraintUnique)
|
|
self.assertFalse(layer.fieldConstraints(2))
|
|
self.assertEqual(layer.fields().at(0).constraints().constraints(), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintOrigin(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintStrength(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintStrengthHard)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraints(), QgsFieldConstraints.ConstraintNotNull | QgsFieldConstraints.ConstraintUnique)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintOrigin(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintOrigin(QgsFieldConstraints.ConstraintUnique),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintStrength(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintStrengthHard)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintStrength(QgsFieldConstraints.ConstraintUnique),
|
|
QgsFieldConstraints.ConstraintStrengthHard)
|
|
|
|
layer.removeFieldConstraint(1, QgsFieldConstraints.ConstraintNotNull)
|
|
layer.removeFieldConstraint(1, QgsFieldConstraints.ConstraintUnique)
|
|
self.assertEqual(layer.fieldConstraints(0), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertFalse(layer.fieldConstraints(1))
|
|
self.assertFalse(layer.fieldConstraints(2))
|
|
self.assertEqual(layer.fields().at(0).constraints().constraints(), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintOrigin(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintStrength(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintStrengthHard)
|
|
self.assertFalse(layer.fields().at(1).constraints().constraints())
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintOrigin(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintOriginNotSet)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintStrength(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintStrengthNotSet)
|
|
|
|
def testSaveRestoreConstraints(self):
|
|
""" test saving and restoring constraints from xml"""
|
|
layer = createLayerWithOnePoint()
|
|
|
|
# no constraints
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer2 = createLayerWithOnePoint()
|
|
self.assertTrue(layer2.readXml(elem, QgsReadWriteContext()))
|
|
self.assertFalse(layer2.fieldConstraints(0))
|
|
self.assertFalse(layer2.fieldConstraints(1))
|
|
|
|
# set some constraints
|
|
layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintNotNull)
|
|
layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintNotNull, QgsFieldConstraints.ConstraintStrengthSoft)
|
|
layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique)
|
|
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer3 = createLayerWithOnePoint()
|
|
self.assertTrue(layer3.readXml(elem, QgsReadWriteContext()))
|
|
self.assertEqual(layer3.fieldConstraints(0), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertEqual(layer3.fieldConstraints(1), QgsFieldConstraints.ConstraintNotNull | QgsFieldConstraints.ConstraintUnique)
|
|
self.assertEqual(layer3.fields().at(0).constraints().constraints(), QgsFieldConstraints.ConstraintNotNull)
|
|
self.assertEqual(layer3.fields().at(0).constraints().constraintOrigin(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintStrength(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintStrengthHard)
|
|
self.assertEqual(layer3.fields().at(1).constraints().constraints(), QgsFieldConstraints.ConstraintNotNull | QgsFieldConstraints.ConstraintUnique)
|
|
self.assertEqual(layer3.fields().at(1).constraints().constraintOrigin(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer3.fields().at(1).constraints().constraintOrigin(QgsFieldConstraints.ConstraintUnique),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintStrength(QgsFieldConstraints.ConstraintNotNull),
|
|
QgsFieldConstraints.ConstraintStrengthSoft)
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintStrength(QgsFieldConstraints.ConstraintUnique),
|
|
QgsFieldConstraints.ConstraintStrengthHard)
|
|
|
|
def testGetSetConstraintExpressions(self):
|
|
""" test getting and setting field constraint expressions """
|
|
layer = createLayerWithOnePoint()
|
|
|
|
self.assertFalse(layer.constraintExpression(0))
|
|
self.assertFalse(layer.constraintExpression(1))
|
|
self.assertFalse(layer.constraintExpression(2))
|
|
|
|
layer.setConstraintExpression(0, '1+2')
|
|
self.assertEqual(layer.constraintExpression(0), '1+2')
|
|
self.assertFalse(layer.constraintExpression(1))
|
|
self.assertFalse(layer.constraintExpression(2))
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintExpression(), '1+2')
|
|
|
|
layer.setConstraintExpression(1, '3+4', 'desc')
|
|
self.assertEqual(layer.constraintExpression(0), '1+2')
|
|
self.assertEqual(layer.constraintExpression(1), '3+4')
|
|
self.assertEqual(layer.constraintDescription(1), 'desc')
|
|
self.assertFalse(layer.constraintExpression(2))
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintExpression(), '1+2')
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintExpression(), '3+4')
|
|
self.assertEqual(layer.fields().at(1).constraints().constraintDescription(), 'desc')
|
|
|
|
layer.setConstraintExpression(1, None)
|
|
self.assertEqual(layer.constraintExpression(0), '1+2')
|
|
self.assertFalse(layer.constraintExpression(1))
|
|
self.assertFalse(layer.constraintExpression(2))
|
|
self.assertEqual(layer.fields().at(0).constraints().constraintExpression(), '1+2')
|
|
self.assertFalse(layer.fields().at(1).constraints().constraintExpression())
|
|
|
|
def testSaveRestoreConstraintExpressions(self):
|
|
""" test saving and restoring constraint expressions from xml"""
|
|
layer = createLayerWithOnePoint()
|
|
|
|
# no constraints
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer2 = createLayerWithOnePoint()
|
|
self.assertTrue(layer2.readXml(elem, QgsReadWriteContext()))
|
|
self.assertFalse(layer2.constraintExpression(0))
|
|
self.assertFalse(layer2.constraintExpression(1))
|
|
|
|
# set some constraints
|
|
layer.setConstraintExpression(0, '1+2')
|
|
layer.setConstraintExpression(1, '3+4', 'desc')
|
|
|
|
doc = QDomDocument("testdoc")
|
|
elem = doc.createElement("maplayer")
|
|
self.assertTrue(layer.writeXml(elem, doc, QgsReadWriteContext()))
|
|
|
|
layer3 = createLayerWithOnePoint()
|
|
self.assertTrue(layer3.readXml(elem, QgsReadWriteContext()))
|
|
self.assertEqual(layer3.constraintExpression(0), '1+2')
|
|
self.assertEqual(layer3.constraintExpression(1), '3+4')
|
|
self.assertEqual(layer3.constraintDescription(1), 'desc')
|
|
self.assertEqual(layer3.fields().at(0).constraints().constraintExpression(), '1+2')
|
|
self.assertEqual(layer3.fields().at(1).constraints().constraintExpression(), '3+4')
|
|
self.assertEqual(layer3.fields().at(1).constraints().constraintDescription(), 'desc')
|
|
self.assertEqual(layer3.fields().at(0).constraints().constraints(), QgsFieldConstraints.ConstraintExpression)
|
|
self.assertEqual(layer3.fields().at(1).constraints().constraints(), QgsFieldConstraints.ConstraintExpression)
|
|
self.assertEqual(layer3.fields().at(0).constraints().constraintOrigin(QgsFieldConstraints.ConstraintExpression),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
self.assertEqual(layer3.fields().at(1).constraints().constraintOrigin(QgsFieldConstraints.ConstraintExpression),
|
|
QgsFieldConstraints.ConstraintOriginLayer)
|
|
|
|
def testGetFeatureLimitWithEdits(self):
|
|
""" test getting features with a limit, when edits are present """
|
|
layer = createLayerWithOnePoint()
|
|
# now has one feature with id 0
|
|
|
|
pr = layer.dataProvider()
|
|
|
|
f1 = QgsFeature(1)
|
|
f1.setAttributes(["test", 3])
|
|
f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(300, 200)))
|
|
f2 = QgsFeature(2)
|
|
f2.setAttributes(["test", 3])
|
|
f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
|
|
f3 = QgsFeature(3)
|
|
f3.setAttributes(["test", 3])
|
|
f3.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200)))
|
|
self.assertTrue(pr.addFeatures([f1, f2, f3]))
|
|
|
|
req = QgsFeatureRequest().setLimit(2)
|
|
self.assertEqual(len(list(layer.getFeatures(req))), 2)
|
|
|
|
# now delete feature f1
|
|
layer.startEditing()
|
|
self.assertTrue(layer.deleteFeature(1))
|
|
req = QgsFeatureRequest().setLimit(2)
|
|
self.assertEqual(len(list(layer.getFeatures(req))), 2)
|
|
layer.rollBack()
|
|
|
|
# change an attribute value required by filter
|
|
layer.startEditing()
|
|
req = QgsFeatureRequest().setFilterExpression('fldint=3').setLimit(2)
|
|
self.assertTrue(layer.changeAttributeValue(2, 1, 4))
|
|
self.assertEqual(len(list(layer.getFeatures(req))), 2)
|
|
layer.rollBack()
|
|
|
|
layer.startEditing()
|
|
req = QgsFeatureRequest().setFilterRect(QgsRectangle(50, 100, 150, 300)).setLimit(2)
|
|
self.assertTrue(layer.changeGeometry(2, QgsGeometry.fromPoint(QgsPoint(500, 600))))
|
|
self.assertEqual(len(list(layer.getFeatures(req))), 2)
|
|
layer.rollBack()
|
|
|
|
def testClone(self):
|
|
# init crs
|
|
srs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId)
|
|
|
|
# init map layer styles
|
|
tmplayer = createLayerWithTwoPoints()
|
|
sym1 = QgsLineSymbol()
|
|
sym1.setColor(Qt.magenta)
|
|
tmplayer.setRenderer(QgsSingleSymbolRenderer(sym1))
|
|
|
|
style0 = QgsMapLayerStyle()
|
|
style0.readFromLayer(tmplayer)
|
|
style1 = QgsMapLayerStyle()
|
|
style1.readFromLayer(tmplayer)
|
|
|
|
# init dependencies layers
|
|
ldep = createLayerWithTwoPoints()
|
|
dep = QgsMapLayerDependency(ldep.id())
|
|
|
|
# init layer
|
|
layer = createLayerWithTwoPoints()
|
|
layer.setBlendMode(QPainter.CompositionMode_Screen)
|
|
layer.styleManager().addStyle('style0', style0)
|
|
layer.styleManager().addStyle('style1', style1)
|
|
layer.setName('MyName')
|
|
layer.setShortName('MyShortName')
|
|
layer.setMinimumScale(0.5)
|
|
layer.setMaximumScale(1.5)
|
|
layer.setScaleBasedVisibility(True)
|
|
layer.setTitle('MyTitle')
|
|
layer.setAbstract('MyAbstract')
|
|
layer.setKeywordList('MyKeywordList')
|
|
layer.setDataUrl('MyDataUrl')
|
|
layer.setDataUrlFormat('MyDataUrlFormat')
|
|
layer.setAttribution('MyAttribution')
|
|
layer.setAttributionUrl('MyAttributionUrl')
|
|
layer.setMetadataUrl('MyMetadataUrl')
|
|
layer.setMetadataUrlType('MyMetadataUrlType')
|
|
layer.setMetadataUrlFormat('MyMetadataUrlFormat')
|
|
layer.setLegendUrl('MyLegendUrl')
|
|
layer.setLegendUrlFormat('MyLegendUrlFormat')
|
|
layer.setDependencies([dep])
|
|
layer.setCrs(srs)
|
|
|
|
layer.setCustomProperty('MyKey0', 'MyValue0')
|
|
layer.setCustomProperty('MyKey1', 'MyValue1')
|
|
|
|
layer.setLayerTransparency(33)
|
|
layer.setProviderEncoding('latin9')
|
|
layer.setDisplayExpression('MyDisplayExpression')
|
|
layer.setMapTipTemplate('MyMapTipTemplate')
|
|
layer.setExcludeAttributesWfs(['MyExcludeAttributeWFS'])
|
|
layer.setExcludeAttributesWms(['MyExcludeAttributeWMS'])
|
|
|
|
layer.setFeatureBlendMode(QPainter.CompositionMode_Xor)
|
|
|
|
sym = QgsLineSymbol()
|
|
sym.setColor(Qt.magenta)
|
|
layer.setRenderer(QgsSingleSymbolRenderer(sym))
|
|
|
|
simplify = layer.simplifyMethod()
|
|
simplify.setTolerance(33.3)
|
|
simplify.setThreshold(0.333)
|
|
layer.setSimplifyMethod(simplify)
|
|
|
|
layer.setFieldAlias(0, 'MyAlias0')
|
|
layer.setFieldAlias(1, 'MyAlias1')
|
|
|
|
jl0 = createLayerWithTwoPoints()
|
|
j0 = QgsVectorLayerJoinInfo()
|
|
j0.setJoinLayer(jl0)
|
|
|
|
jl1 = createLayerWithTwoPoints()
|
|
j1 = QgsVectorLayerJoinInfo()
|
|
j1.setJoinLayer(jl1)
|
|
|
|
layer.addJoin(j0)
|
|
layer.addJoin(j1)
|
|
|
|
fids = layer.allFeatureIds()
|
|
selected_fids = fids[0:3]
|
|
layer.selectByIds(selected_fids)
|
|
|
|
cfg = layer.attributeTableConfig()
|
|
cfg.setSortOrder(Qt.DescendingOrder) # by default AscendingOrder
|
|
layer.setAttributeTableConfig(cfg)
|
|
|
|
pal = QgsPalLayerSettings()
|
|
text_format = QgsTextFormat()
|
|
text_format.setSize(33)
|
|
text_format.setColor(Qt.magenta)
|
|
pal.setFormat(text_format)
|
|
|
|
labeling = QgsVectorLayerSimpleLabeling(pal)
|
|
layer.setLabeling(labeling)
|
|
|
|
diag_renderer = QgsSingleCategoryDiagramRenderer()
|
|
diag_renderer.setAttributeLegend(False) # true by default
|
|
diag_renderer.setSizeLegend(True) # false by default
|
|
layer.setDiagramRenderer(diag_renderer)
|
|
|
|
diag_settings = QgsDiagramLayerSettings()
|
|
diag_settings.setPriority(3)
|
|
diag_settings.setZIndex(0.33)
|
|
layer.setDiagramLayerSettings(diag_settings)
|
|
|
|
edit_form_config = layer.editFormConfig()
|
|
edit_form_config.setUiForm("MyUiForm")
|
|
edit_form_config.setInitFilePath("MyInitFilePath")
|
|
layer.setEditFormConfig(edit_form_config)
|
|
|
|
widget_setup = QgsEditorWidgetSetup("MyWidgetSetupType", {})
|
|
layer.setEditorWidgetSetup(0, widget_setup)
|
|
|
|
layer.setConstraintExpression(0, "MyFieldConstraintExpression")
|
|
layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique, QgsFieldConstraints.ConstraintStrengthHard)
|
|
layer.setDefaultValueExpression(0, "MyDefaultValueExpression")
|
|
|
|
action = QgsAction(QgsAction.Unix, "MyActionDescription", "MyActionCmd")
|
|
layer.actions().addAction(action)
|
|
|
|
# clone layer
|
|
clone = layer.clone()
|
|
|
|
# generate xml from layer
|
|
layer_doc = QDomDocument("doc")
|
|
layer_elem = layer_doc.createElement("maplayer")
|
|
layer.writeLayerXml(layer_elem, layer_doc, QgsReadWriteContext())
|
|
|
|
# generate xml from clone
|
|
clone_doc = QDomDocument("doc")
|
|
clone_elem = clone_doc.createElement("maplayer")
|
|
clone.writeLayerXml(clone_elem, clone_doc, QgsReadWriteContext())
|
|
|
|
# replace id within xml of clone
|
|
clone_id_elem = clone_elem.firstChildElement("id")
|
|
clone_id_elem_patch = clone_doc.createElement("id")
|
|
clone_id_elem_patch_value = clone_doc.createTextNode(layer.id())
|
|
clone_id_elem_patch.appendChild(clone_id_elem_patch_value)
|
|
clone_elem.replaceChild(clone_id_elem_patch, clone_id_elem)
|
|
|
|
# update doc
|
|
clone_doc.appendChild(clone_elem)
|
|
layer_doc.appendChild(layer_elem)
|
|
|
|
# compare xml documents
|
|
self.assertEqual(layer_doc.toString(), clone_doc.toString())
|
|
|
|
|
|
# TODO:
|
|
# - fetch rect: feat with changed geometry: 1. in rect, 2. out of rect
|
|
# - more join tests
|
|
# - import
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|