* Authors: Xan Lopez
* Marco Barisione <marco@barisione.org>
* Jonny Lamb <jonny.lamb@collabora.co.uk>
+ * Xavier Claessens <xclaesse@gmail.com>
*/
/* The original file transfer manager code was copied from Epiphany */
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include <libgnomevfs/gnome-vfs.h>
-#include <libgnomeui/libgnomeui.h>
#define DEBUG_FLAG EMPATHY_DEBUG_FT
#include <libempathy/empathy-debug.h>
#include "empathy-ft-manager.h"
+#include "extensions/extensions.h"
+
/**
* SECTION:empathy-ft-manager
* @short_description: File transfer dialog
COL_FT_OBJECT
};
-enum
-{
- PROGRESS_COL_POS,
- FILE_COL_POS,
- REMAINING_COL_POS
-};
-
/**
* EmpathyFTManagerPriv:
*
G_DEFINE_TYPE (EmpathyFTManager, empathy_ft_manager, G_TYPE_OBJECT);
-static EmpathyFTManager *manager_p = NULL;
-
-/**
- * empathy_ft_manager_get_default:
- *
- * Returns a new #EmpathyFTManager if there is not already one, or the existing
- * one if it exists.
- *
- * Returns: a #EmpathyFTManager
- */
-EmpathyFTManager *
-empathy_ft_manager_get_default (void)
-{
- if (!manager_p)
- manager_p = g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL);
-
- return manager_p;
-}
-
-/**
- * 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);
-
- return ft_manager->priv->window;
-}
+static EmpathyFTManager *manager_singleton = NULL;
static gchar *
ft_manager_format_interval (gint interval)
secs = interval;
if (hours > 0)
+ /* Translators: time left, when it is more than one hour */
return g_strdup_printf (_("%u:%02u.%02u"), hours, mins, secs);
else
+ /* Translators: time left, when is is less than one hour */
return g_strdup_printf (_("%02u.%02u"), mins, secs);
}
GtkTreeModel *model;
GtkTreeIter iter;
EmpathyTpFile *tp_file;
- EmpFileTransferState state;
+ TpFileTransferState state;
gboolean open_enabled = FALSE;
gboolean abort_enabled = FALSE;
state = empathy_tp_file_get_state (tp_file, NULL);
/* I can open the file if the transfer is completed and was incoming */
- open_enabled = (state == EMP_FILE_TRANSFER_STATE_COMPLETED &&
+ open_enabled = (state == TP_FILE_TRANSFER_STATE_COMPLETED &&
empathy_tp_file_is_incoming (tp_file));
/* I can abort if the transfer is not already finished */
- abort_enabled = (state != EMP_FILE_TRANSFER_STATE_CANCELLED &&
- state != EMP_FILE_TRANSFER_STATE_COMPLETED);
+ abort_enabled = (state != TP_FILE_TRANSFER_STATE_CANCELLED &&
+ state != TP_FILE_TRANSFER_STATE_COMPLETED);
+
+ g_object_unref (tp_file);
}
gtk_widget_set_sensitive (ft_manager->priv->open_button, open_enabled);
}
static const gchar *
-ft_manager_state_change_reason_to_string (EmpFileTransferStateChangeReason reason)
+ft_manager_state_change_reason_to_string (TpFileTransferStateChangeReason reason)
{
switch (reason)
{
- case EMP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE:
- return _("File transfer not completed");
- case EMP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_STOPPED:
+ 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 EMP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED:
+ case TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED:
return _("The other participant canceled the file transfer");
- case EMP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR:
+ case TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR:
return _("Error while trying to transfer the file");
- case EMP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_ERROR:
+ case TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_ERROR:
return _("The other participant is unable to transfer the file");
- default:
- return _("Unknown reason");
}
+ return _("Unknown reason");
}
static void
GtkTreeIter iter;
const gchar *filename;
const gchar *contact_name;
- gchar *msg;
- gchar *remaining_str;
+ const gchar *msg;
+ gchar *msg_dup = NULL;
+ gchar *remaining_str = NULL;
gchar *first_line_format;
- gchar *first_line;
- gchar *second_line;
+ gchar *first_line = NULL;
+ gchar *second_line = NULL;
guint64 transferred_bytes;
guint64 total_size;
gint remaining = -1;
gint percent;
- EmpFileTransferState state;
- EmpFileTransferStateChangeReason reason;
+ TpFileTransferState state;
+ TpFileTransferStateChangeReason reason;
gboolean incoming;
row_ref = ft_manager_get_row_from_tp_file (ft_manager, tp_file);
switch (state)
{
- case EMP_FILE_TRANSFER_STATE_PENDING:
- case EMP_FILE_TRANSFER_STATE_OPEN:
- case EMP_FILE_TRANSFER_STATE_ACCEPTED:
+ 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");
+ 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");
first_line = g_strdup_printf (first_line_format, filename, contact_name);
- if (state == EMP_FILE_TRANSFER_STATE_OPEN
- || (incoming && state == EMP_FILE_TRANSFER_STATE_ACCEPTED)
- || (incoming && state == EMP_FILE_TRANSFER_STATE_PENDING))
+ if (state == TP_FILE_TRANSFER_STATE_OPEN || incoming)
{
gchar *total_size_str;
gchar *transferred_bytes_str;
if (total_size == EMPATHY_TP_FILE_UNKNOWN_SIZE)
- /* translators: the text before the "|" is context to
- * help you decide on the correct translation. You MUST
- * OMIT it in the translated string. */
- total_size_str = g_strdup (Q_("file size|Unknown"));
+ total_size_str = g_strdup (C_("file size", "Unknown"));
else
total_size_str = g_format_size_for_display (total_size);
}
else
- second_line = g_strdup (_("Waiting the other participant's response"));
+ second_line = g_strdup (_("Waiting for the other participant's response"));
remaining = empathy_tp_file_get_remaining_time (tp_file);
break;
- case EMP_FILE_TRANSFER_STATE_COMPLETED:
- if (empathy_tp_file_is_incoming (tp_file))
+ 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\" sent to %s"), filename,
contact_name);
- second_line = g_strdup ("File transfer completed");
+ second_line = g_strdup (_("File transfer completed"));
break;
- case EMP_FILE_TRANSFER_STATE_CANCELLED:
- if (empathy_tp_file_is_incoming (tp_file))
+ case TP_FILE_TRANSFER_STATE_CANCELLED:
+ if (incoming)
/* translators: first %s is filename, second %s
* is the contact name */
first_line = g_strdup_printf (
ft_manager_state_change_reason_to_string (reason));
break;
-
- default:
- g_return_if_reached ();
-
}
- if (total_size != EMPATHY_TP_FILE_UNKNOWN_SIZE)
+ 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 == EMP_FILE_TRANSFER_STATE_COMPLETED ||
- state == EMP_FILE_TRANSFER_STATE_CANCELLED)
- remaining_str = g_strdup ("");
- else
- /* translators: the text before the "|" is context to
- * help you decide on the correct translation. You
- * MUST OMIT it in the translated string. */
- remaining_str = g_strdup (Q_("remaining time|Unknown"));
+ 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);
- msg = g_strdup_printf ("%s\n%s", first_line, second_line);
+ 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,
- COL_REMAINING, remaining_str,
+ COL_MESSAGE, msg ? msg : "",
+ COL_REMAINING, remaining_str ? remaining_str : "",
-1);
gtk_tree_path_free (path);
- g_free (msg);
+ g_free (msg_dup);
g_free (first_line);
g_free (second_line);
g_free (remaining_str);
if (percent < 0)
{
percent = 0;
- /* Translators: The text before the "|" is context to help you
- * decide on the correct translation. You MUST OMIT it in the
- * translated string. */
- text = Q_("file transfer percent|Unknown");
+ text = C_("file transfer percent", "Unknown");
}
g_object_set (renderer, "text", text, "value", percent, NULL);
}
static void
-ft_manager_remove_file_from_list (EmpathyFTManager *ft_manager,
+ft_manager_remove_file_from_model (EmpathyFTManager *ft_manager,
EmpathyTpFile *tp_file)
{
GtkTreeRowReference *row_ref;
+ GtkTreeSelection *selection;
GtkTreePath *path = NULL;
- GtkTreeIter iter, iter2;
+ GtkTreeIter iter;
+ gboolean update_selection;
row_ref = ft_manager_get_row_from_tp_file (ft_manager, tp_file);
g_return_if_fail (row_ref);
empathy_contact_get_name (empathy_tp_file_get_contact (tp_file)),
empathy_tp_file_get_filename (tp_file));
- /* Get the row we'll select after removal ("smart" selection) */
-
+ /* Get the iter from the row_ref */
path = gtk_tree_row_reference_get_path (row_ref);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (ft_manager->priv->model),
- &iter, path);
- gtk_tree_path_free (path);
-
- row_ref = NULL;
- iter2 = iter;
- if (gtk_tree_model_iter_next (GTK_TREE_MODEL (ft_manager->priv->model), &iter))
- {
- 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);
- }
- else
- {
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (ft_manager->priv->model), &iter2);
- if (gtk_tree_path_prev (path))
- {
- row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (ft_manager->priv->model),
- path);
- }
- }
+ gtk_tree_model_get_iter (ft_manager->priv->model, &iter, path);
gtk_tree_path_free (path);
- /* Removal */
-
- gtk_list_store_remove (GTK_LIST_STORE (ft_manager->priv->model), &iter2);
- g_object_unref (tp_file);
-
- /* Actual selection */
+ /* 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));
+ update_selection = gtk_tree_selection_iter_is_selected (selection, &iter);
- if (row_ref != NULL)
+ /* 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))
{
- path = gtk_tree_row_reference_get_path (row_ref);
- if (path != NULL)
- {
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (ft_manager->priv->treeview),
- path, NULL, FALSE);
- gtk_tree_path_free (path);
- }
- gtk_tree_row_reference_free (row_ref);
+ 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);
+ if (n_row > 0)
+ gtk_tree_model_iter_nth_child (ft_manager->priv->model, &iter, NULL,
+ n_row - 1);
+ else
+ update_selection = FALSE;
}
+ if (update_selection)
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ empathy_tp_file_close (tp_file);
}
static gboolean
{
EmpathyTpFile *tp_file = EMPATHY_TP_FILE (key);
EmpathyFTManager *self = EMPATHY_FT_MANAGER (user_data);
- EmpFileTransferState state;
+ TpFileTransferState state;
state = empathy_tp_file_get_state (tp_file, NULL);
- if (state == EMP_FILE_TRANSFER_STATE_COMPLETED ||
- state == EMP_FILE_TRANSFER_STATE_CANCELLED)
+ if (state == TP_FILE_TRANSFER_STATE_COMPLETED ||
+ state == TP_FILE_TRANSFER_STATE_CANCELLED)
{
- ft_manager_remove_file_from_list (self, tp_file);
+ ft_manager_remove_file_from_model (self, tp_file);
return TRUE;
}
return FALSE;
}
-static void
-ft_manager_clear (EmpathyFTManager *ft_manager)
-{
- DEBUG ("Clearing file transfer list");
-
- /* Remove completed and cancelled transfers */
- g_hash_table_foreach_remove (ft_manager->priv->tp_file_to_row_ref,
- remove_finished_transfer_foreach, ft_manager);
-}
-
static void
ft_manager_state_changed_cb (EmpathyTpFile *tp_file,
GParamSpec *pspec,
EmpathyFTManager *ft_manager)
{
- gboolean remove;
-
- switch (empathy_tp_file_get_state (tp_file, NULL))
+ if (empathy_tp_file_get_state (tp_file, NULL) ==
+ TP_FILE_TRANSFER_STATE_COMPLETED)
{
- case EMP_FILE_TRANSFER_STATE_COMPLETED:
- if (empathy_tp_file_is_incoming (tp_file))
- {
- GtkRecentManager *manager;
- const gchar *uri;
-
- manager = gtk_recent_manager_get_default ();
- uri = g_object_get_data (G_OBJECT (tp_file), "uri");
- gtk_recent_manager_add_item (manager, uri);
- }
-
- case EMP_FILE_TRANSFER_STATE_CANCELLED:
- /* Automatically remove file transfers if the
- * window if not visible. */
- /* FIXME how do the user know if the file transfer
- * failed? */
- remove = !GTK_WIDGET_VISIBLE (ft_manager->priv->window);
- break;
+ GtkRecentManager *manager;
+ const gchar *uri;
- default:
- remove = FALSE;
- break;
+ 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);
}
- if (remove)
- {
- ft_manager_remove_file_from_list (ft_manager, tp_file);
- g_hash_table_remove (ft_manager->priv->tp_file_to_row_ref, tp_file);
- }
- else
- {
- ft_manager_update_ft_row (ft_manager, tp_file);
- }
+ ft_manager_update_ft_row (ft_manager, tp_file);
}
static void
-ft_manager_add_tp_file_to_list (EmpathyFTManager *ft_manager,
- EmpathyTpFile *tp_file)
+ft_manager_clear (EmpathyFTManager *ft_manager)
{
- GtkTreeRowReference *row_ref;
- GtkTreeIter iter;
- GtkTreeSelection *selection;
- GtkTreePath *path;
- GtkIconTheme *theme;
- gchar *icon_name;
- gchar *content_type;
-
- gtk_list_store_insert_with_values (GTK_LIST_STORE (ft_manager->priv->model),
- &iter, G_MAXINT, COL_FT_OBJECT, tp_file, -1);
-
- 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_object_ref (tp_file);
- g_hash_table_insert (ft_manager->priv->tp_file_to_row_ref, tp_file,
- row_ref);
-
- ft_manager_update_ft_row (ft_manager, tp_file);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (
- ft_manager->priv->treeview));
- gtk_tree_selection_select_iter (selection, &iter);
-
- g_signal_connect (tp_file, "notify::state",
- G_CALLBACK (ft_manager_state_changed_cb), ft_manager);
- g_signal_connect (tp_file, "notify::transferred-bytes",
- G_CALLBACK (ft_manager_transferred_bytes_changed_cb), ft_manager);
-
- g_object_get (tp_file, "content-type", &content_type, NULL);
-
- theme = gtk_icon_theme_get_default ();
- /* FIXME remove the dependency on libgnomeui replacing this function
- * with gio/gvfs or copying the code from gtk-recent.
- * With GTK+ 2.14 we can get the GIcon using g_content_type_get_icon
- * and then use the "gicon" property of GtkCellRendererPixbuf. */
- icon_name = gnome_icon_lookup (theme, NULL, NULL, NULL, NULL,
- content_type, GNOME_ICON_LOOKUP_FLAGS_NONE, NULL);
-
- gtk_list_store_set (GTK_LIST_STORE (
- ft_manager->priv->model), &iter, COL_ICON, icon_name, -1);
+ DEBUG ("Clearing file transfer list");
- gtk_window_present (GTK_WINDOW (ft_manager->priv->window));
- g_free (content_type);
- g_free (icon_name);
+ /* Remove completed and cancelled transfers */
+ g_hash_table_foreach_remove (ft_manager->priv->tp_file_to_row_ref,
+ remove_finished_transfer_foreach, ft_manager);
}
static void
uri = g_object_get_data (G_OBJECT (tp_file), "uri");
DEBUG ("Opening URI: %s", uri);
- empathy_url_show (uri);
+ empathy_url_show (GTK_WIDGET (ft_manager->priv->window), uri);
+ g_object_unref (tp_file);
}
static void
empathy_tp_file_get_filename (tp_file));
empathy_tp_file_cancel (tp_file);
+ g_object_unref (tp_file);
}
static void
-ft_manager_response_cb (GtkWidget *dialog,
+ft_manager_response_cb (GtkWidget *widget,
gint response,
EmpathyFTManager *ft_manager)
{
}
}
-/*
- * Receiving files
+static gboolean
+ft_manager_delete_event_cb (GtkWidget *widget,
+ GdkEvent *event,
+ EmpathyFTManager *ft_manager)
+{
+ ft_manager_clear (ft_manager);
+ if (g_hash_table_size (ft_manager->priv->tp_file_to_row_ref) > 0)
+ {
+ /* There is still FTs on flight, just hide the window */
+ DEBUG ("Hiding window");
+ gtk_widget_hide (widget);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ft_manager_destroy_cb (GtkWidget *widget,
+ EmpathyFTManager *ft_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);
+}
+
+static void
+ft_manager_build_ui (EmpathyFTManager *ft_manager)
+{
+ GtkBuilder *gui;
+ gint x, y, w, h;
+ GtkTreeView *view;
+ GtkListStore *liststore;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+ gchar *filename;
+
+ if (ft_manager->priv->window != NULL)
+ return;
+
+ 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,
+ NULL);
+ g_free (filename);
+
+ empathy_builder_connect (gui, ft_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);
+
+ /* Window geometry. */
+ empathy_geometry_load ("ft-manager", &x, &y, &w, &h);
+
+ if (x >= 0 && y >= 0)
+ {
+ /* 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);
+ }
+
+ 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);
+ }
+
+ /* Setup the tree view */
+ view = GTK_TREE_VIEW (ft_manager->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);
+ gtk_tree_view_set_headers_visible (view, TRUE);
+ gtk_tree_view_set_enable_search (view, FALSE);
+
+ /* Setup the model */
+ liststore = gtk_list_store_new (5,
+ G_TYPE_INT, /* percent */
+ G_TYPE_ICON, /* icon */
+ G_TYPE_STRING, /* message */
+ G_TYPE_STRING, /* remaining */
+ G_TYPE_OBJECT); /* ft_file */
+ gtk_tree_view_set_model (view, GTK_TREE_MODEL (liststore));
+ ft_manager->priv->model = GTK_TREE_MODEL (liststore);
+ g_object_unref (liststore);
+
+ /* Progress column */
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("%"));
+ gtk_tree_view_column_set_sort_column_id (column, COL_PERCENT);
+ gtk_tree_view_insert_column (view, column, -1);
+
+ renderer = gtk_cell_renderer_progress_new ();
+ g_object_set (renderer, "xalign", 0.5, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_cell_data_func (column, renderer,
+ ft_manager_progress_cell_data_func, NULL, NULL);
+
+ /* Icon and filename column*/
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("File"));
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_sort_column_id (column, COL_MESSAGE);
+ gtk_tree_view_column_set_spacing (column, 3);
+ gtk_tree_view_insert_column (view, column, -1);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (renderer, "xpad", 3,
+ "stock-size", GTK_ICON_SIZE_DND, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "gicon", COL_ICON, NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "text", COL_MESSAGE, NULL);
+
+ /* Remaining time column */
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Remaining"));
+ gtk_tree_view_column_set_sort_column_id (column, COL_REMAINING);
+ gtk_tree_view_insert_column (view, column, -1);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer, "xalign", 0.5, NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "text", COL_REMAINING, NULL);
+}
+
+static void
+empathy_ft_manager_finalize (GObject *object)
+{
+ EmpathyFTManager *ft_manager = (EmpathyFTManager *) object;
+
+ DEBUG ("%p", object);
+
+ if (ft_manager->priv->window)
+ gtk_widget_destroy (ft_manager->priv->window);
+
+ g_hash_table_destroy (ft_manager->priv->tp_file_to_row_ref);
+
+ G_OBJECT_CLASS (empathy_ft_manager_parent_class)->finalize (object);
+}
+
+static void
+empathy_ft_manager_init (EmpathyFTManager *ft_manager)
+{
+ EmpathyFTManagerPriv *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE ((ft_manager), EMPATHY_TYPE_FT_MANAGER,
+ EmpathyFTManagerPriv);
+
+ ft_manager->priv = priv;
+
+ priv->tp_file_to_row_ref = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) gtk_tree_row_reference_free);
+}
+
+static GObject *
+empathy_ft_manager_constructor (GType type,
+ guint n_props,
+ GObjectConstructParam *props)
+{
+ GObject *retval;
+
+ if (manager_singleton)
+ {
+ retval = g_object_ref (manager_singleton);
+ }
+ else
+ {
+ retval = G_OBJECT_CLASS (empathy_ft_manager_parent_class)->constructor
+ (type, n_props, props);
+
+ manager_singleton = EMPATHY_FT_MANAGER (retval);
+ g_object_add_weak_pointer (retval, (gpointer) &manager_singleton);
+ }
+
+ return retval;
+}
+
+static void
+empathy_ft_manager_class_init (EmpathyFTManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = empathy_ft_manager_finalize;
+ object_class->constructor = empathy_ft_manager_constructor;
+
+ 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, "notify::transferred-bytes",
+ G_CALLBACK (ft_manager_transferred_bytes_changed_cb), ft_manager);
+
+ gtk_window_present (GTK_WINDOW (ft_manager->priv->window));
+}
typedef struct {
EmpathyFTManager *ft_manager;
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);
empathy_ft_manager_add_tp_file (EmpathyFTManager *ft_manager,
EmpathyTpFile *tp_file)
{
- EmpFileTransferState state;
+ TpFileTransferState state;
g_return_if_fail (EMPATHY_IS_FT_MANAGER (ft_manager));
g_return_if_fail (EMPATHY_IS_TP_FILE (tp_file));
- DEBUG ("Adding a file transfer: contact=%s, filename=%s",
- empathy_contact_get_name (empathy_tp_file_get_contact (tp_file)),
- empathy_tp_file_get_filename (tp_file));
-
state = empathy_tp_file_get_state (tp_file, NULL);
- if (state == EMP_FILE_TRANSFER_STATE_PENDING &&
+ 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);
+
+ 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);
}
-static void
-empathy_ft_manager_finalize (GObject *object)
-{
- EmpathyFTManager *ft_manager = (EmpathyFTManager *) object;
-
- DEBUG ("Finalizing: %p", object);
-
- g_hash_table_destroy (ft_manager->priv->tp_file_to_row_ref);
-
- if (ft_manager->priv->save_geometry_id != 0)
- g_source_remove (ft_manager->priv->save_geometry_id);
-
- G_OBJECT_CLASS (empathy_ft_manager_parent_class)->finalize (object);
-}
-
-static gboolean
-ft_manager_delete_event_cb (GtkWidget *widget,
- GdkEvent *event,
- EmpathyFTManager *ft_manager)
-{
- ft_manager_clear (ft_manager);
- if (g_hash_table_size (ft_manager->priv->tp_file_to_row_ref) == 0)
- {
- DEBUG ("Destroying window");
- if (manager_p != NULL)
- g_object_unref (manager_p);
-
- manager_p = NULL;
- return FALSE;
- }
- else
- {
- DEBUG ("Hiding window");
- gtk_widget_hide (widget);
- return TRUE;
- }
-}
-
-static void
-ft_manager_build_ui (EmpathyFTManager *ft_manager)
-{
- gint x, y, w, h;
- GtkListStore *liststore;
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- GtkTreeSelection *selection;
- gchar *filename;
-
- filename = empathy_file_lookup ("empathy-ft-manager.glade",
- "libempathy-gtk");
- empathy_glade_get_file (filename,
- "ft_manager_dialog", NULL,
- "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,
- NULL);
- g_free (filename);
-
- g_signal_connect (ft_manager->priv->window, "response",
- G_CALLBACK (ft_manager_response_cb), ft_manager);
- g_signal_connect (ft_manager->priv->window, "delete-event",
- G_CALLBACK (ft_manager_delete_event_cb), ft_manager);
- g_signal_connect (ft_manager->priv->window, "configure-event",
- G_CALLBACK (ft_manager_configure_event_cb), ft_manager);
-
- /* Window geometry. */
- empathy_geometry_load ("ft-manager", &x, &y, &w, &h);
-
- if (x >= 0 && y >= 0)
- {
- /* 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);
- }
-
- if (w > 0 && h > 0)
- {
- /* Use the defaults from the glade file if we don't have
- * good w, h geometry. */
- gtk_window_resize (GTK_WINDOW (ft_manager->priv->window), w, h);
- }
-
- gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (
- ft_manager->priv->treeview)), GTK_SELECTION_BROWSE);
-
- liststore = gtk_list_store_new (5, G_TYPE_INT, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_OBJECT);
-
- gtk_tree_view_set_model (GTK_TREE_VIEW(ft_manager->priv->treeview),
- GTK_TREE_MODEL (liststore));
- g_object_unref (liststore);
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(ft_manager->priv->treeview), TRUE);
-
- /* Icon and filename column*/
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_title (column, _("File"));
- renderer = gtk_cell_renderer_pixbuf_new ();
- g_object_set (renderer, "xpad", 3, NULL);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_set_attributes (column, renderer,
- "icon-name", COL_ICON,
- NULL);
- g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DND, NULL);
- renderer = gtk_cell_renderer_text_new ();
- g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- gtk_tree_view_column_pack_start (column, renderer, TRUE);
- gtk_tree_view_column_set_attributes (column, renderer,
- "text", COL_MESSAGE,
- NULL);
- gtk_tree_view_insert_column (GTK_TREE_VIEW (ft_manager->priv->treeview), column,
- FILE_COL_POS);
- gtk_tree_view_column_set_expand (column, TRUE);
- gtk_tree_view_column_set_resizable (column, TRUE);
- gtk_tree_view_column_set_sort_column_id (column, COL_MESSAGE);
- gtk_tree_view_column_set_spacing (column, 3);
-
- /* Progress column */
- renderer = gtk_cell_renderer_progress_new ();
- g_object_set (renderer, "xalign", 0.5, NULL);
- gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (ft_manager->priv->treeview),
- PROGRESS_COL_POS, _("%"),
- renderer,
- NULL);
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (ft_manager->priv->treeview),
- PROGRESS_COL_POS);
- gtk_tree_view_column_set_cell_data_func(column, renderer,
- ft_manager_progress_cell_data_func,
- NULL, NULL);
- gtk_tree_view_column_set_sort_column_id (column, COL_PERCENT);
-
- /* Remaining time column */
- renderer = gtk_cell_renderer_text_new ();
- g_object_set (renderer, "xalign", 0.5, NULL);
- gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (
- ft_manager->priv->treeview), REMAINING_COL_POS, _("Remaining"),
- renderer, "text", COL_REMAINING, NULL);
-
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (
- ft_manager->priv->treeview),
- REMAINING_COL_POS);
- gtk_tree_view_column_set_sort_column_id (column, COL_REMAINING);
-
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (ft_manager->priv->treeview),
- FALSE);
-
- ft_manager->priv->model = GTK_TREE_MODEL (liststore);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (
- ft_manager->priv->treeview));
- g_signal_connect (selection, "changed",
- G_CALLBACK (ft_manager_selection_changed), ft_manager);
-}
-
-static void
-empathy_ft_manager_init (EmpathyFTManager *ft_manager)
-{
- EmpathyFTManagerPriv *priv;
-
- priv = G_TYPE_INSTANCE_GET_PRIVATE ((ft_manager), EMPATHY_TYPE_FT_MANAGER,
- EmpathyFTManagerPriv);
-
- ft_manager->priv = priv;
-
- priv->tp_file_to_row_ref = g_hash_table_new_full (g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) gtk_tree_row_reference_free);
-
- ft_manager_build_ui (ft_manager);
-}
-
-static void
-empathy_ft_manager_class_init (EmpathyFTManagerClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = empathy_ft_manager_finalize;
-
- g_type_class_add_private (object_class, sizeof (EmpathyFTManagerPriv));
-}