This file is indexed.

/usr/share/pyshared/sonata/breadcrumbs.py is in sonata 1.6.2.1-6.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env python

import gtk

class CrumbButton(gtk.ToggleButton):
	"""A ToggleButton tailored for use as a breadcrumb."""
	def __init__(self, image, label):
		gtk.ToggleButton.__init__(self)

		self.set_properties(can_focus=False, relief=gtk.RELIEF_NONE)

		# adapt gtk.Button internal layout code:
		hbox = gtk.HBox(spacing=2)
		align = gtk.Alignment(xalign=0.5, yalign=0.5)
		hbox.pack_start(image, False, False)
		hbox.pack_start(label, True, True)
		align.add(hbox)

		self.add(align)

class CrumbBox(gtk.Box):
	"""A box layout similar to gtk.HBox, but specifically for breadcrumbs.

	* Crumbs in the middle are replaced with an ellipsis if necessary.
	* The root, parent, and current element are always kept visible.
	* The root and parent are put in a condensed form if necessary.
	* The current element is truncated if necessary.
	"""
	__gtype_name__ = 'CrumbBox'
	def __init__(self, *args, **kwargs):
		gtk.Box.__init__(self, *args, **kwargs)

		# FIXME i can't get an internal child ellipsis to render...
#		gtk.widget_push_composite_child()
#		self.ellipsis = gtk.Label("...")
#		self.ellipsis.props.visible = True
#		gtk.widget_pop_composite_child()
#		self.ellipsis.set_parent(self)

	def do_size_request(self, requisition):
		"""This gets called to determine the size we request"""
#		ellipsis_req = self.ellipsis.size_request()
		reqs = [w.size_request() for w in self]

		# This would request "natural" size:
#		pad = 0 if not reqs else (len(reqs)-1)*self.props.spacing
#		requisition.width  = sum(    [r[0] for r in reqs]) + pad
#		requisition.height = max([0]+[r[1] for r in reqs])
#		return

		# Request "minimum" size:

		height = max([0]+[r[1] for r in reqs])

		if len(reqs) == 0: # empty
			width = 0 
		elif len(reqs) < 3: # current crumb
			width = height
		elif len(reqs) == 3: # parent and current
			width = height + height + self.props.spacing
		elif len(reqs) == 4: # root, parent and current
			width = height + height + height + 2*self.props.spacing
		elif len(reqs) > 4: # root, ellipsis, parent, current
			pad = 3*self.props.spacing
			width = height + reqs[1][0] + height + height + pad

		requisition.width = width
		requisition.height = height

	def _req_sum(self, reqs):
		pad = 0 if not reqs else (len(reqs)-1)*self.props.spacing
		return pad+sum([req[0] for req in reqs])

	def _condense(self, req, w):
# FIXME show and hide cause a fight in an infinite loop
#		try:
#			w.get_child().get_child().get_children()[1].hide()
#		except (AttributeError, IndexError):
#			pass
		wr, hr = req
		return (hr, hr) # XXX simplistic: set square size for now

	def _uncondense(self, w):
#		try:
#			w.get_child().get_child().get_children()[1].show()
#		except (AttributeError, IndexError):
			pass

	def _truncate(self, req, amount):
		wr, hr = req
		return (wr-amount, hr) # XXX this can be less than hr, even <0

	def do_size_allocate(self, allocation):
		"""This gets called to layout our child widgets"""
		x0, y0 = allocation.x, allocation.y
		w0, h0 = allocation.width, allocation.height

		crumbs = self.get_children()

		if len(crumbs) < 2:
			return

		# FIXME:
		self.ellipsis = crumbs.pop(1)
		hidden = [self.ellipsis]

		# Undo any earlier condensing
		if len(crumbs) > 0:
			self._uncondense(crumbs[0])
		if len(crumbs) > 1:
			self._uncondense(crumbs[-2])

		reqs = [w.get_child_requisition() for w in crumbs]

		# If necessary, condense the root crumb
		if self._req_sum(reqs) > w0 and len(crumbs) > 2:
			reqs[0] = self._condense(reqs[0], crumbs[0])
			
		# If necessary, replace an increasing amount of the
		# crumbs after the root with the ellipsis
		while self._req_sum(reqs) > w0:
			if self.ellipsis in hidden and len(crumbs) > 3:
				hidden = [crumbs.pop(1)]
				reqs.pop(1)
				crumbs.insert(1, self.ellipsis)
                                req = self.ellipsis.get_child_requisition()
				reqs.insert(1, req)
			elif self.ellipsis in crumbs and len(crumbs) > 4:
				hidden.append(crumbs.pop(2))
				reqs.pop(2)
			else:
				break # don't remove the parent

		# If necessary, condense the parent crumb
		if self._req_sum(reqs) > w0 and len(crumbs) > 1:
			reqs[-2] = self._condense(reqs[-2], crumbs[-2])

		# If necessary, truncate the current crumb
		if self._req_sum(reqs) > w0:
			reqs[-1] = self._truncate(reqs[-1], 
                                                  self._req_sum(reqs)-w0)
			# Now we are at minimum width

		x = 0
		for w, req in zip(crumbs, reqs):
			wr, _hr = req
			w.size_allocate(gtk.gdk.Rectangle(x0+x, y0, wr, h0))
			w.show()
			x += wr + self.props.spacing

		for w in hidden:
			w.size_allocate(gtk.gdk.Rectangle(-1, -1, 0, 0))
			w.hide()

#		def do_forall(self, internal, callback, data):
#			callback(self.ellipsis, data)
#			for w in self.get_children():
#				callback(w, data)

# this file can be run as a simple test program:
if __name__  == '__main__':
	w = gtk.Window()
	crumbs = CrumbBox(spacing=2)

	items = [
		(gtk.STOCK_HARDDISK, "Filesystem"),
		(None, None), # XXX for ellipsis
		(gtk.STOCK_OPEN, "home"),
		(gtk.STOCK_OPEN, "user"),
		(gtk.STOCK_OPEN, "music"),
		(gtk.STOCK_OPEN, "genre"),
		(gtk.STOCK_OPEN, "artist"),
		(gtk.STOCK_OPEN, "album"),
		]
	for stock, text in items:
		if stock:
			image = gtk.image_new_from_stock(stock, 
							 gtk.ICON_SIZE_MENU)
			crumbs.pack_start(CrumbButton(image, gtk.Label(text)))
		else:
			crumbs.pack_start(gtk.Label("..."))

	w.add(crumbs)
	w.connect('hide', gtk.main_quit)
	w.show_all()

	gtk.main()