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
):
10 item
= gtk
.SeparatorMenuItem()
12 item
= gtk
.MenuItem(str(value
).capitalize())
13 item
.connect('activate', lambda item
, v
=value
: fn(v
))
16 menu
.popup(None, None, None, bev
.button
, bev
.time
)
18 rox_filer
= 'http://rox.sourceforge.net/2005/interfaces/ROX-Filer'
29 def interface_for(interface
, impl
):
30 # Since injector 0.16, we can get the interface from the impl
31 # Before that, the impl always comes from the main interface (even for feeds)
32 if hasattr(impl
, 'interface'):
36 class ImplTips(TreeTips
):
37 def __init__(self
, interface
):
38 self
.interface
= interface
40 def get_tooltip_text(self
, impl
):
41 if hasattr(policy
, 'restrictions'):
42 restrictions
= policy
.restrictions
.get(self
.interface
, [])
43 unusable
= policy
.get_unusable_reason(impl
, restrictions
)
46 unusable
= policy
.get_unusable_reason(impl
)
50 if impl
.id.startswith('/'):
51 return _("Local: %s") % impl
.id
52 if policy
.get_cached(impl
):
53 return _("Cached: %s") % policy
.get_implementation_path(impl
)
55 src
= policy
.get_best_source(impl
)
57 size
= pretty_size(src
.size
)
58 return _("Not yet downloaded (%s)") % size
60 return _("No downloads available!")
62 class ImplementationList(gtk
.ScrolledWindow
):
67 def __init__(self
, interface
):
68 gtk
.ScrolledWindow
.__init
__(self
, None, None)
69 self
.set_shadow_type(gtk
.SHADOW_IN
)
71 self
.interface
= interface
73 self
.model
= gtk
.ListStore(object, str, str, str,
74 gobject
.TYPE_BOOLEAN
, gobject
.TYPE_BOOLEAN
,
77 self
.tree_view
= gtk
.TreeView(self
.model
)
79 text
= gtk
.CellRendererText()
80 text_strike
= gtk
.CellRendererText()
81 toggle
= gtk
.CellRendererToggle()
83 stability
= gtk
.TreeViewColumn('Stability', text
, text
= STABILITY
)
85 for column
in (gtk
.TreeViewColumn('Version', text
, text
= VERSION
, strikethrough
= UNUSABLE
),
86 gtk
.TreeViewColumn('Released', text
, text
= RELEASED
, strikethrough
= UNUSABLE
),
88 gtk
.TreeViewColumn('C', toggle
, active
= CACHED
),
89 gtk
.TreeViewColumn('Arch', text
, text
= ARCH
)):
90 self
.tree_view
.append_column(column
)
92 self
.add(self
.tree_view
)
94 tips
= ImplTips(interface
)
96 def motion(tree_view
, ev
):
97 if ev
.window
is not tree_view
.get_bin_window():
99 pos
= tree_view
.get_path_at_pos(int(ev
.x
), int(ev
.y
))
102 row
= self
.model
[path
]
103 if row
[ITEM
] is not tips
.item
:
104 tips
.prime(tree_view
, row
[ITEM
])
108 self
.tree_view
.connect('motion-notify-event', motion
)
109 self
.tree_view
.connect('leave-notify-event', lambda tv
, ev
: tips
.hide())
110 self
.tree_view
.connect('destroy', lambda tv
: tips
.hide())
112 def button_press(tree_view
, bev
):
113 if bev
.button
not in (1, 3):
115 pos
= tree_view
.get_path_at_pos(int(bev
.x
), int(bev
.y
))
118 path
, col
, x
, y
= pos
119 impl
= self
.model
[path
][ITEM
]
121 upstream
= impl
.upstream_stability
or model
.testing
122 choices
= model
.stability_levels
.values()
126 if isinstance(new
, model
.Stability
):
127 impl
.user_stability
= new
129 impl
.user_stability
= None
130 writer
.save_interface(interface_for(interface
, impl
))
132 popup_menu(bev
, ['Unset (%s)' % upstream
, None] + choices
,
134 elif bev
.button
== 3 and policy
.get_cached(impl
):
136 os
.spawnlp(os
.P_WAIT
, '0launch',
137 '0launch', rox_filer
, '-d',
138 policy
.get_implementation_path(impl
))
139 popup_menu(bev
, ['Open cached copy'], open)
140 self
.tree_view
.connect('button-press-event', button_press
)
142 def get_selection(self
):
143 return self
.tree_view
.get_selection()
145 def set_items(self
, items
):
147 if hasattr(policy
, 'restrictions'):
148 restrictions
= policy
.restrictions
.get(self
.interface
, None)
152 new
= self
.model
.append()
153 self
.model
[new
][ITEM
] = item
154 self
.model
[new
][VERSION
] = item
.get_version()
155 if hasattr(item
, 'released') and item
.released
:
156 self
.model
[new
][RELEASED
] = item
.released
158 self
.model
[new
][RELEASED
] = "-"
159 self
.model
[new
][CACHED
] = policy
.get_cached(item
)
160 if item
.user_stability
:
161 self
.model
[new
][STABILITY
] = str(item
.user_stability
).upper()
163 self
.model
[new
][STABILITY
] = item
.upstream_stability
or \
165 self
.model
[new
][ARCH
] = item
.arch
or 'any'
167 self
.model
[new
][UNUSABLE
] = policy
.is_unusable(item
, restrictions
)
169 self
.model
[new
][UNUSABLE
] = policy
.is_unusable(item
)