From 1f0ef0bc2e7d0b99feb05e57f1c15a5a739c48fa Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Wed, 23 Dec 2009 17:10:39 +0100 Subject: Reworked the main window. Images are now placed in their own icon view. Folders are selected in the above tree view, while the icon view displays thumbnails of the images in the selected folder. The thumbnails are cached using the thumbnail specification (~/.thumbnails/). --- thumbnails.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 thumbnails.c (limited to 'thumbnails.c') diff --git a/thumbnails.c b/thumbnails.c new file mode 100644 index 0000000..18e2d9f --- /dev/null +++ b/thumbnails.c @@ -0,0 +1,138 @@ +#include +#include +#include + +#include +#include + +#include "db.h" +#include "thumbnails.h" + +inline static gchar *get_wall_thumb_name(const gchar *filepath) { + GChecksum *ck; + gchar *s; + gchar *cksum; + + ck = g_checksum_new(G_CHECKSUM_MD5); + s = g_strdup_printf("file://%s", filepath); + g_checksum_update(ck, s, -1); + g_free(s); + cksum = g_strdup_printf("%s/.thumbnails/normal/%s.png", g_get_home_dir(), g_checksum_get_string(ck)); + g_checksum_free(ck); + return cksum; +} + +inline static time_t get_mtime(const gchar *filepath) { + struct utimbuf times; + + if(g_utime(filepath, ×) == 0) { + return times.modtime; + } else { + return 0; + } +} + +GdkPixbuf *get_thumbnail(const gchar *filepath) { + GdkPixbuf *pb, *pb2; + gint win_width, win_height, img_width, img_height, width, height; + gdouble scalex, scaley, width_ratio, height_ratio, max_ratio; + GError *error = NULL; + gchar *thumbname; + + thumbname = get_wall_thumb_name(filepath); + + if(g_access(thumbname, F_OK) == 0) { + pb = gdk_pixbuf_new_from_file(thumbname, &error); + g_free(thumbname); + return pb; + } else { + pb = gdk_pixbuf_new_from_file(filepath, &error); + } + + if(!pb) { + g_warning("%s", error->message); + g_free(error); + return NULL; + } + + img_width = gdk_pixbuf_get_width(pb); + img_height = gdk_pixbuf_get_height(pb); + win_width = win_height = 128; + + width_ratio = (gdouble)img_width / (gdouble)win_width; + height_ratio = (gdouble)img_height / (gdouble)win_height; + if(width_ratio > height_ratio) { + width = win_width; + height = (gint)(1.0 / width_ratio * img_height); + } else { + height = win_height; + width = (gint)(1.0 / height_ratio * img_width); + } + scalex = (gdouble)width / (gdouble)img_width; + scaley = (gdouble)height / (gdouble)img_height; + + pb2 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); + gdk_pixbuf_scale(pb, pb2, 0, 0, width, height, 0, 0, scalex, scaley, GDK_INTERP_BILINEAR); + g_object_unref(pb); + + error = NULL; + if(!gdk_pixbuf_save(pb2, thumbname, "png", &error, + "tEXt::Thumb::URI", filepath, + "tEXt::Thumb::MTime", get_mtime(filepath), + "tEXt::Software", "walls", + NULL)) { + g_warning("%s", error->message); + g_free(error); + } + + g_free(thumbname); + + return pb2; +} + +static void fill_wall_list(GtkListStore *liststore, GArray *array) { + GtkTreeIter iter; + + for(int i = 0; i < array->len; i++) { + struct wallpaper_t *wall; + wall = &g_array_index(array, struct wallpaper_t, i); + + gtk_list_store_append(liststore, &iter); + gtk_list_store_set(liststore, &iter, 0, NULL, 1, wall->filepath, -1); + g_free(wall->filepath); + } + g_array_free(array, TRUE); +} + +gpointer add_thumbs_thread(gpointer data) { + GtkListStore *liststore; + GtkTreeIter iter; + int n; + GValue value; + GdkPixbuf *pb = NULL; + const gchar *filepath; + + liststore = GTK_LIST_STORE(data); + + if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(liststore), &iter)) { + return NULL; + } + + n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(liststore), NULL); + + memset(&value, 0, sizeof(GValue)); + + for(int i = 0; i < n; i++) { + gtk_tree_model_get_value(GTK_TREE_MODEL(liststore), &iter, 1, &value); + printf("file: %s\n", g_value_get_string(&value)); + filepath = g_value_get_string(&value); + pb = get_thumbnail(filepath); + g_value_unset(&value); + if(pb) { + gtk_list_store_set(liststore, &iter, 0, pb, -1); + + g_object_unref(pb); + } + gtk_tree_model_iter_next(GTK_TREE_MODEL(liststore), &iter); + } +} -- cgit v1.2.3