PyQt LineEdit с readline довършител?

Работя върху инструмент за команден ред, за който сега правя PyQT GUI. Бих искал да взема текущото си внедряване на автоматично довършване с помощта на модула 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, това, което в крайна сметка бих искал да направя, е да завърша списък с думи, с възможността да имам няколко думи, разделени със символи като +-*/( ) и т.н...

Благодаря!


person Bradley Powers    schedule 09.07.2012    source източник


Отговори (1)


Мога да ви кажа, че първо е огромна болка да се опитате да обвиете QCompleter около нова функционалност. Трябва да можете да задоволите целия интерфейс на QCompleter и да го свържете около този realine код.

Трябва ръчно да актуализирате набор 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)

Има примери тук показва как други хора трябваше да попълнят функционалност в редактиране по избор, където те напълно заобикалят стандартното сигнализиране на допълнителя и го задействат сами. Виждате, че е положено малко усилие.

person jdi    schedule 09.07.2012
comment
Единствената функционалност, която също бих искал да извадя от това, която се предлага в модула readline, е продължаване на извършването на довършване на табулатори в множество думи. Например, ако списъкът ми с думи е aardvark aardwolf, искам да мога да напиша: aardvark-aardw и да натисна tab, след което да го завърша. Някакви идеи? Извинения, ако това е прост проблем, аз съм много нов в PyQt... - person Bradley Powers; 10.07.2012
comment
Добре, току-що разбрах най-близкото, което мога да направя, за да направя това да работи, без да се налага да подкласирам QLineEdit. Добавих и вашата част относно откриването на разделител и продължаващото завършване. - person jdi; 10.07.2012
comment
Отлично, благодаря много за помощта! Има две неща, които текущата ви реализация не прави и които бих искал да видя. Едната е, че се разделя само на тирета и в моята OP споменах, че искам да разделя на множество оператори като +-/^(). Познанията ми за regex на практика са нула, но предполагам, че това е постижимо? Второ, това ще се раздели само веднъж. Например, все още искам завършване на табулация, ако направя „aardvark+aardwolvesbab“, за да съответства на babel в моя списък с думи. мисли? - person Bradley Powers; 10.07.2012
comment
Да, всичко е свързано с регулярния израз. Просто трябва да определите как да го разделите. Няма значение колко сепаратори. Докато разделянето връща двете части, ще работи. Научаването на регулярен израз е отделна задача ;) да се надяваме, че не правите тази част от изискването да приемете този отговор. - person jdi; 10.07.2012
comment
Достатъчно честно. Просто исках да се уверя, че това е всичко. Благодаря за вашата помощ! - person Bradley Powers; 10.07.2012
comment
Току-що актуализирах регулярния израз, за ​​да включва модела, който посочихте в горните коментари. \s означава празни знаци' и следван от другите изрични знаци, които споменахте. Просто ги добавяте към този раздел със скоби. - person jdi; 10.07.2012
comment
Благодаря! Всъщност разгледах регулярните изрази и разбрах това! Те са отличен инструмент. Не съм имал голяма полза от тях преди, тъй като съм роботицист и правя много малко програми с общо предназначение, както сега, но това е добър инструмент за инструментариума. - person Bradley Powers; 11.07.2012