[empathy: 1/14] Implement EmpathyAccount



commit e0b356e25084d47d8953cc7c15fae4a97f62d047
Author: Sjoerd Simons <sjoerd simons collabora co uk>
Date:   Fri Jun 26 14:17:55 2009 +0100

    Implement EmpathyAccount
    
    Refactor EmpathyAccountManager and introduce a seperate EmpathyAccount
    object, which wraps McAccount. When moving to MC5, EmpathyAccount will wrap the
    Telepathy.Account interface. Fixes #587508

 libempathy/Makefile.am               |    3 +
 libempathy/empathy-account-manager.c |  579 ++++++++++++++--------------------
 libempathy/empathy-account-manager.h |   19 +-
 libempathy/empathy-account-priv.h    |   44 +++
 libempathy/empathy-account.c         |  572 +++++++++++++++++++++++++++++++++
 libempathy/empathy-account.h         |   94 ++++++
 6 files changed, 956 insertions(+), 355 deletions(-)
---
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am
index 2877dc6..2767154 100644
--- a/libempathy/Makefile.am
+++ b/libempathy/Makefile.am
@@ -24,6 +24,8 @@ BUILT_SOURCES = 					\
 lib_LTLIBRARIES = libempathy.la
 
 libempathy_la_SOURCES =					\
+	empathy-account.c			\
+	empathy-account-priv.h			\
 	empathy-account-manager.c			\
 	empathy-chatroom.c				\
 	empathy-chatroom-manager.c			\
@@ -74,6 +76,7 @@ libempathy_la_LDFLAGS =		\
        -export-symbols-regex ^empathy_
 
 libempathy_headers =				\
+	empathy-account.h		\
 	empathy-account-manager.h		\
 	empathy-chatroom.h			\
 	empathy-chatroom-manager.h		\
diff --git a/libempathy/empathy-account-manager.c b/libempathy/empathy-account-manager.c
index ff9fd25..a290e9f 100644
--- a/libempathy/empathy-account-manager.c
+++ b/libempathy/empathy-account-manager.c
@@ -16,6 +16,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * Authors: Cosimo Cecchi <cosimo cecchi collabora co uk>
+ *          Sjoerd Simons <sjoerd simons collabora co uk>
  */
 
 #include "config.h"
@@ -23,6 +24,7 @@
 #include <libmissioncontrol/mc-account-monitor.h>
 
 #include "empathy-account-manager.h"
+#include "empathy-account-priv.h"
 #include "empathy-marshal.h"
 #include "empathy-utils.h"
 
@@ -35,22 +37,12 @@ typedef struct {
   McAccountMonitor *monitor;
   MissionControl   *mc;
 
-  GHashTable       *accounts; /* McAccount -> AccountData */
-  GHashTable       *connections; /* TpConnection -> McAccount */
+  GHashTable       *accounts; /* unique name -> EmpathyAccount */
   int               connected;
   int               connecting;
   gboolean          dispose_run;
 } EmpathyAccountManagerPriv;
 
-typedef struct {
-  TpConnection *connection;
-  TpConnectionPresenceType presence;
-  TpConnectionStatus status;
-  gboolean is_enabled;
-
-  guint source_id;
-} AccountData;
-
 enum {
   ACCOUNT_CREATED,
   ACCOUNT_DELETED,
@@ -68,122 +60,155 @@ static EmpathyAccountManager *manager_singleton = NULL;
 
 G_DEFINE_TYPE (EmpathyAccountManager, empathy_account_manager, G_TYPE_OBJECT);
 
-static AccountData *
-account_data_new (McPresence presence,
-                  TpConnectionStatus status,
-                  gboolean is_enabled)
+static TpConnectionPresenceType
+mc_presence_to_tp_presence (McPresence presence)
 {
-  AccountData *retval;
-
-  retval = g_slice_new0 (AccountData);
-  retval->presence = presence;
-  retval->status = status;
-  retval->is_enabled = is_enabled;
-  retval->source_id = 0;
-
-  return retval;
+  switch (presence)
+    {
+      case MC_PRESENCE_OFFLINE:
+        return TP_CONNECTION_PRESENCE_TYPE_OFFLINE;
+      case MC_PRESENCE_AVAILABLE:
+        return TP_CONNECTION_PRESENCE_TYPE_AVAILABLE;
+      case MC_PRESENCE_AWAY:
+        return TP_CONNECTION_PRESENCE_TYPE_AWAY;
+      case MC_PRESENCE_EXTENDED_AWAY:
+        return TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY;
+      case MC_PRESENCE_HIDDEN:
+        return TP_CONNECTION_PRESENCE_TYPE_HIDDEN;
+      case MC_PRESENCE_DO_NOT_DISTURB:
+        return TP_CONNECTION_PRESENCE_TYPE_BUSY;
+      default:
+        return TP_CONNECTION_PRESENCE_TYPE_UNSET;
+    }
 }
 
-static AccountData *
-account_data_new_default (MissionControl *mc,
-                          McAccount *account)
+static void
+emp_account_connection_cb (EmpathyAccount *account,
+  GParamSpec *spec,
+  gpointer manager)
 {
-  McPresence actual_p;
-  TpConnectionStatus actual_c;
-  GError *err = NULL;
-
-  actual_p = mission_control_get_presence_actual (mc, &err);
-  if (err != NULL)
-    {
-      actual_p = MC_PRESENCE_UNSET;
-      g_clear_error (&err);
-    }
+  TpConnection *connection = empathy_account_get_connection (account);
 
-  actual_c = mission_control_get_connection_status (mc, account, &err);
+  DEBUG ("Signalling connection %p of account %s",
+      connection, empathy_account_get_unique_name (account));
 
-  if (err != NULL)
-    {
-      actual_c = TP_CONNECTION_STATUS_DISCONNECTED;
-      g_error_free (err);
-    }
 
-  return account_data_new (actual_p, actual_c, mc_account_is_enabled (account));
+  if (connection != NULL)
+    g_signal_emit (manager, signals[NEW_CONNECTION], 0, connection);
 }
 
 static void
-account_data_free (AccountData *data)
+emp_account_status_changed_cb (EmpathyAccount *account,
+  TpConnectionStatus old,
+  TpConnectionStatus new,
+  TpConnectionStatusReason reason,
+  gpointer user_data)
 {
-  if (data->source_id > 0)
+  EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data);
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+
+  switch (old)
     {
-      g_source_remove (data->source_id);
-      data->source_id = 0;
+      case TP_CONNECTION_STATUS_CONNECTING:
+        priv->connecting--;
+        break;
+      case TP_CONNECTION_STATUS_CONNECTED:
+        priv->connected--;
+        break;
+      default:
+        break;
     }
-  if (data->connection != NULL)
+
+  switch (new)
     {
-      g_object_unref (data->connection);
-      data->connection = NULL;
+      case TP_CONNECTION_STATUS_CONNECTING:
+        priv->connecting++;
+        break;
+      case TP_CONNECTION_STATUS_CONNECTED:
+        priv->connected++;
+        break;
+      default:
+        break;
     }
 
-  g_slice_free (AccountData, data);
+  g_signal_emit (manager, signals[ACCOUNT_CONNECTION_CHANGED], 0,
+    account, reason, new, old);
 }
 
 static void
