diff options
Diffstat (limited to 'src/empathy-ft-manager.c')
-rw-r--r-- | src/empathy-ft-manager.c | 1390 |
1 files changed, 740 insertions, 650 deletions
diff --git a/src/empathy-ft-manager.c b/src/empathy-ft-manager.c index 66e33aefd..bc4f2a7b7 100644 --- a/src/empathy-ft-manager.c +++ b/src/empathy-ft-manager.c @@ -1,8 +1,7 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2003, 2004 Xan Lopez * Copyright (C) 2007 Marco Barisione <marco@barisione.org> - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008-2009 Collabora Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -23,6 +22,7 @@ * Marco Barisione <marco@barisione.org> * Jonny Lamb <jonny.lamb@collabora.co.uk> * Xavier Claessens <xclaesse@gmail.com> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> */ /* The original file transfer manager code was copied from Epiphany */ @@ -46,19 +46,6 @@ #include "empathy-ft-manager.h" -#include "extensions/extensions.h" - -/** - * SECTION:empathy-ft-manager - * @short_description: File transfer dialog - * @see_also: #EmpathyTpFile, empathy_dispatcher_send_file() - * @include: libempthy-gtk/empathy-ft-manager.h - * - * The #EmpathyFTManager object represents the file transfer dialog, - * it can show multiple file transfers at the same time (added - * with empathy_ft_manager_add_tp_file()). - */ - enum { COL_PERCENT, @@ -68,24 +55,19 @@ enum COL_FT_OBJECT }; -/** - * EmpathyFTManagerPriv: - * - * Private fields of the #EmpathyFTManager class. - */ -struct _EmpathyFTManagerPriv -{ +typedef struct { GtkTreeModel *model; - GHashTable *tp_file_to_row_ref; + GHashTable *ft_handler_to_row_ref; /* Widgets */ GtkWidget *window; GtkWidget *treeview; GtkWidget *open_button; GtkWidget *abort_button; + GtkWidget *clear_button; guint save_geometry_id; -}; +} EmpathyFTManagerPriv; enum { @@ -96,10 +78,15 @@ enum G_DEFINE_TYPE (EmpathyFTManager, empathy_ft_manager, G_TYPE_OBJECT); +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyFTManager) + static EmpathyFTManager *manager_singleton = NULL; +static void ft_handler_hashing_started_cb (EmpathyFTHandler *handler, + EmpathyFTManager *manager); + static gchar * -ft_manager_format_interval (gint interval) +ft_manager_format_interval (guint interval) { gint hours, mins, secs; @@ -117,241 +104,62 @@ ft_manager_format_interval (gint interval) return g_strdup_printf (_("%02u.%02u"), mins, secs); } -static GtkTreeRowReference * -ft_manager_get_row_from_tp_file (EmpathyFTManager *ft_manager, - EmpathyTpFile *tp_file) -{ - return g_hash_table_lookup (ft_manager->priv->tp_file_to_row_ref, tp_file); -} - static void -ft_manager_update_buttons (EmpathyFTManager *ft_manager) +ft_manager_update_buttons (EmpathyFTManager *manager) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; - EmpathyTpFile *tp_file; - TpFileTransferState state; + EmpathyFTHandler *handler; gboolean open_enabled = FALSE; gboolean abort_enabled = FALSE; + gboolean clear_enabled = FALSE; + gboolean is_completed, is_cancelled; + GHashTableIter hash_iter; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW ( - ft_manager->priv->treeview)); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &tp_file, -1); - state = empathy_tp_file_get_state (tp_file, NULL); + gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &handler, -1); + + is_completed = empathy_ft_handler_is_completed (handler); + is_cancelled = empathy_ft_handler_is_cancelled (handler); /* I can open the file if the transfer is completed and was incoming */ - open_enabled = (state == TP_FILE_TRANSFER_STATE_COMPLETED && - empathy_tp_file_is_incoming (tp_file)); + open_enabled = (is_completed && empathy_ft_handler_is_incoming (handler)); /* I can abort if the transfer is not already finished */ - abort_enabled = (state != TP_FILE_TRANSFER_STATE_CANCELLED && - state != TP_FILE_TRANSFER_STATE_COMPLETED); + abort_enabled = (is_cancelled == FALSE && is_completed == FALSE); - g_object_unref (tp_file); + g_object_unref (handler); } - gtk_widget_set_sensitive (ft_manager->priv->open_button, open_enabled); - gtk_widget_set_sensitive (ft_manager->priv->abort_button, abort_enabled); -} + g_hash_table_iter_init (&hash_iter, priv->ft_handler_to_row_ref); -static const gchar * -ft_manager_state_change_reason_to_string (TpFileTransferStateChangeReason reason) -{ - switch (reason) + while (g_hash_table_iter_next (&hash_iter, (gpointer *) &handler, NULL)) { - case TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE: - return _("No reason was specified"); - case TP_FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED: - return _("The change in state was requested"); - case TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_STOPPED: - return _("You canceled the file transfer"); - case TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED: - return _("The other participant canceled the file transfer"); - case TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR: - return _("Error while trying to transfer the file"); - case TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_ERROR: - return _("The other participant is unable to transfer the file"); - } - return _("Unknown reason"); -} - -static void -ft_manager_update_ft_row (EmpathyFTManager *ft_manager, - EmpathyTpFile *tp_file) -{ - GtkTreeRowReference *row_ref; - GtkTreePath *path; - GtkTreeIter iter; - const gchar *filename; - const gchar *contact_name; - const gchar *msg; - gchar *msg_dup = NULL; - gchar *remaining_str = NULL; - gchar *first_line_format; - gchar *first_line = NULL; - gchar *second_line = NULL; - guint64 transferred_bytes; - guint64 total_size; - gint remaining = -1; - gint percent; - TpFileTransferState state; - TpFileTransferStateChangeReason reason; - gboolean incoming; - gdouble speed; - - row_ref = ft_manager_get_row_from_tp_file (ft_manager, tp_file); - g_return_if_fail (row_ref != NULL); - - filename = empathy_tp_file_get_filename (tp_file); - contact_name = empathy_contact_get_name (empathy_tp_file_get_contact (tp_file)); - transferred_bytes = empathy_tp_file_get_transferred_bytes (tp_file); - total_size = empathy_tp_file_get_size (tp_file); - state = empathy_tp_file_get_state (tp_file, &reason); - incoming = empathy_tp_file_is_incoming (tp_file); - speed = empathy_tp_file_get_speed (tp_file); + if (empathy_ft_handler_is_completed (handler) || + empathy_ft_handler_is_cancelled (handler)) + clear_enabled = TRUE; - switch (state) - { - case TP_FILE_TRANSFER_STATE_NONE: - /* This should never happen, the CM is broken. But we avoid warning - * because it's not our fault. */ - DEBUG ("State is NONE, probably a broken CM"); + if (clear_enabled) break; - case TP_FILE_TRANSFER_STATE_PENDING: - case TP_FILE_TRANSFER_STATE_OPEN: - case TP_FILE_TRANSFER_STATE_ACCEPTED: - if (incoming) - /* translators: first %s is filename, second %s is the contact name */ - first_line_format = _("Receiving \"%s\" from %s"); - else - /* translators: first %s is filename, second %s is the contact name */ - first_line_format = _("Sending \"%s\" to %s"); - - first_line = g_strdup_printf (first_line_format, filename, contact_name); - - if (state == TP_FILE_TRANSFER_STATE_OPEN || incoming) - { - gchar *total_size_str; - gchar *transferred_bytes_str; - gchar *speed_str; - - if (total_size == EMPATHY_TP_FILE_UNKNOWN_SIZE) - total_size_str = g_strdup (C_("file size", "Unknown")); - else - total_size_str = g_format_size_for_display (total_size); - - transferred_bytes_str = g_format_size_for_display (transferred_bytes); - speed_str = g_format_size_for_display (speed); - - /* translators: first %s is the transferred size, second %s is - * the total file size */ - second_line = g_strdup_printf (_("%s of %s at %s/s"), - transferred_bytes_str, total_size_str, speed_str); - g_free (transferred_bytes_str); - g_free (total_size_str); - g_free (speed_str); - - } - else - second_line = g_strdup (_("Waiting for the other participant's response")); - - remaining = empathy_tp_file_get_remaining_time (tp_file); - break; - - case TP_FILE_TRANSFER_STATE_COMPLETED: - if (incoming) - /* translators: first %s is filename, second %s - * is the contact name */ - first_line = g_strdup_printf ( - _("\"%s\" received from %s"), filename, - contact_name); - else - /* translators: first %s is filename, second %s - * is the contact name */ - first_line = g_strdup_printf ( - _("\"%s\" sent to %s"), filename, - contact_name); - - second_line = g_strdup (_("File transfer completed")); - - break; - - case TP_FILE_TRANSFER_STATE_CANCELLED: - if (incoming) - /* translators: first %s is filename, second %s - * is the contact name */ - first_line = g_strdup_printf ( - _("\"%s\" receiving from %s"), filename, - contact_name); - else - /* translators: first %s is filename, second %s - * is the contact name */ - first_line = g_strdup_printf ( - _("\"%s\" sending to %s"), filename, - contact_name); - - second_line = g_strdup_printf (_("File transfer canceled: %s"), - ft_manager_state_change_reason_to_string (reason)); - - break; - } - - if (total_size != EMPATHY_TP_FILE_UNKNOWN_SIZE && total_size != 0) - percent = transferred_bytes * 100 / total_size; - else - percent = -1; - - if (remaining < 0) - { - if (state == TP_FILE_TRANSFER_STATE_OPEN) - remaining_str = g_strdup (C_("remaining time", "Stalled")); - else if (state != TP_FILE_TRANSFER_STATE_COMPLETED && - state != TP_FILE_TRANSFER_STATE_CANCELLED) - remaining_str = g_strdup (C_("remaining time", "Unknown")); } - else - remaining_str = ft_manager_format_interval (remaining); - - if (first_line != NULL && second_line != NULL) - msg = msg_dup = g_strdup_printf ("%s\n%s", first_line, second_line); - else - msg = first_line ? first_line : second_line; - - /* Set new values in the store */ - path = gtk_tree_row_reference_get_path (row_ref); - gtk_tree_model_get_iter (ft_manager->priv->model, &iter, path); - gtk_list_store_set (GTK_LIST_STORE (ft_manager->priv->model), - &iter, - COL_PERCENT, percent, - COL_MESSAGE, msg ? msg : "", - COL_REMAINING, remaining_str ? remaining_str : "", - -1); - - gtk_tree_path_free (path); - - g_free (msg_dup); - g_free (first_line); - g_free (second_line); - g_free (remaining_str); - ft_manager_update_buttons (ft_manager); -} + gtk_widget_set_sensitive (priv->open_button, open_enabled); + gtk_widget_set_sensitive (priv->abort_button, abort_enabled); -static void -ft_manager_refresh_cb (EmpathyTpFile *tp_file, - EmpathyFTManager *ft_manager) -{ - ft_manager_update_ft_row (ft_manager, tp_file); + if (clear_enabled) + gtk_widget_set_sensitive (priv->clear_button, TRUE); } static void ft_manager_selection_changed (GtkTreeSelection *selection, - EmpathyFTManager *ft_manager) + EmpathyFTManager *manager) { - ft_manager_update_buttons (ft_manager); + ft_manager_update_buttons (manager); } static void @@ -375,79 +183,57 @@ ft_manager_progress_cell_data_func (GtkTreeViewColumn *col, g_object_set (renderer, "text", text, "value", percent, NULL); } -static gboolean -ft_manager_save_geometry_timeout_cb (EmpathyFTManager *ft_manager) -{ - gint x, y, w, h; - - gtk_window_get_size (GTK_WINDOW (ft_manager->priv->window), &w, &h); - gtk_window_get_position (GTK_WINDOW (ft_manager->priv->window), &x, &y); - - empathy_geometry_save ("ft-manager", x, y, w, h); - - ft_manager->priv->save_geometry_id = 0; - - return FALSE; -} - -static gboolean -ft_manager_configure_event_cb (GtkWidget *widget, - GdkEventConfigure *event, - EmpathyFTManager *ft_manager) +static GtkTreeRowReference * +ft_manager_get_row_from_handler (EmpathyFTManager *manager, + EmpathyFTHandler *handler) { - if (ft_manager->priv->save_geometry_id != 0) - g_source_remove (ft_manager->priv->save_geometry_id); + EmpathyFTManagerPriv *priv = GET_PRIV (manager); - ft_manager->priv->save_geometry_id = g_timeout_add (500, - (GSourceFunc) ft_manager_save_geometry_timeout_cb, ft_manager); - - return FALSE; + return g_hash_table_lookup (priv->ft_handler_to_row_ref, handler); } static void -ft_manager_remove_file_from_model (EmpathyFTManager *ft_manager, - EmpathyTpFile *tp_file) +ft_manager_remove_file_from_model (EmpathyFTManager *manager, + EmpathyFTHandler *handler) { GtkTreeRowReference *row_ref; GtkTreeSelection *selection; GtkTreePath *path = NULL; GtkTreeIter iter; gboolean update_selection; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); - row_ref = ft_manager_get_row_from_tp_file (ft_manager, tp_file); + row_ref = ft_manager_get_row_from_handler (manager, handler); g_return_if_fail (row_ref); DEBUG ("Removing file transfer from window: contact=%s, filename=%s", - empathy_contact_get_name (empathy_tp_file_get_contact (tp_file)), - empathy_tp_file_get_filename (tp_file)); + empathy_contact_get_name (empathy_ft_handler_get_contact (handler)), + empathy_ft_handler_get_filename (handler)); /* Get the iter from the row_ref */ path = gtk_tree_row_reference_get_path (row_ref); - gtk_tree_model_get_iter (ft_manager->priv->model, &iter, path); + gtk_tree_model_get_iter (priv->model, &iter, path); gtk_tree_path_free (path); /* We have to update the selection only if we are removing the selected row */ - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ft_manager->priv->treeview)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); update_selection = gtk_tree_selection_iter_is_selected (selection, &iter); /* Remove tp_file's row. After that iter points to the next row */ - if (!gtk_list_store_remove (GTK_LIST_STORE (ft_manager->priv->model), &iter)) + if (!gtk_list_store_remove (GTK_LIST_STORE (priv->model), &iter)) { gint n_row; /* There is no next row, set iter to the last row */ - n_row = gtk_tree_model_iter_n_children (ft_manager->priv->model, NULL); + n_row = gtk_tree_model_iter_n_children (priv->model, NULL); if (n_row > 0) - gtk_tree_model_iter_nth_child (ft_manager->priv->model, &iter, NULL, - n_row - 1); + gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, n_row - 1); else update_selection = FALSE; } if (update_selection) gtk_tree_selection_select_iter (selection, &iter); - - empathy_tp_file_cancel (tp_file); } static gboolean @@ -455,113 +241,679 @@ remove_finished_transfer_foreach (gpointer key, gpointer value, gpointer user_data) { - EmpathyTpFile *tp_file = EMPATHY_TP_FILE (key); - EmpathyFTManager *self = EMPATHY_FT_MANAGER (user_data); - TpFileTransferState state; + EmpathyFTHandler *handler = key; + EmpathyFTManager *manager = user_data; - state = empathy_tp_file_get_state (tp_file, NULL); - if (state == TP_FILE_TRANSFER_STATE_COMPLETED || - state == TP_FILE_TRANSFER_STATE_CANCELLED) + if (empathy_ft_handler_is_completed (handler) || + empathy_ft_handler_is_cancelled (handler)) { - ft_manager_remove_file_from_model (self, tp_file); + ft_manager_remove_file_from_model (manager, handler); return TRUE; } return FALSE; } +static gchar * +ft_manager_format_progress_bytes_and_percentage (guint64 current, + guint64 total, + gdouble speed, + int *percentage) +{ + char *total_str, *current_str, *retval; + char *speed_str = NULL; + + total_str = g_format_size_for_display (total); + current_str = g_format_size_for_display (current); + + if (speed > 0) + speed_str = g_format_size_for_display ((goffset) speed); + + /* translators: first %s is the currently processed size, second %s is + * the total file size */ + retval = speed_str ? + g_strdup_printf (_("%s of %s at %s/s"), current_str, total_str, speed_str) : + g_strdup_printf (_("%s of %s"), current_str, total_str); + + g_free (total_str); + g_free (current_str); + g_free (speed_str); + + if (percentage != NULL) + { + if (total != 0) + *percentage = current * 100 / total; + else + *percentage = -1; + } + + return retval; +} + +static gchar * +ft_manager_format_contact_info (EmpathyFTHandler *handler) +{ + gboolean incoming; + const char *filename, *contact_name, *first_line_format; + char *retval; + + incoming = empathy_ft_handler_is_incoming (handler); + contact_name = empathy_contact_get_name + (empathy_ft_handler_get_contact (handler)); + filename = empathy_ft_handler_get_filename (handler); + + if (incoming) + /* translators: first %s is filename, second %s is the contact name */ + first_line_format = _("Receiving \"%s\" from %s"); + else + /* translators: first %s is filename, second %s is the contact name */ + first_line_format = _("Sending \"%s\" to %s"); + + retval = g_strdup_printf (first_line_format, filename, contact_name); + + return retval; +} + +static gchar * +ft_manager_format_error_message (EmpathyFTHandler *handler, + const GError *error) +{ + const char *contact_name, *filename; + EmpathyContact *contact; + char *first_line, *message; + gboolean incoming; + + contact_name = NULL; + incoming = empathy_ft_handler_is_incoming (handler); + + contact = empathy_ft_handler_get_contact (handler); + if (contact) + contact_name = empathy_contact_get_name (contact); + + filename = empathy_ft_handler_get_filename (handler); + + if (incoming) + /* filename/contact_name here are either both NULL or both valid */ + if (filename && contact_name) + /* translators: first %s is filename, second %s + * is the contact name */ + first_line = g_strdup_printf (_("Error receiving \"%s\" from %s"), filename, + contact_name); + else + first_line = g_strdup (_("Error receiving a file")); + else + /* translators: first %s is filename, second %s + * is the contact name */ + if (filename && contact_name) + first_line = g_strdup_printf (_("Error sending \"%s\" to %s"), filename, + contact_name); + else + first_line = g_strdup (_("Error sending a file")); + + message = g_strdup_printf ("%s\n%s", first_line, error->message); + + g_free (first_line); + + return message; +} + +static void +ft_manager_update_handler_message (EmpathyFTManager *manager, + GtkTreeRowReference *row_ref, + const char *message) +{ + GtkTreePath *path; + GtkTreeIter iter; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + + /* Set new value in the store */ + path = gtk_tree_row_reference_get_path (row_ref); + gtk_tree_model_get_iter (priv->model, &iter, path); + gtk_list_store_set (GTK_LIST_STORE (priv->model), + &iter, + COL_MESSAGE, message ? message : "", + -1); + + gtk_tree_path_free (path); +} + +static void +ft_manager_update_handler_progress (EmpathyFTManager *manager, + GtkTreeRowReference *row_ref, + int percentage) +{ + GtkTreePath *path; + GtkTreeIter iter; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + + /* Set new value in the store */ + path = gtk_tree_row_reference_get_path (row_ref); + gtk_tree_model_get_iter (priv->model, &iter, path); + gtk_list_store_set (GTK_LIST_STORE (priv->model), + &iter, + COL_PERCENT, percentage, + -1); + + gtk_tree_path_free (path); + +} + +static void +ft_manager_update_handler_time (EmpathyFTManager *manager, + GtkTreeRowReference *row_ref, + guint remaining_time) +{ + GtkTreePath *path; + GtkTreeIter iter; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + char *remaining_str; + + remaining_str = ft_manager_format_interval (remaining_time); + + /* Set new value in the store */ + path = gtk_tree_row_reference_get_path (row_ref); + gtk_tree_model_get_iter (priv->model, &iter, path); + gtk_list_store_set (GTK_LIST_STORE (priv->model), + &iter, + COL_REMAINING, remaining_str, + -1); + + gtk_tree_path_free (path); + g_free (remaining_str); +} + +static void +ft_manager_clear_handler_time (EmpathyFTManager *manager, + GtkTreeRowReference *row_ref) +{ + GtkTreePath *path; + GtkTreeIter iter; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + + /* Set new value in the store */ + path = gtk_tree_row_reference_get_path (row_ref); + gtk_tree_model_get_iter (priv->model, &iter, path); + gtk_list_store_set (GTK_LIST_STORE (priv->model), + &iter, + COL_REMAINING, NULL, + -1); + + gtk_tree_path_free (path); +} + +static void +ft_handler_transfer_error_cb (EmpathyFTHandler *handler, + GError *error, + EmpathyFTManager *manager) +{ + char *message; + GtkTreeRowReference *row_ref; + + DEBUG ("Transfer error %s", error->message); + + row_ref = ft_manager_get_row_from_handler (manager, handler); + g_return_if_fail (row_ref != NULL); + + message = ft_manager_format_error_message (handler, error); + + ft_manager_update_handler_message (manager, row_ref, message); + ft_manager_clear_handler_time (manager, row_ref); + ft_manager_update_buttons (manager); + + g_free (message); +} + +static void +do_real_transfer_done (EmpathyFTManager *manager, + EmpathyFTHandler *handler) +{ + const char *contact_name; + const char *filename; + char *first_line, *second_line, *message; + char *uri; + gboolean incoming; + GtkTreeRowReference *row_ref; + GtkRecentManager *recent_manager; + GFile *file; + + row_ref = ft_manager_get_row_from_handler (manager, handler); + g_return_if_fail (row_ref != NULL); + + incoming = empathy_ft_handler_is_incoming (handler); + contact_name = empathy_contact_get_name + (empathy_ft_handler_get_contact (handler)); + filename = empathy_ft_handler_get_filename (handler); + + if (incoming) + /* translators: first %s is filename, second %s + * is the contact name */ + first_line = g_strdup_printf (_("\"%s\" received from %s"), filename, + contact_name); + else + /* translators: first %s is filename, second %s + * is the contact name */ + first_line = g_strdup_printf (_("\"%s\" sent to %s"), filename, + contact_name); + + second_line = g_strdup (_("File transfer completed")); + + message = g_strdup_printf ("%s\n%s", first_line, second_line); + ft_manager_update_handler_message (manager, row_ref, message); + ft_manager_clear_handler_time (manager, row_ref); + + /* update buttons */ + ft_manager_update_buttons (manager); + + g_free (message); + g_free (first_line); + g_free (second_line); + + recent_manager = gtk_recent_manager_get_default (); + file = empathy_ft_handler_get_gfile (handler); + uri = g_file_get_uri (file); + + gtk_recent_manager_add_item (recent_manager, uri); + + g_free (uri); +} + +static void +ft_handler_transfer_done_cb (EmpathyFTHandler *handler, + EmpathyTpFile *tp_file, + EmpathyFTManager *manager) +{ + if (empathy_ft_handler_is_incoming (handler) && + empathy_ft_handler_get_use_hash (handler)) + { + DEBUG ("Transfer done, waiting for hashing-started"); + + /* connect to the signal and return early */ + g_signal_connect (handler, "hashing-started", + G_CALLBACK (ft_handler_hashing_started_cb), manager); + + return; + } + + DEBUG ("Transfer done, no hashing"); + + do_real_transfer_done (manager, handler); +} + +static void +ft_handler_transfer_progress_cb (EmpathyFTHandler *handler, + guint64 current_bytes, + guint64 total_bytes, + guint remaining_time, + gdouble speed, + EmpathyFTManager *manager) +{ + char *first_line, *second_line, *message; + int percentage; + GtkTreeRowReference *row_ref; + + DEBUG ("Transfer progress"); + + row_ref = ft_manager_get_row_from_handler (manager, handler); + g_return_if_fail (row_ref != NULL); + + first_line = ft_manager_format_contact_info (handler); + second_line = ft_manager_format_progress_bytes_and_percentage + (current_bytes, total_bytes, speed, &percentage); + + message = g_strdup_printf ("%s\n%s", first_line, second_line); + + ft_manager_update_handler_message (manager, row_ref, message); + ft_manager_update_handler_progress (manager, row_ref, percentage); + + if (remaining_time > 0) + ft_manager_update_handler_time (manager, row_ref, remaining_time); + + g_free (message); + g_free (first_line); + g_free (second_line); +} + +static void +ft_handler_transfer_started_cb (EmpathyFTHandler *handler, + EmpathyTpFile *tp_file, + EmpathyFTManager *manager) +{ + guint64 transferred_bytes, total_bytes; + + DEBUG ("Transfer started"); + + g_signal_connect (handler, "transfer-progress", + G_CALLBACK (ft_handler_transfer_progress_cb), manager); + g_signal_connect (handler, "transfer-done", + G_CALLBACK (ft_handler_transfer_done_cb), manager); + + transferred_bytes = empathy_ft_handler_get_transferred_bytes (handler); + total_bytes = empathy_ft_handler_get_total_bytes (handler); + + ft_handler_transfer_progress_cb (handler, transferred_bytes, total_bytes, + 0, -1, manager); +} + +static void +ft_handler_hashing_done_cb (EmpathyFTHandler *handler, + EmpathyFTManager *manager) +{ + GtkTreeRowReference *row_ref; + char *first_line, *second_line, *message; + + DEBUG ("Hashing done"); + + /* update the message */ + if (empathy_ft_handler_is_incoming (handler)) + { + do_real_transfer_done (manager, handler); + return; + } + + row_ref = ft_manager_get_row_from_handler (manager, handler); + g_return_if_fail (row_ref != NULL); + + first_line = ft_manager_format_contact_info (handler); + second_line = g_strdup (_("Waiting for the other participant's response")); + message = g_strdup_printf ("%s\n%s", first_line, second_line); + + ft_manager_update_handler_message (manager, row_ref, message); + + g_free (message); + g_free (first_line); + g_free (second_line); + + g_signal_connect (handler, "transfer-started", + G_CALLBACK (ft_handler_transfer_started_cb), manager); +} + +static void +ft_handler_hashing_progress_cb (EmpathyFTHandler *handler, + guint64 current_bytes, + guint64 total_bytes, + EmpathyFTManager *manager) +{ + char *first_line, *second_line, *message; + GtkTreeRowReference *row_ref; + + row_ref = ft_manager_get_row_from_handler (manager, handler); + g_return_if_fail (row_ref != NULL); + + if (empathy_ft_handler_is_incoming (handler)) + first_line = g_strdup_printf (_("Checking integrity of \"%s\""), + empathy_ft_handler_get_filename (handler)); + else + first_line = g_strdup_printf (_("Hashing \"%s\""), + empathy_ft_handler_get_filename (handler)); + + second_line = ft_manager_format_progress_bytes_and_percentage + (current_bytes, total_bytes, -1, NULL); + + message = g_strdup_printf ("%s\n%s", first_line, second_line); + + ft_manager_update_handler_message (manager, row_ref, message); + + g_free (message); + g_free (first_line); + g_free (second_line); +} + +static void +ft_handler_hashing_started_cb (EmpathyFTHandler *handler, + EmpathyFTManager *manager) +{ + char *message, *first_line, *second_line; + GtkTreeRowReference *row_ref; + + DEBUG ("Hashing started"); + + g_signal_connect (handler, "hashing-progress", + G_CALLBACK (ft_handler_hashing_progress_cb), manager); + g_signal_connect (handler, "hashing-done", + G_CALLBACK (ft_handler_hashing_done_cb), manager); + + row_ref = ft_manager_get_row_from_handler (manager, handler); + g_return_if_fail (row_ref != NULL); + + first_line = ft_manager_format_contact_info (handler); + + if (empathy_ft_handler_is_incoming (handler)) + second_line = g_strdup_printf (_("Checking integrity of \"%s\""), + empathy_ft_handler_get_filename (handler)); + else + second_line = g_strdup_printf (_("Hashing \"%s\""), + empathy_ft_handler_get_filename (handler)); + + message = g_strdup_printf ("%s\n%s", first_line, second_line); + + ft_manager_update_handler_message (manager, row_ref, message); + + g_free (first_line); + g_free (second_line); + g_free (message); +} + static void -ft_manager_state_changed_cb (EmpathyTpFile *tp_file, - GParamSpec *pspec, - EmpathyFTManager *ft_manager) +ft_manager_start_transfer (EmpathyFTManager *manager, + EmpathyFTHandler *handler) { - if (empathy_tp_file_get_state (tp_file, NULL) == - TP_FILE_TRANSFER_STATE_COMPLETED) + EmpathyFTManagerPriv *priv; + gboolean is_outgoing; + + priv = GET_PRIV (manager); + + is_outgoing = !empathy_ft_handler_is_incoming (handler); + + DEBUG ("Start transfer, is outgoing %s", + is_outgoing ? "True" : "False"); + + /* now connect the signals */ + g_signal_connect (handler, "transfer-error", + G_CALLBACK (ft_handler_transfer_error_cb), manager); + + if (is_outgoing && empathy_ft_handler_get_use_hash (handler)) { + g_signal_connect (handler, "hashing-started", + G_CALLBACK (ft_handler_hashing_started_cb), manager); + } else { + /* either incoming or outgoing without hash */ + g_signal_connect (handler, "transfer-started", + G_CALLBACK (ft_handler_transfer_started_cb), manager); + } + + empathy_ft_handler_start_transfer (handler); +} + +static void +ft_manager_add_handler_to_list (EmpathyFTManager *manager, + EmpathyFTHandler *handler, + const GError *error) +{ + GtkTreeRowReference *row_ref; + GtkTreeIter iter; + GtkTreeSelection *selection; + GtkTreePath *path; + GIcon *icon; + const char *content_type, *second_line; + char *first_line, *message; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + + icon = NULL; + + /* get the icon name from the mime-type of the file. */ + content_type = empathy_ft_handler_get_content_type (handler); + + if (content_type != NULL) + icon = g_content_type_get_icon (content_type); + + /* append the handler in the store */ + gtk_list_store_insert_with_values (GTK_LIST_STORE (priv->model), + &iter, G_MAXINT, COL_FT_OBJECT, handler, + COL_ICON, icon, -1); + + if (icon != NULL) + g_object_unref (icon); + + /* insert the new row_ref in the hash table */ + path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->model), &iter); + row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->model), path); + gtk_tree_path_free (path); + g_hash_table_insert (priv->ft_handler_to_row_ref, g_object_ref (handler), + row_ref); + + /* select the new row */ + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + gtk_tree_selection_select_iter (selection, &iter); + + if (error != NULL) { - GtkRecentManager *manager; - const gchar *uri; + message = ft_manager_format_error_message (handler, error); + ft_manager_update_handler_message (manager, row_ref, message); - manager = gtk_recent_manager_get_default (); - uri = g_object_get_data (G_OBJECT (tp_file), "uri"); - if (uri != NULL) - gtk_recent_manager_add_item (manager, uri); + g_free (message); + return; } - ft_manager_update_ft_row (ft_manager, tp_file); + /* update the row with the initial values. + * the only case where we postpone this is in case we're managing + * an outgoing+hashing transfer, as the hashing started signal will + * take care of updating the information. + */ + if (empathy_ft_handler_is_incoming (handler) || + !empathy_ft_handler_get_use_hash (handler)) { + first_line = ft_manager_format_contact_info (handler); + second_line = _("Waiting for the other participant's response"); + message = g_strdup_printf ("%s\n%s", first_line, second_line); + + ft_manager_update_handler_message (manager, row_ref, message); + + g_free (first_line); + g_free (message); + } + + /* hook up the signals and start the transfer */ + ft_manager_start_transfer (manager, handler); } static void -ft_manager_clear (EmpathyFTManager *ft_manager) +ft_manager_clear (EmpathyFTManager *manager) { + EmpathyFTManagerPriv *priv; + DEBUG ("Clearing file transfer list"); + priv = GET_PRIV (manager); + /* Remove completed and cancelled transfers */ - g_hash_table_foreach_remove (ft_manager->priv->tp_file_to_row_ref, - remove_finished_transfer_foreach, ft_manager); + g_hash_table_foreach_remove (priv->ft_handler_to_row_ref, + remove_finished_transfer_foreach, manager); + + /* set the clear button back to insensitive */ + gtk_widget_set_sensitive (priv->clear_button, FALSE); } static void -ft_manager_open (EmpathyFTManager *ft_manager) +ft_manager_open (EmpathyFTManager *manager) { GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; - EmpathyTpFile *tp_file; - const gchar *uri; + EmpathyFTHandler *handler; + char *uri; + GFile *file; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ft_manager->priv->treeview)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &tp_file, -1); - g_return_if_fail (tp_file != NULL); + gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &handler, -1); + + file = empathy_ft_handler_get_gfile (handler); + uri = g_file_get_uri (file); - uri = g_object_get_data (G_OBJECT (tp_file), "uri"); DEBUG ("Opening URI: %s", uri); - empathy_url_show (GTK_WIDGET (ft_manager->priv->window), uri); - g_object_unref (tp_file); + empathy_url_show (GTK_WIDGET (priv->window), uri); + + g_object_unref (handler); + g_free (uri); } static void -ft_manager_stop (EmpathyFTManager *ft_manager) +ft_manager_stop (EmpathyFTManager *manager) { GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; - EmpathyTpFile *tp_file; + EmpathyFTHandler *handler; + EmpathyFTManagerPriv *priv; + + priv = GET_PRIV (manager); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ft_manager->priv->treeview)); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &tp_file, -1); - g_return_if_fail (tp_file != NULL); + gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &handler, -1); + g_return_if_fail (handler != NULL); DEBUG ("Stopping file transfer: contact=%s, filename=%s", - empathy_contact_get_name (empathy_tp_file_get_contact (tp_file)), - empathy_tp_file_get_filename (tp_file)); + empathy_contact_get_name (empathy_ft_handler_get_contact (handler)), + empathy_ft_handler_get_filename (handler)); - empathy_tp_file_cancel (tp_file); - g_object_unref (tp_file); + empathy_ft_handler_cancel_transfer (handler); + + g_object_unref (handler); +} + +static gboolean +ft_manager_save_geometry_timeout_cb (EmpathyFTManager *manager) +{ + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + gint x, y, w, h; + + gtk_window_get_size (GTK_WINDOW (priv->window), &w, &h); + gtk_window_get_position (GTK_WINDOW (priv->window), &x, &y); + + empathy_geometry_save ("ft-manager", x, y, w, h); + + priv->save_geometry_id = 0; + + return FALSE; +} + +static gboolean +ft_manager_configure_event_cb (GtkWidget *widget, + GdkEventConfigure *event, + EmpathyFTManager *manager) +{ + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + + if (priv->save_geometry_id != 0) + g_source_remove (priv->save_geometry_id); + + priv->save_geometry_id = g_timeout_add (500, + (GSourceFunc) ft_manager_save_geometry_timeout_cb, manager); + + return FALSE; } static void ft_manager_response_cb (GtkWidget *widget, gint response, - EmpathyFTManager *ft_manager) + EmpathyFTManager *manager) { switch (response) { case RESPONSE_CLEAR: - ft_manager_clear (ft_manager); + ft_manager_clear (manager); break; case RESPONSE_OPEN: - ft_manager_open (ft_manager); + ft_manager_open (manager); break; case RESPONSE_STOP: - ft_manager_stop (ft_manager); + ft_manager_stop (manager); break; } } @@ -569,10 +921,16 @@ ft_manager_response_cb (GtkWidget *widget, static gboolean ft_manager_delete_event_cb (GtkWidget *widget, GdkEvent *event, - EmpathyFTManager *ft_manager) + EmpathyFTManager *manager) { - ft_manager_clear (ft_manager); - if (g_hash_table_size (ft_manager->priv->tp_file_to_row_ref) > 0) + EmpathyFTManagerPriv *priv = GET_PRIV (manager); + + DEBUG ("%p", manager); + + /* remove all the completed/cancelled/errored transfers */ + ft_manager_clear (manager); + + if (g_hash_table_size (priv->ft_handler_to_row_ref) > 0) { /* There is still FTs on flight, just hide the window */ DEBUG ("Hiding window"); @@ -585,16 +943,15 @@ ft_manager_delete_event_cb (GtkWidget *widget, static void ft_manager_destroy_cb (GtkWidget *widget, - EmpathyFTManager *ft_manager) + EmpathyFTManager *manager) { - ft_manager->priv->window = NULL; - if (ft_manager->priv->save_geometry_id != 0) - g_source_remove (ft_manager->priv->save_geometry_id); - g_hash_table_remove_all (ft_manager->priv->tp_file_to_row_ref); + DEBUG ("%p", manager); + + g_object_unref (manager); } static void -ft_manager_build_ui (EmpathyFTManager *ft_manager) +ft_manager_build_ui (EmpathyFTManager *manager) { GtkBuilder *gui; gint x, y, w, h; @@ -604,27 +961,26 @@ ft_manager_build_ui (EmpathyFTManager *ft_manager) GtkCellRenderer *renderer; GtkTreeSelection *selection; gchar *filename; - - if (ft_manager->priv->window != NULL) - return; + EmpathyFTManagerPriv *priv = GET_PRIV (manager); filename = empathy_file_lookup ("empathy-ft-manager.ui", "src"); gui = empathy_builder_get_file (filename, - "ft_manager_dialog", &ft_manager->priv->window, - "ft_list", &ft_manager->priv->treeview, - "open_button", &ft_manager->priv->open_button, - "abort_button", &ft_manager->priv->abort_button, + "ft_manager_dialog", &priv->window, + "ft_list", &priv->treeview, + "clear_button", &priv->clear_button, + "open_button", &priv->open_button, + "abort_button", &priv->abort_button, NULL); g_free (filename); - empathy_builder_connect (gui, ft_manager, + empathy_builder_connect (gui, manager, "ft_manager_dialog", "destroy", ft_manager_destroy_cb, "ft_manager_dialog", "response", ft_manager_response_cb, "ft_manager_dialog", "delete-event", ft_manager_delete_event_cb, "ft_manager_dialog", "configure-event", ft_manager_configure_event_cb, NULL); - g_object_unref (gui); + empathy_builder_unref_and_keep_widget (gui, priv->window); /* Window geometry. */ empathy_geometry_load ("ft-manager", &x, &y, &w, &h); @@ -633,22 +989,22 @@ ft_manager_build_ui (EmpathyFTManager *ft_manager) { /* Let the window manager position it if we don't have * good x, y coordinates. */ - gtk_window_move (GTK_WINDOW (ft_manager->priv->window), x, y); + gtk_window_move (GTK_WINDOW (priv->window), x, y); } if (w > 0 && h > 0) { /* Use the defaults from the ui file if we don't have * good w, h geometry. */ - gtk_window_resize (GTK_WINDOW (ft_manager->priv->window), w, h); + gtk_window_resize (GTK_WINDOW (priv->window), w, h); } /* Setup the tree view */ - view = GTK_TREE_VIEW (ft_manager->priv->treeview); + view = GTK_TREE_VIEW (priv->treeview); selection = gtk_tree_view_get_selection (view); gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); g_signal_connect (selection, "changed", - G_CALLBACK (ft_manager_selection_changed), ft_manager); + G_CALLBACK (ft_manager_selection_changed), manager); gtk_tree_view_set_headers_visible (view, TRUE); gtk_tree_view_set_enable_search (view, FALSE); @@ -658,9 +1014,9 @@ ft_manager_build_ui (EmpathyFTManager *ft_manager) G_TYPE_ICON, /* icon */ G_TYPE_STRING, /* message */ G_TYPE_STRING, /* remaining */ - G_TYPE_OBJECT); /* ft_file */ + G_TYPE_OBJECT); /* ft_handler */ gtk_tree_view_set_model (view, GTK_TREE_MODEL (liststore)); - ft_manager->priv->model = GTK_TREE_MODEL (liststore); + priv->model = GTK_TREE_MODEL (liststore); g_object_unref (liststore); /* Progress column */ @@ -708,36 +1064,45 @@ ft_manager_build_ui (EmpathyFTManager *ft_manager) gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, "text", COL_REMAINING, NULL); + + /* clear button should be sensitive only if there are completed/cancelled + * handlers in the store. + */ + gtk_widget_set_sensitive (priv->clear_button, FALSE); } +/* GObject method overrides */ + static void empathy_ft_manager_finalize (GObject *object) { - EmpathyFTManager *ft_manager = (EmpathyFTManager *) object; + EmpathyFTManagerPriv *priv = GET_PRIV (object); - DEBUG ("%p", object); + DEBUG ("FT Manager %p", object); - if (ft_manager->priv->window) - gtk_widget_destroy (ft_manager->priv->window); + g_hash_table_destroy (priv->ft_handler_to_row_ref); - g_hash_table_destroy (ft_manager->priv->tp_file_to_row_ref); + if (priv->save_geometry_id != 0) + g_source_remove (priv->save_geometry_id); G_OBJECT_CLASS (empathy_ft_manager_parent_class)->finalize (object); } static void -empathy_ft_manager_init (EmpathyFTManager *ft_manager) +empathy_ft_manager_init (EmpathyFTManager *manager) { EmpathyFTManagerPriv *priv; - priv = G_TYPE_INSTANCE_GET_PRIVATE ((ft_manager), EMPATHY_TYPE_FT_MANAGER, + priv = G_TYPE_INSTANCE_GET_PRIVATE ((manager), EMPATHY_TYPE_FT_MANAGER, EmpathyFTManagerPriv); - ft_manager->priv = priv; + manager->priv = priv; - priv->tp_file_to_row_ref = g_hash_table_new_full (g_direct_hash, + priv->ft_handler_to_row_ref = g_hash_table_new_full (g_direct_hash, g_direct_equal, (GDestroyNotify) g_object_unref, (GDestroyNotify) gtk_tree_row_reference_free); + + ft_manager_build_ui (manager); } static GObject * @@ -749,7 +1114,7 @@ empathy_ft_manager_constructor (GType type, if (manager_singleton) { - retval = g_object_ref (manager_singleton); + retval = G_OBJECT (manager_singleton); } else { @@ -774,325 +1139,50 @@ empathy_ft_manager_class_init (EmpathyFTManagerClass *klass) g_type_class_add_private (object_class, sizeof (EmpathyFTManagerPriv)); } -/** - * empathy_ft_manager_dup_singleton: - * - * Returns a reference to the #EmpathyFTManager singleton object. - * - * Returns: a #EmpathyFTManager - */ -EmpathyFTManager * -empathy_ft_manager_dup_singleton (void) -{ - return g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL); -} - -/** - * empathy_ft_manager_get_dialog: - * @ft_manager: an #EmpathyFTManager - * - * Returns the #GtkWidget of @ft_manager. - * - * Returns: the dialog - */ -GtkWidget * -empathy_ft_manager_get_dialog (EmpathyFTManager *ft_manager) -{ - g_return_val_if_fail (EMPATHY_IS_FT_MANAGER (ft_manager), NULL); - - ft_manager_build_ui (ft_manager); - - return ft_manager->priv->window; -} - -static void -ft_manager_add_tp_file_to_list (EmpathyFTManager *ft_manager, - EmpathyTpFile *tp_file) -{ - GtkTreeRowReference *row_ref; - GtkTreeIter iter; - GtkTreeSelection *selection; - GtkTreePath *path; - GIcon *icon; - const gchar *content_type; - - ft_manager_build_ui (ft_manager); - - /* Get the icon name from the mime-type of the file. */ - content_type = empathy_tp_file_get_content_type (tp_file); - icon = g_content_type_get_icon (content_type); - - /* Append the ft in the store */ - gtk_list_store_insert_with_values (GTK_LIST_STORE (ft_manager->priv->model), - &iter, G_MAXINT, COL_FT_OBJECT, tp_file, COL_ICON, icon, -1); - - g_object_unref (icon); - - /* Insert the new row_ref in the hash table */ - path = gtk_tree_model_get_path (GTK_TREE_MODEL (ft_manager->priv->model), - &iter); - row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL ( - ft_manager->priv->model), path); - gtk_tree_path_free (path); - g_hash_table_insert (ft_manager->priv->tp_file_to_row_ref, - g_object_ref (tp_file), row_ref); - - /* Select the new row */ - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW ( - ft_manager->priv->treeview)); - gtk_tree_selection_select_iter (selection, &iter); - - /* Update the row with the initial values, and keep track of changes */ - ft_manager_update_ft_row (ft_manager, tp_file); - g_signal_connect (tp_file, "notify::state", - G_CALLBACK (ft_manager_state_changed_cb), ft_manager); - g_signal_connect (tp_file, "refresh", - G_CALLBACK (ft_manager_refresh_cb), ft_manager); - - gtk_window_present (GTK_WINDOW (ft_manager->priv->window)); -} - -typedef struct { - EmpathyFTManager *ft_manager; - EmpathyTpFile *tp_file; -} ReceiveResponseData; +/* public methods */ -static void -ft_manager_receive_response_data_free (ReceiveResponseData *response_data) -{ - if (!response_data) - return; - - g_object_unref (response_data->tp_file); - g_object_unref (response_data->ft_manager); - g_slice_free (ReceiveResponseData, response_data); -} - -static void -ft_manager_save_dialog_response_cb (GtkDialog *widget, - gint response_id, - ReceiveResponseData *response_data) +void +empathy_ft_manager_add_handler (EmpathyFTHandler *handler) { - if (response_id == GTK_RESPONSE_OK) - { - gchar *uri; - gchar *folder; - - uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (widget)); - - if (uri) - { - GFile *file; - GError *error = NULL; - - file = g_file_new_for_uri (uri); - empathy_tp_file_accept (response_data->tp_file, 0, file, &error); - - if (error) - { - GtkWidget *dialog; - - DEBUG ("Error with opening file to write to: %s", - error->message ? error->message : "no error"); - - /* Error is already translated */ - dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, _("Cannot save file to this location")); - - gtk_message_dialog_format_secondary_text ( - GTK_MESSAGE_DIALOG (dialog), "%s", - error->message); - - g_signal_connect (dialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); - - gtk_widget_show (dialog); - - g_error_free (error); - return; - } + EmpathyFTManager *manager; + EmpathyFTManagerPriv *priv; - g_object_set_data_full (G_OBJECT (response_data->tp_file), - "uri", uri, g_free); + DEBUG ("Adding handler"); - ft_manager_add_tp_file_to_list (response_data->ft_manager, - response_data->tp_file); + g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler)); - g_object_unref (file); - } + manager = g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL); + priv = GET_PRIV (manager); - folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (widget)); - if (folder) - { - empathy_conf_set_string (empathy_conf_get (), - EMPATHY_PREFS_FILE_TRANSFER_DEFAULT_FOLDER, - folder); - g_free (folder); - } - } - - gtk_widget_destroy (GTK_WIDGET (widget)); - ft_manager_receive_response_data_free (response_data); + ft_manager_add_handler_to_list (manager, handler, NULL); + gtk_window_present (GTK_WINDOW (priv->window)); } -static void -ft_manager_create_save_dialog (ReceiveResponseData *response_data) +void +empathy_ft_manager_display_error (EmpathyFTHandler *handler, + const GError *error) { - GtkWidget *widget; - gchar *folder; - - DEBUG ("Creating save file chooser"); - - widget = gtk_file_chooser_dialog_new (_("Save file as..."), - NULL, GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE_AS, GTK_RESPONSE_OK, - NULL); - - if (!empathy_conf_get_string (empathy_conf_get (), - EMPATHY_PREFS_FILE_TRANSFER_DEFAULT_FOLDER, - &folder) || !folder) - folder = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD)); - - if (folder) - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), folder); - - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (widget), - empathy_tp_file_get_filename (response_data->tp_file)); - - gtk_dialog_set_default_response (GTK_DIALOG (widget), - GTK_RESPONSE_OK); - - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (widget), - TRUE); - - g_signal_connect (widget, "response", - G_CALLBACK (ft_manager_save_dialog_response_cb), response_data); - - gtk_widget_show (widget); - - g_free (folder); -} + EmpathyFTManager *manager; + EmpathyFTManagerPriv *priv; -static void -ft_manager_receive_file_response_cb (GtkWidget *dialog, - gint response, - ReceiveResponseData *response_data) -{ - if (response == GTK_RESPONSE_ACCEPT) - ft_manager_create_save_dialog (response_data); - else - { - empathy_tp_file_cancel (response_data->tp_file); - ft_manager_receive_response_data_free (response_data); - } + g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler)); + g_return_if_fail (error != NULL); - gtk_widget_destroy (dialog); -} + manager = g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL); + priv = GET_PRIV (manager); -static void -ft_manager_display_accept_dialog (EmpathyFTManager *ft_manager, - EmpathyTpFile *tp_file) -{ - GtkWidget *dialog; - GtkWidget *image; - GtkWidget *button; - const gchar *contact_name; - const gchar *filename; - guint64 size; - gchar *size_str; - ReceiveResponseData *response_data; - - g_return_if_fail (EMPATHY_IS_FT_MANAGER (ft_manager)); - g_return_if_fail (EMPATHY_IS_TP_FILE (tp_file)); - - DEBUG ("Creating accept dialog"); - - contact_name = empathy_contact_get_name (empathy_tp_file_get_contact (tp_file)); - filename = empathy_tp_file_get_filename (tp_file); - - size = empathy_tp_file_get_size (tp_file); - if (size == EMPATHY_TP_FILE_UNKNOWN_SIZE) - size_str = g_strdup (_("unknown size")); - else - size_str = g_format_size_for_display (size); - - dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO, - GTK_BUTTONS_NONE, - _("%s would like to send you a file"), - contact_name); - - gtk_message_dialog_format_secondary_text - (GTK_MESSAGE_DIALOG (dialog), - /* Translators: the first %s is the file name, the second %s is the file size */ - _("Do you want to accept the file \"%s\" (%s)?"), - filename, size_str); - - /* Icon */ - image = gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_DIALOG); - gtk_widget_show (image); - gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image); - - /* Decline button */ - button = gtk_button_new_with_mnemonic (_("_Decline")); - gtk_button_set_image (GTK_BUTTON (button), - gtk_image_new_from_stock (GTK_STOCK_CANCEL, - GTK_ICON_SIZE_BUTTON)); - gtk_widget_show (button); - gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, - GTK_RESPONSE_REJECT); - - /* Accept button */ - button = gtk_button_new_with_mnemonic (_("_Accept")); - gtk_button_set_image (GTK_BUTTON (button), - gtk_image_new_from_stock (GTK_STOCK_SAVE, - GTK_ICON_SIZE_BUTTON)); - gtk_widget_show (button); - gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, - GTK_RESPONSE_ACCEPT); - GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); - gtk_widget_grab_default (button); - - response_data = g_slice_new0 (ReceiveResponseData); - response_data->ft_manager = g_object_ref (ft_manager); - response_data->tp_file = g_object_ref (tp_file); - - g_signal_connect (dialog, "response", - G_CALLBACK (ft_manager_receive_file_response_cb), response_data); - - gtk_widget_show (dialog); - - g_free (size_str); + ft_manager_add_handler_to_list (manager, handler, error); + gtk_window_present (GTK_WINDOW (priv->window)); } -/** - * empathy_ft_manager_add_tp_file: - * @ft_manager: an #EmpathyFTManager - * @ft: an #EmpathyFT - * - * Adds a file transfer to the file transfer manager dialog @ft_manager. - * The manager dialog then shows the progress and other information about - * @ft. - */ void -empathy_ft_manager_add_tp_file (EmpathyFTManager *ft_manager, - EmpathyTpFile *tp_file) +empathy_ft_manager_show (void) { - TpFileTransferState state; - - g_return_if_fail (EMPATHY_IS_FT_MANAGER (ft_manager)); - g_return_if_fail (EMPATHY_IS_TP_FILE (tp_file)); - - state = empathy_tp_file_get_state (tp_file, NULL); + EmpathyFTManager *manager; + EmpathyFTManagerPriv *priv; - DEBUG ("Adding a file transfer: contact=%s, filename=%s, state=%d", - empathy_contact_get_name (empathy_tp_file_get_contact (tp_file)), - empathy_tp_file_get_filename (tp_file), state); + manager = g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL); + priv = GET_PRIV (manager); - if (state == TP_FILE_TRANSFER_STATE_PENDING && - empathy_tp_file_is_incoming (tp_file)) - ft_manager_display_accept_dialog (ft_manager, tp_file); - else - ft_manager_add_tp_file_to_list (ft_manager, tp_file); + gtk_window_present (GTK_WINDOW (priv->window)); } - |