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