Run/Download is now a toggle button.
[zeroinstall/zeroinstall-mseaborn.git] / zeroinstall / 0launch-gui / mainwindow.py
blob16caa32ac5c45a0ded7fd159f2e253586609d5b8
1 import gtk
2 from logging import warn
3 import os, sys
4 from zeroinstall import SafeException
5 from zeroinstall.support import tasks
6 from iface_browser import InterfaceBrowser
7 import help_box
8 from gui import policy
9 import dialog
11 tips = gtk.Tooltips()
13 SHOW_PREFERENCES = 0
15 class MainWindow:
16 progress = None
17 browser = None
18 window = None
19 cancel_download_and_run = None
21 def __init__(self, download_only):
22 widgets = policy.widgets
24 self.window = widgets.get_widget('main')
25 self.window.set_default_size(gtk.gdk.screen_width() * 2 / 5, 300)
27 self.progress = widgets.get_widget('progress')
29 self.window.connect('destroy', lambda w: self.destroyed())
31 cache = widgets.get_widget('show_cache')
32 cache.connect('clicked',
33 lambda b: os.spawnlp(os.P_WAIT, sys.argv[0], sys.argv[0], '-c'))
35 widgets.get_widget('refresh').connect('clicked', lambda b: policy.refresh_all())
37 # Tree view
38 self.browser = InterfaceBrowser(widgets.get_widget('components'))
40 prefs = widgets.get_widget('preferences')
41 self.window.action_area.set_child_secondary(prefs, True)
43 # Glade won't let me add this to the template!
44 if download_only:
45 run_button = dialog.MixedButton("_Download", gtk.STOCK_EXECUTE, button = gtk.ToggleButton())
46 else:
47 run_button = dialog.MixedButton("_Run", gtk.STOCK_EXECUTE, button = gtk.ToggleButton())
48 self.window.add_action_widget(run_button, gtk.RESPONSE_OK)
49 run_button.show_all()
50 run_button.set_flags(gtk.CAN_DEFAULT)
52 self.window.set_default_response(gtk.RESPONSE_OK)
53 self.window.default_widget.grab_focus()
55 def response(dialog, resp):
56 if resp in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT):
57 self.window.destroy()
58 sys.exit(1)
59 elif resp == gtk.RESPONSE_OK:
60 if self.cancel_download_and_run:
61 self.cancel_download_and_run.trigger()
62 if run_button.get_active():
63 self.cancel_download_and_run = tasks.Blocker("cancel downloads")
64 tasks.Task(self.download_and_run(run_button, self.cancel_download_and_run), "download and run")
65 elif resp == gtk.RESPONSE_HELP:
66 gui_help.display()
67 elif resp == SHOW_PREFERENCES:
68 import preferences
69 preferences.show_preferences()
70 self.window.connect('response', response)
72 def destroy(self):
73 self.window.destroy()
75 def show(self):
76 self.window.show()
78 def set_response_sensitive(self, response, sensitive):
79 self.window.set_response_sensitive(response, sensitive)
81 def destroyed(self):
82 policy.abort_all_downloads()
84 def download_and_run(self, run_button, cancelled):
85 try:
86 task = tasks.Task(policy.download_impls(), "download implementations")
88 blockers = [task.finished, cancelled]
89 yield blockers
90 tasks.check(blockers)
92 if cancelled.happened:
93 policy.abort_all_downloads()
94 return
96 if policy.get_uncached_implementations():
97 dialog.alert('Not all downloads succeeded; cannot run program.')
98 else:
99 from zeroinstall.injector import selections
100 sels = selections.Selections(policy)
101 doc = sels.toDOM()
102 reply = doc.toxml('utf-8')
103 sys.stdout.write(('Length:%8x\n' % len(reply)) + reply)
104 self.window.destroy()
105 sys.exit(0) # Success
106 except SafeException, ex:
107 run_button.set_active(False)
108 policy.handler.report_error(ex)
109 except Exception, ex:
110 run_button.set_active(False)
111 import traceback
112 traceback.print_exc()
113 policy.handler.report_error(ex)
115 gui_help = help_box.HelpBox("Injector Help",
116 ('Overview', """
117 A program is made up of many different components, typically written by different \
118 groups of people. Each component is available in multiple versions. The injector is \
119 used when starting a program. Its job is to decide which implementation of each required \
120 component to use.
122 An interface describes what a component does. The injector starts with \
123 the interface for the program you want to run (like 'The Gimp') and chooses an \
124 implementation (like 'The Gimp 2.2.0'). However, this implementation \
125 will in turn depend on other interfaces, such as 'GTK' (which draws the menus \
126 and buttons). Thus, the injector must choose implementations of \
127 each dependency (each of which may require further interfaces, and so on)."""),
129 ('List of interfaces', """
130 The main window displays all these interfaces, and the version of each chosen \
131 implementation. The top-most one represents the program you tried to run, and each direct \
132 child is a dependency. The 'Fetch' column shows the amount of data that needs to be \
133 downloaded, or '(cached)' if it is already on this computer.
135 If you are happy with the choices shown, click on the Download (or Run) button to \
136 download (and run) the program."""),
138 ('Choosing different versions', """
139 To control which implementations (versions) are chosen you can click on Preferences \
140 and adjust the network policy and the overall stability policy. These settings affect \
141 all programs run using Zero Install.
143 Alternatively, you can edit the policy of an individual interface by selecting it \
144 and clicking on the 'Interface Properties' button. \
145 See that dialog's help text for more information.
147 Right-click on an interface in the list for a menu.
148 """),
150 ('Reporting bugs', """
151 To report a bug, right-click over the interface which you think contains the problem \
152 and choose 'Report a Bug...' from the menu. If you don't know which one is the cause, \
153 choose the top one (i.e. the program itself). The program's author can reassign the \
154 bug if necessary, or switch to using a different version of the library.
155 """),
157 ('The cache', """
158 Each version of a program that is downloaded is stored in the Zero Install cache. This \
159 means that it won't need to be downloaded again each time you run the program. Click on \
160 the 'Show Cache' button to see what is currently in the cache, or to remove versions \
161 you no longer need to save disk space."""),