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>
31 #include <folks/folks.h>
32 #include <folks/folks-telepathy.h>
34 #include <libempathy/empathy-request-util.h>
35 #include <libempathy/empathy-individual-manager.h>
36 #include <libempathy/empathy-chatroom-manager.h>
37 #include <libempathy/empathy-utils.h>
39 #include "empathy-individual-menu.h"
40 #include "empathy-images.h"
41 #include "empathy-log-window.h"
42 #include "empathy-contact-dialogs.h"
43 #include "empathy-gtk-enum-types.h"
44 #include "empathy-individual-edit-dialog.h"
45 #include "empathy-individual-information-dialog.h"
46 #include "empathy-ui-utils.h"
47 #include "empathy-share-my-desktop.h"
48 #include "empathy-linking-dialog.h"
49 #include "empathy-call-utils.h"
51 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndividualMenu)
54 FolksIndividual
*individual
; /* owned */
55 EmpathyIndividualFeatureFlags features
;
56 } EmpathyIndividualMenuPriv
;
64 SIGNAL_LINK_CONTACTS_ACTIVATED
,
68 static guint signals
[LAST_SIGNAL
];
70 G_DEFINE_TYPE (EmpathyIndividualMenu
, empathy_individual_menu
, GTK_TYPE_MENU
);
73 individual_menu_add_personas (GtkMenuShell
*menu
,
74 FolksIndividual
*individual
,
75 EmpathyIndividualFeatureFlags features
)
80 guint persona_count
= 0;
83 g_return_if_fail (GTK_IS_MENU (menu
));
84 g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual
));
85 g_return_if_fail (empathy_folks_individual_contains_contact (individual
));
87 personas
= folks_individual_get_personas (individual
);
88 /* we'll re-use this iterator throughout */
89 iter
= gee_iterable_iterator (GEE_ITERABLE (personas
));
91 /* Make sure we've got enough valid entries for these menu items to add
93 while (gee_iterator_next (iter
))
95 FolksPersona
*persona
= gee_iterator_get (iter
);
96 if (empathy_folks_persona_is_interesting (persona
))
99 g_clear_object (&persona
);
102 /* return early if these entries would add nothing beyond the "quick" items */
103 if (persona_count
<= 1)
106 /* add a separator before the list of personas */
107 item
= gtk_separator_menu_item_new ();
108 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), item
);
109 gtk_widget_show (item
);
111 personas
= folks_individual_get_personas (individual
);
112 for (c
= gee_iterator_first (iter
); c
; c
= gee_iterator_next (iter
))
115 GtkWidget
*contact_item
;
116 GtkWidget
*contact_submenu
;
117 TpContact
*tp_contact
;
118 EmpathyContact
*contact
;
119 TpfPersona
*persona
= gee_iterator_get (iter
);
121 FolksPersonaStore
*store
;
122 const gchar
*account
;
125 if (!empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona
)))
128 tp_contact
= tpf_persona_get_contact (persona
);
129 contact
= empathy_contact_dup_from_tp_contact (tp_contact
);
131 store
= folks_persona_get_store (FOLKS_PERSONA (persona
));
132 account
= folks_persona_store_get_display_name (store
);
134 /* Translators: this is used in the context menu for a contact. The first
135 * parameter is a contact ID (e.g. foo@jabber.org) and the second is one
136 * of the user's account IDs (e.g. me@hotmail.com). */
137 label
= g_strdup_printf (_("%s (%s)"),
138 folks_persona_get_display_id (FOLKS_PERSONA (persona
)), account
);
140 contact_item
= gtk_image_menu_item_new_with_label (label
);
141 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (contact_item
),
143 contact_submenu
= gtk_menu_new ();
144 gtk_menu_item_set_submenu (GTK_MENU_ITEM (contact_item
), contact_submenu
);
145 image
= gtk_image_new_from_icon_name (
146 empathy_icon_name_for_contact (contact
), GTK_ICON_SIZE_MENU
);
147 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (contact_item
), image
);
148 gtk_widget_show (image
);
151 if (features
& EMPATHY_INDIVIDUAL_FEATURE_CHAT
)
153 action
= empathy_individual_chat_menu_item_new (NULL
, contact
);
154 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
155 gtk_widget_show (action
);
159 if (features
& EMPATHY_INDIVIDUAL_FEATURE_SMS
)
161 action
= empathy_individual_sms_menu_item_new (NULL
, contact
);
162 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
163 gtk_widget_show (action
);
166 if (features
& EMPATHY_INDIVIDUAL_FEATURE_CALL
)
169 action
= empathy_individual_audio_call_menu_item_new (NULL
, contact
);
170 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
171 gtk_widget_show (action
);
174 action
= empathy_individual_video_call_menu_item_new (NULL
, contact
);
175 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
176 gtk_widget_show (action
);
180 if (features
& EMPATHY_INDIVIDUAL_FEATURE_LOG
)
182 action
= empathy_individual_log_menu_item_new (NULL
, contact
);
183 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
184 gtk_widget_show (action
);
188 action
= empathy_individual_invite_menu_item_new (NULL
, contact
);
189 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
190 gtk_widget_show (action
);
193 action
= empathy_individual_file_transfer_menu_item_new (NULL
, contact
);
194 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
195 gtk_widget_show (action
);
197 /* Share my desktop */
198 action
= empathy_individual_share_my_desktop_menu_item_new (NULL
,
200 gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu
), action
);
201 gtk_widget_show (action
);
203 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), contact_item
);
204 gtk_widget_show (contact_item
);
207 g_object_unref (contact
);
210 g_clear_object (&persona
);
213 g_clear_object (&iter
);
217 individual_link_menu_item_activate_cb (EmpathyIndividualMenu
*self
)
219 EmpathyIndividualMenuPriv
*priv
= GET_PRIV (self
);
222 dialog
= empathy_linking_dialog_show (priv
->individual
, NULL
);
223 g_signal_emit (self
, signals
[SIGNAL_LINK_CONTACTS_ACTIVATED
], 0, dialog
);
227 empathy_individual_menu_init (EmpathyIndividualMenu
*self
)
229 EmpathyIndividualMenuPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (self
,
230 EMPATHY_TYPE_INDIVIDUAL_MENU
, EmpathyIndividualMenuPriv
);
236 constructed (GObject
*object
)
238 EmpathyIndividualMenuPriv
*priv
= GET_PRIV (object
);
241 FolksIndividual
*individual
;
242 EmpathyIndividualFeatureFlags features
;
245 shell
= GTK_MENU_SHELL (object
);
246 individual
= priv
->individual
;
247 features
= priv
->features
;
250 if (features
& EMPATHY_INDIVIDUAL_FEATURE_CHAT
)
252 item
= empathy_individual_chat_menu_item_new (individual
, NULL
);
255 gtk_menu_shell_append (shell
, item
);
256 gtk_widget_show (item
);
261 if (features
& EMPATHY_INDIVIDUAL_FEATURE_SMS
)
263 item
= empathy_individual_sms_menu_item_new (individual
, NULL
);
266 gtk_menu_shell_append (shell
, item
);
267 gtk_widget_show (item
);
271 if (features
& EMPATHY_INDIVIDUAL_FEATURE_CALL
)
274 item
= empathy_individual_audio_call_menu_item_new (individual
, NULL
);
275 gtk_menu_shell_append (shell
, item
);
276 gtk_widget_show (item
);
279 item
= empathy_individual_video_call_menu_item_new (individual
, NULL
);
280 gtk_menu_shell_append (shell
, item
);
281 gtk_widget_show (item
);
285 if (features
& EMPATHY_INDIVIDUAL_FEATURE_LOG
)
287 item
= empathy_individual_log_menu_item_new (individual
, NULL
);
288 gtk_menu_shell_append (shell
, item
);
289 gtk_widget_show (item
);
293 item
= empathy_individual_invite_menu_item_new (individual
, NULL
);
294 gtk_menu_shell_append (shell
, item
);
295 gtk_widget_show (item
);
298 item
= empathy_individual_file_transfer_menu_item_new (individual
, NULL
);
299 gtk_menu_shell_append (shell
, item
);
300 gtk_widget_show (item
);
302 /* Share my desktop */
303 /* FIXME we should add the "Share my desktop" menu item if Vino is
304 a registered handler in MC5 */
305 item
= empathy_individual_share_my_desktop_menu_item_new (individual
, NULL
);
306 gtk_menu_shell_append (shell
, item
);
307 gtk_widget_show (item
);
309 /* Menu items to target specific contacts */
310 individual_menu_add_personas (GTK_MENU_SHELL (object
), individual
, features
);
313 if (features
& (EMPATHY_INDIVIDUAL_FEATURE_EDIT
|
314 EMPATHY_INDIVIDUAL_FEATURE_INFO
|
315 EMPATHY_INDIVIDUAL_FEATURE_FAVOURITE
|
316 EMPATHY_INDIVIDUAL_FEATURE_LINK
))
318 item
= gtk_separator_menu_item_new ();
319 gtk_menu_shell_append (shell
, item
);
320 gtk_widget_show (item
);
324 if (features
& EMPATHY_INDIVIDUAL_FEATURE_EDIT
)
326 item
= empathy_individual_edit_menu_item_new (individual
);
327 gtk_menu_shell_append (shell
, item
);
328 gtk_widget_show (item
);
332 if (features
& EMPATHY_INDIVIDUAL_FEATURE_LINK
)
334 item
= empathy_individual_link_menu_item_new (individual
);
335 gtk_menu_shell_append (shell
, item
);
337 g_signal_connect_swapped (item
, "activate",
338 (GCallback
) individual_link_menu_item_activate_cb
, object
);
340 gtk_widget_show (item
);
344 if (features
& EMPATHY_INDIVIDUAL_FEATURE_INFO
)
346 item
= empathy_individual_info_menu_item_new (individual
);
347 gtk_menu_shell_append (shell
, item
);
348 gtk_widget_show (item
);
351 /* Favorite checkbox */
352 if (features
& EMPATHY_INDIVIDUAL_FEATURE_FAVOURITE
)
354 item
= empathy_individual_favourite_menu_item_new (individual
);
355 gtk_menu_shell_append (shell
, item
);
356 gtk_widget_show (item
);
361 get_property (GObject
*object
,
366 EmpathyIndividualMenuPriv
*priv
;
368 priv
= GET_PRIV (object
);
372 case PROP_INDIVIDUAL
:
373 g_value_set_object (value
, priv
->individual
);
376 g_value_set_flags (value
, priv
->features
);
379 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
385 set_property (GObject
*object
,
390 EmpathyIndividualMenuPriv
*priv
;
392 priv
= GET_PRIV (object
);
396 case PROP_INDIVIDUAL
:
397 priv
->individual
= g_value_dup_object (value
);
400 priv
->features
= g_value_get_flags (value
);
403 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
409 dispose (GObject
*object
)
411 EmpathyIndividualMenuPriv
*priv
= GET_PRIV (object
);
413 tp_clear_object (&priv
->individual
);
415 G_OBJECT_CLASS (empathy_individual_menu_parent_class
)->dispose (object
);
419 empathy_individual_menu_class_init (EmpathyIndividualMenuClass
*klass
)
421 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
423 object_class
->constructed
= constructed
;
424 object_class
->get_property
= get_property
;
425 object_class
->set_property
= set_property
;
426 object_class
->dispose
= dispose
;
429 * EmpathyIndividualMenu:individual:
431 * The #FolksIndividual the menu is for.
433 g_object_class_install_property (object_class
, PROP_INDIVIDUAL
,
434 g_param_spec_object ("individual",
436 "The #FolksIndividual the menu is for.",
437 FOLKS_TYPE_INDIVIDUAL
,
438 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
));
441 * EmpathyIndividualMenu:features:
443 * A set of feature flags controlling which entries are shown.
445 g_object_class_install_property (object_class
, PROP_FEATURES
,
446 g_param_spec_flags ("features",
448 "A set of feature flags controlling which entries are shown.",
449 EMPATHY_TYPE_INDIVIDUAL_FEATURE_FLAGS
,
450 EMPATHY_INDIVIDUAL_FEATURE_NONE
,
451 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
));
453 signals
[SIGNAL_LINK_CONTACTS_ACTIVATED
] =
454 g_signal_new ("link-contacts-activated", G_OBJECT_CLASS_TYPE (klass
),
455 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
,
456 g_cclosure_marshal_VOID__OBJECT
,
457 G_TYPE_NONE
, 1, EMPATHY_TYPE_LINKING_DIALOG
);
459 g_type_class_add_private (object_class
, sizeof (EmpathyIndividualMenuPriv
));
463 empathy_individual_menu_new (FolksIndividual
*individual
,
464 EmpathyIndividualFeatureFlags features
)
466 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
), NULL
);
467 g_return_val_if_fail (features
!= EMPATHY_INDIVIDUAL_FEATURE_NONE
, NULL
);
469 return g_object_new (EMPATHY_TYPE_INDIVIDUAL_MENU
,
470 "individual", individual
,
471 "features", features
,
475 /* Like menu_item_set_first_contact(), but always operates upon the given
476 * contact. If the contact is non-NULL, it is assumed that the menu entry should
479 menu_item_set_contact (GtkWidget
*item
,
480 EmpathyContact
*contact
,
481 GCallback activate_callback
,
482 EmpathyActionType action_type
)
484 gboolean can_do_action
= FALSE
;
487 can_do_action
= empathy_contact_can_do_action (contact
, action_type
);
488 gtk_widget_set_sensitive (item
, can_do_action
);
490 if (can_do_action
== TRUE
)
492 /* We want to make sure that the EmpathyContact stays alive while the
493 * signal is connected. */
494 g_signal_connect_data (item
, "activate", G_CALLBACK (activate_callback
),
495 g_object_ref (contact
), (GClosureNotify
) g_object_unref
, 0);
498 return can_do_action
;
502 * Set the given menu @item to call @activate_callback using the TpContact
503 * (associated with @individual) with the highest availability who is also valid
504 * whenever @item is activated.
506 * @action_type is the type of action performed by the menu entry; this is used
507 * so that only contacts which can perform that action (e.g. are capable of
508 * receiving video calls) are selected, as appropriate.
511 menu_item_set_first_contact (GtkWidget
*item
,
512 FolksIndividual
*individual
,
513 GCallback activate_callback
,
514 EmpathyActionType action_type
)
516 EmpathyContact
*best_contact
;
518 best_contact
= empathy_contact_dup_best_for_action (individual
, action_type
);
519 menu_item_set_contact (item
, best_contact
, G_CALLBACK (activate_callback
),
521 tp_clear_object (&best_contact
);
527 empathy_individual_chat_menu_item_activated (GtkMenuItem
*item
,
528 EmpathyContact
*contact
)
530 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
532 empathy_chat_with_contact (contact
, empathy_get_current_action_time ());
536 empathy_individual_chat_menu_item_new (FolksIndividual
*individual
,
537 EmpathyContact
*contact
)
542 g_return_val_if_fail ((FOLKS_IS_INDIVIDUAL (individual
) &&
543 empathy_folks_individual_contains_contact (individual
)) ||
544 EMPATHY_IS_CONTACT (contact
),
547 item
= gtk_image_menu_item_new_with_mnemonic (_("_Chat"));
548 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_MESSAGE
,
550 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
551 gtk_widget_show (image
);
555 menu_item_set_contact (item
, contact
,
556 G_CALLBACK (empathy_individual_chat_menu_item_activated
),
557 EMPATHY_ACTION_CHAT
);
561 menu_item_set_first_contact (item
, individual
,
562 G_CALLBACK (empathy_individual_chat_menu_item_activated
),
563 EMPATHY_ACTION_CHAT
);
570 empathy_individual_sms_menu_item_activated (GtkMenuItem
*item
,
571 EmpathyContact
*contact
)
573 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
575 empathy_sms_contact_id (
576 empathy_contact_get_account (contact
),
577 empathy_contact_get_id (contact
),
578 empathy_get_current_action_time ());
582 empathy_individual_sms_menu_item_new (FolksIndividual
*individual
,
583 EmpathyContact
*contact
)
588 g_return_val_if_fail ((FOLKS_IS_INDIVIDUAL (individual
) &&
589 empathy_folks_individual_contains_contact (individual
)) ||
590 EMPATHY_IS_CONTACT (contact
),
593 item
= gtk_image_menu_item_new_with_mnemonic (_("_SMS"));
594 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_SMS
,
596 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
597 gtk_widget_show (image
);
601 menu_item_set_contact (item
, contact
,
602 G_CALLBACK (empathy_individual_sms_menu_item_activated
),
607 menu_item_set_first_contact (item
, individual
,
608 G_CALLBACK (empathy_individual_sms_menu_item_activated
),
616 empathy_individual_audio_call_menu_item_activated (GtkMenuItem
*item
,
617 EmpathyContact
*contact
)
619 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
621 empathy_call_new_with_streams (empathy_contact_get_id (contact
),
622 empathy_contact_get_account (contact
),
624 empathy_get_current_action_time ());
628 empathy_individual_audio_call_menu_item_new (FolksIndividual
*individual
,
629 EmpathyContact
*contact
)
634 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
) ||
635 EMPATHY_IS_CONTACT (contact
),
638 item
= gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Audio Call"));
639 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_VOIP
, GTK_ICON_SIZE_MENU
);
640 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
641 gtk_widget_show (image
);
645 menu_item_set_contact (item
, contact
,
646 G_CALLBACK (empathy_individual_audio_call_menu_item_activated
),
647 EMPATHY_ACTION_AUDIO_CALL
);
651 menu_item_set_first_contact (item
, individual
,
652 G_CALLBACK (empathy_individual_audio_call_menu_item_activated
),
653 EMPATHY_ACTION_AUDIO_CALL
);
660 empathy_individual_video_call_menu_item_activated (GtkMenuItem
*item
,
661 EmpathyContact
*contact
)
663 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
665 empathy_call_new_with_streams (empathy_contact_get_id (contact
),
666 empathy_contact_get_account (contact
),
668 empathy_get_current_action_time ());
672 empathy_individual_video_call_menu_item_new (FolksIndividual
*individual
,
673 EmpathyContact
*contact
)
678 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
) ||
679 EMPATHY_IS_CONTACT (contact
),
682 item
= gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Video Call"));
683 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_VIDEO_CALL
,
685 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
686 gtk_widget_show (image
);
690 menu_item_set_contact (item
, contact
,
691 G_CALLBACK (empathy_individual_video_call_menu_item_activated
),
692 EMPATHY_ACTION_VIDEO_CALL
);
696 menu_item_set_first_contact (item
, individual
,
697 G_CALLBACK (empathy_individual_video_call_menu_item_activated
),
698 EMPATHY_ACTION_VIDEO_CALL
);
705 empathy_individual_log_menu_item_activated (GtkMenuItem
*item
,
706 EmpathyContact
*contact
)
708 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
710 empathy_log_window_show (empathy_contact_get_account (contact
),
711 empathy_contact_get_id (contact
), FALSE
, NULL
);
715 empathy_individual_log_menu_item_new (FolksIndividual
*individual
,
716 EmpathyContact
*contact
)
721 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
) ||
722 EMPATHY_IS_CONTACT (contact
),
725 item
= gtk_image_menu_item_new_with_mnemonic (_("_Previous Conversations"));
726 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_LOG
, GTK_ICON_SIZE_MENU
);
727 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
728 gtk_widget_show (image
);
732 menu_item_set_contact (item
, contact
,
733 G_CALLBACK (empathy_individual_log_menu_item_activated
),
734 EMPATHY_ACTION_VIEW_LOGS
);
738 menu_item_set_first_contact (item
, individual
,
739 G_CALLBACK (empathy_individual_log_menu_item_activated
),
740 EMPATHY_ACTION_VIEW_LOGS
);
747 empathy_individual_file_transfer_menu_item_activated (GtkMenuItem
*item
,
748 EmpathyContact
*contact
)
750 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
752 empathy_send_file_with_file_chooser (contact
);
756 empathy_individual_file_transfer_menu_item_new (FolksIndividual
*individual
,
757 EmpathyContact
*contact
)
762 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
) ||
763 EMPATHY_IS_CONTACT (contact
),
766 item
= gtk_image_menu_item_new_with_mnemonic (_("Send File"));
767 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_DOCUMENT_SEND
,
769 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
770 gtk_widget_show (image
);
774 menu_item_set_contact (item
, contact
,
775 G_CALLBACK (empathy_individual_file_transfer_menu_item_activated
),
776 EMPATHY_ACTION_SEND_FILE
);
780 menu_item_set_first_contact (item
, individual
,
781 G_CALLBACK (empathy_individual_file_transfer_menu_item_activated
),
782 EMPATHY_ACTION_SEND_FILE
);
789 empathy_individual_share_my_desktop_menu_item_activated (GtkMenuItem
*item
,
790 EmpathyContact
*contact
)
792 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
794 empathy_share_my_desktop_share_with_contact (contact
);
798 empathy_individual_share_my_desktop_menu_item_new (FolksIndividual
*individual
,
799 EmpathyContact
*contact
)
804 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
) ||
805 EMPATHY_IS_CONTACT (contact
),
808 item
= gtk_image_menu_item_new_with_mnemonic (_("Share My Desktop"));
809 image
= gtk_image_new_from_icon_name (GTK_STOCK_NETWORK
, GTK_ICON_SIZE_MENU
);
810 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
811 gtk_widget_show (image
);
815 menu_item_set_contact (item
, contact
,
816 G_CALLBACK (empathy_individual_share_my_desktop_menu_item_activated
),
817 EMPATHY_ACTION_SHARE_MY_DESKTOP
);
821 menu_item_set_first_contact (item
, individual
,
822 G_CALLBACK (empathy_individual_share_my_desktop_menu_item_activated
),
823 EMPATHY_ACTION_SHARE_MY_DESKTOP
);
830 favourite_menu_item_toggled_cb (GtkCheckMenuItem
*item
,
831 FolksIndividual
*individual
)
833 folks_favourite_details_set_is_favourite (
834 FOLKS_FAVOURITE_DETAILS (individual
),
835 gtk_check_menu_item_get_active (item
));
839 empathy_individual_favourite_menu_item_new (FolksIndividual
*individual
)
843 item
= gtk_check_menu_item_new_with_label (_("Favorite"));
845 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item
),
846 folks_favourite_details_get_is_favourite (
847 FOLKS_FAVOURITE_DETAILS (individual
)));
849 g_signal_connect (item
, "toggled",
850 G_CALLBACK (favourite_menu_item_toggled_cb
), individual
);
856 individual_info_menu_item_activate_cb (FolksIndividual
*individual
)
858 empathy_individual_information_dialog_show (individual
, NULL
);
862 empathy_individual_info_menu_item_new (FolksIndividual
*individual
)
867 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
), NULL
);
868 g_return_val_if_fail (empathy_folks_individual_contains_contact (individual
),
871 item
= gtk_image_menu_item_new_with_mnemonic (_("Infor_mation"));
872 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_CONTACT_INFORMATION
,
874 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
875 gtk_widget_show (image
);
877 g_signal_connect_swapped (item
, "activate",
878 G_CALLBACK (individual_info_menu_item_activate_cb
),
885 individual_edit_menu_item_activate_cb (FolksIndividual
*individual
)
887 empathy_individual_edit_dialog_show (individual
, NULL
);
891 empathy_individual_edit_menu_item_new (FolksIndividual
*individual
)
893 EmpathyIndividualManager
*manager
;
896 gboolean enable
= FALSE
;
897 EmpathyContact
*contact
;
899 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
), NULL
);
901 contact
= empathy_contact_dup_from_folks_individual (individual
);
903 g_return_val_if_fail (EMPATHY_IS_CONTACT (contact
), NULL
);
905 if (empathy_individual_manager_initialized ())
907 TpConnection
*connection
;
909 manager
= empathy_individual_manager_dup_singleton ();
910 connection
= empathy_contact_get_connection (contact
);
912 enable
= (empathy_connection_can_alias_personas (connection
) &&
913 empathy_connection_can_group_personas (connection
));
915 g_object_unref (manager
);
918 item
= gtk_image_menu_item_new_with_mnemonic (
919 C_("Edit individual (contextual menu)", "_Edit"));
920 image
= gtk_image_new_from_icon_name (GTK_STOCK_EDIT
, GTK_ICON_SIZE_MENU
);
921 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
922 gtk_widget_show (image
);
924 gtk_widget_set_sensitive (item
, enable
);
926 g_signal_connect_swapped (item
, "activate",
927 G_CALLBACK (individual_edit_menu_item_activate_cb
), individual
);
929 g_object_unref (contact
);
935 empathy_individual_link_menu_item_new (FolksIndividual
*individual
)
938 /*GtkWidget *image;*/
940 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
), NULL
);
942 item
= gtk_image_menu_item_new_with_mnemonic (
943 /* Translators: this is a verb meaning "to connect two contacts together
944 * to form a meta-contact". */
945 C_("Link individual (contextual menu)", "_Link Contacts…"));
947 /*image = gtk_image_new_from_icon_name (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
948 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
949 gtk_widget_show (image);*/
951 /* Only allow trusted Individuals to be linked */
952 gtk_widget_set_sensitive (item
,
953 folks_individual_get_trust_level (individual
) ==
954 FOLKS_TRUST_LEVEL_PERSONAS
);
961 FolksIndividual
*individual
;
962 EmpathyContact
*contact
;
963 EmpathyChatroom
*chatroom
;
966 static RoomSubMenuData
*
967 room_sub_menu_data_new (FolksIndividual
*individual
,
968 EmpathyContact
*contact
,
969 EmpathyChatroom
*chatroom
)
971 RoomSubMenuData
*data
;
973 data
= g_slice_new0 (RoomSubMenuData
);
974 if (individual
!= NULL
)
975 data
->individual
= g_object_ref (individual
);
977 data
->contact
= g_object_ref (contact
);
978 data
->chatroom
= g_object_ref (chatroom
);
984 room_sub_menu_data_free (RoomSubMenuData
*data
)
986 tp_clear_object (&data
->individual
);
987 tp_clear_object (&data
->contact
);
988 g_object_unref (data
->chatroom
);
989 g_slice_free (RoomSubMenuData
, data
);
993 room_sub_menu_activate_cb (GtkWidget
*item
,
994 RoomSubMenuData
*data
)
997 EmpathyChatroomManager
*mgr
;
998 EmpathyContact
*contact
= NULL
;
1000 chat
= empathy_chatroom_get_tp_chat (data
->chatroom
);
1003 /* channel was invalidated. Ignoring */
1007 mgr
= empathy_chatroom_manager_dup_singleton (NULL
);
1009 if (data
->contact
!= NULL
)
1010 contact
= g_object_ref (data
->contact
);
1016 /* find the first of this Individual's contacts who can join this room */
1017 personas
= folks_individual_get_personas (data
->individual
);
1019 iter
= gee_iterable_iterator (GEE_ITERABLE (personas
));
1020 while (gee_iterator_next (iter
) && (contact
== NULL
))
1022 TpfPersona
*persona
= gee_iterator_get (iter
);
1023 TpContact
*tp_contact
;
1026 if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona
)))
1028 tp_contact
= tpf_persona_get_contact (persona
);
1029 contact
= empathy_contact_dup_from_tp_contact (tp_contact
);
1031 rooms
= empathy_chatroom_manager_get_chatrooms (mgr
,
1032 empathy_contact_get_account (contact
));
1034 if (g_list_find (rooms
, data
->chatroom
) == NULL
)
1035 g_clear_object (&contact
);
1037 /* if contact != NULL here, we've found our match */
1039 g_list_free (rooms
);
1041 g_clear_object (&persona
);
1043 g_clear_object (&iter
);
1046 g_object_unref (mgr
);
1048 if (contact
== NULL
)
1050 /* contact disappeared. Ignoring */
1054 g_return_if_fail (EMPATHY_IS_CONTACT (contact
));
1056 /* send invitation */
1057 empathy_contact_list_add (EMPATHY_CONTACT_LIST (chat
),
1058 contact
, _("Inviting you to this room"));
1061 g_object_unref (contact
);
1065 create_room_sub_menu (FolksIndividual
*individual
,
1066 EmpathyContact
*contact
,
1067 EmpathyChatroom
*chatroom
)
1070 RoomSubMenuData
*data
;
1072 item
= gtk_menu_item_new_with_label (empathy_chatroom_get_name (chatroom
));
1073 data
= room_sub_menu_data_new (individual
, contact
, chatroom
);
1074 g_signal_connect_data (item
, "activate",
1075 G_CALLBACK (room_sub_menu_activate_cb
), data
,
1076 (GClosureNotify
) room_sub_menu_data_free
, 0);
1082 empathy_individual_invite_menu_item_new (FolksIndividual
*individual
,
1083 EmpathyContact
*contact
)
1087 GtkWidget
*room_item
;
1088 EmpathyChatroomManager
*mgr
;
1089 GList
*rooms
= NULL
;
1090 GList
*names
= NULL
;
1092 GtkWidget
*submenu
= NULL
;
1093 /* map of chat room names to their objects; just a utility to remove
1094 * duplicates and to make construction of the alphabetized list easier */
1095 GHashTable
*name_room_map
;
1097 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual
) ||
1098 EMPATHY_IS_CONTACT (contact
),
1101 name_room_map
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
,
1104 item
= gtk_image_menu_item_new_with_mnemonic (_("_Invite to Chat Room"));
1105 image
= gtk_image_new_from_icon_name (EMPATHY_IMAGE_GROUP_MESSAGE
,
1106 GTK_ICON_SIZE_MENU
);
1107 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item
), image
);
1109 mgr
= empathy_chatroom_manager_dup_singleton (NULL
);
1111 if (contact
!= NULL
)
1113 rooms
= empathy_chatroom_manager_get_chatrooms (mgr
,
1114 empathy_contact_get_account (contact
));
1121 /* find the first of this Individual's contacts who can join this room */
1122 personas
= folks_individual_get_personas (individual
);
1123 iter
= gee_iterable_iterator (GEE_ITERABLE (personas
));
1124 while (gee_iterator_next (iter
))
1126 TpfPersona
*persona
= gee_iterator_get (iter
);
1128 TpContact
*tp_contact
;
1129 EmpathyContact
*contact_cur
;
1131 if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona
)))
1133 tp_contact
= tpf_persona_get_contact (persona
);
1134 contact_cur
= empathy_contact_dup_from_tp_contact (tp_contact
);
1136 rooms_cur
= empathy_chatroom_manager_get_chatrooms (mgr
,
1137 empathy_contact_get_account (contact_cur
));
1138 rooms
= g_list_concat (rooms
, rooms_cur
);
1140 g_object_unref (contact_cur
);
1142 g_clear_object (&persona
);
1144 g_clear_object (&iter
);
1147 /* alphabetize the rooms */
1148 for (l
= rooms
; l
!= NULL
; l
= g_list_next (l
))
1150 EmpathyChatroom
*chatroom
= l
->data
;
1153 if (empathy_chatroom_get_tp_chat (chatroom
) != NULL
)
1157 name
= empathy_chatroom_get_name (chatroom
);
1158 existed
= (g_hash_table_lookup (name_room_map
, name
) != NULL
);
1159 g_hash_table_insert (name_room_map
, (gpointer
) name
,
1160 g_object_ref (chatroom
));
1162 /* this will take care of duplicates in rooms */
1165 names
= g_list_insert_sorted (names
, (gpointer
) name
,
1166 (GCompareFunc
) g_strcmp0
);
1171 for (l
= names
; l
!= NULL
; l
= g_list_next (l
))
1173 const gchar
*name
= l
->data
;
1174 EmpathyChatroom
*chatroom
;
1176 if (G_UNLIKELY (submenu
== NULL
))
1177 submenu
= gtk_menu_new ();
1179 chatroom
= g_hash_table_lookup (name_room_map
, name
);
1180 room_item
= create_room_sub_menu (individual
, contact
, chatroom
);
1181 gtk_menu_shell_append ((GtkMenuShell
*) submenu
, room_item
);
1182 gtk_widget_show (room_item
);
1186 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item
), submenu
);
1188 gtk_widget_set_sensitive (item
, FALSE
);
1190 gtk_widget_show (image
);
1192 g_hash_table_destroy (name_room_map
);
1193 g_object_unref (mgr
);
1194 g_list_free (names
);
1195 g_list_free (rooms
);