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