]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-menu.c
Merge branch 'debugger'
[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-dispatcher.h>
32 #include <libempathy/empathy-utils.h>
33 #include <libempathy/empathy-chatroom-manager.h>
34
35 #include "empathy-contact-menu.h"
36 #include "empathy-images.h"
37 #include "empathy-log-window.h"
38 #include "empathy-contact-dialogs.h"
39 #include "empathy-ui-utils.h"
40
41 GtkWidget *
42 empathy_contact_menu_new (EmpathyContact             *contact,
43                           EmpathyContactFeatureFlags  features)
44 {
45         GtkWidget    *menu;
46         GtkMenuShell *shell;
47         GtkWidget    *item;
48
49         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
50
51         if (features == EMPATHY_CONTACT_FEATURE_NONE) {
52                 return NULL;
53         }
54
55         menu = gtk_menu_new ();
56         shell = GTK_MENU_SHELL (menu);
57
58         /* Chat */
59         if (features & EMPATHY_CONTACT_FEATURE_CHAT) {
60                 item = empathy_contact_chat_menu_item_new (contact);
61                 gtk_menu_shell_append (shell, item);
62                 gtk_widget_show (item);
63         }
64
65         if (features & EMPATHY_CONTACT_FEATURE_CALL) {
66                 /* Audio Call */
67                 item = empathy_contact_audio_call_menu_item_new (contact);
68                 gtk_menu_shell_append (shell, item);
69                 gtk_widget_show (item);
70
71                 /* Video Call */
72                 item = empathy_contact_video_call_menu_item_new (contact);
73                 gtk_menu_shell_append (shell, item);
74                 gtk_widget_show (item);
75         }
76
77         /* Log */
78         if (features & EMPATHY_CONTACT_FEATURE_LOG) {
79                 item = empathy_contact_log_menu_item_new (contact);
80                 gtk_menu_shell_append (shell, item);
81                 gtk_widget_show (item);
82         }
83
84         /* Invite */
85         item = empathy_contact_invite_menu_item_new (contact);
86         gtk_menu_shell_append (shell, item);
87         gtk_widget_show (item);
88
89         /* File transfer */
90         item = empathy_contact_file_transfer_menu_item_new (contact);
91         gtk_menu_shell_append (shell, item);
92         gtk_widget_show (item);
93
94         /* Separator */
95         if (features & (EMPATHY_CONTACT_FEATURE_EDIT |
96                         EMPATHY_CONTACT_FEATURE_INFO)) {
97                 item = gtk_separator_menu_item_new ();
98                 gtk_menu_shell_append (shell, item);
99                 gtk_widget_show (item);
100         }
101
102         /* Edit */
103         if (features & EMPATHY_CONTACT_FEATURE_EDIT) {
104                 item = empathy_contact_edit_menu_item_new (contact);
105                 gtk_menu_shell_append (shell, item);
106                 gtk_widget_show (item);
107         }
108
109         /* Info */
110         if (features & EMPATHY_CONTACT_FEATURE_INFO) {
111                 item = empathy_contact_info_menu_item_new (contact);
112                 gtk_menu_shell_append (shell, item);
113                 gtk_widget_show (item);
114         }
115
116         return menu;
117 }
118
119 static void
120 empathy_contact_chat_menu_item_activated (GtkMenuItem *item,
121         EmpathyContact *contact)
122 {
123   empathy_dispatcher_chat_with_contact (contact, NULL, NULL);
124 }
125
126
127 GtkWidget *
128 empathy_contact_chat_menu_item_new (EmpathyContact *contact)
129 {
130         GtkWidget *item;
131         GtkWidget *image;
132
133         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
134
135         item = gtk_image_menu_item_new_with_mnemonic (_("_Chat"));
136         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_MESSAGE,
137                                               GTK_ICON_SIZE_MENU);
138         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
139         gtk_widget_show (image);
140
141         g_signal_connect (item, "activate",
142                                   G_CALLBACK (empathy_contact_chat_menu_item_activated),
143                                   contact);
144
145         return item;
146 }
147
148 static void
149 empathy_contact_audio_call_menu_item_activated (GtkMenuItem *item,
150         EmpathyContact *contact)
151 {
152         EmpathyCallFactory *factory;
153
154         factory = empathy_call_factory_get ();
155         empathy_call_factory_new_call_with_streams (factory, contact, TRUE, FALSE);
156 }
157
158 GtkWidget *
159 empathy_contact_audio_call_menu_item_new (EmpathyContact *contact)
160 {
161         GtkWidget *item;
162         GtkWidget *image;
163
164         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
165
166         item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Audio Call"));
167         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VOIP,
168                                               GTK_ICON_SIZE_MENU);
169         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
170         gtk_widget_set_sensitive (item, empathy_contact_can_voip (contact));
171         gtk_widget_show (image);
172
173         g_signal_connect (item, "activate",
174                                   G_CALLBACK (empathy_contact_audio_call_menu_item_activated),
175                                   contact);
176
177         return item;
178 }
179
180 static void
181 empathy_contact_video_call_menu_item_activated (GtkMenuItem *item,
182         EmpathyContact *contact)
183 {
184         EmpathyCallFactory *factory;
185
186         factory = empathy_call_factory_get ();
187         empathy_call_factory_new_call_with_streams (factory, contact, TRUE, TRUE);
188 }
189
190 GtkWidget *
191 empathy_contact_video_call_menu_item_new (EmpathyContact *contact)
192 {
193         GtkWidget *item;
194         GtkWidget *image;
195
196         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
197
198         item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Video Call"));
199         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VIDEO_CALL,
200                                               GTK_ICON_SIZE_MENU);
201         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
202         gtk_widget_set_sensitive (item, empathy_contact_can_voip (contact));
203         gtk_widget_show (image);
204
205         g_signal_connect (item, "activate",
206                                   G_CALLBACK (empathy_contact_video_call_menu_item_activated),
207                                   contact);
208
209         return item;
210 }
211
212 static void
213 contact_log_menu_item_activate_cb (EmpathyContact *contact)
214 {
215         empathy_log_window_show (empathy_contact_get_account (contact),
216                                  empathy_contact_get_id (contact),
217                                  FALSE, NULL);
218 }
219
220 GtkWidget *
221 empathy_contact_log_menu_item_new (EmpathyContact *contact)
222 {
223         EmpathyLogManager *manager;
224         gboolean           have_log;
225         GtkWidget         *item;
226         GtkWidget         *image;
227
228         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
229
230         manager = empathy_log_manager_dup_singleton ();
231         have_log = empathy_log_manager_exists (manager,
232                                                empathy_contact_get_account (contact),
233                                                empathy_contact_get_id (contact),
234                                                FALSE);
235         g_object_unref (manager);
236
237         item = gtk_image_menu_item_new_with_mnemonic (_("_View Previous Conversations"));
238         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_LOG,
239                                               GTK_ICON_SIZE_MENU);
240         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
241         gtk_widget_set_sensitive (item, have_log);
242         gtk_widget_show (image);
243
244         g_signal_connect_swapped (item, "activate",
245                                   G_CALLBACK (contact_log_menu_item_activate_cb),
246                                   contact);
247
248         return item;
249 }
250
251 GtkWidget *
252 empathy_contact_file_transfer_menu_item_new (EmpathyContact *contact)
253 {
254         GtkWidget         *item;
255         GtkWidget         *image;
256
257         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
258
259         item = gtk_image_menu_item_new_with_mnemonic (_("Send file"));
260         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_DOCUMENT_SEND,
261                                               GTK_ICON_SIZE_MENU);
262         gtk_widget_set_sensitive (item, empathy_contact_can_send_files (contact));
263         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
264         gtk_widget_show (image);
265
266         g_signal_connect_swapped (item, "activate",
267                                   G_CALLBACK (empathy_send_file_with_file_chooser),
268                                   contact);
269
270         return item;
271 }
272
273 static void
274 contact_info_menu_item_activate_cb (EmpathyContact *contact)
275 {
276         empathy_contact_information_dialog_show (contact, NULL);
277 }
278
279 GtkWidget *
280 empathy_contact_info_menu_item_new (EmpathyContact *contact)
281 {
282         GtkWidget *item;
283         GtkWidget *image;
284
285         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
286
287         item = gtk_image_menu_item_new_with_mnemonic (_("Infor_mation"));
288         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_CONTACT_INFORMATION,
289                                               GTK_ICON_SIZE_MENU);
290         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
291         gtk_widget_show (image);
292
293         g_signal_connect_swapped (item, "activate",
294                                   G_CALLBACK (contact_info_menu_item_activate_cb),
295                                   contact);
296
297         return item;
298 }
299
300 static void
301 contact_edit_menu_item_activate_cb (EmpathyContact *contact)
302 {
303         empathy_contact_edit_dialog_show (contact, NULL);
304 }
305
306 GtkWidget *
307 empathy_contact_edit_menu_item_new (EmpathyContact *contact)
308 {
309         GtkWidget *item;
310         GtkWidget *image;
311
312         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
313
314         item = gtk_image_menu_item_new_with_mnemonic (_("_Edit"));
315         image = gtk_image_new_from_icon_name (GTK_STOCK_EDIT,
316                                               GTK_ICON_SIZE_MENU);
317         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
318         gtk_widget_show (image);
319
320         g_signal_connect_swapped (item, "activate",
321                                   G_CALLBACK (contact_edit_menu_item_activate_cb),
322                                   contact);
323
324         return item;
325 }
326
327 typedef struct  {
328         EmpathyContact *contact;
329         EmpathyChatroom *chatroom;
330 } RoomSubMenuData;
331
332 static RoomSubMenuData *
333 room_sub_menu_data_new (EmpathyContact *contact,
334                         EmpathyChatroom *chatroom)
335 {
336         RoomSubMenuData *data;
337
338         data = g_slice_new (RoomSubMenuData);
339         data->contact = g_object_ref (contact);
340         data->chatroom = g_object_ref (chatroom);
341         return data;
342 }
343
344 static void
345 room_sub_menu_data_free (RoomSubMenuData *data)
346 {
347         /* FIXME: seems this is never called... */
348         g_object_unref (data->contact);
349         g_object_unref (data->chatroom);
350         g_slice_free (RoomSubMenuData, data);
351 }
352
353 static void
354 room_sub_menu_activate_cb (GtkWidget *item,
355                            RoomSubMenuData *data)
356 {
357         TpHandle handle;
358         GArray handles = {(gchar *) &handle, 1};
359         EmpathyTpChat *chat;
360         TpChannel *channel;
361
362         chat = empathy_chatroom_get_tp_chat (data->chatroom);
363         if (chat == NULL) {
364                 /* channel was invalidated. Ignoring */
365                 return;
366         }
367
368         /* send invitation */
369         handle = empathy_contact_get_handle (data->contact);
370         channel = empathy_tp_chat_get_channel (chat);
371         tp_cli_channel_interface_group_call_add_members (channel, -1, &handles,
372                 _("Inviting to this room"), NULL, NULL, NULL, NULL);
373 }
374
375 static GtkWidget *
376 create_room_sub_menu (EmpathyContact *contact,
377                       EmpathyChatroom *chatroom)
378 {
379         GtkWidget *item;
380         RoomSubMenuData *data;
381
382         item = gtk_menu_item_new_with_label (empathy_chatroom_get_name (chatroom));
383         data = room_sub_menu_data_new (contact, chatroom);
384         g_signal_connect_data (item, "activate",
385                                G_CALLBACK (room_sub_menu_activate_cb), data,
386                                (GClosureNotify) room_sub_menu_data_free, 0);
387
388         return item;
389 }
390
391 GtkWidget *
392 empathy_contact_invite_menu_item_new (EmpathyContact *contact)
393 {
394         GtkWidget *item;
395         GtkWidget *image;
396         GtkWidget *room_item;
397         EmpathyChatroomManager *mgr;
398         GList *rooms, *l;
399         GtkWidget *submenu = NULL;
400
401         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
402
403         item = gtk_image_menu_item_new_with_mnemonic (_("_Invite to chatroom"));
404         image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_GROUP_MESSAGE,
405                                               GTK_ICON_SIZE_MENU);
406         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
407
408         mgr = empathy_chatroom_manager_dup_singleton (NULL);
409         rooms = empathy_chatroom_manager_get_chatrooms (mgr,
410                 empathy_contact_get_account (contact));
411
412         for (l = rooms; l != NULL; l = g_list_next (l)) {
413                 EmpathyChatroom *chatroom = l->data;
414
415                 if (empathy_chatroom_get_tp_chat (chatroom) != NULL) {
416                         if (G_UNLIKELY (submenu == NULL))
417                                 submenu = gtk_menu_new ();
418
419                         room_item = create_room_sub_menu (contact, chatroom);
420                         gtk_menu_shell_append ((GtkMenuShell *) submenu, room_item);
421                         gtk_widget_show (room_item);
422                 }
423         }
424
425         if (submenu) {
426                 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
427         } else {
428                 gtk_widget_set_sensitive (item, FALSE);
429         }
430
431         gtk_widget_show (image);
432
433         g_object_unref (mgr);
434         g_list_free (rooms);
435
436         return item;
437 }
438