GUI monitoring is now based on console monitoring.
[zeroinstall/zeroinstall-rsl.git] / zeroinstall / 0launch-gui / gui.py
blob6dc9b591f86a4418c5c5f540cfcbde36d4441121
1 import gtk, os, gobject, sys
2 import gtk.glade
4 from zeroinstall.injector.iface_cache import iface_cache
5 from zeroinstall.injector.policy import Policy
6 from zeroinstall.injector import download, handler
7 from zeroinstall.injector.model import SafeException
8 from zeroinstall.injector.reader import InvalidInterface
9 import dialog
10 from checking import CheckingBox
12 version = '0.31'
14 # Singleton Policy
15 policy = None
17 gladefile = os.path.join(os.path.dirname(__file__), 'zero-install.glade')
19 # Wrapped for glade widget tree that throws a sensible exception if the widget isn't found
20 class Template:
21 def __init__(self, root):
22 self.widgets = gtk.glade.XML(gladefile, root)
23 self.root = root
25 def get_widget(self, name = None):
26 if not name:
27 name = self.root
28 widget = self.widgets.get_widget(name)
29 assert widget, "Widget '%s' not found in glade file '%s'" % (name, gladefile)
30 return widget
32 class GUIHandler(handler.Handler):
33 monitored_downloads = None
34 dl_callbacks = None # Download -> [ callback ]
35 pulse = None
36 policy = None
38 def __init__(self, policy):
39 handler.Handler.__init__(self)
40 self.policy = policy
42 def downloads_changed(self):
43 print "Active downloads list is now: %s" % self.monitored_downloads
44 if self.monitored_downloads and self.pulse is None:
45 def pulse():
46 if self.policy.checking:
47 self.policy.checking.progress.pulse()
48 else:
49 self.policy.window.progress.pulse()
50 return True
51 self.pulse = gobject.timeout_add(50, pulse)
52 self.policy.window.progress.show()
53 elif len(self.monitored_downloads) == 0:
54 if self.pulse:
55 gobject.source_remove(self.pulse)
56 self.policy.window.progress.hide()
57 self.pulse = None
59 if self.policy.checking:
60 self.policy.checking.updates_done(self.policy.versions_changed())
62 def confirm_trust_keys(self, interface, sigs, iface_xml):
63 import trust_box
64 trust_box.confirm_trust(interface, sigs, iface_xml, parent = self.policy.checking or self.policy.window.window)
66 def report_error(self, ex):
67 dialog.alert(None, str(ex))
69 class GUIPolicy(Policy):
70 window = None
71 checking = None # GtkDialog ("Checking for updates...")
72 original_implementation = None
73 download_only = None
74 widgets = None # Glade
76 def __init__(self, interface, download_only, refresh, src = False, restrictions = None):
77 Policy.__init__(self, interface, GUIHandler(self), src = src)
78 self.solver.record_details = True
79 global policy
80 assert policy is None
81 policy = self
83 self.widgets = Template('main')
85 if restrictions:
86 for r in restrictions:
87 self.root_restrictions.append(r)
89 self.download_only = download_only
91 import mainwindow
92 self.window = mainwindow.MainWindow(download_only)
93 root = iface_cache.get_interface(self.root)
94 self.window.browser.set_root(root)
96 if refresh:
97 # If we have feeds then treat this as a refresh,
98 # even if we've never seen the main interface before.
99 # Used the first time the GUI is used, for example.
100 if root.name is not None or root.feeds:
101 self.checking = CheckingBox(root)
103 self.refresh_all(force = False)
105 def show_details(self):
106 """The checking box has disappeared. Should we show the details window, or
107 just run the program right now?"""
108 if self.checking.show_details:
109 return True # User clicked on the Details button
110 if not self.ready:
111 return True # Not ready to start (can't find an implementation)
112 if self.versions_changed():
113 return True # Confirm that the new version should be used
114 if self.get_uncached_implementations():
115 return True # Need to download something; check first
116 return False
118 def store_icon(self, interface, stream):
119 Policy.store_icon(self, interface, stream)
120 if self.window:
121 self.window.browser.build_tree()
123 def recalculate(self, fetch_stale_interfaces = True):
124 Policy.recalculate(self, fetch_stale_interfaces)
125 self.window.set_response_sensitive(gtk.RESPONSE_OK, self.ready)
127 def main(self):
128 if self.checking:
129 self.checking.show()
130 if not self.handler.monitored_downloads:
131 self.checking.updates_done(self.versions_changed())
132 dialog.wait_for_no_windows()
133 show_details = self.show_details()
134 self.checking = None
135 if show_details:
136 self.window.show()
137 gtk.main()
138 else:
139 import download_box
140 download_box.download_with_gui(self.window)
141 else:
142 self.window.show()
143 gtk.main()
145 def abort_all_downloads(self):
146 for dl in self.handler.monitored_downloads.values():
147 dl.abort()
149 def set_original_implementations(self):
150 assert self.original_implementation is None
151 self.original_implementation = policy.implementation.copy()
153 def versions_changed(self):
154 """Return whether we have now chosen any different implementations.
155 If so, we want to show the dialog to the user to confirm the new ones."""
156 if not self.ready:
157 return True
158 if not self.original_implementation:
159 return True # Shouldn't happen?
160 if len(self.original_implementation) != len(self.implementation):
161 return True
162 for iface in self.original_implementation:
163 old = self.original_implementation[iface]
164 if old is None:
165 return True
166 new = self.implementation.get(iface, None)
167 if new is None:
168 return True
169 if old.id != new.id:
170 return True
171 return False