PyQt LineEdit с завершающим readline?
Я работал над инструментом командной строки, для которого сейчас делаю графический интерфейс PyQT. Я хотел бы взять мою текущую реализацию автозаполнения, используя модуль readline, и поместить ее в текстовое поле QLineEdit. Это возможно? У вас есть какие-нибудь рекомендации?
Вот пример того, что я делаю с модулем readline:
import readline
values = ['these','are','my','autocomplete','words']
completions = {}
def completer(text,state):
try:
matches = completions[text]
except KeyError:
matches = [value for value in values if text.upper() in value.upper()]
completions[text] = matches
try:
return matches[state]
except IndexError:
return None
readline.set_completer(completer)
readline.parse_and_bind('tab: menu-complete')
whie 1:
text = raw_input('> ')
text.dostuff()
В конечном счете, если я не могу заставить модуль readline работать в виджете QLineEdit, то, что я в конечном итоге хотел бы сделать, это завершить работу со списком слов с возможностью иметь несколько слов, разделенных такими символами, как +-*/() так далее...
Спасибо!
1 ответ
Я могу сказать вам, что во-первых, это огромная боль, пытаться обернуть QCompleter вокруг новой функциональности. Вы должны быть в состоянии удовлетворить весь интерфейс QCompleter и соединить его с этим реальным кодом.
Вы должны вручную обновить набор QStringListModel в QCompleter и предоставить реализацию получения текущего завершения и общего количества завершений для данного префикса поиска.
Вот рабочий пример, который совместим с режимом PopupCompletion:
import re
class ReadlineCompleter(QtGui.QCompleter):
def __init__(self, completeFn, *args, **kwargs):
super(ReadlineCompleter, self).__init__(*args, **kwargs)
self._completer = completeFn
self.setModel(QtGui.QStringListModel())
self.update()
def setCompletionPrefix(self, val):
super(ReadlineCompleter, self).setCompletionPrefix(val)
self.update()
def currentCompletion(self):
state = self.currentRow()
return self._completionAt(state)
def completionCount(self):
state = 0
while True:
result = self._completionAt(state)
if not result:
break
state += 1
return state
def update(self):
matches = [self._completionAt(i) for i in xrange(self.completionCount())]
self.model().setStringList(matches)
def _completionAt(self, state):
text = str(self.completionPrefix())
# regex to split on any whitespace, or the char set +*/^()-
match = re.match(r'^(.*)([\s+*/^()-]+)(.*)$', text)
if match:
prefix, sep, text = match.groups()
result = self._completer(str(text), state)
if result and match:
result = sep.join([prefix, result])
return '' if result is None else result
Обратите внимание на _completionAt()
метод, я добавил дополнительную функциональность, которую вы хотели, для обнаружения шаблона разделителя. Вы можете настроить это, очевидно. Но он будет отделять последнюю часть и использовать это значение для проверки завершения, а затем снова присоединиться к результату с префиксом.
использование
Важный. Вам необходимо подключить textChanged
сигнал от QLineEdit завершителю для принудительного обновления. В противном случае ни одна из функциональных возможностей не будет использоваться в завершителе.
line = QtGui.QLineEdit()
comp = ReadlineCompleter(completer)
comp.setCompletionMode(comp.PopupCompletion)
line.setCompleter(comp)
# important
line.textChanged.connect(comp.setCompletionPrefix)
Здесь есть примеры, показывающие, как другие люди должны были заполнить функциональность в редактировании пользовательской строки, где они полностью обходят стандартную сигнализацию завершителя и запускают ее самостоятельно. Вы можете увидеть его немного усилий.