Merge lp:~dylanmccall/update-manager/refactored-cellareapackage into lp:update-manager

Proposed by Dylan McCall
Status: Merged
Approved by: Barry Warsaw
Approved revision: 2589
Merged at revision: 2588
Proposed branch: lp:~dylanmccall/update-manager/refactored-cellareapackage
Merge into: lp:update-manager
Diff against target: 142 lines (+63/-49)
1 file modified
UpdateManager/UpdatesAvailable.py (+63/-49)
To merge this branch: bzr merge lp:~dylanmccall/update-manager/refactored-cellareapackage
Reviewer Review Type Date Requested Status
Barry Warsaw (community) Approve
Review via email: mp+145040@code.launchpad.net

Description of the change

While playing with the package column (and pkg_area) in UpdatesAvailable.py, I noticed I was needing to perform shotgun surgery in order to make some small changes: there was a bunch of code in CellAreaPackage that depended on specifics of UpdatesAvailable's tree view. This branch contains a more generalized CellAreaPackage. It isn't exactly _portable_ at this stage, but I think it's a step in the right direction. The assumptions it continues to make are documented, and innocent changes in other parts of the program are less likely to break it. The output should be identical to the existing cell area.

To post a comment you must log in.
2589. By Dylan McCall

In CellAreaPackage, fixed indent for cells at depth 3 to be consistent with current results.

Revision history for this message
Barry Warsaw (barry) wrote :

A few comments:

Line 51: s/not cell_number in/cell_number not in/

Line 104: I factored out the "len(cells) - 1" into a local variable outside the loop for readability and (possibly) improved performance.

Lines 105-108 can be better written as:
    cell_size = self.cached_cell_size.get(cell_number, 0)

Line 110: Removed unnecessary parens.

I'll fix those and sponsor this into trunk (and upload) along with your LP: #1105363 fix.

review: Approve
Revision history for this message
Dylan McCall (dylanmccall) wrote :

