]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-account-widget.c
empathy-account-widget: document that the 'Account:' string is moblin specific
[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 #ifdef HAVE_NBTK
1250       if (priv->creating_account)
1251         /* Translators: this is used only when built on a moblin platform */
1252         gtk_button_set_label (GTK_BUTTON (priv->apply_button),
1253             _("L_og in"));
1254 #endif
1255
1256       gtk_box_pack_end (GTK_BOX (hbox), priv->apply_button, TRUE,
1257           TRUE, 3);
1258       gtk_box_pack_end (GTK_BOX (hbox), priv->cancel_button, TRUE,
1259           TRUE, 3);
1260
1261       gtk_box_pack_end (GTK_BOX (self->ui_details->widget), hbox, FALSE,
1262           FALSE, 3);
1263
1264       g_signal_connect (priv->cancel_button, "clicked",
1265           G_CALLBACK (account_widget_cancel_clicked_cb),
1266           self);
1267       g_signal_connect (priv->apply_button, "clicked",
1268           G_CALLBACK (account_widget_apply_clicked_cb),
1269           self);
1270       gtk_widget_show_all (hbox);
1271
1272       if (priv->creating_account)
1273         /* When creating an account, the user might have nothing to enter.
1274          * That means that no control interaction might occur,
1275          * so we update the control button sensitivity manually.
1276          */
1277         account_widget_handle_control_buttons_sensitivity (self);
1278       else
1279         account_widget_set_control_buttons_sensitivity (self, FALSE);
1280     }
1281
1282   account = empathy_account_settings_get_account (priv->settings);
1283
1284   if (account != NULL)
1285     {
1286       g_signal_connect (account, "notify::enabled",
1287           G_CALLBACK (empathy_account_widget_enabled_cb), self);
1288     }
1289
1290   /* handle the "Enabled" checkbox. We only add it when modifying an account */
1291   if (!priv->creating_account && priv->table_common_settings != NULL)
1292     {
1293 #ifdef HAVE_NBTK
1294       GtkWidget *w;
1295 #endif
1296       guint nb_rows, nb_columns;
1297
1298       priv->original_enabled_checkbox_value =
1299           empathy_account_is_enabled (account);
1300
1301 #ifndef HAVE_NBTK
1302       priv->enabled_checkbox =
1303           gtk_check_button_new_with_label (_("Enabled"));
1304
1305       gtk_toggle_button_set_active (
1306           GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1307           priv->original_enabled_checkbox_value);
1308 #else
1309       /* Translators: this is used only when built on a moblin platform */
1310       w = gtk_label_new (_("Account:"));
1311       gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
1312
1313       priv->enabled_checkbox = nbtk_gtk_light_switch_new ();
1314
1315       nbtk_gtk_light_switch_set_active (
1316           NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox),
1317           priv->original_enabled_checkbox_value);
1318
1319       gtk_widget_show (w);
1320 #endif /* HAVE_NBTK */
1321
1322       g_object_get (priv->table_common_settings, "n-rows", &nb_rows,
1323           "n-columns", &nb_columns, NULL);
1324
1325       gtk_table_resize (GTK_TABLE (priv->table_common_settings), ++nb_rows,
1326           nb_columns);
1327
1328 #ifndef HAVE_NBTK
1329       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1330           priv->enabled_checkbox,
1331           0, nb_columns, nb_rows - 1, nb_rows,
1332           GTK_EXPAND | GTK_FILL, 0, 0, 0);
1333 #else
1334       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1335           w,
1336           0, 1, nb_rows - 1, nb_rows,
1337           GTK_FILL, 0, 0, 0);
1338       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1339           priv->enabled_checkbox,
1340           1, nb_columns, nb_rows - 1, nb_rows,
1341           GTK_EXPAND | GTK_FILL, 0, 0, 0);
1342 #endif /* HAVE_NBTK */
1343
1344       gtk_widget_show (priv->enabled_checkbox);
1345
1346 #ifndef HAVE_NBTK
1347       g_signal_connect (G_OBJECT (priv->enabled_checkbox), "released",
1348           G_CALLBACK (account_widget_enabled_released_cb), self);
1349 #else
1350       g_signal_connect (G_OBJECT (priv->enabled_checkbox), "switch-flipped",
1351           G_CALLBACK (account_widget_switch_flipped_cb), self);
1352 #endif /* HAVE_NBTK */
1353     }
1354
1355   /* hook up to widget destruction to unref ourselves */
1356   g_signal_connect (self->ui_details->widget, "destroy",
1357       G_CALLBACK (account_widget_destroy_cb), self);
1358
1359   empathy_builder_unref_and_keep_widget (self->ui_details->gui,
1360       self->ui_details->widget);
1361   self->ui_details->gui = NULL;
1362 }
1363
1364 static void
1365 do_dispose (GObject *obj)
1366 {
1367   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1368   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1369
1370   if (priv->dispose_run)
1371     return;
1372
1373   priv->dispose_run = TRUE;
1374
1375   empathy_account_settings_is_ready (priv->settings);
1376
1377   if (priv->settings != NULL)
1378     {
1379       EmpathyAccount *account;
1380       account = empathy_account_settings_get_account (priv->settings);
1381
1382       if (account != NULL)
1383         {
1384           g_signal_handlers_disconnect_by_func (account,
1385               empathy_account_widget_enabled_cb, self);
1386         }
1387
1388       g_object_unref (priv->settings);
1389       priv->settings = NULL;
1390     }
1391
1392   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose != NULL)
1393     G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose (obj);
1394 }
1395
1396 static void
1397 do_finalize (GObject *obj)
1398 {
1399   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1400
1401   g_free (self->ui_details->default_focus);
1402   g_slice_free (EmpathyAccountWidgetUIDetails, self->ui_details);
1403
1404   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize != NULL)
1405     G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize (obj);
1406 }
1407
1408 static void
1409 empathy_account_widget_class_init (EmpathyAccountWidgetClass *klass)
1410 {
1411   GObjectClass *oclass = G_OBJECT_CLASS (klass);
1412   GParamSpec *param_spec;
1413
1414   oclass->get_property = do_get_property;
1415   oclass->set_property = do_set_property;
1416   oclass->constructed = do_constructed;
1417   oclass->dispose = do_dispose;
1418   oclass->finalize = do_finalize;
1419
1420   param_spec = g_param_spec_string ("protocol",
1421       "protocol", "The protocol of the account",
1422       NULL,
1423       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1424   g_object_class_install_property (oclass, PROP_PROTOCOL, param_spec);
1425
1426   param_spec = g_param_spec_object ("settings",
1427       "settings", "The settings of the account",
1428       EMPATHY_TYPE_ACCOUNT_SETTINGS,
1429       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1430   g_object_class_install_property (oclass, PROP_SETTINGS, param_spec);
1431
1432   param_spec = g_param_spec_boolean ("simple",
1433       "simple", "Whether the account widget is a simple or an advanced one",
1434       FALSE,
1435       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1436   g_object_class_install_property (oclass, PROP_SIMPLE, param_spec);
1437
1438   param_spec = g_param_spec_boolean ("creating-account",
1439       "creating-account",
1440       "TRUE if we're creating an account, FALSE if we're modifying it",
1441       FALSE,
1442       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1443   g_object_class_install_property (oclass, PROP_CREATING_ACCOUNT, param_spec);
1444
1445   signals[HANDLE_APPLY] =
1446     g_signal_new ("handle-apply", G_TYPE_FROM_CLASS (klass),
1447         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1448         g_cclosure_marshal_VOID__BOOLEAN,
1449         G_TYPE_NONE,
1450         1, G_TYPE_BOOLEAN);
1451
1452   /* This signal is emitted when an account has been created and enabled. */
1453   signals[ACCOUNT_CREATED] =
1454       g_signal_new ("account-created", G_TYPE_FROM_CLASS (klass),
1455           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1456           g_cclosure_marshal_VOID__VOID,
1457           G_TYPE_NONE,
1458           0);
1459
1460   signals[CANCELLED] =
1461       g_signal_new ("cancelled", G_TYPE_FROM_CLASS (klass),
1462           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1463           g_cclosure_marshal_VOID__VOID,
1464           G_TYPE_NONE,
1465           0);
1466
1467   g_type_class_add_private (klass, sizeof (EmpathyAccountWidgetPriv));
1468 }
1469
1470 static void
1471 empathy_account_widget_init (EmpathyAccountWidget *self)
1472 {
1473   EmpathyAccountWidgetPriv *priv =
1474     G_TYPE_INSTANCE_GET_PRIVATE ((self), EMPATHY_TYPE_ACCOUNT_WIDGET,
1475         EmpathyAccountWidgetPriv);
1476
1477   self->priv = priv;
1478   priv->dispose_run = FALSE;
1479
1480   self->ui_details = g_slice_new0 (EmpathyAccountWidgetUIDetails);
1481 }
1482
1483 /* public methods */
1484
1485 void
1486 empathy_account_widget_discard_pending_changes
1487     (EmpathyAccountWidget *widget)
1488 {
1489   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1490
1491   empathy_account_settings_discard_changes (priv->settings);
1492
1493 #ifndef HAVE_NBTK
1494   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1495       priv->original_enabled_checkbox_value);
1496 #else
1497   nbtk_gtk_light_switch_set_active (
1498       NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox),
1499       priv->original_enabled_checkbox_value);
1500 #endif /* HAVE_NBTK */
1501
1502   priv->contains_pending_changes = FALSE;
1503 }
1504
1505 gboolean
1506 empathy_account_widget_contains_pending_changes (EmpathyAccountWidget *widget)
1507 {
1508   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1509
1510   return priv->contains_pending_changes;
1511 }
1512
1513 void
1514 empathy_account_widget_handle_params (EmpathyAccountWidget *self,
1515     const gchar *first_widget,
1516     ...)
1517 {
1518   va_list args;
1519
1520   va_start (args, first_widget);
1521   account_widget_handle_params_valist (self, first_widget, args);
1522   va_end (args);
1523 }
1524
1525 GtkWidget *
1526 empathy_account_widget_get_widget (EmpathyAccountWidget *widget)
1527 {
1528   return widget->ui_details->widget;
1529 }
1530
1531 EmpathyAccountWidget *
1532 empathy_account_widget_new_for_protocol (EmpathyAccountSettings *settings,
1533     gboolean simple)
1534 {
1535   EmpathyAccountWidget *self;
1536
1537   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL);
1538
1539   self = g_object_new
1540     (EMPATHY_TYPE_ACCOUNT_WIDGET,
1541         "settings", settings, "simple", simple,
1542         "creating-account",
1543         empathy_account_settings_get_account (settings) == NULL,
1544         NULL);
1545
1546   return self;
1547 }