max
max

Reputation: 51

Qt QCompleter multiple matches

I am trying to make QCompleter match several equivalent options which are separated with commas. There seemingly is no easy way to do that, but one line of QCompleter reference caught my attention, describing function QCompleter::splitPath: "When used with list models, the first item in the returned list is used for matching." Could this be used in the way I need - split the input string and return it so the unfinished last item is the first in the list? I didn't manage to make it work, but I may be doing something wrong.

Upvotes: 5

Views: 3444

Answers (3)

Hanan Shteingart
Hanan Shteingart

Reputation: 9078

General purpose multi-completer code which supports all separators in the member DELIMITERS can be found in the code snip below. It seems easy but it was very annoying to debug due to very bad documentation on the pyQt side.

class CustomCompleter(QtGui.QCompleter):
    DELIMITERS = r'[()\[\]*+-=/\\]'
    def __init__(self, parent=None):
        QtGui.QCompleter.__init__(self, parent)
    def pathFromIndex(self, index):
        path = QtGui.QCompleter.pathFromIndex(self, index)
        string = self.widget().text()
        split = re.split(self.DELIMITERS, string)[-1]
        if len(split)==len(string):
            string_without_split = ''
        else:
            if len(split)>0:
                string_without_split = string[:-len(split)]
            else:
                string_without_split = string
        return string_without_split+path

    def splitPath(self, path):
        split = re.split(self.DELIMITERS, path)[-1]
        return [split]

Upvotes: 0

Scott
Scott

Reputation: 61

Here is another way of doing it that I think is more in line with the original question. No need for a complex data model, uses a simple QStringListModel instead.

import sys
from PyQt4 import QtCore, QtGui

class test(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        model = QtGui.QStringListModel()
        wordList = ['John Doe','Jane Doe','Albert Einstein', 'Alfred E Newman']
        model.setStringList(wordList)

        layout = QtGui.QVBoxLayout(self)
        self.line = QtGui.QLineEdit(self)
        layout.addWidget(self.line)

        complete = CustomCompleter(self)
        complete.setModel(model)
        complete.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        complete.setCompletionMode(0)
        complete.setWrapAround(False)

        self.line.setCompleter(complete)


class CustomCompleter(QtGui.QCompleter):
    def __init__(self, parent=None):
        QtGui.QCompleter.__init__(self, parent)

    def pathFromIndex(self, index):
        path = QtGui.QCompleter.pathFromIndex(self, index)

        lst = str(self.widget().text()).split(',')
        if len(lst) > 1:
            path = '%s, %s' % (','.join(lst[:-1]), path)

        return path

    def splitPath(self, path):
        path = str(path.split(',')[-1]).lstrip(' ')
        return [path]

#===============================================================================
# Unit Testing
#===============================================================================
if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = test()
    window.show()
    sys.exit(app.exec_())

Upvotes: 6

Live
Live

Reputation: 2001

From what I understand from your question and the doc, you could separate the user-inputted string with commas and make your completer check in your model for a completion.

BUT, after each comma, the index of your model (figure it like a two-dimension array of string) will be incremented.

For example, if you have the following input:

ABCD, EFGH, IJ

and you would like to the completer to finish IJ KL, you would have to have a model that is at least 3 indexes wide because the first text (ABCD) would be completed with the strings in the first column, EFGH would be completed with the second column of your model, etc.

So, I don't know if it could be used in your application.

Best of luck.

Upvotes: 1

Related Questions