[PyQt] Performance problems with QSortFilterProxyModel

Mark Summerfield list at qtrac.plus.com
Thu May 13 11:01:17 BST 2010


On 2010-05-12, Steve Borho wrote:
> On Wed, May 12, 2010 at 1:04 AM, Mark Summerfield <list at qtrac.plus.com> 
wrote:
> > On 2010-05-12, Steve Borho wrote:
> >> Hello,
> >>
> >> The TortoiseHg project is currently porting all of our PyGTK apps to
> >> PyQt, This has been going pretty well so far, but I've hit a snag with
> >> our file status browser.
> >>
> >> I have a simple QAbstractTableModel (4 columns) being displayed in a
> >> QTreeView.  After connecting a QSortFilterProxyModel between the tree
> >> view and the data model, reloading the model became very expensive for
> >> moderately sized data sets.  After calling setSourceModel() with a
> >> model of 555 rows, I counted over 3 million calls to the model data()
> >> method, which takes about 15 seconds.
> >
> > Have you tried switching off sorting just before resetting the model and
> > then switching it back on afterwards?
> 
> I just tried with this:
> 
>   tm = MyTableModel(data)
>   tv.setSortingEnabled(False)
>   proxy.setSourceModel(tm)
>   tv.setSortingEnabled(True)
> 
> But it made no performance difference.

Then maybe no sorting took place?

When you call QAbstractTableView.setSortingEnabled(True), Qt is supposed
to call QAbstractTableView.sortByColumn() to perform the sort. But
sortByColumn() will only have an effect if the model is sortable, that
is, if the QAbsractItemModel you're using has reimplemented the sort()
method (since the base class version does nothing).

Things are slightly different if you use a QSortFilterProxyModel of
course, since that provides an implementation of
QAbsractItemModel.sort(). So in the example you've shown the proxy
should do the sorting.

But I guess you're saying "yes it sorted---but it was just as slow"?

However, you don't mention where the model gets set on the view? Does
this make a difference:

    # tv has no model at this point
    tm = MyTableModel(data)
    tv.setSortingEnabled(False)
    proxy.setSourceModel(tm)
    tv.setModel(proxy) # now tv has a model
    tv.setSortingEnabled(True)
 
Using QSortFilterProxyModel can adversely affect performance. So one
solution is to try to avoid using it, i.e., by reimplementing the sort()
method in your custom QAbstractTableModel. Another solution is to get
the correct ordering without sorting at all by using intrinsically
ordered data structures.

-- 
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
    C++, Python, Qt, PyQt - training and consultancy
        "C++ GUI Programming with Qt 4" - ISBN 0132354160


More information about the PyQt mailing list