Solution - I have converted the C++ example code into python, and post it here to for all to see.
NB - The code assumes your dictionary is located at /usr/share/dict/words.
from PyQt4 import QtGui, QtCore
STARTTEXT = ('This TextEdit provides autocompletions for words that have ' +
'more than 3 characters.\nYou can trigger autocompletion using %s\n\n'''% (
QtGui.QKeySequence("Ctrl+E").toString(QtGui.QKeySequence.NativeText)))
class DictionaryCompleter(QtGui.QCompleter):
def __init__(self, parent=None):
words = []
try:
f = open("/usr/share/dict/words","r")
for word in f:
words.append(word.strip())
f.close()
except IOError:
print "dictionary not in anticipated location"
QtGui.QCompleter.__init__(self, words, parent)
class CompletionTextEdit(QtGui.QTextEdit):
def __init__(self, parent=None):
super(CompletionTextEdit, self).__init__(parent)
self.setMinimumWidth(400)
self.setPlainText(STARTTEXT)
self.completer = None
self.moveCursor(QtGui.QTextCursor.End)
def setCompleter(self, completer):
if self.completer:
self.disconnect(self.completer, 0, self, 0)
if not completer:
return
completer.setWidget(self)
completer.setCompletionMode(QtGui.QCompleter.PopupCompletion)
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.completer = completer
self.connect(self.completer,
QtCore.SIGNAL("activated(const QString&)"), self.insertCompletion)
def insertCompletion(self, completion):
tc = self.textCursor()
extra = (completion.length() -
self.completer.completionPrefix().length())
tc.movePosition(QtGui.QTextCursor.Left)
tc.movePosition(QtGui.QTextCursor.EndOfWord)
tc.insertText(completion.right(extra))
self.setTextCursor(tc)
def textUnderCursor(self):
tc = self.textCursor()
tc.select(QtGui.QTextCursor.WordUnderCursor)
return tc.selectedText()
def focusInEvent(self, event):
if self.completer:
self.completer.setWidget(self);
QtGui.QTextEdit.focusInEvent(self, event)
def keyPressEvent(self, event):
if self.completer and self.completer.popup().isVisible():
if event.key() in (
QtCore.Qt.Key_Enter,
QtCore.Qt.Key_Return,
QtCore.Qt.Key_Escape,
QtCore.Qt.Key_Tab,
QtCore.Qt.Key_Backtab):
event.ignore()
return
## has ctrl-E been pressed??
isShortcut = (event.modifiers() == QtCore.Qt.ControlModifier and
event.key() == QtCore.Qt.Key_E)
if (not self.completer or not isShortcut):
QtGui.QTextEdit.keyPressEvent(self, event)
## ctrl or shift key on it's own??
ctrlOrShift = event.modifiers() in (QtCore.Qt.ControlModifier ,
QtCore.Qt.ShiftModifier)
if ctrlOrShift and event.text().isEmpty():
# ctrl or shift key on it's own
return
eow = QtCore.QString("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=") #end of word
hasModifier = ((event.modifiers() != QtCore.Qt.NoModifier) and
not ctrlOrShift)
completionPrefix = self.textUnderCursor()
if (not isShortcut and (hasModifier or event.text().isEmpty() or
completionPrefix.length() < 3 or
eow.contains(event.text().right(1)))):
self.completer.popup().hide()
return
if (completionPrefix != self.completer.completionPrefix()):
self.completer.setCompletionPrefix(completionPrefix)
popup = self.completer.popup()
popup.setCurrentIndex(
self.completer.completionModel().index(0,0))
cr = self.cursorRect()
cr.setWidth(self.completer.popup().sizeHintForColumn(0)
+ self.completer.popup().verticalScrollBar().sizeHint().width())
self.completer.complete(cr) ## popup it up!
if __name__ == "__main__":
app = QtGui.QApplication([])
completer = DictionaryCompleter()
te = CompletionTextEdit()
te.setCompleter(completer)
te.show()
app.exec_()
8 comments:
Thanks for sharing! Made a handful of minor tweaks for Python3, to use Python strings instead of QStrings, and I was away. Now if only I could find a simple way to match anywhere rather than just prefixes...
Thanks a lot!
I just working on a editor. It's very useful for me.
Yeah, thanks for sharing!
is there a QsciScintilla version of this??
(one that ACTUALLY updates themenu like this)
than you so mush for your code it go on help ma alot
Thanks, this is great! Would it be ok to use this in a BSD-licensed project?
Thank you very much ! Good job !
Post a Comment