From: <sa...@us...> - 2006-10-29 23:36:29
|
Revision: 17621 http://svn.sourceforge.net/gaim/?rev=17621&view=rev Author: sadrul Date: 2006-10-29 15:35:57 -0800 (Sun, 29 Oct 2006) Log Message: ----------- Allow custom buddy icons for people in the buddylist. It's done completely in the UI side. The custom icon does not overwrite the original icon, which is displayed in the tooltip. You can set the icon by dragging an image on the conv window, or on the buddy in the buddylist. You can also set/remove custom icon from the conversation window by right clicking on the icon in the conv window. Modified Paths: -------------- trunk/ChangeLog.API trunk/gtk/gtkblist.c trunk/gtk/gtkconv.c trunk/gtk/gtkutils.c trunk/gtk/gtkutils.h Modified: trunk/ChangeLog.API =================================================================== --- trunk/ChangeLog.API 2006-10-29 23:28:37 UTC (rev 17620) +++ trunk/ChangeLog.API 2006-10-29 23:35:57 UTC (rev 17621) @@ -138,6 +138,7 @@ a change in the values stored in the column. * gaim_find_buddies() returns a list of all buddies in the account if name is NULL. + * gaim_gtk_set_custom_buddy_icon() sets custom icon for a user. Removed: * gaim_gtk_sound_{get,set}_mute() (replaced by the /gaim/gtk/sound/mute Modified: trunk/gtk/gtkblist.c =================================================================== --- trunk/gtk/gtkblist.c 2006-10-29 23:28:37 UTC (rev 17620) +++ trunk/gtk/gtkblist.c 2006-10-29 23:35:57 UTC (rev 17621) @@ -1992,12 +1992,12 @@ } static GdkPixbuf *gaim_gtk_blist_get_buddy_icon(GaimBlistNode *node, - gboolean scaled, gboolean greyed) + gboolean scaled, gboolean greyed, gboolean custom) { GdkPixbuf *buf, *ret = NULL; GdkPixbufLoader *loader; GaimBuddyIcon *icon; - const guchar *data; + const guchar *data = NULL; gsize len; GaimBuddy *buddy = (GaimBuddy *)node; @@ -2014,12 +2014,30 @@ return NULL; #endif - if (!(icon = gaim_buddy_get_icon(buddy))) - if (!(icon = gaim_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/ - return NULL; + if (custom) { + const char *file = gaim_blist_node_get_string((GaimBlistNode*)gaim_buddy_get_contact(buddy), + "custom_buddy_icon"); + if (file && *file) { + char *contents; + GError *err = NULL; + if (!g_file_get_contents(file, &contents, &len, &err)) { + gaim_debug_info("custom -icon", "Could not open custom-icon %s for %s\n", + file, gaim_buddy_get_name(buddy), err->message); + g_error_free(err); + } else + data = (const guchar*)contents; + } + } + if (data == NULL) { + if (!(icon = gaim_buddy_get_icon(buddy))) + if (!(icon = gaim_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/ + return NULL; + data = gaim_buddy_icon_get_data(icon, &len); + custom = FALSE; /* We are not using the custom icon */ + } + loader = gdk_pixbuf_loader_new(); - data = gaim_buddy_icon_get_data(icon, &len); gdk_pixbuf_loader_write(loader, data, len, NULL); gdk_pixbuf_loader_close(loader, NULL); buf = gdk_pixbuf_loader_get_pixbuf(loader); @@ -2027,6 +2045,8 @@ g_object_ref(G_OBJECT(buf)); g_object_unref(G_OBJECT(loader)); + if (custom) + g_free((void*)data); if (buf) { GaimAccount *account = gaim_buddy_get_account(buddy); GaimPluginProtocolInfo *prpl_info = NULL; @@ -2088,7 +2108,7 @@ struct tooltip_data *td = g_new0(struct tooltip_data, 1); td->status_icon = gaim_gtk_blist_get_status_icon(node, GAIM_STATUS_ICON_LARGE); - td->avatar = gaim_gtk_blist_get_buddy_icon(node, !full, FALSE); + td->avatar = gaim_gtk_blist_get_buddy_icon(node, !full, FALSE, FALSE); tooltip_text = gaim_get_tooltip_text(node, full); td->layout = gtk_widget_create_pango_layout(gtkblist->tipwindow, NULL); pango_layout_set_markup(td->layout, tooltip_text, -1); @@ -4470,7 +4490,7 @@ status = gaim_gtk_blist_get_status_icon((GaimBlistNode*)buddy, biglist ? GAIM_STATUS_ICON_LARGE : GAIM_STATUS_ICON_SMALL); - avatar = gaim_gtk_blist_get_buddy_icon((GaimBlistNode *)buddy, TRUE, TRUE); + avatar = gaim_gtk_blist_get_buddy_icon((GaimBlistNode *)buddy, TRUE, TRUE, TRUE); mark = gaim_gtk_blist_get_name_markup(buddy, selected); if (gaim_prefs_get_bool("/gaim/gtk/blist/show_idle_time") && Modified: trunk/gtk/gtkconv.c =================================================================== --- trunk/gtk/gtkconv.c 2006-10-29 23:28:37 UTC (rev 17620) +++ trunk/gtk/gtkconv.c 2006-10-29 23:35:57 UTC (rev 17621) @@ -2354,7 +2354,7 @@ } static void -remove_icon(GaimGtkConversation *gtkconv) +remove_icon(GtkWidget *widget, GaimGtkConversation *gtkconv) { GaimConversation *conv = gtkconv->active_conv; GaimGtkWindow *gtkwin; @@ -2412,7 +2412,54 @@ fclose(fp); } +static const char * +custom_icon_pref_name(GaimGtkConversation *gtkconv) +{ + GaimConversation *conv; + GaimAccount *account; + GaimBuddy *buddy; + + conv = gtkconv->active_conv; + account = gaim_conversation_get_account(conv); + buddy = gaim_find_buddy(account, gaim_conversation_get_name(conv)); + if (buddy) { + GaimContact *contact = gaim_buddy_get_contact(buddy); + return gaim_blist_node_get_string((GaimBlistNode*)contact, "custom_buddy_icon"); + } + return NULL; +} + static void +custom_icon_sel_cb(const char *filename, gpointer data) +{ + if (filename) { + GaimGtkConversation *gtkconv = data; + GaimConversation *conv = gtkconv->active_conv; + GaimAccount *account = gaim_conversation_get_account(conv); + gaim_gtk_set_custom_buddy_icon(account, gaim_conversation_get_name(conv), filename); + } +} + +static void +set_custom_icon_cb(GtkWidget *widget, GaimGtkConversation *gtkconv) +{ + GtkWidget *win = gaim_gtk_buddy_icon_chooser_new(GTK_WINDOW(gtkconv->win->window), + custom_icon_sel_cb, gtkconv); + gtk_widget_show_all(win); +} + +static void +remove_custom_icon_cb(GtkWidget *widget, GaimGtkConversation *gtkconv) +{ + GaimConversation *conv; + GaimAccount *account; + + conv = gtkconv->active_conv; + account = gaim_conversation_get_account(conv); + gaim_gtk_set_custom_buddy_icon(account, gaim_conversation_get_name(conv), NULL); +} + +static void icon_menu_save_cb(GtkWidget *widget, GaimGtkConversation *gtkconv) { GaimConversation *conv = gtkconv->active_conv; @@ -2459,7 +2506,7 @@ icon_menu(GtkObject *obj, GdkEventButton *e, GaimGtkConversation *gtkconv) { static GtkWidget *menu = NULL; - GtkWidget *item; + const char *pref; if (e->button != 3 || e->type != GDK_BUTTON_PRESS) return FALSE; @@ -2481,16 +2528,25 @@ gtkconv->u.im->icon_timer); } - item = gtk_menu_item_new_with_label(_("Hide Icon")); - g_signal_connect_swapped(G_OBJECT(item), "activate", - G_CALLBACK(remove_icon), gtkconv); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - gtk_widget_show(item); + gaim_new_item_from_stock(menu, _("Hide Icon"), NULL, G_CALLBACK(remove_icon), + gtkconv, 0, 0, NULL); gaim_new_item_from_stock(menu, _("Save Icon As..."), GTK_STOCK_SAVE_AS, G_CALLBACK(icon_menu_save_cb), gtkconv, 0, 0, NULL); + gaim_new_item_from_stock(menu, _("Set Custom Icon..."), NULL, + G_CALLBACK(set_custom_icon_cb), gtkconv, + 0, 0, NULL); + + /* Is there a custom icon for this person? */ + pref = custom_icon_pref_name(gtkconv); + if (pref && *pref) { + gaim_new_item_from_stock(menu, _("Remove Custom Icon"), NULL, + G_CALLBACK(remove_custom_icon_cb), gtkconv, + 0, 0, NULL); + } + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time); return TRUE; @@ -2518,7 +2574,7 @@ if (active) gaim_gtkconv_update_buddy_icon(conv); else - remove_icon(gtkconv); + remove_icon(NULL, gtkconv); } /************************************************************************** @@ -5836,7 +5892,8 @@ GdkPixbufAnimation *anim; GError *err = NULL; - const void *data; + const char *custom = NULL; + const void *data = NULL; size_t len; GdkPixbuf *buf; @@ -5893,13 +5950,29 @@ if (gaim_conversation_get_gc(conv) == NULL) return; - icon = gaim_conv_im_get_icon(GAIM_CONV_IM(conv)); + custom = custom_icon_pref_name(gtkconv); + if (custom) { + /* There is a custom icon for this user */ + char *contents = NULL; + if (!g_file_get_contents(custom, &contents, &len, &err)) { + gaim_debug_warning("custom icon", "could not load custom icon %s for %s\n", + custom, gaim_conversation_get_name(conv)); + g_error_free(err); + err = NULL; + } else + data = contents; + } - if (icon == NULL) - return; + if (data == NULL) { + icon = gaim_conv_im_get_icon(GAIM_CONV_IM(conv)); - data = gaim_buddy_icon_get_data(icon, &len); + if (icon == NULL) + return; + data = gaim_buddy_icon_get_data(icon, &len); + custom = NULL; + } + loader = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(loader, data, len, NULL); gdk_pixbuf_loader_close(loader, &err); @@ -5908,6 +5981,9 @@ g_object_ref(G_OBJECT(anim)); g_object_unref(loader); + if (custom) + g_free((void*)data); + if (!anim) return; gtkconv->u.im->anim = anim; Modified: trunk/gtk/gtkutils.c =================================================================== --- trunk/gtk/gtkutils.c 2006-10-29 23:28:37 UTC (rev 17620) +++ trunk/gtk/gtkutils.c 2006-10-29 23:35:57 UTC (rev 17621) @@ -1,5 +1,5 @@ /** - * @file gtkutils.h GTK+ utility functions + * @file gtkutils.c GTK+ utility functions * @ingroup gtkui * * gaim @@ -1296,6 +1296,7 @@ { char *filedata; size_t size; + struct stat st; GError *err = NULL; GaimConversation *conv; GaimGtkConversation *gtkconv; @@ -1303,23 +1304,20 @@ int id; switch (choice) { case DND_BUDDY_ICON: - if (!g_file_get_contents(data->filename, &filedata, &size, - &err)) { + if (g_stat(data->filename, &st)) { char *str; - str = g_strdup_printf(_("The following error has occurred loading %s: %s"), data->filename, err->message); + str = g_strdup_printf(_("The following error has occurred loading %s: %s"), + data->filename, strerror(errno)); gaim_notify_error(NULL, NULL, _("Failed to load image"), str); - - g_error_free(err); g_free(str); return; } - gaim_buddy_icons_set_for_user(data->account, data->who, filedata, size); - g_free(filedata); + gaim_gtk_set_custom_buddy_icon(data->account, data->who, data->filename); break; case DND_FILE_TRANSFER: serv_send_file(gaim_account_get_connection(data->account), data->who, data->filename); @@ -2795,3 +2793,48 @@ } #endif +void gaim_gtk_set_custom_buddy_icon(GaimAccount *account, const char *who, const char *filename) +{ + GaimConversation *conv; + GaimBuddy *buddy; + GaimBlistNode *node; + char *path = NULL; + + buddy = gaim_find_buddy(account, who); + if (!buddy) { + gaim_debug_info("custom-icon", "You can only set custom icon for someone in your buddylist.\n"); + return; + } + + node = (GaimBlistNode*)gaim_buddy_get_contact(buddy); + path = (char*)gaim_blist_node_get_string(node, "custom_buddy_icon"); + if (path) { + struct stat st; + if (g_stat(path, &st) == 0) + g_unlink(path); + path = NULL; + } + + if (filename) { + char *newfile; + + newfile = gaim_gtk_convert_buddy_icon(gaim_find_prpl(gaim_account_get_protocol_id(account)), + filename); + path = gaim_buddy_icons_get_full_path(newfile); + g_free(newfile); + } + + gaim_blist_node_set_string(node, "custom_buddy_icon", path); + g_free(path); + + /* Update the conversation */ + conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, who, account); + if (conv) + gaim_conversation_update(conv, GAIM_CONV_UPDATE_ICON); + + /* Update the buddylist */ + if (buddy) + gaim_blist_update_buddy_icon(buddy); +} + + Modified: trunk/gtk/gtkutils.h =================================================================== --- trunk/gtk/gtkutils.h 2006-10-29 23:28:37 UTC (rev 17620) +++ trunk/gtk/gtkutils.h 2006-10-29 23:35:57 UTC (rev 17621) @@ -475,7 +475,7 @@ * * @param plugin The prpl to conver the icon * @param path The path of a buddy icon to convert - * @return The path of a new buddy icon + * @return The name of a new buddy icon */ char* gaim_gtk_convert_buddy_icon(GaimPlugin *plugin, const char *path); @@ -491,3 +491,13 @@ #endif #endif /* _GAIM_GTKUTILS_H_ */ + +/** + * Set or unset a custom buddyicon for a user. + * + * @param account The account the user belongs to. + * @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. + */ +void gaim_gtk_set_custom_buddy_icon(GaimAccount *account, const char *who, const char *filename); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |