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