[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