You can try this small plugin in python console.
Let there be a layer called polygons
. This layer have some fields including name
which should contain a list of specific values.
When you launch the script you will see this thing:

As I said in a comment section of question: there is a user input line, combobxes (fields, values) and button to set a new value.
Once you select a new layer, field+values comboboxes are changing. Once you change field, a value list is updating accroding to its existance in sample dict. And once you enter something in a line box, values box will filter its content to the closest values to user print.

After you press button Set value
, script will update all selected features' field according to what you select in values combobox. If nothing was found in combobox, field attribute will be updated with a user printed value.
You can change values_dict
according to your layer and test it.
# sample values dict
values_dict = {
"polygons":{
"name": [
"Panthera pardus orientalis",
"Diceros bicornis",
"Pongo pygmaeus",
"Gorilla gorilla diehli",
"Eretmochelys imbricata",
"Rhinoceros sondaicus",
"Crocodile"
]
}
}
class filler(QWidget):
def __init__(self):
super().__init__()
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
self.grid = QGridLayout()
self.grid.setSpacing(10)
# variables
self.current_layer = None
self.fields_data = []
self.values_data = []
# widgets
self.line_search = QLineEdit()
self.combo_fields= QComboBox()
self.combo_values= QComboBox()
self.value_change = QPushButton('Set value')
# gui setup
self.setLayout(self.grid)
self.grid.addWidget(self.line_search, 0, 1, 1, 5)
self.grid.addWidget(self.combo_fields, 2, 1, 1, 2)
self.grid.addWidget(self.combo_values, 2, 3, 1, 3)
self.grid.addWidget(self.value_change, 3, 1, 1, 5)
# actions
iface.currentLayerChanged.connect(self.get_active_layer)
self.combo_fields.currentIndexChanged.connect(self.update_field_data)
self.line_search.textChanged.connect(self.filter_values)
self.value_change.clicked.connect(self.calculate)
self.get_active_layer()
self.show()
def get_active_layer(self):
# get an active layer and load its fields and related values
if iface.activeLayer().type() == QgsVectorLayer.VectorLayer:
self.current_layer = iface.activeLayer()
self.fields_data = self.current_layer.fields().names()
self.combo_fields.clear()
self.combo_fields.addItems(self.fields_data)
self.update_field_data()
def update_field_data(self):
# get field values load in combobox
cur_index = self.combo_fields.currentIndex()
cur_index = cur_index if cur_index!=-1 else 0
self.combo_values.clear()
field_data = values_dict.get(self.current_layer.name(), {})
self.values_data = field_data.get(self.fields_data[cur_index],[])
self.combo_values.addItems(self.values_data)
def filter_values(self):
# filtering values by user text
value_str = self.line_search.text().lower()
if not value_str:
self.combo_values.clear()
self.combo_values.addItems(self.values_data)
return
# dict like {"sample data value": ["Sample Data Value": ["sample", "data", "value"]]}
splitted_values = {n.lower(): [n, n.lower().split()] for n in self.values_data if value_str in n.lower()}
# sorting findings
# if init value starts with user value => wrd_index is 1
# if part of init value starts with user value => wrd_index is 2
# if user value within init value => wrd_index is 3
sorted_data = {}
for key, value in splitted_values.items():
if key.startswith(value_str):
wrd_index = 1
starting_v = [v.startswith(value_str) for v in value[1]]
if any(n for n in starting_v):
wrd_index = 2
else:
wrd_index = 3
sorted_data[value[0]] = wrd_index
# sorting findings by wrd_index and loading them into combobox
sorted_findings = [v[0] for v in list(sorted(sorted_data.items(), key = lambda x: x[1]))]
self.combo_values.clear()
self.combo_values.addItems(sorted_findings)
def calculate(self):
# updating features with new value
# works only if features are selected
list_selected = self.current_layer.selectedFeatureIds()
if not list_selected:
QMessageBox.information(None, "Warning", 'Select features to update')
return
# if nothing was found the user input is taken
new_value = self.combo_values.currentText() if self.combo_values.currentText() else self.line_search.text()
field_id = self.combo_fields.currentIndex()
self.current_layer.startEditing()
for fid in list_selected:
self.current_layer.changeAttributeValue(fid, field_id, new_value)
app = filler()
layer_name
-field_name
-list_of_values
. Plugin has a search line, values combobox and button to change value in field. By using python you can filter out values from list and set a new value in field