<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 12 (filtered medium)">
<style>
<!--
 /* Font Definitions */
 @font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
        {mso-style-priority:99;
        mso-style-link:"Balloon Text Char";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.Section1
        {page:Section1;}
-->
</style>

</head>

<body lang="EN-CA" link="blue" vlink="purple">

<div class="Section1">

<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">

<p class="MsoNormal"><b><span lang="EN-US" style="font-size:10.0pt;font-family:
&quot;Tahoma&quot;,&quot;sans-serif&quot;">From:</span></b><span lang="EN-US" style="font-size:10.0pt;
font-family:&quot;Tahoma&quot;,&quot;sans-serif&quot;"> Bjorn Egil Ludvigsen
[mailto:<a href="mailto:bludvigsen@gmail.com">bludvigsen@gmail.com</a>] <br>
<b>Sent:</b> April-09-10 11:36 AM<br>
<b>To:</b> Darryl Wallace<br>
<b>Cc:</b> <a href="mailto:pyqt@riverbankcomputing.com">pyqt@riverbankcomputing.com</a><br>
<b>Subject:</b> Re: [PyQt] Fast selection of non-contiguous items in QTreeview</span></p>

</div>

<p class="MsoNormal"> </p>

<div>

<p class="MsoNormal">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&#39;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?</p>

</div>

<div>

<p class="MsoNormal"> </p>

</div>

<div>

<p class="MsoNormal">Regards,</p>

</div>

<div>

<p class="MsoNormal" style="margin-bottom:12.0pt">Bjorn</p>

<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;
font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D"> </span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">Hello Bjorn,</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">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.</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;"> </span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">Here’s my example.</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D"> </span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">def searchAndSelect(self,
searchString, column=0):</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">    #If the
user searches for nothing, then return and do nothing</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">    if
len(searchString)==0:</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
return</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">   </span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">   
self.obsTreeView.clearSelection()</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">    #get the
selection model from the view</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">   
selectionModel=self.obsTreeView.selectionModel()</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">    </span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">   
indexes=self.obsTreeModel.match(self.obsTreeModel.index(0, column,
QtCore.QModelIndex()),</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">                                           
QtCore.Qt.DisplayRole, QtCore.QVariant(searchString), </span></p>

<p class="MsoNormalCxSpMiddle" style="mso-margin-top-alt:0cm;margin-right:0cm;
margin-bottom:12.0pt;margin-left:288.0pt"><span style="font-size:11.0pt;
font-family:&quot;Courier New&quot;"> -1,QtCore.Qt.MatchContains)</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">    if
len(indexes)&gt;0:</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
indexesToExclude=[]</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
itemSelection=QtGui.QItemSelection()</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
# Initialize topLeft as the first index.</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
topLeft=indexes[0]</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
bottomRight=None</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
for i in xrange(1, len(indexes)):</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">           
#if the difference between rows is &gt; 1</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">           
#This means that there is a break in the range.</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">           
if indexes[i].row()-indexes[i-1].row()&gt;1:</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">               
# Set the bottomRight value to the previous index.</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">               
bottomRight=indexes[i-1]</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">               
itemSelection.select(topLeft, bottomRight)</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">               
# Set the topLeft as the current Index.</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">               
topLeft=indexes[i]</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
# make sure to select the last bunch</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">     
  bottomRight=indexes[-1]           
</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
itemSelection.select(topLeft, bottomRight)</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">               
</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
selectionModel.select(itemSelection, </span></p>

<p class="MsoNormalCxSpMiddle" style="mso-margin-top-alt:0cm;margin-right:0cm;
margin-bottom:12.0pt;margin-left:180.0pt"><span style="font-size:11.0pt;
font-family:&quot;Courier New&quot;">   QtGui.QItemSelectionModel.Select |
QtGui.QItemSelectionModel.Rows)    </span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">       
self.obsTreeView.scrollTo(indexes[0], QtGui.QAbstractItemView.PositionAtTop)</span></p>

<p class="MsoNormalCxSpMiddle" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">#searchAndSelect</span></p>

<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;
font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D"> </span></p>

<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt;
font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;;color:#1F497D"> </span></p>

</div>

<div>

<p class="MsoNormal">On Thu, Apr 8, 2010 at 3:14 PM, Darryl Wallace &lt;<a href="mailto:darryl.wallace@prosensus.ca">darryl.wallace@prosensus.ca</a>&gt;
wrote:</p>

<div>

<div>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;">Here’s an example of
the code:</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:11.0pt;font-family:&quot;Courier New&quot;"> </span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">def searchAndSelect(self,
searchString, column=0):</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    #If the
user searches for nothing, then return and do nothing</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    if
len(searchString)==0:</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">       
return</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;"> </span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    #get the
selection model from the tree view</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">   
selectionModel=self.obsTreeView.selectionModel()</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">  </span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    # Find
the items in the model.</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    #
obsTreeModel is a QStandardItemModel</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    # This
part is very fast </span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">   
items=self.obsTreeModel.findItems(searchString, QtCore.Qt.MatchContains,
column)</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    </span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    #select
each item</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    # This
part is very slow.</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">    for item
in items:</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">       
selectionModel.select(item.index(), selectionModel.Select|selectionModel.Rows)</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">#searchAndSelect</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;"> </span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">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.</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;"> </span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;">Thanks,<br>
Darryl</span></b></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D"> </span></p>

<div>

<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><b><span lang="EN-US" style="font-size:10.0pt">From:</span></b><span lang="EN-US" style="font-size:10.0pt"> Darryl Wallace [mailto:<a href="mailto:darryl.wallace@prosensus.ca" target="_blank">darryl.wallace@prosensus.ca</a>]
<br>
<b>Sent:</b> April-08-10 2:23 PM<br>
<b>To:</b> &#39;<a href="mailto:pyqt@riverbankcomputing.com" target="_blank">pyqt@riverbankcomputing.com</a>&#39;<br>
<b>Subject:</b> Fast selection of non-contiguous items in QTreeview</span></p>

</div>

</div>

<div>

<div>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> </p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D">Hello,</span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D"> </span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D">I’ve done some reading and
can’t find anything on non-contiguous selection of items in item views
beyond : </span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D"> </span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D">“Selections are made up of <i>selection
ranges</i>. 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.” - </span><a href="http://doc.trolltech.com/4.6/model-view-selection.html#concepts" target="_blank">http://doc.trolltech.com/4.6/model-view-selection.html#concepts</a></p>


<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D"> </span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D">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.</span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D"> </span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D">Any ideas?</span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D"> </span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D">Thanks,</span></p>

<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;color:#1F497D">Darryl</span></p>

</div>

</div>

</div>

</div>

<p class="MsoNormal"><br>
_______________________________________________<br>
PyQt mailing list    <a href="mailto:PyQt@riverbankcomputing.com">PyQt@riverbankcomputing.com</a><br>
<a href="http://www.riverbankcomputing.com/mailman/listinfo/pyqt" target="_blank">http://www.riverbankcomputing.com/mailman/listinfo/pyqt</a></p>

</div>

<p class="MsoNormal"> </p>

</div>

</body>

</html>