LogWindow: better logic for the buttons sensitivity
[empathy-mirror.git] / libempathy-gtk / empathy-account-widget.c
blob0fe6a6bcc7412eb9c35515fecab6ebbd90c4e3c8
1 /*
2 * Copyright (C) 2006-2007 Imendio AB
3 * Copyright (C) 2007-2009 Collabora Ltd.
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.
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.
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
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>
26 #include <config.h>
28 #include <string.h>
30 #include <gtk/gtk.h>
31 #include <glib/gi18n-lib.h>
33 #include <gio/gdesktopappinfo.h>
35 #include <libempathy/empathy-utils.h>
37 #include <telepathy-glib/account.h>
38 #include <telepathy-glib/account-manager.h>
39 #include <telepathy-glib/connection-manager.h>
40 #include <telepathy-glib/util.h>
41 #include <dbus/dbus-protocol.h>
43 #include "empathy-account-widget.h"
44 #include "empathy-account-widget-private.h"
45 #include "empathy-account-widget-sip.h"
46 #include "empathy-account-widget-irc.h"
47 #include "empathy-ui-utils.h"
49 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
50 #include <libempathy/empathy-debug.h>
52 G_DEFINE_TYPE (EmpathyAccountWidget, empathy_account_widget, G_TYPE_OBJECT)
54 typedef enum
56 NO_SERVICE = 0,
57 GTALK_SERVICE,
58 FACEBOOK_SERVICE,
59 N_SERVICES
60 } Service;
62 typedef struct
64 const gchar *label_username_example;
65 gboolean show_advanced;
66 } ServiceInfo;
68 static ServiceInfo services_infos[N_SERVICES] = {
69 { "label_username_example", TRUE },
70 { "label_username_g_example", TRUE },
71 { "label_username_f_example", FALSE },
74 typedef struct {
75 EmpathyAccountSettings *settings;
77 GtkWidget *table_common_settings;
78 GtkWidget *apply_button;
79 GtkWidget *cancel_button;
80 GtkWidget *entry_password;
81 GtkWidget *spinbutton_port;
82 GtkWidget *radiobutton_reuse;
84 gboolean simple;
86 gboolean contains_pending_changes;
88 /* An EmpathyAccountWidget can be used to either create an account or
89 * modify it. When we are creating an account, this member is set to TRUE */
90 gboolean creating_account;
92 /* whether there are any other real accounts. Necessary so we know whether
93 * it's safe to dismiss this widget in some cases (eg, whether the Cancel
94 * button should be sensitive) */
95 gboolean other_accounts_exist;
97 /* if TRUE, the GTK+ destroy signal has been fired and so the widgets
98 * embedded in this account widget can't be used any more
99 * workaround because some async callbacks can be called after the
100 * widget has been destroyed */
101 gboolean destroyed;
103 TpAccountManager *account_manager;
105 GtkWidget *param_account_widget;
106 GtkWidget *param_password_widget;
108 gboolean automatic_change;
109 GtkWidget *remember_password_widget;
111 /* Used only for IRC accounts */
112 EmpathyIrcNetworkChooser *irc_network_chooser;
114 /* Used for 'special' XMPP account having a service associated ensuring that
115 * JIDs have a specific suffix; such as Facebook for example */
116 gchar *jid_suffix;
118 gboolean dispose_run;
119 } EmpathyAccountWidgetPriv;
121 enum {
122 PROP_PROTOCOL = 1,
123 PROP_SETTINGS,
124 PROP_SIMPLE,
125 PROP_CREATING_ACCOUNT,
126 PROP_OTHER_ACCOUNTS_EXIST,
129 enum {
130 HANDLE_APPLY,
131 ACCOUNT_CREATED,
132 CANCELLED,
133 LAST_SIGNAL
136 static void account_widget_apply_and_log_in (EmpathyAccountWidget *);
138 enum {
139 RESPONSE_LAUNCH
142 static guint signals[LAST_SIGNAL] = { 0 };
144 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountWidget)
145 #define CHANGED_TIMEOUT 300
147 #define DIGIT "0-9"
148 #define DIGITS "(["DIGIT"]+)"
149 #define ALPHA "a-zA-Z"
150 #define ALPHAS "(["ALPHA"]+)"
151 #define ALPHADIGIT ALPHA DIGIT
152 #define ALPHADIGITS "(["ALPHADIGIT"]+)"
153 #define ALPHADIGITDASH ALPHA DIGIT "-"
154 #define ALPHADIGITDASHS "(["ALPHADIGITDASH"]*)"
156 #define HOSTNUMBER "("DIGITS"\\."DIGITS"\\."DIGITS"\\."DIGITS")"
157 #define TOPLABEL ALPHAS"|(["ALPHA"]" ALPHADIGITDASHS "["ALPHADIGIT"])"
158 #define DOMAINLABEL ALPHADIGITS"|(["ALPHADIGIT"]" ALPHADIGITDASHS \
159 "["ALPHADIGIT"])"
160 #define HOSTNAME "((" DOMAINLABEL "\\.)+" TOPLABEL ")"
161 /* Based on http://www.ietf.org/rfc/rfc1738.txt (section 5) */
162 #define HOST "("HOSTNAME "|" HOSTNUMBER")"
163 /* Based on http://www.ietf.org/rfc/rfc0822.txt (appendix D) */
164 #define EMAIL_LOCALPART "([^\\(\\)<>@,;:\\\\\"\\[\\]\\s]+)"
166 /* UIN is digital according to the unofficial specification:
167 * http://iserverd.khstu.ru/docum_ext/icqv5.html#CTS
168 * 5 digits minimum according to http://en.wikipedia.org/wiki/ICQ#UIN
169 * According to an user, we can also provide an email address instead of the
170 * ICQ UIN. */
171 #define ICQ_USER_NAME "((["DIGIT"]{5,})|"EMAIL_LOCALPART"@"HOST")"
173 /* Based on http://www.ietf.org/rfc/rfc2812.txt (section 2.3.1) */
174 #define IRC_SPECIAL "_\\[\\]{}\\\\|`^"
175 #define IRC_USER_NAME "(["ALPHA IRC_SPECIAL"]["ALPHADIGITDASH IRC_SPECIAL"]*)"
176 /* Based on http://www.ietf.org/rfc/rfc4622.txt (section 2.2)
177 * We just exclude invalid characters to avoid ucschars and other redundant
178 * complexity */
179 #define JABBER_USER_NAME "([^@:'\"<>&\\s]+)"
180 /* ID is an email according to the unofficial specification:
181 * http://www.hypothetic.org/docs/msn/general/names.php */
182 #define MSN_USER_NAME EMAIL_LOCALPART
183 /* Based on the official help:
184 * http://help.yahoo.com/l/us/yahoo/edit/registration/edit-01.html */
185 #define YAHOO_USER_NAME "(["ALPHA"]["ALPHADIGIT"_\\.]{3,31})"
187 #define ACCOUNT_REGEX_ICQ "^"ICQ_USER_NAME"$"
188 #define ACCOUNT_REGEX_IRC "^"IRC_USER_NAME"$"
189 #define ACCOUNT_REGEX_JABBER "^"JABBER_USER_NAME"@"HOST"$"
190 #define ACCOUNT_REGEX_MSN "^"MSN_USER_NAME"@"HOST"$"
191 #define ACCOUNT_REGEX_YAHOO "^"YAHOO_USER_NAME"$"
193 static void
194 account_widget_set_control_buttons_sensitivity (EmpathyAccountWidget *self,
195 gboolean sensitive)
197 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
199 if (!priv->simple)
201 /* we hit this case because of the 'other-accounts-exist' property handler
202 * being called during init (before constructed()) */
203 if (priv->apply_button == NULL || priv->cancel_button == NULL)
204 return;
206 gtk_widget_set_sensitive (priv->apply_button, sensitive);
207 gtk_widget_set_sensitive (priv->cancel_button,
208 (sensitive || priv->creating_account) && priv->other_accounts_exist);
210 if (sensitive)
212 /* We can't grab default if the widget hasn't be packed in a
213 * window */
214 GtkWidget *window;
216 window = gtk_widget_get_toplevel (priv->apply_button);
217 if (window != NULL &&
218 gtk_widget_is_toplevel (window))
220 gtk_widget_set_can_default (priv->apply_button, TRUE);
221 gtk_widget_grab_default (priv->apply_button);
227 static void
228 account_widget_set_entry_highlighting (GtkEntry *entry,
229 gboolean highlight)
231 g_return_if_fail (GTK_IS_ENTRY (entry));
233 if (highlight)
235 GtkStyleContext *style;
236 GdkRGBA color;
238 style = gtk_widget_get_style_context (GTK_WIDGET (entry));
239 gtk_style_context_get_background_color (style, GTK_STATE_FLAG_SELECTED,
240 &color);
242 /* Here we take the current theme colour and add it to
243 * the colour for white and average the two. This
244 * gives a colour which is inline with the theme but
245 * slightly whiter.
247 empathy_make_color_whiter (&color);
249 gtk_widget_override_background_color (GTK_WIDGET (entry), 0, &color);
251 else
253 gtk_widget_override_background_color (GTK_WIDGET (entry), 0, NULL);
257 static void
258 account_widget_handle_control_buttons_sensitivity (EmpathyAccountWidget *self)
260 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
261 gboolean is_valid;
263 is_valid = empathy_account_settings_is_valid (priv->settings);
265 if (!priv->simple)
266 account_widget_set_control_buttons_sensitivity (self, is_valid);
268 g_signal_emit (self, signals[HANDLE_APPLY], 0, is_valid);
271 static void
272 account_widget_entry_changed_common (EmpathyAccountWidget *self,
273 GtkEntry *entry, gboolean focus)
275 const gchar *str;
276 const gchar *param_name;
277 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
278 gboolean prev_status;
279 gboolean curr_status;
281 str = gtk_entry_get_text (entry);
282 param_name = g_object_get_data (G_OBJECT (entry), "param_name");
283 prev_status = empathy_account_settings_parameter_is_valid (priv->settings,
284 param_name);
286 if (EMP_STR_EMPTY (str))
288 const gchar *value = NULL;
290 empathy_account_settings_unset (priv->settings, param_name);
292 if (focus)
294 value = empathy_account_settings_get_string (priv->settings,
295 param_name);
296 DEBUG ("Unset %s and restore to %s", param_name, value);
297 gtk_entry_set_text (entry, value ? value : "");
300 else
302 DEBUG ("Setting %s to %s", param_name,
303 tp_strdiff (param_name, "password") ? str : "***");
304 empathy_account_settings_set_string (priv->settings, param_name, str);
307 curr_status = empathy_account_settings_parameter_is_valid (priv->settings,
308 param_name);
309 if (curr_status != prev_status)
310 account_widget_set_entry_highlighting (entry, !curr_status);
313 static void
314 account_widget_entry_changed_cb (GtkEditable *entry,
315 EmpathyAccountWidget *self)
317 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
319 if (priv->automatic_change)
320 return;
322 account_widget_entry_changed_common (self, GTK_ENTRY (entry), FALSE);
323 empathy_account_widget_changed (self);
326 static void
327 account_widget_entry_map_cb (GtkEntry *entry,
328 EmpathyAccountWidget *self)
330 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
331 const gchar *param_name;
332 gboolean is_valid;
334 /* need to initialize input highlighting */
335 param_name = g_object_get_data (G_OBJECT (entry), "param_name");
336 is_valid = empathy_account_settings_parameter_is_valid (priv->settings,
337 param_name);
338 account_widget_set_entry_highlighting (entry, !is_valid);
341 static void
342 account_widget_int_changed_cb (GtkWidget *widget,
343 EmpathyAccountWidget *self)
345 const gchar *param_name;
346 gint value;
347 const gchar *signature;
348 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
350 value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
351 param_name = g_object_get_data (G_OBJECT (widget), "param_name");
353 signature = empathy_account_settings_get_dbus_signature (priv->settings,
354 param_name);
355 g_return_if_fail (signature != NULL);
357 DEBUG ("Setting %s to %d", param_name, value);
359 switch ((int)*signature)
361 case DBUS_TYPE_INT16:
362 case DBUS_TYPE_INT32:
363 empathy_account_settings_set_int32 (priv->settings, param_name, value);
364 break;
365 case DBUS_TYPE_INT64:
366 empathy_account_settings_set_int64 (priv->settings, param_name, value);
367 break;
368 case DBUS_TYPE_UINT16:
369 case DBUS_TYPE_UINT32:
370 empathy_account_settings_set_uint32 (priv->settings, param_name, value);
371 break;
372 case DBUS_TYPE_UINT64:
373 empathy_account_settings_set_uint64 (priv->settings, param_name, value);
374 break;
375 default:
376 g_return_if_reached ();
379 empathy_account_widget_changed (self);
382 static void
383 account_widget_checkbutton_toggled_cb (GtkWidget *widget,
384 EmpathyAccountWidget *self)
386 gboolean value;
387 gboolean default_value;
388 const gchar *param_name;
389 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
391 value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
392 param_name = g_object_get_data (G_OBJECT (widget), "param_name");
394 /* FIXME: This is ugly! checkbox don't have a "not-set" value so we
395 * always unset the param and set the value if different from the
396 * default value. */
397 empathy_account_settings_unset (priv->settings, param_name);
398 default_value = empathy_account_settings_get_boolean (priv->settings,
399 param_name);
401 if (default_value == value)
403 DEBUG ("Unset %s and restore to %d", param_name, default_value);
405 else
407 DEBUG ("Setting %s to %d", param_name, value);
408 empathy_account_settings_set_boolean (priv->settings, param_name, value);
411 empathy_account_widget_changed (self);
414 static void
415 account_widget_jabber_ssl_toggled_cb (GtkWidget *checkbutton_ssl,
416 EmpathyAccountWidget *self)
418 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
419 gboolean value;
420 gint32 port = 0;
422 value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_ssl));
423 port = empathy_account_settings_get_uint32 (priv->settings, "port");
425 if (value)
427 if (port == 5222 || port == 0)
428 port = 5223;
430 else
432 if (port == 5223 || port == 0)
433 port = 5222;
436 gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->spinbutton_port), port);
438 priv->contains_pending_changes = TRUE;
441 static void
442 account_widget_combobox_changed_cb (GtkWidget *widget,
443 EmpathyAccountWidget *self)
445 GtkTreeIter iter;
446 GtkTreeModel *model;
447 const gchar *value;
448 const GValue *v;
449 const gchar *default_value = NULL;
450 const gchar *param_name;
451 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
453 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter))
454 return;
456 model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
457 /* the param value is stored in the first column */
458 gtk_tree_model_get (model, &iter, 0, &value, -1);
460 param_name = g_object_get_data (G_OBJECT (widget), "param_name");
462 v = empathy_account_settings_get_default (priv->settings, param_name);
463 if (v != NULL)
464 default_value = g_value_get_string (v);
466 if (!tp_strdiff (value, default_value))
468 DEBUG ("Unset %s and restore to %s", param_name, default_value);
469 empathy_account_settings_unset (priv->settings, param_name);
471 else
473 DEBUG ("Setting %s to %s", param_name, value);
474 empathy_account_settings_set_string (priv->settings, param_name, value);
477 empathy_account_widget_changed (self);
480 static void
481 clear_icon_released_cb (GtkEntry *entry,
482 GtkEntryIconPosition icon_pos,
483 GdkEvent *event,
484 EmpathyAccountWidget *self)
486 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
487 const gchar *param_name;
489 param_name = g_object_get_data (G_OBJECT (entry), "param_name");
491 DEBUG ("Unset %s", param_name);
492 empathy_account_settings_unset (priv->settings, param_name);
493 gtk_entry_set_text (entry, "");
495 empathy_account_widget_changed (self);
498 static void
499 password_entry_changed_cb (GtkEditable *entry,
500 EmpathyAccountWidget *self)
502 const gchar *str;
504 str = gtk_entry_get_text (GTK_ENTRY (entry));
506 gtk_entry_set_icon_sensitive (GTK_ENTRY (entry),
507 GTK_ENTRY_ICON_SECONDARY, !EMP_STR_EMPTY (str));
510 static void
511 password_entry_activated_cb (GtkEntry *entry,
512 EmpathyAccountWidget *self)
514 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
516 if (gtk_widget_get_sensitive (priv->apply_button))
517 account_widget_apply_and_log_in (self);
520 static void
521 account_entry_activated_cb (GtkEntry *entry,
522 EmpathyAccountWidget *self)
524 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
526 if (gtk_widget_get_sensitive (priv->apply_button))
527 account_widget_apply_and_log_in (self);
530 void
531 empathy_account_widget_setup_widget (EmpathyAccountWidget *self,
532 GtkWidget *widget,
533 const gchar *param_name)
535 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
537 g_object_set_data_full (G_OBJECT (widget), "param_name",
538 g_strdup (param_name), g_free);
540 if (GTK_IS_SPIN_BUTTON (widget))
542 gint value = 0;
543 const gchar *signature;
545 signature = empathy_account_settings_get_dbus_signature (priv->settings,
546 param_name);
547 g_return_if_fail (signature != NULL);
549 switch ((int)*signature)
551 case DBUS_TYPE_INT16:
552 case DBUS_TYPE_INT32:
553 value = empathy_account_settings_get_int32 (priv->settings,
554 param_name);
555 break;
556 case DBUS_TYPE_INT64:
557 value = empathy_account_settings_get_int64 (priv->settings,
558 param_name);
559 break;
560 case DBUS_TYPE_UINT16:
561 case DBUS_TYPE_UINT32:
562 value = empathy_account_settings_get_uint32 (priv->settings,
563 param_name);
564 break;
565 case DBUS_TYPE_UINT64:
566 value = empathy_account_settings_get_uint64 (priv->settings,
567 param_name);
568 break;
569 default:
570 g_return_if_reached ();
573 gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
575 g_signal_connect (widget, "value-changed",
576 G_CALLBACK (account_widget_int_changed_cb),
577 self);
579 else if (GTK_IS_ENTRY (widget))
581 const gchar *str = NULL;
583 str = empathy_account_settings_get_string (priv->settings, param_name);
584 gtk_entry_set_text (GTK_ENTRY (widget), str ? str : "");
586 if (!tp_strdiff (param_name, "account"))
587 priv->param_account_widget = widget;
588 else if (!tp_strdiff (param_name, "password"))
589 priv->param_password_widget = widget;
591 if (strstr (param_name, "password"))
593 gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE);
595 /* Add 'clear' icon */
596 gtk_entry_set_icon_from_stock (GTK_ENTRY (widget),
597 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
599 gtk_entry_set_icon_sensitive (GTK_ENTRY (widget),
600 GTK_ENTRY_ICON_SECONDARY, !EMP_STR_EMPTY (str));
602 g_signal_connect (widget, "icon-release",
603 G_CALLBACK (clear_icon_released_cb), self);
604 g_signal_connect (widget, "changed",
605 G_CALLBACK (password_entry_changed_cb), self);
606 g_signal_connect (widget, "activate",
607 G_CALLBACK (password_entry_activated_cb), self);
609 else if (strstr (param_name, "account"))
610 g_signal_connect (widget, "activate",
611 G_CALLBACK (account_entry_activated_cb), self);
614 g_signal_connect (widget, "changed",
615 G_CALLBACK (account_widget_entry_changed_cb), self);
616 g_signal_connect (widget, "map",
617 G_CALLBACK (account_widget_entry_map_cb), self);
619 else if (GTK_IS_TOGGLE_BUTTON (widget))
621 gboolean value = FALSE;
623 value = empathy_account_settings_get_boolean (priv->settings,
624 param_name);
625 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
627 g_signal_connect (widget, "toggled",
628 G_CALLBACK (account_widget_checkbutton_toggled_cb),
629 self);
631 else if (GTK_IS_COMBO_BOX (widget))
633 /* The combo box's model has to contain the param value in its first
634 * column (as a string) */
635 const gchar *str;
636 GtkTreeModel *model;
637 GtkTreeIter iter;
638 gboolean valid;
640 str = empathy_account_settings_get_string (priv->settings, param_name);
641 model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
643 valid = gtk_tree_model_get_iter_first (model, &iter);
644 while (valid)
646 gchar *name;
648 gtk_tree_model_get (model, &iter, 0, &name, -1);
649 if (!tp_strdiff (name, str))
651 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
652 valid = FALSE;
654 else
656 valid = gtk_tree_model_iter_next (model, &iter);
659 g_free (name);
662 g_signal_connect (widget, "changed",
663 G_CALLBACK (account_widget_combobox_changed_cb),
664 self);
666 else
668 DEBUG ("Unknown type of widget for param %s", param_name);
671 gtk_widget_set_sensitive (widget,
672 empathy_account_settings_param_is_supported (priv->settings, param_name));
675 static GHashTable *
676 build_translated_params (void)
678 GHashTable *hash;
680 hash = g_hash_table_new (g_str_hash, g_str_equal);
681 g_hash_table_insert (hash, "account", _("Account"));
682 g_hash_table_insert (hash, "password", _("Password"));
683 g_hash_table_insert (hash, "server", _("Server"));
684 g_hash_table_insert (hash, "port", _("Port"));
686 return hash;
689 static gchar *
690 account_widget_generic_format_param_name (const gchar *param_name)
692 gchar *str;
693 gchar *p;
694 static GHashTable *translated_params = NULL;
696 if (G_UNLIKELY (translated_params == NULL))
697 translated_params = build_translated_params ();
699 /* Translate most common parameters */
700 str = g_hash_table_lookup (translated_params, param_name);
701 if (str != NULL)
702 return g_strdup (str);
704 str = g_strdup (param_name);
706 if (str && g_ascii_isalpha (str[0]))
707 str[0] = g_ascii_toupper (str[0]);
709 while ((p = strchr (str, '-')) != NULL)
711 if (p[1] != '\0' && g_ascii_isalpha (p[1]))
713 p[0] = ' ';
714 p[1] = g_ascii_toupper (p[1]);
717 p++;
720 return str;
723 static void
724 accounts_widget_generic_setup (EmpathyAccountWidget *self,
725 GtkWidget *table_common_settings,
726 GtkWidget *table_advanced_settings)
728 TpConnectionManagerParam *params, *param;
729 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
731 params = empathy_account_settings_get_tp_params (priv->settings);
733 for (param = params; param != NULL && param->name != NULL; param++)
735 GtkWidget *table_settings;
736 guint n_rows = 0;
737 GtkWidget *widget = NULL;
738 gchar *param_name_formatted;
740 if (param->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED)
741 table_settings = table_common_settings;
742 else if (priv->simple)
743 return;
744 else
745 table_settings = table_advanced_settings;
747 param_name_formatted = account_widget_generic_format_param_name
748 (param->name);
749 g_object_get (table_settings, "n-rows", &n_rows, NULL);
750 gtk_table_resize (GTK_TABLE (table_settings), ++n_rows, 2);
752 if (param->dbus_signature[0] == 's')
754 gchar *str;
756 str = g_strdup_printf (_("%s:"), param_name_formatted);
757 widget = gtk_label_new (str);
758 gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
759 g_free (str);
761 gtk_table_attach (GTK_TABLE (table_settings),
762 widget,
763 0, 1,
764 n_rows - 1, n_rows,
765 GTK_FILL, 0,
766 0, 0);
767 gtk_widget_show (widget);
769 widget = gtk_entry_new ();
770 if (strcmp (param->name, "account") == 0)
772 g_signal_connect (widget, "realize",
773 G_CALLBACK (gtk_widget_grab_focus),
774 NULL);
776 gtk_table_attach (GTK_TABLE (table_settings),
777 widget,
778 1, 2,
779 n_rows - 1, n_rows,
780 GTK_FILL | GTK_EXPAND, 0,
781 0, 0);
782 gtk_widget_show (widget);
784 /* int types: ynqiuxt. double type is 'd' */
785 else if (param->dbus_signature[0] == 'y' ||
786 param->dbus_signature[0] == 'n' ||
787 param->dbus_signature[0] == 'q' ||
788 param->dbus_signature[0] == 'i' ||
789 param->dbus_signature[0] == 'u' ||
790 param->dbus_signature[0] == 'x' ||
791 param->dbus_signature[0] == 't' ||
792 param->dbus_signature[0] == 'd')
794 gchar *str = NULL;
795 gdouble minint = 0;
796 gdouble maxint = 0;
797 gdouble step = 1;
799 switch (param->dbus_signature[0])
801 case 'y': minint = G_MININT8; maxint = G_MAXINT8; break;
802 case 'n': minint = G_MININT16; maxint = G_MAXINT16; break;
803 case 'q': minint = 0; maxint = G_MAXUINT16; break;
804 case 'i': minint = G_MININT32; maxint = G_MAXINT32; break;
805 case 'u': minint = 0; maxint = G_MAXUINT32; break;
806 case 'x': minint = G_MININT64; maxint = G_MAXINT64; break;
807 case 't': minint = 0; maxint = G_MAXUINT64; break;
808 case 'd': minint = G_MININT32; maxint = G_MAXINT32;
809 step = 0.1; break;
810 default: g_assert_not_reached ();
813 str = g_strdup_printf (_("%s:"), param_name_formatted);
814 widget = gtk_label_new (str);
815 gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
816 g_free (str);
818 gtk_table_attach (GTK_TABLE (table_settings),
819 widget,
820 0, 1,
821 n_rows - 1, n_rows,
822 GTK_FILL, 0,
823 0, 0);
824 gtk_widget_show (widget);
826 widget = gtk_spin_button_new_with_range (minint, maxint, step);
827 gtk_table_attach (GTK_TABLE (table_settings),
828 widget,
829 1, 2,
830 n_rows - 1, n_rows,
831 GTK_FILL | GTK_EXPAND, 0,
832 0, 0);
833 gtk_widget_show (widget);
835 else if (param->dbus_signature[0] == 'b')
837 widget = gtk_check_button_new_with_label (param_name_formatted);
838 gtk_table_attach (GTK_TABLE (table_settings),
839 widget,
840 0, 2,
841 n_rows - 1, n_rows,
842 GTK_FILL | GTK_EXPAND, 0,
843 0, 0);
844 gtk_widget_show (widget);
846 else
848 DEBUG ("Unknown signature for param %s: %s",
849 param_name_formatted, param->dbus_signature);
852 if (widget)
853 empathy_account_widget_setup_widget (self, widget, param->name);
855 g_free (param_name_formatted);
859 static void
860 account_widget_handle_params_valist (EmpathyAccountWidget *self,
861 const gchar *first_widget,
862 va_list args)
864 GObject *object;
865 const gchar *name;
867 for (name = first_widget; name; name = va_arg (args, const gchar *))
869 const gchar *param_name;
871 param_name = va_arg (args, const gchar *);
872 object = gtk_builder_get_object (self->ui_details->gui, name);
874 if (!object)
876 g_warning ("Builder is missing object '%s'.", name);
877 continue;
880 empathy_account_widget_setup_widget (self, GTK_WIDGET (object),
881 param_name);
885 static void
886 account_widget_cancel_clicked_cb (GtkWidget *button,
887 EmpathyAccountWidget *self)
889 g_signal_emit (self, signals[CANCELLED], 0);
892 static void
893 account_widget_account_enabled_cb (GObject *source_object,
894 GAsyncResult *res,
895 gpointer user_data)
897 GError *error = NULL;
898 TpAccount *account = TP_ACCOUNT (source_object);
899 EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
900 EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
902 tp_account_set_enabled_finish (account, res, &error);
904 if (error != NULL)
906 DEBUG ("Could not enable the account: %s", error->message);
907 g_error_free (error);
909 else
911 empathy_connect_new_account (account, priv->account_manager);
914 /* unref widget - part of the workaround */
915 g_object_unref (widget);
918 static void
919 account_widget_applied_cb (GObject *source_object,
920 GAsyncResult *res,
921 gpointer user_data)
923 GError *error = NULL;
924 TpAccount *account;
925 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source_object);
926 EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data);
927 EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
928 gboolean reconnect_required;
930 empathy_account_settings_apply_finish (settings, res, &reconnect_required,
931 &error);
933 if (error != NULL)
935 DEBUG ("Could not apply changes to account: %s", error->message);
936 g_error_free (error);
937 return;
940 account = empathy_account_settings_get_account (priv->settings);
942 if (account != NULL)
944 if (priv->creating_account)
946 /* By default, when an account is created, we enable it. */
948 /* workaround to keep widget alive during async call */
949 g_object_ref (widget);
951 tp_account_set_enabled_async (account, TRUE,
952 account_widget_account_enabled_cb, widget);
953 g_signal_emit (widget, signals[ACCOUNT_CREATED], 0, account);
955 else
957 /* If the account was offline, we always want to try reconnecting,
958 * to give it a chance to connect if the previous params were wrong.
959 * tp_account_reconnect_async() won't do anything if the requested
960 * presence is offline anyway. */
961 if (tp_account_get_connection_status (account, NULL) ==
962 TP_CONNECTION_STATUS_DISCONNECTED)
963 reconnect_required = TRUE;
965 if (reconnect_required && tp_account_is_enabled (account)
966 && tp_account_is_enabled (account))
968 /* After having applied changes to a user account, we
969 * reconnect it if needed. This is done so the new
970 * information entered by the user is validated on the server. */
971 tp_account_reconnect_async (account, NULL, NULL);
976 if (!priv->destroyed)
977 account_widget_set_control_buttons_sensitivity (widget, FALSE);
979 priv->contains_pending_changes = FALSE;
981 /* unref the widget - part of the workaround */
982 g_object_unref (widget);
985 static void
986 account_widget_apply_and_log_in (EmpathyAccountWidget *self)
988 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
989 gboolean display_name_overridden;
991 if (priv->radiobutton_reuse != NULL)
993 gboolean reuse = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
994 priv->radiobutton_reuse));
996 DEBUG ("Set register param: %d", !reuse);
997 empathy_account_settings_set_boolean (priv->settings, "register", !reuse);
1000 g_object_get (priv->settings,
1001 "display-name-overridden", &display_name_overridden, NULL);
1003 if (priv->creating_account || !display_name_overridden)
1005 gchar *display_name;
1007 /* set default display name for new accounts or update if user didn't
1008 * manually override it. */
1009 display_name = empathy_account_widget_get_default_display_name (self);
1011 empathy_account_settings_set_display_name_async (priv->settings,
1012 display_name, NULL, NULL);
1014 g_free (display_name);
1017 /* workaround to keep widget alive during async call */
1018 g_object_ref (self);
1019 empathy_account_settings_apply_async (priv->settings,
1020 account_widget_applied_cb, self);
1023 static void
1024 account_widget_apply_clicked_cb (GtkWidget *button,
1025 EmpathyAccountWidget *self)
1027 account_widget_apply_and_log_in (self);
1030 static void
1031 account_widget_setup_generic (EmpathyAccountWidget *self)
1033 GtkWidget *table_common_settings;
1034 GtkWidget *table_advanced_settings;
1036 table_common_settings = GTK_WIDGET (gtk_builder_get_object
1037 (self->ui_details->gui, "table_common_settings"));
1038 table_advanced_settings = GTK_WIDGET (gtk_builder_get_object
1039 (self->ui_details->gui, "table_advanced_settings"));
1041 accounts_widget_generic_setup (self, table_common_settings,
1042 table_advanced_settings);
1044 g_object_unref (self->ui_details->gui);
1047 static void
1048 account_widget_settings_ready_cb (EmpathyAccountSettings *settings,
1049 GParamSpec *pspec,
1050 gpointer user_data)
1052 EmpathyAccountWidget *self = user_data;
1053 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1055 if (empathy_account_settings_is_ready (priv->settings))
1056 account_widget_setup_generic (self);
1059 static void
1060 account_widget_build_generic (EmpathyAccountWidget *self,
1061 const char *filename)
1063 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1064 GtkWidget *expander_advanced;
1066 self->ui_details->gui = empathy_builder_get_file (filename,
1067 "table_common_settings", &priv->table_common_settings,
1068 "vbox_generic_settings", &self->ui_details->widget,
1069 "expander_advanced_settings", &expander_advanced,
1070 NULL);
1072 if (priv->simple)
1073 gtk_widget_hide (expander_advanced);
1075 g_object_ref (self->ui_details->gui);
1077 if (empathy_account_settings_is_ready (priv->settings))
1078 account_widget_setup_generic (self);
1079 else
1080 g_signal_connect (priv->settings, "notify::ready",
1081 G_CALLBACK (account_widget_settings_ready_cb), self);
1084 static void
1085 account_widget_launch_external_clicked (GtkWidget *button,
1086 TpAccount *account)
1088 if (!tp_strdiff (tp_account_get_storage_provider (account),
1089 "com.meego.libsocialweb"))
1091 /* we know how to handle this external provider */
1092 GDesktopAppInfo *desktop_info;
1093 GError *error = NULL;
1094 GdkAppLaunchContext *context = NULL;
1095 GdkDisplay *display;
1096 gchar *cmd;
1097 GAppInfo *app_info;
1099 desktop_info = g_desktop_app_info_new ("gnome-control-center.desktop");
1100 if (desktop_info == NULL)
1102 g_critical ("Could not locate 'gnome-control-center.desktop'");
1103 return;
1106 /* glib doesn't have API to start a desktop file with args... (#637875) */
1107 cmd = g_strdup_printf ("%s bisho.desktop", g_app_info_get_commandline (
1108 (GAppInfo *) desktop_info));
1110 app_info = g_app_info_create_from_commandline (cmd, NULL, 0, &error);
1111 g_free (cmd);
1113 if (app_info == NULL)
1115 DEBUG ("Failed to create app info: %s", error->message);
1116 g_error_free (error);
1117 goto out;
1120 display = gdk_display_get_default ();
1121 context = gdk_display_get_app_launch_context (display);
1123 if (!g_app_info_launch (app_info, NULL, (GAppLaunchContext *) context,
1124 &error))
1126 g_critical ("Failed to bisho: %s", error->message);
1127 g_clear_error (&error);
1130 out:
1131 g_object_unref (desktop_info);
1132 tp_clear_object (&app_info);
1133 tp_clear_object (&context);
1137 static void
1138 account_widget_build_external (EmpathyAccountWidget *self,
1139 EmpathyAccountSettings *settings)
1141 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1142 TpAccount *account = empathy_account_settings_get_account (settings);
1143 GtkWidget *bar, *widget;
1144 gchar *str;
1146 self->ui_details->widget = gtk_vbox_new (FALSE, 6);
1147 priv->table_common_settings = gtk_table_new (1, 2, FALSE);
1149 if (!tp_strdiff (tp_account_get_storage_provider (account),
1150 "com.meego.libsocialweb"))
1152 /* we know how to handle this external provider */
1153 str = g_strdup_printf (
1154 _("The account %s is edited via My Web Accounts."),
1155 empathy_account_settings_get_display_name (settings));
1157 else
1159 str = g_strdup_printf (
1160 _("The account %s cannot be edited in Empathy."),
1161 empathy_account_settings_get_display_name (settings));
1164 widget = gtk_label_new (str);
1165 gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
1166 g_free (str);
1168 bar = gtk_info_bar_new ();
1169 gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_INFO);
1170 gtk_container_add (
1171 GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))),
1172 widget);
1173 gtk_container_set_border_width (GTK_CONTAINER (bar), 6);
1175 if (!tp_strdiff (tp_account_get_storage_provider (account),
1176 "com.meego.libsocialweb"))
1178 /* we know how to handle this external provider */
1179 widget = gtk_info_bar_add_button (GTK_INFO_BAR (bar),
1180 _("Launch My Web Accounts"), RESPONSE_LAUNCH);
1182 g_signal_connect (widget, "clicked",
1183 G_CALLBACK (account_widget_launch_external_clicked), account);
1186 gtk_box_pack_start (GTK_BOX (self->ui_details->widget), bar,
1187 FALSE, TRUE, 0);
1188 gtk_box_pack_start (GTK_BOX (self->ui_details->widget),
1189 priv->table_common_settings, FALSE, TRUE, 0);
1191 gtk_widget_show_all (self->ui_details->widget);
1194 static void
1195 account_widget_build_salut (EmpathyAccountWidget *self,
1196 const char *filename)
1198 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1199 GtkWidget *expander_advanced;
1201 self->ui_details->gui = empathy_builder_get_file (filename,
1202 "table_common_settings", &priv->table_common_settings,
1203 "vbox_salut_settings", &self->ui_details->widget,
1204 "expander_advanced_settings", &expander_advanced,
1205 NULL);
1207 empathy_account_widget_handle_params (self,
1208 "entry_published", "published-name",
1209 "entry_nickname", "nickname",
1210 "entry_first_name", "first-name",
1211 "entry_last_name", "last-name",
1212 "entry_email", "email",
1213 "entry_jid", "jid",
1214 NULL);
1216 if (priv->simple)
1217 gtk_widget_hide (expander_advanced);
1219 self->ui_details->default_focus = g_strdup ("entry_first_name");
1222 static void
1223 account_widget_build_irc (EmpathyAccountWidget *self,
1224 const char *filename)
1226 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1228 empathy_account_settings_set_regex (priv->settings, "account",
1229 ACCOUNT_REGEX_IRC);
1231 if (priv->simple)
1233 priv->irc_network_chooser = empathy_account_widget_irc_build_simple (self,
1234 filename);
1236 else
1238 priv->irc_network_chooser = empathy_account_widget_irc_build (self,
1239 filename, &priv->table_common_settings);
1243 static void
1244 account_widget_build_sip (EmpathyAccountWidget *self,
1245 const char *filename)
1247 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1248 empathy_account_widget_sip_build (self, filename,
1249 &priv->table_common_settings);
1251 if (priv->simple)
1253 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1254 self->ui_details->gui, "remember_password_simple"));
1256 else
1258 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1259 self->ui_details->gui, "remember_password"));
1263 static void
1264 account_widget_build_msn (EmpathyAccountWidget *self,
1265 const char *filename)
1267 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1269 empathy_account_settings_set_regex (priv->settings, "account",
1270 ACCOUNT_REGEX_MSN);
1272 if (priv->simple)
1274 self->ui_details->gui = empathy_builder_get_file (filename,
1275 "vbox_msn_simple", &self->ui_details->widget,
1276 NULL);
1278 empathy_account_widget_handle_params (self,
1279 "entry_id_simple", "account",
1280 "entry_password_simple", "password",
1281 NULL);
1283 self->ui_details->default_focus = g_strdup ("entry_id_simple");
1285 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1286 self->ui_details->gui, "remember_password_simple"));
1288 else
1290 self->ui_details->gui = empathy_builder_get_file (filename,
1291 "table_common_msn_settings", &priv->table_common_settings,
1292 "vbox_msn_settings", &self->ui_details->widget,
1293 NULL);
1295 empathy_account_widget_handle_params (self,
1296 "entry_id", "account",
1297 "entry_password", "password",
1298 "entry_server", "server",
1299 "spinbutton_port", "port",
1300 NULL);
1302 self->ui_details->default_focus = g_strdup ("entry_id");
1304 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1305 self->ui_details->gui, "remember_password"));
1309 static void
1310 suffix_id_widget_changed_cb (GtkWidget *entry,
1311 EmpathyAccountWidget *self)
1313 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1314 const gchar *account;
1316 g_assert (priv->jid_suffix != NULL);
1318 account_widget_entry_changed_common (self, GTK_ENTRY (entry), FALSE);
1320 account = empathy_account_settings_get_string (priv->settings, "account");
1321 if (!EMP_STR_EMPTY (account) &&
1322 !g_str_has_suffix (account, priv->jid_suffix))
1324 gchar *tmp;
1326 tmp = g_strdup_printf ("%s%s", account, priv->jid_suffix);
1328 DEBUG ("Change account from '%s' to '%s'", account, tmp);
1330 empathy_account_settings_set_string (priv->settings, "account", tmp);
1331 g_free (tmp);
1334 empathy_account_widget_changed (self);
1337 static gchar *
1338 remove_jid_suffix (EmpathyAccountWidget *self,
1339 const gchar *str)
1341 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1343 g_assert (priv->jid_suffix != NULL);
1345 if (!g_str_has_suffix (str, priv->jid_suffix))
1346 return g_strdup (str);
1348 return g_strndup (str, strlen (str) - strlen (priv->jid_suffix));
1351 static void
1352 setup_id_widget_with_suffix (EmpathyAccountWidget *self,
1353 GtkWidget *widget,
1354 const gchar *suffix)
1356 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1357 const gchar *str = NULL;
1359 g_object_set_data_full (G_OBJECT (widget), "param_name",
1360 g_strdup ("account"), g_free);
1362 g_assert (priv->jid_suffix == NULL);
1363 priv->jid_suffix = g_strdup (suffix);
1365 str = empathy_account_settings_get_string (priv->settings, "account");
1366 if (str != NULL)
1368 gchar *tmp;
1370 tmp = remove_jid_suffix (self, str);
1371 gtk_entry_set_text (GTK_ENTRY (widget), tmp);
1372 g_free (tmp);
1375 priv->param_account_widget = widget;
1377 g_signal_connect (widget, "changed",
1378 G_CALLBACK (suffix_id_widget_changed_cb), self);
1381 static Service
1382 account_widget_get_service (EmpathyAccountWidget *self)
1384 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1385 const gchar *icon_name, *service;
1387 icon_name = empathy_account_settings_get_icon_name (priv->settings);
1388 service = empathy_account_settings_get_service (priv->settings);
1390 /* Previous versions of Empathy didn't set the Service property on Facebook
1391 * and gtalk accounts, so we check using the icon name as well. */
1392 if (!tp_strdiff (icon_name, "im-google-talk") ||
1393 !tp_strdiff (service, "google-talk"))
1394 return GTALK_SERVICE;
1396 if (!tp_strdiff (icon_name, "im-facebook") ||
1397 !tp_strdiff (service, "facebook"))
1398 return FACEBOOK_SERVICE;
1400 return NO_SERVICE;
1403 static void
1404 account_widget_build_jabber (EmpathyAccountWidget *self,
1405 const char *filename)
1407 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1408 GtkWidget *spinbutton_port;
1409 GtkWidget *checkbutton_ssl;
1410 GtkWidget *label_id, *label_password;
1411 GtkWidget *label_id_create, *label_password_create;
1412 GtkWidget *label_example_fb;
1413 GtkWidget *label_example;
1414 GtkWidget *expander_advanced;
1415 GtkWidget *entry_id;
1416 Service service;
1418 service = account_widget_get_service (self);
1420 empathy_account_settings_set_regex (priv->settings, "account",
1421 ACCOUNT_REGEX_JABBER);
1423 if (priv->simple && service == NO_SERVICE)
1425 /* Simple widget for XMPP */
1426 self->ui_details->gui = empathy_builder_get_file (filename,
1427 "vbox_jabber_simple", &self->ui_details->widget,
1428 "label_id_simple", &label_id,
1429 "label_id_create", &label_id_create,
1430 "label_password_simple", &label_password,
1431 "label_password_create", &label_password_create,
1432 NULL);
1434 if (empathy_account_settings_get_boolean (priv->settings, "register"))
1436 gtk_widget_hide (label_id);
1437 gtk_widget_hide (label_password);
1438 gtk_widget_show (label_id_create);
1439 gtk_widget_show (label_password_create);
1442 empathy_account_widget_handle_params (self,
1443 "entry_id_simple", "account",
1444 "entry_password_simple", "password",
1445 NULL);
1447 self->ui_details->default_focus = g_strdup ("entry_id_simple");
1449 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1450 self->ui_details->gui, "remember_password_simple"));
1452 else if (priv->simple && service == GTALK_SERVICE)
1454 /* Simple widget for Google Talk */
1455 self->ui_details->gui = empathy_builder_get_file (filename,
1456 "vbox_gtalk_simple", &self->ui_details->widget,
1457 NULL);
1459 empathy_account_widget_handle_params (self,
1460 "entry_id_g_simple", "account",
1461 "entry_password_g_simple", "password",
1462 NULL);
1464 self->ui_details->default_focus = g_strdup ("entry_id_g_simple");
1466 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1467 self->ui_details->gui, "remember_password_g_simple"));
1469 else if (priv->simple && service == FACEBOOK_SERVICE)
1471 /* Simple widget for Facebook */
1472 self->ui_details->gui = empathy_builder_get_file (filename,
1473 "vbox_fb_simple", &self->ui_details->widget,
1474 "entry_id_fb_simple", &entry_id,
1475 NULL);
1477 empathy_account_widget_handle_params (self,
1478 "entry_password_fb_simple", "password",
1479 NULL);
1481 setup_id_widget_with_suffix (self, entry_id, "@chat.facebook.com");
1483 self->ui_details->default_focus = g_strdup ("entry_id_fb_simple");
1485 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1486 self->ui_details->gui, "remember_password_fb_simple"));
1488 else
1490 ServiceInfo info = services_infos[service];
1492 /* Full widget for XMPP, Google Talk and Facebook*/
1493 self->ui_details->gui = empathy_builder_get_file (filename,
1494 "table_common_settings", &priv->table_common_settings,
1495 "vbox_jabber_settings", &self->ui_details->widget,
1496 "spinbutton_port", &spinbutton_port,
1497 "checkbutton_ssl", &checkbutton_ssl,
1498 "label_username_f_example", &label_example_fb,
1499 info.label_username_example, &label_example,
1500 "expander_advanced", &expander_advanced,
1501 "entry_id", &entry_id,
1502 "label_id", &label_id,
1503 NULL);
1505 empathy_account_widget_handle_params (self,
1506 "entry_password", "password",
1507 "entry_resource", "resource",
1508 "entry_server", "server",
1509 "spinbutton_port", "port",
1510 "spinbutton_priority", "priority",
1511 "checkbutton_ssl", "old-ssl",
1512 "checkbutton_ignore_ssl_errors", "ignore-ssl-errors",
1513 "checkbutton_encryption", "require-encryption",
1514 NULL);
1516 if (service == FACEBOOK_SERVICE)
1518 gtk_label_set_label (GTK_LABEL (label_id), _("Username:"));
1520 /* Facebook special case the entry ID widget to hide the
1521 * "@chat.facebook.com" part */
1522 setup_id_widget_with_suffix (self, entry_id, "@chat.facebook.com");
1524 else
1526 empathy_account_widget_setup_widget (self, entry_id, "account");
1529 self->ui_details->default_focus = g_strdup ("entry_id");
1530 priv->spinbutton_port = spinbutton_port;
1532 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1533 self->ui_details->gui, "remember_password"));
1535 g_signal_connect (checkbutton_ssl, "toggled",
1536 G_CALLBACK (account_widget_jabber_ssl_toggled_cb),
1537 self);
1539 if (service == FACEBOOK_SERVICE)
1541 GtkContainer *parent;
1542 GList *children;
1544 /* Removing the label from list of focusable widgets */
1545 parent = GTK_CONTAINER (gtk_widget_get_parent (label_example_fb));
1546 children = gtk_container_get_children (parent);
1547 children = g_list_remove (children, label_example_fb);
1548 gtk_container_set_focus_chain (parent, children);
1549 g_list_free (children);
1552 gtk_widget_show (label_example);
1554 if (!info.show_advanced)
1555 gtk_widget_hide (expander_advanced);
1559 static void
1560 account_widget_build_icq (EmpathyAccountWidget *self,
1561 const char *filename)
1563 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1564 GtkWidget *spinbutton_port;
1566 empathy_account_settings_set_regex (priv->settings, "account",
1567 ACCOUNT_REGEX_ICQ);
1569 if (priv->simple)
1571 self->ui_details->gui = empathy_builder_get_file (filename,
1572 "vbox_icq_simple", &self->ui_details->widget,
1573 NULL);
1575 empathy_account_widget_handle_params (self,
1576 "entry_uin_simple", "account",
1577 "entry_password_simple", "password",
1578 NULL);
1580 self->ui_details->default_focus = g_strdup ("entry_uin_simple");
1582 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1583 self->ui_details->gui, "remember_password_simple"));
1585 else
1587 self->ui_details->gui = empathy_builder_get_file (filename,
1588 "table_common_settings", &priv->table_common_settings,
1589 "vbox_icq_settings", &self->ui_details->widget,
1590 "spinbutton_port", &spinbutton_port,
1591 NULL);
1593 empathy_account_widget_handle_params (self,
1594 "entry_uin", "account",
1595 "entry_password", "password",
1596 "entry_server", "server",
1597 "spinbutton_port", "port",
1598 "entry_charset", "charset",
1599 NULL);
1601 self->ui_details->default_focus = g_strdup ("entry_uin");
1603 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1604 self->ui_details->gui, "remember_password"));
1608 static void
1609 account_widget_build_aim (EmpathyAccountWidget *self,
1610 const char *filename)
1612 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1613 GtkWidget *spinbutton_port;
1615 if (priv->simple)
1617 self->ui_details->gui = empathy_builder_get_file (filename,
1618 "vbox_aim_simple", &self->ui_details->widget,
1619 NULL);
1621 empathy_account_widget_handle_params (self,
1622 "entry_screenname_simple", "account",
1623 "entry_password_simple", "password",
1624 NULL);
1626 self->ui_details->default_focus = g_strdup ("entry_screenname_simple");
1628 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1629 self->ui_details->gui, "remember_password_simple"));
1631 else
1633 self->ui_details->gui = empathy_builder_get_file (filename,
1634 "table_common_settings", &priv->table_common_settings,
1635 "vbox_aim_settings", &self->ui_details->widget,
1636 "spinbutton_port", &spinbutton_port,
1637 NULL);
1639 empathy_account_widget_handle_params (self,
1640 "entry_screenname", "account",
1641 "entry_password", "password",
1642 "entry_server", "server",
1643 "spinbutton_port", "port",
1644 NULL);
1646 self->ui_details->default_focus = g_strdup ("entry_screenname");
1648 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1649 self->ui_details->gui, "remember_password"));
1653 static void
1654 account_widget_build_yahoo (EmpathyAccountWidget *self,
1655 const char *filename)
1657 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1659 empathy_account_settings_set_regex (priv->settings, "account",
1660 ACCOUNT_REGEX_YAHOO);
1662 if (priv->simple)
1664 self->ui_details->gui = empathy_builder_get_file (filename,
1665 "vbox_yahoo_simple", &self->ui_details->widget,
1666 NULL);
1668 empathy_account_widget_handle_params (self,
1669 "entry_id_simple", "account",
1670 "entry_password_simple", "password",
1671 NULL);
1673 self->ui_details->default_focus = g_strdup ("entry_id_simple");
1675 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1676 self->ui_details->gui, "remember_password_simple"));
1678 else
1680 self->ui_details->gui = empathy_builder_get_file (filename,
1681 "table_common_settings", &priv->table_common_settings,
1682 "vbox_yahoo_settings", &self->ui_details->widget,
1683 NULL);
1685 empathy_account_widget_handle_params (self,
1686 "entry_id", "account",
1687 "entry_password", "password",
1688 "entry_locale", "room-list-locale",
1689 "entry_charset", "charset",
1690 "spinbutton_port", "port",
1691 "checkbutton_ignore_invites", "ignore-invites",
1692 NULL);
1694 self->ui_details->default_focus = g_strdup ("entry_id");
1696 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1697 self->ui_details->gui, "remember_password"));
1701 static void
1702 account_widget_build_groupwise (EmpathyAccountWidget *self,
1703 const char *filename)
1705 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1707 if (priv->simple)
1709 self->ui_details->gui = empathy_builder_get_file (filename,
1710 "vbox_groupwise_simple", &self->ui_details->widget,
1711 NULL);
1713 empathy_account_widget_handle_params (self,
1714 "entry_id_simple", "account",
1715 "entry_password_simple", "password",
1716 NULL);
1718 self->ui_details->default_focus = g_strdup ("entry_id_simple");
1720 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1721 self->ui_details->gui, "remember_password_simple"));
1723 else
1725 self->ui_details->gui = empathy_builder_get_file (filename,
1726 "table_common_groupwise_settings", &priv->table_common_settings,
1727 "vbox_groupwise_settings", &self->ui_details->widget,
1728 NULL);
1730 empathy_account_widget_handle_params (self,
1731 "entry_id", "account",
1732 "entry_password", "password",
1733 "entry_server", "server",
1734 "spinbutton_port", "port",
1735 NULL);
1737 self->ui_details->default_focus = g_strdup ("entry_id");
1739 priv->remember_password_widget = GTK_WIDGET (gtk_builder_get_object (
1740 self->ui_details->gui, "remember_password"));
1744 static void
1745 account_widget_destroy_cb (GtkWidget *widget,
1746 EmpathyAccountWidget *self)
1748 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1749 /* set the destroyed flag - workaround */
1750 priv->destroyed = TRUE;
1752 g_object_unref (self);
1755 void
1756 empathy_account_widget_set_other_accounts_exist (EmpathyAccountWidget *self,
1757 gboolean others_exist)
1759 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1761 priv->other_accounts_exist = others_exist;
1763 if (priv->creating_account)
1764 account_widget_handle_control_buttons_sensitivity (self);
1767 static void
1768 do_set_property (GObject *object,
1769 guint prop_id,
1770 const GValue *value,
1771 GParamSpec *pspec)
1773 EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1775 switch (prop_id)
1777 case PROP_SETTINGS:
1778 priv->settings = g_value_dup_object (value);
1779 break;
1780 case PROP_SIMPLE:
1781 priv->simple = g_value_get_boolean (value);
1782 break;
1783 case PROP_CREATING_ACCOUNT:
1784 priv->creating_account = g_value_get_boolean (value);
1785 break;
1786 case PROP_OTHER_ACCOUNTS_EXIST:
1787 empathy_account_widget_set_other_accounts_exist (
1788 EMPATHY_ACCOUNT_WIDGET (object), g_value_get_boolean (value));
1789 break;
1790 default:
1791 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1795 static void
1796 do_get_property (GObject *object,
1797 guint prop_id,
1798 GValue *value,
1799 GParamSpec *pspec)
1801 EmpathyAccountWidgetPriv *priv = GET_PRIV (object);
1803 switch (prop_id)
1805 case PROP_PROTOCOL:
1806 g_value_set_string (value,
1807 empathy_account_settings_get_protocol (priv->settings));
1808 break;
1809 case PROP_SETTINGS:
1810 g_value_set_object (value, priv->settings);
1811 break;
1812 case PROP_SIMPLE:
1813 g_value_set_boolean (value, priv->simple);
1814 break;
1815 case PROP_CREATING_ACCOUNT:
1816 g_value_set_boolean (value, priv->creating_account);
1817 break;
1818 case PROP_OTHER_ACCOUNTS_EXIST:
1819 g_value_set_boolean (value, priv->other_accounts_exist);
1820 break;
1821 default:
1822 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1826 static void
1827 set_apply_button (EmpathyAccountWidget *self)
1829 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1830 GtkWidget *image;
1832 /* We can't use the stock button as its accelerator ('A') clashes with the
1833 * Add button. */
1834 gtk_button_set_use_stock (GTK_BUTTON (priv->apply_button), FALSE);
1836 gtk_button_set_label (GTK_BUTTON (priv->apply_button), _("A_pply"));
1837 gtk_button_set_use_underline (GTK_BUTTON (priv->apply_button), TRUE);
1839 image = gtk_image_new_from_stock (GTK_STOCK_APPLY, GTK_ICON_SIZE_BUTTON);
1840 gtk_button_set_image (GTK_BUTTON (priv->apply_button), image);
1843 static void
1844 presence_changed_cb (TpAccountManager *manager,
1845 TpConnectionPresenceType state,
1846 const gchar *status,
1847 const gchar *message,
1848 EmpathyAccountWidget *self)
1850 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1852 if (priv->destroyed)
1853 return;
1855 if (priv->apply_button == NULL)
1856 /* This button doesn't exist in 'simple' mode */
1857 return;
1859 if (state > TP_CONNECTION_PRESENCE_TYPE_OFFLINE &&
1860 priv->creating_account)
1862 /* We are online and creating a new account, display a Login button */
1863 GtkWidget *image;
1865 gtk_button_set_use_stock (GTK_BUTTON (priv->apply_button), FALSE);
1866 gtk_button_set_label (GTK_BUTTON (priv->apply_button), _("L_og in"));
1868 image = gtk_image_new_from_stock (GTK_STOCK_CONNECT,
1869 GTK_ICON_SIZE_BUTTON);
1870 gtk_button_set_image (GTK_BUTTON (priv->apply_button), image);
1872 else
1874 /* We are offline or modifying an existing account, display
1875 * a Save button */
1876 set_apply_button (self);
1880 static void
1881 account_manager_ready_cb (GObject *source_object,
1882 GAsyncResult *result,
1883 gpointer user_data)
1885 EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (user_data);
1886 TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
1887 GError *error = NULL;
1888 TpConnectionPresenceType state;
1890 if (!tp_account_manager_prepare_finish (account_manager, result, &error))
1892 DEBUG ("Failed to prepare account manager: %s", error->message);
1893 g_error_free (error);
1894 goto out;
1897 state = tp_account_manager_get_most_available_presence (account_manager, NULL,
1898 NULL);
1900 /* simulate a presence change so the apply button will be changed
1901 * if needed */
1902 presence_changed_cb (account_manager, state, NULL, NULL, self);
1904 out:
1905 g_object_unref (self);
1908 #define WIDGET(cm, proto) \
1909 { #cm, #proto, "empathy-account-widget-"#proto".ui", \
1910 account_widget_build_##proto }
1912 #ifndef HAVE_MEEGO
1913 /* Meego doesn't support registration */
1914 static void
1915 add_register_buttons (EmpathyAccountWidget *self,
1916 TpAccount *account)
1918 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1919 const TpConnectionManagerProtocol *protocol;
1920 GtkWidget *radiobutton_register;
1921 GtkWidget *vbox = self->ui_details->widget;
1923 if (!priv->creating_account)
1924 return;
1926 protocol = empathy_account_settings_get_tp_protocol (priv->settings);
1927 if (protocol == NULL)
1928 return;
1930 if (!tp_connection_manager_protocol_can_register (protocol))
1931 return;
1933 if (account_widget_get_service (self) != NO_SERVICE)
1934 return;
1936 if (priv->simple)
1937 return;
1939 priv->radiobutton_reuse = gtk_radio_button_new_with_label (NULL,
1940 _("This account already exists on the server"));
1941 radiobutton_register = gtk_radio_button_new_with_label (
1942 gtk_radio_button_get_group (GTK_RADIO_BUTTON (priv->radiobutton_reuse)),
1943 _("Create a new account on the server"));
1945 gtk_box_pack_start (GTK_BOX (vbox), priv->radiobutton_reuse, FALSE, FALSE, 0);
1946 gtk_box_pack_start (GTK_BOX (vbox), radiobutton_register, FALSE, FALSE, 0);
1947 gtk_box_reorder_child (GTK_BOX (vbox), priv->radiobutton_reuse, 0);
1948 gtk_box_reorder_child (GTK_BOX (vbox), radiobutton_register, 1);
1949 gtk_widget_show (priv->radiobutton_reuse);
1950 gtk_widget_show (radiobutton_register);
1952 #endif /* HAVE_MEEGO */
1954 static void
1955 remember_password_toggled_cb (GtkToggleButton *button,
1956 EmpathyAccountWidget *self)
1958 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1960 if (gtk_toggle_button_get_active (button))
1962 gtk_widget_set_sensitive (priv->param_password_widget, TRUE);
1964 else
1966 gtk_widget_set_sensitive (priv->param_password_widget, FALSE);
1967 gtk_entry_set_text (GTK_ENTRY (priv->param_password_widget), "");
1968 empathy_account_settings_unset (priv->settings, "password");
1972 static void
1973 account_settings_password_retrieved_cb (GObject *object,
1974 gpointer user_data)
1976 EmpathyAccountWidget *self = user_data;
1977 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
1978 const gchar *password = empathy_account_settings_get_string (
1979 priv->settings, "password");
1981 if (password != NULL)
1983 /* We have to do this so that when we call gtk_entry_set_text,
1984 * the ::changed callback doesn't think the user made the
1985 * change. */
1986 priv->automatic_change = TRUE;
1987 gtk_entry_set_text (GTK_ENTRY (priv->param_password_widget), password);
1988 priv->automatic_change = FALSE;
1991 gtk_toggle_button_set_active (
1992 GTK_TOGGLE_BUTTON (priv->remember_password_widget),
1993 !EMP_STR_EMPTY (password));
1996 static void
1997 do_constructed (GObject *obj)
1999 EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
2000 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
2001 TpAccount *account;
2002 TpStorageRestrictionFlags storage_restrictions;
2003 const gchar *display_name, *default_display_name;
2004 guint i = 0;
2005 struct {
2006 const gchar *cm_name;
2007 const gchar *protocol;
2008 const char *file;
2009 void (*func)(EmpathyAccountWidget *self, const gchar *filename);
2010 } widgets [] = {
2011 { "salut", "local-xmpp", "empathy-account-widget-local-xmpp.ui",
2012 account_widget_build_salut },
2013 WIDGET (gabble, jabber),
2014 WIDGET (butterfly, msn),
2015 WIDGET (haze, icq),
2016 WIDGET (haze, aim),
2017 WIDGET (haze, yahoo),
2018 WIDGET (haze, groupwise),
2019 WIDGET (idle, irc),
2020 WIDGET (sofiasip, sip),
2023 account = empathy_account_settings_get_account (priv->settings);
2025 if (account != NULL)
2026 storage_restrictions = tp_account_get_storage_restrictions (account);
2027 else
2028 storage_restrictions = 0;
2030 /* Empathy can only edit accounts without the Cannot_Set_Parameters flag */
2031 if (storage_restrictions & TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS)
2033 DEBUG ("Account is provided by an external storage provider");
2035 account_widget_build_external (self, priv->settings);
2037 else
2039 const gchar *protocol, *cm_name;
2041 cm_name = empathy_account_settings_get_cm (priv->settings);
2042 protocol = empathy_account_settings_get_protocol (priv->settings);
2044 for (i = 0 ; i < G_N_ELEMENTS (widgets); i++)
2046 if (!tp_strdiff (widgets[i].cm_name, cm_name) &&
2047 !tp_strdiff (widgets[i].protocol, protocol))
2049 gchar *filename;
2051 filename = empathy_file_lookup (widgets[i].file,
2052 "libempathy-gtk");
2053 widgets[i].func (self, filename);
2054 g_free (filename);
2056 break;
2060 if (i == G_N_ELEMENTS (widgets))
2062 gchar *filename = empathy_file_lookup (
2063 "empathy-account-widget-generic.ui", "libempathy-gtk");
2064 account_widget_build_generic (self, filename);
2065 g_free (filename);
2069 /* handle default focus */
2070 if (self->ui_details->default_focus != NULL)
2072 GObject *default_focus_entry;
2074 default_focus_entry = gtk_builder_get_object
2075 (self->ui_details->gui, self->ui_details->default_focus);
2076 g_signal_connect (default_focus_entry, "realize",
2077 G_CALLBACK (gtk_widget_grab_focus),
2078 NULL);
2081 /* remember password */
2082 if (priv->param_password_widget != NULL
2083 && priv->remember_password_widget != NULL
2084 && empathy_account_settings_supports_sasl (priv->settings))
2086 if (priv->simple)
2088 gtk_toggle_button_set_active (
2089 GTK_TOGGLE_BUTTON (priv->remember_password_widget), TRUE);
2091 else
2093 gtk_toggle_button_set_active (
2094 GTK_TOGGLE_BUTTON (priv->remember_password_widget),
2095 !EMP_STR_EMPTY (empathy_account_settings_get_string (
2096 priv->settings, "password")));
2098 /* The password might not have been retrieved from the
2099 * keyring yet. We should update the remember password
2100 * toggle button and the password entry when/if it is. */
2101 tp_g_signal_connect_object (priv->settings, "password-retrieved",
2102 G_CALLBACK (account_settings_password_retrieved_cb), self, 0);
2105 g_signal_connect (priv->remember_password_widget, "toggled",
2106 G_CALLBACK (remember_password_toggled_cb), self);
2108 remember_password_toggled_cb (
2109 GTK_TOGGLE_BUTTON (priv->remember_password_widget), self);
2111 else if (priv->remember_password_widget != NULL
2112 && !empathy_account_settings_supports_sasl (priv->settings))
2114 gtk_widget_set_visible (priv->remember_password_widget, FALSE);
2117 /* dup and init the account-manager */
2118 priv->account_manager = tp_account_manager_dup ();
2120 g_object_ref (self);
2121 tp_account_manager_prepare_async (priv->account_manager, NULL,
2122 account_manager_ready_cb, self);
2124 /* handle apply and cancel button */
2125 if (!priv->simple &&
2126 !(storage_restrictions &
2127 TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS))
2129 GtkWidget *hbox = gtk_hbox_new (TRUE, 3);
2130 GtkWidget *image;
2132 /* We can't use the stock button as its accelerator ('C') clashes with
2133 * the Close button. */
2134 priv->cancel_button = gtk_button_new ();
2135 gtk_button_set_label (GTK_BUTTON (priv->cancel_button), _("Ca_ncel"));
2136 gtk_button_set_use_underline (GTK_BUTTON (priv->cancel_button), TRUE);
2138 image = gtk_image_new_from_stock (GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON);
2139 gtk_button_set_image (GTK_BUTTON (priv->cancel_button), image);
2141 priv->apply_button = gtk_button_new ();
2142 set_apply_button (self);
2144 /* We'll change this button to a "Log in" one if we are creating a new
2145 * account and are connected. */
2146 tp_g_signal_connect_object (priv->account_manager,
2147 "most-available-presence-changed",
2148 G_CALLBACK (presence_changed_cb), obj, 0);
2150 gtk_box_pack_end (GTK_BOX (hbox), priv->apply_button, TRUE,
2151 TRUE, 3);
2152 gtk_box_pack_end (GTK_BOX (hbox), priv->cancel_button, TRUE,
2153 TRUE, 3);
2155 gtk_box_pack_end (GTK_BOX (self->ui_details->widget), hbox, FALSE,
2156 FALSE, 3);
2158 g_signal_connect (priv->cancel_button, "clicked",
2159 G_CALLBACK (account_widget_cancel_clicked_cb),
2160 self);
2161 g_signal_connect (priv->apply_button, "clicked",
2162 G_CALLBACK (account_widget_apply_clicked_cb),
2163 self);
2164 gtk_widget_show_all (hbox);
2166 if (priv->creating_account)
2167 /* When creating an account, the user might have nothing to enter.
2168 * That means that no control interaction might occur,
2169 * so we update the control button sensitivity manually.
2171 account_widget_handle_control_buttons_sensitivity (self);
2172 else
2173 account_widget_set_control_buttons_sensitivity (self, FALSE);
2176 #ifndef HAVE_MEEGO
2177 add_register_buttons (self, account);
2178 #endif /* HAVE_MEEGO */
2180 /* hook up to widget destruction to unref ourselves */
2181 g_signal_connect (self->ui_details->widget, "destroy",
2182 G_CALLBACK (account_widget_destroy_cb), self);
2184 if (self->ui_details->gui != NULL)
2186 empathy_builder_unref_and_keep_widget (self->ui_details->gui,
2187 self->ui_details->widget);
2188 self->ui_details->gui = NULL;
2191 display_name = empathy_account_settings_get_display_name (priv->settings);
2192 default_display_name = empathy_account_widget_get_default_display_name (self);
2194 if (tp_strdiff (display_name, default_display_name) &&
2195 !priv->creating_account)
2197 /* The display name of the account is not the one that we'd assign by
2198 * default; assume that the user changed it manually */
2199 g_object_set (priv->settings, "display-name-overridden", TRUE, NULL);
2203 static void
2204 do_dispose (GObject *obj)
2206 EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
2207 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
2209 if (priv->dispose_run)
2210 return;
2212 priv->dispose_run = TRUE;
2214 if (priv->settings != NULL)
2216 g_object_unref (priv->settings);
2217 priv->settings = NULL;
2220 if (priv->account_manager != NULL)
2222 g_object_unref (priv->account_manager);
2223 priv->account_manager = NULL;
2226 if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose != NULL)
2227 G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose (obj);
2230 static void
2231 do_finalize (GObject *obj)
2233 EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj);
2234 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
2236 g_free (self->ui_details->default_focus);
2237 g_slice_free (EmpathyAccountWidgetUIDetails, self->ui_details);
2239 g_free (priv->jid_suffix);
2241 if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize != NULL)
2242 G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize (obj);
2245 static void
2246 empathy_account_widget_class_init (EmpathyAccountWidgetClass *klass)
2248 GObjectClass *oclass = G_OBJECT_CLASS (klass);
2249 GParamSpec *param_spec;
2251 oclass->get_property = do_get_property;
2252 oclass->set_property = do_set_property;
2253 oclass->constructed = do_constructed;
2254 oclass->dispose = do_dispose;
2255 oclass->finalize = do_finalize;
2257 param_spec = g_param_spec_string ("protocol",
2258 "protocol", "The protocol of the account",
2259 NULL,
2260 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
2261 g_object_class_install_property (oclass, PROP_PROTOCOL, param_spec);
2263 param_spec = g_param_spec_object ("settings",
2264 "settings", "The settings of the account",
2265 EMPATHY_TYPE_ACCOUNT_SETTINGS,
2266 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
2267 g_object_class_install_property (oclass, PROP_SETTINGS, param_spec);
2269 param_spec = g_param_spec_boolean ("simple",
2270 "simple", "Whether the account widget is a simple or an advanced one",
2271 FALSE,
2272 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
2273 g_object_class_install_property (oclass, PROP_SIMPLE, param_spec);
2275 param_spec = g_param_spec_boolean ("creating-account",
2276 "creating-account",
2277 "TRUE if we're creating an account, FALSE if we're modifying it",
2278 FALSE,
2279 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
2280 g_object_class_install_property (oclass, PROP_CREATING_ACCOUNT, param_spec);
2282 param_spec = g_param_spec_boolean ("other-accounts-exist",
2283 "other-accounts-exist",
2284 "TRUE if there are any other accounts (even if this isn't yet saved)",
2285 FALSE,
2286 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
2287 g_object_class_install_property (oclass, PROP_OTHER_ACCOUNTS_EXIST,
2288 param_spec);
2290 signals[HANDLE_APPLY] =
2291 g_signal_new ("handle-apply", G_TYPE_FROM_CLASS (klass),
2292 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
2293 g_cclosure_marshal_VOID__BOOLEAN,
2294 G_TYPE_NONE,
2295 1, G_TYPE_BOOLEAN);
2297 /* This signal is emitted when an account has been created and enabled. */
2298 signals[ACCOUNT_CREATED] =
2299 g_signal_new ("account-created", G_TYPE_FROM_CLASS (klass),
2300 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
2301 g_cclosure_marshal_VOID__OBJECT,
2302 G_TYPE_NONE,
2303 1, G_TYPE_OBJECT);
2305 signals[CANCELLED] =
2306 g_signal_new ("cancelled", G_TYPE_FROM_CLASS (klass),
2307 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
2308 g_cclosure_marshal_VOID__VOID,
2309 G_TYPE_NONE,
2312 g_type_class_add_private (klass, sizeof (EmpathyAccountWidgetPriv));
2315 static void
2316 empathy_account_widget_init (EmpathyAccountWidget *self)
2318 EmpathyAccountWidgetPriv *priv =
2319 G_TYPE_INSTANCE_GET_PRIVATE ((self), EMPATHY_TYPE_ACCOUNT_WIDGET,
2320 EmpathyAccountWidgetPriv);
2322 self->priv = priv;
2323 priv->dispose_run = FALSE;
2325 self->ui_details = g_slice_new0 (EmpathyAccountWidgetUIDetails);
2328 /* public methods */
2330 void
2331 empathy_account_widget_discard_pending_changes
2332 (EmpathyAccountWidget *widget)
2334 EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
2336 empathy_account_settings_discard_changes (priv->settings);
2337 priv->contains_pending_changes = FALSE;
2340 gboolean
2341 empathy_account_widget_contains_pending_changes (EmpathyAccountWidget *widget)
2343 EmpathyAccountWidgetPriv *priv = GET_PRIV (widget);
2345 return priv->contains_pending_changes;
2348 void
2349 empathy_account_widget_handle_params (EmpathyAccountWidget *self,
2350 const gchar *first_widget,
2351 ...)
2353 va_list args;
2355 va_start (args, first_widget);
2356 account_widget_handle_params_valist (self, first_widget, args);
2357 va_end (args);
2360 GtkWidget *
2361 empathy_account_widget_get_widget (EmpathyAccountWidget *widget)
2363 return widget->ui_details->widget;
2366 EmpathyAccountWidget *
2367 empathy_account_widget_new_for_protocol (EmpathyAccountSettings *settings,
2368 gboolean simple)
2370 EmpathyAccountWidget *self;
2372 g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL);
2374 self = g_object_new
2375 (EMPATHY_TYPE_ACCOUNT_WIDGET,
2376 "settings", settings, "simple", simple,
2377 "creating-account",
2378 empathy_account_settings_get_account (settings) == NULL,
2379 NULL);
2381 return self;
2384 gchar *
2385 empathy_account_widget_get_default_display_name (EmpathyAccountWidget *self)
2387 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
2388 const gchar *login_id;
2389 const gchar *protocol, *p;
2390 gchar *default_display_name;
2391 Service service;
2393 login_id = empathy_account_settings_get_string (priv->settings, "account");
2394 protocol = empathy_account_settings_get_protocol (priv->settings);
2395 service = account_widget_get_service (self);
2397 if (login_id != NULL)
2399 /* TODO: this should be done in empathy-account-widget-irc */
2400 if (!tp_strdiff (protocol, "irc"))
2402 EmpathyIrcNetwork *network;
2404 network = empathy_irc_network_chooser_get_network (
2405 priv->irc_network_chooser);
2406 g_assert (network != NULL);
2408 /* To translators: The first parameter is the login id and the
2409 * second one is the network. The resulting string will be something
2410 * like: "MyUserName on freenode".
2411 * You should reverse the order of these arguments if the
2412 * server should come before the login id in your locale.*/
2413 default_display_name = g_strdup_printf (_("%1$s on %2$s"),
2414 login_id, empathy_irc_network_get_name (network));
2416 else if (service == FACEBOOK_SERVICE)
2418 gchar *tmp;
2420 tmp = remove_jid_suffix (self, login_id);
2421 default_display_name = g_strdup_printf ("Facebook (%s)", tmp);
2422 g_free (tmp);
2424 else
2426 default_display_name = g_strdup (login_id);
2429 return default_display_name;
2432 if ((p = empathy_protocol_name_to_display_name (protocol)) != NULL)
2433 protocol = p;
2435 if (protocol != NULL)
2437 /* To translators: The parameter is the protocol name. The resulting
2438 * string will be something like: "Jabber Account" */
2439 default_display_name = g_strdup_printf (_("%s Account"), protocol);
2441 else
2443 default_display_name = g_strdup (_("New account"));
2446 return default_display_name;
2449 /* Used by subclass to indicate that widget contains pending changes */
2450 void
2451 empathy_account_widget_changed (EmpathyAccountWidget *self)
2453 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
2455 account_widget_handle_control_buttons_sensitivity (self);
2456 priv->contains_pending_changes = TRUE;
2459 void
2460 empathy_account_widget_set_account_param (EmpathyAccountWidget *self,
2461 const gchar *account)
2463 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
2465 if (priv->param_account_widget == NULL)
2466 return;
2468 gtk_entry_set_text (GTK_ENTRY (priv->param_account_widget), account);
2471 void
2472 empathy_account_widget_set_password_param (EmpathyAccountWidget *self,
2473 const gchar *account)
2475 EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
2477 if (priv->param_password_widget == NULL)
2478 return;
2480 gtk_entry_set_text (GTK_ENTRY (priv->param_password_widget), account);