# HG changeset patch # User Colin Clark # Date 1531905401 -3600 # Node ID d9764817aad8bee52ca92054a02c51a43f06ac4b # Parent 6ed30da8b62df647791203cffd780a7b05a49d64 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 diff -r 6ed30da8b62d -r d9764817aad8 src/Makefile.am --- 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 \ diff -r 6ed30da8b62d -r d9764817aad8 src/image-load.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); diff -r 6ed30da8b62d -r d9764817aad8 src/image_load_collection.c --- /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: */ diff -r 6ed30da8b62d -r d9764817aad8 src/image_load_collection.h --- /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: */ diff -r 6ed30da8b62d -r d9764817aad8 src/thumb.c --- 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; diff -r 6ed30da8b62d -r d9764817aad8 src/thumb_standard.c --- 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;