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