]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-account-widget.c
Add a generic UI to make easy building UI for protocol specific settings. Port empath...
[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 (GTK_SPIN_BUTTON (widget));
77         param_name = g_object_get_data (G_OBJECT (widget), "param_name");
78
79         if (value == 0) {
80                 gint val;
81
82                 mc_account_unset_param (account, param_name);
83                 mc_account_get_param_int (account, param_name, &val);
84                 empathy_debug (DEBUG_DOMAIN, "Unset %s and restore to %d", param_name, val);
85                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), val);
86         } else {
87                 empathy_debug (DEBUG_DOMAIN, "Setting %s to %d", param_name, (gint) value);
88                 mc_account_set_param_int (account, param_name, (gint) value);
89         }
90 }
91
92 static void  
93 account_widget_checkbutton_toggled_cb (GtkWidget *widget,
94                                        McAccount *account)
95 {
96         gboolean     value;
97         gboolean     default_value;
98         const gchar *param_name;
99
100         value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
101         param_name = g_object_get_data (G_OBJECT (widget), "param_name");
102
103         /* FIXME: This is ugly! checkbox don't have a "not-set" value so we
104          * always unset the param and set the value if different from the
105          * default value. */
106         mc_account_unset_param (account, param_name);
107         mc_account_get_param_boolean (account, param_name, &default_value);
108
109         if (default_value == value) {
110                 empathy_debug (DEBUG_DOMAIN, "Unset %s and restore to %d", param_name, default_value);
111         } else {
112                 empathy_debug (DEBUG_DOMAIN, "Setting %s to %d", param_name, value);
113                 mc_account_set_param_boolean (account, param_name, value);
114         }
115 }
116
117 static void
118 account_widget_forget_clicked_cb (GtkWidget *button,
119                                   GtkWidget *entry)
120 {
121         McAccount   *account;
122         const gchar *param_name;
123
124         param_name = g_object_get_data (G_OBJECT (entry), "param_name");
125         account = g_object_get_data (G_OBJECT (entry), "account");
126
127         empathy_debug (DEBUG_DOMAIN, "Unset %s", param_name);
128         mc_account_unset_param (account, param_name);
129         gtk_entry_set_text (GTK_ENTRY (entry), "");
130 }
131
132 static void
133 account_widget_password_changed_cb (GtkWidget *entry,
134                                     GtkWidget *button)
135 {
136         const gchar *str;
137
138         str = gtk_entry_get_text (GTK_ENTRY (entry));
139         gtk_widget_set_sensitive (button, !G_STR_EMPTY (str));
140 }
141
142 static void  
143 account_widget_jabber_ssl_toggled_cb (GtkWidget *checkbutton_ssl,
144                                       GtkWidget *spinbutton_port)
145 {
146         McAccount *account;
147         gboolean   value;
148         gint       port = 0;
149
150         value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_ssl));
151         account = g_object_get_data (G_OBJECT (spinbutton_port), "account");
152         mc_account_get_param_int (account, "port", &port);
153
154         if (value) {
155                 if (port == 5222 || port == 0) {
156                         port = 5223;
157                 }
158         } else {
159                 if (port == 5223 || port == 0) {
160                         port = 5222;
161                 }
162         }
163
164         gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_port), port);
165 }
166
167 static void
168 account_widget_destroy_cb (GtkWidget *widget,
169                            McAccount *account)
170 {
171         empathy_debug (DEBUG_DOMAIN, "destroyed!");
172         g_object_unref (account);
173 }
174
175 static void
176 account_widget_setup_widget (GtkWidget   *widget,
177                              McAccount   *account,
178                              const gchar *param_name)
179 {
180         g_object_set_data_full (G_OBJECT (widget), "param_name", 
181                                 g_strdup (param_name), g_free);
182
183         if (GTK_IS_SPIN_BUTTON (widget)) {
184                 gint value = 0;
185
186                 mc_account_get_param_int (account, param_name, &value);
187                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
188
189                 g_signal_connect (widget, "value-changed",
190                                   G_CALLBACK (account_widget_int_changed_cb),
191                                   account);
192         }
193         else if (GTK_IS_ENTRY (widget)) {
194                 gchar *str = NULL;
195
196                 mc_account_get_param_string (account, param_name, &str);
197                 gtk_entry_set_text (GTK_ENTRY (widget), str ? str : "");
198                 g_free (str);
199
200                 if (strstr (param_name, "password")) {
201                         gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE);
202                 }
203
204                 g_signal_connect (widget, "focus-out-event",
205                                   G_CALLBACK (account_widget_entry_focus_cb),
206                                   account);
207         }
208         else if (GTK_IS_TOGGLE_BUTTON (widget)) {
209                 gboolean value = FALSE;
210
211                 mc_account_get_param_boolean (account, param_name, &value);
212                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
213
214                 g_signal_connect (widget, "toggled",
215                                   G_CALLBACK (account_widget_checkbutton_toggled_cb),
216                                   account);
217         } else {
218                 empathy_debug (DEBUG_DOMAIN,
219                                "Unknown type of widget for param %s",
220                                param_name);
221         }
222 }
223
224 static gchar *
225 account_widget_generic_format_param_name (const gchar *param_name)
226 {
227         gchar *str;
228         gchar *p;
229
230         str = g_strdup (param_name);
231         
232         if (str && g_ascii_isalpha (str[0])) {
233                 str[0] = g_ascii_toupper (str[0]);
234         }
235         
236         while ((p = strchr (str, '-')) != NULL) {
237                 if (p[1] != '\0' && g_ascii_isalpha (p[1])) {
238                         p[0] = ' ';
239                         p[1] = g_ascii_toupper (p[1]);
240                 }
241
242                 p++;
243         }
244         
245         return str;
246 }
247
248 static void
249 accounts_widget_generic_setup (McAccount *account,
250                                GtkWidget *table_settings)
251 {
252         McProtocol *protocol;
253         McProfile  *profile;
254         GSList     *params, *l;
255         guint       n_rows = 0;
256
257         profile = mc_account_get_profile (account);
258         protocol = mc_profile_get_protocol (profile);
259
260         if (!protocol) {
261                 /* The CM is not installed, MC shouldn't list them
262                  * see SF bug #1688779
263                  * FIXME: We should display something asking the user to 
264                  * install the CM
265                  */
266                 g_object_unref (profile);
267                 return;
268         }
269
270         params = mc_protocol_get_params (protocol);
271
272         for (l = params; l; l = l->next) {
273                 McProtocolParam *param;
274                 GtkWidget       *widget = NULL;
275                 gchar           *param_name_formatted;
276
277                 param = l->data;
278                 param_name_formatted = account_widget_generic_format_param_name (param->name);
279                 gtk_table_resize (GTK_TABLE (table_settings), ++n_rows, 2);
280
281                 if (param->signature[0] == 's') {
282                         gchar *str;
283
284                         str = g_strdup_printf (_("%s:"), param_name_formatted);
285                         widget = gtk_label_new (str);
286                         gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
287                         g_free (str);
288
289                         gtk_table_attach (GTK_TABLE (table_settings),
290                                           widget,
291                                           0, 1,
292                                           n_rows - 1, n_rows,
293                                           GTK_FILL, 0,
294                                           0, 0);
295
296                         widget = gtk_entry_new ();
297                         gtk_table_attach (GTK_TABLE (table_settings),
298                                           widget,
299                                           1, 2,
300                                           n_rows - 1, n_rows,
301                                           GTK_FILL | GTK_EXPAND, 0,
302                                           0, 0);
303                 }
304                 /* int types: ynqiuxt. double type is 'd' */
305                 else if (param->signature[0] == 'y' ||
306                          param->signature[0] == 'n' ||
307                          param->signature[0] == 'q' ||
308                          param->signature[0] == 'i' ||
309                          param->signature[0] == 'u' ||
310                          param->signature[0] == 'x' ||
311                          param->signature[0] == 't' ||
312                          param->signature[0] == 'd') {
313                         gchar   *str = NULL;
314                         gdouble  minint = 0;
315                         gdouble  maxint = 0;
316                         gdouble  step = 1;
317
318                         switch (param->signature[0]) {
319                         case 'y': minint = G_MININT8;  maxint = G_MAXINT8;   break;
320                         case 'n': minint = G_MININT16; maxint = G_MAXINT16;  break;
321                         case 'q': minint = 0;          maxint = G_MAXUINT16; break;
322                         case 'i': minint = G_MININT32; maxint = G_MAXINT32;  break;
323                         case 'u': minint = 0;          maxint = G_MAXUINT32; break;
324                         case 'x': minint = G_MININT64; maxint = G_MAXINT64;  break;
325                         case 't': minint = 0;          maxint = G_MAXUINT64; break;
326                         case 'd': minint = G_MININT32; maxint = G_MAXINT32; step = 0.1; break;
327                         }
328
329                         str = g_strdup_printf (_("%s:"), param_name_formatted);
330                         widget = gtk_label_new (str);
331                         gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
332                         g_free (str);
333
334                         gtk_table_attach (GTK_TABLE (table_settings),
335                                           widget,
336                                           0, 1,
337                                           n_rows - 1, n_rows,
338                                           GTK_FILL, 0,
339                                           0, 0);
340
341                         widget = gtk_spin_button_new_with_range (minint, maxint, step);
342                         gtk_table_attach (GTK_TABLE (table_settings),
343                                           widget,
344                                           1, 2,
345                                           n_rows - 1, n_rows,
346                                           GTK_FILL | GTK_EXPAND, 0,
347                                           0, 0);
348                 }
349                 else if (param->signature[0] == 'b') {
350                         widget = gtk_check_button_new_with_label (param_name_formatted);
351                         gtk_table_attach (GTK_TABLE (table_settings),
352                                           widget,
353                                           0, 2,
354                                           n_rows - 1, n_rows,
355                                           GTK_FILL | GTK_EXPAND, 0,
356                                           0, 0);
357                 } else {
358                         empathy_debug (DEBUG_DOMAIN,
359                                        "Unknown signature for param %s: %s",
360                                        param_name_formatted, param->signature);
361                 }
362
363                 if (widget) {
364                         account_widget_setup_widget (widget, account, param->name);
365                 }
366
367                 g_free (param_name_formatted);
368         }
369
370         g_slist_free (params);
371         g_object_unref (profile);
372         g_object_unref (protocol);
373 }
374
375 static GtkWidget *
376 account_widget_new_valist (McAccount   *account,
377                            GladeXML    *gui,
378                            const gchar *root,
379                            const gchar *first_widget_name,
380                            va_list      args)
381 {
382         GtkWidget   *widget;
383         const gchar *widget_name;
384
385         for (widget_name = first_widget_name; widget_name; widget_name = va_arg (args, gchar*)) {
386                 const gchar *param_name;
387
388                 param_name = va_arg (args, gchar*);
389
390                 widget = glade_xml_get_widget (gui, widget_name);
391
392                 if (!widget) {
393                         g_warning ("Glade is missing widget '%s'.", widget_name);
394                         continue;
395                 }
396
397                 account_widget_setup_widget (widget, account, param_name);
398         }
399
400         widget = glade_xml_get_widget (gui, root);
401         g_signal_connect (widget, "destroy",
402                           G_CALLBACK (account_widget_destroy_cb),
403                           g_object_ref (account));
404
405         return widget;
406 }
407
408 GtkWidget *
409 empathy_account_widget_new_with_glade (McAccount   *account,
410                                        GladeXML    *gui,
411                                        const gchar *root,
412                                        const gchar *first_widget_name,
413                                        ...)
414 {
415         GtkWidget *widget;
416         va_list    args;
417
418         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
419
420         va_start (args, first_widget_name);
421         widget = account_widget_new_valist (account, gui, root,
422                                             first_widget_name,
423                                             args);
424         va_end (args);
425
426         return widget;
427 }
428
429 void
430 emapthy_account_widget_add_forget_button (McAccount   *account,
431                                           GladeXML    *glade,
432                                           const gchar *button,
433                                           const gchar *entry)
434 {
435         GtkWidget *button_forget;
436         GtkWidget *entry_password;
437         gchar     *password = NULL;
438         
439         button_forget = glade_xml_get_widget (glade, button);
440         entry_password = glade_xml_get_widget (glade, entry);
441
442         mc_account_get_param_string (account, "password", &password);
443         gtk_widget_set_sensitive (button_forget, !G_STR_EMPTY (password));
444         g_free (password);
445
446         g_signal_connect (button_forget, "clicked",
447                           G_CALLBACK (account_widget_forget_clicked_cb),
448                           entry_password);
449         g_signal_connect (entry_password, "changed",
450                           G_CALLBACK (account_widget_password_changed_cb),
451                           button_forget);
452
453         g_object_set_data_full (G_OBJECT (entry_password), "account",
454                                 g_object_ref (account),
455                                 g_object_unref);
456 }
457
458 GtkWidget *
459 empathy_account_widget_generic_new (McAccount *account)
460 {
461         GtkWidget *table_settings;
462         GtkWidget *sw;
463
464         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
465
466         table_settings = gtk_table_new (0, 2, FALSE);
467         gtk_table_set_row_spacings (GTK_TABLE (table_settings), 6);
468         gtk_table_set_col_spacings (GTK_TABLE (table_settings), 6);
469         sw = gtk_scrolled_window_new (NULL, NULL);
470         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
471                                         GTK_POLICY_AUTOMATIC,
472                                         GTK_POLICY_AUTOMATIC);
473         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw),
474                                                table_settings);
475         
476         accounts_widget_generic_setup (account, table_settings);
477
478         g_signal_connect (sw, "destroy",
479                           G_CALLBACK (account_widget_destroy_cb),
480                           g_object_ref (account));
481
482         gtk_widget_show_all (sw);
483
484         return sw;
485 }
486
487 GtkWidget *
488 empathy_account_widget_salut_new (McAccount *account)
489 {
490         GladeXML  *glade;
491         GtkWidget *widget;
492
493         glade = empathy_glade_get ("empathy-account-widget-salut.glade",
494                                    "vbox_salut_settings",
495                                    NULL);
496
497         widget = empathy_account_widget_new_with_glade (account, glade,
498                         "vbox_salut_settings",
499                         "entry_published", "published-name",
500                         "entry_nickname", "nickname",
501                         "entry_first_name", "first-name",
502                         "entry_last_name", "last-name",
503                         "entry_email", "email",
504                         "entry_jid", "jid",
505                         NULL);
506
507         g_object_unref (glade);
508
509         gtk_widget_show (widget);
510
511         return widget;
512 }
513
514 GtkWidget *
515 empathy_account_widget_msn_new (McAccount *account)
516 {
517         GladeXML  *glade;
518         GtkWidget *widget;
519
520         glade = empathy_glade_get ("empathy-account-widget-msn.glade",
521                                    "vbox_msn_settings",
522                                    NULL);
523
524         widget = empathy_account_widget_new_with_glade (account, glade,
525                         "vbox_msn_settings",
526                         "entry_id", "account",
527                         "entry_password", "password",
528                         "entry_server", "server",
529                         "spinbutton_port", "port",
530                         NULL);
531
532         emapthy_account_widget_add_forget_button (account, glade,
533                                                   "button_forget",
534                                                   "entry_password");
535
536         g_object_unref (glade);
537
538         gtk_widget_show (widget);
539
540         return widget;
541 }
542
543 GtkWidget *
544 empathy_account_widget_jabber_new (McAccount *account)
545 {
546         GladeXML  *glade;
547         GtkWidget *widget;
548         GtkWidget *spinbutton_port;
549         GtkWidget *checkbutton_ssl;
550
551         glade = empathy_glade_get_file ("empathy-account-widget-jabber.glade",
552                                         "vbox_jabber_settings",
553                                         NULL,
554                                         "spinbutton_port", &spinbutton_port,
555                                         "checkbutton_ssl", &checkbutton_ssl,
556                                         NULL);
557
558         widget = empathy_account_widget_new_with_glade (account, glade,
559                         "vbox_jabber_settings",
560                         "entry_id", "account",
561                         "entry_password", "password",
562                         "entry_resource", "resource",
563                         "entry_server", "server",
564                         "spinbutton_port", "port",
565                         "spinbutton_priority", "priority",
566                         "checkbutton_ssl", "old-ssl",
567                         "checkbutton_ignore_ssl_errors", "ignore-ssl-errors",
568                         "checkbutton_encryption", "require-encryption",
569                         NULL);
570
571         emapthy_account_widget_add_forget_button (account, glade,
572                                                   "button_forget",
573                                                   "entry_password");
574
575         g_signal_connect (checkbutton_ssl, "toggled",
576                           G_CALLBACK (account_widget_jabber_ssl_toggled_cb),
577                           spinbutton_port);
578
579         g_object_set_data_full (G_OBJECT (spinbutton_port), "account",
580                                 g_object_ref (account),
581                                 g_object_unref);
582
583         g_object_unref (glade);
584
585         gtk_widget_show (widget);
586
587         return widget;
588 }
589