aboutsummaryrefslogtreecommitdiffstats
path: root/embed/downloader-view.c
diff options
context:
space:
mode:
Diffstat (limited to 'embed/downloader-view.c')
-rw-r--r--embed/downloader-view.c1100
1 files changed, 1100 insertions, 0 deletions
diff --git a/embed/downloader-view.c b/embed/downloader-view.c
new file mode 100644
index 000000000..97e05a613
--- /dev/null
+++ b/embed/downloader-view.c
@@ -0,0 +1,1100 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Marco Pesenti Gritti
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "downloader-view.h"
+#include "eel-gconf-extensions.h"
+#include "ephy-gui.h"
+#include "ephy-prefs.h"
+#include "ephy-ellipsizing-label.h"
+#include "ephy-embed-utils.h"
+#include "ephy-file-helpers.h"
+
+#include <gtk/gtktreeview.h>
+#include <gtk/gtkliststore.h>
+#include <gtk/gtktreeviewcolumn.h>
+#include <libgnome/gnome-i18n.h>
+#include <libgnomeui/gnome-dialog-util.h>
+#include <libgnomeui/gnome-dialog.h>
+#include <gtk/gtkprogressbar.h>
+#include <libgnomevfs/gnome-vfs-mime-handlers.h>
+
+enum
+{
+ DOWNLOAD_REMOVE,
+ DOWNLOAD_PAUSE,
+ DOWNLOAD_RESUME,
+ LAST_SIGNAL
+};
+
+enum
+{
+ COL_PERCENT,
+ COL_FILENAME,
+ COL_SIZE,
+ COL_REMAINING,
+ COL_PERSIST_OBJECT
+};
+
+struct DownloaderViewPrivate
+{
+ GHashTable *details_hash;
+ GtkTreeModel *model;
+ gboolean show_details;
+
+ /* Widgets */
+ GtkWidget *treeview;
+ GtkWidget *details_file;
+ GtkWidget *details_location;
+ GtkWidget *details_status;
+ GtkWidget *details_elapsed;
+ GtkWidget *details_remaining;
+ GtkWidget *details_progress;
+ GtkWidget *details_button;
+ GtkWidget *keep_open_check;
+ GtkWidget *pause_button;
+ GtkWidget *resume_button;
+ GtkWidget *abort_button;
+ GtkWidget *open_button;
+};
+
+typedef struct
+{
+ glong elapsed;
+ glong remaining;
+ gfloat speed;
+ gint size_total;
+ gint size_done;
+ gfloat progress;
+ gboolean can_pause;
+ gchar *filename;
+ gchar *source;
+ gchar *dest;
+ DownloadStatus status;
+
+ GtkTreeRowReference *ref;
+} DownloadDetails;
+
+typedef struct
+{
+ gboolean can_resume;
+ gboolean can_pause;
+ gboolean can_abort;
+ gboolean can_open;
+ DownloaderViewPrivate *priv;
+} ControlsInfo;
+
+enum
+{
+ PROP_TREEVIEW,
+ PROP_KEEP_OPEN,
+ PROP_DETAILS_FRAME,
+ PROP_DETAILS_SEPARATOR,
+ PROP_DETAILS_TABLE,
+ PROP_DETAILS_STATUS,
+ PROP_DETAILS_ELAPSED,
+ PROP_DETAILS_REMAINING,
+ PROP_DETAILS_PROGRESS,
+ PROP_PAUSE_BUTTON,
+ PROP_RESUME_BUTTON,
+ PROP_ABORT_BUTTON,
+ PROP_OPEN_BUTTON,
+ PROP_DETAILS_BUTTON
+};
+
+static const
+EphyDialogProperty properties [] =
+{
+ { PROP_TREEVIEW, "clist", NULL, PT_NORMAL, NULL },
+ { PROP_KEEP_OPEN, "keep_open_check", CONF_DOWNLOADING_KEEP_OPEN, PT_NORMAL, NULL },
+ { PROP_DETAILS_FRAME, "details_frame", NULL, PT_NORMAL, NULL },
+ { PROP_DETAILS_SEPARATOR, "details_separator", NULL, PT_NORMAL, NULL },
+ { PROP_DETAILS_TABLE, "details_table", NULL, PT_NORMAL, NULL },
+ { PROP_DETAILS_STATUS, "details_status", NULL, PT_NORMAL, NULL },
+ { PROP_DETAILS_ELAPSED, "details_elapsed", NULL, PT_NORMAL, NULL },
+ { PROP_DETAILS_REMAINING, "details_remaining", NULL, PT_NORMAL, NULL },
+ { PROP_DETAILS_PROGRESS, "details_progress", NULL, PT_NORMAL, NULL },
+ { PROP_PAUSE_BUTTON, "pause_button", NULL, PT_NORMAL, NULL },
+ { PROP_RESUME_BUTTON, "resume_button", NULL, PT_NORMAL, NULL },
+ { PROP_ABORT_BUTTON, "abort_button", NULL, PT_NORMAL, NULL },
+ { PROP_OPEN_BUTTON, "open_button", NULL, PT_NORMAL, NULL },
+ { PROP_DETAILS_BUTTON, "details_togglebutton", CONF_DOWNLOADING_SHOW_DETAILS, PT_NORMAL, NULL },
+
+ { -1, NULL, NULL }
+};
+
+static void
+downloader_view_build_ui (DownloaderView *dv);
+static void
+downloader_view_class_init (DownloaderViewClass *klass);
+static void
+downloader_view_finalize (GObject *object);
+static void
+downloader_view_init (DownloaderView *dv);
+
+/* Callbacks */
+void
+download_dialog_resume_cb (GtkButton *button, DownloaderView *dv);
+void
+download_dialog_pause_cb (GtkButton *button, DownloaderView *dv);
+void
+download_dialog_abort_cb (GtkButton *button, DownloaderView *dv);
+static void
+downloader_treeview_selection_changed_cb (GtkTreeSelection *selection,
+ DownloaderView *dv);
+gboolean
+download_dialog_delete_cb (GtkWidget *window, GdkEventAny *event,
+ DownloaderView *dv);
+void
+download_dialog_details_cb (GtkToggleButton *button,
+ DownloaderView *dv);
+void
+download_dialog_open_cb (GtkWidget *button,
+ DownloaderView *dv);
+
+static GObjectClass *parent_class = NULL;
+static guint downloader_view_signals[LAST_SIGNAL] = { 0 };
+
+GType
+downloader_view_get_type (void)
+{
+ static GType downloader_view_type = 0;
+
+ if (downloader_view_type == 0)
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (DownloaderViewClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) downloader_view_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (DownloaderView),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) downloader_view_init
+ };
+
+ downloader_view_type = g_type_register_static (EPHY_DIALOG_TYPE,
+ "DownloaderView",
+ &our_info, 0);
+ }
+
+ return downloader_view_type;
+}
+
+static void
+format_time (gchar *buffer, glong time)
+{
+ gint secs, hours, mins;
+
+ secs = (gint)(time + .5);
+ hours = secs / 3600;
+ secs -= hours * 3600;
+ mins = secs / 60;
+ secs -= mins * 60;
+
+ if (hours)
+ {
+ sprintf (buffer, "%u:%02u.%02u", hours, mins, secs);
+ }
+ else
+ {
+ sprintf (buffer, "%02u.%02u", mins, secs);
+ }
+}
+
+static void
+downloader_view_class_init (DownloaderViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ EphyDialogClass *ephy_dialog_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ ephy_dialog_class = EPHY_DIALOG_CLASS (klass);
+
+ object_class->finalize = downloader_view_finalize;
+
+ /* init signals */
+ downloader_view_signals[DOWNLOAD_REMOVE] =
+ g_signal_new ("download_remove",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DownloaderViewClass, download_remove),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ downloader_view_signals[DOWNLOAD_PAUSE] =
+ g_signal_new ("download_pause",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DownloaderViewClass, download_pause),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ downloader_view_signals[DOWNLOAD_RESUME] =
+ g_signal_new ("download_resume",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DownloaderViewClass, download_resume),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+}
+
+static void
+destroy_details_cb (DownloadDetails *details)
+{
+ g_free (details->filename);
+ g_free (details->source);
+ g_free (details->dest);
+ g_free (details);
+}
+
+static void
+downloader_view_init (DownloaderView *dv)
+{
+ dv->priv = g_new0 (DownloaderViewPrivate, 1);
+ dv->priv->details_hash = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ (GDestroyNotify)destroy_details_cb);
+
+ downloader_view_build_ui (dv);
+}
+
+static void
+downloader_view_finalize (GObject *object)
+{
+ DownloaderView *dv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_DOWNLOADER_VIEW (object));
+
+ dv = DOWNLOADER_VIEW (object);
+
+ g_return_if_fail (dv->priv != NULL);
+
+ g_hash_table_destroy (dv->priv->details_hash);
+
+ g_free (dv->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+DownloaderView *
+downloader_view_new (void)
+{
+ return DOWNLOADER_VIEW (g_object_new
+ (DOWNLOADER_VIEW_TYPE, NULL));
+}
+
+static void
+controls_info_foreach (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ ControlsInfo *info)
+{
+ DownloadDetails *details;
+ GValue val = {0, };
+ gpointer persist_object;
+
+ gtk_tree_model_get_value (model, iter, COL_PERSIST_OBJECT, &val);
+ persist_object = g_value_get_pointer (&val);
+
+ details = g_hash_table_lookup (info->priv->details_hash,
+ persist_object);
+
+ info->can_pause |= details->can_pause;
+ info->can_resume |= (details->status == DOWNLOAD_STATUS_PAUSED);
+ info->can_abort |= (details->status != DOWNLOAD_STATUS_COMPLETED);
+ info->can_open |= (details->status == DOWNLOAD_STATUS_COMPLETED);
+}
+
+static void
+downloader_view_update_controls (DownloaderViewPrivate *priv)
+{
+ GtkTreeSelection *selection;
+ ControlsInfo *info;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->treeview));
+
+ info = g_new0 (ControlsInfo, 1);
+ info->priv = priv;
+
+ /* initial conditions */
+ info->can_pause = info->can_resume = info->can_abort
+ = info->can_open = FALSE;
+
+ if (selection)
+ {
+ gtk_tree_selection_selected_foreach
+ (selection,
+ (GtkTreeSelectionForeachFunc)controls_info_foreach,
+ info);
+ }
+
+ /* setup buttons */
+ gtk_widget_set_sensitive (priv->pause_button, info->can_pause);
+ gtk_widget_set_sensitive (priv->resume_button, info->can_resume);
+ gtk_widget_set_sensitive (priv->abort_button, info->can_abort);
+ gtk_widget_set_sensitive (priv->open_button, info->can_open);
+
+ g_free (info);
+}
+
+static void
+downloader_view_update_details (DownloaderViewPrivate *priv,
+ DownloadDetails *details)
+{
+ gchar buffer[50];
+
+ ephy_ellipsizing_label_set_text
+ (EPHY_ELLIPSIZING_LABEL (priv->details_location),
+ details->source);
+ ephy_ellipsizing_label_set_text
+ (EPHY_ELLIPSIZING_LABEL (priv->details_file),
+ details->filename);
+
+ if (details->size_total >= 10000)
+ {
+ sprintf (buffer, _("%.1f of %.1f MB"),
+ details->size_done / 1024.0,
+ details->size_total / 1024.0);
+ }
+ else if (details->size_total > 0)
+ {
+ sprintf (buffer, _("%d of %d KB"),
+ details->size_done,
+ details->size_total);
+ }
+ else
+ {
+ sprintf (buffer, _("%d KB"),
+ details->size_done);
+ }
+
+ if (details->speed > 0)
+ {
+ sprintf (buffer, "%s at %.1f KB/s", buffer, details->speed);
+ }
+ gtk_label_set_text (GTK_LABEL (priv->details_status),
+ buffer);
+
+ format_time (buffer, details->elapsed/1000000);
+ gtk_label_set_text (GTK_LABEL (priv->details_elapsed),
+ buffer);
+
+ format_time (buffer, details->remaining);
+ gtk_label_set_text (GTK_LABEL (priv->details_remaining),
+ buffer);
+
+ if (details->progress >= 0)
+ {
+ gtk_progress_bar_set_fraction
+ (GTK_PROGRESS_BAR (priv->details_progress),
+ details->progress);
+ }
+ else
+ {
+ gtk_progress_bar_pulse
+ (GTK_PROGRESS_BAR (priv->details_progress));
+ }
+}
+
+static gboolean
+get_selected_row (DownloaderViewPrivate *priv, GtkTreeIter *iter)
+{
+ GList *l;
+ GtkTreePath *node;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->treeview));
+ l = gtk_tree_selection_get_selected_rows (selection, &model);
+
+ if (l == NULL) return FALSE;
+
+ node = l->data;
+ gtk_tree_model_get_iter (model, iter, node);
+
+ g_list_foreach (l, (GFunc)gtk_tree_path_free, NULL);
+ g_list_free (l);
+
+ return TRUE;
+}
+
+static void
+downloader_view_set_download_info (DownloaderViewPrivate *priv,
+ DownloadDetails *details,
+ GtkTreeIter *iter)
+{
+ gchar buffer[50];
+ GtkTreePath *path;
+ GtkTreePath *selected_path = NULL;
+ GtkTreeIter selected_iter;
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection
+ (GTK_TREE_VIEW(priv->treeview));
+
+ if (get_selected_row (priv, &selected_iter))
+ {
+ selected_path = gtk_tree_model_get_path
+ (priv->model, &selected_iter);
+ }
+
+ path = gtk_tree_row_reference_get_path (details->ref);
+
+ gtk_list_store_set (GTK_LIST_STORE (priv->model),
+ iter,
+ COL_FILENAME, details->filename,
+ -1);
+
+ /* Progress */
+ if (details->status == DOWNLOAD_STATUS_COMPLETED)
+ details->progress = 1;
+ sprintf (buffer, "%.1f%%",
+ details->progress > 0 ?
+ details->progress * 100.0 :
+ 0);
+ gtk_list_store_set (GTK_LIST_STORE (priv->model),
+ iter,
+ COL_PERCENT, buffer,
+ -1);
+
+ /* Total */
+ if (details->size_total >= 10000)
+ {
+ sprintf (buffer, "%.2f MB", details->size_total / 1024.0);
+ }
+ else if (details->size_total > 0)
+ {
+ sprintf (buffer, "%d KB", details->size_total);
+ }
+ else
+ {
+ sprintf (buffer, _("Unknown"));
+ }
+
+ gtk_list_store_set (GTK_LIST_STORE (priv->model),
+ iter,
+ COL_SIZE, buffer,
+ -1);
+
+ /* Remaining */
+ if (details->remaining >= 0)
+ {
+ format_time (buffer, details->remaining);
+ }
+ else
+ {
+ sprintf (buffer, _("Unknown"));
+ }
+ gtk_list_store_set (GTK_LIST_STORE (priv->model),
+ iter,
+ COL_REMAINING, buffer,
+ -1);
+
+ if (gtk_tree_path_compare (path, selected_path) == 0)
+ {
+ downloader_view_update_details (priv, details);
+ }
+}
+
+static void
+ensure_selected_row (DownloaderView *dv)
+{
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ g_return_if_fail (IS_DOWNLOADER_VIEW(dv));
+
+ selection = gtk_tree_view_get_selection
+ (GTK_TREE_VIEW(dv->priv->treeview));
+ if (get_selected_row (dv->priv, &iter))
+ {
+ /* there is already a selection */
+ return;
+ }
+
+ if (gtk_tree_model_get_iter_first (dv->priv->model, &iter))
+ {
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
+}
+
+void
+downloader_view_add_download (DownloaderView *dv,
+ gchar *filename,
+ gchar *source,
+ gchar *dest,
+ gpointer persist_object)
+{
+ GtkTreeIter iter;
+ DownloadDetails *details;
+ GtkTreeSelection *selection;
+
+ details = g_new0 (DownloadDetails, 1);
+ details->filename = g_strdup (filename);
+ details->source = g_strdup (source);
+ details->dest = g_strdup (dest);
+ details->elapsed = -1;
+ details->remaining = -1;
+ details->speed = -1;
+ details->size_total = -1;
+ details->size_done = -1;
+ details->progress = -1;
+ dv->priv->show_details = FALSE;
+
+ g_hash_table_insert (dv->priv->details_hash,
+ persist_object,
+ details);
+
+ gtk_list_store_append (GTK_LIST_STORE (dv->priv->model),
+ &iter);
+
+ details->ref = gtk_tree_row_reference_new
+ (GTK_TREE_MODEL (dv->priv->model),
+ gtk_tree_model_get_path
+ (GTK_TREE_MODEL (dv->priv->model), &iter));
+
+ gtk_list_store_set (GTK_LIST_STORE (dv->priv->model),
+ &iter,
+ COL_PERSIST_OBJECT, persist_object,
+ -1);
+
+ selection = gtk_tree_view_get_selection
+ (GTK_TREE_VIEW(dv->priv->treeview));
+ gtk_tree_selection_unselect_all (selection);
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ downloader_view_set_download_info (dv->priv, details, &iter);
+
+ ephy_dialog_show (EPHY_DIALOG(dv));
+}
+
+void
+downloader_view_remove_download (DownloaderView *dv,
+ gpointer persist_object)
+{
+ DownloadDetails *details;
+ GtkTreeIter iter;
+ GValue keep_open = {0, };
+
+ details = g_hash_table_lookup (dv->priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (dv->priv->model),
+ &iter,
+ gtk_tree_row_reference_get_path (details->ref));
+
+ gtk_list_store_remove (GTK_LIST_STORE (dv->priv->model), &iter);
+
+ g_hash_table_remove (dv->priv->details_hash,
+ persist_object);
+
+ ephy_dialog_get_value (EPHY_DIALOG(dv), PROP_KEEP_OPEN, &keep_open);
+
+ if (!g_value_get_boolean (&keep_open) &&
+ g_hash_table_size (dv->priv->details_hash) == 0)
+ {
+ g_object_unref (dv);
+ }
+ else
+ {
+ ensure_selected_row (dv);
+ }
+}
+
+void
+downloader_view_set_download_progress (DownloaderView *dv,
+ glong elapsed,
+ glong remaining,
+ gfloat speed,
+ gint size_total,
+ gint size_done,
+ gfloat progress,
+ gboolean can_pause,
+ gpointer persist_object)
+{
+ DownloadDetails *details;
+ GtkTreeIter iter;
+
+ details = g_hash_table_lookup (dv->priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ details->elapsed = elapsed;
+ details->remaining = remaining;
+ details->speed = speed;
+ details->size_total = size_total;
+ details->size_done = size_done;
+ details->can_pause = can_pause;
+ details->progress = progress;
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (dv->priv->model),
+ &iter,
+ gtk_tree_row_reference_get_path (details->ref));
+
+ downloader_view_set_download_info (dv->priv, details, &iter);
+}
+
+void
+downloader_view_set_download_status (DownloaderView *dv,
+ DownloadStatus status,
+ gpointer persist_object)
+{
+ DownloadDetails *details;
+ GtkTreeIter iter;
+ GValue keep_open = {0, };
+
+ details = g_hash_table_lookup (dv->priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ details->status = status;
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (dv->priv->model),
+ &iter,
+ gtk_tree_row_reference_get_path (details->ref));
+
+ downloader_view_set_download_info (dv->priv, details, &iter);
+ downloader_view_update_controls (dv->priv);
+
+ ephy_dialog_get_value (EPHY_DIALOG(dv), PROP_KEEP_OPEN, &keep_open);
+
+ if (status == DOWNLOAD_STATUS_COMPLETED &&
+ !g_value_get_boolean (&keep_open))
+ {
+ downloader_view_remove_download (dv, persist_object);
+ }
+}
+
+static void
+downloader_view_build_ui (DownloaderView *dv)
+{
+ DownloaderViewPrivate *priv = dv->priv;
+ GtkListStore *liststore;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+ GtkWidget *details_table;
+ EphyDialog *d = EPHY_DIALOG (dv);
+
+ ephy_dialog_construct (d,
+ properties,
+ "epiphany.glade",
+ "download_manager_dialog");
+
+ /* lookup needed widgets */
+ priv->treeview = ephy_dialog_get_control (d, PROP_TREEVIEW);
+ priv->details_status = ephy_dialog_get_control (d, PROP_DETAILS_STATUS);
+ priv->details_elapsed = ephy_dialog_get_control (d, PROP_DETAILS_ELAPSED);
+ priv->details_remaining = ephy_dialog_get_control (d, PROP_DETAILS_REMAINING);
+ priv->details_progress = ephy_dialog_get_control (d, PROP_DETAILS_PROGRESS);
+ priv->keep_open_check = ephy_dialog_get_control (d, PROP_KEEP_OPEN);
+ priv->details_button = ephy_dialog_get_control (d, PROP_DETAILS_BUTTON);
+ priv->pause_button = ephy_dialog_get_control (d, PROP_PAUSE_BUTTON);
+ priv->resume_button = ephy_dialog_get_control (d, PROP_RESUME_BUTTON);
+ priv->abort_button = ephy_dialog_get_control (d, PROP_ABORT_BUTTON);
+ priv->open_button = ephy_dialog_get_control (d, PROP_OPEN_BUTTON);
+ details_table = ephy_dialog_get_control (d, PROP_DETAILS_TABLE);
+
+ /* create file and location details labels */
+ priv->details_location = ephy_ellipsizing_label_new ("");
+ priv->details_file = ephy_ellipsizing_label_new ("");
+ gtk_table_attach_defaults (GTK_TABLE(details_table), priv->details_location,
+ 1, 2, 0, 1);
+ gtk_table_attach_defaults (GTK_TABLE(details_table), priv->details_file,
+ 1, 2, 1, 2);
+ gtk_misc_set_alignment (GTK_MISC(priv->details_location), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC(priv->details_file), 0, 0);
+ gtk_label_set_selectable (GTK_LABEL(priv->details_location), TRUE);
+ gtk_label_set_selectable (GTK_LABEL(priv->details_file), TRUE);
+ gtk_widget_show (priv->details_location);
+ gtk_widget_show (priv->details_file);
+
+ liststore = gtk_list_store_new (5,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW(priv->treeview),
+ GTK_TREE_MODEL (liststore));
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(priv->treeview),
+ TRUE);
+
+ renderer = gtk_cell_renderer_text_new ();
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(priv->treeview),
+ 0, _("%"),
+ renderer,
+ "text", 0,
+ NULL);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW(priv->treeview), 0);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_reorderable (column, TRUE);
+ gtk_tree_view_column_set_sort_column_id (column, COL_PERCENT);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(priv->treeview),
+ COL_FILENAME, _("Filename"),
+ renderer,
+ "text", COL_FILENAME,
+ NULL);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW(priv->treeview),
+ COL_FILENAME);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_reorderable (column, TRUE);
+ gtk_tree_view_column_set_sort_column_id (column, COL_FILENAME);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(priv->treeview),
+ COL_SIZE, _("Size"),
+ renderer,
+ "text", COL_SIZE,
+ NULL);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW(priv->treeview),
+ COL_SIZE);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_reorderable (column, TRUE);
+ gtk_tree_view_column_set_sort_column_id (column, COL_SIZE);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(priv->treeview),
+ COL_REMAINING, _("Remaining"),
+ renderer,
+ "text", COL_REMAINING,
+ NULL);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW(priv->treeview),
+ COL_REMAINING);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_reorderable (column, TRUE);
+ gtk_tree_view_column_set_sort_column_id (column, COL_REMAINING);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->treeview));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (downloader_treeview_selection_changed_cb), dv);
+
+ priv->model = GTK_TREE_MODEL (liststore);
+}
+
+static void
+resume_selection_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
+ DownloaderView *dv)
+{
+ DownloadDetails *details;
+ GValue val = {0, };
+ gpointer *persist_object;
+
+ gtk_tree_model_get_value (model, iter, COL_PERSIST_OBJECT, &val);
+ persist_object = g_value_get_pointer (&val);
+
+ details = g_hash_table_lookup (dv->priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ if (details->status == DOWNLOAD_STATUS_COMPLETED) return;
+
+ downloader_view_set_download_status (dv, DOWNLOAD_STATUS_RESUMING, persist_object);
+
+ g_signal_emit (G_OBJECT (dv), downloader_view_signals[DOWNLOAD_RESUME], 0);
+}
+
+void
+download_dialog_resume_cb (GtkButton *button, DownloaderView *dv)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dv->priv->treeview));
+
+ gtk_tree_selection_selected_foreach
+ (selection,
+ (GtkTreeSelectionForeachFunc)resume_selection_foreach,
+ (gpointer)dv);
+}
+
+static void
+pause_selection_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
+ DownloaderView *dv)
+{
+ DownloadDetails *details;
+ GValue val = {0, };
+ gpointer *persist_object;
+
+ gtk_tree_model_get_value (model, iter, COL_PERSIST_OBJECT, &val);
+ persist_object = g_value_get_pointer (&val);
+
+ details = g_hash_table_lookup (dv->priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ if (details->status == DOWNLOAD_STATUS_COMPLETED) return;
+
+ downloader_view_set_download_status (dv, DOWNLOAD_STATUS_PAUSED, persist_object);
+
+ g_signal_emit (G_OBJECT (dv), downloader_view_signals[DOWNLOAD_PAUSE], 0);
+}
+
+void
+download_dialog_pause_cb (GtkButton *button, DownloaderView *dv)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dv->priv->treeview));
+
+ gtk_tree_selection_selected_foreach
+ (selection,
+ (GtkTreeSelectionForeachFunc)pause_selection_foreach,
+ (gpointer)dv);
+}
+
+void
+download_dialog_abort_cb (GtkButton *button, DownloaderView *dv)
+{
+ GList *l, *r = NULL;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dv->priv->treeview));
+ l = gtk_tree_selection_get_selected_rows (selection, &model);
+ for (;l != NULL; l = l->next)
+ {
+ r = g_list_append (r, gtk_tree_row_reference_new
+ (model, (GtkTreePath *)l->data));
+ }
+
+ for (; r != NULL; r = g_list_next (r))
+ {
+ GtkTreeRowReference *node = r->data;
+ GValue val = {0, };
+ gpointer *persist_object;
+ GtkTreeIter iter;
+ DownloadDetails *details;
+
+ gtk_tree_model_get_iter (model, &iter,
+ gtk_tree_row_reference_get_path (node));
+
+ gtk_tree_model_get_value (model, &iter,
+ COL_PERSIST_OBJECT, &val);
+ persist_object = g_value_get_pointer (&val);
+
+ details = g_hash_table_lookup (dv->priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ g_signal_emit (G_OBJECT (dv), downloader_view_signals[DOWNLOAD_REMOVE], 0);
+
+ downloader_view_remove_download (dv, persist_object);
+
+ gtk_tree_row_reference_free (node);
+ }
+
+ l = g_list_first (l);
+ g_list_foreach (l, (GFunc)gtk_tree_path_free, NULL);
+ g_list_free (l);
+ g_list_free (r);
+}
+
+static void
+downloader_treeview_selection_changed_cb (GtkTreeSelection *selection,
+ DownloaderView *dv)
+{
+ GtkTreeIter iter;
+ GValue val = {0, };
+ gpointer *persist_object;
+ DownloadDetails *details = NULL;
+ GtkWidget *details_frame;
+ DownloaderViewPrivate *priv= dv->priv;
+
+ details_frame = ephy_dialog_get_control (EPHY_DIALOG(dv),
+ PROP_DETAILS_FRAME);
+
+ if (get_selected_row (priv, &iter))
+ {
+ gtk_tree_model_get_value (priv->model, &iter, COL_PERSIST_OBJECT, &val);
+ persist_object = g_value_get_pointer (&val);
+
+ details = g_hash_table_lookup (priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ gtk_widget_set_sensitive (details_frame, TRUE);
+
+ downloader_view_update_details (priv, details);
+ downloader_view_update_controls (priv);
+ }
+ else
+ {
+ gtk_label_set_text (GTK_LABEL (priv->details_location), "");
+ gtk_label_set_text (GTK_LABEL (priv->details_file), "");
+ gtk_label_set_text (GTK_LABEL (priv->details_status), "");
+ gtk_label_set_text (GTK_LABEL (priv->details_elapsed), "");
+ gtk_label_set_text (GTK_LABEL (priv->details_remaining), "");
+ gtk_progress_bar_set_fraction
+ (GTK_PROGRESS_BAR (priv->details_progress),
+ 0);
+
+ gtk_widget_set_sensitive (details_frame, FALSE);
+ }
+}
+
+static void
+alive_download_foreach (gpointer persist_object,
+ DownloadDetails *details,
+ gboolean *alive)
+{
+ if (details->status != DOWNLOAD_STATUS_COMPLETED)
+ {
+ *alive = TRUE;
+ }
+}
+
+static gboolean
+delete_pending_foreach (gpointer persist_object,
+ DownloadDetails *details,
+ DownloaderView *dv)
+{
+ g_signal_emit (G_OBJECT (dv), downloader_view_signals[DOWNLOAD_REMOVE],
+ 0, persist_object);
+
+ return TRUE;
+}
+
+gboolean
+download_dialog_delete_cb (GtkWidget *window, GdkEventAny *event,
+ DownloaderView *dv)
+{
+ GtkWidget *dialog;
+ gboolean choice;
+ gboolean alive_download = FALSE;
+
+ g_hash_table_foreach (dv->priv->details_hash,
+ (GHFunc)alive_download_foreach,
+ &alive_download);
+
+ if (!alive_download) return FALSE;
+
+ /* build question dialog */
+ dialog = gtk_message_dialog_new (
+ GTK_WINDOW(window),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_YES_NO,
+ _("Cancel all pending downloads?"));
+
+ /* run it */
+ choice = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ /* do the appropriate thing */
+ if (choice == GTK_RESPONSE_YES)
+ {
+ g_hash_table_foreach_remove (dv->priv->details_hash,
+ (GHRFunc)delete_pending_foreach,
+ dv);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+download_dialog_details_cb (GtkToggleButton *button,
+ DownloaderView *dv)
+{
+ GtkWidget *details_frame;
+ GtkWidget *details_separator;
+
+ details_frame = ephy_dialog_get_control (EPHY_DIALOG(dv),
+ PROP_DETAILS_FRAME);
+ details_separator = ephy_dialog_get_control (EPHY_DIALOG(dv),
+ PROP_DETAILS_SEPARATOR);
+
+ if (gtk_toggle_button_get_active (button))
+ {
+ gtk_widget_show (GTK_WIDGET (details_frame));
+ gtk_widget_show (GTK_WIDGET (details_separator));
+ dv->priv->show_details = TRUE;
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (details_frame));
+ gtk_widget_hide (GTK_WIDGET (details_separator));
+ dv->priv->show_details = FALSE;
+ }
+
+}
+
+static void
+open_selection_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
+ DownloaderView *dv)
+{
+ DownloadDetails *details;
+ GValue val = {0, };
+ gpointer *persist_object;
+ GnomeVFSMimeApplication *app;
+ char *mime;
+
+ gtk_tree_model_get_value (model, iter, COL_PERSIST_OBJECT, &val);
+ persist_object = g_value_get_pointer (&val);
+
+ details = g_hash_table_lookup (dv->priv->details_hash,
+ persist_object);
+ g_return_if_fail (details);
+
+ if (details->status != DOWNLOAD_STATUS_COMPLETED) return;
+
+ mime = gnome_vfs_get_mime_type (details->dest);
+ g_return_if_fail (mime != NULL);
+
+ app = gnome_vfs_mime_get_default_application (mime);
+ if (app)
+ {
+ ephy_file_launch_application (app->command,
+ details->dest,
+ app->requires_terminal);
+ }
+ else
+ {
+ GtkWidget *parent;
+ parent = gtk_widget_get_toplevel (dv->priv->open_button);
+ ephy_embed_utils_nohandler_dialog_run (parent);
+ }
+
+ g_free(mime);
+}
+
+void
+download_dialog_open_cb (GtkWidget *button,
+ DownloaderView *dv)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dv->priv->treeview));
+
+ gtk_tree_selection_selected_foreach
+ (selection,
+ (GtkTreeSelectionForeachFunc)open_selection_foreach,
+ (gpointer)dv);
+}