diff options
Diffstat (limited to 'libempathy')
-rw-r--r-- | libempathy/empathy-contact-list.c | 58 | ||||
-rw-r--r-- | libempathy/empathy-contact-list.h | 52 | ||||
-rw-r--r-- | libempathy/empathy-contact-manager.c | 78 | ||||
-rw-r--r-- | libempathy/empathy-idle.c | 233 | ||||
-rw-r--r-- | libempathy/empathy-idle.h | 15 | ||||
-rw-r--r-- | libempathy/empathy-marshal.list | 8 | ||||
-rw-r--r-- | libempathy/empathy-tp-chatroom.c | 14 | ||||
-rw-r--r-- | libempathy/empathy-tp-contact-list.c | 355 |
8 files changed, 598 insertions, 215 deletions
diff --git a/libempathy/empathy-contact-list.c b/libempathy/empathy-contact-list.c index b7d02010b..c55d0abf9 100644 --- a/libempathy/empathy-contact-list.c +++ b/libempathy/empathy-contact-list.c @@ -23,6 +23,7 @@ #include "config.h" #include "empathy-contact-list.h" +#include "empathy-marshal.h" static void contact_list_base_init (gpointer klass); @@ -70,10 +71,49 @@ contact_list_base_init (gpointer klass) G_TYPE_NONE, 1, GOSSIP_TYPE_CONTACT); + g_signal_new ("local-pending", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + empathy_marshal_VOID__OBJECT_STRING, + G_TYPE_NONE, + 2, GOSSIP_TYPE_CONTACT, G_TYPE_STRING); + initialized = TRUE; } } +EmpathyContactListInfo * +empathy_contact_list_info_new (GossipContact *contact, + const gchar *message) +{ + EmpathyContactListInfo *info; + + g_return_val_if_fail (GOSSIP_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) +{ + if (!info) { + return; + } + + if (info->contact) { + g_object_unref (info->contact); + } + g_free (info->message); + + g_slice_free (EmpathyContactListInfo, info); +} + void empathy_contact_list_setup (EmpathyContactList *list) { @@ -122,12 +162,24 @@ empathy_contact_list_remove (EmpathyContactList *list, } GList * -empathy_contact_list_get_contacts (EmpathyContactList *list) +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)->get_members) { + return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_members (list); + } + + return NULL; +} + +GList * +empathy_contact_list_get_local_pending (EmpathyContactList *list) { g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (list), NULL); - if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_contacts) { - return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_contacts (list); + if (EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending) { + return EMPATHY_CONTACT_LIST_GET_IFACE (list)->get_local_pending (list); } return NULL; diff --git a/libempathy/empathy-contact-list.h b/libempathy/empathy-contact-list.h index 02ec3186d..09f54621d 100644 --- a/libempathy/empathy-contact-list.h +++ b/libempathy/empathy-contact-list.h @@ -37,33 +37,43 @@ G_BEGIN_DECLS typedef struct _EmpathyContactList EmpathyContactList; typedef struct _EmpathyContactListIface EmpathyContactListIface; +typedef struct { + GossipContact *contact; + gchar *message; +} EmpathyContactListInfo; + struct _EmpathyContactListIface { GTypeInterface base_iface; /* VTabled */ - void (*setup) (EmpathyContactList *list); - GossipContact * (*find) (EmpathyContactList *list, - const gchar *id); - void (*add) (EmpathyContactList *list, - GossipContact *contact, - const gchar *message); - void (*remove) (EmpathyContactList *list, - GossipContact *contact, - const gchar *message); - GList * (*get_contacts) (EmpathyContactList *list); + void (*setup) (EmpathyContactList *list); + GossipContact * (*find) (EmpathyContactList *list, + const gchar *id); + void (*add) (EmpathyContactList *list, + GossipContact *contact, + const gchar *message); + void (*remove) (EmpathyContactList *list, + GossipContact *contact, + const gchar *message); + GList * (*get_members) (EmpathyContactList *list); + GList * (*get_local_pending) (EmpathyContactList *list); }; -GType empathy_contact_list_get_type (void) G_GNUC_CONST; -void empathy_contact_list_setup (EmpathyContactList *list); -GossipContact * empathy_contact_list_find (EmpathyContactList *list, - const gchar *id); -void empathy_contact_list_add (EmpathyContactList *list, - GossipContact *contact, - const gchar *message); -void empathy_contact_list_remove (EmpathyContactList *list, - GossipContact *contact, - const gchar *message); -GList * empathy_contact_list_get_contacts (EmpathyContactList *list); +GType empathy_contact_list_get_type (void) G_GNUC_CONST; +EmpathyContactListInfo *empathy_contact_list_info_new (GossipContact *contact, + const gchar *message); +void empathy_contact_list_info_free (EmpathyContactListInfo *info); +void empathy_contact_list_setup (EmpathyContactList *list); +GossipContact * empathy_contact_list_find (EmpathyContactList *list, + const gchar *id); +void empathy_contact_list_add (EmpathyContactList *list, + GossipContact *contact, + const gchar *message); +void empathy_contact_list_remove (EmpathyContactList *list, + GossipContact *contact, + const gchar *message); +GList * empathy_contact_list_get_members (EmpathyContactList *list); +GList * empathy_contact_list_get_local_pending (EmpathyContactList *list); G_END_DECLS diff --git a/libempathy/empathy-contact-manager.c b/libempathy/empathy-contact-manager.c index fa62da98f..5e5f09a43 100644 --- a/libempathy/empathy-contact-manager.c +++ b/libempathy/empathy-contact-manager.c @@ -65,7 +65,8 @@ static void contact_manager_add (EmpathyContactList static void contact_manager_remove (EmpathyContactList *manager, GossipContact *contact, const gchar *message); -static GList * contact_manager_get_contacts (EmpathyContactList *manager); +static GList * contact_manager_get_members (EmpathyContactList *manager); +static GList * contact_manager_get_local_pending (EmpathyContactList *manager); static void contact_manager_setup_foreach (McAccount *account, EmpathyTpContactList *list, EmpathyContactManager *manager); @@ -80,6 +81,10 @@ static void contact_manager_added_cb (EmpathyTpContactList static void contact_manager_removed_cb (EmpathyTpContactList *list, GossipContact *contact, EmpathyContactManager *manager); +static void contact_manager_local_pending_cb (EmpathyTpContactList *list, + GossipContact *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, @@ -88,7 +93,10 @@ static void contact_manager_rename_group_foreach (McAccount static void contact_manager_get_groups_foreach (McAccount *account, EmpathyTpContactList *list, GList **all_groups); -static void contact_manager_get_contacts_foreach (McAccount *account, +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, @@ -115,11 +123,12 @@ empathy_contact_manager_class_init (EmpathyContactManagerClass *klass) static void contact_manager_iface_init (EmpathyContactListIface *iface) { - iface->setup = contact_manager_setup; - iface->find = contact_manager_find; - iface->add = contact_manager_add; - iface->remove = contact_manager_remove; - iface->get_contacts = contact_manager_get_contacts; + 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; } static void @@ -269,7 +278,7 @@ contact_manager_remove (EmpathyContactList *manager, } static GList * -contact_manager_get_contacts (EmpathyContactList *manager) +contact_manager_get_members (EmpathyContactList *manager) { EmpathyContactManagerPriv *priv; GList *contacts = NULL; @@ -279,12 +288,29 @@ contact_manager_get_contacts (EmpathyContactList *manager) priv = GET_PRIV (manager); g_hash_table_foreach (priv->lists, - (GHFunc) contact_manager_get_contacts_foreach, + (GHFunc) contact_manager_get_members_foreach, &contacts); 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; +} + EmpathyTpContactList * empathy_contact_manager_get_list (EmpathyContactManager *manager, McAccount *account) @@ -435,6 +461,9 @@ contact_manager_add_account (EmpathyContactManager *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); @@ -461,6 +490,15 @@ contact_manager_removed_cb (EmpathyTpContactList *list, } static void +contact_manager_local_pending_cb (EmpathyTpContactList *list, + GossipContact *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) { @@ -482,6 +520,9 @@ contact_manager_destroy_cb (EmpathyTpContactList *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); @@ -520,13 +561,24 @@ contact_manager_get_groups_foreach (McAccount *account, } static void -contact_manager_get_contacts_foreach (McAccount *account, - EmpathyTpContactList *list, - GList **contacts) +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 void +contact_manager_get_local_pending_foreach (McAccount *account, + EmpathyTpContactList *list, + GList **contacts) { GList *l; - l = empathy_contact_list_get_contacts (EMPATHY_CONTACT_LIST (list)); + l = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (list)); *contacts = g_list_concat (*contacts, l); } diff --git a/libempathy/empathy-idle.c b/libempathy/empathy-idle.c index 6b9cfb3b9..f9b50bd40 100644 --- a/libempathy/empathy-idle.c +++ b/libempathy/empathy-idle.c @@ -27,8 +27,6 @@ #include <libtelepathy/tp-helpers.h> -#include <libmissioncontrol/mission-control.h> - #include "empathy-idle.h" #include "gossip-utils.h" #include "gossip-debug.h" @@ -49,6 +47,9 @@ struct _EmpathyIdlePriv { MissionControl *mc; DBusGProxy *gs_proxy; gboolean is_idle; + McPresence state; + McPresence slack_state; + gchar *status; McPresence saved_state; gchar *saved_status; guint ext_away_timeout; @@ -57,6 +58,17 @@ struct _EmpathyIdlePriv { static void empathy_idle_class_init (EmpathyIdleClass *klass); static void empathy_idle_init (EmpathyIdle *idle); static void idle_finalize (GObject *object); +static void idle_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void idle_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); +static void idle_presence_changed_cb (MissionControl *mc, + McPresence state, + EmpathyIdle *idle); static void idle_session_idle_changed_cb (DBusGProxy *gs_proxy, gboolean is_idle, EmpathyIdle *idle); @@ -64,7 +76,12 @@ static void idle_ext_away_start (EmpathyIdle *idle); static void idle_ext_away_stop (EmpathyIdle *idle); static gboolean idle_ext_away_cb (EmpathyIdle *idle); -//static guint signals[LAST_SIGNAL]; +enum { + PROP_0, + PROP_STATE, + PROP_STATUS, + PROP_SLACK_STATE +}; G_DEFINE_TYPE (EmpathyIdle, empathy_idle, G_TYPE_OBJECT) @@ -74,6 +91,34 @@ empathy_idle_class_init (EmpathyIdleClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = idle_finalize; + object_class->get_property = idle_get_property; + object_class->set_property = idle_set_property; + + g_object_class_install_property (object_class, + PROP_STATE, + g_param_spec_uint ("state", + "state", + "state", + MC_PRESENCE_UNSET, + LAST_MC_PRESENCE, + MC_PRESENCE_AVAILABLE, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_STATUS, + g_param_spec_string ("status", + "status", + "status", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_SLACK_STATE, + g_param_spec_uint ("slack-state", + "slack-state", + "slack-state", + MC_PRESENCE_UNSET, + LAST_MC_PRESENCE, + MC_PRESENCE_UNSET, + G_PARAM_READWRITE)); g_type_class_add_private (object_class, sizeof (EmpathyIdlePriv)); } @@ -87,6 +132,8 @@ empathy_idle_init (EmpathyIdle *idle) priv->is_idle = FALSE; priv->mc = gossip_mission_control_new (); + priv->state = mission_control_get_presence_actual (priv->mc, NULL); + priv->status = mission_control_get_presence_message_actual (priv->mc, NULL); priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (), "org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", @@ -102,6 +149,10 @@ empathy_idle_init (EmpathyIdle *idle) dbus_g_proxy_connect_signal (priv->gs_proxy, "SessionIdleChanged", G_CALLBACK (idle_session_idle_changed_cb), idle, NULL); + dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), + "PresenceStatusActual", + G_CALLBACK (idle_presence_changed_cb), + idle, NULL); } static void @@ -111,6 +162,7 @@ idle_finalize (GObject *object) priv = GET_PRIV (object); + g_free (priv->status); g_free (priv->saved_status); g_object_unref (priv->mc); @@ -121,6 +173,62 @@ idle_finalize (GObject *object) idle_ext_away_stop (EMPATHY_IDLE (object)); } +static void +idle_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyIdlePriv *priv; + EmpathyIdle *idle; + + priv = GET_PRIV (object); + idle = EMPATHY_IDLE (object); + + switch (param_id) { + case PROP_STATE: + g_value_set_uint (value, empathy_idle_get_state (idle)); + break; + case PROP_STATUS: + g_value_set_string (value, empathy_idle_get_status (idle)); + break; + case PROP_SLACK_STATE: + g_value_set_uint (value, empathy_idle_get_slack_state (idle)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static void +idle_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyIdlePriv *priv; + EmpathyIdle *idle; + + priv = GET_PRIV (object); + idle = EMPATHY_IDLE (object); + + switch (param_id) { + case PROP_STATE: + empathy_idle_set_state (idle, g_value_get_uint (value)); + break; + case PROP_STATUS: + empathy_idle_set_status (idle, g_value_get_string (value)); + break; + case PROP_SLACK_STATE: + empathy_idle_set_slack_state (idle, g_value_get_uint (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + EmpathyIdle * empathy_idle_new (void) { @@ -136,6 +244,99 @@ empathy_idle_new (void) return idle; } +McPresence +empathy_idle_get_state (EmpathyIdle *idle) +{ + EmpathyIdlePriv *priv; + + priv = GET_PRIV (idle); + + return priv->state; +} + +void +empathy_idle_set_state (EmpathyIdle *idle, + McPresence state) +{ + EmpathyIdlePriv *priv; + + priv = GET_PRIV (idle); + + mission_control_set_presence (priv->mc, + state, + priv->status, + NULL, NULL); +} + +const gchar * +empathy_idle_get_status (EmpathyIdle *idle) +{ + EmpathyIdlePriv *priv; + + priv = GET_PRIV (idle); + + return priv->status; +} + +void +empathy_idle_set_status (EmpathyIdle *idle, + const gchar *status) +{ + EmpathyIdlePriv *priv; + + priv = GET_PRIV (idle); + + mission_control_set_presence (priv->mc, + priv->state, + status, + NULL, NULL); +} + +McPresence +empathy_idle_get_slack_state (EmpathyIdle *idle) +{ + EmpathyIdlePriv *priv; + + priv = GET_PRIV (idle); + + return priv->slack_state; +} + +void +empathy_idle_set_slack_state (EmpathyIdle *idle, + McPresence state) +{ + EmpathyIdlePriv *priv; + + priv = GET_PRIV (idle); + + priv->slack_state = state; + + g_object_notify (G_OBJECT (idle), "slack-state"); +} + +static void +idle_presence_changed_cb (MissionControl *mc, + McPresence state, + EmpathyIdle *idle) +{ + EmpathyIdlePriv *priv; + + priv = GET_PRIV (idle); + + g_free (priv->status); + priv->state = state; + priv->status = mission_control_get_presence_message_actual (priv->mc, NULL); + + if (G_STR_EMPTY (priv->status)) { + g_free (priv->status); + priv->status = g_strdup (gossip_presence_state_get_default_status (state)); + } + + g_object_notify (G_OBJECT (idle), "state"); + g_object_notify (G_OBJECT (idle), "status"); +} + static void idle_session_idle_changed_cb (DBusGProxy *gs_proxy, gboolean is_idle, @@ -150,30 +351,29 @@ idle_session_idle_changed_cb (DBusGProxy *gs_proxy, is_idle ? "yes" : "no"); if (is_idle && !priv->is_idle) { - McPresence new_state = MC_PRESENCE_AWAY; + McPresence new_state; /* We are now idle, set state to away */ - priv->saved_state = mission_control_get_presence_actual (priv->mc, NULL); - priv->saved_status = mission_control_get_presence_message_actual (priv->mc, NULL); - - if (priv->saved_state <= MC_PRESENCE_OFFLINE || - priv->saved_state == MC_PRESENCE_HIDDEN) { + if (priv->state <= MC_PRESENCE_OFFLINE || + priv->state == MC_PRESENCE_HIDDEN) { /* We are not online so nothing to do here */ return; - } else if (priv->saved_state == MC_PRESENCE_AWAY || - priv->saved_state == MC_PRESENCE_EXTENDED_AWAY) { + } else if (priv->state == MC_PRESENCE_AWAY || + priv->state == MC_PRESENCE_EXTENDED_AWAY) { /* User set away manually, when coming back we restore * default presence. */ - new_state = priv->saved_state; + new_state = priv->state; priv->saved_state = MC_PRESENCE_AVAILABLE; priv->saved_status = NULL; + } else { + new_state = MC_PRESENCE_AWAY; + priv->saved_state = priv->state; + priv->saved_status = g_strdup (priv->status); } gossip_debug (DEBUG_DOMAIN, "Going to autoaway"); - mission_control_set_presence (priv->mc, - new_state, - priv->saved_status, - NULL, NULL); + empathy_idle_set_state (idle, new_state); + idle_ext_away_start (idle); } else if (!is_idle && priv->is_idle) { /* We are no more idle, restore state */ @@ -187,6 +387,7 @@ idle_session_idle_changed_cb (DBusGProxy *gs_proxy, priv->saved_state, priv->saved_status, NULL, NULL); + g_free (priv->saved_status); priv->saved_status = NULL; } diff --git a/libempathy/empathy-idle.h b/libempathy/empathy-idle.h index df8846b9b..13c5dd293 100644 --- a/libempathy/empathy-idle.h +++ b/libempathy/empathy-idle.h @@ -25,6 +25,8 @@ #include <glib.h> +#include <libmissioncontrol/mission-control.h> + G_BEGIN_DECLS #define EMPATHY_TYPE_IDLE (empathy_idle_get_type ()) @@ -46,8 +48,17 @@ struct _EmpathyIdleClass { GObjectClass parent_class; }; -GType empathy_idle_get_type (void) G_GNUC_CONST; -EmpathyIdle *empathy_idle_new (void); +GType empathy_idle_get_type (void) G_GNUC_CONST; +EmpathyIdle *empathy_idle_new (void); +McPresence empathy_idle_get_state (EmpathyIdle *idle); +void empathy_idle_set_state (EmpathyIdle *idle, + McPresence state); +const gchar *empathy_idle_get_status (EmpathyIdle *idle); +void empathy_idle_set_status (EmpathyIdle *idle, + const gchar *message); +McPresence empathy_idle_get_slack_state (EmpathyIdle *idle); +void empathy_idle_set_slack_state (EmpathyIdle *idle, + McPresence state); G_END_DECLS diff --git a/libempathy/empathy-marshal.list b/libempathy/empathy-marshal.list index f13e9f08d..3b36b7be0 100644 --- a/libempathy/empathy-marshal.list +++ b/libempathy/empathy-marshal.list @@ -1,8 +1,10 @@ -VOID:POINTER,UINT,UINT,STRING VOID:OBJECT,UINT VOID:OBJECT,OBJECT -VOID:INT,STRING VOID:OBJECT,OBJECT,UINT -VOID:UINT,BOOLEAN VOID:OBJECT,BOOLEAN VOID:OBJECT,STRING,STRING +VOID:OBJECT,STRING +VOID:POINTER,UINT,UINT,STRING +VOID:INT,STRING +VOID:UINT,BOOLEAN + diff --git a/libempathy/empathy-tp-chatroom.c b/libempathy/empathy-tp-chatroom.c index eb47c9bb3..232db30fd 100644 --- a/libempathy/empathy-tp-chatroom.c +++ b/libempathy/empathy-tp-chatroom.c @@ -72,7 +72,7 @@ static void tp_chatroom_add (EmpathyContactList * static void tp_chatroom_remove (EmpathyContactList *list, GossipContact *contact, const gchar *message); -static GList * tp_chatroom_get_contacts (EmpathyContactList *list); +static GList * tp_chatroom_get_members (EmpathyContactList *list); G_DEFINE_TYPE_WITH_CODE (EmpathyTpChatroom, empathy_tp_chatroom, EMPATHY_TYPE_TP_CHAT, G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST, @@ -91,11 +91,11 @@ 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_contacts = tp_chatroom_get_contacts; + 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; } static void @@ -339,7 +339,7 @@ tp_chatroom_remove (EmpathyContactList *list, } static GList * -tp_chatroom_get_contacts (EmpathyContactList *list) +tp_chatroom_get_members (EmpathyContactList *list) { EmpathyTpChatroomPriv *priv; GArray *members; diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c index 7668057e7..284f51138 100644 --- a/libempathy/empathy-tp-contact-list.c +++ b/libempathy/empathy-tp-contact-list.c @@ -52,12 +52,12 @@ struct _EmpathyTpContactListPriv { GossipContact *user_contact; gboolean setup; - GossipTelepathyGroup *known; GossipTelepathyGroup *publish; GossipTelepathyGroup *subscribe; GHashTable *groups; GHashTable *contacts; + GList *local_pending; DBusGProxy *aliasing_iface; DBusGProxy *avatars_iface; @@ -67,7 +67,6 @@ struct _EmpathyTpContactListPriv { }; typedef enum { - TP_CONTACT_LIST_TYPE_KNOWN, TP_CONTACT_LIST_TYPE_PUBLISH, TP_CONTACT_LIST_TYPE_SUBSCRIBE, TP_CONTACT_LIST_TYPE_UNKNOWN, @@ -103,7 +102,10 @@ static void tp_contact_list_add (EmpathyC static void tp_contact_list_remove (EmpathyContactList *list, GossipContact *contact, const gchar *message); -static GList * tp_contact_list_get_contacts (EmpathyContactList *list); +static GList * tp_contact_list_get_members (EmpathyContactList *list); +static GList * tp_contact_list_get_local_pending (EmpathyContactList *list); +static void tp_contact_list_remove_local_pending (EmpathyTpContactList *list, + GossipContact *contact); static void tp_contact_list_contact_removed_foreach (guint handle, GossipContact *contact, EmpathyTpContactList *list); @@ -120,20 +122,20 @@ static void tp_contact_list_newchannel_cb (DBusGPro gboolean suppress_handle, EmpathyTpContactList *list); static TpContactListType tp_contact_list_get_type (EmpathyTpContactList *list, - TpChan *list_chan); -static void tp_contact_list_contact_added_cb (GossipTelepathyGroup *group, + GossipTelepathyGroup *group); +static void tp_contact_list_added_cb (GossipTelepathyGroup *group, GArray *handles, guint actor_handle, guint reason, const gchar *message, EmpathyTpContactList *list); -static void tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group, +static void tp_contact_list_removed_cb (GossipTelepathyGroup *group, GArray *handles, guint actor_handle, guint reason, const gchar *message, EmpathyTpContactList *list); -static void tp_contact_list_local_pending_cb (GossipTelepathyGroup *group, +static void tp_contact_list_pending_cb (GossipTelepathyGroup *group, GArray *handles, guint actor_handle, guint reason, @@ -173,7 +175,7 @@ static void tp_contact_list_group_members_removed_cb (GossipTe guint reason, const gchar *message, EmpathyTpContactList *list); -static void tp_contact_list_get_contacts_foreach (guint handle, +static void tp_contact_list_get_members_foreach (guint handle, GossipContact *contact, GList **contacts); static void tp_contact_list_get_info (EmpathyTpContactList *list, @@ -248,11 +250,12 @@ empathy_tp_contact_list_class_init (EmpathyTpContactListClass *klass) 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_contacts = tp_contact_list_get_contacts; + 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; } static void @@ -293,15 +296,9 @@ tp_contact_list_finalize (GObject *object) if (priv->tp_conn) { g_object_unref (priv->tp_conn); } - - if (priv->known) { - g_object_unref (priv->known); - } - if (priv->subscribe) { g_object_unref (priv->subscribe); } - if (priv->publish) { g_object_unref (priv->publish); } @@ -312,6 +309,9 @@ tp_contact_list_finalize (GObject *object) 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_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object); } @@ -383,6 +383,7 @@ empathy_tp_contact_list_new (McAccount *account) error ? error->message : "No error given"); g_clear_error (&error); } else { + /* FIXME: this adds the handle to the roster */ priv->user_contact = empathy_tp_contact_list_get_from_handle (list, handle); } @@ -490,11 +491,10 @@ tp_contact_list_remove (EmpathyContactList *list, handle = gossip_contact_get_handle (contact); gossip_telepathy_group_remove_member (priv->subscribe, handle, message); gossip_telepathy_group_remove_member (priv->publish, handle, message); - gossip_telepathy_group_remove_member (priv->known, handle, message); } static GList * -tp_contact_list_get_contacts (EmpathyContactList *list) +tp_contact_list_get_members (EmpathyContactList *list) { EmpathyTpContactListPriv *priv; GList *contacts = NULL; @@ -503,14 +503,25 @@ tp_contact_list_get_contacts (EmpathyContactList *list) priv = GET_PRIV (list); - /* FIXME: we should only return contacts that are in the contact list */ g_hash_table_foreach (priv->contacts, - (GHFunc) tp_contact_list_get_contacts_foreach, + (GHFunc) tp_contact_list_get_members_foreach, &contacts); return contacts; } +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); +} + McAccount * empathy_tp_contact_list_get_account (EmpathyTpContactList *list) { @@ -943,87 +954,77 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy, if (handle_type == TP_HANDLE_TYPE_LIST) { TpContactListType list_type; - list_type = tp_contact_list_get_type (list, new_chan); + group = gossip_telepathy_group_new (new_chan, priv->tp_conn); + + list_type = tp_contact_list_get_type (list, group); if (list_type == TP_CONTACT_LIST_TYPE_UNKNOWN) { - gossip_debug (DEBUG_DOMAIN, "Unknown contact list channel"); + gossip_debug (DEBUG_DOMAIN, + "Type of contact list channel unknown: %s", + gossip_telepathy_group_get_name (group)); + g_object_unref (new_chan); + g_object_unref (group); return; + } else { + gossip_debug (DEBUG_DOMAIN, + "New contact list channel of type: %d", + list_type); } - gossip_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); - group = gossip_telepathy_group_new (new_chan, priv->tp_conn); + members = gossip_telepathy_group_get_members (group); + tp_contact_list_added_cb (group, members, 0, + TP_CHANNEL_GROUP_CHANGE_REASON_NONE, + NULL, list); + g_array_free (members, TRUE); + + if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) { + GList *pendings, *l; - switch (list_type) { - case TP_CONTACT_LIST_TYPE_KNOWN: - if (priv->known) { - g_object_unref (priv->known); - } - priv->known = group; - break; - case TP_CONTACT_LIST_TYPE_PUBLISH: if (priv->publish) { g_object_unref (priv->publish); } priv->publish = group; - break; - case TP_CONTACT_LIST_TYPE_SUBSCRIBE: - if (priv->subscribe) { - g_object_unref (priv->subscribe); - } - priv->subscribe = group; - break; - default: - g_assert_not_reached (); - } - - /* Connect and setup the new contact-list group */ - if (list_type == TP_CONTACT_LIST_TYPE_KNOWN || - list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) { - g_signal_connect (group, "members-added", - G_CALLBACK (tp_contact_list_contact_added_cb), - list); - g_signal_connect (group, "members-removed", - G_CALLBACK (tp_contact_list_contact_removed_cb), - list); - - members = gossip_telepathy_group_get_members (group); - tp_contact_list_contact_added_cb (group, members, 0, - TP_CHANNEL_GROUP_CHANGE_REASON_NONE, - NULL, list); - g_array_free (members, TRUE); - } - if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) { - GList *members, *l; - GArray *pending; + /* Makes no sense to be in remote-pending */ g_signal_connect (group, "local-pending", - G_CALLBACK (tp_contact_list_local_pending_cb), + G_CALLBACK (tp_contact_list_pending_cb), list); - members = gossip_telepathy_group_get_local_pending_members_with_info (group); - if (!members) { - g_object_unref (new_chan); - return; + pendings = gossip_telepathy_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) { + GossipTpGroupInfo *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); + gossip_telepathy_group_info_list_free (pendings); } - - pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); - for (l = members; l; l = l->next) { - GossipTpGroupInfo *info; - - info = l->data; - - g_array_insert_val (pending, 0, info->member); - tp_contact_list_local_pending_cb (group, pending, - info->actor, - info->reason, - info->message, - list); + } + else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) { + if (priv->subscribe) { + g_object_unref (priv->subscribe); } - - gossip_telepathy_group_info_list_free (members); - g_array_free (pending, TRUE); + priv->subscribe = group; + } else { + g_assert_not_reached (); } } else if (handle_type == TP_HANDLE_TYPE_GROUP) { @@ -1065,72 +1066,69 @@ tp_contact_list_newchannel_cb (DBusGProxy *proxy, static TpContactListType tp_contact_list_get_type (EmpathyTpContactList *list, - TpChan *list_chan) + GossipTelepathyGroup *group) { EmpathyTpContactListPriv *priv; - GArray *handles; - gchar **handle_name; TpContactListType list_type; - GError *error = NULL; + const gchar *name; priv = GET_PRIV (list); - handles = g_array_new (FALSE, FALSE, sizeof (guint)); - g_array_append_val (handles, list_chan->handle); - - if (!tp_conn_inspect_handles (DBUS_G_PROXY (priv->tp_conn), - TP_HANDLE_TYPE_LIST, - handles, - &handle_name, - &error)) { - gossip_debug (DEBUG_DOMAIN, - "InspectHandle Error: %s", - error ? error->message : "No error given"); - g_clear_error (&error); - g_array_free (handles, TRUE); - return TP_CONTACT_LIST_TYPE_UNKNOWN; - } - - if (strcmp (*handle_name, "subscribe") == 0) { + name = gossip_telepathy_group_get_name (group); + if (strcmp (name, "subscribe") == 0) { list_type = TP_CONTACT_LIST_TYPE_SUBSCRIBE; - } else if (strcmp (*handle_name, "publish") == 0) { + } else if (strcmp (name, "publish") == 0) { list_type = TP_CONTACT_LIST_TYPE_PUBLISH; - } else if (strcmp (*handle_name, "known") == 0) { - list_type = TP_CONTACT_LIST_TYPE_KNOWN; } else { list_type = TP_CONTACT_LIST_TYPE_UNKNOWN; } - g_strfreev (handle_name); - g_array_free (handles, TRUE); - return list_type; } static void -tp_contact_list_contact_added_cb (GossipTelepathyGroup *group, - GArray *handles, - guint actor_handle, - guint reason, - const gchar *message, - EmpathyTpContactList *list) +tp_contact_list_added_cb (GossipTelepathyGroup *group, + GArray *handles, + guint actor_handle, + guint reason, + const gchar *message, + EmpathyTpContactList *list) { EmpathyTpContactListPriv *priv; GList *added_list, *l; + TpContactListType list_type; priv = GET_PRIV (list); - added_list = empathy_tp_contact_list_get_from_handles (list, handles); + 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) { - GossipContact *contact; + GossipContact *contact; + GossipSubscription subscription; contact = GOSSIP_CONTACT (l->data); + + gossip_debug (DEBUG_DOMAIN, "Contact '%s' added to list type %d", + gossip_contact_get_name (contact), + list_type); + + subscription = gossip_contact_get_subscription (contact); + if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) { + subscription |= GOSSIP_SUBSCRIPTION_FROM; + } + else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) { + subscription |= GOSSIP_SUBSCRIPTION_TO; + } + tp_contact_list_block_contact (list, contact); - gossip_contact_set_subscription (contact, GOSSIP_SUBSCRIPTION_BOTH); + gossip_contact_set_subscription (contact, subscription); tp_contact_list_unblock_contact (list, contact); - g_signal_emit_by_name (list, "contact-added", contact); + if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) { + tp_contact_list_remove_local_pending (list, contact); + g_signal_emit_by_name (list, "contact-added", contact); + } g_object_unref (contact); } @@ -1139,31 +1137,48 @@ tp_contact_list_contact_added_cb (GossipTelepathyGroup *group, } static void -tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group, - GArray *handles, - guint actor_handle, - guint reason, - const gchar *message, - EmpathyTpContactList *list) +tp_contact_list_removed_cb (GossipTelepathyGroup *group, + GArray *handles, + guint actor_handle, + guint reason, + const gchar *message, + EmpathyTpContactList *list) { EmpathyTpContactListPriv *priv; GList *removed_list, *l; + TpContactListType list_type; priv = GET_PRIV (list); - removed_list = empathy_tp_contact_list_get_from_handles (list, handles); + 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) { - GossipContact *contact; - guint handle; + GossipContact *contact; + GossipSubscription subscription; contact = GOSSIP_CONTACT (l->data); - handle = gossip_contact_get_handle (contact); - g_hash_table_remove (priv->contacts, GUINT_TO_POINTER (handle)); + gossip_debug (DEBUG_DOMAIN, "Contact '%s' removed from list type %d", + gossip_contact_get_name (contact), + list_type); + + subscription = gossip_contact_get_subscription (contact); + if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) { + subscription &= !GOSSIP_SUBSCRIPTION_FROM; + } + else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) { + subscription &= !GOSSIP_SUBSCRIPTION_TO; + } - g_signal_emit_by_name (list, "contact-removed", contact); + tp_contact_list_block_contact (list, contact); + gossip_contact_set_subscription (contact, subscription); + tp_contact_list_unblock_contact (list, contact); + if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) { + tp_contact_list_remove_local_pending (list, contact); + g_signal_emit_by_name (list, "contact-removed", contact); + } g_object_unref (contact); } @@ -1171,30 +1186,41 @@ tp_contact_list_contact_removed_cb (GossipTelepathyGroup *group, } static void -tp_contact_list_local_pending_cb (GossipTelepathyGroup *group, - GArray *handles, - guint actor_handle, - guint reason, - const gchar *message, - EmpathyTpContactList *list) +tp_contact_list_pending_cb (GossipTelepathyGroup *group, + GArray *handles, + guint actor_handle, + guint reason, + const gchar *message, + EmpathyTpContactList *list) { EmpathyTpContactListPriv *priv; GList *pending_list, *l; + TpContactListType list_type; priv = GET_PRIV (list); - pending_list = empathy_tp_contact_list_get_from_handles (list, handles); + 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) { GossipContact *contact; contact = GOSSIP_CONTACT (l->data); - /* FIXME: Is that the correct way ? */ - tp_contact_list_block_contact (list, contact); - gossip_contact_set_subscription (contact, GOSSIP_SUBSCRIPTION_FROM); - tp_contact_list_unblock_contact (list, contact); - g_signal_emit_by_name (list, "contact-added", contact); + gossip_debug (DEBUG_DOMAIN, "Contact '%s' pending in list type %d", + gossip_contact_get_name (contact), + list_type); + + if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) { + EmpathyContactListInfo *info; + + info = empathy_contact_list_info_new (contact, message); + priv->local_pending = g_list_prepend (priv->local_pending, + info); + + g_signal_emit_by_name (list, "local-pending", + contact, message); + } g_object_unref (contact); } @@ -1203,6 +1229,30 @@ tp_contact_list_local_pending_cb (GossipTelepathyGroup *group, } static void +tp_contact_list_remove_local_pending (EmpathyTpContactList *list, + GossipContact *contact) +{ + EmpathyTpContactListPriv *priv; + GList *l; + + priv = GET_PRIV (list); + + for (l = priv->local_pending; l; l = l->next) { + EmpathyContactListInfo *info; + + info = l->data; + if (gossip_contact_equal (contact, info->contact)) { + gossip_debug (DEBUG_DOMAIN, "Contact no more local-pending: %s", + gossip_contact_get_name (contact)); + + priv->local_pending = g_list_delete_link (priv->local_pending, l); + empathy_contact_list_info_free (info); + break; + } + } +} + +static void tp_contact_list_groups_updated_cb (GossipContact *contact, GParamSpec *param, EmpathyTpContactList *list) @@ -1531,11 +1581,16 @@ tp_contact_list_group_members_removed_cb (GossipTelepathyGroup *group, } static void -tp_contact_list_get_contacts_foreach (guint handle, +tp_contact_list_get_members_foreach (guint handle, GossipContact *contact, GList **contacts) { - *contacts = g_list_append (*contacts, g_object_ref (contact)); + GossipSubscription subscription; + + subscription = gossip_contact_get_subscription (contact); + if (subscription & GOSSIP_SUBSCRIPTION_TO) { + *contacts = g_list_append (*contacts, g_object_ref (contact)); + } } static void |