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