Update year to 2009 in various places
[zeroinstall/zeroinstall-rsl.git] / zeroinstall / 0launch-gui / preferences.py
blob6b48d8e856de416638024eee4ad4c8d9a388c36d
1 # Copyright (C) 2009, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 import gtk
5 from dialog import Template
6 from zeroinstall.gtkui import help_box
7 from zeroinstall.injector.model import network_levels
8 from zeroinstall.injector import trust, gpg
9 from freshness import freshness_levels, Freshness
10 from sets import Set
12 tips = gtk.Tooltips()
14 SHOW_CACHE = 0
16 network_names = {
17 'off-line': _('Off-line'),
18 'minimal': _('Minimal'),
19 'full': _('Full'),
22 class Preferences:
23 def __init__(self, policy):
24 widgets = Template('preferences_box')
26 self.window = widgets.get_widget('preferences_box')
27 self.window.connect('destroy', lambda w: self.destroyed())
29 network = widgets.get_widget('network_use')
30 for level in network_levels:
31 network.append_text(network_names.get(level, level.capitalize()))
32 network.set_active(list(network_levels).index(policy.network_use))
34 def set_network_use(combo):
35 policy.network_use = network_levels[network.get_active()]
36 policy.save_config()
37 policy.solve_with_downloads()
38 network.connect('changed', set_network_use)
40 # Freshness
41 times = [x.time for x in freshness_levels]
42 if policy.freshness not in times:
43 freshness_levels.append(Freshness(policy.freshness,
44 '%d seconds' % policy.freshness))
45 times.append(policy.freshness)
46 eb = gtk.EventBox() # For the tooltip
47 freshness = widgets.get_widget('freshness')
48 for level in freshness_levels:
49 freshness.append_text(str(level))
50 freshness.set_active(times.index(policy.freshness))
51 def set_freshness(combo):
52 policy.freshness = freshness_levels[freshness.get_active()].time
53 policy.save_config()
54 policy.recalculate()
55 freshness.connect('changed', set_freshness)
57 stable_toggle = widgets.get_widget('help_test')
58 stable_toggle.set_active(policy.help_with_testing)
59 def toggle_stability(toggle):
60 policy.help_with_testing = toggle.get_active()
61 policy.save_config()
62 policy.recalculate()
63 stable_toggle.connect('toggled', toggle_stability)
65 # Keys
66 keys_view = widgets.get_widget('trusted_keys')
67 KeyList(keys_view)
69 # Responses
70 self.window.set_default_response(gtk.RESPONSE_CLOSE)
71 self.window.default_widget.grab_focus()
73 def response(dialog, resp):
74 if resp in (gtk.RESPONSE_CLOSE, gtk.RESPONSE_DELETE_EVENT):
75 self.window.destroy()
76 elif resp == gtk.RESPONSE_HELP:
77 gui_help.display()
78 self.window.connect('response', response)
80 self.window.set_default_size(-1, gtk.gdk.screen_height() / 3)
82 def destroyed(self):
83 global preferences_box
84 preferences_box = None
86 class KeyList:
87 def __init__(self, tv):
88 self.trusted_keys = gtk.TreeStore(str, object)
89 tv.set_model(self.trusted_keys)
90 tc = gtk.TreeViewColumn(_('Trusted keys'), gtk.CellRendererText(), text = 0)
91 tv.append_column(tc)
92 trust.trust_db.ensure_uptodate()
94 def update_keys():
95 # Remember which ones are open
96 expanded_elements = set()
97 def add_row(tv, path):
98 if len(path) == 1:
99 domain = self.trusted_keys[path][0]
100 expanded_elements.add(domain)
101 tv.map_expanded_rows(add_row)
103 self.trusted_keys.clear()
104 domains = {}
106 keys = gpg.load_keys(trust.trust_db.keys.keys())
108 for fingerprint in keys:
109 for domain in trust.trust_db.keys[fingerprint]:
110 if domain not in domains:
111 domains[domain] = Set()
112 domains[domain].add(keys[fingerprint])
113 for domain in domains:
114 iter = self.trusted_keys.append(None, [domain, None])
115 for key in domains[domain]:
116 self.trusted_keys.append(iter, [key.name, key])
118 def may_expand(model, path, iter):
119 if len(path) == 1:
120 if model[iter][0] in expanded_elements:
121 tv.expand_row(path, False)
122 self.trusted_keys.foreach(may_expand)
124 trust.trust_db.watchers.append(update_keys)
125 tv.connect('destroy', lambda w: trust.trust_db.watchers.remove(update_keys))
127 update_keys()
129 def remove_key(fingerprint, domain):
130 trust.trust_db.untrust_key(fingerprint, domain)
131 trust.trust_db.notify()
133 def trusted_keys_button_press(tv, bev):
134 if bev.type == gtk.gdk.BUTTON_PRESS and bev.button == 3:
135 pos = tv.get_path_at_pos(int(bev.x), int(bev.y))
136 if not pos:
137 return False
138 path, col, x, y = pos
139 if len(path) != 2:
140 return False
142 domain = self.trusted_keys[path[:-1]][0]
143 key = self.trusted_keys[path][1]
145 menu = gtk.Menu()
147 item = gtk.MenuItem(_('Remove key for "%s"') % key.get_short_name())
148 item.connect('activate',
149 lambda item, fp = key.fingerprint, d = domain: remove_key(fp, d))
150 item.show()
151 menu.append(item)
153 menu.popup(None, None, None, bev.button, bev.time)
154 return True
155 return False
156 tv.connect('button-press-event', trusted_keys_button_press)
158 preferences_box = None
159 def show_preferences(policy):
160 global preferences_box
161 if preferences_box:
162 preferences_box.destroy()
163 preferences_box = Preferences(policy)
164 preferences_box.window.show()
166 gui_help = help_box.HelpBox("Zero Install Preferences Help",
167 ('Overview', """
169 There are three ways to control which implementations are chosen. You can adjust the \
170 network policy and the overall stability policy, which affect all interfaces, or you \
171 can edit the policy of individual interfaces."""),
173 ('Network use', """
174 The 'Network use' option controls how the injector uses the network. If off-line, \
175 the network is not used at all. If 'Minimal' is selected then the injector will use \
176 the network if needed, but only if it has no choice. It will run an out-of-date \
177 version rather than download a newer one. If 'Full' is selected, the injector won't \
178 worry about how much it downloads, but will always pick the version it thinks is best."""),
180 ('Freshness', """
181 The feed files, which provide the information about which versions are \
182 available, are also cached. To update them, click on 'Refresh all now'. You can also \
183 get the injector to check for new versions automatically from time to time using \
184 the Freshness setting."""),
186 ('Help test new versions', """
187 The overall stability policy can either be to prefer stable versions, or to help test \
188 new versions. Choose whichever suits you. Since different programmers have different \
189 ideas of what 'stable' means, you may wish to override this on a per-interface basis.
191 To set the policy for an interface individually, select it in the main window and \
192 click on 'Interface Properties'. See that dialog's help text for more information."""),
194 ('Security', """
195 This section lists all keys which you currently trust. When fetching a new program or \
196 updates for an existing one, the feed must be signed by one of these keys. If not, \
197 you will be prompted to confirm that you trust the new key, and it will then be added \
198 to this list. To remove a key, right-click on it and choose 'Remove' from the menu."""),