Merged revisions 4282-4285,4288-4293,4297-4298,4307,4309-4313,4322,4324-4431,4434-4494,4500-4508,4515,4517,4525-4545,4548-4555,4558-4572,4574-4576,4579,4582-4615,4618-4628,4630-4634,4636-4641,4643-4654,4656-4675,4677,4679-4685,4687-4750 via svnmerge from

svn://svn.netsurf-browser.org/branches/mikeL/netsurf

........
  r4689 | mikeL | 2008-07-17 19:59:20 +0100 (Thu, 17 Jul 2008) | 1 line
  
  Changed the toolbar at the bottom of the downloads dialog to a horizontal button box and added a 'Close' button (Based on a suggestion from the dev list). Internationalized the rest of the strings. Fixed many style errors (thanks rjek). Set authentication fields in the options dialog to be insensitive when proxy type is simple. Namespace'd the rest of download.h
........
  r4690 | mikeL | 2008-07-17 21:39:39 +0100 (Thu, 17 Jul 2008) | 1 line
  
  Removed close button. fixed text on resume button
........
  r4691 | mikeL | 2008-07-17 22:13:13 +0100 (Thu, 17 Jul 2008) | 1 line
  
  Added gtk downloads section
........
  r4715 | mikeL | 2008-07-20 19:41:39 +0100 (Sun, 20 Jul 2008) | 1 line
  
  Downloads are now automatically sorted (Downloading, Error'd, Completed, Canceled). New downloads appear at the beginning of the list. Removed leftover callback for close button. Downloads without a known total size are now handled correctly (bouncing progress block). Fixed bug where shift+click downloads would throw an error (encoding is now always set to binary).
........
  r4716 | mikeL | 2008-07-20 19:45:24 +0100 (Sun, 20 Jul 2008) | 1 line
  
  Removed unnecessary wndDownloads section
........
  r4717 | mikeL | 2008-07-20 19:53:44 +0100 (Sun, 20 Jul 2008) | 1 line
  
  Removed label on url in about dialog. Removed extra variable from the input callback. These changes should have already been committed a while back but for some reason they were skipped
........
  r4718 | mikeL | 2008-07-21 04:56:28 +0100 (Mon, 21 Jul 2008) | 1 line
  
  Total progress bar is now working and acts correctly with downloads of unknown size. All downloads are now stored in a GList (this will later make it possible to implement things like clearing all inactive downloads). Individual downloads no longer update themselves every .5 seconds, the function nsgtk_download_update is called using a g_timeout and cycles through the GList updating the total progress bar and each download. Downloads of unknown size now report their total size upon completion.
........
  r4719 | mikeL | 2008-07-21 05:06:17 +0100 (Mon, 21 Jul 2008) | 1 line
  
  Changed names of two functions that change sensitivity and status.
........
  r4720 | mikeL | 2008-07-21 16:56:41 +0100 (Mon, 21 Jul 2008) | 1 line
  
  Updated messages file
........
  r4722 | mikeL | 2008-07-21 21:44:23 +0100 (Mon, 21 Jul 2008) | 1 line
  
  Clear button now clears all inactive downloads when there is no selection.
........
  r4723 | mikeL | 2008-07-21 22:11:00 +0100 (Mon, 21 Jul 2008) | 1 line
  
  Fixed the total progress bar lagging behind events such as cancelations.
........
  r4727 | mikeL | 2008-07-23 19:33:53 +0100 (Wed, 23 Jul 2008) | 1 line
  
  Added an overwrite confirmation dialog for the 'save' button
........
  r4728 | mikeL | 2008-07-23 19:43:44 +0100 (Wed, 23 Jul 2008) | 1 line
  
  Save as dialog now starts in the default download directory instead of the user's home folder
........
  r4729 | mikeL | 2008-07-23 20:02:34 +0100 (Wed, 23 Jul 2008) | 1 line
  
  Updated Copyright information
........
  r4734 | mikeL | 2008-07-24 19:30:12 +0100 (Thu, 24 Jul 2008) | 1 line
  
  Fixed Info column not being set to expand
........

svn path=/trunk/netsurf/; revision=4752
This commit is contained in:
Rob Kendrick 2008-07-26 17:30:26 +00:00
parent 7ae05a60ae
commit e894e38c37
10 changed files with 485 additions and 410 deletions

View File

@ -304,6 +304,11 @@ Unwritten:Writing data to file failed.
# download window.
#
gtkSizeInfo:%s of %s
gtkProgressBar:%.0f%% of %u files
gtkProgressBarPulse:Downloading %u files
gtkProgressBarPulseSingle:Downloading %u file
# Column Headers
#
gtkProgress:Progress
@ -311,22 +316,29 @@ gtkDetails:Details
gtkSpeed:Speed
gtkRemaining:Remaining
# Status
# Status Messages
# spaces necessary
#
gtkError:Error
gtkComplete:Complete
gtkCanceled:Canceled
gtkWorking:Working
gtkError: Error
gtkComplete: Complete
gtkCanceled: Canceled
gtkWorking: Working
# Dialogs
#
gtkQuit:Quit NetSurf?
gtkDownloadsRunning:There are still downloads running, if you quit now these will be canceled and the files deleted.
gtkStartDownload:Download file?
gtkOverwrite:A file named "%s" already exists. Do you want to replace it?
gtkOverwriteInfo:The file already exists in "%s". Replacing it will overwrite its contents.
gtkFailed:Download failed
gtkFileError:File error: %s
gtkInfo:%s from %s is %s in size
gtkSave:Save file as...
gtkUnknownHost:an unknown host
gtkUnknownFile:
gtkUnknownSize:unknown
# Printing user interface tokens
# ==============================

View File

@ -6,7 +6,7 @@
# Use libharu to enable PDF export and GTK printing support. There is no
# auto-detection available for this, as it does not have a pkg-config file.
NETSURF_USE_HARU_PDF=YES
NETSURF_USE_HARU_PDF=NO
# The following options are GTK-specific
ifeq ($(TARGET),gtk)

View File

@ -880,6 +880,10 @@ bool browser_window_input_callback(struct browser_window *bw,
input->gadget->caret_form_offset =
get_form_offset(input, text_box, box_offset);
/* update the form offset */
input->gadget->caret_form_offset =
get_form_offset(input, text_box, box_offset);
selection_get_end(bw->sel, &end_offset);
box_coords(input, &box_x, &box_y);

View File

@ -52,10 +52,9 @@ void nsgtk_about_dialog_init(GtkWindow *parent, struct browser_window *bw, const
gtk_about_dialog_set_url_hook (launch_url, (gpointer) bw, NULL);
gtk_show_about_dialog(parent, "artists", artists, "authors", authors,
"comments", description,"copyright", copyright, "documenters", documenters,
"license", licence,
"program-name", name, "translator-credits", translators,
"version", version, "website", url, "website-label", url_label,
"comments", description,"copyright", copyright,
"documenters", documenters, "license", licence, "program-name", name,
"translator-credits", translators, "version", version, "website", url,
"wrap-license", FALSE, NULL);
}

View File

@ -317,7 +317,7 @@ COMBO_CHANGED(comboProxyType, proxy_type)
option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NTLM;
break;
}
gboolean sensitive = (!proxy_type == 0);
gboolean sensitive = (option_http_proxy_auth);
gtk_widget_set_sensitive (entryProxyHost, sensitive);
gtk_widget_set_sensitive (entryProxyPort, sensitive);
gtk_widget_set_sensitive (entryProxyUser, sensitive);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008 Rob Kendrick <rjek@netsurf-browser.org>
* Copyright 2008 Michael Lester <element3260@gmail.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -30,43 +30,51 @@
#include "gtk/options.h"
#include "gtk/gtk_download.h"
#define UPDATE_RATE 500 /* In milliseconds */
#define GLADE_NAME "downloads.glade"
static GtkWindow *nsgtk_download_window, *nsgtk_download_parent;
static GtkWidget *nsgtk_download_progressBar;
static GtkProgressBar *nsgtk_download_progress_bar;
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" };
static gboolean nsgtk_download_hide (GtkWidget *window);
static GTimer *nsgtk_downloads_timer;
static GList *nsgtk_downloads_list, *nsgtk_download_buttons;
static gint nsgtk_downloads_num_active;
static gchar* status_messages[] = { NULL, "gtkWorking", "gtkError",
"gtkComplete", "gtkCanceled" };
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 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_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(
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);
static void nsgtk_download_change_status (
struct gui_download_window *dl, nsgtk_download_status status);
static gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain,
gchar *size);
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);
@ -81,8 +89,8 @@ void nsgtk_download_init()
nsgtk_download_buttons =
glade_xml_get_widget_prefix(gladeFile, "button");
nsgtk_download_progressBar =
glade_xml_get_widget(gladeFile, "progressBar");
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_parent = NULL;
@ -92,6 +100,8 @@ void nsgtk_download_init()
gtk_window_set_destroy_with_parent(GTK_WINDOW(nsgtk_download_window),
FALSE);
nsgtk_downloads_timer = g_timer_new();
nsgtk_download_tree = nsgtk_download_tree_view_new(gladeFile);
nsgtk_download_store = gtk_list_store_new(NSGTK_DOWNLOAD_N_COLUMNS,
@ -99,12 +109,22 @@ void nsgtk_download_init()
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_sortable_set_sort_func(GTK_TREE_SORTABLE(nsgtk_download_store),
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);
g_object_unref(nsgtk_download_store);
nsgtk_download_selection =
@ -113,38 +133,36 @@ void nsgtk_download_init()
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_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);
}
void nsgtk_download_destroy ()
{
gtk_tree_selection_select_all(nsgtk_download_selection);
nsgtk_download_selection_do(NULL, nsgtk_download_store_cancel_item);
nsgtk_download_do(nsgtk_download_store_cancel_item);
}
bool nsgtk_check_for_downloads (GtkWindow *parent)
{
if (nsgtk_downloads != 0) {
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>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>");
"<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);
@ -176,13 +194,16 @@ 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));
gboolean unknown_size = total_size == 0;
const gchar *size = (total_size == 0 ?
messages_get("gtkUnknownSize") :
human_friendly_bytesize(total_size));
nsgtk_download_parent = nsgtk_scaffolding_get_window(gui);
struct gui_download_window *download = malloc(sizeof *download);
if (url_nice(url, &filename, false) != URL_FUNC_OK)
strcpy(filename, messages_get("gtkUnknownFile"));
@ -192,20 +213,26 @@ struct gui_download_window *gui_download_window_create(const char *url,
destination = nsgtk_download_dialog_show(filename, domain, size);
if (destination == NULL)
return NULL;
download = malloc(sizeof *download);
/* 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), &nsgtk_download_iter));
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->start_time = g_timer_elapsed(nsgtk_downloads_timer, NULL);
download->time_remaining = -1;
download->status = NSGTK_DOWNLOAD_NONE;
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->progress = 0;
download->error = NULL;
download->write = g_io_channel_new_file(destination, "w",
&download->error);
@ -213,25 +240,23 @@ struct gui_download_window *gui_download_window_create(const char *url,
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);
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);
nsgtk_downloads++;
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);
nsgtk_downloads_list = g_list_prepend(nsgtk_downloads_list, download);
return download;
}
@ -241,35 +266,19 @@ void gui_download_window_data(struct gui_download_window *dw, const char *data,
{
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);
nsgtk_download_change_sensitivity(dw, NSGTK_DOWNLOAD_CLEAR);
nsgtk_download_change_status(dw, NSGTK_DOWNLOAD_ERROR);
nsgtk_download_update(TRUE);
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_store_update_item(dw);
dw->last_update = elapsed;
}
}
@ -285,16 +294,16 @@ void gui_download_window_done(struct gui_download_window *dw)
g_io_channel_unref(dw->write);
dw->speed = 0;
dw->time_remaining = -1;
dw->progress = 100;
nsgtk_download_sensitivity_set(dw, NSGTK_DOWNLOAD_CLEAR);
dw->status = NSGTK_DOWNLOAD_COMPLETE;
dw->size_total = dw->size_downloaded;
nsgtk_download_change_sensitivity(dw, NSGTK_DOWNLOAD_CLEAR);
nsgtk_download_change_status(dw, NSGTK_DOWNLOAD_COMPLETE);
if (option_downloads_clear)
nsgtk_download_store_clear_item(dw);
else
nsgtk_download_store_update_item(dw);
nsgtk_downloads--;
nsgtk_download_update(TRUE);
}
@ -309,8 +318,8 @@ GtkTreeView* nsgtk_download_tree_view_new(GladeXML *gladeFile)
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);
NSGTK_DOWNLOAD_PROGRESS, "pulse", NSGTK_DOWNLOAD_PULSE,
"text", NSGTK_DOWNLOAD_STATUS, NULL);
/* Information column */
renderer = gtk_cell_renderer_text_new();
@ -347,34 +356,146 @@ void nsgtk_download_tree_view_row_activated(GtkTreeView *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);
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 (!GTK_WIDGET_VISIBLE(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++;
}
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);
gchar *speed = g_strconcat(human_friendly_bytesize(dl->speed), "/s",
NULL);
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_PROGRESS, dl->progress,
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);
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);
@ -384,94 +505,75 @@ 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,
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);
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->status = NSGTK_DOWNLOAD_CANCELED;
dl->speed = 0;
dl->size_downloaded = 0;
dl->progress = 0;
dl->time_remaining = -1;
nsgtk_download_sensitivity_set(dl, NSGTK_DOWNLOAD_CLEAR);
nsgtk_download_change_sensitivity(dl, NSGTK_DOWNLOAD_CLEAR);
nsgtk_download_change_status(dl, NSGTK_DOWNLOAD_CANCELED);
if (dl->fetch)
fetch_abort(dl->fetch);
g_unlink(dl->filename);
nsgtk_download_store_update_item(dl);
nsgtk_downloads--;
nsgtk_download_update(TRUE);
}
}
void nsgtk_download_selection_do(GtkWidget *button, selection_action action)
void nsgtk_download_sensitivity_evaluate (GtkTreeSelection *selection)
{
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);
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_sensitivity_selection_changed (GtkTreeSelection *selection)
{
GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store);
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;
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;
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);
}
@ -490,12 +592,36 @@ void nsgtk_download_sensitivity_update_buttons(
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 (gchar *filename, gchar *domain, gchar *size)
gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain,
const gchar *size)
{
enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS };
GtkWidget *dialog;
gchar *destination = NULL;
gchar *message = g_strdup(messages_get("gtkStartDownload"));
gchar *info = g_strdup_printf(messages_get("gtkInfo"), filename,
domain, size);
@ -504,7 +630,7 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, gchar *size)
GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
"<span size=\"x-large\" weight=\"ultrabold\">%s</span>"
"\n\n<small>%s</small>",
messages_get("gtkStartDownload"), info);
message, info);
gtk_dialog_add_buttons(GTK_DIALOG(dialog), GTK_STOCK_SAVE,
GTK_RESPONSE_DOWNLOAD, GTK_STOCK_CANCEL,
@ -513,6 +639,7 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, gchar *size)
gint result = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
g_free(message);
g_free(info);
switch (result) {
@ -526,6 +653,9 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, gchar *size)
NULL);
gtk_file_chooser_set_current_name
(GTK_FILE_CHOOSER(dialog), filename);
gtk_file_chooser_set_current_folder
(GTK_FILE_CHOOSER(dialog),
option_downloads_directory);
gtk_file_chooser_set_do_overwrite_confirmation
(GTK_FILE_CHOOSER(dialog),
option_request_overwrite);
@ -540,6 +670,44 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, gchar *size)
case GTK_RESPONSE_DOWNLOAD: {
destination = g_strconcat(option_downloads_directory,
"/", filename, NULL);
/* Test if file already exists and display overwrite
* confirmation if needed */
if (g_file_test(destination, G_FILE_TEST_EXISTS)
&& option_request_overwrite) {
message = g_strdup_printf(messages_get(
"gtkOverwrite"), filename);
info = g_strdup_printf(messages_get(
"gtkOverwriteInfo"),
option_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),
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;
}
}
@ -548,15 +716,19 @@ gchar* nsgtk_download_dialog_show (gchar *filename, gchar *domain, gchar *size)
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,
gchar *size_info = g_strdup_printf(messages_get("gtkSizeInfo"),
human_friendly_bytesize(dl->size_downloaded),
dl->size_total == 0 ? "Unknown" :
human_friendly_bytesize(dl->size_total));
dl->size_total == 0 ? messages_get("gtkUnknownSize") :
human_friendly_bytesize(dl->size_total));
if (dl->status != NSGTK_DOWNLOAD_ERROR)
return g_strdup_printf("%s\n%s",
dl->name->str, size_info);
else
return g_strdup_printf("%s\n%s", dl->name->str,
dl->error->message);
g_free(size_info);
}
gchar* nsgtk_download_time_to_string (gint seconds)

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008 Rob Kendrick <rjek@netsurf-browser.org>
* Copyright 2008 Michael Lester <element3260@gmail.com>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -26,6 +26,7 @@ enum {
NSGTK_DOWNLOAD_INFO,
NSGTK_DOWNLOAD_REMAINING,
NSGTK_DOWNLOAD_SPEED,
NSGTK_DOWNLOAD_PULSE,
NSGTK_DOWNLOAD_STATUS,
NSGTK_DOWNLOAD,
@ -33,11 +34,11 @@ enum {
};
typedef enum {
NSGTK_DOWNLOAD_NONE,
NSGTK_DOWNLOAD_WORKING,
NSGTK_DOWNLOAD_ERROR,
NSGTK_DOWNLOAD_COMPLETE,
NSGTK_DOWNLOAD_CANCELED,
NSGTK_DOWNLOAD_NONE
NSGTK_DOWNLOAD_CANCELED
} nsgtk_download_status;
typedef enum {
@ -57,18 +58,17 @@ struct gui_download_window {
gint size_total;
gint size_downloaded;
gint progress;
gfloat last_update;
gfloat time_remaining;
gfloat start_time;
gfloat speed;
gchar *filename;
GtkTreeRowReference *row;
GTimer *timer;
GIOChannel *write;
GError *error;
};
typedef void (*selection_action)(struct gui_download_window *dl);
typedef void (*nsgtk_download_selection_action)(struct gui_download_window *dl);
void nsgtk_download_init();
void nsgtk_download_destroy (void);

View File

@ -82,13 +82,13 @@ void gui_start_selection(struct gui_window *g)
void gui_paste_from_clipboard(struct gui_window *g, int x, int y)
{
char *text;
gchar *text;
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
text = gtk_clipboard_wait_for_text (clipboard);
/* clipboard_wait... converts the string to utf8 for us */
if (text != NULL)
browser_window_paste_text(g->bw, text, strlen(text), true);
free(text);
g_free(text);
}
bool gui_empty_clipboard(void)
@ -103,8 +103,8 @@ bool gui_empty_clipboard(void)
bool gui_commit_clipboard(void)
{
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_text (clipboard, current_selection->str, -1);
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_text(clipboard, current_selection->str, -1);
return true;
}

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.4 on Mon Jul 14 18:30:15 2008 -->
<?xml version="1.0"?>
<glade-interface>
<requires-version lib="gtk+" version="2.12"/>
<widget class="GtkWindow" id="wndDownloads">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="title" translatable="yes">NetSurf Downloads</property>
@ -14,94 +13,136 @@
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<child>
<widget class="GtkTreeView" id="treeDownloads">
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_clickable">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<widget class="GtkTreeView" id="treeDownloads">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="search_column">2</property>
<property name="show_expanders">False</property>
<property name="rubber_banding">True</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="border_width">2</property>
<child>
<widget class="GtkProgressBar" id="progressBar">
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="fraction">0.20999999344348907</property>
<property name="text" translatable="yes">21% of 3 files</property>
<property name="top_padding">2</property>
<property name="bottom_padding">2</property>
<property name="left_padding">2</property>
<property name="right_padding">2</property>
<child>
<widget class="GtkProgressBar" id="progressBar">
<property name="visible">True</property>
<property name="show_text">True</property>
<property name="text" translatable="yes">0% of 0 files</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="toolbar2">
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
<property name="show_arrow">False</property>
<property name="icon_size">GTK_ICON_SIZE_MENU</property>
<property name="icon_size_set">True</property>
<property name="homogeneous">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkToolButton" id="buttonPause">
<widget class="GtkButton" id="buttonPause">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="is_important">True</property>
<property name="label"> Pause</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-media-pause</property>
<signal name="clicked" handler="button_clear_clicked" object="NULL"/>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-media-pause</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="buttonPlay">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="response_id">0</property>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<child>
<widget class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="stock">gtk-media-play</property>
<property name="icon_size">2</property>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Resume</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="buttonResume">
<widget class="GtkButton" id="buttonCancel">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="is_important">True</property>
<property name="label"> Resume</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-media-play</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-cancel</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="buttonCancel">
<widget class="GtkButton" id="buttonClear">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="is_important">True</property>
<property name="label"> Cancel</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-cancel</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-clear</property>
<property name="relief">GTK_RELIEF_NONE</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="buttonClear">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="tooltip" translatable="yes">Remove completed or cancelled downloads from the list</property>
<property name="visible_vertical">False</property>
<property name="is_important">True</property>
<property name="label"> Clear</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-clear</property>
<signal name="clicked" handler="button_clear_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">GTK_PACK_END</property>
<property name="position">1</property>
</packing>
</child>
@ -109,7 +150,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
</widget>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<?xml version="1.0"?>
<glade-interface>
<requires-version lib="gtk+" version="2.12"/>
<widget class="GtkWindow" id="wndBrowser">
<property name="title" translatable="yes">NetSurf</property>
<property name="window_position">GTK_WIN_POS_CENTER</property>
@ -24,7 +23,6 @@
<property name="tooltip" translatable="yes">Opens a new browser window.</property>
<property name="label" translatable="yes">_New Window</property>
<property name="use_underline">True</property>
<accelerator key="N" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image554">
<property name="visible">True</property>
@ -32,6 +30,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="N" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -40,7 +39,6 @@
<property name="tooltip" translatable="yes">Open a file on your computer into this browser window.</property>
<property name="label" translatable="yes">_Open File...</property>
<property name="use_underline">True</property>
<accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image555">
<property name="visible">True</property>
@ -48,6 +46,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="F" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -56,7 +55,6 @@
<property name="tooltip" translatable="yes">Close this browser window.</property>
<property name="label" translatable="yes">_Close Window</property>
<property name="use_underline">True</property>
<accelerator key="W" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image556">
<property name="visible">True</property>
@ -64,6 +62,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="W" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -78,7 +77,6 @@
<property name="tooltip" translatable="yes">Save this page to disc, optionally including images, etc.</property>
<property name="label" translatable="yes">Save page...</property>
<property name="use_underline">True</property>
<accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image557">
<property name="visible">True</property>
@ -86,6 +84,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="S" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -166,7 +165,6 @@
<property name="tooltip" translatable="yes">Produce a hardcopy on your printer.</property>
<property name="label" translatable="yes">Print...</property>
<property name="use_underline">True</property>
<accelerator key="P" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image559">
<property name="visible">True</property>
@ -174,6 +172,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="P" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -245,7 +244,7 @@
<property name="label">gtk-select-all</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<accelerator key="a" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="a" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -260,7 +259,7 @@
<property name="tooltip" translatable="yes">Find specific text in the current browser window.</property>
<property name="label" translatable="yes">_Find...</property>
<property name="use_underline">True</property>
<accelerator key="F" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="F" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -299,7 +298,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Stop</property>
<property name="use_underline">True</property>
<accelerator key="Escape" modifiers="" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image561">
<property name="visible">True</property>
@ -307,6 +305,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="Escape" signal="activate"/>
</widget>
</child>
<child>
@ -314,7 +313,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Reload</property>
<property name="use_underline">True</property>
<accelerator key="F5" modifiers="" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image562">
<property name="visible">True</property>
@ -322,6 +320,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="F5" signal="activate"/>
</widget>
</child>
<child>
@ -335,7 +334,6 @@
<property name="tooltip" translatable="yes">Scale the page in the current browser window to be smaller or larger.</property>
<property name="label" translatable="yes">_Scale View...</property>
<property name="use_underline">True</property>
<accelerator key="F11" modifiers="" signal="activate"/>
<child>
<widget class="GtkMenu" id="scale_view_menu">
<child>
@ -343,9 +341,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Zoom _in</property>
<property name="use_underline">True</property>
<accelerator key="equal" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="KP_Add" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="plus" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image564">
<property name="visible">True</property>
@ -353,6 +348,9 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="equal" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="KP_Add" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="plus" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -360,8 +358,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Normal size</property>
<property name="use_underline">True</property>
<accelerator key="KP_0" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="0" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image565">
<property name="visible">True</property>
@ -369,6 +365,8 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="KP_0" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="0" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -376,8 +374,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">Zoom _out</property>
<property name="use_underline">True</property>
<accelerator key="KP_Subtract" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="minus" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image566">
<property name="visible">True</property>
@ -385,6 +381,8 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="KP_Subtract" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="minus" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
</widget>
@ -396,6 +394,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="F11" signal="activate"/>
</widget>
</child>
<child>
@ -403,7 +402,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Fullscreen</property>
<property name="use_underline">True</property>
<accelerator key="F11" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image567">
<property name="visible">True</property>
@ -411,6 +409,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="F11" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -550,7 +549,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Back</property>
<property name="use_underline">True</property>
<accelerator key="Left" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image568">
<property name="visible">True</property>
@ -558,6 +556,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="Left" signal="activate" modifiers="GDK_MOD1_MASK"/>
</widget>
</child>
<child>
@ -565,7 +564,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Forward</property>
<property name="use_underline">True</property>
<accelerator key="Right" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image569">
<property name="visible">True</property>
@ -573,6 +571,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="Right" signal="activate" modifiers="GDK_MOD1_MASK"/>
</widget>
</child>
<child>
@ -580,7 +579,6 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Home</property>
<property name="use_underline">True</property>
<accelerator key="Home" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image570">
<property name="visible">True</property>
@ -588,6 +586,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="Home" signal="activate" modifiers="GDK_MOD1_MASK"/>
</widget>
</child>
<child>
@ -601,7 +600,7 @@
<property name="tooltip" translatable="yes">Show the history tree for this browser window.</property>
<property name="label" translatable="yes">_Local history...</property>
<property name="use_underline">True</property>
<accelerator key="F7" modifiers="" signal="activate"/>
<accelerator key="F7" signal="activate"/>
</widget>
</child>
<child>
@ -610,7 +609,7 @@
<property name="tooltip" translatable="yes">Show the history tree for all windows.</property>
<property name="label" translatable="yes">_Global history...</property>
<property name="use_underline">True</property>
<accelerator key="F7" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="F7" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@ -634,7 +633,7 @@
<property name="tooltip" translatable="yes">Open a window showing all your bookmarks.</property>
<property name="label" translatable="yes">_Show Bookmarks...</property>
<property name="use_underline">True</property>
<accelerator key="F6" modifiers="" signal="activate"/>
<accelerator key="F6" signal="activate"/>
</widget>
</child>
<child>
@ -648,7 +647,7 @@
<property name="tooltip" translatable="yes">Open an address into this browser window.</property>
<property name="label" translatable="yes">_Open location...</property>
<property name="use_underline">True</property>
<accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<accelerator key="L" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
</widget>
@ -669,7 +668,6 @@
<property name="tooltip" translatable="yes">Shows the contents of the NetSurf manual.</property>
<property name="label" translatable="yes">_Contents...</property>
<property name="use_underline">True</property>
<accelerator key="F1" modifiers="" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image571">
<property name="visible">True</property>
@ -677,6 +675,7 @@
<property name="icon_size">1</property>
</widget>
</child>
<accelerator key="F1" signal="activate"/>
</widget>
</child>
<child>
@ -839,7 +838,6 @@
<property name="label" translatable="yes">Status bar text goes here</property>
<property name="selectable">True</property>
<property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
<property name="width_chars">50</property>
</widget>
<packing>
<property name="resize">False</property>
@ -1536,157 +1534,6 @@
</widget>
</child>
</widget>
<widget class="GtkWindow" id="wndDownloads">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="title" translatable="yes">NetSurf Downloads</property>
<property name="window_position">GTK_WIN_POS_CENTER</property>
<property name="default_width">500</property>
<property name="default_height">400</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_UTILITY</property>
<signal name="delete_event" handler="gtk_widget_hide"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<child>
<widget class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
<property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
<child>
<widget class="GtkToolButton" id="downloadPause">
<property name="visible">True</property>
<property name="label">Pause</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-media-pause</property>
<signal name="clicked" handler="nsgtk_downloadPause_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="downloadResume">
<property name="visible">True</property>
<property name="label">Resume</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-media-play</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="downloadCancel">
<property name="visible">True</property>
<property name="label">Cancel</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-cancel</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="downloadCleanup">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Remove completed or cancelled downloads from the list</property>
<property name="visible_vertical">False</property>
<property name="is_important">True</property>
<property name="label">Clean up</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-clear</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkSeparatorToolItem" id="toolbutton2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="draw">False</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<widget class="GtkToolItem" id="toolProgress">
<property name="visible">True</property>
<property name="is_important">True</property>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkProgressBar" id="progressbar1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="fraction">0.10000000149011612</property>
<property name="text" translatable="yes">10% of 5 files</property>
<property name="ellipsize">PANGO_ELLIPSIZE_END</property>
</widget>
<packing>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">230kB/sec, 12 minutes remaining</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<widget class="GtkSeparatorToolItem" id="toolbutton1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="draw">False</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkTreeView" id="treeDownloads">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK</property>
<property name="reorderable">True</property>
<property name="rules_hint">True</property>
<property name="rubber_banding">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkMenu" id="menuPopup">
<child>
<widget class="GtkImageMenuItem" id="popupBack">