/* * Authors: Rodney Dawes * * Copyright 2003-2006 Novell, Inc. (www.novell.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation * * 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., 59 Temple Street #330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include "gnome-wp-item.h" #include "gnome-wp-utils.h" GnomeWPItem * gnome_wp_item_new (const gchar * filename, GHashTable * wallpapers, GnomeThumbnailFactory * thumbnails) { GnomeWPItem * item = NULL; GdkColor color1, color2; GConfClient * client; client = gconf_client_get_default (); item = g_new0 (GnomeWPItem, 1); item->filename = gnome_vfs_unescape_string_for_display (filename); item->fileinfo = gnome_wp_info_new (item->filename, thumbnails); item->shade_type = gconf_client_get_string (client, WP_SHADING_KEY, NULL); item->pri_color = gconf_client_get_string (client, WP_PCOLOR_KEY, NULL); item->sec_color = gconf_client_get_string (client, WP_SCOLOR_KEY, NULL); gdk_color_parse (item->pri_color, &color1); gdk_color_parse (item->sec_color, &color2); item->pcolor = gdk_color_copy (&color1); item->scolor = gdk_color_copy (&color2); if (item->fileinfo != NULL && !strncmp (item->fileinfo->mime_type, "image/", strlen ("image/"))) { if (item->name == NULL) { if (g_utf8_validate (item->fileinfo->name, -1, NULL)) item->name = g_strdup (item->fileinfo->name); else item->name = g_filename_to_utf8 (item->fileinfo->name, -1, NULL, NULL, NULL); } item->options = gconf_client_get_string (client, WP_OPTIONS_KEY, NULL); if (!strcmp (item->options, "none")) { item->options = g_strdup ("scaled"); } gnome_wp_item_update_description (item); g_hash_table_insert (wallpapers, g_strdup (item->filename), item); } else { gnome_wp_item_free (item); item = NULL; } g_object_unref (client); return item; } void gnome_wp_item_free (GnomeWPItem * item) { if (item == NULL) { return; } g_free (item->name); g_free (item->filename); g_free (item->description); g_free (item->imguri); g_free (item->options); g_free (item->shade_type); g_free (item->pri_color); g_free (item->sec_color); if (item->pcolor != NULL) gdk_color_free (item->pcolor); if (item->scolor != NULL) gdk_color_free (item->scolor); gnome_wp_info_free (item->fileinfo); gnome_wp_info_free (item->uriinfo); gtk_tree_row_reference_free (item->rowref); item = NULL; } GnomeWPItem * gnome_wp_item_dup (GnomeWPItem * item) { GnomeWPItem * new_item; GdkColor color1, color2; if (item == NULL) { return NULL; } new_item = g_new0 (GnomeWPItem, 1); new_item->name = g_strdup (item->name); new_item->filename = g_strdup (item->filename); new_item->description = g_strdup (item->description); new_item->imguri = g_strdup (item->imguri); new_item->options = g_strdup (item->options); new_item->shade_type = g_strdup (item->shade_type); new_item->pri_color = g_strdup (item->pri_color); new_item->sec_color = g_strdup (item->sec_color); gdk_color_parse (item->pri_color, &color1); gdk_color_parse (item->sec_color, &color2); item->pcolor = gdk_color_copy (&color1); item->scolor = gdk_color_copy (&color2); new_item->fileinfo = gnome_wp_info_dup (item->fileinfo); new_item->uriinfo = gnome_wp_info_dup (item->uriinfo); new_item->rowref = gtk_tree_row_reference_copy (item->rowref); new_item->deleted = item->deleted; new_item->width = item->width; new_item->height = item->height; return new_item; } static void collect_save_options (GdkPixbuf * pixbuf, gchar *** keys, gchar *** vals, gint width, gint height) { gchar ** options; gint n, count; count = 0; options = g_object_get_qdata (G_OBJECT (pixbuf), g_quark_from_static_string ("gdk_pixbuf_options")); if (options) { for (n = 0; options[2 * n]; n++) { ++count; *keys = g_realloc (*keys, sizeof (gchar *) * (count + 1)); *vals = g_realloc (*vals, sizeof (gchar *) * (count + 1)); (*keys)[count - 1] = g_strdup (options[2 * n]); (*vals)[count - 1] = g_strdup (options[2 * n + 1]); (*keys)[count] = NULL; (*vals)[count] = NULL; } } ++count; *keys = g_realloc (*keys, sizeof (gchar *) * (count + 1)); *vals = g_realloc (*vals, sizeof (gchar *) * (count + 1)); (*keys)[count - 1] = g_strdup ("tEXt::Thumb::Image::Width"); (*vals)[count - 1] = g_strdup_printf ("%d", width); (*keys)[count] = NULL; (*vals)[count] = NULL; ++count; *keys = g_realloc (*keys, sizeof (gchar *) * (count + 1)); *vals = g_realloc (*vals, sizeof (gchar *) * (count + 1)); (*keys)[count - 1] = g_strdup ("tEXt::Thumb::Image::Height"); (*vals)[count - 1] = g_strdup_printf ("%d", height); (*keys)[count] = NULL; (*vals)[count] = NULL; } #define LIST_IMAGE_WIDTH 64 GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item, GnomeThumbnailFactory * thumbs) { GdkPixbuf * pixbuf, * bgpixbuf; GdkPixbuf * tmpbuf; GdkPixbuf * scaled = NULL; gint sw, sh, bw, bh, pw, ph, tw, th; gdouble ratio; sw = sh = bw = bh = pw = ph = tw = th = 0; /* Get the size of the screen and calculate our aspect ratio divisor We do this, so that images are thumbnailed as they would look on the screen in reality */ sw = gdk_screen_get_width (gdk_screen_get_default ()); sh = gdk_screen_get_height (gdk_screen_get_default ()); ratio = (gdouble) sw / (gdouble) LIST_IMAGE_WIDTH; bw = sw / ratio; bh = sh / ratio; /* Create the pixbuf for the background colors, which will show up for oddly sized images, smaller images that are centered, or alpha images */ if (!strcmp (item->shade_type, "solid")) { bgpixbuf = gnome_wp_pixbuf_new_solid (item->pcolor, bw, bh); } else if (!strcmp (item->shade_type, "vertical-gradient")) { bgpixbuf = gnome_wp_pixbuf_new_gradient (GTK_ORIENTATION_VERTICAL, item->pcolor, item->scolor, bw, bh); } else { bgpixbuf = gnome_wp_pixbuf_new_gradient (GTK_ORIENTATION_HORIZONTAL, item->pcolor, item->scolor, bw, bh); } /* Load up the thumbnail image using the thumbnail spec If the image doesn't exist, we create it If we are creating the thumbnail for "No Wallpaper", then we just copy the background colors pixbuf we created above, here */ if (item->fileinfo->thumburi != NULL && g_file_test (item->fileinfo->thumburi, G_FILE_TEST_EXISTS)) { pixbuf = gdk_pixbuf_new_from_file (item->fileinfo->thumburi, NULL); } else if (!strcmp (item->filename, "(none)")) { return bgpixbuf; } else { gchar * escaped_path; escaped_path = gnome_vfs_escape_path_string (item->filename); pixbuf = gnome_thumbnail_factory_generate_thumbnail (thumbs, escaped_path, item->fileinfo->mime_type); gnome_thumbnail_factory_save_thumbnail (thumbs, pixbuf, escaped_path, item->fileinfo->mtime); g_free (escaped_path); } if (pixbuf != NULL) { const gchar * w_val, * h_val; w_val = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Width"); h_val = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Height"); if (item->width <= 0 || item->height <= 0) { if (w_val && h_val) { item->width = atoi (w_val); item->height = atoi (h_val); } else { gchar ** keys = NULL; gchar ** vals = NULL; tmpbuf = gdk_pixbuf_new_from_file (item->filename, NULL); item->width = gdk_pixbuf_get_width (tmpbuf); item->height = gdk_pixbuf_get_height (tmpbuf); collect_save_options (pixbuf, &keys, &vals, item->width, item->height); gdk_pixbuf_savev (pixbuf, item->fileinfo->thumburi, "png", keys, vals, NULL); g_object_unref (tmpbuf); g_strfreev (keys); g_strfreev (vals); } } pw = gdk_pixbuf_get_width (pixbuf); ph = gdk_pixbuf_get_height (pixbuf); if (item->width <= bw && item->height <= bh) ratio = 1.0; tw = item->width / ratio; th = item->height / ratio; if (!strcmp (item->options, "wallpaper")) { scaled = gnome_wp_pixbuf_tile (pixbuf, bgpixbuf, tw, th); } else if (!strcmp (item->options, "centered")) { scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th); } else if (!strcmp (item->options, "stretched")) { scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, bw, bh); } else if (!strcmp (item->options, "scaled")) { if ((gdouble) ph * (gdouble) bw > (gdouble) pw * (gdouble) bh) { tw = 0.5 + (gdouble) pw * (gdouble) bh / (gdouble) ph; th = bh; } else { th = 0.5 + (gdouble) ph * (gdouble) bw / (gdouble) pw; tw = bw; } scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th); } else if (!strcmp (item->options, "zoom")) { if ((gdouble) ph * (gdouble) bw < (gdouble) pw * (gdouble) bh) { tw = 0.5 + (gdouble) pw * (gdouble) bh / (gdouble) ph; th = bh; } else { th = 0.5 + (gdouble) ph * (gdouble) bw / (gdouble) pw; tw = bw; } scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th); } } g_object_unref (pixbuf); g_object_unref (bgpixbuf); return scaled; } void gnome_wp_item_update_description (GnomeWPItem * item) { if (!strcmp (item->filename, "(none)")) { item->description = g_strdup_printf ("%s", item->name); } else { gchar * info; info = g_strdup_printf ("%s, %d %s x %d %s", gnome_vfs_mime_get_description (item->fileinfo->mime_type), item->width, ngettext ("pixel", "pixels", item->width), item->height, ngettext ("pixel", "pixels", item->height)); item->description = g_markup_printf_escaped ("%s\n" "%s", item->name, info); g_free (info); } }