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 */
31 #include "empathy-ft-manager.h"
33 #include <glib/gi18n.h>
34 #include <tp-account-widgets/tpaw-builder.h>
36 #include "empathy-geometry.h"
37 #include "empathy-ui-utils.h"
38 #include "empathy-utils.h"
40 #define DEBUG_FLAG EMPATHY_DEBUG_FT
41 #include "empathy-debug.h"
54 GHashTable
*ft_handler_to_row_ref
;
59 GtkWidget
*open_button
;
60 GtkWidget
*abort_button
;
61 GtkWidget
*clear_button
;
62 } EmpathyFTManagerPriv
;
72 G_DEFINE_TYPE (EmpathyFTManager
, empathy_ft_manager
, G_TYPE_OBJECT
);
74 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyFTManager)
76 static EmpathyFTManager
*manager_singleton
= NULL
;
78 static void ft_handler_hashing_started_cb (EmpathyFTHandler
*handler
,
79 EmpathyFTManager
*manager
);
82 ft_manager_format_interval (guint interval
)
84 gint hours
, mins
, secs
;
86 hours
= interval
/ 3600;
87 interval
-= hours
* 3600;
89 interval
-= mins
* 60;
93 /* Translators: time left, when it is more than one hour */
94 return g_strdup_printf (_("%u∶%02u.%02u"), hours
, mins
, secs
);
96 /* Translators: time left, when is is less than one hour */
97 return g_strdup_printf (_("%02u.%02u"), mins
, secs
);
101 ft_manager_update_buttons (EmpathyFTManager
*manager
)
103 GtkTreeSelection
*selection
;
106 EmpathyFTHandler
*handler
;
107 gboolean open_enabled
= FALSE
;
108 gboolean abort_enabled
= FALSE
;
109 gboolean clear_enabled
= FALSE
;
110 gboolean is_completed
, is_cancelled
;
111 GHashTableIter hash_iter
;
112 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
114 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
116 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
118 gtk_tree_model_get (model
, &iter
, COL_FT_OBJECT
, &handler
, -1);
120 is_completed
= empathy_ft_handler_is_completed (handler
);
121 is_cancelled
= empathy_ft_handler_is_cancelled (handler
);
123 /* I can open the file if the transfer is completed and was incoming */
124 open_enabled
= (is_completed
&& empathy_ft_handler_is_incoming (handler
));
126 /* I can abort if the transfer is not already finished */
127 abort_enabled
= (is_cancelled
== FALSE
&& is_completed
== FALSE
);
129 g_object_unref (handler
);
132 g_hash_table_iter_init (&hash_iter
, priv
->ft_handler_to_row_ref
);
134 while (g_hash_table_iter_next (&hash_iter
, (gpointer
*) &handler
, NULL
))
136 if (empathy_ft_handler_is_completed (handler
) ||
137 empathy_ft_handler_is_cancelled (handler
))
138 clear_enabled
= TRUE
;
144 gtk_widget_set_sensitive (priv
->open_button
, open_enabled
);
145 gtk_widget_set_sensitive (priv
->abort_button
, abort_enabled
);
148 gtk_widget_set_sensitive (priv
->clear_button
, TRUE
);
152 ft_manager_selection_changed (GtkTreeSelection
*selection
,
153 EmpathyFTManager
*manager
)
155 ft_manager_update_buttons (manager
);
159 ft_manager_progress_cell_data_func (GtkTreeViewColumn
*col
,
160 GtkCellRenderer
*renderer
,
165 const gchar
*text
= NULL
;
168 gtk_tree_model_get (model
, iter
, COL_PERCENT
, &percent
, -1);
173 text
= C_("file transfer percent", "Unknown");
176 g_object_set (renderer
, "text", text
, "value", percent
, NULL
);
179 static GtkTreeRowReference
*
180 ft_manager_get_row_from_handler (EmpathyFTManager
*manager
,
181 EmpathyFTHandler
*handler
)
183 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
185 return g_hash_table_lookup (priv
->ft_handler_to_row_ref
, handler
);
189 ft_manager_remove_file_from_model (EmpathyFTManager
*manager
,
190 EmpathyFTHandler
*handler
)
192 GtkTreeRowReference
*row_ref
;
193 GtkTreeSelection
*selection
;
194 GtkTreePath
*path
= NULL
;
196 gboolean update_selection
;
197 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
199 row_ref
= ft_manager_get_row_from_handler (manager
, handler
);
200 g_return_if_fail (row_ref
);
202 DEBUG ("Removing file transfer from window: contact=%s, filename=%s",
203 empathy_contact_get_alias (empathy_ft_handler_get_contact (handler
)),
204 empathy_ft_handler_get_filename (handler
));
206 /* Get the iter from the row_ref */
207 path
= gtk_tree_row_reference_get_path (row_ref
);
208 gtk_tree_model_get_iter (priv
->model
, &iter
, path
);
209 gtk_tree_path_free (path
);
211 /* We have to update the selection only if we are removing the selected row */
212 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
213 update_selection
= gtk_tree_selection_iter_is_selected (selection
, &iter
);
215 /* Remove tp_file's row. After that iter points to the next row */
216 if (!gtk_list_store_remove (GTK_LIST_STORE (priv
->model
), &iter
))
220 /* There is no next row, set iter to the last row */
221 n_row
= gtk_tree_model_iter_n_children (priv
->model
, NULL
);
223 gtk_tree_model_iter_nth_child (priv
->model
, &iter
, NULL
, n_row
- 1);
225 update_selection
= FALSE
;
228 if (update_selection
)
229 gtk_tree_selection_select_iter (selection
, &iter
);
233 remove_finished_transfer_foreach (gpointer key
,
237 EmpathyFTHandler
*handler
= key
;
238 EmpathyFTManager
*manager
= user_data
;
240 if (empathy_ft_handler_is_completed (handler
) ||
241 empathy_ft_handler_is_cancelled (handler
))
243 ft_manager_remove_file_from_model (manager
, handler
);
251 ft_manager_format_progress_bytes_and_percentage (guint64 current
,
256 char *total_str
, *current_str
, *retval
;
257 char *speed_str
= NULL
;
259 total_str
= g_format_size (total
);
260 current_str
= g_format_size (current
);
263 speed_str
= g_format_size ((goffset
) speed
);
266 /* translators: first %s is the currently processed size, second %s is
267 * the total file size */
268 g_strdup_printf (_("%s of %s at %s/s"), current_str
, total_str
, speed_str
) :
269 g_strdup_printf (_("%s of %s"), current_str
, total_str
);
272 g_free (current_str
);
275 if (percentage
!= NULL
)
278 *percentage
= current
* 100 / total
;
287 ft_manager_format_contact_info (EmpathyFTHandler
*handler
)
290 const char *filename
, *contact_name
, *first_line_format
;
293 incoming
= empathy_ft_handler_is_incoming (handler
);
294 contact_name
= empathy_contact_get_alias
295 (empathy_ft_handler_get_contact (handler
));
296 filename
= empathy_ft_handler_get_filename (handler
);
299 /* translators: first %s is filename, second %s is the contact name */
300 first_line_format
= _("Receiving “%s” from %s");
302 /* translators: first %s is filename, second %s is the contact name */
303 first_line_format
= _("Sending “%s” to %s");
305 retval
= g_strdup_printf (first_line_format
, filename
, contact_name
);
311 ft_manager_format_error_message (EmpathyFTHandler
*handler
,
314 const char *contact_name
, *filename
;
315 EmpathyContact
*contact
;
316 char *first_line
, *message
;
320 incoming
= empathy_ft_handler_is_incoming (handler
);
322 contact
= empathy_ft_handler_get_contact (handler
);
324 contact_name
= empathy_contact_get_alias (contact
);
326 filename
= empathy_ft_handler_get_filename (handler
);
329 /* filename/contact_name here are either both NULL or both valid */
330 if (filename
&& contact_name
)
331 /* translators: first %s is filename, second %s
332 * is the contact name */
333 first_line
= g_strdup_printf (_("Error receiving “%s” from %s"), filename
,
336 first_line
= g_strdup (_("Error receiving a file"));
338 if (filename
&& contact_name
)
339 /* translators: first %s is filename, second %s
340 * is the contact name */
341 first_line
= g_strdup_printf (_("Error sending “%s” to %s"), filename
,
344 first_line
= g_strdup (_("Error sending a file"));
346 message
= g_strdup_printf ("%s\n%s", first_line
, error
->message
);
354 ft_manager_update_handler_message (EmpathyFTManager
*manager
,
355 GtkTreeRowReference
*row_ref
,
360 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
362 /* Set new value in the store */
363 path
= gtk_tree_row_reference_get_path (row_ref
);
364 gtk_tree_model_get_iter (priv
->model
, &iter
, path
);
365 gtk_list_store_set (GTK_LIST_STORE (priv
->model
),
367 COL_MESSAGE
, message
? message
: "",
370 gtk_tree_path_free (path
);
374 ft_manager_update_handler_progress (EmpathyFTManager
*manager
,
375 GtkTreeRowReference
*row_ref
,
380 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
382 /* Set new value in the store */
383 path
= gtk_tree_row_reference_get_path (row_ref
);
384 gtk_tree_model_get_iter (priv
->model
, &iter
, path
);
385 gtk_list_store_set (GTK_LIST_STORE (priv
->model
),
387 COL_PERCENT
, percentage
,
390 gtk_tree_path_free (path
);
395 ft_manager_update_handler_time (EmpathyFTManager
*manager
,
396 GtkTreeRowReference
*row_ref
,
397 guint remaining_time
)
401 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
404 remaining_str
= ft_manager_format_interval (remaining_time
);
406 /* Set new value in the store */
407 path
= gtk_tree_row_reference_get_path (row_ref
);
408 gtk_tree_model_get_iter (priv
->model
, &iter
, path
);
409 gtk_list_store_set (GTK_LIST_STORE (priv
->model
),
411 COL_REMAINING
, remaining_str
,
414 gtk_tree_path_free (path
);
415 g_free (remaining_str
);
419 ft_manager_clear_handler_time (EmpathyFTManager
*manager
,
420 GtkTreeRowReference
*row_ref
)
424 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
426 /* Set new value in the store */
427 path
= gtk_tree_row_reference_get_path (row_ref
);
428 gtk_tree_model_get_iter (priv
->model
, &iter
, path
);
429 gtk_list_store_set (GTK_LIST_STORE (priv
->model
),
434 gtk_tree_path_free (path
);
438 ft_handler_transfer_error_cb (EmpathyFTHandler
*handler
,
440 EmpathyFTManager
*manager
)
443 GtkTreeRowReference
*row_ref
;
445 DEBUG ("Transfer error %s", error
->message
);
447 row_ref
= ft_manager_get_row_from_handler (manager
, handler
);
448 g_return_if_fail (row_ref
!= NULL
);
450 message
= ft_manager_format_error_message (handler
, error
);
452 ft_manager_update_handler_message (manager
, row_ref
, message
);
453 ft_manager_clear_handler_time (manager
, row_ref
);
454 ft_manager_update_buttons (manager
);
460 do_real_transfer_done (EmpathyFTManager
*manager
,
461 EmpathyFTHandler
*handler
)
463 const char *contact_name
;
464 const char *filename
;
465 char *first_line
, *second_line
, *message
;
468 GtkTreeRowReference
*row_ref
;
469 GtkRecentManager
*recent_manager
;
472 row_ref
= ft_manager_get_row_from_handler (manager
, handler
);
473 g_return_if_fail (row_ref
!= NULL
);
475 incoming
= empathy_ft_handler_is_incoming (handler
);
476 contact_name
= empathy_contact_get_alias
477 (empathy_ft_handler_get_contact (handler
));
478 filename
= empathy_ft_handler_get_filename (handler
);
481 /* translators: first %s is filename, second %s
482 * is the contact name */
483 first_line
= g_strdup_printf (_("“%s” received from %s"), filename
,
486 /* translators: first %s is filename, second %s
487 * is the contact name */
488 first_line
= g_strdup_printf (_("“%s” sent to %s"), filename
,
491 second_line
= g_strdup (_("File transfer completed"));
493 message
= g_strdup_printf ("%s\n%s", first_line
, second_line
);
494 ft_manager_update_handler_message (manager
, row_ref
, message
);
495 ft_manager_clear_handler_time (manager
, row_ref
);
498 ft_manager_update_buttons (manager
);
502 g_free (second_line
);
504 recent_manager
= gtk_recent_manager_get_default ();
505 file
= empathy_ft_handler_get_gfile (handler
);
506 uri
= g_file_get_uri (file
);
508 gtk_recent_manager_add_item (recent_manager
, uri
);
514 ft_handler_transfer_done_cb (EmpathyFTHandler
*handler
,
515 TpFileTransferChannel
*channel
,
516 EmpathyFTManager
*manager
)
518 if (empathy_ft_handler_is_incoming (handler
) &&
519 empathy_ft_handler_get_use_hash (handler
))
521 DEBUG ("Transfer done, waiting for hashing-started");
523 /* connect to the signal and return early */
524 g_signal_connect (handler
, "hashing-started",
525 G_CALLBACK (ft_handler_hashing_started_cb
), manager
);
530 DEBUG ("Transfer done, no hashing");
532 do_real_transfer_done (manager
, handler
);
536 ft_handler_transfer_progress_cb (EmpathyFTHandler
*handler
,
537 guint64 current_bytes
,
539 guint remaining_time
,
541 EmpathyFTManager
*manager
)
543 char *first_line
, *second_line
, *message
;
545 GtkTreeRowReference
*row_ref
;
547 DEBUG ("Transfer progress");
549 row_ref
= ft_manager_get_row_from_handler (manager
, handler
);
550 g_return_if_fail (row_ref
!= NULL
);
552 first_line
= ft_manager_format_contact_info (handler
);
553 second_line
= ft_manager_format_progress_bytes_and_percentage
554 (current_bytes
, total_bytes
, speed
, &percentage
);
556 message
= g_strdup_printf ("%s\n%s", first_line
, second_line
);
558 ft_manager_update_handler_message (manager
, row_ref
, message
);
559 ft_manager_update_handler_progress (manager
, row_ref
, percentage
);
561 if (remaining_time
> 0)
562 ft_manager_update_handler_time (manager
, row_ref
, remaining_time
);
566 g_free (second_line
);
570 ft_handler_transfer_started_cb (EmpathyFTHandler
*handler
,
571 TpFileTransferChannel
*channel
,
572 EmpathyFTManager
*manager
)
574 guint64 transferred_bytes
, total_bytes
;
576 DEBUG ("Transfer started");
578 g_signal_connect (handler
, "transfer-progress",
579 G_CALLBACK (ft_handler_transfer_progress_cb
), manager
);
580 g_signal_connect (handler
, "transfer-done",
581 G_CALLBACK (ft_handler_transfer_done_cb
), manager
);
583 transferred_bytes
= empathy_ft_handler_get_transferred_bytes (handler
);
584 total_bytes
= empathy_ft_handler_get_total_bytes (handler
);
586 ft_handler_transfer_progress_cb (handler
, transferred_bytes
, total_bytes
,
591 ft_handler_hashing_done_cb (EmpathyFTHandler
*handler
,
592 EmpathyFTManager
*manager
)
594 GtkTreeRowReference
*row_ref
;
595 char *first_line
, *second_line
, *message
;
597 DEBUG ("Hashing done");
599 /* update the message */
600 if (empathy_ft_handler_is_incoming (handler
))
602 do_real_transfer_done (manager
, handler
);
606 row_ref
= ft_manager_get_row_from_handler (manager
, handler
);
607 g_return_if_fail (row_ref
!= NULL
);
609 first_line
= ft_manager_format_contact_info (handler
);
610 second_line
= g_strdup (_("Waiting for the other participant’s response"));
611 message
= g_strdup_printf ("%s\n%s", first_line
, second_line
);
613 ft_manager_update_handler_message (manager
, row_ref
, message
);
617 g_free (second_line
);
619 g_signal_connect (handler
, "transfer-started",
620 G_CALLBACK (ft_handler_transfer_started_cb
), manager
);
624 ft_handler_hashing_progress_cb (EmpathyFTHandler
*handler
,
625 guint64 current_bytes
,
627 EmpathyFTManager
*manager
)
629 char *first_line
, *second_line
, *message
;
630 GtkTreeRowReference
*row_ref
;
632 row_ref
= ft_manager_get_row_from_handler (manager
, handler
);
633 g_return_if_fail (row_ref
!= NULL
);
635 if (empathy_ft_handler_is_incoming (handler
))
636 first_line
= g_strdup_printf (_("Checking integrity of “%s”"),
637 empathy_ft_handler_get_filename (handler
));
639 first_line
= g_strdup_printf (_("Hashing “%s”"),
640 empathy_ft_handler_get_filename (handler
));
642 second_line
= ft_manager_format_progress_bytes_and_percentage
643 (current_bytes
, total_bytes
, -1, NULL
);
645 message
= g_strdup_printf ("%s\n%s", first_line
, second_line
);
647 ft_manager_update_handler_message (manager
, row_ref
, message
);
651 g_free (second_line
);
655 ft_handler_hashing_started_cb (EmpathyFTHandler
*handler
,
656 EmpathyFTManager
*manager
)
658 char *message
, *first_line
, *second_line
;
659 GtkTreeRowReference
*row_ref
;
661 DEBUG ("Hashing started");
663 g_signal_connect (handler
, "hashing-progress",
664 G_CALLBACK (ft_handler_hashing_progress_cb
), manager
);
665 g_signal_connect (handler
, "hashing-done",
666 G_CALLBACK (ft_handler_hashing_done_cb
), manager
);
668 row_ref
= ft_manager_get_row_from_handler (manager
, handler
);
669 g_return_if_fail (row_ref
!= NULL
);
671 first_line
= ft_manager_format_contact_info (handler
);
673 if (empathy_ft_handler_is_incoming (handler
))
674 second_line
= g_strdup_printf (_("Checking integrity of “%s”"),
675 empathy_ft_handler_get_filename (handler
));
677 second_line
= g_strdup_printf (_("Hashing “%s”"),
678 empathy_ft_handler_get_filename (handler
));
680 message
= g_strdup_printf ("%s\n%s", first_line
, second_line
);
682 ft_manager_update_handler_message (manager
, row_ref
, message
);
685 g_free (second_line
);
690 ft_manager_start_transfer (EmpathyFTManager
*manager
,
691 EmpathyFTHandler
*handler
)
693 gboolean is_outgoing
;
695 is_outgoing
= !empathy_ft_handler_is_incoming (handler
);
697 DEBUG ("Start transfer, is outgoing %s",
698 is_outgoing
? "True" : "False");
700 /* now connect the signals */
701 g_signal_connect (handler
, "transfer-error",
702 G_CALLBACK (ft_handler_transfer_error_cb
), manager
);
704 if (is_outgoing
&& empathy_ft_handler_get_use_hash (handler
)) {
705 g_signal_connect (handler
, "hashing-started",
706 G_CALLBACK (ft_handler_hashing_started_cb
), manager
);
708 /* either incoming or outgoing without hash */
709 g_signal_connect (handler
, "transfer-started",
710 G_CALLBACK (ft_handler_transfer_started_cb
), manager
);
713 empathy_ft_handler_start_transfer (handler
);
717 ft_manager_add_handler_to_list (EmpathyFTManager
*manager
,
718 EmpathyFTHandler
*handler
,
721 GtkTreeRowReference
*row_ref
;
723 GtkTreeSelection
*selection
;
726 const char *content_type
, *second_line
;
727 char *first_line
, *message
;
728 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
732 /* get the icon name from the mime-type of the file. */
733 content_type
= empathy_ft_handler_get_content_type (handler
);
735 if (content_type
!= NULL
)
736 icon
= g_content_type_get_icon (content_type
);
738 /* append the handler in the store */
739 gtk_list_store_insert_with_values (GTK_LIST_STORE (priv
->model
),
740 &iter
, G_MAXINT
, COL_FT_OBJECT
, handler
,
744 g_object_unref (icon
);
746 /* insert the new row_ref in the hash table */
747 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (priv
->model
), &iter
);
748 row_ref
= gtk_tree_row_reference_new (GTK_TREE_MODEL (priv
->model
), path
);
749 gtk_tree_path_free (path
);
750 g_hash_table_insert (priv
->ft_handler_to_row_ref
, g_object_ref (handler
),
753 /* select the new row */
754 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
755 gtk_tree_selection_select_iter (selection
, &iter
);
759 message
= ft_manager_format_error_message (handler
, error
);
760 ft_manager_update_handler_message (manager
, row_ref
, message
);
766 /* update the row with the initial values.
767 * the only case where we postpone this is in case we're managing
768 * an outgoing+hashing transfer, as the hashing started signal will
769 * take care of updating the information.
771 if (empathy_ft_handler_is_incoming (handler
) ||
772 !empathy_ft_handler_get_use_hash (handler
)) {
773 first_line
= ft_manager_format_contact_info (handler
);
774 second_line
= _("Waiting for the other participant’s response");
775 message
= g_strdup_printf ("%s\n%s", first_line
, second_line
);
777 ft_manager_update_handler_message (manager
, row_ref
, message
);
783 /* hook up the signals and start the transfer */
784 ft_manager_start_transfer (manager
, handler
);
788 ft_manager_clear (EmpathyFTManager
*manager
)
790 EmpathyFTManagerPriv
*priv
;
792 DEBUG ("Clearing file transfer list");
794 priv
= GET_PRIV (manager
);
796 /* Remove completed and cancelled transfers */
797 g_hash_table_foreach_remove (priv
->ft_handler_to_row_ref
,
798 remove_finished_transfer_foreach
, manager
);
800 /* set the clear button back to insensitive */
801 gtk_widget_set_sensitive (priv
->clear_button
, FALSE
);
805 ft_manager_open (EmpathyFTManager
*manager
)
807 GtkTreeSelection
*selection
;
810 EmpathyFTHandler
*handler
;
811 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
813 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
815 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
818 gtk_tree_model_get (model
, &iter
, COL_FT_OBJECT
, &handler
, -1);
820 if (empathy_ft_handler_is_completed (handler
)){
824 file
= empathy_ft_handler_get_gfile (handler
);
825 uri
= g_file_get_uri (file
);
827 DEBUG ("Opening URI: %s", uri
);
828 empathy_url_show (GTK_WIDGET (priv
->window
), uri
);
832 g_object_unref (handler
);
836 ft_manager_stop (EmpathyFTManager
*manager
)
838 GtkTreeSelection
*selection
;
841 EmpathyFTHandler
*handler
;
842 EmpathyFTManagerPriv
*priv
;
844 priv
= GET_PRIV (manager
);
846 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->treeview
));
848 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
851 gtk_tree_model_get (model
, &iter
, COL_FT_OBJECT
, &handler
, -1);
852 g_return_if_fail (handler
!= NULL
);
854 DEBUG ("Stopping file transfer: contact=%s, filename=%s",
855 empathy_contact_get_alias (empathy_ft_handler_get_contact (handler
)),
856 empathy_ft_handler_get_filename (handler
));
858 empathy_ft_handler_cancel_transfer (handler
);
860 g_object_unref (handler
);
864 close_window (EmpathyFTManager
*manager
)
866 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
868 DEBUG ("%p", manager
);
870 /* remove all the completed/cancelled/errored transfers */
871 ft_manager_clear (manager
);
873 if (g_hash_table_size (priv
->ft_handler_to_row_ref
) > 0)
875 /* There is still FTs on flight, just hide the window */
876 DEBUG ("Hiding window");
877 gtk_widget_hide (priv
->window
);
885 ft_manager_response_cb (GtkWidget
*widget
,
887 EmpathyFTManager
*manager
)
889 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
894 ft_manager_clear (manager
);
897 ft_manager_open (manager
);
900 ft_manager_stop (manager
);
903 if (!close_window (manager
))
904 gtk_widget_destroy (priv
->window
);
906 case GTK_RESPONSE_NONE
:
907 case GTK_RESPONSE_DELETE_EVENT
:
911 g_assert_not_reached ();
916 ft_manager_delete_event_cb (GtkWidget
*widget
,
918 EmpathyFTManager
*manager
)
920 return close_window (manager
);
924 ft_manager_destroy_cb (GtkWidget
*widget
,
925 EmpathyFTManager
*manager
)
927 DEBUG ("%p", manager
);
929 g_object_unref (manager
);
933 ft_view_button_press_event_cb (GtkWidget
*widget
,
935 EmpathyFTManager
*manager
)
938 if (event
->type
!= GDK_2BUTTON_PRESS
)
941 ft_manager_open (manager
);
947 ft_manager_key_press_event_cb (GtkWidget
*widget
,
951 if ((event
->state
& GDK_CONTROL_MASK
&& event
->keyval
== GDK_KEY_w
)
952 || event
->keyval
== GDK_KEY_Escape
)
954 gtk_widget_destroy (widget
);
962 ft_manager_build_ui (EmpathyFTManager
*manager
)
966 GtkListStore
*liststore
;
967 GtkTreeViewColumn
*column
;
968 GtkCellRenderer
*renderer
;
969 GtkTreeSelection
*selection
;
971 EmpathyFTManagerPriv
*priv
= GET_PRIV (manager
);
973 filename
= empathy_file_lookup ("empathy-ft-manager.ui", "src");
974 gui
= tpaw_builder_get_file (filename
,
975 "ft_manager_dialog", &priv
->window
,
976 "ft_list", &priv
->treeview
,
977 "clear_button", &priv
->clear_button
,
978 "open_button", &priv
->open_button
,
979 "abort_button", &priv
->abort_button
,
983 tpaw_builder_connect (gui
, manager
,
984 "ft_manager_dialog", "destroy", ft_manager_destroy_cb
,
985 "ft_manager_dialog", "response", ft_manager_response_cb
,
986 "ft_manager_dialog", "delete-event", ft_manager_delete_event_cb
,
987 "ft_manager_dialog", "key-press-event", ft_manager_key_press_event_cb
,
990 tpaw_builder_unref_and_keep_widget (gui
, priv
->window
);
992 /* Window geometry. */
993 empathy_geometry_bind (GTK_WINDOW (priv
->window
), "ft-manager");
995 /* Setup the tree view */
996 view
= GTK_TREE_VIEW (priv
->treeview
);
997 selection
= gtk_tree_view_get_selection (view
);
998 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_BROWSE
);
999 g_signal_connect (selection
, "changed",
1000 G_CALLBACK (ft_manager_selection_changed
), manager
);
1001 g_signal_connect (view
, "button-press-event",
1002 G_CALLBACK (ft_view_button_press_event_cb
),
1004 gtk_tree_view_set_headers_visible (view
, TRUE
);
1005 gtk_tree_view_set_enable_search (view
, FALSE
);
1007 /* Setup the model */
1008 liststore
= gtk_list_store_new (5,
1009 G_TYPE_INT
, /* percent */
1010 G_TYPE_ICON
, /* icon */
1011 G_TYPE_STRING
, /* message */
1012 G_TYPE_STRING
, /* remaining */
1013 G_TYPE_OBJECT
); /* ft_handler */
1014 gtk_tree_view_set_model (view
, GTK_TREE_MODEL (liststore
));
1015 priv
->model
= GTK_TREE_MODEL (liststore
);
1016 g_object_unref (liststore
);
1018 /* Progress column */
1019 column
= gtk_tree_view_column_new ();
1020 gtk_tree_view_column_set_title (column
, _("%"));
1021 gtk_tree_view_column_set_sort_column_id (column
, COL_PERCENT
);
1022 gtk_tree_view_insert_column (view
, column
, -1);
1024 renderer
= gtk_cell_renderer_progress_new ();
1025 g_object_set (renderer
, "xalign", 0.5, NULL
);
1026 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1027 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
1028 ft_manager_progress_cell_data_func
, NULL
, NULL
);
1030 /* Icon and filename column*/
1031 column
= gtk_tree_view_column_new ();
1032 gtk_tree_view_column_set_title (column
, _("File"));
1033 gtk_tree_view_column_set_expand (column
, TRUE
);
1034 gtk_tree_view_column_set_resizable (column
, TRUE
);
1035 gtk_tree_view_column_set_sort_column_id (column
, COL_MESSAGE
);
1036 gtk_tree_view_column_set_spacing (column
, 3);
1037 gtk_tree_view_insert_column (view
, column
, -1);
1039 renderer
= gtk_cell_renderer_pixbuf_new ();
1040 g_object_set (renderer
, "xpad", 3,
1041 "stock-size", GTK_ICON_SIZE_DND
, NULL
);
1042 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1043 gtk_tree_view_column_set_attributes (column
, renderer
,
1044 "gicon", COL_ICON
, NULL
);
1046 renderer
= gtk_cell_renderer_text_new ();
1047 g_object_set (renderer
, "ellipsize", PANGO_ELLIPSIZE_END
, NULL
);
1048 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
1049 gtk_tree_view_column_set_attributes (column
, renderer
,
1050 "text", COL_MESSAGE
, NULL
);
1052 /* Remaining time column */
1053 column
= gtk_tree_view_column_new ();
1054 gtk_tree_view_column_set_title (column
, _("Remaining"));
1055 gtk_tree_view_column_set_sort_column_id (column
, COL_REMAINING
);
1056 gtk_tree_view_insert_column (view
, column
, -1);
1058 renderer
= gtk_cell_renderer_text_new ();
1059 g_object_set (renderer
, "xalign", 0.5, NULL
);
1060 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1061 gtk_tree_view_column_set_attributes (column
, renderer
,
1062 "text", COL_REMAINING
, NULL
);
1064 /* clear button should be sensitive only if there are completed/cancelled
1065 * handlers in the store.
1067 gtk_widget_set_sensitive (priv
->clear_button
, FALSE
);
1070 /* GObject method overrides */
1073 empathy_ft_manager_finalize (GObject
*object
)
1075 EmpathyFTManagerPriv
*priv
= GET_PRIV (object
);
1077 DEBUG ("FT Manager %p", object
);
1079 g_hash_table_unref (priv
->ft_handler_to_row_ref
);
1081 G_OBJECT_CLASS (empathy_ft_manager_parent_class
)->finalize (object
);
1085 empathy_ft_manager_init (EmpathyFTManager
*manager
)
1087 EmpathyFTManagerPriv
*priv
;
1089 priv
= G_TYPE_INSTANCE_GET_PRIVATE ((manager
), EMPATHY_TYPE_FT_MANAGER
,
1090 EmpathyFTManagerPriv
);
1092 manager
->priv
= priv
;
1094 priv
->ft_handler_to_row_ref
= g_hash_table_new_full (g_direct_hash
,
1095 g_direct_equal
, (GDestroyNotify
) g_object_unref
,
1096 (GDestroyNotify
) gtk_tree_row_reference_free
);
1098 ft_manager_build_ui (manager
);
1102 empathy_ft_manager_constructor (GType type
,
1104 GObjectConstructParam
*props
)
1108 if (manager_singleton
)
1110 retval
= G_OBJECT (manager_singleton
);
1114 retval
= G_OBJECT_CLASS (empathy_ft_manager_parent_class
)->constructor
1115 (type
, n_props
, props
);
1117 manager_singleton
= EMPATHY_FT_MANAGER (retval
);
1118 g_object_add_weak_pointer (retval
, (gpointer
) &manager_singleton
);
1125 empathy_ft_manager_class_init (EmpathyFTManagerClass
*klass
)
1127 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
1129 object_class
->finalize
= empathy_ft_manager_finalize
;
1130 object_class
->constructor
= empathy_ft_manager_constructor
;
1132 g_type_class_add_private (object_class
, sizeof (EmpathyFTManagerPriv
));
1135 /* public methods */
1138 empathy_ft_manager_add_handler (EmpathyFTHandler
*handler
)
1140 EmpathyFTManager
*manager
;
1141 EmpathyFTManagerPriv
*priv
;
1143 DEBUG ("Adding handler");
1145 g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler
));
1147 manager
= g_object_new (EMPATHY_TYPE_FT_MANAGER
, NULL
);
1148 priv
= GET_PRIV (manager
);
1150 ft_manager_add_handler_to_list (manager
, handler
, NULL
);
1151 gtk_window_present (GTK_WINDOW (priv
->window
));
1155 empathy_ft_manager_display_error (EmpathyFTHandler
*handler
,
1156 const GError
*error
)
1158 EmpathyFTManager
*manager
;
1159 EmpathyFTManagerPriv
*priv
;
1161 g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler
));
1162 g_return_if_fail (error
!= NULL
);
1164 manager
= g_object_new (EMPATHY_TYPE_FT_MANAGER
, NULL
);
1165 priv
= GET_PRIV (manager
);
1167 ft_manager_add_handler_to_list (manager
, handler
, error
);
1168 gtk_window_present (GTK_WINDOW (priv
->window
));
1172 empathy_ft_manager_show (void)
1174 EmpathyFTManager
*manager
;
1175 EmpathyFTManagerPriv
*priv
;
1177 manager
= g_object_new (EMPATHY_TYPE_FT_MANAGER
, NULL
);
1178 priv
= GET_PRIV (manager
);
1180 gtk_window_present (GTK_WINDOW (priv
->window
));