Search code examples
pythonqtqabstracttablemodelqcompleter

Using a QCompleter in a QTableView with Qt and Python


I'm reading up on how to make my QAbstractTableModel editable, and it looks pretty straightforward.

But how do I set up an editable cell to use a QCompleter? I take it somehow I have to tell the QTableView to use a QLineEdit widget? How can I do this?


edit: hmm, I guess it has something with QTableView.setItemDelegateForColumn() but I don't know anything about delegates or how to use them.


edit: I tried RobbieE's solution, got something that sort of works but it gets the geometry of the popup combo box wrong and crashes Python when I press Enter.

class CompleterDelegate(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None, completerSetupFunction=None):
        super(CompleterDelegate, self).__init__(parent)
        self._completerSetupFunction = completerSetupFunction
    def createEditor(self, parent, option, index):
        return QtGui.QLineEdit(parent)
    def setEditorData(self, editor, index):
        super(CompleterDelegate, self).setEditorData(editor, index)
        self._completerSetupFunction(editor, index)

My _completerSetupFunction looks something like this:

def setupFunc(editor, index):
    completer = MyCompleter(editor)
    completer.setCompletionColumn(0)
    completer.setCompletionRole(QtCore.Qt.DisplayRole)
    completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)    
    editor.setCompleter(completer)
    completer.setModel(myAbstractItemModel)

Solution

  • Per RobbieE's suggestion, I subclassed QStyledItemDelegate. But the correct place to apply the completer is when the editor is created, not setEditorData.

    class CompleterDelegate(QtGui.QStyledItemDelegate):
        def __init__(self, parent=None, completerSetupFunction=None):
            super(CompleterDelegate, self).__init__(parent)
            self._completerSetupFunction = completerSetupFunction
        def createEditor(self, parent, option, index):
            editor = QtGui.QLineEdit(parent)
            self._completerSetupFunction(editor, index)
            return editor
    

    and then I use a completerSetupFunction that basically looks like this:

    def _completerSetupFunction(editor, index):
        print "completer setup: editor=%s, index=%s" % (editor, index)
        completer = QtGui.QCompleter(base_items, editor)
        completer.setCompletionColumn(0)
        completer.setCompletionRole(QtCore.Qt.EditRole)
        completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        try:    
            editor.setCompleter(completer)            
        except:
            pass
    

    Here's a complete example as a github gist.