changeset 2798:d9764817aad8

Collection preview If the folder containing collection files (usually $HOME/.local/share/geeqie/collections) is opened, the image pane will show a montage of the thumbnails (to a maximum of 20) of the images in the selected collection. Requires ImageMagick. This is a simplistic implementation, and should be improved e.g. Use collect-io.c to parse the collection file Use cached thumbnails instead of re-creating Use Geeqie to create the montage instead of using ImageMagick
author Colin Clark <colin.clark@cclark.uk>
date Wed, 18 Jul 2018 10:16:41 +0100
parents 6ed30da8b62d
children ea4163f0c769
files src/Makefile.am src/image-load.c src/image_load_collection.c src/image_load_collection.h src/thumb.c src/thumb_standard.c
diffstat 6 files changed, 206 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile.am	Sun Jul 15 11:02:07 2018 +0100
+++ b/src/Makefile.am	Wed Jul 18 10:16:41 2018 +0100
@@ -181,6 +181,8 @@
 	image_load_tiff.h\
 	image_load_dds.c\
 	image_load_dds.h\
+	image_load_collection.c\
+	image_load_collection.h\
 	image_load_ffmpegthumbnailer.c\
 	image_load_ffmpegthumbnailer.h\
 	image-overlay.c	\
--- a/src/image-load.c	Sun Jul 15 11:02:07 2018 +0100
+++ b/src/image-load.c	Wed Jul 18 10:16:41 2018 +0100
@@ -26,6 +26,7 @@
 #include "image_load_tiff.h"
 #include "image_load_dds.h"
 #include "image_load_ffmpegthumbnailer.h"
+#include "image_load_collection.h"
 
 #include "exif.h"
 #include "filedata.h"
@@ -643,6 +644,12 @@
 		image_loader_backend_set_dds(&il->backend);
 		}
 	else
