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