I have read through the QCompleter docs (https://doc.qt.io/qt-5/qcompleter.html) and I've tried to implement QCompleter for a QPlainTextEdit.
Now I've got it to work like this:
But the problem with that is, if you start writing a word that is in the list created by keyword.kwlist, then it focuses on the popup that pops up under the cursor and it doesn't let me keep typing.
But when converting the code from c++ to python on the QCompleter docs page, i could still type even if it offered me a selection of words below.
I've tried setting focus to self.editor but that didn't work. I need help with this and the position of the popup. Right now it's kind of blocking the view of the word.
The way it should function is like this:
but that only works with QLineEdit.
from PyQt5.QtWidgets import QCompleter, QPlainTextEdit, QApplication, QWidget, QHBoxLayout
import sys
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QTextCursor, QFont, QTextOption
import keyword
class Completer(QCompleter):
insertText = pyqtSignal(str)
def __init__(self, myKeywords=None, parent=None):
myKeywords = keyword.kwlist
QCompleter.__init__(self, myKeywords, parent)
self.activated.connect(self.changeCompletion)
def changeCompletion(self, completion):
if completion.find("(") != -1:
completion = completion[:completion.find("(")]
print(completion)
print("completion is " + str(completion))
self.insertText.emit(completion + " ")
self.popup().hide()
class MyTextEdit(QWidget):
def __init__(self, *args):
super().__init__(*args)
font = QFont()
font.setPointSize(12)
self.editor = QPlainTextEdit()
self.setFont(font)
self.completer = None
self.hbox = QHBoxLayout(self)
self.editor.textChanged.connect(self.complete)
self.hbox.addWidget(self.editor)
def setCompleter(self, completer):
if self.completer:
print("completer is: " + str(completer))
self.disconnect()
if not completer:
print("completer is: " + str(completer))
return
completer.setWidget(self)
completer.setCompletionMode(QCompleter.PopupCompletion)
completer.setCaseSensitivity(Qt.CaseInsensitive)
self.completer = completer
self.completer.insertText.connect(self.insertCompletion)
def insertCompletion(self, completion):
tc = self.editor.textCursor()
extra = (len(completion) - len(self.completer.completionPrefix()))
tc.movePosition(QTextCursor.Left)
tc.movePosition(QTextCursor.EndOfWord)
tc.insertText(completion[-extra:])
self.editor.setTextCursor(tc)
def textUnderCursor(self):
tc = self.editor.textCursor()
tc.select(QTextCursor.WordUnderCursor)
return tc.selectedText()
def complete(self):
completionPrefix = self.textUnderCursor()
print("completion prefix is: " + str(completionPrefix))
self.completer.setCompletionPrefix(completionPrefix)
popup = self.completer.popup()
popup.setCurrentIndex(
self.completer.completionModel().index(0, 0))
cr = self.editor.cursorRect()
cr.setWidth(
self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width())
self.completer.complete(cr)
if __name__ == "__main__":
app = QApplication(sys.argv)
completer = Completer()
te = MyTextEdit()
te.setCompleter(completer)
te.show()
sys.exit(app.exec_())