I have data with multiple columns (like "first name"/"surname" or "postal code"/"place name"), and I would now like to have (something like) a qcompleter which only matches from the start of each column.
This means an input of "a" would show the suggestions like "Andrea Miller" or "John Adams" but not "Jane Doe" or "Tom Masters".
Any hints how to implements this?
A workaround is to disable QCompleter filtering and use a QSortFilterProxyModel to do custom filtering:
import sys
from PySide2 import QtCore, QtWidgets
class FilterModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent=None):
super().__init__(parent)
self._prefix = ""
@property
def prefix(self):
return self._prefix
@prefix.setter
def prefix(self, prefix):
self._prefix = prefix.lower()
self.invalidateFilter()
def filterAcceptsRow(self, sourceRow, sourceParent):
if not self.prefix:
return True
text = (
self.sourceModel()
.index(sourceRow, self.filterKeyColumn(), sourceParent)
.data()
)
for word in text.split():
if word.lower().startswith(self.prefix):
return True
return False
class Completer(QtWidgets.QCompleter):
def setModel(self, model):
proxy_internal_model = FilterModel(self)
proxy_internal_model.setSourceModel(model)
model.setParent(proxy_internal_model)
super().setModel(proxy_internal_model)
def splitPath(self, path):
if isinstance(self.model(), FilterModel):
self.model().prefix = path
return [""]
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QLineEdit()
texts = ["Andrea Miller", "John Adams", "Jane Doe", "Tom Masters"]
completer = Completer(w)
completer.setModel(QtCore.QStringListModel(texts, w))
w.setCompleter(completer)
w.show()
sys.exit(app.exec_())