title: How can I efficiently expand an entire subtree of a QTreeView?
body: <p>EDIT: it turns out that the root performance problem was a size-to-fit function attached to the expanded() signal, so I'm going to accept the first answer and delete this question for being misleading.</p>
  
  <p>Note: I'm asking this question so I can provide an answer for it (and maybe get a better answer). The solution is not intuitive.</p>
  
  <p>MacOS builds of Qt may have a way for the user to expand an entire QTreeView subtree (there was an open bug for it) but non-MacOS builds definitely do not. I am trying to implement the behavior "shift-click on the item decoration expands the entire subtree".</p>
  
  <p>There are two problems. The easier of the two is detecting a shift-click on the decoration. I do this by intercepting the expanded/collapsed signals; they check some "global" state set up by the mousePressEvent:</p>
  
  <pre><code># similar implementation for _on_expanded
  @pyqtSlot(QModelIndex)
  def _on_collapsed(self, index):
      if self._in_shift_press:
          self._in_shift_press = False
          _recursive_set_expanded(self, index, False)
  
  def mousePressEvent(self, evt):
      # Make shift-click expand/collapse all
      if int(evt.modifiers() &amp; Qt.ShiftModifier) != 0:
          self._in_shift_press = True
      try:
          QTreeView.mousePressEvent(self, evt)
      finally:
          self._in_shift_press = False
  </code></pre>
  
  <p>This is a little ugly, but it works well enough.</p>
  
  <p>The harder problem is implementing _recursive_set_expanded(view, root, state). A recursive collapse is very quick. However, the obvious implementation of calling view.setExpanded(True) on all descendents of an index is very very slow -- multiple seconds for ~100 indices. The problem is not an expensive data model, since view.expandAll() is very fast.</p>
  
  <p>Some source diving shows that expandAll() does significantly less work than expand(). However, the Qt API doesn't expose an expandSubtree() method. How can this be made fast, short of digging into the private implementation?</p>