-connection_invalidated_cb (TpProxy *connection,
-                           guint    domain,
-                           gint     code,
-                           gchar   *message,
-                           EmpathyAccountManager *manager)
+emp_account_presence_changed_cb (EmpathyAccount *account,
+  TpConnectionPresenceType old,
+  TpConnectionPresenceType new,
+  gpointer user_data)
 {
-  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
-  McAccount *account;
-  AccountData *data;
+  EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data);
+  g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0,
+    account, new, old);
+}
 
-  DEBUG ("Message: %s", message);
+static EmpathyAccount *
+create_account (EmpathyAccountManager *manager,
+  const gchar *account_name,
+  McAccount *mc_account)
+{
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+  EmpathyAccount *account;
+  TpConnectionStatus status;
+  TpConnectionPresenceType presence;
+  McPresence mc_presence;
+  TpConnection *connection;
+  GError *error = NULL;
 
-  account = g_hash_table_lookup (priv->connections, connection);
-  g_assert (account != NULL);
+  if ((account = g_hash_table_lookup (priv->accounts, account_name)) != NULL)
+    return account;
 
-  data = g_hash_table_lookup (priv->accounts, account);
-  g_assert (data != NULL);
+  account = _empathy_account_new (mc_account);
+  g_hash_table_insert (priv->accounts, g_strdup (account_name),
+    account);
 
-  g_object_unref (data->connection);
-  data->connection = NULL;
+  _empathy_account_set_enabled (account,
+      mc_account_is_enabled (mc_account));
 
-  g_hash_table_remove (priv->connections, connection);
-}
+  g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
 
-static void
-connection_ready_cb (TpConnection *connection,
-                     const GError *error,
-                     gpointer manager)
-{
-  /* Errors will be handled in invalidated callback */
-  if (error != NULL)
-    return;
+  g_signal_connect (account, "notify::connection",
+    G_CALLBACK (emp_account_connection_cb), manager);
 
-  g_signal_emit (manager, signals[NEW_CONNECTION], 0, connection);
-}
+  connection = mission_control_get_tpconnection (priv->mc,
+    mc_account, NULL);
+  _empathy_account_set_connection (account, connection);
 
-static void
-account_manager_update_connection (EmpathyAccountManager *manager,
-                                   AccountData *data,
-                                   McAccount *account)
-{
-  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+  status = mission_control_get_connection_status (priv->mc,
+     mc_account, &error);
 
-  if (data->connection)
-    return;
+  if (error != NULL)
+    {
+      status = TP_CONNECTION_STATUS_DISCONNECTED;
+      g_clear_error (&error);
+    }
 
-  data->connection = mission_control_get_tpconnection (priv->mc, account, NULL);
-  if (data->connection != NULL)
+  mc_presence = mission_control_get_presence_actual (priv->mc, &error);
+  if (error != NULL)
+    {
+      presence = TP_CONNECTION_PRESENCE_TYPE_UNSET;
+      g_clear_error (&error);
+    }
+  else
     {
-      g_signal_connect (data->connection, "invalidated",
-          G_CALLBACK (connection_invalidated_cb), manager);
-      g_hash_table_insert (priv->connections, g_object_ref (data->connection),
-          g_object_ref (account));
-      tp_connection_call_when_ready (data->connection, connection_ready_cb,
-          manager);
+      presence = mc_presence_to_tp_presence (mc_presence);
     }
+
+  g_signal_connect (account, "status-changed",
+    G_CALLBACK (emp_account_status_changed_cb), manager);
+
+  g_signal_connect (account, "presence-changed",
+    G_CALLBACK (emp_account_presence_changed_cb), manager);
+
+  _empathy_account_set_status (account, status,
+    TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
+    presence);
+
+  return account;
 }
 
 static void
@@ -191,32 +216,10 @@ account_created_cb (McAccountMonitor *mon,
                     gchar *account_name,
                     EmpathyAccountManager *manager)
 {
-  McAccount *account;
-  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
-  TpConnectionStatus initial_status;
-
-  account = mc_account_lookup (account_name);
+  McAccount *mc_account = mc_account_lookup (account_name);
 
-  if (account)
-    {
-      AccountData *data;
-
-      data = account_data_new_default (priv->mc, account);
-      g_hash_table_insert (priv->accounts, g_object_ref (account), data);
-
-      initial_status = mission_control_get_connection_status (priv->mc,
-							      account, NULL);
-
-      if (initial_status == TP_CONNECTION_STATUS_CONNECTED)
-	priv->connected++;
-      else if (initial_status == TP_CONNECTION_STATUS_CONNECTING)
-	priv->connecting++;
-
-      account_manager_update_connection (manager, data, account);
-
-      g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
-      g_object_unref (account);
-    }
+  if (mc_account != NULL)
+    create_account (manager, account_name, mc_account);
 }
 
 static void
@@ -224,16 +227,15 @@ account_deleted_cb (McAccountMonitor *mon,
                     gchar *account_name,
                     EmpathyAccountManager *manager)
 {
-  McAccount *account;
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+  EmpathyAccount *account;
 
-  account = mc_account_lookup (account_name);
+  account = g_hash_table_lookup (priv->accounts, account_name);
 
   if (account)
     {
-      g_hash_table_remove (priv->accounts, account);
       g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account);
-      g_object_unref (account);
+      g_hash_table_remove (priv->accounts, account_name);
     }
 }
 
@@ -242,15 +244,13 @@ account_changed_cb (McAccountMonitor *mon,
                     gchar *account_name,
                     EmpathyAccountManager *manager)
 {
-  McAccount *account;
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+  EmpathyAccount *account;
 
-  account = mc_account_lookup (account_name);
+  account = g_hash_table_lookup (priv->accounts, account_name);
 
-  if (account)
-    {
-      g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account);
-      g_object_unref (account);
-    }
+  if (account != NULL)
+    g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account);
 }
 
 static void
