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