By default, the QCompleter offers auto-completion suggestion for the entirety of the text in an input widget (QLineEdit or whatever). This means word-by-word suggestion is not possible. So, I tried to subclass the QCompleter and override its splitPath and pathFromIndex method to customize its behavior.
class My_Completer(QCompleter):
def __init__(self, parent=None):
super().__init__(parent)
self.setCaseSensitivity(Qt.CaseInsensitive)
self.setFilterMode(Qt.MatchStartsWith)
model = QStringListModel()
model.setStringList([])
self.setModel(model)
def update_suggestions(self, suggestions:list):
model: QStringListModel = self.model()
model.setStringList(suggestions)
def pathFromIndex(self, index):
# Get the selected completion suggestion
completion = super().pathFromIndex(index)
# Get the original text
cursor_pos = self.widget().cursorPosition()
text = self.widget().text()[:cursor_pos]
last_space = text.rfind(' ')
if last_space == -1:
# No space found, so we replace the entire text
new_text = completion
else:
# Replace only the last word
new_text = text[:last_space + 1] + completion
# Append the text after the cursor if any
remainder_text = self.widget().text()[cursor_pos:]
return new_text + remainder_text
def splitPath(self, path):
cursor_pos = self.widget().cursorPosition()
text = self.widget().text()[:cursor_pos]
path = text.split(' ')[-1]
if path:
return [path]
else:
return ['----']
In the splitPath method, I split the text of the input widget and return the last last word before the cursor position for the completer object to match for possible suggestions. In the pathFromIndex method, I try to insert the selected suggestion to the input widget. The above code could provide word-by-word suggestions, but it has a major flaw.
I noticed that when iterating over the popup suggestions on the UI, the completer object actually emits 2 signals during the process. One is when a suggestion is highlighted. The other is when a suggestion is officially selected, or in Qt’s term, activated.
For both the highlighted and activated signals, they insert the suggestions to the input widget and then set the cursor position to the end of the string. This is not something what I want. When a suggestion is highlighted, nothing should happen. And when a suggestion is activated, it should only insert the suggestion and then set the cursor position to the end of the inserted suggestion, not the end of the entire string. I have tried to connect custom slot functions to the highlighted and activated signals to implement the behavior I want (adjusting the cursor position etc.), but to no avail. The built-in behavior were still there. So there has to be some built-in functions executed after my slot functions.
I guess my question is, how do I or what are the built-in functions I should override to prevent the QCompleter to set the cursor position to the end by default for activated suggestions and completely disable the default highlighted behavior.
Also, there is a minor question about the QCompleter popup style. I can use below qss statement to custmize the backgroud color of the popup. But how do I customize the backgroud color of highlighted suggestions?
QAbstractItemView {
background-color: black;
color: white;
}