# HG changeset patch # User Etan Reisner # Date 1210907907 0 # Node ID bc58e2d9f0f5419741764af428a71a57aeb390c7 # Parent b17d6defb9224052bdecb111e08b1bba1b1cd0b1# Parent 0ca259d5f928b0fef1a54869387324e355a6df84 merge of '979e05e68e2d32cdffe65f350b71fd6e6ae89af9' and 'df0ddcef268608879c9e3ecd095cb74903d279e8' diff -r b17d6defb922 -r bc58e2d9f0f5 ChangeLog.API --- a/ChangeLog.API Fri May 16 03:18:20 2008 +0000 +++ b/ChangeLog.API Fri May 16 03:18:27 2008 +0000 @@ -19,10 +19,23 @@ * GTK+ Custom Smiley API. version 2.5.0: - libpurple: - Added: - * purple_serv_got_join_chat_failed - * chat-join-failed signal (see conversation-signals.dox) + libpurple: + Added: + * purple_serv_got_join_chat_failed + * chat-join-failed signal (see conversation-signals.dox) + * purple_blist_update_node_icon + * purple_buddy_icons_node_has_custom_icon + * purple_buddy_icons_node_find_custom_icon + * purple_buddy_icons_node_set_custom_icon + * purple_buddy_icons_node_set_custom_icon_from_file + + Deprecated: + * purple_blist_update_buddy_icon + * purple_buddy_icons_has_custom_icon + * purple_buddy_icons_find_custom_icon + * purple_buddy_icons_set_custom_icon + * pidgin_set_custom_buddy_icon + perl: Added: * Purple::Prefs::get_children_names. diff -r b17d6defb922 -r bc58e2d9f0f5 libpurple/blist.c --- a/libpurple/blist.c Fri May 16 03:18:20 2008 +0000 +++ b/libpurple/blist.c Fri May 16 03:18:27 2008 +0000 @@ -824,16 +824,25 @@ ops->update(purplebuddylist, (PurpleBlistNode *)buddy); } -void purple_blist_update_buddy_icon(PurpleBuddy *buddy) +void +purple_blist_update_node_icon(PurpleBlistNode *node) { PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - g_return_if_fail(buddy != NULL); + g_return_if_fail(node != NULL); if (ops && ops->update) - ops->update(purplebuddylist, (PurpleBlistNode *)buddy); + ops->update(purplebuddylist, node); } +#ifndef PURPLE_DISABLE_DEPRECATED +void +purple_blist_update_buddy_icon(PurpleBuddy *buddy) +{ + purple_blist_update_node_icon((PurpleBlistNode *)buddy); +} +#endif + /* * TODO: Maybe remove the call to this from server.c and call it * from oscar.c and toc.c instead? @@ -1197,7 +1206,7 @@ purple_signal_emit(purple_blist_get_handle(), "buddy-icon-changed", buddy); - purple_blist_update_buddy_icon(buddy); + purple_blist_update_node_icon((PurpleBlistNode*)buddy); } PurpleAccount * diff -r b17d6defb922 -r bc58e2d9f0f5 libpurple/blist.h --- a/libpurple/blist.h Fri May 16 03:18:20 2008 +0000 +++ b/libpurple/blist.h Fri May 16 03:18:27 2008 +0000 @@ -317,11 +317,22 @@ void purple_blist_update_buddy_status(PurpleBuddy *buddy, PurpleStatus *old_status); /** + * Updates a node's custom icon. + * + * @param node The PurpleBlistNode whose custom icon has changed. + * @since 2.5.0 + */ +void purple_blist_update_node_icon(PurpleBlistNode *node); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** * Updates a buddy's icon. * * @param buddy The buddy whose buddy icon has changed + * @deprecated Use purple_blist_update_node_icon() instead. */ void purple_blist_update_buddy_icon(PurpleBuddy *buddy); +#endif /** * Renames a buddy in the buddy list. diff -r b17d6defb922 -r bc58e2d9f0f5 libpurple/buddyicon.c --- a/libpurple/buddyicon.c Fri May 16 03:18:20 2008 +0000 +++ b/libpurple/buddyicon.c Fri May 16 03:18:27 2008 +0000 @@ -92,8 +92,10 @@ */ static GHashTable *icon_file_cache = NULL; -/* This one is used for both custom buddy icons - * on PurpleContacts and account icons. */ +/** + * This hash table is used for both custom buddy icons on PurpleBlistNodes and + * account icons. + */ static GHashTable *pointer_icon_cache = NULL; static char *cache_dir = NULL; @@ -684,14 +686,6 @@ return (icon ? purple_buddy_icon_ref(icon) : NULL); } -gboolean -purple_buddy_icons_has_custom_icon(PurpleContact *contact) -{ - g_return_val_if_fail(contact != NULL, FALSE); - - return (purple_blist_node_get_string((PurpleBlistNode*)contact, "custom_buddy_icon") != NULL); -} - PurpleStoredImage * purple_buddy_icons_find_account_icon(PurpleAccount *account) { @@ -807,24 +801,32 @@ return ret; } -PurpleStoredImage * -purple_buddy_icons_find_custom_icon(PurpleContact *contact) +gboolean +purple_buddy_icons_node_has_custom_icon(PurpleBlistNode *node) { - PurpleStoredImage *img; - const char *custom_icon_file; - const char *dirname; + g_return_val_if_fail(node != NULL, FALSE); + + return (purple_blist_node_get_string(node, "custom_buddy_icon") != NULL); +} + +PurpleStoredImage * +purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node) +{ char *path; + size_t len; guchar *data; - size_t len; + PurpleStoredImage *img; + const char *custom_icon_file, *dirname; - g_return_val_if_fail(contact != NULL, NULL); + g_return_val_if_fail(node != NULL, NULL); - if ((img = g_hash_table_lookup(pointer_icon_cache, contact))) + if ((img = g_hash_table_lookup(pointer_icon_cache, node))) { return purple_imgstore_ref(img); } - custom_icon_file = purple_blist_node_get_string((PurpleBlistNode*)contact, "custom_buddy_icon"); + custom_icon_file = purple_blist_node_get_string(node, + "custom_buddy_icon"); if (custom_icon_file == NULL) return NULL; @@ -836,7 +838,7 @@ { g_free(path); img = purple_buddy_icon_data_new(data, len, custom_icon_file); - g_hash_table_insert(pointer_icon_cache, contact, img); + g_hash_table_insert(pointer_icon_cache, node, img); return img; } g_free(path); @@ -845,66 +847,79 @@ } PurpleStoredImage * -purple_buddy_icons_set_custom_icon(PurpleContact *contact, - guchar *icon_data, size_t icon_len) +purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node, + guchar *icon_data, size_t icon_len) { + char *old_icon; PurpleStoredImage *old_img; PurpleStoredImage *img = NULL; - char *old_icon; - PurpleBlistNode *child; + + g_return_val_if_fail(node != NULL, NULL); - old_img = g_hash_table_lookup(pointer_icon_cache, contact); + if (!PURPLE_BLIST_NODE_IS_CONTACT(node) && + !PURPLE_BLIST_NODE_IS_CHAT(node) && + !PURPLE_BLIST_NODE_IS_GROUP(node)) { + return NULL; + } - if (icon_data != NULL && icon_len > 0) - { + old_img = g_hash_table_lookup(pointer_icon_cache, node); + + if (icon_data != NULL && icon_len > 0) { img = purple_buddy_icon_data_new(icon_data, icon_len, NULL); } - old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)contact, + old_icon = g_strdup(purple_blist_node_get_string(node, "custom_buddy_icon")); - if (img && purple_buddy_icons_is_caching()) - { + if (img && purple_buddy_icons_is_caching()) { const char *filename = purple_imgstore_get_filename(img); - purple_blist_node_set_string((PurpleBlistNode *)contact, - "custom_buddy_icon", + purple_blist_node_set_string(node, "custom_buddy_icon", filename); ref_filename(filename); - } - else - { - purple_blist_node_remove_setting((PurpleBlistNode *)contact, - "custom_buddy_icon"); + } else { + purple_blist_node_remove_setting(node, "custom_buddy_icon"); } unref_filename(old_icon); if (img) - g_hash_table_insert(pointer_icon_cache, contact, img); + g_hash_table_insert(pointer_icon_cache, node, img); else - g_hash_table_remove(pointer_icon_cache, contact); + g_hash_table_remove(pointer_icon_cache, node); - for (child = contact->node.child ; child ; child = child->next) - { - PurpleBuddy *buddy; - PurpleConversation *conv; + if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { + PurpleBlistNode *child; + for (child = node->child ; child ; child = child->next) + { + PurpleBuddy *buddy; + PurpleConversation *conv; + + if (!PURPLE_BLIST_NODE_IS_BUDDY(child)) + continue; + + buddy = (PurpleBuddy *)child; - if (!PURPLE_BLIST_NODE_IS_BUDDY(child)) - continue; - - buddy = (PurpleBuddy *)child; + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); + if (conv) + purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - purple_buddy_get_name(buddy), - purple_buddy_get_account(buddy)); - if (conv) + /* Is this call necessary anymore? Can the buddies + * themselves need updating when the custom buddy + * icon changes? */ + purple_blist_update_node_icon((PurpleBlistNode*)buddy); + } + } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { + PurpleConversation *conv = NULL; + + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, purple_chat_get_name((PurpleChat*)node), purple_chat_get_account((PurpleChat*)node)); + if (conv) { purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON); - - purple_blist_update_buddy_icon(buddy); + } } - if (old_img) + purple_blist_update_node_icon(node); + + if (old_img) { purple_imgstore_unref(old_img); - else if (old_icon) - { + } else if (old_icon) { /* The old icon may not have been loaded into memory. In that * case, we'll need to uncache the filename. The filenames * are ref-counted, so this is safe. */ @@ -915,6 +930,49 @@ return img; } +PurpleStoredImage * +purple_buddy_icons_node_set_custom_icon_from_file(PurpleBlistNode *node, + const gchar *filename) +{ + size_t len; + guchar *data; + + g_return_val_if_fail(node != NULL, NULL); + + if (!PURPLE_BLIST_NODE_IS_CONTACT(node) && + !PURPLE_BLIST_NODE_IS_CHAT(node) && + !PURPLE_BLIST_NODE_IS_GROUP(node)) { + return NULL; + } + + if (!read_icon_file(filename, &data, &len)) { + return NULL; + } + + return purple_buddy_icons_node_set_custom_icon(node, data, len); +} + +#ifndef PURPLE_DISABLE_DEPRECATED +gboolean +purple_buddy_icons_has_custom_icon(PurpleContact *contact) +{ + return purple_buddy_icons_node_has_custom_icon((PurpleBlistNode*)contact); +} + +PurpleStoredImage * +purple_buddy_icons_find_custom_icon(PurpleContact *contact) +{ + return purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact); +} + +PurpleStoredImage * +purple_buddy_icons_set_custom_icon(PurpleContact *contact, guchar *icon_data, + size_t icon_len) +{ + return purple_buddy_icons_node_set_custom_icon((PurpleBlistNode*)contact, icon_data, icon_len); +} +#endif + void _purple_buddy_icon_set_old_icons_dir(const char *dirname) { @@ -1138,7 +1196,9 @@ } } } - else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || + PURPLE_BLIST_NODE_IS_CHAT(node) || + PURPLE_BLIST_NODE_IS_GROUP(node)) { const char *filename; diff -r b17d6defb922 -r bc58e2d9f0f5 libpurple/buddyicon.h --- a/libpurple/buddyicon.h Fri May 16 03:18:20 2008 +0000 +++ b/libpurple/buddyicon.h Fri May 16 03:18:27 2008 +0000 @@ -218,16 +218,6 @@ purple_buddy_icons_find(PurpleAccount *account, const char *username); /** - * Returns a boolean indicating if a given contact has a custom buddy icon. - * - * @param contact The contact - * - * @return A boolean indicating if @a contact has a custom buddy icon. - */ -gboolean -purple_buddy_icons_has_custom_icon(PurpleContact *contact); - -/** * Returns the buddy icon image for an account. * * The caller owns a reference to the image in the store, and must dereference @@ -277,7 +267,18 @@ purple_buddy_icons_get_account_icon_timestamp(PurpleAccount *account); /** - * Returns the custom buddy icon image for a contact. + * Returns a boolean indicating if a given blist node has a custom buddy icon. + * + * @param node The blist node. + * + * @return A boolean indicating if @a node has a custom buddy icon. + * @since 2.5.0 + */ +gboolean +purple_buddy_icons_node_has_custom_icon(PurpleBlistNode *node); + +/** + * Returns the custom buddy icon image for a blist node. * * The caller owns a reference to the image in the store, and must dereference * the image with purple_imgstore_unref() for it to be freed. @@ -286,31 +287,82 @@ * needed, so it should be called in any case where you want the * appropriate icon. * - * @param contact The contact + * @param node The node. + * + * @return The custom buddy icon. + * @since 2.5.0 + */ +PurpleStoredImage * +purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node); + +/** + * Sets a custom buddy icon for a blist node. + * + * This function will deal with saving a record of the icon, caching the data, + * etc. + * + * @param node The blist node for which to set a custom icon. + * @param icon_data The image data of the icon, which the buddy icon code will + * free. + * @param icon_len The length of the data in @a icon_data. + * + * @return The icon that was set. The caller does NOT own a reference to this, + * and must call purple_imgstore_ref() if it wants one. + * @since 2.5.0 + */ +PurpleStoredImage * +purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node, + guchar *icon_data, size_t icon_len); + +/** + * Sets a custom buddy icon for a blist node. * - * @return The custom buddy icon image. + * Convenience wrapper around purple_buddy_icons_node_set_custom_icon. + * @see purple_buddy_icons_node_set_custom_icon() + * + * @param node The blist node for which to set a custom icon. + * @param filename The path to the icon to set for the blist node. + * + * @return The icon that was set. The caller does NOT own a reference to this, + * and must call purple_imgstore_ref() if it wants one. + * @since 2.5.0 + */ +PurpleStoredImage * +purple_buddy_icons_node_set_custom_icon_from_file(PurpleBlistNode *node, + const gchar *filename); + +#ifndef PURPLE_DISABLE_DEPRECATED +/** + * PurpleContact version of purple_buddy_icons_node_has_custom_icon. + * + * @copydoc purple_buddy_icons_node_has_custom_icon() + * + * @deprecated Use purple_buddy_icons_node_has_custom_icon instead. + */ +gboolean +purple_buddy_icons_has_custom_icon(PurpleContact *contact); + +/** + * PurpleContact version of purple_buddy_icons_node_find_custom_icon. + * + * @copydoc purple_buddy_icons_node_find_custom_icon() + * + * @deprecated Use purple_buddy_icons_node_find_custom_icon instead. */ PurpleStoredImage * purple_buddy_icons_find_custom_icon(PurpleContact *contact); /** - * Sets a custom buddy icon for a user. - * - * This function will deal with saving a record of the icon, - * caching the data, etc. + * PurpleContact version of purple_buddy_icons_node_set_custom_icon. * - * @param contact The contact for which to set a custom icon. - * @param icon_data The image data of the icon, which the - * buddy icon code will free. - * @param icon_len The length of the data in @a icon_data. + * @copydoc purple_buddy_icons_node_set_custom_icon() * - * @return The icon that was set. The caller does NOT own - * a reference to this, and must call purple_imgstore_ref() - * if it wants one. + * @deprecated Use purple_buddy_icons_node_set_custom_icon instead. */ PurpleStoredImage * purple_buddy_icons_set_custom_icon(PurpleContact *contact, guchar *icon_data, size_t icon_len); +#endif /** * Sets whether or not buddy icon caching is enabled. diff -r b17d6defb922 -r bc58e2d9f0f5 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Fri May 16 03:18:20 2008 +0000 +++ b/pidgin/gtkconv.c Fri May 16 03:18:27 2008 +0000 @@ -2722,10 +2722,22 @@ custom_icon_sel_cb(const char *filename, gpointer data) { if (filename) { + const gchar *name; + PurpleBuddy *buddy; + PurpleContact *contact; PidginConversation *gtkconv = data; PurpleConversation *conv = gtkconv->active_conv; PurpleAccount *account = purple_conversation_get_account(conv); - pidgin_set_custom_buddy_icon(account, purple_conversation_get_name(conv), filename); + + name = purple_conversation_get_name(conv); + buddy = purple_find_buddy(account, name); + if (!buddy) { + purple_debug_info("custom-icon", "You can only set custom icons for people on your buddylist.\n"); + return; + } + contact = purple_buddy_get_contact(buddy); + + purple_buddy_icons_node_set_custom_icon_from_file((PurpleBlistNode*)contact, filename); } } @@ -2767,12 +2779,21 @@ static void remove_custom_icon_cb(GtkWidget *widget, PidginConversation *gtkconv) { - PurpleConversation *conv; + const gchar *name; + PurpleBuddy *buddy; PurpleAccount *account; - - conv = gtkconv->active_conv; + PurpleContact *contact; + PurpleConversation *conv = gtkconv->active_conv; + account = purple_conversation_get_account(conv); - pidgin_set_custom_buddy_icon(account, purple_conversation_get_name(conv), NULL); + name = purple_conversation_get_name(conv); + buddy = purple_find_buddy(account, name); + if (!buddy) { + return; + } + contact = purple_buddy_get_contact(buddy); + + purple_buddy_icons_node_set_custom_icon_from_file((PurpleBlistNode*)contact, NULL); } static void @@ -2873,7 +2894,7 @@ if (buddy) { PurpleContact *contact = purple_buddy_get_contact(buddy); - if (contact && purple_buddy_icons_has_custom_icon(contact)) + if (contact && purple_buddy_icons_node_has_custom_icon((PurpleBlistNode*)contact)) { pidgin_new_item_from_stock(menu, _("Remove Custom Icon"), NULL, G_CALLBACK(remove_custom_icon_cb), gtkconv, @@ -6817,7 +6838,7 @@ { PurpleContact *contact = purple_buddy_get_contact(buddy); if (contact) { - custom_img = purple_buddy_icons_find_custom_icon(contact); + custom_img = purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact); if (custom_img) { /* There is a custom icon for this user */ data = purple_imgstore_get_data(custom_img); diff -r b17d6defb922 -r bc58e2d9f0f5 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Fri May 16 03:18:20 2008 +0000 +++ b/pidgin/gtkutils.c Fri May 16 03:18:27 2008 +0000 @@ -1436,7 +1436,7 @@ static void dnd_image_ok_callback(_DndData *data, int choice) { - char *filedata; + gchar *filedata; size_t size; struct stat st; GError *err = NULL; @@ -1444,6 +1444,8 @@ PidginConversation *gtkconv; GtkTextIter iter; int id; + PurpleBuddy *buddy; + PurpleContact *contact; switch (choice) { case DND_BUDDY_ICON: if (g_stat(data->filename, &st)) { @@ -1459,7 +1461,13 @@ return; } - pidgin_set_custom_buddy_icon(data->account, data->who, data->filename); + buddy = purple_find_buddy(data->account, data->who); + if (!buddy) { + purple_debug_info("custom-icon", "You can only set custom icons for people on your buddylist.\n"); + break; + } + contact = purple_buddy_get_contact(buddy); + purple_buddy_icons_node_set_custom_icon_from_file((PurpleBlistNode*)contact, data->filename); break; case DND_FILE_TRANSFER: serv_send_file(purple_account_get_connection(data->account), data->who, data->filename); @@ -2869,12 +2877,11 @@ } #endif /* ! Gtk 2.6.0 */ +#ifndef PURPLE_DISABLE_DEPRECATED void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) { PurpleBuddy *buddy; PurpleContact *contact; - gpointer data = NULL; - size_t len = 0; buddy = purple_find_buddy(account, who); if (!buddy) { @@ -2883,20 +2890,9 @@ } contact = purple_buddy_get_contact(buddy); - - if (filename) { - const char *prpl_id = purple_account_get_protocol_id(account); - PurplePlugin *prpl = purple_find_prpl(prpl_id); - - data = pidgin_convert_buddy_icon(prpl, filename, &len); - - /* We don't want to delete the old icon if the new one didn't load. */ - if (data == NULL) - return; - } - - purple_buddy_icons_set_custom_icon(contact, data, len); + purple_buddy_icons_node_set_custom_icon_from_file((PurpleBlistNode*)contact, filename); } +#endif char *pidgin_make_pretty_arrows(const char *str) { diff -r b17d6defb922 -r bc58e2d9f0f5 pidgin/gtkutils.h --- a/pidgin/gtkutils.h Fri May 16 03:18:20 2008 +0000 +++ b/pidgin/gtkutils.h Fri May 16 03:18:27 2008 +0000 @@ -638,6 +638,7 @@ GError **error); #endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Set or unset a custom buddyicon for a user. * @@ -645,8 +646,10 @@ * @param who The name of the user. * @param filename The path of the custom icon. If this is @c NULL, then any * previously set custom buddy icon for the user is removed. + * @deprecated See purple_buddy_icons_node_set_custom_icon_from_file() */ void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename); +#endif /** * Converts "->" and "<-" in strings to Unicode arrow characters, for use in referencing