[PyQt] Fast selection of non-contiguous items in QTreeview

Darryl Wallace darryl.wallace at prosensus.ca
Fri Apr 9 19:02:34 BST 2010


*From:* Bjorn Egil Ludvigsen [mailto:bludvigsen at gmail.com]
*Sent:* April-09-10 11:36 AM
*To:* Darryl Wallace
*Cc:* pyqt at riverbankcomputing.com
*Subject:* Re: [PyQt] Fast selection of non-contiguous items in QTreeview



I am planning similar things and will run into the same issue as you I
suspect. My benchmark will be a table model with up to 1 million rows. Each
of the rows may have 1,000 items (columns) and I need filter features to
select rows (numerical simulations). Related to this and Darryl's question,
would someone like to comment in general on the feasibility of using PyQt
for such large table models (or tree models etc.) and the maximum
responsiveness one can achieve?



Regards,

Bjorn



Hello Bjorn,

I achieved some major improvements by using QItemSelection and looping
through the selected indexes and building ranges.  It’s much faster to build
the QItemSelection object then it is to select individual items.



Here’s my example.



def searchAndSelect(self, searchString, column=0):

    #If the user searches for nothing, then return and do nothing

    if len(searchString)==0:

        return



    self.obsTreeView.clearSelection()

    #get the selection model from the view

    selectionModel=self.obsTreeView.selectionModel()



    indexes=self.obsTreeModel.match(self.obsTreeModel.index(0, column,
QtCore.QModelIndex()),

                                            QtCore.Qt.DisplayRole,
QtCore.QVariant(searchString),

 -1,QtCore.Qt.MatchContains)

    if len(indexes)>0:

        indexesToExclude=[]

        itemSelection=QtGui.QItemSelection()

        # Initialize topLeft as the first index.

        topLeft=indexes[0]

        bottomRight=None

        for i in xrange(1, len(indexes)):

            #if the difference between rows is > 1

            #This means that there is a break in the range.

            if indexes[i].row()-indexes[i-1].row()>1:

                # Set the bottomRight value to the previous index.

                bottomRight=indexes[i-1]

                itemSelection.select(topLeft, bottomRight)

                # Set the topLeft as the current Index.

                topLeft=indexes[i]

        # make sure to select the last bunch

        bottomRight=indexes[-1]

        itemSelection.select(topLeft, bottomRight)



        selectionModel.select(itemSelection,

   QtGui.QItemSelectionModel.Select | QtGui.QItemSelectionModel.Rows)



        self.obsTreeView.scrollTo(indexes[0],
QtGui.QAbstractItemView.PositionAtTop)

#searchAndSelect





On Thu, Apr 8, 2010 at 3:14 PM, Darryl Wallace <darryl.wallace at prosensus.ca>
wrote:

*Here’s an example of the code:*

* *

*def searchAndSelect(self, searchString, column=0):*

*    #If the user searches for nothing, then return and do nothing*

*    if len(searchString)==0:*

*        return*

* *

*    #get the selection model from the tree view*

*    selectionModel=self.obsTreeView.selectionModel()*

*  *

*    # Find the items in the model.*

*    # obsTreeModel is a QStandardItemModel*

*    # This part is very fast *

*    items=self.obsTreeModel.findItems(searchString,
QtCore.Qt.MatchContains, column)*

*    *

*    #select each item*

*    # This part is very slow.*

*    for item in items:*

*        selectionModel.select(item.index(),
selectionModel.Select|selectionModel.Rows)*

*#searchAndSelect*

* *

*Does anyone have any tips on speeding up the selection part?  I’ve tried
blocking the signals of the selection model incase the selectionChanged
signal of QItemSelectionModel is causing a re-draw but it didn’t seem to
help.*

* *

*Thanks,
Darryl*



*From:* Darryl Wallace [mailto:darryl.wallace at prosensus.ca]
*Sent:* April-08-10 2:23 PM
*To:* 'pyqt at riverbankcomputing.com'
*Subject:* Fast selection of non-contiguous items in QTreeview



Hello,



I’ve done some reading and can’t find anything on non-contiguous selection
of items in item views beyond :



“Selections are made up of *selection ranges*. These efficiently maintain
information about large selections of items by recording only the starting
and ending model indexes for each range of selected items. Non-contiguous
selections of items are constructed by using more than one selection range
to describe the selection.” -
http://doc.trolltech.com/4.6/model-view-selection.html#concepts



Currently we have implemented a selection of items by scanning each row in
the model to see if it should be “selected” based on certain criteria.  Is
there a faster way to do this as looping in Python through a large (50,000
rows)?  When selections can be specified with selection ranges the selection
is fast.  However, our worst case scenario is that every-other item need be
selected: 25,000 selection ranges would be created and then we would just be
looping through everything again anyways.



Any ideas?



Thanks,

Darryl


_______________________________________________
PyQt mailing list    PyQt at riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20100409/64514978/attachment-0001.html>


More information about the PyQt mailing list