diff options
Diffstat (limited to 'gtk/download.c')
-rw-r--r-- | gtk/download.c | 1211 |
1 files changed, 604 insertions, 607 deletions
diff --git a/gtk/download.c b/gtk/download.c index 5e22352b4..71b1aa633 100644 --- a/gtk/download.c +++ b/gtk/download.c @@ -70,7 +70,7 @@ struct gui_download_window { struct download_context *ctx; nsgtk_download_actions sensitivity; nsgtk_download_status status; - + GString *name; GString *time_left; gint size_total; @@ -79,7 +79,7 @@ struct gui_download_window { gfloat time_remaining; gfloat start_time; gfloat speed; - + GtkTreeRowReference *row; GIOChannel *write; GError *error; @@ -96,113 +96,448 @@ static GtkTreeSelection *nsgtk_download_selection; static GtkTreeIter nsgtk_download_iter; static GTimer *nsgtk_downloads_timer; -static GList *nsgtk_downloads_list, *nsgtk_download_buttons; +static GList *nsgtk_downloads_list; +static GtkButton *nsgtk_download_button_pause; +static GtkButton *nsgtk_download_button_clear; +static GtkButton *nsgtk_download_button_cancel; +static GtkButton *nsgtk_download_button_resume; static gint nsgtk_downloads_num_active; -static const gchar* status_messages[] = { NULL, "gtkWorking", "gtkError", - "gtkComplete", "gtkCanceled" }; +static const gchar* status_messages[] = { NULL, "gtkWorking", "gtkError", + "gtkComplete", "gtkCanceled" }; + + + +static GtkTreeView* nsgtk_download_tree_view_new(GtkBuilder *gladeFile) +{ + GtkTreeView *treeview; + GtkCellRenderer *renderer; + + treeview = GTK_TREE_VIEW(gtk_builder_get_object(gladeFile, "treeDownloads")); + + /* 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, "pulse", NSGTK_DOWNLOAD_PULSE, + "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; +} + +static gint +nsgtk_download_sort(GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer userdata) +{ + struct gui_download_window *dl1, *dl2; + + gtk_tree_model_get(model, a, NSGTK_DOWNLOAD, &dl1, -1); + gtk_tree_model_get(model, b, NSGTK_DOWNLOAD, &dl2, -1); + + return dl1->status - dl2->status; +} + +static 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(GTK_WIDGET(nsgtk_download_button_pause), + sensitivity & NSGTK_DOWNLOAD_PAUSE); + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_clear), + sensitivity & NSGTK_DOWNLOAD_CLEAR); + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_cancel), + sensitivity & NSGTK_DOWNLOAD_CANCEL); + gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_resume), + sensitivity & NSGTK_DOWNLOAD_RESUME); +} + +static void nsgtk_download_sensitivity_evaluate(GtkTreeSelection *selection) +{ + GtkTreeIter iter; + GList *rows; + gboolean selected = gtk_tree_selection_count_selected_rows(selection); + GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store); + nsgtk_download_actions sensitivity = 0; + struct gui_download_window *dl; + + if (selected) { + rows = gtk_tree_selection_get_selected_rows(selection, &model); + while (rows != NULL) { + 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; + } + } else { + rows = nsgtk_downloads_list; + while (rows != NULL) { + dl = rows->data; + sensitivity |= (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR); + rows = rows->next; + } + } -static gboolean nsgtk_download_hide(GtkWidget *window); -static GtkTreeView *nsgtk_download_tree_view_new(GladeXML *gladeFile); + nsgtk_download_sensitivity_update_buttons(sensitivity); +} + +static void nsgtk_download_do(nsgtk_download_selection_action action) +{ + GList *rows, *dls = NULL; + GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store); + gboolean selection_exists = gtk_tree_selection_count_selected_rows( + nsgtk_download_selection); + + if (selection_exists) { + 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(rows, (GFunc)gtk_tree_path_free, NULL); + g_list_foreach(rows, (GFunc)g_free, NULL); + g_list_free(rows); + } else + dls = g_list_copy(nsgtk_downloads_list); + + g_list_foreach(dls, (GFunc)action, NULL); + g_list_free(dls); +} + +static gchar* nsgtk_download_info_to_string(struct gui_download_window *dl) +{ + gchar *size_info = g_strdup_printf(messages_get("gtkSizeInfo"), + human_friendly_bytesize(dl->size_downloaded), + dl->size_total == 0 ? messages_get("gtkUnknownSize") : + human_friendly_bytesize(dl->size_total)); + + gchar *r; + + if (dl->status != NSGTK_DOWNLOAD_ERROR) + r = g_strdup_printf("%s\n%s", dl->name->str, size_info); + else + r = g_strdup_printf("%s\n%s", dl->name->str, + dl->error->message); + + g_free(size_info); + + return r; +} + +static 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); +} + +static void nsgtk_download_store_update_item (struct gui_download_window *dl) +{ + gchar *info = nsgtk_download_info_to_string(dl); + char *human = human_friendly_bytesize(dl->speed); + char speed[strlen(human) + SLEN("/s") + 1]; + sprintf(speed, "%s/s", human); + gchar *time = nsgtk_download_time_to_string(dl->time_remaining); + gboolean pulse = dl->status == NSGTK_DOWNLOAD_WORKING; + + /* 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_PULSE, pulse ? dl->progress : -1, + NSGTK_DOWNLOAD_PROGRESS, pulse ? 0 : dl->progress, + NSGTK_DOWNLOAD_INFO, info, + NSGTK_DOWNLOAD_SPEED, dl->speed == 0 ? "-" : speed, + NSGTK_DOWNLOAD_REMAINING, time, + NSGTK_DOWNLOAD, dl, + -1); + + g_free(info); + g_free(time); +} + +static gboolean nsgtk_download_update(gboolean force_update) +{ + /* Be sure we need to update */ + if (!nsgtk_widget_get_visible(GTK_WIDGET(nsgtk_download_window))) + return TRUE; + + GList *list; + gchar *text; + gboolean update, pulse_mode = FALSE; + gint downloaded = 0, total = 0, dls = 0; + gfloat percent, elapsed = g_timer_elapsed(nsgtk_downloads_timer, NULL); + nsgtk_downloads_num_active = 0; + + for (list = nsgtk_downloads_list; list != NULL; list = list->next) { + struct gui_download_window *dl = list->data; + update = force_update; + + switch (dl->status) { + case NSGTK_DOWNLOAD_WORKING: + pulse_mode = TRUE; + + case NSGTK_DOWNLOAD_NONE: + dl->speed = dl->size_downloaded / + (elapsed - dl->start_time); + if (dl->status == NSGTK_DOWNLOAD_NONE) { + dl->time_remaining = (dl->size_total - + dl->size_downloaded)/ + dl->speed; + dl->progress = (gfloat) + dl->size_downloaded / + dl->size_total * 100; + } else + dl->progress++; + + nsgtk_downloads_num_active++; + update = TRUE; + + case NSGTK_DOWNLOAD_COMPLETE: + downloaded += dl->size_downloaded; + total += dl->size_total; + dls++; + + default: + ;//Do nothing + + } + if (update) + nsgtk_download_store_update_item(dl); + } + + if (pulse_mode) { + text = g_strdup_printf( + messages_get(nsgtk_downloads_num_active > 1 ? + "gtkProgressBarPulse" : + "gtkProgressBarPulseSingle"), + nsgtk_downloads_num_active); + gtk_progress_bar_pulse(nsgtk_download_progress_bar); + gtk_progress_bar_set_text(nsgtk_download_progress_bar, text); + } else { + percent = total != 0 ? (gfloat)downloaded / total : 0; + text = g_strdup_printf(messages_get("gtkProgressBar"), + floor(percent*100), dls); + gtk_progress_bar_set_fraction(nsgtk_download_progress_bar, + percent); + gtk_progress_bar_set_text(nsgtk_download_progress_bar, text); + } + + g_free(text); + + if (nsgtk_downloads_num_active == 0) + return FALSE; /* Returning FALSE here cancels the g_timeout */ + else + return TRUE; +} + +static void nsgtk_download_store_clear_item(struct gui_download_window *dl) +{ + if (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR) { + nsgtk_downloads_list = g_list_remove(nsgtk_downloads_list, dl); + + 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); + + download_context_destroy(dl->ctx); + g_string_free(dl->name, TRUE); + g_string_free(dl->time_left, TRUE); + g_free(dl); + + nsgtk_download_sensitivity_evaluate(nsgtk_download_selection); + nsgtk_download_update(FALSE); + } +} + static void nsgtk_download_tree_view_row_activated(GtkTreeView *tree, - GtkTreePath *path, GtkTreeViewColumn *column, gpointer data); - -static gint nsgtk_download_sort(GtkTreeModel *model, GtkTreeIter *a, - GtkTreeIter *b, gpointer userdata); -static gboolean nsgtk_download_update(gboolean force_update); -static void nsgtk_download_do(nsgtk_download_selection_action action); - -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_sensitivity_evaluate(GtkTreeSelection *selection); -static void nsgtk_download_sensitivity_update_buttons( - nsgtk_download_actions sensitivity); - -static void nsgtk_download_change_sensitivity( - struct gui_download_window *dl, nsgtk_download_actions sens); + 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_do(nsgtk_download_store_clear_item); + } +} + +static void nsgtk_download_change_sensitivity(struct gui_download_window *dl, + nsgtk_download_actions sensitivity) +{ + dl->sensitivity = sensitivity; + nsgtk_download_sensitivity_evaluate(nsgtk_download_selection); +} + static void nsgtk_download_change_status ( - struct gui_download_window *dl, nsgtk_download_status status); + struct gui_download_window *dl, nsgtk_download_status status) +{ + dl->status = status; + if (status != NSGTK_DOWNLOAD_NONE) { + 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_STATUS, + messages_get(status_messages[status]), -1); + } +} + +static void nsgtk_download_store_cancel_item (struct gui_download_window *dl) +{ + if (dl->sensitivity & NSGTK_DOWNLOAD_CANCEL) { + dl->speed = 0; + dl->size_downloaded = 0; + dl->progress = 0; + dl->time_remaining = -1; + nsgtk_download_change_sensitivity(dl, NSGTK_DOWNLOAD_CLEAR); + nsgtk_download_change_status(dl, NSGTK_DOWNLOAD_CANCELED); -static gchar* nsgtk_download_dialog_show (const gchar *filename, - const gchar *domain, const 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); + download_context_abort(dl->ctx); - + g_unlink(download_context_get_filename(dl->ctx)); + + nsgtk_download_update(TRUE); + } +} + +static gboolean nsgtk_download_hide (GtkWidget *window) +{ + gtk_widget_hide(window); + return TRUE; +} bool nsgtk_download_init(const char *glade_file_location) { - GladeXML *gladeFile; + GError* error = NULL; + GtkBuilder* builder = gtk_builder_new(); - gladeFile = glade_xml_new(glade_file_location, NULL, NULL); - if (gladeFile == NULL) + if (!gtk_builder_add_from_file(builder, glade_file_location, &error)) + { + g_warning("Couldn't load builder file: %s", error->message); + g_error_free(error); return false; + } - nsgtk_download_buttons = - glade_xml_get_widget_prefix(gladeFile, "button"); - nsgtk_download_progress_bar = GTK_PROGRESS_BAR(glade_xml_get_widget( - gladeFile, "progressBar")); - nsgtk_download_window = GTK_WINDOW(glade_xml_get_widget(gladeFile, - "wndDownloads")); + nsgtk_download_button_pause = GTK_BUTTON(gtk_builder_get_object(builder, "buttonPause")); + nsgtk_download_button_clear = GTK_BUTTON(gtk_builder_get_object(builder, "buttonClear")); + nsgtk_download_button_cancel = GTK_BUTTON(gtk_builder_get_object(builder, "buttonCancel")); + nsgtk_download_button_resume = GTK_BUTTON(gtk_builder_get_object(builder, "buttonPlay")); + + nsgtk_download_progress_bar = GTK_PROGRESS_BAR(gtk_builder_get_object(builder, "progressBar")); + nsgtk_download_window = GTK_WINDOW(gtk_builder_get_object(builder, "wndDownloads")); nsgtk_download_parent = NULL; - + gtk_window_set_transient_for(GTK_WINDOW(nsgtk_download_window), - nsgtk_download_parent); + nsgtk_download_parent); gtk_window_set_destroy_with_parent(GTK_WINDOW(nsgtk_download_window), - FALSE); - + FALSE); + nsgtk_downloads_timer = g_timer_new(); - - nsgtk_download_tree = nsgtk_download_tree_view_new(gladeFile); - + + nsgtk_download_tree = nsgtk_download_tree_view_new(builder); + nsgtk_download_store = gtk_list_store_new(NSGTK_DOWNLOAD_N_COLUMNS, - G_TYPE_INT, /* % complete */ - G_TYPE_STRING, /* Description */ - G_TYPE_STRING, /* Time remaining */ - G_TYPE_STRING, /* Speed */ - G_TYPE_INT, /* Pulse */ - G_TYPE_STRING, /* Status */ - G_TYPE_POINTER /* Download structure */ - ); - - + G_TYPE_INT, /* % complete */ + G_TYPE_STRING, /* Description */ + G_TYPE_STRING, /* Time remaining */ + G_TYPE_STRING, /* Speed */ + G_TYPE_INT, /* Pulse */ + G_TYPE_STRING, /* Status */ + G_TYPE_POINTER /* Download structure */ + ); + + gtk_tree_view_set_model(nsgtk_download_tree, - GTK_TREE_MODEL(nsgtk_download_store)); - + GTK_TREE_MODEL(nsgtk_download_store)); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(nsgtk_download_store), - NSGTK_DOWNLOAD_STATUS, - (GtkTreeIterCompareFunc) nsgtk_download_sort, NULL, NULL); + NSGTK_DOWNLOAD_STATUS, + (GtkTreeIterCompareFunc) nsgtk_download_sort, NULL, NULL); gtk_tree_sortable_set_sort_column_id( - GTK_TREE_SORTABLE(nsgtk_download_store), - NSGTK_DOWNLOAD_STATUS, GTK_SORT_ASCENDING); - + GTK_TREE_SORTABLE(nsgtk_download_store), + NSGTK_DOWNLOAD_STATUS, GTK_SORT_ASCENDING); + g_object_unref(nsgtk_download_store); - - nsgtk_download_selection = - gtk_tree_view_get_selection(nsgtk_download_tree); + + 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_evaluate), NULL); - g_signal_connect(nsgtk_download_tree, "row-activated", - G_CALLBACK(nsgtk_download_tree_view_row_activated), - NULL); - g_signal_connect_swapped(glade_xml_get_widget(gladeFile, "buttonClear"), - "clicked", G_CALLBACK(nsgtk_download_do), - nsgtk_download_store_clear_item); - g_signal_connect_swapped(glade_xml_get_widget(gladeFile, - "buttonCancel"), "clicked", - G_CALLBACK(nsgtk_download_do), - nsgtk_download_store_cancel_item); - g_signal_connect(G_OBJECT(nsgtk_download_window), "delete-event", - G_CALLBACK(nsgtk_download_hide), NULL); - - return true; + GTK_SELECTION_MULTIPLE); + + g_signal_connect(G_OBJECT(nsgtk_download_selection), "changed", + G_CALLBACK(nsgtk_download_sensitivity_evaluate), NULL); + g_signal_connect(nsgtk_download_tree, "row-activated", + G_CALLBACK(nsgtk_download_tree_view_row_activated), + NULL); + g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonClear"), + "clicked", + G_CALLBACK(nsgtk_download_do), + nsgtk_download_store_clear_item); + g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonCancel"), + "clicked", + G_CALLBACK(nsgtk_download_do), + nsgtk_download_store_cancel_item); + g_signal_connect(G_OBJECT(nsgtk_download_window), "delete-event", + G_CALLBACK(nsgtk_download_hide), NULL); + + return true; } void nsgtk_download_destroy () @@ -215,57 +550,187 @@ bool nsgtk_check_for_downloads (GtkWindow *parent) if (nsgtk_downloads_num_active != 0) { GtkWidget *dialog; dialog = gtk_message_dialog_new_with_markup(parent, - GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, - "<big><b>%s</b></big>\n\n" - "<small>%s</small>", messages_get("gtkQuit"), - messages_get("gtkDownloadsRunning")); - gtk_dialog_add_buttons(GTK_DIALOG(dialog), "gtk-cancel", - GTK_RESPONSE_CANCEL, "gtk-quit", - GTK_RESPONSE_CLOSE, NULL); - + GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, + GTK_BUTTONS_NONE, + "<big><b>%s</b></big>\n\n" + "<small>%s</small>", messages_get("gtkQuit"), + messages_get("gtkDownloadsRunning")); + 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); + 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; +static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *domain, + const gchar *size) +{ + enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS }; + GtkWidget *dialog; + char *destination = NULL; + gchar *message = g_strdup(messages_get("gtkStartDownload")); + 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>", + message, 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(message); + 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_current_folder + (GTK_FILE_CHOOSER(dialog), + nsoption_charp(downloads_directory)); + gtk_file_chooser_set_do_overwrite_confirmation + (GTK_FILE_CHOOSER(dialog), + nsoption_bool(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 = malloc(strlen(nsoption_charp(downloads_directory)) + + strlen(filename) + SLEN("/") + 1); + if (destination == NULL) { + warn_user(messages_get("NoMemory"), 0); + break; + } + sprintf(destination, "%s/%s", + nsoption_charp(downloads_directory), filename); + /* Test if file already exists and display overwrite + * confirmation if needed */ + if (g_file_test(destination, G_FILE_TEST_EXISTS) && + nsoption_bool(request_overwrite)) { + message = g_strdup_printf(messages_get( + "gtkOverwrite"), filename); + info = g_strdup_printf(messages_get( + "gtkOverwriteInfo"), + nsoption_charp(downloads_directory)); + + dialog = gtk_message_dialog_new_with_markup( + nsgtk_download_parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_CANCEL, + "<b>%s</b>",message); + gtk_message_dialog_format_secondary_markup( + GTK_MESSAGE_DIALOG(dialog), + "%s", info); + + GtkWidget *button = gtk_dialog_add_button( + GTK_DIALOG(dialog), + "_Replace", + GTK_RESPONSE_DOWNLOAD); + gtk_button_set_image(GTK_BUTTON(button), + gtk_image_new_from_stock( + "gtk-save", + GTK_ICON_SIZE_BUTTON)); + + gint result = gtk_dialog_run(GTK_DIALOG( + dialog)); + if (result == GTK_RESPONSE_CANCEL) + destination = NULL; + + gtk_widget_destroy(dialog); + g_free(message); + g_free(info); + } + break; + } + } + return destination; +} + + +static 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; +} + +static 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); } struct gui_download_window *gui_download_window_create(download_context *ctx, - struct gui_window *gui) + struct gui_window *gui) { const char *url = download_context_get_url(ctx); unsigned long total_size = download_context_get_total_length(ctx); gchar *domain; gchar *destination; gboolean unknown_size = total_size == 0; - const char *size = (total_size == 0 ? - messages_get("gtkUnknownSize") : - human_friendly_bytesize(total_size)); - - nsgtk_download_parent = - nsgtk_scaffolding_window(nsgtk_get_scaffold(gui)); + const char *size = (total_size == 0 ? + messages_get("gtkUnknownSize") : + human_friendly_bytesize(total_size)); + + nsgtk_download_parent = + nsgtk_scaffolding_window(nsgtk_get_scaffold(gui)); struct gui_download_window *download = malloc(sizeof *download); if (download == NULL) return NULL; - + if (url_host(url, &domain) != URL_FUNC_OK) { domain = g_strdup(messages_get("gtkUnknownHost")); if (domain == NULL) { @@ -273,24 +738,24 @@ struct gui_download_window *gui_download_window_create(download_context *ctx, return NULL; } } - + destination = nsgtk_download_dialog_show( - download_context_get_filename(ctx), domain, size); + download_context_get_filename(ctx), domain, size); if (destination == NULL) { g_free(domain); free(download); return NULL; } - - /* Add the new row and store the reference to it (which keeps track of + + /* Add the new row and store the reference to it (which keeps track of * the tree changes) */ gtk_list_store_prepend(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), - gtk_tree_model_get_path( - GTK_TREE_MODEL(nsgtk_download_store), - &nsgtk_download_iter)); - + &nsgtk_download_iter)); + download->ctx = ctx; download->name = g_string_new(download_context_get_filename(ctx)); download->time_left = g_string_new(""); @@ -311,44 +776,44 @@ struct gui_download_window *gui_download_window_create(download_context *ctx, free(download); return NULL; } - g_io_channel_set_encoding(download->write, NULL, &download->error); + g_io_channel_set_encoding(download->write, NULL, &download->error); nsgtk_download_change_sensitivity(download, NSGTK_DOWNLOAD_CANCEL); - + nsgtk_download_store_create_item(download); nsgtk_download_show(nsgtk_download_parent); - - if (unknown_size) + + if (unknown_size) nsgtk_download_change_status(download, NSGTK_DOWNLOAD_WORKING); - + if (nsgtk_downloads_num_active == 0) { - g_timeout_add(UPDATE_RATE, - (GSourceFunc) nsgtk_download_update, FALSE); + g_timeout_add(UPDATE_RATE, + (GSourceFunc) nsgtk_download_update, FALSE); } nsgtk_downloads_list = g_list_prepend(nsgtk_downloads_list, download); - - return download; + + return download; } -nserror gui_download_window_data(struct gui_download_window *dw, - const char *data, unsigned int size) +nserror 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->speed = 0; dw->time_remaining = -1; - + nsgtk_download_change_sensitivity(dw, NSGTK_DOWNLOAD_CLEAR); nsgtk_download_change_status(dw, NSGTK_DOWNLOAD_ERROR); - + nsgtk_download_update(TRUE); - + gtk_window_present(nsgtk_download_window); return NSERROR_SAVE_FAILED; - } + } dw->size_downloaded += size; return NSERROR_OK; @@ -356,7 +821,7 @@ nserror gui_download_window_data(struct gui_download_window *dw, void gui_download_window_error(struct gui_download_window *dw, - const char *error_msg) + const char *error_msg) { } @@ -365,14 +830,14 @@ 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->time_remaining = -1; dw->progress = 100; dw->size_total = dw->size_downloaded; nsgtk_download_change_sensitivity(dw, NSGTK_DOWNLOAD_CLEAR); nsgtk_download_change_status(dw, NSGTK_DOWNLOAD_COMPLETE); - + if (nsoption_bool(downloads_clear)) nsgtk_download_store_clear_item(dw); else @@ -380,485 +845,17 @@ void gui_download_window_done(struct gui_download_window *dw) } -GtkTreeView* nsgtk_download_tree_view_new(GladeXML *gladeFile) -{ - GtkTreeView *treeview = GTK_TREE_VIEW(glade_xml_get_widget(gladeFile, - "treeDownloads")); - GtkCellRenderer *renderer; - - /* 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, "pulse", NSGTK_DOWNLOAD_PULSE, - "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_do(nsgtk_download_store_clear_item); - } -} - -gint nsgtk_download_sort (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, - gpointer userdata) -{ - struct gui_download_window *dl1, *dl2; - - gtk_tree_model_get(model, a, NSGTK_DOWNLOAD, &dl1, -1); - gtk_tree_model_get(model, b, NSGTK_DOWNLOAD, &dl2, -1); - - return dl1->status - dl2->status; -} - -void nsgtk_download_do(nsgtk_download_selection_action action) -{ - GList *rows, *dls = NULL; - GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store); - gboolean selection_exists = gtk_tree_selection_count_selected_rows( - nsgtk_download_selection); - - if (selection_exists) { - 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(rows, (GFunc)gtk_tree_path_free, NULL); - g_list_foreach(rows, (GFunc)g_free, NULL); - g_list_free(rows); - } else - dls = g_list_copy(nsgtk_downloads_list); - - g_list_foreach(dls, (GFunc)action, NULL); - g_list_free(dls); -} - -gboolean nsgtk_download_update(gboolean force_update) -{ - /* Be sure we need to update */ - if (!nsgtk_widget_get_visible(GTK_WIDGET(nsgtk_download_window))) - return TRUE; - - GList *list; - gchar *text; - gboolean update, pulse_mode = FALSE; - gint downloaded = 0, total = 0, dls = 0; - gfloat percent, elapsed = g_timer_elapsed(nsgtk_downloads_timer, NULL); - nsgtk_downloads_num_active = 0; - - for (list = nsgtk_downloads_list; list != NULL; list = list->next) { - struct gui_download_window *dl = list->data; - update = force_update; - - switch (dl->status) { - case NSGTK_DOWNLOAD_WORKING: - pulse_mode = TRUE; - - case NSGTK_DOWNLOAD_NONE: - dl->speed = dl->size_downloaded / - (elapsed - dl->start_time); - if (dl->status == NSGTK_DOWNLOAD_NONE) { - dl->time_remaining = (dl->size_total - - dl->size_downloaded)/ - dl->speed; - dl->progress = (gfloat) - dl->size_downloaded / - dl->size_total * 100; - } else - dl->progress++; - - nsgtk_downloads_num_active++; - update = TRUE; - - case NSGTK_DOWNLOAD_COMPLETE: - downloaded += dl->size_downloaded; - total += dl->size_total; - dls++; - - default: - ;//Do nothing - - } - if (update) - nsgtk_download_store_update_item(dl); - } - - if (pulse_mode) { - text = g_strdup_printf( - messages_get(nsgtk_downloads_num_active > 1 ? - "gtkProgressBarPulse" : - "gtkProgressBarPulseSingle"), - nsgtk_downloads_num_active); - gtk_progress_bar_pulse(nsgtk_download_progress_bar); - gtk_progress_bar_set_text(nsgtk_download_progress_bar, text); - } else { - percent = total != 0 ? (gfloat)downloaded / total : 0; - text = g_strdup_printf(messages_get("gtkProgressBar"), - floor(percent*100), dls); - gtk_progress_bar_set_fraction(nsgtk_download_progress_bar, - percent); - gtk_progress_bar_set_text(nsgtk_download_progress_bar, text); - } - - g_free(text); - - if (nsgtk_downloads_num_active == 0) - return FALSE; /* Returning FALSE here cancels the g_timeout */ - else - return TRUE; -} - -void nsgtk_download_store_update_item (struct gui_download_window *dl) -{ - gchar *info = nsgtk_download_info_to_string(dl); - char *human = human_friendly_bytesize(dl->speed); - char speed[strlen(human) + SLEN("/s") + 1]; - sprintf(speed, "%s/s", human); - gchar *time = nsgtk_download_time_to_string(dl->time_remaining); - gboolean pulse = dl->status == NSGTK_DOWNLOAD_WORKING; - - /* 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_PULSE, pulse ? dl->progress : -1, - NSGTK_DOWNLOAD_PROGRESS, pulse ? 0 : dl->progress, - NSGTK_DOWNLOAD_INFO, info, - NSGTK_DOWNLOAD_SPEED, dl->speed == 0 ? "-" : speed, - NSGTK_DOWNLOAD_REMAINING, time, - NSGTK_DOWNLOAD, dl, - -1); - - g_free(info); - 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) { - nsgtk_downloads_list = g_list_remove(nsgtk_downloads_list, dl); - - 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); - download_context_destroy(dl->ctx); - g_string_free(dl->name, TRUE); - g_string_free(dl->time_left, TRUE); - g_free(dl); - - nsgtk_download_sensitivity_evaluate(nsgtk_download_selection); - nsgtk_download_update(FALSE); - } -} -void nsgtk_download_store_cancel_item (struct gui_download_window *dl) -{ - if (dl->sensitivity & NSGTK_DOWNLOAD_CANCEL) { - dl->speed = 0; - dl->size_downloaded = 0; - dl->progress = 0; - dl->time_remaining = -1; - nsgtk_download_change_sensitivity(dl, NSGTK_DOWNLOAD_CLEAR); - nsgtk_download_change_status(dl, NSGTK_DOWNLOAD_CANCELED); - - download_context_abort(dl->ctx); - - g_unlink(download_context_get_filename(dl->ctx)); - - nsgtk_download_update(TRUE); - } -} -void nsgtk_download_sensitivity_evaluate (GtkTreeSelection *selection) -{ - GtkTreeIter iter; - GList *rows; - gboolean selected = gtk_tree_selection_count_selected_rows(selection); - GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store); - nsgtk_download_actions sensitivity = 0; - struct gui_download_window *dl; - - if (selected) { - rows = gtk_tree_selection_get_selected_rows(selection, &model); - while (rows != NULL) { - 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; - } - } else { - rows = nsgtk_downloads_list; - while (rows != NULL) { - dl = rows->data; - sensitivity |= (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR); - 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); -} -void nsgtk_download_change_sensitivity(struct gui_download_window *dl, - nsgtk_download_actions sensitivity) -{ - dl->sensitivity = sensitivity; - nsgtk_download_sensitivity_evaluate(nsgtk_download_selection); -} -void nsgtk_download_change_status ( - struct gui_download_window *dl, nsgtk_download_status status) -{ - dl->status = status; - if (status != NSGTK_DOWNLOAD_NONE) { - 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_STATUS, - messages_get(status_messages[status]), -1); - } -} - -gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *domain, - const gchar *size) -{ - enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS }; - GtkWidget *dialog; - char *destination = NULL; - gchar *message = g_strdup(messages_get("gtkStartDownload")); - 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>", - message, 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(message); - 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_current_folder - (GTK_FILE_CHOOSER(dialog), - nsoption_charp(downloads_directory)); - gtk_file_chooser_set_do_overwrite_confirmation - (GTK_FILE_CHOOSER(dialog), - nsoption_bool(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 = malloc(strlen(nsoption_charp(downloads_directory)) - + strlen(filename) + SLEN("/") + 1); - if (destination == NULL) { - warn_user(messages_get("NoMemory"), 0); - break; - } - sprintf(destination, "%s/%s", - nsoption_charp(downloads_directory), filename); - /* Test if file already exists and display overwrite - * confirmation if needed */ - if (g_file_test(destination, G_FILE_TEST_EXISTS) && - nsoption_bool(request_overwrite)) { - message = g_strdup_printf(messages_get( - "gtkOverwrite"), filename); - info = g_strdup_printf(messages_get( - "gtkOverwriteInfo"), - nsoption_charp(downloads_directory)); - - dialog = gtk_message_dialog_new_with_markup( - nsgtk_download_parent, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_CANCEL, - "<b>%s</b>",message); - gtk_message_dialog_format_secondary_markup( - GTK_MESSAGE_DIALOG(dialog), - "%s", info); - - GtkWidget *button = gtk_dialog_add_button( - GTK_DIALOG(dialog), - "_Replace", - GTK_RESPONSE_DOWNLOAD); - gtk_button_set_image(GTK_BUTTON(button), - gtk_image_new_from_stock( - "gtk-save", - GTK_ICON_SIZE_BUTTON)); - - gint result = gtk_dialog_run(GTK_DIALOG( - dialog)); - if (result == GTK_RESPONSE_CANCEL) - destination = NULL; - - gtk_widget_destroy(dialog); - g_free(message); - g_free(info); - } - break; - } - } - return destination; -} -gchar* nsgtk_download_info_to_string (struct gui_download_window *dl) -{ - gchar *size_info = g_strdup_printf(messages_get("gtkSizeInfo"), - human_friendly_bytesize(dl->size_downloaded), - dl->size_total == 0 ? messages_get("gtkUnknownSize") : - human_friendly_bytesize(dl->size_total)); - - gchar *r; - if (dl->status != NSGTK_DOWNLOAD_ERROR) - r = g_strdup_printf("%s\n%s", dl->name->str, size_info); - else - r = g_strdup_printf("%s\n%s", dl->name->str, - dl->error->message); - - g_free(size_info); - return r; -} -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; -} |