Merge lp:~garyvdm/bzr-explorer/better_tree_filter into lp:bzr-explorer

Proposed by Gary van der Merwe
Status: Merged
Merged at revision: 481
Proposed branch: lp:~garyvdm/bzr-explorer/better_tree_filter
Merge into: lp:bzr-explorer
Diff against target: 146 lines (+36/-76)
2 files modified
lib/commands.py (+8/-0)
lib/wt_browser.py (+28/-76)
To merge this branch: bzr merge lp:~garyvdm/bzr-explorer/better_tree_filter
Reviewer Review Type Date Requested Status
Bazaar Explorer Developers Pending
Review via email: mp+20519@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Gary van der Merwe (garyvdm) wrote :

This makes the _QBrowseFilterProxyModel better use TreeFilterProxyModel. This makes the code simpler, and faster.

I've also make the auto expand more intelligent.

Unfortunately when I did this, I discovered that TreeFilterProxyModel is not as extendible as I thought. So I have made some improvements to TreeFilterProxyModel in qbzr. In order to be compatible with older versions of qbzr, I've duplicated some of the qbzr code into BE. Once we don't have to support qbzr 0.18, we can remove this.

457. By Gary van der Merwe <garyvdm@pinkies>

Update filter_id so that it is compatable with the latest version of qbzr.

Revision history for this message
Gary van der Merwe (garyvdm) wrote :

bialix: Sorry - I just missed you on irc.

bialix> GaryvdM: maybe I simply should dogfood your bzr-explorer patch? I'm not
bialix> really wise to easily review your changes

I would just like a second set of eyes on it. I don't contrubite a lot to
explorer, so there may be some things that I am un aware of. Any way, it makes
seens from the qbzr TreeWidget point of view.

bialix> about duplication: maybe it's worth to require in explorer trunk
bialix> compatibility with newer qbzr? and keep explorer 1.0.x as compatible
bialix> with qbzr 0.18?

I would be happy with that. I'll prepair a patch for this.

Revision history for this message
Gary van der Merwe (garyvdm) wrote :

P.s. If you want to look at the code with out the duplication, pull rev 456.1.1 (revid:garyvdm@pinkies-20100317191428-0ylldclj4cu9pdn)

I'm looking at checking for a minimum qbzr version.

458. By Gary van der Merwe

