Add an EmpathyIndividualMenu::link-contacts-activated signal
[empathy-mirror.git] / libempathy / empathy-account-settings.c
blobc470ce052d7fa5ad0a95dc0b2220f03c5625fa02
1 /*
2 * empathy-account-settings.c - Source for EmpathyAccountSettings
3 * Copyright (C) 2009 Collabora Ltd.
4 * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <stdio.h>
23 #include <stdlib.h>
25 #include <telepathy-glib/account-manager.h>
26 #include <telepathy-glib/util.h>
27 #include <telepathy-glib/interfaces.h>
28 #include <telepathy-glib/gtypes.h>
30 #include "empathy-account-settings.h"
31 #include "empathy-connection-managers.h"
32 #include "empathy-utils.h"
33 #include "empathy-idle.h"
35 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
36 #include <libempathy/empathy-debug.h>
38 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountSettings)
40 G_DEFINE_TYPE(EmpathyAccountSettings, empathy_account_settings, G_TYPE_OBJECT)
42 enum {
43 PROP_ACCOUNT = 1,
44 PROP_CM_NAME,
45 PROP_PROTOCOL,
46 PROP_DISPLAY_NAME,
47 PROP_DISPLAY_NAME_OVERRIDDEN,
48 PROP_READY
51 /* private structure */
52 typedef struct _EmpathyAccountSettingsPriv EmpathyAccountSettingsPriv;
54 struct _EmpathyAccountSettingsPriv
56 gboolean dispose_has_run;
57 EmpathyConnectionManagers *managers;
58 TpAccountManager *account_manager;
60 TpConnectionManager *manager;
62 TpAccount *account;
63 gchar *cm_name;
64 gchar *protocol;
65 gchar *display_name;
66 gchar *icon_name;
67 gboolean display_name_overridden;
68 gboolean ready;
70 GHashTable *parameters;
71 GArray *unset_parameters;
72 GArray *required_params;
74 gulong managers_ready_id;
76 GSimpleAsyncResult *apply_result;
79 static void
80 empathy_account_settings_init (EmpathyAccountSettings *obj)
82 EmpathyAccountSettingsPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE ((obj),
83 EMPATHY_TYPE_ACCOUNT_SETTINGS, EmpathyAccountSettingsPriv);
85 obj->priv = priv;
87 /* allocate any data required by the object here */
88 priv->managers = empathy_connection_managers_dup_singleton ();
89 priv->account_manager = tp_account_manager_dup ();
91 priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
92 g_free, (GDestroyNotify) tp_g_value_slice_free);
94 priv->unset_parameters = g_array_new (TRUE, FALSE, sizeof (gchar *));
97 static void empathy_account_settings_dispose (GObject *object);
98 static void empathy_account_settings_finalize (GObject *object);
99 static void empathy_account_settings_account_ready_cb (GObject *source_object,
100 GAsyncResult *result, gpointer user_data);
101 static void empathy_account_settings_managers_ready_cb (GObject *obj,
102 GParamSpec *pspec, gpointer user_data);
103 static void empathy_account_settings_check_readyness (
104 EmpathyAccountSettings *self);
106 static void
107 empathy_account_settings_set_property (GObject *object,
108 guint prop_id,
109 const GValue *value,
110 GParamSpec *pspec)
112 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (object);
113 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
115 switch (prop_id)
117 case PROP_ACCOUNT:
118 priv->account = g_value_dup_object (value);
119 break;
120 case PROP_CM_NAME:
121 priv->cm_name = g_value_dup_string (value);
122 break;
123 case PROP_PROTOCOL:
124 priv->protocol = g_value_dup_string (value);
125 break;
126 case PROP_DISPLAY_NAME:
127 priv->display_name = g_value_dup_string (value);
128 break;
129 case PROP_DISPLAY_NAME_OVERRIDDEN:
130 priv->display_name_overridden = g_value_get_boolean (value);
131 break;
132 default:
133 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
134 break;
138 static void
139 empathy_account_settings_get_property (GObject *object,
140 guint prop_id,
141 GValue *value,
142 GParamSpec *pspec)
144 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (object);
145 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
147 switch (prop_id)
149 case PROP_ACCOUNT:
150 g_value_set_object (value, priv->account);
151 break;
152 case PROP_CM_NAME:
153 g_value_set_string (value, priv->cm_name);
154 break;
155 case PROP_PROTOCOL:
156 g_value_set_string (value, priv->protocol);
157 break;
158 case PROP_DISPLAY_NAME:
159 g_value_set_string (value, priv->display_name);
160 break;
161 case PROP_DISPLAY_NAME_OVERRIDDEN:
162 g_value_set_boolean (value, priv->display_name_overridden);
163 break;
164 case PROP_READY:
165 g_value_set_boolean (value, priv->ready);
166 break;
167 default:
168 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
169 break;
173 static void
174 empathy_account_settings_constructed (GObject *object)
176 EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object);
177 EmpathyAccountSettingsPriv *priv = GET_PRIV (self);
179 if (priv->account != NULL)
181 g_free (priv->cm_name);
182 g_free (priv->protocol);
184 priv->cm_name =
185 g_strdup (tp_account_get_connection_manager (priv->account));
186 priv->protocol =
187 g_strdup (tp_account_get_protocol (priv->account));
188 priv->icon_name = g_strdup
189 (tp_account_get_icon_name (priv->account));
191 else
193 priv->icon_name = empathy_protocol_icon_name (priv->protocol);
196 g_assert (priv->cm_name != NULL && priv->protocol != NULL);
198 empathy_account_settings_check_readyness (self);
200 if (!priv->ready)
202 tp_account_prepare_async (priv->account, NULL,
203 empathy_account_settings_account_ready_cb, self);
204 tp_g_signal_connect_object (priv->managers, "notify::ready",
205 G_CALLBACK (empathy_account_settings_managers_ready_cb), object, 0);
208 if (G_OBJECT_CLASS (
209 empathy_account_settings_parent_class)->constructed != NULL)
210 G_OBJECT_CLASS (
211 empathy_account_settings_parent_class)->constructed (object);
215 static void
216 empathy_account_settings_class_init (
217 EmpathyAccountSettingsClass *empathy_account_settings_class)
219 GObjectClass *object_class = G_OBJECT_CLASS (empathy_account_settings_class);
221 g_type_class_add_private (empathy_account_settings_class, sizeof
222 (EmpathyAccountSettingsPriv));
224 object_class->dispose = empathy_account_settings_dispose;
225 object_class->finalize = empathy_account_settings_finalize;
226 object_class->set_property = empathy_account_settings_set_property;
227 object_class->get_property = empathy_account_settings_get_property;
228 object_class->constructed = empathy_account_settings_constructed;
230 g_object_class_install_property (object_class, PROP_ACCOUNT,
231 g_param_spec_object ("account",
232 "Account",
233 "The TpAccount backing these settings",
234 TP_TYPE_ACCOUNT,
235 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
237 g_object_class_install_property (object_class, PROP_CM_NAME,
238 g_param_spec_string ("connection-manager",
239 "connection-manager",
240 "The name of the connection manager this account uses",
241 NULL,
242 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
244 g_object_class_install_property (object_class, PROP_PROTOCOL,
245 g_param_spec_string ("protocol",
246 "Protocol",
247 "The name of the protocol this account uses",
248 NULL,
249 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
251 g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
252 g_param_spec_string ("display-name",
253 "display-name",
254 "The display name account these settings belong to",
255 NULL,
256 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
258 g_object_class_install_property (object_class, PROP_DISPLAY_NAME_OVERRIDDEN,
259 g_param_spec_boolean ("display-name-overridden",
260 "display-name-overridden",
261 "Whether the display name for this account has been manually "
262 "overridden",
263 FALSE,
264 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
266 g_object_class_install_property (object_class, PROP_READY,
267 g_param_spec_boolean ("ready",
268 "Ready",
269 "Whether this account is ready to be used",
270 FALSE,
271 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
274 static void
275 empathy_account_settings_dispose (GObject *object)
277 EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object);
278 EmpathyAccountSettingsPriv *priv = GET_PRIV (self);
280 if (priv->dispose_has_run)
281 return;
283 priv->dispose_has_run = TRUE;
285 if (priv->managers_ready_id != 0)
286 g_signal_handler_disconnect (priv->managers, priv->managers_ready_id);
287 priv->managers_ready_id = 0;
289 if (priv->managers != NULL)
290 g_object_unref (priv->managers);
291 priv->managers = NULL;
293 if (priv->manager != NULL)
294 g_object_unref (priv->manager);
295 priv->manager = NULL;
297 if (priv->account_manager != NULL)
298 g_object_unref (priv->account_manager);
299 priv->account_manager = NULL;
301 if (priv->account != NULL)
302 g_object_unref (priv->account);
303 priv->account = NULL;
305 /* release any references held by the object here */
306 if (G_OBJECT_CLASS (empathy_account_settings_parent_class)->dispose)
307 G_OBJECT_CLASS (empathy_account_settings_parent_class)->dispose (object);
310 static void
311 empathy_account_settings_free_unset_parameters (
312 EmpathyAccountSettings *settings)
314 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
315 guint i;
317 for (i = 0 ; i < priv->unset_parameters->len; i++)
318 g_free (g_array_index (priv->unset_parameters, gchar *, i));
320 g_array_set_size (priv->unset_parameters, 0);
323 static void
324 empathy_account_settings_finalize (GObject *object)
326 EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object);
327 EmpathyAccountSettingsPriv *priv = GET_PRIV (self);
329 /* free any data held directly by the object here */
330 g_free (priv->cm_name);
331 g_free (priv->protocol);
332 g_free (priv->display_name);
333 g_free (priv->icon_name);
335 if (priv->required_params != NULL)
336 g_array_free (priv->required_params, TRUE);
338 g_hash_table_destroy (priv->parameters);
340 empathy_account_settings_free_unset_parameters (self);
341 g_array_free (priv->unset_parameters, TRUE);
343 G_OBJECT_CLASS (empathy_account_settings_parent_class)->finalize (object);
346 static void
347 empathy_account_settings_check_readyness (EmpathyAccountSettings *self)
349 EmpathyAccountSettingsPriv *priv = GET_PRIV (self);
350 const TpConnectionManagerProtocol *tp_protocol;
352 if (priv->ready)
353 return;
355 if (priv->account != NULL
356 && !tp_account_is_prepared (priv->account, TP_ACCOUNT_FEATURE_CORE))
357 return;
359 if (!empathy_connection_managers_is_ready (priv->managers))
360 return;
362 priv->manager = empathy_connection_managers_get_cm (
363 priv->managers, priv->cm_name);
365 if (priv->manager == NULL)
366 return;
368 if (priv->account != NULL)
370 g_free (priv->display_name);
371 priv->display_name =
372 g_strdup (tp_account_get_display_name (priv->account));
374 g_free (priv->icon_name);
375 priv->icon_name =
376 g_strdup (tp_account_get_icon_name (priv->account));
379 tp_protocol = tp_connection_manager_get_protocol (priv->manager,
380 priv->protocol);
382 if (tp_protocol == NULL)
384 priv->manager = NULL;
385 return;
388 if (priv->required_params == NULL)
390 TpConnectionManagerParam *cur;
391 char *val;
393 priv->required_params = g_array_new (TRUE, FALSE, sizeof (gchar *));
395 for (cur = tp_protocol->params; cur->name != NULL; cur++)
397 if (tp_connection_manager_param_is_required (cur))
399 val = g_strdup (cur->name);
400 g_array_append_val (priv->required_params, val);
405 g_object_ref (priv->manager);
407 priv->ready = TRUE;
408 g_object_notify (G_OBJECT (self), "ready");
411 static void
412 empathy_account_settings_account_ready_cb (GObject *source_object,
413 GAsyncResult *result,
414 gpointer user_data)
416 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data);
417 TpAccount *account = TP_ACCOUNT (source_object);
418 GError *error = NULL;
420 if (!tp_account_prepare_finish (account, result, &error))
422 DEBUG ("Failed to prepare account: %s", error->message);
423 g_error_free (error);
424 return;
427 empathy_account_settings_check_readyness (settings);
430 static void
431 empathy_account_settings_managers_ready_cb (GObject *object,
432 GParamSpec *pspec,
433 gpointer user_data)
435 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data);
437 empathy_account_settings_check_readyness (settings);
440 EmpathyAccountSettings *
441 empathy_account_settings_new (const gchar *connection_manager,
442 const gchar *protocol,
443 const char *display_name)
445 return g_object_new (EMPATHY_TYPE_ACCOUNT_SETTINGS,
446 "connection-manager", connection_manager,
447 "protocol", protocol,
448 "display-name", display_name,
449 NULL);
452 EmpathyAccountSettings *
453 empathy_account_settings_new_for_account (TpAccount *account)
455 return g_object_new (EMPATHY_TYPE_ACCOUNT_SETTINGS,
456 "account", account,
457 NULL);
460 TpConnectionManagerParam *
461 empathy_account_settings_get_tp_params (EmpathyAccountSettings *settings)
463 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
464 const TpConnectionManagerProtocol *tp_protocol;
466 g_return_val_if_fail (priv->manager != NULL, NULL);
467 g_return_val_if_fail (priv->protocol != NULL, NULL);
469 tp_protocol = tp_connection_manager_get_protocol (priv->manager,
470 priv->protocol);
471 if (tp_protocol == NULL)
473 DEBUG ("Can't retrieve TpConnectionManagerProtocol for protocol '%s'",
474 priv->protocol);
475 return NULL;
478 return tp_protocol->params;
481 gboolean
482 empathy_account_settings_is_ready (EmpathyAccountSettings *settings)
484 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
486 return priv->ready;
489 const gchar *
490 empathy_account_settings_get_cm (EmpathyAccountSettings *settings)
492 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
494 return priv->cm_name;
497 const gchar *
498 empathy_account_settings_get_protocol (EmpathyAccountSettings *settings)
500 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
502 return priv->protocol;
505 gchar *
506 empathy_account_settings_get_icon_name (EmpathyAccountSettings *settings)
508 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
510 return priv->icon_name;
513 const gchar *
514 empathy_account_settings_get_display_name (EmpathyAccountSettings *settings)
516 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
518 return priv->display_name;
521 TpAccount *
522 empathy_account_settings_get_account (EmpathyAccountSettings *settings)
524 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
526 return priv->account;
529 static gboolean
530 empathy_account_settings_is_unset (EmpathyAccountSettings *settings,
531 const gchar *param)
533 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
534 GArray *a;
535 guint i;
537 a = priv->unset_parameters;
539 for (i = 0; i < a->len; i++)
541 if (!tp_strdiff (g_array_index (a, gchar *, i), param))
542 return TRUE;
545 return FALSE;
548 static TpConnectionManagerParam *
549 empathy_account_settings_get_tp_param (EmpathyAccountSettings *settings,
550 const gchar *param)
552 TpConnectionManagerParam *tp_params =
553 empathy_account_settings_get_tp_params (settings);
554 TpConnectionManagerParam *p;
556 for (p = tp_params; p != NULL && p->name != NULL; p++)
558 if (tp_strdiff (p->name, param))
559 continue;
561 return p;
564 return NULL;
567 static void
568 account_settings_remove_from_unset (EmpathyAccountSettings *settings,
569 const gchar *param)
571 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
572 guint idx;
573 gchar *val;
575 for (idx = 0; idx < priv->unset_parameters->len; idx++)
577 val = g_array_index (priv->unset_parameters, gchar *, idx);
579 if (!tp_strdiff (val, param))
581 priv->unset_parameters =
582 g_array_remove_index (priv->unset_parameters, idx);
583 g_free (val);
585 break;
590 const GValue *
591 empathy_account_settings_get_default (EmpathyAccountSettings *settings,
592 const gchar *param)
594 TpConnectionManagerParam *p;
596 p = empathy_account_settings_get_tp_param (settings, param);
598 if (p == NULL || !(p->flags & TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT))
599 return NULL;
601 return &(p->default_value);
604 const gchar *
605 empathy_account_settings_get_dbus_signature (EmpathyAccountSettings *settings,
606 const gchar *param)
608 TpConnectionManagerParam *p;
610 p = empathy_account_settings_get_tp_param (settings, param);
612 if (p == NULL)
613 return NULL;
615 return p->dbus_signature;
618 const GValue *
619 empathy_account_settings_get (EmpathyAccountSettings *settings,
620 const gchar *param)
622 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
623 const GValue *result = NULL;
625 /* Lookup the update parameters we set */
626 result = tp_asv_lookup (priv->parameters, param);
627 if (result != NULL)
628 return result;
630 /* If the parameters isn't unset use the accounts setting if any */
631 if (priv->account != NULL
632 && !empathy_account_settings_is_unset (settings, param))
634 const GHashTable *parameters;
636 parameters = tp_account_get_parameters (priv->account);
637 result = tp_asv_lookup (parameters, param);
639 if (result != NULL)
640 return result;
643 /* fallback to the default */
644 return empathy_account_settings_get_default (settings, param);
647 void
648 empathy_account_settings_unset (EmpathyAccountSettings *settings,
649 const gchar *param)
651 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
652 gchar *v;
653 if (empathy_account_settings_is_unset (settings, param))
654 return;
656 v = g_strdup (param);
658 g_array_append_val (priv->unset_parameters, v);
659 g_hash_table_remove (priv->parameters, param);
662 void
663 empathy_account_settings_discard_changes (EmpathyAccountSettings *settings)
665 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
667 g_hash_table_remove_all (priv->parameters);
668 empathy_account_settings_free_unset_parameters (settings);
671 const gchar *
672 empathy_account_settings_get_string (EmpathyAccountSettings *settings,
673 const gchar *param)
675 const GValue *v;
677 v = empathy_account_settings_get (settings, param);
679 if (v == NULL || !G_VALUE_HOLDS_STRING (v))
680 return NULL;
682 return g_value_get_string (v);
685 gint32
686 empathy_account_settings_get_int32 (EmpathyAccountSettings *settings,
687 const gchar *param)
689 const GValue *v;
690 gint32 ret = 0;
692 v = empathy_account_settings_get (settings, param);
694 if (v == NULL)
695 return 0;
697 switch G_VALUE_TYPE (v)
699 case G_TYPE_UCHAR:
700 ret = g_value_get_uchar (v);
701 break;
702 case G_TYPE_INT:
703 ret = g_value_get_int (v);
704 break;
705 case G_TYPE_UINT:
706 ret = CLAMP (g_value_get_uint (v), (guint) G_MININT32,
707 G_MAXINT32);
708 break;
709 case G_TYPE_INT64:
710 ret = CLAMP (g_value_get_int64 (v), G_MININT32, G_MAXINT32);
711 break;
712 case G_TYPE_UINT64:
713 ret = CLAMP (g_value_get_uint64 (v), (guint64) G_MININT32,
714 G_MAXINT32);
715 break;
716 default:
717 ret = 0;
718 break;
721 return ret;
724 gint64
725 empathy_account_settings_get_int64 (EmpathyAccountSettings *settings,
726 const gchar *param)
728 const GValue *v;
729 gint64 ret = 0;
731 v = empathy_account_settings_get (settings, param);
732 if (v == NULL)
733 return 0;
735 switch G_VALUE_TYPE (v)
737 case G_TYPE_UCHAR:
738 ret = g_value_get_uchar (v);
739 break;
740 case G_TYPE_INT:
741 ret = g_value_get_int (v);
742 break;
743 case G_TYPE_UINT:
744 ret = g_value_get_uint (v);
745 break;
746 case G_TYPE_INT64:
747 ret = g_value_get_int64 (v);
748 break;
749 case G_TYPE_UINT64:
750 ret = CLAMP (g_value_get_uint64 (v), (guint64) G_MININT64, G_MAXINT64);
751 break;
752 default:
753 ret = 0;
754 break;
757 return ret;
760 guint32
761 empathy_account_settings_get_uint32 (EmpathyAccountSettings *settings,
762 const gchar *param)
764 const GValue *v;
765 guint32 ret;
767 v = empathy_account_settings_get (settings, param);
768 if (v == NULL)
769 return 0;
771 switch G_VALUE_TYPE (v)
773 case G_TYPE_UCHAR:
774 ret = g_value_get_uchar (v);
775 break;
776 case G_TYPE_INT:
777 ret = MAX (0, g_value_get_int (v));
778 break;
779 case G_TYPE_UINT:
780 ret = g_value_get_uint (v);
781 break;
782 case G_TYPE_INT64:
783 ret = CLAMP (g_value_get_int64 (v), 0, G_MAXUINT32);
784 break;
785 case G_TYPE_UINT64:
786 ret = MIN (g_value_get_uint64 (v), G_MAXUINT32);
787 break;
788 default:
789 ret = 0;
790 break;
793 return ret;
796 guint64
797 empathy_account_settings_get_uint64 (EmpathyAccountSettings *settings,
798 const gchar *param)
800 const GValue *v;
801 guint64 ret = 0;
803 v = empathy_account_settings_get (settings, param);
805 if (v == NULL || !G_VALUE_HOLDS_INT (v))
806 return 0;
808 switch G_VALUE_TYPE (v)
810 case G_TYPE_UCHAR:
811 ret = g_value_get_uchar (v);
812 break;
813 case G_TYPE_INT:
814 ret = MAX (0, g_value_get_int (v));
815 break;
816 case G_TYPE_UINT:
817 ret = g_value_get_uint (v);
818 break;
819 case G_TYPE_INT64:
820 ret = MAX (0, g_value_get_int64 (v));
821 break;
822 case G_TYPE_UINT64:
823 ret = g_value_get_uint64 (v);
824 break;
825 default:
826 ret = 0;
827 break;
830 return ret;
833 gboolean
834 empathy_account_settings_get_boolean (EmpathyAccountSettings *settings,
835 const gchar *param)
837 const GValue *v;
839 v = empathy_account_settings_get (settings, param);
841 if (v == NULL || !G_VALUE_HOLDS_BOOLEAN (v))
842 return FALSE;
844 return g_value_get_boolean (v);
847 void
848 empathy_account_settings_set_string (EmpathyAccountSettings *settings,
849 const gchar *param,
850 const gchar *value)
852 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
854 tp_asv_set_string (priv->parameters, g_strdup (param), value);
856 account_settings_remove_from_unset (settings, param);
859 void
860 empathy_account_settings_set_int32 (EmpathyAccountSettings *settings,
861 const gchar *param,
862 gint32 value)
864 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
866 tp_asv_set_int32 (priv->parameters, g_strdup (param), value);
868 account_settings_remove_from_unset (settings, param);
871 void
872 empathy_account_settings_set_int64 (EmpathyAccountSettings *settings,
873 const gchar *param,
874 gint64 value)
876 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
878 tp_asv_set_int64 (priv->parameters, g_strdup (param), value);
880 account_settings_remove_from_unset (settings, param);
883 void
884 empathy_account_settings_set_uint32 (EmpathyAccountSettings *settings,
885 const gchar *param,
886 guint32 value)
888 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
890 tp_asv_set_uint32 (priv->parameters, g_strdup (param), value);
892 account_settings_remove_from_unset (settings, param);
895 void
896 empathy_account_settings_set_uint64 (EmpathyAccountSettings *settings,
897 const gchar *param,
898 guint64 value)
900 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
902 tp_asv_set_uint64 (priv->parameters, g_strdup (param), value);
904 account_settings_remove_from_unset (settings, param);
907 void
908 empathy_account_settings_set_boolean (EmpathyAccountSettings *settings,
909 const gchar *param,
910 gboolean value)
912 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
914 tp_asv_set_boolean (priv->parameters, g_strdup (param), value);
916 account_settings_remove_from_unset (settings, param);
919 static void
920 account_settings_display_name_set_cb (GObject *src,
921 GAsyncResult *res,
922 gpointer user_data)
924 GError *error = NULL;
925 TpAccount *account = TP_ACCOUNT (src);
926 GSimpleAsyncResult *set_result = user_data;
928 tp_account_set_display_name_finish (account, res, &error);
930 if (error != NULL)
932 g_simple_async_result_set_from_error (set_result, error);
933 g_error_free (error);
936 g_simple_async_result_complete (set_result);
937 g_object_unref (set_result);
940 void
941 empathy_account_settings_set_display_name_async (
942 EmpathyAccountSettings *settings,
943 const gchar *name,
944 GAsyncReadyCallback callback,
945 gpointer user_data)
947 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
948 GSimpleAsyncResult *result;
950 result = g_simple_async_result_new (G_OBJECT (settings),
951 callback, user_data, empathy_account_settings_set_display_name_finish);
953 if (!tp_strdiff (name, priv->display_name))
955 /* Nothing to do */
956 g_simple_async_result_complete_in_idle (result);
957 return;
960 if (priv->account == NULL)
962 if (priv->display_name != NULL)
963 g_free (priv->display_name);
965 priv->display_name = g_strdup (name);
967 g_simple_async_result_complete_in_idle (result);
969 return;
972 tp_account_set_display_name_async (priv->account, name,
973 account_settings_display_name_set_cb, result);
976 gboolean
977 empathy_account_settings_set_display_name_finish (
978 EmpathyAccountSettings *settings,
979 GAsyncResult *result,
980 GError **error)
982 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
983 error))
984 return FALSE;
986 g_return_val_if_fail (g_simple_async_result_is_valid (result,
987 G_OBJECT (settings), empathy_account_settings_set_display_name_finish),
988 FALSE);
990 return TRUE;
993 static void
994 account_settings_icon_name_set_cb (GObject *src,
995 GAsyncResult *res,
996 gpointer user_data)
998 GError *error = NULL;
999 TpAccount *account = TP_ACCOUNT (src);
1000 GSimpleAsyncResult *set_result = user_data;
1002 tp_account_set_icon_name_finish (account, res, &error);
1004 if (error != NULL)
1006 g_simple_async_result_set_from_error (set_result, error);
1007 g_error_free (error);
1010 g_simple_async_result_complete (set_result);
1011 g_object_unref (set_result);
1014 void
1015 empathy_account_settings_set_icon_name_async (
1016 EmpathyAccountSettings *settings,
1017 const gchar *name,
1018 GAsyncReadyCallback callback,
1019 gpointer user_data)
1021 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
1022 GSimpleAsyncResult *result;
1024 result = g_simple_async_result_new (G_OBJECT (settings),
1025 callback, user_data, empathy_account_settings_set_icon_name_finish);
1027 if (priv->account == NULL)
1029 if (priv->icon_name != NULL)
1030 g_free (priv->icon_name);
1032 priv->icon_name = g_strdup (name);
1034 g_simple_async_result_complete_in_idle (result);
1036 return;
1039 tp_account_set_icon_name_async (priv->account, name,
1040 account_settings_icon_name_set_cb, result);
1043 gboolean
1044 empathy_account_settings_set_icon_name_finish (
1045 EmpathyAccountSettings *settings,
1046 GAsyncResult *result,
1047 GError **error)
1049 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
1050 error))
1051 return FALSE;
1053 g_return_val_if_fail (g_simple_async_result_is_valid (result,
1054 G_OBJECT (settings), empathy_account_settings_set_icon_name_finish),
1055 FALSE);
1057 return TRUE;
1060 static void
1061 empathy_account_settings_account_updated (GObject *source,
1062 GAsyncResult *result,
1063 gpointer user_data)
1065 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data);
1066 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
1067 GSimpleAsyncResult *r;
1068 GError *error = NULL;
1070 if (!tp_account_update_parameters_finish (TP_ACCOUNT (source),
1071 result, NULL, &error))
1073 g_simple_async_result_set_from_error (priv->apply_result, error);
1074 g_error_free (error);
1076 else
1078 empathy_account_settings_discard_changes (settings);
1081 r = priv->apply_result;
1082 priv->apply_result = NULL;
1084 g_simple_async_result_complete (r);
1085 g_object_unref (r);
1088 static void
1089 empathy_account_settings_created_cb (GObject *source,
1090 GAsyncResult *result,
1091 gpointer user_data)
1093 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data);
1094 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
1095 TpAccount *account;
1096 GError *error = NULL;
1097 GSimpleAsyncResult *r;
1099 account = tp_account_manager_create_account_finish (
1100 TP_ACCOUNT_MANAGER (source), result, &error);
1102 if (account == NULL)
1104 g_simple_async_result_set_from_error (priv->apply_result, error);
1106 else
1108 priv->account = g_object_ref (account);
1109 empathy_account_settings_discard_changes (settings);
1112 r = priv->apply_result;
1113 priv->apply_result = NULL;
1115 g_simple_async_result_complete (r);
1116 g_object_unref (r);
1120 static void
1121 empathy_account_settings_do_create_account (EmpathyAccountSettings *settings)
1123 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
1124 GHashTable *properties;
1125 TpConnectionPresenceType type;
1126 gchar *status;
1127 gchar *message;
1128 EmpathyIdle *idle;
1130 properties = tp_asv_new (NULL, NULL);
1132 idle = empathy_idle_dup_singleton ();
1133 type = empathy_idle_get_requested_presence (idle, &status, &message);
1134 g_object_unref (idle);
1136 if (type != TP_CONNECTION_PRESENCE_TYPE_UNSET)
1138 /* Create the account with the requested presence the same as the current
1139 * global requested presence, but don't enable it */
1140 GValueArray *presence;
1141 GValue vtype = { 0, };
1142 GValue vstatus = { 0, };
1143 GValue vmessage = { 0, };
1145 presence = g_value_array_new (3);
1147 g_value_init (&vtype, G_TYPE_UINT);
1148 g_value_set_uint (&vtype, type);
1149 g_value_array_append (presence, &vtype);
1151 g_value_init (&vstatus, G_TYPE_STRING);
1152 g_value_take_string (&vstatus, status);
1153 g_value_array_append (presence, &vstatus);
1155 g_value_init (&vmessage, G_TYPE_STRING);
1156 g_value_take_string (&vmessage, message);
1157 g_value_array_append (presence, &vmessage);
1159 tp_asv_take_boxed (properties, TP_IFACE_ACCOUNT ".RequestedPresence",
1160 TP_STRUCT_TYPE_SIMPLE_PRESENCE, presence);
1163 tp_asv_set_string (properties, TP_IFACE_ACCOUNT ".Icon",
1164 priv->icon_name);
1166 tp_account_manager_create_account_async (priv->account_manager,
1167 priv->cm_name, priv->protocol, priv->display_name,
1168 priv->parameters, properties,
1169 empathy_account_settings_created_cb,
1170 settings);
1172 g_hash_table_unref (properties);
1175 static void
1176 empathy_account_settings_manager_ready_cb (GObject *source_object,
1177 GAsyncResult *result,
1178 gpointer user_data)
1180 EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data);
1181 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
1182 TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
1183 GError *error = NULL;
1185 if (!tp_account_manager_prepare_finish (account_manager, result, &error))
1187 DEBUG ("Failed to prepare account manager: %s", error->message);
1188 g_error_free (error);
1189 return;
1192 g_assert (priv->apply_result != NULL && priv->account == NULL);
1193 empathy_account_settings_do_create_account (settings);
1196 void
1197 empathy_account_settings_apply_async (EmpathyAccountSettings *settings,
1198 GAsyncReadyCallback callback,
1199 gpointer user_data)
1201 EmpathyAccountSettingsPriv *priv = GET_PRIV (settings);
1203 if (priv->apply_result != NULL)
1205 g_simple_async_report_error_in_idle (G_OBJECT (settings),
1206 callback, user_data,
1207 G_IO_ERROR, G_IO_ERROR_PENDING, "Applying already in progress");
1208 return;
1211 priv->apply_result = g_simple_async_result_new (G_OBJECT (settings),
1212 callback, user_data, empathy_account_settings_apply_finish);
1214 if (priv->account == NULL)
1216 tp_account_manager_prepare_async (priv->account_manager, NULL,
1217 empathy_account_settings_manager_ready_cb, settings);
1219 else
1221 tp_account_update_parameters_async (priv->account,
1222 priv->parameters, (const gchar **)priv->unset_parameters->data,
1223 empathy_account_settings_account_updated, settings);
1227 gboolean
1228 empathy_account_settings_apply_finish (EmpathyAccountSettings *settings,
1229 GAsyncResult *result,
1230 GError **error)
1232 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
1233 error))
1234 return FALSE;
1236 g_return_val_if_fail (g_simple_async_result_is_valid (result,
1237 G_OBJECT (settings), empathy_account_settings_apply_finish), FALSE);
1239 return TRUE;
1242 gboolean
1243 empathy_account_settings_has_account (EmpathyAccountSettings *settings,
1244 TpAccount *account)
1246 EmpathyAccountSettingsPriv *priv;
1247 const gchar *account_path;
1248 const gchar *priv_account_path;
1250 g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE);
1251 g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
1253 priv = GET_PRIV (settings);
1255 if (priv->account == NULL)
1256 return FALSE;
1258 account_path = tp_proxy_get_object_path (TP_PROXY (account));
1259 priv_account_path = tp_proxy_get_object_path (TP_PROXY (priv->account));
1261 return (!tp_strdiff (account_path, priv_account_path));
1264 gboolean
1265 empathy_account_settings_is_valid (EmpathyAccountSettings *settings)
1267 EmpathyAccountSettingsPriv *priv;
1268 guint idx;
1269 gchar *current;
1270 gboolean missed = FALSE;
1272 g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE);
1274 priv = GET_PRIV (settings);
1276 for (idx = 0; idx < priv->required_params->len; idx++)
1278 current = g_array_index (priv->required_params, gchar *, idx);
1280 /* first, look if it's set in our own parameters */
1281 if (tp_asv_lookup (priv->parameters, current))
1282 continue;
1284 /* if we did not unset the parameter, look if it's in the account */
1285 if (priv->account != NULL &&
1286 !empathy_account_settings_is_unset (settings, current))
1288 const GHashTable *account_params;
1290 account_params = tp_account_get_parameters (priv->account);
1291 if (tp_asv_lookup (account_params, current))
1292 continue;
1295 missed = TRUE;
1296 break;
1299 return !missed;
1302 const TpConnectionManagerProtocol *
1303 empathy_account_settings_get_tp_protocol (EmpathyAccountSettings *self)
1305 EmpathyAccountSettingsPriv *priv = GET_PRIV (self);
1307 return tp_connection_manager_get_protocol (priv->manager, priv->protocol);