]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-account-widget.c
Merge branch 'moblin'
[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         }
641     }
642
643   account_widget_set_control_buttons_sensitivity (widget, FALSE);
644 }
645
646 static void
647 account_widget_apply_clicked_cb (GtkWidget *button,
648     EmpathyAccountWidget *self)
649 {
650   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
651
652   empathy_account_settings_apply_async (priv->settings,
653       account_widget_applied_cb, self);
654 }
655
656 static void
657 account_widget_setup_generic (EmpathyAccountWidget *self)
658 {
659   GtkWidget *table_common_settings;
660   GtkWidget *table_advanced_settings;
661
662   table_common_settings = GTK_WIDGET (gtk_builder_get_object
663       (self->ui_details->gui, "table_common_settings"));
664   table_advanced_settings = GTK_WIDGET (gtk_builder_get_object
665       (self->ui_details->gui, "table_advanced_settings"));
666
667   accounts_widget_generic_setup (self, table_common_settings,
668       table_advanced_settings);
669
670   g_object_unref (self->ui_details->gui);
671 }
672
673 static void
674 account_widget_settings_ready_cb (EmpathyAccountSettings *settings,
675     GParamSpec *pspec,
676     gpointer user_data)
677 {
678   EmpathyAccountWidget *self = user_data;
679   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
680
681   if (empathy_account_settings_is_ready (priv->settings))
682     account_widget_setup_generic (self);
683 }
684
685 static void
686 account_widget_build_generic (EmpathyAccountWidget *self,
687     const char *filename)
688 {
689   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
690   GtkWidget *expander_advanced;
691
692   self->ui_details->gui = empathy_builder_get_file (filename,
693       "table_common_settings", &priv->table_common_settings,
694       "vbox_generic_settings", &self->ui_details->widget,
695       "expander_advanced_settings", &expander_advanced,
696       NULL);
697
698   if (priv->simple)
699     gtk_widget_hide (expander_advanced);
700
701   g_object_ref (self->ui_details->gui);
702
703   if (empathy_account_settings_is_ready (priv->settings))
704     account_widget_setup_generic (self);
705   else
706     g_signal_connect (priv->settings, "notify::ready",
707         G_CALLBACK (account_widget_settings_ready_cb), self);
708 }
709
710 static void
711 account_widget_build_salut (EmpathyAccountWidget *self,
712     const char *filename)
713 {
714   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
715
716   self->ui_details->gui = empathy_builder_get_file (filename,
717       "table_common_settings", &priv->table_common_settings,
718       "vbox_salut_settings", &self->ui_details->widget,
719       NULL);
720
721   empathy_account_widget_handle_params (self,
722       "entry_published", "published-name",
723       "entry_nickname", "nickname",
724       "entry_first_name", "first-name",
725       "entry_last_name", "last-name",
726       "entry_email", "email",
727       "entry_jid", "jid",
728       NULL);
729
730   self->ui_details->default_focus = g_strdup ("entry_nickname");
731 }
732
733 static void
734 account_widget_build_irc (EmpathyAccountWidget *self,
735   const char *filename)
736 {
737   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
738   empathy_account_widget_irc_build (self, filename,
739     &priv->table_common_settings);
740 }
741
742 static void
743 account_widget_build_sip (EmpathyAccountWidget *self,
744   const char *filename)
745 {
746   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
747   empathy_account_widget_sip_build (self, filename,
748     &priv->table_common_settings);
749 }
750
751 static void
752 account_widget_build_msn (EmpathyAccountWidget *self,
753     const char *filename)
754 {
755   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
756
757   if (priv->simple)
758     {
759       self->ui_details->gui = empathy_builder_get_file (filename,
760           "vbox_msn_simple", &self->ui_details->widget,
761           NULL);
762
763       empathy_account_widget_handle_params (self,
764           "entry_id_simple", "account",
765           "entry_password_simple", "password",
766           NULL);
767
768       self->ui_details->default_focus = g_strdup ("entry_id_simple");
769     }
770   else
771     {
772       self->ui_details->gui = empathy_builder_get_file (filename,
773           "table_common_msn_settings", &priv->table_common_settings,
774           "vbox_msn_settings", &self->ui_details->widget,
775           NULL);
776
777       empathy_account_widget_handle_params (self,
778           "entry_id", "account",
779           "entry_password", "password",
780           "entry_server", "server",
781           "spinbutton_port", "port",
782           NULL);
783
784       self->ui_details->default_focus = g_strdup ("entry_id");
785       self->ui_details->add_forget = TRUE;
786     }
787 }
788
789 static void
790 account_widget_build_jabber (EmpathyAccountWidget *self,
791     const char *filename)
792 {
793   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
794   GtkWidget *spinbutton_port;
795   GtkWidget *checkbutton_ssl;
796   GtkWidget *label_id, *label_password;
797   GtkWidget *label_id_create, *label_password_create;
798   GtkWidget *label_example_gtalk, *label_example_jabber;
799   gboolean is_gtalk;
800
801   is_gtalk = !tp_strdiff (
802       empathy_account_settings_get_icon_name (priv->settings),
803       "im-google-talk");
804
805   if (priv->simple && !is_gtalk)
806     {
807       self->ui_details->gui = empathy_builder_get_file (filename,
808           "vbox_jabber_simple", &self->ui_details->widget,
809           "label_id_simple", &label_id,
810           "label_id_create", &label_id_create,
811           "label_password_simple", &label_password,
812           "label_password_create", &label_password_create,
813           NULL);
814
815       if (empathy_account_settings_get_boolean (priv->settings, "register"))
816         {
817           gtk_widget_hide (label_id);
818           gtk_widget_hide (label_password);
819           gtk_widget_show (label_id_create);
820           gtk_widget_show (label_password_create);
821         }
822
823       empathy_account_widget_handle_params (self,
824           "entry_id_simple", "account",
825           "entry_password_simple", "password",
826           NULL);
827
828       self->ui_details->default_focus = g_strdup ("entry_id_simple");
829     }
830   else if (priv->simple && is_gtalk)
831     {
832       self->ui_details->gui = empathy_builder_get_file (filename,
833           "vbox_gtalk_simple", &self->ui_details->widget,
834           NULL);
835
836       empathy_account_widget_handle_params (self,
837           "entry_id_g_simple", "account",
838           "entry_password_g_simple", "password",
839           NULL);
840
841       self->ui_details->default_focus = g_strdup ("entry_id_g_simple");
842     }
843   else
844     {
845       self->ui_details->gui = empathy_builder_get_file (filename,
846           "table_common_settings", &priv->table_common_settings,
847           "vbox_jabber_settings", &self->ui_details->widget,
848           "spinbutton_port", &spinbutton_port,
849           "checkbutton_ssl", &checkbutton_ssl,
850           "label_username_example", &label_example_jabber,
851           "label_username_g_example", &label_example_gtalk,
852           NULL);
853
854       empathy_account_widget_handle_params (self,
855           "entry_id", "account",
856           "entry_password", "password",
857           "entry_resource", "resource",
858           "entry_server", "server",
859           "spinbutton_port", "port",
860           "spinbutton_priority", "priority",
861           "checkbutton_ssl", "old-ssl",
862           "checkbutton_ignore_ssl_errors", "ignore-ssl-errors",
863           "checkbutton_encryption", "require-encryption",
864           NULL);
865
866       self->ui_details->default_focus = g_strdup ("entry_id");
867       self->ui_details->add_forget = TRUE;
868       priv->spinbutton_port = spinbutton_port;
869
870       g_signal_connect (checkbutton_ssl, "toggled",
871           G_CALLBACK (account_widget_jabber_ssl_toggled_cb),
872           self);
873
874       if (is_gtalk)
875         {
876           gtk_widget_hide (label_example_jabber);
877           gtk_widget_show (label_example_gtalk);
878         }
879     }
880 }
881
882 static void
883 account_widget_build_icq (EmpathyAccountWidget *self,
884     const char *filename)
885 {
886   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
887   GtkWidget *spinbutton_port;
888
889   if (priv->simple)
890     {
891       self->ui_details->gui = empathy_builder_get_file (filename,
892           "vbox_icq_simple", &self->ui_details->widget,
893           NULL);
894
895       empathy_account_widget_handle_params (self,
896           "entry_uin_simple", "account",
897           "entry_password_simple", "password",
898           NULL);
899
900       self->ui_details->default_focus = g_strdup ("entry_uin_simple");
901     }
902   else
903     {
904       self->ui_details->gui = empathy_builder_get_file (filename,
905           "table_common_settings", &priv->table_common_settings,
906           "vbox_icq_settings", &self->ui_details->widget,
907           "spinbutton_port", &spinbutton_port,
908           NULL);
909
910       empathy_account_widget_handle_params (self,
911           "entry_uin", "account",
912           "entry_password", "password",
913           "entry_server", "server",
914           "spinbutton_port", "port",
915           "entry_charset", "charset",
916           NULL);
917
918       self->ui_details->default_focus = g_strdup ("entry_uin");
919       self->ui_details->add_forget = TRUE;
920     }
921 }
922
923 static void
924 account_widget_build_aim (EmpathyAccountWidget *self,
925     const char *filename)
926 {
927   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
928   GtkWidget *spinbutton_port;
929
930   if (priv->simple)
931     {
932       self->ui_details->gui = empathy_builder_get_file (filename,
933           "vbox_aim_simple", &self->ui_details->widget,
934           NULL);
935
936       empathy_account_widget_handle_params (self,
937           "entry_screenname_simple", "account",
938           "entry_password_simple", "password",
939           NULL);
940
941       self->ui_details->default_focus = g_strdup ("entry_screenname_simple");
942     }
943   else
944     {
945       self->ui_details->gui = empathy_builder_get_file (filename,
946           "table_common_settings", &priv->table_common_settings,
947           "vbox_aim_settings", &self->ui_details->widget,
948           "spinbutton_port", &spinbutton_port,
949           NULL);
950
951       empathy_account_widget_handle_params (self,
952           "entry_screenname", "account",
953           "entry_password", "password",
954           "entry_server", "server",
955           "spinbutton_port", "port",
956           NULL);
957
958       self->ui_details->default_focus = g_strdup ("entry_screenname");
959       self->ui_details->add_forget = TRUE;
960     }
961 }
962
963 static void
964 account_widget_build_yahoo (EmpathyAccountWidget *self,
965     const char *filename)
966 {
967   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
968
969   if (priv->simple)
970     {
971       self->ui_details->gui = empathy_builder_get_file (filename,
972           "vbox_yahoo_simple", &self->ui_details->widget,
973           NULL);
974
975       empathy_account_widget_handle_params (self,
976           "entry_id_simple", "account",
977           "entry_password_simple", "password",
978           NULL);
979
980       self->ui_details->default_focus = g_strdup ("entry_id_simple");
981     }
982   else
983     {
984       self->ui_details->gui = empathy_builder_get_file (filename,
985           "table_common_settings", &priv->table_common_settings,
986           "vbox_yahoo_settings", &self->ui_details->widget,
987           NULL);
988
989       empathy_account_widget_handle_params (self,
990           "entry_id", "account",
991           "entry_password", "password",
992           "entry_server", "server",
993           "entry_locale", "room-list-locale",
994           "entry_charset", "charset",
995           "spinbutton_port", "port",
996           "checkbutton_yahoojp", "yahoojp",
997           "checkbutton_ignore_invites", "ignore-invites",
998           NULL);
999
1000       self->ui_details->default_focus = g_strdup ("entry_id");
1001       self->ui_details->add_forget = TRUE;
1002     }
1003 }
1004
1005 static void
1006 account_widget_build_groupwise (EmpathyAccountWidget *self,
1007     const char *filename)
1008 {
1009   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1010
1011   if (priv->simple)
1012     {
1013       self->ui_details->gui = empathy_builder_get_file (filename,
1014           "vbox_groupwise_simple", &self->ui_details->widget,
1015           NULL);
1016
1017       empathy_account_widget_handle_params (self,
1018           "entry_id_simple", "account",
1019           "entry_password_simple", "password",
1020           NULL);
1021
1022       self->ui_details->default_focus = g_strdup ("entry_id_simple");
1023     }
1024   else
1025     {
1026       self->ui_details->gui = empathy_builder_get_file (filename,
1027           "table_common_groupwise_settings", &priv->table_common_settings,
1028           "vbox_groupwise_settings", &self->ui_details->widget,
1029           NULL);
1030
1031       empathy_account_widget_handle_params (self,
1032           "entry_id", "account",
1033           "entry_password", "password",
1034           "entry_server", "server",
1035           "spinbutton_port", "port",
1036           NULL);
1037
1038       self->ui_details->default_focus = g_strdup ("entry_id");
1039       self->ui_details->add_forget = TRUE;
1040     }
1041 }
1042
1043 static void
1044 account_widget_destroy_cb (GtkWidget *widget,
1045     EmpathyAccountWidget *self)
1046 {
1047   g_object_unref (self);
1048 }
1049
1050 static void
1051 empathy_account_widget_enabled_cb (EmpathyAccount *account,
1052       GParamSpec *spec,
1053       gpointer user_data)
1054 {
1055   EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
1056   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1057   gboolean enabled = empathy_account_is_enabled (account);
1058
1059   if (priv->enabled_checkbox != NULL)
1060     {
1061 #ifndef HAVE_NBTK
1062       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1063           enabled);
1064 #else
1065       nbtk_gtk_light_switch_set_active (
1066           NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox),
1067           enabled);
1068 #endif /* HAVE_NBTK */
1069     }
1070 }
1071
1072 static void
1073 #ifndef HAVE_NBTK
1074 account_widget_enabled_released_cb (GtkToggleButton *toggle_button,
1075     gpointer user_data)
1076 #else
1077 account_widget_switch_flipped_cb (NbtkGtkLightSwitch *sw,
1078     gboolean state,
1079     gpointer user_data)
1080 #endif /* HAVE_NBTK */
1081 {
1082   EmpathyAccountWidgetPriv *priv = GET_PRIV (user_data);
1083   EmpathyAccount *account;
1084 #ifndef HAVE_NBTK
1085   gboolean state;
1086
1087   state = gtk_toggle_button_get_active (toggle_button);
1088 #endif
1089
1090   account = empathy_account_settings_get_account (priv->settings);
1091
1092   /* Enable the account according to the value of the "Enabled" checkbox */
1093   empathy_account_set_enabled_async (account, state, NULL, NULL);
1094 }
1095
1096 static void
1097 do_set_property (GObject *object,
1098     guint prop_id,
1099     const GValue *value,
1100     GParamSpec *pspec)
1101 {
1102   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1103
1104   switch (prop_id)
1105     {
1106     case PROP_SETTINGS:
1107       priv->settings = g_value_dup_object (value);
1108       break;
1109     case PROP_SIMPLE:
1110       priv->simple = g_value_get_boolean (value);
1111       break;
1112     case PROP_CREATING_ACCOUNT:
1113       priv->creating_account = g_value_get_boolean (value);
1114       break;
1115     default:
1116       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1117     }
1118 }
1119
1120 static void
1121 do_get_property (GObject *object,
1122     guint prop_id,
1123     GValue *value,
1124     GParamSpec *pspec)
1125 {
1126   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1127
1128   switch (prop_id)
1129     {
1130     case PROP_PROTOCOL:
1131       g_value_set_string (value,
1132         empathy_account_settings_get_protocol (priv->settings));
1133       break;
1134     case PROP_SETTINGS:
1135       g_value_set_object (value, priv->settings);
1136       break;
1137     case PROP_SIMPLE:
1138       g_value_set_boolean (value, priv->simple);
1139       break;
1140     case PROP_CREATING_ACCOUNT:
1141       g_value_set_boolean (value, priv->creating_account);
1142       break;
1143     default:
1144       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1145     }
1146 }
1147
1148 #define WIDGET(cm, proto) \
1149   { #cm, #proto, "empathy-account-widget-"#proto".ui", \
1150     account_widget_build_##proto }
1151
1152 static void
1153 do_constructed (GObject *obj)
1154 {
1155   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1156   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1157   EmpathyAccount *account;
1158   const gchar *protocol, *cm_name;
1159   int i = 0;
1160   struct {
1161     const gchar *cm_name;
1162     const gchar *protocol;
1163     const char *file;
1164     void (*func)(EmpathyAccountWidget *self, const gchar *filename);
1165   } widgets [] = {
1166     { "salut", "local-xmpp", "empathy-account-widget-local-xmpp.ui",
1167         account_widget_build_salut },
1168     WIDGET (gabble, jabber),
1169     WIDGET (butterfly, msn),
1170     WIDGET (haze, icq),
1171     WIDGET (haze, aim),
1172     WIDGET (haze, yahoo),
1173     WIDGET (haze, groupwise),
1174     WIDGET (idle, irc),
1175     WIDGET (sofiasip, sip),
1176   };
1177
1178   cm_name = empathy_account_settings_get_cm (priv->settings);
1179   protocol = empathy_account_settings_get_protocol (priv->settings);
1180
1181   for (i = 0 ; i < G_N_ELEMENTS (widgets); i++)
1182     {
1183       if (!tp_strdiff (widgets[i].cm_name, cm_name) &&
1184           !tp_strdiff (widgets[i].protocol, protocol))
1185         {
1186           gchar *filename;
1187
1188           filename = empathy_file_lookup (widgets[i].file,
1189               "libempathy-gtk");
1190           widgets[i].func (self, filename);
1191           g_free (filename);
1192
1193           break;
1194         }
1195     }
1196
1197   if (i == G_N_ELEMENTS (widgets))
1198     {
1199       gchar *filename = empathy_file_lookup (
1200           "empathy-account-widget-generic.ui", "libempathy-gtk");
1201       account_widget_build_generic (self, filename);
1202       g_free (filename);
1203     }
1204
1205   /* handle default focus */
1206   if (self->ui_details->default_focus != NULL)
1207     {
1208       GObject *default_focus_entry;
1209
1210       default_focus_entry = gtk_builder_get_object
1211         (self->ui_details->gui, self->ui_details->default_focus);
1212       g_signal_connect (default_focus_entry, "realize",
1213           G_CALLBACK (gtk_widget_grab_focus),
1214           NULL);
1215     }
1216
1217   /* handle forget button */
1218   if (self->ui_details->add_forget)
1219     {
1220       const gchar *password = NULL;
1221
1222       priv->button_forget = GTK_WIDGET (gtk_builder_get_object
1223           (self->ui_details->gui, "button_forget"));
1224       priv->entry_password = GTK_WIDGET (gtk_builder_get_object
1225           (self->ui_details->gui, "entry_password"));
1226
1227       password = empathy_account_settings_get_string (priv->settings,
1228           "password");
1229       gtk_widget_set_sensitive (priv->button_forget,
1230           !EMP_STR_EMPTY (password));
1231
1232       g_signal_connect (priv->button_forget, "clicked",
1233           G_CALLBACK (account_widget_forget_clicked_cb),
1234           self);
1235       g_signal_connect (priv->entry_password, "changed",
1236           G_CALLBACK (account_widget_password_changed_cb),
1237           self);
1238     }
1239
1240   /* handle apply and cancel button */
1241   if (!priv->simple)
1242     {
1243       GtkWidget *hbox = gtk_hbox_new (TRUE, 3);
1244
1245       priv->cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
1246       priv->apply_button = gtk_button_new_from_stock (
1247         priv->creating_account ? GTK_STOCK_CONNECT : GTK_STOCK_APPLY);
1248
1249       gtk_box_pack_end (GTK_BOX (hbox), priv->apply_button, TRUE,
1250           TRUE, 3);
1251       gtk_box_pack_end (GTK_BOX (hbox), priv->cancel_button, TRUE,
1252           TRUE, 3);
1253
1254       gtk_box_pack_end (GTK_BOX (self->ui_details->widget), hbox, FALSE,
1255           FALSE, 3);
1256
1257       g_signal_connect (priv->cancel_button, "clicked",
1258           G_CALLBACK (account_widget_cancel_clicked_cb),
1259           self);
1260       g_signal_connect (priv->apply_button, "clicked",
1261           G_CALLBACK (account_widget_apply_clicked_cb),
1262           self);
1263       gtk_widget_show_all (hbox);
1264
1265       if (priv->creating_account)
1266         /* When creating an account, the user might have nothing to enter.
1267          * That means that no control interaction might occur,
1268          * so we update the control button sensitivity manually.
1269          */
1270         account_widget_handle_control_buttons_sensitivity (self);
1271       else
1272         account_widget_set_control_buttons_sensitivity (self, FALSE);
1273     }
1274
1275   account = empathy_account_settings_get_account (priv->settings);
1276
1277   if (account != NULL)
1278     {
1279       g_signal_connect (account, "notify::enabled",
1280           G_CALLBACK (empathy_account_widget_enabled_cb), self);
1281     }
1282
1283   /* handle the "Enabled" checkbox. We only add it when modifying an account */
1284   if (!priv->creating_account && priv->table_common_settings != NULL)
1285     {
1286 #ifdef HAVE_NBTK
1287       GtkWidget *w;
1288 #endif
1289       guint nb_rows, nb_columns;
1290
1291       priv->original_enabled_checkbox_value =
1292           empathy_account_is_enabled (account);
1293
1294 #ifndef HAVE_NBTK
1295       priv->enabled_checkbox =
1296           gtk_check_button_new_with_label (_("Enabled"));
1297
1298       gtk_toggle_button_set_active (
1299           GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1300           priv->original_enabled_checkbox_value);
1301 #else
1302       w = gtk_label_new (_("Account:"));
1303       gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
1304
1305       priv->enabled_checkbox = nbtk_gtk_light_switch_new ();
1306
1307       nbtk_gtk_light_switch_set_active (
1308           NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox),
1309           priv->original_enabled_checkbox_value);
1310
1311       gtk_widget_show (w);
1312 #endif /* HAVE_NBTK */
1313
1314       g_object_get (priv->table_common_settings, "n-rows", &nb_rows,
1315           "n-columns", &nb_columns, NULL);
1316
1317       gtk_table_resize (GTK_TABLE (priv->table_common_settings), ++nb_rows,
1318           nb_columns);
1319
1320 #ifndef HAVE_NBTK
1321       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1322           priv->enabled_checkbox,
1323           0, nb_columns, nb_rows - 1, nb_rows,
1324           GTK_EXPAND | GTK_FILL, 0, 0, 0);
1325 #else
1326       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1327           w,
1328           0, 1, nb_rows - 1, nb_rows,
1329           GTK_FILL, 0, 0, 0);
1330       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1331           priv->enabled_checkbox,
1332           1, nb_columns, nb_rows - 1, nb_rows,
1333           GTK_EXPAND | GTK_FILL, 0, 0, 0);
1334 #endif /* HAVE_NBTK */
1335
1336       gtk_widget_show (priv->enabled_checkbox);
1337
1338 #ifndef HAVE_NBTK
1339       g_signal_connect (G_OBJECT (priv->enabled_checkbox), "released",
1340           G_CALLBACK (account_widget_enabled_released_cb), self);
1341 #else
1342       g_signal_connect (G_OBJECT (priv->enabled_checkbox), "switch-flipped",
1343           G_CALLBACK (account_widget_switch_flipped_cb), self);
1344 #endif /* HAVE_NBTK */
1345     }
1346
1347   /* hook up to widget destruction to unref ourselves */
1348   g_signal_connect (self->ui_details->widget, "destroy",
1349       G_CALLBACK (account_widget_destroy_cb), self);
1350
1351   empathy_builder_unref_and_keep_widget (self->ui_details->gui,
1352       self->ui_details->widget);
1353   self->ui_details->gui = NULL;
1354 }
1355
1356 static void
1357 do_dispose (GObject *obj)
1358 {
1359   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1360   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1361
1362   if (priv->dispose_run)
1363     return;
1364
1365   priv->dispose_run = TRUE;
1366
1367   empathy_account_settings_is_ready (priv->settings);
1368
1369   if (priv->settings != NULL)
1370     {
1371       EmpathyAccount *account;
1372       account = empathy_account_settings_get_account (priv->settings);
1373
1374       if (account != NULL)
1375         {
1376           g_signal_handlers_disconnect_by_func (account,
1377               empathy_account_widget_enabled_cb, self);
1378         }
1379
1380       g_object_unref (priv->settings);
1381       priv->settings = NULL;
1382     }
1383
1384   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose != NULL)
1385     G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose (obj);
1386 }
1387
1388 static void
1389 do_finalize (GObject *obj)
1390 {
1391   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1392
1393   g_free (self->ui_details->default_focus);
1394   g_slice_free (EmpathyAccountWidgetUIDetails, self->ui_details);
1395
1396   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize != NULL)
1397     G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize (obj);
1398 }
1399
1400 static void
1401 empathy_account_widget_class_init (EmpathyAccountWidgetClass *klass)
1402 {
1403   GObjectClass *oclass = G_OBJECT_CLASS (klass);
1404   GParamSpec *param_spec;
1405
1406   oclass->get_property = do_get_property;
1407   oclass->set_property = do_set_property;
1408   oclass->constructed = do_constructed;
1409   oclass->dispose = do_dispose;
1410   oclass->finalize = do_finalize;
1411
1412   param_spec = g_param_spec_string ("protocol",
1413       "protocol", "The protocol of the account",
1414       NULL,
1415       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1416   g_object_class_install_property (oclass, PROP_PROTOCOL, param_spec);
1417
1418   param_spec = g_param_spec_object ("settings",
1419       "settings", "The settings of the account",
1420       EMPATHY_TYPE_ACCOUNT_SETTINGS,
1421       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1422   g_object_class_install_property (oclass, PROP_SETTINGS, param_spec);
1423
1424   param_spec = g_param_spec_boolean ("simple",
1425       "simple", "Whether the account widget is a simple or an advanced one",
1426       FALSE,
1427       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1428   g_object_class_install_property (oclass, PROP_SIMPLE, param_spec);
1429
1430   param_spec = g_param_spec_boolean ("creating-account",
1431       "creating-account",
1432       "TRUE if we're creating an account, FALSE if we're modifying it",
1433       FALSE,
1434       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1435   g_object_class_install_property (oclass, PROP_CREATING_ACCOUNT, param_spec);
1436
1437   signals[HANDLE_APPLY] =
1438     g_signal_new ("handle-apply", G_TYPE_FROM_CLASS (klass),
1439         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1440         g_cclosure_marshal_VOID__BOOLEAN,
1441         G_TYPE_NONE,
1442         1, G_TYPE_BOOLEAN);
1443
1444   /* This signal is emitted when an account has been created and enabled. */
1445   signals[ACCOUNT_CREATED] =
1446       g_signal_new ("account-created", G_TYPE_FROM_CLASS (klass),
1447           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1448           g_cclosure_marshal_VOID__VOID,
1449           G_TYPE_NONE,
1450           0);
1451
1452   signals[CANCELLED] =
1453       g_signal_new ("cancelled", G_TYPE_FROM_CLASS (klass),
1454           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1455           g_cclosure_marshal_VOID__VOID,
1456           G_TYPE_NONE,
1457           0);
1458
1459   g_type_class_add_private (klass, sizeof (EmpathyAccountWidgetPriv));
1460 }
1461
1462 static void
1463 empathy_account_widget_init (EmpathyAccountWidget *self)
1464 {
1465   EmpathyAccountWidgetPriv *priv =
1466     G_TYPE_INSTANCE_GET_PRIVATE ((self), EMPATHY_TYPE_ACCOUNT_WIDGET,
1467         EmpathyAccountWidgetPriv);
1468
1469   self->priv = priv;
1470   priv->dispose_run = FALSE;
1471
1472   self->ui_details = g_slice_new0 (EmpathyAccountWidgetUIDetails);
1473 }
1474
1475 /* public methods */
1476
1477 void
1478 empathy_account_widget_discard_pending_changes
1479     (EmpathyAccountWidget *widget)
1480 {
1481   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1482
1483   empathy_account_settings_discard_changes (priv->settings);
1484
1485 #ifndef HAVE_NBTK
1486   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1487       priv->original_enabled_checkbox_value);
1488 #else
1489   nbtk_gtk_light_switch_set_active (
1490       NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox),
1491       priv->original_enabled_checkbox_value);
1492 #endif /* HAVE_NBTK */
1493
1494   priv->contains_pending_changes = FALSE;
1495 }
1496
1497 gboolean
1498 empathy_account_widget_contains_pending_changes (EmpathyAccountWidget *widget)
1499 {
1500   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1501
1502   return priv->contains_pending_changes;
1503 }
1504
1505 void
1506 empathy_account_widget_handle_params (EmpathyAccountWidget *self,
1507     const gchar *first_widget,
1508     ...)
1509 {
1510   va_list args;
1511
1512   va_start (args, first_widget);
1513   account_widget_handle_params_valist (self, first_widget, args);
1514   va_end (args);
1515 }
1516
1517 GtkWidget *
1518 empathy_account_widget_get_widget (EmpathyAccountWidget *widget)
1519 {
1520   return widget->ui_details->widget;
1521 }
1522
1523 EmpathyAccountWidget *
1524 empathy_account_widget_new_for_protocol (EmpathyAccountSettings *settings,
1525     gboolean simple)
1526 {
1527   EmpathyAccountWidget *self;
1528
1529   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL);
1530
1531   self = g_object_new
1532     (EMPATHY_TYPE_ACCOUNT_WIDGET,
1533         "settings", settings, "simple", simple,
1534         "creating-account",
1535         empathy_account_settings_get_account (settings) == NULL,
1536         NULL);
1537
1538   return self;
1539 }