Require qbzr 0.19

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/commands.py'
2--- lib/commands.py 2010-03-07 04:51:24 +0000
3+++ lib/commands.py 2010-08-09 14:56:47 +0000
4@@ -133,6 +133,14 @@
5
6 def run(self, location=None, hat=None, dry_run=False,
7 desktop=None, zzz=False, experimental=False, screenshots=False):
8+
9+ required_qbzr_version = (0, 19)
10+ from bzrlib.plugins import qbzr
11+ if qbzr.version_info < required_qbzr_version:
12+ from bzrlib.errors import IncompatibleAPI
13+ raise IncompatibleAPI(qbzr, required_qbzr_version,
14+ qbzr.version_info, qbzr.version_info)
15+
16 from bzrlib.plugins.qbzr.lib import uifactory
17 _init_explorer_command(zzz, experimental)
18
19
20=== modified file 'lib/wt_browser.py'
21--- lib/wt_browser.py 2010-02-15 12:41:51 +0000
22+++ lib/wt_browser.py 2010-08-09 14:56:47 +0000
23@@ -591,85 +591,25 @@
24 def __init__(self, *args):
25 treewidget.TreeFilterProxyModel.__init__(self, *args)
26 self.text_to_match = None
27- self._interesting = None
28- self._all_data_loaded = False
29- self._text_match_count = 0
30
31 def setTextToMatch(self, text):
32 self.text_to_match = text
33- self._update_interesting()
34 self.invalidateFilter()
35
36- def _update_interesting(self):
37- if not self.text_to_match:
38- self._interesting = None
39- return
40- text = self.text_to_match
41- interesting = set([''])
42- directories = set()
43- for path in self._iter_paths():
44- if path.find(text) >= 0:
45- interesting.add(path)
46- directories.update(parent_directories(path))
47- self._text_match_count = len(interesting)
48- interesting.update(directories)
49- #print "\ninteresting for %s ...\n%s\n" % (text,
50- # "\n".join(sorted(interesting)))
51- self._interesting = interesting
52-
53- def _iter_paths(self):
54- # The source model loads data lazily. We need everything loaded
55- # to find the complete set of paths though
56- self._ensure_all_data_loaded()
57- return iter(self.source_model.inventory_data_by_path.keys())
58-
59- def _ensure_all_data_loaded(self):
60- if self._all_data_loaded:
61- return
62- model = self.source_model
63- for id in range(0, len(model.inventory_data)):
64- self._load_dirs(model, id)
65- self._all_data_loaded = True
66-
67- def _load_dirs(self, model, id):
68- item_data = model.inventory_data[id]
69- if item_data.item.kind == "directory":
70- if item_data.children_ids is None:
71- # This locks and unlocks the tree each time.
72- # I wonder how that impacts performance?
73- model.load_dir(id)
74- for child_id in item_data.children_ids:
75- self._load_dirs(model, child_id)
76-
77- def filterAcceptsRow(self, source_row, source_parent):
78- result = treewidget.TreeFilterProxyModel.filterAcceptsRow(
79- self, source_row, source_parent)
80- if result and self._interesting:
81- # Apply the text filter (matches found earlier)
82- path, kind = self._get_path_info(source_row, source_parent)
83- result = path in self._interesting
84- return result
85-
86- def _get_path_info(self, source_row, source_parent):
87- """Return path, kind for a model item."""
88- model = self.source_model
89- parent_id = source_parent.internalId()
90- children_ids = model.inventory_data[parent_id].children_ids
91- # Why is this check required?
92- if len(children_ids) <= source_row:
93- return None, None
94- id = children_ids[source_row]
95- data = model.inventory_data[id]
96- return data.path, data.item.kind
97-
98- def text_match_count(self):
99- """Number of items matching text or 0 if unknown.
100-
101- Note: The number is across the WHOLE tree, not just those displayed
102- after applying the combined filtering.
103+ def filter_id(self, id, item_data):
104+ """Determines wether a item should be displayed.
105+ Returns :
106+ * True: Show the item
107+ * False: Donot show the item
108+ * None: Show the item if there are any children that are visible.
109 """
110- return self._text_match_count
111-
112+ show = treewidget.TreeFilterProxyModel.filter_id(self, id, item_data)
113+ if self.text_to_match and show:
114+ if item_data.path.find(self.text_to_match) >=1:
115+ return True
116+ else:
117+ return None
118+ return show
119
120 class _QBrowseTreeWidget(treewidget.TreeWidget):
121 """Subclass the standard QBzr TreeWidget to patch in more features.
122@@ -781,9 +721,21 @@
123 # Automatically expand the tree if the match count is small.
124 # The number could be configurable one day provided the doc
125 # was very clear about potential vs actual match counts
126- matches = self._tree_viewer.tree_filter_model.text_match_count()
127- if matches <= 10:
128- self._tree_viewer.expandAll()
129+ parents = [QtCore.QModelIndex()] # start at the root
130+ next_parents = []
131+ expanded = 0
132+ while parents and expanded <= 15:
133+ for parent in parents:
134+ matches = self._tree_viewer.tree_filter_model.rowCount(parent)
135+ if matches and matches <= 5:
136+ self._tree_viewer.expand(parent)
137+ if (self._tree_viewer.isExpanded(parent) or
138+ parent == QtCore.QModelIndex()):
139+ expanded += matches
140+ for i in range(matches):
141+ next_parents.append(
142+ self._tree_viewer.tree_filter_model.index(i, 0, parent))
143+ parents = next_parents
144 # Reset our memory wrt what's expanded. This is perhaps a little
145 # heavy handed wrt text matching as that isn't remembered across
146 # tree switches. (Then again, perhaps it should be.)

Subscribers

People subscribed via source and target branches