1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2008-2010 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Authors: Xavier Claessens <xclaesse@gmail.com>
20 * Travis Reitter <travis.reitter@collabora.co.uk>
27 #include <glib/gi18n-lib.h>
29 #include <telepathy-glib/util.h>
30 #include <telepathy-logger/log-manager.h>
31 #include <folks/folks.h>
32 #include <folks/folks-telepathy.h>
34 #include <libempathy/empathy-call-factory.h>
35 #include <libempathy/empathy-dispatcher.h>
36 #include <libempathy/empathy-contact-manager.h>
37 #include <libempathy/empathy-individual-manager.h>
38 #include <libempathy/empathy-chatroom-manager.h>
39 #include <libempathy/empathy-utils.h>
41 #include "empathy-individual-menu.h"
42 #include "empathy-images.h"
43 #include "empathy-log-window.h"
44 #include "empathy-contact-dialogs.h"
45 #include "empathy-individual-dialogs.h"
46 #include "empathy-individual-information-dialog.h"
47 #include "empathy-ui-utils.h"
48 #include "empathy-share-my-desktop.h"
49 #include "empathy-linking-dialog.h"
52 individual_menu_add_personas (GtkMenuShell *menu,
53 FolksIndividual *individual,
54 EmpathyIndividualFeatureFlags features)
58 guint persona_count = 0;
60 g_return_if_fail (GTK_IS_MENU (menu));
61 g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));
62 g_return_if_fail (empathy_folks_individual_contains_contact (individual));
64 personas = folks_individual_get_personas (individual);
66 /* Make sure we've got enough valid entries for these menu items to add
68 for (l = personas; l != NULL; l = l->next)
70 if (!TPF_IS_PERSONA (l->data))
76 /* return early if these entries would add nothing beyond the "quick" items */
77 if (persona_count <= 1)
80 /* add a separator before the list of personas */
81 item = gtk_separator_menu_item_new ();
82 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
83 gtk_widget_show (item);
85 personas = folks_individual_get_personas (individual);
86 for (l = personas; l != NULL; l = l->next)
89 GtkWidget *contact_item;
90 GtkWidget *contact_submenu;
91 TpContact *tp_contact;
92 EmpathyContact *contact;
93 TpfPersona *persona = l->data;
95 FolksPersonaStore *store;
99 if (!TPF_IS_PERSONA (persona))
102 tp_contact = tpf_persona_get_contact (persona);
103 contact = empathy_contact_dup_from_tp_contact (tp_contact);
105 store = folks_persona_get_store (FOLKS_PERSONA (persona));
106 account = folks_persona_store_get_display_name (store);
107 label = g_strdup_printf (_("%s (%s)"),
108 folks_persona_get_display_id (FOLKS_PERSONA (persona)), account);
110 contact_item = gtk_image_menu_item_new_with_label (label);
111 contact_submenu = gtk_menu_new ();
112 gtk_menu_item_set_submenu (GTK_MENU_ITEM (contact_item), contact_submenu);
113 image = gtk_image_new_from_icon_name (
114 empathy_icon_name_for_contact (contact), GTK_ICON_SIZE_MENU);
115 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (contact_item), image);
116 gtk_widget_show (image);
119 if (features & EMPATHY_INDIVIDUAL_FEATURE_CHAT)
121 action = empathy_individual_chat_menu_item_new (NULL, contact);
122 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
123 gtk_widget_show (action);
126 if (features & EMPATHY_INDIVIDUAL_FEATURE_CALL)
129 action = empathy_individual_audio_call_menu_item_new (NULL, contact);
130 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
131 gtk_widget_show (action);
134 action = empathy_individual_video_call_menu_item_new (NULL, contact);
135 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
136 gtk_widget_show (action);
140 if (features & EMPATHY_INDIVIDUAL_FEATURE_LOG)
142 action = empathy_individual_log_menu_item_new (NULL, contact);
143 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
144 gtk_widget_show (action);
148 action = empathy_individual_invite_menu_item_new (NULL, contact);
149 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
150 gtk_widget_show (action);
153 action = empathy_individual_file_transfer_menu_item_new (NULL, contact);
154 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
155 gtk_widget_show (action);
157 /* Share my desktop */
158 action = empathy_individual_share_my_desktop_menu_item_new (NULL,
160 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
161 gtk_widget_show (action);
163 gtk_menu_shell_append (GTK_MENU_SHELL (menu), contact_item);
164 gtk_widget_show (contact_item);
167 g_object_unref (contact);
172 empathy_individual_menu_new (FolksIndividual *individual,
173 EmpathyIndividualFeatureFlags features)
179 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
181 if (features == EMPATHY_INDIVIDUAL_FEATURE_NONE)
184 menu = gtk_menu_new ();
185 shell = GTK_MENU_SHELL (menu);
188 item = empathy_individual_add_menu_item_new (individual);
191 gtk_menu_shell_append (shell, item);
192 gtk_widget_show (item);
196 if (features & EMPATHY_INDIVIDUAL_FEATURE_CHAT)
198 item = empathy_individual_chat_menu_item_new (individual, NULL);
201 gtk_menu_shell_append (shell, item);
202 gtk_widget_show (item);
206 if (features & EMPATHY_INDIVIDUAL_FEATURE_CALL)
209 item = empathy_individual_audio_call_menu_item_new (individual, NULL);
210 gtk_menu_shell_append (shell, item);
211 gtk_widget_show (item);
214 item = empathy_individual_video_call_menu_item_new (individual, NULL);
215 gtk_menu_shell_append (shell, item);
216 gtk_widget_show (item);
220 if (features & EMPATHY_INDIVIDUAL_FEATURE_LOG)
222 item = empathy_individual_log_menu_item_new (individual);
223 gtk_menu_shell_append (shell, item);
224 gtk_widget_show (item);
228 item = empathy_individual_invite_menu_item_new (individual);
229 gtk_menu_shell_append (shell, item);
230 gtk_widget_show (item);
233 item = empathy_individual_file_transfer_menu_item_new (individual);
234 gtk_menu_shell_append (shell, item);
235 gtk_widget_show (item);
237 /* Share my desktop */
238 /* FIXME we should add the "Share my desktop" menu item if Vino is
239 a registered handler in MC5 */
240 item = empathy_individual_share_my_desktop_menu_item_new (individual);
241 gtk_menu_shell_append (shell, item);
242 gtk_widget_show (item);
244 /* Menu items to target specific contacts */
245 individual_menu_add_personas (GTK_MENU_SHELL (menu), individual, features);
248 if (features & (EMPATHY_INDIVIDUAL_FEATURE_EDIT |
249 EMPATHY_INDIVIDUAL_FEATURE_INFO |
250 EMPATHY_INDIVIDUAL_FEATURE_FAVOURITE |
251 EMPATHY_INDIVIDUAL_FEATURE_LINK))
253 item = gtk_separator_menu_item_new ();
254 gtk_menu_shell_append (shell, item);
255 gtk_widget_show (item);
259 if (features & EMPATHY_INDIVIDUAL_FEATURE_EDIT)
261 item = empathy_individual_edit_menu_item_new (individual);
262 gtk_menu_shell_append (shell, item);
263 gtk_widget_show (item);
267 if (features & EMPATHY_INDIVIDUAL_FEATURE_LINK)
269 item = empathy_individual_link_menu_item_new (individual);
270 gtk_menu_shell_append (shell, item);
271 gtk_widget_show (item);
275 if (features & EMPATHY_INDIVIDUAL_FEATURE_INFO)
277 item = empathy_individual_info_menu_item_new (individual);
278 gtk_menu_shell_append (shell, item);
279 gtk_widget_show (item);
282 /* Favorite checkbox */
283 if (features & EMPATHY_INDIVIDUAL_FEATURE_FAVOURITE)
285 item = empathy_individual_favourite_menu_item_new (individual);
286 gtk_menu_shell_append (shell, item);
287 gtk_widget_show (item);
294 empathy_individual_add_menu_item_activated (GtkMenuItem *item,
295 FolksIndividual *individual)
299 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item));
300 if (!gtk_widget_is_toplevel (toplevel) || !GTK_IS_WINDOW (toplevel))
303 empathy_new_individual_dialog_show_with_individual (GTK_WINDOW (toplevel),
308 empathy_individual_add_menu_item_new (FolksIndividual *individual)
312 EmpathyIndividualManager *manager = NULL;
313 EmpathyContact *contact = NULL;
314 TpConnection *connection;
316 gboolean found = FALSE;
317 EmpathyIndividualManagerFlags flags;
319 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
321 if (!empathy_individual_manager_initialized ())
327 manager = empathy_individual_manager_dup_singleton ();
328 contact = empathy_contact_dup_from_folks_individual (individual);
329 connection = empathy_contact_get_connection (contact);
331 flags = empathy_individual_manager_get_flags_for_connection (manager,
334 if (!(flags & EMPATHY_INDIVIDUAL_MANAGER_CAN_ADD))
340 members = empathy_individual_manager_get_members (
341 EMPATHY_INDIVIDUAL_MANAGER (manager));
343 for (l = members; l && !found; l = l->next)
345 if (!tp_strdiff (folks_individual_get_id (l->data),
346 folks_individual_get_id (individual)))
351 g_list_free (members);
359 item = gtk_image_menu_item_new_with_mnemonic (_("_Add Contactā¦"));
360 image = gtk_image_new_from_icon_name (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
361 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
363 g_signal_connect (item, "activate",
364 G_CALLBACK (empathy_individual_add_menu_item_activated),
368 tp_clear_object (&contact);
369 tp_clear_object (&manager);
374 typedef gboolean (*SensitivityPredicate) (EmpathyContact *contact);
376 /* Like menu_item_set_first_contact(), but always operates upon the given
379 menu_item_set_contact (GtkWidget *item,
380 EmpathyContact *contact,
381 GCallback activate_callback,
382 SensitivityPredicate sensitivity_predicate)
384 gboolean contact_valid = TRUE;
386 if (sensitivity_predicate != NULL)
388 contact_valid = sensitivity_predicate (contact);
389 gtk_widget_set_sensitive (item, sensitivity_predicate (contact));
392 g_signal_connect (item, "activate", G_CALLBACK (activate_callback),
395 return contact_valid;
399 * Set the given menu @item to call @activate_callback upon the first valid
400 * TpContact associated with @individual whenever @item is activated.
402 * @sensitivity_predicate is an optional function to determine whether the menu
403 * item should be insensitive (if the function returns @FALSE). Otherwise, the
404 * menu item's sensitivity will not change.
407 menu_item_set_first_contact (GtkWidget *item,
408 FolksIndividual *individual,
409 GCallback activate_callback,
410 SensitivityPredicate sensitivity_predicate)
414 personas = folks_individual_get_personas (individual);
415 for (l = personas; l != NULL; l = l->next)
417 TpContact *tp_contact;
418 EmpathyContact *contact;
419 TpfPersona *persona = l->data;
420 gboolean contact_valid = TRUE;
422 if (!TPF_IS_PERSONA (persona))
425 tp_contact = tpf_persona_get_contact (persona);
426 contact = empathy_contact_dup_from_tp_contact (tp_contact);
428 contact_valid = menu_item_set_contact (item, contact,
429 G_CALLBACK (activate_callback), sensitivity_predicate);
431 g_object_unref (contact);
433 /* stop after the first valid match */
442 empathy_individual_chat_menu_item_activated (GtkMenuItem *item,
443 EmpathyContact *contact)
445 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
447 empathy_dispatcher_chat_with_contact (contact, gtk_get_current_event_time ());
451 empathy_individual_chat_menu_item_new (FolksIndividual *individual,
452 EmpathyContact *contact)
457 g_return_val_if_fail ((FOLKS_IS_INDIVIDUAL (individual) &&
458 empathy_folks_individual_contains_contact (individual)) ||
459 EMPATHY_IS_CONTACT (contact),
462 item = gtk_image_menu_item_new_with_mnemonic (_("_Chat"));
463 image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_MESSAGE,
465 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
466 gtk_widget_show (image);
470 menu_item_set_contact (item, contact,
471 G_CALLBACK (empathy_individual_chat_menu_item_activated), NULL);
475 menu_item_set_first_contact (item, individual,
476 G_CALLBACK (empathy_individual_chat_menu_item_activated), NULL);
483 empathy_individual_audio_call_menu_item_activated (GtkMenuItem *item,
484 EmpathyContact *contact)
486 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
488 empathy_call_factory_new_call_with_streams (contact, TRUE, FALSE,
489 gtk_get_current_event_time (), NULL);
493 empathy_individual_audio_call_menu_item_new (FolksIndividual *individual,
494 EmpathyContact *contact)
499 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual) ||
500 EMPATHY_IS_CONTACT (contact),
503 item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Audio Call"));
504 image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VOIP, GTK_ICON_SIZE_MENU);
505 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
506 gtk_widget_show (image);
510 menu_item_set_contact (item, contact,
511 G_CALLBACK (empathy_individual_audio_call_menu_item_activated),
512 empathy_contact_can_voip_audio);
516 menu_item_set_first_contact (item, individual,
517 G_CALLBACK (empathy_individual_audio_call_menu_item_activated),
518 empathy_contact_can_voip_audio);
525 empathy_individual_video_call_menu_item_activated (GtkMenuItem *item,
526 EmpathyContact *contact)
528 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
530 empathy_call_factory_new_call_with_streams (contact, TRUE, TRUE,
531 gtk_get_current_event_time (), NULL);
535 empathy_individual_video_call_menu_item_new (FolksIndividual *individual,
536 EmpathyContact *contact)
541 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual) ||
542 EMPATHY_IS_CONTACT (contact),
545 item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Video Call"));
546 image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VIDEO_CALL,
548 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
549 gtk_widget_show (image);
553 menu_item_set_contact (item, contact,
554 G_CALLBACK (empathy_individual_video_call_menu_item_activated),
555 empathy_contact_can_voip_video);
559 menu_item_set_first_contact (item, individual,
560 G_CALLBACK (empathy_individual_video_call_menu_item_activated),
561 empathy_contact_can_voip_video);
568 individual_log_menu_item_activate_cb (FolksIndividual *individual)
570 EmpathyContact *contact;
572 contact = empathy_contact_dup_from_folks_individual (individual);
574 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
576 empathy_log_window_show (empathy_contact_get_account (contact),
577 empathy_contact_get_id (contact), FALSE, NULL);
579 g_object_unref (contact);
583 empathy_individual_log_menu_item_new (FolksIndividual *individual)
585 TplLogManager *manager;
589 EmpathyContact *contact;
591 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
593 contact = empathy_contact_dup_from_folks_individual (individual);
595 g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
597 manager = tpl_log_manager_dup_singleton ();
598 have_log = tpl_log_manager_exists (manager,
599 empathy_contact_get_account (contact), empathy_contact_get_id (contact),
601 g_object_unref (manager);
603 item = gtk_image_menu_item_new_with_mnemonic (_("_Previous Conversations"));
604 image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_LOG, GTK_ICON_SIZE_MENU);
605 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
606 gtk_widget_set_sensitive (item, have_log);
607 gtk_widget_show (image);
609 g_signal_connect_swapped (item, "activate",
610 G_CALLBACK (individual_log_menu_item_activate_cb), individual);
612 g_object_unref (contact);
618 empathy_individual_file_transfer_menu_item_activated (GtkMenuItem *item,
619 EmpathyContact *contact)
621 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
623 empathy_send_file_with_file_chooser (contact);
627 empathy_individual_file_transfer_menu_item_new (FolksIndividual *individual)
632 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
634 item = gtk_image_menu_item_new_with_mnemonic (_("Send File"));
635 image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_DOCUMENT_SEND,
637 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
638 gtk_widget_show (image);
640 menu_item_set_first_contact (item, individual,
641 G_CALLBACK (empathy_individual_file_transfer_menu_item_activated),
642 empathy_contact_can_send_files);
648 empathy_individual_share_my_desktop_menu_item_activated (GtkMenuItem *item,
649 EmpathyContact *contact)
651 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
653 empathy_share_my_desktop_share_with_contact (contact);
657 empathy_individual_share_my_desktop_menu_item_new (FolksIndividual *individual)
662 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
664 item = gtk_image_menu_item_new_with_mnemonic (_("Share My Desktop"));
665 image = gtk_image_new_from_icon_name (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU);
666 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
667 gtk_widget_show (image);
669 menu_item_set_first_contact (item, individual,
670 G_CALLBACK (empathy_individual_share_my_desktop_menu_item_activated),
671 empathy_contact_can_use_rfb_stream_tube);
677 favourite_menu_item_toggled_cb (GtkCheckMenuItem *item,
678 FolksIndividual *individual)
680 folks_favourite_set_is_favourite (FOLKS_FAVOURITE (individual),
681 gtk_check_menu_item_get_active (item));
685 empathy_individual_favourite_menu_item_new (FolksIndividual *individual)
689 item = gtk_check_menu_item_new_with_label (_("Favorite"));
691 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
692 folks_favourite_get_is_favourite (FOLKS_FAVOURITE (individual)));
694 g_signal_connect (item, "toggled",
695 G_CALLBACK (favourite_menu_item_toggled_cb), individual);
701 individual_info_menu_item_activate_cb (FolksIndividual *individual)
703 empathy_individual_information_dialog_show (individual, NULL);
707 empathy_individual_info_menu_item_new (FolksIndividual *individual)
712 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
713 g_return_val_if_fail (empathy_folks_individual_contains_contact (individual),
716 item = gtk_image_menu_item_new_with_mnemonic (_("Infor_mation"));
717 image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_CONTACT_INFORMATION,
719 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
720 gtk_widget_show (image);
722 g_signal_connect_swapped (item, "activate",
723 G_CALLBACK (individual_info_menu_item_activate_cb),
730 individual_edit_menu_item_activate_cb (FolksIndividual *individual)
732 EmpathyContact *contact;
734 contact = empathy_contact_dup_from_folks_individual (individual);
735 empathy_contact_edit_dialog_show (contact, NULL);
737 tp_clear_object (&contact);
741 empathy_individual_edit_menu_item_new (FolksIndividual *individual)
743 EmpathyIndividualManager *manager;
746 gboolean enable = FALSE;
747 EmpathyContact *contact;
749 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
751 contact = empathy_contact_dup_from_folks_individual (individual);
753 g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
755 if (empathy_individual_manager_initialized ())
757 TpConnection *connection;
758 EmpathyIndividualManagerFlags flags;
760 manager = empathy_individual_manager_dup_singleton ();
761 connection = empathy_contact_get_connection (contact);
762 flags = empathy_individual_manager_get_flags_for_connection (
763 manager, connection);
765 enable = (flags & EMPATHY_INDIVIDUAL_MANAGER_CAN_ALIAS ||
766 flags & EMPATHY_INDIVIDUAL_MANAGER_CAN_GROUP);
768 g_object_unref (manager);
771 item = gtk_image_menu_item_new_with_mnemonic (
772 C_("Edit individual (contextual menu)", "_Edit"));
773 image = gtk_image_new_from_icon_name (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
774 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
775 gtk_widget_show (image);
777 gtk_widget_set_sensitive (item, enable);
779 g_signal_connect_swapped (item, "activate",
780 G_CALLBACK (individual_edit_menu_item_activate_cb), individual);
782 g_object_unref (contact);
788 individual_link_menu_item_activate_cb (FolksIndividual *individual)
790 empathy_linking_dialog_show (individual, NULL);
794 empathy_individual_link_menu_item_new (FolksIndividual *individual)
797 /*GtkWidget *image;*/
799 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
801 item = gtk_image_menu_item_new_with_mnemonic (
802 C_("Link individual (contextual menu)", "_Linkā¦"));
804 /*image = gtk_image_new_from_icon_name (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
805 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
806 gtk_widget_show (image);*/
808 g_signal_connect_swapped (item, "activate",
809 G_CALLBACK (individual_link_menu_item_activate_cb), individual);
816 FolksIndividual *individual;
817 EmpathyChatroom *chatroom;
820 static RoomSubMenuData *
821 room_sub_menu_data_new (FolksIndividual *individual,
822 EmpathyChatroom *chatroom)
824 RoomSubMenuData *data;
826 data = g_slice_new (RoomSubMenuData);
827 data->individual = g_object_ref (individual);
828 data->chatroom = g_object_ref (chatroom);
833 room_sub_menu_data_free (RoomSubMenuData *data)
835 g_object_unref (data->individual);
836 g_object_unref (data->chatroom);
837 g_slice_free (RoomSubMenuData, data);
841 room_sub_menu_activate_cb (GtkWidget *item,
842 RoomSubMenuData *data)
845 EmpathyChatroomManager *mgr;
846 EmpathyContact *contact = NULL;
849 chat = empathy_chatroom_get_tp_chat (data->chatroom);
852 /* channel was invalidated. Ignoring */
856 mgr = empathy_chatroom_manager_dup_singleton (NULL);
858 /* find the first of this Individual's contacts who can join this room */
859 personas = folks_individual_get_personas (data->individual);
860 for (l = personas; l != NULL && contact == NULL; l = g_list_next (l))
862 TpfPersona *persona = l->data;
863 TpContact *tp_contact;
866 if (!TPF_IS_PERSONA (persona))
869 tp_contact = tpf_persona_get_contact (persona);
870 contact = empathy_contact_dup_from_tp_contact (tp_contact);
872 rooms = empathy_chatroom_manager_get_chatrooms (mgr,
873 empathy_contact_get_account (contact));
875 if (g_list_find (rooms, data->chatroom) == NULL)
876 tp_clear_object (&contact);
878 /* if contact != NULL here, we've found our match */
883 g_object_unref (mgr);
887 /* contact disappeared. Ignoring */
891 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
893 /* send invitation */
894 empathy_contact_list_add (EMPATHY_CONTACT_LIST (chat),
895 contact, _("Inviting you to this room"));
897 g_object_unref (contact);
901 create_room_sub_menu (FolksIndividual *individual,
902 EmpathyChatroom *chatroom)
905 RoomSubMenuData *data;
907 item = gtk_menu_item_new_with_label (empathy_chatroom_get_name (chatroom));
908 data = room_sub_menu_data_new (individual, chatroom);
909 g_signal_connect_data (item, "activate",
910 G_CALLBACK (room_sub_menu_activate_cb), data,
911 (GClosureNotify) room_sub_menu_data_free, 0);
917 empathy_individual_invite_menu_item_new (FolksIndividual *individual)
921 GtkWidget *room_item;
922 EmpathyChatroomManager *mgr;
927 GtkWidget *submenu = NULL;
928 /* map of chat room names to their objects; just a utility to remove
929 * duplicates and to make construction of the alphabetized list easier */
930 GHashTable *name_room_map;
932 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
934 name_room_map = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
937 item = gtk_image_menu_item_new_with_mnemonic (_("_Invite to Chat Room"));
938 image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_GROUP_MESSAGE,
940 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
942 mgr = empathy_chatroom_manager_dup_singleton (NULL);
944 /* collect the rooms from amongst all accounts for this Individual */
945 personas = folks_individual_get_personas (individual);
946 for (l = personas; l != NULL; l = g_list_next (l))
948 TpfPersona *persona = l->data;
950 TpContact *tp_contact;
951 EmpathyContact *contact;
953 if (!TPF_IS_PERSONA (persona))
956 tp_contact = tpf_persona_get_contact (persona);
957 contact = empathy_contact_dup_from_tp_contact (tp_contact);
959 rooms_cur = empathy_chatroom_manager_get_chatrooms (mgr,
960 empathy_contact_get_account (contact));
961 rooms = g_list_concat (rooms, rooms_cur);
963 g_object_unref (contact);
966 /* alphabetize the rooms */
967 for (l = rooms; l != NULL; l = g_list_next (l))
969 EmpathyChatroom *chatroom = l->data;
972 if (empathy_chatroom_get_tp_chat (chatroom) != NULL)
976 name = empathy_chatroom_get_name (chatroom);
977 existed = (g_hash_table_lookup (name_room_map, name) != NULL);
978 g_hash_table_insert (name_room_map, (gpointer) name,
979 g_object_ref (chatroom));
981 /* this will take care of duplicates in rooms */
984 names = g_list_insert_sorted (names, (gpointer) name,
985 (GCompareFunc) g_strcmp0);
990 for (l = names; l != NULL; l = g_list_next (l))
992 const gchar *name = l->data;
993 EmpathyChatroom *chatroom;
995 if (G_UNLIKELY (submenu == NULL))
996 submenu = gtk_menu_new ();
998 chatroom = g_hash_table_lookup (name_room_map, name);
999 room_item = create_room_sub_menu (individual, chatroom);
1000 gtk_menu_shell_append ((GtkMenuShell *) submenu, room_item);
1001 gtk_widget_show (room_item);
1005 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
1007 gtk_widget_set_sensitive (item, FALSE);
1009 gtk_widget_show (image);
1011 g_hash_table_destroy (name_room_map);
1012 g_object_unref (mgr);
1013 g_list_free (names);
1014 g_list_free (rooms);