b65219775a1b0f4de01b0364e8f779517714594f
[empathy.git] / libempathy-gtk / empathy-account-widget.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2006-2007 Imendio AB
4  * Copyright (C) 2007 Collabora Ltd.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  * 
21  * Authors: Xavier Claessens <xclaesse@gmail.com>
22  *          Martyn Russell <martyn@imendio.com>
23  */
24
25 #include <config.h>
26
27 #include <string.h>
28
29 #include <gtk/gtk.h>
30 #include <glib/gi18n.h>
31
32 #include <libmissioncontrol/mc-account.h>
33 #include <libmissioncontrol/mc-protocol.h>
34
35 #include <libempathy/empathy-debug.h>
36
37 #include "empathy-account-widget.h"
38 #include "empathy-ui-utils.h"
39
40 #define DEBUG_DOMAIN "AccountWidget"
41
42 static gboolean 
43 account_widget_entry_focus_cb (GtkWidget     *widget,
44                                GdkEventFocus *event,
45                                McAccount     *account)
46 {
47         const gchar *str;
48         const gchar *param_name;
49
50         str = gtk_entry_get_text (GTK_ENTRY (widget));
51         param_name = g_object_get_data (G_OBJECT (widget), "param_name");
52
53         if (G_STR_EMPTY (str)) {
54                 gchar *value = NULL;
55
56                 mc_account_unset_param (account, param_name);
57                 mc_account_get_param_string (account, param_name, &value);
58                 empathy_debug (DEBUG_DOMAIN, "Unset %s and restore to %s", param_name, value);
59                 gtk_entry_set_text (GTK_ENTRY (widget), value ? value : "");
60                 g_free (value);
61         } else {
62                 empathy_debug (DEBUG_DOMAIN, "Setting %s to %s", param_name, str);
63                 mc_account_set_param_string (account, param_name, str);
64         }
65
66         return FALSE;
67 }
68
69 static void
70 account_widget_int_changed_cb (GtkWidget *widget,
71                                McAccount *account)
72 {
73         const gchar *param_name;
74         gint         value;
75
76         value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
77         param_name = g_object_get_data (G_OBJECT (widget), "param_name");
78
79         if (value == 0) {
80                 mc_account_unset_param (account, param_name);
81                 mc_account_get_param_int (account, param_name, &value);
82                 empathy_debug (DEBUG_DOMAIN, "Unset %s and restore to %d", param_name, value);
83                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
84         } else {
85                 empathy_debug (DEBUG_DOMAIN, "Setting %s to %d", param_name, value);
86                 mc_account_set_param_int (account, param_name, value);
87         }
88 }
89
90 static void  
91 account_widget_checkbutton_toggled_cb (GtkWidget *widget,
92                                        McAccount *account)
93 {
94         gboolean     value;
95         gboolean     default_value;
96         const gchar *param_name;
97
98         value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
99         param_name = g_object_get_data (G_OBJECT (widget), "param_name");
100
101         /* FIXME: This is ugly! checkbox don't have a "not-set" value so we
102          * always unset the param and set the value if different from the
103          * default value. */
104         mc_account_unset_param (account, param_name);
105         mc_account_get_param_boolean (account, param_name, &default_value);
106
107         if (default_value == value) {
108                 empathy_debug (DEBUG_DOMAIN, "Unset %s and restore to %d", param_name, default_value);
109         } else {
110                 empathy_debug (DEBUG_DOMAIN, "Setting %s to %d", param_name, value);
111                 mc_account_set_param_boolean (account, param_name, value);
112         }
113 }
114
115 static void
116 account_widget_forget_clicked_cb (GtkWidget *button,
117                                   GtkWidget *entry)
118 {
119         McAccount   *account;
120         const gchar *param_name;
121
122         param_name = g_object_get_data (G_OBJECT (entry), "param_name");
123         account = g_object_get_data (G_OBJECT (entry), "account");
124
125         empathy_debug (DEBUG_DOMAIN, "Unset %s", param_name);
126         mc_account_unset_param (account, param_name);
127         gtk_entry_set_text (GTK_ENTRY (entry), "");
128 }
129
130 static void
131 account_widget_password_changed_cb (GtkWidget *entry,
132                                     GtkWidget *button)
133 {
134         const gchar *str;
135
136         str = gtk_entry_get_text (GTK_ENTRY (entry));
137         gtk_widget_set_sensitive (button, !G_STR_EMPTY (str));
138 }
139
140 static void  
141 account_widget_jabber_ssl_toggled_cb (GtkWidget *checkbutton_ssl,
142                                       GtkWidget *spinbutton_port)
143 {
144         McAccount *account;
145         gboolean   value;
146         gint       port = 0;
147
148         value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_ssl));
149         account = g_object_get_data (G_OBJECT (spinbutton_port), "account");
150         mc_account_get_param_int (account, "port", &port);
151
152         if (value) {
153                 if (port == 5222 || port == 0) {
154                         port = 5223;
155                 }
156         } else {
157                 if (port == 5223 || port == 0) {
158                         port = 5222;
159                 }
160         }
161
162         gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_port), port);
163 }
164
165 static void
166 account_widget_setup_widget (GtkWidget   *widget,
167                              McAccount   *account,
168                              const gchar *param_name)
169 {
170         g_object_set_data_full (G_OBJECT (widget), "param_name", 
171                                 g_strdup (param_name), g_free);
172         g_object_set_data_full (G_OBJECT (widget), "account", 
173                                 g_object_ref (account), g_object_unref);
174
175         if (GTK_IS_SPIN_BUTTON (widget)) {
176                 gint value = 0;
177
178                 mc_account_get_param_int (account, param_name, &value);
179                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
180
181                 g_signal_connect (widget, "value-changed",
182                                   G_CALLBACK (account_widget_int_changed_cb),
183                                   account);
184         }
185         else if (GTK_IS_ENTRY (widget)) {
186                 gchar *str = NULL;
187
188                 mc_account_get_param_string (account, param_name, &str);
189                 gtk_entry_set_text (GTK_ENTRY (widget), str ? str : "");
190                 g_free (str);
191
192                 if (strstr (param_name, "password")) {
193                         gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE);
194                 }
195
196                 g_signal_connect (widget, "focus-out-event",
197                                   G_CALLBACK (account_widget_entry_focus_cb),
198                                   account);
199         }
200         else if (GTK_IS_TOGGLE_BUTTON (widget)) {
201                 gboolean value = FALSE;
202
203                 mc_account_get_param_boolean (account, param_name, &value);
204                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
205
206                 g_signal_connect (widget, "toggled",
207                                   G_CALLBACK (account_widget_checkbutton_toggled_cb),
208                                   account);
209         } else {
210                 empathy_debug (DEBUG_DOMAIN,
211                                "Unknown type of widget for param %s",
212                                param_name);
213         }
214 }
215
216 static gchar *
217 account_widget_generic_format_param_name (const gchar *param_name)
218 {
219         gchar *str;
220         gchar *p;
221
222         str = g_strdup (param_name);
223         
224         if (str && g_ascii_isalpha (str[0])) {
225                 str[0] = g_ascii_toupper (str[0]);
226         }
227         
228         while ((p = strchr (str, '-')) != NULL) {
229                 if (p[1] != '\0' && g_ascii_isalpha (p[1])) {
230                         p[0] = ' ';
231                         p[1] = g_ascii_toupper (p[1]);
232                 }
233
234                 p++;
235         }
236         
237         return str;
238 }
239
240 static void
241 accounts_widget_generic_setup (McAccount *account,
242                                GtkWidget *table_settings)
243 {
244         McProtocol *protocol;
245         McProfile  *profile;
246         GSList     *params, *l;
247         guint       n_rows = 0;
248
249         profile = mc_account_get_profile (account);
250         protocol = mc_profile_get_protocol (profile);
251
252         if (!protocol) {
253                 /* The CM is not installed, MC shouldn't list them
254                  * see SF bug #1688779
255                  * FIXME: We should display something asking the user to 
256                  * install the CM
257                  */
258                 g_object_unref (profile);
259                 return;
260         }
261
262         params = mc_protocol_get_params (protocol);
263
264         for (l = params; l; l = l->next) {
265                 McProtocolParam *param;
266                 GtkWidget       *widget = NULL;
267                 gchar           *param_name_formatted;
268
269                 param = l->data;
270                 param_name_formatted = account_widget_generic_format_param_name (param->name);
271                 gtk_table_resize (GTK_TABLE (table_settings), ++n_rows, 2);
272
273                 if (param->signature[0] == 's') {
274                         gchar *str;
275
276                         str = g_strdup_printf (_("%s:"), param_name_formatted);
277                         widget = gtk_label_new (str);
278                         gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
279                         g_free (str);
280
281                         gtk_table_attach (GTK_TABLE (table_settings),
282                                           widget,
283                                           0, 1,
284                                           n_rows - 1, n_rows,
285                                           GTK_FILL, 0,
286                                           0, 0);
287
288                         widget = gtk_entry_new ();
289                         gtk_table_attach (GTK_TABLE (table_settings),
290                                           widget,
291                                           1, 2,
292                                           n_rows - 1, n_rows,
293                                           GTK_FILL | GTK_EXPAND, 0,
294                                           0, 0);
295                 }
296                 /* int types: ynqiuxt. double type is 'd' */
297                 else if (param->signature[0] == 'y' ||
298                          param->signature[0] == 'n' ||
299                          param->signature[0] == 'q' ||
300                          param->signature[0] == 'i' ||
301                          param->signature[0] == 'u' ||
302                          param->signature[0] == 'x' ||
303                          param->signature[0] == 't' ||
304                          param->signature[0] == 'd') {
305                         gchar   *str = NULL;
306                         gdouble  minint = 0;
307                         gdouble  maxint = 0;
308                         gdouble  step = 1;
309
310                         switch (param->signature[0]) {
311                         case 'y': minint = G_MININT8;  maxint = G_MAXINT8;   break;
312                         case 'n': minint = G_MININT16; maxint = G_MAXINT16;  break;
313                         case 'q': minint = 0;          maxint = G_MAXUINT16; break;
314                         case 'i': minint = G_MININT32; maxint = G_MAXINT32;  break;
315                         case 'u': minint = 0;          maxint = G_MAXUINT32; break;
316                         case 'x': minint = G_MININT64; maxint = G_MAXINT64;  break;
317                         case 't': minint = 0;          maxint = G_MAXUINT64; break;
318                         case 'd': minint = G_MININT32; maxint = G_MAXINT32; step = 0.1; break;
319                         }
320
321                         str = g_strdup_printf (_("%s:"), param_name_formatted);
322                         widget = gtk_label_new (str);
323                         gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
324                         g_free (str);
325
326                         gtk_table_attach (GTK_TABLE (table_settings),
327                                           widget,
328                                           0, 1,
329                                           n_rows - 1, n_rows,
330                                           GTK_FILL, 0,
331                                           0, 0);
332
333                         widget = gtk_spin_button_new_with_range (minint, maxint, step);
334                         gtk_table_attach (GTK_TABLE (table_settings),
335                                           widget,
336                                           1, 2,
337                                           n_rows - 1, n_rows,
338                                           GTK_FILL | GTK_EXPAND, 0,
339                                           0, 0);
340                 }
341                 else if (param->signature[0] == 'b') {
342                         widget = gtk_check_button_new_with_label (param_name_formatted);
343                         gtk_table_attach (GTK_TABLE (table_settings),
344                                           widget,
345                                           0, 2,
346                                           n_rows - 1, n_rows,
347                                           GTK_FILL | GTK_EXPAND, 0,
348                                           0, 0);
349                 } else {
350                         empathy_debug (DEBUG_DOMAIN,
351                                        "Unknown signature for param %s: %s",
352                                        param_name_formatted, param->signature);
353                 }
354
355                 if (widget) {
356                         account_widget_setup_widget (widget, account, param->name);
357                 }
358
359                 g_free (param_name_formatted);
360         }
361
362         g_slist_free (params);
363         g_object_unref (profile);
364         g_object_unref (protocol);
365 }
366
367 static void
368 account_widget_handle_params_valist (McAccount   *account,
369                                      GladeXML    *gui,
370                                      const gchar *first_widget_name,
371                                      va_list      args)
372 {
373         GtkWidget   *widget;
374         const gchar *widget_name;
375
376         for (widget_name = first_widget_name; widget_name; widget_name = va_arg (args, gchar*)) {
377                 const gchar *param_name;
378
379                 param_name = va_arg (args, gchar*);
380
381                 widget = glade_xml_get_widget (gui, widget_name);
382
383                 if (!widget) {
384                         g_warning ("Glade is missing widget '%s'.", widget_name);
385                         continue;
386                 }
387
388                 account_widget_setup_widget (widget, account, param_name);
389         }
390 }
391
392 void
393 empathy_account_widget_handle_params (McAccount   *account,
394                                       GladeXML    *gui,
395                                       const gchar *first_widget_name,
396                                       ...)
397 {
398         va_list args;
399
400         g_return_if_fail (MC_IS_ACCOUNT (account));
401
402         va_start (args, first_widget_name);
403         account_widget_handle_params_valist (account, gui,
404                                              first_widget_name,
405                                              args);
406         va_end (args);
407 }
408
409 void
410 emapthy_account_widget_add_forget_button (McAccount   *account,
411                                           GladeXML    *glade,
412                                           const gchar *button,
413                                           const gchar *entry)
414 {
415         GtkWidget *button_forget;
416         GtkWidget *entry_password;
417         gchar     *password = NULL;
418         
419         button_forget = glade_xml_get_widget (glade, button);
420         entry_password = glade_xml_get_widget (glade, entry);
421
422         mc_account_get_param_string (account, "password", &password);
423         gtk_widget_set_sensitive (button_forget, !G_STR_EMPTY (password));
424         g_free (password);
425
426         g_signal_connect (button_forget, "clicked",
427                           G_CALLBACK (account_widget_forget_clicked_cb),
428                           entry_password);
429         g_signal_connect (entry_password, "changed",
430                           G_CALLBACK (account_widget_password_changed_cb),
431                           button_forget);
432 }
433
434 GtkWidget *
435 empathy_account_widget_generic_new (McAccount *account)
436 {
437         GtkWidget *table_settings;
438         GtkWidget *sw;
439
440         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
441
442         table_settings = gtk_table_new (0, 2, FALSE);
443         gtk_table_set_row_spacings (GTK_TABLE (table_settings), 6);
444         gtk_table_set_col_spacings (GTK_TABLE (table_settings), 6);
445         sw = gtk_scrolled_window_new (NULL, NULL);
446         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
447                                         GTK_POLICY_AUTOMATIC,
448                                         GTK_POLICY_AUTOMATIC);
449         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw),
450                                                table_settings);
451         
452         accounts_widget_generic_setup (account, table_settings);
453
454         gtk_widget_show_all (sw);
455
456         return sw;
457 }
458
459 GtkWidget *
460 empathy_account_widget_salut_new (McAccount *account)
461 {
462         GladeXML  *glade;
463         GtkWidget *widget;
464
465         glade = empathy_glade_get_file ("empathy-account-widget-salut.glade",
466                                         "vbox_salut_settings",
467                                         NULL,
468                                         "vbox_salut_settings", &widget,
469                                         NULL);
470
471         empathy_account_widget_handle_params (account, glade,
472                         "entry_published", "published-name",
473                         "entry_nickname", "nickname",
474                         "entry_first_name", "first-name",
475                         "entry_last_name", "last-name",
476                         "entry_email", "email",
477                         "entry_jid", "jid",
478                         NULL);
479
480         g_object_unref (glade);
481
482         gtk_widget_show (widget);
483
484         return widget;
485 }
486
487 GtkWidget *
488 empathy_account_widget_msn_new (McAccount *account)
489 {
490         GladeXML  *glade;
491         GtkWidget *widget;
492
493         glade = empathy_glade_get_file ("empathy-account-widget-msn.glade",
494                                         "vbox_msn_settings",
495                                         NULL,
496                                         "vbox_msn_settings", &widget,
497                                         NULL);
498
499         empathy_account_widget_handle_params (account, glade,
500                         "entry_id", "account",
501                         "entry_password", "password",
502                         "entry_server", "server",
503                         "spinbutton_port", "port",
504                         NULL);
505
506         emapthy_account_widget_add_forget_button (account, glade,
507                                                   "button_forget",
508                                                   "entry_password");
509
510         g_object_unref (glade);
511
512         gtk_widget_show (widget);
513
514         return widget;
515 }
516
517 GtkWidget *
518 empathy_account_widget_jabber_new (McAccount *account)
519 {
520         GladeXML  *glade;
521         GtkWidget *widget;
522         GtkWidget *spinbutton_port;
523         GtkWidget *checkbutton_ssl;
524
525         glade = empathy_glade_get_file ("empathy-account-widget-jabber.glade",
526                                         "vbox_jabber_settings",
527                                         NULL,
528                                         "vbox_jabber_settings", &widget,
529                                         "spinbutton_port", &spinbutton_port,
530                                         "checkbutton_ssl", &checkbutton_ssl,
531                                         NULL);
532
533         empathy_account_widget_handle_params (account, glade,
534                         "entry_id", "account",
535                         "entry_password", "password",
536                         "entry_resource", "resource",
537                         "entry_server", "server",
538                         "spinbutton_port", "port",
539                         "spinbutton_priority", "priority",
540                         "checkbutton_ssl", "old-ssl",
541                         "checkbutton_ignore_ssl_errors", "ignore-ssl-errors",
542                         "checkbutton_encryption", "require-encryption",
543                         NULL);
544
545         emapthy_account_widget_add_forget_button (account, glade,
546                                                   "button_forget",
547                                                   "entry_password");
548
549         g_signal_connect (checkbutton_ssl, "toggled",
550                           G_CALLBACK (account_widget_jabber_ssl_toggled_cb),
551                           spinbutton_port);
552
553         g_object_unref (glade);
554
555         gtk_widget_show (widget);
556
557         return widget;
558 }
559
560 GtkWidget *
561 empathy_account_widget_icq_new (McAccount *account)
562 {
563         GladeXML  *glade;
564         GtkWidget *widget;
565         GtkWidget *spinbutton_port;
566
567         glade = empathy_glade_get_file ("empathy-account-widget-icq.glade",
568                                         "vbox_icq_settings",
569                                         NULL,
570                                         "vbox_icq_settings", &widget,
571                                         "spinbutton_port", &spinbutton_port,
572                                         NULL);
573
574         empathy_account_widget_handle_params (account, glade,
575                         "entry_uin", "account",
576                         "entry_password", "password",
577                         "entry_server", "server",
578                         "spinbutton_port", "port",
579                         "entry_charset", "charset",
580                         NULL);
581
582         emapthy_account_widget_add_forget_button (account, glade,
583                                                   "button_forget",
584                                                   "entry_password");
585
586         g_object_unref (glade);
587
588         gtk_widget_show (widget);
589
590         return widget;
591 }
592