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
8 from checking
import CheckingBox
15 class GUIPolicy(Policy
):
18 monitored_downloads
= None
19 checking
= None # GtkDialog ("Checking for updates...")
20 original_implementation
= None
25 def __init__(self
, interface
, prog_args
, download_only
, refresh
, main
):
26 Policy
.__init
__(self
, interface
)
31 self
.prog_args
= prog_args
32 self
.download_only
= download_only
33 self
.monitored_downloads
= []
36 self
.window
= mainwindow
.MainWindow(prog_args
, download_only
)
37 root
= policy
.get_interface(policy
.root
)
38 self
.window
.browser
.set_root(root
)
41 if root
.name
is not None:
42 self
.checking
= CheckingBox(root
)
44 self
.refresh_all(force
= False)
46 def show_details(self
):
47 """The checking box has disappeared. Should we show the details window, or
48 just run the program right now?"""
49 if self
.checking
.show_details
:
50 return True # User clicked on the Details button
52 return True # Not ready to start (can't find an implementation)
53 if self
.versions_changed():
54 return True # Confirm that the new version should be used
55 if self
.get_uncached_implementations():
56 return True # Need to download something; check first
59 def monitor_download(self
, dl
):
60 self
.monitored_downloads
.append(dl
)
62 error_stream
= dl
.start()
63 def error_ready(src
, cond
):
64 got
= os
.read(src
.fileno(), 100)
67 self
.monitored_downloads
.remove(dl
)
68 if len(self
.monitored_downloads
) == 0:
69 gobject
.source_remove(self
.pulse
)
70 self
.window
.progress
.hide()
73 data
= dl
.error_stream_closed()
74 self
.check_signed_data(dl
, data
)
75 except download
.DownloadError
, ex
:
76 dialog
.alert(self
.window
,
77 "Error downloading interface '%s':\n\n%s" %
78 (dl
.interface
.uri
, ex
))
79 except InvalidInterface
, ex
:
80 dialog
.alert(self
.window
,
81 "Syntax error in downloaded interface '%s':\n\n%s" %
82 (dl
.interface
.uri
, ex
))
83 except SafeException
, ex
:
84 dialog
.alert(self
.window
,
85 "Error updating interface '%s':\n\n%s" %
86 (dl
.interface
.uri
, ex
))
88 if len(self
.monitored_downloads
) == 0 and self
.checking
:
89 self
.checking
.updates_done(self
.versions_changed())
91 dl
.error_stream_data(got
)
94 gobject
.io_add_watch(error_stream
,
95 gobject
.IO_IN | gobject
.IO_HUP
,
98 if self
.pulse
is None:
101 self
.checking
.progress
.pulse()
103 self
.window
.progress
.pulse()
105 self
.pulse
= gobject
.timeout_add(50, pulse
)
106 self
.window
.progress
.show()
108 def recalculate(self
):
109 Policy
.recalculate(self
)
114 print >>sys
.stderr
, "Your version of the injector is very old. " \
115 "Try upgrading (http://0install.net/injector.html)"
117 self
.window
.set_response_sensitive(gtk
.RESPONSE_OK
, self
.ready
)
119 def confirm_trust_keys(self
, interface
, sigs
, iface_xml
):
121 trust_box
.confirm_trust(interface
, sigs
, iface_xml
)
126 if not self
.monitored_downloads
:
127 self
.checking
.updates_done(self
.versions_changed())
128 dialog
.wait_for_no_windows()
129 show_details
= self
.show_details()
136 download_box
.download_with_gui(self
.window
, self
.prog_args
, main
= self
.main_exec
,
137 run_afterwards
= not self
.download_only
)
142 def get_best_source(self
, impl
):
143 """Return the best download source for this implementation."""
144 if impl
.download_sources
:
145 return impl
.download_sources
[0]
148 def refresh_all(self
, force
= True):
149 if hasattr(Policy
, 'refresh_all'):
150 Policy
.refresh_all(self
, force
)
152 # XXX: Remove this. Moved to Policy.
153 for x
in self
.walk_interfaces():
154 self
.begin_iface_download(x
, force
)
156 def abort_all_downloads(self
):
157 for x
in self
.monitored_downloads
[:]:
160 def set_original_implementations(self
):
161 assert self
.original_implementation
is None
162 self
.original_implementation
= policy
.implementation
.copy()
164 def versions_changed(self
):
165 """Return whether we have now chosen any different implementations.
166 If so, we want to show the dialog to the user to confirm the new ones."""
169 if not self
.original_implementation
:
170 return True # Shouldn't happen?
171 if len(self
.original_implementation
) != len(self
.implementation
):
173 for iface
in self
.original_implementation
:
174 old
= self
.original_implementation
[iface
]
177 new
= self
.implementation
.get(iface
, None)
184 def pretty_size(size
):
188 return '%d bytes' % size
190 for unit
in ('Kb', 'Mb', 'Gb', 'Tb'):
194 return '%.1f %s' % (size
, unit
)