@@ -258,20 +258,15 @@ account_disabled_cb (McAccountMonitor *mon,
                      gchar *account_name,
                      EmpathyAccountManager *manager)
 {
-  McAccount *account;
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
-  AccountData *data;
+  EmpathyAccount *account;
 
-  account = mc_account_lookup (account_name);
+  account = g_hash_table_lookup (priv->accounts, account_name);
 
   if (account)
     {
-      data = g_hash_table_lookup (priv->accounts, account);
-      g_assert (data);
-      data->is_enabled = FALSE;
-
+      _empathy_account_set_enabled (account, FALSE);
       g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account);
-      g_object_unref (account);
     }
 }
 
@@ -280,135 +275,60 @@ account_enabled_cb (McAccountMonitor *mon,
                     gchar *account_name,
                     EmpathyAccountManager *manager)
 {
-  McAccount *account;
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
-  AccountData *data;
+  EmpathyAccount *account;
 
-  account = mc_account_lookup (account_name);
+  account = g_hash_table_lookup (priv->accounts, account_name);
 
   if (account)
     {
-      data = g_hash_table_lookup (priv->accounts, account);
-      g_assert (data);
-      data->is_enabled = TRUE;
-
+      _empathy_account_set_enabled (account, TRUE);
       g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account);
-      g_object_unref (account);
-    }
-}
-
-static void
-update_connection_numbers (EmpathyAccountManager *manager,
-                           TpConnectionStatus status,
-                           TpConnectionStatus old_s)
-{
-  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
-
-  if (status == TP_CONNECTION_STATUS_CONNECTED)
-    {
-      priv->connected++;
-      if (old_s == TP_CONNECTION_STATUS_CONNECTING)
-        priv->connecting--;
-    }
-
-  if (status == TP_CONNECTION_STATUS_CONNECTING)
-    {
-      priv->connecting++;
-      if (old_s == TP_CONNECTION_STATUS_CONNECTED)
-        priv->connected--;
-    }
-
-  if (status == TP_CONNECTION_STATUS_DISCONNECTED)
-    {
-      if (old_s == TP_CONNECTION_STATUS_CONNECTED)
-        priv->connected--;
-
-      if (old_s == TP_CONNECTION_STATUS_CONNECTING)
-        priv->connecting--;
     }
 }
 
-static gboolean
-remove_data_timeout (gpointer _data)
-{
-  AccountData *data = _data;
-
-  data->source_id = 0;
-
-  return FALSE;
-}
-
 typedef struct {
   TpConnectionStatus status;
-  McPresence presence;
+  TpConnectionPresenceType presence;
   TpConnectionStatusReason reason;
   gchar *unique_name;
   EmpathyAccountManager *manager;
+  McAccount *mc_account;
 } ChangedSignalData;
 
 static gboolean
 account_status_changed_idle_cb (ChangedSignalData *signal_data)
 {
-  McAccount *account;
-  AccountData *data;
-  McPresence presence, old_p;
-  TpConnectionStatus status, old_s;
-  gboolean emit_presence = FALSE, emit_connection = FALSE;
+  EmpathyAccount *account;
   EmpathyAccountManager *manager = signal_data->manager;
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
 
-  presence = signal_data->presence;
-  status = signal_data->status;
-  account = mc_account_lookup (signal_data->unique_name);
+  account = g_hash_table_lookup (priv->accounts,
+    signal_data->unique_name);
 
   if (account)
     {
-      data = g_hash_table_lookup (priv->accounts, account);
-      g_assert (data);
-
-      old_p = data->presence;
-      old_s = data->status;
-
-      if (old_p != presence)
+      if (empathy_account_get_connection (account) == NULL)
         {
-          data->presence = presence;
-          emit_presence = TRUE;
-        }
+          TpConnection *connection;
 
-      if (old_s != status)
-        {
-          data->status = status;
-          update_connection_numbers (manager, status, old_s);
+          connection = mission_control_get_tpconnection (priv->mc,
+             signal_data->mc_account, NULL);
 
-          if (status == TP_CONNECTION_STATUS_CONNECTED)
+          if (connection != NULL)
             {
-                if (data->source_id > 0)
-                  {
-                    g_source_remove (data->source_id);
-                    data->source_id = 0;
-                  }
-
-                data->source_id = g_timeout_add_seconds (10,
-                                                         remove_data_timeout,
-                                                         data);
+              _empathy_account_set_connection (account, connection);
+              g_object_unref (connection);
             }
-          emit_connection = TRUE;
         }
 
-      account_manager_update_connection (manager, data, account);
-
-      if (emit_presence)
-        g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0,
-                       account, presence, old_p);
-
-      if (emit_connection)
-        g_signal_emit (manager, signals[ACCOUNT_CONNECTION_CHANGED], 0,
-                       account, signal_data->reason, status, old_s);
-
-      g_object_unref (account);
+      _empathy_account_set_status (account, signal_data->status,
+        signal_data->reason,
+        signal_data->presence);
     }
 
   g_object_unref (signal_data->manager);
+  g_object_unref (signal_data->mc_account);
   g_free (signal_data->unique_name);
   g_slice_free (ChangedSignalData, signal_data);
 
@@ -424,38 +344,18 @@ account_status_changed_cb (MissionControl *mc,
                            EmpathyAccountManager *manager)
 {
   ChangedSignalData *data;
-  TpConnectionPresenceType tp_presence;
 
-  switch (presence)
-    {
-      case MC_PRESENCE_OFFLINE:
-        tp_presence = TP_CONNECTION_PRESENCE_TYPE_OFFLINE;
-        break;
-      case MC_PRESENCE_AVAILABLE:
-        tp_presence = TP_CONNECTION_PRESENCE_TYPE_AVAILABLE;
-        break;
-      case MC_PRESENCE_AWAY:
-        tp_presence = TP_CONNECTION_PRESENCE_TYPE_AWAY;
-        break;
-      case MC_PRESENCE_EXTENDED_AWAY:
-        tp_presence = TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY;
-        break;
-      case MC_PRESENCE_HIDDEN:
-        tp_presence = TP_CONNECTION_PRESENCE_TYPE_HIDDEN;
-        break;
-      case MC_PRESENCE_DO_NOT_DISTURB:
-        tp_presence = TP_CONNECTION_PRESENCE_TYPE_BUSY;
-        break;
-      default:
-        tp_presence = TP_CONNECTION_PRESENCE_TYPE_UNSET;
-    }
+  DEBUG ("Status of account %s became "
+    "status: %d presence: %d reason: %d", unique_name, status,
+    presence, reason);
 
   data = g_slice_new0 (ChangedSignalData);
   data->status = status;
-  data->presence = tp_presence;
+  data->presence = mc_presence_to_tp_presence (presence);
   data->reason = reason;
   data->unique_name = g_strdup (unique_name);
   data->manager = g_object_ref (manager);
+  data->mc_account = mc_account_lookup (unique_name);
 
   g_idle_add ((GSourceFunc) account_status_changed_idle_cb, data);
 }
@@ -467,35 +367,33 @@ empathy_account_manager_init (EmpathyAccountManager *manager)
   GList *mc_accounts, *l;
 
   priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
-				      EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv);
+      EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv);
+
   manager->priv = priv;
   priv->monitor = mc_account_monitor_new ();
   priv->mc = empathy_mission_control_dup_singleton ();
   priv->connected = priv->connecting = 0;
   priv->dispose_run = FALSE;
 
-  priv->accounts = g_hash_table_new_full (empathy_account_hash,
-                                          empathy_account_equal,
-                                          g_object_unref,
-                                          (GDestroyNotify) account_data_free);
-  priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-                                             g_object_unref, g_object_unref);
+  priv->accounts = g_hash_table_new_full (g_str_hash, g_str_equal,
+      g_free, (GDestroyNotify) g_object_unref);
 
   mc_accounts = mc_accounts_list ();
 
   for (l = mc_accounts; l; l = l->next)
-    account_created_cb (priv->monitor, (char *) mc_account_get_unique_name (l->data), manager);
+    account_created_cb (priv->monitor,
+      (char *) mc_account_get_unique_name (l->data), manager);
 
   g_signal_connect (priv->monitor, "account-created",
-                    G_CALLBACK (account_created_cb), manager);
+      G_CALLBACK (account_created_cb), manager);
   g_signal_connect (priv->monitor, "account-deleted",
-                    G_CALLBACK (account_deleted_cb), manager);
+      G_CALLBACK (account_deleted_cb), manager);
   g_signal_connect (priv->monitor, "account-disabled",
-                    G_CALLBACK (account_disabled_cb), manager);
+      G_CALLBACK (account_disabled_cb), manager);
   g_signal_connect (priv->monitor, "account-enabled",
-                    G_CALLBACK (account_enabled_cb), manager);
+      G_CALLBACK (account_enabled_cb), manager);
   g_signal_connect (priv->monitor, "account-changed",
-                    G_CALLBACK (account_changed_cb), manager);
+      G_CALLBACK (account_changed_cb), manager);
 
   dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged",
                                G_CALLBACK (account_status_changed_cb),
@@ -505,27 +403,12 @@ empathy_account_manager_init (EmpathyAccountManager *manager)
 }
 
 static void
-account_manager_disconnect_foreach (gpointer key,
-                                    gpointer value,
-                                    gpointer user_data)
-{
-  TpConnection *connection = key;
-  EmpathyAccountManager *manager = user_data;
-
-  g_signal_handlers_disconnect_by_func (connection, connection_invalidated_cb,
-    manager);
-}
-
-static void
 do_finalize (GObject *obj)
 {
   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
 
-  g_hash_table_unref (priv->accounts);
-  g_hash_table_foreach (priv->connections, account_manager_disconnect_foreach,
-    obj);
-  g_hash_table_unref (priv->connections);
+  g_hash_table_destroy (priv->accounts);
 
   G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj);
 }
@@ -610,7 +493,7 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   NULL, NULL,
                   g_cclosure_marshal_VOID__OBJECT,
                   G_TYPE_NONE,
-                  1, MC_TYPE_ACCOUNT);
+                  1, EMPATHY_TYPE_ACCOUNT);
 
   signals[ACCOUNT_DELETED] =
     g_signal_new ("account-deleted",
@@ -620,7 +503,7 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   NULL, NULL,
                   g_cclosure_marshal_VOID__OBJECT,
                   G_TYPE_NONE,
-                  1, MC_TYPE_ACCOUNT);
+                  1, EMPATHY_TYPE_ACCOUNT);
 
   signals[ACCOUNT_ENABLED] =
     g_signal_new ("account-enabled",
@@ -630,7 +513,7 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   NULL, NULL,
                   g_cclosure_marshal_VOID__OBJECT,
                   G_TYPE_NONE,
-                  1, MC_TYPE_ACCOUNT);
+                  1, EMPATHY_TYPE_ACCOUNT);
 
   signals[ACCOUNT_DISABLED] =
     g_signal_new ("account-disabled",
@@ -640,7 +523,7 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   NULL, NULL,
                   g_cclosure_marshal_VOID__OBJECT,
                   G_TYPE_NONE,
-                  1, MC_TYPE_ACCOUNT);
+                  1, EMPATHY_TYPE_ACCOUNT);
 
   signals[ACCOUNT_CHANGED] =
     g_signal_new ("account-changed",
@@ -650,7 +533,7 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   NULL, NULL,
                   g_cclosure_marshal_VOID__OBJECT,
                   G_TYPE_NONE,
-                  1, MC_TYPE_ACCOUNT);
+                  1, EMPATHY_TYPE_ACCOUNT);
 
   signals[ACCOUNT_CONNECTION_CHANGED] =
     g_signal_new ("account-connection-changed",
@@ -660,7 +543,7 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   NULL, NULL,
                   _empathy_marshal_VOID__OBJECT_INT_UINT_UINT,
                   G_TYPE_NONE,
-                  4, MC_TYPE_ACCOUNT,
+                  4, EMPATHY_TYPE_ACCOUNT,
                   G_TYPE_INT,   /* reason */
                   G_TYPE_UINT,  /* actual connection */
                   G_TYPE_UINT); /* previous connection */
@@ -673,7 +556,7 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass)
                   NULL, NULL,
                   _empathy_marshal_VOID__OBJECT_INT_INT,
                   G_TYPE_NONE,
-                  3, MC_TYPE_ACCOUNT,
+                  3, EMPATHY_TYPE_ACCOUNT,
                   G_TYPE_INT,  /* actual presence */
                   G_TYPE_INT); /* previous presence */
 
@@ -698,6 +581,16 @@ empathy_account_manager_dup_singleton (void)
   return g_object_new (EMPATHY_TYPE_ACCOUNT_MANAGER, NULL);
 }
 