Great! Thanks, Barry :)
(Somehow got all this way without noticing dict.get can return a default value. Exciting!)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UpdateManager/UpdatesAvailable.py'
2--- UpdateManager/UpdatesAvailable.py 2013-01-25 15:41:59 +0000
3+++ UpdateManager/UpdatesAvailable.py 2013-01-25 23:21:21 +0000
4@@ -91,75 +91,89 @@
5 class CellAreaPackage(Gtk.CellAreaBox):
6 """This CellArea lays our package cells side by side, without allocating
7 width for a cell if it isn't present (like icons for header labels).
8+ We assume that the last cell should be expanded to fill remaining space,
9+ and other cells have a fixed width.
10 """
11
12 def __init__(self, indent_toplevel=False):
13 Gtk.CellAreaBox.__init__(self)
14 self.indent_toplevel = indent_toplevel
15 self.column = None
16- self.toggle_size = None
17- self.pixbuf_size = None
18- self.cached_cell_start = {}
19+ self.cached_cell_size = {}
20
21 def do_foreach_alloc(self, context, widget, cell_area_in, bg_area_in,
22 callback):
23- # First, gather cell renderers and make sure they are what we expect
24 cells = []
25 def gather(cell, data):
26 cells.append(cell)
27 self.foreach(gather, None)
28- if (len(cells) != 3 or
29- not isinstance(cells[0], Gtk.CellRendererToggle) or
30- not isinstance(cells[1], Gtk.CellRendererPixbuf) or
31- not isinstance(cells[2], Gtk.CellRendererText)):
32- return
33- toggle = cells[0]
34- pixbuf = cells[1]
35- text = cells[2]
36-
37- # Now just grab some size info
38+
39+ cell_is_hidden = {}
40+
41+ # Record the space required by each cell
42+ for cell_number, cell in enumerate(cells):
43+ # Detect if this cell should be allocated space
44+ if isinstance(cell, Gtk.CellRendererPixbuf):
45+ gicon = cell.get_property("gicon")
46+ hide_cell = gicon is None
47+ else:
48+ hide_cell = False
49+ cell_is_hidden[cell_number] = hide_cell
50+
51+ if not hide_cell and not cell_number in self.cached_cell_size:
52+ min_size, natural_size = cell.get_preferred_width(widget)
53+ self.cached_cell_size[cell_number] = natural_size
54+
55 cell_area = cell_area_in.copy()
56 bg_area = bg_area_in.copy()
57 spacing = self.get_property("spacing")
58- gicon = pixbuf.get_property("gicon")
59 cell_start = self.get_cell_start(widget)
60 orig_end = cell_area.width + cell_area.x
61- if self.toggle_size is None:
62- toggle_min, self.toggle_size = toggle.get_preferred_width(widget)
63- if gicon and self.pixbuf_size is None:
64- pixbuf_min, self.pixbuf_size = pixbuf.get_preferred_width(widget)
65-
66- # And finally, start handling each cell
67-
68 cur_path = self.get_current_path_string()
69 depth = Gtk.TreePath.new_from_string(cur_path).get_depth()
70- if gicon is not None and self.indent_toplevel:
71- # if not a header, align with header rows
72- depth = depth + 1
73- if depth == 1:
74- cell_area.x = cell_start
75- elif depth == 2:
76- cell_area.x = cell_start + self.toggle_size + spacing
77- elif depth == 3:
78- # Oddly, cells don't line up if we simply use spacing * 2
79- cell_area.x = cell_start + self.toggle_size * 2 + spacing + 1
80- cell_area.width = self.toggle_size
81- if callback(cells[0], cell_area.copy(), bg_area.copy()):
82- return
83-
84- cell_area.x = cell_area.x + cell_area.width + spacing
85- if gicon is None:
86- cell_area.width = 0
87- else:
88- cell_area.width = self.pixbuf_size
89- if callback(cells[1], cell_area.copy(), bg_area.copy()):
90- return
91-
92- if gicon is not None:
93- cell_area.x = cell_area.x + cell_area.width + spacing
94- cell_area.width = orig_end - cell_area.x
95- if callback(cells[2], cell_area.copy(), bg_area.copy()):
96- return
97+
98+ # And finally, start handling each cell
99+ extra_cell_width = 0
100+ cell_area.x = cell_start
101+ cell_area.width = 0
102+
103+ for cell_number, cell in enumerate(cells):
104+ is_last_cell = cell_number == len(cells)-1
105+ if cell_number in self.cached_cell_size:
106+ cell_size = self.cached_cell_size[cell_number]
107+ else:
108+ cell_size = 0
109+
110+ if (cell_area.width > 0 and extra_cell_width == 0):
111+ cell_area.x += cell_area.width + spacing
112+
113+ if cell_number == 0:
114+ # The first cell is affected by its depth in the tree
115+ if not cell_is_hidden[1] and self.indent_toplevel:
116+ # if not a header, align with header rows
117+ depth += 1
118+ if depth > 1:
119+ indent = max(0, depth - 1)
120+ indent_size = cell_size * indent
121+ if depth == 2:
122+ indent_extra = spacing
123+ elif depth == 3:
124+ indent_extra = spacing + 1
125+ else:
126+ indent_extra = spacing * indent
127+ cell_area.x += indent_size + indent_extra
128+
129+ if is_last_cell:
130+ cell_size = max(cell_size, orig_end - cell_area.x)
131+ if not cell_is_hidden[cell_number]:
132+ cell_area.width = cell_size + extra_cell_width
133+ extra_cell_width = 0
134+ else:
135+ cell_area.width = 0
136+ extra_cell_width = cell_size + spacing
137+
138+ if callback(cell, cell_area.copy(), bg_area.copy()):
139+ return
140
141 def do_event(self, context, widget, event, cell_area, flags):
142 # This override is just to trick our parent implementation into

Subscribers

People subscribed via source and target branches

to status/vote changes: