1# -*- coding: utf-8 -*- 2"""QGIS Unit tests for the attribute table model. 3 4.. note:: This program is free software; you can redistribute it and/or modify 5it under the terms of the GNU General Public License as published by 6the Free Software Foundation; either version 2 of the License, or 7(at your option) any later version. 8""" 9__author__ = 'Matthias Kuhn' 10__date__ = '27/05/2015' 11__copyright__ = 'Copyright 2015, The QGIS Project' 12 13from qgis.gui import ( 14 QgsAttributeTableModel, 15 QgsGui 16) 17from qgis.core import ( 18 QgsFeature, 19 QgsGeometry, 20 QgsPointXY, 21 QgsVectorLayer, 22 QgsVectorLayerCache, 23 QgsConditionalStyle, 24) 25from qgis.PyQt.QtCore import Qt 26from qgis.PyQt.QtGui import QColor 27from qgis.testing import (start_app, 28 unittest 29 ) 30 31start_app() 32 33 34class TestQgsAttributeTableModel(unittest.TestCase): 35 36 @classmethod 37 def setUpClass(cls): 38 QgsGui.editorWidgetRegistry().initEditors() 39 40 def setUp(self): 41 self.layer = self.createLayer() 42 self.cache = QgsVectorLayerCache(self.layer, 100) 43 self.am = QgsAttributeTableModel(self.cache) 44 self.am.loadLayer() 45 46 def tearDown(self): 47 del self.am 48 del self.cache 49 del self.layer 50 51 def createLayer(self): 52 layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", 53 "addfeat", "memory") 54 pr = layer.dataProvider() 55 features = list() 56 for i in range(10): 57 f = QgsFeature() 58 f.setAttributes(["test", i]) 59 f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100 * i, 2 ^ i))) 60 features.append(f) 61 62 self.assertTrue(pr.addFeatures(features)) 63 return layer 64 65 def testLoad(self): 66 self.assertEqual(self.am.rowCount(), 10) 67 self.assertEqual(self.am.columnCount(), 2) 68 69 def testRemove(self): 70 self.layer.startEditing() 71 self.layer.deleteFeature(5) 72 self.assertEqual(self.am.rowCount(), 9) 73 self.layer.selectByIds([1, 3, 6, 7]) 74 self.layer.deleteSelectedFeatures() 75 self.assertEqual(self.am.rowCount(), 5) 76 77 def testAdd(self): 78 self.layer.startEditing() 79 80 f = QgsFeature() 81 f.setAttributes(["test", 8]) 82 f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) 83 self.layer.addFeature(f) 84 85 self.assertEqual(self.am.rowCount(), 11) 86 87 def testRemoveColumns(self): 88 self.assertTrue(self.layer.startEditing()) 89 90 self.assertTrue(self.layer.deleteAttribute(1)) 91 92 self.assertEqual(self.am.columnCount(), 1) 93 94 def testEdit(self): 95 fid = 2 96 field_idx = 1 97 new_value = 333 98 99 # get the same feature from model and layer 100 feature = self.layer.getFeature(fid) 101 model_index = self.am.idToIndex(fid) 102 feature_model = self.am.feature(model_index) 103 104 # check that feature from layer and model are sync 105 self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) 106 107 # change attribute value for a feature and commit 108 self.layer.startEditing() 109 self.layer.changeAttributeValue(fid, field_idx, new_value) 110 self.layer.commitChanges() 111 112 # check the feature in layer is good 113 feature = self.layer.getFeature(fid) 114 self.assertEqual(feature.attribute(field_idx), new_value) 115 116 # get the same feature from model and layer 117 model_index = self.am.idToIndex(fid) 118 feature_model = self.am.feature(model_index) 119 120 # check that index from layer and model are sync 121 self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) 122 123 def testStyle(self): 124 style_threshold = 2 125 color = QColor(133, 133, 133) 126 style = QgsConditionalStyle() 127 style.setRule(f'"fldint" <= {style_threshold}') 128 style.setTextColor(color) 129 self.layer.conditionalStyles().setRowStyles([style]) 130 131 for f in self.layer.getFeatures(): 132 model_index = self.am.idToIndex(f.id()) 133 text_color = self.am.data(model_index, Qt.TextColorRole) 134 135 if f['fldint'] <= style_threshold: 136 self.assertEqual(text_color, color) 137 else: 138 self.assertIsNone(text_color) 139 140 self.assertTrue(self.layer.startEditing()) 141 142 feature1 = self.layer.getFeature(2) 143 feature1['fldint'] = style_threshold + 1 144 feature2 = self.layer.getFeature(8) 145 feature2['fldint'] = style_threshold 146 147 self.assertTrue(self.layer.updateFeature(feature1)) 148 self.assertTrue(self.layer.updateFeature(feature2)) 149 self.assertTrue(self.layer.commitChanges()) 150 151 for f in self.layer.getFeatures(): 152 model_index = self.am.idToIndex(f.id()) 153 text_color = self.am.data(model_index, Qt.TextColorRole) 154 155 if f['fldint'] <= style_threshold: 156 self.assertEqual(color, text_color, f'Feature {f.id()} should have color') 157 else: 158 self.assertIsNone(text_color, f'Feature {f.id()} should have no color') 159 160 self.layer.conditionalStyles().setRowStyles([]) 161 162 163if __name__ == '__main__': 164 unittest.main() 165