]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-dialogs.c
contact-menu: use tp-glib blocking API
[empathy.git] / libempathy-gtk / empathy-contact-dialogs.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007-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  *          Danielle Madeley <danielle.madeley@collabora.co.uk>
21  */
22
23 #include <config.h>
24
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include <gtk/gtk.h>
29 #include <glib/gi18n-lib.h>
30
31 #include <telepathy-glib/account-manager.h>
32
33 #include <libempathy/empathy-contact-manager.h>
34 #include <libempathy/empathy-contact-list.h>
35 #include <libempathy/empathy-tp-contact-factory.h>
36 #include <libempathy/empathy-utils.h>
37
38 #include "empathy-contact-dialogs.h"
39 #include "empathy-contact-widget.h"
40 #include "empathy-ui-utils.h"
41
42 static GList *subscription_dialogs = NULL;
43 static GList *information_dialogs = NULL;
44 static GList *edit_dialogs = NULL;
45 static GtkWidget *personal_dialog = NULL;
46 static GtkWidget *new_contact_dialog = NULL;
47
48 static gint
49 contact_dialogs_find (GtkDialog      *dialog,
50                       EmpathyContact *contact)
51 {
52         GtkWidget     *contact_widget;
53         EmpathyContact *this_contact;
54
55         contact_widget = g_object_get_data (G_OBJECT (dialog), "contact_widget");
56         this_contact = empathy_contact_widget_get_contact (contact_widget);
57
58         return contact != this_contact;
59 }
60
61 /*
62  *  Subscription dialog
63  */
64
65 static void
66 subscription_dialog_response_cb (GtkDialog *dialog,
67                                  gint       response,
68                                  GtkWidget *contact_widget)
69 {
70         EmpathyContactManager *manager;
71         EmpathyContact        *contact;
72
73         manager = empathy_contact_manager_dup_singleton ();
74         contact = empathy_contact_widget_get_contact (contact_widget);
75
76         if (response == GTK_RESPONSE_YES) {
77                 empathy_contact_list_add (EMPATHY_CONTACT_LIST (manager),
78                                           contact, "");
79
80                 empathy_contact_set_alias (contact,
81                         empathy_contact_widget_get_alias (contact_widget));
82         }
83         else if (response == GTK_RESPONSE_NO) {
84                 empathy_contact_list_remove (EMPATHY_CONTACT_LIST (manager),
85                                              contact, "");
86         }
87         else if (response == GTK_RESPONSE_REJECT) {
88                 gboolean abusive;
89
90                 /* confirm the blocking */
91                 if (empathy_block_contact_dialog_show (GTK_WINDOW (dialog), contact,
92                                                        NULL, &abusive)) {
93                         empathy_contact_list_remove (
94                                         EMPATHY_CONTACT_LIST (manager),
95                                         contact, "");
96                         empathy_contact_list_set_blocked (
97                                         EMPATHY_CONTACT_LIST (manager),
98                                         contact, TRUE, abusive);
99                 } else {
100                         /* if they don't confirm, return back to the
101                          * first dialog */
102                         goto finally;
103                 }
104         }
105
106         subscription_dialogs = g_list_remove (subscription_dialogs, dialog);
107         gtk_widget_destroy (GTK_WIDGET (dialog));
108
109 finally:
110         g_object_unref (manager);
111 }
112
113 void
114 empathy_subscription_dialog_show (EmpathyContact *contact,
115                                   const gchar *message,
116                                   GtkWindow     *parent)
117 {
118         GtkBuilder *gui;
119         GtkWidget *dialog;
120         GtkWidget *hbox_subscription;
121         GtkWidget *vbox;
122         GtkWidget *contact_widget;
123         GtkWidget *block_user_button;
124         GList     *l;
125         gchar     *filename;
126         EmpathyContactManager *manager;
127         EmpathyContactListFlags flags;
128
129         manager = empathy_contact_manager_dup_singleton ();
130
131         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
132
133         l = g_list_find_custom (subscription_dialogs,
134                                 contact,
135                                 (GCompareFunc) contact_dialogs_find);
136         if (l) {
137                 gtk_window_present (GTK_WINDOW (l->data));
138                 return;
139         }
140
141         filename = empathy_file_lookup ("empathy-contact-dialogs.ui",
142                                         "libempathy-gtk");
143         gui = empathy_builder_get_file (filename,
144                                       "subscription_request_dialog", &dialog,
145                                       "hbox_subscription", &hbox_subscription,
146                                       "block-user-button", &block_user_button,
147                                       NULL);
148         g_free (filename);
149         g_object_unref (gui);
150
151         vbox = gtk_vbox_new (FALSE, 6);
152
153         gtk_box_pack_end (GTK_BOX (hbox_subscription), vbox,
154                           TRUE, TRUE, 0);
155
156         /* Contact info widget */
157         contact_widget = empathy_contact_widget_new (contact,
158                                                      EMPATHY_CONTACT_WIDGET_NO_SET_ALIAS |
159                                                      EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
160                                                      EMPATHY_CONTACT_WIDGET_EDIT_GROUPS |
161                                                      EMPATHY_CONTACT_WIDGET_SHOW_DETAILS);
162         gtk_box_pack_start (GTK_BOX (vbox),
163                           contact_widget,
164                           TRUE, TRUE,
165                           0);
166
167         if (!tp_str_empty (message)) {
168                 GtkWidget *label;
169                 gchar *tmp;
170
171                 label = gtk_label_new ("");
172                 tmp = g_strdup_printf ("<i>%s</i>", message);
173
174                 gtk_label_set_markup (GTK_LABEL (label), tmp);
175                 g_free (tmp);
176                 gtk_widget_show (label);
177
178                 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
179         }
180
181         gtk_widget_show (contact_widget);
182         gtk_widget_show (vbox);
183
184         g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
185         subscription_dialogs = g_list_prepend (subscription_dialogs, dialog);
186
187         g_signal_connect (dialog, "response",
188                           G_CALLBACK (subscription_dialog_response_cb),
189                           contact_widget);
190
191         flags = empathy_contact_manager_get_flags_for_connection (manager,
192                                 empathy_contact_get_connection (contact));
193
194         if (flags & EMPATHY_CONTACT_LIST_CAN_BLOCK)
195                 gtk_widget_show (block_user_button);
196
197         if (parent) {
198                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
199         }
200
201         g_object_unref (manager);
202         gtk_widget_show (dialog);
203 }
204
205 /*
206  *  Information dialog
207  */
208
209 static void
210 contact_dialogs_response_cb (GtkDialog *dialog,
211                              gint       response,
212                              GList    **dialogs)
213 {
214         *dialogs = g_list_remove (*dialogs, dialog);
215         gtk_widget_destroy (GTK_WIDGET (dialog));
216 }
217
218 void
219 empathy_contact_information_dialog_show (EmpathyContact *contact,
220                                          GtkWindow      *parent)
221 {
222         GtkWidget *dialog;
223         GtkWidget *button;
224         GtkWidget *contact_widget;
225         GList     *l;
226
227         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
228
229         l = g_list_find_custom (information_dialogs,
230                                 contact,
231                                 (GCompareFunc) contact_dialogs_find);
232         if (l) {
233                 gtk_window_present (GTK_WINDOW (l->data));
234                 return;
235         }
236
237         /* Create dialog */
238         dialog = gtk_dialog_new ();
239         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
240         gtk_window_set_title (GTK_WINDOW (dialog),
241                 empathy_contact_get_alias (contact));
242
243         /* Close button */
244         button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
245         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
246         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
247                                       button,
248                                       GTK_RESPONSE_CLOSE);
249         gtk_widget_set_can_default (button, TRUE);
250         gtk_window_set_default (GTK_WINDOW (dialog), button);
251         gtk_widget_show (button);
252
253         /* Contact info widget */
254         contact_widget = empathy_contact_widget_new (contact,
255                 EMPATHY_CONTACT_WIDGET_SHOW_LOCATION |
256                 EMPATHY_CONTACT_WIDGET_SHOW_DETAILS);
257         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
258         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
259                             contact_widget,
260                             TRUE, TRUE, 0);
261         gtk_widget_show (contact_widget);
262
263         g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
264         information_dialogs = g_list_prepend (information_dialogs, dialog);
265
266         g_signal_connect (dialog, "response",
267                           G_CALLBACK (contact_dialogs_response_cb),
268                           &information_dialogs);
269
270         if (parent) {
271                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
272         }
273
274         gtk_widget_show (dialog);
275 }
276
277 void
278 empathy_contact_edit_dialog_show (EmpathyContact *contact,
279                                   GtkWindow      *parent)
280 {
281         GtkWidget *dialog;
282         GtkWidget *button;
283         GtkWidget *contact_widget;
284         GList     *l;
285
286         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
287
288         l = g_list_find_custom (edit_dialogs,
289                                 contact,
290                                 (GCompareFunc) contact_dialogs_find);
291         if (l) {
292                 gtk_window_present (GTK_WINDOW (l->data));
293                 return;
294         }
295
296         /* Create dialog */
297         dialog = gtk_dialog_new ();
298         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
299         gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Contact Information"));
300
301         /* Close button */
302         button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
303         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
304         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
305                                       button,
306                                       GTK_RESPONSE_CLOSE);
307         gtk_widget_set_can_default (button, TRUE);
308         gtk_window_set_default (GTK_WINDOW (dialog), button);
309         gtk_widget_show (button);
310
311         /* Contact info widget */
312         contact_widget = empathy_contact_widget_new (contact,
313                 EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
314                 EMPATHY_CONTACT_WIDGET_EDIT_GROUPS |
315                 EMPATHY_CONTACT_WIDGET_EDIT_FAVOURITE);
316         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
317         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
318                             contact_widget,
319                             TRUE, TRUE, 0);
320         gtk_widget_show (contact_widget);
321
322         g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
323         edit_dialogs = g_list_prepend (edit_dialogs, dialog);
324
325         g_signal_connect (dialog, "response",
326                           G_CALLBACK (contact_dialogs_response_cb),
327                           &edit_dialogs);
328
329         if (parent) {
330                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
331         }
332
333         gtk_widget_show (dialog);
334 }
335
336 void
337 empathy_contact_personal_dialog_show (GtkWindow *parent)
338 {
339         GtkWidget *button;
340         GtkWidget *contact_widget;
341
342         if (personal_dialog) {
343                 gtk_window_present (GTK_WINDOW (personal_dialog));
344                 return;
345         }
346
347         /* Create dialog */
348         personal_dialog = gtk_dialog_new ();
349         gtk_window_set_resizable (GTK_WINDOW (personal_dialog), FALSE);
350         gtk_window_set_title (GTK_WINDOW (personal_dialog), _("Personal Information"));
351
352         /* Close button */
353         button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
354         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
355         gtk_dialog_add_action_widget (GTK_DIALOG (personal_dialog),
356                                       button,
357                                       GTK_RESPONSE_CLOSE);
358         gtk_widget_set_can_default (button, TRUE);
359         gtk_window_set_default (GTK_WINDOW (personal_dialog), button);
360         gtk_widget_show (button);
361
362         /* Contact info widget */
363         contact_widget = empathy_contact_widget_new (NULL,
364                 EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT |
365                 EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
366                 EMPATHY_CONTACT_WIDGET_EDIT_AVATAR |
367                 EMPATHY_CONTACT_WIDGET_EDIT_DETAILS);
368         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
369         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (personal_dialog))),
370                             contact_widget,
371                             TRUE, TRUE, 0);
372         empathy_contact_widget_set_account_filter (contact_widget,
373                 empathy_account_chooser_filter_is_connected, NULL);
374         gtk_widget_show (contact_widget);
375
376         g_signal_connect (personal_dialog, "response",
377                           G_CALLBACK (gtk_widget_destroy), NULL);
378         g_object_add_weak_pointer (G_OBJECT (personal_dialog),
379                                    (gpointer) &personal_dialog);
380
381         if (parent) {
382                 gtk_window_set_transient_for (GTK_WINDOW (personal_dialog), parent);
383         }
384
385         gtk_widget_show (personal_dialog);
386 }
387
388 /*
389  *  New contact dialog
390  */
391
392 static void
393 can_add_contact_to_account (TpAccount                                 *account,
394                             EmpathyAccountChooserFilterResultCallback  callback,
395                             gpointer                                   callback_data,
396                             gpointer                                   user_data)
397 {
398         EmpathyContactManager *contact_manager;
399         TpConnection          *connection;
400         gboolean               result;
401
402         connection = tp_account_get_connection (account);
403         if (connection == NULL) {
404                 callback (FALSE, callback_data);
405                 return;
406         }
407
408         contact_manager = empathy_contact_manager_dup_singleton ();
409         result = empathy_contact_manager_get_flags_for_connection (
410                 contact_manager, connection) & EMPATHY_CONTACT_LIST_CAN_ADD;
411         g_object_unref (contact_manager);
412
413         callback (result, callback_data);
414 }
415
416 static void
417 new_contact_response_cb (GtkDialog *dialog,
418                          gint       response,
419                          GtkWidget *contact_widget)
420 {
421         EmpathyContactManager *manager;
422         EmpathyContact         *contact;
423
424         manager = empathy_contact_manager_dup_singleton ();
425         contact = empathy_contact_widget_get_contact (contact_widget);
426
427         if (contact && response == GTK_RESPONSE_OK) {
428                 empathy_contact_list_add (EMPATHY_CONTACT_LIST (manager),
429                                           contact, "");
430         }
431
432         new_contact_dialog = NULL;
433         gtk_widget_destroy (GTK_WIDGET (dialog));
434         g_object_unref (manager);
435 }
436
437 void
438 empathy_new_contact_dialog_show (GtkWindow *parent)
439 {
440         empathy_new_contact_dialog_show_with_contact (parent, NULL);
441 }
442
443 void
444 empathy_new_contact_dialog_show_with_contact (GtkWindow *parent,
445                                               EmpathyContact *contact)
446 {
447         GtkWidget *dialog;
448         GtkWidget *button;
449         GtkWidget *contact_widget;
450
451         if (new_contact_dialog) {
452                 gtk_window_present (GTK_WINDOW (new_contact_dialog));
453                 return;
454         }
455
456         /* Create dialog */
457         dialog = gtk_dialog_new ();
458         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
459         gtk_window_set_title (GTK_WINDOW (dialog), _("New Contact"));
460
461         /* Cancel button */
462         button = gtk_button_new_with_label (GTK_STOCK_CANCEL);
463         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
464         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
465                                       button,
466                                       GTK_RESPONSE_CANCEL);
467         gtk_widget_show (button);
468
469         /* Add button */
470         button = gtk_button_new_with_label (GTK_STOCK_ADD);
471         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
472         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
473                                       button,
474                                       GTK_RESPONSE_OK);
475         gtk_widget_show (button);
476
477         /* Contact info widget */
478         contact_widget = empathy_contact_widget_new (contact,
479                                                      EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
480                                                      EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT |
481                                                      EMPATHY_CONTACT_WIDGET_EDIT_ID |
482                                                      EMPATHY_CONTACT_WIDGET_EDIT_GROUPS);
483         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
484         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
485                             contact_widget,
486                             TRUE, TRUE, 0);
487         empathy_contact_widget_set_account_filter (contact_widget,
488                                                    can_add_contact_to_account,
489                                                    NULL);
490         gtk_widget_show (contact_widget);
491
492         new_contact_dialog = dialog;
493
494         g_signal_connect (dialog, "response",
495                           G_CALLBACK (new_contact_response_cb),
496                           contact_widget);
497
498         if (parent) {
499                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
500         }
501
502         gtk_widget_show (dialog);
503 }
504
505 /**
506  * empathy_block_contact_dialog_show:
507  * @parent: the parent of this dialog (or %NULL)
508  * @contact: the contact for this dialog
509  * @abusive: a pointer to store the value of the abusive contact check box
510  *  (or %NULL)
511  *
512  * Returns: %TRUE if the user wishes to block the contact
513  */
514 gboolean
515 empathy_block_contact_dialog_show (GtkWindow      *parent,
516                                    EmpathyContact *contact,
517                                    GdkPixbuf      *avatar,
518                                    gboolean       *abusive)
519 {
520         EmpathyContactManager *manager;
521         EmpathyContactListFlags flags;
522         GtkWidget *dialog;
523         GtkWidget *abusive_check = NULL;
524         int res;
525
526         manager = empathy_contact_manager_dup_singleton ();
527         flags = empathy_contact_manager_get_flags_for_connection (manager,
528                         empathy_contact_get_connection (contact));
529
530         dialog = gtk_message_dialog_new (parent,
531                         GTK_DIALOG_MODAL,
532                         GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
533                         _("Block %s?"),
534                         empathy_contact_get_alias (contact));
535
536         gtk_message_dialog_format_secondary_text (
537                         GTK_MESSAGE_DIALOG (dialog),
538                         _("Are you sure you want to block '%s' from "
539                           "contacting you again?"),
540                         empathy_contact_get_alias (contact));
541         gtk_dialog_add_buttons (GTK_DIALOG (dialog),
542                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
543                         _("_Block"), GTK_RESPONSE_REJECT,
544                         NULL);
545
546         if (avatar != NULL) {
547                 GtkWidget *image = gtk_image_new_from_pixbuf (avatar);
548                 gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
549                 gtk_widget_show (image);
550         }
551
552         /* ask the user if they want to also report the contact as abusive */
553         if (flags & EMPATHY_CONTACT_LIST_CAN_REPORT_ABUSIVE) {
554                 GtkWidget *vbox;
555
556                 vbox = gtk_message_dialog_get_message_area (
557                                 GTK_MESSAGE_DIALOG (dialog));
558                 abusive_check = gtk_check_button_new_with_mnemonic (
559                                 _("_Report this contact as abusive"));
560
561                 gtk_box_pack_start (GTK_BOX (vbox), abusive_check,
562                                     FALSE, TRUE, 0);
563                 gtk_widget_show (abusive_check);
564         }
565
566         res = gtk_dialog_run (GTK_DIALOG (dialog));
567         if (abusive != NULL) {
568                 if (abusive_check != NULL) {
569                         *abusive = gtk_toggle_button_get_active (
570                                         GTK_TOGGLE_BUTTON (abusive_check));
571                 } else {
572                         *abusive = FALSE;
573                 }
574         }
575
576         gtk_widget_destroy (dialog);
577         g_object_unref (manager);
578
579         return res == GTK_RESPONSE_REJECT;
580 }