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