Collection preview
authorColin Clark <colin.clark@cclark.uk>
Wed, 18 Jul 2018 09:16:41 +0000 (10:16 +0100)
committerColin Clark <colin.clark@cclark.uk>
Wed, 18 Jul 2018 09:16:41 +0000 (10:16 +0100)
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

src/Makefile.am
src/image-load.c
src/image_load_collection.c [new file with mode: 0644]
src/image_load_collection.h [new file with mode: 0644]
src/thumb.c
src/thumb_standard.c

index 6ea6ff3..c6951b1 100644 (file)
@@ -181,6 +181,8 @@ geeqie_SOURCES = \
        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 \
index 79a94d9..4e7d63f 100644 (file)
@@ -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"
@@ -642,6 +643,12 @@ static void image_loader_setup_loader(ImageLoader *il)
                DEBUG_1("Using dds loader");
                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);
 
diff --git a/src/image_load_collection.c b/src/image_load_collection.c
new file mode 100644 (file)
index 0000000..d8bd281
--- /dev/null
@@ -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: */
diff --git a/src/image_load_collection.h b/src/image_load_collection.h
new file mode 100644 (file)
index 0000000..dbc201a
--- /dev/null
@@ -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: */
index cdd4e55..b960d9a 100644 (file)
@@ -337,7 +337,7 @@ gboolean thumb_loader_start(ThumbLoader *tl, FileData *fd)
 
        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;
index 6d9e4a8..b156f70 100644 (file)
@@ -667,7 +667,7 @@ gboolean thumb_loader_std_start(ThumbLoaderStd *tl, FileData *fd)
 
 
        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;