Make errors in the download box selectable (requested by Peter Prohaska).
[zeroinstall.git] / properties.py
blob83e51cb9e1ccabbea0b24c0be2c8da42947b86d0
1 from zeroinstall.injector.model import *
2 from zeroinstall.injector import writer
3 import gtk
5 import help_box
6 from dialog import Dialog
7 from gui import policy
8 from impl_list import ImplementationList
9 import time
11 _dialogs = {} # Interface -> Properties
13 def enumerate(items):
14 x = 0
15 for i in items:
16 yield x, i
17 x += 1
19 def format_para(para):
20 lines = [l.strip() for l in para.split('\n')]
21 return ' '.join(lines)
23 class Description(gtk.ScrolledWindow):
24 def __init__(self):
25 gtk.ScrolledWindow.__init__(self, None, None)
26 self.set_shadow_type(gtk.SHADOW_IN)
27 self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
28 description = gtk.TextView()
29 description.set_left_margin(4)
30 description.set_right_margin(4)
31 description.set_wrap_mode(gtk.WRAP_WORD)
32 description.set_editable(False)
33 description.set_cursor_visible(False)
34 self.add(description)
36 self.buffer = description.get_buffer()
37 self.heading_style = self.buffer.create_tag(underline = True, scale = 1.2)
38 description.set_size_request(-1, 100)
40 def set_details(self, interface):
41 buffer = self.buffer
42 heading_style = self.heading_style
44 buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
46 iter = buffer.get_start_iter()
48 buffer.insert_with_tags(iter,
49 '%s (%s)' % (interface.get_name(), interface.summary), heading_style)
51 buffer.insert(iter, '\n%s\n' % interface.uri)
53 # (converts to local time)
54 if interface.last_modified:
55 buffer.insert(iter, '\nLast upstream change: %s' % time.ctime(interface.last_modified))
57 if interface.last_checked:
58 buffer.insert(iter, '\nLast checked: %s' % time.ctime(interface.last_checked))
60 if hasattr(interface, 'feeds') and interface.feeds:
61 for feed in interface.feeds:
62 buffer.insert(iter, '\nLocal feed: %s' % feed)
64 buffer.insert_with_tags(iter, '\n\nDescription\n', heading_style)
66 paragraphs = [format_para(p) for p in (interface.description or "-").split('\n\n')]
68 buffer.insert(iter, '\n\n'.join(paragraphs))
71 class Properties(Dialog):
72 interface = None
73 use_list = None
75 def __init__(self, interface):
76 Dialog.__init__(self)
77 self.interface = interface
78 self.set_title('Interface ' + interface.get_name())
79 self.set_default_size(gtk.gdk.screen_width() / 2,
80 gtk.gdk.screen_height() / 3)
82 vbox = gtk.VBox(False, 4)
83 vbox.set_border_width(4)
84 self.vbox.pack_start(vbox, True, True, 0)
86 self.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP)
87 self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CANCEL)
88 self.set_default_response(gtk.RESPONSE_CANCEL)
90 def response(dialog, resp):
91 if resp == gtk.RESPONSE_CANCEL:
92 self.destroy()
93 #elif resp == 1:
94 # policy.begin_iface_download(interface, True)
95 elif resp == gtk.RESPONSE_HELP:
96 properties_help.display()
97 self.connect('response', response)
99 main_hbox = gtk.HBox(False, 5)
100 vbox.pack_start(main_hbox, True, True, 0)
102 description = Description()
103 description.set_details(interface)
104 main_hbox.pack_start(description, True, True, 0)
106 main_hbox.pack_start(self.build_versions_column(interface), False, True, 0)
108 self.update_list()
109 vbox.show_all()
111 def updated():
112 self.update_list()
113 description.set_details(interface)
114 self.connect('destroy', lambda s: policy.watchers.remove(updated))
115 policy.watchers.append(updated)
117 def update_list(self):
118 impls = policy.get_ranked_implementations(self.interface)
119 self.use_list.set_items(impls)
121 def build_versions_column(self, interface):
122 assert self.use_list is None
124 vbox = gtk.VBox(False, 2)
126 hbox = gtk.HBox(False, 2)
127 vbox.pack_start(hbox, False, True, 0)
129 stability = gtk.combo_box_new_text()
130 stability.append_text('Use default setting')
131 stability.set_active(0)
132 for i, x in enumerate((stable, testing, developer)):
133 stability.append_text(str(x).capitalize())
134 if x is interface.stability_policy:
135 stability.set_active(i + 1)
136 hbox.pack_start(gtk.Label('Preferred stability:'), False, True, 0)
137 hbox.pack_start(stability, False, True, 0)
138 def set_stability_policy(combo):
139 i = stability.get_active()
140 if i == 0:
141 new_stability = None
142 else:
143 name = stability.get_model()[i][0].lower()
144 new_stability = stability_levels[name]
145 interface.set_stability_policy(new_stability)
146 writer.save_interface(interface)
147 policy.recalculate()
148 stability.connect('changed', set_stability_policy)
150 self.use_list = ImplementationList(interface)
151 self.use_list.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
152 vbox.pack_start(self.use_list, True, True, 0)
154 return vbox
156 def edit(interface):
157 assert isinstance(interface, Interface)
158 if interface in _dialogs:
159 _dialogs[interface].destroy()
160 _dialogs[interface] = Properties(interface)
161 _dialogs[interface].show()
163 properties_help = help_box.HelpBox("Injector Properties Help",
164 ('Interface properties', """
165 This window displays information about an interface. On the left is some information \
166 about the interface:
168 - At the top is its short name.
169 - Below that is the full name; this is also location which is used to update \
170 the information.
171 - 'Last upstream change' shows the version of the cached copy of the interface file.
172 - 'Last checked' is the last time a fresh copy of the upstream interface file was \
173 downloaded.
174 - 'Local feed' is shown if you have other sources of versions of this program (for \
175 example, a CVS checkout).
176 - The long description of the interface."""),
178 ('Implementations', """
179 The main part of the window is a list of all known implementations of the interface. \
180 The columns have the following meanings:
182 Version gives the version number. High-numbered versions are considered to be \
183 better than low-numbered ones.
185 Stability is 'stable' if the implementation is believed to be stable, 'buggy' if \
186 it is known to contain serious bugs, and 'testing' if its stability is not yet \
187 known. This information is normally supplied and updated by the author of the \
188 software, but you can override their rating (overridden values are shown in upper-case). \
189 You can also use the special level 'preferred'.
191 C(ached) indicates whether the implementation is already stored on your computer. \
192 In off-line mode, only cached implementations are considered for use.
194 Arch indicates what kind of computer system the implementation is for, or 'any' \
195 if it works with all types of system.
196 """),
197 ('Sort order', """
198 The implementations are listed in the injector's currently preferred order (the one \
199 at the top will actually be used). Usable implementations all come before unusable \
200 ones.
202 Unusable ones are those for incompatible \
203 architectures, those marked as 'buggy', versions explicitly marked as incompatible with \
204 another interface you are using and, in off-line mode, uncached implementations. Unusable \
205 implementations are shown crossed out.
207 For the usable implementations, the order is as follows:
209 - Preferred implementations come first.
211 - Then, if network use is set to 'Minimal', cached implementations come before \
212 non-cached.
214 - Then, implementations at or above the selected stability level come before all others.
216 - Then, higher-numbered versions come before low-numbered ones.
218 - Then cached come before non-cached (for 'Full' network use mode).
219 """))