1 import gtk
, os
, gobject
, sys
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 from zeroinstall
.support
import tasks
11 from checking
import CheckingBox
18 gladefile
= os
.path
.join(os
.path
.dirname(__file__
), 'zero-install.glade')
20 # Wrapped for glade widget tree that throws a sensible exception if the widget isn't found
22 def __init__(self
, root
):
23 self
.widgets
= gtk
.glade
.XML(gladefile
, root
)
26 def get_widget(self
, name
= None):
29 widget
= self
.widgets
.get_widget(name
)
30 assert widget
, "Widget '%s' not found in glade file '%s'" % (name
, gladefile
)
33 class GUIHandler(handler
.Handler
):
34 dl_callbacks
= None # Download -> [ callback ]
38 def __init__(self
, policy
):
39 handler
.Handler
.__init
__(self
)
42 def downloads_changed(self
):
43 if self
.monitored_downloads
and self
.pulse
is None:
45 if self
.policy
.checking
:
46 self
.policy
.checking
.progress
.pulse()
48 self
.policy
.window
.progress
.pulse()
50 self
.pulse
= gobject
.timeout_add(50, pulse
)
51 self
.policy
.window
.progress
.show()
52 elif len(self
.monitored_downloads
) == 0:
54 gobject
.source_remove(self
.pulse
)
55 self
.policy
.window
.progress
.hide()
58 if self
.policy
.checking
:
59 self
.policy
.checking
.updates_done(self
.policy
.versions_changed())
61 def confirm_trust_keys(self
, interface
, sigs
, iface_xml
):
62 if self
.policy
.checking
:
63 # Switch to main view if there are keys to be confirmed
64 self
.policy
.checking
.updates_done(True)
65 self
.policy
.window
.show()
67 return trust_box
.confirm_trust(interface
, sigs
, iface_xml
, parent
= self
.policy
.window
.window
)
69 def report_error(self
, ex
):
70 dialog
.alert(None, str(ex
))
72 class GUIPolicy(Policy
):
74 checking
= None # GtkDialog ("Checking for updates...")
75 original_implementation
= None
77 widgets
= None # Glade
79 def __init__(self
, interface
, download_only
, src
= False, restrictions
= None):
80 Policy
.__init
__(self
, interface
, GUIHandler(self
), src
= src
)
81 self
.solver
.record_details
= True
86 self
.widgets
= Template('main')
89 for r
in restrictions
:
90 self
.root_restrictions
.append(r
)
92 self
.download_only
= download_only
95 self
.window
= mainwindow
.MainWindow(download_only
)
96 root
= iface_cache
.get_interface(self
.root
)
97 self
.window
.browser
.set_root(root
)
99 self
.watchers
.append(self
.update_display
)
101 def show_details(self
):
102 """The checking box has disappeared. Should we show the details window, or
103 just run the program right now?"""
104 if self
.checking
.show_details_clicked
.happened
:
105 return True # User clicked on the Details button
107 return True # Not ready to start (can't find an implementation)
108 if self
.versions_changed():
109 return True # Confirm that the new version should be used
110 if self
.get_uncached_implementations():
111 return True # Need to download something; check first
114 def update_display(self
):
115 self
.window
.set_response_sensitive(gtk
.RESPONSE_OK
, self
.ready
)
117 def main(self
, refresh
):
119 # If we have feeds then treat this as an update check,
120 # even if we've never seen the main interface before.
121 # Used the first time the GUI is used, for example.
122 root
= iface_cache
.get_interface(self
.root
)
123 if root
.name
is not None or root
.feeds
:
124 self
.checking
= CheckingBox(root
)
126 solved
= self
.solve_with_downloads(force
= refresh
)
132 blockers
= [solved
, self
.checking
.show_details_clicked
, self
.checking
.cancelled
]
135 tasks
.check(blockers
)
136 except Exception, ex
:
139 if not (self
.checking
.show_details_clicked
.happened
or self
.checking
.cancelled
.happened
):
140 self
.checking
.updates_done(self
.versions_changed())
141 blockers
= tasks
.TimeoutBlocker(0.5, "checking result timeout")
143 tasks
.check(blockers
)
144 self
.checking
.destroy()
146 show_details
= self
.show_details() or error
151 dialog
.alert(self
.window
.window
, "Failed to check for updates: %s" % ex
)
154 from zeroinstall
.injector
import selections
155 sels
= selections
.Selections(policy
)
157 reply
= doc
.toxml('utf-8')
158 sys
.stdout
.write(('Length:%8x\n' % len(reply
)) + reply
)
159 self
.window
.destroy()
160 sys
.exit(0) # Success
166 except Exception, ex
:
168 traceback
.print_exc()
169 dialog
.alert(self
.window
.window
, str(ex
))
172 def abort_all_downloads(self
):
173 for dl
in self
.handler
.monitored_downloads
.values():
176 def set_original_implementations(self
):
177 assert self
.original_implementation
is None
178 self
.original_implementation
= policy
.implementation
.copy()
180 def versions_changed(self
):
181 """Return whether we have now chosen any different implementations.
182 If so, we want to show the dialog to the user to confirm the new ones."""
185 if not self
.original_implementation
:
186 return True # Shouldn't happen?
187 if len(self
.original_implementation
) != len(self
.implementation
):
189 for iface
in self
.original_implementation
:
190 old
= self
.original_implementation
[iface
]
193 new
= self
.implementation
.get(iface
, None)