2 from logging
import warn
6 from dialog
import Dialog
, MixedButton
, frame
7 from zeroinstall
.injector
.model
import network_levels
8 from zeroinstall
.injector
import trust
, gpg
9 from freshness
import freshness_levels
, Freshness
16 class Preferences(Dialog
):
19 self
.set_title('Zero Install Preferences')
21 self
.connect('destroy', lambda w
: self
.destroyed())
23 content
= gtk
.VBox(False, 2)
24 content
.set_border_width(8)
25 self
.vbox
.pack_start(content
, True, True, 0)
27 vbox
= gtk
.VBox(False, 0)
28 frame(content
, 'Policy settings', vbox
)
31 hbox
= gtk
.HBox(False, 2)
32 vbox
.pack_start(hbox
, False, True, 0)
33 hbox
.set_border_width(4)
35 eb
= gtk
.EventBox() # For the tooltip
36 network
= gtk
.combo_box_new_text()
38 for level
in network_levels
:
39 network
.append_text(level
.capitalize())
40 network
.set_active(list(network_levels
).index(policy
.network_use
))
41 hbox
.pack_start(gtk
.Label('Network use:'), False, True, 0)
42 hbox
.pack_start(eb
, True, True, 2)
43 def set_network_use(combo
):
44 policy
.network_use
= network_levels
[network
.get_active()]
47 network
.connect('changed', set_network_use
)
48 tips
.set_tip(eb
, _('This controls whether the injector will always try to '
49 'run the best version, downloading it if needed, or whether it will prefer '
50 'to run an older version that is already on your machine.'))
55 hbox
= gtk
.HBox(False, 2)
56 vbox
.pack_start(hbox
, False, True, 0)
57 hbox
.set_border_width(4)
59 times
= [x
.time
for x
in freshness_levels
]
60 if policy
.freshness
not in times
:
61 freshness_levels
.append(Freshness(policy
.freshness
,
62 '%d seconds' % policy
.freshness
))
63 times
.append(policy
.freshness
)
64 eb
= gtk
.EventBox() # For the tooltip
65 freshness
= gtk
.combo_box_new_text()
67 for level
in freshness_levels
:
68 freshness
.append_text(str(level
))
69 freshness
.set_active(times
.index(policy
.freshness
))
70 hbox
.pack_start(gtk
.Label('Freshness:'), False, True, 0)
71 hbox
.pack_start(eb
, True, True, 2)
72 def set_freshness(combo
):
73 policy
.freshness
= freshness_levels
[freshness
.get_active()].time
76 freshness
.connect('changed', set_freshness
)
77 tips
.set_tip(eb
, _('Sets how often the injector will check for new versions.'))
79 stable_toggle
= gtk
.CheckButton('Help test new versions')
80 vbox
.pack_start(stable_toggle
, False, True, 0)
81 tips
.set_tip(stable_toggle
,
82 "Try out new versions as soon as they are available, instead of "
83 "waiting for them to be marked as 'stable'. "
84 "This sets the default policy. Click on 'Interface Properties...' "
85 "to set the policy for an individual interface.")
86 stable_toggle
.set_active(policy
.help_with_testing
)
87 def toggle_stability(toggle
):
88 policy
.help_with_testing
= toggle
.get_active()
91 stable_toggle
.connect('toggled', toggle_stability
)
94 if hasattr(gpg
, 'Key'):
97 keys_area
= gtk
.Label('Sorry, this feature requires 0launch >= 0.27')
98 keys_area
.set_alignment(0, 0)
99 frame(content
, 'Security', keys_area
, expand
= True)
103 self
.add_button(gtk
.STOCK_HELP
, gtk
.RESPONSE_HELP
)
104 self
.add_button(gtk
.STOCK_CLOSE
, gtk
.RESPONSE_CLOSE
)
106 self
.set_default_response(gtk
.RESPONSE_CLOSE
)
107 self
.default_widget
.grab_focus()
109 def response(dialog
, resp
):
111 if resp
in (gtk
.RESPONSE_CLOSE
, gtk
.RESPONSE_DELETE_EVENT
):
113 elif resp
== gtk
.RESPONSE_HELP
:
115 self
.connect('response', response
)
117 self
.set_default_size(-1, gtk
.gdk
.screen_height() / 3)
121 global preferences_box
122 preferences_box
= None
124 class KeyList(gtk
.VBox
):
126 gtk
.VBox
.__init
__(self
, False, 0)
128 label
= gtk
.Label('')
129 label
.set_markup('<i>You have said that you trust these keys to sign software updates.</i>')
130 label
.set_padding(4, 4)
131 label
.set_alignment(0, 0.5)
132 self
.pack_start(label
, False, True, 0)
134 trusted_keys
= gtk
.TreeStore(str, object)
135 tv
= gtk
.TreeView(trusted_keys
)
136 tc
= gtk
.TreeViewColumn('Trusted keys', gtk
.CellRendererText(), text
= 0)
138 swin
= gtk
.ScrolledWindow(None, None)
139 swin
.set_shadow_type(gtk
.SHADOW_IN
)
140 swin
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_ALWAYS
)
142 trust
.trust_db
.ensure_uptodate()
143 trust
.trust_db
.watchers
.append(lambda: self
.update_keys(trusted_keys
))
144 self
.pack_start(swin
, True, True, 0)
145 self
.update_keys(trusted_keys
)
147 def remove_key(fingerprint
, domain
):
148 trust
.trust_db
.untrust_key(fingerprint
, domain
)
149 trust
.trust_db
.notify()
151 def trusted_keys_button_press(tv
, bev
):
152 if bev
.type == gtk
.gdk
.BUTTON_PRESS
and bev
.button
== 3:
153 pos
= tv
.get_path_at_pos(int(bev
.x
), int(bev
.y
))
156 path
, col
, x
, y
= pos
160 domain
= trusted_keys
[path
[:-1]][0]
161 key
= trusted_keys
[path
][1]
165 item
= gtk
.MenuItem('Remove key for "%s"' % key
.get_short_name())
166 item
.connect('activate',
167 lambda item
, fp
= key
.fingerprint
, d
= domain
: remove_key(fp
, d
))
171 menu
.popup(None, None, None, bev
.button
, bev
.time
)
174 tv
.connect('button-press-event', trusted_keys_button_press
)
176 def update_keys(self
, trusted_keys
):
179 for fingerprint
in trust
.trust_db
.keys
:
180 key
= gpg
.load_key(fingerprint
)
181 for domain
in trust
.trust_db
.keys
[fingerprint
]:
182 if domain
not in domains
:
183 domains
[domain
] = Set()
184 domains
[domain
].add(key
)
185 for domain
in domains
:
186 iter = trusted_keys
.append(None, [domain
, None])
187 for key
in domains
[domain
]:
188 trusted_keys
.append(iter, [key
.name
, key
])
190 preferences_box
= None
191 def show_preferences():
192 global preferences_box
193 if preferences_box
is not None:
194 preferences_box
.present()
196 preferences_box
= Preferences()
197 preferences_box
.show()
199 gui_help
= help_box
.HelpBox("Zero Install Preferences Help",
202 There are three ways to control which implementations are chosen. You can adjust the \
203 network policy and the overall stability policy, which affect all interfaces, or you \
204 can edit the policy of individual interfaces."""),
207 The 'Network use' option controls how the injector uses the network. If off-line, \
208 the network is not used at all. If 'Minimal' is selected then the injector will use \
209 the network if needed, but only if it has no choice. It will run an out-of-date \
210 version rather than download a newer one. If 'Full' is selected, the injector won't \
211 worry about how much it downloads, but will always pick the version it thinks is best."""),
214 The feed files, which provide the information about which versions are \
215 available, are also cached. To update them, click on 'Refresh all now'. You can also \
216 get the injector to check for new versions automatically from time to time using \
217 the Freshness setting."""),
219 ('Help test new versions', """
220 The overall stability policy can either be to prefer stable versions, or to help test \
221 new versions. Choose whichever suits you. Since different programmers have different \
222 ideas of what 'stable' means, you may wish to override this on a per-interface basis.
224 To set the policy for an interface individually, select it in the main window and \
225 click on 'Interface Properties'. See that dialog's help text for more information."""),
228 This section lists all keys which you currently trust. When fetching a new program or \
229 updates for an existing one, the feed must be signed by one of these keys. If not, \
230 you will be prompted to confirm that you trust the new key, and it will then be added \
231 to this list. To remove a key, right-click on it and choose 'Remove' from the menu."""),