Mercurial > pidgin.yaz
changeset 26733:a373ce73add0
Merging the changes in theme-foo, and the theme editor plugin.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 25 Apr 2009 19:09:36 +0000 |
parents | dbe2731f0a35 (diff) 951102c642c5 (current diff) |
children | bed515729afe |
files | |
diffstat | 22 files changed, 1427 insertions(+), 518 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog.API Thu Apr 23 20:05:26 2009 +0000 +++ b/ChangeLog.API Sat Apr 25 19:09:36 2009 +0000 @@ -77,6 +77,10 @@ * pidgin_sound_is_customized * pidgin_utils_init, pidgin_utils_uninit * pidgin_notify_pounce_add + * PidginBlistTheme, PidginBlistThemeLoader API + * PidginIconTheme, PidginStatusIconTheme, PidginIconThemeLoader + API + * pidgin_stock_id_from_status_primitive libgnt: Added:
--- a/pidgin/gtkblist-theme-loader.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkblist-theme-loader.c Sat Apr 25 19:09:36 2009 +0000 @@ -38,6 +38,22 @@ * Buddy List Theme Builder *****************************************************************************/ +static PidginThemeFont * +pidgin_theme_font_parse(xmlnode *node) +{ + const char *font; + const char *colordesc; + GdkColor color; + + font = xmlnode_get_attrib(node, "font"); + + if ((colordesc = xmlnode_get_attrib(node, "color")) == NULL || + !gdk_color_parse(colordesc, &color)) + gdk_color_parse(DEFAULT_TEXT_COLOR, &color); + + return pidgin_theme_font_new(font, &color); +} + static PurpleTheme * pidgin_blist_loader_build(const gchar *dir) { @@ -46,10 +62,24 @@ const gchar *temp; gboolean success = TRUE; GdkColor bgcolor, expanded_bgcolor, collapsed_bgcolor, contact_color; - GdkColor color; - FontColorPair expanded, collapsed, contact, online, away, offline, idle, message, message_nick_said, status; + PidginThemeFont *expanded, *collapsed, *contact, *online, *away, *offline, *idle, *message, *message_nick_said, *status; PidginBlistLayout layout; PidginBlistTheme *theme; + int i; + struct { + const char *tag; + PidginThemeFont **font; + } lookups[] = { + {"contact_text", &contact}, + {"online_text", &online}, + {"away_text", &away}, + {"offline_text", &offline}, + {"idle_text", &idle}, + {"message_text", &message}, + {"message_nick_said_text", &message_nick_said}, + {"status_text", &status}, + {NULL, NULL} + }; /* Find the theme file */ g_return_val_if_fail(dir != NULL, NULL); @@ -76,11 +106,7 @@ if ((success = (success && (sub_node = xmlnode_get_child(root_node, "groups")) != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "expanded")) != NULL))) { - expanded.font = xmlnode_get_attrib(sub_sub_node, "font"); - - if ((temp = xmlnode_get_attrib(sub_sub_node, "text_color")) != NULL && gdk_color_parse(temp, &color)) - expanded.color = temp; - else expanded.color = DEFAULT_TEXT_COLOR; + expanded = pidgin_theme_font_parse(sub_sub_node); if ((temp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(temp, &expanded_bgcolor)) gdk_colormap_alloc_color(gdk_colormap_get_system(), &expanded_bgcolor, FALSE, TRUE); @@ -90,11 +116,7 @@ if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "collapsed")) != NULL))) { - collapsed.font = xmlnode_get_attrib(sub_sub_node, "font"); - - if((temp = xmlnode_get_attrib(sub_sub_node, "text_color")) != NULL && gdk_color_parse(temp, &color)) - collapsed.color = temp; - else collapsed.color = DEFAULT_TEXT_COLOR; + collapsed = pidgin_theme_font_parse(sub_sub_node); if ((temp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(temp, &collapsed_bgcolor)) gdk_colormap_alloc_color(gdk_colormap_get_system(), &collapsed_bgcolor, FALSE, TRUE); @@ -121,60 +143,13 @@ memset(&contact_color, 0, sizeof(GdkColor)); } - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "contact_text")) != NULL))) { - contact.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - contact.color = temp; - else contact.color = DEFAULT_TEXT_COLOR; - } - - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "online_text")) != NULL))) { - online.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - online.color = temp; - else online.color = DEFAULT_TEXT_COLOR; - } - - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "away_text")) != NULL))) { - away.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - away.color = temp; - else away.color = DEFAULT_TEXT_COLOR; - } - - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "offline_text")) != NULL))) { - offline.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - offline.color = temp; - else offline.color = DEFAULT_TEXT_COLOR; - } - - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "idle_text")) != NULL))) { - idle.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - idle.color = temp; - else idle.color = DEFAULT_TEXT_COLOR; - } - - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "message_text")) != NULL))) { - message.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - message.color = temp; - else message.color = DEFAULT_TEXT_COLOR; - } - - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "message_nick_said_text")) != NULL))) { - message_nick_said.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - message_nick_said.color = temp; - else message_nick_said.color = DEFAULT_TEXT_COLOR; - } - - if ((success = (success && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "status_text")) != NULL))) { - status.font = xmlnode_get_attrib(sub_sub_node, "font"); - if(gdk_color_parse(temp = xmlnode_get_attrib(sub_sub_node, "color"), &color)) - status.color = temp; - else status.color = DEFAULT_TEXT_COLOR; + for (i = 0; success && lookups[i].tag; i++) { + if ((success = (sub_node != NULL && + (sub_sub_node = xmlnode_get_child(sub_node, lookups[i].tag)) != NULL))) { + *(lookups[i].font) = pidgin_theme_font_parse(sub_sub_node); + } else { + *(lookups[i].font) = NULL; + } } /* name is required for theme manager */ @@ -191,19 +166,24 @@ "background-color", &bgcolor, "layout", &layout, "expanded-color", &expanded_bgcolor, - "expanded-text", &expanded, + "expanded-text", expanded, "collapsed-color", &collapsed_bgcolor, - "collapsed-text", &collapsed, + "collapsed-text", collapsed, "contact-color", &contact_color, - "contact", &contact, - "online", &online, - "away", &away, - "offline", &offline, - "idle", &idle, - "message", &message, - "message_nick_said", &message_nick_said, - "status", &status, NULL); + "contact", contact, + "online", online, + "away", away, + "offline", offline, + "idle", idle, + "message", message, + "message_nick_said", message_nick_said, + "status", status, NULL); + for (i = 0; lookups[i].tag; i++) { + if (*lookups[i].font) { + pidgin_theme_font_free(*lookups[i].font); + } + } xmlnode_free(root_node); g_free(data);
--- a/pidgin/gtkblist-theme-loader.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkblist-theme-loader.h Sat Apr 25 19:09:36 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file gtkblist-loader.h Pidgin Buddy List Theme Loader Class API + * @file gtkblist-theme-loader.h Pidgin Buddy List Theme Loader Class API */ /* pidgin
--- a/pidgin/gtkblist-theme.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkblist-theme.c Sat Apr 25 19:09:36 2009 +0000 @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#include "internal.h" #include "gtkblist-theme.h" #define PIDGIN_BLIST_THEME_GET_PRIVATE(Gobject) \ @@ -37,27 +38,34 @@ /* groups */ GdkColor *expanded_color; - FontColorPair *expanded; + PidginThemeFont *expanded; GdkColor *collapsed_color; - FontColorPair *collapsed; + PidginThemeFont *collapsed; /* buddy */ GdkColor *contact_color; - FontColorPair *contact; + PidginThemeFont *contact; - FontColorPair *online; - FontColorPair *away; - FontColorPair *offline; - FontColorPair *idle; - FontColorPair *message; - FontColorPair *message_nick_said; + PidginThemeFont *online; + PidginThemeFont *away; + PidginThemeFont *offline; + PidginThemeFont *idle; + PidginThemeFont *message; + PidginThemeFont *message_nick_said; - FontColorPair *status; + PidginThemeFont *status; } PidginBlistThemePrivate; +struct _PidginThemeFont +{ + gchar *font; + gchar color[10]; + GdkColor *gdkcolor; +}; + /****************************************************************************** * Globals *****************************************************************************/ @@ -92,23 +100,83 @@ * Helpers *****************************************************************************/ +PidginThemeFont * +pidgin_theme_font_new(const gchar *face, GdkColor *color) +{ + PidginThemeFont *font = g_new0(PidginThemeFont, 1); + font->font = g_strdup(face); + if (color) + pidgin_theme_font_set_color(font, color); + return font; +} + void -free_font_and_color(FontColorPair *pair) +pidgin_theme_font_free(PidginThemeFont *pair) { if (pair != NULL) { - g_free((gchar *)pair->font); - g_free((gchar *)pair->color); + g_free(pair->font); + if (pair->gdkcolor) + gdk_color_free(pair->gdkcolor); g_free(pair); } } -static FontColorPair * -copy_font_and_color(const FontColorPair *pair) +static PidginThemeFont * +copy_font_and_color(const PidginThemeFont *pair) +{ + PidginThemeFont *copy = g_new0(PidginThemeFont, 1); + copy->font = g_strdup(pair->font); + strncpy(copy->color, pair->color, sizeof(copy->color) - 1); + if (pair->gdkcolor) + copy->gdkcolor = gdk_color_copy(pair->gdkcolor); + return copy; +} + +void +pidgin_theme_font_set_font_face(PidginThemeFont *font, const gchar *face) +{ + g_return_if_fail(font); + g_return_if_fail(face); + + g_free(font->font); + font->font = g_strdup(face); +} + +void +pidgin_theme_font_set_color(PidginThemeFont *font, const GdkColor *color) { - FontColorPair *copy = g_new0(FontColorPair, 1); - copy->font = g_strdup(pair->font); - copy->color = g_strdup(pair->color); - return copy; + g_return_if_fail(font); + + if (font->gdkcolor) + gdk_color_free(font->gdkcolor); + + font->gdkcolor = color ? gdk_color_copy(color) : NULL; + if (color) + g_snprintf(font->color, sizeof(font->color), + "#%02x%02x%02x", color->red >> 8, color->green >> 8, color->blue >> 8); + else + font->color[0] = '\0'; +} + +const gchar * +pidgin_theme_font_get_font_face(PidginThemeFont *font) +{ + g_return_val_if_fail(font, NULL); + return font->font; +} + +const GdkColor * +pidgin_theme_font_get_color(PidginThemeFont *font) +{ + g_return_val_if_fail(font, NULL); + return font->gdkcolor; +} + +const gchar * +pidgin_theme_font_get_color_describe(PidginThemeFont *font) +{ + g_return_val_if_fail(font, NULL); + return font->color[0] ? font->color : NULL; } /****************************************************************************** @@ -130,7 +198,7 @@ switch (param_id) { case PROP_BACKGROUND_COLOR: - g_value_set_pointer(value, pidgin_blist_theme_get_background_color(theme)); + g_value_set_boxed(value, pidgin_blist_theme_get_background_color(theme)); break; case PROP_OPACITY: g_value_set_double(value, pidgin_blist_theme_get_opacity(theme)); @@ -139,19 +207,19 @@ g_value_set_pointer(value, pidgin_blist_theme_get_layout(theme)); break; case PROP_EXPANDED_COLOR: - g_value_set_pointer(value, pidgin_blist_theme_get_expanded_background_color(theme)); + g_value_set_boxed(value, pidgin_blist_theme_get_expanded_background_color(theme)); break; case PROP_EXPANDED_TEXT: g_value_set_pointer(value, pidgin_blist_theme_get_expanded_text_info(theme)); break; case PROP_COLLAPSED_COLOR: - g_value_set_pointer(value, pidgin_blist_theme_get_collapsed_background_color(theme)); + g_value_set_boxed(value, pidgin_blist_theme_get_collapsed_background_color(theme)); break; case PROP_COLLAPSED_TEXT: g_value_set_pointer(value, pidgin_blist_theme_get_collapsed_text_info(theme)); break; case PROP_CONTACT_COLOR: - g_value_set_pointer(value, pidgin_blist_theme_get_contact_color(theme)); + g_value_set_boxed(value, pidgin_blist_theme_get_contact_color(theme)); break; case PROP_CONTACT: g_value_set_pointer(value, pidgin_blist_theme_get_contact_text_info(theme)); @@ -191,7 +259,7 @@ switch (param_id) { case PROP_BACKGROUND_COLOR: - pidgin_blist_theme_set_background_color(theme, g_value_get_pointer(value)); + pidgin_blist_theme_set_background_color(theme, g_value_get_boxed(value)); break; case PROP_OPACITY: pidgin_blist_theme_set_opacity(theme, g_value_get_double(value)); @@ -200,19 +268,19 @@ pidgin_blist_theme_set_layout(theme, g_value_get_pointer(value)); break; case PROP_EXPANDED_COLOR: - pidgin_blist_theme_set_expanded_background_color(theme, g_value_get_pointer(value)); + pidgin_blist_theme_set_expanded_background_color(theme, g_value_get_boxed(value)); break; case PROP_EXPANDED_TEXT: pidgin_blist_theme_set_expanded_text_info(theme, g_value_get_pointer(value)); break; case PROP_COLLAPSED_COLOR: - pidgin_blist_theme_set_collapsed_background_color(theme, g_value_get_pointer(value)); + pidgin_blist_theme_set_collapsed_background_color(theme, g_value_get_boxed(value)); break; case PROP_COLLAPSED_TEXT: pidgin_blist_theme_set_collapsed_text_info(theme, g_value_get_pointer(value)); break; case PROP_CONTACT_COLOR: - pidgin_blist_theme_set_contact_color(theme, g_value_get_pointer(value)); + pidgin_blist_theme_set_contact_color(theme, g_value_get_boxed(value)); break; case PROP_CONTACT: pidgin_blist_theme_set_contact_text_info(theme, g_value_get_pointer(value)); @@ -252,25 +320,29 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(obj); /* Buddy List */ - gdk_color_free(priv->bgcolor); + if (priv->bgcolor) + gdk_color_free(priv->bgcolor); g_free(priv->layout); /* Group */ - gdk_color_free(priv->expanded_color); - free_font_and_color(priv->expanded); - gdk_color_free(priv->collapsed_color); - free_font_and_color(priv->collapsed); + if (priv->expanded_color) + gdk_color_free(priv->expanded_color); + pidgin_theme_font_free(priv->expanded); + if (priv->collapsed_color) + gdk_color_free(priv->collapsed_color); + pidgin_theme_font_free(priv->collapsed); /* Buddy */ - gdk_color_free(priv->contact_color); - free_font_and_color(priv->contact); - free_font_and_color(priv->online); - free_font_and_color(priv->away); - free_font_and_color(priv->offline); - free_font_and_color(priv->idle); - free_font_and_color(priv->message); - free_font_and_color(priv->message_nick_said); - free_font_and_color(priv->status); + if (priv->contact_color) + gdk_color_free(priv->contact_color); + pidgin_theme_font_free(priv->contact); + pidgin_theme_font_free(priv->online); + pidgin_theme_font_free(priv->away); + pidgin_theme_font_free(priv->offline); + pidgin_theme_font_free(priv->idle); + pidgin_theme_font_free(priv->message); + pidgin_theme_font_free(priv->message_nick_said); + pidgin_theme_font_free(priv->status); g_free(priv); @@ -290,81 +362,81 @@ obj_class->finalize = pidgin_blist_theme_finalize; /* Buddy List */ - pspec = g_param_spec_pointer("background-color", "Background Color", - "The background color for the buddy list", - G_PARAM_READWRITE); + pspec = g_param_spec_boxed("background-color", _("Background Color"), + _("The background color for the buddy list"), + GDK_TYPE_COLOR, G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_BACKGROUND_COLOR, pspec); - pspec = g_param_spec_pointer("layout", "Layout", - "The layout of icons, name, and status of the blist", + pspec = g_param_spec_pointer("layout", _("Layout"), + _("The layout of icons, name, and status of the blist"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_LAYOUT, pspec); /* Group */ - pspec = g_param_spec_pointer("expanded-color", "Expanded Background Color", - "The background color of an expanded group", - G_PARAM_READWRITE); + pspec = g_param_spec_boxed("expanded-color", _("Expanded Background Color"), + _("The background color of an expanded group"), + GDK_TYPE_COLOR, G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_EXPANDED_COLOR, pspec); - pspec = g_param_spec_pointer("expanded-text", "Expanded Text", - "The text information for when a group is expanded", + pspec = g_param_spec_pointer("expanded-text", _("Expanded Text"), + _("The text information for when a group is expanded"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_EXPANDED_TEXT, pspec); - pspec = g_param_spec_pointer("collapsed-color", "Collapsed Background Color", - "The background color of a collapsed group", - G_PARAM_READWRITE); + pspec = g_param_spec_boxed("collapsed-color", _("Collapsed Background Color"), + _("The background color of a collapsed group"), + GDK_TYPE_COLOR, G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_COLLAPSED_COLOR, pspec); - pspec = g_param_spec_pointer("collapsed-text", "Collapsed Text", - "The text information for when a group is collapsed", + pspec = g_param_spec_pointer("collapsed-text", _("Collapsed Text"), + _("The text information for when a group is collapsed"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_COLLAPSED_TEXT, pspec); /* Buddy */ - pspec = g_param_spec_pointer("contact-color", "Contact/Chat Background Color", - "The background color of a contact or chat", - G_PARAM_READWRITE); + pspec = g_param_spec_boxed("contact-color", _("Contact/Chat Background Color"), + _("The background color of a contact or chat"), + GDK_TYPE_COLOR, G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_CONTACT_COLOR, pspec); - pspec = g_param_spec_pointer("contact", "Contact Text", - "The text information for when a contact is expanded", + pspec = g_param_spec_pointer("contact", _("Contact Text"), + _("The text information for when a contact is expanded"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_CONTACT, pspec); - pspec = g_param_spec_pointer("online", "On-line Text", - "The text information for when a buddy is online", + pspec = g_param_spec_pointer("online", _("On-line Text"), + _("The text information for when a buddy is online"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_ONLINE, pspec); - pspec = g_param_spec_pointer("away", "Away Text", - "The text information for when a buddy is away", + pspec = g_param_spec_pointer("away", _("Away Text"), + _("The text information for when a buddy is away"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_AWAY, pspec); - pspec = g_param_spec_pointer("offline", "Off-line Text", - "The text information for when a buddy is off-line", + pspec = g_param_spec_pointer("offline", _("Off-line Text"), + _("The text information for when a buddy is off-line"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_OFFLINE, pspec); - pspec = g_param_spec_pointer("idle", "Idle Text", - "The text information for when a buddy is idle", + pspec = g_param_spec_pointer("idle", _("Idle Text"), + _("The text information for when a buddy is idle"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_IDLE, pspec); - pspec = g_param_spec_pointer("message", "Message Text", - "The text information for when a buddy has an unread message", + pspec = g_param_spec_pointer("message", _("Message Text"), + _("The text information for when a buddy has an unread message"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_MESSAGE, pspec); - pspec = g_param_spec_pointer("message_nick_said", "Message (Nick Said) Text", - "The text information for when a chat has an unread message that mentions your nick", + pspec = g_param_spec_pointer("message_nick_said", _("Message (Nick Said) Text"), + _("The text information for when a chat has an unread message that mentions your nick"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_MESSAGE_NICK_SAID, pspec); - pspec = g_param_spec_pointer("status", "Status Text", - "The text information for a buddy's status", + pspec = g_param_spec_pointer("status", _("Status Text"), + _("The text information for a buddy's status"), G_PARAM_READWRITE); g_object_class_install_property(obj_class, PROP_STATUS, pspec); } @@ -447,7 +519,7 @@ return priv->expanded_color; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -471,7 +543,7 @@ return priv->collapsed_color; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -495,7 +567,7 @@ return priv->contact_color; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_contact_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -507,7 +579,7 @@ return priv->contact; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -519,7 +591,7 @@ return priv->online; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -531,7 +603,7 @@ return priv->away; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -543,7 +615,7 @@ return priv->offline; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_idle_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -555,7 +627,7 @@ return priv->idle; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -567,7 +639,7 @@ return priv->message; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_unread_message_nick_said_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -579,7 +651,7 @@ return priv->message_nick_said; } -FontColorPair * +PidginThemeFont * pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme) { PidginBlistThemePrivate *priv; @@ -601,7 +673,8 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - gdk_color_free(priv->bgcolor); + if (priv->bgcolor) + gdk_color_free(priv->bgcolor); priv->bgcolor = gdk_color_copy(color); } @@ -639,12 +712,13 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - gdk_color_free(priv->expanded_color); + if (priv->expanded_color) + gdk_color_free(priv->expanded_color); priv->expanded_color = gdk_color_copy(color); } void -pidgin_blist_theme_set_expanded_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_expanded_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -652,7 +726,7 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->expanded); + pidgin_theme_font_free(priv->expanded); priv->expanded = copy_font_and_color(pair); } @@ -665,12 +739,13 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - gdk_color_free(priv->collapsed_color); + if (priv->collapsed_color) + gdk_color_free(priv->collapsed_color); priv->collapsed_color = gdk_color_copy(color); } void -pidgin_blist_theme_set_collapsed_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_collapsed_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -678,7 +753,7 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->collapsed); + pidgin_theme_font_free(priv->collapsed); priv->collapsed = copy_font_and_color(pair); } @@ -691,12 +766,13 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - gdk_color_free(priv->contact_color); + if (priv->contact_color) + gdk_color_free(priv->contact_color); priv->contact_color = gdk_color_copy(color); } void -pidgin_blist_theme_set_contact_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_contact_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -704,12 +780,12 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->contact); + pidgin_theme_font_free(priv->contact); priv->contact = copy_font_and_color(pair); } void -pidgin_blist_theme_set_online_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_online_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -717,12 +793,12 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->online); + pidgin_theme_font_free(priv->online); priv->online = copy_font_and_color(pair); } void -pidgin_blist_theme_set_away_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_away_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -730,12 +806,12 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->away); + pidgin_theme_font_free(priv->away); priv->away = copy_font_and_color(pair); } void -pidgin_blist_theme_set_offline_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_offline_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -743,12 +819,12 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->offline); + pidgin_theme_font_free(priv->offline); priv->offline = copy_font_and_color(pair); } void -pidgin_blist_theme_set_idle_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_idle_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -756,12 +832,12 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->idle); + pidgin_theme_font_free(priv->idle); priv->idle = copy_font_and_color(pair); } void -pidgin_blist_theme_set_unread_message_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_unread_message_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -769,12 +845,12 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->message); + pidgin_theme_font_free(priv->message); priv->message = copy_font_and_color(pair); } void -pidgin_blist_theme_set_unread_message_nick_said_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_unread_message_nick_said_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -782,12 +858,12 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->message_nick_said); + pidgin_theme_font_free(priv->message_nick_said); priv->message_nick_said = copy_font_and_color(pair); } void -pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, const FontColorPair *pair) +pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair) { PidginBlistThemePrivate *priv; @@ -795,6 +871,6 @@ priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); - free_font_and_color(priv->status); + pidgin_theme_font_free(priv->status); priv->status = copy_font_and_color(pair); }
--- a/pidgin/gtkblist-theme.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkblist-theme.h Sat Apr 25 19:09:36 2009 +0000 @@ -59,12 +59,15 @@ PurpleThemeClass parent_class; }; +#if 0 typedef struct { const gchar *font; const gchar *color; -} FontColorPair; +} PidginThemeFont; +#endif +typedef struct _PidginThemeFont PidginThemeFont; typedef struct { @@ -78,13 +81,68 @@ } PidginBlistLayout; /**************************************************************************/ -/** @name FontColorPair API */ +/** @name PidginThemeFont API */ /**************************************************************************/ /** + * Create a new PidginThemeFont. + * + * @param face The font face + * @param color The color of the font + * + * @return A newly created PidginThemeFont + */ +PidginThemeFont * pidgin_theme_font_new(const gchar *face, GdkColor *color); + +/** * Frees a font and color pair + * + * @param font The theme font + */ +void pidgin_theme_font_free(PidginThemeFont *font); + +/** + * Set the font-face of a PidginThemeFont. + * + * @param font The PidginThemeFont + * @param face The font-face */ -void free_font_and_color(FontColorPair *pair); +void pidgin_theme_font_set_font_face(PidginThemeFont *font, const gchar *face); + +/** + * Set the color of a PidginThemeFont. + * + * @param font The PidginThemeFont + * @param color The color + */ +void pidgin_theme_font_set_color(PidginThemeFont *font, const GdkColor *color); + +/** + * Get the font-face of a PidginThemeFont. + * + * @param font The PidginThemeFont + * + * @return The font-face, or NULL if none is set. + */ +const gchar * pidgin_theme_font_get_font_face(PidginThemeFont *font); + +/** + * Get the color of a PidginThemeFont as a GdkColor object. + * + * @param font The PidginThemeFont + * + * @return The color, or NULL if none is set. + */ +const GdkColor * pidgin_theme_font_get_color(PidginThemeFont *font); + +/** + * Get the color of a PidginThemeFont. + * + * @param font The PidginThemeFont + * + * @return The color, or NULL if none is set. + */ +const gchar * pidgin_theme_font_get_color_describe(PidginThemeFont *font); /**************************************************************************/ /** @name Purple Buddy List Theme API */ @@ -102,6 +160,8 @@ /** * Returns the background color of the buddy list. * + * @param theme The PidginBlist theme. + * * @returns A gdk color. */ GdkColor *pidgin_blist_theme_get_background_color(PidginBlistTheme *theme); @@ -110,6 +170,8 @@ * Returns the opacity of the buddy list window * (0.0 or clear to 1.0 fully opaque). * + * @param theme The PidginBlist theme. + * * @returns The opacity */ gdouble pidgin_blist_theme_get_opacity(PidginBlistTheme *theme); @@ -117,6 +179,8 @@ /** * Returns the layout to be used with the buddy list. * + * @param theme The PidginBlist theme. + * * @returns The buddy list layout. */ PidginBlistLayout *pidgin_blist_theme_get_layout(PidginBlistTheme *theme); @@ -124,6 +188,8 @@ /** * Returns the background color to be used with expanded groups. * + * @param theme The PidginBlist theme. + * * @returns A gdk color. */ GdkColor *pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme); @@ -131,13 +197,17 @@ /** * Returns the text font and color to be used with expanded groups. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme); /** * Returns the background color to be used with collapsed groups. * + * @param theme The PidginBlist theme. + * * @returns A gdk color. */ GdkColor *pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme); @@ -145,13 +215,17 @@ /** * Returns the text font and color to be used with collapsed groups. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme); /** * Returns the colors to be used for contacts and chats. * + * @param theme The PidginBlist theme. + * * @returns A gdkcolor for contacts and chats. */ GdkColor *pidgin_blist_theme_get_contact_color(PidginBlistTheme *theme); @@ -159,65 +233,82 @@ /** * Returns the text font and color to be used for expanded contacts. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_contact_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_contact_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for online buddies. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for away and idle buddies. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for offline buddies. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for idle buddies. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_idle_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_idle_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for buddies with unread messages. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for chats with unread messages * that mention your nick. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_unread_message_nick_said_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_unread_message_nick_said_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for a buddy's status message. * + * @param theme The PidginBlist theme. + * * @returns A font and color pair. */ - FontColorPair *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme); + PidginThemeFont *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme); /* Set Methods */ /** * Sets the background color to be used for this buddy list theme. * + * @param theme The PidginBlist theme. * @param color The new background color. */ void pidgin_blist_theme_set_background_color(PidginBlistTheme *theme, const GdkColor *color); @@ -225,6 +316,7 @@ /** * Sets the opacity to be used for this buddy list theme. * + * @param theme The PidginBlist theme. * @param opacity The new opacity setting. */ void pidgin_blist_theme_set_opacity(PidginBlistTheme *theme, gdouble opacity); @@ -232,6 +324,7 @@ /** * Sets the buddy list layout to be used for this buddy list theme. * + * @param theme The PidginBlist theme. * @param layout The new layout. */ void pidgin_blist_theme_set_layout(PidginBlistTheme *theme, const PidginBlistLayout *layout); @@ -239,6 +332,7 @@ /** * Sets the background color to be used for expanded groups. * + * @param theme The PidginBlist theme. * @param color The new background color. */ void pidgin_blist_theme_set_expanded_background_color(PidginBlistTheme *theme, const GdkColor *color); @@ -246,13 +340,15 @@ /** * Sets the text color and font to be used for expanded groups. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_expanded_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_expanded_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the background color to be used for collapsed groups. * + * @param theme The PidginBlist theme. * @param color The new background color. */ void pidgin_blist_theme_set_collapsed_background_color(PidginBlistTheme *theme, const GdkColor *color); @@ -260,13 +356,15 @@ /** * Sets the text color and font to be used for expanded groups. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_collapsed_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_collapsed_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the background color to be used for contacts and chats. * + * @param theme The PidginBlist theme. * @param color The color to use for contacts and chats. */ void pidgin_blist_theme_set_contact_color(PidginBlistTheme *theme, const GdkColor *color); @@ -274,59 +372,67 @@ /** * Sets the text color and font to be used for expanded contacts. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_contact_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_contact_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the text color and font to be used for online buddies. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_online_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_online_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the text color and font to be used for away and idle buddies. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_away_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_away_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the text color and font to be used for offline buddies. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_offline_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_offline_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the text color and font to be used for idle buddies. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_idle_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_idle_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the text color and font to be used for buddies with unread messages. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_unread_message_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_unread_message_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the text color and font to be used for a chat with unread messages * that mention your nick. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_unread_message_nick_said_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_unread_message_nick_said_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); /** * Sets the text color and font to be used for buddy status messages. * + * @param theme The PidginBlist theme. * @param pair The new text font at color pair. */ -void pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, const FontColorPair *pair); +void pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); G_END_DECLS #endif /* PIDGIN_BLIST_THEME_H */
--- a/pidgin/gtkblist.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkblist.c Sat Apr 25 19:09:36 2009 +0000 @@ -3902,6 +3902,24 @@ return ret; } +static const char * +theme_font_get_color_default(PidginThemeFont *font, const char *def) +{ + const char *ret; + if (!font || !(ret = pidgin_theme_font_get_color_describe(font))) + ret = def; + return ret; +} + +static const char * +theme_font_get_face_default(PidginThemeFont *font, const char *def) +{ + const char *ret; + if (!font || !(ret = pidgin_theme_font_get_font_face(font))) + ret = def; + return ret; +} + gchar * pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased) { @@ -3916,7 +3934,7 @@ PurpleConversation *conv = find_conversation_with_buddy(b); gboolean hidden_conv = FALSE; gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); - FontColorPair *pair = NULL; + PidginThemeFont *statusfont = NULL, *namefont = NULL; PidginBlistTheme *theme; if (conv != NULL) { @@ -4034,46 +4052,29 @@ /* choose the colors of the text */ theme = pidgin_blist_get_theme(); - - if (purple_presence_is_idle(presence)) { - if (theme) - pair = pidgin_blist_theme_get_idle_text_info(theme); - status_color = name_color = (pair != NULL && pair->color != NULL) ? pair->color : "dim grey"; - status_font = name_font = (pair != NULL && pair->font != NULL) ? pair->font : ""; - - } else if (!purple_presence_is_online(presence)) { - if (theme) - pair = pidgin_blist_theme_get_offline_text_info(theme); - name_color = (pair != NULL && pair->color != NULL) ? pair->color : NULL; - name_font = (pair != NULL && pair->font != NULL) ? pair->font : ""; - - if (theme) - pair = pidgin_blist_theme_get_status_text_info(theme); - status_color = (pair != NULL && pair->color != NULL) ? pair->color : "dim grey"; - status_font = (pair != NULL && pair->font != NULL) ? pair->font : ""; - - } else if (purple_presence_is_available(presence)) { - if (theme) - pair = pidgin_blist_theme_get_online_text_info(theme); - name_color = (pair != NULL && pair->color != NULL) ? pair->color : NULL; - name_font = (pair != NULL && pair->font != NULL) ? pair->font : ""; - - if (theme) - pair = pidgin_blist_theme_get_status_text_info(theme); - status_color = (pair != NULL && pair->color != NULL) ? pair->color : "dim grey"; - status_font = (pair != NULL && pair->font != NULL) ? pair->font : ""; - - } else { - if (theme) - pair = pidgin_blist_theme_get_away_text_info(theme); - name_color = (pair != NULL && pair->color != NULL) ? pair->color : NULL; - name_font = (pair != NULL && pair->font != NULL) ? pair->font : ""; - - if (theme) - pair = pidgin_blist_theme_get_status_text_info(theme); - status_color = (pair != NULL && pair->color != NULL) ? pair->color : "dim grey"; - status_font = (pair != NULL && pair->font != NULL) ? pair->font : ""; - } + name_color = NULL; + + if (theme) { + if (purple_presence_is_idle(presence)) { + namefont = statusfont = pidgin_blist_theme_get_idle_text_info(theme); + name_color = "dim grey"; + } else if (!purple_presence_is_online(presence)) { + namefont = pidgin_blist_theme_get_offline_text_info(theme); + statusfont = pidgin_blist_theme_get_status_text_info(theme); + } else if (purple_presence_is_available(presence)) { + namefont = pidgin_blist_theme_get_online_text_info(theme); + statusfont = pidgin_blist_theme_get_status_text_info(theme); + } else { + namefont = pidgin_blist_theme_get_away_text_info(theme); + statusfont = pidgin_blist_theme_get_status_text_info(theme); + } + } + + name_color = theme_font_get_color_default(namefont, name_color); + name_font = theme_font_get_face_default(namefont, ""); + + status_color = theme_font_get_color_default(statusfont, "dim grey"); + status_font = theme_font_get_face_default(statusfont, ""); if (aliased && selected) { if (theme) { @@ -6196,7 +6197,7 @@ char *mark, *esc; PurpleBlistNode *selected_node = NULL; GtkTreeIter iter; - FontColorPair *pair; + PidginThemeFont *pair; gchar const *text_color, *text_font; PidginBlistTheme *theme; @@ -6223,8 +6224,8 @@ pair = pidgin_blist_theme_get_collapsed_text_info(theme); - text_color = (selected || pair == NULL || pair->color == NULL) ? NULL : pair->color; - text_font = (pair == NULL || pair->font == NULL) ? "" : pair->font; + text_color = selected ? NULL : theme_font_get_color_default(pair, NULL); + text_font = theme_font_get_face_default(pair, ""); esc = g_markup_escape_text(group->name, -1); if (text_color) { @@ -6282,7 +6283,7 @@ if (idle_secs > 0) { - FontColorPair *pair = NULL; + PidginThemeFont *pair = NULL; const gchar *textcolor; time_t t; int ihrs, imin; @@ -6291,18 +6292,18 @@ ihrs = (t - idle_secs) / 3600; imin = ((t - idle_secs) / 60) % 60; - if (!selected && theme != NULL && (pair = pidgin_blist_theme_get_idle_text_info(theme)) != NULL && pair->color != NULL) - textcolor = pair->color; + if (!selected && theme != NULL && (pair = pidgin_blist_theme_get_idle_text_info(theme)) != NULL) + textcolor = pidgin_theme_font_get_color_describe(pair); else textcolor = NULL; if (textcolor) { idle = g_strdup_printf("<span color='%s' font_desc='%s'>%d:%02d</span>", - textcolor, (pair == NULL || pair->font == NULL) ? "" : pair->font, + textcolor, theme_font_get_face_default(pair, ""), ihrs, imin); } else { idle = g_strdup_printf("<span font_desc='%s'>%d:%02d</span>", - (pair == NULL || pair->font == NULL) ? "" : pair->font, + theme_font_get_face_default(pair, ""), ihrs, imin); } } @@ -6387,7 +6388,7 @@ const gchar *fg_color, *font; GdkColor *color = NULL; PidginBlistTheme *theme = pidgin_blist_get_theme(); - FontColorPair *pair; + PidginThemeFont *pair; gboolean selected = (gtkblist->selected_node == cnode); mark = g_markup_escape_text(purple_contact_get_alias(contact), -1); @@ -6400,8 +6401,8 @@ color = pidgin_blist_theme_get_contact_color(theme); } - font = (pair == NULL || pair->font == NULL) ? "" : pair->font; - fg_color = (selected || pair == NULL || pair->color == NULL) ? NULL : pair->color; + font = theme_font_get_face_default(pair, ""); + fg_color = selected ? NULL : theme_font_get_color_default(pair, NULL); if (fg_color) { tmp = g_strdup_printf("<span font_desc='%s' color='%s'>%s</span>", @@ -6498,7 +6499,7 @@ PurpleConversation *conv; gboolean hidden = FALSE; GdkColor *bgcolor = NULL; - FontColorPair *pair; + PidginThemeFont *pair; PidginBlistTheme *theme; gboolean selected = (gtkblist->selected_node == node); gboolean nick_said = FALSE; @@ -6536,12 +6537,10 @@ else pair = pidgin_blist_theme_get_online_text_info(theme); - font = (pair == NULL || pair->font == NULL) ? "" : pair->font; - if (selected || pair == NULL || pair->color == NULL) + font = theme_font_get_face_default(pair, ""); + if (selected || !(color = theme_font_get_color_default(pair, NULL))) /* nick_said color is the same as gtkconv:tab-label-attention */ color = (nick_said ? "#006aff" : NULL); - else - color = pair->color; if (color) { tmp = g_strdup_printf("<span font_desc='%s' color='%s' weight='%s'>%s</span>",
--- a/pidgin/gtkconv.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkconv.c Sat Apr 25 19:09:36 2009 +0000 @@ -2512,13 +2512,49 @@ return get_prpl_icon_list(account); } +static const char * +pidgin_conv_get_icon_stock(PurpleConversation *conv) +{ + PurpleAccount *account = NULL; + const char *stock = NULL; + + g_return_val_if_fail(conv != NULL, NULL); + + account = purple_conversation_get_account(conv); + g_return_val_if_fail(account != NULL, NULL); + + /* Use the buddy icon, if possible */ + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + const char *name = NULL; + PurpleBuddy *b; + name = purple_conversation_get_name(conv); + b = purple_find_buddy(account, name); + if (b != NULL) { + PurplePresence *p = purple_buddy_get_presence(b); + PurpleStatus *active = purple_presence_get_active_status(p); + PurpleStatusType *type = purple_status_get_type(active); + PurpleStatusPrimitive prim = purple_status_type_get_primitive(type); + stock = pidgin_stock_id_from_status_primitive(prim); + } else { + stock = PIDGIN_STOCK_STATUS_PERSON; + } + } else { + stock = PIDGIN_STOCK_STATUS_CHAT; + } + + return stock; +} + static GdkPixbuf * pidgin_conv_get_icon(PurpleConversation *conv, GtkWidget *parent, const char *icon_size) { PurpleAccount *account = NULL; const char *name = NULL; + const char *stock = NULL; GdkPixbuf *status = NULL; PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + GtkIconSize size; + g_return_val_if_fail(conv != NULL, NULL); account = purple_conversation_get_account(conv); @@ -2531,40 +2567,17 @@ if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { PurpleBuddy *b = purple_find_buddy(account, name); if (b != NULL) { - PurplePresence *p = purple_buddy_get_presence(b); /* I hate this hack. It fixes a bug where the pending message icon * displays in the conv tab even though it shouldn't. * A better solution would be great. */ if (ops && ops->update) ops->update(NULL, (PurpleBlistNode*)b); - - /* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */ - if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY)) - status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, parent, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY)) - status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, parent, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) - status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, parent, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE)) - status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, parent, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) - status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, parent, icon_size); - else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) - status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, parent, icon_size); - } - } - - /* If they don't have a buddy icon, then use the PRPL icon */ - if (status == NULL) { - GtkIconSize size = gtk_icon_size_from_name(icon_size); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_PERSON, - size, "GtkWidget"); - } else { - status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_CHAT, - size, "GtkWidget"); - } - } + } + } + + stock = pidgin_conv_get_icon_stock(conv); + size = gtk_icon_size_from_name(icon_size); + status = gtk_widget_render_icon (parent, stock, size, "GtkWidget"); return status; } @@ -2582,9 +2595,9 @@ PidginConversation *gtkconv; PidginWindow *win; GList *l; - GdkPixbuf *status = NULL; - GdkPixbuf *infopane_status = NULL; GdkPixbuf *emblem = NULL; + const char *status = NULL; + const char *infopane_status = NULL; g_return_if_fail(conv != NULL); @@ -2593,8 +2606,7 @@ if (conv != gtkconv->active_conv) return; - status = pidgin_conv_get_tab_icon(conv, TRUE); - infopane_status = pidgin_conv_get_tab_icon(conv, FALSE); + status = infopane_status = pidgin_conv_get_icon_stock(conv); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { PurpleBuddy *b = purple_find_buddy(conv->account, conv->name); @@ -2604,8 +2616,8 @@ g_return_if_fail(status != NULL); - gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status); - gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status); + g_object_set(G_OBJECT(gtkconv->icon), "stock", status, NULL); + g_object_set(G_OBJECT(gtkconv->menu_icon), "stock", status, NULL); gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), &(gtkconv->infopane_iter), @@ -2633,9 +2645,6 @@ gtk_widget_queue_resize(gtkconv->infopane); gtk_widget_queue_draw(gtkconv->infopane); - if (status != NULL) - g_object_unref(status); - if (pidgin_conv_window_is_active_conversation(conv) && (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM || gtkconv->u.im->anim == NULL)) @@ -3071,16 +3080,13 @@ PurpleConversation *conv = (PurpleConversation*)l->data; PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - GtkWidget *icon = gtk_image_new(); - GdkPixbuf *pbuf = pidgin_conv_get_icon(conv, icon, PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC); + GtkWidget *icon = gtk_image_new_from_stock(pidgin_conv_get_icon_stock(conv), + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC)); GtkWidget *item; gchar *text = g_strdup_printf("%s (%d)", gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)), gtkconv->unseen_count); - gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf); - g_object_unref(pbuf); - item = gtk_image_menu_item_new_with_label(text); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(unseen_conv_menu_cb), conv); @@ -3941,12 +3947,9 @@ update_send_to_selection(win); } -static GdkPixbuf * +static const char * get_chat_buddy_status_icon(PurpleConvChat *chat, const char *name, PurpleConvChatBuddyFlags flags) { - PidginConversation *gtkconv = PIDGIN_CONVERSATION(chat->conv); - GdkPixbuf *pixbuf, *scale, *scale2; - char *filename; const char *image = NULL; if (flags & PURPLE_CBFLAGS_FOUNDER) { @@ -3962,28 +3965,7 @@ } else { return NULL; } - - pixbuf = gtk_widget_render_icon (gtkconv->tab_cont, image, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), - "GtkTreeView"); - - if (!pixbuf) - return NULL; - - scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR); - g_object_unref(pixbuf); - - if (flags && purple_conv_chat_is_user_ignored(chat, name)) { -/* TODO: the .../status/default directory isn't installed, should it be? */ - filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "status", "default", "ignored.png", NULL); - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - scale2 = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR); - g_object_unref(pixbuf); - gdk_pixbuf_composite(scale2, scale, 0, 0, 16, 16, 0, 0, 1, 1, GDK_INTERP_BILINEAR, 192); - g_object_unref(scale2); - } - - return scale; + return image; } static void @@ -3995,7 +3977,7 @@ PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info; GtkListStore *ls; - GdkPixbuf *pixbuf; + const char *stock; GtkTreeIter iter; gboolean is_me = FALSE; gboolean is_buddy; @@ -4017,7 +3999,7 @@ ls = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list))); - pixbuf = get_chat_buddy_status_icon(chat, name, flags); + stock = get_chat_buddy_status_icon(chat, name, flags); if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) is_me = TRUE; @@ -4052,7 +4034,7 @@ * Inserting in the "wrong" location has no visible ill effects. - F.P. */ -1, /* "row" */ - CHAT_USERS_ICON_COLUMN, pixbuf, + CHAT_USERS_ICON_STOCK_COLUMN, stock, CHAT_USERS_ALIAS_COLUMN, alias, CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, CHAT_USERS_NAME_COLUMN, name, @@ -4063,7 +4045,7 @@ #else gtk_list_store_append(ls, &iter); gtk_list_store_set(ls, &iter, - CHAT_USERS_ICON_COLUMN, pixbuf, + CHAT_USERS_ICON_STOCK_COLUMN, stock, CHAT_USERS_ALIAS_COLUMN, alias, CHAT_USERS_ALIAS_KEY_COLUMN, alias_key, CHAT_USERS_NAME_COLUMN, name, @@ -4073,8 +4055,6 @@ -1); #endif - if (pixbuf) - g_object_unref(pixbuf); if (is_me && color) gdk_color_free(color); g_free(alias_key); @@ -4721,16 +4701,18 @@ ls = gtk_list_store_new(CHAT_USERS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, - GDK_TYPE_COLOR, G_TYPE_INT); + GDK_TYPE_COLOR, G_TYPE_INT, G_TYPE_STRING); gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(ls), CHAT_USERS_ALIAS_KEY_COLUMN, sort_chat_users, NULL, NULL); list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls)); rend = gtk_cell_renderer_pixbuf_new(); - + g_object_set(G_OBJECT(rend), + "stock-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), + NULL); col = gtk_tree_view_column_new_with_attributes(NULL, rend, - "pixbuf", CHAT_USERS_ICON_COLUMN, NULL); + "stock-id", CHAT_USERS_ICON_STOCK_COLUMN, NULL); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_append_column(GTK_TREE_VIEW(list), col); ul_width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width"); @@ -4757,7 +4739,7 @@ "foreground-set", TRUE, "weight-set", TRUE, NULL); - g_object_set(G_OBJECT(rend), "editable", TRUE, NULL); + g_object_set(G_OBJECT(rend), "editable", TRUE, NULL); col = gtk_tree_view_column_new_with_attributes(NULL, rend, "text", CHAT_USERS_ALIAS_COLUMN, @@ -4848,7 +4830,7 @@ pidgin_conv_create_tooltip, NULL); gtkconv->infopane = gtk_cell_view_new(); - gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF); + gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF); gtk_cell_view_set_model(GTK_CELL_VIEW(gtkconv->infopane), GTK_TREE_MODEL(gtkconv->infopane_model)); g_object_unref(gtkconv->infopane_model); @@ -4871,8 +4853,10 @@ rend = gtk_cell_renderer_pixbuf_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_ICON_COLUMN, NULL); - g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "stock-id", CONV_ICON_COLUMN, NULL); + g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, + "stock-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), + NULL); rend = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, TRUE); @@ -9434,6 +9418,12 @@ /* Status icon. */ gtkconv->icon = gtk_image_new(); gtkconv->menu_icon = gtk_image_new(); + g_object_set(G_OBJECT(gtkconv->icon), + "icon-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC), + NULL); + g_object_set(G_OBJECT(gtkconv->menu_icon), + "icon-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC), + NULL); gtk_widget_show(gtkconv->icon); update_tab_icon(conv);
--- a/pidgin/gtkconv.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkconv.h Sat Apr 25 19:09:36 2009 +0000 @@ -51,6 +51,7 @@ CHAT_USERS_FLAGS_COLUMN, CHAT_USERS_COLOR_COLUMN, CHAT_USERS_WEIGHT_COLUMN, + CHAT_USERS_ICON_STOCK_COLUMN, /** @since 2.6.0 */ CHAT_USERS_COLUMNS };
--- a/pidgin/gtkicon-theme-loader.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkicon-theme-loader.h Sat Apr 25 19:09:36 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file gtkicon-loader.h Pidgin Icon Theme Loader Class API + * @file gtkicon-theme-loader.h Pidgin Icon Theme Loader Class API */ /* purple
--- a/pidgin/gtkicon-theme.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkicon-theme.h Sat Apr 25 19:09:36 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file icon-theme.h Pidgin Icon Theme Class API + * @file gtkicon-theme.h Pidgin Icon Theme Class API */ /* pidgin
--- a/pidgin/gtknotify.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtknotify.h Sat Apr 25 19:09:36 2009 +0000 @@ -32,8 +32,10 @@ /** * Adds a buddy pounce to the buddy pounce dialog * + * @param account The account + * @param pounce The pounce * @param alias The buddy alias - * @param event Event description + * @param event Event description * @param message Pounce message * @param date Pounce date */
--- a/pidgin/gtksavedstatuses.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtksavedstatuses.c Sat Apr 25 19:09:36 2009 +0000 @@ -398,23 +398,7 @@ static const gchar * get_stock_icon_from_primitive(PurpleStatusPrimitive type) { - switch (type) { - case PURPLE_STATUS_AVAILABLE: - return PIDGIN_STOCK_STATUS_AVAILABLE; - case PURPLE_STATUS_AWAY: - return PIDGIN_STOCK_STATUS_AWAY; - case PURPLE_STATUS_EXTENDED_AWAY: - return PIDGIN_STOCK_STATUS_XA; - case PURPLE_STATUS_INVISIBLE: - return PIDGIN_STOCK_STATUS_INVISIBLE; - case PURPLE_STATUS_OFFLINE: - return PIDGIN_STOCK_STATUS_OFFLINE; - case PURPLE_STATUS_UNAVAILABLE: - return PIDGIN_STOCK_STATUS_BUSY; - default: - /* this shouldn't happen */ - return NULL; - } + return pidgin_stock_id_from_status_primitive(type); } static void @@ -1503,16 +1487,19 @@ gtk_size_group_add_widget(sg, label); dialog->model = gtk_list_store_new(SUBSTATUS_NUM_COLUMNS, - GDK_TYPE_PIXBUF, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(dialog->model)); dialog->box = GTK_COMBO_BOX(combo); rend = GTK_CELL_RENDERER(gtk_cell_renderer_pixbuf_new()); + g_object_set(G_OBJECT(rend), + "stock-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), + NULL); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, FALSE); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), rend, - "pixbuf", SUBSTATUS_COLUMN_ICON, NULL); + "stock-id", SUBSTATUS_COLUMN_ICON, NULL); rend = GTK_CELL_RENDERER(gtk_cell_renderer_text_new()); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, TRUE); @@ -1574,8 +1561,8 @@ for (list = purple_account_get_status_types(account); list; list = list->next) { PurpleStatusType *status_type; - GdkPixbuf *pixbuf; const char *id, *name; + PurpleStatusPrimitive prim; status_type = list->data; @@ -1588,17 +1575,15 @@ continue; id = purple_status_type_get_id(status_type); - pixbuf = pidgin_create_status_icon(purple_status_type_get_primitive(status_type), combo, PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL); + prim = purple_status_type_get_primitive(status_type); name = purple_status_type_get_name(status_type); gtk_list_store_append(dialog->model, &iter); gtk_list_store_set(dialog->model, &iter, - SUBSTATUS_COLUMN_ICON, pixbuf, + SUBSTATUS_COLUMN_ICON, pidgin_stock_id_from_status_primitive(prim), SUBSTATUS_COLUMN_STATUS_ID, id, SUBSTATUS_COLUMN_STATUS_NAME, name, -1); - if (pixbuf != NULL) - g_object_unref(pixbuf); if ((status_id != NULL) && !strcmp(status_id, id)) { gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo), &iter); @@ -1705,18 +1690,15 @@ { GtkTreeIter iter; gboolean currently_selected = FALSE; - GdkPixbuf *pixbuf = pidgin_create_status_icon(primitive, w, PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL); gtk_list_store_append(model, &iter); gtk_list_store_set(model, &iter, SS_MENU_TYPE_COLUMN, SS_MENU_ENTRY_TYPE_PRIMITIVE, - SS_MENU_ICON_COLUMN, pixbuf, + SS_MENU_ICON_COLUMN, pidgin_stock_id_from_status_primitive(primitive), SS_MENU_TEXT_COLUMN, purple_primitive_get_name_from_type(primitive), SS_MENU_DATA_COLUMN, GINT_TO_POINTER(primitive), SS_MENU_EMBLEM_VISIBLE_COLUMN, FALSE, -1); - if (pixbuf != NULL) - g_object_unref(pixbuf); if (purple_savedstatus_is_transient(current_status) && !purple_savedstatus_has_substatuses(current_status) @@ -1730,23 +1712,20 @@ pidgin_status_menu_update_iter(GtkWidget *combobox, GtkListStore *store, GtkTreeIter *iter, PurpleSavedStatus *status) { - GdkPixbuf *pixbuf; + PurpleStatusPrimitive primitive; if (store == NULL) store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combobox))); - pixbuf = pidgin_create_status_icon(purple_savedstatus_get_type(status), - combobox, PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL); + primitive = purple_savedstatus_get_type(status); gtk_list_store_set(store, iter, SS_MENU_TYPE_COLUMN, SS_MENU_ENTRY_TYPE_SAVEDSTATUS, - SS_MENU_ICON_COLUMN, pixbuf, + SS_MENU_ICON_COLUMN, pidgin_stock_id_from_status_primitive(primitive), SS_MENU_TEXT_COLUMN, purple_savedstatus_get_title(status), SS_MENU_DATA_COLUMN, GINT_TO_POINTER(purple_savedstatus_get_creation_time(status)), SS_MENU_EMBLEM_COLUMN, GTK_STOCK_SAVE, SS_MENU_EMBLEM_VISIBLE_COLUMN, TRUE, -1); - if (pixbuf) - g_object_unref(G_OBJECT(pixbuf)); } static gboolean @@ -1828,7 +1807,7 @@ GtkCellRenderer *icon_rend; GtkCellRenderer *emblem_rend; - model = gtk_list_store_new(SS_MENU_NUM_COLUMNS, G_TYPE_INT, GDK_TYPE_PIXBUF, + model = gtk_list_store_new(SS_MENU_NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN); combobox = gtk_combo_box_new(); @@ -1875,10 +1854,13 @@ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), icon_rend, FALSE); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), text_rend, TRUE); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), emblem_rend, FALSE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), icon_rend, "pixbuf", SS_MENU_ICON_COLUMN, NULL); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), icon_rend, "stock-id", SS_MENU_ICON_COLUMN, NULL); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), text_rend, "markup", SS_MENU_TEXT_COLUMN, NULL); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), emblem_rend, "stock-id", SS_MENU_EMBLEM_COLUMN, "visible", SS_MENU_EMBLEM_VISIBLE_COLUMN, NULL); + g_object_set(G_OBJECT(icon_rend), + "stock-size", gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), + NULL); gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), index); g_signal_connect(G_OBJECT(combobox), "changed", G_CALLBACK(status_menu_cb), callback);
--- a/pidgin/gtkstatus-icon-theme.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkstatus-icon-theme.h Sat Apr 25 19:09:36 2009 +0000 @@ -1,5 +1,5 @@ /** - * @file status_icon-theme.h Pidgin Icon Theme Class API + * @file gtkstatus-icon-theme.h Pidgin Icon Theme Class API */ /* pidgin
--- a/pidgin/gtkstatusbox.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkstatusbox.c Sat Apr 25 19:09:36 2009 +0000 @@ -98,6 +98,9 @@ /** A PidginStatusBoxItemType */ TYPE_COLUMN, + /** This is the stock-id for the icon. */ + ICON_STOCK_COLUMN, + /** * This is a GdkPixbuf (the other columns are strings). * This column is visible. @@ -599,32 +602,6 @@ ); } -static GdkPixbuf * -pidgin_status_box_get_pixbuf(PidginStatusBox *status_box, PurpleStatusPrimitive prim) -{ - GdkPixbuf *pixbuf; - GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL); - if (prim == PURPLE_STATUS_UNAVAILABLE) - pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), PIDGIN_STOCK_STATUS_BUSY, - icon_size, "PidginStatusBox"); - else if (prim == PURPLE_STATUS_AWAY) - pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), PIDGIN_STOCK_STATUS_AWAY, - icon_size, "PidginStatusBox"); - else if (prim == PURPLE_STATUS_EXTENDED_AWAY) - pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), PIDGIN_STOCK_STATUS_XA, - icon_size, "PidginStatusBox"); - else if (prim == PURPLE_STATUS_INVISIBLE) - pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), PIDGIN_STOCK_STATUS_INVISIBLE, - icon_size, "PidginStatusBox"); - else if (prim == PURPLE_STATUS_OFFLINE) - pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), PIDGIN_STOCK_STATUS_OFFLINE, - icon_size, "PidginStatusBox"); - else - pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box), PIDGIN_STOCK_STATUS_AVAILABLE, - icon_size, "PidginStatusBox"); - return pixbuf; -} - /** * This updates the text displayed on the status box so that it shows * the current status. This is the only function in this file that @@ -638,7 +615,8 @@ char aa_color[8]; PurpleSavedStatus *saved_status; char *primary, *secondary, *text; - GdkPixbuf *pixbuf, *emblem = NULL; + const char *stock = NULL; + GdkPixbuf *pixbuf = NULL, *emblem = NULL; GtkTreePath *path; gboolean account_status = FALSE; PurpleAccount *acct = (status_box->account) ? status_box->account : status_box->token_status_account; @@ -722,13 +700,13 @@ PurpleStatusType *status_type; PurpleStatusPrimitive prim; if (account_status) { - status_type = purple_status_get_type(purple_account_get_active_status(acct)); + status_type = purple_status_get_type(purple_account_get_active_status(acct)); prim = purple_status_type_get_primitive(status_type); } else { - prim = purple_savedstatus_get_type(saved_status); + prim = purple_savedstatus_get_type(saved_status); } - pixbuf = pidgin_status_box_get_pixbuf(status_box, prim); + stock = pidgin_stock_id_from_status_primitive(prim); } if (status_box->account != NULL) { @@ -750,12 +728,13 @@ * really need to be a list store?) */ gtk_list_store_set(status_box->store, &(status_box->iter), + ICON_STOCK_COLUMN, (gpointer)stock, ICON_COLUMN, pixbuf, TEXT_COLUMN, text, EMBLEM_COLUMN, emblem, EMBLEM_VISIBLE_COLUMN, (emblem != NULL), -1); - if ((status_box->typing == 0) && (!status_box->connecting)) + if (pixbuf && (status_box->typing == 0) && (!status_box->connecting)) g_object_unref(pixbuf); g_free(text); if (emblem) @@ -924,7 +903,6 @@ add_popular_statuses(PidginStatusBox *statusbox) { GList *list, *cur; - GdkPixbuf *pixbuf; list = purple_savedstatuses_get_popular(6); if (list == NULL) @@ -945,8 +923,6 @@ prim = purple_savedstatus_get_type(saved); - pixbuf = pidgin_status_box_get_pixbuf(statusbox, prim); - if (purple_savedstatus_is_transient(saved)) { /* @@ -967,11 +943,9 @@ } pidgin_status_box_add(statusbox, type, - pixbuf, purple_savedstatus_get_title(saved), stripped, + NULL, purple_savedstatus_get_title(saved), stripped, GINT_TO_POINTER(purple_savedstatus_get_creation_time(saved))); g_free(stripped); - if (pixbuf != NULL) - g_object_unref(G_OBJECT(pixbuf)); } g_list_free(list); @@ -1032,7 +1006,6 @@ { /* Per-account */ GList *l; - GdkPixbuf *pixbuf; for (l = purple_account_get_status_types(account); l != NULL; l = l->next) { @@ -1045,22 +1018,17 @@ prim = purple_status_type_get_primitive(status_type); - pixbuf = pidgin_status_box_get_pixbuf(status_box, prim); - pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), - PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf, + PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, NULL, purple_status_type_get_name(status_type), NULL, GINT_TO_POINTER(purple_status_type_get_primitive(status_type))); - if (pixbuf != NULL) - g_object_unref(pixbuf); } } static void pidgin_status_box_regenerate(PidginStatusBox *status_box) { - GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3, *pixbuf4, *pixbuf5; GtkIconSize icon_size; icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL); @@ -1075,8 +1043,6 @@ if (status_box->account == NULL) { - pixbuf = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_STATUS_AVAILABLE, - icon_size, "PidginStatusBox"); /* Do all the currently enabled accounts have the same statuses? * If so, display them instead of our global list. */ @@ -1084,25 +1050,11 @@ add_account_statuses(status_box, status_box->token_status_account); } else { /* Global */ - pixbuf2 = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_STATUS_AWAY, - icon_size, "PidginStatusBox"); - pixbuf3 = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_STATUS_OFFLINE, - icon_size, "PidginStatusBox"); - pixbuf4 = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_STATUS_INVISIBLE, - icon_size, "PidginStatusBox"); - pixbuf5 = gtk_widget_render_icon (GTK_WIDGET(status_box->vbox), PIDGIN_STOCK_STATUS_BUSY, - icon_size, "PidginStatusBox"); - - pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf, _("Available"), NULL, GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE)); - pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf2, _("Away"), NULL, GINT_TO_POINTER(PURPLE_STATUS_AWAY)); - pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf5, _("Do not disturb"), NULL, GINT_TO_POINTER(PURPLE_STATUS_UNAVAILABLE)); - pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf4, _("Invisible"), NULL, GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE)); - pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, pixbuf3, _("Offline"), NULL, GINT_TO_POINTER(PURPLE_STATUS_OFFLINE)); - - if (pixbuf2) g_object_unref(G_OBJECT(pixbuf2)); - if (pixbuf3) g_object_unref(G_OBJECT(pixbuf3)); - if (pixbuf4) g_object_unref(G_OBJECT(pixbuf4)); - if (pixbuf5) g_object_unref(G_OBJECT(pixbuf5)); + pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, NULL, _("Available"), NULL, GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE)); + pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, NULL, _("Away"), NULL, GINT_TO_POINTER(PURPLE_STATUS_AWAY)); + pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, NULL, _("Do not disturb"), NULL, GINT_TO_POINTER(PURPLE_STATUS_UNAVAILABLE)); + pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, NULL, _("Invisible"), NULL, GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE)); + pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_PRIMITIVE, NULL, _("Offline"), NULL, GINT_TO_POINTER(PURPLE_STATUS_OFFLINE)); } add_popular_statuses(status_box); @@ -1110,7 +1062,6 @@ pidgin_status_box_add_separator(PIDGIN_STATUS_BOX(status_box)); pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_CUSTOM, NULL, _("New status..."), NULL, NULL); pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_SAVED, NULL, _("Saved statuses..."), NULL, NULL); - if (pixbuf) g_object_unref(G_OBJECT(pixbuf)); status_menu_refresh_iter(status_box); pidgin_status_box_refresh(status_box); @@ -1778,9 +1729,9 @@ status_box->vsep = gtk_vseparator_new(); status_box->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE); - status_box->store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, + status_box->store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN); - status_box->dropdown_store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING, + status_box->dropdown_store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN); gtk_cell_view_set_model(GTK_CELL_VIEW(status_box->cell_view), GTK_TREE_MODEL(status_box->store)); @@ -1855,7 +1806,7 @@ gtk_tree_view_column_pack_start(status_box->column, icon_rend, FALSE); gtk_tree_view_column_pack_start(status_box->column, text_rend, TRUE); gtk_tree_view_column_pack_start(status_box->column, emblem_rend, FALSE); - gtk_tree_view_column_set_attributes(status_box->column, icon_rend, "pixbuf", ICON_COLUMN, NULL); + gtk_tree_view_column_set_attributes(status_box->column, icon_rend, "pixbuf", ICON_COLUMN, "stock-id", ICON_STOCK_COLUMN, NULL); gtk_tree_view_column_set_attributes(status_box->column, text_rend, "markup", TEXT_COLUMN, NULL); gtk_tree_view_column_set_attributes(status_box->column, emblem_rend, "stock-id", EMBLEM_COLUMN, "visible", EMBLEM_VISIBLE_COLUMN, NULL); gtk_container_add(GTK_CONTAINER(status_box->scrolled_window), status_box->tree_view); @@ -1874,7 +1825,7 @@ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, FALSE); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, TRUE); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), emblem_rend, FALSE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, "pixbuf", ICON_COLUMN, NULL); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, "pixbuf", ICON_COLUMN, "stock-id", ICON_STOCK_COLUMN, NULL); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, "markup", TEXT_COLUMN, NULL); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), emblem_rend, "pixbuf", EMBLEM_COLUMN, "visible", EMBLEM_VISIBLE_COLUMN, NULL); #if GTK_CHECK_VERSION(2, 6, 0) @@ -2133,7 +2084,8 @@ * * @param status_box The status box itself. * @param type A PidginStatusBoxItemType. - * @param pixbuf The icon to associate with this row in the menu. + * @param pixbuf The icon to associate with this row in the menu. The + * function will try to decide a pixbuf if none is given. * @param title The title of this item. For the primitive entries, * this is something like "Available" or "Away." For * the saved statuses, this is something like @@ -2149,10 +2101,12 @@ * creation timestamp. */ void -pidgin_status_box_add(PidginStatusBox *status_box, PidginStatusBoxItemType type, GdkPixbuf *pixbuf, const char *title, const char *desc, gpointer data) +pidgin_status_box_add(PidginStatusBox *status_box, PidginStatusBoxItemType type, GdkPixbuf *pixbuf, + const char *title, const char *desc, gpointer data) { GtkTreeIter iter; char *text; + const char *stock = NULL; if (desc == NULL) { @@ -2179,9 +2133,25 @@ g_free(escaped_desc); } + if (!pixbuf) { + PurpleStatusPrimitive prim = PURPLE_STATUS_UNSET; + if (type == PIDGIN_STATUS_BOX_TYPE_PRIMITIVE) { + prim = GPOINTER_TO_INT(data); + } else if (type == PIDGIN_STATUS_BOX_TYPE_SAVED_POPULAR || + type == PIDGIN_STATUS_BOX_TYPE_POPULAR) { + PurpleSavedStatus *saved = purple_savedstatus_find_by_creation_time(GPOINTER_TO_INT(data)); + if (saved) { + prim = purple_savedstatus_get_type(saved); + } + } + + stock = pidgin_stock_id_from_status_primitive(prim); + } + gtk_list_store_append(status_box->dropdown_store, &iter); gtk_list_store_set(status_box->dropdown_store, &iter, TYPE_COLUMN, type, + ICON_STOCK_COLUMN, stock, ICON_COLUMN, pixbuf, TEXT_COLUMN, text, TITLE_COLUMN, title,
--- a/pidgin/gtkutils.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkutils.c Sat Apr 25 19:09:36 2009 +0000 @@ -1464,7 +1464,7 @@ str); g_free(str); - return; + break; } buddy = purple_find_buddy(data->account, data->who); @@ -1494,7 +1494,7 @@ g_error_free(err); g_free(str); - return; + break; } id = purple_imgstore_add_with_id(filedata, size, data->filename); @@ -1715,29 +1715,42 @@ { GtkIconSize icon_size = gtk_icon_size_from_name(size); GdkPixbuf *pixbuf = NULL; - - if (prim == PURPLE_STATUS_UNAVAILABLE) - pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_BUSY, - icon_size, "GtkWidget"); - else if (prim == PURPLE_STATUS_AWAY) - pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AWAY, - icon_size, "GtkWidget"); - else if (prim == PURPLE_STATUS_EXTENDED_AWAY) - pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_XA, - icon_size, "GtkWidget"); - else if (prim == PURPLE_STATUS_INVISIBLE) - pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_INVISIBLE, - icon_size, "GtkWidget"); - else if (prim == PURPLE_STATUS_OFFLINE) - pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_OFFLINE, - icon_size, "GtkWidget"); - else - pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AVAILABLE, - icon_size, "GtkWidget"); + const char *stock = pidgin_stock_id_from_status_primitive(prim); + + pixbuf = gtk_widget_render_icon (w, stock ? stock : PIDGIN_STOCK_STATUS_AVAILABLE, + icon_size, "GtkWidget"); return pixbuf; - } +const char * +pidgin_stock_id_from_status_primitive(PurpleStatusPrimitive prim) +{ + const char *stock = NULL; + switch (prim) { + case PURPLE_STATUS_UNSET: + stock = NULL; + break; + case PURPLE_STATUS_UNAVAILABLE: + stock = PIDGIN_STOCK_STATUS_BUSY; + break; + case PURPLE_STATUS_AWAY: + stock = PIDGIN_STOCK_STATUS_AWAY; + break; + case PURPLE_STATUS_EXTENDED_AWAY: + stock = PIDGIN_STOCK_STATUS_XA; + break; + case PURPLE_STATUS_INVISIBLE: + stock = PIDGIN_STOCK_STATUS_INVISIBLE; + break; + case PURPLE_STATUS_OFFLINE: + stock = PIDGIN_STOCK_STATUS_OFFLINE; + break; + default: + stock = PIDGIN_STOCK_STATUS_AVAILABLE; + break; + } + return stock; +} GdkPixbuf * pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size)
--- a/pidgin/gtkutils.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/gtkutils.h Sat Apr 25 19:09:36 2009 +0000 @@ -569,6 +569,16 @@ */ GdkPixbuf * pidgin_create_status_icon(PurpleStatusPrimitive primitive, GtkWidget *w, const char *size); +/** + * Returns an appropriate stock-id for a status primitive. + * + * @param prim The status primitive + * + * @return The stock-id + * + * @since 2.6.0 + */ +const char *pidgin_stock_id_from_status_primitive(PurpleStatusPrimitive prim); /** * Append a PurpleMenuAction to a menu.
--- a/pidgin/pidginstock.c Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/pidginstock.c Sat Apr 25 19:09:36 2009 +0000 @@ -320,7 +320,7 @@ } static gchar * -find_icon_file(PidginStatusIconTheme *theme, const gchar *size, SizedStockIcon sized_icon, gboolean rtl) +find_icon_file(PidginIconTheme *theme, const gchar *size, SizedStockIcon sized_icon, gboolean rtl) { const gchar *file, *dir; gchar *file_full = NULL; @@ -352,7 +352,7 @@ } static void -add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, PidginStatusIconTheme *theme, +add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, PidginIconTheme *theme, const char *size, SizedStockIcon sized_icon, gboolean translucent) { char *filename; @@ -409,6 +409,16 @@ } } +static void +reload_settings(void) +{ +#if GTK_CHECK_VERSION(2,4,0) + GtkSettings *setting = NULL; + setting = gtk_settings_get_default(); + gtk_rc_reset_styles(setting); +#endif +} + /***************************************************************************** * Public API functions *****************************************************************************/ @@ -447,9 +457,9 @@ translucent = gtk_icon_set_new(); #define ADD_SIZED_ICON(name, size) if (sized_status_icons[i].name) { \ - add_sized_icon(normal, name, theme, size, sized_status_icons[i], FALSE); \ + add_sized_icon(normal, name, PIDGIN_ICON_THEME(theme), size, sized_status_icons[i], FALSE); \ if (sized_status_icons[i].translucent_name) \ - add_sized_icon(translucent, name, theme, size, sized_status_icons[i], TRUE); \ + add_sized_icon(translucent, name, PIDGIN_ICON_THEME(theme), size, sized_status_icons[i], TRUE); \ } ADD_SIZED_ICON(microscopic, "11"); ADD_SIZED_ICON(extra_small, "16"); @@ -471,52 +481,45 @@ gtk_widget_destroy(win); g_object_unref(G_OBJECT(icon_factory)); + reload_settings(); } void -pidgin_stock_init(void) +pidgin_stock_load_stock_icon_theme(PidginStockIconTheme *theme) { GtkIconFactory *icon_factory; - size_t i; + gint i; GtkWidget *win; - PidginIconThemeLoader *loader; - const gchar *path = NULL; - - if (stock_initted) - return; - stock_initted = TRUE; + if (theme != NULL) { + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/stock/icon-theme", + purple_theme_get_name(PURPLE_THEME(theme))); + purple_prefs_set_path(PIDGIN_PREFS_ROOT "/stock/icon-theme-dir", + purple_theme_get_dir(PURPLE_THEME(theme))); + } + else { + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/stock/icon-theme", ""); + purple_prefs_set_path(PIDGIN_PREFS_ROOT "/stock/icon-theme-dir", ""); + } - /* Setup the status icon theme */ - loader = g_object_new(PIDGIN_TYPE_ICON_THEME_LOADER, "type", "status-icon", NULL); - purple_theme_manager_register_type(PURPLE_THEME_LOADER(loader)); - purple_prefs_add_string(PIDGIN_PREFS_ROOT "/status/icon-theme", ""); - purple_prefs_add_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir", ""); - - /* Setup the icon factory. */ icon_factory = gtk_icon_factory_new(); gtk_icon_factory_add_default(icon_factory); - /* Er, yeah, a hack, but it works. :) */ win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_realize(win); /* All non-sized icons */ - for (i = 0; i < G_N_ELEMENTS(stock_icons); i++) - { + for (i = 0; i < G_N_ELEMENTS(stock_icons); i++) { GtkIconSource *source; GtkIconSet *iconset; gchar *filename; - if (stock_icons[i].dir == NULL) - { + if (stock_icons[i].dir == NULL) { /* GTK+ Stock icon */ iconset = gtk_style_lookup_icon_set(gtk_widget_get_style(win), stock_icons[i].filename); - } - else - { + } else { filename = find_file(stock_icons[i].dir, stock_icons[i].filename); if (filename == NULL) @@ -540,21 +543,13 @@ gtk_icon_set_unref(iconset); } - /* register custom icon sizes */ - microscopic = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, 11, 11); - extra_small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, 16, 16); - small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_SMALL, 22, 22); - medium = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MEDIUM, 32, 32); - large = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_LARGE, 48, 48); - huge = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_HUGE, 64, 64); - /* All non-status sized icons */ for (i = 0; i < G_N_ELEMENTS(sized_stock_icons); i++) { GtkIconSet *iconset = gtk_icon_set_new(); #define ADD_SIZED_ICON(name, size) if (sized_stock_icons[i].name) \ - add_sized_icon(iconset, name, NULL, size, sized_stock_icons[i], FALSE); + add_sized_icon(iconset, name, PIDGIN_ICON_THEME(theme), size, sized_stock_icons[i], FALSE); ADD_SIZED_ICON(microscopic, "11"); ADD_SIZED_ICON(extra_small, "16"); ADD_SIZED_ICON(small, "22"); @@ -569,6 +564,40 @@ gtk_widget_destroy(win); g_object_unref(G_OBJECT(icon_factory)); + reload_settings(); +} + +void +pidgin_stock_init(void) +{ + PidginIconThemeLoader *loader, *stockloader; + const gchar *path = NULL; + + if (stock_initted) + return; + + stock_initted = TRUE; + + /* Setup the status icon theme */ + loader = g_object_new(PIDGIN_TYPE_ICON_THEME_LOADER, "type", "status-icon", NULL); + purple_theme_manager_register_type(PURPLE_THEME_LOADER(loader)); + purple_prefs_add_string(PIDGIN_PREFS_ROOT "/status/icon-theme", ""); + purple_prefs_add_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir", ""); + + stockloader = g_object_new(PIDGIN_TYPE_ICON_THEME_LOADER, "type", "stock-icon", NULL); + purple_theme_manager_register_type(PURPLE_THEME_LOADER(stockloader)); + purple_prefs_add_string(PIDGIN_PREFS_ROOT "/stock/icon-theme", ""); + purple_prefs_add_path(PIDGIN_PREFS_ROOT "/stock/icon-theme-dir", ""); + + /* register custom icon sizes */ + microscopic = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, 11, 11); + extra_small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, 16, 16); + small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_SMALL, 22, 22); + medium = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MEDIUM, 32, 32); + large = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_LARGE, 48, 48); + huge = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_HUGE, 64, 64); + + pidgin_stock_load_stock_icon_theme(NULL); /* Pre-load Status icon theme - this avoids a bug with displaying the correct icon in the tray, theme is destroyed after*/ if (purple_prefs_get_string(PIDGIN_PREFS_ROOT "/icon/status/theme") && @@ -583,3 +612,31 @@ /* Register the stock items. */ gtk_stock_add_static(stock_items, G_N_ELEMENTS(stock_items)); } + +static void +pidgin_stock_icon_theme_class_init(PidginStockIconThemeClass *klass) +{ +} + +GType +pidgin_stock_icon_theme_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (PidginStockIconThemeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)pidgin_stock_icon_theme_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PidginStockIconTheme), + 0, /* n_preallocs */ + NULL, + NULL, /* value table */ + }; + type = g_type_register_static(PIDGIN_TYPE_ICON_THEME, + "PidginStockIconTheme", &info, 0); + } + return type; +}
--- a/pidgin/pidginstock.h Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/pidginstock.h Sat Apr 25 19:09:36 2009 +0000 @@ -185,15 +185,54 @@ #define PIDGIN_ICON_SIZE_TANGO_HUGE "pidgin-icon-size-tango-huge" /** + * extends PidginIconTheme (gtkicon-theme.h) + * A pidgin stock icon theme. + * This object represents a Pidgin stock icon theme. + * + * PidginStockIconTheme is a PidginIconTheme Object. + */ +typedef struct _PidginStockIconTheme PidginStockIconTheme; +typedef struct _PidginStockIconThemeClass PidginStockIconThemeClass; + +#define PIDGIN_TYPE_STOCK_ICON_THEME (pidgin_stock_icon_theme_get_type ()) +#define PIDGIN_STOCK_ICON_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIDGIN_TYPE_STOCK_ICON_THEME, PidginStockIconTheme)) +#define PIDGIN_STOCK_ICON_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIDGIN_TYPE_STOCK_ICON_THEME, PidginStockIconThemeClass)) +#define PIDGIN_IS_STOCK_ICON_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIDGIN_TYPE_STOCK_ICON_THEME)) +#define PIDGIN_IS_STOCK_ICON_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIDGIN_TYPE_STOCK_ICON_THEME)) +#define PIDGIN_STOCK_ICON_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIDGIN_TYPE_STOCK_ICON_THEME, PidginStockIconThemeClass)) + +struct _PidginStockIconTheme +{ + PidginIconTheme parent; +}; + +struct _PidginStockIconThemeClass +{ + PidginIconThemeClass parent_class; +}; + +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType pidgin_stock_icon_theme_get_type(void); + +/** * Loades all of the icons from the status icon theme into Pidgin stock * * @param theme the theme to load, or null to load all the default icons */ void pidgin_stock_load_status_icon_theme(PidginStatusIconTheme *theme); + +void pidgin_stock_load_stock_icon_theme(PidginStockIconTheme *theme); + /** * Sets up the purple stock repository. */ void pidgin_stock_init(void); +G_END_DECLS #endif /* _PIDGIN_STOCK_H_ */
--- a/pidgin/plugins/Makefile.am Thu Apr 23 20:05:26 2009 +0000 +++ b/pidgin/plugins/Makefile.am Sat Apr 25 19:09:36 2009 +0000 @@ -43,6 +43,7 @@ relnot_la_LDFLAGS = -module -avoid-version sendbutton_la_LDFLAGS = -module -avoid-version spellchk_la_LDFLAGS = -module -avoid-version +themeedit_la_LDFLAGS = -module -avoid-version timestamp_la_LDFLAGS = -module -avoid-version timestamp_format_la_LDFLAGS = -module -avoid-version xmppconsole_la_LDFLAGS = -module -avoid-version @@ -61,6 +62,7 @@ relnot.la \ sendbutton.la \ spellchk.la \ + themeedit.la \ timestamp.la \ timestamp_format.la \ xmppconsole.la @@ -82,6 +84,7 @@ relnot_la_SOURCES = relnot.c sendbutton_la_SOURCES = sendbutton.c spellchk_la_SOURCES = spellchk.c +themeedit_la_SOURCES = themeedit.c themeedit-icon.c themeedit-icon.h timestamp_la_SOURCES = timestamp.c timestamp_format_la_SOURCES = timestamp_format.c xmppconsole_la_SOURCES = xmppconsole.c @@ -99,6 +102,7 @@ relnot_la_LIBADD = $(GLIB_LIBS) sendbutton_la_LIBADD = $(GTK_LIBS) spellchk_la_LIBADD = $(GTK_LIBS) +themeedit_la_LIBADD = $(GTK_LIBS) timestamp_la_LIBADD = $(GTK_LIBS) timestamp_format_la_LIBADD = $(GTK_LIBS) xmppconsole_la_LIBADD = $(GTK_LIBS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/plugins/themeedit-icon.c Sat Apr 25 19:09:36 2009 +0000 @@ -0,0 +1,312 @@ +/* Pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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 + */ +#include "internal.h" +#include "pidgin.h" +#include "debug.h" +#include "version.h" + +#include "theme-manager.h" + +#include "gtkblist.h" +#include "gtkblist-theme.h" +#include "gtkutils.h" +#include "gtkplugin.h" + +#include "pidginstock.h" +#include "themeedit-icon.h" + +typedef enum +{ + FLAG_SIZE_MICROSOPIC = 0, + FLAG_SIZE_EXTRA_SMALL, + FLAG_SIZE_SMALL, + FLAG_SIZE_MEDIUM, + FLAG_SIZE_LARGE, + FLAG_SIZE_HUGE, + FLAG_SIZE_NONE, +} SectionFlags; + +#define SECTION_FLAGS_ALL (0x3f) + +static const char *stocksizes [] = { + [FLAG_SIZE_MICROSOPIC] = PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, + [FLAG_SIZE_EXTRA_SMALL] = PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, + [FLAG_SIZE_SMALL] = PIDGIN_ICON_SIZE_TANGO_SMALL, + [FLAG_SIZE_MEDIUM] = PIDGIN_ICON_SIZE_TANGO_MEDIUM, + [FLAG_SIZE_LARGE] = PIDGIN_ICON_SIZE_TANGO_LARGE, + [FLAG_SIZE_HUGE] = PIDGIN_ICON_SIZE_TANGO_HUGE, + [FLAG_SIZE_NONE] = NULL, +}; + +static const struct options { + const char *stockid; + const char *text; +} statuses[] = { + {PIDGIN_STOCK_STATUS_AVAILABLE, N_("Available")}, + {PIDGIN_STOCK_STATUS_AWAY, N_("Away")}, + {PIDGIN_STOCK_STATUS_XA, N_("Extended Away")}, + {PIDGIN_STOCK_STATUS_BUSY, N_("Busy")}, + {PIDGIN_STOCK_STATUS_OFFLINE, N_("Offline")}, + {PIDGIN_STOCK_STATUS_LOGIN, N_("Just logged in")}, + {PIDGIN_STOCK_STATUS_LOGOUT, N_("Just logged out")}, + {PIDGIN_STOCK_STATUS_PERSON, N_("Icon for Contact/\nIcon for Unknown person")}, + {PIDGIN_STOCK_STATUS_CHAT, N_("Icon for Chat")}, + {NULL, NULL} +}, chatemblems[] = { + {PIDGIN_STOCK_STATUS_IGNORED, N_("Ignored")}, + {PIDGIN_STOCK_STATUS_FOUNDER, N_("Founder")}, + {PIDGIN_STOCK_STATUS_OPERATOR, N_("Operator")}, + {PIDGIN_STOCK_STATUS_HALFOP, N_("Half Operator")}, + {PIDGIN_STOCK_STATUS_VOICE, N_("Voice")}, + {NULL, NULL} +}, dialogicons[] = { + {PIDGIN_STOCK_DIALOG_AUTH, N_("Authorization dialog")}, + {PIDGIN_STOCK_DIALOG_ERROR, N_("Error dialog")}, + {PIDGIN_STOCK_DIALOG_INFO, N_("Information dialog")}, + {PIDGIN_STOCK_DIALOG_MAIL, N_("Mail dialog")}, + {PIDGIN_STOCK_DIALOG_QUESTION, N_("Question dialog")}, + {PIDGIN_STOCK_DIALOG_WARNING, N_("Warning dialog")}, + {NULL, NULL}, + {PIDGIN_STOCK_DIALOG_COOL, N_("What kind of dialog is this?")}, +}; + +static const struct { + const char *heading; + const struct options *options; + SectionFlags flags; +} sections[] = { + {N_("Status Icons"), statuses, SECTION_FLAGS_ALL ^ (1 << FLAG_SIZE_HUGE)}, + {N_("Chatroom Emblems"), chatemblems, FLAG_SIZE_SMALL}, + {N_("Dialog Icons"), dialogicons, (1 << FLAG_SIZE_EXTRA_SMALL) | (1 << FLAG_SIZE_HUGE)}, + {NULL, NULL, 0} +}; + +static PidginStatusIconTheme * +create_icon_theme(GtkWidget *window) +{ + int s, i, j; + char *dirname = "/tmp"; /* FIXME */ + PidginStatusIconTheme *theme = g_object_new(PIDGIN_TYPE_STATUS_ICON_THEME, "type", "status-icon", + "author", getlogin(), + "directory", dirname, + NULL); + + for (s = 0; sections[s].heading; s++) { + GtkWidget *vbox = g_object_get_data(G_OBJECT(window), sections[s].heading); + for (i = 0; sections[s].options[i].stockid; i++) { + GtkWidget *image = g_object_get_data(G_OBJECT(vbox), sections[s].options[i].stockid); + GdkPixbuf *pixbuf = g_object_get_data(G_OBJECT(image), "pixbuf"); + if (!pixbuf) + continue; + pidgin_icon_theme_set_icon(PIDGIN_ICON_THEME(theme), sections[s].options[i].stockid, + sections[s].options[i].stockid); + for (j = 0; stocksizes[j]; j++) { + int width, height; + GtkIconSize iconsize; + char size[8]; + char *name; + GdkPixbuf *scale; + GError *error = NULL; + + if (!(sections[s].flags & (1 << j))) + continue; + + iconsize = gtk_icon_size_from_name(stocksizes[j]); + gtk_icon_size_lookup(iconsize, &width, &height); + g_snprintf(size, sizeof(size), "%d", width); + + if (i == 0) { + name = g_build_filename(dirname, size, NULL); + purple_build_dir(name, S_IRUSR | S_IWUSR | S_IXUSR); + g_free(name); + } + + name = g_build_filename(dirname, size, sections[s].options[i].stockid, NULL); + scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR); + gdk_pixbuf_save(scale, name, "png", &error, "compression", "9", NULL); + g_free(name); + g_object_unref(G_OBJECT(scale)); + if (error) + g_error_free(error); + } + } + } + return theme; +} + +static void +use_icon_theme(GtkWidget *w, GtkWidget *window) +{ + /* I don't quite understand the icon-theme stuff. For example, I don't + * know why PidginIconTheme needs to be abstract, or how PidginStatusIconTheme + * would be different from other PidginIconTheme's (e.g. PidginStockIconTheme) + * etc., but anyway, this works for now. + * + * Here's an interesting note: A PidginStatusIconTheme can be used for both + * stock and status icons. Like I said, I don't quite know how they could be + * different. So I am going to just keep it as it is, for now anyway, until I + * have the time to dig through this, or someone explains this stuff to me + * clearly. + * -- Sad + */ + PidginStatusIconTheme *theme = create_icon_theme(window); + pidgin_stock_load_status_icon_theme(PIDGIN_STATUS_ICON_THEME(theme)); + pidgin_stock_load_stock_icon_theme((PidginStockIconTheme *)theme); + pidgin_blist_refresh(purple_get_blist()); + g_object_unref(theme); +} + +#ifdef NOT_SADRUL +static void +save_icon_theme(GtkWidget *w, GtkWidget *window) +{ + /* TODO: SAVE! */ + gtk_widget_destroy(window); +} +#endif + +static void +close_icon_theme(GtkWidget *w, GtkWidget *window) +{ + gtk_widget_destroy(window); +} + +static void +stock_icon_selected(const char *filename, gpointer image) +{ + GError *error = NULL; + GdkPixbuf *scale; + int i; + GdkPixbuf *pixbuf; + + if (!filename) + return; + + pixbuf = gdk_pixbuf_new_from_file(filename, &error); + if (error || !pixbuf) { + purple_debug_error("theme-editor-icon", "Unable to load icon file '%s' (%s)\n", + filename, error ? error->message : "Reason unknown"); + if (error) + g_error_free(error); + return; + } + + scale = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(GTK_IMAGE(image), scale); + g_object_unref(G_OBJECT(scale)); + + /* Update the size previews */ + for (i = 0; stocksizes[i]; i++) { + int width, height; + GtkIconSize iconsize; + GtkWidget *prev = g_object_get_data(G_OBJECT(image), stocksizes[i]); + if (!prev) + continue; + iconsize = gtk_icon_size_from_name(stocksizes[i]); + gtk_icon_size_lookup(iconsize, &width, &height); + scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(GTK_IMAGE(prev), scale); + g_object_unref(G_OBJECT(scale)); + } + + /* Save the original pixbuf so we can use it for resizing later */ + g_object_set_data_full(G_OBJECT(image), "pixbuf", pixbuf, + (GDestroyNotify)g_object_unref); +} + +static gboolean +change_stock_image(GtkWidget *widget, GdkEventButton *event, GtkWidget *image) +{ + GtkWidget *win = pidgin_buddy_icon_chooser_new(GTK_WINDOW(gtk_widget_get_toplevel(widget)), + stock_icon_selected, image); + gtk_widget_show_all(win); + + return TRUE; +} + +void pidgin_icon_theme_edit(void) +{ + GtkWidget *dialog; + GtkWidget *box, *vbox; + GtkWidget *notebook; + GtkSizeGroup *sizegroup; + int s, i, j; + dialog = pidgin_create_dialog(_("Pidgin Icon Theme Editor"), 0, "theme-editor-icon", FALSE); + box = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog), FALSE, PIDGIN_HIG_BOX_SPACE); + + notebook = gtk_notebook_new(); + gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, PIDGIN_HIG_BOX_SPACE); + sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + + for (s = 0; sections[s].heading; s++) { + const char *heading = sections[s].heading; + + box = gtk_vbox_new(FALSE, 0); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), box, gtk_label_new(heading)); + + vbox = pidgin_make_frame(box, heading); + g_object_set_data(G_OBJECT(dialog), heading, vbox); + + for (i = 0; sections[s].options[i].stockid; i++) { + const char *id = sections[s].options[i].stockid; + const char *text = _(sections[s].options[i].text); + + GtkWidget *hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); + GtkWidget *label = gtk_label_new(text); + GtkWidget *image = gtk_image_new_from_stock(id, + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)); + GtkWidget *ebox = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(ebox), image); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + g_signal_connect(G_OBJECT(ebox), "button-press-event", G_CALLBACK(change_stock_image), image); + g_object_set_data(G_OBJECT(image), "property-name", (gpointer)id); + + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), ebox, FALSE, FALSE, 0); + + for (j = 0; stocksizes[j]; j++) { + GtkWidget *sh; + + if (!(sections[s].flags & (1 << j))) + continue; + + sh = gtk_image_new_from_stock(id, gtk_icon_size_from_name(stocksizes[j])); + gtk_box_pack_start(GTK_BOX(hbox), sh, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(image), stocksizes[j], sh); + } + + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + + g_object_set_data(G_OBJECT(vbox), id, image); + } + } + +#ifdef NOT_SADRUL + pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, G_CALLBACK(save_icon_theme), dialog); +#endif + pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_APPLY, G_CALLBACK(use_icon_theme), dialog); + pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CLOSE, G_CALLBACK(close_icon_theme), dialog); + gtk_widget_show_all(dialog); + g_object_unref(sizegroup); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/plugins/themeedit-icon.h Sat Apr 25 19:09:36 2009 +0000 @@ -0,0 +1,2 @@ +void pidgin_icon_theme_edit(void); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/plugins/themeedit.c Sat Apr 25 19:09:36 2009 +0000 @@ -0,0 +1,362 @@ +/* Pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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 + */ +#include "internal.h" +#include "pidgin.h" +#include "version.h" + +#include "theme-manager.h" + +#include "gtkblist.h" +#include "gtkblist-theme.h" +#include "gtkutils.h" +#include "gtkplugin.h" + +#define PLUGIN_ID "gtk-theme-editor" + +#include "themeedit-icon.h" + +static gboolean +prop_type_is_color(PidginBlistTheme *theme, const char *prop) +{ + PidginBlistThemeClass *klass = PIDGIN_BLIST_THEME_GET_CLASS(theme); + GParamSpec *spec = g_object_class_find_property(G_OBJECT_CLASS(klass), prop); + + return G_IS_PARAM_SPEC_BOXED(spec); +} + +#ifdef NOT_SADRUL +static void +save_blist_theme(GtkWidget *w, GtkWidget *window) +{ + /* TODO: SAVE! */ + gtk_widget_destroy(window); +} +#endif + +static void +close_blist_theme(GtkWidget *w, GtkWidget *window) +{ + gtk_widget_destroy(window); +} + +static void +theme_color_selected(GtkDialog *dialog, gint response, const char *prop) +{ + if (response == GTK_RESPONSE_OK) { + GdkColor color; + PidginBlistTheme *theme; + + gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dialog)->colorsel), &color); + + theme = pidgin_blist_get_theme(); + + if (prop_type_is_color(theme, prop)) { + g_object_set(G_OBJECT(theme), prop, &color, NULL); + } else { + PidginThemeFont *font = NULL; + g_object_get(G_OBJECT(theme), prop, &font, NULL); + if (!font) { + font = pidgin_theme_font_new(NULL, &color); + g_object_set(G_OBJECT(theme), prop, font, NULL); + pidgin_theme_font_free(font); + } else { + pidgin_theme_font_set_color(font, &color); + } + } + pidgin_blist_set_theme(theme); + } + + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +static void +theme_font_face_selected(GtkWidget *dialog, gint response, gpointer font) +{ + if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) { + const char *fontname = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog)); + pidgin_theme_font_set_font_face(font, fontname); + pidgin_blist_refresh(purple_get_blist()); + } + gtk_widget_destroy(dialog); +} + +static void +theme_font_select_face(GtkWidget *widget, gpointer prop) +{ + GtkWidget *dialog; + PidginBlistTheme *theme; + PidginThemeFont *font = NULL; + const char *face; + + theme = pidgin_blist_get_theme(); + g_object_get(G_OBJECT(theme), prop, &font, NULL); + + if (!font) { + font = pidgin_theme_font_new(NULL, NULL); + g_object_set(G_OBJECT(theme), prop, font, NULL); + pidgin_theme_font_free(font); + g_object_get(G_OBJECT(theme), prop, &font, NULL); + } + + face = pidgin_theme_font_get_font_face(font); + dialog = gtk_font_selection_dialog_new(_("Select Font")); + if (face && *face) + gtk_font_selection_set_font_name(GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(dialog)->fontsel), + face); + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(theme_font_face_selected), + font); + gtk_widget_show_all(dialog); +} + +static void +theme_color_select(GtkWidget *widget, gpointer prop) +{ + GtkWidget *dialog; + PidginBlistTheme *theme; + const GdkColor *color = NULL; + + theme = pidgin_blist_get_theme(); + + if (prop_type_is_color(theme, prop)) { + g_object_get(G_OBJECT(theme), prop, &color, NULL); + } else { + PidginThemeFont *pair = NULL; + g_object_get(G_OBJECT(theme), prop, &pair, NULL); + if (pair) + color = pidgin_theme_font_get_color(pair); + } + + dialog = gtk_color_selection_dialog_new(_("Select Color")); + if (color) + gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dialog)->colorsel), + color); + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(theme_color_selected), + prop); + + gtk_widget_show_all(dialog); +} + +static GtkWidget * +pidgin_theme_create_color_selector(const char *text, const char *blurb, const char *prop, + GtkSizeGroup *sizegroup) +{ + GtkWidget *color; + GtkWidget *hbox, *label; + + hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); + + label = gtk_label_new(_(text)); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION(2, 12, 0) + gtk_widget_set_tooltip_text(label, blurb); +#endif + + color = pidgin_pixbuf_button_from_stock("", GTK_STOCK_SELECT_COLOR, + PIDGIN_BUTTON_HORIZONTAL); + g_signal_connect(G_OBJECT(color), "clicked", G_CALLBACK(theme_color_select), + (gpointer)prop); + gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 0); + + return hbox; +} + +static GtkWidget * +pidgin_theme_create_font_selector(const char *text, const char *blurb, const char *prop, + GtkSizeGroup *sizegroup) +{ + GtkWidget *color, *font; + GtkWidget *hbox, *label; + + hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); + + label = gtk_label_new(_(text)); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_size_group_add_widget(sizegroup, label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION(2, 12, 0) + gtk_widget_set_tooltip_text(label, blurb); +#endif + + font = pidgin_pixbuf_button_from_stock("", GTK_STOCK_SELECT_FONT, + PIDGIN_BUTTON_HORIZONTAL); + g_signal_connect(G_OBJECT(font), "clicked", G_CALLBACK(theme_font_select_face), + (gpointer)prop); + gtk_box_pack_start(GTK_BOX(hbox), font, FALSE, FALSE, 0); + + color = pidgin_pixbuf_button_from_stock("", GTK_STOCK_SELECT_COLOR, + PIDGIN_BUTTON_HORIZONTAL); + g_signal_connect(G_OBJECT(color), "clicked", G_CALLBACK(theme_color_select), + (gpointer)prop); + gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 0); + + return hbox; +} + +static void +pidgin_blist_theme_edit(void) +{ + GtkWidget *dialog; + GtkWidget *box; + GtkSizeGroup *group; + PidginBlistTheme *theme; + GObjectClass *klass; + int i, j; + static struct { + const char *header; + const char *props[12]; + } sections[] = { + {N_("Contact"), { + "contact-color", + "contact", + "online", + "away", + "offline", + "idle", + "message", + "message_nick_said", + "status", + NULL + } + }, + {N_("Group"), { + "expanded-color", + "expanded-text", + "collapsed-color", + "collapsed-text", + NULL + } + }, + { NULL, { } } + }; + + dialog = pidgin_create_dialog(_("Pidgin Buddylist Theme Editor"), 0, "theme-editor-blist", FALSE); + box = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog), FALSE, PIDGIN_HIG_BOX_SPACE); + + theme = pidgin_blist_get_theme(); + if (!theme) { + theme = g_object_new(PIDGIN_TYPE_BLIST_THEME, "type", "blist", + "author", getlogin(), + NULL); + pidgin_blist_set_theme(theme); + } + klass = G_OBJECT_CLASS(PIDGIN_BLIST_THEME_GET_CLASS(theme)); + + group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + for (i = 0; sections[i].header; i++) { + GtkWidget *vbox; + GtkWidget *hbox; + GParamSpec *spec; + + vbox = pidgin_make_frame(box, _(sections[i].header)); + for (j = 0; sections[i].props[j]; j++) { + const char *label; + const char *blurb; + spec = g_object_class_find_property(klass, sections[i].props[j]); + label = g_param_spec_get_nick(spec); + blurb = g_param_spec_get_blurb(spec); + if (G_IS_PARAM_SPEC_BOXED(spec)) { + hbox = pidgin_theme_create_color_selector(label, blurb, + sections[i].props[j], group); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + } else { + hbox = pidgin_theme_create_font_selector(label, blurb, + sections[i].props[j], group); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + } + } + } + + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), TRUE); +#ifdef NOT_SADRUL + pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, G_CALLBACK(save_blist_theme), dialog); +#endif + pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CLOSE, G_CALLBACK(close_blist_theme), dialog); + + gtk_widget_show_all(dialog); + + g_object_unref(group); +} + +static gboolean +plugin_load(PurplePlugin *plugin) +{ + return TRUE; +} + +static GList * +actions(PurplePlugin *plugin, gpointer context) +{ + GList *l = NULL; + PurplePluginAction *act = NULL; + + act = purple_plugin_action_new(_("Edit Buddylist Theme"), pidgin_blist_theme_edit); + l = g_list_append(l, act); + act = purple_plugin_action_new(_("Edit Icon Theme"), pidgin_icon_theme_edit); + l = g_list_append(l, act); + + return l; +} + +static PurplePluginInfo info = +{ + PURPLE_PLUGIN_MAGIC, + PURPLE_MAJOR_VERSION, + PURPLE_MINOR_VERSION, + PURPLE_PLUGIN_STANDARD, /**< type */ + PIDGIN_PLUGIN_TYPE, /**< ui_requirement */ + 0, /**< flags */ + NULL, /**< dependencies */ + PURPLE_PRIORITY_DEFAULT, /**< priority */ + + PLUGIN_ID, /**< id */ + N_("Pidgin Theme Editor"), /**< name */ + DISPLAY_VERSION, /**< version */ + /** summary */ + N_("Pidgin Theme Editor."), + /** description */ + N_("Pidgin Theme Editor"), + "Sadrul Habib Chowdhury <imadil@gmail.com>", /**< author */ + PURPLE_WEBSITE, /**< homepage */ + + plugin_load, /**< load */ + NULL, /**< unload */ + NULL, /**< destroy */ + + NULL, /**< ui_info */ + NULL, /**< extra_info */ + NULL, + actions, + + /* padding */ + NULL, + NULL, + NULL, + NULL +}; + +static void +init_plugin(PurplePlugin *plugin) +{ +} + +PURPLE_INIT_PLUGIN(themeeditor, init_plugin, info)