2 * Copyright (C) 2003, 2004 Xan Lopez
3 * Copyright (C) 2007 Marco Barisione <marco@barisione.org>
4 * Copyright (C) 2008-2009 Collabora Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 * Marco Barisione <marco@barisione.org>
23 * Jonny Lamb <jonny.lamb@collabora.co.uk>
24 * Xavier Claessens <xclaesse@gmail.com>
25 * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
28 /* The original file transfer manager code was copied from Epiphany */
34 #include <glib/gi18n.h>
36 #include <gdk/gdkkeysyms.h>
38 #define DEBUG_FLAG EMPATHY_DEBUG_FT
39 #include <libempathy/empathy-debug.h>
40 #include <libempathy/empathy-tp-file.h>
41 #include <libempathy/empathy-utils.h>
43 #include <libempathy-gtk/empathy-conf.h>
44 #include <libempathy-gtk/empathy-ui-utils.h>
45 #include <libempathy-gtk/empathy-geometry.h>
46 #include <libempathy-gtk/empathy-images.h>
48 #include "empathy-ft-manager.h"
61 GHashTable *ft_handler_to_row_ref;
66 GtkWidget *open_button;
67 GtkWidget *abort_button;
68 GtkWidget *clear_button;
69 } EmpathyFTManagerPriv;
78 G_DEFINE_TYPE (EmpathyFTManager, empathy_ft_manager, G_TYPE_OBJECT);
80 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyFTManager)
82 static EmpathyFTManager *manager_singleton = NULL;
84 static void ft_handler_hashing_started_cb (EmpathyFTHandler *handler,
85 EmpathyFTManager *manager);
88 ft_manager_format_interval (guint interval)
90 gint hours, mins, secs;
92 hours = interval / 3600;
93 interval -= hours * 3600;
95 interval -= mins * 60;
99 /* Translators: time left, when it is more than one hour */
100 return g_strdup_printf (_("%u:%02u.%02u"), hours, mins, secs);
102 /* Translators: time left, when is is less than one hour */
103 return g_strdup_printf (_("%02u.%02u"), mins, secs);
107 ft_manager_update_buttons (EmpathyFTManager *manager)
109 GtkTreeSelection *selection;
112 EmpathyFTHandler *handler;
113 gboolean open_enabled = FALSE;
114 gboolean abort_enabled = FALSE;
115 gboolean clear_enabled = FALSE;
116 gboolean is_completed, is_cancelled;
117 GHashTableIter hash_iter;
118 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
120 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
122 if (gtk_tree_selection_get_selected (selection, &model, &iter))
124 gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &handler, -1);
126 is_completed = empathy_ft_handler_is_completed (handler);
127 is_cancelled = empathy_ft_handler_is_cancelled (handler);
129 /* I can open the file if the transfer is completed and was incoming */
130 open_enabled = (is_completed && empathy_ft_handler_is_incoming (handler));
132 /* I can abort if the transfer is not already finished */
133 abort_enabled = (is_cancelled == FALSE && is_completed == FALSE);
135 g_object_unref (handler);
138 g_hash_table_iter_init (&hash_iter, priv->ft_handler_to_row_ref);
140 while (g_hash_table_iter_next (&hash_iter, (gpointer *) &handler, NULL))
142 if (empathy_ft_handler_is_completed (handler) ||
143 empathy_ft_handler_is_cancelled (handler))
144 clear_enabled = TRUE;
150 gtk_widget_set_sensitive (priv->open_button, open_enabled);
151 gtk_widget_set_sensitive (priv->abort_button, abort_enabled);
154 gtk_widget_set_sensitive (priv->clear_button, TRUE);
158 ft_manager_selection_changed (GtkTreeSelection *selection,
159 EmpathyFTManager *manager)
161 ft_manager_update_buttons (manager);
165 ft_manager_progress_cell_data_func (GtkTreeViewColumn *col,
166 GtkCellRenderer *renderer,
171 const gchar *text = NULL;
174 gtk_tree_model_get (model, iter, COL_PERCENT, &percent, -1);
179 text = C_("file transfer percent", "Unknown");
182 g_object_set (renderer, "text", text, "value", percent, NULL);
185 static GtkTreeRowReference *
186 ft_manager_get_row_from_handler (EmpathyFTManager *manager,
187 EmpathyFTHandler *handler)
189 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
191 return g_hash_table_lookup (priv->ft_handler_to_row_ref, handler);
195 ft_manager_remove_file_from_model (EmpathyFTManager *manager,
196 EmpathyFTHandler *handler)
198 GtkTreeRowReference *row_ref;
199 GtkTreeSelection *selection;
200 GtkTreePath *path = NULL;
202 gboolean update_selection;
203 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
205 row_ref = ft_manager_get_row_from_handler (manager, handler);
206 g_return_if_fail (row_ref);
208 DEBUG ("Removing file transfer from window: contact=%s, filename=%s",
209 empathy_contact_get_name (empathy_ft_handler_get_contact (handler)),
210 empathy_ft_handler_get_filename (handler));
212 /* Get the iter from the row_ref */
213 path = gtk_tree_row_reference_get_path (row_ref);
214 gtk_tree_model_get_iter (priv->model, &iter, path);
215 gtk_tree_path_free (path);
217 /* We have to update the selection only if we are removing the selected row */
218 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
219 update_selection = gtk_tree_selection_iter_is_selected (selection, &iter);
221 /* Remove tp_file's row. After that iter points to the next row */
222 if (!gtk_list_store_remove (GTK_LIST_STORE (priv->model), &iter))
226 /* There is no next row, set iter to the last row */
227 n_row = gtk_tree_model_iter_n_children (priv->model, NULL);
229 gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, n_row - 1);
231 update_selection = FALSE;
234 if (update_selection)
235 gtk_tree_selection_select_iter (selection, &iter);
239 remove_finished_transfer_foreach (gpointer key,
243 EmpathyFTHandler *handler = key;
244 EmpathyFTManager *manager = user_data;
246 if (empathy_ft_handler_is_completed (handler) ||
247 empathy_ft_handler_is_cancelled (handler))
249 ft_manager_remove_file_from_model (manager, handler);
257 ft_manager_format_progress_bytes_and_percentage (guint64 current,
262 char *total_str, *current_str, *retval;
263 char *speed_str = NULL;
265 total_str = g_format_size_for_display (total);
266 current_str = g_format_size_for_display (current);
269 speed_str = g_format_size_for_display ((goffset) speed);
271 /* translators: first %s is the currently processed size, second %s is
272 * the total file size */
274 g_strdup_printf (_("%s of %s at %s/s"), current_str, total_str, speed_str) :
275 g_strdup_printf (_("%s of %s"), current_str, total_str);
278 g_free (current_str);
281 if (percentage != NULL)
284 *percentage = current * 100 / total;
293 ft_manager_format_contact_info (EmpathyFTHandler *handler)
296 const char *filename, *contact_name, *first_line_format;
299 incoming = empathy_ft_handler_is_incoming (handler);
300 contact_name = empathy_contact_get_name
301 (empathy_ft_handler_get_contact (handler));
302 filename = empathy_ft_handler_get_filename (handler);
305 /* translators: first %s is filename, second %s is the contact name */
306 first_line_format = _("Receiving \"%s\" from %s");
308 /* translators: first %s is filename, second %s is the contact name */
309 first_line_format = _("Sending \"%s\" to %s");
311 retval = g_strdup_printf (first_line_format, filename, contact_name);
317 ft_manager_format_error_message (EmpathyFTHandler *handler,
320 const char *contact_name, *filename;
321 EmpathyContact *contact;
322 char *first_line, *message;
326 incoming = empathy_ft_handler_is_incoming (handler);
328 contact = empathy_ft_handler_get_contact (handler);
330 contact_name = empathy_contact_get_name (contact);
332 filename = empathy_ft_handler_get_filename (handler);
335 /* filename/contact_name here are either both NULL or both valid */
336 if (filename && contact_name)
337 /* translators: first %s is filename, second %s
338 * is the contact name */
339 first_line = g_strdup_printf (_("Error receiving \"%s\" from %s"), filename,
342 first_line = g_strdup (_("Error receiving a file"));
344 /* translators: first %s is filename, second %s
345 * is the contact name */
346 if (filename && contact_name)
347 first_line = g_strdup_printf (_("Error sending \"%s\" to %s"), filename,
350 first_line = g_strdup (_("Error sending a file"));
352 message = g_strdup_printf ("%s\n%s", first_line, error->message);
360 ft_manager_update_handler_message (EmpathyFTManager *manager,
361 GtkTreeRowReference *row_ref,
366 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
368 /* Set new value in the store */
369 path = gtk_tree_row_reference_get_path (row_ref);
370 gtk_tree_model_get_iter (priv->model, &iter, path);
371 gtk_list_store_set (GTK_LIST_STORE (priv->model),
373 COL_MESSAGE, message ? message : "",
376 gtk_tree_path_free (path);
380 ft_manager_update_handler_progress (EmpathyFTManager *manager,
381 GtkTreeRowReference *row_ref,
386 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
388 /* Set new value in the store */
389 path = gtk_tree_row_reference_get_path (row_ref);
390 gtk_tree_model_get_iter (priv->model, &iter, path);
391 gtk_list_store_set (GTK_LIST_STORE (priv->model),
393 COL_PERCENT, percentage,
396 gtk_tree_path_free (path);
401 ft_manager_update_handler_time (EmpathyFTManager *manager,
402 GtkTreeRowReference *row_ref,
403 guint remaining_time)
407 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
410 remaining_str = ft_manager_format_interval (remaining_time);
412 /* Set new value in the store */
413 path = gtk_tree_row_reference_get_path (row_ref);
414 gtk_tree_model_get_iter (priv->model, &iter, path);
415 gtk_list_store_set (GTK_LIST_STORE (priv->model),
417 COL_REMAINING, remaining_str,
420 gtk_tree_path_free (path);
421 g_free (remaining_str);
425 ft_manager_clear_handler_time (EmpathyFTManager *manager,
426 GtkTreeRowReference *row_ref)
430 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
432 /* Set new value in the store */
433 path = gtk_tree_row_reference_get_path (row_ref);
434 gtk_tree_model_get_iter (priv->model, &iter, path);
435 gtk_list_store_set (GTK_LIST_STORE (priv->model),
440 gtk_tree_path_free (path);
444 ft_handler_transfer_error_cb (EmpathyFTHandler *handler,
446 EmpathyFTManager *manager)
449 GtkTreeRowReference *row_ref;
451 DEBUG ("Transfer error %s", error->message);
453 row_ref = ft_manager_get_row_from_handler (manager, handler);
454 g_return_if_fail (row_ref != NULL);
456 message = ft_manager_format_error_message (handler, error);
458 ft_manager_update_handler_message (manager, row_ref, message);
459 ft_manager_clear_handler_time (manager, row_ref);
460 ft_manager_update_buttons (manager);
466 do_real_transfer_done (EmpathyFTManager *manager,
467 EmpathyFTHandler *handler)
469 const char *contact_name;
470 const char *filename;
471 char *first_line, *second_line, *message;
474 GtkTreeRowReference *row_ref;
475 GtkRecentManager *recent_manager;
478 row_ref = ft_manager_get_row_from_handler (manager, handler);
479 g_return_if_fail (row_ref != NULL);
481 incoming = empathy_ft_handler_is_incoming (handler);
482 contact_name = empathy_contact_get_name
483 (empathy_ft_handler_get_contact (handler));
484 filename = empathy_ft_handler_get_filename (handler);
487 /* translators: first %s is filename, second %s
488 * is the contact name */
489 first_line = g_strdup_printf (_("\"%s\" received from %s"), filename,
492 /* translators: first %s is filename, second %s
493 * is the contact name */
494 first_line = g_strdup_printf (_("\"%s\" sent to %s"), filename,
497 second_line = g_strdup (_("File transfer completed"));
499 message = g_strdup_printf ("%s\n%s", first_line, second_line);
500 ft_manager_update_handler_message (manager, row_ref, message);
501 ft_manager_clear_handler_time (manager, row_ref);
504 ft_manager_update_buttons (manager);
508 g_free (second_line);
510 recent_manager = gtk_recent_manager_get_default ();
511 file = empathy_ft_handler_get_gfile (handler);
512 uri = g_file_get_uri (file);
514 gtk_recent_manager_add_item (recent_manager, uri);
520 ft_handler_transfer_done_cb (EmpathyFTHandler *handler,
521 EmpathyTpFile *tp_file,
522 EmpathyFTManager *manager)
524 if (empathy_ft_handler_is_incoming (handler) &&
525 empathy_ft_handler_get_use_hash (handler))
527 DEBUG ("Transfer done, waiting for hashing-started");
529 /* connect to the signal and return early */
530 g_signal_connect (handler, "hashing-started",
531 G_CALLBACK (ft_handler_hashing_started_cb), manager);
536 DEBUG ("Transfer done, no hashing");
538 do_real_transfer_done (manager, handler);
542 ft_handler_transfer_progress_cb (EmpathyFTHandler *handler,
543 guint64 current_bytes,
545 guint remaining_time,
547 EmpathyFTManager *manager)
549 char *first_line, *second_line, *message;
551 GtkTreeRowReference *row_ref;
553 DEBUG ("Transfer progress");
555 row_ref = ft_manager_get_row_from_handler (manager, handler);
556 g_return_if_fail (row_ref != NULL);
558 first_line = ft_manager_format_contact_info (handler);
559 second_line = ft_manager_format_progress_bytes_and_percentage
560 (current_bytes, total_bytes, speed, &percentage);
562 message = g_strdup_printf ("%s\n%s", first_line, second_line);
564 ft_manager_update_handler_message (manager, row_ref, message);
565 ft_manager_update_handler_progress (manager, row_ref, percentage);
567 if (remaining_time > 0)
568 ft_manager_update_handler_time (manager, row_ref, remaining_time);
572 g_free (second_line);
576 ft_handler_transfer_started_cb (EmpathyFTHandler *handler,
577 EmpathyTpFile *tp_file,
578 EmpathyFTManager *manager)
580 guint64 transferred_bytes, total_bytes;
582 DEBUG ("Transfer started");
584 g_signal_connect (handler, "transfer-progress",
585 G_CALLBACK (ft_handler_transfer_progress_cb), manager);
586 g_signal_connect (handler, "transfer-done",
587 G_CALLBACK (ft_handler_transfer_done_cb), manager);
589 transferred_bytes = empathy_ft_handler_get_transferred_bytes (handler);
590 total_bytes = empathy_ft_handler_get_total_bytes (handler);
592 ft_handler_transfer_progress_cb (handler, transferred_bytes, total_bytes,
597 ft_handler_hashing_done_cb (EmpathyFTHandler *handler,
598 EmpathyFTManager *manager)
600 GtkTreeRowReference *row_ref;
601 char *first_line, *second_line, *message;
603 DEBUG ("Hashing done");
605 /* update the message */
606 if (empathy_ft_handler_is_incoming (handler))
608 do_real_transfer_done (manager, handler);
612 row_ref = ft_manager_get_row_from_handler (manager, handler);
613 g_return_if_fail (row_ref != NULL);
615 first_line = ft_manager_format_contact_info (handler);
616 second_line = g_strdup (_("Waiting for the other participant's response"));
617 message = g_strdup_printf ("%s\n%s", first_line, second_line);
619 ft_manager_update_handler_message (manager, row_ref, message);
623 g_free (second_line);
625 g_signal_connect (handler, "transfer-started",
626 G_CALLBACK (ft_handler_transfer_started_cb), manager);
630 ft_handler_hashing_progress_cb (EmpathyFTHandler *handler,
631 guint64 current_bytes,
633 EmpathyFTManager *manager)
635 char *first_line, *second_line, *message;
636 GtkTreeRowReference *row_ref;
638 row_ref = ft_manager_get_row_from_handler (manager, handler);
639 g_return_if_fail (row_ref != NULL);
641 if (empathy_ft_handler_is_incoming (handler))
642 first_line = g_strdup_printf (_("Checking integrity of \"%s\""),
643 empathy_ft_handler_get_filename (handler));
645 first_line = g_strdup_printf (_("Hashing \"%s\""),
646 empathy_ft_handler_get_filename (handler));
648 second_line = ft_manager_format_progress_bytes_and_percentage
649 (current_bytes, total_bytes, -1, NULL);
651 message = g_strdup_printf ("%s\n%s", first_line, second_line);
653 ft_manager_update_handler_message (manager, row_ref, message);
657 g_free (second_line);
661 ft_handler_hashing_started_cb (EmpathyFTHandler *handler,
662 EmpathyFTManager *manager)
664 char *message, *first_line, *second_line;
665 GtkTreeRowReference *row_ref;
667 DEBUG ("Hashing started");
669 g_signal_connect (handler, "hashing-progress",
670 G_CALLBACK (ft_handler_hashing_progress_cb), manager);
671 g_signal_connect (handler, "hashing-done",
672 G_CALLBACK (ft_handler_hashing_done_cb), manager);
674 row_ref = ft_manager_get_row_from_handler (manager, handler);
675 g_return_if_fail (row_ref != NULL);
677 first_line = ft_manager_format_contact_info (handler);
679 if (empathy_ft_handler_is_incoming (handler))
680 second_line = g_strdup_printf (_("Checking integrity of \"%s\""),
681 empathy_ft_handler_get_filename (handler));
683 second_line = g_strdup_printf (_("Hashing \"%s\""),
684 empathy_ft_handler_get_filename (handler));
686 message = g_strdup_printf ("%s\n%s", first_line, second_line);
688 ft_manager_update_handler_message (manager, row_ref, message);
691 g_free (second_line);
696 ft_manager_start_transfer (EmpathyFTManager *manager,
697 EmpathyFTHandler *handler)
699 EmpathyFTManagerPriv *priv;
700 gboolean is_outgoing;
702 priv = GET_PRIV (manager);
704 is_outgoing = !empathy_ft_handler_is_incoming (handler);
706 DEBUG ("Start transfer, is outgoing %s",
707 is_outgoing ? "True" : "False");
709 /* now connect the signals */
710 g_signal_connect (handler, "transfer-error",
711 G_CALLBACK (ft_handler_transfer_error_cb), manager);
713 if (is_outgoing && empathy_ft_handler_get_use_hash (handler)) {
714 g_signal_connect (handler, "hashing-started",
715 G_CALLBACK (ft_handler_hashing_started_cb), manager);
717 /* either incoming or outgoing without hash */
718 g_signal_connect (handler, "transfer-started",
719 G_CALLBACK (ft_handler_transfer_started_cb), manager);
722 empathy_ft_handler_start_transfer (handler);
726 ft_manager_add_handler_to_list (EmpathyFTManager *manager,
727 EmpathyFTHandler *handler,
730 GtkTreeRowReference *row_ref;
732 GtkTreeSelection *selection;
735 const char *content_type, *second_line;
736 char *first_line, *message;
737 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
741 /* get the icon name from the mime-type of the file. */
742 content_type = empathy_ft_handler_get_content_type (handler);
744 if (content_type != NULL)
745 icon = g_content_type_get_icon (content_type);
747 /* append the handler in the store */
748 gtk_list_store_insert_with_values (GTK_LIST_STORE (priv->model),
749 &iter, G_MAXINT, COL_FT_OBJECT, handler,
753 g_object_unref (icon);
755 /* insert the new row_ref in the hash table */
756 path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->model), &iter);
757 row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->model), path);
758 gtk_tree_path_free (path);
759 g_hash_table_insert (priv->ft_handler_to_row_ref, g_object_ref (handler),
762 /* select the new row */
763 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
764 gtk_tree_selection_select_iter (selection, &iter);
768 message = ft_manager_format_error_message (handler, error);
769 ft_manager_update_handler_message (manager, row_ref, message);
775 /* update the row with the initial values.
776 * the only case where we postpone this is in case we're managing
777 * an outgoing+hashing transfer, as the hashing started signal will
778 * take care of updating the information.
780 if (empathy_ft_handler_is_incoming (handler) ||
781 !empathy_ft_handler_get_use_hash (handler)) {
782 first_line = ft_manager_format_contact_info (handler);
783 second_line = _("Waiting for the other participant's response");
784 message = g_strdup_printf ("%s\n%s", first_line, second_line);
786 ft_manager_update_handler_message (manager, row_ref, message);
792 /* hook up the signals and start the transfer */
793 ft_manager_start_transfer (manager, handler);
797 ft_manager_clear (EmpathyFTManager *manager)
799 EmpathyFTManagerPriv *priv;
801 DEBUG ("Clearing file transfer list");
803 priv = GET_PRIV (manager);
805 /* Remove completed and cancelled transfers */
806 g_hash_table_foreach_remove (priv->ft_handler_to_row_ref,
807 remove_finished_transfer_foreach, manager);
809 /* set the clear button back to insensitive */
810 gtk_widget_set_sensitive (priv->clear_button, FALSE);
814 ft_manager_open (EmpathyFTManager *manager)
816 GtkTreeSelection *selection;
819 EmpathyFTHandler *handler;
822 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
824 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
826 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
829 gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &handler, -1);
831 file = empathy_ft_handler_get_gfile (handler);
832 uri = g_file_get_uri (file);
834 DEBUG ("Opening URI: %s", uri);
835 empathy_url_show (GTK_WIDGET (priv->window), uri);
837 g_object_unref (handler);
842 ft_manager_stop (EmpathyFTManager *manager)
844 GtkTreeSelection *selection;
847 EmpathyFTHandler *handler;
848 EmpathyFTManagerPriv *priv;
850 priv = GET_PRIV (manager);
852 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
854 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
857 gtk_tree_model_get (model, &iter, COL_FT_OBJECT, &handler, -1);
858 g_return_if_fail (handler != NULL);
860 DEBUG ("Stopping file transfer: contact=%s, filename=%s",
861 empathy_contact_get_name (empathy_ft_handler_get_contact (handler)),
862 empathy_ft_handler_get_filename (handler));
864 empathy_ft_handler_cancel_transfer (handler);
866 g_object_unref (handler);
870 ft_manager_response_cb (GtkWidget *widget,
872 EmpathyFTManager *manager)
877 ft_manager_clear (manager);
880 ft_manager_open (manager);
883 ft_manager_stop (manager);
889 ft_manager_delete_event_cb (GtkWidget *widget,
891 EmpathyFTManager *manager)
893 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
895 DEBUG ("%p", manager);
897 /* remove all the completed/cancelled/errored transfers */
898 ft_manager_clear (manager);
900 if (g_hash_table_size (priv->ft_handler_to_row_ref) > 0)
902 /* There is still FTs on flight, just hide the window */
903 DEBUG ("Hiding window");
904 gtk_widget_hide (widget);
912 ft_manager_destroy_cb (GtkWidget *widget,
913 EmpathyFTManager *manager)
915 DEBUG ("%p", manager);
917 g_object_unref (manager);
921 ft_manager_key_press_event_cb (GtkWidget *widget,
925 if ((event->state & GDK_CONTROL_MASK && event->keyval == GDK_w)
926 || event->keyval == GDK_Escape)
928 gtk_widget_destroy (widget);
936 ft_manager_build_ui (EmpathyFTManager *manager)
940 GtkListStore *liststore;
941 GtkTreeViewColumn *column;
942 GtkCellRenderer *renderer;
943 GtkTreeSelection *selection;
945 EmpathyFTManagerPriv *priv = GET_PRIV (manager);
947 filename = empathy_file_lookup ("empathy-ft-manager.ui", "src");
948 gui = empathy_builder_get_file (filename,
949 "ft_manager_dialog", &priv->window,
950 "ft_list", &priv->treeview,
951 "clear_button", &priv->clear_button,
952 "open_button", &priv->open_button,
953 "abort_button", &priv->abort_button,
957 empathy_builder_connect (gui, manager,
958 "ft_manager_dialog", "destroy", ft_manager_destroy_cb,
959 "ft_manager_dialog", "response", ft_manager_response_cb,
960 "ft_manager_dialog", "delete-event", ft_manager_delete_event_cb,
961 "ft_manager_dialog", "key-press-event", ft_manager_key_press_event_cb,
964 empathy_builder_unref_and_keep_widget (gui, priv->window);
966 /* Window geometry. */
967 empathy_geometry_bind (GTK_WINDOW (priv->window), "ft-manager");
969 /* Setup the tree view */
970 view = GTK_TREE_VIEW (priv->treeview);
971 selection = gtk_tree_view_get_selection (view);
972 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
973 g_signal_connect (selection, "changed",
974 G_CALLBACK (ft_manager_selection_changed), manager);
975 gtk_tree_view_set_headers_visible (view, TRUE);
976 gtk_tree_view_set_enable_search (view, FALSE);
978 /* Setup the model */
979 liststore = gtk_list_store_new (5,
980 G_TYPE_INT, /* percent */
981 G_TYPE_ICON, /* icon */
982 G_TYPE_STRING, /* message */
983 G_TYPE_STRING, /* remaining */
984 G_TYPE_OBJECT); /* ft_handler */
985 gtk_tree_view_set_model (view, GTK_TREE_MODEL (liststore));
986 priv->model = GTK_TREE_MODEL (liststore);
987 g_object_unref (liststore);
989 /* Progress column */
990 column = gtk_tree_view_column_new ();
991 gtk_tree_view_column_set_title (column, _("%"));
992 gtk_tree_view_column_set_sort_column_id (column, COL_PERCENT);
993 gtk_tree_view_insert_column (view, column, -1);
995 renderer = gtk_cell_renderer_progress_new ();
996 g_object_set (renderer, "xalign", 0.5, NULL);
997 gtk_tree_view_column_pack_start (column, renderer, FALSE);
998 gtk_tree_view_column_set_cell_data_func (column, renderer,
999 ft_manager_progress_cell_data_func, NULL, NULL);
1001 /* Icon and filename column*/
1002 column = gtk_tree_view_column_new ();
1003 gtk_tree_view_column_set_title (column, _("File"));
1004 gtk_tree_view_column_set_expand (column, TRUE);
1005 gtk_tree_view_column_set_resizable (column, TRUE);
1006 gtk_tree_view_column_set_sort_column_id (column, COL_MESSAGE);
1007 gtk_tree_view_column_set_spacing (column, 3);
1008 gtk_tree_view_insert_column (view, column, -1);
1010 renderer = gtk_cell_renderer_pixbuf_new ();
1011 g_object_set (renderer, "xpad", 3,
1012 "stock-size", GTK_ICON_SIZE_DND, NULL);
1013 gtk_tree_view_column_pack_start (column, renderer, FALSE);
1014 gtk_tree_view_column_set_attributes (column, renderer,
1015 "gicon", COL_ICON, NULL);
1017 renderer = gtk_cell_renderer_text_new ();
1018 g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1019 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1020 gtk_tree_view_column_set_attributes (column, renderer,
1021 "text", COL_MESSAGE, NULL);
1023 /* Remaining time column */
1024 column = gtk_tree_view_column_new ();
1025 gtk_tree_view_column_set_title (column, _("Remaining"));
1026 gtk_tree_view_column_set_sort_column_id (column, COL_REMAINING);
1027 gtk_tree_view_insert_column (view, column, -1);
1029 renderer = gtk_cell_renderer_text_new ();
1030 g_object_set (renderer, "xalign", 0.5, NULL);
1031 gtk_tree_view_column_pack_start (column, renderer, FALSE);
1032 gtk_tree_view_column_set_attributes (column, renderer,
1033 "text", COL_REMAINING, NULL);
1035 /* clear button should be sensitive only if there are completed/cancelled
1036 * handlers in the store.
1038 gtk_widget_set_sensitive (priv->clear_button, FALSE);
1041 /* GObject method overrides */
1044 empathy_ft_manager_finalize (GObject *object)
1046 EmpathyFTManagerPriv *priv = GET_PRIV (object);
1048 DEBUG ("FT Manager %p", object);
1050 g_hash_table_destroy (priv->ft_handler_to_row_ref);
1052 G_OBJECT_CLASS (empathy_ft_manager_parent_class)->finalize (object);
1056 empathy_ft_manager_init (EmpathyFTManager *manager)
1058 EmpathyFTManagerPriv *priv;
1060 priv = G_TYPE_INSTANCE_GET_PRIVATE ((manager), EMPATHY_TYPE_FT_MANAGER,
1061 EmpathyFTManagerPriv);
1063 manager->priv = priv;
1065 priv->ft_handler_to_row_ref = g_hash_table_new_full (g_direct_hash,
1066 g_direct_equal, (GDestroyNotify) g_object_unref,
1067 (GDestroyNotify) gtk_tree_row_reference_free);
1069 ft_manager_build_ui (manager);
1073 empathy_ft_manager_constructor (GType type,
1075 GObjectConstructParam *props)
1079 if (manager_singleton)
1081 retval = G_OBJECT (manager_singleton);
1085 retval = G_OBJECT_CLASS (empathy_ft_manager_parent_class)->constructor
1086 (type, n_props, props);
1088 manager_singleton = EMPATHY_FT_MANAGER (retval);
1089 g_object_add_weak_pointer (retval, (gpointer) &manager_singleton);
1096 empathy_ft_manager_class_init (EmpathyFTManagerClass *klass)
1098 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1100 object_class->finalize = empathy_ft_manager_finalize;
1101 object_class->constructor = empathy_ft_manager_constructor;
1103 g_type_class_add_private (object_class, sizeof (EmpathyFTManagerPriv));
1106 /* public methods */
1109 empathy_ft_manager_add_handler (EmpathyFTHandler *handler)
1111 EmpathyFTManager *manager;
1112 EmpathyFTManagerPriv *priv;
1114 DEBUG ("Adding handler");
1116 g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler));
1118 manager = g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL);
1119 priv = GET_PRIV (manager);
1121 ft_manager_add_handler_to_list (manager, handler, NULL);
1122 gtk_window_present (GTK_WINDOW (priv->window));
1126 empathy_ft_manager_display_error (EmpathyFTHandler *handler,
1127 const GError *error)
1129 EmpathyFTManager *manager;
1130 EmpathyFTManagerPriv *priv;
1132 g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler));
1133 g_return_if_fail (error != NULL);
1135 manager = g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL);
1136 priv = GET_PRIV (manager);
1138 ft_manager_add_handler_to_list (manager, handler, error);
1139 gtk_window_present (GTK_WINDOW (priv->window));
1143 empathy_ft_manager_show (void)
1145 EmpathyFTManager *manager;
1146 EmpathyFTManagerPriv *priv;
1148 manager = g_object_new (EMPATHY_TYPE_FT_MANAGER, NULL);
1149 priv = GET_PRIV (manager);
1151 gtk_window_present (GTK_WINDOW (priv->window));