Support downloads from GUI.
[zeroinstall.git] / download_box.py
blobeb69785d6030e4d2fca4617ab42901bf462ad33b
1 import gtk
2 import os
4 from model import SafeException
5 from gui import policy
6 from dialog import Dialog
7 import download
8 import dialog
10 def pretty_size(size):
11 return str(size) + ' b'
13 def download_and_run(mainwindow, prog_args):
14 """If all downloads are ready, runs the program. Otherwise,
15 hides mainwindow, shows the download progress box and then runs
16 it. On error, mainwindow is re-shown."""
17 downloads = []
18 for iface, impl in policy.get_uncached_implementations():
19 if not impl.download_sources:
20 raise SafeException("Implementation " + impl + " of "
21 "interface " + iface + " cannot be "
22 "downloaded (no download locations given in "
23 "interface!")
24 dl = download.begin_impl_download(impl.download_sources[0],
25 force = True)
26 downloads.append((iface, dl))
27 def run_it():
28 import run
29 try:
30 run.execute(policy, prog_args)
31 mainwindow.destroy()
32 except SafeException, ex:
33 box = gtk.MessageDialog(self, gtk.DIALOG_MODAL,
34 gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
35 str(ex))
36 box.run()
37 box.destroy()
38 mainwindow.show()
39 if downloads:
40 DownloadProgessBox(run_it, downloads, mainwindow).show()
41 else:
42 run_it()
44 class DownloadProgessBox(Dialog):
45 mainwindow = None
46 run_it = None
47 n_downloads = None
48 idle_timeout = None
50 def __init__(self, run_it, downloads, mainwindow):
51 Dialog.__init__(self)
52 self.set_title('Downloading, please wait...')
53 self.mainwindow = mainwindow
54 self.run_it = run_it
55 self.n_downloads = 0
57 self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
59 table = gtk.Table(len(downloads) + 1, 3)
60 self.vbox.pack_start(table, False, False, 0)
61 table.set_row_spacings(4)
62 table.set_col_spacings(10)
63 table.set_border_width(10)
65 bars = []
67 row = 0
68 for iface, dl in downloads:
69 bar = gtk.ProgressBar()
70 bars.append((dl, bar))
71 table.attach(gtk.Label(iface.get_name()),
72 0, 1, row, row + 1)
73 table.attach(gtk.Label(pretty_size(dl.source.size)),
74 1, 2, row, row + 1)
75 table.attach(bar, 2, 3, row, row + 1)
76 row += 1
77 self.start_download(dl)
79 mainwindow.hide()
80 self.vbox.show_all()
82 def resp(box, resp):
83 for iface, dl in downloads:
84 dl.abort()
85 gtk.timeout_remove(self.idle_timeout)
86 self.idle_timeout = None
87 self.destroy()
88 mainwindow.show()
89 self.connect('response', resp)
91 def update_bars():
92 if self.n_downloads == 0:
93 self.run_it()
94 return False
95 for dl, bar in bars:
96 perc = dl.get_current_fraction()
97 bar.set_fraction(perc)
98 return True
100 self.idle_timeout = gtk.timeout_add(250, update_bars)
102 def start_download(self, dl):
103 error_stream = dl.start()
104 def error_ready(src, cond):
105 got = os.read(src.fileno(), 100)
106 if not got:
107 error_stream.close()
108 self.n_downloads -= 1
109 try:
110 data = dl.error_stream_closed()
111 except download.DownloadError, ex:
112 dialog.alert(self,
113 "Error downloading '%s':\n\n%s" %
114 (dl.url, ex))
115 try:
116 policy.add_to_cache(dl.source, data)
117 except SafeException, ex:
118 dialog.alert(self,
119 "Error unpacking '%s':\n\n%s" %
120 (dl.url, ex))
121 return False
122 dl.error_stream_data(got)
123 return True
125 self.n_downloads += 1
126 gtk.input_add(error_stream, gtk.gdk.INPUT_READ, error_ready)