Update year to 2009 in various places
[zeroinstall/zeroinstall-rsl.git] / zeroinstall / 0launch-gui / impl_list.py
blob3f9ae17cb7819d591277083416d0e03d553826a3
1 # Copyright (C) 2009, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 import gtk, gobject, os
5 from zeroinstall.injector import model, writer
6 from zeroinstall import support
7 from zeroinstall.gtkui.treetips import TreeTips
8 import utils
10 def popup_menu(bev, values, fn):
11 menu = gtk.Menu()
12 for value in values:
13 if value is None:
14 item = gtk.SeparatorMenuItem()
15 else:
16 item = gtk.MenuItem(str(value).capitalize())
17 item.connect('activate', lambda item, v=value: fn(v))
18 item.show()
19 menu.append(item)
20 menu.popup(None, None, None, bev.button, bev.time)
22 rox_filer = 'http://rox.sourceforge.net/2005/interfaces/ROX-Filer'
24 # Columns
25 ITEM = 0
26 ARCH = 1
27 STABILITY = 2
28 VERSION = 3
29 FETCH = 4
30 UNUSABLE = 5
31 RELEASED = 6
32 NOTES = 7
34 class ImplTips(TreeTips):
35 def __init__(self, policy, interface):
36 self.policy = policy
37 self.interface = interface
39 def get_tooltip_text(self):
40 impl = self.item
41 if impl.id.startswith('/'):
42 return _("Local: %s") % impl.id
43 if impl.id.startswith('package:'):
44 return _("Native package: %s") % impl.id.split(':', 1)[1]
45 if self.policy.get_cached(impl):
46 return _("Cached: %s") % self.policy.get_implementation_path(impl)
48 src = self.policy.fetcher.get_best_source(impl)
49 if src:
50 size = support.pretty_size(src.size)
51 return _("Not yet downloaded (%s)") % size
52 else:
53 return _("No downloads available!")
55 class ImplementationList:
56 tree_view = None
57 model = None
58 interface = None
59 policy = None
61 def __init__(self, policy, interface, widgets):
62 self.interface = interface
63 self.policy = policy
65 self.model = gtk.ListStore(object, str, str, str, # Item, arch, stability, version,
66 str, gobject.TYPE_BOOLEAN, str, str) # fetch, unusable, released, notes
68 self.tree_view = widgets.get_widget('versions_list')
69 self.tree_view.set_model(self.model)
71 text = gtk.CellRendererText()
72 text_strike = gtk.CellRendererText()
74 stability = gtk.TreeViewColumn(_('Stability'), text, text = STABILITY)
76 for column in (gtk.TreeViewColumn(_('Version'), text_strike, text = VERSION, strikethrough = UNUSABLE),
77 gtk.TreeViewColumn(_('Released'), text, text = RELEASED),
78 stability,
79 gtk.TreeViewColumn(_('Fetch'), text, text = FETCH),
80 gtk.TreeViewColumn(_('Arch'), text_strike, text = ARCH, strikethrough = UNUSABLE),
81 gtk.TreeViewColumn(_('Notes'), text, text = NOTES)):
82 self.tree_view.append_column(column)
84 tips = ImplTips(policy, interface)
86 def motion(tree_view, ev):
87 if ev.window is not tree_view.get_bin_window():
88 return False
89 pos = tree_view.get_path_at_pos(int(ev.x), int(ev.y))
90 if pos:
91 path = pos[0]
92 row = self.model[path]
93 if row[ITEM] is not tips.item:
94 tips.prime(tree_view, row[ITEM])
95 else:
96 tips.hide()
98 self.tree_view.connect('motion-notify-event', motion)
99 self.tree_view.connect('leave-notify-event', lambda tv, ev: tips.hide())
100 self.tree_view.connect('destroy', lambda tv: tips.hide())
102 def button_press(tree_view, bev):
103 if bev.button not in (1, 3):
104 return False
105 pos = tree_view.get_path_at_pos(int(bev.x), int(bev.y))
106 if not pos:
107 return False
108 path, col, x, y = pos
109 impl = self.model[path][ITEM]
110 if col == stability:
111 upstream = impl.upstream_stability or model.testing
112 choices = model.stability_levels.values()
113 choices.sort()
114 choices.reverse()
115 def set(new):
116 if isinstance(new, model.Stability):
117 impl.user_stability = new
118 else:
119 impl.user_stability = None
120 writer.save_feed(impl.feed)
121 self.policy.recalculate()
122 popup_menu(bev, ['Unset (%s)' % upstream, None] + choices,
123 set)
124 elif bev.button == 3 and self.policy.get_cached(impl):
125 def open(item):
126 os.spawnlp(os.P_WAIT, '0launch',
127 '0launch', rox_filer, '-d',
128 self.policy.get_implementation_path(impl))
129 popup_menu(bev, ['Open cached copy'], open)
130 self.tree_view.connect('button-press-event', button_press)
132 def get_selection(self):
133 return self.tree_view.get_selection()
135 def set_items(self, items):
136 self.model.clear()
137 for item, unusable in items:
138 new = self.model.append()
139 self.model[new][ITEM] = item
140 self.model[new][VERSION] = item.get_version()
141 self.model[new][RELEASED] = item.released or "-"
142 self.model[new][FETCH] = utils.get_fetch_info(self.policy, item)
143 if item.user_stability:
144 self.model[new][STABILITY] = str(item.user_stability).upper()
145 else:
146 self.model[new][STABILITY] = item.upstream_stability or \
147 model.testing
148 self.model[new][ARCH] = item.arch or 'any'
149 self.model[new][UNUSABLE] = bool(unusable)
150 self.model[new][NOTES] = unusable
152 def clear(self):
153 self.model.clear()