Added accelerator for Download button.
[zeroinstall.git] / mainwindow.py
blobf582f4a7495168e449292d1dc7f925916e3fe186
1 import gtk
2 import sys
3 from iface_browser import InterfaceBrowser
4 import help_box
5 from gui import policy
6 from dialog import Dialog
7 from zeroinstall.injector.model import stable, testing, network_levels, SafeException
8 from freshness import freshness_levels, Freshness
10 tips = gtk.Tooltips()
12 class MainWindow(Dialog):
13 progress = None
14 browser = None
16 def __init__(self, prog_args, download_only):
17 Dialog.__init__(self)
18 self.set_title('Dependency Injector')
19 self.set_default_size(gtk.gdk.screen_width() / 3, 300)
21 self.connect('destroy', lambda w: self.destroyed())
23 # Network use
24 hbox = gtk.HBox(False, 2)
25 self.vbox.pack_start(hbox, False, True, 0)
26 hbox.set_border_width(4)
28 eb = gtk.EventBox() # For the tooltip
29 network = gtk.combo_box_new_text()
30 eb.add(network)
31 for level in network_levels:
32 network.append_text(level.capitalize())
33 network.set_active(list(network_levels).index(policy.network_use))
34 hbox.pack_start(gtk.Label('Network use:'), False, True, 0)
35 hbox.pack_start(eb, True, True, 2)
36 def set_network_use(combo):
37 policy.network_use = network_levels[network.get_active()]
38 policy.save_config()
39 policy.recalculate()
40 network.connect('changed', set_network_use)
41 tips.set_tip(eb, _('This controls whether the injector will always try to '
42 'run the best version, downloading it if needed, or whether it will prefer '
43 'to run an older version that is already on your machine.'))
45 hbox.show_all()
47 # Freshness
48 hbox = gtk.HBox(False, 2)
49 self.vbox.pack_start(hbox, False, True, 0)
50 hbox.set_border_width(4)
52 times = [x.time for x in freshness_levels]
53 if policy.freshness not in times:
54 freshness_levels.append(Freshness(policy.freshness,
55 '%d seconds' % policy.freshness))
56 times.append(policy.freshness)
57 eb = gtk.EventBox() # For the tooltip
58 freshness = gtk.combo_box_new_text()
59 eb.add(freshness)
60 for level in freshness_levels:
61 freshness.append_text(str(level))
62 freshness.set_active(times.index(policy.freshness))
63 hbox.pack_start(gtk.Label('Freshness:'), False, True, 0)
64 hbox.pack_start(eb, True, True, 2)
65 def set_freshness(combo):
66 policy.freshness = freshness_levels[freshness.get_active()].time
67 policy.save_config()
68 policy.recalculate()
69 freshness.connect('changed', set_freshness)
70 tips.set_tip(eb, _('Sets how often the injector will check for new versions.'))
72 button = gtk.Button('_Refresh all now')
73 button.connect('clicked', lambda b: policy.refresh_all())
74 tips.set_tip(button, _('Check all the interfaces below for updates.'))
75 hbox.pack_start(button, False, True, 2)
77 hbox.show_all()
79 # Tree view
80 self.browser = InterfaceBrowser()
81 self.vbox.pack_start(self.browser, True, True, 0)
82 self.browser.show()
84 # Select versions
85 hbox = gtk.HBox(False, 2)
86 self.vbox.pack_start(hbox, False, True, 0)
87 hbox.set_border_width(4)
89 button = gtk.Button('Interface Properties...')
90 self.browser.edit_properties.connect_proxy(button)
91 hbox.pack_start(button, False, True, 0)
92 tips.set_tip(button, _('See and edit the details of the selected interface.'))
94 stable_toggle = gtk.CheckButton('Help test new versions')
95 hbox.pack_start(stable_toggle, False, True, 0)
96 tips.set_tip(stable_toggle,
97 "Try out new versions as soon as they are available, instead of "
98 "waiting for them to be marked as 'stable'. "
99 "This sets the default policy. Click on 'Interface Properties...' "
100 "to set the policy for an individual interface.")
101 stable_toggle.set_active(policy.help_with_testing)
102 def toggle_stability(toggle):
103 policy.help_with_testing = toggle.get_active()
104 policy.save_config()
105 policy.recalculate()
106 stable_toggle.connect('toggled', toggle_stability)
108 hbox.show_all()
110 # Progress bar
111 self.progress = gtk.ProgressBar()
112 self.vbox.pack_start(self.progress, False, True, 0)
114 # Responses
116 self.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP)
117 self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
118 if download_only:
119 self.add_mixed_button('_Download', gtk.STOCK_NETWORK, gtk.RESPONSE_OK)
120 else:
121 self.add_button(gtk.STOCK_EXECUTE, gtk.RESPONSE_OK)
122 self.set_default_response(gtk.RESPONSE_OK)
123 self.default_widget.grab_focus()
125 def response(dialog, resp):
126 import download_box
127 if resp == gtk.RESPONSE_CANCEL:
128 self.destroy()
129 sys.exit(1)
130 elif resp == gtk.RESPONSE_OK:
131 download_box.download_with_gui(self, prog_args, main = policy.main_exec,
132 run_afterwards = not download_only)
133 elif resp == gtk.RESPONSE_HELP:
134 gui_help.display()
135 self.connect('response', response)
137 def destroyed(self):
138 policy.abort_all_downloads()
141 gui_help = help_box.HelpBox("Injector Help",
142 ('Overview', """
143 A program is made up of many different components, typically written by different \
144 groups of people. Each component is available in multiple versions. The injector is \
145 used when starting a program. Its job is to decide which implementation of each required \
146 component to use.
148 An interface describes what a component does. The injector starts with \
149 the interface for the program you want to run (like 'The Gimp') and chooses an \
150 implementation (like 'The Gimp 2.2.0'). However, this implementation \
151 will in turn depend on other interfaces, such as 'GTK' (which draws the menus \
152 and buttons). Thus, the injector must choose implementations of \
153 each dependency (each of which may require further interfaces, and so on)."""),
155 ('List of interfaces', """
156 The main window displays all these interfaces, and the version of each chosen \
157 implementation. The top-most one represents the program you tried to run, and each direct \
158 child is a dependency. The 'Fetch' column shows the amount of data that needs to be \
159 downloaded, or '(cached)' if it is already on this computer.
161 If you are happy with the choices shown, click on the Download (or Execute) button to \
162 download (and run) the program."""),
164 ('Choosing different versions', """
165 There are three ways to control which implementations are chosen. You can adjust the \
166 network policy and the overall stability policy, which affect all interfaces, or you \
167 can edit the policy of individual interfaces.
169 The 'Network use' option controls how the injector uses the network. If off-line, \
170 the network is not used at all. If 'Minimal' is selected then the injector will use \
171 the network if needed, but only if it has no choice. It will run an out-of-date \
172 version rather than download a newer one. If 'Full' is selected, the injector won't \
173 worry about how much it downloads, but will always pick the version it thinks is best.
175 The overall stability policy can either be to prefer stable versions, or to help test \
176 new versions. Choose whichever suits you. Since different programmers have different \
177 ideas of what 'stable' means, you may wish to override this on a per-interface basis \
178 (see below).
180 To set the policy for an interface individually, select it and click on 'Interface \
181 Properties'. See that dialog's help text for more information."""),
183 ('Freshness', """
184 The interface files, which provide the information about which versions are \
185 available, are also cached. To update them, click on 'Refresh all now'. You can also \
186 get the injector to check for new versions automatically from time to time using \
187 the Freshness setting."""))