Source

thg-qt-mq / mani-autoexpand.patch

# HG changeset patch
# User Angel Ezquerra <angel.ezquerra@gmail.com>
# Date 1344374954 -7200
# Node ID 07638e2f5444499048240ed38fa74c2c3c11b3e4
# Parent  c1718bb37efd902533495110b1b913e4daa7ee27
manifest: automatically expand the tree if the number of items is large, collapse it otherwise

Up until now, using the manifest file filter would not automatically expand the
manifest tree unless the clean files were not being shown. The result was that
many filter matches would be hidden by default, and the user had to expand the
correspoding tree folders to view them, with no way to expand them all.

The reason for this behavoir was that it is expensive to expand a tree when the
number of items is large.

This change makes it so that if the number of items in the tree is less than 40,
the tree will be automatically expanded. Otherwise the tree is automatically
collapsed.

In addition, it is possible to change this number of items limit, and whether
the tree is collapsed when the number of items is greater than that limit. In
order to do so, you can set the following configuration keys on the tortoisehg
section:

- manifest.autoexpand: Can be an integer or a boolean. Defaults to 40.
    - integer: The maximum number of items that causes the tree to be
    automatically expanded
    - boolean: if True, always expand the tree; if False, never expand it
    automatically
- manifest.autocollapse: A boolean. Defaults to True
    - if True, automatically collapse the tree when it is not automatically
    expanded.

diff --git a/tortoisehg/hgqt/manifestdialog.py b/tortoisehg/hgqt/manifestdialog.py
--- a/tortoisehg/hgqt/manifestdialog.py
+++ b/tortoisehg/hgqt/manifestdialog.py
@@ -260,6 +260,7 @@
         self._treemodel = ManifestModel(self._repo, self._rev,
                                         statusfilter=self._statusfilter.status(),
                                         parent=self)
+        self._treemodel.fileringCompleted.connect(self._autoexpandtree)
         self._treemodel.setNameFilter(self.le.text())
 
         oldmodel = self._treeview.model()
@@ -294,8 +295,33 @@
     @pyqtSlot()
     def _autoexpandtree(self):
         """expand file tree if the number of the items isn't large"""
-        if 'C' not in self._statusfilter.status():
+        model = self._treeview.model()
+        if model.numitems == 0:
+            return
+        # There may several conditions that may lead us to expand the tree
+        # Always expand if:
+        # 1. clean files are not being shown
+        expand = 'C' not in self._statusfilter.status()
+        if not expand:
+            # 2. an autoexpand limit has not been set and there
+            #    are not many files in the tree
+            # 3. an autoexpand limit has been set
+            #     This can be set as a number of items or as a boolean
+            try:
+                expandlimit = self._repo.ui.configint('tortoisehg',
+                    'manifest.autoexpand', 40)
+                expand = (model.numitems <= expandlimit)
+            except:
+                expand = self._repo.ui.configbool('tortoisehg',
+                    'manifest.autoexpand', False)
+        if expand:
             self._treeview.expandAll()
+        else:
+            collapse = self._repo.ui.configbool('tortoisehg',
+                'manifest.autocollapse', True)
+            if collapse:
+                self._treeview.collapseAll()
+
 
     def reload(self):
         # TODO
diff --git a/tortoisehg/hgqt/manifestmodel.py b/tortoisehg/hgqt/manifestmodel.py
--- a/tortoisehg/hgqt/manifestmodel.py
+++ b/tortoisehg/hgqt/manifestmodel.py
@@ -23,6 +23,7 @@
     Qt model to display a hg manifest, ie. the tree of files at a
     given revision. To be used with a QTreeView.
     """
+    fileringCompleted = pyqtSignal()
 
     StatusRole = Qt.UserRole + 1
     """Role for file change status"""
@@ -36,6 +37,7 @@
 
         self._diricon = QApplication.style().standardIcon(QStyle.SP_DirIcon)
         self._fileicon = QApplication.style().standardIcon(QStyle.SP_FileIcon)
+        self.numitems = 0
         self._repo = repo
         self._rev = rev
         self._subinfo = {}
@@ -232,6 +234,7 @@
             return
         self._namefilter = pattern
         self._rebuildrootentry()
+        self.fileringCompleted.emit()
 
     @property
     def nameFilter(self):
@@ -305,7 +308,9 @@
             """Add files to the tree according to their state"""
             if self._namefilter:
                 files = fnmatch.filter(files, '*%s*' % self._namefilter)
+            numfiles = 0
             for path in files:
+                numfiles += 1
                 if not pathinstatus(path, status, uncleanpaths):
                     continue
 
@@ -324,9 +329,11 @@
                         break
                 else:
                     e.setstatus('C')
+            return numfiles
 
         # Add subrepos to the tree
         def addrepocontentstotree(roote, ctx, toproot=''):
+            numitems = 0
             subpaths = ctx.substate.keys()
             for path in subpaths:
                 if not 'S' in self._statusfilter:
@@ -374,20 +381,22 @@
                             self._subinfo[toprelpath]['ctx'] = sctx
 
                             # Add the subrepo contents to the tree
-                            e = addrepocontentstotree(e, sctx, toprelpath)
+                            e, numitemsinsub = \
+                                addrepocontentstotree(e, sctx, toprelpath)
+                            numitems += numitemsinsub
 
             # Add regular files to the tree
             status, uncleanpaths, files = getctxtreeinfo(ctx)
 
-            addfilestotree(roote, files, status, uncleanpaths)
-            return roote
+            numitems += addfilestotree(roote, files, status, uncleanpaths)
+            return roote, numitems
 
         # Clear the _subinfo
         self._subinfo = {}
         roote = _Entry()
         ctx = self._repo[self._rev]
 
-        addrepocontentstotree(roote, ctx)
+        e, self.numitems = addrepocontentstotree(roote, ctx)
         roote.sort()
         return roote
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.