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
):
63 return trust_box
.confirm_trust(interface
, sigs
, iface_xml
, parent
= self
.policy
.checking
or self
.policy
.window
.window
)
65 def report_error(self
, ex
):
66 dialog
.alert(None, str(ex
))
68 class GUIPolicy(Policy
):
70 checking
= None # GtkDialog ("Checking for updates...")
71 original_implementation
= None
73 widgets
= None # Glade
75 def __init__(self
, interface
, download_only
, src
= False, restrictions
= None):
76 Policy
.__init
__(self
, interface
, GUIHandler(self
), src
= src
)
77 self
.solver
.record_details
= True
82 self
.widgets
= Template('main')
85 for r
in restrictions
:
86 self
.root_restrictions
.append(r
)
88 self
.download_only
= download_only
91 self
.window
= mainwindow
.MainWindow(download_only
)
92 root
= iface_cache
.get_interface(self
.root
)
93 self
.window
.browser
.set_root(root
)
95 self
.watchers
.append(self
.update_display
)
97 def show_details(self
):
98 """The checking box has disappeared. Should we show the details window, or
99 just run the program right now?"""
100 if self
.checking
.show_details_clicked
.happened
:
101 return True # User clicked on the Details button
103 return True # Not ready to start (can't find an implementation)
104 if self
.versions_changed():
105 return True # Confirm that the new version should be used
106 if self
.get_uncached_implementations():
107 return True # Need to download something; check first
110 def store_icon(self
, interface
, stream
):
111 Policy
.store_icon(self
, interface
, stream
)
113 self
.window
.browser
.build_tree()
115 def update_display(self
):
116 self
.window
.set_response_sensitive(gtk
.RESPONSE_OK
, self
.ready
)
118 def main(self
, refresh
):
120 # If we have feeds then treat this as an update check,
121 # even if we've never seen the main interface before.
122 # Used the first time the GUI is used, for example.
123 root
= self
.get_interface(self
.root
)
124 if root
.name
is not None or root
.feeds
:
125 self
.checking
= CheckingBox(root
)
127 solved
= tasks
.Task(self
.solve_with_downloads(force
= refresh
), "solve_with_downloads")
133 blockers
= [solved
.finished
, self
.checking
.show_details_clicked
, self
.checking
.cancelled
]
136 tasks
.check(blockers
)
137 except Exception, ex
:
140 self
.checking
.updates_done(self
.versions_changed())
142 show_details
= self
.show_details() or error
147 dialog
.alert(self
.window
.window
, "Failed to check for updates: %s" % ex
)
150 from zeroinstall
.injector
import selections
151 sels
= selections
.Selections(policy
)
153 reply
= doc
.toxml('utf-8')
154 sys
.stdout
.write(('Length:%8x\n' % len(reply
)) + reply
)
155 self
.window
.destroy()
156 sys
.exit(0) # Success
159 yield solved
.finished
161 tasks
.check(solved
.finished
)
162 except Exception, ex
:
164 traceback
.print_exc()
165 dialog
.alert(self
.window
.window
, str(ex
))
168 def abort_all_downloads(self
):
169 for dl
in self
.handler
.monitored_downloads
.values():
172 def set_original_implementations(self
):
173 assert self
.original_implementation
is None
174 self
.original_implementation
= policy
.implementation
.copy()
176 def versions_changed(self
):
177 """Return whether we have now chosen any different implementations.
178 If so, we want to show the dialog to the user to confirm the new ones."""
181 if not self
.original_implementation
:
182 return True # Shouldn't happen?
183 if len(self
.original_implementation
) != len(self
.implementation
):
185 for iface
in self
.original_implementation
:
186 old
= self
.original_implementation
[iface
]
189 new
= self
.implementation
.get(iface
, None)