diff options
Diffstat (limited to 'gtk/gtk_download.c')
-rw-r--r-- | gtk/gtk_download.c | 638 |
1 files changed, 556 insertions, 82 deletions
diff --git a/gtk/gtk_download.c b/gtk/gtk_download.c index ab16d6786..e84b6d2fd 100644 --- a/gtk/gtk_download.c +++ b/gtk/gtk_download.c @@ -17,113 +17,587 @@ */ #include <gtk/gtk.h> +#include <glib/gstdio.h> #include "utils/log.h" - +#include "utils/utils.h" +#include "utils/url.h" +#include "utils/messages.h" +#include "content/fetch.h" +#include "desktop/gui.h" #include "gtk/gtk_gui.h" +#include "gtk/gtk_scaffolding.h" +#include "gtk/options.h" #include "gtk/gtk_download.h" -static GtkWindow *wndDownload; -static GtkTreeView *treeDownloads; -static GtkListStore *list_downloads; +#define GLADE_NAME "downloads.glade" -enum { - COLUMN_URL = 0, - COLUMN_DESTINATION, - COLUMN_PERCENTAGE, - COLUMN_DESCRIPTION, +static GtkWindow *nsgtk_download_window, *nsgtk_download_parent; +static GtkWidget *nsgtk_download_progressBar; - N_COLUMNS -}; +static GtkTreeView *nsgtk_download_tree; +static GtkListStore *nsgtk_download_store; +static GtkTreeSelection *nsgtk_download_selection; +static GtkTreeIter nsgtk_download_iter; +static GList *nsgtk_download_buttons; +static gint nsgtk_downloads; +gchar* status_messages[] = { "gtkWorking", "gtkError", "gtkComplete", + "gtkCanceled" }; -void nsgtk_downloadPause_clicked(GtkToolButton *button, gpointer data); +static gboolean nsgtk_download_hide (GtkWidget *window); + +static GtkTreeView *nsgtk_download_tree_view_new(GladeXML *gladeFile); +static void nsgtk_download_tree_view_row_activated(GtkTreeView *tree, + GtkTreePath *path, GtkTreeViewColumn *column, gpointer data); + +static void nsgtk_download_store_update_item(struct gui_download_window *dl); +static void nsgtk_download_store_create_item (struct gui_download_window *dl); +static void nsgtk_download_store_clear_item (struct gui_download_window *dl); +static void nsgtk_download_store_cancel_item (struct gui_download_window *dl); + +static void nsgtk_download_selection_do(GtkWidget *button, + selection_action action); + +static void nsgtk_download_sensitivity_set(struct gui_download_window *dl, + nsgtk_download_actions sensitivity); +static void nsgtk_download_sensitivity_selection_changed( + GtkTreeSelection *selection); +static void nsgtk_download_sensitivity_update_buttons( + nsgtk_download_actions sensitivity); + +static gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, + gchar *size); +static gchar* nsgtk_download_info_to_string (struct gui_download_window *dl); +static gchar* nsgtk_download_time_to_string (gint seconds); +static gboolean nsgtk_download_handle_error (GError *error); -static void nsgtk_download_add(const char *url, const char *dest, int prog, const char *desc) -{ - GtkTreeIter iter; - gtk_list_store_append(list_downloads, &iter); - gtk_list_store_set(list_downloads, &iter, - COLUMN_URL, url, - COLUMN_DESTINATION, dest, - COLUMN_PERCENTAGE, prog, - COLUMN_DESCRIPTION, desc, - -1); -} -void nsgtk_download_initialise(void) +void nsgtk_download_init() { - wndDownload = GTK_WINDOW(glade_xml_get_widget(gladeWindows, - "wndDownloads")); - treeDownloads = GTK_TREE_VIEW(glade_xml_get_widget(gladeWindows, - "treeDownloads")); + gchar *glade_location = g_strconcat(res_dir_location, GLADE_NAME, NULL); + GladeXML *gladeFile = glade_xml_new(glade_location, NULL, NULL); + g_free(glade_location); + + nsgtk_download_buttons = + glade_xml_get_widget_prefix(gladeFile, "button"); + nsgtk_download_progressBar = + glade_xml_get_widget(gladeFile, "progressBar"); + nsgtk_download_window = GTK_WINDOW(glade_xml_get_widget(gladeFile, + "wndDownloads")); + nsgtk_download_parent = NULL; + + gtk_window_set_transient_for(GTK_WINDOW(nsgtk_download_window), + nsgtk_download_parent); + gtk_window_set_destroy_with_parent(GTK_WINDOW(nsgtk_download_window), + FALSE); - gtk_tool_item_set_expand(GTK_TOOL_ITEM( - glade_xml_get_widget(gladeWindows, "toolProgress")), TRUE); + nsgtk_download_tree = nsgtk_download_tree_view_new(gladeFile); - list_downloads = gtk_list_store_new(N_COLUMNS, - G_TYPE_STRING, /* URL */ - G_TYPE_STRING, /* Destination */ + nsgtk_download_store = gtk_list_store_new(NSGTK_DOWNLOAD_N_COLUMNS, G_TYPE_INT, /* % complete */ - G_TYPE_STRING /* time left */ + G_TYPE_STRING, /* Description */ + G_TYPE_STRING, /* Time remaining */ + G_TYPE_STRING, /* Speed */ + G_TYPE_STRING, /* Status */ + G_TYPE_POINTER /* Download structure */ ); - gtk_tree_view_set_model(treeDownloads, GTK_TREE_MODEL(list_downloads)); - - gtk_tree_view_insert_column_with_attributes(treeDownloads, -1, - "URL", - gtk_cell_renderer_text_new(), - "ellipsize", PANGO_ELLIPSIZE_START, - "text", - COLUMN_URL, - NULL); - -/* gtk_tree_view_insert_column_with_attributes(treeDownloads, -1, - "Destination", - gtk_cell_renderer_text_new(), - "text", - COLUMN_DESTINATION, - NULL);*/ - - gtk_tree_view_insert_column_with_attributes(treeDownloads, -1, - "Progress", - gtk_cell_renderer_progress_new(), - "value", - COLUMN_PERCENTAGE, - NULL); - - gtk_tree_view_insert_column_with_attributes(treeDownloads, -1, - "Details", - gtk_cell_renderer_text_new(), - "text", - COLUMN_DESCRIPTION, - NULL); - - /* add some fake entries to play about with */ - nsgtk_download_add("http://www.netsurf-browser.org/downloads/netsurf-1.0.zip", - "/home/rjek/Downloads/netsurf-1.0.zip", - 23, - "500kB of 2MB, 120kB/sec, 12 seconds"); + gtk_tree_view_set_model(nsgtk_download_tree, + GTK_TREE_MODEL(nsgtk_download_store)); + g_object_unref(nsgtk_download_store); + + nsgtk_download_selection = + gtk_tree_view_get_selection(nsgtk_download_tree); + gtk_tree_selection_set_mode(nsgtk_download_selection, + GTK_SELECTION_MULTIPLE); + + g_signal_connect(G_OBJECT(nsgtk_download_selection), "changed", + G_CALLBACK(nsgtk_download_sensitivity_selection_changed), + NULL); + g_signal_connect(G_OBJECT(nsgtk_download_window), "delete-event", + G_CALLBACK(nsgtk_download_hide), NULL); + g_signal_connect(glade_xml_get_widget(gladeFile, "buttonClear"), + "clicked", G_CALLBACK(nsgtk_download_selection_do), + nsgtk_download_store_clear_item); + g_signal_connect(glade_xml_get_widget(gladeFile, "buttonCancel"), + "clicked", G_CALLBACK(nsgtk_download_selection_do), + nsgtk_download_store_cancel_item); + g_signal_connect(nsgtk_download_tree, "row-activated", + G_CALLBACK(nsgtk_download_tree_view_row_activated), + NULL); +} + +void nsgtk_download_destroy () +{ + gtk_tree_selection_select_all(nsgtk_download_selection); + nsgtk_download_selection_do(NULL, nsgtk_download_store_cancel_item); +} + +bool nsgtk_check_for_downloads (GtkWindow *parent) +{ + if (nsgtk_downloads != 0) { + GtkWidget *dialog; + dialog = gtk_message_dialog_new_with_markup(parent, + GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, + GTK_BUTTONS_NONE, + "<big><b>Quit NetSurf?</b></big>\n\n" + "<small>There are still downloads running, " + "if you quit now these will be canceled and the" + " files deleted</small>"); + gtk_dialog_add_buttons(GTK_DIALOG(dialog), "gtk-cancel", + GTK_RESPONSE_CANCEL, "gtk-quit", + GTK_RESPONSE_CLOSE, NULL); + + gint response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + + if (response == GTK_RESPONSE_CANCEL) + return true; + } + + return false; +} + +void nsgtk_download_show(GtkWindow *parent) +{ + gtk_window_set_transient_for(nsgtk_download_window, + nsgtk_download_parent); + gtk_window_present(nsgtk_download_window); +} + +gboolean nsgtk_download_hide (GtkWidget *window) +{ + gtk_widget_hide(window); + return TRUE; +} + +struct gui_download_window *gui_download_window_create(const char *url, + const char *mime_type, struct fetch *fetch, + unsigned int total_size, struct gui_window *gui) +{ + nsgtk_download_parent = nsgtk_scaffolding_get_window(gui); + struct gui_download_window *download; + gchar *domain; + gchar *filename; + gchar *destination; + gchar *size = (total_size == 0 ? + "Unknown" : human_friendly_bytesize(total_size)); + + if (url_nice(url, &filename, false) != URL_FUNC_OK) + strcpy(filename, messages_get("gtkUnknownFile")); + if (url_host(url, &domain) != URL_FUNC_OK) + strcpy(domain, messages_get("gtkUnknownHost")); + + destination = nsgtk_download_dialog_show(filename, domain, size); + if (destination == NULL) + return NULL; + + download = malloc(sizeof *download); + download->fetch = fetch; + download->name = g_string_new(filename); + download->time_left = g_string_new(""); + download->size_total = total_size; + download->size_downloaded = 0; + download->speed = 0; + download->time_remaining = -1; + download->filename = destination; + download->status = (total_size == 0 ? NSGTK_DOWNLOAD_WORKING : + NSGTK_DOWNLOAD_NONE); + download->progress = (total_size == 0 ? 100 : 0); + download->timer = g_timer_new(); + download->error = NULL; + download->write = g_io_channel_new_file(destination, "w", + &download->error); + if (nsgtk_download_handle_error(download->error)) { + free(download); + return NULL; + } + + if (g_str_has_prefix(mime_type, "text") == FALSE) + g_io_channel_set_encoding(download->write, NULL, + &download->error); + + /* Add the new row and store the reference to it (which keeps track of + * the tree changes) */ + gtk_list_store_append(nsgtk_download_store, &nsgtk_download_iter); + download->row = gtk_tree_row_reference_new( + GTK_TREE_MODEL(nsgtk_download_store), + gtk_tree_model_get_path(GTK_TREE_MODEL + (nsgtk_download_store), &nsgtk_download_iter)); + + nsgtk_download_sensitivity_set(download, NSGTK_DOWNLOAD_CANCEL); + + nsgtk_download_store_create_item(download); + nsgtk_download_show(nsgtk_download_parent); + + nsgtk_downloads++; + return download; +} + + +void gui_download_window_data(struct gui_download_window *dw, const char *data, + unsigned int size) +{ + g_io_channel_write_chars(dw->write, data, size, NULL, &dw->error); + if (dw->error != NULL) { + dw->status = NSGTK_DOWNLOAD_ERROR; + dw->speed = 0; + dw->time_remaining = -1; + dw->sensitivity = NSGTK_DOWNLOAD_CLEAR; + nsgtk_download_store_update_item(dw); + fetch_abort(dw->fetch); + + nsgtk_downloads--; + gtk_window_present(nsgtk_download_window); + return; + } + + dw->size_downloaded += size; + gfloat elapsed = g_timer_elapsed(dw->timer, NULL); + + /* If enough time has gone by, update the window */ + if (elapsed - dw->last_update > .5 && + GTK_WIDGET_VISIBLE(nsgtk_download_window)) { + dw->speed = dw->size_downloaded / elapsed; + dw->time_remaining = (dw->size_total - dw->size_downloaded)/ + dw->speed; + + if (dw->size_total) + dw->progress = (gfloat)(dw->size_downloaded)/ + dw->size_total*100; - nsgtk_download_add("http://www.rjek.com/gniggle.zip", - "/home/rjek/Downloads/gniggle.zip", - 68, - "20kB of 90kB, 63kB/sec, 2 seconds"); + nsgtk_download_store_update_item(dw); + dw->last_update = elapsed; + } +} + + +void gui_download_window_error(struct gui_download_window *dw, + const char *error_msg) +{ +} + + +void gui_download_window_done(struct gui_download_window *dw) +{ + g_io_channel_shutdown(dw->write, TRUE, &dw->error); + g_io_channel_unref(dw->write); + + dw->speed = 0; + dw->progress = 100; + nsgtk_download_sensitivity_set(dw, NSGTK_DOWNLOAD_CLEAR); + dw->status = NSGTK_DOWNLOAD_COMPLETE; + + if (option_downloads_clear) + nsgtk_download_store_clear_item(dw); + else + nsgtk_download_store_update_item(dw); + + nsgtk_downloads--; +} + + +GtkTreeView* nsgtk_download_tree_view_new(GladeXML *gladeFile) +{ + GtkTreeView *treeview = GTK_TREE_VIEW(glade_xml_get_widget(gladeFile, + "treeDownloads")); + GtkCellRenderer *renderer; + gchar *progress, *information, *speed, *remaining; + + /* Progress column */ + renderer = gtk_cell_renderer_progress_new(); + gtk_tree_view_insert_column_with_attributes (treeview, -1, + messages_get("gtkProgress"), renderer, "value", + NSGTK_DOWNLOAD_PROGRESS, "text", + NSGTK_DOWNLOAD_STATUS, NULL); + + /* Information column */ + renderer = gtk_cell_renderer_text_new(); + g_object_set(G_OBJECT(renderer), "wrap-mode", PANGO_WRAP_WORD_CHAR, + "wrap-width", 300, NULL); + gtk_tree_view_insert_column_with_attributes (treeview, -1, + messages_get("gtkDetails"), renderer, "text", + NSGTK_DOWNLOAD_INFO, NULL); + gtk_tree_view_column_set_expand(gtk_tree_view_get_column(treeview, + NSGTK_DOWNLOAD_INFO), TRUE); + + /* Time remaining column */ + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes (treeview, -1, + messages_get("gtkRemaining"), renderer, "text", + NSGTK_DOWNLOAD_REMAINING, NULL); + + /* Speed column */ + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes (treeview, -1, + messages_get("gtkSpeed"), renderer, "text", + NSGTK_DOWNLOAD_SPEED, NULL); + + return treeview; +} + +void nsgtk_download_tree_view_row_activated(GtkTreeView *tree, + GtkTreePath *path, GtkTreeViewColumn *column, gpointer data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_tree_view_get_model(tree); + + if (gtk_tree_model_get_iter(model, &iter, path)) { + /* TODO: This will be a context action (pause, start, clear) */ + nsgtk_download_selection_do(NULL, + nsgtk_download_store_clear_item); + } +} + +void nsgtk_download_store_update_item (struct gui_download_window *dl) +{ + gchar *info = nsgtk_download_info_to_string(dl); + gchar *speed = g_strconcat(human_friendly_bytesize(dl->speed), "/s", + NULL); + gchar *time = nsgtk_download_time_to_string(dl->time_remaining); + + /* Updates iter (which is needed to set and get data) with the dl row */ + gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store), + &nsgtk_download_iter, + gtk_tree_row_reference_get_path(dl->row)); + + gtk_list_store_set (nsgtk_download_store, &nsgtk_download_iter, + NSGTK_DOWNLOAD_PROGRESS, dl->progress, + NSGTK_DOWNLOAD_INFO, info, + NSGTK_DOWNLOAD_SPEED, dl->speed == 0 ? "-" : speed, + NSGTK_DOWNLOAD_REMAINING, time, + -1); + if (dl->status != NSGTK_DOWNLOAD_NONE) + gtk_list_store_set(nsgtk_download_store, &nsgtk_download_iter, + NSGTK_DOWNLOAD_STATUS, + messages_get(status_messages[dl->status])); + + g_free(info); + g_free(speed); + g_free(time); +} + +void nsgtk_download_store_create_item (struct gui_download_window *dl) +{ + nsgtk_download_store_update_item(dl); + /* The iter has already been updated to this row */ + gtk_list_store_set (nsgtk_download_store, &nsgtk_download_iter, + NSGTK_DOWNLOAD, dl, -1); +} + +void nsgtk_download_store_clear_item (struct gui_download_window *dl) +{ + if (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR) { + gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store), + &nsgtk_download_iter, + gtk_tree_row_reference_get_path(dl->row)); + gtk_list_store_remove(nsgtk_download_store, + &nsgtk_download_iter); + g_free(dl); + } +} + +void nsgtk_download_store_cancel_item (struct gui_download_window *dl) +{ + if (dl->sensitivity & NSGTK_DOWNLOAD_CANCEL) { + dl->status = NSGTK_DOWNLOAD_CANCELED; + dl->speed = 0; + dl->progress = 0; + dl->time_remaining = -1; + nsgtk_download_sensitivity_set(dl, NSGTK_DOWNLOAD_CLEAR); + + if (dl->fetch) + fetch_abort(dl->fetch); + + g_unlink(dl->filename); + + nsgtk_download_store_update_item(dl); + + nsgtk_downloads--; + } +} + +void nsgtk_download_selection_do(GtkWidget *button, selection_action action) +{ + GList *rows, *dls = NULL; + GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store); + + rows = gtk_tree_selection_get_selected_rows(nsgtk_download_selection, + &model); + while (rows != NULL) { + struct gui_download_window *dl; + gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store), + &nsgtk_download_iter, (GtkTreePath*)rows->data); + gtk_tree_model_get(GTK_TREE_MODEL(nsgtk_download_store), + &nsgtk_download_iter, NSGTK_DOWNLOAD, + &dl, -1); + dls = g_list_prepend(dls, dl); + + rows = rows->next; + } + g_list_foreach(dls, (GFunc)action, NULL); - nsgtk_download_add("http://www.whopper.com/biggy.iso", - "/home/rjek/Downlaods/biggy.iso", - 2, - "2MB of 1923MB, 3kB/sec, 20 hours"); + g_list_foreach(rows, (GFunc)gtk_tree_path_free, NULL); + g_list_foreach(rows, (GFunc)g_free, NULL); + g_list_free(rows); + g_list_free(dls); +} +void nsgtk_download_sensitivity_set(struct gui_download_window *dl, + nsgtk_download_actions sensitivity) +{ + dl->sensitivity = sensitivity; + if (gtk_tree_selection_path_is_selected(nsgtk_download_selection, + gtk_tree_row_reference_get_path(dl->row))) + nsgtk_download_sensitivity_update_buttons(sensitivity); + } -void nsgtk_download_show(void) +void nsgtk_download_sensitivity_selection_changed (GtkTreeSelection *selection) +{ + GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store); + GtkTreeIter iter; + GList *rows; + nsgtk_download_actions sensitivity = 0; + + rows = gtk_tree_selection_get_selected_rows(selection, &model); + while (rows != NULL) { + struct gui_download_window *dl; + gtk_tree_model_get_iter(model, &iter, (GtkTreePath*)rows->data); + gtk_tree_model_get(model, &iter, NSGTK_DOWNLOAD, &dl, -1); + sensitivity |= dl->sensitivity; + rows = rows->next; + } + + nsgtk_download_sensitivity_update_buttons(sensitivity); +} + +void nsgtk_download_sensitivity_update_buttons( + nsgtk_download_actions sensitivity) +{ + /* Glade seems to pack the buttons in an arbitrary order */ + enum { PAUSE_BUTTON, CLEAR_BUTTON, CANCEL_BUTTON, RESUME_BUTTON }; + + gtk_widget_set_sensitive(g_list_nth_data(nsgtk_download_buttons, + PAUSE_BUTTON), sensitivity & NSGTK_DOWNLOAD_PAUSE); + gtk_widget_set_sensitive(g_list_nth_data(nsgtk_download_buttons, + CLEAR_BUTTON), sensitivity & NSGTK_DOWNLOAD_CLEAR); + gtk_widget_set_sensitive(g_list_nth_data(nsgtk_download_buttons, + CANCEL_BUTTON), sensitivity & NSGTK_DOWNLOAD_CANCEL); + gtk_widget_set_sensitive(g_list_nth_data(nsgtk_download_buttons, + RESUME_BUTTON), sensitivity & NSGTK_DOWNLOAD_RESUME); +} + +gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, gchar *size) { - gtk_widget_show_all(GTK_WIDGET(wndDownload)); - gdk_window_raise(GTK_WIDGET(wndDownload)->window); + enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS }; + GtkWidget *dialog; + gchar *destination = NULL; + gchar *info = g_strdup_printf(messages_get("gtkInfo"), filename, + domain, size); + + dialog = gtk_message_dialog_new_with_markup(nsgtk_download_parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + "<span size=\"x-large\" weight=\"ultrabold\">%s</span>" + "\n\n<small>%s</small>", + messages_get("gtkStartDownload"), info); + + gtk_dialog_add_buttons(GTK_DIALOG(dialog), GTK_STOCK_SAVE, + GTK_RESPONSE_DOWNLOAD, GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE_AS, + GTK_RESPONSE_SAVE_AS, NULL); + + gint result = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + g_free(info); + + switch (result) { + case GTK_RESPONSE_SAVE_AS: { + dialog = gtk_file_chooser_dialog_new + (messages_get("gtkSave"), + nsgtk_download_parent, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER(dialog), filename); + gtk_file_chooser_set_do_overwrite_confirmation + (GTK_FILE_CHOOSER(dialog), + option_request_overwrite); + + gint result = gtk_dialog_run(GTK_DIALOG(dialog)); + if (result == GTK_RESPONSE_ACCEPT) + destination = gtk_file_chooser_get_filename + (GTK_FILE_CHOOSER(dialog)); + gtk_widget_destroy(dialog); + break; + } + case GTK_RESPONSE_DOWNLOAD: { + destination = g_strconcat(option_downloads_directory, + "/", filename, NULL); + break; + } + } + return destination; } -void nsgtk_downloadPause_clicked(GtkToolButton *button, gpointer data) +gchar* nsgtk_download_info_to_string (struct gui_download_window *dl) +{ + if (dl->status != NSGTK_DOWNLOAD_ERROR) + return g_strdup_printf("%s\n%s of %s completed", + dl->name->str, + human_friendly_bytesize(dl->size_downloaded), + dl->size_total == 0 ? "Unknown" : + human_friendly_bytesize(dl->size_total)); + else + return g_strdup_printf("%s\n%s", dl->name->str, + dl->error->message); +} + +gchar* nsgtk_download_time_to_string (gint seconds) { + gint hours, minutes; + if (seconds < 0) + return g_strdup("-"); + + hours = seconds / 3600; + seconds -= hours * 3600; + minutes = seconds / 60; + seconds -= minutes * 60; + + if (hours > 0) + return g_strdup_printf("%u:%02u:%02u", hours, minutes, + seconds); + else + return g_strdup_printf("%u:%02u", minutes, seconds); } + +gboolean nsgtk_download_handle_error (GError *error) +{ + if (error != NULL) { + GtkWidget*dialog; + gchar *message = g_strdup_printf(messages_get("gtkFileError"), + error->message); + + dialog = gtk_message_dialog_new_with_markup + (nsgtk_download_parent, + GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "<big><b>%s</b></big>\n\n" + "<small>%s</small>", messages_get("gtkFailed"), + message); + + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + return TRUE; + } + return FALSE; +} + + |