[PyQt] Just for fun: QCompleter accessing a QListWidget's internal model through a proxy ?
Hi everyone, After many moons of lurking I have finally subscribed to ask for advice about my current challenge: In this app I'm working on (my first real, non-trivial one, admittedly), I have a number of QListWidgets in the main window, holding plain strings, each with an associated QLineEdit for input. They work just fine, and there really is no need for anything more elaborate than list widgets for what they do. Only now that it's almost finished, with everything in place and the code working well, I just discovered the existence of QCompleters by accident... and obviously now I want them in the line edits. However, QCompleters are designed to work only with real models, not convenience widgets. Of course it's very easy to use them with a plain QStringList, but it feels somewhat clunky and inefficient to duplicate the list widget's content to the completer's string list, refreshing it each time that content changes... and I don't really feel like retooling the entire UI to use QListViews just for the sake of completers. So I thought, perhaps naively, that it might be possible to build a kind of proxy model, that would feed a completer with data pulled from a list widget's hidden, internal model. After quite some time trying to make sense of the Qt docs (which seem to contradict themselves sometimes), I settled on the following : - make the model a subclass of QAbstractListModel; - reimplement the rowCount(), data() and index() methods as required, to fetch the relevant data from the list widget (passed as a parameter to the constructor). Here is the entire model code : class proxyModel(QAbstractListModel): def __init__(self, qlwi, parent=None): QAbstractListModel.__init__(self, parent) self.qlwi = qlwi def index (self, row, col = 0, parent = None): return self.qlwi.indexFromItem(self.qlwi.item(row)) def rowCount (self, parent = None): return self.qlwi.count() def data (self, index, role = Qt.DisplayRole): return self.qlwi.itemFromIndex(index).data(role) I have verified (with good old prints) that the three methods return the expected values and types (QModelIndex, int and QVariant), reflecting changes made to the list widget on the fly. Unfortunately, setting a completer's model to a proxyModel instance does exactly nothing: everything works just as before, without completion. Lacking a better understanding of the Qt internals, I'm at a loss as to which way I should dig now... I tried to Google for prior art, and found nothing relevant, which usually means one of two things : - the entire notion is stupid and impossible, for some fundamental reason that eludes me; - or else it is actually so trivial that no one has ever thought of documenting it, and I'm just missing something really obvious. Either way, I'd welcome suggestions and pointers to the what and why, hopefully learning something important about (Py)Qt in the process... Thanks in advance, fp ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Just for fun: QCompleter accessing a QListWidget's internal model through a proxy ?
On Tuesday 17 August 2010 11:23:55 fpp wrote: Hi everyone, After many moons of lurking I have finally subscribed to ask for advice about my current challenge: In this app I'm working on (my first real, non-trivial one, admittedly), I have a number of QListWidgets in the main window, holding plain strings, each with an associated QLineEdit for input. They work just fine, and there really is no need for anything more elaborate than list widgets for what they do. Only now that it's almost finished, with everything in place and the code working well, I just discovered the existence of QCompleters by accident... and obviously now I want them in the line edits. However, QCompleters are designed to work only with real models, not convenience widgets. Of course it's very easy to use them with a plain QStringList, but it feels somewhat clunky and inefficient to duplicate the list widget's content to the completer's string list, refreshing it each time that content changes... and I don't really feel like retooling the entire UI to use QListViews just for the sake of completers. So I thought, perhaps naively, that it might be possible to build a kind of proxy model, that would feed a completer with data pulled from a list widget's hidden, internal model. I could be overlooking something but I don't see why you can't use the list widget's model directly. The details of the implemenation may be private, but the QAbstractItemModel interface is still public and usable. Should be as simple as completer = QCompleter( listWidget.model(), parent ) Matt ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Just for fun: QCompleter accessing a QListWidget's internal model through a proxy ?
On Tue, Aug 17, 2010 at 9:25 PM, Matt Newell newe...@blur.com wrote: On Tuesday 17 August 2010 11:23:55 fpp wrote: So I thought, perhaps naively, that it might be possible to build a kind of proxy model, that would feed a completer with data pulled from a list widget's hidden, internal model. I could be overlooking something but I don't see why you can't use the list widget's model directly. The details of the implementation may be private, but the QAbstractItemModel interface is still public and usable. Should be as simple as completer = QCompleter( listWidget.model(), parent ) Indeed it is !... self.slaps_forehead() Wow, that was quick... so it was actually option #2 of my self-prediction: or else it is so trivial that no one has ever thought of documenting it, and I'm just missing something really obvious. ...which is good news. Just the usual result of my inability to parse the Qt docs, wrap my head around object models, and generally add two plus two. Thanks Matt ! fp ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt