]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-account-widget.c
account_widget_combobox_changed_cb: check that param has a default
[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 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         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       account_widget_setup_widget (self, GTK_WIDGET (object), param_name);
637     }
638 }
639
640 static void
641 account_widget_cancel_clicked_cb (GtkWidget *button,
642     EmpathyAccountWidget *self)
643 {
644   g_signal_emit (self, signals[CANCELLED], 0);
645 }
646
647 static void
648 account_widget_account_enabled_cb (GObject *source_object,
649     GAsyncResult *res,
650     gpointer user_data)
651 {
652   GError *error = NULL;
653   TpAccount *account = TP_ACCOUNT (source_object);
654   EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
655   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
656
657   tp_account_set_enabled_finish (account, res, &error);
658
659   if (error != NULL)
660     {
661       DEBUG ("Could not automatically enable new account: %s", error->message);
662       g_error_free (error);
663     }
664   else
665     {
666       priv->account_created = TRUE;
667       g_signal_emit (widget, signals[ACCOUNT_CREATED], 0);
668     }
669 }
670
671 static void
672 account_widget_applied_cb (GObject *source_object,
673     GAsyncResult *res,
674     gpointer user_data)
675 {
676   GError *error = NULL;
677   TpAccount *account;
678   EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source_object);
679   EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
680   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
681
682   empathy_account_settings_apply_finish (settings, res, &error);
683
684   if (error != NULL)
685     {
686       DEBUG ("Could not apply changes to account: %s", error->message);
687       g_error_free (error);
688       return;
689     }
690
691   account = empathy_account_settings_get_account (priv->settings);
692
693   if (account != NULL)
694     {
695       if (priv->creating_account)
696         {
697           /* By default, when an account is created, we enable it. */
698           tp_account_set_enabled_async (account, TRUE,
699               account_widget_account_enabled_cb, widget);
700         }
701       else if (priv->enabled_checkbox != NULL)
702         {
703           gboolean enabled_checked;
704
705           enabled_checked =
706 #ifndef HAVE_MOBLIN
707             gtk_toggle_button_get_active (
708                 GTK_TOGGLE_BUTTON (priv->enabled_checkbox));
709 #else
710             nbtk_gtk_light_switch_get_active (
711                 NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox));
712 #endif
713
714           if (tp_account_is_enabled (account) && enabled_checked)
715             {
716               /* After having applied changes to a user account, we
717                * automatically reconnect it. This is done so the new
718                * information entered by the user is validated on the server. */
719               tp_account_reconnect_async (account, NULL, NULL);
720             }
721         }
722     }
723
724   account_widget_set_control_buttons_sensitivity (widget, FALSE);
725 }
726
727 static void
728 account_widget_apply_clicked_cb (GtkWidget *button,
729     EmpathyAccountWidget *self)
730 {
731   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
732
733   empathy_account_settings_apply_async (priv->settings,
734       account_widget_applied_cb, self);
735 }
736
737 static void
738 account_widget_setup_generic (EmpathyAccountWidget *self)
739 {
740   GtkWidget *table_common_settings;
741   GtkWidget *table_advanced_settings;
742
743   table_common_settings = GTK_WIDGET (gtk_builder_get_object
744       (self->ui_details->gui, "table_common_settings"));
745   table_advanced_settings = GTK_WIDGET (gtk_builder_get_object
746       (self->ui_details->gui, "table_advanced_settings"));
747
748   accounts_widget_generic_setup (self, table_common_settings,
749       table_advanced_settings);
750
751   g_object_unref (self->ui_details->gui);
752 }
753
754 static void
755 account_widget_settings_ready_cb (EmpathyAccountSettings *settings,
756     GParamSpec *pspec,
757     gpointer user_data)
758 {
759   EmpathyAccountWidget *self = user_data;
760   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
761
762   if (empathy_account_settings_is_ready (priv->settings))
763     account_widget_setup_generic (self);
764 }
765
766 static void
767 account_widget_build_generic (EmpathyAccountWidget *self,
768     const char *filename)
769 {
770   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
771   GtkWidget *expander_advanced;
772
773   self->ui_details->gui = empathy_builder_get_file (filename,
774       "table_common_settings", &priv->table_common_settings,
775       "vbox_generic_settings", &self->ui_details->widget,
776       "expander_advanced_settings", &expander_advanced,
777       NULL);
778
779   if (priv->simple)
780     gtk_widget_hide (expander_advanced);
781
782   g_object_ref (self->ui_details->gui);
783
784   if (empathy_account_settings_is_ready (priv->settings))
785     account_widget_setup_generic (self);
786   else
787     g_signal_connect (priv->settings, "notify::ready",
788         G_CALLBACK (account_widget_settings_ready_cb), self);
789 }
790
791 static void
792 account_widget_build_salut (EmpathyAccountWidget *self,
793     const char *filename)
794 {
795   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
796
797   self->ui_details->gui = empathy_builder_get_file (filename,
798       "table_common_settings", &priv->table_common_settings,
799       "vbox_salut_settings", &self->ui_details->widget,
800       NULL);
801
802   empathy_account_widget_handle_params (self,
803       "entry_published", "published-name",
804       "entry_nickname", "nickname",
805       "entry_first_name", "first-name",
806       "entry_last_name", "last-name",
807       "entry_email", "email",
808       "entry_jid", "jid",
809       NULL);
810
811   self->ui_details->default_focus = g_strdup ("entry_first_name");
812 }
813
814 static void
815 account_widget_build_irc (EmpathyAccountWidget *self,
816   const char *filename)
817 {
818   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
819   empathy_account_widget_irc_build (self, filename,
820     &priv->table_common_settings);
821 }
822
823 static void
824 account_widget_build_sip (EmpathyAccountWidget *self,
825   const char *filename)
826 {
827   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
828   empathy_account_widget_sip_build (self, filename,
829     &priv->table_common_settings);
830 }
831
832 static void
833 account_widget_build_msn (EmpathyAccountWidget *self,
834     const char *filename)
835 {
836   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
837
838   if (priv->simple)
839     {
840       self->ui_details->gui = empathy_builder_get_file (filename,
841           "vbox_msn_simple", &self->ui_details->widget,
842           NULL);
843
844       empathy_account_widget_handle_params (self,
845           "entry_id_simple", "account",
846           "entry_password_simple", "password",
847           NULL);
848
849       self->ui_details->default_focus = g_strdup ("entry_id_simple");
850     }
851   else
852     {
853       self->ui_details->gui = empathy_builder_get_file (filename,
854           "table_common_msn_settings", &priv->table_common_settings,
855           "vbox_msn_settings", &self->ui_details->widget,
856           NULL);
857
858       empathy_account_widget_handle_params (self,
859           "entry_id", "account",
860           "entry_password", "password",
861           "entry_server", "server",
862           "spinbutton_port", "port",
863           NULL);
864
865       self->ui_details->default_focus = g_strdup ("entry_id");
866       self->ui_details->add_forget = TRUE;
867     }
868 }
869
870 static void
871 account_widget_build_jabber (EmpathyAccountWidget *self,
872     const char *filename)
873 {
874   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
875   GtkWidget *spinbutton_port;
876   GtkWidget *checkbutton_ssl;
877   GtkWidget *label_id, *label_password;
878   GtkWidget *label_id_create, *label_password_create;
879   GtkWidget *label_example_gtalk, *label_example_jabber;
880   gboolean is_gtalk;
881
882   is_gtalk = !tp_strdiff (
883       empathy_account_settings_get_icon_name (priv->settings),
884       "im-google-talk");
885
886   if (priv->simple && !is_gtalk)
887     {
888       self->ui_details->gui = empathy_builder_get_file (filename,
889           "vbox_jabber_simple", &self->ui_details->widget,
890           "label_id_simple", &label_id,
891           "label_id_create", &label_id_create,
892           "label_password_simple", &label_password,
893           "label_password_create", &label_password_create,
894           NULL);
895
896       if (empathy_account_settings_get_boolean (priv->settings, "register"))
897         {
898           gtk_widget_hide (label_id);
899           gtk_widget_hide (label_password);
900           gtk_widget_show (label_id_create);
901           gtk_widget_show (label_password_create);
902         }
903
904       empathy_account_widget_handle_params (self,
905           "entry_id_simple", "account",
906           "entry_password_simple", "password",
907           NULL);
908
909       self->ui_details->default_focus = g_strdup ("entry_id_simple");
910     }
911   else if (priv->simple && is_gtalk)
912     {
913       self->ui_details->gui = empathy_builder_get_file (filename,
914           "vbox_gtalk_simple", &self->ui_details->widget,
915           NULL);
916
917       empathy_account_widget_handle_params (self,
918           "entry_id_g_simple", "account",
919           "entry_password_g_simple", "password",
920           NULL);
921
922       self->ui_details->default_focus = g_strdup ("entry_id_g_simple");
923     }
924   else
925     {
926       self->ui_details->gui = empathy_builder_get_file (filename,
927           "table_common_settings", &priv->table_common_settings,
928           "vbox_jabber_settings", &self->ui_details->widget,
929           "spinbutton_port", &spinbutton_port,
930           "checkbutton_ssl", &checkbutton_ssl,
931           "label_username_example", &label_example_jabber,
932           "label_username_g_example", &label_example_gtalk,
933           NULL);
934
935       empathy_account_widget_handle_params (self,
936           "entry_id", "account",
937           "entry_password", "password",
938           "entry_resource", "resource",
939           "entry_server", "server",
940           "spinbutton_port", "port",
941           "spinbutton_priority", "priority",
942           "checkbutton_ssl", "old-ssl",
943           "checkbutton_ignore_ssl_errors", "ignore-ssl-errors",
944           "checkbutton_encryption", "require-encryption",
945           NULL);
946
947       self->ui_details->default_focus = g_strdup ("entry_id");
948       self->ui_details->add_forget = TRUE;
949       priv->spinbutton_port = spinbutton_port;
950
951       g_signal_connect (checkbutton_ssl, "toggled",
952           G_CALLBACK (account_widget_jabber_ssl_toggled_cb),
953           self);
954
955       if (is_gtalk)
956         {
957           gtk_widget_hide (label_example_jabber);
958           gtk_widget_show (label_example_gtalk);
959         }
960     }
961 }
962
963 static void
964 account_widget_build_icq (EmpathyAccountWidget *self,
965     const char *filename)
966 {
967   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
968   GtkWidget *spinbutton_port;
969
970   if (priv->simple)
971     {
972       self->ui_details->gui = empathy_builder_get_file (filename,
973           "vbox_icq_simple", &self->ui_details->widget,
974           NULL);
975
976       empathy_account_widget_handle_params (self,
977           "entry_uin_simple", "account",
978           "entry_password_simple", "password",
979           NULL);
980
981       self->ui_details->default_focus = g_strdup ("entry_uin_simple");
982     }
983   else
984     {
985       self->ui_details->gui = empathy_builder_get_file (filename,
986           "table_common_settings", &priv->table_common_settings,
987           "vbox_icq_settings", &self->ui_details->widget,
988           "spinbutton_port", &spinbutton_port,
989           NULL);
990
991       empathy_account_widget_handle_params (self,
992           "entry_uin", "account",
993           "entry_password", "password",
994           "entry_server", "server",
995           "spinbutton_port", "port",
996           "entry_charset", "charset",
997           NULL);
998
999       self->ui_details->default_focus = g_strdup ("entry_uin");
1000       self->ui_details->add_forget = TRUE;
1001     }
1002 }
1003
1004 static void
1005 account_widget_build_aim (EmpathyAccountWidget *self,
1006     const char *filename)
1007 {
1008   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1009   GtkWidget *spinbutton_port;
1010
1011   if (priv->simple)
1012     {
1013       self->ui_details->gui = empathy_builder_get_file (filename,
1014           "vbox_aim_simple", &self->ui_details->widget,
1015           NULL);
1016
1017       empathy_account_widget_handle_params (self,
1018           "entry_screenname_simple", "account",
1019           "entry_password_simple", "password",
1020           NULL);
1021
1022       self->ui_details->default_focus = g_strdup ("entry_screenname_simple");
1023     }
1024   else
1025     {
1026       self->ui_details->gui = empathy_builder_get_file (filename,
1027           "table_common_settings", &priv->table_common_settings,
1028           "vbox_aim_settings", &self->ui_details->widget,
1029           "spinbutton_port", &spinbutton_port,
1030           NULL);
1031
1032       empathy_account_widget_handle_params (self,
1033           "entry_screenname", "account",
1034           "entry_password", "password",
1035           "entry_server", "server",
1036           "spinbutton_port", "port",
1037           NULL);
1038
1039       self->ui_details->default_focus = g_strdup ("entry_screenname");
1040       self->ui_details->add_forget = TRUE;
1041     }
1042 }
1043
1044 static void
1045 account_widget_build_yahoo (EmpathyAccountWidget *self,
1046     const char *filename)
1047 {
1048   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1049
1050   if (priv->simple)
1051     {
1052       self->ui_details->gui = empathy_builder_get_file (filename,
1053           "vbox_yahoo_simple", &self->ui_details->widget,
1054           NULL);
1055
1056       empathy_account_widget_handle_params (self,
1057           "entry_id_simple", "account",
1058           "entry_password_simple", "password",
1059           NULL);
1060
1061       self->ui_details->default_focus = g_strdup ("entry_id_simple");
1062     }
1063   else
1064     {
1065       self->ui_details->gui = empathy_builder_get_file (filename,
1066           "table_common_settings", &priv->table_common_settings,
1067           "vbox_yahoo_settings", &self->ui_details->widget,
1068           NULL);
1069
1070       empathy_account_widget_handle_params (self,
1071           "entry_id", "account",
1072           "entry_password", "password",
1073           "entry_server", "server",
1074           "entry_locale", "room-list-locale",
1075           "entry_charset", "charset",
1076           "spinbutton_port", "port",
1077           "checkbutton_yahoojp", "yahoojp",
1078           "checkbutton_ignore_invites", "ignore-invites",
1079           NULL);
1080
1081       self->ui_details->default_focus = g_strdup ("entry_id");
1082       self->ui_details->add_forget = TRUE;
1083     }
1084 }
1085
1086 static void
1087 account_widget_build_groupwise (EmpathyAccountWidget *self,
1088     const char *filename)
1089 {
1090   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1091
1092   if (priv->simple)
1093     {
1094       self->ui_details->gui = empathy_builder_get_file (filename,
1095           "vbox_groupwise_simple", &self->ui_details->widget,
1096           NULL);
1097
1098       empathy_account_widget_handle_params (self,
1099           "entry_id_simple", "account",
1100           "entry_password_simple", "password",
1101           NULL);
1102
1103       self->ui_details->default_focus = g_strdup ("entry_id_simple");
1104     }
1105   else
1106     {
1107       self->ui_details->gui = empathy_builder_get_file (filename,
1108           "table_common_groupwise_settings", &priv->table_common_settings,
1109           "vbox_groupwise_settings", &self->ui_details->widget,
1110           NULL);
1111
1112       empathy_account_widget_handle_params (self,
1113           "entry_id", "account",
1114           "entry_password", "password",
1115           "entry_server", "server",
1116           "spinbutton_port", "port",
1117           NULL);
1118
1119       self->ui_details->default_focus = g_strdup ("entry_id");
1120       self->ui_details->add_forget = TRUE;
1121     }
1122 }
1123
1124 static void
1125 account_widget_destroy_cb (GtkWidget *widget,
1126     EmpathyAccountWidget *self)
1127 {
1128   g_object_unref (self);
1129 }
1130
1131 static void
1132 empathy_account_widget_enabled_cb (TpAccount *account,
1133       GParamSpec *spec,
1134       gpointer user_data)
1135 {
1136   EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
1137   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1138   gboolean enabled = tp_account_is_enabled (account);
1139
1140   if (priv->enabled_checkbox != NULL)
1141     {
1142 #ifndef HAVE_MOBLIN
1143       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_checkbox),
1144           enabled);
1145 #else
1146       nbtk_gtk_light_switch_set_active (
1147           NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox),
1148           enabled);
1149 #endif /* HAVE_MOBLIN */
1150     }
1151 }
1152
1153 static void
1154 #ifndef HAVE_MOBLIN
1155 account_widget_enabled_released_cb (GtkToggleButton *toggle_button,
1156     gpointer user_data)
1157 #else
1158 account_widget_switch_flipped_cb (NbtkGtkLightSwitch *sw,
1159     gboolean state,
1160     gpointer user_data)
1161 #endif /* HAVE_MOBLIN */
1162 {
1163   EmpathyAccountWidgetPriv *priv = GET_PRIV (user_data);
1164   TpAccount *account;
1165 #ifndef HAVE_MOBLIN
1166   gboolean state;
1167
1168   state = gtk_toggle_button_get_active (toggle_button);
1169 #endif
1170
1171   account = empathy_account_settings_get_account (priv->settings);
1172
1173   /* Enable the account according to the value of the "Enabled" checkbox */
1174   tp_account_set_enabled_async (account, state, NULL, NULL);
1175 }
1176
1177 static void
1178 do_set_property (GObject *object,
1179     guint prop_id,
1180     const GValue *value,
1181     GParamSpec *pspec)
1182 {
1183   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1184
1185   switch (prop_id)
1186     {
1187     case PROP_SETTINGS:
1188       priv->settings = g_value_dup_object (value);
1189       break;
1190     case PROP_SIMPLE:
1191       priv->simple = g_value_get_boolean (value);
1192       break;
1193     case PROP_CREATING_ACCOUNT:
1194       priv->creating_account = g_value_get_boolean (value);
1195       break;
1196     default:
1197       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1198     }
1199 }
1200
1201 static void
1202 do_get_property (GObject *object,
1203     guint prop_id,
1204     GValue *value,
1205     GParamSpec *pspec)
1206 {
1207   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1208
1209   switch (prop_id)
1210     {
1211     case PROP_PROTOCOL:
1212       g_value_set_string (value,
1213         empathy_account_settings_get_protocol (priv->settings));
1214       break;
1215     case PROP_SETTINGS:
1216       g_value_set_object (value, priv->settings);
1217       break;
1218     case PROP_SIMPLE:
1219       g_value_set_boolean (value, priv->simple);
1220       break;
1221     case PROP_CREATING_ACCOUNT:
1222       g_value_set_boolean (value, priv->creating_account);
1223       break;
1224     default:
1225       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1226     }
1227 }
1228
1229 static void
1230 presence_changed_cb (TpAccountManager *manager,
1231     TpConnectionPresenceType state,
1232     const gchar *status,
1233     const gchar *message,
1234     EmpathyAccountWidget *self)
1235 {
1236   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1237
1238   if (state > TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
1239     {
1240       /* We are online, display a Login button */
1241       GtkWidget *image;
1242
1243       gtk_button_set_use_stock (GTK_BUTTON (priv->apply_button), FALSE);
1244       gtk_button_set_label (GTK_BUTTON (priv->apply_button), _("L_og in"));
1245
1246       image = gtk_image_new_from_stock (GTK_STOCK_CONNECT,
1247           GTK_ICON_SIZE_BUTTON);
1248       gtk_button_set_image (GTK_BUTTON (priv->apply_button), image);
1249     }
1250   else
1251     {
1252       /* We are offline, display a Save button */
1253       gtk_button_set_image (GTK_BUTTON (priv->apply_button), NULL);
1254       gtk_button_set_use_stock (GTK_BUTTON (priv->apply_button), TRUE);
1255       gtk_button_set_label (GTK_BUTTON (priv->apply_button), GTK_STOCK_SAVE);
1256     }
1257 }
1258
1259 static void
1260 account_manager_ready_cb (GObject *source_object,
1261     GAsyncResult *result,
1262     gpointer user_data)
1263 {
1264   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (user_data);
1265   TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
1266   GError *error = NULL;
1267   TpConnectionPresenceType state;
1268
1269   if (!tp_account_manager_prepare_finish (account_manager, result, &error))
1270     {
1271       DEBUG ("Failed to prepare account manager: %s", error->message);
1272       g_error_free (error);
1273       return;
1274     }
1275
1276   state = tp_account_manager_get_most_available_presence (account_manager, NULL,
1277       NULL);
1278
1279   /* simulate a presence change so the apply button will be changed
1280    * if needed */
1281   presence_changed_cb (account_manager, state, NULL, NULL, self);
1282 }
1283
1284 #define WIDGET(cm, proto) \
1285   { #cm, #proto, "empathy-account-widget-"#proto".ui", \
1286     account_widget_build_##proto }
1287
1288 static void
1289 do_constructed (GObject *obj)
1290 {
1291   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1292   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1293   TpAccount *account;
1294   const gchar *protocol, *cm_name;
1295   guint i = 0;
1296   struct {
1297     const gchar *cm_name;
1298     const gchar *protocol;
1299     const char *file;
1300     void (*func)(EmpathyAccountWidget *self, const gchar *filename);
1301   } widgets [] = {
1302     { "salut", "local-xmpp", "empathy-account-widget-local-xmpp.ui",
1303         account_widget_build_salut },
1304     WIDGET (gabble, jabber),
1305     WIDGET (butterfly, msn),
1306     WIDGET (haze, icq),
1307     WIDGET (haze, aim),
1308     WIDGET (haze, yahoo),
1309     WIDGET (haze, groupwise),
1310     WIDGET (idle, irc),
1311     WIDGET (sofiasip, sip),
1312   };
1313
1314   cm_name = empathy_account_settings_get_cm (priv->settings);
1315   protocol = empathy_account_settings_get_protocol (priv->settings);
1316
1317   for (i = 0 ; i < G_N_ELEMENTS (widgets); i++)
1318     {
1319       if (!tp_strdiff (widgets[i].cm_name, cm_name) &&
1320           !tp_strdiff (widgets[i].protocol, protocol))
1321         {
1322           gchar *filename;
1323
1324           filename = empathy_file_lookup (widgets[i].file,
1325               "libempathy-gtk");
1326           widgets[i].func (self, filename);
1327           g_free (filename);
1328
1329           break;
1330         }
1331     }
1332
1333   if (i == G_N_ELEMENTS (widgets))
1334     {
1335       gchar *filename = empathy_file_lookup (
1336           "empathy-account-widget-generic.ui", "libempathy-gtk");
1337       account_widget_build_generic (self, filename);
1338       g_free (filename);
1339     }
1340
1341   /* handle default focus */
1342   if (self->ui_details->default_focus != NULL)
1343     {
1344       GObject *default_focus_entry;
1345
1346       default_focus_entry = gtk_builder_get_object
1347         (self->ui_details->gui, self->ui_details->default_focus);
1348       g_signal_connect (default_focus_entry, "realize",
1349           G_CALLBACK (gtk_widget_grab_focus),
1350           NULL);
1351     }
1352
1353   /* handle forget button */
1354   if (self->ui_details->add_forget)
1355     {
1356       const gchar *password = NULL;
1357
1358       priv->button_forget = GTK_WIDGET (gtk_builder_get_object
1359           (self->ui_details->gui, "button_forget"));
1360       priv->entry_password = GTK_WIDGET (gtk_builder_get_object
1361           (self->ui_details->gui, "entry_password"));
1362
1363       password = empathy_account_settings_get_string (priv->settings,
1364           "password");
1365       gtk_widget_set_sensitive (priv->button_forget,
1366           !EMP_STR_EMPTY (password));
1367
1368       g_signal_connect (priv->button_forget, "clicked",
1369           G_CALLBACK (account_widget_forget_clicked_cb),
1370           self);
1371       g_signal_connect (priv->entry_password, "changed",
1372           G_CALLBACK (account_widget_password_changed_cb),
1373           self);
1374     }
1375
1376   /* handle apply and cancel button */
1377   if (!priv->simple)
1378     {
1379       GtkWidget *hbox = gtk_hbox_new (TRUE, 3);
1380
1381       priv->cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
1382
1383       if (priv->creating_account)
1384         {
1385           priv->account_manager = tp_account_manager_dup ();
1386
1387           empathy_signal_connect_weak (priv->account_manager,
1388               "most-available-presence-changed",
1389               G_CALLBACK (presence_changed_cb), obj);
1390
1391           tp_account_manager_prepare_async (priv->account_manager, NULL,
1392               account_manager_ready_cb, self);
1393
1394           /* Assumre we are offline, display a Save button. We'll update
1395            * it once the account manager is ready if needed */
1396           priv->apply_button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
1397         }
1398       else
1399         {
1400           /* We are editing an existing account, display an Apply button */
1401           priv->apply_button = gtk_button_new_from_stock (GTK_STOCK_APPLY);
1402         }
1403
1404       gtk_box_pack_end (GTK_BOX (hbox), priv->apply_button, TRUE,
1405           TRUE, 3);
1406       gtk_box_pack_end (GTK_BOX (hbox), priv->cancel_button, TRUE,
1407           TRUE, 3);
1408
1409       gtk_box_pack_end (GTK_BOX (self->ui_details->widget), hbox, FALSE,
1410           FALSE, 3);
1411
1412       g_signal_connect (priv->cancel_button, "clicked",
1413           G_CALLBACK (account_widget_cancel_clicked_cb),
1414           self);
1415       g_signal_connect (priv->apply_button, "clicked",
1416           G_CALLBACK (account_widget_apply_clicked_cb),
1417           self);
1418       gtk_widget_show_all (hbox);
1419
1420       if (priv->creating_account)
1421         /* When creating an account, the user might have nothing to enter.
1422          * That means that no control interaction might occur,
1423          * so we update the control button sensitivity manually.
1424          */
1425         account_widget_handle_control_buttons_sensitivity (self);
1426       else
1427         account_widget_set_control_buttons_sensitivity (self, FALSE);
1428     }
1429
1430   account = empathy_account_settings_get_account (priv->settings);
1431
1432   if (account != NULL)
1433     {
1434       g_signal_connect (account, "notify::enabled",
1435           G_CALLBACK (empathy_account_widget_enabled_cb), self);
1436     }
1437
1438   /* handle the "Enabled" checkbox. We only add it when modifying an account */
1439   if (!priv->creating_account && priv->table_common_settings != NULL)
1440     {
1441 #ifdef HAVE_MOBLIN
1442       GtkWidget *w;
1443 #endif
1444       guint nb_rows, nb_columns;
1445       gboolean is_enabled;
1446
1447       is_enabled = tp_account_is_enabled (account);
1448
1449 #ifndef HAVE_MOBLIN
1450       priv->enabled_checkbox =
1451           gtk_check_button_new_with_label (_("Enabled"));
1452
1453       gtk_toggle_button_set_active (
1454           GTK_TOGGLE_BUTTON (priv->enabled_checkbox), is_enabled);
1455 #else
1456       /* Translators: this is used only when built on a moblin platform */
1457       w = gtk_label_new (_("Account:"));
1458       gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5);
1459
1460       priv->enabled_checkbox = nbtk_gtk_light_switch_new ();
1461
1462       nbtk_gtk_light_switch_set_active (
1463           NBTK_GTK_LIGHT_SWITCH (priv->enabled_checkbox), is_enabled);
1464
1465       gtk_widget_show (w);
1466 #endif /* HAVE_MOBLIN */
1467
1468       g_object_get (priv->table_common_settings, "n-rows", &nb_rows,
1469           "n-columns", &nb_columns, NULL);
1470
1471       gtk_table_resize (GTK_TABLE (priv->table_common_settings), ++nb_rows,
1472           nb_columns);
1473
1474 #ifndef HAVE_MOBLIN
1475       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1476           priv->enabled_checkbox,
1477           0, nb_columns, nb_rows - 1, nb_rows,
1478           GTK_EXPAND | GTK_FILL, 0, 0, 0);
1479 #else
1480       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1481           w,
1482           0, 1, nb_rows - 1, nb_rows,
1483           GTK_FILL, 0, 0, 0);
1484       gtk_table_attach (GTK_TABLE (priv->table_common_settings),
1485           priv->enabled_checkbox,
1486           1, nb_columns, nb_rows - 1, nb_rows,
1487           GTK_EXPAND | GTK_FILL, 0, 0, 0);
1488 #endif /* HAVE_MOBLIN */
1489
1490       gtk_widget_show (priv->enabled_checkbox);
1491
1492 #ifndef HAVE_MOBLIN
1493       g_signal_connect (G_OBJECT (priv->enabled_checkbox), "released",
1494           G_CALLBACK (account_widget_enabled_released_cb), self);
1495 #else
1496       g_signal_connect (G_OBJECT (priv->enabled_checkbox), "switch-flipped",
1497           G_CALLBACK (account_widget_switch_flipped_cb), self);
1498 #endif /* HAVE_MOBLIN */
1499     }
1500
1501   /* hook up to widget destruction to unref ourselves */
1502   g_signal_connect (self->ui_details->widget, "destroy",
1503       G_CALLBACK (account_widget_destroy_cb), self);
1504
1505   empathy_builder_unref_and_keep_widget (self->ui_details->gui,
1506       self->ui_details->widget);
1507   self->ui_details->gui = NULL;
1508 }
1509
1510 static void
1511 do_dispose (GObject *obj)
1512 {
1513   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1514   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1515
1516   if (priv->dispose_run)
1517     return;
1518
1519   priv->dispose_run = TRUE;
1520
1521   empathy_account_settings_is_ready (priv->settings);
1522
1523   if (priv->settings != NULL)
1524     {
1525       TpAccount *account;
1526       account = empathy_account_settings_get_account (priv->settings);
1527
1528       if (account != NULL)
1529         {
1530           g_signal_handlers_disconnect_by_func (account,
1531               empathy_account_widget_enabled_cb, self);
1532         }
1533
1534       g_object_unref (priv->settings);
1535       priv->settings = NULL;
1536     }
1537
1538   if (priv->account_manager != NULL)
1539     {
1540       g_object_unref (priv->account_manager);
1541       priv->account_manager = NULL;
1542     }
1543
1544   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose != NULL)
1545     G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose (obj);
1546 }
1547
1548 static void
1549 do_finalize (GObject *obj)
1550 {
1551   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1552
1553   g_free (self->ui_details->default_focus);
1554   g_slice_free (EmpathyAccountWidgetUIDetails, self->ui_details);
1555
1556   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize != NULL)
1557     G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize (obj);
1558 }
1559
1560 static void
1561 empathy_account_widget_class_init (EmpathyAccountWidgetClass *klass)
1562 {
1563   GObjectClass *oclass = G_OBJECT_CLASS (klass);
1564   GParamSpec *param_spec;
1565
1566   oclass->get_property = do_get_property;
1567   oclass->set_property = do_set_property;
1568   oclass->constructed = do_constructed;
1569   oclass->dispose = do_dispose;
1570   oclass->finalize = do_finalize;
1571
1572   param_spec = g_param_spec_string ("protocol",
1573       "protocol", "The protocol of the account",
1574       NULL,
1575       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
1576   g_object_class_install_property (oclass, PROP_PROTOCOL, param_spec);
1577
1578   param_spec = g_param_spec_object ("settings",
1579       "settings", "The settings of the account",
1580       EMPATHY_TYPE_ACCOUNT_SETTINGS,
1581       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1582   g_object_class_install_property (oclass, PROP_SETTINGS, param_spec);
1583
1584   param_spec = g_param_spec_boolean ("simple",
1585       "simple", "Whether the account widget is a simple or an advanced one",
1586       FALSE,
1587       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1588   g_object_class_install_property (oclass, PROP_SIMPLE, param_spec);
1589
1590   param_spec = g_param_spec_boolean ("creating-account",
1591       "creating-account",
1592       "TRUE if we're creating an account, FALSE if we're modifying it",
1593       FALSE,
1594       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1595   g_object_class_install_property (oclass, PROP_CREATING_ACCOUNT, param_spec);
1596
1597   signals[HANDLE_APPLY] =
1598     g_signal_new ("handle-apply", G_TYPE_FROM_CLASS (klass),
1599         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1600         g_cclosure_marshal_VOID__BOOLEAN,
1601         G_TYPE_NONE,
1602         1, G_TYPE_BOOLEAN);
1603
1604   /* This signal is emitted when an account has been created and enabled. */
1605   signals[ACCOUNT_CREATED] =
1606       g_signal_new ("account-created", G_TYPE_FROM_CLASS (klass),
1607           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1608           g_cclosure_marshal_VOID__VOID,
1609           G_TYPE_NONE,
1610           0);
1611
1612   signals[CANCELLED] =
1613       g_signal_new ("cancelled", G_TYPE_FROM_CLASS (klass),
1614           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1615           g_cclosure_marshal_VOID__VOID,
1616           G_TYPE_NONE,
1617           0);
1618
1619   g_type_class_add_private (klass, sizeof (EmpathyAccountWidgetPriv));
1620 }
1621
1622 static void
1623 empathy_account_widget_init (EmpathyAccountWidget *self)
1624 {
1625   EmpathyAccountWidgetPriv *priv =
1626     G_TYPE_INSTANCE_GET_PRIVATE ((self), EMPATHY_TYPE_ACCOUNT_WIDGET,
1627         EmpathyAccountWidgetPriv);
1628
1629   self->priv = priv;
1630   priv->dispose_run = FALSE;
1631
1632   self->ui_details = g_slice_new0 (EmpathyAccountWidgetUIDetails);
1633 }
1634
1635 /* public methods */
1636
1637 void
1638 empathy_account_widget_discard_pending_changes
1639     (EmpathyAccountWidget *widget)
1640 {
1641   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1642
1643   empathy_account_settings_discard_changes (priv->settings);
1644   priv->contains_pending_changes = FALSE;
1645 }
1646
1647 gboolean
1648 empathy_account_widget_contains_pending_changes (EmpathyAccountWidget *widget)
1649 {
1650   EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
1651
1652   if (priv->creating_account && !priv->account_created)
1653     /* We always want to warn the user if he's in the process of creating a
1654      * new account which hasn't been actually created yet. */
1655     return TRUE;
1656
1657   return priv->contains_pending_changes;
1658 }
1659
1660 void
1661 empathy_account_widget_handle_params (EmpathyAccountWidget *self,
1662     const gchar *first_widget,
1663     ...)
1664 {
1665   va_list args;
1666
1667   va_start (args, first_widget);
1668   account_widget_handle_params_valist (self, first_widget, args);
1669   va_end (args);
1670 }
1671
1672 GtkWidget *
1673 empathy_account_widget_get_widget (EmpathyAccountWidget *widget)
1674 {
1675   return widget->ui_details->widget;
1676 }
1677
1678 EmpathyAccountWidget *
1679 empathy_account_widget_new_for_protocol (EmpathyAccountSettings *settings,
1680     gboolean simple)
1681 {
1682   EmpathyAccountWidget *self;
1683
1684   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL);
1685
1686   self = g_object_new
1687     (EMPATHY_TYPE_ACCOUNT_WIDGET,
1688         "settings", settings, "simple", simple,
1689         "creating-account",
1690         empathy_account_settings_get_account (settings) == NULL,
1691         NULL);
1692
1693   return self;
1694 }
1695
1696 gchar *
1697 empathy_account_widget_get_default_display_name (EmpathyAccountWidget *self)
1698 {
1699   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1700   const gchar *login_id;
1701   const gchar *protocol, *p;
1702   gchar *default_display_name;
1703
1704   login_id = empathy_account_settings_get_string (priv->settings, "account");
1705   protocol = empathy_account_settings_get_protocol (priv->settings);
1706
1707   if (login_id != NULL)
1708     {
1709       /* TODO: this should be done in empathy-account-widget-irc */
1710       if (!tp_strdiff (protocol, "irc"))
1711         {
1712           const gchar* server;
1713           server = empathy_account_settings_get_string (priv->settings,
1714               "server");
1715
1716           /* To translators: The first parameter is the login id and the
1717            * second one is the server. The resulting string will be something
1718            * like: "MyUserName on chat.freenode.net".
1719            * You should reverse the order of these arguments if the
1720            * server should come before the login id in your locale.*/
1721           default_display_name = g_strdup_printf (_("%1$s on %2$s"),
1722               login_id, server);
1723         }
1724       else
1725         {
1726           default_display_name = g_strdup (login_id);
1727         }
1728
1729       return default_display_name;
1730     }
1731
1732   if ((p = empathy_protocol_name_to_display_name (protocol)) != NULL)
1733     protocol = p;
1734
1735   if (protocol != NULL)
1736     {
1737       /* To translators: The parameter is the protocol name. The resulting
1738        * string will be something like: "Jabber Account" */
1739       default_display_name = g_strdup_printf (_("%s Account"), protocol);
1740     }
1741   else
1742     {
1743       default_display_name = g_strdup (_("New account"));
1744     }
1745
1746   return default_display_name;
1747 }