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