The GUI now returns an XML selections document in all cases, rather than
[zeroinstall.git] / zeroinstall / 0launch-gui / download_box.py
blobd7840b5f67f15a9254ea971bcd6b9f27d7f39441
1 import gtk
2 import os, sys
3 import sets # Note: for Python 2.3; frozenset is only in Python 2.4
5 from zeroinstall.injector.model import SafeException
6 from zeroinstall.injector import download, writer
7 from gui import policy, pretty_size
8 from dialog import Dialog
10 import warnings
11 warnings.filterwarnings('ignore', category = DeprecationWarning, module='download_box')
13 def download_with_gui(mainwindow):
14 """If all downloads are ready, prints the selected versions and exits. Otherwise,
15 hides mainwindow, shows the download progress box and then prints them.
16 On error, mainwindow is re-shown and returns False. Before starting,
17 any current downloads (interfaces) are aborted.
18 On success, calls sys.exit(0)."""
19 try:
20 policy.abort_all_downloads()
22 # Existing downloads don't disappear until the kill signal takes
23 # effect. Rather than waiting, just filter them out later.
24 existing_downloads = sets.ImmutableSet(policy.monitored_downloads)
26 for iface, impl in policy.get_uncached_implementations():
27 if not impl.download_sources:
28 raise SafeException("Implementation " + impl.id + " of "
29 "interface " + iface.get_name() + " cannot be "
30 "downloaded (no download locations given in "
31 "interface!)")
32 source = policy.get_best_source(impl)
33 if hasattr(policy, 'begin_impl_download'):
34 policy.begin_impl_download(impl, source, force = True)
35 else:
36 dl = download.begin_impl_download(source, force = True)
37 policy.monitor_download(dl)
38 def run_it():
39 policy.abort_all_downloads()
41 from zeroinstall.injector import selections
42 sels = selections.Selections(policy)
43 doc = sels.toDOM()
44 doc.writexml(sys.stdout)
45 sys.stdout.write('\n')
46 mainwindow.destroy()
47 sys.exit(0) # Success
48 if sets.ImmutableSet(policy.monitored_downloads) - existing_downloads:
49 DownloadProgessBox(run_it, mainwindow).show()
50 else:
51 run_it()
52 except SafeException, ex:
53 box = gtk.MessageDialog(None, gtk.DIALOG_MODAL,
54 gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
55 str(ex))
56 box.run()
57 box.destroy()
58 mainwindow.show()
60 class DownloadProgessBox(Dialog):
61 mainwindow = None
62 run_it = None
63 idle_timeout = None
64 errors = False
66 def __init__(self, run_it, mainwindow):
67 Dialog.__init__(self)
68 self.set_title('Downloading, please wait...')
69 self.mainwindow = mainwindow
70 assert self.mainwindow.download_box is None
71 self.mainwindow.download_box = self
72 self.run_it = run_it
74 self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
76 if hasattr(download, 'ImplementationDownload'):
77 downloads = [(x, x.source.size) for x in policy.handler.monitored_downloads
78 if isinstance(x, download.ImplementationDownload)]
79 else:
80 downloads = [(x, x.expected_size) for x in policy.handler.monitored_downloads
81 if hasattr(x, 'expected_size')]
83 table = gtk.Table(len(downloads) + 1, 3)
84 self.vbox.pack_start(table, False, False, 0)
85 table.set_row_spacings(4)
86 table.set_col_spacings(10)
87 table.set_border_width(10)
89 bars = []
91 row = 0
92 for dl, size in downloads:
93 bar = gtk.ProgressBar()
94 bars.append((dl, bar))
95 table.attach(gtk.Label(os.path.basename(dl.url)),
96 0, 1, row, row + 1)
97 table.attach(gtk.Label(pretty_size(size)),
98 1, 2, row, row + 1)
99 table.attach(bar, 2, 3, row, row + 1)
100 row += 1
102 mainwindow.hide()
103 self.vbox.show_all()
105 def resp(box, resp):
106 for dl, size in downloads:
107 dl.abort()
108 gtk.timeout_remove(self.idle_timeout)
109 self.idle_timeout = None
110 self.destroy()
111 mainwindow.download_box = None
112 mainwindow.show()
113 policy.recalculate()
114 self.connect('response', resp)
116 def update_bars():
117 if not policy.monitored_downloads:
118 if policy.get_uncached_implementations():
119 return False
120 self.destroy()
121 self.run_it()
122 for dl, bar in bars:
123 perc = dl.get_current_fraction()
124 if perc >= 0:
125 bar.set_fraction(perc)
126 return True
128 self.idle_timeout = gtk.timeout_add(250, update_bars)