QCompleter and Tab key

3.4k Views Asked by At

I'm trying to make a Completion when pressing tab, you get the first completion of all possibilities.

But, in a QWidget-based main window, pressing tab will make that QLineEdit lost focus, and completion popup hides after that.

Is there a way to fix it ?

3

There are 3 best solutions below

1
On

There is probably a better solution but one that comes to mind is to change the focus policy for all other widgets on the form to something that doesn't include "tab" focus. The only options that don't use the tab key are Qt::ClickFocus and Qt::NoFocus.

0
On

Whew. It took me some time to figure this out :) Multiple times I have tried to solve this problem, but always gave up. Now, I dug enough to find the answer.

OP, please pardon me, because the code here is Python, but should be understandable and work for C++ as well.

Basically, the problem I had was "how to select an entry in the QCompleter"; I didn't notice before, but the answer is in the popup() method. QCompleter works with a model and a view, which contains the things to show.

You can change the current row as you wish, then get the index of that row in the model, then select it in the pop-up.

In my code, I subclassed QLineEdit, created a tabPressed signal which is emitted every time Tab is pressed. Then, connected this signal to a method of the same class which does this:

  1. get the current index;
  2. select the index in the popup;
  3. advance to the next row.

As implementation, this is very trivial, but for my current purpose this is enough. Here's the skeleton (just for the tab part, it's missing the model and everything else).

class MyLineEdit(QLineEdit):
    tabPressed = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._compl = QCompleter()
        self.tabPressed.connect(self.next_completion)

    def next_completion(self):
        index = self._compl.currentIndex()
        self._compl.popup().setCurrentIndex(index)
        start = self._compl.currentRow()
        if not self._compl.setCurrentRow(start + 1):
            self._compl.setCurrentRow(0)

    def event(self, event):
        if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
            self.tabPressed.emit()
            return True
        return super().event(event)

You may need to adjust/fix few things, but this is the basic idea.

EDIT:

For details see

http://www.qtcentre.org/threads/23518-How-to-change-completion-rule-of-QCompleter

There's a little issue: when Return is pressed, the things don't work properly. Maybe you can find a solution to this problem in the link above, or in the referenced resources therein. I'll fix this in the next few days and update this answer.

0
On

Have you tried to subclass QLineEdit and intercept the key press event?

Alternatively you could set up an event filter.