]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-menu.c
Updated Basque language
[empathy.git] / libempathy-gtk / empathy-contact-menu.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2008 Collabora Ltd.
4  *
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.
9  *
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.
14  *
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
18  *
19  * Authors: Xavier Claessens <xclaesse@gmail.com>
20  */
21
22 #include "config.h"
23
24 #include <string.h>
25
26 #include <glib/gi18n-lib.h>
27 #include <gtk/gtk.h>
28
29 #include <libempathy/empathy-call-factory.h>
30 #include <libempathy/empathy-log-manager.h>
31 #include <libempathy/empathy-contact-manager.h>
32 #include <libempathy/empathy-dispatcher.h>
33 #include <libempathy/empathy-utils.h>
34 #include <libempathy/empathy-chatroom-manager.h>
35 #include <libempathy/empathy-contact-manager.h>
36
37 #include "empathy-contact-menu.h"
38 #include "empathy-images.h"
39 #include "empathy-log-window.h"
40 #include "empathy-contact-dialogs.h"
41 #include "empathy-ui-utils.h"
42 #include "empathy-share-my-desktop.h"
43
44 GtkWidget *
45 empathy_contact_menu_new (EmpathyContact             *contact,
46                           EmpathyContactFeatureFlags  features)
47 {
48         GtkWidget    *menu;
49         GtkMenuShell *shell;
50         GtkWidget    *item;
51
52         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
53
54         if (features == EMPATHY_CONTACT_FEATURE_NONE) {
55                 return NULL;
56         }
57
58         menu = gtk_menu_new ();
59         shell = GTK_MENU_SHELL (menu);
60
61         /* Add Contact */
62         item = empathy_contact_add_menu_item_new (contact);
63         if (item) {
64                 gtk_menu_shell_append (shell, item);
65                 gtk_widget_show (item);
66         }
67
68         /* Chat */
69         if (features & EMPATHY_CONTACT_FEATURE_CHAT) {
70                 item = empathy_contact_chat_menu_item_new (contact);
71                 gtk_menu_shell_append (shell, item);
72                 gtk_widget_show (item);
73         }
74
75         if (features & EMPATHY_CONTACT_FEATURE_CALL) {
76                 /* Audio Call */
77                 item = empathy_contact_audio_call_menu_item_new (contact);
78                 gtk_menu_shell_append (shell, item);
79                 gtk_widget_show (item);
80
81                 /* Video Call */
82                 item = empathy_contact_video_call_menu_item_new (contact);
83                 gtk_menu_shell_append (shell, item);
84                 gtk_widget_show (item);
85         }
86
87         /* Log */
88         if (features & EMPATHY_CONTACT_FEATURE_LOG) {
89                 item = empathy_contact_log_menu_item_new (contact);
90                 gtk_menu_shell_append (shell, item);
91                 gtk_widget_show (item);
92         }
93
94         /* Invite */
95         item = empathy_contact_invite_menu_item_new (contact);
96         gtk_menu_shell_append (shell, item);
97         gtk_widget_show (item);
98
99         /* File transfer */
100         item = empathy_contact_file_transfer_menu_item_new (contact);
101         gtk_menu_shell_append (shell, item);
102         gtk_widget_show (item);
103
104         /* Share my desktop */
105         /* FIXME we should add the "Share my desktop" menu item if Vino is
106         a registered handler in MC5 */
107         item = empathy_contact_share_my_desktop_menu_item_new (contact);
108         gtk_menu_shell_append (shell, item);
109         gtk_widget_show (item);
110
111         /* Separator */
112         if (features & (EMPATHY_CONTACT_FEATURE_EDIT |
113                         EMPATHY_CONTACT_FEATURE_INFO)) {
114                 item = gtk_separator_menu_item_new ();
115                 gtk_menu_shell_append (shell, item);
116                 gtk_widget_show (item);
117         }
118
119         /* Edit */
120         if (features & EMPATHY_CONTACT_FEATURE_EDIT) {
121                 item = empathy_contact_edit_menu_item_new (contact);
122                 gtk_menu_shell_append (shell, item);
123                 gtk_widget_show (item);
124         }
125
126         /* Info */
127         if (features & EMPATHY_CONTACT_FEATURE_INFO) {
128                 item = empathy_contact_info_menu_item_new (contact);
129                 gtk_menu_shell_append (shell, item);
130                 gtk_widget_show (item);
131         }
132
133         return menu;
134 }
135
136 static void
137 empathy_contact_add_menu_item_activated (GtkMenuItem *item,
138         EmpathyContact *contact)
139 {
140         GtkWidget *toplevel;
141
142         toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item));
143         if (!GTK_WIDGET_TOPLEVEL (toplevel) || !GTK_IS_WINDOW (toplevel)) {
144                 toplevel = NULL;
145         }
146
147         empathy_new_contact_dialog_show_with_contact (GTK_WINDOW (toplevel),
148                                                       contact);
149 }
150
151 GtkWidget *
152 empathy_contact_add_menu_item_new (EmpathyContact *contact)
153 {
154         GtkWidget *item;
155         GtkWidget *image;
156         EmpathyContactManager *manager;
157         TpConnection *connection;
158         GList *l, *members;
159         gboolean found = FALSE;
160         EmpathyContactListFlags flags;
161
162         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
163
164         if (!empathy_contact_manager_initialized ()) {
165                 return NULL;
166         }
167
168         manager = empathy_contact_manager_dup_singleton ();
169         connection = empathy_contact_get_connection (contact);
170
171         flags = empathy_contact_manager_get_flags_for_connection (manager,
172                         connection);
173
174         if (!(flags & EMPATHY_CONTACT_LIST_CAN_ADD)) {
175                 return NULL;
176         }
177
178         members = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (manager));
179         for (l = members; l; l = l->next) {
180                 if (!found && empathy_contact_equal (l->data, contact)) {
181                         found = TRUE;
182                         /* we keep iterating so that we don't leak contact
183                          * refs */
184                 }
185
186                 g_object_unref (l->data);
187         }
188         g_list_free (members);
189         g_object_unref (manager);
190
191         if (found) {
192                 return NULL;
193         }
194
195         item = gtk_image_menu_item_new_with_mnemonic (_("_Add Contact..."));
196         image = gtk_image_new_from_icon_name (GTK_STOCK_ADD,
197                                               GTK_ICON_SIZE_MENU);
198         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
199
200         g_signal_connect (item, "activate",
201                         G_CALLBACK (empathy_contact_add_menu_item_activated),
202                         contact);
203
204         return item;
205 }
206
207 static void
208 empathy_contact_chat_menu_item_activated (GtkMenuItem *item,
209         EmpathyContact *contact)
210 {
211   empathy_dispatcher_chat_with_contact (contact, NULL, NULL);
212 }
213
214 GtkWidget *
215 empathy_contact_chat_menu_item_new (EmpathyContact *contact)
216 {
217         GtkWidget *item;
218         GtkWidget *image;
219
220         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
221
222         item = gtk_image_menu_item_new_with_mnemonic (_("_Chat"));
223         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_MESSAGE,
224                                               GTK_ICON_SIZE_MENU);
225         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
226         gtk_widget_show (image);
227
228         g_signal_connect (item, "activate",
229                                   G_CALLBACK (empathy_contact_chat_menu_item_activated),
230                                   contact);
231
232         return item;
233 }
234
235 static void
236 empathy_contact_audio_call_menu_item_activated (GtkMenuItem *item,
237         EmpathyContact *contact)
238 {
239         EmpathyCallFactory *factory;
240
241         factory = empathy_call_factory_get ();
242         empathy_call_factory_new_call_with_streams (factory, contact, TRUE, FALSE);
243 }
244
245 GtkWidget *
246 empathy_contact_audio_call_menu_item_new (EmpathyContact *contact)
247 {
248         GtkWidget *item;
249         GtkWidget *image;
250
251         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
252
253         item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Audio Call"));
254         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VOIP,
255                                               GTK_ICON_SIZE_MENU);
256         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
257         gtk_widget_set_sensitive (item, empathy_contact_can_voip_audio (contact));
258         gtk_widget_show (image);
259
260         g_signal_connect (item, "activate",
261                                   G_CALLBACK (empathy_contact_audio_call_menu_item_activated),
262                                   contact);
263
264         return item;
265 }
266
267 static void
268 empathy_contact_video_call_menu_item_activated (GtkMenuItem *item,
269         EmpathyContact *contact)
270 {
271         EmpathyCallFactory *factory;
272
273         factory = empathy_call_factory_get ();
274         empathy_call_factory_new_call_with_streams (factory, contact, TRUE, TRUE);
275 }
276
277 GtkWidget *
278 empathy_contact_video_call_menu_item_new (EmpathyContact *contact)
279 {
280         GtkWidget *item;
281         GtkWidget *image;
282
283         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
284
285         item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Video Call"));
286         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VIDEO_CALL,
287                                               GTK_ICON_SIZE_MENU);
288         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
289         gtk_widget_set_sensitive (item, empathy_contact_can_voip_video (contact));
290         gtk_widget_show (image);
291
292         g_signal_connect (item, "activate",
293                                   G_CALLBACK (empathy_contact_video_call_menu_item_activated),
294                                   contact);
295
296         return item;
297 }
298
299 static void
300 contact_log_menu_item_activate_cb (EmpathyContact *contact)
301 {
302         empathy_log_window_show (empathy_contact_get_account (contact),
303                                  empathy_contact_get_id (contact),
304                                  FALSE, NULL);
305 }
306
307 GtkWidget *
308 empathy_contact_log_menu_item_new (EmpathyContact *contact)
309 {
310         EmpathyLogManager *manager;
311         gboolean           have_log;
312         GtkWidget         *item;
313         GtkWidget         *image;
314
315         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
316
317         manager = empathy_log_manager_dup_singleton ();
318         have_log = empathy_log_manager_exists (manager,
319                                                empathy_contact_get_account (contact),
320                                                empathy_contact_get_id (contact),
321                                                FALSE);
322         g_object_unref (manager);
323
324         item = gtk_image_menu_item_new_with_mnemonic (_("_View Previous Conversations"));
325         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_LOG,
326                                               GTK_ICON_SIZE_MENU);
327         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
328         gtk_widget_set_sensitive (item, have_log);
329         gtk_widget_show (image);
330
331         g_signal_connect_swapped (item, "activate",
332                                   G_CALLBACK (contact_log_menu_item_activate_cb),
333                                   contact);
334
335         return item;
336 }
337
338 GtkWidget *
339 empathy_contact_file_transfer_menu_item_new (EmpathyContact *contact)
340 {
341         GtkWidget         *item;
342         GtkWidget         *image;
343
344         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
345
346         item = gtk_image_menu_item_new_with_mnemonic (_("Send file"));
347         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_DOCUMENT_SEND,
348                                               GTK_ICON_SIZE_MENU);
349         gtk_widget_set_sensitive (item, empathy_contact_can_send_files (contact));
350         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
351         gtk_widget_show (image);
352
353         g_signal_connect_swapped (item, "activate",
354                                   G_CALLBACK (empathy_send_file_with_file_chooser),
355                                   contact);
356
357         return item;
358 }
359
360 /* FIXME  we should check if the contact supports vnc stream tube */
361 GtkWidget *
362 empathy_contact_share_my_desktop_menu_item_new (EmpathyContact *contact)
363 {
364         GtkWidget         *item;
365         GtkWidget         *image;
366
367         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
368
369         item = gtk_image_menu_item_new_with_mnemonic (_("Share my desktop"));
370         image = gtk_image_new_from_icon_name (GTK_STOCK_NETWORK,
371                                               GTK_ICON_SIZE_MENU);
372         gtk_widget_set_sensitive (item, empathy_contact_can_use_stream_tube (contact));
373         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
374         gtk_widget_show (image);
375
376         g_signal_connect_swapped (item, "activate",
377                                   G_CALLBACK (empathy_share_my_desktop_share_with_contact),
378                                   contact);
379
380         return item;
381 }
382
383 static void
384 contact_info_menu_item_activate_cb (EmpathyContact *contact)
385 {
386         empathy_contact_information_dialog_show (contact, NULL);
387 }
388
389 GtkWidget *
390 empathy_contact_info_menu_item_new (EmpathyContact *contact)
391 {
392         GtkWidget *item;
393         GtkWidget *image;
394
395         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
396
397         item = gtk_image_menu_item_new_with_mnemonic (_("Infor_mation"));
398         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_CONTACT_INFORMATION,
399                                               GTK_ICON_SIZE_MENU);
400         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
401         gtk_widget_show (image);
402
403         g_signal_connect_swapped (item, "activate",
404                                   G_CALLBACK (contact_info_menu_item_activate_cb),
405                                   contact);
406
407         return item;
408 }
409
410 static void
411 contact_edit_menu_item_activate_cb (EmpathyContact *contact)
412 {
413         empathy_contact_edit_dialog_show (contact, NULL);
414 }
415
416 GtkWidget *
417 empathy_contact_edit_menu_item_new (EmpathyContact *contact)
418 {
419         EmpathyContactManager *manager;
420         GtkWidget *item;
421         GtkWidget *image;
422         gboolean enable = FALSE;
423
424         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
425
426         if (empathy_contact_manager_initialized ()) {
427                 TpConnection *connection;
428                 EmpathyContactListFlags flags;
429
430                 manager = empathy_contact_manager_dup_singleton ();
431                 connection = empathy_contact_get_connection (contact);
432                 flags = empathy_contact_manager_get_flags_for_connection (
433                                 manager, connection);
434
435                 enable = (flags & EMPATHY_CONTACT_LIST_CAN_ALIAS ||
436                           flags & EMPATHY_CONTACT_LIST_CAN_GROUP);
437
438                 g_object_unref (manager);
439         }
440
441         item = gtk_image_menu_item_new_with_mnemonic (_("_Edit"));
442         image = gtk_image_new_from_icon_name (GTK_STOCK_EDIT,
443                                               GTK_ICON_SIZE_MENU);
444         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
445         gtk_widget_show (image);
446
447         gtk_widget_set_sensitive (item, enable);
448
449         g_signal_connect_swapped (item, "activate",
450                                   G_CALLBACK (contact_edit_menu_item_activate_cb),
451                                   contact);
452
453         return item;
454 }
455
456 typedef struct  {
457         EmpathyContact *contact;
458         EmpathyChatroom *chatroom;
459 } RoomSubMenuData;
460
461 static RoomSubMenuData *
462 room_sub_menu_data_new (EmpathyContact *contact,
463                         EmpathyChatroom *chatroom)
464 {
465         RoomSubMenuData *data;
466
467         data = g_slice_new (RoomSubMenuData);
468         data->contact = g_object_ref (contact);
469         data->chatroom = g_object_ref (chatroom);
470         return data;
471 }
472
473 static void
474 room_sub_menu_data_free (RoomSubMenuData *data)
475 {
476         /* FIXME: seems this is never called... */
477         g_object_unref (data->contact);
478         g_object_unref (data->chatroom);
479         g_slice_free (RoomSubMenuData, data);
480 }
481
482 static void
483 room_sub_menu_activate_cb (GtkWidget *item,
484                            RoomSubMenuData *data)
485 {
486         TpHandle handle;
487         GArray handles = {(gchar *) &handle, 1};
488         EmpathyTpChat *chat;
489         TpChannel *channel;
490
491         chat = empathy_chatroom_get_tp_chat (data->chatroom);
492         if (chat == NULL) {
493                 /* channel was invalidated. Ignoring */
494                 return;
495         }
496
497         /* send invitation */
498         handle = empathy_contact_get_handle (data->contact);
499         channel = empathy_tp_chat_get_channel (chat);
500         tp_cli_channel_interface_group_call_add_members (channel, -1, &handles,
501                 _("Inviting to this room"), NULL, NULL, NULL, NULL);
502 }
503
504 static GtkWidget *
505 create_room_sub_menu (EmpathyContact *contact,
506                       EmpathyChatroom *chatroom)
507 {
508         GtkWidget *item;
509         RoomSubMenuData *data;
510
511         item = gtk_menu_item_new_with_label (empathy_chatroom_get_name (chatroom));
512         data = room_sub_menu_data_new (contact, chatroom);
513         g_signal_connect_data (item, "activate",
514                                G_CALLBACK (room_sub_menu_activate_cb), data,
515                                (GClosureNotify) room_sub_menu_data_free, 0);
516
517         return item;
518 }
519
520 GtkWidget *
521 empathy_contact_invite_menu_item_new (EmpathyContact *contact)
522 {
523         GtkWidget *item;
524         GtkWidget *image;
525         GtkWidget *room_item;
526         EmpathyChatroomManager *mgr;
527         GList *rooms, *l;
528         GtkWidget *submenu = NULL;
529
530         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
531
532         item = gtk_image_menu_item_new_with_mnemonic (_("_Invite to chatroom"));
533         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_GROUP_MESSAGE,
534                                               GTK_ICON_SIZE_MENU);
535         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
536
537         mgr = empathy_chatroom_manager_dup_singleton (NULL);
538         rooms = empathy_chatroom_manager_get_chatrooms (mgr,
539                 empathy_contact_get_account (contact));
540
541         for (l = rooms; l != NULL; l = g_list_next (l)) {
542                 EmpathyChatroom *chatroom = l->data;
543
544                 if (empathy_chatroom_get_tp_chat (chatroom) != NULL) {
545                         if (G_UNLIKELY (submenu == NULL))
546                                 submenu = gtk_menu_new ();
547
548                         room_item = create_room_sub_menu (contact, chatroom);
549                         gtk_menu_shell_append ((GtkMenuShell *) submenu, room_item);
550                         gtk_widget_show (room_item);
551                 }
552         }
553
554         if (submenu) {
555                 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
556         } else {
557                 gtk_widget_set_sensitive (item, FALSE);
558         }
559
560         gtk_widget_show (image);
561
562         g_object_unref (mgr);
563         g_list_free (rooms);
564
565         return item;
566 }
567