Better text formatting for interface details window.
[zeroinstall.git] / impl_list.py
blob79e3f812e158df3174ff18c265de2b816cfe19dc
1 import gtk, gobject, os
2 from zeroinstall.injector import model, writer
3 from gui import policy, pretty_size
4 from treetips import TreeTips
6 def popup_menu(bev, values, fn):
7 menu = gtk.Menu()
8 for value in values:
9 if value is None:
10 item = gtk.SeparatorMenuItem()
11 else:
12 item = gtk.MenuItem(str(value).capitalize())
13 item.connect('activate', lambda item, v=value: fn(v))
14 item.show()
15 menu.append(item)
16 menu.popup(None, None, None, bev.button, bev.time)
18 rox_filer = 'http://rox.sourceforge.net/2005/interfaces/ROX-Filer'
20 # Columns
21 ITEM = 0
22 ARCH = 1
23 STABILITY = 2
24 VERSION = 3
25 CACHED = 4
26 UNUSABLE = 5
27 RELEASED = 6
29 class ImplTips(TreeTips):
30 def get_tooltip_text(self, item):
31 interface, id = item
32 if id.startswith('/'):
33 return _("Local: %s") % id
34 impl = interface.implementations[id]
35 if policy.get_cached(impl):
36 return _("Cached: %s") % policy.get_implementation_path(impl)
38 src = policy.get_best_source(impl)
39 if src:
40 size = pretty_size(src.size)
41 return _("Not yet downloaded (%s)") % size
42 else:
43 return _("No downloads available!")
45 tips = ImplTips()
47 class ImplementationList(gtk.ScrolledWindow):
48 tree_view = None
49 model = None
51 def __init__(self, interface):
52 gtk.ScrolledWindow.__init__(self, None, None)
53 self.set_shadow_type(gtk.SHADOW_IN)
55 self.model = gtk.ListStore(object, str, str, str,
56 gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
57 str)
59 self.tree_view = gtk.TreeView(self.model)
61 text = gtk.CellRendererText()
62 text_strike = gtk.CellRendererText()
63 toggle = gtk.CellRendererToggle()
65 stability = gtk.TreeViewColumn('Stability', text, text = STABILITY)
67 for column in (gtk.TreeViewColumn('Version', text, text = VERSION, strikethrough = UNUSABLE),
68 gtk.TreeViewColumn('Released', text, text = RELEASED, strikethrough = UNUSABLE),
69 stability,
70 gtk.TreeViewColumn('C', toggle, active = CACHED),
71 gtk.TreeViewColumn('Arch', text, text = ARCH)):
72 self.tree_view.append_column(column)
74 self.add(self.tree_view)
76 def motion(tree_view, ev):
77 if ev.window is not tree_view.get_bin_window():
78 return False
79 pos = tree_view.get_path_at_pos(int(ev.x), int(ev.y))
80 if pos:
81 path = pos[0]
82 row = self.model[path]
83 tips.prime(tree_view, (interface, row[ITEM].id))
84 else:
85 tips.hide()
87 self.tree_view.connect('motion-notify-event', motion)
88 self.tree_view.connect('leave-notify-event', lambda tv, ev: tips.hide())
90 def button_press(tree_view, bev):
91 if bev.button not in (1, 3):
92 return False
93 pos = tree_view.get_path_at_pos(int(bev.x), int(bev.y))
94 if not pos:
95 return False
96 path, col, x, y = pos
97 impl = self.model[path][ITEM]
98 if col == stability:
99 upstream = impl.upstream_stability or model.testing
100 choices = model.stability_levels.values()
101 choices.sort()
102 choices.reverse()
103 def set(new):
104 if isinstance(new, model.Stability):
105 impl.user_stability = new
106 else:
107 impl.user_stability = None
108 writer.save_interface(interface)
109 policy.recalculate()
110 popup_menu(bev, ['Unset (%s)' % upstream, None] + choices,
111 set)
112 elif bev.button == 3 and policy.get_cached(impl):
113 def open(item):
114 os.spawnlp(os.P_WAIT, '0launch',
115 '0launch', rox_filer, '-d',
116 policy.get_implementation_path(impl))
117 popup_menu(bev, ['Open cached copy'], open)
118 self.tree_view.connect('button-press-event', button_press)
120 def get_selection(self):
121 return self.tree_view.get_selection()
123 def set_items(self, items):
124 self.model.clear()
125 for item in items:
126 new = self.model.append()
127 self.model[new][ITEM] = item
128 self.model[new][VERSION] = item.get_version()
129 if hasattr(item, 'released') and item.released:
130 self.model[new][RELEASED] = item.released
131 else:
132 self.model[new][RELEASED] = "-"
133 self.model[new][CACHED] = policy.get_cached(item)
134 if item.user_stability:
135 self.model[new][STABILITY] = str(item.user_stability).upper()
136 else:
137 self.model[new][STABILITY] = item.upstream_stability or \
138 model.testing
139 self.model[new][ARCH] = item.arch or 'any'
140 self.model[new][UNUSABLE] = policy.is_unusable(item)
142 def clear(self):
143 self.model.clear()