class EnumComboBox(QComboBox): changeCallback = QtCore.Signal(str) def __init__(self, values=[], parent=None): super(EnumComboBox, self).__init__(parent) self.setFocusPolicy(QtCore.Qt.StrongFocus) self.setEditable(True) self.completer = QCompleter(self) # always show all completions self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.pFilterModel = QtCore.QSortFilterProxyModel(self) self.pFilterModel.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) self.setInsertPolicy(self.NoInsert) self.completer.setPopup(self.view()) self.setCompleter(self.completer) self.lineEdit().textEdited[str].connect( self.pFilterModel.setFilterFixedString) self.lineEdit().returnPressed.connect(self.onReturnPressed) self.completer.activated.connect(self.setTextIfCompleterIsClicked) self.model = QtGui.QStandardItemModel() for i, value in enumerate(values): item = QtGui.QStandardItem(value) self.model.setItem(i, 0, item) self.setModel(self.model) self.setModelColumn(0) self.currentIndexChanged.connect(self.onIndexChanged) def onReturnPressed(self): self.changeCallback.emit(self.currentText()) def onIndexChanged(self, index): self.changeCallback.emit(self.currentText()) def setModel(self, model): super(EnumComboBox, self).setModel(model) self.pFilterModel.setSourceModel(model) self.completer.setModel(self.pFilterModel) def setModelColumn(self, column): self.completer.setCompletionColumn(column) self.pFilterModel.setFilterKeyColumn(column) super(EnumComboBox, self).setModelColumn(column) def view(self): return self.completer.popup() def index(self): return self.currentIndex() def setTextIfCompleterIsClicked(self, text): if text: index = self.findText(text) self.setCurrentIndex(index)
class WCompletionTextEdit(QPlainTextEdit): def __init__(self, parent=None): super(WCompletionTextEdit, self).__init__(parent) self.setMinimumWidth(400) self.completer = QCompleter(_defaultWordList, self) self.moveCursor(QtGui.QTextCursor.End) font = QtGui.QFont() font.setFamily("Consolas") self.setFont(font) self.setCompleter(self.completer) def setCompleter(self, completer): completer.setWidget(self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.completer = completer self.completer.activated.connect(self.insertCompletion) def insertCompletion(self, completion): tc = self.textCursor() tc.movePosition(QtGui.QTextCursor.Left) tc.movePosition(QtGui.QTextCursor.EndOfWord) tc.insertText(completion.replace(self.completer.completionPrefix(), '')) 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) QPlainTextEdit.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-space been pressed?? isShortcut = (event.modifiers() == QtCore.Qt.ControlModifier and event.key() == QtCore.Qt.Key_Space) if (not self.completer or not isShortcut): QPlainTextEdit.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() == '': # ctrl or shift key on it's own return # end of word eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=" hasModifier = ((event.modifiers() != QtCore.Qt.NoModifier) and not ctrlOrShift) completionPrefix = self.textUnderCursor() if (not isShortcut and (hasModifier or event.text() == '' or len(completionPrefix) < 3 or event.text()[:-1] in eow)): 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()) # popup it up! self.completer.complete(cr)