[PyQt] Performance problems with QSortFilterProxyModel

Steve Borho steve at borho.org
Thu Jun 3 16:35:47 BST 2010

On Tue, May 11, 2010 at 8:33 PM, Steve Borho <steve at borho.org> 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.
> I googled around and found some complaints that
> resizeColumnToContents() was expensive when the sort filter was in
> use, and I confirmed that in our case  (using simple print profiling).
>  However, removing the resize statements only moves the performance
> hit till later on.  I can only guess the sort model is waiting for
> it's first access to perform the initial sort.
> I'm pretty sure I could implement the simple sorting and filtering we
> need in our data model, but before I do I thought I'd ask here if
> there was some common problem that could cause this performance hit.
> This kind of smells like the kind of problem caused by not disabling a
> signal while you do certain operations.

Another TortoiseHg developer has developed a patch that vastly
improved the performance of the proxy model sort.   It's still not as
fast has implementing the sort ourselves, so we'll not be going back
to it, but I thought I would post the fix here for posterity.  The
patch applies to our QAbstractTableModel derived class.

     def rowCount(self, parent):
+        if parent.isValid():
+            return 0 # no child
         return len(self.rows)

     def columnCount(self, parent):
+        if parent.isValid():
+            return 0 # no child
         return len(self.headers)

I hope that helps someone else.

Steve Borho

More information about the PyQt mailing list