public class DownloadItem : GLib.Object { public string url; public int size; public string md5; public DownloadItem (string url, int size, string md5) { this.url = url; this.size = size; this.md5 = md5; } } public class DownloadList : GLib.Object { private Gee.ArrayList files = new Gee.ArrayList (); private GLib.Mutex files_mutex = new GLib.Mutex (); private GLib.Mutex worker_mutex = new GLib.Mutex (); private bool worker_is_running = false; private int total_size = 0; private int total_downloaded = 0; private int i; public signal void download_started (string url); public signal void download_finished (string url); public signal void download_progressed (double item, double total); public int queue_file (string url, int size, string md5) { DownloadItem item = new DownloadItem(url, size, md5); this.files_mutex.lock (); stdout.printf ("Inserting %s\n", url); this.files.add (item); this.total_size += item.size; this.files_mutex.unlock (); if(!this.worker_is_running) { this.worker_mutex.lock (); this.worker_is_running = true; this.worker_mutex.unlock (); try { stdout.printf("Creating worker thread\n"); Thread.create (this.run, false); } catch (ThreadError e) { error ("Erreur de Thread : %s\n", e.message); this.worker_is_running = false; } } return 0; } public DownloadItem pick_up () { this.files_mutex.lock (); DownloadItem item = files.get (0); this.files.remove (item); this.files_mutex.unlock(); return item; } public void* run () { stdout.printf("Beginning worker thread\n"); DownloadItem item; while (this.files.size > 0) { item = this.pick_up (); stdout.printf("item : %d Total : %d\n", total_downloaded, total_size); this.download_started (item.url); for ( i = 1; i <= item.size; i++) { this.total_downloaded += 1; GLib.Thread.usleep(100000); this.download_progressed(i * 1.0 / item.size, this.total_downloaded * 1.0 / this.total_size); }; this.download_finished (item.url); } stdout.printf("All items downloaded\n"); this.worker_mutex.lock (); this.worker_is_running = false; this.worker_mutex.unlock (); stdout.printf("Exiting worker thread\n"); return null; } } public class MainWindow : GLib.Object { public static int main (string[] args) { if (!Thread.supported ()) { error ("Cannot run without thread support."); } Gtk.init(ref args); UpdaterController uc = new UpdaterController(); uc.create_window(); Gtk.main(); return 0; } } public class UpdaterController : GLib.Object { private UpdaterWindow view; private DownloadList download_list; public UpdaterController () { this.view = new UpdaterWindow (); this.view.destroy += Gtk.main_quit; this.download_list = new DownloadList (); this.download_list.download_finished += (klass, url) => { stdout.printf("Downloaded %s\n", url); }; this.download_list.download_started += (klass, url) => { stdout.printf("Downloading %s\n", url); }; this.download_list.download_progressed += (klass, item_fraction, total_fraction) => { this.view.item_fraction(item_fraction); this.view.total_fraction(total_fraction); // this.view.item_total_fraction(item_fraction, total_fraction); }; } public void create_window () { this.view.show_all(); this.download_list.queue_file ("dummy_site/files", 20, ""); this.download_list.queue_file ("dummy_site/files", 20, ""); this.download_list.queue_file ("dummy_site/files", 30, ""); } } public class DownloadProgressBar : Gtk.VBox { public Gtk.ProgressBar item_pb; public Gtk.ProgressBar total_pb; public DownloadProgressBar() { this.item_pb = new Gtk.ProgressBar(); this.total_pb = new Gtk.ProgressBar(); this.pack_start(this.item_pb, false, false, 0); this.pack_start(this.total_pb, false, false, 0); } } public class UpdaterWindow : Gtk.Window { private DownloadProgressBar dpb; public UpdaterWindow() { this.title = "Simple Updater"; this.set_default_size(600, 400); this.position = Gtk.WindowPosition.CENTER; this.dpb = new DownloadProgressBar(); this.add(dpb); } public void item_fraction(double p) { this.dpb.item_pb.fraction = p; } public void total_fraction(double p) { this.dpb.total_pb.fraction = p; } public void item_total_fraction(double i, double t) { this.dpb.total_pb.fraction = t; this.dpb.item_pb.fraction = i; } }