+EmpathyAccount *
+empathy_account_manager_create (EmpathyAccountManager *manager,
+  McProfile *profile)
+{
+  McAccount *mc_account = mc_account_create (profile);
+  return g_object_ref (create_account (manager,
+      mc_account_get_unique_name (mc_account),
+      mc_account));
+}
+
 int
 empathy_account_manager_get_connected_accounts (EmpathyAccountManager *manager)
 {
@@ -722,23 +615,6 @@ empathy_account_manager_get_connecting_accounts (EmpathyAccountManager *manager)
   return priv->connecting;
 }
 
-gboolean
-empathy_account_manager_is_account_just_connected (EmpathyAccountManager *manager,
-                                                   McAccount *account)
-{
-  EmpathyAccountManagerPriv *priv;
-  AccountData *data;
-
-  g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), FALSE);
-
-  priv = GET_PRIV (manager);
-  data = g_hash_table_lookup (priv->accounts, account);
-
-  g_assert (data);
-
-  return (data->source_id > 0);
-}
-
 /**
  * empathy_account_manager_get_count:
  * @manager: a #EmpathyAccountManager
@@ -759,62 +635,59 @@ empathy_account_manager_get_count (EmpathyAccountManager *manager)
   return g_hash_table_size (priv->accounts);
 }
 
-McAccount *
+EmpathyAccount *
 empathy_account_manager_get_account (EmpathyAccountManager *manager,
                                      TpConnection          *connection)
 {
   EmpathyAccountManagerPriv *priv;
+  GHashTableIter iter;
+  gpointer value;
 
   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), 0);
 
   priv = GET_PRIV (manager);
 
-  return g_hash_table_lookup (priv->connections, connection);
+  g_hash_table_iter_init (&iter, priv->accounts);
+  while (g_hash_table_iter_next (&iter, NULL, &value))
+    {
+      EmpathyAccount *account = EMPATHY_ACCOUNT (value);
+
+      if (connection == empathy_account_get_connection (account))
+          return account;
+    }
+
+  return NULL;
 }
 
-GList *
-empathy_account_manager_dup_accounts (EmpathyAccountManager *manager)
+EmpathyAccount *
+empathy_account_manager_lookup (EmpathyAccountManager *manager,
+    const gchar *unique_name)
 {
-  EmpathyAccountManagerPriv *priv;
-  GList *ret;
-
-  g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+  EmpathyAccount *account;
 
-  priv = GET_PRIV (manager);
+  account = g_hash_table_lookup (priv->accounts, unique_name);
 
-  ret = g_hash_table_get_keys (priv->accounts);
-  g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+  if (account != NULL)
+    g_object_ref (account);
 
-  return ret;
+  return account;
 }
 
-/**
- * empathy_account_manager_get_connection:
- * @manager: a #EmpathyAccountManager
- * @account: a #McAccount
- *
- * Get the connection of the accounts, or NULL if account is offline or the
- * connection is not yet ready. This function does not return a new ref.
- *
- * Returns: the connection of the accounts.
- **/
-TpConnection *
-empathy_account_manager_get_connection (EmpathyAccountManager *manager,
-                                        McAccount *account)
+GList *
+empathy_account_manager_dup_accounts (EmpathyAccountManager *manager)
 {
   EmpathyAccountManagerPriv *priv;
-  AccountData *data;
+  GList *ret;
 
   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
-  g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
 
   priv = GET_PRIV (manager);
 
-  data = g_hash_table_lookup (priv->accounts, account);
-  if (data && data->connection && tp_connection_is_ready (data->connection))
-    return data->connection;
+  ret = g_hash_table_get_values (priv->accounts);
+  g_list_foreach (ret, (GFunc) g_object_ref, NULL);
 
-  return NULL;
+  return ret;
 }
 
 /**
@@ -831,18 +704,30 @@ empathy_account_manager_dup_connections (EmpathyAccountManager *manager)
 {
   EmpathyAccountManagerPriv *priv;
   GHashTableIter iter;
-  gpointer connection;
+  gpointer value;
   GList *ret = NULL;
 
   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_MANAGER (manager), NULL);
 
   priv = GET_PRIV (manager);
 
-  g_hash_table_iter_init (&iter, priv->connections);
-  while (g_hash_table_iter_next (&iter, &connection, NULL))
-    if (connection != NULL && tp_connection_is_ready (connection))
-      ret = g_list_prepend (ret, g_object_ref (connection));
+  g_hash_table_iter_init (&iter, priv->accounts);
+  while (g_hash_table_iter_next (&iter, NULL, &value))
+    {
+      EmpathyAccount *account = EMPATHY_ACCOUNT (value);
+      TpConnection *connection;
+
+      connection = empathy_account_get_connection (account);
+      if (connection != NULL)
+        ret = g_list_prepend (ret, g_object_ref (connection));
+    }
 
   return ret;
 }
 
+void
+empathy_account_manager_remove (EmpathyAccountManager *manager,
+    EmpathyAccount *account)
+{
+  mc_account_delete (_empathy_account_get_mc_account (account));
+}
diff --git a/libempathy/empathy-account-manager.h b/libempathy/empathy-account-manager.h
index 11ca6ac..b04571f 100644
--- a/libempathy/empathy-account-manager.h
+++ b/libempathy/empathy-account-manager.h
@@ -24,7 +24,7 @@
 
 #include <glib-object.h>
 
-#include <libmissioncontrol/mc-account.h>
+#include "empathy-account.h"
 
 G_BEGIN_DECLS
 
@@ -52,25 +52,28 @@ GType empathy_account_manager_get_type (void);
 /* public methods */
 
 EmpathyAccountManager * empathy_account_manager_dup_singleton (void);
+EmpathyAccount *        empathy_account_manager_create
+                                (EmpathyAccountManager *manager,
+                                 McProfile *profile);
 int                     empathy_account_manager_get_connected_accounts
                                 (EmpathyAccountManager *manager);
 int                     empathy_account_manager_get_connecting_accounts
                                 (EmpathyAccountManager *manager);
-gboolean                empathy_account_manager_is_account_just_connected
-                                (EmpathyAccountManager *manager,
-                                 McAccount             *account);
 int                     empathy_account_manager_get_count
                                 (EmpathyAccountManager *manager);
-McAccount *             empathy_account_manager_get_account
+EmpathyAccount *        empathy_account_manager_get_account
                                 (EmpathyAccountManager *manager,
                                  TpConnection          *connection);
+EmpathyAccount *        empathy_account_manager_lookup
+                                (EmpathyAccountManager *manager,
+                                 const gchar *unique_name);
 GList *                 empathy_account_manager_dup_accounts
                                 (EmpathyAccountManager *manager);
-TpConnection *          empathy_account_manager_get_connection
-                                (EmpathyAccountManager *manager,
-                                 McAccount             *account);
 GList *                 empathy_account_manager_dup_connections
                                 (EmpathyAccountManager *manager);
