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