]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-dialogs.c
contact-dialogs: 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                         TpContact *tp_contact;
94
95                         empathy_contact_list_remove (
96                                         EMPATHY_CONTACT_LIST (manager),
97                                         contact, "");
98
99                         tp_contact = empathy_contact_get_tp_contact (contact);
100
101                         tp_contact_block_async (tp_contact, abusive, NULL, NULL);
102                 } else {
103                         /* if they don't confirm, return back to the
104                          * first dialog */
105                         goto finally;
106                 }
107         }
108
109         subscription_dialogs = g_list_remove (subscription_dialogs, dialog);
110         gtk_widget_destroy (GTK_WIDGET (dialog));
111
112 finally:
113         g_object_unref (manager);
114 }
115
116 void
117 empathy_subscription_dialog_show (EmpathyContact *contact,
118                                   const gchar *message,
119                                   GtkWindow     *parent)
120 {
121         GtkBuilder *gui;
122         GtkWidget *dialog;
123         GtkWidget *hbox_subscription;
124         GtkWidget *vbox;
125         GtkWidget *contact_widget;
126         GtkWidget *block_user_button;
127         GList     *l;
128         gchar     *filename;
129         TpConnection *conn;
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         conn = empathy_contact_get_connection (contact);
192
193         if (tp_proxy_has_interface_by_id (conn,
194                 TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_BLOCKING))
195                 gtk_widget_show (block_user_button);
196
197         if (parent) {
198                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
199         }
200
201         gtk_widget_show (dialog);
202 }
203
204 /*
205  *  Information dialog
206  */
207
208 static void
209 contact_dialogs_response_cb (GtkDialog *dialog,
210                              gint       response,
211                              GList    **dialogs)
212 {
213         *dialogs = g_list_remove (*dialogs, dialog);
214         gtk_widget_destroy (GTK_WIDGET (dialog));
215 }
216
217 void
218 empathy_contact_information_dialog_show (EmpathyContact *contact,
219                                          GtkWindow      *parent)
220 {
221         GtkWidget *dialog;
222         GtkWidget *button;
223         GtkWidget *contact_widget;
224         GList     *l;
225
226         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
227
228         l = g_list_find_custom (information_dialogs,
229                                 contact,
230                                 (GCompareFunc) contact_dialogs_find);
231         if (l) {
232                 gtk_window_present (GTK_WINDOW (l->data));
233                 return;
234         }
235
236         /* Create dialog */
237         dialog = gtk_dialog_new ();
238         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
239         gtk_window_set_title (GTK_WINDOW (dialog),
240                 empathy_contact_get_alias (contact));
241
242         /* Close button */
243         button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
244         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
245         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
246                                       button,
247                                       GTK_RESPONSE_CLOSE);
248         gtk_widget_set_can_default (button, TRUE);
249         gtk_window_set_default (GTK_WINDOW (dialog), button);
250         gtk_widget_show (button);
251
252         /* Contact info widget */
253         contact_widget = empathy_contact_widget_new (contact,
254                 EMPATHY_CONTACT_WIDGET_SHOW_LOCATION |
255                 EMPATHY_CONTACT_WIDGET_SHOW_DETAILS);
256         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
257         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
258                             contact_widget,
259                             TRUE, TRUE, 0);
260         gtk_widget_show (contact_widget);
261
262         g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
263         information_dialogs = g_list_prepend (information_dialogs, dialog);
264
265         g_signal_connect (dialog, "response",
266                           G_CALLBACK (contact_dialogs_response_cb),
267                           &information_dialogs);
268
269         if (parent) {
270                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
271         }
272
273         gtk_widget_show (dialog);
274 }
275
276 void
277 empathy_contact_edit_dialog_show (EmpathyContact *contact,
278                                   GtkWindow      *parent)
279 {
280         GtkWidget *dialog;
281         GtkWidget *button;
282         GtkWidget *contact_widget;
283         GList     *l;
284
285         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
286
287         l = g_list_find_custom (edit_dialogs,
288                                 contact,
289                                 (GCompareFunc) contact_dialogs_find);
290         if (l) {
291                 gtk_window_present (GTK_WINDOW (l->data));
292                 return;
293         }
294
295         /* Create dialog */
296         dialog = gtk_dialog_new ();
297         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
298         gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Contact Information"));
299
300         /* Close button */
301         button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
302         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
303         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
304                                       button,
305                                       GTK_RESPONSE_CLOSE);
306         gtk_widget_set_can_default (button, TRUE);
307         gtk_window_set_default (GTK_WINDOW (dialog), button);
308         gtk_widget_show (button);
309
310         /* Contact info widget */
311         contact_widget = empathy_contact_widget_new (contact,
312                 EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
313                 EMPATHY_CONTACT_WIDGET_EDIT_GROUPS |
314                 EMPATHY_CONTACT_WIDGET_EDIT_FAVOURITE);
315         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
316         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
317                             contact_widget,
318                             TRUE, TRUE, 0);
319         gtk_widget_show (contact_widget);
320
321         g_object_set_data (G_OBJECT (dialog), "contact_widget", contact_widget);
322         edit_dialogs = g_list_prepend (edit_dialogs, dialog);
323
324         g_signal_connect (dialog, "response",
325                           G_CALLBACK (contact_dialogs_response_cb),
326                           &edit_dialogs);
327
328         if (parent) {
329                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
330         }
331
332         gtk_widget_show (dialog);
333 }
334
335 void
336 empathy_contact_personal_dialog_show (GtkWindow *parent)
337 {
338         GtkWidget *button;
339         GtkWidget *contact_widget;
340
341         if (personal_dialog) {
342                 gtk_window_present (GTK_WINDOW (personal_dialog));
343                 return;
344         }
345
346         /* Create dialog */
347         personal_dialog = gtk_dialog_new ();
348         gtk_window_set_resizable (GTK_WINDOW (personal_dialog), FALSE);
349         gtk_window_set_title (GTK_WINDOW (personal_dialog), _("Personal Information"));
350
351         /* Close button */
352         button = gtk_button_new_with_label (GTK_STOCK_CLOSE);
353         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
354         gtk_dialog_add_action_widget (GTK_DIALOG (personal_dialog),
355                                       button,
356                                       GTK_RESPONSE_CLOSE);
357         gtk_widget_set_can_default (button, TRUE);
358         gtk_window_set_default (GTK_WINDOW (personal_dialog), button);
359         gtk_widget_show (button);
360
361         /* Contact info widget */
362         contact_widget = empathy_contact_widget_new (NULL,
363                 EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT |
364                 EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
365                 EMPATHY_CONTACT_WIDGET_EDIT_AVATAR |
366                 EMPATHY_CONTACT_WIDGET_EDIT_DETAILS);
367         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
368         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (personal_dialog))),
369                             contact_widget,
370                             TRUE, TRUE, 0);
371         empathy_contact_widget_set_account_filter (contact_widget,
372                 empathy_account_chooser_filter_is_connected, NULL);
373         gtk_widget_show (contact_widget);
374
375         g_signal_connect (personal_dialog, "response",
376                           G_CALLBACK (gtk_widget_destroy), NULL);
377         g_object_add_weak_pointer (G_OBJECT (personal_dialog),
378                                    (gpointer) &personal_dialog);
379
380         if (parent) {
381                 gtk_window_set_transient_for (GTK_WINDOW (personal_dialog), parent);
382         }
383
384         gtk_widget_show (personal_dialog);
385 }
386
387 /*
388  *  New contact dialog
389  */
390
391 static void
392 can_add_contact_to_account (TpAccount                                 *account,
393                             EmpathyAccountChooserFilterResultCallback  callback,
394                             gpointer                                   callback_data,
395                             gpointer                                   user_data)
396 {
397         EmpathyContactManager *contact_manager;
398         TpConnection          *connection;
399         gboolean               result;
400
401         connection = tp_account_get_connection (account);
402         if (connection == NULL) {
403                 callback (FALSE, callback_data);
404                 return;
405         }
406
407         contact_manager = empathy_contact_manager_dup_singleton ();
408         result = empathy_contact_manager_get_flags_for_connection (
409                 contact_manager, connection) & EMPATHY_CONTACT_LIST_CAN_ADD;
410         g_object_unref (contact_manager);
411
412         callback (result, callback_data);
413 }
414
415 static void
416 new_contact_response_cb (GtkDialog *dialog,
417                          gint       response,
418                          GtkWidget *contact_widget)
419 {
420         EmpathyContactManager *manager;
421         EmpathyContact         *contact;
422
423         manager = empathy_contact_manager_dup_singleton ();
424         contact = empathy_contact_widget_get_contact (contact_widget);
425
426         if (contact && response == GTK_RESPONSE_OK) {
427                 empathy_contact_list_add (EMPATHY_CONTACT_LIST (manager),
428                                           contact, "");
429         }
430
431         new_contact_dialog = NULL;
432         gtk_widget_destroy (GTK_WIDGET (dialog));
433         g_object_unref (manager);
434 }
435
436 void
437 empathy_new_contact_dialog_show (GtkWindow *parent)
438 {
439         empathy_new_contact_dialog_show_with_contact (parent, NULL);
440 }
441
442 void
443 empathy_new_contact_dialog_show_with_contact (GtkWindow *parent,
444                                               EmpathyContact *contact)
445 {
446         GtkWidget *dialog;
447         GtkWidget *button;
448         GtkWidget *contact_widget;
449
450         if (new_contact_dialog) {
451                 gtk_window_present (GTK_WINDOW (new_contact_dialog));
452                 return;
453         }
454
455         /* Create dialog */
456         dialog = gtk_dialog_new ();
457         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
458         gtk_window_set_title (GTK_WINDOW (dialog), _("New Contact"));
459
460         /* Cancel button */
461         button = gtk_button_new_with_label (GTK_STOCK_CANCEL);
462         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
463         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
464                                       button,
465                                       GTK_RESPONSE_CANCEL);
466         gtk_widget_show (button);
467
468         /* Add button */
469         button = gtk_button_new_with_label (GTK_STOCK_ADD);
470         gtk_button_set_use_stock (GTK_BUTTON (button), TRUE);
471         gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
472                                       button,
473                                       GTK_RESPONSE_OK);
474         gtk_widget_show (button);
475
476         /* Contact info widget */
477         contact_widget = empathy_contact_widget_new (contact,
478                                                      EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
479                                                      EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT |
480                                                      EMPATHY_CONTACT_WIDGET_EDIT_ID |
481                                                      EMPATHY_CONTACT_WIDGET_EDIT_GROUPS);
482         gtk_container_set_border_width (GTK_CONTAINER (contact_widget), 8);
483         gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
484                             contact_widget,
485                             TRUE, TRUE, 0);
486         empathy_contact_widget_set_account_filter (contact_widget,
487                                                    can_add_contact_to_account,
488                                                    NULL);
489         gtk_widget_show (contact_widget);
490
491         new_contact_dialog = dialog;
492
493         g_signal_connect (dialog, "response",
494                           G_CALLBACK (new_contact_response_cb),
495                           contact_widget);
496
497         if (parent) {
498                 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
499         }
500
501         gtk_widget_show (dialog);
502 }
503
504 /**
505  * empathy_block_contact_dialog_show:
506  * @parent: the parent of this dialog (or %NULL)
507  * @contact: the contact for this dialog
508  * @abusive: a pointer to store the value of the abusive contact check box
509  *  (or %NULL)
510  *
511  * Returns: %TRUE if the user wishes to block the contact
512  */
513 gboolean
514 empathy_block_contact_dialog_show (GtkWindow      *parent,
515                                    EmpathyContact *contact,
516                                    GdkPixbuf      *avatar,
517                                    gboolean       *abusive)
518 {
519         GtkWidget *dialog;
520         GtkWidget *abusive_check = NULL;
521         int res;
522         TpConnection *conn;
523
524         dialog = gtk_message_dialog_new (parent,
525                         GTK_DIALOG_MODAL,
526                         GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
527                         _("Block %s?"),
528                         empathy_contact_get_alias (contact));
529
530         gtk_message_dialog_format_secondary_text (
531                         GTK_MESSAGE_DIALOG (dialog),
532                         _("Are you sure you want to block '%s' from "
533                           "contacting you again?"),
534                         empathy_contact_get_alias (contact));
535         gtk_dialog_add_buttons (GTK_DIALOG (dialog),
536                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
537                         _("_Block"), GTK_RESPONSE_REJECT,
538                         NULL);
539
540         if (avatar != NULL) {
541                 GtkWidget *image = gtk_image_new_from_pixbuf (avatar);
542                 gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
543                 gtk_widget_show (image);
544         }
545
546         conn = empathy_contact_get_connection (contact);
547
548         /* ask the user if they want to also report the contact as abusive */
549         if (tp_connection_can_report_abusive (conn)) {
550                 GtkWidget *vbox;
551
552                 vbox = gtk_message_dialog_get_message_area (
553                                 GTK_MESSAGE_DIALOG (dialog));
554                 abusive_check = gtk_check_button_new_with_mnemonic (
555                                 _("_Report this contact as abusive"));
556
557                 gtk_box_pack_start (GTK_BOX (vbox), abusive_check,
558                                     FALSE, TRUE, 0);
559                 gtk_widget_show (abusive_check);
560         }
561
562         res = gtk_dialog_run (GTK_DIALOG (dialog));
563         if (abusive != NULL) {
564                 if (abusive_check != NULL) {
565                         *abusive = gtk_toggle_button_get_active (
566                                         GTK_TOGGLE_BUTTON (abusive_check));
567                 } else {
568                         *abusive = FALSE;
569                 }
570         }
571
572         gtk_widget_destroy (dialog);
573
574         return res == GTK_RESPONSE_REJECT;
575 }