As far as I know, the QCompleter can only provide a suggested completion list for strings that start by the same string that has been entered for example in a QLineEdit. I'd like it to propose any string that contain this as substring, regardless of whether is it in its beginning or in its middle... That is, for a list listOfStrings and a given substring, I'd like it to suggest every string in [s for s in listOfStrings if substring in s] instead of the actual [s for s in listOfStrings if substring == s[:len(substring)]]
I tried to subclass the QCompleter class but without any luck... Here is what I have so far:
from PySide import QtCore, QtGui
class Completer(QtGui.QCompleter):
def __init__(self,stringlist,parent=None):
super(Completer,self).__init__(parent)
self.stringlist = stringlist
completeModel = QtGui.QStringListModel()
completeModel.setStringList(stringlist)
self.setModel(completeModel)
self.activated[QtCore.QModelIndex].connect(self.activatedWrap)
def activatedWrap(self, index):
print(self.stringlist[index.row()])
self.parent().setText(self.stringlist[index.row()])
def popup(self):
pop = super(Completer,self).popup()
pop.setModel(QtGui.QStringListModel(self.stringlist))
return pop
class AutoCompleteEdit(QtGui.QLineEdit):
def __init__(self, stringlist, separator = ' ', addSpaceAfterCompleting = True):
super(AutoCompleteEdit, self).__init__()
self._separator = separator
self.stringList = stringlist
self._addSpaceAfterCompleting = addSpaceAfterCompleting
self._completer = Completer(stringlist, self)
self._completer.setModelSorting(QtGui.QCompleter.CaseInsensitivelySortedModel)
self.setCompleter(self._completer)
self._keysToIgnore = [QtCore.Qt.Key_Enter,
QtCore.Qt.Key_Return,
QtCore.Qt.Key_Escape,
QtCore.Qt.Key_Tab]
def keyPressEvent(self, event):
if self._completer.popup().isVisible():
if event.key() in self._keysToIgnore:
event.ignore()
return
text = self.text() + event.text()
print(completionPrefix)
self._completer.stringlist = [s for s in self.stringList if text in s]
print(self._completer.stringlist)
super(AutoCompleteEdit, self).keyPressEvent(event)
It work partially... remaining issues that I have a hard time fixing are
- List item The trick "completionPrefix = self.text() + event.text()" is a bit too much of a naive attempt to get the text that the QLineEdit will have after the "super(AutoCompleteEdit, self).keyPressEvent(event)" call... it does not work with backspace, arrow keys, etc...
- List item The text of the QLineEdit set in activatedWrap() with the "self.parent().setText(self.stringlist[index.row()])" call gets overwritten by the QCompleter (and is set to an incorrect value)...
Arguably, the whole approach is not very elegant since it just tries to patch over the behavior of the QCompleter while leaving it finding its own matches behind the scene... but I did not find any better way to approach the problem so far!