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