diff options
author | Jon Bergli Heier <snakebite@jvnv.net> | 2009-12-23 17:10:39 +0100 |
---|---|---|
committer | Jon Bergli Heier <snakebite@jvnv.net> | 2009-12-23 17:10:39 +0100 |
commit | 1f0ef0bc2e7d0b99feb05e57f1c15a5a739c48fa (patch) | |
tree | d9000823af75d35d8c0b7a18d51b250c4c674b28 /thumbnails.c | |
parent | a539fdf38688cbed984d9db1f08deaaf34eaf9e0 (diff) |
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/).
Diffstat (limited to 'thumbnails.c')
-rw-r--r-- | thumbnails.c | 138 |
1 files changed, 138 insertions, 0 deletions
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 <unistd.h> +#include <utime.h> +#include <string.h> + +#include <glib/gstdio.h> +#include <gtk/gtk.h> + +#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); + } +} |