]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-account-widget.c
React to entry changes immediately
[empathy.git] / libempathy-gtk / empathy-account-widget.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2006-2007 Imendio AB
4  * Copyright (C) 2007-2009 Collabora Ltd.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA  02110-1301  USA
20  *
21  * Authors: Xavier Claessens <xclaesse@gmail.com>
22  *          Martyn Russell <martyn@imendio.com>
23  *          Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
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 *apply_button;
56   GtkWidget *entry_password;
57   GtkWidget *button_forget;
58   GtkWidget *spinbutton_port;
59
60   gboolean simple;
61
62   gboolean dispose_run;
63 } EmpathyAccountWidgetPriv;
64
65 enum {
66   PROP_PROTOCOL = 1,
67   PROP_SETTINGS,
68   PROP_SIMPLE
69 };
70
71 enum {
72   HANDLE_APPLY,
73   LAST_SIGNAL
74 };
75
76 static guint signals[LAST_SIGNAL] = { 0 };
77
78 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountWidget)
79 #define CHANGED_TIMEOUT 300
80
81 static void
82 account_widget_handle_apply_sensitivity (EmpathyAccountWidget *self)
83 {
84   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
85   gboolean is_valid;
86
87   is_valid = empathy_account_settings_is_valid (priv->settings);
88
89   if (!priv->simple)
90     gtk_widget_set_sensitive (priv->apply_button, is_valid);
91
92   g_signal_emit (self, signals[HANDLE_APPLY], 0, is_valid);
93 }
94
95 static void
96 account_widget_entry_changed_common (EmpathyAccountWidget *self,
97     GtkEntry *entry, gboolean focus)
98 {
99   const gchar *str;
100   const gchar *param_name;
101   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
102
103   str = gtk_entry_get_text (entry);
104   param_name = g_object_get_data (G_OBJECT (entry), "param_name");
105
106   if (EMP_STR_EMPTY (str))
107     {
108       const gchar *value = NULL;
109
110       empathy_account_settings_unset (priv->settings, param_name);
111
112       if (focus)
113         {
114           value = empathy_account_settings_get_string (priv->settings,
115               param_name);
116           DEBUG ("Unset %s and restore to %s", param_name, value);
117           gtk_entry_set_text (entry, value ? value : "");
118         }
119     }
120   else
121     {
122       DEBUG ("Setting %s to %s", param_name,
123           strstr (param_name, "password") ? "***" : str);
124       empathy_account_settings_set_string (priv->settings, param_name, str);
125     }
126
127   account_widget_handle_apply_sensitivity (self);
128 }
129
130 static gboolean
131 account_widget_entry_focus_cb (GtkWidget *widget,
132     GdkEventFocus *event,
133     EmpathyAccountWidget *self)
134 {
135   account_widget_entry_changed_common (self, GTK_ENTRY (widget), TRUE);
136
137   return FALSE;
138 }
139
140 static void
141 account_widget_entry_changed_cb (GtkEditable *entry,
142     EmpathyAccountWidget *self)
143 {
144   account_widget_entry_changed_common (self, GTK_ENTRY (entry), FALSE);
145 }
146
147 static void
148 account_widget_int_changed_cb (GtkWidget *widget,
149     EmpathyAccountWidget *self)
150 {
151   const gchar *param_name;
152   gint value;
153   const gchar *signature;
154   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
155
156   value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
157   param_name = g_object_get_data (G_OBJECT (widget), "param_name");
158
159   signature = empathy_account_settings_get_dbus_signature (priv->settings,
160     param_name);
161   g_return_if_fail (signature != NULL);
162
163   DEBUG ("Setting %s to %d", param_name, value);
164
165   switch ((int)*signature)
166     {
167     case DBUS_TYPE_INT16:
168     case DBUS_TYPE_INT32:
169       empathy_account_settings_set_int32 (priv->settings, param_name, value);
170       break;
171     case DBUS_TYPE_INT64:
172       empathy_account_settings_set_int64 (priv->settings, param_name, value);
173       break;
174     case DBUS_TYPE_UINT16:
175     case DBUS_TYPE_UINT32:
176       empathy_account_settings_set_uint32 (priv->settings, param_name, value);
177       break;
178     case DBUS_TYPE_UINT64:
179       empathy_account_settings_set_uint64 (priv->settings, param_name, value);
180       break;
181     default:
182       g_return_if_reached ();
183     }
184
185   account_widget_handle_apply_sensitivity (self);
186 }
187
188 static void
189 account_widget_checkbutton_toggled_cb (GtkWidget *widget,
190     EmpathyAccountWidget *self)
191 {
192   gboolean     value;
193   gboolean     default_value;
194   const gchar *param_name;
195   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
196
197   value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
198   param_name = g_object_get_data (G_OBJECT (widget), "param_name");
199
200   /* FIXME: This is ugly! checkbox don't have a "not-set" value so we
201    * always unset the param and set the value if different from the
202    * default value. */
203   empathy_account_settings_unset (priv->settings, param_name);
204   default_value = empathy_account_settings_get_boolean (priv->settings,
205       param_name);
206
207   if (default_value == value)
208     {
209       DEBUG ("Unset %s and restore to %d", param_name, default_value);
210     }
211   else
212     {
213       DEBUG ("Setting %s to %d", param_name, value);
214       empathy_account_settings_set_boolean (priv->settings, param_name, value);
215     }
216
217   account_widget_handle_apply_sensitivity (self);
218 }
219
220 static void
221 account_widget_forget_clicked_cb (GtkWidget *button,
222     EmpathyAccountWidget *self)
223 {
224   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
225   const gchar *param_name;
226
227   param_name = g_object_get_data (G_OBJECT (priv->entry_password),
228       "param_name");
229
230   DEBUG ("Unset %s", param_name);
231   empathy_account_settings_unset (priv->settings, param_name);
232   gtk_entry_set_text (GTK_ENTRY (priv->entry_password), "");
233
234   account_widget_handle_apply_sensitivity (self);
235 }
236
237 static void
238 account_widget_password_changed_cb (GtkWidget *entry,
239     EmpathyAccountWidget *self)
240 {
241   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
242   const gchar *str;
243
244   str = gtk_entry_get_text (GTK_ENTRY (entry));
245   gtk_widget_set_sensitive (priv->button_forget, !EMP_STR_EMPTY (str));
246 }
247
248 static void
249 account_widget_jabber_ssl_toggled_cb (GtkWidget *checkbutton_ssl,
250     EmpathyAccountWidget *self)
251 {
252   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
253   gboolean   value;
254   gint32       port = 0;
255
256   value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_ssl));
257   port = empathy_account_settings_get_uint32 (priv->settings, "port");
258
259   if (value)
260     {
261       if (port == 5222 || port == 0)
262         port = 5223;
263     }
264   else
265     {
266       if (port == 5223 || port == 0)
267         port = 5222;
268     }
269
270   gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->spinbutton_port), port);
271 }
272
273 static void
274 account_widget_setup_widget (EmpathyAccountWidget *self,
275     GtkWidget *widget,
276     const gchar *param_name)
277 {
278   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
279
280   g_object_set_data_full (G_OBJECT (widget), "param_name",
281       g_strdup (param_name), g_free);
282
283   if (GTK_IS_SPIN_BUTTON (widget))
284     {
285       gint value = 0;
286       const gchar *signature;
287
288       signature = empathy_account_settings_get_dbus_signature (priv->settings,
289           param_name);
290       g_return_if_fail (signature != NULL);
291
292       switch ((int)*signature)
293         {
294           case DBUS_TYPE_INT16:
295           case DBUS_TYPE_INT32:
296             value = empathy_account_settings_get_int32 (priv->settings,
297               param_name);
298             break;
299           case DBUS_TYPE_INT64:
300             value = empathy_account_settings_get_int64 (priv->settings,
301               param_name);
302             break;
303           case DBUS_TYPE_UINT16:
304           case DBUS_TYPE_UINT32:
305             value = empathy_account_settings_get_uint32 (priv->settings,
306               param_name);
307             break;
308           case DBUS_TYPE_UINT64:
309             value = empathy_account_settings_get_uint64 (priv->settings,
310                 param_name);
311             break;
312           default:
313             g_return_if_reached ();
314         }
315
316       gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
317
318       g_signal_connect (widget, "value-changed",
319           G_CALLBACK (account_widget_int_changed_cb),
320           self);
321     }
322   else if (GTK_IS_ENTRY (widget))
323     {
324       const gchar *str = NULL;
325
326       str = empathy_account_settings_get_string (priv->settings, param_name);
327       gtk_entry_set_text (GTK_ENTRY (widget), str ? str : "");
328
329       if (strstr (param_name, "password"))
330         {
331           gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE);
332         }
333
334       g_signal_connect (widget, "focus-out-event",
335           G_CALLBACK (account_widget_entry_focus_cb),
336           self);
337       g_signal_connect (widget, "changed",
338           G_CALLBACK (account_widget_entry_changed_cb), self);
339     }
340   else if (GTK_IS_TOGGLE_BUTTON (widget))
341     {
342       gboolean value = FALSE;
343
344       value = empathy_account_settings_get_boolean (priv->settings,
345           param_name);
346       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
347
348       g_signal_connect (widget, "toggled",
349           G_CALLBACK (account_widget_checkbutton_toggled_cb),
350           self);
351     }
352   else
353     {
354       DEBUG ("Unknown type of widget for param %s", param_name);
355     }
356 }
357
358 static gchar *
359 account_widget_generic_format_param_name (const gchar *param_name)
360 {
361   gchar *str;
362   gchar *p;
363
364   str = g_strdup (param_name);
365
366   if (str && g_ascii_isalpha (str[0]))
367     str[0] = g_ascii_toupper (str[0]);
368
369   while ((p = strchr (str, '-')) != NULL)
370     {
371       if (p[1] != '\0' && g_ascii_isalpha (p[1]))
372         {
373           p[0] = ' ';
374           p[1] = g_ascii_toupper (p[1]);
375         }
376
377       p++;
378     }
379
380   return str;
381 }
382
383 static void
384 accounts_widget_generic_setup (EmpathyAccountWidget *self,
385     GtkWidget *table_common_settings,
386     GtkWidget *table_advanced_settings)
387 {
388   TpConnectionManagerParam *params, *param;
389   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
390
391   params = empathy_account_settings_get_tp_params (priv->settings);
392
393   for (param = params; param != NULL && param->name != NULL; param++)
394     {
395       GtkWidget       *table_settings;
396       guint            n_rows = 0;
397       GtkWidget       *widget = NULL;
398       gchar           *param_name_formatted;
399
400       if (param->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED)
401         table_settings = table_common_settings;
402       else if (priv->simple)
403         return;
404       else
405         table_settings = table_advanced_settings;
406
407       param_name_formatted = account_widget_generic_format_param_name
408         (param->name);
409       g_object_get (table_settings, "n-rows", &n_rows, NULL);
410       gtk_table_resize (GTK_TABLE (table_settings), ++n_rows, 2);
411
412       if (param->dbus_signature[0] == 's')
413         {
414           gchar *str;
415
416           str = g_strdup_printf (_("%s:"), param_name_formatted);
417           widget = gtk_label_new (str);
418           gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
419           g_free (str);
420
421           gtk_table_attach (GTK_TABLE (table_settings),
422               widget,
423               0, 1,
424               n_rows - 1, n_rows,
425               GTK_FILL, 0,
426               0, 0);
427           gtk_widget_show (widget);
428
429           widget = gtk_entry_new ();
430           if (strcmp (param->name, "account") == 0)
431             {
432               g_signal_connect (widget, "realize",
433                   G_CALLBACK (gtk_widget_grab_focus),
434                   NULL);
435             }
436           gtk_table_attach (GTK_TABLE (table_settings),
437               widget,
438               1, 2,
439               n_rows - 1, n_rows,
440               GTK_FILL | GTK_EXPAND, 0,
441               0, 0);
442           gtk_widget_show (widget);
443         }
444       /* int types: ynqiuxt. double type is 'd' */
445       else if (param->dbus_signature[0] == 'y' ||
446           param->dbus_signature[0] == 'n' ||
447           param->dbus_signature[0] == 'q' ||
448           param->dbus_signature[0] == 'i' ||
449           param->dbus_signature[0] == 'u' ||
450           param->dbus_signature[0] == 'x' ||
451           param->dbus_signature[0] == 't' ||
452           param->dbus_signature[0] == 'd')
453         {
454           gchar   *str = NULL;
455           gdouble  minint = 0;
456           gdouble  maxint = 0;
457           gdouble  step = 1;
458
459           switch (param->dbus_signature[0])
460             {
461             case 'y': minint = G_MININT8;  maxint = G_MAXINT8;   break;
462             case 'n': minint = G_MININT16; maxint = G_MAXINT16;  break;
463             case 'q': minint = 0;          maxint = G_MAXUINT16; break;
464             case 'i': minint = G_MININT32; maxint = G_MAXINT32;  break;
465             case 'u': minint = 0;          maxint = G_MAXUINT32; break;
466             case 'x': minint = G_MININT64; maxint = G_MAXINT64;  break;
467             case 't': minint = 0;          maxint = G_MAXUINT64; break;
468             case 'd': minint = G_MININT32; maxint = G_MAXINT32;
469               step = 0.1; break;
470             }
471
472           str = g_strdup_printf (_("%s:"), param_name_formatted);
473           widget = gtk_label_new (str);
474           gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
475           g_free (str);
476
477           gtk_table_attach (GTK_TABLE (table_settings),
478               widget,
479               0, 1,
480               n_rows - 1, n_rows,
481               GTK_FILL, 0,
482               0, 0);
483           gtk_widget_show (widget);
484
485           widget = gtk_spin_button_new_with_range (minint, maxint, step);
486           gtk_table_attach (GTK_TABLE (table_settings),
487               widget,
488               1, 2,
489               n_rows - 1, n_rows,
490               GTK_FILL | GTK_EXPAND, 0,
491               0, 0);
492           gtk_widget_show (widget);
493         }
494       else if (param->dbus_signature[0] == 'b')
495         {
496           widget = gtk_check_button_new_with_label (param_name_formatted);
497           gtk_table_attach (GTK_TABLE (table_settings),
498               widget,
499               0, 2,
500               n_rows - 1, n_rows,
501               GTK_FILL | GTK_EXPAND, 0,
502               0, 0);
503           gtk_widget_show (widget);
504         }
505       else
506         {
507           DEBUG ("Unknown signature for param %s: %s",
508               param_name_formatted, param->dbus_signature);
509         }
510
511       if (widget)
512         account_widget_setup_widget (self, widget, param->name);
513
514       g_free (param_name_formatted);
515     }
516 }
517
518 static void
519 account_widget_handle_params_valist (EmpathyAccountWidget *self,
520     const gchar *first_widget,
521     va_list args)
522 {
523   GObject *object;
524   const gchar *name;
525
526   for (name = first_widget; name; name = va_arg (args, const gchar *))
527     {
528       const gchar *param_name;
529
530       param_name = va_arg (args, const gchar *);
531       object = gtk_builder_get_object (self->ui_details->gui, name);
532
533       if (!object)
534         {
535           g_warning ("Builder is missing object '%s'.", name);
536           continue;
537         }
538
539       account_widget_setup_widget (self, GTK_WIDGET (object), param_name);
540     }
541 }
542
543 static void
544 account_widget_apply_clicked_cb (GtkWidget *button,
545     EmpathyAccountWidget *self)
546 {
547   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
548
549   empathy_account_settings_apply_async (priv->settings, NULL, NULL);
550 }
551
552 static void
553 account_widget_setup_generic (EmpathyAccountWidget *self)
554 {
555   GtkWidget *table_common_settings;
556   GtkWidget *table_advanced_settings;
557
558   table_common_settings = GTK_WIDGET (gtk_builder_get_object
559       (self->ui_details->gui, "table_common_settings"));
560   table_advanced_settings = GTK_WIDGET (gtk_builder_get_object
561       (self->ui_details->gui, "table_advanced_settings"));
562
563   accounts_widget_generic_setup (self, table_common_settings,
564       table_advanced_settings);
565
566   g_object_unref (self->ui_details->gui);
567 }
568
569 static void
570 account_widget_settings_ready_cb (EmpathyAccountSettings *settings,
571     GParamSpec *pspec,
572     gpointer user_data)
573 {
574   EmpathyAccountWidget *self = user_data;
575   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
576
577   if (empathy_account_settings_is_ready (priv->settings))
578     account_widget_setup_generic (self);
579 }
580
581 static void
582 account_widget_build_generic (EmpathyAccountWidget *self,
583     const char *filename)
584 {
585   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
586   GtkWidget *expander_advanced;
587
588   self->ui_details->gui = empathy_builder_get_file (filename,
589       "vbox_generic_settings", &self->ui_details->widget,
590       "expander_advanced_settings", &expander_advanced,
591       NULL);
592
593   if (priv->simple)
594     gtk_widget_hide (expander_advanced);
595
596   g_object_ref (self->ui_details->gui);
597
598   if (empathy_account_settings_is_ready (priv->settings))
599     account_widget_setup_generic (self);
600   else
601     g_signal_connect (priv->settings, "notify::ready",
602         G_CALLBACK (account_widget_settings_ready_cb), self);
603 }
604
605 static void
606 account_widget_build_salut (EmpathyAccountWidget *self,
607     const char *filename)
608 {
609   self->ui_details->gui = empathy_builder_get_file (filename,
610       "vbox_salut_settings", &self->ui_details->widget,
611       NULL);
612
613   empathy_account_widget_handle_params (self,
614       "entry_published", "published-name",
615       "entry_nickname", "nickname",
616       "entry_first_name", "first-name",
617       "entry_last_name", "last-name",
618       "entry_email", "email",
619       "entry_jid", "jid",
620       NULL);
621
622   self->ui_details->default_focus = g_strdup ("entry_nickname");
623 }
624
625 static void
626 account_widget_build_msn (EmpathyAccountWidget *self,
627     const char *filename)
628 {
629   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
630
631   if (priv->simple)
632     {
633       self->ui_details->gui = empathy_builder_get_file (filename,
634           "vbox_msn_simple", &self->ui_details->widget,
635           NULL);
636
637       empathy_account_widget_handle_params (self,
638           "entry_id_simple", "account",
639           "entry_password_simple", "password",
640           NULL);
641
642       self->ui_details->default_focus = g_strdup ("entry_id_simple");
643     }
644   else
645     {
646       self->ui_details->gui = empathy_builder_get_file (filename,
647           "vbox_msn_settings", &self->ui_details->widget,
648           NULL);
649
650       empathy_account_widget_handle_params (self,
651           "entry_id", "account",
652           "entry_password", "password",
653           "entry_server", "server",
654           "spinbutton_port", "port",
655           NULL);
656
657       self->ui_details->default_focus = g_strdup ("entry_id");
658       self->ui_details->add_forget = TRUE;
659     }
660 }
661
662 static void
663 account_widget_build_jabber (EmpathyAccountWidget *self,
664     const char *filename)
665 {
666   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
667   GtkWidget *spinbutton_port;
668   GtkWidget *checkbutton_ssl;
669
670   if (priv->simple)
671     {
672       self->ui_details->gui = empathy_builder_get_file (filename,
673           "vbox_jabber_simple", &self->ui_details->widget,
674           NULL);
675       
676       empathy_account_widget_handle_params (self,
677           "entry_id_simple", "account",
678           "entry_password_simple", "password",
679           NULL);
680
681       self->ui_details->default_focus = g_strdup ("entry_id_simple");
682     }
683   else
684     {
685       self->ui_details->gui = empathy_builder_get_file (filename,
686           "vbox_jabber_settings", &self->ui_details->widget,
687           "spinbutton_port", &spinbutton_port,
688           "checkbutton_ssl", &checkbutton_ssl,
689           NULL);
690
691       empathy_account_widget_handle_params (self,
692           "entry_id", "account",
693           "entry_password", "password",
694           "entry_resource", "resource",
695           "entry_server", "server",
696           "spinbutton_port", "port",
697           "spinbutton_priority", "priority",
698           "checkbutton_ssl", "old-ssl",
699           "checkbutton_ignore_ssl_errors", "ignore-ssl-errors",
700           "checkbutton_encryption", "require-encryption",
701           NULL);
702
703       self->ui_details->default_focus = g_strdup ("entry_id");
704       self->ui_details->add_forget = TRUE;
705       priv->spinbutton_port = spinbutton_port;
706
707       g_signal_connect (checkbutton_ssl, "toggled",
708           G_CALLBACK (account_widget_jabber_ssl_toggled_cb),
709           self);
710     }
711 }
712
713 static void
714 account_widget_build_icq (EmpathyAccountWidget *self,
715     const char *filename)
716 {
717   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
718   GtkWidget *spinbutton_port;
719
720   if (priv->simple)
721     {
722       self->ui_details->gui = empathy_builder_get_file (filename,
723           "vbox_icq_simple", &self->ui_details->widget,
724           NULL);
725
726       empathy_account_widget_handle_params (self,
727           "entry_uin_simple", "account",
728           "entry_password_simple", "password",
729           NULL);
730
731       self->ui_details->default_focus = g_strdup ("entry_uin_simple");
732     }
733   else
734     {
735       self->ui_details->gui = empathy_builder_get_file (filename,
736           "vbox_icq_settings", &self->ui_details->widget,
737           "spinbutton_port", &spinbutton_port,
738           NULL);
739
740       empathy_account_widget_handle_params (self,
741           "entry_uin", "account",
742           "entry_password", "password",
743           "entry_server", "server",
744           "spinbutton_port", "port",
745           "entry_charset", "charset",
746           NULL);
747
748       self->ui_details->default_focus = g_strdup ("entry_uin");
749       self->ui_details->add_forget = TRUE;
750     }
751 }
752
753 static void
754 account_widget_build_aim (EmpathyAccountWidget *self,
755     const char *filename)
756 {
757   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
758   GtkWidget *spinbutton_port;
759
760   if (priv->simple)
761     {
762       self->ui_details->gui = empathy_builder_get_file (filename,
763           "vbox_aim_simple", &self->ui_details->widget,
764           NULL);
765
766       empathy_account_widget_handle_params (self,
767           "entry_screenname_simple", "account",
768           "entry_password_simple", "password",
769           NULL);
770
771       self->ui_details->default_focus = g_strdup ("entry_screenname_simple");
772     }
773   else
774     {
775       self->ui_details->gui = empathy_builder_get_file (filename,
776           "vbox_aim_settings", &self->ui_details->widget,
777           "spinbutton_port", &spinbutton_port,
778           NULL);
779
780       empathy_account_widget_handle_params (self,
781           "entry_screenname", "account",
782           "entry_password", "password",
783           "entry_server", "server",
784           "spinbutton_port", "port",
785           NULL);
786
787       self->ui_details->default_focus = g_strdup ("entry_screenname");
788       self->ui_details->add_forget = TRUE;
789     }
790 }
791
792 static void
793 account_widget_build_yahoo (EmpathyAccountWidget *self,
794     const char *filename)
795 {
796   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
797   
798   if (priv->simple)
799     {
800       self->ui_details->gui = empathy_builder_get_file (filename,
801           "vbox_yahoo_simple", &self->ui_details->widget,
802           NULL);
803
804       empathy_account_widget_handle_params (self,
805           "entry_id_simple", "account",
806           "entry_password_simple", "password",
807           NULL);
808
809       self->ui_details->default_focus = g_strdup ("entry_id_simple");
810     }
811   else
812     {
813       self->ui_details->gui = empathy_builder_get_file (filename,
814           "vbox_yahoo_settings", &self->ui_details->widget,
815           NULL);
816
817       empathy_account_widget_handle_params (self,
818           "entry_id", "account",
819           "entry_password", "password",
820           "entry_server", "server",
821           "entry_locale", "room-list-locale",
822           "entry_charset", "charset",
823           "spinbutton_port", "port",
824           "checkbutton_yahoojp", "yahoojp",
825           "checkbutton_ignore_invites", "ignore-invites",
826           NULL);
827
828       self->ui_details->default_focus = g_strdup ("entry_id");
829       self->ui_details->add_forget = TRUE;
830     }
831 }
832
833 static void
834 account_widget_build_groupwise (EmpathyAccountWidget *self,
835     const char *filename)
836 {
837   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
838
839   if (priv->simple)
840     {
841       self->ui_details->gui = empathy_builder_get_file (filename,
842           "vbox_groupwise_simple", &self->ui_details->widget,
843           NULL);
844
845       empathy_account_widget_handle_params (self,
846           "entry_id_simple", "account",
847           "entry_password_simple", "password",
848           NULL);
849
850       self->ui_details->default_focus = g_strdup ("entry_id_simple");
851     }
852   else
853     {
854       self->ui_details->gui = empathy_builder_get_file (filename,
855           "vbox_groupwise_settings", &self->ui_details->widget,
856           NULL);
857
858       empathy_account_widget_handle_params (self,
859           "entry_id", "account",
860           "entry_password", "password",
861           "entry_server", "server",
862           "spinbutton_port", "port",
863           NULL);
864
865       self->ui_details->default_focus = g_strdup ("entry_id");
866       self->ui_details->add_forget = TRUE;
867     }
868 }
869
870 static void
871 account_widget_destroy_cb (GtkWidget *widget,
872     EmpathyAccountWidget *self)
873 {
874   g_object_unref (self);
875 }
876
877 static void
878 do_set_property (GObject *object,
879     guint prop_id,
880     const GValue *value,
881     GParamSpec *pspec)
882 {
883   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
884
885   switch (prop_id)
886     {
887     case PROP_PROTOCOL:
888       priv->protocol = g_value_dup_string (value);
889       break;
890     case PROP_SETTINGS:
891       priv->settings = g_value_dup_object (value);
892       break;
893     case PROP_SIMPLE:
894       priv->simple = g_value_get_boolean (value);
895       break;
896     default:
897       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
898     }
899 }
900
901 static void
902 do_get_property (GObject *object,
903     guint prop_id,
904     GValue *value,
905     GParamSpec *pspec)
906 {
907   EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
908
909   switch (prop_id)
910     {
911     case PROP_PROTOCOL:
912       g_value_set_string (value, priv->protocol);
913       break;
914     case PROP_SETTINGS:
915       g_value_set_object (value, priv->settings);
916       break;
917     case PROP_SIMPLE:
918       g_value_set_boolean (value, priv->simple);
919       break;
920     default:
921       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
922     }
923 }
924
925 static void
926 do_constructed (GObject *obj)
927 {
928   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
929   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
930   char *uiname, *filename;
931
932   uiname = g_strconcat ("empathy-account-widget-", priv->protocol,
933       ".ui", NULL);
934   filename = empathy_file_lookup (uiname, "libempathy-gtk");
935
936   if (!tp_strdiff (priv->protocol, "local-xmpp"))
937     account_widget_build_salut (self, filename);
938   else if (!tp_strdiff (priv->protocol, "msn"))
939     account_widget_build_msn (self, filename);
940   else if (!tp_strdiff (priv->protocol, "jabber"))
941     account_widget_build_jabber (self, filename);
942   else if (!tp_strdiff (priv->protocol, "icq"))
943     account_widget_build_icq (self, filename);
944   else if (!tp_strdiff (priv->protocol, "aim"))
945     account_widget_build_aim (self, filename);
946   else if (!tp_strdiff (priv->protocol, "yahoo"))
947     account_widget_build_yahoo (self, filename);
948   else if (!tp_strdiff (priv->protocol, "groupwise"))
949     account_widget_build_groupwise (self, filename);
950   else if (!tp_strdiff (priv->protocol, "irc"))
951     empathy_account_widget_irc_build (self, filename);
952   else if (!tp_strdiff (priv->protocol, "sip"))
953     empathy_account_widget_sip_build (self, filename);
954   else
955     {
956       g_free (filename);
957
958       filename = empathy_file_lookup (
959           "empathy-account-widget-generic.ui", "libempathy-gtk");
960       account_widget_build_generic (self, filename);
961     }
962
963   g_free (uiname);
964   g_free (filename);
965
966   /* handle default focus */
967   if (self->ui_details->default_focus != NULL)
968     {
969       GObject *default_focus_entry;
970
971       default_focus_entry = gtk_builder_get_object
972         (self->ui_details->gui, self->ui_details->default_focus);
973       g_signal_connect (default_focus_entry, "realize",
974           G_CALLBACK (gtk_widget_grab_focus),
975           NULL);
976     }
977
978   /* handle forget button */
979   if (self->ui_details->add_forget)
980     {
981       const gchar *password = NULL;
982
983       priv->button_forget = GTK_WIDGET (gtk_builder_get_object
984           (self->ui_details->gui, "button_forget"));
985       priv->entry_password = GTK_WIDGET (gtk_builder_get_object
986           (self->ui_details->gui, "entry_password"));
987
988       password = empathy_account_settings_get_string (priv->settings,
989           "password");
990       gtk_widget_set_sensitive (priv->button_forget,
991           !EMP_STR_EMPTY (password));
992
993       g_signal_connect (priv->button_forget, "clicked",
994           G_CALLBACK (account_widget_forget_clicked_cb),
995           self);
996       g_signal_connect (priv->entry_password, "changed",
997           G_CALLBACK (account_widget_password_changed_cb),
998           self);
999     }
1000
1001   /* handle apply button */
1002   if (!priv->simple)
1003     {
1004       priv->apply_button = gtk_button_new_from_stock (GTK_STOCK_APPLY);
1005       gtk_box_pack_end (GTK_BOX (self->ui_details->widget), priv->apply_button,
1006           FALSE, FALSE, 3);
1007
1008       g_signal_connect (priv->apply_button, "clicked",
1009           G_CALLBACK (account_widget_apply_clicked_cb),
1010           self);
1011       account_widget_handle_apply_sensitivity (self);
1012       gtk_widget_show (priv->apply_button);
1013     }
1014
1015   /* hook up to widget destruction to unref ourselves */
1016   g_signal_connect (self->ui_details->widget, "destroy",
1017       G_CALLBACK (account_widget_destroy_cb), self);
1018
1019   empathy_builder_unref_and_keep_widget (self->ui_details->gui,
1020       self->ui_details->widget);
1021   self->ui_details->gui = NULL;
1022 }
1023
1024 static void
1025 do_dispose (GObject *obj)
1026 {
1027   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1028   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1029
1030   if (priv->dispose_run)
1031     return;
1032
1033   priv->dispose_run = TRUE;
1034
1035   if (priv->settings != NULL)
1036     {
1037       g_object_unref (priv->settings);
1038       priv->settings = NULL;
1039     }
1040
1041   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose != NULL)
1042     G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose (obj);
1043 }
1044
1045 static void
1046 do_finalize (GObject *obj)
1047 {
1048   EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
1049   EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1050
1051   g_free (self->ui_details->default_focus);
1052   g_slice_free (EmpathyAccountWidgetUIDetails, self->ui_details);
1053
1054   g_free (priv->protocol);
1055
1056   if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize != NULL)
1057     G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize (obj);
1058 }
1059
1060 static void
1061 empathy_account_widget_class_init (EmpathyAccountWidgetClass *klass)
1062 {
1063   GObjectClass *oclass = G_OBJECT_CLASS (klass);
1064   GParamSpec *param_spec;
1065
1066   oclass->get_property = do_get_property;
1067   oclass->set_property = do_set_property;
1068   oclass->constructed = do_constructed;
1069   oclass->dispose = do_dispose;
1070   oclass->finalize = do_finalize;
1071
1072   param_spec = g_param_spec_string ("protocol",
1073       "protocol", "The protocol of the account",
1074       NULL,
1075       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1076   g_object_class_install_property (oclass, PROP_PROTOCOL, param_spec);
1077
1078   param_spec = g_param_spec_object ("settings",
1079       "settings", "The settings of the account",
1080       EMPATHY_TYPE_ACCOUNT_SETTINGS,
1081       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1082   g_object_class_install_property (oclass, PROP_SETTINGS, param_spec);
1083
1084   param_spec = g_param_spec_boolean ("simple",
1085       "simple", "Whether the account widget is a simple or an advanced one",
1086       FALSE,
1087       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1088   g_object_class_install_property (oclass, PROP_SIMPLE, param_spec);
1089
1090   signals[HANDLE_APPLY] =
1091     g_signal_new ("handle-apply", G_TYPE_FROM_CLASS (klass),
1092         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
1093         g_cclosure_marshal_VOID__BOOLEAN,
1094         G_TYPE_NONE,
1095         1, G_TYPE_BOOLEAN);
1096
1097   g_type_class_add_private (klass, sizeof (EmpathyAccountWidgetPriv));
1098 }
1099
1100 static void
1101 empathy_account_widget_init (EmpathyAccountWidget *self)
1102 {
1103   EmpathyAccountWidgetPriv *priv =
1104     G_TYPE_INSTANCE_GET_PRIVATE ((self), EMPATHY_TYPE_ACCOUNT_WIDGET,
1105         EmpathyAccountWidgetPriv);
1106
1107   self->priv = priv;
1108   priv->dispose_run = FALSE;
1109
1110   self->ui_details = g_slice_new0 (EmpathyAccountWidgetUIDetails);
1111 }
1112
1113 /* public methods */
1114
1115 void
1116 empathy_account_widget_handle_params (EmpathyAccountWidget *self,
1117     const gchar *first_widget,
1118     ...)
1119 {
1120   va_list args;
1121
1122   va_start (args, first_widget);
1123   account_widget_handle_params_valist (self, first_widget, args);
1124   va_end (args);
1125 }
1126
1127 GtkWidget *
1128 empathy_account_widget_new_for_protocol (const char *protocol,
1129     EmpathyAccountSettings *settings)
1130 {
1131   EmpathyAccountWidget *self;
1132   EmpathyAccountWidgetPriv *priv;
1133
1134   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL);
1135   g_return_val_if_fail (settings != NULL, NULL);
1136
1137   self = g_object_new
1138     (EMPATHY_TYPE_ACCOUNT_WIDGET, "protocol", protocol,
1139         "settings", settings, NULL);
1140   priv = GET_PRIV (self);
1141
1142   return self->ui_details->widget;
1143 }
1144
1145 GtkWidget *
1146 empathy_account_widget_simple_new_for_protocol (const char *protocol,
1147     EmpathyAccountSettings *settings, EmpathyAccountWidget **object)
1148 {
1149   EmpathyAccountWidget *self;
1150
1151   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL);
1152   g_return_val_if_fail (protocol != NULL, NULL);
1153
1154   self = g_object_new
1155     (EMPATHY_TYPE_ACCOUNT_WIDGET, "protocol", protocol,
1156         "settings", settings, "simple", TRUE, NULL);
1157
1158   *object = self;
1159
1160   return self->ui_details->widget;
1161 }