Use new GTK tooltips API
[zeroinstall/zeroinstall-afb.git] / zeroinstall / 0launch-gui / impl_list.py
blob4edf018499fda61f61b59ced3e6ce1c6a1dbea16
1 # Copyright (C) 2009, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 import gtk, gobject, os, pango
5 from zeroinstall.injector import model, writer
6 from zeroinstall import support
7 import utils
9 def _build_stability_menu(policy, impl):
10 menu = gtk.Menu()
12 upstream = impl.upstream_stability or model.testing
13 choices = model.stability_levels.values()
14 choices.sort()
15 choices.reverse()
17 def set(new):
18 if isinstance(new, model.Stability):
19 impl.user_stability = new
20 else:
21 impl.user_stability = None
22 writer.save_feed(impl.feed)
23 import main
24 main.recalculate()
26 item = gtk.MenuItem(_('Unset (%s)') % _(str(upstream).capitalize()).lower())
27 item.connect('activate', lambda item: set(None))
28 item.show()
29 menu.append(item)
31 item = gtk.SeparatorMenuItem()
32 item.show()
33 menu.append(item)
35 for value in choices:
36 item = gtk.MenuItem(_(str(value)).capitalize())
37 item.connect('activate', lambda item, v = value: set(v))
38 item.show()
39 menu.append(item)
41 return menu
43 rox_filer = 'http://rox.sourceforge.net/2005/interfaces/ROX-Filer'
45 # Columns
46 ITEM = 0
47 ARCH = 1
48 STABILITY = 2
49 VERSION = 3
50 FETCH = 4
51 UNUSABLE = 5
52 RELEASED = 6
53 NOTES = 7
54 WEIGHT = 8 # Selected item is bold
55 LANGS = 9
57 def get_tooltip_text(policy, interface, impl):
58 if impl.local_path:
59 return _("Local: %s") % impl.local_path
60 if impl.id.startswith('package:'):
61 return _("Native package: %s") % impl.id.split(':', 1)[1]
62 if policy.get_cached(impl):
63 return _("Cached: %s") % policy.get_implementation_path(impl)
65 src = policy.fetcher.get_best_source(impl)
66 if src:
67 size = support.pretty_size(src.size)
68 return _("Not yet downloaded (%s)") % size
69 else:
70 return _("No downloads available!")
72 class ImplementationList:
73 tree_view = None
74 model = None
75 interface = None
76 policy = None
78 def __init__(self, policy, interface, widgets):
79 self.interface = interface
80 self.policy = policy
82 self.model = gtk.ListStore(object, str, str, str, # Item, arch, stability, version,
83 str, gobject.TYPE_BOOLEAN, str, str, # fetch, unusable, released, notes,
84 int, str) # weight, langs
86 self.tree_view = widgets.get_widget('versions_list')
87 self.tree_view.set_model(self.model)
89 text = gtk.CellRendererText()
90 text_strike = gtk.CellRendererText()
92 stability = gtk.TreeViewColumn(_('Stability'), text, text = STABILITY)
94 for column in (gtk.TreeViewColumn(_('Version'), text_strike, text = VERSION, strikethrough = UNUSABLE, weight = WEIGHT),
95 gtk.TreeViewColumn(_('Released'), text, text = RELEASED, weight = WEIGHT),
96 stability,
97 gtk.TreeViewColumn(_('Fetch'), text, text = FETCH, weight = WEIGHT),
98 gtk.TreeViewColumn(_('Arch'), text_strike, text = ARCH, strikethrough = UNUSABLE, weight = WEIGHT),
99 gtk.TreeViewColumn(_('Lang'), text_strike, text = LANGS, strikethrough = UNUSABLE, weight = WEIGHT),
100 gtk.TreeViewColumn(_('Notes'), text, text = NOTES, weight = WEIGHT)):
101 self.tree_view.append_column(column)
103 self.tree_view.set_property('has-tooltip', True)
104 def tooltip_callback(widget, x, y, keyboard_mode, tooltip):
105 x, y = self.tree_view.convert_widget_to_bin_window_coords(x, y)
106 pos = self.tree_view.get_path_at_pos(x, y)
107 if pos:
108 self.tree_view.set_tooltip_cell(tooltip, pos[0], None, None)
109 path = pos[0]
110 row = self.model[path]
111 if row[ITEM]:
112 tooltip.set_text(get_tooltip_text(policy, interface, row[ITEM]))
113 return True
114 return False
115 self.tree_view.connect('query-tooltip', tooltip_callback)
117 def button_press(tree_view, bev):
118 if bev.button not in (1, 3):
119 return False
120 pos = tree_view.get_path_at_pos(int(bev.x), int(bev.y))
121 if not pos:
122 return False
123 path, col, x, y = pos
124 impl = self.model[path][ITEM]
126 menu = gtk.Menu()
128 stability_menu = gtk.MenuItem(_('Rating'))
129 stability_menu.set_submenu(_build_stability_menu(self.policy, impl))
130 stability_menu.show()
131 menu.append(stability_menu)
133 if not impl.id.startswith('package:') and self.policy.get_cached(impl):
134 def open():
135 os.spawnlp(os.P_WAIT, '0launch',
136 '0launch', rox_filer, '-d',
137 self.policy.get_implementation_path(impl))
138 item = gtk.MenuItem(_('Open cached copy'))
139 item.connect('activate', lambda item: open())
140 item.show()
141 menu.append(item)
143 menu.popup(None, None, None, bev.button, bev.time)
145 self.tree_view.connect('button-press-event', button_press)
147 def get_selection(self):
148 return self.tree_view.get_selection()
150 def set_items(self, items):
151 self.model.clear()
152 selected = self.policy.solver.selections.get(self.interface, None)
153 for item, unusable in items:
154 new = self.model.append()
155 self.model[new][ITEM] = item
156 self.model[new][VERSION] = item.get_version()
157 self.model[new][RELEASED] = item.released or "-"
158 self.model[new][FETCH] = utils.get_fetch_info(self.policy, item)
159 if item.user_stability:
160 if item.user_stability == model.insecure:
161 self.model[new][STABILITY] = _('INSECURE')
162 elif item.user_stability == model.buggy:
163 self.model[new][STABILITY] = _('BUGGY')
164 elif item.user_stability == model.developer:
165 self.model[new][STABILITY] = _('DEVELOPER')
166 elif item.user_stability == model.testing:
167 self.model[new][STABILITY] = _('TESTING')
168 elif item.user_stability == model.stable:
169 self.model[new][STABILITY] = _('STABLE')
170 elif item.user_stability == model.packaged:
171 self.model[new][STABILITY] = _('PACKAGED')
172 elif item.user_stability == model.preferred:
173 self.model[new][STABILITY] = _('PREFERRED')
174 else:
175 self.model[new][STABILITY] = _(str(item.upstream_stability) or str(model.testing))
176 self.model[new][ARCH] = item.arch or _('any')
177 if selected is item:
178 self.model[new][WEIGHT] = pango.WEIGHT_BOLD
179 else:
180 self.model[new][WEIGHT] = pango.WEIGHT_NORMAL
181 self.model[new][UNUSABLE] = bool(unusable)
182 self.model[new][LANGS] = item.langs or '-'
183 self.model[new][NOTES] = unusable and _(unusable) or _('None')
185 def clear(self):
186 self.model.clear()