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