gossip r2770 - in trunk: . libgossip src
- From: mr svn gnome org
- To: svn-commits-list gnome org
- Subject: gossip r2770 - in trunk: . libgossip src
- Date: Fri, 14 Mar 2008 17:26:18 +0000 (GMT)
Author: mr
Date: Fri Mar 14 17:26:18 2008
New Revision: 2770
URL: http://svn.gnome.org/viewvc/gossip?rev=2770&view=rev
Log:
Don't show offline people on the roster if they have TO subscription,
throttle updates to contacts and don't set groups twice leading to
speed loss
Modified:
trunk/ChangeLog
trunk/libgossip/gossip-contact.c
trunk/libgossip/gossip-contact.h
trunk/libgossip/gossip-jabber.c
trunk/src/gossip-contact-list.c
Modified: trunk/libgossip/gossip-contact.c
==============================================================================
--- trunk/libgossip/gossip-contact.c (original)
+++ trunk/libgossip/gossip-contact.c Fri Mar 14 17:26:18 2008
@@ -61,8 +61,6 @@
guint param_id,
const GValue *value,
GParamSpec *pspec);
-static void contact_set_type (GossipContact *contact,
- GossipContactType type);
static void contact_set_presences (GossipContact *contact,
GList *presences);
@@ -298,8 +296,8 @@
switch (param_id) {
case PROP_TYPE:
- contact_set_type (GOSSIP_CONTACT (object),
- g_value_get_int (value));
+ gossip_contact_set_type (GOSSIP_CONTACT (object),
+ g_value_get_int (value));
break;
case PROP_NAME:
gossip_contact_set_name (GOSSIP_CONTACT (object),
@@ -569,9 +567,9 @@
return priv->subscription;
}
-static void
-contact_set_type (GossipContact *contact,
- GossipContactType type)
+void
+gossip_contact_set_type (GossipContact *contact,
+ GossipContactType type)
{
GossipContactPriv *priv;
Modified: trunk/libgossip/gossip-contact.h
==============================================================================
--- trunk/libgossip/gossip-contact.h (original)
+++ trunk/libgossip/gossip-contact.h Fri Mar 14 17:26:18 2008
@@ -91,6 +91,8 @@
GList * gossip_contact_get_presence_list (GossipContact *contact);
GList * gossip_contact_get_groups (GossipContact *contact);
GossipSubscription gossip_contact_get_subscription (GossipContact *contact);
+void gossip_contact_set_type (GossipContact *contact,
+ GossipContactType type);
void gossip_contact_set_id (GossipContact *contact,
const gchar *id);
void gossip_contact_set_name (GossipContact *contact,
Modified: trunk/libgossip/gossip-jabber.c
==============================================================================
--- trunk/libgossip/gossip-jabber.c (original)
+++ trunk/libgossip/gossip-jabber.c Fri Mar 14 17:26:18 2008
@@ -2640,12 +2640,9 @@
const gchar *jid_str;
const gchar *subscription;
gboolean added_item = FALSE;
- gboolean removed_item = FALSE;
- LmMessageNode *subnode;
LmMessageNode *child;
GList *groups;
const gchar *name;
- GList *new_groups;
if (strcmp (node->name, "item") != 0) {
continue;
@@ -2663,30 +2660,9 @@
type = gossip_contact_get_type (contact);
- /* Groups */
- groups = NULL;
- for (subnode = node->children; subnode; subnode = subnode->next) {
- if (strcmp (subnode->name, "group") != 0) {
- continue;
- }
-
- if (subnode->value) {
- /* FIXME: unescape the markup here: #342927 */
- groups = g_list_append (groups, subnode->value);
- }
- }
-
- /* FIXME: why is this here if we set the groups below */
- if (groups) {
- gossip_contact_set_groups (contact, groups);
- }
-
- g_list_free (groups);
-
/* Subscription */
subscription = lm_message_node_get_attribute (node, "subscription");
if (contact && subscription) {
- GossipContactType contact_type;
GossipSubscription subscription_type;
if (strcmp (subscription, "remove") == 0) {
@@ -2717,24 +2693,10 @@
* subscription requests for people already on
* the roster with "to" or "from" conditions.
*/
- if (subscription_type != GOSSIP_SUBSCRIPTION_NONE) {
- g_object_get (contact, "type", &contact_type, NULL);
- if (contact_type != GOSSIP_CONTACT_TYPE_CONTACTLIST) {
- added_item = TRUE;
- }
-
- contact_type = GOSSIP_CONTACT_TYPE_CONTACTLIST;
- g_object_set (contact, "type", contact_type, NULL);
- } else {
- g_object_get (contact, "type", &contact_type, NULL);
- if (contact_type == GOSSIP_CONTACT_TYPE_CONTACTLIST) {
- removed_item = TRUE;
- }
-
- contact_type = GOSSIP_CONTACT_TYPE_TEMPORARY;
- g_object_set (contact, "type", contact_type, NULL);
- }
+
+ added_item = TRUE;
+ gossip_contact_set_type (contact, GOSSIP_CONTACT_TYPE_CONTACTLIST);
gossip_contact_set_subscription (contact, subscription_type);
}
@@ -2743,27 +2705,23 @@
gossip_contact_set_name (contact, name);
}
- new_groups = NULL;
+ groups = NULL;
for (child = node->children; child; child = child->next) {
+ /* FIXME: unescape the markup here: #342927 */
if (strcmp (child->name, "group") == 0 && child->value) {
- new_groups = g_list_append (new_groups, child->value);
+ groups = g_list_prepend (groups, child->value);
}
}
- if (new_groups) {
- gossip_contact_set_groups (contact, new_groups);
+ if (groups) {
+ groups = g_list_reverse (groups);
+ gossip_contact_set_groups (contact, groups);
+ g_list_free (groups);
}
- g_list_free (new_groups);
-
if (added_item) {
g_signal_emit_by_name (jabber, "contact-added", contact);
}
-
- if (removed_item) {
- g_signal_emit_by_name (jabber, "contact-removed", contact);
- g_hash_table_remove (priv->contacts, gossip_contact_get_id (contact));
- }
}
}
Modified: trunk/src/gossip-contact-list.c
==============================================================================
--- trunk/src/gossip-contact-list.c (original)
+++ trunk/src/gossip-contact-list.c Fri Mar 14 17:26:18 2008
@@ -63,6 +63,9 @@
/* Time after connecting which we wait before active users are enabled */
#define ACTIVE_USER_WAIT_TO_ENABLE_TIME 5000
+/* Time to wait before updating a user (i.e. to throttle updates) */
+#define UPDATE_USER_DELAY_TIME 500
+
#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CONTACT_LIST, GossipContactListPriv))
struct _GossipContactListPriv {
@@ -71,6 +74,7 @@
GHashTable *groups;
GHashTable *flash_table;
GHashTable *active_contacts;
+ GHashTable *update_contacts;
GHashTable *set_group_state;
GtkUIManager *ui;
@@ -184,7 +188,7 @@
GossipContact *contact);
static void contact_list_remove_contact (GossipContactList *list,
GossipContact *contact,
- gboolean remove_flash);
+ gboolean shallow_remove);
static void contact_list_create_model (GossipContactList *list);
static void contact_list_setup_view (GossipContactList *list);
static void contact_list_drag_data_received (GtkWidget *widget,
@@ -550,6 +554,12 @@
(GDestroyNotify)
contact_list_contact_set_active_destroy_cb);
+ priv->update_contacts = g_hash_table_new_full (gossip_contact_hash,
+ gossip_contact_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify)
+ contact_list_contact_set_active_destroy_cb);
+
priv->set_group_state = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
@@ -649,6 +659,7 @@
g_hash_table_destroy (priv->flash_table);
/* FIXME: Shouldn't we free the groups hash table? */
g_hash_table_destroy (priv->active_contacts);
+ g_hash_table_destroy (priv->update_contacts);
g_hash_table_destroy (priv->set_group_state);
g_free (priv->filter_text);
@@ -912,26 +923,6 @@
GossipContact *contact,
GossipContactList *list)
{
- gossip_debug (DEBUG_DOMAIN,
- "Contact:'%s' added",
- gossip_contact_get_name (contact));
-
- g_signal_connect (contact, "notify::groups",
- G_CALLBACK (contact_list_contact_groups_updated_cb),
- list);
- g_signal_connect (contact, "notify::presences",
- G_CALLBACK (contact_list_contact_updated_cb),
- list);
- g_signal_connect (contact, "notify::name",
- G_CALLBACK (contact_list_contact_updated_cb),
- list);
- g_signal_connect (contact, "notify::avatar",
- G_CALLBACK (contact_list_contact_updated_cb),
- list);
- g_signal_connect (contact, "notify::type",
- G_CALLBACK (contact_list_contact_updated_cb),
- list);
-
contact_list_add_contact (list, contact);
}
@@ -962,39 +953,72 @@
* would have to check the groups already set up for each
* contact and then see what has been updated.
*/
- contact_list_remove_contact (list, contact, FALSE);
+ contact_list_remove_contact (list, contact, TRUE);
contact_list_add_contact (list, contact);
}
-static void
-contact_list_contact_updated_cb (GossipContact *contact,
- GParamSpec *param,
- GossipContactList *list)
+static gboolean
+contact_list_contact_updated_delay_cb (ActiveContactData *data)
{
+ GossipContactList *list;
+ GossipContactListPriv *priv;
+ GossipContact *contact;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ list = data->list;
+ contact = data->contact;
+
+ priv = GET_PRIV (list);
+
+ if (g_hash_table_lookup (priv->update_contacts, contact)) {
+ g_hash_table_remove (priv->update_contacts, contact);
+ }
+
gossip_debug (DEBUG_DOMAIN,
"Contact:'%s' updated, checking roster is in sync...",
gossip_contact_get_name (contact));
contact_list_contact_update (list, contact);
+
+ return FALSE;
}
static void
-contact_list_contact_removed_cb (GossipSession *session,
- GossipContact *contact,
+contact_list_contact_updated_cb (GossipContact *contact,
+ GParamSpec *param,
GossipContactList *list)
{
- gossip_debug (DEBUG_DOMAIN,
- "Contact:'%s' removed",
- gossip_contact_get_name (contact));
+ /* Since we may get many updates at one time, we throttle
+ * these to make sure we don't over update the roster for the
+ * same contact.
+ */
- g_signal_handlers_disconnect_by_func (contact,
- G_CALLBACK (contact_list_contact_groups_updated_cb),
- list);
- g_signal_handlers_disconnect_by_func (contact,
- G_CALLBACK (contact_list_contact_updated_cb),
- list);
+ ActiveContactData *data;
+ GossipContactListPriv *priv;
+
+ priv = GET_PRIV (list);
+
+ if (g_hash_table_lookup (priv->update_contacts, contact)) {
+ g_hash_table_remove (priv->update_contacts, contact);
+ }
- contact_list_remove_contact (list, contact, TRUE);
+ data = g_new0 (ActiveContactData, 1);
+ data->list = g_object_ref (list);
+ data->contact = g_object_ref (contact);
+ data->timeout_id = g_timeout_add (UPDATE_USER_DELAY_TIME,
+ (GSourceFunc) contact_list_contact_updated_delay_cb,
+ data);
+
+ g_hash_table_insert (priv->update_contacts, g_object_ref (contact), data);
+}
+
+static void
+contact_list_contact_removed_cb (GossipSession *session,
+ GossipContact *contact,
+ GossipContactList *list)
+{
+ contact_list_remove_contact (list, contact, FALSE);
}
static void
@@ -1435,9 +1459,47 @@
GtkTreeIter iter, iter_group, iter_separator;
GtkTreeModel *model;
GList *l, *groups;
+ GList *iters;
+
+ /* Note: The shallow_add flag is here so we know if we
+ * should connect the signal handlers for GossipContact.
+ * We also use this function with _remove_contact() when we
+ * update contacts with complex group changes, since it is
+ * easier.
+ */
priv = GET_PRIV (list);
+ gossip_debug (DEBUG_DOMAIN,
+ "Contact:'%s' adding...",
+ gossip_contact_get_name (contact));
+
+ iters = contact_list_find_contact (list, contact);
+ if (iters) {
+ gossip_debug (DEBUG_DOMAIN, " - Already exists, not adding");
+
+ g_list_foreach (iters, (GFunc) gtk_tree_iter_free, NULL);
+ g_list_free (iters);
+
+ return;
+ }
+
+ /* Add signals */
+ gossip_debug (DEBUG_DOMAIN, " - Setting signal handlers");
+
+ g_signal_connect (contact, "notify::groups",
+ G_CALLBACK (contact_list_contact_groups_updated_cb),
+ list);
+ g_signal_connect (contact, "notify::presences",
+ G_CALLBACK (contact_list_contact_updated_cb),
+ list);
+ g_signal_connect (contact, "notify::name",
+ G_CALLBACK (contact_list_contact_updated_cb),
+ list);
+ g_signal_connect (contact, "notify::avatar",
+ G_CALLBACK (contact_list_contact_updated_cb),
+ list);
+
model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
/* If no groups just add it at the top level. */
@@ -1574,12 +1636,23 @@
static void
contact_list_remove_contact (GossipContactList *list,
GossipContact *contact,
- gboolean remove_flash)
+ gboolean shallow_remove)
{
GossipContactListPriv *priv;
GtkTreeModel *model;
GList *iters, *l;
+ /* Note: The shallow_remove flag is here so we know if we
+ * should disconnect the signal handlers for GossipContact.
+ * We also use this function with _add_contact() when we
+ * update contacts with complex group changes, since it is
+ * easier.
+ */
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Contact:'%s' removing...",
+ gossip_contact_get_name (contact));
+
priv = GET_PRIV (list);
iters = contact_list_find_contact (list, contact);
@@ -1606,6 +1679,8 @@
if (children <= 2) {
gtk_tree_store_remove (priv->store, &parent_iter);
} else {
+ gtk_tree_store_remove (priv->store, l->data);
+
/* To make sure the parent is hidden
* correctly if we now have no more
* online contacts, we emit the
@@ -1628,11 +1703,21 @@
g_list_free (iters);
gossip_debug (DEBUG_DOMAIN,
- "Now %d top level nodes remaining in the tree\n",
+ " - Now %d top level nodes remaining in the tree\n",
gtk_tree_model_iter_n_children (model, NULL));
}
- if (remove_flash) {
+ gossip_debug (DEBUG_DOMAIN, " - Unsetting signal handlers");
+
+ g_signal_handlers_disconnect_by_func (contact,
+ contact_list_contact_groups_updated_cb,
+ list);
+ g_signal_handlers_disconnect_by_func (contact,
+ contact_list_contact_updated_cb,
+ list);
+
+ if (!shallow_remove) {
+ gossip_debug (DEBUG_DOMAIN, " - Removing flash information");
g_hash_table_remove (priv->flash_table, contact);
}
}
@@ -2657,7 +2742,8 @@
has_activity = g_hash_table_lookup (priv->active_contacts, contact) != NULL;
subscription = gossip_contact_get_subscription (contact);
- has_no_subscription = subscription != GOSSIP_SUBSCRIPTION_BOTH;
+ has_no_subscription = (subscription == GOSSIP_SUBSCRIPTION_NONE ||
+ subscription == GOSSIP_SUBSCRIPTION_FROM);
/* If we have a reason to remain visible in the roster, then
* set visible TRUE (i.e we have events pending, we are
@@ -3271,7 +3357,7 @@
iters = contact_list_find_contact (list, contact);
if (!iters) {
gossip_debug (DEBUG_DOMAIN,
- "Contact:'%s' not found in treeview, adding...",
+ "Contact:'%s' not found in treeview",
gossip_contact_get_name (contact));
return;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]