summaryrefslogtreecommitdiff
path: root/thumbnails.c
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2009-12-23 17:10:39 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2009-12-23 17:10:39 +0100
commit1f0ef0bc2e7d0b99feb05e57f1c15a5a739c48fa (patch)
treed9000823af75d35d8c0b7a18d51b250c4c674b28 /thumbnails.c
parenta539fdf38688cbed984d9db1f08deaaf34eaf9e0 (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.c138
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, &times) == 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);
+ }
+}