Continue automatically if versions haven't changed.
[zeroinstall.git] / gui.py
blob29461668f9b691f2ebfe8d984897722fa25a0d7b
1 import gtk, os, gobject, sys
3 from zeroinstall.injector.policy import Policy
4 from zeroinstall.injector import download
5 from zeroinstall.injector.model import SafeException
6 from zeroinstall.injector.reader import InvalidInterface
7 import dialog
8 from checking import CheckingBox
10 version = '0.7'
12 # Singleton Policy
13 policy = None
15 class GUIPolicy(Policy):
16 window = None
17 pulse = None
18 monitored_downloads = None
19 checking = None # GtkDialog ("Checking for updates...")
20 original_implementation = None
22 def __init__(self, interface, prog_args, download_only, refresh):
23 Policy.__init__(self, interface)
24 global policy
25 assert policy is None
26 policy = self
27 self.monitored_downloads = []
29 import mainwindow
30 self.window = mainwindow.MainWindow(prog_args, download_only)
31 root = policy.get_interface(policy.root)
32 self.window.browser.set_root(root)
34 if refresh:
35 if root.name is not None:
36 self.checking = CheckingBox(root)
37 def checking_destroyed(c):
38 self.checking = None
39 if self.ready is False or self.versions_changed():
40 self.window.show()
41 else:
42 import download_box
43 download_box.download_with_gui(self.window, prog_args,
44 run_afterwards = not download_only)
45 self.checking.connect('destroy', checking_destroyed)
47 self.refresh_all(force = False)
49 def monitor_download(self, dl):
50 self.monitored_downloads.append(dl)
52 error_stream = dl.start()
53 def error_ready(src, cond):
54 got = os.read(src.fileno(), 100)
55 if not got:
56 error_stream.close()
57 self.monitored_downloads.remove(dl)
58 if len(self.monitored_downloads) == 0:
59 gobject.source_remove(self.pulse)
60 self.window.progress.hide()
61 if self.checking:
62 self.checking.updates_done()
63 self.pulse = None
64 try:
65 data = dl.error_stream_closed()
66 self.check_signed_data(dl, data)
67 except download.DownloadError, ex:
68 dialog.alert(self.window,
69 "Error downloading interface '%s':\n\n%s" %
70 (dl.interface.uri, ex))
71 except InvalidInterface, ex:
72 dialog.alert(self.window,
73 "Syntax error in downloaded interface '%s':\n\n%s" %
74 (dl.interface.uri, ex))
75 except SafeException, ex:
76 dialog.alert(self.window,
77 "Error updating interface '%s':\n\n%s" %
78 (dl.interface.uri, ex))
79 return False
80 dl.error_stream_data(got)
81 return True
83 gobject.io_add_watch(error_stream,
84 gobject.IO_IN | gobject.IO_HUP,
85 error_ready)
87 if self.pulse is None:
88 def pulse():
89 if self.checking:
90 self.checking.progress.pulse()
91 else:
92 self.window.progress.pulse()
93 return True
94 self.pulse = gobject.timeout_add(50, pulse)
95 self.window.progress.show()
97 def recalculate(self):
98 Policy.recalculate(self)
99 try:
100 self.ready
101 except:
102 self.ready = True
103 print >>sys.stderr, "Your version of the injector is very old. " \
104 "Try upgrading (http://0install.net/injector.html)"
105 else:
106 self.window.set_response_sensitive(gtk.RESPONSE_OK, self.ready)
108 def confirm_trust_keys(self, interface, sigs, iface_xml):
109 import trust_box
110 trust_box.confirm_trust(interface, sigs, iface_xml)
112 def main(self):
113 if self.checking:
114 self.checking.show()
115 else:
116 self.window.show()
117 gtk.main()
119 def get_best_source(self, impl):
120 """Return the best download source for this implementation."""
121 return impl.download_sources[0]
123 # XXX: Remove this. Moved to Policy.
124 def refresh_all(self, force = True):
125 for x in self.walk_interfaces():
126 self.begin_iface_download(x, force)
128 def abort_all_downloads(self):
129 for x in self.monitored_downloads[:]:
130 x.abort()
132 def set_original_implementations(self):
133 assert self.original_implementation is None
134 self.original_implementation = policy.implementation.copy()
136 def versions_changed(self):
137 """Return whether we have now chosen any different implementations.
138 If so, we want to show the dialog to the user to confirm the new ones."""
139 assert self.ready
140 if not self.original_implementation:
141 print "No originals"
142 return True # Shouldn't happen?
143 if len(self.original_implementation) != len(self.implementation):
144 print "Size changed"
145 return True
146 for iface in self.original_implementation:
147 old = self.original_implementation[iface]
148 if old is None:
149 print "Old interface is None"
150 return True
151 new = self.implementation.get(iface, None)
152 if new is None:
153 print "New interface is None"
154 return True
155 if old.id != new.id:
156 print "IDs differ"
157 return True
158 return False
160 def pretty_size(size):
161 if size is None:
162 return '?'
163 if size < 2048:
164 return '%d bytes' % size
165 size = float(size)
166 for unit in ('Kb', 'Mb', 'Gb', 'Tb'):
167 size /= 1024
168 if size < 2048:
169 break
170 return '%.1f %s' % (size, unit)