]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-account-widget.c
Fixed some of the EmpathyAccountWidget's control button behaviour.
[empathy.git] / libempathy-gtk / empathy-account-widget.c
1 /*
2  * Copyright (C) 2006-2007 Imendio AB
3  * Copyright (C) 2007-2009 Collabora Ltd.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program 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  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors: Xavier Claessens <xclaesse@gmail.com>
21  *          Martyn Russell <martyn@imendio.com>
22  *          Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
23  *          Jonathan Tellier <jonathan.tellier@gmail.com>
24  */
25
26 #include <config.h>
27
28 #include <string.h>
29
30 #include <gtk/gtk.h>
31 #include <glib/gi18n-lib.h>
32
33 #include <libempathy/empathy-utils.h>
34 #include <libempathy/empathy-account.h>
35
36 #include <telepathy-glib/connection-manager.h>
37 #include <telepathy-glib/util.h>
38 #include <dbus/dbus-protocol.h>
39
40 #include "empathy-account-widget.h"
41 #include "empathy-account-widget-private.h"
42 #include "empathy-account-widget-sip.h"
43 #include "empathy-account-widget-irc.h"
44 #include "empathy-ui-utils.h"
45
46 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
47 #include <libempathy/empathy-debug.h>
48
49 G_DEFINE_TYPE (EmpathyAccountWidget, empathy_account_widget, G_TYPE_OBJECT)
50
51 typedef struct {
52   EmpathyAccountSettings *settings;
53
54   GtkWidget *table_common_settings;
55   GtkWidget *apply_button;
56   GtkWidget *cancel_button;
57   GtkWidget *entry_password;
58   GtkWidget *button_forget;
59   GtkWidget *spinbutton_port;
60   GtkWidget *enabled_checkbox;
61
62   gboolean simple;
63
64   gboolean contains_pending_changes;
65   gboolean original_enabled_checkbox_value;
66
67   /* An EmpathyAccountWidget can be used to either create an account or
68    * modify it. When we are creating an account, this member is set to TRUE */
69   gboolean creating_account;
70
71   gboolean dispose_run;
72 } EmpathyAccountWidgetPriv;
73
74 enum {
75   PROP_PROTOCOL = 1,
76   PROP_SETTINGS,
77   PROP_SIMPLE,
78   PROP_CREATING_ACCOUNT
79 };
80
81 enum {
82   HANDLE_APPLY,
83   ACCOUNT_CREATED,
84   CANCELLED,
85   LAST_SIGNAL
86 };
87
88 static guint signals[LAST_SIGNAL] = { 0 };
89
90 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountWidget)
91 #define CHANGED_TIMEOUT 300
92
93 static void
94 account_widget_set_control_buttons_sensitivity (EmpathyAccountWidget *self,
95     gboolean sensitive)
96 {
97   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
98
99   if (!priv->simple)
100     {
101       gtk_widget_set_sensitive (priv->apply_button, sensitive);
102       gtk_widget_set_sensitive (
103           priv->cancel_button, sensitive || priv->creating_account);
104
105       priv->contains_pending_changes = sensitive;
106     }
107 }
108
109 static void
110 account_widget_handle_control_buttons_sensitivity (EmpathyAccountWidget *self)
111 {
112   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
113   gboolean is_valid;
114
115   is_valid = empathy_account_settings_is_valid (priv->settings);
116
117   if (!priv->simple)
118       account_widget_set_control_buttons_sensitivity (self, is_valid);
119
120   g_signal_emit (self, signals[HANDLE_APPLY], 0, is_valid);
121 }
122
123 static void
124 account_widget_entry_changed_common (EmpathyAccountWidget *self,
125     GtkEntry *entry, gboolean focus)
126 {
127   const gchar *str;
128   const gchar *param_name;
129   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
130
131   str = gtk_entry_get_text (entry);
132   param_name = g_object_get_data (G_OBJECT (entry), "param_name");
133
134   if (EMP_STR_EMPTY (str))
135     {
136       const gchar *value = NULL;
137
138       empathy_account_settings_unset (priv->settings, param_name);
139
140       if (focus)
141         {
142           value = empathy_account_settings_get_string (priv->settings,
143               param_name);
144           DEBUG ("Unset %s and restore to %s", param_name, value);
145           gtk_entry_set_text (entry, value ? value : "");
146         }
147     }
148   else
149     {
150       DEBUG ("Setting %s to %s", param_name,
151           tp_strdiff (param_name, "password") ? str : "***");
152       empathy_account_settings_set_string (priv->settings, param_name, str);
153     }
154 }
155
156 static void
157 account_widget_entry_changed_cb (GtkEditable *entry,
158     EmpathyAccountWidget *self)
159 {
160   account_widget_entry_changed_common (self, GTK_ENTRY (entry), FALSE);
161   account_widget_handle_control_buttons_sensitivity (self);
162 }
163
164 static void
165 account_widget_int_changed_cb (GtkWidget *widget,
166     EmpathyAccountWidget *self)
167 {
168   const gchar *param_name;
169   gint value;
170   const gchar *signature;
171   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
172
173   value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
174   param_name = g_object_get_data (G_OBJECT (widget), "param_name");
175
176   signature = empathy_account_settings_get_dbus_signature (priv->settings,
177     param_name);
178   g_return_if_fail (signature != NULL);
179
180   DEBUG ("Setting %s to %d", param_name, value);
181
182   switch ((int)*signature)
183     {
184     case DBUS_TYPE_INT16:
185     case DBUS_TYPE_INT32:
186       empathy_account_settings_set_int32 (priv->settings, param_name, value);
187       break;
188     case DBUS_TYPE_INT64:
189       empathy_account_settings_set_int64 (priv->settings, param_name, value);
190       break;
191     case DBUS_TYPE_UINT16:
192     case DBUS_TYPE_UINT32:
193       empathy_account_settings_set_uint32 (priv->settings, param_name, value);
194       break;
195     case DBUS_TYPE_UINT64:
196       empathy_account_settings_set_uint64 (priv->settings, param_name, value);
197       break;
198     default:
199       g_return_if_reached ();
200     }
201
202   account_widget_handle_control_buttons_sensitivity (self);
203 }
204
205 static void
206 account_widget_checkbutton_toggled_cb (GtkWidget *widget,
207     EmpathyAccountWidget *self)
208 {
209   gboolean     value;
210   gboolean     default_value;
211   const gchar *param_name;
212   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
213
214   value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
215   param_name = g_object_get_data (G_OBJECT (widget), "param_name");
216
217   /* FIXME: This is ugly! checkbox don't have a "not-set" value so we
218    * always unset the param and set the value if different from the
219    * default value. */
220   empathy_account_settings_unset (priv->settings, param_name);
221   default_value = empathy_account_settings_get_boolean (priv->settings,
222       param_name);
223
224   if (default_value == value)
225     {
226       DEBUG ("Unset %s and restore to %d", param_name, default_value);
227     }
228   else
229     {
230       DEBUG ("Setting %s to %d", param_name, value);
231       empathy_account_settings_set_boolean (priv->settings, param_name, value);
232     }
233
234   account_widget_handle_control_buttons_sensitivity (self);
235 }
236
237 static void
238 account_widget_forget_clicked_cb (GtkWidget *button,
239     EmpathyAccountWidget *self)
240 {
241   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
242   const gchar *param_name;
243
244   param_name = g_object_get_data (G_OBJECT (priv->entry_password),
245       "param_name");
246
247   DEBUG ("Unset %s", param_name);
248   empathy_account_settings_unset (priv->settings, param_name);
249   gtk_entry_set_text (GTK_ENTRY (priv->entry_password), "");
250
251   account_widget_handle_control_buttons_sensitivity (self);
252 }
253
254 static void
255 account_widget_password_changed_cb (GtkWidget *entry,
256     EmpathyAccountWidget *self)
257 {
258   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
259   const gchar *str;
260
261   str = gtk_entry_get_text (GTK_ENTRY (entry));
262   gtk_widget_set_sensitive (priv->button_forget, !EMP_STR_EMPTY (str));
263 }
264
265 static void
266 account_widget_jabber_ssl_toggled_cb (GtkWidget *checkbutton_ssl,
267     EmpathyAccountWidget *self)
268 {
269   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
270   gboolean   value;
271   gint32       port = 0;
272
273   value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_ssl));
274   port = empathy_account_settings_get_uint32 (priv->settings, "port");
275
276   if (value)
277     {
278       if (port == 5222 || port == 0)
279         port = 5223;
280     }
281   else
282     {
283       if (port == 5223 || port == 0)
284         port = 5222;
285     }
286
287   gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->spinbutton_port), port);
288 }
289
290 static void
291 account_widget_setup_widget (EmpathyAccountWidget *self,
292     GtkWidget *widget,
293     const gchar *param_name)
294 {
295   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
296
297   g_object_set_data_full (G_OBJECT (widget), "param_name",
298       g_strdup (param_name), g_free);
299
300   if (GTK_IS_SPIN_BUTTON (widget))
301     {
302       gint value = 0;
303       const gchar *signature;
304
305       signature = empathy_account_settings_get_dbus_signature (priv->settings,
306           param_name);
307       g_return_if_fail (signature != NULL);
308
309       switch ((int)*signature)
310         {
311           case DBUS_TYPE_INT16:
312           case DBUS_TYPE_INT32:
313             value = empathy_account_settings_get_int32 (priv->settings,
314               param_name);
315             break;
316           case DBUS_TYPE_INT64:
317             value = empathy_account_settings_get_int64 (priv->settings,
318               param_name);
319             break;
320           case DBUS_TYPE_UINT16:
321           case DBUS_TYPE_UINT32:
322             value = empathy_account_settings_get_uint32 (priv->settings,
323               param_name);
324             break;
325           case DBUS_TYPE_UINT64:
326             value = empathy_account_settings_get_uint64 (priv->settings,
327                 param_name);
328             break;
329           default:
330             g_return_if_reached ();
331         }
332
333       gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
334
335       g_signal_connect (widget, "value-changed",
336           G_CALLBACK (account_widget_int_changed_cb),
337           self);
338     }
339   else if (GTK_IS_ENTRY (widget))
340     {
341       const gchar *str = NULL;
342
343       str = empathy_account_settings_get_string (priv->settings, param_name);
344       gtk_entry_set_text (GTK_ENTRY (widget), str ? str : "");
345
346       if (strstr (param_name, "password"))
347         {
348           gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE);
349         }
350
351       g_signal_connect (widget, "changed",
352           G_CALLBACK (account_widget_entry_changed_cb), self);
353     }
354   else if (GTK_IS_TOGGLE_BUTTON (widget))
355     {
356       gboolean value = FALSE;
357
358       value = empathy_account_settings_get_boolean (priv->settings,
359           param_name);
360       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
361
362       g_signal_connect (widget, "toggled",
363           G_CALLBACK (account_widget_checkbutton_toggled_cb),
364           self);
365     }
366   else
367     {
368       DEBUG ("Unknown type of widget for param %s", param_name);
369     }
370 }
371
372 static gchar *
373 account_widget_generic_format_param_name (const gchar *param_name)
374 {
375   gchar *str;
376   gchar *p;
377
378   str = g_strdup (param_name);
379
380   if (str && g_ascii_isalpha (str[0]))
381     str[0] = g_ascii_toupper (str[0]);
382
383   while ((p = strchr (str, '-')) != NULL)
384     {
385       if (p[1] != '\0' && g_ascii_isalpha (p[1]))
386         {
387           p[0] = ' ';
388           p[1] = g_ascii_toupper (p[1]);
389         }
390
391       p++;
392     }
393
394   return str;
395 }
396
397 static void
398 accounts_widget_generic_setup (EmpathyAccountWidget *self,
399     GtkWidget *table_common_settings,
400     GtkWidget *table_advanced_settings)
401 {
402   TpConnectionManagerParam *params, *param;
403   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
404
405   params = empathy_account_settings_get_tp_params (priv->settings);
406
407   for (param = params; param != NULL && param->name != NULL; param++)
408     {
409       GtkWidget       *table_settings;
410       guint            n_rows = 0;
411       GtkWidget       *widget = NULL;
412       gchar           *param_name_formatted;
413
414       if (param->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED)
415         table_settings = table_common_settings;
416       else if (priv->simple)
417         return;
418       else
419         table_settings = table_advanced_settings;
420
421       param_name_formatted = account_widget_generic_format_param_name
422         (param->name);
423       g_object_get (table_settings, "n-rows", &n_rows, NULL);
424       gtk_table_resize (GTK_TABLE (table_settings), ++n_rows, 2);
425
426       if (param->dbus_signature[0] == 's')
427         {
428           gchar *str;
429
430           str = g_strdup_printf (_("%s:"), param_name_formatted);
431           widget = gtk_label_new (str);
432           gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
433           g_free (str);
434
435           gtk_table_attach (GTK_TABLE (table_settings),
436               widget,
437               0, 1,
438               n_rows - 1, n_rows,
439               GTK_FILL, 0,
440               0, 0);
441           gtk_widget_show (widget);
442
443           widget = gtk_entry_new ();
444           if (strcmp (param->name, "account") == 0)
445             {
446               g_signal_connect (widget, "realize",
447                   G_CALLBACK (gtk_widget_grab_focus),
448                   NULL);
449             }
450           gtk_table_attach (GTK_TABLE (table_settings),
451               widget,
452               1, 2,
453               n_rows - 1, n_rows,
454               GTK_FILL | GTK_EXPAND, 0,
455               0, 0);
456           gtk_widget_show (widget);
457         }
458       /* int types: ynqiuxt. double type is 'd' */
459       else if (param->dbus_signature[0] == 'y' ||
460           param->dbus_signature[0] == 'n' ||
461           param->dbus_signature[0] == 'q' ||
462           param->dbus_signature[0] == 'i' ||
463           param->dbus_signature[0] == 'u' ||
464           param->dbus_signature[0] == 'x' ||
465           param->dbus_signature[0] == 't' ||
466           param->dbus_signature[0] == 'd')
467         {
468           gchar   *str = NULL;
469           gdouble  minint = 0;
470           gdouble  maxint = 0;
471           gdouble  step = 1;
472
473           switch (param->dbus_signature[0])
474             {
475             case 'y': minint = G_MININT8;  maxint = G_MAXINT8;   break;
476             case 'n': minint = G_MININT16; maxint = G_MAXINT16;  break;
477             case 'q': minint = 0;          maxint = G_MAXUINT16; break;
478             case 'i': minint = G_MININT32; maxint = G_MAXINT32;  break;
479             case 'u': minint = 0;          maxint = G_MAXUINT32; break;
480             case 'x': minint = G_MININT64; maxint = G_MAXINT64;  break;
481             case 't': minint = 0;          maxint = G_MAXUINT64; break;
482             case 'd': minint = G_MININT32; maxint = G_MAXINT32;
483               step = 0.1; break;
484             }
485
486           str = g_strdup_printf (_("%s:"), param_name_formatted);
487           widget = gtk_label_new (str);
488           gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
489           g_free (str);
490
491           gtk_table_attach (GTK_TABLE (table_settings),
492               widget,
493               0, 1,
494               n_rows - 1, n_rows,
495               GTK_FILL, 0,
496               0, 0);
497           gtk_widget_show (widget);
498
499           widget = gtk_spin_button_new_with_range (minint, maxint, step);
500           gtk_table_attach (GTK_TABLE (table_settings),
501               widget,
502               1, 2,
503               n_rows - 1, n_rows,
504               GTK_FILL | GTK_EXPAND, 0,
505               0, 0);
506           gtk_widget_show (widget);
507         }
508       else if (param->dbus_signature[0] == 'b')
509         {
510           widget = gtk_check_button_new_with_label (param_name_formatted);
511           gtk_table_attach (GTK_TABLE (table_settings),
512               widget,
513               0, 2,
514               n_rows - 1, n_rows,
515               GTK_FILL | GTK_EXPAND, 0,
516               0, 0);
517           gtk_widget_show (widget);
518         }
519       else
520         {
521           DEBUG ("Unknown signature for param %s: %s",
522               param_name_formatted, param->dbus_signature);
523         }
524
525       if (widget)
526         account_widget_setup_widget (self, widget, param->name);
527
528       g_free (param_name_formatted);
529     }
530 }
531
532 static void
533 account_widget_handle_params_valist (EmpathyAccountWidget *self,
534     const gchar *first_widget,
535     va_list args)
536 {
537   GObject *object;
538   const gchar *name;
539
540   for (name = first_widget; name; name = va_arg (args, const gchar *))
541     {
542       const gchar *param_name;
543
544       param_name = va_arg (args, const gchar *);
545       object = gtk_builder_get_object (self->ui_details->gui, name);
546
547       if (!object)
548         {
549           g_warning ("Builder is missing object '%s'.", name);
550           continue;
551         }
552
553       account_widget_setup_widget (self, GTK_WIDGET (object), param_name);
554     }
555 }
556
557 static void
558 account_widget_cancel_clicked_cb (GtkWidget *button,
559     EmpathyAccountWidget *self)
560 {
561   g_signal_emit (self, signals[CANCELLED], 0);
562 }
563
564 static void
565 account_widget_account_enabled_cb (GObject *source_object,
566     GAsyncResult *res,
567     gpointer user_data)
568 {
569   GError *error = NULL;
570   EmpathyAccount *account = EMPATHY_ACCOUNT (source_object);
571   EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
572
573   empathy_account_set_enabled_finish (account, res, &error);
574
575   if (error != NULL)
576     {
577       DEBUG ("Could not automatically enable new account: %s", error->message);
578       g_error_free (error);
579     }
580   else
581     {
582       g_signal_emit (widget, signals[ACCOUNT_CREATED], 0);
583     }
584 }
585
586 static void
587 account_widget_applied_cb (GObject *source_object,
588     GAsyncResult *res,
589     gpointer user_data)
590 {
591   GError *error = NULL;
592   EmpathyAccount *account;
593   EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source_object);
594   EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
595   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
596
597   empathy_account_settings_apply_finish (settings, res, &error);
598
599   if (error != NULL)
600     {
601       DEBUG ("Could not apply changes to account: %s", error->message);
602       g_error_free (error);
603       return;
604     }
605
606   account = empathy_account_settings_get_account (priv->settings);
607
608   if (account != NULL)
609     {
610       if (priv->creating_account)
611         {
612           /* By default, when an account is created, we enable it. */
613           empathy_account_set_enabled_async (account, TRUE,
614               account_widget_account_enabled_cb, widget);
615         }
616       else if (priv->enabled_checkbox != NULL)
617         {
618           gboolean enabled_checked;
619
620           enabled_checked = gtk_toggle_button_get_active (
621               GTK_TOGGLE_BUTTON (priv->enabled_checkbox));
622
623           if (empathy_account_is_enabled (account) && enabled_checked)
624             {
625               /* After having applied changes to a user account, we
626                * automatically reconnect it. This is done so the new
627                * information entered by the user is validated on the server. */
628               empathy_account_reconnect_async (account, NULL, NULL);
629             }
630           else
631             {
632               /* The account is disabled so we enable it according to the value
633                * of the "Enabled" checkbox */
634               empathy_account_set_enabled_async (account, enabled_checked,
635                   NULL, NULL);
636             }
637         }
638     }
639
640   account_widget_set_control_buttons_sensitivity (widget, FALSE);
641 }
642
643 static void
644 account_widget_apply_clicked_cb (GtkWidget *button,
645     EmpathyAccountWidget *self)
646 {
647   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
648
649   empathy_account_settings_apply_async (priv->settings,
650       account_widget_applied_cb, self);
651 }
652
653 static void
654 account_widget_setup_generic (EmpathyAccountWidget *self)
655 {
656   GtkWidget *table_common_settings;
657   GtkWidget *table_advanced_settings;
658
659   table_common_settings = GTK_WIDGET (gtk_builder_get_object
660       (self->ui_details->gui, "table_common_settings"));
661   table_advanced_settings = GTK_WIDGET (gtk_builder_get_object
662       (self->ui_details->gui, "table_advanced_settings"));
663
664   accounts_widget_generic_setup (self, table_common_settings,
665       table_advanced_settings);
666
667   g_object_unref (self->ui_details->gui);
668 }
669
670 static void
671 account_widget_settings_ready_cb (EmpathyAccountSettings *settings,
672     GParamSpec *pspec,
673     gpointer user_data)
674 {
675   EmpathyAccountWidget *self = user_data;
676   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
677
678   if (empathy_account_settings_is_ready (priv->settings))
679     account_widget_setup_generic (self);
680 }
681
682 static void
683 account_widget_build_generic (EmpathyAccountWidget *self,
684     const char *filename)
685 {
686   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
687   GtkWidget *expander_advanced;
688
689   self->ui_details->gui = empathy_builder_get_file (filename,
690       "table_common_settings", &priv->table_common_settings,
691       "vbox_generic_settings", &self->ui_details->widget,
692       "expander_advanced_settings", &expander_advanced,
693       NULL);
694
695   if (priv->simple)
696     gtk_widget_hide (expander_advanced);
697
698   g_object_ref (self->ui_details->gui);
699
700   if (empathy_account_settings_is_ready (priv->settings))
701     account_widget_setup_generic (self);
702   else
703     g_signal_connect (priv->settings, "notify::ready",
704         G_CALLBACK (account_widget_settings_ready_cb), self);
705 }
706
707 static void
708 account_widget_build_salut (EmpathyAccountWidget *self,
709     const char *filename)
710 {
711   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
712
713   self->ui_details->gui = empathy_builder_get_file (filename,
714       "table_common_settings", &priv->table_common_settings,
715       "vbox_salut_settings", &self->ui_details->widget,
716       NULL);
717
718   empathy_account_widget_handle_params (self,
719       "entry_published", "published-name",
720       "entry_nickname", "nickname",
721       "entry_first_name", "first-name",
722       "entry_last_name", "last-name",
723       "entry_email", "email",
724       "entry_jid", "jid",
725       NULL);
726
727   self->ui_details->default_focus = g_strdup ("entry_nickname");
728 }
729
730 static void
731 account_widget_build_irc (EmpathyAccountWidget *self,
732   const char *filename)
733 {
734   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
735   empathy_account_widget_irc_build (self, filename,
736     &priv->table_common_settings);
737 }
738
739 static void
740 account_widget_build_sip (EmpathyAccountWidget *self,
741   const char *filename)
742 {
743   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
744   empathy_account_widget_sip_build (self, filename,
745     &priv->table_common_settings);
746 }
747
748 static void
749 account_widget_build_msn (EmpathyAccountWidget *self,
750     const char *filename)
751 {
752   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
753
754   if (priv->simple)
755     {
756       self->ui_details->gui = empathy_builder_get_file (filename,
757           "vbox_msn_simple", &self->ui_details->widget,
758           NULL);
759
760       empathy_account_widget_handle_params (self,
761           "entry_id_simple", "account",
762           "entry_password_simple", "password",
763           NULL);
764
765       self->ui_details->default_focus = g_strdup ("entry_id_simple");
766     }
767   else
768     {
769       self->ui_details->gui = empathy_builder_get_file (filename,
770           "table_common_msn_settings", &priv->table_common_settings,
771           "vbox_msn_settings", &self->ui_details->widget,
772           NULL);
773
774       empathy_account_widget_handle_params (self,
775           "entry_id", "account",
776           "entry_password", "password",
777           "entry_server", "server",
778           "spinbutton_port", "port",
779           NULL);
780
781       self->ui_details->default_focus = g_strdup ("entry_id");
782       self->ui_details->add_forget = TRUE;
783     }
784 }
785
786 static void
787 account_widget_build_jabber (EmpathyAccountWidget *self,
788     const char *filename)
789 {
790   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
791   GtkWidget *spinbutton_port;
792   GtkWidget *checkbutton_ssl;
793   GtkWidget *label_id, *label_password;
794   GtkWidget *label_id_create, *label_password_create;
795
796   if (priv->simple)
797     {
798       self->ui_details->gui = empathy_builder_get_file (filename,
799           "vbox_jabber_simple", &self->ui_details->widget,
800           "label_id_simple", &label_id,
801           "label_id_create", &label_id_create,
802           "label_password_simple", &label_password,
803           "label_password_create", &label_password_create,
804           NULL);
805
806       if (empathy_account_settings_get_boolean (priv->settings, "register"))
807         {
808           gtk_widget_hide (label_id);
809           gtk_widget_hide (label_password);
810           gtk_widget_show (label_id_create);
811           gtk_widget_show (label_password_create);
812         }
813
814       empathy_account_widget_handle_params (self,
815           "entry_id_simple", "account",
816           "entry_password_simple", "password",
817           NULL);
818
819       self->ui_details->default_focus = g_strdup ("entry_id_simple");
820     }
821   else
822     {
823       self->ui_details->gui = empathy_builder_get_file (filename,
824           "table_common_settings", &priv->table_common_settings,
825           "vbox_jabber_settings", &self->ui_details->widget,
826           "spinbutton_port", &spinbutton_port,
827           "checkbutton_ssl", &checkbutton_ssl,
828           NULL);
829
830       empathy_account_widget_handle_params (self,
831           "entry_id", "account",
832           "entry_password", "password",
833           "entry_resource", "resource",
834           "entry_server", "server",
835           "spinbutton_port", "port",
836           "spinbutton_priority", "priority",
837           "checkbutton_ssl", "old-ssl",
838           "checkbutton_ignore_ssl_errors", "ignore-ssl-errors",
839           "checkbutton_encryption", "require-encryption",
840           NULL);
841
842       self->ui_details->default_focus = g_strdup ("entry_id");
843       self->ui_details->add_forget = TRUE;
844       priv->spinbutton_port = spinbutton_port;
845
846       g_signal_connect (checkbutton_ssl, "toggled",
847           G_CALLBACK (account_widget_jabber_ssl_toggled_cb),
848           self);
849     }
850 }
851
852 static void
853 account_widget_build_icq (EmpathyAccountWidget *self,
854     const char *filename)
855 {
856   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
857   GtkWidget *spinbutton_port;
858
859   if (priv->simple)
860     {
861       self->ui_details->gui = empathy_builder_get_file (filename,
862           "vbox_icq_simple", &self->ui_details->widget,
863           NULL);
864
865       empathy_account_widget_handle_params (self,
866           "entry_uin_simple", "account",
867           "entry_password_simple", "password",
868           NULL);
869
870       self->ui_details->default_focus = g_strdup ("entry_uin_simple");
871     }
872   else
873     {
874       self->ui_details->gui = empathy_builder_get_file (filename,
875           "table_common_settings", &priv->table_common_settings,
876           "vbox_icq_settings", &self->ui_details->widget,
877           "spinbutton_port", &spinbutton_port,
878           NULL);
879
880       empathy_account_widget_handle_params (self,
881           "entry_uin", "account",
882           "entry_password", "password",
883           "entry_server", "server",
884           "spinbutton_port", "port",
885           "entry_charset", "charset",
886           NULL);
887
888       self->ui_details->default_focus = g_strdup ("entry_uin");
889       self->ui_details->add_forget = TRUE;
890     }
891 }
892
893 static void
894 account_widget_build_aim (EmpathyAccountWidget *self,
895     const char *filename)
896 {
897   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
898   GtkWidget *spinbutton_port;
899
900   if (priv->simple)
901     {
902       self->ui_details->gui = empathy_builder_get_file (filename,
903           "vbox_aim_simple", &self->ui_details->widget,
904           NULL);
905
906       empathy_account_widget_handle_params (self,
907           "entry_screenname_simple", "account",
908           "entry_password_simple", "password",
909           NULL);
910
911       self->ui_details->default_focus = g_strdup ("entry_screenname_simple");
912     }
913   else
914     {
915       self->ui_details->gui = empathy_builder_get_file (filename,
916           "table_common_settings", &priv->table_common_settings,
917           "vbox_aim_settings", &self->ui_details->widget,
918           "spinbutton_port", &spinbutton_port,
919           NULL);
920
921       empathy_account_widget_handle_params (self,
922           "entry_screenname", "account",
923           "entry_password", "password",
924           "entry_server", "server",
925           "spinbutton_port", "port",
926           NULL);
927
928       self->ui_details->default_focus = g_strdup ("entry_screenname");
929       self->ui_details->add_forget = TRUE;
930     }
931 }
932
933 static void
934 account_widget_build_yahoo (EmpathyAccountWidget *self,
935     const char *filename)
936 {
937   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
938
939   if (priv->simple)
940     {
941       self->ui_details->gui = empathy_builder_get_file (filename,
942           "vbox_yahoo_simple", &self->ui_details->widget,
943           NULL);
944
945       empathy_account_widget_handle_params (self,
946           "entry_id_simple", "account",
947           "entry_password_simple", "password",
948           NULL);
949
950       self->ui_details->default_focus = g_strdup ("entry_id_simple");
951     }
952   else
953     {
954       self->ui_details->gui = empathy_builder_get_file (filename,
955           "table_common_settings", &priv->table_common_settings,
956           "vbox_yahoo_settings", &self->ui_details->widget,
957           NULL);
958
959       empathy_account_widget_handle_params (self,
960           "entry_id", "account",
961           "entry_password", "password",
962           "entry_server", "server",
963           "entry_locale", "room-list-locale",
964           "entry_charset", "charset",
965           "spinbutton_port", "port",
966           "checkbutton_yahoojp", "yahoojp",
967           "checkbutton_ignore_invites", "ignore-invites",
968           NULL);
969
970       self->ui_details->default_focus = g_strdup ("entry_id");
971       self->ui_details->add_forget = TRUE;
972     }
973 }
974
975 static void
976 account_widget_build_groupwise (EmpathyAccountWidget *self,
977     const char *filename)
978 {
979   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
980
981   if (priv->simple)
982     {
983       self->ui_details->gui = empathy_builder_get_file (filename,
984           "vbox_groupwise_simple", &self->ui_details->widget,
985           NULL);
986
987       empathy_account_widget_handle_params (self,
988           "entry_id_simple", "account",
989           "entry_password_simple", "password",
990           NULL);
991
992       self->ui_details->default_focus = g_strdup ("entry_id_simple");
993     }
994   else
995     {
996       self->ui_details->gui = empathy_builder_get_file (filename,
997           "table_common_groupwise_settings", &priv->table_common_settings,
998           "vbox_groupwise_settings", &self->ui_details->widget,
999           NULL);
1000
1001       empathy_account_widget_handle_params (self,
1002           "entry_id", "account",
1003           "entry_password", "password",
1004           "entry_server", "server",
1005           "spinbutton_port", "port",
1006           NULL);
1007
1008       self->ui_details->default_focus = g_strdup ("entry_id");
1009       self->ui_details->add_forget = TRUE;
1010     }
1011 }
1012
1013 static void
1014 account_widget_destroy_cb (GtkWidget *widget,
1015     EmpathyAccountWidget *self)
1016 {
1017   g_object_unref (self);
1018 }
1019
1020 static void
1021 empathy_account_widget_enabled_cb (EmpathyAccount *account,
1022       GParamSpec *spec,
1023       gpointer user_data)
1024 {
1025   EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
1026   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1027   gboolean enabled = empathy_account_is_enabled (account);
1028
1029   if (priv->enabled_checkbox != NULL)
1030     {
1031       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1032           enabled);
1033     }
1034 }
1035
1036 static void
1037 account_widget_enabled_released_cb (GtkToggleButton *toggle_button,
1038     gpointer user_data)
1039 {
1040   account_widget_handle_control_buttons_sensitivity (
1041       EMPATHY_ACCOUNT_WIDGET (user_data));
1042 }
1043
1044 static void
1045 do_set_property (GObject *object,
1046     guint prop_id,
1047     const GValue *value,
1048     GParamSpec *pspec)
1049 {
1050   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1051
1052   switch (prop_id)
1053     {
1054     case PROP_SETTINGS:
1055       priv->settings = g_value_dup_object (value);
1056       break;
1057     case PROP_SIMPLE:
1058       priv->simple = g_value_get_boolean (value);
1059       break;
1060     case PROP_CREATING_ACCOUNT:
1061       priv->creating_account = g_value_get_boolean (value);
1062       break;
1063     default:
1064       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1065     }
1066 }
1067
1068 static void
1069 do_get_property (GObject *object,
1070     guint prop_id,
1071     GValue *value,
1072     GParamSpec *pspec)
1073 {
1074   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1075
1076   switch (prop_id)
1077     {
1078     case PROP_PROTOCOL:
1079       g_value_set_string (value,
1080         empathy_account_settings_get_protocol (priv->settings));
1081       break;
1082     case PROP_SETTINGS:
1083       g_value_set_object (value, priv->settings);
1084       break;
1085     case PROP_SIMPLE:
1086       g_value_set_boolean (value, priv->simple);
1087       break;
1088     case PROP_CREATING_ACCOUNT:
1089       g_value_set_boolean (value, priv->creating_account);
1090       break;
1091     default:
1092       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1093     }
1094 }
1095
1096 #define WIDGET(cm, proto) \
1097   { #cm, #proto, "empathy-account-widget-"#proto".ui", \
1098     account_widget_build_##proto }
1099
1100 static void
1101 do_constructed (GObject *obj)
1102 {
1103   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1104   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1105   EmpathyAccount *account;
1106   const gchar *protocol, *cm_name;
1107   int i = 0;
1108   struct {
1109     const gchar *cm_name;
1110     const gchar *protocol;
1111     const char *file;
1112     void (*func)(EmpathyAccountWidget *self, const gchar *filename);
1113   } widgets [] = {
1114     { "salut", "local-xmpp", "empathy-account-widget-local-xmpp.ui",
1115         account_widget_build_salut },
1116     WIDGET (gabble, jabber),
1117     WIDGET (butterfly, msn),
1118     WIDGET (haze, icq),
1119     WIDGET (haze, aim),
1120     WIDGET (haze, yahoo),
1121     WIDGET (haze, groupwise),
1122     WIDGET (idle, irc),
1123     WIDGET (sofiasip, sip),
1124   };
1125
1126   cm_name = empathy_account_settings_get_cm (priv->settings);
1127   protocol = empathy_account_settings_get_protocol (priv->settings);
1128
1129   for (i = 0 ; i < G_N_ELEMENTS (widgets); i++)
1130     {
1131       if (!tp_strdiff (widgets[i].cm_name, cm_name) &&
1132           !tp_strdiff (widgets[i].protocol, protocol))
1133         {
1134           gchar *filename;
1135
1136           filename = empathy_file_lookup (widgets[i].file,
1137               "libempathy-gtk");
1138           widgets[i].func (self, filename);
1139           g_free (filename);
1140
1141           break;
1142         }
1143     }
1144
1145   if (i == G_N_ELEMENTS (widgets))
1146     {
1147       gchar *filename = empathy_file_lookup (
1148           "empathy-account-widget-generic.ui", "libempathy-gtk");
1149       account_widget_build_generic (self, filename);
1150       g_free (filename);
1151     }
1152
1153   /* handle default focus */
1154   if (self->ui_details->default_focus != NULL)
1155     {
1156       GObject *default_focus_entry;
1157
1158       default_focus_entry = gtk_builder_get_object
1159         (self->ui_details->gui, self->ui_details->default_focus);
1160       g_signal_connect (default_focus_entry, "realize",
1161           G_CALLBACK (gtk_widget_grab_focus),
1162           NULL);
1163     }
1164
1165   /* handle forget button */
1166   if (self->ui_details->add_forget)
1167     {
1168       const gchar *password = NULL;
1169
1170       priv->button_forget = GTK_WIDGET (gtk_builder_get_object
1171           (self->ui_details->gui, "button_forget"));
1172       priv->entry_password = GTK_WIDGET (gtk_builder_get_object
1173           (self->ui_details->gui, "entry_password"));
1174
1175       password = empathy_account_settings_get_string (priv->settings,
1176           "password");
1177       gtk_widget_set_sensitive (priv->button_forget,
1178           !EMP_STR_EMPTY (password));
1179
1180       g_signal_connect (priv->button_forget, "clicked",
1181           G_CALLBACK (account_widget_forget_clicked_cb),
1182           self);
1183       g_signal_connect (priv->entry_password, "changed",
1184           G_CALLBACK (account_widget_password_changed_cb),
1185           self);
1186     }
1187
1188   /* handle apply and cancel button */
1189   if (!priv->simple)
1190     {
1191       GtkWidget *hbox = gtk_hbox_new (TRUE, 3);
1192
1193       priv->cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
1194       priv->apply_button = gtk_button_new_from_stock (
1195         priv->creating_account ? GTK_STOCK_CONNECT : GTK_STOCK_APPLY);
1196
1197       gtk_box_pack_end (GTK_BOX (hbox), priv->apply_button, TRUE,
1198           TRUE, 3);
1199       gtk_box_pack_end (GTK_BOX (hbox), priv->cancel_button, TRUE,
1200           TRUE, 3);
1201
1202       gtk_box_pack_end (GTK_BOX (self->ui_details->widget), hbox, FALSE,
1203           FALSE, 3);
1204
1205       g_signal_connect (priv->cancel_button, "clicked",
1206           G_CALLBACK (account_widget_cancel_clicked_cb),
1207           self);
1208       g_signal_connect (priv->apply_button, "clicked",
1209           G_CALLBACK (account_widget_apply_clicked_cb),
1210           self);
1211       gtk_widget_show_all (hbox);
1212
1213       if (!tp_strdiff (protocol, "irc") && priv->creating_account)
1214         {
1215           /* For the IRC protocol, when creating an account, the user might
1216            * have nothing to enter. That means that no control interaction
1217            * might occur, so the control buttons sensitivity might never get
1218            * updated. That's why we have to explicitly call this function. */
1219           account_widget_handle_control_buttons_sensitivity (self);
1220         }
1221       else
1222         {
1223           account_widget_set_control_buttons_sensitivity (self, FALSE);
1224         }
1225     }
1226
1227   account = empathy_account_settings_get_account (priv->settings);
1228
1229   if (account != NULL)
1230     {
1231       g_signal_connect (account, "notify::enabled",
1232           G_CALLBACK (empathy_account_widget_enabled_cb), self);
1233     }
1234
1235   /* handle the "Enabled" checkbox. We only add it when modifying an account */
1236   if (!priv->creating_account && priv->table_common_settings != NULL)
1237     {
1238       guint nb_rows, nb_columns;
1239
1240       priv->enabled_checkbox =
1241           gtk_check_button_new_with_label (_("Enabled"));
1242       priv->original_enabled_checkbox_value =
1243           empathy_account_is_enabled (account);
1244       gtk_toggle_button_set_active (
1245           GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1246           priv->original_enabled_checkbox_value);
1247
1248       g_object_get (priv->table_common_settings, "n-rows", &nb_rows,
1249           "n-columns", &nb_columns, NULL);
1250
1251       gtk_table_resize (GTK_TABLE (priv->table_common_settings), ++nb_rows,
1252           nb_columns);
1253
1254       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1255           priv->enabled_checkbox, 0, nb_columns, nb_rows - 1, nb_rows,
1256           GTK_EXPAND | GTK_FILL, 0, 0, 0);
1257
1258       gtk_widget_show (priv->enabled_checkbox);
1259
1260       g_signal_connect (G_OBJECT (priv->enabled_checkbox), "released",
1261           G_CALLBACK (account_widget_enabled_released_cb), self);
1262     }
1263
1264   /* hook up to widget destruction to unref ourselves */
1265   g_signal_connect (self->ui_details->widget, "destroy",
1266       G_CALLBACK (account_widget_destroy_cb), self);
1267
1268   empathy_builder_unref_and_keep_widget (self->ui_details->gui,
1269       self->ui_details->widget);
1270   self->ui_details->gui = NULL;
1271 }
1272
1273 static void
1274 do_dispose (GObject *obj)
1275 {
1276   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1277   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1278
1279   if (priv->dispose_run)
1280     return;
1281
1282   priv->dispose_run = TRUE;
1283
1284   empathy_account_settings_is_ready (priv->settings);
1285
1286   if (priv->settings != NULL)
1287     {
1288       EmpathyAccount *account;
1289       account = empathy_account_settings_get_account (priv->settings);
1290
1291       if (account != NULL)
1292         {
1293           g_signal_handlers_disconnect_by_func (account,
1294               empathy_account_widget_enabled_cb, self);
1295         }
1296
1297       g_object_unref (priv->settings);
1298       priv->settings = NULL;
1299     }
1300
1301   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose != NULL)
1302     G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose (obj);
1303 }
1304
1305 static void
1306 do_finalize (GObject *obj)
1307 {
1308   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1309
1310   g_free (self->ui_details->default_focus);
1311   g_slice_free (EmpathyAccountWidgetUIDetails, self->ui_details);
1312
1313   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize != NULL)
1314     G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize (obj);
1315 }
1316
1317 static void
1318 empathy_account_widget_class_init (EmpathyAccountWidgetClass *klass)
1319 {
1320   GObjectClass *oclass = G_OBJECT_CLASS (klass);
1321   GParamSpec *param_spec;
1322
1323   oclass->get_property = do_get_property;
1324   oclass->set_property = do_set_property;
1325   oclass->constructed = do_constructed;
1326   oclass->dispose = do_dispose;
1327   oclass->finalize = do_finalize;
1328
1329   param_spec = g_param_spec_string ("protocol",
1330       "protocol", "The protocol of the account",
1331       NULL,
1332       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1333   g_object_class_install_property (oclass, PROP_PROTOCOL, param_spec);
1334
1335   param_spec = g_param_spec_object ("settings",
1336       "settings", "The settings of the account",
1337       EMPATHY_TYPE_ACCOUNT_SETTINGS,
1338       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1339   g_object_class_install_property (oclass, PROP_SETTINGS, param_spec);
1340
1341   param_spec = g_param_spec_boolean ("simple",
1342       "simple", "Whether the account widget is a simple or an advanced one",
1343       FALSE,
1344       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1345   g_object_class_install_property (oclass, PROP_SIMPLE, param_spec);
1346
1347   param_spec = g_param_spec_boolean ("creating-account",
1348       "creating-account",
1349       "TRUE if we're creating an account, FALSE if we're modifying it",
1350       FALSE,
1351       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1352   g_object_class_install_property (oclass, PROP_CREATING_ACCOUNT, param_spec);
1353
1354   signals[HANDLE_APPLY] =
1355     g_signal_new ("handle-apply", G_TYPE_FROM_CLASS (klass),
1356         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1357         g_cclosure_marshal_VOID__BOOLEAN,
1358         G_TYPE_NONE,
1359         1, G_TYPE_BOOLEAN);
1360
1361   /* This signal is emitted when an account has been created and enabled. */
1362   signals[ACCOUNT_CREATED] =
1363       g_signal_new ("account-created", G_TYPE_FROM_CLASS (klass),
1364           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1365           g_cclosure_marshal_VOID__VOID,
1366           G_TYPE_NONE,
1367           0);
1368
1369   signals[CANCELLED] =
1370       g_signal_new ("cancelled", G_TYPE_FROM_CLASS (klass),
1371           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1372           g_cclosure_marshal_VOID__VOID,
1373           G_TYPE_NONE,
1374           0);
1375
1376   g_type_class_add_private (klass, sizeof (EmpathyAccountWidgetPriv));
1377 }
1378
1379 static void
1380 empathy_account_widget_init (EmpathyAccountWidget *self)
1381 {
1382   EmpathyAccountWidgetPriv *priv =
1383     G_TYPE_INSTANCE_GET_PRIVATE ((self), EMPATHY_TYPE_ACCOUNT_WIDGET,
1384         EmpathyAccountWidgetPriv);
1385
1386   self->priv = priv;
1387   priv->dispose_run = FALSE;
1388
1389   self->ui_details = g_slice_new0 (EmpathyAccountWidgetUIDetails);
1390 }
1391
1392 /* public methods */
1393
1394 void
1395 empathy_account_widget_discard_pending_changes
1396     (EmpathyAccountWidget *widget)
1397 {
1398   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1399
1400   empathy_account_settings_discard_changes (priv->settings);
1401   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1402       priv->original_enabled_checkbox_value);
1403   priv->contains_pending_changes = FALSE;
1404 }
1405
1406 gboolean
1407 empathy_account_widget_contains_pending_changes (EmpathyAccountWidget *widget)
1408 {
1409   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1410
1411   return priv->contains_pending_changes;
1412 }
1413
1414 void
1415 empathy_account_widget_handle_params (EmpathyAccountWidget *self,
1416     const gchar *first_widget,
1417     ...)
1418 {
1419   va_list args;
1420
1421   va_start (args, first_widget);
1422   account_widget_handle_params_valist (self, first_widget, args);
1423   va_end (args);
1424 }
1425
1426 GtkWidget *
1427 empathy_account_widget_get_widget (EmpathyAccountWidget *widget)
1428 {
1429   return widget->ui_details->widget;
1430 }
1431
1432 EmpathyAccountWidget *
1433 empathy_account_widget_new_for_protocol (EmpathyAccountSettings *settings,
1434     gboolean simple)
1435 {
1436   EmpathyAccountWidget *self;
1437
1438   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL);
1439
1440   self = g_object_new
1441     (EMPATHY_TYPE_ACCOUNT_WIDGET,
1442         "settings", settings, "simple", simple,
1443         "creating-account",
1444         empathy_account_settings_get_account (settings) == NULL,
1445         NULL);
1446
1447   return self;
1448 }