diff options
author | Gary Kramlich <grim@reaperworld.com> | 2021-02-03 18:49:38 -0600 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2021-02-03 18:49:38 -0600 |
commit | bc38c82dcc17ca6e074b350f1b6d6ffa46cc9185 (patch) | |
tree | d058c2b469baad3adfb4323697eb0def52dc827f /libpurple/buddy.c | |
parent | 9423b663f3d84c08407e471289c08e03f840953f (diff) | |
download | pidgin-bc38c82dcc17ca6e074b350f1b6d6ffa46cc9185.tar.gz |
Update buddy.c to more closely match our current gobject structure.
Testing Done:
Compiled and ran pidgin locally.
Reviewed at https://reviews.imfreedom.org/r/473/
Diffstat (limited to 'libpurple/buddy.c')
-rw-r--r-- | libpurple/buddy.c | 770 |
1 files changed, 384 insertions, 386 deletions
diff --git a/libpurple/buddy.c b/libpurple/buddy.c index d86e553db0..a3de7de087 100644 --- a/libpurple/buddy.c +++ b/libpurple/buddy.c @@ -1,5 +1,6 @@ /* - * purple + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this @@ -16,32 +17,27 @@ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * + * along with this program; if not, see <https://www.gnu.org/licenses/>. */ + #include "internal.h" #include "purplebuddypresence.h" #include "purpleprotocolclient.h" #include "util.h" -typedef struct _PurpleBuddyPrivate PurpleBuddyPrivate; - -struct _PurpleBuddyPrivate { - char *name; /* The name of the buddy. */ - char *local_alias; /* The user-set alias of the buddy */ - char *server_alias; /* The server-specified alias of the buddy. - (i.e. MSN "Friendly Names") */ - void *proto_data; /* This allows the protocol to associate - whatever data it wants with a buddy. */ - PurpleBuddyIcon *icon; /* The buddy icon. */ - PurpleAccount *account; /* the account this buddy belongs to */ - PurplePresence *presence; /* Presense information of the buddy */ - PurpleMediaCaps media_caps; /* The media capabilities of the buddy. */ - - gboolean is_constructed; /* Indicates if the buddy has finished - being constructed. */ -}; +typedef struct { + gchar *name; + gchar *local_alias; + gchar *server_alias; + + gpointer proto_data; + + PurpleBuddyIcon *icon; + PurpleAccount *account; + PurplePresence *presence; + + PurpleMediaCaps media_caps; +} PurpleBuddyPrivate; enum { PROP_0, @@ -52,37 +48,233 @@ enum { PROP_ACCOUNT, PROP_PRESENCE, PROP_MEDIA_CAPS, - PROP_LAST + N_PROPERTIES }; +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + +G_DEFINE_TYPE_WITH_PRIVATE(PurpleBuddy, purple_buddy, PURPLE_TYPE_BLIST_NODE) + /****************************************************************************** - * Globals + * Helpers *****************************************************************************/ -static GParamSpec *properties[PROP_LAST]; +static void +purple_buddy_set_account(PurpleBuddy *buddy, PurpleAccount *account) { + PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(buddy); -G_DEFINE_TYPE_WITH_PRIVATE(PurpleBuddy, purple_buddy, PURPLE_TYPE_BLIST_NODE) + if(g_set_object(&priv->account, account)) { + g_object_notify_by_pspec(G_OBJECT(buddy), properties[PROP_ACCOUNT]); + } +} /****************************************************************************** - * API + * GObject Implementation *****************************************************************************/ -void -purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) +static void +purple_buddy_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurpleBuddy *buddy = PURPLE_BUDDY(obj); + + switch (param_id) { + case PROP_NAME: + purple_buddy_set_name(buddy, g_value_get_string(value)); + break; + case PROP_LOCAL_ALIAS: + purple_buddy_set_local_alias(buddy, g_value_get_string(value)); + break; + case PROP_SERVER_ALIAS: + purple_buddy_set_server_alias(buddy, g_value_get_string(value)); + break; + case PROP_ICON: + purple_buddy_set_icon(buddy, g_value_get_pointer(value)); + break; + case PROP_ACCOUNT: + purple_buddy_set_account(buddy, + PURPLE_ACCOUNT(g_value_get_object(value))); + break; + case PROP_MEDIA_CAPS: + purple_buddy_set_media_caps(buddy, g_value_get_enum(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_buddy_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleBuddy *buddy = PURPLE_BUDDY(obj); + + switch (param_id) { + case PROP_NAME: + g_value_set_string(value, purple_buddy_get_name(buddy)); + break; + case PROP_LOCAL_ALIAS: + g_value_set_string(value, purple_buddy_get_local_alias(buddy)); + break; + case PROP_SERVER_ALIAS: + g_value_set_string(value, purple_buddy_get_server_alias(buddy)); + break; + case PROP_ICON: + g_value_set_pointer(value, purple_buddy_get_icon(buddy)); + break; + case PROP_ACCOUNT: + g_value_set_object(value, purple_buddy_get_account(buddy)); + break; + case PROP_PRESENCE: + g_value_set_object(value, purple_buddy_get_presence(buddy)); + break; + case PROP_MEDIA_CAPS: + g_value_set_enum(value, purple_buddy_get_media_caps(buddy)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_buddy_init(PurpleBuddy *buddy) { +} + +static void +purple_buddy_constructed(GObject *object) { + PurpleBuddy *buddy = PURPLE_BUDDY(object); + PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(buddy); + + G_OBJECT_CLASS(purple_buddy_parent_class)->constructed(object); + + priv->presence = PURPLE_PRESENCE(purple_buddy_presence_new(buddy)); + purple_presence_set_status_active(priv->presence, "offline", TRUE); + + purple_blist_new_node(purple_blist_get_default(), + PURPLE_BLIST_NODE(buddy)); +} + +static void +purple_buddy_dispose(GObject *object) { + PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(PURPLE_BUDDY(object)); + + g_clear_pointer(&priv->icon, purple_buddy_icon_unref); + g_clear_object(&priv->presence); + + G_OBJECT_CLASS(purple_buddy_parent_class)->dispose(object); +} + +static void +purple_buddy_finalize(GObject *object) { + PurpleBuddy *buddy = PURPLE_BUDDY(object); + PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(buddy); + PurpleProtocol *protocol; + + /* + * Tell the owner protocol that we're about to free the buddy so it + * can free proto_data + */ + protocol = purple_protocols_find(purple_account_get_protocol_id(priv->account)); + if(protocol) { + purple_protocol_client_buddy_free(PURPLE_PROTOCOL_CLIENT(protocol), + buddy); + } + + g_free(priv->name); + g_free(priv->local_alias); + g_free(priv->server_alias); + + G_OBJECT_CLASS(purple_buddy_parent_class)->finalize(object); +} + +static void purple_buddy_class_init(PurpleBuddyClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + obj_class->constructed = purple_buddy_constructed; + obj_class->dispose = purple_buddy_dispose; + obj_class->finalize = purple_buddy_finalize; + obj_class->get_property = purple_buddy_get_property; + obj_class->set_property = purple_buddy_set_property; + + properties[PROP_NAME] = g_param_spec_string( + "name", "Name", + "The name of the buddy.", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + properties[PROP_LOCAL_ALIAS] = g_param_spec_string( + "local-alias", "Local alias", + "Local alias of thee buddy.", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + properties[PROP_SERVER_ALIAS] = g_param_spec_string( + "server-alias", "Server alias", + "Server-side alias of the buddy.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + properties[PROP_ICON] = g_param_spec_pointer( + "icon", "Buddy icon", + "The icon for the buddy.", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + properties[PROP_ACCOUNT] = g_param_spec_object( + "account", "Account", + "The account for the buddy.", + PURPLE_TYPE_ACCOUNT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + properties[PROP_PRESENCE] = g_param_spec_object( + "presence", "Presence", + "The status information for the buddy.", + PURPLE_TYPE_PRESENCE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + properties[PROP_MEDIA_CAPS] = g_param_spec_enum( + "media-caps", "Media capabilities", + "The media capabilities of the buddy.", + PURPLE_MEDIA_TYPE_CAPS, PURPLE_MEDIA_CAPS_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +} + +/****************************************************************************** + * Public API + *****************************************************************************/ +PurpleBuddy * +purple_buddy_new(PurpleAccount *account, const gchar *name, const gchar *alias) { + g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); + g_return_val_if_fail(name != NULL, NULL); + + return g_object_new( + PURPLE_TYPE_BUDDY, + "account", account, + "name", name, + "local-alias", alias, + NULL); +} + +void +purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) { PurpleBuddyPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_BUDDY(buddy)); priv = purple_buddy_get_instance_private(buddy); + if(priv->icon == icon) { + return; + } - if (priv->icon != icon) - { - purple_buddy_icon_unref(priv->icon); - priv->icon = (icon != NULL ? purple_buddy_icon_ref(icon) : NULL); - - g_object_notify_by_pspec(G_OBJECT(buddy), - properties[PROP_ICON]); + g_clear_pointer(&priv->icon, purple_buddy_icon_unref); + if(icon != NULL) { + priv->icon = purple_buddy_icon_ref(icon); } + g_object_notify_by_pspec(G_OBJECT(buddy), properties[PROP_ICON]); + purple_signal_emit(purple_blist_get_handle(), "buddy-icon-changed", buddy); purple_blist_update_node(purple_blist_get_default(), @@ -90,105 +282,104 @@ purple_buddy_set_icon(PurpleBuddy *buddy, PurpleBuddyIcon *icon) } PurpleBuddyIcon * -purple_buddy_get_icon(PurpleBuddy *buddy) -{ +purple_buddy_get_icon(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); + return priv->icon; } PurpleAccount * -purple_buddy_get_account(PurpleBuddy *buddy) -{ +purple_buddy_get_account(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); + return priv->account; } void -purple_buddy_set_name(PurpleBuddy *buddy, const char *name) -{ +purple_buddy_set_name(PurpleBuddy *buddy, const gchar *name) { + PurpleBuddyList *blist = NULL; PurpleBuddyPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_BUDDY(buddy)); priv = purple_buddy_get_instance_private(buddy); - purple_blist_update_buddies_cache(buddy, name); + if(priv->name != NULL) { + purple_blist_update_buddies_cache(buddy, name); + } g_free(priv->name); priv->name = purple_utf8_strip_unprintables(name); g_object_notify_by_pspec(G_OBJECT(buddy), properties[PROP_NAME]); - purple_blist_save_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); - purple_blist_update_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); + blist = purple_blist_get_default(); + purple_blist_save_node(blist, PURPLE_BLIST_NODE(buddy)); + purple_blist_update_node(blist, PURPLE_BLIST_NODE(buddy)); } -const char * -purple_buddy_get_name(PurpleBuddy *buddy) -{ +const gchar * +purple_buddy_get_name(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); + return priv->name; } gpointer -purple_buddy_get_protocol_data(PurpleBuddy *buddy) -{ +purple_buddy_get_protocol_data(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); + return priv->proto_data; } void -purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data) -{ +purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data) { PurpleBuddyPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_BUDDY(buddy)); priv = purple_buddy_get_instance_private(buddy); + priv->proto_data = data; } -const char *purple_buddy_get_alias_only(PurpleBuddy *buddy) -{ +const gchar * +purple_buddy_get_alias_only(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); - if ((priv->local_alias != NULL) && (*priv->local_alias != '\0')) { + if((priv->local_alias != NULL) && (*priv->local_alias != '\0')) { return priv->local_alias; - } else if ((priv->server_alias != NULL) && - (*priv->server_alias != '\0')) { - + } else if((priv->server_alias != NULL) && (*priv->server_alias != '\0')) { return priv->server_alias; } return NULL; } -const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy) -{ +const gchar * +purple_buddy_get_contact_alias(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; - PurpleContact *c; + PurpleContact *c = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); @@ -196,24 +387,27 @@ const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy) /* Search for an alias for the buddy. In order of precedence: */ /* The local buddy alias */ - if (priv->local_alias != NULL) + if(priv->local_alias != NULL) { return priv->local_alias; + } /* The contact alias */ c = purple_buddy_get_contact(buddy); - if ((c != NULL) && (purple_contact_get_alias(c) != NULL)) + if((c != NULL) && (purple_contact_get_alias(c) != NULL)) { return purple_contact_get_alias(c); + } /* The server alias */ - if ((priv->server_alias) && (*priv->server_alias)) + if((priv->server_alias) && (*priv->server_alias != '\0')) { return priv->server_alias; + } /* The buddy's user name (i.e. no alias) */ return priv->name; } -const char *purple_buddy_get_alias(PurpleBuddy *buddy) -{ +const gchar * +purple_buddy_get_alias(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); @@ -222,201 +416,217 @@ const char *purple_buddy_get_alias(PurpleBuddy *buddy) /* Search for an alias for the buddy. In order of precedence: */ /* The buddy alias */ - if (priv->local_alias != NULL) + if(priv->local_alias != NULL) { return priv->local_alias; + } /* The server alias */ - if ((priv->server_alias) && (*priv->server_alias)) + if((priv->server_alias) && (*priv->server_alias != '\0')) { return priv->server_alias; + } /* The buddy's user name (i.e. no alias) */ return priv->name; } void -purple_buddy_set_local_alias(PurpleBuddy *buddy, const char *alias) -{ +purple_buddy_set_local_alias(PurpleBuddy *buddy, const gchar *alias) { + PurpleBuddyList *blist = NULL; PurpleBuddyPrivate *priv = NULL; - PurpleIMConversation *im; - char *old_alias; - char *new_alias = NULL; + PurpleIMConversation *im = NULL; + gchar *old_alias = NULL, *new_alias = NULL; g_return_if_fail(PURPLE_IS_BUDDY(buddy)); priv = purple_buddy_get_instance_private(buddy); - if ((alias != NULL) && (*alias != '\0')) + if((alias != NULL) && (*alias != '\0')) { new_alias = purple_utf8_strip_unprintables(alias); + } - if (purple_strequal(priv->local_alias, new_alias)) { + if(purple_strequal(priv->local_alias, new_alias)) { g_free(new_alias); return; } old_alias = priv->local_alias; - if ((new_alias != NULL) && (*new_alias != '\0')) + if((new_alias != NULL) && (*new_alias != '\0')) { priv->local_alias = new_alias; - else { + } else { priv->local_alias = NULL; - g_free(new_alias); /* could be "\0" */ + g_free(new_alias); } - g_object_notify_by_pspec(G_OBJECT(buddy), - properties[PROP_LOCAL_ALIAS]); + g_object_notify_by_pspec(G_OBJECT(buddy), properties[PROP_LOCAL_ALIAS]); - purple_blist_save_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); - purple_blist_update_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); + blist = purple_blist_get_default(); + purple_blist_save_node(blist, PURPLE_BLIST_NODE(buddy)); + purple_blist_update_node(blist, PURPLE_BLIST_NODE(buddy)); - im = purple_conversations_find_im_with_account(priv->name, - priv->account); - if (im) + im = purple_conversations_find_im_with_account(priv->name, priv->account); + if(PURPLE_IS_IM_CONVERSATION(im)) { purple_conversation_autoset_title(PURPLE_CONVERSATION(im)); + } - purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", - buddy, old_alias); + purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", buddy, + old_alias); g_free(old_alias); } -const char *purple_buddy_get_local_alias(PurpleBuddy *buddy) -{ +const gchar * +purple_buddy_get_local_alias(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); + return priv->local_alias; } void -purple_buddy_set_server_alias(PurpleBuddy *buddy, const char *alias) -{ +purple_buddy_set_server_alias(PurpleBuddy *buddy, const gchar *alias) { + PurpleBuddyList *blist = NULL; PurpleBuddyPrivate *priv = NULL; - PurpleIMConversation *im; - char *old_alias; - char *new_alias = NULL; + PurpleIMConversation *im = NULL; + gchar *old_alias = NULL, *new_alias = NULL; g_return_if_fail(PURPLE_IS_BUDDY(buddy)); priv = purple_buddy_get_instance_private(buddy); - if ((alias != NULL) && (*alias != '\0') && g_utf8_validate(alias, -1, NULL)) + if((alias != NULL) && (*alias != '\0') && g_utf8_validate(alias, -1, NULL)) + { new_alias = purple_utf8_strip_unprintables(alias); + } - if (purple_strequal(priv->server_alias, new_alias)) { + if(purple_strequal(priv->server_alias, new_alias)) { g_free(new_alias); + return; } old_alias = priv->server_alias; - if ((new_alias != NULL) && (*new_alias != '\0')) + if((new_alias != NULL) && (*new_alias != '\0')) { priv->server_alias = new_alias; - else { + } else { priv->server_alias = NULL; - g_free(new_alias); /* could be "\0"; */ + g_free(new_alias); } - g_object_notify_by_pspec(G_OBJECT(buddy), - properties[PROP_SERVER_ALIAS]); + g_object_notify_by_pspec(G_OBJECT(buddy), properties[PROP_SERVER_ALIAS]); - purple_blist_save_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); - purple_blist_update_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); + blist = purple_blist_get_default(); + purple_blist_save_node(blist, PURPLE_BLIST_NODE(buddy)); + purple_blist_update_node(blist, PURPLE_BLIST_NODE(buddy)); - im = purple_conversations_find_im_with_account(priv->name, - priv->account); - if (im) + im = purple_conversations_find_im_with_account(priv->name, priv->account); + if(PURPLE_IS_IM_CONVERSATION(im)) { purple_conversation_autoset_title(PURPLE_CONVERSATION(im)); + } - purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", - buddy, old_alias); + purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased", buddy, + old_alias); g_free(old_alias); } -const char *purple_buddy_get_server_alias(PurpleBuddy *buddy) -{ +const gchar * +purple_buddy_get_server_alias(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); - if ((priv->server_alias) && (*priv->server_alias)) + if((priv->server_alias) && (*priv->server_alias != '\0')) { return priv->server_alias; + } return NULL; } -PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy) -{ +PurpleContact * +purple_buddy_get_contact(PurpleBuddy *buddy) { + PurpleBlistNode *parent = NULL; + g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); - return PURPLE_CONTACT(PURPLE_BLIST_NODE(buddy)->parent); + parent = purple_blist_node_get_parent(PURPLE_BLIST_NODE(buddy)); + if(PURPLE_IS_CONTACT(parent)) { + return PURPLE_CONTACT(parent); + } + + return NULL; } -PurplePresence *purple_buddy_get_presence(PurpleBuddy *buddy) -{ +PurplePresence * +purple_buddy_get_presence(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); priv = purple_buddy_get_instance_private(buddy); + return priv->presence; } void -purple_buddy_update_status(PurpleBuddy *buddy, PurpleStatus *old_status) -{ +purple_buddy_update_status(PurpleBuddy *buddy, PurpleStatus *old_status) { + PurpleBuddyList *blist = NULL; PurpleBuddyPrivate *priv = NULL; - PurpleStatus *status; - PurpleBlistNode *cnode; - PurpleContact *contact; - PurpleCountingNode *contact_counter, *group_counter; + PurpleStatus *status = NULL; + gpointer handle = NULL; + + gboolean old_online = FALSE, new_online = FALSE; g_return_if_fail(PURPLE_IS_BUDDY(buddy)); priv = purple_buddy_get_instance_private(buddy); - status = purple_presence_get_active_status(priv->presence); + blist = purple_blist_get_default(); + handle = purple_blist_get_handle(); purple_debug_info("blistnodetypes", "Updating buddy status for %s (%s)\n", - priv->name, purple_account_get_protocol_name(priv->account)); - - if (purple_status_is_online(status) && - !purple_status_is_online(old_status)) { - - purple_signal_emit(purple_blist_get_handle(), "buddy-signed-on", buddy); - - cnode = PURPLE_BLIST_NODE(buddy)->parent; + priv->name, + purple_account_get_protocol_name(priv->account)); + + old_online = purple_status_is_online(old_status); + new_online = purple_status_is_online(status); + + if(old_online != new_online) { + PurpleBlistNode *cnode = NULL, *gnode = NULL; + PurpleContact *contact = NULL; + PurpleCountingNode *contact_counter = NULL, *group_counter = NULL; + gint delta = 0, limit = 0; + + if(new_online) { + purple_signal_emit(handle, "buddy-signed-on", buddy); + delta = 1; + limit = 1; + } else { + purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "last_seen", + time(NULL)); + + purple_signal_emit(handle, "buddy-signed-off", buddy); + delta = -1; + limit = 0; + } + + cnode = purple_blist_node_get_parent(PURPLE_BLIST_NODE(buddy)); contact = PURPLE_CONTACT(cnode); contact_counter = PURPLE_COUNTING_NODE(contact); - group_counter = PURPLE_COUNTING_NODE(cnode->parent); - - purple_counting_node_change_online_count(contact_counter, +1); - if (purple_counting_node_get_online_count(contact_counter) == 1) - purple_counting_node_change_online_count(group_counter, +1); - } else if (!purple_status_is_online(status) && - purple_status_is_online(old_status)) { + gnode = purple_blist_node_get_parent(cnode); + group_counter = PURPLE_COUNTING_NODE(gnode); - purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "last_seen", time(NULL)); - purple_signal_emit(purple_blist_get_handle(), "buddy-signed-off", buddy); - - cnode = PURPLE_BLIST_NODE(buddy)->parent; - contact = PURPLE_CONTACT(cnode); - contact_counter = PURPLE_COUNTING_NODE(contact); - group_counter = PURPLE_COUNTING_NODE(cnode->parent); - - purple_counting_node_change_online_count(contact_counter, -1); - if (purple_counting_node_get_online_count(contact_counter) == 0) - purple_counting_node_change_online_count(group_counter, -1); + purple_counting_node_change_online_count(contact_counter, delta); + if(purple_counting_node_get_online_count(contact_counter) == limit) { + purple_counting_node_change_online_count(group_counter, delta); + } } else { - purple_signal_emit(purple_blist_get_handle(), - "buddy-status-changed", buddy, old_status, - status); + purple_signal_emit(handle, "buddy-status-changed", buddy, old_status, + status); } /* @@ -431,22 +641,22 @@ purple_buddy_update_status(PurpleBuddy *buddy, PurpleStatus *old_status) */ purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy)); - purple_blist_update_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); + purple_blist_update_node(blist, PURPLE_BLIST_NODE(buddy)); } -PurpleMediaCaps purple_buddy_get_media_caps(PurpleBuddy *buddy) -{ +PurpleMediaCaps +purple_buddy_get_media_caps(PurpleBuddy *buddy) { PurpleBuddyPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), 0); priv = purple_buddy_get_instance_private(buddy); + return priv->media_caps; } -void purple_buddy_set_media_caps(PurpleBuddy *buddy, PurpleMediaCaps media_caps) -{ +void +purple_buddy_set_media_caps(PurpleBuddy *buddy, PurpleMediaCaps media_caps) { PurpleBuddyPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_BUDDY(buddy)); @@ -454,236 +664,24 @@ void purple_buddy_set_media_caps(PurpleBuddy *buddy, PurpleMediaCaps media_caps) priv = purple_buddy_get_instance_private(buddy); priv->media_caps = media_caps; - g_object_notify_by_pspec(G_OBJECT(buddy), - properties[PROP_MEDIA_CAPS]); + g_object_notify_by_pspec(G_OBJECT(buddy), properties[PROP_MEDIA_CAPS]); } -PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy) -{ +PurpleGroup * +purple_buddy_get_group(PurpleBuddy *buddy) { + PurpleBlistNode *contact = NULL, *group = NULL; + g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); - if (PURPLE_BLIST_NODE(buddy)->parent == NULL) + contact = purple_blist_node_get_parent(PURPLE_BLIST_NODE(buddy)); + if(!PURPLE_IS_CONTACT(contact)) { return purple_blist_get_default_group(); - - return PURPLE_GROUP(PURPLE_BLIST_NODE(buddy)->parent->parent); -} - -/****************************************************************************** - * GObject Stuff - *****************************************************************************/ -static void -purple_buddy_set_property(GObject *obj, guint param_id, const GValue *value, - GParamSpec *pspec) -{ - PurpleBuddy *buddy = PURPLE_BUDDY(obj); - PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(buddy); - - switch (param_id) { - case PROP_NAME: - if (priv->is_constructed) - purple_buddy_set_name(buddy, g_value_get_string(value)); - else - priv->name = - purple_utf8_strip_unprintables(g_value_get_string(value)); - break; - case PROP_LOCAL_ALIAS: - if (priv->is_constructed) - purple_buddy_set_local_alias(buddy, g_value_get_string(value)); - else - priv->local_alias = - purple_utf8_strip_unprintables(g_value_get_string(value)); - break; - case PROP_SERVER_ALIAS: - purple_buddy_set_server_alias(buddy, g_value_get_string(value)); - break; - case PROP_ICON: - purple_buddy_set_icon(buddy, g_value_get_pointer(value)); - break; - case PROP_ACCOUNT: - priv->account = g_value_get_object(value); - break; - case PROP_MEDIA_CAPS: - purple_buddy_set_media_caps(buddy, g_value_get_enum(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_buddy_get_property(GObject *obj, guint param_id, GValue *value, - GParamSpec *pspec) -{ - PurpleBuddy *buddy = PURPLE_BUDDY(obj); - - switch (param_id) { - case PROP_NAME: - g_value_set_string(value, purple_buddy_get_name(buddy)); - break; - case PROP_LOCAL_ALIAS: - g_value_set_string(value, purple_buddy_get_local_alias(buddy)); - break; - case PROP_SERVER_ALIAS: - g_value_set_string(value, purple_buddy_get_server_alias(buddy)); - break; - case PROP_ICON: - g_value_set_pointer(value, purple_buddy_get_icon(buddy)); - break; - case PROP_ACCOUNT: - g_value_set_object(value, purple_buddy_get_account(buddy)); - break; - case PROP_PRESENCE: - g_value_set_object(value, purple_buddy_get_presence(buddy)); - break; - case PROP_MEDIA_CAPS: - g_value_set_enum(value, purple_buddy_get_media_caps(buddy)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; } -} - -static void -purple_buddy_init(PurpleBuddy *buddy) -{ -} - -static void -purple_buddy_constructed(GObject *object) { - PurpleBuddy *buddy = PURPLE_BUDDY(object); - PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(buddy); - - G_OBJECT_CLASS(purple_buddy_parent_class)->constructed(object); - - priv->presence = PURPLE_PRESENCE(purple_buddy_presence_new(buddy)); - purple_presence_set_status_active(priv->presence, "offline", TRUE); - purple_blist_new_node(purple_blist_get_default(), - PURPLE_BLIST_NODE(buddy)); - - priv->is_constructed = TRUE; -} - -static void -purple_buddy_dispose(GObject *object) { - PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(PURPLE_BUDDY(object)); - - if (priv->icon) { - purple_buddy_icon_unref(priv->icon); - priv->icon = NULL; + group = purple_blist_node_get_parent(contact); + if(PURPLE_IS_GROUP(group)) { + return PURPLE_GROUP(group); } - if (priv->presence) { - g_object_unref(priv->presence); - priv->presence = NULL; - } - - G_OBJECT_CLASS(purple_buddy_parent_class)->dispose(object); -} - -static void -purple_buddy_finalize(GObject *object) { - PurpleBuddy *buddy = PURPLE_BUDDY(object); - PurpleBuddyPrivate *priv = purple_buddy_get_instance_private(buddy); - PurpleProtocol *protocol; - - /* - * Tell the owner protocol that we're about to free the buddy so it - * can free proto_data - */ - protocol = purple_protocols_find(purple_account_get_protocol_id(priv->account)); - if(protocol) { - purple_protocol_client_buddy_free(PURPLE_PROTOCOL_CLIENT(protocol), - buddy); - } - - g_free(priv->name); - g_free(priv->local_alias); - g_free(priv->server_alias); - - G_OBJECT_CLASS(purple_buddy_parent_class)->finalize(object); -} - -static void purple_buddy_class_init(PurpleBuddyClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - - obj_class->dispose = purple_buddy_dispose; - obj_class->finalize = purple_buddy_finalize; - - /* Setup properties */ - obj_class->get_property = purple_buddy_get_property; - obj_class->set_property = purple_buddy_set_property; - obj_class->constructed = purple_buddy_constructed; - - properties[PROP_NAME] = g_param_spec_string( - "name", - "Name", - "The name of the buddy.", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS - ); - - properties[PROP_LOCAL_ALIAS] = g_param_spec_string( - "local-alias", - "Local alias", - "Local alias of thee buddy.", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS - ); - - properties[PROP_SERVER_ALIAS] = g_param_spec_string( - "server-alias", - "Server alias", - "Server-side alias of the buddy.", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS - ); - - properties[PROP_ICON] = g_param_spec_pointer( - "icon", - "Buddy icon", - "The icon for the buddy.", - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS - ); - - properties[PROP_ACCOUNT] = g_param_spec_object( - "account", - "Account", - "The account for the buddy.", - PURPLE_TYPE_ACCOUNT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS - ); - - properties[PROP_PRESENCE] = g_param_spec_object( - "presence", - "Presence", - "The status information for the buddy.", - PURPLE_TYPE_PRESENCE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS - ); - - properties[PROP_MEDIA_CAPS] = g_param_spec_enum( - "media-caps", - "Media capabilities", - "The media capabilities of the buddy.", - PURPLE_MEDIA_TYPE_CAPS, PURPLE_MEDIA_CAPS_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS - ); - - g_object_class_install_properties(obj_class, PROP_LAST, properties); -} - -PurpleBuddy * -purple_buddy_new(PurpleAccount *account, const char *name, const char *alias) -{ - g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); - g_return_val_if_fail(name != NULL, NULL); - - return g_object_new(PURPLE_TYPE_BUDDY, - "account", account, - "name", name, - "local-alias", alias, - NULL); + return NULL; } |