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