pidgin.next.minor: 41bf77ad: Add support for setting and removing cus...
deryni at pidgin.im
deryni at pidgin.im
Sat May 17 16:16:33 EDT 2008
-----------------------------------------------------------------
Revision: 41bf77ad2b3c42618362f5e2daace6c5a25a9907
Ancestor: 586a914e39d5e3980aaf78c661660b38cd7d9538
Author: deryni at pidgin.im
Date: 2008-05-17T19:53:28
Branch: im.pidgin.pidgin.next.minor
URL: http://d.pidgin.im/viewmtn/revision/info/41bf77ad2b3c42618362f5e2daace6c5a25a9907
Modified files:
ChangeLog pidgin/gtkblist.c
ChangeLog:
Add support for setting and removing custom buddy icons to contacts, chats,
and groups via their respective right-click menus in the buddy list. Also
display the buddy icons for chats and groups in the buddy list.
-------------- next part --------------
============================================================
--- ChangeLog 0e1391ad1734f8bde42a1862e8e7f41e2f5c8fb6
+++ ChangeLog 979ea11c01b4a6839c9f9480691b66aa3425a65f
@@ -1,5 +1,14 @@ Pidgin and Finch: The Pimpin' Penguin IM
Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
+version 2.5.0:
+ Pidgin:
+ * Custom buddy icons can now be added and removed to buddy list
+ entries via the buddy list entry right-click menu.
+
+ General:
+ * Group and Chat buddy list entries can now be given custom buddy
+ icons.
+
version 2.x.x:
libpurple:
* In MySpaceIM, messages from spambots are discarded (Justin Williams)
============================================================
--- pidgin/gtkblist.c 659352d9fd6f6430cc672395ef55176b7452c5ed
+++ pidgin/gtkblist.c 8686e4910c3ff16e31cea704aa06fb5747ba028d
@@ -1529,6 +1529,44 @@ gtk_blist_key_press_cb(GtkWidget *tv, Gd
return FALSE;
}
+static void
+set_node_custom_icon_cb(const gchar *filename, gpointer data)
+{
+ if (filename) {
+ PurpleBlistNode *node = (PurpleBlistNode*)data;
+
+ purple_buddy_icons_node_set_custom_icon_from_file(node,
+ filename);
+ }
+}
+
+static void
+set_node_custom_icon(GtkWidget *w, PurpleBlistNode *node)
+{
+ /* This doesn't keep track of the returned dialog (so that successive
+ * calls could be made to re-display that dialog). Do we want that? */
+ GtkWidget *win = pidgin_buddy_icon_chooser_new(NULL, set_node_custom_icon_cb, node);
+ gtk_widget_show_all(win);
+}
+
+static void
+remove_node_custom_icon(GtkWidget *w, PurpleBlistNode *node)
+{
+ purple_buddy_icons_node_set_custom_icon(node, NULL, 0);
+}
+
+static void
+add_buddy_icon_menu_items(GtkWidget *menu, PurpleBlistNode *node)
+{
+ pidgin_new_item_from_stock(menu, _("Set Custom Icon"), NULL,
+ G_CALLBACK(set_node_custom_icon), node, 0,
+ 0, NULL);
+
+ pidgin_new_item_from_stock(menu, _("Remove Custom Icon"), NULL,
+ G_CALLBACK(remove_node_custom_icon), node,
+ 0, 0, NULL);
+}
+
static GtkWidget *
create_group_menu (PurpleBlistNode *node, PurpleGroup *g)
{
@@ -1552,12 +1590,13 @@ create_group_menu (PurpleBlistNode *node
NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL);
}
+ add_buddy_icon_menu_items(menu, node);
+
pidgin_append_blist_node_extended_menu(menu, node);
return menu;
}
-
static GtkWidget *
create_chat_menu(PurpleBlistNode *node, PurpleChat *c)
{
@@ -1590,6 +1629,8 @@ create_chat_menu(PurpleBlistNode *node,
pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE,
G_CALLBACK(pidgin_blist_remove_cb), node, 0, 0, NULL);
+ add_buddy_icon_menu_items(menu, node);
+
return menu;
}
@@ -1611,6 +1652,8 @@ create_contact_menu (PurpleBlistNode *no
pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE,
G_CALLBACK(pidgin_blist_remove_cb), node, 0, 0, NULL);
+ add_buddy_icon_menu_items(menu, node);
+
pidgin_separator(menu);
pidgin_new_item_from_stock(menu, _("_Collapse"), GTK_STOCK_ZOOM_OUT,
@@ -2492,51 +2535,71 @@ static GdkPixbuf *pidgin_blist_get_buddy
static GdkPixbuf *pidgin_blist_get_buddy_icon(PurpleBlistNode *node,
- gboolean scaled, gboolean greyed)
+ gboolean scaled, gboolean greyed)
{
- GdkPixbuf *buf, *ret = NULL;
+ gsize len;
GdkPixbufLoader *loader;
- PurpleBuddyIcon *icon = NULL;
+ PurpleBuddy *buddy = NULL;
+ PurpleGroup *group = NULL;
const guchar *data = NULL;
- gsize len;
- PurpleBuddy *buddy = NULL;
+ GdkPixbuf *buf, *ret = NULL;
+ PurpleBuddyIcon *icon = NULL;
PurpleAccount *account = NULL;
+ PurpleContact *contact = NULL;
+ PurpleStoredImage *custom_img;
PurplePluginProtocolInfo *prpl_info = NULL;
- PurpleStoredImage *custom_img;
+ gint orig_width, orig_height, scale_width, scale_height;
- if(PURPLE_BLIST_NODE_IS_CONTACT(node)) {
+ if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
buddy = purple_contact_get_priority_buddy((PurpleContact*)node);
- } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+ contact = (PurpleContact*)node;
+ } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
buddy = (PurpleBuddy*)node;
+ contact = purple_buddy_get_contact(buddy);
+ } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
+ group = (PurpleGroup*)node;
+ } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
+ /* We don't need to do anything here. We just need to not fall
+ * into the else block and return. */
} else {
return NULL;
}
- if(buddy == NULL)
- return NULL;
+ if (buddy) {
+ account = purple_buddy_get_account(buddy);
+ }
- account = purple_buddy_get_account(buddy);
-
- if(account && account->gc)
+ if(account && account->gc) {
prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl);
+ }
#if 0
if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"))
return NULL;
#endif
- custom_img = purple_buddy_icons_find_custom_icon(purple_buddy_get_contact(buddy));
- if (custom_img)
- {
+ /* If we have a contact then this is either a contact or a buddy and
+ * we want to fetch the custom icon for the contact. If we don't have
+ * a contact then this is a group or some other type of node and we
+ * want to use that directly. */
+ if (contact) {
+ custom_img = purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact);
+ } else {
+ custom_img = purple_buddy_icons_node_find_custom_icon(node);
+ }
+
+ if (custom_img) {
data = purple_imgstore_get_data(custom_img);
len = purple_imgstore_get_size(custom_img);
}
if (data == NULL) {
- /* Not sure I like this...*/
- if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name)))
- return NULL;
- data = purple_buddy_icon_get_data(icon, &len);
+ if (buddy) {
+ /* Not sure I like this...*/
+ if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name)))
+ return NULL;
+ data = purple_buddy_icon_get_data(icon, &len);
+ }
if(data == NULL)
return NULL;
@@ -2554,56 +2617,68 @@ static GdkPixbuf *pidgin_blist_get_buddy
g_object_ref(G_OBJECT(buf));
g_object_unref(G_OBJECT(loader));
- if (buf) {
- int orig_width, orig_height;
- int scale_width, scale_height;
+ if (!buf) {
+ return NULL;
+ }
- if (greyed) {
+ if (greyed) {
+ gboolean offline = FALSE, idle = TRUE;
+
+ if (buddy) {
PurplePresence *presence = purple_buddy_get_presence(buddy);
if (!PURPLE_BUDDY_IS_ONLINE(buddy))
- gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.0, FALSE);
+ offline = TRUE;
if (purple_presence_is_idle(presence))
- gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.25, FALSE);
+ idle = TRUE;
+ } else if (group) {
+ if (purple_blist_get_group_online_count(group) == 0)
+ offline = TRUE;
}
- /* i'd use the pidgin_buddy_icon_get_scale_size() thing,
- * but it won't tell me the original size, which I need for scaling
- * purposes */
- scale_width = orig_width = gdk_pixbuf_get_width(buf);
- scale_height = orig_height = gdk_pixbuf_get_height(buf);
+ if (offline)
+ gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.0, FALSE);
- if (prpl_info && prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY)
- purple_buddy_icon_get_scale_size(&prpl_info->icon_spec, &scale_width, &scale_height);
+ if (idle)
+ gdk_pixbuf_saturate_and_pixelate(buf, buf, 0.25, FALSE);
+ }
- if (scaled || scale_height > 200 || scale_width > 200) {
- GdkPixbuf *tmpbuf;
- float scale_size = scaled ? 32.0 : 200.0;
- if(scale_height > scale_width) {
- scale_width = scale_size * (double)scale_width / (double)scale_height;
- scale_height = scale_size;
- } else {
- scale_height = scale_size * (double)scale_height / (double)scale_width;
- scale_width = scale_size;
- }
- /* scale & round before making square, so rectangular (but non-square)
- * images get rounded corners too */
- tmpbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_width, scale_height);
- gdk_pixbuf_fill(tmpbuf, 0x00000000);
- gdk_pixbuf_scale(buf, tmpbuf, 0, 0, scale_width, scale_height, 0, 0, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR);
- if (pidgin_gdk_pixbuf_is_opaque(tmpbuf))
- pidgin_gdk_pixbuf_make_round(tmpbuf);
- ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_size, scale_size);
- gdk_pixbuf_fill(ret, 0x00000000);
- gdk_pixbuf_copy_area(tmpbuf, 0, 0, scale_width, scale_height, ret, (scale_size-scale_width)/2, (scale_size-scale_height)/2);
- g_object_unref(G_OBJECT(tmpbuf));
+ /* I'd use the pidgin_buddy_icon_get_scale_size() thing, but it won't
+ * tell me the original size, which I need for scaling purposes. */
+ scale_width = orig_width = gdk_pixbuf_get_width(buf);
+ scale_height = orig_height = gdk_pixbuf_get_height(buf);
+
+ if (prpl_info && prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY)
+ purple_buddy_icon_get_scale_size(&prpl_info->icon_spec, &scale_width, &scale_height);
+
+ if (scaled || scale_height > 200 || scale_width > 200) {
+ GdkPixbuf *tmpbuf;
+ float scale_size = scaled ? 32.0 : 200.0;
+ if(scale_height > scale_width) {
+ scale_width = scale_size * (double)scale_width / (double)scale_height;
+ scale_height = scale_size;
} else {
- ret = gdk_pixbuf_scale_simple(buf,scale_width,scale_height, GDK_INTERP_BILINEAR);
+ scale_height = scale_size * (double)scale_height / (double)scale_width;
+ scale_width = scale_size;
}
- g_object_unref(G_OBJECT(buf));
+ /* Scale & round before making square, so rectangular (but
+ * non-square) images get rounded corners too. */
+ tmpbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_width, scale_height);
+ gdk_pixbuf_fill(tmpbuf, 0x00000000);
+ gdk_pixbuf_scale(buf, tmpbuf, 0, 0, scale_width, scale_height, 0, 0, (double)scale_width/(double)orig_width, (double)scale_height/(double)orig_height, GDK_INTERP_BILINEAR);
+ if (pidgin_gdk_pixbuf_is_opaque(tmpbuf))
+ pidgin_gdk_pixbuf_make_round(tmpbuf);
+ ret = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_size, scale_size);
+ gdk_pixbuf_fill(ret, 0x00000000);
+ gdk_pixbuf_copy_area(tmpbuf, 0, 0, scale_width, scale_height, ret, (scale_size-scale_width)/2, (scale_size-scale_height)/2);
+ g_object_unref(G_OBJECT(tmpbuf));
+ } else {
+ ret = gdk_pixbuf_scale_simple(buf,scale_width,scale_height, GDK_INTERP_BILINEAR);
}
+ g_object_unref(G_OBJECT(buf));
return ret;
}
+
/* # - Status Icon
* P - Protocol Icon
* A - Buddy Icon
@@ -5819,14 +5894,16 @@ static gboolean pidgin_blist_group_has_s
return FALSE;
}
-/*This version of pidgin_blist_update_group can take the original buddy
-or a group, but has much better algorithmic performance with a pre-known buddy*/
-static void pidgin_blist_update_group(PurpleBuddyList *list, PurpleBlistNode *node)
+/* This version of pidgin_blist_update_group can take the original buddy or a
+ * group, but has much better algorithmic performance with a pre-known buddy.
+ */
+static void pidgin_blist_update_group(PurpleBuddyList *list,
+ PurpleBlistNode *node)
{
+ gint count;
PurpleGroup *group;
- int count;
+ PurpleBlistNode* gnode;
gboolean show = FALSE, show_offline = FALSE;
- PurpleBlistNode* gnode;
g_return_if_fail(node != NULL);
@@ -5861,13 +5938,14 @@ static void pidgin_blist_update_group(Pu
}
if (show) {
+ gchar *title;
+ gboolean biglist;
GtkTreeIter iter;
GtkTreePath *path;
gboolean expanded;
GdkColor bgcolor;
- char *title;
+ GdkPixbuf *avatar = NULL;
-
if(!insert_node(list, gnode, &iter))
return;
@@ -5878,17 +5956,23 @@ static void pidgin_blist_update_group(Pu
gtk_tree_path_free(path);
title = pidgin_get_group_title(gnode, expanded);
+ biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
+ if (biglist) {
+ avatar = pidgin_blist_get_buddy_icon(gnode, TRUE, TRUE);
+ }
+
gtk_tree_store_set(gtkblist->treemodel, &iter,
STATUS_ICON_VISIBLE_COLUMN, FALSE,
STATUS_ICON_COLUMN, NULL,
NAME_COLUMN, title,
NODE_COLUMN, gnode,
- /* BGCOLOR_COLUMN, &bgcolor, */
+ /* BGCOLOR_COLUMN, &bgcolor, */
GROUP_EXPANDER_COLUMN, TRUE,
GROUP_EXPANDER_VISIBLE_COLUMN, TRUE,
CONTACT_EXPANDER_VISIBLE_COLUMN, FALSE,
- BUDDY_ICON_VISIBLE_COLUMN, FALSE,
+ BUDDY_ICON_COLUMN, avatar,
+ BUDDY_ICON_VISIBLE_COLUMN, biglist,
IDLE_VISIBLE_COLUMN, FALSE,
EMBLEM_VISIBLE_COLUMN, FALSE,
-1);
@@ -6178,7 +6262,7 @@ static void pidgin_blist_update_chat(Pur
STATUS_ICON_COLUMN, status,
STATUS_ICON_VISIBLE_COLUMN, TRUE,
BUDDY_ICON_COLUMN, avatar ? avatar : gtkblist->empty_avatar,
- BUDDY_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"),
+ BUDDY_ICON_VISIBLE_COLUMN, showicons,
EMBLEM_COLUMN, emblem,
EMBLEM_VISIBLE_COLUMN, emblem != NULL,
PROTOCOL_ICON_COLUMN, prpl_icon,
More information about the Commits
mailing list