Put description area in its own class.
[zeroinstall.git] / download_box.py
bloba22c39d93d901cae932570d933cd0f73aed37fab
1 import gtk
2 import os
4 from model import SafeException
5 from gui import policy, pretty_size
6 from dialog import Dialog
7 import download
8 import dialog
10 def download_with_gui(mainwindow, prog_args, run_afterwards):
11 """If all downloads are ready, runs the program. Otherwise,
12 hides mainwindow, shows the download progress box and then runs
13 it. On error, mainwindow is re-shown."""
14 downloads = []
15 for iface, impl in policy.get_uncached_implementations():
16 if not impl.download_sources:
17 raise SafeException("Implementation " + impl.id + " of "
18 "interface " + iface.get_name() + " cannot be "
19 "downloaded (no download locations given in "
20 "interface!")
21 dl = download.begin_impl_download(policy.get_best_source(impl),
22 force = True)
23 downloads.append((iface, dl))
24 def run_it():
25 if not run_afterwards:
26 mainwindow.destroy()
27 return
28 import run
29 try:
30 run.execute(policy, prog_args)
31 mainwindow.destroy()
32 except SafeException, ex:
33 box = gtk.MessageDialog(None, 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
49 errors = False
51 def __init__(self, run_it, downloads, mainwindow):
52 Dialog.__init__(self)
53 self.set_title('Downloading, please wait...')
54 self.mainwindow = mainwindow
55 self.run_it = run_it
56 self.n_downloads = 0
58 self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
60 table = gtk.Table(len(downloads) + 1, 3)
61 self.vbox.pack_start(table, False, False, 0)
62 table.set_row_spacings(4)
63 table.set_col_spacings(10)
64 table.set_border_width(10)
66 bars = []
68 row = 0
69 for iface, dl in downloads:
70 bar = gtk.ProgressBar()
71 bars.append((dl, bar))
72 table.attach(gtk.Label(iface.get_name()),
73 0, 1, row, row + 1)
74 table.attach(gtk.Label(pretty_size(dl.source.size)),
75 1, 2, row, row + 1)
76 table.attach(bar, 2, 3, row, row + 1)
77 row += 1
78 self.start_download(dl)
80 mainwindow.hide()
81 self.vbox.show_all()
83 def resp(box, resp):
84 for iface, dl in downloads:
85 dl.abort()
86 gtk.timeout_remove(self.idle_timeout)
87 self.idle_timeout = None
88 self.destroy()
89 mainwindow.show()
90 self.connect('response', resp)
92 def update_bars():
93 if self.n_downloads == 0:
94 if not self.errors:
95 self.destroy()
96 self.run_it()
97 return False
98 for dl, bar in bars:
99 perc = dl.get_current_fraction()
100 bar.set_fraction(perc)
101 return True
103 self.idle_timeout = gtk.timeout_add(250, update_bars)
105 def start_download(self, dl):
106 error_stream = dl.start()
107 def error_ready(src, cond):
108 got = os.read(src.fileno(), 100)
109 if not got:
110 error_stream.close()
111 self.n_downloads -= 1
112 try:
113 data = dl.error_stream_closed()
114 policy.add_to_cache(dl.source, data)
115 except SafeException, ex:
116 label = gtk.Label("Error getting '%s':\n%s" % (dl.url, ex))
117 label.set_padding(4, 4)
118 self.vbox.pack_start(label, False, True, 2)
119 label.show()
120 self.errors = True
121 return False
122 return False
123 dl.error_stream_data(got)
124 return True
126 self.n_downloads += 1
127 gtk.input_add(error_stream, gtk.gdk.INPUT_READ, error_ready)