I'm very new to QT so please assume I know nothing. I want an auto-complete where it only matches against the text after the last comma.
e.g. if my word bank is ["alpha", "beta", "vector space"], and the user currently has typed "epsilon,dog,space" then it should match against "vector space" since "space" is a substring of "vector space".
I'm using PyQt6 and my current code looks something like this (adapted from a YouTube tutorial):
line_of_text = QLineEdit("")
word_bank = [name for name,value in names_dict.items()]
completer = QCompleter(word_bank)
completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
completer.setFilterMode(Qt.MatchContains)
line_of_text.setCompleter(completer)
So currently, if word_bank is ["alpha", "beta", "vector space"], then if line_of_text had the string "epsilon,dog,space" then it wouldn't match against anything because "epsilon,dog,space" isn't a substring of "alpha" nor "beta" nor "vector space".
How can I alter my code to achieve what I would like to achieve? -- I'm experienced with programming, just not with Qt.
PS: I have tried doing
line_of_text.textChanged[str].connect(my_function)
where my_function takes only the substring of line_of_text after the last comma and feeds it to completer.setCompletionPrefix and then calls completer.complete(). This simply does not work. I assume the reason is that completer.complete() updates the completion prefix from line_of_text, causing the call to completer.setCompletionPrefix to be overwritten immediately after.
CodePudding user response:
One solution is to use the textChanged signal to set the completion prefix, and bypass the built-in behaviour of the line-edit to allow greater control of when and how the completions happen.
Below is a basic implementation that shows how to do that. By default, it only shows completions when the text after the last comma has more than single character - but that can be easily adjusted:
from PyQt6 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.edit = QtWidgets.QLineEdit()
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.edit)
word_bank = ['alpha', 'beta', 'vector space']
self.completer = QtWidgets.QCompleter(word_bank)
self.completer.setCaseSensitivity(
QtCore.Qt.CaseSensitivity.CaseInsensitive)
self.completer.setFilterMode(QtCore.Qt.MatchFlag.MatchContains)
self.completer.setWidget(self.edit)
self.completer.activated.connect(self.handleCompletion)
self.edit.textChanged.connect(self.handleTextChanged)
self._completing = False
def handleTextChanged(self, text):
if not self._completing:
found = False
prefix = text.rpartition(',')[-1]
if len(prefix) > 1:
self.completer.setCompletionPrefix(prefix)
if self.completer.currentRow() >= 0:
found = True
if found:
self.completer.complete()
else:
self.completer.popup().hide()
def handleCompletion(self, text):
if not self._completing:
self._completing = True
prefix = self.completer.completionPrefix()
self.edit.setText(self.edit.text()[:-len(prefix)] text)
self._completing = False
if __name__ == '__main__':
app = QtWidgets.QApplication(['Test'])
window = Window()
window.setGeometry(600, 100, 300, 50)
window.show()
app.exec()
CodePudding user response:
(Assuming str is the string from the text input) Have you tried separating str using the , character, then iterating over each of the words separated by a comma.
for word in str.split(","):
for check in word_bank:
etc...
the connected function will be called in your case whenever the string entered changes.