Translate some missing strings
[zeroinstall/zeroinstall-afb.git] / zeroinstall / 0launch-gui / impl_list.py
blob9c13522d2cd29d512357857bf64b86ab8138df02
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 from zeroinstall.gtkui.treetips import TreeTips
8 import utils
10 def _build_stability_menu(policy, impl):
11 menu = gtk.Menu()
13 upstream = impl.upstream_stability or model.testing
14 choices = model.stability_levels.values()
15 choices.sort()
16 choices.reverse()
18 def set(new):
19 if isinstance(new, model.Stability):
20 impl.user_stability = new
21 else:
22 impl.user_stability = None
23 writer.save_feed(impl.feed)
24 import main
25 main.recalculate()
27 item = gtk.MenuItem(_('Unset (%s)') % _(str(upstream).capitalize()).lower())
28 item.connect('activate', lambda item: set(None))
29 item.show()
30 menu.append(item)
32 item = gtk.SeparatorMenuItem()
33 item.show()
34 menu.append(item)
36 for value in choices:
37 item = gtk.MenuItem(_(str(value)).capitalize())
38 item.connect('activate', lambda item, v = value: set(v))
39 item.show()
40 menu.append(item)
42 return menu
44 rox_filer = 'http://rox.sourceforge.net/2005/interfaces/ROX-Filer'
46 # Columns
47 ITEM = 0
48 ARCH = 1
49 STABILITY = 2
50 VERSION = 3
51 FETCH = 4
52 UNUSABLE = 5
53 RELEASED = 6
54 NOTES = 7
55 WEIGHT = 8 # Selected item is bold
56 LANGS = 9
58 class ImplTips(TreeTips):
59 def __init__(self, policy, interface):
60 self.policy = policy
61 self.interface = interface
63 def get_tooltip_text(self):
64 impl = self.item
65 if impl.local_path:
66 return _("Local: %s") % impl.local_path
67 if impl.id.startswith('package:'):
68 return _("Native package: %s") % impl.id.split(':', 1)[1]
69 if self.policy.get_cached(impl):
70 return _("Cached: %s") % self.policy.get_implementation_path(impl)
72 src = self.policy.fetcher.get_best_source(impl)
73 if src:
74 size = support.pretty_size(src.size)
75 return _("Not yet downloaded (%s)") % size
76 else:
77 return _("No downloads available!")
79 class ImplementationList:
80 tree_view = None
81 model = None
82 interface = None
83 policy = None
85 def __init__(self, policy, interface, widgets):
86 self.interface = interface
87 self.policy = policy
89 self.model = gtk.ListStore(object, str, str, str, # Item, arch, stability, version,
90 str, gobject.TYPE_BOOLEAN, str, str, # fetch, unusable, released, notes,
91 int, str) # weight, langs
93 self.tree_view = widgets.get_widget('versions_list')
94 self.tree_view.set_model(self.model)
96 text = gtk.CellRendererText()
97 text_strike = gtk.CellRendererText()
99 stability = gtk.TreeViewColumn(_('Stability'), text, text = STABILITY)
101 for column in (gtk.TreeViewColumn(_('Version'), text_strike, text = VERSION, strikethrough = UNUSABLE, weight = WEIGHT),
102 gtk.TreeViewColumn(_('Released'), text, text = RELEASED, weight = WEIGHT),
103 stability,
104 gtk.TreeViewColumn(_('Fetch'), text, text = FETCH, weight = WEIGHT),
105 gtk.TreeViewColumn(_('Arch'), text_strike, text = ARCH, strikethrough = UNUSABLE, weight = WEIGHT),
106 gtk.TreeViewColumn(_('Lang'), text_strike, text = LANGS, strikethrough = UNUSABLE, weight = WEIGHT),
107 gtk.TreeViewColumn(_('Notes'), text, text = NOTES, weight = WEIGHT)):
108 self.tree_view.append_column(column)
110 tips = ImplTips(policy, interface)
112 def motion(tree_view, ev):
113 if ev.window is not tree_view.get_bin_window():
114 return False
115 pos = tree_view.get_path_at_pos(int(ev.x), int(ev.y))
116 if pos:
117 path = pos[0]
118 row = self.model[path]
119 if row[ITEM] is not tips.item:
120 tips.prime(tree_view, row[ITEM])
121 else:
122 tips.hide()
124 self.tree_view.connect('motion-notify-event', motion)
125 self.tree_view.connect('leave-notify-event', lambda tv, ev: tips.hide())
126 self.tree_view.connect('destroy', lambda tv: tips.hide())
128 def button_press(tree_view, bev):
129 if bev.button not in (1, 3):
130 return False
131 pos = tree_view.get_path_at_pos(int(bev.x), int(bev.y))
132 if not pos:
133 return False
134 path, col, x, y = pos
135 impl = self.model[path][ITEM]
137 menu = gtk.Menu()
139 stability_menu = gtk.MenuItem(_('Rating'))
140 stability_menu.set_submenu(_build_stability_menu(self.policy, impl))
141 stability_menu.show()
142 menu.append(stability_menu)
144 if not impl.id.startswith('package:') and self.policy.get_cached(impl):
145 def open():
146 os.spawnlp(os.P_WAIT, '0launch',
147 '0launch', rox_filer, '-d',
148 self.policy.get_implementation_path(impl))
149 item = gtk.MenuItem(_('Open cached copy'))
150 item.connect('activate', lambda item: open())
151 item.show()
152 menu.append(item)
154 menu.popup(None, None, None, bev.button, bev.time)
156 self.tree_view.connect('button-press-event', button_press)
158 def get_selection(self):
159 return self.tree_view.get_selection()
161 def set_items(self, items):
162 self.model.clear()
163 selected = self.policy.solver.selections.get(self.interface, None)
164 for item, unusable in items:
165 new = self.model.append()
166 self.model[new][ITEM] = item
167 self.model[new][VERSION] = item.get_version()
168 self.model[new][RELEASED] = item.released or "-"
169 self.model[new][FETCH] = utils.get_fetch_info(self.policy, item)
170 if item.user_stability:
171 if item.user_stability == model.insecure:
172 self.model[new][STABILITY] = _('INSECURE')
173 elif item.user_stability == model.buggy:
174 self.model[new][STABILITY] = _('BUGGY')
175 elif item.user_stability == model.developer:
176 self.model[new][STABILITY] = _('DEVELOPER')
177 elif item.user_stability == model.testing:
178 self.model[new][STABILITY] = _('TESTING')
179 elif item.user_stability == model.stable:
180 self.model[new][STABILITY] = _('STABLE')
181 elif item.user_stability == model.packaged:
182 self.model[new][STABILITY] = _('PACKAGED')
183 elif item.user_stability == model.preferred:
184 self.model[new][STABILITY] = _('PREFERRED')
185 else:
186 self.model[new][STABILITY] = _(str(item.upstream_stability) or str(model.testing))
187 self.model[new][ARCH] = item.arch or _('any')
188 if selected is item:
189 self.model[new][WEIGHT] = pango.WEIGHT_BOLD
190 else:
191 self.model[new][WEIGHT] = pango.WEIGHT_NORMAL
192 self.model[new][UNUSABLE] = bool(unusable)
193 self.model[new][LANGS] = item.langs or '-'
194 self.model[new][NOTES] = unusable and _(unusable) or _('None')
196 def clear(self):
197 self.model.clear()