+void                    empathy_account_manager_remove (
+                                 EmpathyAccountManager *manager,
+                                 EmpathyAccount *account);
 
 G_END_DECLS
 
diff --git a/libempathy/empathy-account-priv.h b/libempathy/empathy-account-priv.h
new file mode 100644
index 0000000..8b656b4
--- /dev/null
+++ b/libempathy/empathy-account-priv.h
@@ -0,0 +1,44 @@
+/*
+ * empathy-account-priv.h - Private Header for EmpathyAccount
+ * Copyright (C) 2009 Collabora Ltd.
+ * @author Sjoerd Simons <sjoerd simons collabora co uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __EMPATHY_ACCOUNT_PRIV_H__
+#define __EMPATHY_ACCOUNT_PRIV_H__
+
+#include <glib.h>
+
+#include <libmissioncontrol/mc-account.h>
+#include "empathy-account.h"
+
+G_BEGIN_DECLS
+
+EmpathyAccount *_empathy_account_new (McAccount *account);
+void _empathy_account_set_status (EmpathyAccount *account,
+    TpConnectionStatus status,
+    TpConnectionStatusReason reason,
+    TpConnectionPresenceType presence);
+void _empathy_account_set_connection (EmpathyAccount *account,
+    TpConnection *connection);
+void _empathy_account_set_enabled (EmpathyAccount *account,
+    gboolean enabled);
+McAccount *_empathy_account_get_mc_account (EmpathyAccount *account);
+
+G_END_DECLS
+
+#endif /* #ifndef __EMPATHY_ACCOUNT_PRIV_H__*/
diff --git a/libempathy/empathy-account.c b/libempathy/empathy-account.c
new file mode 100644
index 0000000..34b2ad6
--- /dev/null
+++ b/libempathy/empathy-account.c
@@ -0,0 +1,572 @@
+/*
+ * empathy-account.c - Source for EmpathyAccount
+ * Copyright (C) 2009 Collabora Ltd.
+ * @author Sjoerd Simons <sjoerd simons collabora co uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <telepathy-glib/enums.h>
+
+#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
+#include <libempathy/empathy-debug.h>
+
+#include "empathy-account.h"
+#include "empathy-account-priv.h"
+#include "empathy-utils.h"
+#include "empathy-marshal.h"
+
+/* signals */
+enum {
+  STATUS_CHANGED,
+  PRESENCE_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* properties */
+enum {
+  PROP_ENABLED = 1,
+  PROP_PRESENCE,
+  PROP_CONNECTION_STATUS,
+  PROP_CONNECTION_STATUS_REASON,
+  PROP_CONNECTION,
+  PROP_UNIQUE_NAME,
+  PROP_DISPLAY_NAME
+};
+
+G_DEFINE_TYPE(EmpathyAccount, empathy_account, G_TYPE_OBJECT)
+
+/* private structure */
+typedef struct _EmpathyAccountPriv EmpathyAccountPriv;
+
+struct _EmpathyAccountPriv
+{
+  gboolean dispose_has_run;
+
+  TpConnection *connection;
+  guint connection_invalidated_id;
+
+  TpConnectionStatus status;
+  TpConnectionStatusReason reason;
+  TpConnectionPresenceType presence;
+
+  gboolean enabled;
+  glong connect_time;
+
+  McAccount *mc_account;
+};
+
+#define GET_PRIV(obj)  EMPATHY_GET_PRIV (obj, EmpathyAccount)
+
+static void
+empathy_account_init (EmpathyAccount *obj)
+{
+  EmpathyAccountPriv *priv;
+
+  priv =  G_TYPE_INSTANCE_GET_PRIVATE (obj,
+    EMPATHY_TYPE_ACCOUNT, EmpathyAccountPriv);
+
+  obj->priv = priv;
+
+  priv->status = TP_CONNECTION_STATUS_DISCONNECTED;
+}
+
+static void
+empathy_account_get_property (GObject *object,
+    guint prop_id,
+    GValue *value,
+    GParamSpec *pspec)
+{
+  EmpathyAccount *account = EMPATHY_ACCOUNT (object);
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  switch (prop_id)
+    {
+      case PROP_ENABLED:
+        g_value_set_boolean (value, priv->enabled);
+        break;
+      case PROP_PRESENCE:
+        g_value_set_uint (value, priv->presence);
+        break;
+      case PROP_CONNECTION_STATUS:
+        g_value_set_uint (value, priv->status);
+        break;
+      case PROP_CONNECTION_STATUS_REASON:
+        g_value_set_uint (value, priv->reason);
+        break;
+      case PROP_CONNECTION:
+        g_value_set_object (value,
+            empathy_account_get_connection (account));
+        break;
+      case PROP_UNIQUE_NAME:
+        g_value_set_string (value,
+            empathy_account_get_unique_name (account));
+        break;
+      case PROP_DISPLAY_NAME:
+        g_value_set_string (value,
+            empathy_account_get_display_name (account));
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void empathy_account_dispose (GObject *object);
+static void empathy_account_finalize (GObject *object);
+
+static void
+empathy_account_class_init (EmpathyAccountClass *empathy_account_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (empathy_account_class);
+
+  g_type_class_add_private (empathy_account_class,
+    sizeof (EmpathyAccountPriv));
+
+  object_class->get_property = empathy_account_get_property;
+  object_class->dispose = empathy_account_dispose;
+  object_class->finalize = empathy_account_finalize;
+
+  g_object_class_install_property (object_class, PROP_ENABLED,
+    g_param_spec_boolean ("enabled",
+      "Enabled",
+      "Whether this account is enabled or not",
+      FALSE,
+      G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_PRESENCE,
+    g_param_spec_uint ("presence",
+      "Presence",
+      "The account connections presence type",
+      0,
+      NUM_TP_CONNECTION_PRESENCE_TYPES,
+      TP_CONNECTION_PRESENCE_TYPE_UNSET,
+      G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_CONNECTION_STATUS,
+    g_param_spec_uint ("status",
+      "ConnectionStatus",
+      "The accounts connections status type",
+      0,
+      NUM_TP_CONNECTION_STATUSES,
+      TP_CONNECTION_STATUS_DISCONNECTED,
+      G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_CONNECTION_STATUS_REASON,
+    g_param_spec_uint ("status-reason",
+      "ConnectionStatusReason",
+      "The account connections status reason",
+      0,
+      NUM_TP_CONNECTION_STATUS_REASONS,
+      TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
+      G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_CONNECTION,
+    g_param_spec_object ("connection",
+      "Connection",
+      "The accounts connection",
+      TP_TYPE_CONNECTION,
+      G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_UNIQUE_NAME,
+    g_param_spec_string ("unique-name",
+      "UniqueName",
+      "The accounts unique name",
+      NULL,
+      G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
+    g_param_spec_string ("display-name",
+      "DisplayName",
+      "The accounts display name",
+      NULL,
+      G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+  signals[STATUS_CHANGED] = g_signal_new ("status-changed",
+    G_TYPE_FROM_CLASS (object_class),
+    G_SIGNAL_RUN_LAST,
+    0, NULL, NULL,
+    _empathy_marshal_VOID__UINT_UINT_UINT,
+    G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
+
+  signals[PRESENCE_CHANGED] = g_signal_new ("presence-changed",
+    G_TYPE_FROM_CLASS (object_class),
+    G_SIGNAL_RUN_LAST,
+    0, NULL, NULL,
+    _empathy_marshal_VOID__UINT_UINT,
+    G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+}
+
+void
+empathy_account_dispose (GObject *object)
+{
+  EmpathyAccount *self = EMPATHY_ACCOUNT (object);
+  EmpathyAccountPriv *priv = GET_PRIV (self);
+
+  if (priv->dispose_has_run)
+    return;
+
+  priv->dispose_has_run = TRUE;
+
+  if (priv->connection_invalidated_id != 0)
+    g_signal_handler_disconnect (priv->connection,
+        priv->connection_invalidated_id);
+  priv->connection_invalidated_id = 0;
+
+  if (priv->connection != NULL)
+    g_object_unref (priv->connection);
+  priv->connection = NULL;
+
+  /* release any references held by the object here */
+  if (G_OBJECT_CLASS (empathy_account_parent_class)->dispose != NULL)
+    G_OBJECT_CLASS (empathy_account_parent_class)->dispose (object);
+}
+
+void
+empathy_account_finalize (GObject *object)
+{
+  /* free any data held directly by the object here */
+  if (G_OBJECT_CLASS (empathy_account_parent_class)->finalize != NULL)
+    G_OBJECT_CLASS (empathy_account_parent_class)->finalize (object);
+}
+
+gboolean
+empathy_account_is_just_connected (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  GTimeVal val;
+
+  if (priv->status != TP_CONNECTION_STATUS_CONNECTED)
+    return FALSE;
+
+  g_get_current_time (&val);
+
+  return (val.tv_sec - priv->connect_time) < 10;
+}
+
+/**
+ * empathy_account_get_connection:
+ * @account: a #EmpathyAccount
+ *
+ * Get the connection of the account, or NULL if account is offline or the
+ * connection is not yet ready. This function does not return a new ref.
+ *
+ * Returns: the connection of the account.
+ **/
+TpConnection *
+empathy_account_get_connection (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  if (priv->connection != NULL &&
+      tp_connection_is_ready (priv->connection))
+    return priv->connection;
+
+  return NULL;
+}
+
+/**
+ * empathy_account_get_unique_name:
+ * @account: a #EmpathyAccount
+ *
+ * Returns: the unique name of the account.
+ **/
+const gchar *
+empathy_account_get_unique_name (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  return mc_account_get_unique_name (priv->mc_account);
+}
+
+/**
+ * empathy_account_get_display_name:
+ * @account: a #EmpathyAccount
+ *
+ * Returns: the display name of the account.
+ **/
+const gchar *
+empathy_account_get_display_name (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  return mc_account_get_display_name (priv->mc_account);
+}
+
+gboolean
+empathy_account_is_valid (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  return mc_account_is_complete (priv->mc_account);
+}
+
+void
+empathy_account_set_enabled (EmpathyAccount *account, gboolean enabled)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  mc_account_set_enabled (priv->mc_account, enabled);
+}
+
+gboolean
+empathy_account_is_enabled (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  return priv->enabled;
+}
+
+void
+empathy_account_unset_param (EmpathyAccount *account, const gchar *param)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  mc_account_unset_param (priv->mc_account, param);
+}
+
+gchar *
+empathy_account_get_param_string (EmpathyAccount *account, const gchar *param)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  gchar *value = NULL;
+
+  mc_account_get_param_string (priv->mc_account, param, &value);
+  return value;
+}
+
+gint
+empathy_account_get_param_int (EmpathyAccount *account, const gchar *param)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  int value;
+
+  mc_account_get_param_int (priv->mc_account, param, &value);
+  return value;
+}
+
+gboolean
+empathy_account_get_param_boolean (EmpathyAccount *account, const gchar *param)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  gboolean value;
+
+  mc_account_get_param_boolean (priv->mc_account, param, &value);
+  return value;
+}
+
+void
+empathy_account_set_param_string (EmpathyAccount *account,
+  const gchar *param,
+  const gchar *value)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  mc_account_set_param_string (priv->mc_account, param, value);
+}
+
+void
+empathy_account_set_param_int (EmpathyAccount *account,
+  const gchar *param,
+  gint value)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  mc_account_set_param_int (priv->mc_account, param, value);
+}
+
+void
+empathy_account_set_param_boolean (EmpathyAccount *account,
+  const gchar *param,
+  gboolean value)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  mc_account_set_param_boolean (priv->mc_account, param, value);
+}
+
+void
+empathy_account_set_display_name (EmpathyAccount *account,
+    const gchar *display_name)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  mc_account_set_display_name (priv->mc_account, display_name);
+}
+
+McProfile *
+empathy_account_get_profile (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  return mc_account_get_profile (priv->mc_account);
+}
+
+EmpathyAccount *
+_empathy_account_new (McAccount *mc_account)
+{
+  EmpathyAccount *account;
+  EmpathyAccountPriv *priv;
+
+  account = g_object_new (EMPATHY_TYPE_ACCOUNT, NULL);
+  priv = GET_PRIV (account);
+  priv->mc_account = mc_account;
+
+  return account;
+}
+
+void _empathy_account_set_status (EmpathyAccount *account,
+    TpConnectionStatus status,
+    TpConnectionStatusReason reason,
+    TpConnectionPresenceType presence)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  TpConnectionStatus old_s = priv->status;
+  TpConnectionPresenceType old_p = priv->presence;
+
+  priv->status = status;
+  priv->presence = presence;
+
+  if (priv->status != old_s)
+    {
+      if (priv->status == TP_CONNECTION_STATUS_CONNECTED)
+        {
+          GTimeVal val;
+          g_get_current_time (&val);
+
+          priv->connect_time = val.tv_sec;
+        }
+
+      priv->reason = reason;
+      g_signal_emit (account, signals[STATUS_CHANGED], 0,
+        old_s, priv->status, reason);
+
+      g_object_notify (G_OBJECT (account), "status");
+    }
+
+  if (priv->presence != old_p)
+    {
+      g_signal_emit (account, signals[PRESENCE_CHANGED], 0,
+        old_p, priv->presence);
+      g_object_notify (G_OBJECT (account), "presence");
+    }
+}
+
+static void
+empathy_account_connection_ready_cb (TpConnection *connection,
+    const GError *error,
+    gpointer user_data)
+{
+  EmpathyAccount *account = EMPATHY_ACCOUNT (user_data);
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  if (error != NULL)
+    {
+      DEBUG ("(%s) Connection failed to become ready: %s",
+        empathy_account_get_unique_name (account), error->message);
+      priv->connection = NULL;
+    }
+  else
+    {
+      DEBUG ("(%s) Connection ready",
+        empathy_account_get_unique_name (account));
+      g_object_notify (G_OBJECT (account), "connection");
+    }
+}
+
+static void
+_empathy_account_connection_invalidated_cb (TpProxy *self,
+  guint    domain,
+  gint     code,
+  gchar   *message,
+  gpointer user_data)
+{
+  EmpathyAccount *account = EMPATHY_ACCOUNT (user_data);
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  if (priv->connection == NULL)
+    return;
+
+  DEBUG ("(%s) Connection invalidated",
+    empathy_account_get_unique_name (account));
+
+  g_assert (priv->connection == TP_CONNECTION (self));
+
+  g_signal_handler_disconnect (priv->connection,
+    priv->connection_invalidated_id);
+  priv->connection_invalidated_id = 0;
+
+  g_object_unref (priv->connection);
+  priv->connection = NULL;
+
+  g_object_notify (G_OBJECT (account), "connection");
+}
+
+void
+_empathy_account_set_connection (EmpathyAccount *account,
+    TpConnection *connection)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  if (priv->connection == connection)
+    return;
+
+  /* Connection already set, don't set the new one */
+  if (connection != NULL && priv->connection != NULL)
+    return;
+
+  if (connection == NULL)
+    {
+      g_signal_handler_disconnect (priv->connection,
+        priv->connection_invalidated_id);
+      priv->connection_invalidated_id = 0;
+
+      g_object_unref (priv->connection);
+      priv->connection = NULL;
+      g_object_notify (G_OBJECT (account), "connection");
+    }
+  else
+    {
+      priv->connection = g_object_ref (connection);
+      priv->connection_invalidated_id = g_signal_connect (priv->connection,
+          "invalidated",
+          G_CALLBACK (_empathy_account_connection_invalidated_cb),
+          account);
+
+      tp_connection_call_when_ready (priv->connection,
+        empathy_account_connection_ready_cb, account);
+    }
+}
+
+void
+_empathy_account_set_enabled (EmpathyAccount *account,
+    gboolean enabled)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+
+  if (priv->enabled == enabled)
+    return;
+
+  priv->enabled = enabled;
+  g_object_notify (G_OBJECT (account), "enabled");
+}
+
+McAccount *
+_empathy_account_get_mc_account (EmpathyAccount *account)
+{
+  EmpathyAccountPriv *priv = GET_PRIV (account);
+  return priv->mc_account;
+}
diff --git a/libempathy/empathy-account.h b/libempathy/empathy-account.h
new file mode 100644
index 0000000..75babd8
--- /dev/null
+++ b/libempathy/empathy-account.h
@@ -0,0 +1,94 @@
+/*
+ * empathy-account.h - Header for EmpathyAccount
+ * Copyright (C) 2009 Collabora Ltd.
+ * @author Sjoerd Simons <sjoerd simons collabora co uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __EMPATHY_ACCOUNT_H__
+#define __EMPATHY_ACCOUNT_H__
+
+#include <glib-object.h>
+
+#include <telepathy-glib/connection.h>
+#include <libmissioncontrol/mc-profile.h>
+
+G_BEGIN_DECLS
+
+typedef struct _EmpathyAccount EmpathyAccount;
+typedef struct _EmpathyAccountClass EmpathyAccountClass;
+
+struct _EmpathyAccountClass {
+    GObjectClass parent_class;
+};
+
+struct _EmpathyAccount {
+    GObject parent;
+    gpointer priv;
+};
+
+GType empathy_account_get_type (void);
+
+/* TYPE MACROS */
+#define EMPATHY_TYPE_ACCOUNT (empathy_account_get_type ())
+#define EMPATHY_ACCOUNT(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_ACCOUNT, EmpathyAccount))
+#define EMPATHY_ACCOUNT_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_ACCOUNT, EmpathyAccountClass))
+#define EMPATHY_IS_ACCOUNT(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_ACCOUNT))
+#define EMPATHY_IS_ACCOUNT_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_ACCOUNT))
+#define EMPATHY_ACCOUNT_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNT, \
+    EmpathyAccountClass))
+
+gboolean empathy_account_is_just_connected (EmpathyAccount *account);
+TpConnection *empathy_account_get_connection (EmpathyAccount *account);
+const gchar *empathy_account_get_unique_name (EmpathyAccount *account);
+const gchar *empathy_account_get_display_name (EmpathyAccount *account);
+
+void empathy_account_set_enabled (EmpathyAccount *account,
+  gboolean enabled);
+gboolean empathy_account_is_enabled (EmpathyAccount *account);
+
+void empathy_account_unset_param (EmpathyAccount *account, const gchar *param);
+gchar *empathy_account_get_param_string (EmpathyAccount *account,
+    const gchar *param);
+gint empathy_account_get_param_int (EmpathyAccount *account,
+    const gchar *param);
+gboolean empathy_account_get_param_boolean (EmpathyAccount *account,
+    const gchar *param);
+
+void empathy_account_set_param_string (EmpathyAccount *account,
+    const gchar *param, const gchar *value);
+void empathy_account_set_param_int (EmpathyAccount *account,
+    const gchar *param, gint value);
+void empathy_account_set_param_boolean (EmpathyAccount *account,
+    const gchar *param, gboolean value);
+
+gboolean empathy_account_is_valid (EmpathyAccount *account);
+
+void empathy_account_set_display_name (EmpathyAccount *account,
+    const gchar *display_name);
+
+
+/* TODO remove McProfile */
+McProfile *empathy_account_get_profile (EmpathyAccount *account);
+
+G_END_DECLS
+
+#endif /* #ifndef __EMPATHY_ACCOUNT_H__*/



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]