aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy
diff options
context:
space:
mode:
authorXavier Claessens <xclaesse@src.gnome.org>2007-08-31 00:49:52 +0800
committerXavier Claessens <xclaesse@src.gnome.org>2007-08-31 00:49:52 +0800
commit0b0bb0f621d8e1cda1508d9062a279459fc3b955 (patch)
tree03ad0e8b2180f5e3d6821fbab6315b33c7baf4d8 /libempathy
parent3a535643a694d0dd1bed8e0b7a2fd6fd21e6ee0c (diff)
downloadgsoc2013-empathy-0b0bb0f621d8e1cda1508d9062a279459fc3b955.tar
gsoc2013-empathy-0b0bb0f621d8e1cda1508d9062a279459fc3b955.tar.gz
gsoc2013-empathy-0b0bb0f621d8e1cda1508d9062a279459fc3b955.tar.bz2
gsoc2013-empathy-0b0bb0f621d8e1cda1508d9062a279459fc3b955.tar.lz
gsoc2013-empathy-0b0bb0f621d8e1cda1508d9062a279459fc3b955.tar.xz
gsoc2013-empathy-0b0bb0f621d8e1cda1508d9062a279459fc3b955.tar.zst
gsoc2013-empathy-0b0bb0f621d8e1cda1508d9062a279459fc3b955.zip
Completely reworked ContactList API. Fixes bug #471611, bug #467280, bug #459540 and bug #462907.
svn path=/trunk/; revision=280
Diffstat (limited to 'libempathy')
-rw-r--r--libempathy/Makefile.am6
-rw-r--r--libempathy/empathy-avatar.c2
-rw-r--r--libempathy/empathy-avatar.h4
-rw-r--r--libempathy/empathy-contact-factory.c1102
-rw-r--r--libempathy/empathy-contact-factory.h72
-rw-r--r--libempathy/empathy-contact-list.c147
-rw-r--r--libempathy/empathy-contact-list.h79
-rw-r--r--libempathy/empathy-contact-manager.c684
-rw-r--r--libempathy/empathy-contact-manager.h17
-rw-r--r--libempathy/empathy-contact.c367
-rw-r--r--libempathy/empathy-contact.h89
-rw-r--r--libempathy/empathy-log-manager.c18
-rw-r--r--libempathy/empathy-marshal.list12
-rw-r--r--libempathy/empathy-tp-chat.c39
-rw-r--r--libempathy/empathy-tp-chatroom.c164
-rw-r--r--libempathy/empathy-tp-contact-list.c2205
-rw-r--r--libempathy/empathy-tp-contact-list.h17
-rw-r--r--libempathy/empathy-tp-group.c864
-rw-r--r--libempathy/empathy-tp-group.h71
19 files changed, 3048 insertions, 2911 deletions
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am
index 39dfa9b62..c24a16f21 100644
--- a/libempathy/Makefile.am
+++ b/libempathy/Makefile.am
@@ -17,7 +17,6 @@ lib_LTLIBRARIES = libempathy.la
libempathy_la_SOURCES = \
empathy-conf.c \
- empathy-contact.c \
empathy-avatar.c \
empathy-time.c \
empathy-presence.c \
@@ -26,8 +25,10 @@ libempathy_la_SOURCES = \
empathy-message.c \
empathy-chatroom-manager.c \
empathy-chatroom.c \
+ empathy-contact.c \
empathy-contact-list.c \
empathy-contact-manager.c \
+ empathy-contact-factory.c \
empathy-tp-group.c \
empathy-tp-contact-list.c \
empathy-tp-chat.c \
@@ -50,7 +51,6 @@ libempathy_la_LDFLAGS = \
libempathy_headers = \
empathy-conf.h \
- empathy-contact.h \
empathy-avatar.h \
empathy-time.h \
empathy-presence.h \
@@ -59,8 +59,10 @@ libempathy_headers = \
empathy-message.h \
empathy-chatroom-manager.h \
empathy-chatroom.h \
+ empathy-contact.h \
empathy-contact-list.h \
empathy-contact-manager.h \
+ empathy-contact-factory.h \
empathy-tp-group.h \
empathy-tp-contact-list.h \
empathy-tp-chat.h \
diff --git a/libempathy/empathy-avatar.c b/libempathy/empathy-avatar.c
index e5a2a73a9..425f23f55 100644
--- a/libempathy/empathy-avatar.c
+++ b/libempathy/empathy-avatar.c
@@ -28,7 +28,7 @@
#define DEBUG_DOMAIN "Avatar"
GType
-empathy_avatar_get_gtype (void)
+empathy_avatar_get_type (void)
{
static GType type_id = 0;
diff --git a/libempathy/empathy-avatar.h b/libempathy/empathy-avatar.h
index 73d69cf79..6b28e8e7a 100644
--- a/libempathy/empathy-avatar.h
+++ b/libempathy/empathy-avatar.h
@@ -25,7 +25,7 @@
G_BEGIN_DECLS
-#define EMPATHY_TYPE_AVATAR (empathy_avatar_get_gtype ())
+#define EMPATHY_TYPE_AVATAR (empathy_avatar_get_type ())
typedef struct _EmpathyAvatar EmpathyAvatar;
@@ -36,7 +36,7 @@ struct _EmpathyAvatar {
guint refcount;
};
-GType empathy_avatar_get_gtype (void) G_GNUC_CONST;
+GType empathy_avatar_get_type (void) G_GNUC_CONST;
EmpathyAvatar * empathy_avatar_new (guchar *avatar,
gsize len,
gchar *format);
diff --git a/libempathy/empathy-contact-factory.c b/libempathy/empathy-contact-factory.c
new file mode 100644
index 000000000..1c91a65b6
--- /dev/null
+++ b/libempathy/empathy-contact-factory.c
@@ -0,0 +1,1102 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <libtelepathy/tp-conn.h>
+#include <libtelepathy/tp-conn-iface-aliasing-gen.h>
+#include <libtelepathy/tp-conn-iface-presence-gen.h>
+#include <libtelepathy/tp-conn-iface-avatars-gen.h>
+#include <libmissioncontrol/mission-control.h>
+
+#include "empathy-contact-factory.h"
+#include "empathy-utils.h"
+#include "empathy-debug.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+ EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactoryPriv))
+
+#define DEBUG_DOMAIN "ContactFactory"
+
+struct _EmpathyContactFactoryPriv {
+ MissionControl *mc;
+ GHashTable *accounts;
+};
+
+typedef struct {
+ EmpathyContactFactory *factory;
+ McAccount *account;
+ guint nb_pending_calls;
+
+ TpConn *tp_conn;
+ DBusGProxy *aliasing_iface;
+ DBusGProxy *avatars_iface;
+ DBusGProxy *presence_iface;
+
+ GList *contacts;
+ guint self_handle;
+} ContactFactoryAccountData;
+
+typedef struct {
+ ContactFactoryAccountData *account_data;
+ GList *contacts;
+} RequestHandlesData;
+
+typedef struct {
+ ContactFactoryAccountData *account_data;
+ guint *handles;
+} RequestAliasesData;
+
+typedef struct {
+ ContactFactoryAccountData *account_data;
+ EmpathyContact *contact;
+} RequestAvatarData;
+
+static void empathy_contact_factory_class_init (EmpathyContactFactoryClass *klass);
+static void empathy_contact_factory_init (EmpathyContactFactory *factory);
+
+G_DEFINE_TYPE (EmpathyContactFactory, empathy_contact_factory, G_TYPE_OBJECT);
+
+static gint
+contact_factory_find_by_handle (gconstpointer a,
+ gconstpointer b)
+{
+ EmpathyContact *contact;
+ guint handle;
+
+ contact = EMPATHY_CONTACT (a);
+ handle = GPOINTER_TO_UINT (b);
+
+ return handle - empathy_contact_get_handle (contact);
+}
+
+static EmpathyContact *
+contact_factory_account_data_find_by_handle (ContactFactoryAccountData *account_data,
+ guint handle)
+{
+ GList *l;
+
+ l = g_list_find_custom (account_data->contacts,
+ GUINT_TO_POINTER (handle),
+ contact_factory_find_by_handle);
+
+ return l ? l->data : NULL;
+}
+
+static gint
+contact_factory_find_by_id (gconstpointer a,
+ gconstpointer b)
+{
+ EmpathyContact *contact;
+ const gchar *id = b;
+
+ contact = EMPATHY_CONTACT (a);
+
+ return strcmp (id, empathy_contact_get_id (contact));
+}
+
+static EmpathyContact *
+contact_factory_account_data_find_by_id (ContactFactoryAccountData *account_data,
+ const gchar *id)
+{
+ GList *l;
+
+ l = g_list_find_custom (account_data->contacts,
+ id,
+ contact_factory_find_by_id);
+
+ return l ? l->data : NULL;
+}
+
+static void contact_factory_account_data_free (gpointer data);
+
+static void
+contact_factory_account_data_return_call (ContactFactoryAccountData *account_data)
+{
+ if (--account_data->nb_pending_calls == 0 &&
+ account_data->contacts == NULL) {
+ contact_factory_account_data_free (account_data);
+ }
+}
+
+static void
+contact_factory_presences_table_foreach (const gchar *state_str,
+ GHashTable *presences_table,
+ EmpathyPresence **presence)
+{
+ McPresence state;
+ const GValue *message;
+
+ state = empathy_presence_state_from_str (state_str);
+ if (state == MC_PRESENCE_UNSET) {
+ return;
+ }
+
+ if (*presence) {
+ g_object_unref (*presence);
+ *presence = NULL;
+ }
+
+ *presence = empathy_presence_new ();
+ empathy_presence_set_state (*presence, state);
+
+ message = g_hash_table_lookup (presences_table, "message");
+ if (message != NULL) {
+ empathy_presence_set_status (*presence,
+ g_value_get_string (message));
+ }
+}
+
+static void
+contact_factory_parse_presence_foreach (guint handle,
+ GValueArray *presence_struct,
+ ContactFactoryAccountData *account_data)
+{
+ GHashTable *presences_table;
+ EmpathyContact *contact;
+ EmpathyPresence *presence = NULL;
+
+ contact = contact_factory_account_data_find_by_handle (account_data,
+ handle);
+ if (!contact) {
+ return;
+ }
+
+ presences_table = g_value_get_boxed (g_value_array_get_nth (presence_struct, 1));
+
+ g_hash_table_foreach (presences_table,
+ (GHFunc) contact_factory_presences_table_foreach,
+ &presence);
+
+ empathy_debug (DEBUG_DOMAIN, "Changing presence for contact %s (%d) to %s (%d)",
+ empathy_contact_get_id (contact),
+ handle,
+ presence ? empathy_presence_get_status (presence) : "unset",
+ presence ? empathy_presence_get_state (presence) : MC_PRESENCE_UNSET);
+
+ empathy_contact_set_presence (contact, presence);
+}
+
+static void
+contact_factory_get_presence_cb (DBusGProxy *proxy,
+ GHashTable *handle_table,
+ GError *error,
+ gpointer user_data)
+{
+ ContactFactoryAccountData *account_data = user_data;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
+ error->message);
+ goto OUT;
+ }
+
+ g_hash_table_foreach (handle_table,
+ (GHFunc) contact_factory_parse_presence_foreach,
+ account_data);
+OUT:
+ contact_factory_account_data_return_call (account_data);
+}
+
+static void
+contact_factory_presence_update_cb (DBusGProxy *proxy,
+ GHashTable *handle_table,
+ ContactFactoryAccountData *account_data)
+{
+ g_hash_table_foreach (handle_table,
+ (GHFunc) contact_factory_parse_presence_foreach,
+ account_data);
+}
+
+static void
+contact_factory_set_aliases_cb (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data)
+{
+ ContactFactoryAccountData *account_data = user_data;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Error setting alias: %s",
+ error->message);
+ }
+
+ contact_factory_account_data_return_call (account_data);
+}
+
+static void
+contact_factory_request_aliases_cb (DBusGProxy *proxy,
+ gchar **contact_names,
+ GError *error,
+ gpointer user_data)
+{
+ RequestAliasesData *data = user_data;
+ guint i = 0;
+ gchar **name;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
+ error->message);
+ goto OUT;
+ }
+
+ for (name = contact_names; *name; name++) {
+ EmpathyContact *contact;
+
+ contact = contact_factory_account_data_find_by_handle (data->account_data,
+ data->handles[i]);
+ if (!contact) {
+ continue;
+ }
+
+ empathy_debug (DEBUG_DOMAIN, "Renaming contact %s (%d) to %s (request cb)",
+ empathy_contact_get_id (contact),
+ data->handles[i], *name);
+
+ empathy_contact_set_name (contact, *name);
+
+ i++;
+ }
+
+OUT:
+ contact_factory_account_data_return_call (data->account_data);
+ g_free (data->handles);
+ g_slice_free (RequestAliasesData, data);
+}
+
+static void
+contact_factory_aliases_changed_cb (DBusGProxy *proxy,
+ GPtrArray *renamed_handlers,
+ gpointer user_data)
+{
+ ContactFactoryAccountData *account_data = user_data;
+ guint i;
+
+ for (i = 0; renamed_handlers->len > i; i++) {
+ guint handle;
+ const gchar *alias;
+ GValueArray *renamed_struct;
+ EmpathyContact *contact;
+
+ renamed_struct = g_ptr_array_index (renamed_handlers, i);
+ handle = g_value_get_uint(g_value_array_get_nth (renamed_struct, 0));
+ alias = g_value_get_string(g_value_array_get_nth (renamed_struct, 1));
+ contact = contact_factory_account_data_find_by_handle (account_data, handle);
+
+ if (!contact) {
+ /* We don't know this contact, skip */
+ continue;
+ }
+
+ if (G_STR_EMPTY (alias)) {
+ alias = NULL;
+ }
+
+ empathy_debug (DEBUG_DOMAIN, "Renaming contact %s (%d) to %s (changed cb)",
+ empathy_contact_get_id (contact),
+ handle, alias);
+
+ empathy_contact_set_name (contact, alias);
+ }
+}
+
+static void
+contact_factory_request_avatars_cb (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data)
+{
+ ContactFactoryAccountData *account_data = user_data;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Error requesting avatars: %s",
+ error->message);
+ }
+
+ contact_factory_account_data_return_call (account_data);
+}
+
+static void
+contact_factory_request_avatar_cb (DBusGProxy *proxy,
+ GArray *avatar_data,
+ gchar *mime_type,
+ GError *error,
+ gpointer user_data)
+{
+ RequestAvatarData *data = user_data;
+ EmpathyAvatar *avatar;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Error requesting avatar: %s",
+ error->message);
+ goto OUT;
+ }
+
+ empathy_debug (DEBUG_DOMAIN, "Avatar received for %s (%d)",
+ empathy_contact_get_id (data->contact),
+ empathy_contact_get_handle (data->contact));
+
+ avatar = empathy_avatar_new (avatar_data->data,
+ avatar_data->len,
+ mime_type);
+ empathy_contact_set_avatar (data->contact, avatar);
+ empathy_avatar_unref (avatar);
+
+OUT:
+ g_object_unref (data->contact);
+ contact_factory_account_data_return_call (data->account_data);
+ g_slice_free (RequestAvatarData, data);
+}
+
+static void
+contact_factory_avatar_updated_cb (DBusGProxy *proxy,
+ guint handle,
+ gchar *new_token,
+ gpointer user_data)
+{
+ ContactFactoryAccountData *account_data = user_data;
+ RequestAvatarData *data;
+ EmpathyContact *contact;
+
+ contact = contact_factory_account_data_find_by_handle (account_data,
+ handle);
+ if (!contact) {
+ return;
+ }
+
+ account_data->nb_pending_calls++;
+ data = g_slice_new0 (RequestAvatarData);
+ data->account_data = account_data;
+ data->contact = g_object_ref (contact);
+ tp_conn_iface_avatars_request_avatar_async (account_data->avatars_iface,
+ handle,
+ contact_factory_request_avatar_cb,
+ data);
+}
+
+static void
+contact_factory_avatar_retrieved_cb (DBusGProxy *proxy,
+ guint handle,
+ gchar *token,
+ GArray *avatar_data,
+ gchar *mime_type,
+ gpointer user_data)
+{
+ ContactFactoryAccountData *account_data = user_data;
+ EmpathyContact *contact;
+ EmpathyAvatar *avatar;
+
+ contact = contact_factory_account_data_find_by_handle (account_data,
+ handle);
+ if (!contact) {
+ return;
+ }
+
+ avatar = empathy_avatar_new (avatar_data->data,
+ avatar_data->len,
+ mime_type);
+ empathy_contact_set_avatar (contact, avatar);
+ empathy_avatar_unref (avatar);
+}
+
+static void
+contact_factory_request_everything (ContactFactoryAccountData *account_data,
+ GArray *handles)
+{
+ if (account_data->presence_iface) {
+ account_data->nb_pending_calls++;
+ tp_conn_iface_presence_get_presence_async (account_data->presence_iface,
+ handles,
+ contact_factory_get_presence_cb,
+ account_data);
+ }
+
+ if (account_data->aliasing_iface) {
+ RequestAliasesData *data;
+
+ account_data->nb_pending_calls++;
+ data = g_slice_new (RequestAliasesData);
+ data->account_data = account_data;
+ data->handles = g_memdup (handles->data, handles->len * sizeof (guint));
+
+ tp_conn_iface_aliasing_request_aliases_async (account_data->aliasing_iface,
+ handles,
+ contact_factory_request_aliases_cb,
+ data);
+ }
+
+ if (account_data->avatars_iface) {
+ account_data->nb_pending_calls++;
+ tp_conn_iface_avatars_request_avatars_async (account_data->avatars_iface,
+ handles,
+ contact_factory_request_avatars_cb,
+ account_data);
+ }
+}
+
+static void
+contact_factory_request_handles_cb (DBusGProxy *proxy,
+ GArray *handles,
+ GError *error,
+ gpointer user_data)
+{
+ RequestHandlesData *data = user_data;
+ GList *l;
+ guint i = 0;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to request handles: %s",
+ error->message);
+ goto OUT;
+ }
+
+ for (l = data->contacts; l; l = l->next) {
+ guint handle;
+
+ handle = g_array_index (handles, guint, i);
+ empathy_contact_set_handle (l->data, handle);
+ if (handle == data->account_data->self_handle) {
+ empathy_contact_set_is_user (l->data, TRUE);
+ }
+
+ i++;
+ }
+
+ contact_factory_request_everything (data->account_data, handles);
+
+OUT:
+ g_list_foreach (data->contacts, (GFunc) g_object_unref, NULL);
+ g_list_free (data->contacts);
+ contact_factory_account_data_return_call (data->account_data);
+ g_slice_free (RequestHandlesData, data);
+}
+
+static void
+contact_factory_disconnect_contact_foreach (gpointer data,
+ gpointer user_data)
+{
+ EmpathyContact *contact = data;
+
+ empathy_contact_set_presence (contact, NULL);
+ empathy_contact_set_handle (contact, 0);
+}
+
+static void
+contact_factory_destroy_cb (TpConn *tp_conn,
+ ContactFactoryAccountData *account_data)
+{
+ empathy_debug (DEBUG_DOMAIN, "Account disconnected or CM crashed");
+
+ g_object_unref (account_data->tp_conn);
+ account_data->tp_conn = NULL;
+ account_data->aliasing_iface = NULL;
+ account_data->avatars_iface = NULL;
+ account_data->presence_iface = NULL;
+
+ g_list_foreach (account_data->contacts,
+ contact_factory_disconnect_contact_foreach,
+ account_data);
+}
+
+static void
+contact_factory_account_data_disconnect (ContactFactoryAccountData *account_data)
+{
+ if (account_data->aliasing_iface) {
+ dbus_g_proxy_disconnect_signal (account_data->aliasing_iface,
+ "AliasesChanged",
+ G_CALLBACK (contact_factory_aliases_changed_cb),
+ account_data);
+ }
+ if (account_data->avatars_iface) {
+ dbus_g_proxy_disconnect_signal (account_data->avatars_iface,
+ "AvatarUpdated",
+ G_CALLBACK (contact_factory_avatar_updated_cb),
+ account_data);
+ dbus_g_proxy_disconnect_signal (account_data->avatars_iface,
+ "AvatarRetrieved",
+ G_CALLBACK (contact_factory_avatar_retrieved_cb),
+ account_data);
+ }
+ if (account_data->presence_iface) {
+ dbus_g_proxy_disconnect_signal (account_data->presence_iface,
+ "PresenceUpdate",
+ G_CALLBACK (contact_factory_presence_update_cb),
+ account_data);
+ }
+ if (account_data->tp_conn) {
+ g_signal_handlers_disconnect_by_func (account_data->tp_conn,
+ contact_factory_destroy_cb,
+ account_data);
+ }
+}
+
+static void
+contact_factory_account_data_update (ContactFactoryAccountData *account_data)
+{
+ EmpathyContactFactory *factory = account_data->factory;
+ EmpathyContactFactoryPriv *priv = GET_PRIV (factory);
+ McAccount *account = account_data->account;
+ TpConn *tp_conn = NULL;
+ RequestHandlesData *data;
+ const gchar **contact_ids;
+ guint i;
+ GList *l;
+ GError *error;
+
+ if (account_data->account) {
+ guint status;
+
+ /* status == 0 means the status is CONNECTED */
+ status = mission_control_get_connection_status (priv->mc,
+ account, NULL);
+ if (status == 0) {
+ tp_conn = mission_control_get_connection (priv->mc,
+ account, NULL);
+ }
+ }
+
+ if (!tp_conn) {
+ /* We are not connected anymore, remove the old connection */
+ contact_factory_account_data_disconnect (account_data);
+ if (account_data->tp_conn) {
+ contact_factory_destroy_cb (account_data->tp_conn,
+ account_data);
+ }
+ return;
+ }
+ else if (account_data->tp_conn) {
+ /* We were connected and we still are connected, nothing
+ * changed so nothing to do. */
+ g_object_unref (tp_conn);
+ return;
+ }
+
+ /* We got a new connection */
+ account_data->tp_conn = tp_conn;
+ account_data->aliasing_iface = tp_conn_get_interface (tp_conn,
+ TELEPATHY_CONN_IFACE_ALIASING_QUARK);
+ account_data->avatars_iface = tp_conn_get_interface (tp_conn,
+ TELEPATHY_CONN_IFACE_AVATARS_QUARK);
+ account_data->presence_iface = tp_conn_get_interface (tp_conn,
+ TELEPATHY_CONN_IFACE_PRESENCE_QUARK);
+
+ /* Connect signals */
+ if (account_data->aliasing_iface) {
+ dbus_g_proxy_connect_signal (account_data->aliasing_iface,
+ "AliasesChanged",
+ G_CALLBACK (contact_factory_aliases_changed_cb),
+ account_data, NULL);
+ }
+ if (account_data->avatars_iface) {
+ dbus_g_proxy_connect_signal (account_data->avatars_iface,
+ "AvatarUpdated",
+ G_CALLBACK (contact_factory_avatar_updated_cb),
+ account_data, NULL);
+ dbus_g_proxy_connect_signal (account_data->avatars_iface,
+ "AvatarRetrieved",
+ G_CALLBACK (contact_factory_avatar_retrieved_cb),
+ account_data, NULL);
+ }
+ if (account_data->presence_iface) {
+ dbus_g_proxy_connect_signal (account_data->presence_iface,
+ "PresenceUpdate",
+ G_CALLBACK (contact_factory_presence_update_cb),
+ account_data, NULL);
+ }
+ g_signal_connect (tp_conn, "destroy",
+ G_CALLBACK (contact_factory_destroy_cb),
+ account_data);
+
+ /* Get our own handle */
+ if (!tp_conn_get_self_handle (DBUS_G_PROXY (account_data->tp_conn),
+ &account_data->self_handle,
+ &error)) {
+ empathy_debug (DEBUG_DOMAIN, "GetSelfHandle Error: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ }
+
+ /* Request new handles for all contacts */
+ if (account_data->contacts) {
+ data = g_slice_new (RequestHandlesData);
+ data->account_data = account_data;
+ data->contacts = g_list_copy (account_data->contacts);
+ g_list_foreach (data->contacts, (GFunc) g_object_ref, NULL);
+
+ i = g_list_length (data->contacts);
+ contact_ids = g_new0 (const gchar*, i + 1);
+ i = 0;
+ for (l = data->contacts; l; l = l->next) {
+ contact_ids[i] = empathy_contact_get_id (l->data);
+ i++;
+ }
+
+ account_data->nb_pending_calls++;
+ tp_conn_request_handles_async (DBUS_G_PROXY (account_data->tp_conn),
+ TP_HANDLE_TYPE_CONTACT,
+ contact_ids,
+ contact_factory_request_handles_cb,
+ data);
+ g_free (contact_ids);
+ }
+}
+
+static void
+contact_factory_weak_notify (gpointer data,
+ GObject *where_the_object_was)
+{
+ ContactFactoryAccountData *account_data = data;
+
+ empathy_debug (DEBUG_DOMAIN, "Remove finalized contact %p",
+ where_the_object_was);
+
+ account_data->contacts = g_list_remove (account_data->contacts,
+ where_the_object_was);
+ if (!account_data->contacts) {
+ EmpathyContactFactoryPriv *priv;
+
+ priv = GET_PRIV (account_data->factory);
+
+ g_hash_table_remove (priv->accounts, account_data->account);
+ }
+}
+
+static void
+contact_factory_remove_foreach (gpointer data,
+ gpointer user_data)
+{
+ ContactFactoryAccountData *account_data = user_data;
+ EmpathyContact *contact = data;
+
+ g_object_weak_unref (G_OBJECT (contact),
+ contact_factory_weak_notify,
+ account_data);
+}
+
+static ContactFactoryAccountData *
+contact_factory_account_data_new (EmpathyContactFactory *factory,
+ McAccount *account)
+{
+ ContactFactoryAccountData *account_data;
+
+ account_data = g_slice_new0 (ContactFactoryAccountData);
+ account_data->factory = factory;
+ account_data->account = g_object_ref (account);
+
+ contact_factory_account_data_update (account_data);
+
+ return account_data;
+}
+
+static void
+contact_factory_account_data_free (gpointer data)
+{
+ ContactFactoryAccountData *account_data = data;
+
+ contact_factory_account_data_disconnect (account_data);
+
+ if (account_data->contacts) {
+ g_list_foreach (account_data->contacts,
+ contact_factory_remove_foreach,
+ account_data);
+ g_list_free (account_data->contacts);
+ account_data->contacts = NULL;
+ }
+
+ if (account_data->account) {
+ g_object_unref (account_data->account);
+ account_data->account = NULL;
+ }
+
+ if (account_data->tp_conn) {
+ g_object_unref (account_data->tp_conn);
+ account_data->tp_conn = NULL;
+ account_data->aliasing_iface = NULL;
+ account_data->avatars_iface = NULL;
+ account_data->presence_iface = NULL;
+ }
+
+ /* Keep the struct alive if we have calls in flight, it will be
+ * destroyed once all calls returned. */
+ if (account_data->nb_pending_calls == 0) {
+ g_slice_free (ContactFactoryAccountData, account_data);
+ }
+}
+
+static void
+contact_factory_status_changed_cb (MissionControl *mc,
+ TelepathyConnectionStatus status,
+ McPresence presence,
+ TelepathyConnectionStatusReason reason,
+ const gchar *unique_name,
+ EmpathyContactFactory *factory)
+{
+ EmpathyContactFactoryPriv *priv = GET_PRIV (factory);
+ ContactFactoryAccountData *account_data;
+ McAccount *account;
+
+ account = mc_account_lookup (unique_name);
+ account_data = g_hash_table_lookup (priv->accounts, account);
+ if (account_data) {
+ contact_factory_account_data_update (account_data);
+ }
+ g_object_unref (account);
+}
+
+static ContactFactoryAccountData *
+contact_factory_account_data_get (EmpathyContactFactory *factory,
+ McAccount *account)
+{
+ EmpathyContactFactoryPriv *priv = GET_PRIV (factory);
+ ContactFactoryAccountData *account_data;
+
+ account_data = g_hash_table_lookup (priv->accounts, account);
+ if (!account_data) {
+ account_data = contact_factory_account_data_new (factory, account);
+ g_hash_table_insert (priv->accounts,
+ g_object_ref (account),
+ account_data);
+ }
+
+ return account_data;
+}
+
+static void
+contact_factory_account_data_add_contact (ContactFactoryAccountData *account_data,
+ EmpathyContact *contact)
+{
+ g_object_weak_ref (G_OBJECT (contact),
+ contact_factory_weak_notify,
+ account_data);
+ account_data->contacts = g_list_prepend (account_data->contacts, contact);
+
+ if (!account_data->presence_iface) {
+ EmpathyPresence *presence;
+
+ /* We have no presence iface, set default presence
+ * to available */
+ presence = empathy_presence_new_full (MC_PRESENCE_AVAILABLE,
+ NULL);
+
+ empathy_contact_set_presence (contact, presence);
+ g_object_unref (presence);
+ }
+
+ empathy_debug (DEBUG_DOMAIN, "Contact added: %s (%d)",
+ empathy_contact_get_id (contact),
+ empathy_contact_get_handle (contact));
+}
+
+static void
+contact_factory_hold_handles_cb (DBusGProxy *proxy,
+ GError *error,
+ gpointer userdata)
+{
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to hold handles: %s",
+ error->message);
+ }
+}
+
+EmpathyContact *
+empathy_contact_factory_get_user (EmpathyContactFactory *factory,
+ McAccount *account)
+{
+ ContactFactoryAccountData *account_data;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+ g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+
+ account_data = contact_factory_account_data_get (factory, account);
+
+ return empathy_contact_factory_get_from_handle (factory, account,
+ account_data->self_handle);
+}
+
+EmpathyContact *
+empathy_contact_factory_get_from_id (EmpathyContactFactory *factory,
+ McAccount *account,
+ const gchar *id)
+{
+ ContactFactoryAccountData *account_data;
+ EmpathyContact *contact;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+ g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+ g_return_val_if_fail (id != NULL, NULL);
+
+ /* Check if the contact already exists */
+ account_data = contact_factory_account_data_get (factory, account);
+ contact = contact_factory_account_data_find_by_id (account_data, id);
+ if (contact) {
+ return g_object_ref (contact);
+ }
+
+ /* Create new contact */
+ contact = g_object_new (EMPATHY_TYPE_CONTACT,
+ "account", account,
+ "id", id,
+ NULL);
+ contact_factory_account_data_add_contact (account_data, contact);
+
+ /* If the account is connected, request contact's handle */
+ if (account_data->tp_conn) {
+ RequestHandlesData *data;
+ const gchar *contact_ids[] = {id, NULL};
+
+ account_data->nb_pending_calls++;
+ data = g_slice_new (RequestHandlesData);
+ data->account_data = account_data;
+ data->contacts = g_list_prepend (NULL, g_object_ref (contact));
+ tp_conn_request_handles_async (DBUS_G_PROXY (account_data->tp_conn),
+ TP_HANDLE_TYPE_CONTACT,
+ contact_ids,
+ contact_factory_request_handles_cb,
+ data);
+ }
+
+ return contact;
+}
+
+EmpathyContact *
+empathy_contact_factory_get_from_handle (EmpathyContactFactory *factory,
+ McAccount *account,
+ guint handle)
+{
+ EmpathyContact *contact;
+ GArray *handles;
+ GList *contacts;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+ g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+
+ handles = g_array_new (FALSE, FALSE, sizeof (guint));
+ g_array_append_val (handles, handle);
+
+ contacts = empathy_contact_factory_get_from_handles (factory, account, handles);
+ g_array_free (handles, TRUE);
+
+ contact = contacts ? contacts->data : NULL;
+ g_list_free (contacts);
+
+ return contact;
+}
+
+GList *
+empathy_contact_factory_get_from_handles (EmpathyContactFactory *factory,
+ McAccount *account,
+ GArray *handles)
+{
+ ContactFactoryAccountData *account_data;
+ GList *contacts = NULL;
+ GArray *new_handles;
+ gchar **handles_names;
+ guint i;
+ GError *error = NULL;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory), NULL);
+ g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+ g_return_val_if_fail (handles != NULL, NULL);
+
+ /* Search all contacts we already have */
+ account_data = contact_factory_account_data_get (factory, account);
+ new_handles = g_array_new (FALSE, FALSE, sizeof (guint));
+ for (i = 0; i < handles->len; i++) {
+ EmpathyContact *contact;
+ guint handle;
+
+ handle = g_array_index (handles, guint, i);
+ if (handle == 0) {
+ continue;
+ }
+
+ contact = contact_factory_account_data_find_by_handle (account_data, handle);
+ if (contact) {
+ contacts = g_list_prepend (contacts, g_object_ref (contact));
+ } else {
+ g_array_append_val (new_handles, handle);
+ }
+ }
+
+ if (new_handles->len == 0) {
+ g_array_free (new_handles, TRUE);
+ return contacts;
+ }
+
+ /* Get the IDs of all new handles */
+ if (!tp_conn_inspect_handles (DBUS_G_PROXY (account_data->tp_conn),
+ TP_HANDLE_TYPE_CONTACT,
+ new_handles,
+ &handles_names,
+ &error)) {
+ empathy_debug (DEBUG_DOMAIN,
+ "Couldn't inspect contact: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ g_array_free (new_handles, TRUE);
+ return contacts;
+ }
+
+ /* Create new contacts */
+ for (i = 0; i < new_handles->len; i++) {
+ EmpathyContact *contact;
+ gchar *id;
+ guint handle;
+ gboolean is_user;
+
+ id = handles_names[i];
+ handle = g_array_index (new_handles, guint, i);
+
+ is_user = (handle == account_data->self_handle);
+ contact = g_object_new (EMPATHY_TYPE_CONTACT,
+ "account", account,
+ "handle", handle,
+ "id", id,
+ "is-user", is_user,
+ NULL);
+ contact_factory_account_data_add_contact (account_data,
+ contact);
+ contacts = g_list_prepend (contacts, contact);
+ g_free (id);
+ }
+ g_free (handles_names);
+
+ /* Hold all new handles. */
+ tp_conn_hold_handles_async (DBUS_G_PROXY (account_data->tp_conn),
+ TP_HANDLE_TYPE_CONTACT,
+ new_handles,
+ contact_factory_hold_handles_cb,
+ NULL);
+
+ contact_factory_request_everything (account_data, new_handles);
+
+ g_array_free (new_handles, TRUE);
+
+ return contacts;
+}
+
+void
+empathy_contact_factory_set_name (EmpathyContactFactory *factory,
+ EmpathyContact *contact,
+ const gchar *name)
+{
+ ContactFactoryAccountData *account_data;
+ McAccount *account;
+ GHashTable *new_alias;
+ guint handle;
+
+ g_return_if_fail (EMPATHY_IS_CONTACT_FACTORY (factory));
+ g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+ account = empathy_contact_get_account (contact);
+ account_data = contact_factory_account_data_get (factory, account);
+
+ if (!account_data->aliasing_iface) {
+ return;
+ }
+
+ handle = empathy_contact_get_handle (contact);
+
+ empathy_debug (DEBUG_DOMAIN, "Setting alias for contact %s (%d) to %s",
+ empathy_contact_get_id (contact),
+ handle, name);
+
+ new_alias = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ g_free);
+
+ g_hash_table_insert (new_alias,
+ GUINT_TO_POINTER (handle),
+ g_strdup (name));
+
+ account_data->nb_pending_calls++;
+ tp_conn_iface_aliasing_set_aliases_async (account_data->aliasing_iface,
+ new_alias,
+ contact_factory_set_aliases_cb,
+ account_data);
+
+ g_hash_table_destroy (new_alias);
+}
+
+static void
+contact_factory_finalize (GObject *object)
+{
+ EmpathyContactFactoryPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
+ "AccountStatusChanged",
+ G_CALLBACK (contact_factory_status_changed_cb),
+ object);
+
+ g_hash_table_destroy (priv->accounts);
+ g_object_unref (priv->mc);
+
+ G_OBJECT_CLASS (empathy_contact_factory_parent_class)->finalize (object);
+}
+
+static void
+empathy_contact_factory_class_init (EmpathyContactFactoryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = contact_factory_finalize;
+
+ g_type_class_add_private (object_class, sizeof (EmpathyContactFactoryPriv));
+}
+
+static void
+empathy_contact_factory_init (EmpathyContactFactory *factory)
+{
+ EmpathyContactFactoryPriv *priv;
+
+ priv = GET_PRIV (factory);
+
+ priv->mc = empathy_mission_control_new ();
+ priv->accounts = g_hash_table_new_full (empathy_account_hash,
+ empathy_account_equal,
+ g_object_unref,
+ contact_factory_account_data_free);
+
+ dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
+ "AccountStatusChanged",
+ G_CALLBACK (contact_factory_status_changed_cb),
+ factory, NULL);
+}
+
+EmpathyContactFactory *
+empathy_contact_factory_new (void)
+{
+ static EmpathyContactFactory *factory = NULL;
+
+ if (!factory) {
+ factory = g_object_new (EMPATHY_TYPE_CONTACT_FACTORY, NULL);
+ g_object_add_weak_pointer (G_OBJECT (factory), (gpointer) &factory);
+ } else {
+ g_object_ref (factory);
+ }
+
+ return factory;
+}
+
diff --git a/libempathy/empathy-contact-factory.h b/libempathy/empathy-contact-factory.h
new file mode 100644
index 000000000..1379371ab
--- /dev/null
+++ b/libempathy/empathy-contact-factory.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_CONTACT_FACTORY_H__
+#define __EMPATHY_CONTACT_FACTORY_H__
+
+#include <glib.h>
+
+#include <libmissioncontrol/mc-account.h>
+
+#include "empathy-contact.h"
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_CONTACT_FACTORY (empathy_contact_factory_get_type ())
+#define EMPATHY_CONTACT_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactory))
+#define EMPATHY_CONTACT_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactoryClass))
+#define EMPATHY_IS_CONTACT_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CONTACT_FACTORY))
+#define EMPATHY_IS_CONTACT_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_CONTACT_FACTORY))
+#define EMPATHY_CONTACT_FACTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_CONTACT_FACTORY, EmpathyContactFactoryClass))
+
+typedef struct _EmpathyContactFactory EmpathyContactFactory;
+typedef struct _EmpathyContactFactoryClass EmpathyContactFactoryClass;
+typedef struct _EmpathyContactFactoryPriv EmpathyContactFactoryPriv;
+
+struct _EmpathyContactFactory {
+ GObject parent;
+};
+
+struct _EmpathyContactFactoryClass {
+ GObjectClass parent_class;
+};
+
+GType empathy_contact_factory_get_type (void) G_GNUC_CONST;
+EmpathyContactFactory *empathy_contact_factory_new (void);
+EmpathyContact * empathy_contact_factory_get_user (EmpathyContactFactory *factory,
+ McAccount *account);
+EmpathyContact * empathy_contact_factory_get_from_id (EmpathyContactFactory *factory,
+ McAccount *account,
+ const gchar *id);
+EmpathyContact * empathy_contact_factory_get_from_handle (EmpathyContactFactory *factory,
+ McAccount *account,
+ guint handle);
+GList * empathy_contact_factory_get_from_handles (EmpathyContactFactory *factory,
+ McAccount *account,
+ GArray *handles);
+void empathy_contact_factory_set_name (EmpathyContactFactory *factory,
+ EmpathyContact *contact,
+ const gchar *name);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_CONTACT_FACTORY_H__ */
diff --git a/libempathy/empathy-contact-list.c b/libempathy/empathy-contact-list.c
index cc388d7ec..80308314e 100644
--- a/libempathy/empathy-contact-list.c
+++ b/libempathy/empathy-contact-list.c
@@ -53,149 +53,154 @@ contact_list_base_init (gpointer klass)
static gboolean initialized = FALSE;
if (!initialized) {
- g_signal_new ("contact-added",
+ g_signal_new ("members-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
+ empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING_BOOLEAN,
G_TYPE_NONE,
- 1, EMPATHY_TYPE_CONTACT);
+ 5, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT,
+ G_TYPE_UINT, G_TYPE_STRING, G_TYPE_BOOLEAN);
- g_signal_new ("contact-removed",
+ g_signal_new ("pendings-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
+ empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING_BOOLEAN,
G_TYPE_NONE,
- 1, EMPATHY_TYPE_CONTACT);
+ 5, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT,
+ G_TYPE_UINT, G_TYPE_STRING, G_TYPE_BOOLEAN);
- g_signal_new ("local-pending",
+ g_signal_new ("groups-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- empathy_marshal_VOID__OBJECT_STRING,
+ empathy_marshal_VOID__OBJECT_STRING_BOOLEAN,
G_TYPE_NONE,
- 2, EMPATHY_TYPE_CONTACT, G_TYPE_STRING);
+ 3, EMPATHY_TYPE_CONTACT, G_TYPE_STRING, G_TYPE_BOOLEAN);
initialized = TRUE;
}
}
-EmpathyContactListInfo *
-empathy_contact_list_info_new (EmpathyContact *contact,
- const gchar *message)
-{
- EmpathyContactListInfo *info;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
- info = g_slice_new0 (EmpathyContactListInfo);
- info->contact = g_object_ref (contact);
- info->message = g_strdup (message);
-
- return info;
-}
-
void
-empathy_contact_list_info_free (EmpathyContactListInfo *info)
+empathy_contact_list_add (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message)
{
- if (!info) {
- return;
- }
+ g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+ g_return_if_fail (EMPATHY_IS_CONTACT (contact));
- if (info->contact) {
- g_object_unref (info->contact);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->add) {
+ EMPATHY_CONTACT_LIST_GET_IFACE (list)->add (list, contact, message);
}
- g_free (info->message);
-
- g_slice_free (EmpathyContactListInfo, info);
}
void
-empathy_contact_list_setup (EmpathyContactList *list)
+empathy_contact_list_remove (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message)
{
g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+ g_return_if_fail (EMPATHY_IS_CONTACT (contact));
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->setup) {
- EMPATHY_CONTACT_LIST_GET_IFACE (list)->setup (list);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove) {
+ EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove (list, contact, message);
}
}
-EmpathyContact *
-empathy_contact_list_find (EmpathyContactList *list,
- const gchar *id)
+GList *
+empathy_contact_list_get_members (EmpathyContactList *list)
{
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->find) {
- return EMPATHY_CONTACT_LIST_GET_IFACE (list)->find (list, id);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members (list);
}
return NULL;
}
-void
-empathy_contact_list_add (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message)
+GList *
+empathy_contact_list_get_pendings (EmpathyContactList *list)
{
- g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->add) {
- EMPATHY_CONTACT_LIST_GET_IFACE (list)->add (list, contact, message);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_pendings) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_pendings (list);
}
+
+ return NULL;
}
-void
-empathy_contact_list_remove (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message)
+GList *
+empathy_contact_list_get_all_groups (EmpathyContactList *list)
{
- g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove) {
- EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove (list, contact, message);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_all_groups) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_all_groups (list);
}
+
+ return NULL;
}
GList *
-empathy_contact_list_get_members (EmpathyContactList *list)
+empathy_contact_list_get_groups (EmpathyContactList *list,
+ EmpathyContact *contact)
{
g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members) {
- return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members (list);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_groups) {
+ return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_groups (list, contact);
}
return NULL;
}
-GList *
-empathy_contact_list_get_local_pending (EmpathyContactList *list)
+void
+empathy_contact_list_add_to_group (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group)
{
- g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL);
+ g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+ g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+ g_return_if_fail (group != NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending) {
- return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending (list);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->add_to_group) {
+ EMPATHY_CONTACT_LIST_GET_IFACE (list)->add_to_group (list, contact, group);
}
+}
- return NULL;
+void
+empathy_contact_list_remove_from_group (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group)
+{
+ g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+ g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+ g_return_if_fail (group != NULL);
+
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove_from_group) {
+ EMPATHY_CONTACT_LIST_GET_IFACE (list)->remove_from_group (list, contact, group);
+ }
}
void
-empathy_contact_list_process_pending (EmpathyContactList *list,
- EmpathyContact *contact,
- gboolean accept)
+empathy_contact_list_rename_group (EmpathyContactList *list,
+ const gchar *old_group,
+ const gchar *new_group)
{
g_return_if_fail (EMPATHY_IS_CONTACT_LIST (list));
+ g_return_if_fail (old_group != NULL);
+ g_return_if_fail (new_group != NULL);
- if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->process_pending) {
- EMPATHY_CONTACT_LIST_GET_IFACE (list)->process_pending (list,
- contact,
- accept);
+ if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->rename_group) {
+ EMPATHY_CONTACT_LIST_GET_IFACE (list)->rename_group (list, old_group, new_group);
}
}
diff --git a/libempathy/empathy-contact-list.h b/libempathy/empathy-contact-list.h
index 959f5c51f..4b027f083 100644
--- a/libempathy/empathy-contact-list.h
+++ b/libempathy/empathy-contact-list.h
@@ -26,6 +26,7 @@
#include <glib-object.h>
#include "empathy-contact.h"
+#include "empathy-tp-group.h"
G_BEGIN_DECLS
@@ -37,49 +38,53 @@ G_BEGIN_DECLS
typedef struct _EmpathyContactList EmpathyContactList;
typedef struct _EmpathyContactListIface EmpathyContactListIface;
-typedef struct {
- EmpathyContact *contact;
- gchar *message;
-} EmpathyContactListInfo;
-
struct _EmpathyContactListIface {
GTypeInterface base_iface;
/* VTabled */
- void (*setup) (EmpathyContactList *list);
- EmpathyContact * (*find) (EmpathyContactList *list,
- const gchar *id);
- void (*add) (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message);
- void (*remove) (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message);
- GList * (*get_members) (EmpathyContactList *list);
- GList * (*get_local_pending) (EmpathyContactList *list);
- void (*process_pending) (EmpathyContactList *list,
- EmpathyContact *contact,
- gboolean accept);
+ void (*add) (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message);
+ void (*remove) (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message);
+ GList * (*get_members) (EmpathyContactList *list);
+ GList * (*get_pendings) (EmpathyContactList *list);
+ GList * (*get_all_groups) (EmpathyContactList *list);
+ GList * (*get_groups) (EmpathyContactList *list,
+ EmpathyContact *contact);
+ void (*add_to_group) (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group);
+ void (*remove_from_group) (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group);
+ void (*rename_group) (EmpathyContactList *list,
+ const gchar *old_group,
+ const gchar *new_group);
};
-GType empathy_contact_list_get_type (void) G_GNUC_CONST;
-EmpathyContactListInfo *empathy_contact_list_info_new (EmpathyContact *contact,
- const gchar *message);
-void empathy_contact_list_info_free (EmpathyContactListInfo *info);
-void empathy_contact_list_setup (EmpathyContactList *list);
-EmpathyContact * empathy_contact_list_find (EmpathyContactList *list,
- const gchar *id);
-void empathy_contact_list_add (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message);
-void empathy_contact_list_remove (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message);
-GList * empathy_contact_list_get_members (EmpathyContactList *list);
-GList * empathy_contact_list_get_local_pending (EmpathyContactList *list);
-void empathy_contact_list_process_pending (EmpathyContactList *list,
- EmpathyContact *contact,
- gboolean accept);
+GType empathy_contact_list_get_type (void) G_GNUC_CONST;
+void empathy_contact_list_add (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message);
+void empathy_contact_list_remove (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message);
+GList * empathy_contact_list_get_members (EmpathyContactList *list);
+GList * empathy_contact_list_get_pendings (EmpathyContactList *list);
+GList * empathy_contact_list_get_all_groups (EmpathyContactList *list);
+GList * empathy_contact_list_get_groups (EmpathyContactList *list,
+ EmpathyContact *contact);
+void empathy_contact_list_add_to_group (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group);
+void empathy_contact_list_remove_from_group (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group);
+void empathy_contact_list_rename_group (EmpathyContactList *list,
+ const gchar *old_group,
+ const gchar *new_group);
G_END_DECLS
diff --git a/libempathy/empathy-contact-manager.c b/libempathy/empathy-contact-manager.c
index cc00108c8..575814fab 100644
--- a/libempathy/empathy-contact-manager.c
+++ b/libempathy/empathy-contact-manager.c
@@ -39,100 +39,171 @@
struct _EmpathyContactManagerPriv {
GHashTable *lists;
MissionControl *mc;
- gboolean setup;
};
-typedef struct {
- const gchar *old_group;
- const gchar *new_group;
-} ContactManagerRenameGroupData;
-
-typedef struct {
- EmpathyContact *contact;
- const gchar *id;
-} ContactManagerFindData;
-
-static void empathy_contact_manager_class_init (EmpathyContactManagerClass *klass);
-static void contact_manager_iface_init (EmpathyContactListIface *iface);
-static void empathy_contact_manager_init (EmpathyContactManager *manager);
-static void contact_manager_finalize (GObject *object);
-static void contact_manager_setup (EmpathyContactList *manager);
-static EmpathyContact *contact_manager_find (EmpathyContactList *manager,
- const gchar *id);
-static void contact_manager_add (EmpathyContactList *manager,
- EmpathyContact *contact,
- const gchar *message);
-static void contact_manager_remove (EmpathyContactList *manager,
- EmpathyContact *contact,
- const gchar *message);
-static GList * contact_manager_get_members (EmpathyContactList *manager);
-static GList * contact_manager_get_local_pending (EmpathyContactList *manager);
-static void contact_manager_process_pending (EmpathyContactList *manager,
- EmpathyContact *contact,
- gboolean accept);
-static void contact_manager_setup_foreach (McAccount *account,
- EmpathyTpContactList *list,
- EmpathyContactManager *manager);
-static gboolean contact_manager_find_foreach (McAccount *account,
- EmpathyTpContactList *list,
- ContactManagerFindData *data);
-static void contact_manager_add_account (EmpathyContactManager *manager,
- McAccount *account);
-static void contact_manager_added_cb (EmpathyTpContactList *list,
- EmpathyContact *contact,
- EmpathyContactManager *manager);
-static void contact_manager_removed_cb (EmpathyTpContactList *list,
- EmpathyContact *contact,
- EmpathyContactManager *manager);
-static void contact_manager_local_pending_cb (EmpathyTpContactList *list,
- EmpathyContact *contact,
- const gchar *message,
- EmpathyContactManager *manager);
-static void contact_manager_destroy_cb (EmpathyTpContactList *list,
- EmpathyContactManager *manager);
-static void contact_manager_rename_group_foreach (McAccount *account,
- EmpathyTpContactList *list,
- ContactManagerRenameGroupData *data);
-static void contact_manager_get_groups_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **all_groups);
-static void contact_manager_get_members_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **contacts);
-static void contact_manager_get_local_pending_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **contacts);
-static void contact_manager_status_changed_cb (MissionControl *mc,
- TelepathyConnectionStatus status,
- McPresence presence,
- TelepathyConnectionStatusReason reason,
- const gchar *unique_name,
- EmpathyContactManager *manager);
+static void empathy_contact_manager_class_init (EmpathyContactManagerClass *klass);
+static void empathy_contact_manager_init (EmpathyContactManager *manager);
+static void contact_manager_iface_init (EmpathyContactListIface *iface);
G_DEFINE_TYPE_WITH_CODE (EmpathyContactManager, empathy_contact_manager, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
contact_manager_iface_init));
static void
-empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
+contact_manager_members_changed_cb (EmpathyTpContactList *list,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ gchar *message,
+ gboolean is_member,
+ EmpathyContactManager *manager)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ g_signal_emit_by_name (manager, "members-changed",
+ contact, actor, reason, message, is_member);
+}
- object_class->finalize = contact_manager_finalize;
+static void
+contact_manager_pendings_changed_cb (EmpathyTpContactList *list,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ gchar *message,
+ gboolean is_pending,
+ EmpathyContactManager *manager)
+{
+ g_signal_emit_by_name (manager, "pendings-changed",
+ contact, actor, reason, message, is_pending);
+}
- g_type_class_add_private (object_class, sizeof (EmpathyContactManagerPriv));
+static void
+contact_manager_groups_changed_cb (EmpathyTpContactList *list,
+ EmpathyContact *contact,
+ gchar *group,
+ gboolean is_member,
+ EmpathyContactManager *manager)
+{
+ g_signal_emit_by_name (manager, "groups-changed",
+ contact, group, is_member);
}
+static void contact_manager_destroy_cb (EmpathyTpContactList *list,
+ EmpathyContactManager *manager);
+
static void
-contact_manager_iface_init (EmpathyContactListIface *iface)
+contact_manager_disconnect_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
- iface->setup = contact_manager_setup;
- iface->find = contact_manager_find;
- iface->add = contact_manager_add;
- iface->remove = contact_manager_remove;
- iface->get_members = contact_manager_get_members;
- iface->get_local_pending = contact_manager_get_local_pending;
- iface->process_pending = contact_manager_process_pending;
+ EmpathyTpContactList *list = value;
+ EmpathyContactManager *manager = user_data;
+
+ /* Disconnect signals from the list */
+ g_signal_handlers_disconnect_by_func (list,
+ contact_manager_members_changed_cb,
+ manager);
+ g_signal_handlers_disconnect_by_func (list,
+ contact_manager_pendings_changed_cb,
+ manager);
+ g_signal_handlers_disconnect_by_func (list,
+ contact_manager_groups_changed_cb,
+ manager);
+ g_signal_handlers_disconnect_by_func (list,
+ contact_manager_destroy_cb,
+ manager);
+}
+
+static void
+contact_manager_destroy_cb (EmpathyTpContactList *list,
+ EmpathyContactManager *manager)
+{
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+ McAccount *account;
+
+ account = empathy_tp_contact_list_get_account (list);
+
+ empathy_debug (DEBUG_DOMAIN, "Removing account: %s",
+ mc_account_get_display_name (account));
+
+ contact_manager_disconnect_foreach (account, list, manager);
+ g_hash_table_remove (priv->lists, account);
+}
+
+static void
+contact_manager_add_account (EmpathyContactManager *manager,
+ McAccount *account)
+{
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+ EmpathyTpContactList *list;
+
+ if (g_hash_table_lookup (priv->lists, account)) {
+ return;
+ }
+
+ empathy_debug (DEBUG_DOMAIN, "Adding new account: %s",
+ mc_account_get_display_name (account));
+
+ list = empathy_tp_contact_list_new (account);
+ if (!list) {
+ return;
+ }
+
+ g_hash_table_insert (priv->lists, g_object_ref (account), list);
+
+ /* Connect signals */
+ g_signal_connect (list, "members-changed",
+ G_CALLBACK (contact_manager_members_changed_cb),
+ manager);
+ g_signal_connect (list, "pendings-changed",
+ G_CALLBACK (contact_manager_pendings_changed_cb),
+ manager);
+ g_signal_connect (list, "groups-changed",
+ G_CALLBACK (contact_manager_groups_changed_cb),
+ manager);
+ g_signal_connect (list, "destroy",
+ G_CALLBACK (contact_manager_destroy_cb),
+ manager);
+}
+
+static void
+contact_manager_status_changed_cb (MissionControl *mc,
+ TelepathyConnectionStatus status,
+ McPresence presence,
+ TelepathyConnectionStatusReason reason,
+ const gchar *unique_name,
+ EmpathyContactManager *manager)
+{
+ McAccount *account;
+
+ if (status != TP_CONN_STATUS_CONNECTED) {
+ /* We only care about newly connected accounts */
+ return;
+ }
+
+ account = mc_account_lookup (unique_name);
+ contact_manager_add_account (manager, account);
+ g_object_unref (account);
+}
+
+static void
+contact_manager_finalize (GObject *object)
+{
+ EmpathyContactManagerPriv *priv = GET_PRIV (object);
+
+ g_hash_table_foreach (priv->lists,
+ contact_manager_disconnect_foreach,
+ object);
+ g_hash_table_destroy (priv->lists);
+ g_object_unref (priv->mc);
+}
+
+static void
+empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = contact_manager_finalize;
+
+ g_type_class_add_private (object_class, sizeof (EmpathyContactManagerPriv));
}
static void
@@ -158,27 +229,12 @@ empathy_contact_manager_init (EmpathyContactManager *manager)
/* Get ContactList for existing connections */
accounts = mission_control_get_online_connections (priv->mc, NULL);
for (l = accounts; l; l = l->next) {
- McAccount *account;
-
- account = l->data;
- contact_manager_add_account (manager, account);
-
- g_object_unref (account);
+ contact_manager_add_account (manager, l->data);
+ g_object_unref (l->data);
}
g_slist_free (accounts);
}
-static void
-contact_manager_finalize (GObject *object)
-{
- EmpathyContactManagerPriv *priv;
-
- priv = GET_PRIV (object);
-
- g_hash_table_destroy (priv->lists);
- g_object_unref (priv->mc);
-}
-
EmpathyContactManager *
empathy_contact_manager_new (void)
{
@@ -194,62 +250,28 @@ empathy_contact_manager_new (void)
return manager;
}
-static void
-contact_manager_setup (EmpathyContactList *manager)
-{
- EmpathyContactManagerPriv *priv;
-
- g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
-
- priv = GET_PRIV (manager);
-
- if (priv->setup) {
- /* Already done */
- return;
- }
-
- g_hash_table_foreach (priv->lists,
- (GHFunc) contact_manager_setup_foreach,
- manager);
-
- priv->setup = TRUE;
-}
-
-static EmpathyContact *
-contact_manager_find (EmpathyContactList *manager,
- const gchar *id)
+EmpathyTpContactList *
+empathy_contact_manager_get_list (EmpathyContactManager *manager,
+ McAccount *account)
{
- EmpathyContactManagerPriv *priv;
- ContactManagerFindData data;
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
- g_return_val_if_fail (id != NULL, NULL);
-
- priv = GET_PRIV (manager);
-
- data.contact = NULL;
- data.id = id;
-
- g_hash_table_find (priv->lists,
- (GHRFunc) contact_manager_find_foreach,
- &data);
+ g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
- return data.contact;
+ return g_hash_table_lookup (priv->lists, account);
}
static void
contact_manager_add (EmpathyContactList *manager,
- EmpathyContact *contact,
+ EmpathyContact *contact,
const gchar *message)
{
- EmpathyContactManagerPriv *priv;
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
EmpathyContactList *list;
McAccount *account;
g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
- priv = GET_PRIV (manager);
account = empathy_contact_get_account (contact);
list = g_hash_table_lookup (priv->lists, account);
@@ -264,14 +286,11 @@ contact_manager_remove (EmpathyContactList *manager,
EmpathyContact *contact,
const gchar *message)
{
- EmpathyContactManagerPriv *priv;
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
EmpathyContactList *list;
McAccount *account;
g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
- priv = GET_PRIV (manager);
account = empathy_contact_get_account (contact);
list = g_hash_table_lookup (priv->lists, account);
@@ -281,16 +300,25 @@ contact_manager_remove (EmpathyContactList *manager,
}
}
+static void
+contact_manager_get_members_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts)
+{
+ GList *l;
+
+ l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
+ *contacts = g_list_concat (*contacts, l);
+}
+
static GList *
contact_manager_get_members (EmpathyContactList *manager)
{
- EmpathyContactManagerPriv *priv;
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
GList *contacts = NULL;
g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
- priv = GET_PRIV (manager);
-
g_hash_table_foreach (priv->lists,
(GHFunc) contact_manager_get_members_foreach,
&contacts);
@@ -298,337 +326,169 @@ contact_manager_get_members (EmpathyContactList *manager)
return contacts;
}
-static GList *
-contact_manager_get_local_pending (EmpathyContactList *manager)
-{
- EmpathyContactManagerPriv *priv;
- GList *pending = NULL;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
-
- priv = GET_PRIV (manager);
-
- g_hash_table_foreach (priv->lists,
- (GHFunc) contact_manager_get_local_pending_foreach,
- &pending);
-
- return pending;
-}
-
static void
-contact_manager_process_pending (EmpathyContactList *manager,
- EmpathyContact *contact,
- gboolean accept)
+contact_manager_get_pendings_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **contacts)
{
- EmpathyContactManagerPriv *priv;
- EmpathyContactList *list;
- McAccount *account;
-
- g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
- priv = GET_PRIV (manager);
-
- account = empathy_contact_get_account (contact);
- list = g_hash_table_lookup (priv->lists, account);
-
- if (list) {
- empathy_contact_list_process_pending (list, contact, accept);
- }
-}
-
-EmpathyTpContactList *
-empathy_contact_manager_get_list (EmpathyContactManager *manager,
- McAccount *account)
-{
- EmpathyContactManagerPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
- g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-
- priv = GET_PRIV (manager);
+ GList *l;
- return g_hash_table_lookup (priv->lists, account);
+ l = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (list));
+ *contacts = g_list_concat (*contacts, l);
}
-EmpathyContact *
-empathy_contact_manager_get_user (EmpathyContactManager *manager,
- McAccount *account)
+static GList *
+contact_manager_get_pendings (EmpathyContactList *manager)
{
- EmpathyContactManagerPriv *priv;
- EmpathyTpContactList *list;
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+ GList *contacts = NULL;
g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
- g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-
- priv = GET_PRIV (manager);
- list = g_hash_table_lookup (priv->lists, account);
-
- if (!list) {
- return NULL;
- }
+ g_hash_table_foreach (priv->lists,
+ (GHFunc) contact_manager_get_pendings_foreach,
+ &contacts);
- return empathy_tp_contact_list_get_user (list);
+ return contacts;
}
-EmpathyContact *
-empathy_contact_manager_create (EmpathyContactManager *manager,
- McAccount *account,
- const gchar *id)
+static void
+contact_manager_get_all_groups_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ GList **all_groups)
{
- EmpathyContactManagerPriv *priv;
- EmpathyTpContactList *list;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
- g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
- g_return_val_if_fail (id != NULL, NULL);
-
- priv = GET_PRIV (manager);
+ GList *groups, *l;
- list = g_hash_table_lookup (priv->lists, account);
-
- if (!list) {
- return NULL;
+ groups = empathy_contact_list_get_all_groups (EMPATHY_CONTACT_LIST (list));
+ for (l = groups; l; l = l->next) {
+ if (!g_list_find_custom (*all_groups,
+ l->data,
+ (GCompareFunc) strcmp)) {
+ *all_groups = g_list_prepend (*all_groups, l->data);
+ } else {
+ g_free (l->data);
+ }
}
- return empathy_tp_contact_list_get_from_id (list, id);
-}
-
-void
-empathy_contact_manager_rename_group (EmpathyContactManager *manager,
- const gchar *old_group,
- const gchar *new_group)
-{
- EmpathyContactManagerPriv *priv;
- ContactManagerRenameGroupData data;
-
- g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
- g_return_if_fail (old_group != NULL);
- g_return_if_fail (new_group != NULL);
-
- priv = GET_PRIV (manager);
-
- data.old_group = old_group;
- data.new_group = new_group;
-
- g_hash_table_foreach (priv->lists,
- (GHFunc) contact_manager_rename_group_foreach,
- &data);
+ g_list_free (groups);
}
-GList *
-empathy_contact_manager_get_groups (EmpathyContactManager *manager)
+static GList *
+contact_manager_get_all_groups (EmpathyContactList *manager)
{
- EmpathyContactManagerPriv *priv;
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
GList *groups = NULL;
g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
- priv = GET_PRIV (manager);
-
g_hash_table_foreach (priv->lists,
- (GHFunc) contact_manager_get_groups_foreach,
+ (GHFunc) contact_manager_get_all_groups_foreach,
&groups);
return groups;
}
-static void
-contact_manager_setup_foreach (McAccount *account,
- EmpathyTpContactList *list,
- EmpathyContactManager *manager)
+static GList *
+contact_manager_get_groups (EmpathyContactList *manager,
+ EmpathyContact *contact)
{
- empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
-}
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+ EmpathyContactList *list;
+ McAccount *account;
-static gboolean
-contact_manager_find_foreach (McAccount *account,
- EmpathyTpContactList *list,
- ContactManagerFindData *data)
-{
- data->contact = empathy_contact_list_find (EMPATHY_CONTACT_LIST (list),
- data->id);
+ g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
+
+ account = empathy_contact_get_account (contact);
+ list = g_hash_table_lookup (priv->lists, account);
- if (data->contact) {
- return TRUE;
+ if (list) {
+ return empathy_contact_list_get_groups (list, contact);
}
- return FALSE;
+ return NULL;
}
static void
-contact_manager_add_account (EmpathyContactManager *manager,
- McAccount *account)
+contact_manager_add_to_group (EmpathyContactList *manager,
+ EmpathyContact *contact,
+ const gchar *group)
{
- EmpathyContactManagerPriv *priv;
- EmpathyTpContactList *list;
-
- priv = GET_PRIV (manager);
-
- if (g_hash_table_lookup (priv->lists, account)) {
- return;
- }
-
- empathy_debug (DEBUG_DOMAIN, "Adding new account: %s",
- mc_account_get_display_name (account));
-
- list = empathy_tp_contact_list_new (account);
- if (!list) {
- return;
- }
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+ EmpathyContactList *list;
+ McAccount *account;
- g_hash_table_insert (priv->lists, g_object_ref (account), list);
+ g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
- /* Connect signals */
- g_signal_connect (list, "contact-added",
- G_CALLBACK (contact_manager_added_cb),
- manager);
- g_signal_connect (list, "contact-removed",
- G_CALLBACK (contact_manager_removed_cb),
- manager);
- g_signal_connect (list, "local-pending",
- G_CALLBACK (contact_manager_local_pending_cb),
- manager);
- g_signal_connect (list, "destroy",
- G_CALLBACK (contact_manager_destroy_cb),
- manager);
+ account = empathy_contact_get_account (contact);
+ list = g_hash_table_lookup (priv->lists, account);
- if (priv->setup) {
- empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
+ if (list) {
+ empathy_contact_list_add_to_group (list, contact, group);
}
}
static void
-contact_manager_added_cb (EmpathyTpContactList *list,
- EmpathyContact *contact,
- EmpathyContactManager *manager)
+contact_manager_remove_from_group (EmpathyContactList *manager,
+ EmpathyContact *contact,
+ const gchar *group)
{
- g_signal_emit_by_name (manager, "contact-added", contact);
-}
-
-static void
-contact_manager_removed_cb (EmpathyTpContactList *list,
- EmpathyContact *contact,
- EmpathyContactManager *manager)
-{
- g_signal_emit_by_name (manager, "contact-removed", contact);
-}
-
-static void
-contact_manager_local_pending_cb (EmpathyTpContactList *list,
- EmpathyContact *contact,
- const gchar *message,
- EmpathyContactManager *manager)
-{
- g_signal_emit_by_name (manager, "local-pending", contact, message);
-}
-
-static void
-contact_manager_destroy_cb (EmpathyTpContactList *list,
- EmpathyContactManager *manager)
-{
- EmpathyContactManagerPriv *priv;
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+ EmpathyContactList *list;
McAccount *account;
- priv = GET_PRIV (manager);
-
- account = empathy_tp_contact_list_get_account (list);
-
- empathy_debug (DEBUG_DOMAIN, "Removing account: %s",
- mc_account_get_display_name (account));
+ g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
- /* Disconnect signals from the list */
- g_signal_handlers_disconnect_by_func (list,
- contact_manager_added_cb,
- manager);
- g_signal_handlers_disconnect_by_func (list,
- contact_manager_removed_cb,
- manager);
- g_signal_handlers_disconnect_by_func (list,
- contact_manager_local_pending_cb,
- manager);
- g_signal_handlers_disconnect_by_func (list,
- contact_manager_destroy_cb,
- manager);
+ account = empathy_contact_get_account (contact);
+ list = g_hash_table_lookup (priv->lists, account);
- g_hash_table_remove (priv->lists, account);
+ if (list) {
+ empathy_contact_list_remove_from_group (list, contact, group);
+ }
}
-static void
-contact_manager_rename_group_foreach (McAccount *account,
- EmpathyTpContactList *list,
- ContactManagerRenameGroupData *data)
-{
- empathy_tp_contact_list_rename_group (list,
- data->old_group,
- data->new_group);
-}
+typedef struct {
+ const gchar *old_group;
+ const gchar *new_group;
+} RenameGroupData;
static void
-contact_manager_get_groups_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **all_groups)
+contact_manager_rename_group_foreach (McAccount *account,
+ EmpathyTpContactList *list,
+ RenameGroupData *data)
{
- GList *groups, *l;
-
- groups = empathy_tp_contact_list_get_groups (list);
- for (l = groups; l; l = l->next) {
- if (!g_list_find_custom (*all_groups,
- l->data,
- (GCompareFunc) strcmp)) {
- *all_groups = g_list_append (*all_groups,
- g_strdup (l->data));
- }
- g_free (l->data);
- }
-
- g_list_free (groups);
+ empathy_contact_list_rename_group (EMPATHY_CONTACT_LIST (list),
+ data->old_group,
+ data->new_group);
}
static void
-contact_manager_get_members_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **contacts)
+contact_manager_rename_group (EmpathyContactList *manager,
+ const gchar *old_group,
+ const gchar *new_group)
{
- GList *l;
-
- l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
- *contacts = g_list_concat (*contacts, l);
-}
+ EmpathyContactManagerPriv *priv = GET_PRIV (manager);
+ RenameGroupData data;
-static void
-contact_manager_get_local_pending_foreach (McAccount *account,
- EmpathyTpContactList *list,
- GList **contacts)
-{
- GList *l;
+ g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
- l = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (list));
- *contacts = g_list_concat (*contacts, l);
+ data.old_group = old_group;
+ data.new_group = new_group;
+ g_hash_table_foreach (priv->lists,
+ (GHFunc) contact_manager_rename_group_foreach,
+ &data);
}
static void
-contact_manager_status_changed_cb (MissionControl *mc,
- TelepathyConnectionStatus status,
- McPresence presence,
- TelepathyConnectionStatusReason reason,
- const gchar *unique_name,
- EmpathyContactManager *manager)
+contact_manager_iface_init (EmpathyContactListIface *iface)
{
- EmpathyContactManagerPriv *priv;
- McAccount *account;
-
- priv = GET_PRIV (manager);
-
- if (status != TP_CONN_STATUS_CONNECTED) {
- /* We only care about newly connected accounts */
- return;
- }
-
- account = mc_account_lookup (unique_name);
- contact_manager_add_account (manager, account);
-
- g_object_unref (account);
+ iface->add = contact_manager_add;
+ iface->remove = contact_manager_remove;
+ iface->get_members = contact_manager_get_members;
+ iface->get_pendings = contact_manager_get_pendings;
+ iface->get_all_groups = contact_manager_get_all_groups;
+ iface->get_groups = contact_manager_get_groups;
+ iface->add_to_group = contact_manager_add_to_group;
+ iface->remove_from_group = contact_manager_remove_from_group;
+ iface->rename_group = contact_manager_rename_group;
}
diff --git a/libempathy/empathy-contact-manager.h b/libempathy/empathy-contact-manager.h
index 768301ae7..41144cf43 100644
--- a/libempathy/empathy-contact-manager.h
+++ b/libempathy/empathy-contact-manager.h
@@ -51,19 +51,10 @@ struct _EmpathyContactManagerClass {
GObjectClass parent_class;
};
-GType empathy_contact_manager_get_type (void) G_GNUC_CONST;
-EmpathyContactManager *empathy_contact_manager_new (void);
-EmpathyTpContactList * empathy_contact_manager_get_list (EmpathyContactManager *manager,
- McAccount *account);
-EmpathyContact * empathy_contact_manager_get_user (EmpathyContactManager *manager,
- McAccount *account);
-EmpathyContact * empathy_contact_manager_create (EmpathyContactManager *manager,
- McAccount *account,
- const gchar *id);
-void empathy_contact_manager_rename_group (EmpathyContactManager *manager,
- const gchar *old_group,
- const gchar *new_group);
-GList * empathy_contact_manager_get_groups (EmpathyContactManager *manager);
+GType empathy_contact_manager_get_type (void) G_GNUC_CONST;
+EmpathyContactManager *empathy_contact_manager_new (void);
+EmpathyTpContactList * empathy_contact_manager_get_list (EmpathyContactManager *manager,
+ McAccount *account);
G_END_DECLS
diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c
index d3935ad6c..505e190c0 100644
--- a/libempathy/empathy-contact.c
+++ b/libempathy/empathy-contact.c
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * Copyright (C) 2004-2007 Imendio AB
+ * Copyright (C) 2004 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -19,6 +20,7 @@
*
* Authors: Mikael Hallendal <micke@imendio.com>
* Martyn Russell <martyn@imendio.com>
+ * Xavier Claessens <xclaesse@gmail.com>
*/
#include "config.h"
@@ -41,26 +43,26 @@ typedef struct _EmpathyContactPriv EmpathyContactPriv;
struct _EmpathyContactPriv {
gchar *id;
gchar *name;
- EmpathyAvatar *avatar;
+ EmpathyAvatar *avatar;
McAccount *account;
- EmpathyPresence *presence;
- GList *groups;
- EmpathySubscription subscription;
+ EmpathyPresence *presence;
guint handle;
gboolean is_user;
};
-static void contact_class_init (EmpathyContactClass *class);
-static void contact_init (EmpathyContact *contact);
-static void contact_finalize (GObject *object);
-static void contact_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec);
-static void contact_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec);
+static void empathy_contact_class_init (EmpathyContactClass *class);
+static void empathy_contact_init (EmpathyContact *contact);
+static void contact_finalize (GObject *object);
+static void contact_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void contact_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+G_DEFINE_TYPE (EmpathyContact, empathy_contact, G_TYPE_OBJECT);
enum {
PROP_0,
@@ -75,41 +77,12 @@ enum {
PROP_IS_USER
};
-static gpointer parent_class = NULL;
-
-GType
-empathy_contact_get_gtype (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (EmpathyContactClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) contact_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (EmpathyContact),
- 0, /* n_preallocs */
- (GInstanceInitFunc) contact_init
- };
-
- type = g_type_register_static (G_TYPE_OBJECT,
- "EmpathyContact",
- &info, 0);
- }
-
- return type;
-}
-
static void
-contact_class_init (EmpathyContactClass *class)
+empathy_contact_class_init (EmpathyContactClass *class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (class);
- parent_class = g_type_class_peek_parent (class);
object_class->finalize = contact_finalize;
object_class->get_property = contact_get_property;
@@ -156,23 +129,6 @@ contact_class_init (EmpathyContactClass *class)
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
- PROP_GROUPS,
- g_param_spec_pointer ("groups",
- "Contact groups",
- "Groups of contact",
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class,
- PROP_SUBSCRIPTION,
- g_param_spec_flags ("subscription",
- "Contact Subscription",
- "The subscription status of the contact",
- EMPATHY_TYPE_SUBSCRIPTION,
- EMPATHY_SUBSCRIPTION_NONE,
- G_PARAM_READWRITE));
-
-
- g_object_class_install_property (object_class,
PROP_HANDLE,
g_param_spec_uint ("handle",
"Contact Handle",
@@ -193,7 +149,7 @@ contact_class_init (EmpathyContactClass *class)
}
static void
-contact_init (EmpathyContact *contact)
+empathy_contact_init (EmpathyContact *contact)
{
}
@@ -217,16 +173,11 @@ contact_finalize (GObject *object)
g_object_unref (priv->presence);
}
- if (priv->groups) {
- g_list_foreach (priv->groups, (GFunc) g_free, NULL);
- g_list_free (priv->groups);
- }
-
if (priv->account) {
g_object_unref (priv->account);
}
- (G_OBJECT_CLASS (parent_class)->finalize) (object);
+ G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object);
}
static void
@@ -257,12 +208,6 @@ contact_get_property (GObject *object,
case PROP_PRESENCE:
g_value_set_object (value, priv->presence);
break;
- case PROP_GROUPS:
- g_value_set_pointer (value, priv->groups);
- break;
- case PROP_SUBSCRIPTION:
- g_value_set_flags (value, priv->subscription);
- break;
case PROP_HANDLE:
g_value_set_uint (value, priv->handle);
break;
@@ -306,14 +251,6 @@ contact_set_property (GObject *object,
empathy_contact_set_presence (EMPATHY_CONTACT (object),
EMPATHY_PRESENCE (g_value_get_object (value)));
break;
- case PROP_GROUPS:
- empathy_contact_set_groups (EMPATHY_CONTACT (object),
- g_value_get_pointer (value));
- break;
- case PROP_SUBSCRIPTION:
- empathy_contact_set_subscription (EMPATHY_CONTACT (object),
- g_value_get_flags (value));
- break;
case PROP_HANDLE:
empathy_contact_set_handle (EMPATHY_CONTACT (object),
g_value_get_uint (value));
@@ -338,8 +275,8 @@ empathy_contact_new (McAccount *account)
EmpathyContact *
empathy_contact_new_full (McAccount *account,
- const gchar *id,
- const gchar *name)
+ const gchar *id,
+ const gchar *name)
{
return g_object_new (EMPATHY_TYPE_CONTACT,
"account", account,
@@ -364,107 +301,6 @@ empathy_contact_get_id (EmpathyContact *contact)
return "";
}
-const gchar *
-empathy_contact_get_name (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
-
- priv = GET_PRIV (contact);
-
- if (G_STR_EMPTY (priv->name)) {
- return empathy_contact_get_id (contact);
- }
-
- return priv->name;
-}
-
-EmpathyAvatar *
-empathy_contact_get_avatar (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
- priv = GET_PRIV (contact);
-
- return priv->avatar;
-}
-
-McAccount *
-empathy_contact_get_account (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
- priv = GET_PRIV (contact);
-
- return priv->account;
-}
-
-EmpathyPresence *
-empathy_contact_get_presence (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
- priv = GET_PRIV (contact);
-
- return priv->presence;
-}
-
-GList *
-empathy_contact_get_groups (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
-
- priv = GET_PRIV (contact);
-
- return priv->groups;
-}
-
-EmpathySubscription
-empathy_contact_get_subscription (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact),
- EMPATHY_SUBSCRIPTION_NONE);
-
- priv = GET_PRIV (contact);
-
- return priv->subscription;
-}
-
-guint
-empathy_contact_get_handle (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
-
- priv = GET_PRIV (contact);
-
- return priv->handle;
-}
-
-gboolean
-empathy_contact_is_user (EmpathyContact *contact)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
-
- priv = GET_PRIV (contact);
-
- return priv->is_user;
-}
-
void
empathy_contact_set_id (EmpathyContact *contact,
const gchar *id)
@@ -486,6 +322,22 @@ empathy_contact_set_id (EmpathyContact *contact,
g_object_notify (G_OBJECT (contact), "id");
}
+const gchar *
+empathy_contact_get_name (EmpathyContact *contact)
+{
+ EmpathyContactPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
+
+ priv = GET_PRIV (contact);
+
+ if (G_STR_EMPTY (priv->name)) {
+ return empathy_contact_get_id (contact);
+ }
+
+ return priv->name;
+}
+
void
empathy_contact_set_name (EmpathyContact *contact,
const gchar *name)
@@ -507,6 +359,18 @@ empathy_contact_set_name (EmpathyContact *contact,
g_object_notify (G_OBJECT (contact), "name");
}
+EmpathyAvatar *
+empathy_contact_get_avatar (EmpathyContact *contact)
+{
+ EmpathyContactPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+ priv = GET_PRIV (contact);
+
+ return priv->avatar;
+}
+
void
empathy_contact_set_avatar (EmpathyContact *contact,
EmpathyAvatar *avatar)
@@ -533,9 +397,21 @@ empathy_contact_set_avatar (EmpathyContact *contact,
g_object_notify (G_OBJECT (contact), "avatar");
}
+McAccount *
+empathy_contact_get_account (EmpathyContact *contact)
+{
+ EmpathyContactPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+ priv = GET_PRIV (contact);
+
+ return priv->account;
+}
+
void
empathy_contact_set_account (EmpathyContact *contact,
- McAccount *account)
+ McAccount *account)
{
EmpathyContactPriv *priv;
@@ -556,9 +432,21 @@ empathy_contact_set_account (EmpathyContact *contact,
g_object_notify (G_OBJECT (contact), "account");
}
+EmpathyPresence *
+empathy_contact_get_presence (EmpathyContact *contact)
+{
+ EmpathyContactPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+ priv = GET_PRIV (contact);
+
+ return priv->presence;
+}
+
void
empathy_contact_set_presence (EmpathyContact *contact,
- EmpathyPresence *presence)
+ EmpathyPresence *presence)
{
EmpathyContactPriv *priv;
@@ -582,34 +470,21 @@ empathy_contact_set_presence (EmpathyContact *contact,
g_object_notify (G_OBJECT (contact), "presence");
}
-void
-empathy_contact_set_groups (EmpathyContact *contact,
- GList *groups)
+guint
+empathy_contact_get_handle (EmpathyContact *contact)
{
EmpathyContactPriv *priv;
- GList *old_groups, *l;
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
priv = GET_PRIV (contact);
- old_groups = priv->groups;
- priv->groups = NULL;
-
- for (l = groups; l; l = l->next) {
- priv->groups = g_list_append (priv->groups,
- g_strdup (l->data));
- }
-
- g_list_foreach (old_groups, (GFunc) g_free, NULL);
- g_list_free (old_groups);
-
- g_object_notify (G_OBJECT (contact), "groups");
+ return priv->handle;
}
void
-empathy_contact_set_subscription (EmpathyContact *contact,
- EmpathySubscription subscription)
+empathy_contact_set_handle (EmpathyContact *contact,
+ guint handle)
{
EmpathyContactPriv *priv;
@@ -617,32 +492,25 @@ empathy_contact_set_subscription (EmpathyContact *contact,
priv = GET_PRIV (contact);
- if (priv->subscription == subscription) {
+ if (priv->handle == handle) {
return;
}
- priv->subscription = subscription;
+ priv->handle = handle;
- g_object_notify (G_OBJECT (contact), "subscription");
+ g_object_notify (G_OBJECT (contact), "handle");
}
-void
-empathy_contact_set_handle (EmpathyContact *contact,
- guint handle)
+gboolean
+empathy_contact_is_user (EmpathyContact *contact)
{
EmpathyContactPriv *priv;
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+ g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
priv = GET_PRIV (contact);
- if (priv->handle == handle) {
- return;
- }
-
- priv->handle = handle;
-
- g_object_notify (G_OBJECT (contact), "handle");
+ return priv->is_user;
}
void
@@ -664,43 +532,6 @@ empathy_contact_set_is_user (EmpathyContact *contact,
g_object_notify (G_OBJECT (contact), "is-user");
}
-void
-empathy_contact_add_group (EmpathyContact *contact,
- const gchar *group)
-{
- EmpathyContactPriv *priv;
-
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
- g_return_if_fail (group != NULL);
-
- priv = GET_PRIV (contact);
-
- if (!g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
- priv->groups = g_list_prepend (priv->groups, g_strdup (group));
- g_object_notify (G_OBJECT (contact), "groups");
- }
-}
-
-void
-empathy_contact_remove_group (EmpathyContact *contact,
- const gchar *group)
-{
- EmpathyContactPriv *priv;
- GList *l;
-
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
- g_return_if_fail (group != NULL);
-
- priv = GET_PRIV (contact);
-
- l = g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp);
- if (l) {
- g_free (l->data);
- priv->groups = g_list_delete_link (priv->groups, l);
- g_object_notify (G_OBJECT (contact), "groups");
- }
-}
-
gboolean
empathy_contact_is_online (EmpathyContact *contact)
{
@@ -717,24 +548,6 @@ empathy_contact_is_online (EmpathyContact *contact)
return (empathy_presence_get_state (priv->presence) > MC_PRESENCE_OFFLINE);
}
-gboolean
-empathy_contact_is_in_group (EmpathyContact *contact,
- const gchar *group)
-{
- EmpathyContactPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
- g_return_val_if_fail (!G_STR_EMPTY (group), FALSE);
-
- priv = GET_PRIV (contact);
-
- if (g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
const gchar *
empathy_contact_get_status (EmpathyContact *contact)
{
diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h
index b32d451bb..87a26f0dd 100644
--- a/libempathy/empathy-contact.h
+++ b/libempathy/empathy-contact.h
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2004 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -16,6 +17,10 @@
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
+ *
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ * Martyn Russell <martyn@imendio.com>
+ * Xavier Claessens <xclaesse@gmail.com>
*/
#ifndef __EMPATHY_CONTACT_H__
@@ -30,7 +35,7 @@
G_BEGIN_DECLS
-#define EMPATHY_TYPE_CONTACT (empathy_contact_get_gtype ())
+#define EMPATHY_TYPE_CONTACT (empathy_contact_get_type ())
#define EMPATHY_CONTACT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_CONTACT, EmpathyContact))
#define EMPATHY_CONTACT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_CONTACT, EmpathyContactClass))
#define EMPATHY_IS_CONTACT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CONTACT))
@@ -48,57 +53,37 @@ struct _EmpathyContactClass {
GObjectClass parent_class;
};
-typedef enum {
- EMPATHY_SUBSCRIPTION_NONE = 0,
- EMPATHY_SUBSCRIPTION_TO = 1 << 0, /* We send our presence to that contact */
- EMPATHY_SUBSCRIPTION_FROM = 1 << 1, /* That contact sends his presence to us */
- EMPATHY_SUBSCRIPTION_BOTH = EMPATHY_SUBSCRIPTION_TO | EMPATHY_SUBSCRIPTION_FROM
-} EmpathySubscription;
-
-GType empathy_contact_get_gtype (void) G_GNUC_CONST;
-
-EmpathyContact * empathy_contact_new (McAccount *account);
-EmpathyContact * empathy_contact_new_full (McAccount *account,
- const gchar *id,
- const gchar *name);
-const gchar * empathy_contact_get_id (EmpathyContact *contact);
-const gchar * empathy_contact_get_name (EmpathyContact *contact);
-EmpathyAvatar * empathy_contact_get_avatar (EmpathyContact *contact);
-McAccount * empathy_contact_get_account (EmpathyContact *contact);
-EmpathyPresence * empathy_contact_get_presence (EmpathyContact *contact);
-GList * empathy_contact_get_groups (EmpathyContact *contact);
-EmpathySubscription empathy_contact_get_subscription (EmpathyContact *contact);
-guint empathy_contact_get_handle (EmpathyContact *contact);
-gboolean empathy_contact_is_user (EmpathyContact *contact);
-void empathy_contact_set_id (EmpathyContact *contact,
- const gchar *id);
-void empathy_contact_set_name (EmpathyContact *contact,
- const gchar *name);
-void empathy_contact_set_avatar (EmpathyContact *contact,
- EmpathyAvatar *avatar);
-void empathy_contact_set_account (EmpathyContact *contact,
- McAccount *account);
-void empathy_contact_set_presence (EmpathyContact *contact,
- EmpathyPresence *presence);
-void empathy_contact_set_groups (EmpathyContact *contact,
- GList *categories);
-void empathy_contact_set_subscription (EmpathyContact *contact,
- EmpathySubscription subscription);
-void empathy_contact_set_handle (EmpathyContact *contact,
- guint handle);
-void empathy_contact_set_is_user (EmpathyContact *contact,
- gboolean is_user);
-void empathy_contact_add_group (EmpathyContact *contact,
- const gchar *group);
-void empathy_contact_remove_group (EmpathyContact *contact,
- const gchar *group);
-gboolean empathy_contact_is_online (EmpathyContact *contact);
-gboolean empathy_contact_is_in_group (EmpathyContact *contact,
- const gchar *group);
-const gchar * empathy_contact_get_status (EmpathyContact *contact);
-gboolean empathy_contact_equal (gconstpointer v1,
- gconstpointer v2);
-guint empathy_contact_hash (gconstpointer key);
+GType empathy_contact_get_type (void) G_GNUC_CONST;
+EmpathyContact * empathy_contact_new (McAccount *account);
+EmpathyContact * empathy_contact_new_full (McAccount *account,
+ const gchar *id,
+ const gchar *name);
+const gchar * empathy_contact_get_id (EmpathyContact *contact);
+void empathy_contact_set_id (EmpathyContact *contact,
+ const gchar *id);
+const gchar * empathy_contact_get_name (EmpathyContact *contact);
+void empathy_contact_set_name (EmpathyContact *contact,
+ const gchar *name);
+EmpathyAvatar * empathy_contact_get_avatar (EmpathyContact *contact);
+void empathy_contact_set_avatar (EmpathyContact *contact,
+ EmpathyAvatar *avatar);
+McAccount * empathy_contact_get_account (EmpathyContact *contact);
+void empathy_contact_set_account (EmpathyContact *contact,
+ McAccount *account);
+EmpathyPresence * empathy_contact_get_presence (EmpathyContact *contact);
+void empathy_contact_set_presence (EmpathyContact *contact,
+ EmpathyPresence *presence);
+guint empathy_contact_get_handle (EmpathyContact *contact);
+void empathy_contact_set_handle (EmpathyContact *contact,
+ guint handle);
+gboolean empathy_contact_is_user (EmpathyContact *contact);
+void empathy_contact_set_is_user (EmpathyContact *contact,
+ gboolean is_user);
+gboolean empathy_contact_is_online (EmpathyContact *contact);
+const gchar * empathy_contact_get_status (EmpathyContact *contact);
+gboolean empathy_contact_equal (gconstpointer v1,
+ gconstpointer v2);
+guint empathy_contact_hash (gconstpointer key);
G_END_DECLS
diff --git a/libempathy/empathy-log-manager.c b/libempathy/empathy-log-manager.c
index e234ec521..e47f50fb8 100644
--- a/libempathy/empathy-log-manager.c
+++ b/libempathy/empathy-log-manager.c
@@ -634,24 +634,22 @@ log_manager_get_dir (EmpathyLogManager *manager,
{
const gchar *account_id;
gchar *basedir;
- gchar *str;
account_id = mc_account_get_unique_name (account);
- basedir =
- str = g_build_path (G_DIR_SEPARATOR_S,
- log_manager_get_basedir (manager),
- account_id,
- chat_id,
- NULL);
if (chatroom) {
basedir = g_build_path (G_DIR_SEPARATOR_S,
- str,
+ log_manager_get_basedir (manager),
+ account_id,
LOG_DIR_CHATROOMS,
+ chat_id,
NULL);
- g_free (str);
} else {
- basedir = str;
+ basedir = g_build_path (G_DIR_SEPARATOR_S,
+ log_manager_get_basedir (manager),
+ account_id,
+ chat_id,
+ NULL);
}
return basedir;
diff --git a/libempathy/empathy-marshal.list b/libempathy/empathy-marshal.list
index 3b36b7be0..383bfbbed 100644
--- a/libempathy/empathy-marshal.list
+++ b/libempathy/empathy-marshal.list
@@ -1,10 +1,14 @@
VOID:OBJECT,UINT
-VOID:OBJECT,OBJECT
-VOID:OBJECT,OBJECT,UINT
VOID:OBJECT,BOOLEAN
-VOID:OBJECT,STRING,STRING
+VOID:OBJECT,POINTER
VOID:OBJECT,STRING
-VOID:POINTER,UINT,UINT,STRING
+VOID:OBJECT,STRING,STRING
+VOID:OBJECT,STRING,BOOLEAN
+VOID:OBJECT,OBJECT
+VOID:OBJECT,OBJECT,UINT
+VOID:OBJECT,OBJECT,UINT,STRING
+VOID:OBJECT,OBJECT,UINT,STRING,BOOLEAN
+VOID:OBJECT,OBJECT,STRING
VOID:INT,STRING
VOID:UINT,BOOLEAN
diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c
index 077afe36e..fc943f0c6 100644
--- a/libempathy/empathy-tp-chat.c
+++ b/libempathy/empathy-tp-chat.c
@@ -31,8 +31,7 @@
#include <libtelepathy/tp-props-iface.h>
#include "empathy-tp-chat.h"
-#include "empathy-contact-manager.h"
-#include "empathy-tp-contact-list.h"
+#include "empathy-contact-factory.h"
#include "empathy-marshal.h"
#include "empathy-debug.h"
#include "empathy-time.h"
@@ -44,8 +43,8 @@
#define DEBUG_DOMAIN "TpChat"
struct _EmpathyTpChatPriv {
- EmpathyTpContactList *list;
- EmpathyContactManager *manager;
+ EmpathyContactFactory *factory;
+ EmpathyContact *user;
McAccount *account;
gchar *id;
MissionControl *mc;
@@ -363,11 +362,11 @@ tp_chat_finalize (GObject *object)
g_object_unref (priv->tp_chan);
}
- if (priv->manager) {
- g_object_unref (priv->manager);
+ if (priv->factory) {
+ g_object_unref (priv->factory);
}
- if (priv->list) {
- g_object_unref (priv->list);
+ if (priv->user) {
+ g_object_unref (priv->user);
}
if (priv->account) {
g_object_unref (priv->account);
@@ -392,10 +391,9 @@ tp_chat_constructor (GType type,
priv = GET_PRIV (chat);
- priv->manager = empathy_contact_manager_new ();
- priv->list = empathy_contact_manager_get_list (priv->manager, priv->account);
+ priv->factory = empathy_contact_factory_new ();
+ priv->user = empathy_contact_factory_get_user (priv->factory, priv->account);
priv->mc = empathy_mission_control_new ();
- g_object_ref (priv->list);
priv->text_iface = tp_chan_get_interface (priv->tp_chan,
TELEPATHY_CHAN_IFACE_TEXT_QUARK);
@@ -750,12 +748,10 @@ empathy_tp_chat_get_id (EmpathyTpChat *chat)
priv = GET_PRIV (chat);
- if (priv->id) {
- return priv->id;
+ if (!priv->id) {
+ priv->id = empathy_inspect_channel (priv->account, priv->tp_chan);
}
- priv->id = empathy_inspect_channel (priv->account, priv->tp_chan);
-
return priv->id;
}
@@ -885,7 +881,9 @@ tp_chat_state_changed_cb (DBusGProxy *chat_state_iface,
priv = GET_PRIV (chat);
- contact = empathy_tp_contact_list_get_from_handle (priv->list, handle);
+ contact = empathy_contact_factory_get_from_handle (priv->factory,
+ priv->account,
+ handle);
empathy_debug (DEBUG_DOMAIN, "Chat state changed for %s (%d): %d",
empathy_contact_get_name (contact),
@@ -906,22 +904,21 @@ tp_chat_build_message (EmpathyTpChat *chat,
EmpathyTpChatPriv *priv;
EmpathyMessage *message;
EmpathyContact *sender;
- EmpathyContact *receiver;
priv = GET_PRIV (chat);
- receiver = empathy_tp_contact_list_get_user (priv->list);
if (from_handle == 0) {
- sender = g_object_ref (receiver);
+ sender = g_object_ref (priv->user);
} else {
- sender = empathy_tp_contact_list_get_from_handle (priv->list,
+ sender = empathy_contact_factory_get_from_handle (priv->factory,
+ priv->account,
from_handle);
}
message = empathy_message_new (message_body);
empathy_message_set_type (message, type);
empathy_message_set_sender (message, sender);
- empathy_message_set_receiver (message, receiver);
+ empathy_message_set_receiver (message, priv->user);
empathy_message_set_timestamp (message, (EmpathyTime) timestamp);
g_object_unref (sender);
diff --git a/libempathy/empathy-tp-chatroom.c b/libempathy/empathy-tp-chatroom.c
index 32716865d..72f083942 100644
--- a/libempathy/empathy-tp-chatroom.c
+++ b/libempathy/empathy-tp-chatroom.c
@@ -23,9 +23,8 @@
#include <config.h>
#include "empathy-tp-chatroom.h"
-#include "empathy-tp-contact-list.h"
#include "empathy-contact-list.h"
-#include "empathy-contact-manager.h"
+#include "empathy-contact-factory.h"
#include "empathy-tp-group.h"
#include "empathy-utils.h"
#include "empathy-debug.h"
@@ -36,8 +35,7 @@
#define DEBUG_DOMAIN "TpChatroom"
struct _EmpathyTpChatroomPriv {
- EmpathyContactManager *manager;
- EmpathyTpContactList *list;
+ EmpathyContactFactory *factory;
EmpathyTpGroup *group;
gboolean is_invited;
@@ -49,21 +47,18 @@ static void empathy_tp_chatroom_class_init (EmpathyTpChatroomClass *
static void tp_chatroom_iface_init (EmpathyContactListIface *iface);
static void empathy_tp_chatroom_init (EmpathyTpChatroom *chatroom);
static void tp_chatroom_finalize (GObject *object);
-static void tp_chatroom_members_added_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
+static void tp_chatroom_member_added_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
guint reason,
const gchar *message,
- EmpathyTpChatroom *list);
-static void tp_chatroom_members_removed_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
+ EmpathyTpChatroom *chatroom);
+static void tp_chatroom_member_removed_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
guint reason,
const gchar *message,
- EmpathyTpChatroom *list);
-static void tp_chatroom_setup (EmpathyContactList *list);
-static EmpathyContact * tp_chatroom_find (EmpathyContactList *list,
- const gchar *id);
+ EmpathyTpChatroom *chatroom);
static void tp_chatroom_add (EmpathyContactList *list,
EmpathyContact *contact,
const gchar *message);
@@ -89,8 +84,6 @@ empathy_tp_chatroom_class_init (EmpathyTpChatroomClass *klass)
static void
tp_chatroom_iface_init (EmpathyContactListIface *iface)
{
- iface->setup = tp_chatroom_setup;
- iface->find = tp_chatroom_find;
iface->add = tp_chatroom_add;
iface->remove = tp_chatroom_remove;
iface->get_members = tp_chatroom_get_members;
@@ -111,7 +104,7 @@ tp_chatroom_finalize (GObject *object)
priv = GET_PRIV (chatroom);
g_object_unref (priv->group);
- g_object_unref (priv->manager);
+ g_object_unref (priv->factory);
if (priv->invitor) {
g_object_unref (priv->invitor);
@@ -129,7 +122,7 @@ empathy_tp_chatroom_new (McAccount *account,
EmpathyTpChatroomPriv *priv;
EmpathyTpChatroom *chatroom;
GList *members, *l;
- guint self_handle;
+ EmpathyContact *user;
g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
@@ -141,40 +134,41 @@ empathy_tp_chatroom_new (McAccount *account,
priv = GET_PRIV (chatroom);
- priv->manager = empathy_contact_manager_new ();
- priv->list = empathy_contact_manager_get_list (priv->manager, account);
+ priv->factory = empathy_contact_factory_new ();
priv->group = empathy_tp_group_new (account, tp_chan);
- g_signal_connect (priv->group, "members-added",
- G_CALLBACK (tp_chatroom_members_added_cb),
+ g_signal_connect (priv->group, "member-added",
+ G_CALLBACK (tp_chatroom_member_added_cb),
chatroom);
- g_signal_connect (priv->group, "members-removed",
- G_CALLBACK (tp_chatroom_members_removed_cb),
+ g_signal_connect (priv->group, "member-removed",
+ G_CALLBACK (tp_chatroom_member_removed_cb),
chatroom);
/* Check if we are invited to join the chat */
- self_handle = empathy_tp_group_get_self_handle (priv->group);
- members = empathy_tp_group_get_local_pending_members_with_info (priv->group);
+ user = empathy_tp_group_get_self_contact (priv->group);
+ members = empathy_tp_group_get_local_pendings (priv->group);
for (l = members; l; l = l->next) {
- EmpathyTpGroupInfo *info;
+ EmpathyPendingInfo *info;
info = l->data;
- if (info->member != self_handle) {
+ if (!empathy_contact_equal (user, info->member)) {
continue;
}
- priv->invitor = empathy_tp_contact_list_get_from_handle (priv->list,
- info->actor);
+ priv->invitor = g_object_ref (info->actor);
priv->invit_message = g_strdup (info->message);
priv->is_invited = TRUE;
- empathy_debug (DEBUG_DOMAIN, "We are invited to join by %s: %s",
- empathy_contact_get_name (priv->invitor),
- priv->invit_message);
+ empathy_debug (DEBUG_DOMAIN, "We are invited to join by %s (%d): %s",
+ empathy_contact_get_id (priv->invitor),
+ empathy_contact_get_handle (priv->invitor),
+ priv->invit_message);
}
- empathy_tp_group_info_list_free (members);
+ g_list_foreach (members, (GFunc) empathy_pending_info_free, NULL);
+ g_list_free (members);
+ g_object_unref (user);
return chatroom;
}
@@ -204,7 +198,7 @@ void
empathy_tp_chatroom_accept_invitation (EmpathyTpChatroom *chatroom)
{
EmpathyTpChatroomPriv *priv;
- guint self_handle;
+ EmpathyContact *user;
g_return_if_fail (EMPATHY_IS_TP_CHATROOM (chatroom));
@@ -220,80 +214,42 @@ empathy_tp_chatroom_accept_invitation (EmpathyTpChatroom *chatroom)
priv->invit_message = NULL;
/* Add ourself in the members of the room */
- self_handle = empathy_tp_group_get_self_handle (priv->group);
- empathy_tp_group_add_member (priv->group, self_handle,
- "Just for fun");
+ user = empathy_tp_group_get_self_contact (priv->group);
+ empathy_tp_group_add_member (priv->group, user, "");
+ g_object_unref (user);
}
void
empathy_tp_chatroom_set_topic (EmpathyTpChatroom *chatroom,
const gchar *topic)
{
+ /* FIXME: not implemented */
}
static void
-tp_chatroom_members_added_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpChatroom *chatroom)
+tp_chatroom_member_added_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message,
+ EmpathyTpChatroom *chatroom)
{
- EmpathyTpChatroomPriv *priv;
- GList *contacts, *l;
-
- priv = GET_PRIV (chatroom);
-
- contacts = empathy_tp_contact_list_get_from_handles (priv->list, handles);
- for (l = contacts; l; l = l->next) {
- EmpathyContact *contact;
-
- contact = l->data;
-
- g_signal_emit_by_name (chatroom, "contact-added", contact);
-
- g_object_unref (contact);
- }
- g_list_free (contacts);
-}
-
-static void
-tp_chatroom_members_removed_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpChatroom *chatroom)
-{
- EmpathyTpChatroomPriv *priv;
- GList *contacts, *l;
-
- priv = GET_PRIV (chatroom);
-
- contacts = empathy_tp_contact_list_get_from_handles (priv->list, handles);
- for (l = contacts; l; l = l->next) {
- EmpathyContact *contact;
-
- contact = l->data;
-
- g_signal_emit_by_name (chatroom, "contact-removed", contact);
-
- g_object_unref (contact);
- }
- g_list_free (contacts);
+ g_signal_emit_by_name (chatroom, "members-changed",
+ contact, actor, reason, message,
+ TRUE);
}
static void
-tp_chatroom_setup (EmpathyContactList *list)
-{
- /* Nothing to do */
-}
-
-static EmpathyContact *
-tp_chatroom_find (EmpathyContactList *list,
- const gchar *id)
+tp_chatroom_member_removed_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message,
+ EmpathyTpChatroom *chatroom)
{
- return NULL;
+ g_signal_emit_by_name (chatroom, "members-changed",
+ contact, actor, reason, message,
+ FALSE);
}
static void
@@ -308,9 +264,7 @@ tp_chatroom_add (EmpathyContactList *list,
priv = GET_PRIV (list);
- empathy_tp_group_add_member (priv->group,
- empathy_contact_get_handle (contact),
- message);
+ empathy_tp_group_add_member (priv->group, contact, message);
}
static void
@@ -325,26 +279,18 @@ tp_chatroom_remove (EmpathyContactList *list,
priv = GET_PRIV (list);
- empathy_tp_group_remove_member (priv->group,
- empathy_contact_get_handle (contact),
- message);
+ empathy_tp_group_remove_member (priv->group, contact, message);
}
static GList *
tp_chatroom_get_members (EmpathyContactList *list)
{
EmpathyTpChatroomPriv *priv;
- GArray *members;
- GList *contacts;
g_return_val_if_fail (EMPATHY_IS_TP_CHATROOM (list), NULL);
priv = GET_PRIV (list);
- members = empathy_tp_group_get_members (priv->group);
- contacts = empathy_tp_contact_list_get_from_handles (priv->list, members);
- g_array_free (members, TRUE);
-
- return contacts;
+ return empathy_tp_group_get_members (priv->group);
}
diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c
index a5c54b74e..16ecad807 100644
--- a/libempathy/empathy-tp-contact-list.c
+++ b/libempathy/empathy-tp-contact-list.c
@@ -30,9 +30,6 @@
#include <libtelepathy/tp-conn.h>
#include <libtelepathy/tp-chan.h>
#include <libtelepathy/tp-chan-type-contact-list-gen.h>
-#include <libtelepathy/tp-conn-iface-aliasing-gen.h>
-#include <libtelepathy/tp-conn-iface-presence-gen.h>
-#include <libtelepathy/tp-conn-iface-avatars-gen.h>
#include "empathy-tp-contact-list.h"
#include "empathy-contact-list.h"
@@ -44,906 +41,305 @@
EMPATHY_TYPE_TP_CONTACT_LIST, EmpathyTpContactListPriv))
#define DEBUG_DOMAIN "TpContactList"
-#define MAX_AVATAR_REQUESTS 10
struct _EmpathyTpContactListPriv {
TpConn *tp_conn;
McAccount *account;
MissionControl *mc;
- EmpathyContact *user_contact;
- gboolean setup;
const gchar *protocol_group;
EmpathyTpGroup *publish;
EmpathyTpGroup *subscribe;
-
- GHashTable *groups;
- GHashTable *contacts;
GList *members;
- GList *local_pending;
+ GList *pendings;
- DBusGProxy *aliasing_iface;
- DBusGProxy *avatars_iface;
- DBusGProxy *presence_iface;
+ GList *groups;
+ GHashTable *contacts_groups;
};
typedef enum {
TP_CONTACT_LIST_TYPE_PUBLISH,
TP_CONTACT_LIST_TYPE_SUBSCRIBE,
- TP_CONTACT_LIST_TYPE_UNKNOWN,
- TP_CONTACT_LIST_TYPE_COUNT
+ TP_CONTACT_LIST_TYPE_UNKNOWN
} TpContactListType;
-typedef struct {
- guint handle;
- GList *new_groups;
-} TpContactListData;
-
-typedef struct {
- EmpathyTpContactList *list;
- guint handle;
-} TpContactListAvatarRequestData;
-
-typedef struct {
- EmpathyTpContactList *list;
- guint *handles;
-} TpContactListAliasesRequestData;
-
-static void empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass);
-static void tp_contact_list_iface_init (EmpathyContactListIface *iface);
-static void empathy_tp_contact_list_init (EmpathyTpContactList *list);
-static void tp_contact_list_finalize (GObject *object);
-static void tp_contact_list_finalize_proxies (EmpathyTpContactList *list);
-static void tp_contact_list_setup (EmpathyContactList *list);
-static EmpathyContact * tp_contact_list_find (EmpathyContactList *list,
- const gchar *id);
-static void tp_contact_list_add (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message);
-static void tp_contact_list_remove (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message);
-static GList * tp_contact_list_get_members (EmpathyContactList *list);
-static GList * tp_contact_list_get_local_pending (EmpathyContactList *list);
-static void tp_contact_list_process_pending (EmpathyContactList *list,
- EmpathyContact *contact,
- gboolean accept);
-static void tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
- EmpathyContact *contact);
-static void tp_contact_list_contact_removed_foreach (guint handle,
- EmpathyContact *contact,
- EmpathyTpContactList *list);
-static void tp_contact_list_destroy_cb (DBusGProxy *proxy,
- EmpathyTpContactList *list);
-static gboolean tp_contact_list_find_foreach (guint handle,
- EmpathyContact *contact,
- gchar *id);
-static void tp_contact_list_newchannel_cb (DBusGProxy *proxy,
- const gchar *object_path,
- const gchar *channel_type,
- TelepathyHandleType handle_type,
- guint channel_handle,
- gboolean suppress_handle,
- EmpathyTpContactList *list);
-static TpContactListType tp_contact_list_get_type (EmpathyTpContactList *list,
- EmpathyTpGroup *group);
-static void tp_contact_list_added_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list);
-static void tp_contact_list_removed_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list);
-static void tp_contact_list_pending_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list);
-static void tp_contact_list_groups_updated_cb (EmpathyContact *contact,
- GParamSpec *param,
- EmpathyTpContactList *list);
-static void tp_contact_list_name_updated_cb (EmpathyContact *contact,
- GParamSpec *param,
- EmpathyTpContactList *list);
-static void tp_contact_list_update_groups_foreach (gchar *object_path,
- EmpathyTpGroup *group,
- TpContactListData *data);
-static EmpathyTpGroup * tp_contact_list_get_group (EmpathyTpContactList *list,
- const gchar *name);
-static gboolean tp_contact_list_find_group (gchar *key,
- EmpathyTpGroup *group,
- gchar *group_name);
-static void tp_contact_list_get_groups_foreach (gchar *key,
- EmpathyTpGroup *group,
- GList **groups);
-static void tp_contact_list_group_channel_closed_cb (TpChan *channel,
- EmpathyTpContactList *list);
-static void tp_contact_list_group_members_added_cb (EmpathyTpGroup *group,
- GArray *members,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list);
-static void tp_contact_list_group_members_removed_cb (EmpathyTpGroup *group,
- GArray *members,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list);
-static void tp_contact_list_get_info (EmpathyTpContactList *list,
- GArray *handles);
-static void tp_contact_list_request_avatar (EmpathyTpContactList *list,
- guint handle);
-static void tp_contact_list_start_avatar_requests (void);
-static void tp_contact_list_avatar_update_cb (DBusGProxy *proxy,
- guint handle,
- gchar *new_token,
- EmpathyTpContactList *list);
-static void tp_contact_list_request_avatar_cb (DBusGProxy *proxy,
- GArray *avatar_data,
- gchar *mime_type,
- GError *error,
- TpContactListAvatarRequestData *data);
-static void tp_contact_list_aliases_update_cb (DBusGProxy *proxy,
- GPtrArray *handlers,
- EmpathyTpContactList *list);
-static void tp_contact_list_request_aliases_cb (DBusGProxy *proxy,
- gchar **contact_names,
- GError *error,
- TpContactListAliasesRequestData *data);
-static void tp_contact_list_presence_update_cb (DBusGProxy *proxy,
- GHashTable *handle_table,
- EmpathyTpContactList *list);
-static void tp_contact_list_parse_presence_foreach (guint handle,
- GValueArray *presence_struct,
- EmpathyTpContactList *list);
-static void tp_contact_list_presences_table_foreach (const gchar *state_str,
- GHashTable *presences_table,
- EmpathyPresence **presence);
-static void tp_contact_list_status_changed_cb (MissionControl *mc,
- TelepathyConnectionStatus status,
- McPresence presence,
- TelepathyConnectionStatusReason reason,
- const gchar *unique_name,
- EmpathyTpContactList *list);
+static void empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass);
+static void empathy_tp_contact_list_init (EmpathyTpContactList *list);
+static void tp_contact_list_iface_init (EmpathyContactListIface *iface);
enum {
DESTROY,
LAST_SIGNAL
};
-static guint signals[LAST_SIGNAL];
-GList *avatar_requests_queue = NULL;
-guint n_avatar_requests = 0;
+static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE_WITH_CODE (EmpathyTpContactList, empathy_tp_contact_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
tp_contact_list_iface_init));
static void
-empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = tp_contact_list_finalize;
-
- signals[DESTROY] =
- g_signal_new ("destroy",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- g_type_class_add_private (object_class, sizeof (EmpathyTpContactListPriv));
-}
-
-static void
-tp_contact_list_iface_init (EmpathyContactListIface *iface)
-{
- iface->setup = tp_contact_list_setup;
- iface->find = tp_contact_list_find;
- iface->add = tp_contact_list_add;
- iface->remove = tp_contact_list_remove;
- iface->get_members = tp_contact_list_get_members;
- iface->get_local_pending = tp_contact_list_get_local_pending;
- iface->process_pending = tp_contact_list_process_pending;
-}
-
-static void
-empathy_tp_contact_list_init (EmpathyTpContactList *list)
+tp_contact_list_group_destroy_cb (EmpathyTpGroup *group,
+ EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
- priv = GET_PRIV (list);
+ empathy_debug (DEBUG_DOMAIN, "Group destroyed: %s",
+ empathy_tp_group_get_name (group));
- priv->groups = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_object_unref);
- priv->contacts = g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- NULL,
- (GDestroyNotify) g_object_unref);
+ priv->groups = g_list_remove (priv->groups, group);
+ g_object_unref (group);
}
static void
-tp_contact_list_finalize (GObject *object)
+tp_contact_list_group_member_added_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- EmpathyTpContactList *list;
-
- list = EMPATHY_TP_CONTACT_LIST (object);
- priv = GET_PRIV (list);
-
- empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
-
- dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
- "AccountStatusChanged",
- G_CALLBACK (tp_contact_list_status_changed_cb),
- list);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ const gchar *group_name;
+ GList **groups;
- tp_contact_list_finalize_proxies (list);
-
- if (priv->tp_conn) {
- g_object_unref (priv->tp_conn);
- }
- if (priv->subscribe) {
- g_object_unref (priv->subscribe);
- }
- if (priv->publish) {
- g_object_unref (priv->publish);
- }
-
- g_object_unref (priv->account);
- g_object_unref (priv->user_contact);
- g_object_unref (priv->mc);
- g_hash_table_destroy (priv->groups);
- g_hash_table_destroy (priv->contacts);
-
- g_list_foreach (priv->local_pending, (GFunc) empathy_contact_list_info_free, NULL);
- g_list_free (priv->local_pending);
-
- g_list_foreach (priv->members, (GFunc) g_object_unref, NULL);
- g_list_free (priv->members);
-
- G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
-}
-
-EmpathyTpContactList *
-empathy_tp_contact_list_new (McAccount *account)
-{
- EmpathyTpContactListPriv *priv;
- EmpathyTpContactList *list;
- MissionControl *mc;
- McProfile *profile;
- const gchar *protocol_name;
- guint handle;
- GError *error = NULL;
-
- g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-
- mc = empathy_mission_control_new ();
-
- if (mission_control_get_connection_status (mc, account, NULL) != 0) {
- /* The account is not connected, nothing to do. */
- return NULL;
- }
-
- list = g_object_new (EMPATHY_TYPE_TP_CONTACT_LIST, NULL);
- priv = GET_PRIV (list);
-
- priv->tp_conn = mission_control_get_connection (mc, account, NULL);
- priv->account = g_object_ref (account);
- priv->mc = mc;
-
- /* Check for protocols that does not support contact groups. We can
- * put all contacts into a special group in that case.
- * FIXME: Default group should be an information in the profile */
- profile = mc_account_get_profile (account);
- protocol_name = mc_profile_get_protocol_name (profile);
- if (strcmp (protocol_name, "local-xmpp") == 0) {
- priv->protocol_group = _("People nearby");
- }
- g_object_unref (profile);
-
- g_signal_connect (priv->tp_conn, "destroy",
- G_CALLBACK (tp_contact_list_destroy_cb),
- list);
- dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
- "AccountStatusChanged",
- G_CALLBACK (tp_contact_list_status_changed_cb),
- list, NULL);
-
- priv->aliasing_iface = tp_conn_get_interface (priv->tp_conn,
- TELEPATHY_CONN_IFACE_ALIASING_QUARK);
- priv->avatars_iface = tp_conn_get_interface (priv->tp_conn,
- TELEPATHY_CONN_IFACE_AVATARS_QUARK);
- priv->presence_iface = tp_conn_get_interface (priv->tp_conn,
- TELEPATHY_CONN_IFACE_PRESENCE_QUARK);
-
- if (priv->aliasing_iface) {
- dbus_g_proxy_connect_signal (priv->aliasing_iface,
- "AliasesChanged",
- G_CALLBACK (tp_contact_list_aliases_update_cb),
- list, NULL);
- }
-
- if (priv->avatars_iface) {
- dbus_g_proxy_connect_signal (priv->avatars_iface,
- "AvatarUpdated",
- G_CALLBACK (tp_contact_list_avatar_update_cb),
- list, NULL);
+ if (!g_list_find (priv->members, contact)) {
+ return;
}
- if (priv->presence_iface) {
- dbus_g_proxy_connect_signal (priv->presence_iface,
- "PresenceUpdate",
- G_CALLBACK (tp_contact_list_presence_update_cb),
- list, NULL);
+ groups = g_hash_table_lookup (priv->contacts_groups, contact);
+ if (!groups) {
+ groups = g_slice_new0 (GList*);
+ g_hash_table_insert (priv->contacts_groups,
+ g_object_ref (contact),
+ groups);
}
- /* Get our own handle and contact */
- if (!tp_conn_get_self_handle (DBUS_G_PROXY (priv->tp_conn),
- &handle, &error)) {
- empathy_debug (DEBUG_DOMAIN, "GetSelfHandle Error: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- } else {
- priv->user_contact = empathy_tp_contact_list_get_from_handle (list, handle);
- empathy_contact_set_is_user (priv->user_contact, TRUE);
+ group_name = empathy_tp_group_get_name (group);
+ if (!g_list_find_custom (*groups, group_name, (GCompareFunc) strcmp)) {
+ empathy_debug (DEBUG_DOMAIN, "Contact %s (%d) added to group %s",
+ empathy_contact_get_id (contact),
+ empathy_contact_get_handle (contact),
+ group_name);
+ *groups = g_list_prepend (*groups, g_strdup (group_name));
+ g_signal_emit_by_name (list, "groups-changed", contact,
+ group_name,
+ TRUE);
}
-
- return list;
}
static void
-tp_contact_list_setup (EmpathyContactList *list)
+tp_contact_list_group_member_removed_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- GPtrArray *channels;
- GError *error = NULL;
- guint i;
-
- g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
- priv = GET_PRIV (list);
-
- empathy_debug (DEBUG_DOMAIN, "setup contact list: %p", list);
-
- priv->setup = TRUE;
- dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
- G_CALLBACK (tp_contact_list_newchannel_cb),
- list, NULL);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ const gchar *group_name;
+ GList **groups, *l;
- /* Get existing channels */
- if (!tp_conn_list_channels (DBUS_G_PROXY (priv->tp_conn),
- &channels,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Failed to get list of open channels: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
+ if (!g_list_find (priv->members, contact)) {
return;
}
- for (i = 0; channels->len > i; i++) {
- GValueArray *chan_struct;
- const gchar *object_path;
- const gchar *chan_iface;
- TelepathyHandleType handle_type;
- guint handle;
-
- chan_struct = g_ptr_array_index (channels, i);
- object_path = g_value_get_boxed (g_value_array_get_nth (chan_struct, 0));
- chan_iface = g_value_get_string (g_value_array_get_nth (chan_struct, 1));
- handle_type = g_value_get_uint (g_value_array_get_nth (chan_struct, 2));
- handle = g_value_get_uint (g_value_array_get_nth (chan_struct, 3));
-
- tp_contact_list_newchannel_cb (DBUS_G_PROXY (priv->tp_conn),
- object_path, chan_iface,
- handle_type, handle,
- FALSE,
- EMPATHY_TP_CONTACT_LIST (list));
-
- g_value_array_free (chan_struct);
+ groups = g_hash_table_lookup (priv->contacts_groups, contact);
+ if (!groups) {
+ return;
}
- g_ptr_array_free (channels, TRUE);
-}
-
-static EmpathyContact *
-tp_contact_list_find (EmpathyContactList *list,
- const gchar *id)
-{
- EmpathyTpContactListPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
- priv = GET_PRIV (list);
-
- return g_hash_table_find (priv->contacts,
- (GHRFunc) tp_contact_list_find_foreach,
- (gchar*) id);
-}
-
-static void
-tp_contact_list_add (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message)
-{
- EmpathyTpContactListPriv *priv;
- guint handle;
-
- g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
- priv = GET_PRIV (list);
-
- handle = empathy_contact_get_handle (contact);
- empathy_tp_group_add_member (priv->subscribe, handle, message);
-}
-
-static void
-tp_contact_list_remove (EmpathyContactList *list,
- EmpathyContact *contact,
- const gchar *message)
-{
- EmpathyTpContactListPriv *priv;
- guint handle;
-
- g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
-
- priv = GET_PRIV (list);
-
- handle = empathy_contact_get_handle (contact);
- empathy_tp_group_remove_member (priv->subscribe, handle, message);
-}
-
-static GList *
-tp_contact_list_get_members (EmpathyContactList *list)
-{
- EmpathyTpContactListPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
- priv = GET_PRIV (list);
-
- g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
- return g_list_copy (priv->members);
-}
-
-static GList *
-tp_contact_list_get_local_pending (EmpathyContactList *list)
-{
- EmpathyTpContactListPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
- priv = GET_PRIV (list);
-
- return g_list_copy (priv->local_pending);
-}
-
-static void
-tp_contact_list_process_pending (EmpathyContactList *list,
- EmpathyContact *contact,
- gboolean accept)
-{
- EmpathyTpContactListPriv *priv;
- guint handle;
-
- g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
- g_return_if_fail (EMPATHY_IS_CONTACT (contact));
-
- priv = GET_PRIV (list);
-
- handle = empathy_contact_get_handle (contact);
- if (accept) {
- empathy_tp_group_add_member (priv->publish, handle, NULL);
- empathy_tp_group_add_member (priv->subscribe, handle, NULL);
- } else {
- empathy_tp_group_remove_member (priv->publish, handle, NULL);
+ group_name = empathy_tp_group_get_name (group);
+ if ((l = g_list_find_custom (*groups, group_name, (GCompareFunc) strcmp))) {
+ empathy_debug (DEBUG_DOMAIN, "Contact %s (%d) removed from group %s",
+ empathy_contact_get_id (contact),
+ empathy_contact_get_handle (contact),
+ group_name);
+ *groups = g_list_delete_link (*groups, l);
+ g_signal_emit_by_name (list, "groups-changed", contact,
+ group_name,
+ FALSE);
}
}
-McAccount *
-empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
-{
- EmpathyTpContactListPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
- priv = GET_PRIV (list);
-
- return priv->account;
-}
-
-EmpathyContact *
-empathy_tp_contact_list_get_user (EmpathyTpContactList *list)
+static EmpathyTpGroup *
+tp_contact_list_find_group (EmpathyTpContactList *list,
+ const gchar *group)
{
- EmpathyTpContactListPriv *priv;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ GList *l;
- priv = GET_PRIV (list);
-
- return priv->user_contact;
+ for (l = priv->groups; l; l = l->next) {
+ if (strcmp (group, empathy_tp_group_get_name (l->data)) == 0) {
+ return l->data;
+ }
+ }
+ return NULL;
}
-EmpathyContact *
-empathy_tp_contact_list_get_from_id (EmpathyTpContactList *list,
- const gchar *id)
+static TpContactListType
+tp_contact_list_get_type (EmpathyTpContactList *list,
+ EmpathyTpGroup *group)
{
EmpathyTpContactListPriv *priv;
- EmpathyContact *contact;
- const gchar *contact_ids[] = {id, NULL};
- GArray *handles;
- guint handle;
- GError *error = NULL;
+ TpContactListType list_type;
+ const gchar *name;
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
- g_return_val_if_fail (id != NULL, NULL);
-
priv = GET_PRIV (list);
- contact = tp_contact_list_find (EMPATHY_CONTACT_LIST (list), id);
- if (contact) {
- return g_object_ref (contact);
- }
-
- /* The id is unknown, requests a new handle */
- if (!tp_conn_request_handles (DBUS_G_PROXY (priv->tp_conn),
- TP_HANDLE_TYPE_CONTACT,
- contact_ids,
- &handles, &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "RequestHandle for %s failed: %s", id,
- error ? error->message : "No error given");
- g_clear_error (&error);
- return NULL;
- }
-
- handle = g_array_index(handles, guint, 0);
- g_array_free (handles, TRUE);
-
- return empathy_tp_contact_list_get_from_handle (list, handle);
-}
-
-EmpathyContact *
-empathy_tp_contact_list_get_from_handle (EmpathyTpContactList *list,
- guint handle)
-{
- EmpathyContact *contact;
- GArray *handles;
- GList *contacts;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
- handles = g_array_new (FALSE, FALSE, sizeof (guint));
- g_array_append_val (handles, handle);
-
- contacts = empathy_tp_contact_list_get_from_handles (list, handles);
- g_array_free (handles, TRUE);
-
- if (!contacts) {
- return NULL;
+ name = empathy_tp_group_get_name (group);
+ if (strcmp (name, "subscribe") == 0) {
+ list_type = TP_CONTACT_LIST_TYPE_SUBSCRIBE;
+ } else if (strcmp (name, "publish") == 0) {
+ list_type = TP_CONTACT_LIST_TYPE_PUBLISH;
+ } else {
+ list_type = TP_CONTACT_LIST_TYPE_UNKNOWN;
}
- contact = contacts->data;
- g_list_free (contacts);
-
- return contact;
+ return list_type;
}
-GList *
-empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
- GArray *handles)
+static void
+tp_contact_list_add_member (EmpathyTpContactList *list,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message)
{
- EmpathyTpContactListPriv *priv;
- gchar **handles_names;
- gchar **id;
- GArray *new_handles;
- GList *contacts = NULL;
- guint i;
- GError *error = NULL;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
- g_return_val_if_fail (handles != NULL, NULL);
-
- priv = GET_PRIV (list);
-
- /* Search all handles we already have */
- new_handles = g_array_new (FALSE, FALSE, sizeof (guint));
- for (i = 0; i < handles->len; i++) {
- EmpathyContact *contact;
- guint handle;
-
- handle = g_array_index (handles, guint, i);
-
- if (handle == 0) {
- continue;
- }
-
- contact = g_hash_table_lookup (priv->contacts,
- GUINT_TO_POINTER (handle));
-
- if (contact) {
- contacts = g_list_prepend (contacts,
- g_object_ref (contact));
- } else {
- g_array_append_val (new_handles, handle);
- }
- }
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ GList *l;
- if (new_handles->len == 0) {
- g_array_free (new_handles, TRUE);
- return contacts;
- }
+ /* Add to the list and emit signal */
+ priv->members = g_list_prepend (priv->members, g_object_ref (contact));
+ g_signal_emit_by_name (list, "members-changed",
+ contact, actor, reason, message,
+ TRUE);
- /* Holds all handles we don't have yet.
- * FIXME: We should release them at some point. */
- if (!tp_conn_hold_handles (DBUS_G_PROXY (priv->tp_conn),
- TP_HANDLE_TYPE_CONTACT,
- new_handles, &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "HoldHandles Error: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- g_array_free (new_handles, TRUE);
- return contacts;
+ /* This contact is now member, implicitly accept pending. */
+ if (g_list_find (priv->pendings, contact)) {
+ empathy_tp_group_add_member (priv->publish, contact, "");
}
- /* Get the IDs of all new handles */
- if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn),
- TP_HANDLE_TYPE_CONTACT,
- new_handles,
- &handles_names,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "InspectHandle Error: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- g_array_free (new_handles, TRUE);
- return contacts;
- }
-
- /* Create contact objects */
- for (i = 0, id = handles_names; *id && i < new_handles->len; id++, i++) {
- EmpathyContact *contact;
- guint handle;
-
- handle = g_array_index (new_handles, guint, i);
- contact = g_object_new (EMPATHY_TYPE_CONTACT,
- "account", priv->account,
- "id", *id,
- "handle", handle,
- NULL);
-
- if (priv->protocol_group) {
- empathy_contact_add_group (contact, priv->protocol_group);
+ /* Update groups of the contact */
+ for (l = priv->groups; l; l = l->next) {
+ if (empathy_tp_group_is_member (l->data, contact)) {
+ tp_contact_list_group_member_added_cb (l->data, contact,
+ NULL, 0, NULL,
+ list);
}
-
- if (!priv->presence_iface) {
- EmpathyPresence *presence;
-
- /* We have no presence iface, set default presence
- * to available */
- presence = empathy_presence_new_full (MC_PRESENCE_AVAILABLE,
- NULL);
-
- empathy_contact_set_presence (contact, presence);
- g_object_unref (presence);
- }
-
- g_signal_connect (contact, "notify::groups",
- G_CALLBACK (tp_contact_list_groups_updated_cb),
- list);
- g_signal_connect (contact, "notify::name",
- G_CALLBACK (tp_contact_list_name_updated_cb),
- list);
-
- empathy_debug (DEBUG_DOMAIN, "new contact created: %s (%d)",
- *id, handle);
-
- g_hash_table_insert (priv->contacts,
- GUINT_TO_POINTER (handle),
- contact);
-
- contacts = g_list_prepend (contacts, g_object_ref (contact));
}
-
- tp_contact_list_get_info (list, new_handles);
-
- g_array_free (new_handles, TRUE);
- g_strfreev (handles_names);
-
- return contacts;
}
-void
-empathy_tp_contact_list_rename_group (EmpathyTpContactList *list,
- const gchar *old_group,
- const gchar *new_group)
+static void
+tp_contact_list_added_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- EmpathyTpGroup *group;
- GArray *members;
-
- g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
- g_return_if_fail (old_group != NULL);
- g_return_if_fail (new_group != NULL);
-
- priv = GET_PRIV (list);
-
- group = g_hash_table_find (priv->groups,
- (GHRFunc) tp_contact_list_find_group,
- (gchar*) old_group);
- if (!group) {
- /* The group doesn't exists on this account */
- return;
- }
-
- empathy_debug (DEBUG_DOMAIN, "rename group %s to %s", group, new_group);
-
- /* Remove all members from the old group */
- members = empathy_tp_group_get_members (group);
- empathy_tp_group_remove_members (group, members, "");
- tp_contact_list_group_members_removed_cb (group, members,
- 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
- NULL, list);
- g_hash_table_remove (priv->groups,
- empathy_tp_group_get_object_path (group));
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ TpContactListType list_type;
- /* Add all members to the new group */
- group = tp_contact_list_get_group (list, new_group);
- if (group) {
- empathy_tp_group_add_members (group, members, "");
+ list_type = tp_contact_list_get_type (list, group);
+ empathy_debug (DEBUG_DOMAIN, "Contact %s (%d) added to list type %d",
+ empathy_contact_get_id (contact),
+ empathy_contact_get_handle (contact),
+ list_type);
+
+ /* We now get the presence of that contact, add it to members */
+ if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE &&
+ !g_list_find (priv->members, contact)) {
+ tp_contact_list_add_member (list, contact, actor, reason, message);
+ }
+
+ /* We now send our presence to that contact, remove it from pendings */
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH &&
+ g_list_find (priv->pendings, contact)) {
+ g_signal_emit_by_name (list, "pendings-changed",
+ contact, actor, reason, message,
+ FALSE);
+ priv->pendings = g_list_remove (priv->pendings, contact);
+ g_object_unref (contact);
}
}
-GList *
-empathy_tp_contact_list_get_groups (EmpathyTpContactList *list)
-{
- EmpathyTpContactListPriv *priv;
- GList *groups = NULL;
-
- g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-
- priv = GET_PRIV (list);
-
- g_hash_table_foreach (priv->groups,
- (GHFunc) tp_contact_list_get_groups_foreach,
- &groups);
-
- groups = g_list_sort (groups, (GCompareFunc) strcmp);
-
- return groups;
-}
-
static void
-tp_contact_list_finalize_proxies (EmpathyTpContactList *list)
+tp_contact_list_removed_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message,
+ EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
-
- priv = GET_PRIV (list);
-
- if (priv->tp_conn) {
- g_signal_handlers_disconnect_by_func (priv->tp_conn,
- tp_contact_list_destroy_cb,
- list);
- dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
- G_CALLBACK (tp_contact_list_newchannel_cb),
- list);
- }
-
- if (priv->aliasing_iface) {
- dbus_g_proxy_disconnect_signal (priv->aliasing_iface,
- "AliasesChanged",
- G_CALLBACK (tp_contact_list_aliases_update_cb),
- list);
- }
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ TpContactListType list_type;
- if (priv->avatars_iface) {
- dbus_g_proxy_disconnect_signal (priv->avatars_iface,
- "AvatarUpdated",
- G_CALLBACK (tp_contact_list_avatar_update_cb),
- list);
+ list_type = tp_contact_list_get_type (list, group);
+ empathy_debug (DEBUG_DOMAIN, "Contact %s (%d) removed from list type %d",
+ empathy_contact_get_id (contact),
+ empathy_contact_get_handle (contact),
+ list_type);
+
+ /* This contact refuses to send us his presence, remove from members. */
+ if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE &&
+ g_list_find (priv->members, contact)) {
+ g_signal_emit_by_name (list, "members-changed",
+ contact, actor, reason, message,
+ FALSE);
+ priv->members = g_list_remove (priv->members, contact);
+ g_object_unref (contact);
}
- if (priv->presence_iface) {
- dbus_g_proxy_disconnect_signal (priv->presence_iface,
- "PresenceUpdate",
- G_CALLBACK (tp_contact_list_presence_update_cb),
- list);
+ /* We refuse to send our presence to that contact, remove from pendings */
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH &&
+ g_list_find (priv->pendings, contact)) {
+ g_signal_emit_by_name (list, "pendings-changed",
+ contact, actor, reason, message,
+ FALSE);
+ priv->pendings = g_list_remove (priv->pendings, contact);
+ g_object_unref (contact);
}
}
static void
-tp_contact_list_destroy_cb (DBusGProxy *proxy,
+tp_contact_list_pending_cb (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ EmpathyContact *actor,
+ guint reason,
+ const gchar *message,
EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
-
- priv = GET_PRIV (list);
-
- empathy_debug (DEBUG_DOMAIN, "Connection destroyed... "
- "Account disconnected or CM crashed");
-
- /* DBus proxies should NOT be used anymore */
- g_object_unref (priv->tp_conn);
- priv->tp_conn = NULL;
- priv->aliasing_iface = NULL;
- priv->avatars_iface = NULL;
- priv->presence_iface = NULL;
-
- /* Remove all contacts */
- g_hash_table_foreach (priv->contacts,
- (GHFunc) tp_contact_list_contact_removed_foreach,
- list);
- g_hash_table_remove_all (priv->contacts);
-
- /* Tell the world to not use us anymore */
- g_signal_emit (list, signals[DESTROY], 0);
-}
-
-static void
-tp_contact_list_contact_removed_foreach (guint handle,
- EmpathyContact *contact,
- EmpathyTpContactList *list)
-{
- g_signal_handlers_disconnect_by_func (contact,
- tp_contact_list_groups_updated_cb,
- list);
- g_signal_handlers_disconnect_by_func (contact,
- tp_contact_list_name_updated_cb,
- list);
-
- g_signal_emit_by_name (list, "contact-removed", contact);
-}
-
-static void
-tp_contact_list_block_contact (EmpathyTpContactList *list,
- EmpathyContact *contact)
-{
- g_signal_handlers_block_by_func (contact,
- tp_contact_list_groups_updated_cb,
- list);
- g_signal_handlers_block_by_func (contact,
- tp_contact_list_name_updated_cb,
- list);
-}
-
-static void
-tp_contact_list_unblock_contact (EmpathyTpContactList *list,
- EmpathyContact *contact)
-{
- g_signal_handlers_unblock_by_func (contact,
- tp_contact_list_groups_updated_cb,
- list);
- g_signal_handlers_unblock_by_func (contact,
- tp_contact_list_name_updated_cb,
- list);
-}
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ TpContactListType list_type;
-static gboolean
-tp_contact_list_find_foreach (guint handle,
- EmpathyContact *contact,
- gchar *id)
-{
- if (strcmp (empathy_contact_get_id (contact), id) == 0) {
- return TRUE;
+ list_type = tp_contact_list_get_type (list, group);
+ empathy_debug (DEBUG_DOMAIN, "Contact %s (%d) pending in list type %d",
+ empathy_contact_get_id (contact),
+ empathy_contact_get_handle (contact),
+ list_type);
+
+ /* We want this contact in our contact list but we don't get its
+ * presence yet. Add to members anyway. */
+ if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE &&
+ !g_list_find (priv->members, contact)) {
+ tp_contact_list_add_member (list, contact, actor, reason, message);
+ }
+
+ /* This contact wants our presence, auto accept if he is member,
+ * otherwise he is pending. */
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH &&
+ !g_list_find (priv->pendings, contact)) {
+ if (g_list_find (priv->members, contact)) {
+ empathy_tp_group_add_member (priv->publish, contact, "");
+ } else {
+ priv->pendings = g_list_prepend (priv->pendings,
+ g_object_ref (contact));
+ g_signal_emit_by_name (list, "pendings-changed",
+ contact, actor, reason, message,
+ TRUE);
+ }
}
-
- return FALSE;
}
static void
@@ -955,17 +351,13 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy,
gboolean suppress_handle,
EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
EmpathyTpGroup *group;
TpChan *new_chan;
const gchar *bus_name;
- GArray *members;
-
- priv = GET_PRIV (list);
if (strcmp (channel_type, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST) != 0 ||
- suppress_handle ||
- !priv->setup) {
+ suppress_handle) {
return;
}
@@ -973,962 +365,629 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy,
new_chan = tp_chan_new (tp_get_bus (),
bus_name,
object_path,
- channel_type, handle_type, channel_handle);
+ channel_type,
+ handle_type,
+ channel_handle);
g_return_if_fail (TELEPATHY_IS_CHAN (new_chan));
- if (handle_type == TP_HANDLE_TYPE_LIST) {
- TpContactListType list_type;
+ group = empathy_tp_group_new (priv->account, new_chan);
+ g_object_unref (new_chan);
- group = empathy_tp_group_new (priv->account, new_chan);
+ if (handle_type == TP_HANDLE_TYPE_LIST) {
+ TpContactListType list_type;
+ GList *contacts, *l;
list_type = tp_contact_list_get_type (list, group);
- if (list_type == TP_CONTACT_LIST_TYPE_UNKNOWN) {
- empathy_debug (DEBUG_DOMAIN,
- "Type of contact list channel unknown: %s",
- empathy_tp_group_get_name (group));
-
- g_object_unref (new_chan);
- g_object_unref (group);
- return;
- } else {
- empathy_debug (DEBUG_DOMAIN,
- "New contact list channel of type: %d",
- list_type);
- }
-
- g_signal_connect (group, "members-added",
- G_CALLBACK (tp_contact_list_added_cb),
- list);
- g_signal_connect (group, "members-removed",
- G_CALLBACK (tp_contact_list_removed_cb),
- list);
-
- if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
- GList *pendings, *l;
-
- if (priv->publish) {
- g_object_unref (priv->publish);
- }
+ if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH && !priv->publish) {
priv->publish = group;
- /* Makes no sense to be in remote-pending */
+ /* Publish is the list of contacts to who we send our
+ * presence. Makes no sense to be in remote-pending */
g_signal_connect (group, "local-pending",
G_CALLBACK (tp_contact_list_pending_cb),
list);
- pendings = empathy_tp_group_get_local_pending_members_with_info (group);
- if (pendings) {
- GArray *pending;
-
- pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
- for (l = pendings; l; l = l->next) {
- EmpathyTpGroupInfo *info;
-
- info = l->data;
-
- g_array_insert_val (pending, 0, info->member);
- tp_contact_list_pending_cb (group, pending,
- info->actor,
- info->reason,
- info->message,
- list);
- }
- g_array_free (pending, TRUE);
- empathy_tp_group_info_list_free (pendings);
+ contacts = empathy_tp_group_get_local_pendings (group);
+ for (l = contacts; l; l = l->next) {
+ EmpathyPendingInfo *info = l->data;
+
+ tp_contact_list_pending_cb (group,
+ info->member,
+ info->actor,
+ 0,
+ info->message,
+ list);
+ empathy_pending_info_free (info);
}
+ g_list_free (contacts);
}
- if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- GArray *remote_pendings = NULL;
-
- if (priv->subscribe) {
- g_object_unref (priv->subscribe);
- }
+ else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE && !priv->subscribe) {
priv->subscribe = group;
- /* Makes no sense to be in local-pending */
+ /* Subscribe is the list of contacts from who we
+ * receive presence. Makes no sense to be in
+ * local-pending */
g_signal_connect (group, "remote-pending",
G_CALLBACK (tp_contact_list_pending_cb),
list);
- empathy_tp_group_get_all_members (group,
- &members,
- NULL,
- &remote_pendings);
-
- tp_contact_list_pending_cb (group, remote_pendings, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
- NULL,
- list);
- g_array_free (remote_pendings, TRUE);
+
+ contacts = empathy_tp_group_get_remote_pendings (group);
+ for (l = contacts; l; l = l->next) {
+ tp_contact_list_pending_cb (group,
+ l->data,
+ NULL, 0,
+ NULL, list);
+ g_object_unref (l->data);
+ }
+ g_list_free (contacts);
} else {
- members = empathy_tp_group_get_members (group);
+ empathy_debug (DEBUG_DOMAIN,
+ "Type of contact list channel unknown "
+ "or aleady have that list: %s",
+ empathy_tp_group_get_name (group));
+ g_object_unref (group);
+ return;
}
+ empathy_debug (DEBUG_DOMAIN,
+ "New contact list channel of type: %d",
+ list_type);
+
+ g_signal_connect (group, "member-added",
+ G_CALLBACK (tp_contact_list_added_cb),
+ list);
+ g_signal_connect (group, "member-removed",
+ G_CALLBACK (tp_contact_list_removed_cb),
+ list);
- tp_contact_list_added_cb (group, members, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
- NULL, list);
- g_array_free (members, TRUE);
+ contacts = empathy_tp_group_get_members (group);
+ for (l = contacts; l; l = l->next) {
+ tp_contact_list_added_cb (group,
+ l->data,
+ NULL, 0, NULL,
+ list);
+ g_object_unref (l->data);
+ }
+ g_list_free (contacts);
}
else if (handle_type == TP_HANDLE_TYPE_GROUP) {
- const gchar *object_path;
+ const gchar *group_name;
+ GList *contacts, *l;
- object_path = dbus_g_proxy_get_path (DBUS_G_PROXY (new_chan));
- if (g_hash_table_lookup (priv->groups, object_path)) {
- g_object_unref (new_chan);
+ /* Check if already exists */
+ group_name = empathy_tp_group_get_name (group);
+ if (tp_contact_list_find_group (list, group_name)) {
+ g_object_unref (group);
return;
}
- group = empathy_tp_group_new (priv->account, new_chan);
-
empathy_debug (DEBUG_DOMAIN, "New server-side group channel: %s",
- empathy_tp_group_get_name (group));
+ group_name);
- dbus_g_proxy_connect_signal (DBUS_G_PROXY (new_chan), "Closed",
- G_CALLBACK
- (tp_contact_list_group_channel_closed_cb),
- list, NULL);
+ priv->groups = g_list_prepend (priv->groups, group);
- g_hash_table_insert (priv->groups, g_strdup (object_path), group);
- g_signal_connect (group, "members-added",
- G_CALLBACK (tp_contact_list_group_members_added_cb),
+ g_signal_connect (group, "member-added",
+ G_CALLBACK (tp_contact_list_group_member_added_cb),
list);
- g_signal_connect (group, "members-removed",
- G_CALLBACK (tp_contact_list_group_members_removed_cb),
+ g_signal_connect (group, "member-removed",
+ G_CALLBACK (tp_contact_list_group_member_removed_cb),
+ list);
+ g_signal_connect (group, "destroy",
+ G_CALLBACK (tp_contact_list_group_destroy_cb),
list);
- members = empathy_tp_group_get_members (group);
- tp_contact_list_group_members_added_cb (group, members, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
- NULL, list);
- g_array_free (members, TRUE);
+ contacts = empathy_tp_group_get_members (group);
+ for (l = contacts; l; l = l->next) {
+ tp_contact_list_group_member_added_cb (group, l->data,
+ NULL, 0, NULL,
+ list);
+ g_object_unref (l->data);
+ }
+ g_list_free (contacts);
+ } else {
+ empathy_debug (DEBUG_DOMAIN,
+ "Unknown handle type (%d) for contact list channel",
+ handle_type);
+ g_object_unref (group);
}
-
- g_object_unref (new_chan);
}
-static TpContactListType
-tp_contact_list_get_type (EmpathyTpContactList *list,
- EmpathyTpGroup *group)
+static void
+tp_contact_list_remove_all (EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- TpContactListType list_type;
- const gchar *name;
-
- priv = GET_PRIV (list);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ GList *l;
- name = empathy_tp_group_get_name (group);
- if (strcmp (name, "subscribe") == 0) {
- list_type = TP_CONTACT_LIST_TYPE_SUBSCRIBE;
- } else if (strcmp (name, "publish") == 0) {
- list_type = TP_CONTACT_LIST_TYPE_PUBLISH;
- } else {
- list_type = TP_CONTACT_LIST_TYPE_UNKNOWN;
+ for (l = priv->members; l; l = l->next) {
+ g_signal_emit_by_name (list, "members-changed", l->data,
+ NULL, 0, NULL,
+ FALSE);
+ g_object_unref (l->data);
+ }
+ for (l = priv->pendings; l; l = l->next) {
+ g_signal_emit_by_name (list, "pendings-changed", l->data,
+ NULL, 0, NULL,
+ FALSE);
+ g_object_unref (l->data);
}
- return list_type;
+ g_list_free (priv->members);
+ g_list_free (priv->pendings);
+ priv->members = NULL;
+ priv->pendings = NULL;
}
static void
-tp_contact_list_added_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_destroy_cb (TpConn *tp_conn,
+ EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- GList *added_list, *l;
- TpContactListType list_type;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
- priv = GET_PRIV (list);
+ empathy_debug (DEBUG_DOMAIN, "Account disconnected or CM crashed");
- list_type = tp_contact_list_get_type (list, group);
-
- added_list = empathy_tp_contact_list_get_from_handles (list, handles);
- for (l = added_list; l; l = l->next) {
- EmpathyContact *contact;
- EmpathySubscription subscription;
-
- contact = EMPATHY_CONTACT (l->data);
-
- empathy_debug (DEBUG_DOMAIN, "Contact '%s' added to list type %d",
- empathy_contact_get_name (contact),
- list_type);
+ /* DBus proxie should NOT be used anymore */
+ g_object_unref (priv->tp_conn);
+ priv->tp_conn = NULL;
- subscription = empathy_contact_get_subscription (contact);
- if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- subscription |= EMPATHY_SUBSCRIPTION_FROM;
- }
- else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
- subscription |= EMPATHY_SUBSCRIPTION_TO;
- tp_contact_list_remove_local_pending (list, contact);
- }
+ tp_contact_list_remove_all (list);
- tp_contact_list_block_contact (list, contact);
- empathy_contact_set_subscription (contact, subscription);
- tp_contact_list_unblock_contact (list, contact);
+ /* Tell the world to not use us anymore */
+ g_signal_emit (list, signals[DESTROY], 0);
+}
- if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- if (!g_list_find (priv->members, contact)) {
- priv->members = g_list_prepend (priv->members,
- g_object_ref (contact));
- g_signal_emit_by_name (list, "contact-added", contact);
- }
- }
+static void
+tp_contact_list_disconnect (EmpathyTpContactList *list)
+{
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
- g_object_unref (contact);
+ if (priv->tp_conn) {
+ g_signal_handlers_disconnect_by_func (priv->tp_conn,
+ tp_contact_list_destroy_cb,
+ list);
+ dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
+ G_CALLBACK (tp_contact_list_newchannel_cb),
+ list);
}
-
- g_list_free (added_list);
}
static void
-tp_contact_list_removed_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_status_changed_cb (MissionControl *mc,
+ TelepathyConnectionStatus status,
+ McPresence presence,
+ TelepathyConnectionStatusReason reason,
+ const gchar *unique_name,
+ EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- GList *removed_list, *l;
- TpContactListType list_type;
-
- priv = GET_PRIV (list);
-
- list_type = tp_contact_list_get_type (list, group);
-
- removed_list = empathy_tp_contact_list_get_from_handles (list, handles);
- for (l = removed_list; l; l = l->next) {
- EmpathyContact *contact;
- EmpathySubscription subscription;
-
- contact = EMPATHY_CONTACT (l->data);
-
- empathy_debug (DEBUG_DOMAIN, "Contact '%s' removed from list type %d",
- empathy_contact_get_name (contact),
- list_type);
-
- subscription = empathy_contact_get_subscription (contact);
- if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- subscription &= !EMPATHY_SUBSCRIPTION_FROM;
- }
- else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
- subscription &= !EMPATHY_SUBSCRIPTION_TO;
- tp_contact_list_remove_local_pending (list, contact);
- }
-
- tp_contact_list_block_contact (list, contact);
- empathy_contact_set_subscription (contact, subscription);
- tp_contact_list_unblock_contact (list, contact);
-
- if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- GList *l;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ McAccount *account;
- if ((l = g_list_find (priv->members, contact))) {
- g_signal_emit_by_name (list, "contact-removed", contact);
- priv->members = g_list_delete_link (priv->members, l);
- g_object_unref (contact);
- }
- }
- g_object_unref (contact);
+ account = mc_account_lookup (unique_name);
+ if (status != TP_CONN_STATUS_CONNECTED &&
+ empathy_account_equal (account, priv->account)) {
+ /* We are disconnected */
+ tp_contact_list_disconnect (list);
+ tp_contact_list_destroy_cb (priv->tp_conn, list);
}
- g_list_free (removed_list);
+ g_object_unref (account);
}
static void
-tp_contact_list_pending_cb (EmpathyTpGroup *group,
- GArray *handles,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_group_list_free (GList **groups)
+{
+ g_list_foreach (*groups, (GFunc) g_free, NULL);
+ g_list_free (*groups);
+ g_slice_free (GList*, groups);
+}
+
+static void
+tp_contact_list_finalize (GObject *object)
{
EmpathyTpContactListPriv *priv;
- GList *pending_list, *l;
- TpContactListType list_type;
+ EmpathyTpContactList *list;
+ list = EMPATHY_TP_CONTACT_LIST (object);
priv = GET_PRIV (list);
- list_type = tp_contact_list_get_type (list, group);
-
- pending_list = empathy_tp_contact_list_get_from_handles (list, handles);
- for (l = pending_list; l; l = l->next) {
- EmpathyContact *contact;
-
- contact = EMPATHY_CONTACT (l->data);
-
- empathy_debug (DEBUG_DOMAIN, "Contact '%s' pending in list type %d",
- empathy_contact_get_name (contact),
- list_type);
-
- if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
- if (!g_list_find (priv->members, contact)) {
- EmpathyContactListInfo *info;
-
- info = empathy_contact_list_info_new (contact, message);
- priv->local_pending = g_list_prepend (priv->local_pending,
- info);
+ empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
- g_signal_emit_by_name (list, "local-pending",
- contact, message);
- } else {
- guint handle;
+ tp_contact_list_disconnect (list);
+ tp_contact_list_remove_all (list);
- /* That contact wants our presence and he is
- * in our roster. Accept to publish our presence
- * without asking the user. */
- handle = empathy_contact_get_handle (contact);
- empathy_tp_group_add_member (priv->publish,
- handle, "");
- }
- }
- else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
- if (!g_list_find (priv->members, contact)) {
- priv->members = g_list_prepend (priv->members,
- g_object_ref (contact));
- g_signal_emit_by_name (list, "contact-added", contact);
- }
- }
+ if (priv->mc) {
+ dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
+ "AccountStatusChanged",
+ G_CALLBACK (tp_contact_list_status_changed_cb),
+ list);
+ g_object_unref (priv->mc);
+ }
- g_object_unref (contact);
+ if (priv->subscribe) {
+ g_object_unref (priv->subscribe);
+ }
+ if (priv->publish) {
+ g_object_unref (priv->publish);
}
+ if (priv->account) {
+ g_object_unref (priv->account);
+ }
+ if (priv->tp_conn) {
+ g_object_unref (priv->tp_conn);
+ }
+
+ g_hash_table_destroy (priv->contacts_groups);
+ g_list_foreach (priv->groups, (GFunc) g_object_unref, NULL);
+ g_list_free (priv->groups);
- g_list_free (pending_list);
+ G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
}
static void
-tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
- EmpathyContact *contact)
+empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass)
{
- EmpathyTpContactListPriv *priv;
- GList *l;
-
- priv = GET_PRIV (list);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- for (l = priv->local_pending; l; l = l->next) {
- EmpathyContactListInfo *info;
+ object_class->finalize = tp_contact_list_finalize;
- info = l->data;
- if (empathy_contact_equal (contact, info->contact)) {
- empathy_debug (DEBUG_DOMAIN, "Contact no more local-pending: %s",
- empathy_contact_get_name (contact));
+ signals[DESTROY] =
+ g_signal_new ("destroy",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
- priv->local_pending = g_list_delete_link (priv->local_pending, l);
- empathy_contact_list_info_free (info);
- break;
- }
- }
+ g_type_class_add_private (object_class, sizeof (EmpathyTpContactListPriv));
}
static void
-tp_contact_list_groups_updated_cb (EmpathyContact *contact,
- GParamSpec *param,
- EmpathyTpContactList *list)
+empathy_tp_contact_list_init (EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- TpContactListData data;
- GList *groups, *l;
-
- priv = GET_PRIV (list);
-
- /* Make sure all groups are created */
- groups = empathy_contact_get_groups (contact);
- for (l = groups; l; l = l->next) {
- tp_contact_list_get_group (list, l->data);
- }
-
- data.handle = empathy_contact_get_handle (contact);
- data.new_groups = groups;
-
- g_hash_table_foreach (priv->groups,
- (GHFunc) tp_contact_list_update_groups_foreach,
- &data);
}
static void
-tp_contact_list_name_updated_cb (EmpathyContact *contact,
- GParamSpec *param,
- EmpathyTpContactList *list)
+tp_contact_list_setup (EmpathyTpContactList *list)
{
- EmpathyTpContactListPriv *priv;
- GHashTable *new_alias;
- const gchar *new_name;
- guint handle;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ GPtrArray *channels;
+ guint i;
GError *error = NULL;
- priv = GET_PRIV (list);
-
- if (!priv->aliasing_iface) {
- return;
- }
-
- handle = empathy_contact_get_handle (contact);
- new_name = empathy_contact_get_name (contact);
-
- empathy_debug (DEBUG_DOMAIN, "renaming handle %d to %s",
- handle, new_name);
-
- new_alias = g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- NULL,
- g_free);
-
- g_hash_table_insert (new_alias,
- GUINT_TO_POINTER (handle),
- g_strdup (new_name));
+ g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
- if (!tp_conn_iface_aliasing_set_aliases (priv->aliasing_iface,
- new_alias,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Couldn't rename contact: %s",
+ /* Get existing channels */
+ if (!tp_conn_list_channels (DBUS_G_PROXY (priv->tp_conn),
+ &channels,
+ &error)) {
+ empathy_debug (DEBUG_DOMAIN,
+ "Failed to get list of open channels: %s",
error ? error->message : "No error given");
g_clear_error (&error);
+ return;
}
- g_hash_table_destroy (new_alias);
-}
-
-static void
-tp_contact_list_update_groups_foreach (gchar *object_path,
- EmpathyTpGroup *group,
- TpContactListData *data)
-{
- gboolean is_member;
- gboolean found = FALSE;
- const gchar *group_name;
- GList *l;
-
- is_member = empathy_tp_group_is_member (group, data->handle);
- group_name = empathy_tp_group_get_name (group);
+ for (i = 0; i < channels->len; i++) {
+ GValueArray *chan_struct;
+ const gchar *object_path;
+ const gchar *chan_iface;
+ TelepathyHandleType handle_type;
+ guint handle;
- for (l = data->new_groups; l; l = l->next) {
- if (strcmp (group_name, l->data) == 0) {
- found = TRUE;
- break;
- }
- }
+ chan_struct = g_ptr_array_index (channels, i);
+ object_path = g_value_get_boxed (g_value_array_get_nth (chan_struct, 0));
+ chan_iface = g_value_get_string (g_value_array_get_nth (chan_struct, 1));
+ handle_type = g_value_get_uint (g_value_array_get_nth (chan_struct, 2));
+ handle = g_value_get_uint (g_value_array_get_nth (chan_struct, 3));
- if (is_member && !found) {
- /* We are no longer member of this group */
- empathy_debug (DEBUG_DOMAIN, "Contact %d removed from group '%s'",
- data->handle, group_name);
- empathy_tp_group_remove_member (group, data->handle, "");
- }
+ tp_contact_list_newchannel_cb (DBUS_G_PROXY (priv->tp_conn),
+ object_path, chan_iface,
+ handle_type, handle,
+ FALSE,
+ list);
- if (!is_member && found) {
- /* We are now member of this group */
- empathy_debug (DEBUG_DOMAIN, "Contact %d added to group '%s'",
- data->handle, group_name);
- empathy_tp_group_add_member (group, data->handle, "");
+ g_value_array_free (chan_struct);
}
+ g_ptr_array_free (channels, TRUE);
}
-static EmpathyTpGroup *
-tp_contact_list_get_group (EmpathyTpContactList *list,
- const gchar *name)
+EmpathyTpContactList *
+empathy_tp_contact_list_new (McAccount *account)
{
EmpathyTpContactListPriv *priv;
- EmpathyTpGroup *group;
- TpChan *group_channel;
- GArray *handles;
- guint group_handle;
- char *group_object_path;
- const char *names[2] = {name, NULL};
- GError *error = NULL;
-
- priv = GET_PRIV (list);
+ EmpathyTpContactList *list;
+ MissionControl *mc;
+ TpConn *tp_conn = NULL;
+ McProfile *profile;
+ const gchar *protocol_name;
- group = g_hash_table_find (priv->groups,
- (GHRFunc) tp_contact_list_find_group,
- (gchar*) name);
- if (group) {
- return group;
- }
+ g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
- empathy_debug (DEBUG_DOMAIN, "creating new group: %s", name);
+ mc = empathy_mission_control_new ();
- if (!tp_conn_request_handles (DBUS_G_PROXY (priv->tp_conn),
- TP_HANDLE_TYPE_GROUP,
- names,
- &handles,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Couldn't request the creation of a new handle for group: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- return NULL;
+ /* status==0 means CONNECTED */
+ if (mission_control_get_connection_status (mc, account, NULL) == 0) {
+ tp_conn = mission_control_get_connection (mc, account, NULL);
}
- group_handle = g_array_index (handles, guint, 0);
- g_array_free (handles, TRUE);
-
- if (!tp_conn_request_channel (DBUS_G_PROXY (priv->tp_conn),
- TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
- TP_HANDLE_TYPE_GROUP,
- group_handle,
- FALSE,
- &group_object_path,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Couldn't request the creation of a new group channel: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
+ if (!tp_conn) {
+ /* The account is not connected, nothing to do. */
+ g_object_unref (mc);
return NULL;
}
- group_channel = tp_chan_new (tp_get_bus (),
- dbus_g_proxy_get_bus_name (DBUS_G_PROXY (priv->tp_conn)),
- group_object_path,
- TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
- TP_HANDLE_TYPE_GROUP,
- group_handle);
-
- dbus_g_proxy_connect_signal (DBUS_G_PROXY (group_channel),
- "Closed",
- G_CALLBACK
- (tp_contact_list_group_channel_closed_cb),
- list,
- NULL);
-
- group = empathy_tp_group_new (priv->account, group_channel);
- g_hash_table_insert (priv->groups, group_object_path, group);
- g_signal_connect (group, "members-added",
- G_CALLBACK (tp_contact_list_group_members_added_cb),
- list);
- g_signal_connect (group, "members-removed",
- G_CALLBACK (tp_contact_list_group_members_removed_cb),
- list);
+ list = g_object_new (EMPATHY_TYPE_TP_CONTACT_LIST, NULL);
+ priv = GET_PRIV (list);
- return group;
-}
+ priv->tp_conn = tp_conn;
+ priv->account = g_object_ref (account);
+ priv->mc = mc;
+ priv->contacts_groups = g_hash_table_new_full (empathy_contact_hash,
+ empathy_contact_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) tp_contact_list_group_list_free);
-static gboolean
-tp_contact_list_find_group (gchar *key,
- EmpathyTpGroup *group,
- gchar *group_name)
-{
- if (strcmp (group_name, empathy_tp_group_get_name (group)) == 0) {
- return TRUE;
+ /* Check for protocols that does not support contact groups. We can
+ * put all contacts into a special group in that case.
+ * FIXME: Default group should be an information in the profile */
+ profile = mc_account_get_profile (account);
+ protocol_name = mc_profile_get_protocol_name (profile);
+ if (strcmp (protocol_name, "local-xmpp") == 0) {
+ priv->protocol_group = _("People nearby");
}
+ g_object_unref (profile);
- return FALSE;
-}
+ /* Connect signals */
+ dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
+ "AccountStatusChanged",
+ G_CALLBACK (tp_contact_list_status_changed_cb),
+ list, NULL);
+ dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
+ G_CALLBACK (tp_contact_list_newchannel_cb),
+ list, NULL);
+ g_signal_connect (priv->tp_conn, "destroy",
+ G_CALLBACK (tp_contact_list_destroy_cb),
+ list);
-static void
-tp_contact_list_get_groups_foreach (gchar *key,
- EmpathyTpGroup *group,
- GList **groups)
-{
- const gchar *name;
+ tp_contact_list_setup (list);
- name = empathy_tp_group_get_name (group);
- *groups = g_list_append (*groups, g_strdup (name));
+ return list;
}
-static void
-tp_contact_list_group_channel_closed_cb (TpChan *channel,
- EmpathyTpContactList *list)
+McAccount *
+empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
{
EmpathyTpContactListPriv *priv;
+ g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
+
priv = GET_PRIV (list);
- g_hash_table_remove (priv->groups,
- dbus_g_proxy_get_path (DBUS_G_PROXY (channel)));
+ return priv->account;
}
static void
-tp_contact_list_group_members_added_cb (EmpathyTpGroup *group,
- GArray *members,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_add (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message)
{
- EmpathyTpContactListPriv *priv;
- GList *added_list, *l;
- const gchar *group_name;
-
- priv = GET_PRIV (list);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
- group_name = empathy_tp_group_get_name (group);
- added_list = empathy_tp_contact_list_get_from_handles (list, members);
-
- for (l = added_list; l; l = l->next) {
- EmpathyContact *contact;
-
- contact = EMPATHY_CONTACT (l->data);
-
- tp_contact_list_block_contact (list, contact);
- empathy_contact_add_group (contact, group_name);
- tp_contact_list_unblock_contact (list, contact);
+ g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
- g_object_unref (contact);
+ empathy_tp_group_add_member (priv->subscribe, contact, message);
+ if (g_list_find (priv->pendings, contact)) {
+ empathy_tp_group_add_member (priv->publish, contact, message);
}
-
- g_list_free (added_list);
}
static void
-tp_contact_list_group_members_removed_cb (EmpathyTpGroup *group,
- GArray *members,
- guint actor_handle,
- guint reason,
- const gchar *message,
- EmpathyTpContactList *list)
+tp_contact_list_remove (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *message)
{
- EmpathyTpContactListPriv *priv;
- GList *removed_list, *l;
- const gchar *group_name;
-
- priv = GET_PRIV (list);
-
- group_name = empathy_tp_group_get_name (group);
- removed_list = empathy_tp_contact_list_get_from_handles (list, members);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
- for (l = removed_list; l; l = l->next) {
- EmpathyContact *contact;
-
- contact = l->data;
-
- tp_contact_list_block_contact (list, contact);
- empathy_contact_remove_group (contact, group_name);
- tp_contact_list_unblock_contact (list, contact);
-
- g_object_unref (contact);
- }
+ g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
- g_list_free (removed_list);
+ empathy_tp_group_remove_member (priv->subscribe, contact, message);
+ empathy_tp_group_remove_member (priv->publish, contact, message);
}
-static void
-tp_contact_list_get_info (EmpathyTpContactList *list,
- GArray *handles)
+static GList *
+tp_contact_list_get_members (EmpathyContactList *list)
{
- EmpathyTpContactListPriv *priv;
- GError *error = NULL;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
- priv = GET_PRIV (list);
-
- if (priv->presence_iface) {
- /* FIXME: We should use GetPresence instead */
- if (!tp_conn_iface_presence_request_presence (priv->presence_iface,
- handles, &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Could not request presences: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- }
- }
-
- if (priv->aliasing_iface) {
- TpContactListAliasesRequestData *data;
-
- data = g_slice_new (TpContactListAliasesRequestData);
- data->list = list;
- data->handles = g_memdup (handles->data, handles->len * sizeof (guint));
-
- tp_conn_iface_aliasing_request_aliases_async (priv->aliasing_iface,
- handles,
- (tp_conn_iface_aliasing_request_aliases_reply)
- tp_contact_list_request_aliases_cb,
- data);
- }
-
- if (priv->avatars_iface) {
- guint i;
-
- for (i = 0; i < handles->len; i++) {
- guint handle;
+ g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
- handle = g_array_index (handles, gint, i);
- tp_contact_list_request_avatar (list, handle);
- }
- }
+ g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
+ return g_list_copy (priv->members);
}
-static void
-tp_contact_list_request_avatar (EmpathyTpContactList *list,
- guint handle)
+static GList *
+tp_contact_list_get_pendings (EmpathyContactList *list)
{
- EmpathyTpContactListPriv *priv;
- TpContactListAvatarRequestData *data;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
- priv = GET_PRIV (list);
-
- /* We queue avatar requests to not send too many dbus async
- * calls at once. If we don't we reach the dbus's limit of
- * pending calls */
- data = g_slice_new (TpContactListAvatarRequestData);
- data->list = g_object_ref (list);
- data->handle = handle;
- avatar_requests_queue = g_list_append (avatar_requests_queue, data);
- tp_contact_list_start_avatar_requests ();
-}
+ g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
-static void
-tp_contact_list_start_avatar_requests (void)
-{
- empathy_debug (DEBUG_DOMAIN, "Start avatar requests, pending calls: %d",
- n_avatar_requests);
-
- while (n_avatar_requests < MAX_AVATAR_REQUESTS && avatar_requests_queue) {
- EmpathyTpContactListPriv *priv;
- TpContactListAvatarRequestData *data;
-
- data = avatar_requests_queue->data;
- priv = GET_PRIV (data->list);
-
- n_avatar_requests++;
- avatar_requests_queue = g_list_delete_link (avatar_requests_queue,
- avatar_requests_queue);
-
- empathy_debug (DEBUG_DOMAIN, "Calling RequestAvatar async");
- tp_conn_iface_avatars_request_avatar_async (priv->avatars_iface,
- data->handle,
- (tp_conn_iface_avatars_request_avatar_reply)
- tp_contact_list_request_avatar_cb,
- data);
- }
+ g_list_foreach (priv->pendings, (GFunc) g_object_ref, NULL);
+ return g_list_copy (priv->pendings);
}
-static void
-tp_contact_list_avatar_update_cb (DBusGProxy *proxy,
- guint handle,
- gchar *new_token,
- EmpathyTpContactList *list)
+static GList *
+tp_contact_list_get_all_groups (EmpathyContactList *list)
{
- EmpathyTpContactListPriv *priv;
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ GList *groups = NULL, *l;
- priv = GET_PRIV (list);
+ g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
- if (!g_hash_table_lookup (priv->contacts, GUINT_TO_POINTER (handle))) {
- /* We don't know this contact, skip */
- return;
- }
+ for (l = priv->groups; l; l = l->next) {
+ const gchar *name;
- empathy_debug (DEBUG_DOMAIN, "Changing avatar for %d to %s",
- handle, new_token);
+ name = empathy_tp_group_get_name (l->data);
+ groups = g_list_prepend (groups, g_strdup (name));
+ }
- tp_contact_list_request_avatar (list, handle);
+ return groups;
}
-static void
-tp_contact_list_request_avatar_cb (DBusGProxy *proxy,
- GArray *avatar_data,
- gchar *mime_type,
- GError *error,
- TpContactListAvatarRequestData *data)
+static GList *
+tp_contact_list_get_groups (EmpathyContactList *list,
+ EmpathyContact *contact)
{
- EmpathyContact *contact;
-
- contact = empathy_tp_contact_list_get_from_handle (data->list, data->handle);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ GList **groups;
+ GList *ret = NULL, *l;
- if (error) {
- empathy_debug (DEBUG_DOMAIN, "Error requesting avatar for %s: %s",
- empathy_contact_get_name (contact),
- error ? error->message : "No error given");
- } else {
- EmpathyAvatar *avatar;
+ g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
- empathy_debug (DEBUG_DOMAIN, "Avatar received for %s (%d)",
- empathy_contact_get_id (contact),
- data->handle);
-
- avatar = empathy_avatar_new (avatar_data->data,
- avatar_data->len,
- mime_type);
- tp_contact_list_block_contact (data->list, contact);
- empathy_contact_set_avatar (contact, avatar);
- tp_contact_list_unblock_contact (data->list, contact);
- empathy_avatar_unref (avatar);
+ groups = g_hash_table_lookup (priv->contacts_groups, contact);
+ if (!groups) {
+ return NULL;
}
- n_avatar_requests--;
- tp_contact_list_start_avatar_requests ();
+ for (l = *groups; l; l = l->next) {
+ ret = g_list_prepend (ret, g_strdup (l->data));
+ }
- g_object_unref (contact);
- g_object_unref (data->list);
- g_slice_free (TpContactListAvatarRequestData, data);
+ return ret;
}
-static void
-tp_contact_list_aliases_update_cb (DBusGProxy *proxy,
- GPtrArray *renamed_handlers,
- EmpathyTpContactList *list)
+static EmpathyTpGroup *
+tp_contact_list_get_group (EmpathyTpContactList *list,
+ const gchar *group)
{
- EmpathyTpContactListPriv *priv;
- guint i;
-
- priv = GET_PRIV (list);
+ EmpathyTpContactListPriv *priv = GET_PRIV (list);
+ EmpathyTpGroup *tp_group;
+ gchar *object_path;
+ guint handle;
+ GArray *handles;
+ const char *names[2] = {group, NULL};
+ GError *error = NULL;
- for (i = 0; renamed_handlers->len > i; i++) {
- guint handle;
- const gchar *alias;
- GValueArray *renamed_struct;
- EmpathyContact *contact;
+ tp_group = tp_contact_list_find_group (list, group);
+ if (tp_group) {
+ return tp_group;
+ }
- renamed_struct = g_ptr_array_index (renamed_handlers, i);
- handle = g_value_get_uint(g_value_array_get_nth (renamed_struct, 0));
- alias = g_value_get_string(g_value_array_get_nth (renamed_struct, 1));
+ empathy_debug (DEBUG_DOMAIN, "creating new group: %s", group);
- if (!g_hash_table_lookup (priv->contacts, GUINT_TO_POINTER (handle))) {
- /* We don't know this contact, skip */
- continue;
- }
+ if (!tp_conn_request_handles (DBUS_G_PROXY (priv->tp_conn),
+ TP_HANDLE_TYPE_GROUP,
+ names,
+ &handles,
+ &error)) {
+ empathy_debug (DEBUG_DOMAIN,
+ "Failed to RequestHandles: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ return NULL;
+ }
+ handle = g_array_index (handles, guint, 0);
+ g_array_free (handles, TRUE);
- if (G_STR_EMPTY (alias)) {
- alias = NULL;
- }
+ if (!tp_conn_request_channel (DBUS_G_PROXY (priv->tp_conn),
+ TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+ TP_HANDLE_TYPE_GROUP,
+ handle,
+ FALSE,
+ &object_path,
+ &error)) {
+ empathy_debug (DEBUG_DOMAIN,
+ "Failed to RequestChannel: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ return NULL;
+ }
- contact = empathy_tp_contact_list_get_from_handle (list, handle);
- tp_contact_list_block_contact (list, contact);
- empathy_contact_set_name (contact, alias);
- tp_contact_list_unblock_contact (list, contact);
- g_object_unref (contact);
+ tp_contact_list_newchannel_cb (DBUS_G_PROXY (priv->tp_conn),
+ object_path,
+ TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
+ TP_HANDLE_TYPE_GROUP,
+ handle, FALSE,
+ list);
+ g_free (object_path);
- empathy_debug (DEBUG_DOMAIN, "contact %d renamed to %s (update cb)",
- handle, alias);
- }
+ return tp_contact_list_find_group (list, group);
}
static void
-tp_contact_list_request_aliases_cb (DBusGProxy *proxy,
- gchar **contact_names,
- GError *error,
- TpContactListAliasesRequestData *data)
+tp_contact_list_add_to_group (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group)
{
- guint i = 0;
- gchar **name;
+ EmpathyTpGroup *tp_group;
- if (error) {
- empathy_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
- error->message);
- }
-
- for (name = contact_names; *name && !error; name++) {
- EmpathyContact *contact;
-
- contact = empathy_tp_contact_list_get_from_handle (data->list,
- data->handles[i]);
- tp_contact_list_block_contact (data->list, contact);
- empathy_contact_set_name (contact, *name);
- tp_contact_list_unblock_contact (data->list, contact);
- g_object_unref (contact);
-
- empathy_debug (DEBUG_DOMAIN, "contact %d renamed to %s (request cb)",
- data->handles[i], *name);
+ g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
- i++;
- }
+ tp_group = tp_contact_list_get_group (EMPATHY_TP_CONTACT_LIST (list),
+ group);
- g_free (data->handles);
- g_slice_free (TpContactListAliasesRequestData, data);
+ empathy_tp_group_add_member (tp_group, contact, "");
}
static void
-tp_contact_list_presence_update_cb (DBusGProxy *proxy,
- GHashTable *handle_table,
- EmpathyTpContactList *list)
+tp_contact_list_remove_from_group (EmpathyContactList *list,
+ EmpathyContact *contact,
+ const gchar *group)
{
- g_hash_table_foreach (handle_table,
- (GHFunc) tp_contact_list_parse_presence_foreach,
- list);
-}
+ EmpathyTpGroup *tp_group;
-static void
-tp_contact_list_parse_presence_foreach (guint handle,
- GValueArray *presence_struct,
- EmpathyTpContactList *list)
-{
- EmpathyTpContactListPriv *priv;
- GHashTable *presences_table;
- EmpathyContact *contact;
- EmpathyPresence *presence = NULL;
+ g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
- priv = GET_PRIV (list);
+ tp_group = tp_contact_list_find_group (EMPATHY_TP_CONTACT_LIST (list),
+ group);
- if (!g_hash_table_lookup (priv->contacts, GUINT_TO_POINTER (handle))) {
- /* We don't know this contact, skip */
- return;
+ if (tp_group) {
+ empathy_tp_group_remove_member (tp_group, contact, "");
}
-
- contact = empathy_tp_contact_list_get_from_handle (list, handle);
- presences_table = g_value_get_boxed (g_value_array_get_nth (presence_struct, 1));
-
- g_hash_table_foreach (presences_table,
- (GHFunc) tp_contact_list_presences_table_foreach,
- &presence);
-
- empathy_debug (DEBUG_DOMAIN, "Presence changed for %s (%d) to %s (%d)",
- empathy_contact_get_name (contact),
- handle,
- presence ? empathy_presence_get_status (presence) : "unset",
- presence ? empathy_presence_get_state (presence) : MC_PRESENCE_UNSET);
-
- tp_contact_list_block_contact (list, contact);
- empathy_contact_set_presence (contact, presence);
- tp_contact_list_unblock_contact (list, contact);
-
- g_object_unref (contact);
}
static void
-tp_contact_list_presences_table_foreach (const gchar *state_str,
- GHashTable *presences_table,
- EmpathyPresence **presence)
+tp_contact_list_rename_group (EmpathyContactList *list,
+ const gchar *old_group,
+ const gchar *new_group)
{
- McPresence state;
- const GValue *message;
+ EmpathyTpGroup *tp_group;
+ GList *members;
- state = empathy_presence_state_from_str (state_str);
- if ((state == MC_PRESENCE_UNSET) || (state == MC_PRESENCE_OFFLINE)) {
+ g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
+
+ tp_group = tp_contact_list_find_group (EMPATHY_TP_CONTACT_LIST (list),
+ old_group);
+ if (!tp_group) {
return;
}
- if (*presence) {
- g_object_unref (*presence);
- *presence = NULL;
- }
+ empathy_debug (DEBUG_DOMAIN, "rename group %s to %s", old_group, new_group);
- *presence = empathy_presence_new ();
- empathy_presence_set_state (*presence, state);
+ /* Remove all members from the old group */
+ members = empathy_tp_group_get_members (tp_group);
+ empathy_tp_group_remove_members (tp_group, members, "");
+ empathy_tp_group_close (tp_group);
- message = g_hash_table_lookup (presences_table, "message");
- if (message != NULL) {
- empathy_presence_set_status (*presence,
- g_value_get_string (message));
- }
+ /* Add all members to the new group */
+ tp_group = tp_contact_list_get_group (EMPATHY_TP_CONTACT_LIST (list),
+ new_group);
+ empathy_tp_group_add_members (tp_group, members, "");
+
+ g_list_foreach (members, (GFunc) g_object_unref, NULL);
+ g_list_free (members);
}
static void
-tp_contact_list_status_changed_cb (MissionControl *mc,
- TelepathyConnectionStatus status,
- McPresence presence,
- TelepathyConnectionStatusReason reason,
- const gchar *unique_name,
- EmpathyTpContactList *list)
+tp_contact_list_iface_init (EmpathyContactListIface *iface)
{
- EmpathyTpContactListPriv *priv;
- McAccount *account;
-
- priv = GET_PRIV (list);
-
- account = mc_account_lookup (unique_name);
- if (status != TP_CONN_STATUS_DISCONNECTED ||
- !empathy_account_equal (account, priv->account) ||
- !priv->tp_conn) {
- g_object_unref (account);
- return;
- }
-
- /* We are disconnected, do just like if the connection was destroyed */
- g_signal_handlers_disconnect_by_func (priv->tp_conn,
- tp_contact_list_destroy_cb,
- list);
- tp_contact_list_destroy_cb (DBUS_G_PROXY (priv->tp_conn), list);
-
- g_object_unref (account);
+ iface->add = tp_contact_list_add;
+ iface->remove = tp_contact_list_remove;
+ iface->get_members = tp_contact_list_get_members;
+ iface->get_pendings = tp_contact_list_get_pendings;
+ iface->get_all_groups = tp_contact_list_get_all_groups;
+ iface->get_groups = tp_contact_list_get_groups;
+ iface->add_to_group = tp_contact_list_add_to_group;
+ iface->remove_from_group = tp_contact_list_remove_from_group;
+ iface->rename_group = tp_contact_list_rename_group;
}
diff --git a/libempathy/empathy-tp-contact-list.h b/libempathy/empathy-tp-contact-list.h
index f0eccb375..6ac4662fa 100644
--- a/libempathy/empathy-tp-contact-list.h
+++ b/libempathy/empathy-tp-contact-list.h
@@ -50,20 +50,9 @@ struct _EmpathyTpContactListClass {
GObjectClass parent_class;
};
-GType empathy_tp_contact_list_get_type (void) G_GNUC_CONST;
-EmpathyTpContactList * empathy_tp_contact_list_new (McAccount *account);
-McAccount * empathy_tp_contact_list_get_account (EmpathyTpContactList *list);
-EmpathyContact * empathy_tp_contact_list_get_user (EmpathyTpContactList *list);
-EmpathyContact * empathy_tp_contact_list_get_from_id (EmpathyTpContactList *list,
- const gchar *id);
-EmpathyContact * empathy_tp_contact_list_get_from_handle (EmpathyTpContactList *list,
- guint handle);
-GList * empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
- GArray *handles);
-void empathy_tp_contact_list_rename_group (EmpathyTpContactList *list,
- const gchar *old_group,
- const gchar *new_group);
-GList * empathy_tp_contact_list_get_groups (EmpathyTpContactList *list);
+GType empathy_tp_contact_list_get_type (void) G_GNUC_CONST;
+EmpathyTpContactList * empathy_tp_contact_list_new (McAccount *account);
+McAccount * empathy_tp_contact_list_get_account (EmpathyTpContactList *list);
G_END_DECLS
diff --git a/libempathy/empathy-tp-group.c b/libempathy/empathy-tp-group.c
index b86a00e28..1ffab9ecd 100644
--- a/libempathy/empathy-tp-group.c
+++ b/libempathy/empathy-tp-group.c
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
+ * Copyright (C) 2007 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -16,18 +17,22 @@
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
*/
#include <config.h>
#include <dbus/dbus-glib.h>
#include <libtelepathy/tp-chan.h>
+#include <libtelepathy/tp-chan-gen.h>
#include <libtelepathy/tp-chan-iface-group-gen.h>
#include <libtelepathy/tp-constants.h>
#include <libtelepathy/tp-conn.h>
-#include "empathy-debug.h"
#include "empathy-tp-group.h"
+#include "empathy-contact-factory.h"
+#include "empathy-debug.h"
#include "empathy-utils.h"
#include "empathy-marshal.h"
@@ -37,32 +42,27 @@
#define DEBUG_DOMAIN "TpGroup"
struct _EmpathyTpGroupPriv {
- McAccount *account;
- DBusGProxy *group_iface;
- TpChan *tp_chan;
- gchar *group_name;
+ EmpathyContactFactory *factory;
+ McAccount *account;
+ DBusGProxy *group_iface;
+ TpChan *tp_chan;
+ gchar *group_name;
+ guint self_handle;
+
+ GList *members;
+ GList *local_pendings;
+ GList *remote_pendings;
};
static void empathy_tp_group_class_init (EmpathyTpGroupClass *klass);
static void empathy_tp_group_init (EmpathyTpGroup *group);
-static void tp_group_finalize (GObject *object);
-static void tp_group_destroy_cb (DBusGProxy *proxy,
- EmpathyTpGroup *group);
-static void tp_group_members_changed_cb (DBusGProxy *group_iface,
- gchar *message,
- GArray *added,
- GArray *removed,
- GArray *local_pending,
- GArray *remote_pending,
- guint actor,
- guint reason,
- EmpathyTpGroup *group);
enum {
- MEMBERS_ADDED,
- MEMBERS_REMOVED,
+ MEMBER_ADDED,
+ MEMBER_REMOVED,
LOCAL_PENDING,
REMOTE_PENDING,
+ DESTROY,
LAST_SIGNAL
};
@@ -70,6 +70,409 @@ static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (EmpathyTpGroup, empathy_tp_group, G_TYPE_OBJECT);
+static EmpathyContact *
+tp_group_get_contact (EmpathyTpGroup *group,
+ guint handle)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ EmpathyContact *contact = NULL;
+
+ if (handle != 0) {
+ contact = empathy_contact_factory_get_from_handle (priv->factory,
+ priv->account,
+ handle);
+ }
+
+ if (contact && empathy_contact_get_handle (contact) == priv->self_handle) {
+ empathy_contact_set_is_user (contact, TRUE);
+ }
+
+ return contact;
+}
+
+static GList *
+tp_group_get_contacts (EmpathyTpGroup *group,
+ GArray *handles)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GList *contacts, *l;
+
+ if (!handles) {
+ return NULL;
+ }
+
+ contacts = empathy_contact_factory_get_from_handles (priv->factory,
+ priv->account,
+ handles);
+
+ /* FIXME: Only useful if the group has a different self handle than
+ * the connection, otherwise the contact factory already set that
+ * property. That can be known using group flags. */
+ for (l = contacts; l; l = l->next) {
+ if (empathy_contact_get_handle (l->data) == priv->self_handle) {
+ empathy_contact_set_is_user (l->data, TRUE);
+ }
+ }
+
+ return contacts;
+}
+
+EmpathyPendingInfo *
+empathy_pending_info_new (EmpathyContact *member,
+ EmpathyContact *actor,
+ const gchar *message)
+{
+ EmpathyPendingInfo *info;
+
+ info = g_slice_new0 (EmpathyPendingInfo);
+
+ if (member) {
+ info->member = g_object_ref (member);
+ }
+ if (actor) {
+ info->actor = g_object_ref (actor);
+ }
+ if (message) {
+ info->message = g_strdup (message);
+ }
+
+ return info;
+}
+
+void
+empathy_pending_info_free (EmpathyPendingInfo *info)
+{
+ if (!info) {
+ return;
+ }
+
+ if (info->member) {
+ g_object_unref (info->member);
+ }
+ if (info->actor) {
+ g_object_unref (info->actor);
+ }
+ g_free (info->message);
+
+ g_slice_free (EmpathyPendingInfo, info);
+}
+
+static gint
+tp_group_local_pending_find (gconstpointer a,
+ gconstpointer b)
+{
+ const EmpathyPendingInfo *info = a;
+
+ return (info->member != b);
+}
+
+static void
+tp_group_remove_from_pendings (EmpathyTpGroup *group,
+ EmpathyContact *contact)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GList *l;
+
+ /* local pending */
+ l = g_list_find_custom (priv->local_pendings,
+ contact,
+ tp_group_local_pending_find);
+ if (l) {
+ empathy_pending_info_free (l->data);
+ priv->local_pendings = g_list_delete_link (priv->local_pendings, l);
+ }
+
+ /* remote pending */
+ l = g_list_find (priv->remote_pendings, contact);
+ if (l) {
+ g_object_unref (l->data);
+ priv->remote_pendings = g_list_delete_link (priv->remote_pendings, l);
+ }
+}
+
+static void
+tp_group_members_changed_cb (DBusGProxy *group_iface,
+ const gchar *message,
+ GArray *added,
+ GArray *removed,
+ GArray *local_pending,
+ GArray *remote_pending,
+ guint actor,
+ guint reason,
+ EmpathyTpGroup *group)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ EmpathyContact *actor_contact = NULL;
+ GList *contacts, *l, *ll;
+
+ actor_contact = tp_group_get_contact (group, actor);
+
+ empathy_debug (DEBUG_DOMAIN, "Members changed for list %s:\n"
+ " added-len=%d, current-len=%d\n"
+ " removed-len=%d\n"
+ " local-pending-len=%d, current-len=%d\n"
+ " remote-pending-len=%d, current-len=%d",
+ empathy_tp_group_get_name (group),
+ added ? added->len : 0, g_list_length (priv->members),
+ removed ? removed->len : 0,
+ local_pending ? local_pending->len : 0,
+ g_list_length (priv->local_pendings),
+ remote_pending ? remote_pending->len : 0,
+ g_list_length (priv->remote_pendings));
+
+ /* Contacts added */
+ contacts = tp_group_get_contacts (group, added);
+ for (l = contacts; l; l = l->next) {
+ tp_group_remove_from_pendings (group, l->data);
+
+ /* If the contact is not yet member, add it and emit signal */
+ if (!g_list_find (priv->members, l->data)) {
+ priv->members = g_list_prepend (priv->members,
+ g_object_ref (l->data));
+ g_signal_emit (group, signals[MEMBER_ADDED], 0,
+ l->data, actor_contact, reason, message);
+ }
+ g_object_unref (l->data);
+ }
+ g_list_free (contacts);
+
+ /* Contacts removed */
+ contacts = tp_group_get_contacts (group, removed);
+ for (l = contacts; l; l = l->next) {
+ tp_group_remove_from_pendings (group, l->data);
+
+ /* If the contact is member, remove it and emit signal */
+ if ((ll = g_list_find (priv->members, l->data))) {
+ g_object_unref (ll->data);
+ priv->members = g_list_delete_link (priv->members, ll);
+ g_signal_emit (group, signals[MEMBER_REMOVED], 0,
+ l->data, actor_contact, reason, message);
+ }
+ g_object_unref (l->data);
+ }
+ g_list_free (contacts);
+
+ /* Contacts local pending */
+ contacts = tp_group_get_contacts (group, local_pending);
+ for (l = contacts; l; l = l->next) {
+ /* If the contact is not yet local-pending, add it and emit signal */
+ if (!g_list_find_custom (priv->members, l->data,
+ tp_group_local_pending_find)) {
+ EmpathyPendingInfo *info;
+
+ info = empathy_pending_info_new (l->data,
+ actor_contact,
+ message);
+
+ priv->local_pendings = g_list_prepend (priv->local_pendings, info);
+ g_signal_emit (group, signals[LOCAL_PENDING], 0,
+ l->data, actor_contact, reason, message);
+ }
+ g_object_unref (l->data);
+ }
+ g_list_free (contacts);
+
+ /* Contacts remote pending */
+ contacts = tp_group_get_contacts (group, remote_pending);
+ for (l = contacts; l; l = l->next) {
+ /* If the contact is not yet remote-pending, add it and emit signal */
+ if (!g_list_find (priv->remote_pendings, l->data)) {
+ priv->remote_pendings = g_list_prepend (priv->remote_pendings,
+ g_object_ref (l->data));
+ g_signal_emit (group, signals[REMOTE_PENDING], 0,
+ l->data, actor_contact, reason, message);
+ }
+ g_object_unref (l->data);
+ }
+ g_list_free (contacts);
+
+ if (actor_contact) {
+ g_object_unref (actor_contact);
+ }
+
+ empathy_debug (DEBUG_DOMAIN, "Members changed done for list %s:\n"
+ " members-len=%d\n"
+ " local-pendings-len=%d\n"
+ " remote-pendings-len=%d",
+ empathy_tp_group_get_name (group),
+ g_list_length (priv->members),
+ g_list_length (priv->local_pendings),
+ g_list_length (priv->remote_pendings));
+}
+
+static void
+tp_group_destroy_cb (TpChan *tp_chan,
+ EmpathyTpGroup *group)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+ empathy_debug (DEBUG_DOMAIN, "Account disconnected or CM crashed");
+
+ g_object_unref (priv->tp_chan);
+ priv->group_iface = NULL;
+ priv->tp_chan = NULL;
+
+ g_signal_emit (group, signals[DESTROY], 0);
+}
+
+static void tp_group_closed_cb (DBusGProxy *proxy,
+ EmpathyTpGroup *group);
+
+static void
+tp_group_disconnect (EmpathyTpGroup *group)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+ if (priv->group_iface) {
+ dbus_g_proxy_disconnect_signal (priv->group_iface, "MembersChanged",
+ G_CALLBACK (tp_group_members_changed_cb),
+ group);
+ }
+ if (priv->tp_chan) {
+ g_signal_handlers_disconnect_by_func (priv->tp_chan,
+ tp_group_destroy_cb,
+ group);
+ dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
+ G_CALLBACK (tp_group_closed_cb),
+ group);
+ }
+}
+
+static void
+tp_group_closed_cb (DBusGProxy *proxy,
+ EmpathyTpGroup *group)
+{
+ tp_group_disconnect (group);
+ tp_group_destroy_cb (TELEPATHY_CHAN (proxy), group);
+}
+
+static void
+tp_group_get_members_cb (DBusGProxy *proxy,
+ GArray *handles,
+ GError *error,
+ gpointer user_data)
+{
+ EmpathyTpGroup *group = user_data;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to get members: %s",
+ error->message);
+ return;
+ }
+
+ tp_group_members_changed_cb (priv->group_iface,
+ NULL, /* message */
+ handles, /* added */
+ NULL, /* removed */
+ NULL, /* local_pending */
+ NULL, /* remote_pending */
+ 0, /* actor */
+ 0, /* reason */
+ group);
+}
+
+static void
+tp_group_get_local_pending_cb (DBusGProxy *proxy,
+ GPtrArray *array,
+ GError *error,
+ gpointer user_data)
+{
+ EmpathyTpGroup *group = user_data;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GArray *handles;
+ guint i;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to get local pendings: %s",
+ error->message);
+ return;
+ }
+
+ handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
+ for (i = 0; array->len > i; i++) {
+ GValueArray *pending_struct;
+ const gchar *message;
+ guint member_handle;
+ guint actor_handle;
+ guint reason;
+
+ pending_struct = g_ptr_array_index (array, i);
+ member_handle = g_value_get_uint (g_value_array_get_nth (pending_struct, 0));
+ actor_handle = g_value_get_uint (g_value_array_get_nth (pending_struct, 1));
+ reason = g_value_get_uint (g_value_array_get_nth (pending_struct, 2));
+ message = g_value_get_string (g_value_array_get_nth (pending_struct, 3));
+
+ g_array_insert_val (handles, 0, member_handle);
+ tp_group_members_changed_cb (priv->group_iface,
+ message, /* message */
+ NULL, /* added */
+ NULL, /* removed */
+ handles, /* local_pending */
+ NULL, /* remote_pending */
+ actor_handle, /* actor */
+ reason, /* reason */
+ group);
+ }
+ g_array_free (handles, TRUE);
+}
+
+static void
+tp_group_get_remote_pending_cb (DBusGProxy *proxy,
+ GArray *handles,
+ GError *error,
+ gpointer user_data)
+{
+ EmpathyTpGroup *group = user_data;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "Failed to get remote pendings: %s",
+ error->message);
+ return;
+ }
+
+ tp_group_members_changed_cb (priv->group_iface,
+ NULL, /* message */
+ NULL, /* added */
+ NULL, /* removed */
+ NULL, /* local_pending */
+ handles, /* remote_pending */
+ 0, /* actor */
+ 0, /* reason */
+ group);
+}
+
+static void
+tp_group_finalize (GObject *object)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (object);
+
+ tp_group_disconnect (EMPATHY_TP_GROUP (object));
+
+ if (priv->tp_chan) {
+ g_object_unref (priv->tp_chan);
+ }
+ if (priv->account) {
+ g_object_unref (priv->account);
+ }
+ if (priv->factory) {
+ g_object_unref (priv->factory);
+ }
+ g_free (priv->group_name);
+
+ g_list_foreach (priv->members, (GFunc) g_object_unref, NULL);
+ g_list_free (priv->members);
+
+ g_list_foreach (priv->local_pendings, (GFunc) empathy_pending_info_free, NULL);
+ g_list_free (priv->local_pendings);
+
+ g_list_foreach (priv->remote_pendings, (GFunc) g_object_unref, NULL);
+ g_list_free (priv->remote_pendings);
+
+ G_OBJECT_CLASS (empathy_tp_group_parent_class)->finalize (object);
+}
+
static void
empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
{
@@ -77,25 +480,25 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
object_class->finalize = tp_group_finalize;
- signals[MEMBERS_ADDED] =
- g_signal_new ("members-added",
+ signals[MEMBER_ADDED] =
+ g_signal_new ("member-added",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+ empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
G_TYPE_NONE,
- 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+ 4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
- signals[MEMBERS_REMOVED] =
- g_signal_new ("members-removed",
+ signals[MEMBER_REMOVED] =
+ g_signal_new ("member-removed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+ empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
G_TYPE_NONE,
- 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+ 4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
signals[LOCAL_PENDING] =
g_signal_new ("local-pending",
@@ -103,9 +506,9 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+ empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
G_TYPE_NONE,
- 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+ 4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
signals[REMOTE_PENDING] =
g_signal_new ("remote-pending",
@@ -113,9 +516,19 @@ empathy_tp_group_class_init (EmpathyTpGroupClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- empathy_marshal_VOID__POINTER_UINT_UINT_STRING,
+ empathy_marshal_VOID__OBJECT_OBJECT_UINT_STRING,
G_TYPE_NONE,
- 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING);
+ 4, EMPATHY_TYPE_CONTACT, EMPATHY_TYPE_CONTACT, G_TYPE_UINT, G_TYPE_STRING);
+
+ signals[DESTROY] =
+ g_signal_new ("destroy",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
g_type_class_add_private (object_class, sizeof (EmpathyTpGroupPriv));
}
@@ -125,36 +538,6 @@ empathy_tp_group_init (EmpathyTpGroup *group)
{
}
-static void
-tp_group_finalize (GObject *object)
-{
- EmpathyTpGroupPriv *priv;
-
- priv = GET_PRIV (object);
-
- if (priv->group_iface) {
- g_signal_handlers_disconnect_by_func (priv->group_iface,
- tp_group_destroy_cb,
- object);
- dbus_g_proxy_disconnect_signal (priv->group_iface, "MembersChanged",
- G_CALLBACK (tp_group_members_changed_cb),
- object);
- g_object_unref (priv->group_iface);
- }
-
- if (priv->account) {
- g_object_unref (priv->account);
- }
-
- if (priv->tp_chan) {
- g_object_unref (priv->tp_chan);
- }
-
- g_free (priv->group_name);
-
- G_OBJECT_CLASS (empathy_tp_group_parent_class)->finalize (object);
-}
-
EmpathyTpGroup *
empathy_tp_group_new (McAccount *account,
TpChan *tp_chan)
@@ -162,6 +545,7 @@ empathy_tp_group_new (McAccount *account,
EmpathyTpGroup *group;
EmpathyTpGroupPriv *priv;
DBusGProxy *group_iface;
+ GError *error;
g_return_val_if_fail (TELEPATHY_IS_CHAN (tp_chan), NULL);
g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
@@ -175,262 +559,205 @@ empathy_tp_group_new (McAccount *account,
priv->account = g_object_ref (account);
priv->tp_chan = g_object_ref (tp_chan);
- priv->group_iface = g_object_ref (group_iface);
+ priv->group_iface = group_iface;
+ priv->factory = empathy_contact_factory_new ();
+
+ if (!tp_chan_iface_group_get_self_handle (priv->group_iface,
+ &priv->self_handle,
+ &error)) {
+ empathy_debug (DEBUG_DOMAIN,
+ "Failed to get self handle: %s",
+ error ? error->message : "No error given");
+ g_clear_error (&error);
+ }
dbus_g_proxy_connect_signal (priv->group_iface, "MembersChanged",
G_CALLBACK (tp_group_members_changed_cb),
group, NULL);
- g_signal_connect (group_iface, "destroy",
+ dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
+ G_CALLBACK (tp_group_closed_cb),
+ group, NULL);
+ g_signal_connect (priv->tp_chan, "destroy",
G_CALLBACK (tp_group_destroy_cb),
group);
+ tp_chan_iface_group_get_members_async (priv->group_iface,
+ tp_group_get_members_cb,
+ group);
+ tp_chan_iface_group_get_local_pending_members_with_info_async (priv->group_iface,
+ tp_group_get_local_pending_cb,
+ group);
+ tp_chan_iface_group_get_remote_pending_members_async (priv->group_iface,
+ tp_group_get_remote_pending_cb,
+ group);
+
return group;
}
+static void
+tp_group_async_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+ const gchar *msg = user_data;
+
+ if (error) {
+ empathy_debug (DEBUG_DOMAIN, "%s: %s", msg, error->message);
+ }
+}
+
+void
+empathy_tp_group_close (EmpathyTpGroup *group)
+{
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+ tp_chan_close_async (DBUS_G_PROXY (priv->tp_chan),
+ tp_group_async_cb,
+ "Failed to close");
+}
+
+static GArray *
+tp_group_get_handles (GList *contacts)
+{
+ GArray *handles;
+ guint length;
+ GList *l;
+
+ length = g_list_length (contacts);
+ handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), length);
+
+ for (l = contacts; l; l = l->next) {
+ guint handle;
+
+ handle = empathy_contact_get_handle (l->data);
+ g_array_append_val (handles, handle);
+ }
+
+ return handles;
+}
+
void
empathy_tp_group_add_members (EmpathyTpGroup *group,
- GArray *handles,
+ GList *contacts,
const gchar *message)
{
- EmpathyTpGroupPriv *priv;
- GError *error = NULL;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GArray *handles;
g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
- g_return_if_fail (handles != NULL);
+ g_return_if_fail (contacts != NULL);
- priv = GET_PRIV (group);
+ handles = tp_group_get_handles (contacts);
+ tp_chan_iface_group_add_members_async (priv->group_iface,
+ handles,
+ message,
+ tp_group_async_cb,
+ "Failed to add members");
- if (!tp_chan_iface_group_add_members (priv->group_iface,
- handles,
- message,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Failed to add members: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- }
+ g_array_free (handles, TRUE);
}
void
empathy_tp_group_add_member (EmpathyTpGroup *group,
- guint handle,
+ EmpathyContact *contact,
const gchar *message)
{
- GArray *handles;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GArray *handles;
+ guint handle;
+ handle = empathy_contact_get_handle (contact);
handles = g_array_new (FALSE, FALSE, sizeof (guint));
g_array_append_val (handles, handle);
- empathy_tp_group_add_members (group, handles, message);
+ tp_chan_iface_group_add_members_async (priv->group_iface,
+ handles,
+ message,
+ tp_group_async_cb,
+ "Failed to add member");
g_array_free (handles, TRUE);
}
void
empathy_tp_group_remove_members (EmpathyTpGroup *group,
- GArray *handles,
+ GList *contacts,
const gchar *message)
{
- EmpathyTpGroupPriv *priv;
- GError *error = NULL;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GArray *handles;
g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
+ g_return_if_fail (contacts != NULL);
- priv = GET_PRIV (group);
+ handles = tp_group_get_handles (contacts);
+ tp_chan_iface_group_remove_members_async (priv->group_iface,
+ handles,
+ message,
+ tp_group_async_cb,
+ "Failed to remove members");
- if (!tp_chan_iface_group_remove_members (priv->group_iface,
- handles,
- message,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Failed to remove members: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- }
+ g_array_free (handles, TRUE);
}
void
empathy_tp_group_remove_member (EmpathyTpGroup *group,
- guint handle,
+ EmpathyContact *contact,
const gchar *message)
{
- GArray *handles;
-
- g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GArray *handles;
+ guint handle;
+ handle = empathy_contact_get_handle (contact);
handles = g_array_new (FALSE, FALSE, sizeof (guint));
g_array_append_val (handles, handle);
- empathy_tp_group_remove_members (group, handles, message);
+ tp_chan_iface_group_remove_members_async (priv->group_iface,
+ handles,
+ message,
+ tp_group_async_cb,
+ "Failed to remove member");
g_array_free (handles, TRUE);
}
-GArray *
+GList *
empathy_tp_group_get_members (EmpathyTpGroup *group)
{
- EmpathyTpGroupPriv *priv;
- GArray *members;
- GError *error = NULL;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
- g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
+ g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
- priv = GET_PRIV (group);
-
- if (!tp_chan_iface_group_get_members (priv->group_iface,
- &members,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Couldn't get members: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- return NULL;
- }
-
- return members;
-}
-
-void
-empathy_tp_group_get_all_members (EmpathyTpGroup *group,
- GArray **members,
- GArray **local_pending,
- GArray **remote_pending)
-{
- EmpathyTpGroupPriv *priv;
- GError *error = NULL;
-
- g_return_if_fail (EMPATHY_IS_TP_GROUP (group));
-
- priv = GET_PRIV (group);
-
- if (!tp_chan_iface_group_get_all_members (priv->group_iface,
- members,
- local_pending,
- remote_pending,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Couldn't get all members: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- }
+ return g_list_copy (priv->members);
}
GList *
-empathy_tp_group_get_local_pending_members_with_info (EmpathyTpGroup *group)
-{
- EmpathyTpGroupPriv *priv;
- GPtrArray *array;
- guint i;
- GList *infos = NULL;
- GError *error = NULL;
-
- g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
-
- priv = GET_PRIV (group);
-
- if (!tp_chan_iface_group_get_local_pending_members_with_info (priv->group_iface,
- &array,
- &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "GetLocalPendingMembersWithInfo failed: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
-
- return NULL;
- }
-
- if (!array) {
- /* This happens with butterfly because
- * GetLocalPendingMembersWithInfo is not
- * implemented */
- return NULL;
- }
-
- for (i = 0; array->len > i; i++) {
- GValueArray *pending_struct;
- EmpathyTpGroupInfo *info;
- const gchar *message;
-
- info = g_slice_new (EmpathyTpGroupInfo);
-
- pending_struct = g_ptr_array_index (array, i);
- info->member = g_value_get_uint (g_value_array_get_nth (pending_struct, 0));
- info->actor = g_value_get_uint (g_value_array_get_nth (pending_struct, 1));
- info->reason = g_value_get_uint (g_value_array_get_nth (pending_struct, 2));
- message = g_value_get_string (g_value_array_get_nth (pending_struct, 3));
- info->message = g_strdup (message);
- g_value_array_free (pending_struct);
-
- infos = g_list_prepend (infos, info);
- }
- g_ptr_array_free (array, TRUE);
-
- return infos;
-}
-
-void
-empathy_tp_group_info_list_free (GList *infos)
+empathy_tp_group_get_local_pendings (EmpathyTpGroup *group)
{
- GList *l;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+ GList *pendings = NULL, *l;
- for (l = infos; l; l = l->next) {
- EmpathyTpGroupInfo *info;
+ for (l = priv->local_pendings; l; l = l->next) {
+ EmpathyPendingInfo *info;
+ EmpathyPendingInfo *new_info;
info = l->data;
-
- g_free (info->message);
- g_slice_free (EmpathyTpGroupInfo, info);
+ new_info = empathy_pending_info_new (info->member,
+ info->actor,
+ info->message);
+ pendings = g_list_prepend (pendings, new_info);
}
- g_list_free (infos);
-}
-
-static void
-tp_group_destroy_cb (DBusGProxy *proxy,
- EmpathyTpGroup *group)
-{
- EmpathyTpGroupPriv *priv;
-
- priv = GET_PRIV (group);
-
- g_object_unref (priv->group_iface);
- g_object_unref (priv->tp_chan);
- priv->group_iface = NULL;
- priv->tp_chan = NULL;
+ return pendings;
}
-static void
-tp_group_members_changed_cb (DBusGProxy *group_iface,
- gchar *message,
- GArray *added,
- GArray *removed,
- GArray *local_pending,
- GArray *remote_pending,
- guint actor,
- guint reason,
- EmpathyTpGroup *group)
+GList *
+empathy_tp_group_get_remote_pendings (EmpathyTpGroup *group)
{
- EmpathyTpGroupPriv *priv;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
- priv = GET_PRIV (group);
+ g_list_foreach (priv->remote_pendings, (GFunc) g_object_ref, NULL);
- /* emit signals */
- if (added->len > 0) {
- g_signal_emit (group, signals[MEMBERS_ADDED], 0,
- added, actor, reason, message);
- }
- if (removed->len > 0) {
- g_signal_emit (group, signals[MEMBERS_REMOVED], 0,
- removed, actor, reason, message);
- }
- if (local_pending->len > 0) {
- g_signal_emit (group, signals[LOCAL_PENDING], 0,
- local_pending, actor, reason, message);
- }
- if (remote_pending->len > 0) {
- g_signal_emit (group, signals[REMOTE_PENDING], 0,
- remote_pending, actor, reason, message);
- }
+ return g_list_copy (priv->remote_pendings);
}
const gchar *
@@ -443,35 +770,21 @@ empathy_tp_group_get_name (EmpathyTpGroup *group)
priv = GET_PRIV (group);
/* Lazy initialisation */
- if (priv->group_name) {
- return priv->group_name;
+ if (!priv->group_name) {
+ priv->group_name = empathy_inspect_channel (priv->account, priv->tp_chan);
}
- priv->group_name = empathy_inspect_channel (priv->account, priv->tp_chan);
-
return priv->group_name;
}
-guint
-empathy_tp_group_get_self_handle (EmpathyTpGroup *group)
+EmpathyContact *
+empathy_tp_group_get_self_contact (EmpathyTpGroup *group)
{
- EmpathyTpGroupPriv *priv;
- guint handle;
- GError *error = NULL;
-
- g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), 0 );
-
- priv = GET_PRIV (group);
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
- if (!tp_chan_iface_group_get_self_handle (priv->group_iface, &handle, &error)) {
- empathy_debug (DEBUG_DOMAIN,
- "Failed to get self handle: %s",
- error ? error->message : "No error given");
- g_clear_error (&error);
- return 0;
- }
+ g_return_val_if_fail (EMPATHY_IS_TP_GROUP (group), NULL);
- return handle;
+ return tp_group_get_contact (group, priv->self_handle);
}
const gchar *
@@ -488,21 +801,10 @@ empathy_tp_group_get_object_path (EmpathyTpGroup *group)
gboolean
empathy_tp_group_is_member (EmpathyTpGroup *group,
- guint handle)
+ EmpathyContact *contact)
{
- GArray *members;
- guint i;
- gboolean found = FALSE;
-
- members = empathy_tp_group_get_members (group);
- for (i = 0; i < members->len; i++) {
- if (g_array_index (members, guint, i) == handle) {
- found = TRUE;
- break;
- }
- }
- g_array_free (members, TRUE);
-
- return found;
+ EmpathyTpGroupPriv *priv = GET_PRIV (group);
+
+ return g_list_find (priv->members, contact) != NULL;
}
diff --git a/libempathy/empathy-tp-group.h b/libempathy/empathy-tp-group.h
index 5ea7bfc71..14cbd4649 100644
--- a/libempathy/empathy-tp-group.h
+++ b/libempathy/empathy-tp-group.h
@@ -1,6 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2006 Xavier Claessens <xclaesse@gmail.com>
+ * Copyright (C) 2007 Collabora Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -16,6 +17,8 @@
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
*/
#ifndef __EMPATHY_TP_GROUP_H__
@@ -24,8 +27,11 @@
#include <glib.h>
#include <libtelepathy/tp-chan.h>
+#include <libtelepathy/tp-constants.h>
#include <libmissioncontrol/mc-account.h>
+#include "empathy-contact.h"
+
G_BEGIN_DECLS
#define EMPATHY_TYPE_TP_GROUP (empathy_tp_group_get_type ())
@@ -48,39 +54,40 @@ struct _EmpathyTpGroupClass {
};
typedef struct {
- guint member;
- guint actor;
- guint reason;
- gchar *message;
-} EmpathyTpGroupInfo;
+ EmpathyContact *member;
+ EmpathyContact *actor;
+ gchar *message;
+ guint reason;
+} EmpathyPendingInfo;
-GType empathy_tp_group_get_type (void) G_GNUC_CONST;
-EmpathyTpGroup * empathy_tp_group_new (McAccount *account,
- TpChan *tp_chan);
-void empathy_tp_group_add_members (EmpathyTpGroup *group,
- GArray *handles,
- const gchar *message);
-void empathy_tp_group_add_member (EmpathyTpGroup *group,
- guint handle,
- const gchar *message);
-void empathy_tp_group_remove_members (EmpathyTpGroup *group,
- GArray *handle,
- const gchar *message);
-void empathy_tp_group_remove_member (EmpathyTpGroup *group,
- guint handle,
- const gchar *message);
-GArray * empathy_tp_group_get_members (EmpathyTpGroup *group);
-void empathy_tp_group_get_all_members (EmpathyTpGroup *group,
- GArray **members,
- GArray **local_pending,
- GArray **remote_pending);
-GList * empathy_tp_group_get_local_pending_members_with_info (EmpathyTpGroup *group);
-void empathy_tp_group_info_list_free (GList *infos);
-const gchar * empathy_tp_group_get_name (EmpathyTpGroup *group);
-guint empathy_tp_group_get_self_handle (EmpathyTpGroup *group);
-const gchar * empathy_tp_group_get_object_path (EmpathyTpGroup *group);
-gboolean empathy_tp_group_is_member (EmpathyTpGroup *group,
- guint handle);
+GType empathy_tp_group_get_type (void) G_GNUC_CONST;
+EmpathyTpGroup * empathy_tp_group_new (McAccount *account,
+ TpChan *tp_chan);
+void empathy_tp_group_close (EmpathyTpGroup *group);
+void empathy_tp_group_add_members (EmpathyTpGroup *group,
+ GList *contacts,
+ const gchar *message);
+void empathy_tp_group_add_member (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ const gchar *message);
+void empathy_tp_group_remove_members (EmpathyTpGroup *group,
+ GList *contacts,
+ const gchar *message);
+void empathy_tp_group_remove_member (EmpathyTpGroup *group,
+ EmpathyContact *contact,
+ const gchar *message);
+GList * empathy_tp_group_get_members (EmpathyTpGroup *group);
+GList * empathy_tp_group_get_local_pendings (EmpathyTpGroup *group);
+GList * empathy_tp_group_get_remote_pendings (EmpathyTpGroup *group);
+const gchar * empathy_tp_group_get_name (EmpathyTpGroup *group);
+EmpathyContact * empathy_tp_group_get_self_contact (EmpathyTpGroup *group);
+const gchar * empathy_tp_group_get_object_path (EmpathyTpGroup *group);
+gboolean empathy_tp_group_is_member (EmpathyTpGroup *group,
+ EmpathyContact *contact);
+EmpathyPendingInfo *empathy_pending_info_new (EmpathyContact *member,
+ EmpathyContact *actor,
+ const gchar *message);
+void empathy_pending_info_free (EmpathyPendingInfo *info);
G_END_DECLS