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