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
import _
6 from zeroinstall
.injector
import model
, writer
7 from zeroinstall
import support
8 from zeroinstall
.gtkui
import gtkutils
11 def _build_stability_menu(policy
, impl
):
14 upstream
= impl
.upstream_stability
or model
.testing
15 choices
= model
.stability_levels
.values()
20 if isinstance(new
, model
.Stability
):
21 impl
.user_stability
= new
23 impl
.user_stability
= None
24 writer
.save_feed(impl
.feed
)
28 item
= gtk
.MenuItem(_('Unset (%s)') % _(str(upstream
).capitalize()).lower())
29 item
.connect('activate', lambda item
: set(None))
33 item
= gtk
.SeparatorMenuItem()
38 item
= gtk
.MenuItem(_(str(value
)).capitalize())
39 item
.connect('activate', lambda item
, v
= value
: set(v
))
45 rox_filer
= 'http://rox.sourceforge.net/2005/interfaces/ROX-Filer'
56 WEIGHT
= 8 # Selected item is bold
59 def get_tooltip_text(policy
, interface
, impl
):
61 return _("Local: %s") % impl
.local_path
62 if impl
.id.startswith('package:'):
63 return _("Native package: %s") % impl
.id.split(':', 1)[1]
64 if policy
.get_cached(impl
):
65 return _("Cached: %s") % policy
.get_implementation_path(impl
)
67 src
= policy
.fetcher
.get_best_source(impl
)
69 size
= support
.pretty_size(src
.size
)
70 return _("Not yet downloaded (%s)") % size
72 return _("No downloads available!")
74 class ImplementationList
:
80 def __init__(self
, policy
, interface
, widgets
):
81 self
.interface
= interface
84 self
.model
= gtk
.ListStore(object, str, str, str, # Item, arch, stability, version,
85 str, gobject
.TYPE_BOOLEAN
, str, str, # fetch, unusable, released, notes,
86 int, str) # weight, langs
88 self
.tree_view
= widgets
.get_widget('versions_list')
89 self
.tree_view
.set_model(self
.model
)
91 text
= gtk
.CellRendererText()
92 text_strike
= gtk
.CellRendererText()
94 stability
= gtk
.TreeViewColumn(_('Stability'), text
, text
= STABILITY
)
96 for column
in (gtk
.TreeViewColumn(_('Version'), text_strike
, text
= VERSION
, strikethrough
= UNUSABLE
, weight
= WEIGHT
),
97 gtk
.TreeViewColumn(_('Released'), text
, text
= RELEASED
, weight
= WEIGHT
),
99 gtk
.TreeViewColumn(_('Fetch'), text
, text
= FETCH
, weight
= WEIGHT
),
100 gtk
.TreeViewColumn(_('Arch'), text_strike
, text
= ARCH
, strikethrough
= UNUSABLE
, weight
= WEIGHT
),
101 gtk
.TreeViewColumn(_('Lang'), text_strike
, text
= LANGS
, strikethrough
= UNUSABLE
, weight
= WEIGHT
),
102 gtk
.TreeViewColumn(_('Notes'), text
, text
= NOTES
, weight
= WEIGHT
)):
103 self
.tree_view
.append_column(column
)
105 self
.tree_view
.set_property('has-tooltip', True)
106 def tooltip_callback(widget
, x
, y
, keyboard_mode
, tooltip
):
107 x
, y
= self
.tree_view
.convert_widget_to_bin_window_coords(x
, y
)
108 pos
= self
.tree_view
.get_path_at_pos(x
, y
)
110 self
.tree_view
.set_tooltip_cell(tooltip
, pos
[0], None, None)
112 row
= self
.model
[path
]
114 tooltip
.set_text(get_tooltip_text(policy
, interface
, row
[ITEM
]))
117 self
.tree_view
.connect('query-tooltip', tooltip_callback
)
119 def button_press(tree_view
, bev
):
120 if bev
.button
not in (1, 3):
122 pos
= tree_view
.get_path_at_pos(int(bev
.x
), int(bev
.y
))
125 path
, col
, x
, y
= pos
126 impl
= self
.model
[path
][ITEM
]
130 stability_menu
= gtk
.MenuItem(_('Rating'))
131 stability_menu
.set_submenu(_build_stability_menu(self
.policy
, impl
))
132 stability_menu
.show()
133 menu
.append(stability_menu
)
135 if not impl
.id.startswith('package:') and self
.policy
.get_cached(impl
):
137 os
.spawnlp(os
.P_WAIT
, '0launch',
138 '0launch', rox_filer
, '-d',
139 self
.policy
.get_implementation_path(impl
))
140 item
= gtk
.MenuItem(_('Open cached copy'))
141 item
.connect('activate', lambda item
: open())
145 item
= gtk
.MenuItem(_('Explain this decision'))
146 item
.connect('activate', lambda item
: self
.show_explaination(impl
))
150 menu
.popup(None, None, None, bev
.button
, bev
.time
)
152 self
.tree_view
.connect('button-press-event', button_press
)
154 def show_explaination(self
, impl
):
155 reason
= self
.policy
.solver
.justify_decision(self
.policy
.requirements
, self
.interface
, impl
)
156 gtkutils
.show_message_box(self
.tree_view
.get_toplevel(), reason
, gtk
.MESSAGE_INFO
)
158 def get_selection(self
):
159 return self
.tree_view
.get_selection()
161 def set_items(self
, items
):
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')
186 self
.model
[new
][STABILITY
] = _(str(item
.upstream_stability
) or str(model
.testing
))
187 self
.model
[new
][ARCH
] = item
.arch
or _('any')
189 self
.model
[new
][WEIGHT
] = pango
.WEIGHT_BOLD
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')