+	if (il->fd->format_class == FORMAT_CLASS_COLLECTION)
+		{
+		DEBUG_1("Using custom collection loader");
+		image_loader_backend_set_collection(&il->backend);
+		}
+	else
 		image_loader_backend_set_default(&il->backend);
 
 	il->loader = il->backend.loader_new(image_loader_area_updated_cb, image_loader_size_cb, image_loader_area_prepared_cb, il);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/image_load_collection.c	Wed Jul 18 10:16:41 2018 +0100
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 20018 - The Geeqie Team
+ *
+ * Author: Colin Clark
+ *
+ * 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 02110-1301 USA.
+ */
+
+#include "main.h"
+#include "image-load.h"
+#include "image_load_collection.h"
+
+#include "misc.h"
+
+typedef struct _ImageLoaderCOLLECTION ImageLoaderCOLLECTION;
+struct _ImageLoaderCOLLECTION {
+	ImageLoaderBackendCbAreaUpdated area_updated_cb;
+	ImageLoaderBackendCbSize size_cb;
+	ImageLoaderBackendCbAreaPrepared area_prepared_cb;
+	gpointer data;
+	GdkPixbuf *pixbuf;
+	guint requested_width;
+	guint requested_height;
+	gboolean abort;
+};
+
+static gboolean image_loader_collection_load(gpointer loader, const guchar *buf, gsize count, GError **error)
+{
+	ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader;
+	ImageLoader *il = ld->data;
+
+	#define LINE_LENGTH 1000
+	#define MAX_LINES 23
+
+	gboolean ret = FALSE;
+	gchar *randname;
+	gchar *cmd_line;
+	FILE *fp = NULL;
+	gint line_count = 0;
+	GString *file_names = g_string_new(NULL);
+	gchar line[LINE_LENGTH];
+
+	if (runcmd("which montage >/dev/null 2>&1") == 0)
+		{
+		fp = fopen(il->fd->path, "r");
+		if (fp)
+			{
+			while(fgets(line, LINE_LENGTH, fp) && line_count < MAX_LINES)
+				{
+				/* get rid of ending \n from fgets */
+				line[strlen(line) - 1] = '\0';
+				if (line[0] && line[0] != '#')
+					{
+					file_names = g_string_append(file_names, line);
+					file_names = g_string_append(file_names, " ");
+					}
+				line_count++;
+				}
+			fclose(fp);
+
+			if (file_names->len > 0)
+				{
+				randname = g_strdup("geeqie_collection_XXXXXX.png");
+				g_mkstemp(randname);
+
+				cmd_line = g_strdup_printf("montage %s -geometry %dx%d+1+1 %s >/dev/null 2>&1", file_names->str, options->thumbnails.max_width, options->thumbnails.max_height, randname);
+
+				runcmd(cmd_line);
+				ld->pixbuf = gdk_pixbuf_new_from_file(randname, NULL);
+				if (ld->pixbuf)
+					{
+					ld->area_updated_cb(loader, 0, 0, gdk_pixbuf_get_width(ld->pixbuf), gdk_pixbuf_get_height(ld->pixbuf), ld->data);
+					}
+
+				unlink(randname);
+				g_free(randname);
+				g_string_free(file_names, TRUE);
+				g_free(cmd_line);
+
+				ret = TRUE;
+				}
+			else
+				{
+				g_string_free(file_names, TRUE);
+				}
+			}
+		}
+	return ret;
+}
+
+static gpointer image_loader_collection_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data)
+{
+	ImageLoaderCOLLECTION *loader = g_new0(ImageLoaderCOLLECTION, 1);
+	loader->area_updated_cb = area_updated_cb;
+	loader->size_cb = size_cb;
+	loader->area_prepared_cb = area_prepared_cb;
+	loader->data = data;
+	return (gpointer) loader;
+}
+
+static void image_loader_collection_set_size(gpointer loader, int width, int height)
+{
+	ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader;
+	ld->requested_width = width;
+	ld->requested_height = height;
+}
+
+static GdkPixbuf* image_loader_collection_get_pixbuf(gpointer loader)
+{
+	ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader;
+	return ld->pixbuf;
+}
+
+static gchar* image_loader_collection_get_format_name(gpointer loader)
+{
+	return g_strdup("collection");
+}
+static gchar** image_loader_collection_get_format_mime_types(gpointer loader)
+{
+	static gchar *mime[] = {"image/png", NULL};
+	return g_strdupv(mime);
+}
+
+static gboolean image_loader_collection_close(gpointer loader, GError **error)
+{
+	return TRUE;
+}
+
+static void image_loader_collection_abort(gpointer loader)
+{
+	ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader;
+	ld->abort = TRUE;
+}
+
+static void image_loader_collection_free(gpointer loader)
+{
+	ImageLoaderCOLLECTION *ld = (ImageLoaderCOLLECTION *) loader;
+	if (ld->pixbuf) g_object_unref(ld->pixbuf);
+	g_free(ld);
+}
+
+void image_loader_backend_set_collection(ImageLoaderBackend *funcs)
+{
+	funcs->loader_new = image_loader_collection_new;
+	funcs->set_size = image_loader_collection_set_size;
+	funcs->load = image_loader_collection_load;
+	funcs->write = NULL;
+	funcs->get_pixbuf = image_loader_collection_get_pixbuf;
+	funcs->close = image_loader_collection_close;
+	funcs->abort = image_loader_collection_abort;
+	funcs->free = image_loader_collection_free;
+	funcs->get_format_name = image_loader_collection_get_format_name;
+	funcs->get_format_mime_types = image_loader_collection_get_format_mime_types;
+}
+
+/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/image_load_collection.h	Wed Jul 18 10:16:41 2018 +0100
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 20018 - The Geeqie Team
+ *
+ * Author: Colin Clark
+ *
+ * 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 02110-1301 USA.
+ */
+
+#ifndef IMAGE_LOAD_COLLECTION_H
+#define IMAGE_LOAD_COLLECTION_H
+
+void image_loader_backend_set_collection(ImageLoaderBackend *funcs);
+
+#endif
+/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/thumb.c	Sun Jul 15 11:02:07 2018 +0100
+++ b/src/thumb.c	Wed Jul 18 10:16:41 2018 +0100
@@ -337,7 +337,7 @@
 
 	if (!tl->fd) tl->fd = file_data_ref(fd);
 
-	if (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && !options->file_filter.disable)
+	if (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_COLLECTION && tl->fd->format_class != FORMAT_CLASS_VIDEO && !options->file_filter.disable)
 		{
 		thumb_loader_set_fallback(tl);
 		return FALSE;
--- a/src/thumb_standard.c	Sun Jul 15 11:02:07 2018 +0100
+++ b/src/thumb_standard.c	Wed Jul 18 10:16:41 2018 +0100
@@ -667,7 +667,7 @@
 
 
 	tl->fd = file_data_ref(fd);
-	if (!stat_utf8(fd->path, &st) || (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && !options->file_filter.disable))
+	if (!stat_utf8(fd->path, &st) || (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && tl->fd->format_class != FORMAT_CLASS_COLLECTION && !options->file_filter.disable))
 		{
 		thumb_loader_std_set_fallback(tl);
 		return FALSE;