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