1 # Copyright (C) 2009, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
5 from zeroinstall
.gtkui
import gtk
6 from dialog
import Template
7 from zeroinstall
import _
8 from zeroinstall
.gtkui
import help_box
9 from zeroinstall
.injector
.model
import network_levels
10 from zeroinstall
.injector
import trust
, gpg
11 from freshness
import freshness_levels
, Freshness
16 def __init__(self
, config
, notify_cb
= None):
18 notify_cb
= lambda: None
20 def connect_toggle(widget_name
, setting_name
):
21 widget
= widgets
.get_widget(widget_name
)
22 widget
.set_active(getattr(config
, setting_name
))
23 def toggle(w
, config
= config
, setting_name
= setting_name
):
24 setattr(config
, setting_name
, w
.get_active())
27 widget
.connect('toggled', toggle
)
29 widgets
= Template('preferences_box')
31 self
.window
= widgets
.get_widget('preferences_box')
32 self
.window
.connect('destroy', lambda w
: self
.destroyed())
34 network
= widgets
.get_widget('network_use')
35 network
.set_active(list(network_levels
).index(config
.network_use
))
37 def set_network_use(combo
):
38 config
.network_use
= network_levels
[network
.get_active()]
41 network
.connect('changed', set_network_use
)
44 times
= [x
.time
for x
in freshness_levels
]
45 if config
.freshness
not in times
:
46 freshness_levels
.append(Freshness(config
.freshness
,
47 '%d seconds' % config
.freshness
))
48 times
.append(config
.freshness
)
49 freshness
= widgets
.get_widget('freshness')
50 freshness_model
= freshness
.get_model()
51 for level
in freshness_levels
:
52 i
= freshness_model
.append()
53 freshness_model
.set_value(i
, 0, str(level
))
54 freshness
.set_active(times
.index(config
.freshness
))
55 def set_freshness(combo
, freshness
= freshness
): # (pygtk bug?)
56 config
.freshness
= freshness_levels
[freshness
.get_active()].time
59 freshness
.connect('changed', set_freshness
)
61 connect_toggle('help_test', 'help_with_testing')
64 keys_view
= widgets
.get_widget('trusted_keys')
66 connect_toggle('auto_approve', 'auto_approve_keys')
69 self
.window
.set_default_response(gtk
.RESPONSE_CLOSE
)
70 self
.window
.get_default_widget().grab_focus()
72 def response(dialog
, resp
):
73 if resp
in (gtk
.RESPONSE_CLOSE
, gtk
.RESPONSE_DELETE_EVENT
):
75 elif resp
== gtk
.RESPONSE_HELP
:
77 self
.window
.connect('response', response
)
79 self
.window
.set_default_size(-1, gtk
.gdk
.screen_height() / 3)
82 global preferences_box
83 preferences_box
= None
86 def __init__(self
, tv
):
87 self
.trusted_keys
= gtk
.TreeStore(str, object)
88 tv
.set_model(self
.trusted_keys
)
89 tc
= gtk
.TreeViewColumn(_('Trusted keys'), gtk
.CellRendererText(), text
= 0)
91 trust
.trust_db
.ensure_uptodate()
94 # Remember which ones are open
95 expanded_elements
= set()
96 def add_row(tv
, path
, unused
= None):
98 domain
= self
.trusted_keys
[path
][0]
99 expanded_elements
.add(domain
)
100 tv
.map_expanded_rows(add_row
, None)
102 self
.trusted_keys
.clear()
105 keys
= gpg
.load_keys(list(trust
.trust_db
.keys
.keys()))
107 for fingerprint
in keys
:
108 for domain
in trust
.trust_db
.keys
[fingerprint
]:
109 if domain
not in domains
:
110 domains
[domain
] = set()
111 domains
[domain
].add(keys
[fingerprint
])
112 for domain
in sorted(domains
):
113 iter = self
.trusted_keys
.append(None, [domain
, None])
114 for key
in domains
[domain
]:
115 self
.trusted_keys
.append(iter, [key
.name
, key
])
117 def may_expand(model
, path
, iter, unused
):
118 if gtk
.path_depth(path
) == 1:
119 if model
[iter][0] in expanded_elements
:
120 tv
.expand_row(path
, False)
121 self
.trusted_keys
.foreach(may_expand
, None)
123 trust
.trust_db
.watchers
.append(update_keys
)
124 tv
.connect('destroy', lambda w
: trust
.trust_db
.watchers
.remove(update_keys
))
128 def remove_key(fingerprint
, domain
):
129 trust
.trust_db
.untrust_key(fingerprint
, domain
)
130 trust
.trust_db
.notify()
132 def trusted_keys_button_press(tv
, bev
):
133 if bev
.type == gtk
.gdk
.BUTTON_PRESS
and bev
.button
== 3:
134 pos
= tv
.get_path_at_pos(int(bev
.x
), int(bev
.y
))
137 path
, col
, x
, y
= pos
138 if gtk
.path_depth(path
) != 2:
141 key
= self
.trusted_keys
[path
][1]
142 domain
= self
.trusted_keys
[gtk
.path_parent(path
)][0]
146 item
= gtk
.MenuItem(_('Remove key for "%s"') % key
.get_short_name())
147 item
.connect('activate',
148 lambda item
, fp
= key
.fingerprint
, d
= domain
: remove_key(fp
, d
))
152 if sys
.version_info
[0] > 2:
153 menu
.popup(None, None, None, None, bev
.button
, bev
.time
)
155 menu
.popup(None, None, None, bev
.button
, bev
.time
)
158 tv
.connect('button-press-event', trusted_keys_button_press
)
160 preferences_box
= None
161 def show_preferences(config
, notify_cb
= None):
162 global preferences_box
164 preferences_box
.window
.destroy()
165 preferences_box
= Preferences(config
, notify_cb
)
166 preferences_box
.window
.show()
167 return preferences_box
.window
169 gui_help
= help_box
.HelpBox(_("Zero Install Preferences Help"),
170 (_('Overview'), '\n\n' +
171 _("""There are three ways to control which implementations are chosen. You can adjust the \
172 network policy and the overall stability policy, which affect all interfaces, or you \
173 can edit the policy of individual interfaces.""")),
175 (_('Network use'), '\n' +
176 _("""The 'Network use' option controls how the injector uses the network. If off-line, \
177 the network is not used at all. If 'Minimal' is selected then the injector will use \
178 the network if needed, but only if it has no choice. It will run an out-of-date \
179 version rather than download a newer one. If 'Full' is selected, the injector won't \
180 worry about how much it downloads, but will always pick the version it thinks is best.""")),
182 (_('Freshness'), '\n' +
183 _("""The feed files, which provide the information about which versions are \
184 available, are also cached. To update them, click on 'Refresh all now'. You can also \
185 get the injector to check for new versions automatically from time to time using \
186 the Freshness setting.""")),
188 (_('Help test new versions'), '\n' +
189 _("""The overall stability policy can either be to prefer stable versions, or to help test \
190 new versions. Choose whichever suits you. Since different programmers have different \
191 ideas of what 'stable' means, you may wish to override this on a per-interface basis.
193 To set the policy for an interface individually, select it in the main window and \
194 click on 'Interface Properties'. See that dialog's help text for more information.""")),
196 (_('Security'), '\n' +
197 _("""This section lists all keys which you currently trust. When fetching a new program or \
198 updates for an existing one, the feed must be signed by one of these keys. If not, \
199 you will be prompted to confirm that you trust the new key, and it will then be added \
202 If "Automatic approval for new feeds" is on, new keys will be automatically approved if \
203 you haven't used the program before and the key is known to the key information server. \
204 When updating feeds, confirmation for new keys is always required.
206 To remove a key, right-click on it and choose 'Remove' from the menu.""")),