Mercurial > geeqie.yaz
changeset 586:905688aa2317
split filelist.c to filefilter.c and filedata.c
author | nadvornik |
---|---|
date | Mon, 05 May 2008 19:11:12 +0000 |
parents | 4875d67823b4 |
children | 5963c394ba53 |
files | src/Makefile.am src/bar_exif.c src/bar_info.c src/bar_sort.c src/cache-loader.c src/cache_maint.c src/collect-io.c src/collect-table.c src/collect.c src/dupe.c src/editors.c src/exif-common.c src/exiv2.cc src/filedata.c src/filedata.h src/filefilter.c src/filefilter.h src/filelist.c src/filelist.h src/image-load.c src/image-overlay.c src/image.c src/img-view.c src/info.c src/layout.c src/layout_image.c src/layout_util.c src/main.c src/menu.c src/pan-types.h src/preferences.c src/print.c src/rcfile.c src/search.c src/slideshow.c src/thumb.c src/ui_bookmark.c src/ui_utildlg.c src/utilops.c src/view_dir.c src/view_dir_list.c src/view_dir_tree.c src/view_file_icon.c src/view_file_list.h |
diffstat | 44 files changed, 1528 insertions(+), 1479 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Makefile.am Mon May 05 09:21:01 2008 +0000 +++ b/src/Makefile.am Mon May 05 19:11:12 2008 +0000 @@ -104,8 +104,10 @@ exif-int.h \ exif-common.c \ exiv2.cc \ - filelist.c \ - filelist.h \ + filedata.c \ + filedata.h \ + filefilter.c \ + filefilter.h \ format_canon.c \ format_canon.h \ format_fuji.c \
--- a/src/bar_exif.c Mon May 05 09:21:01 2008 +0000 +++ b/src/bar_exif.c Mon May 05 19:11:12 2008 +0000 @@ -17,7 +17,7 @@ #include "exif.h" #include "ui_bookmark.h" #include "ui_misc.h" -#include "filelist.h" +#include "filedata.h" #include <math.h>
--- a/src/bar_info.c Mon May 05 09:21:01 2008 +0000 +++ b/src/bar_info.c Mon May 05 19:11:12 2008 +0000 @@ -18,7 +18,7 @@ #include "cache.h" #include "debug.h" -#include "filelist.h" +#include "filedata.h" #include "info.h" #include "secure_save.h" #include "utilops.h"
--- a/src/bar_sort.c Mon May 05 09:21:01 2008 +0000 +++ b/src/bar_sort.c Mon May 05 19:11:12 2008 +0000 @@ -16,7 +16,7 @@ #include "collect.h" #include "collect-io.h" -#include "filelist.h" +#include "filedata.h" #include "layout.h" #include "layout_image.h" #include "utilops.h"
--- a/src/cache-loader.c Mon May 05 09:21:01 2008 +0000 +++ b/src/cache-loader.c Mon May 05 19:11:12 2008 +0000 @@ -14,7 +14,7 @@ #include "cache-loader.h" #include "cache.h" -#include "filelist.h" +#include "filedata.h" #include "exif.h" #include "md5-util.h" #include "ui_fileops.h"
--- a/src/cache_maint.c Mon May 05 09:21:01 2008 +0000 +++ b/src/cache_maint.c Mon May 05 19:11:12 2008 +0000 @@ -15,7 +15,7 @@ #include "cache.h" #include "debug.h" -#include "filelist.h" +#include "filedata.h" #include "thumb.h" #include "thumb_standard.h" #include "ui_fileops.h"
--- a/src/collect-io.c Mon May 05 09:21:01 2008 +0000 +++ b/src/collect-io.c Mon May 05 19:11:12 2008 +0000 @@ -16,7 +16,7 @@ #include "collect.h" #include "debug.h" -#include "filelist.h" +#include "filedata.h" #include "layout_util.h" #include "rcfile.h" #include "secure_save.h"
--- a/src/collect-table.c Mon May 05 09:21:01 2008 +0000 +++ b/src/collect-table.c Mon May 05 19:11:12 2008 +0000 @@ -21,7 +21,7 @@ #include "dnd.h" #include "dupe.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" #include "img-view.h" #include "info.h" #include "layout.h"
--- a/src/collect.c Mon May 05 09:21:01 2008 +0000 +++ b/src/collect.c Mon May 05 19:11:12 2008 +0000 @@ -19,7 +19,7 @@ #include "collect-table.h" #include "debug.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" #include "img-view.h" #include "info.h" #include "layout.h"
--- a/src/dupe.c Mon May 05 09:21:01 2008 +0000 +++ b/src/dupe.c Mon May 05 19:11:12 2008 +0000 @@ -20,7 +20,7 @@ #include "debug.h" #include "dnd.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" #include "image-load.h" #include "img-view.h" #include "info.h"
--- a/src/editors.c Mon May 05 09:21:01 2008 +0000 +++ b/src/editors.c Mon May 05 19:11:12 2008 +0000 @@ -19,7 +19,8 @@ #include "ui_spinner.h" #include "ui_utildlg.h" -#include "filelist.h" +#include "filedata.h" +#include "filefilter.h" #include <errno.h>
--- a/src/exif-common.c Mon May 05 09:21:01 2008 +0000 +++ b/src/exif-common.c Mon May 05 19:11:12 2008 +0000 @@ -36,7 +36,8 @@ #include "exif.h" #include "debug.h" -#include "filelist.h" +#include "filedata.h" +#include "filefilter.h" #include "format_raw.h" #include "ui_fileops.h"
--- a/src/exiv2.cc Mon May 05 09:21:01 2008 +0000 +++ b/src/exiv2.cc Mon May 05 19:11:12 2008 +0000 @@ -55,7 +55,7 @@ #include "exif.h" #include "debug.h" -#include "filelist.h" +#include "filefilter.h" #include "ui_fileops.h" }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/filedata.c Mon May 05 19:11:12 2008 +0000 @@ -0,0 +1,889 @@ +/* + * Geeqie + * (C) 2006 John Ellis + * Copyright (C) 2008 The Geeqie Team + * + * Author: John Ellis + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + + +#include "main.h" +#include "filedata.h" + +#include "filefilter.h" +#include "cache.h" +#include "debug.h" +#include "rcfile.h" +#include "secure_save.h" +#include "thumb_standard.h" +#include "ui_fileops.h" + + +static gint sidecar_file_priority(const gchar *path); + + +/* + *----------------------------------------------------------------------------- + * text conversion utils + *----------------------------------------------------------------------------- + */ + +gchar *text_from_size(gint64 size) +{ + gchar *a, *b; + gchar *s, *d; + gint l, n, i; + + /* what I would like to use is printf("%'d", size) + * BUT: not supported on every libc :( + */ + if (size > G_MAXUINT) + { + /* the %lld conversion is not valid in all libcs, so use a simple work-around */ + a = g_strdup_printf("%d%09d", (guint)(size / 1000000000), (guint)(size % 1000000000)); + } + else + { + a = g_strdup_printf("%d", (guint)size); + } + l = strlen(a); + n = (l - 1)/ 3; + if (n < 1) return a; + + b = g_new(gchar, l + n + 1); + + s = a; + d = b; + i = l - n * 3; + while (*s != '\0') + { + if (i < 1) + { + i = 3; + *d = ','; + d++; + } + + *d = *s; + s++; + d++; + i--; + } + *d = '\0'; + + g_free(a); + return b; +} + +gchar *text_from_size_abrev(gint64 size) +{ + if (size < (gint64)1024) + { + return g_strdup_printf(_("%d bytes"), (gint)size); + } + if (size < (gint64)1048576) + { + return g_strdup_printf(_("%.1f K"), (double)size / 1024.0); + } + if (size < (gint64)1073741824) + { + return g_strdup_printf(_("%.1f MB"), (double)size / 1048576.0); + } + + /* to avoid overflowing the double, do division in two steps */ + size /= 1048576; + return g_strdup_printf(_("%.1f GB"), (double)size / 1024.0); +} + +/* note: returned string is valid until next call to text_from_time() */ +const gchar *text_from_time(time_t t) +{ + static gchar *ret = NULL; + gchar buf[128]; + gint buflen; + struct tm *btime; + GError *error = NULL; + + btime = localtime(&t); + + /* the %x warning about 2 digit years is not an error */ + buflen = strftime(buf, sizeof(buf), "%x %H:%M", btime); + if (buflen < 1) return ""; + + g_free(ret); + ret = g_locale_to_utf8(buf, buflen, NULL, NULL, &error); + if (error) + { + printf("Error converting locale strftime to UTF-8: %s\n", error->message); + g_error_free(error); + return ""; + } + + return ret; +} + +/* + *----------------------------------------------------------------------------- + * file info struct + *----------------------------------------------------------------------------- + */ + +FileData *file_data_merge_sidecar_files(FileData *target, FileData *source); +static void file_data_check_sidecars(FileData *fd); +FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd); + + +static void file_data_set_path(FileData *fd, const gchar *path) +{ + + if (strcmp(path, "/") == 0) + { + fd->path = g_strdup(path); + fd->name = fd->path; + fd->extension = fd->name + 1; + return; + } + + fd->path = g_strdup(path); + fd->name = filename_from_path(fd->path); + + if (strcmp(fd->name, "..") == 0) + { + gchar *dir = remove_level_from_path(path); + g_free(fd->path); + fd->path = remove_level_from_path(dir); + g_free(dir); + fd->name = ".."; + fd->extension = fd->name + 2; + return; + } + else if (strcmp(fd->name, ".") == 0) + { + g_free(fd->path); + fd->path = remove_level_from_path(path); + fd->name = "."; + fd->extension = fd->name + 1; + return; + } + + fd->extension = extension_from_path(fd->path); + if (fd->extension == NULL) + fd->extension = fd->name + strlen(fd->name); +} + +static void file_data_check_changed_files(FileData *fd, struct stat *st) +{ + GList *work; + if (fd->size != st->st_size || + fd->date != st->st_mtime) + { + fd->size = st->st_size; + fd->date = st->st_mtime; + if (fd->pixbuf) g_object_unref(fd->pixbuf); + fd->pixbuf = NULL; + } + + work = fd->sidecar_files; + while (work) + { + FileData *sfd = work->data; + struct stat st; + + if (!stat_utf8(sfd->path, &st)) + { + file_data_disconnect_sidecar_file(fd, sfd); + } + + file_data_check_changed_files(sfd, &st); + work = work->next; + } +} + +static GHashTable *file_data_pool = NULL; + +static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars) +{ + FileData *fd; + + DEBUG_2("file_data_new: '%s' %d", path_utf8, check_sidecars); + + if (!file_data_pool) + file_data_pool = g_hash_table_new(g_str_hash, g_str_equal); + + fd = g_hash_table_lookup(file_data_pool, path_utf8); + if (fd) + { + file_data_check_changed_files(fd, st); + DEBUG_2("file_data_pool hit: '%s'", fd->path); + return file_data_ref(fd); + } + + fd = g_new0(FileData, 1); + + file_data_set_path(fd, path_utf8); + + fd->original_path = g_strdup(path_utf8); + fd->size = st->st_size; + fd->date = st->st_mtime; + fd->pixbuf = NULL; + fd->sidecar_files = NULL; + fd->ref = 1; + fd->magick = 0x12345678; + + g_hash_table_insert(file_data_pool, fd->original_path, fd); + + if (check_sidecars && sidecar_file_priority(fd->extension)) + file_data_check_sidecars(fd); + return fd; +} + +static void file_data_check_sidecars(FileData *fd) +{ + int base_len = fd->extension - fd->path; + GString *fname = g_string_new_len(fd->path, base_len); + FileData *parent_fd = NULL; + GList *work = sidecar_ext_get_list(); + while (work) + { + /* check for possible sidecar files; + the sidecar files created here are referenced only via fd->sidecar_files or fd->parent, + they have fd->ref set to 0 and file_data unref must chack and free them all together + (using fd->ref would cause loops and leaks) + */ + + FileData *new_fd; + + gchar *ext = work->data; + work = work->next; + + if (strcmp(ext, fd->extension) == 0) + { + new_fd = fd; /* processing the original file */ + } + else + { + struct stat nst; + g_string_truncate(fname, base_len); + g_string_append(fname, ext); + + if (!stat_utf8(fname->str, &nst)) + continue; + + new_fd = file_data_new(fname->str, &nst, FALSE); + new_fd->ref--; /* do not use ref here */ + } + + if (!parent_fd) + parent_fd = new_fd; /* parent is the one with the highest prio, found first */ + else + file_data_merge_sidecar_files(parent_fd, new_fd); + } + g_string_free(fname, TRUE); +} + + +static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars) +{ + gchar *path_utf8 = path_to_utf8(path); + FileData *ret = file_data_new(path_utf8, st, check_sidecars); + g_free(path_utf8); + return ret; +} + +FileData *file_data_new_simple(const gchar *path_utf8) +{ + struct stat st; + + if (!stat_utf8(path_utf8, &st)) + { + st.st_size = 0; + st.st_mtime = 0; + } + + return file_data_new(path_utf8, &st, TRUE); +} + +FileData *file_data_add_sidecar_file(FileData *target, FileData *sfd) +{ + sfd->parent = target; + if(!g_list_find(target->sidecar_files, sfd)) + target->sidecar_files = g_list_prepend(target->sidecar_files, sfd); + return target; +} + + +FileData *file_data_merge_sidecar_files(FileData *target, FileData *source) +{ + GList *work; + file_data_add_sidecar_file(target, source); + + work = source->sidecar_files; + while (work) + { + FileData *sfd = work->data; + file_data_add_sidecar_file(target, sfd); + work = work->next; + } + + g_list_free(source->sidecar_files); + source->sidecar_files = NULL; + + target->sidecar_files = filelist_sort(target->sidecar_files, SORT_NAME, TRUE); + return target; +} + + + +FileData *file_data_ref(FileData *fd) +{ + if (fd == NULL) return NULL; + +// return g_memdup(fd, sizeof(FileData)); + g_assert(fd->magick == 0x12345678); + fd->ref++; + return fd; +} + +static void file_data_free(FileData *fd) +{ + g_assert(fd->magick == 0x12345678); + g_assert(fd->ref == 0); + + g_hash_table_remove(file_data_pool, fd->original_path); + + g_free(fd->path); + g_free(fd->original_path); + if (fd->pixbuf) g_object_unref(fd->pixbuf); + + + g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */ + + file_data_change_info_free(NULL, fd); + g_free(fd); +} + +void file_data_unref(FileData *fd) +{ + if (fd == NULL) return; + g_assert(fd->magick == 0x12345678); + + fd->ref--; + DEBUG_2("file_data_unref (%d): '%s'", fd->ref, fd->path); + + if (fd->ref == 0) + { + FileData *parent = fd->parent ? fd->parent : fd; + + GList *work; + + if (parent->ref > 0) + return; + + work = parent->sidecar_files; + while (work) + { + FileData *sfd = work->data; + if (sfd->ref > 0) + return; + work = work->next; + } + + /* none of parent/children is referenced, we can free everything */ + + DEBUG_2("file_data_unref: deleting '%s', parent '%s'", fd->path, parent->path); + + work = parent->sidecar_files; + while (work) + { + FileData *sfd = work->data; + file_data_free(sfd); + work = work->next; + } + + g_list_free(parent->sidecar_files); + parent->sidecar_files = NULL; + + file_data_free(parent); + + } +} + +FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd) +{ + sfd->parent = target; + g_assert(g_list_find(target->sidecar_files, sfd)); + + target->sidecar_files = g_list_remove(target->sidecar_files, sfd); + sfd->parent = NULL; + + if (sfd->ref == 0) { + file_data_free(sfd); + return NULL; + } + + return sfd; +} + +/* compare name without extension */ +gint file_data_compare_name_without_ext(FileData *fd1, FileData *fd2) +{ + size_t len1 = fd1->extension - fd1->name; + size_t len2 = fd2->extension - fd2->name; + + if (len1 < len2) return -1; + if (len1 > len2) return 1; + + return strncmp(fd1->name, fd2->name, len1); +} + +void file_data_do_change(FileData *fd) +{ +//FIXME sidecars + g_assert(fd->change); + g_free(fd->path); + g_hash_table_remove(file_data_pool, fd->original_path); + g_free(fd->original_path); + file_data_set_path(fd, fd->change->dest); + fd->original_path = g_strdup(fd->change->dest); + g_hash_table_insert(file_data_pool, fd->original_path, fd); + +} + +gboolean file_data_add_change_info(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest) +{ + + FileDataChangeInfo *fdci; + + if (fd->change) return FALSE; + + fdci = g_new0(FileDataChangeInfo, 1); + + fdci->type = type; + + if (src) + fdci->source = g_strdup(src); + else + fdci->source = g_strdup(fd->path); + + if (dest) + fdci->dest = g_strdup(dest); + + fd->change = fdci; + return TRUE; +} + +void file_data_change_info_free(FileDataChangeInfo *fdci, FileData *fd) +{ + if (!fdci && fd) + fdci = fd->change; + + if (!fdci) + return; + + g_free(fdci->source); + g_free(fdci->dest); + + g_free(fdci); + + if (fd) + fd->change = NULL; +} + + + + +/* + *----------------------------------------------------------------------------- + * sidecar file info struct + *----------------------------------------------------------------------------- + */ + + + +static gint sidecar_file_priority(const gchar *path) +{ + const char *extension = extension_from_path(path); + int i = 1; + GList *work; + if (extension == NULL) + return 0; + + work = sidecar_ext_get_list(); + + while (work) { + gchar *ext = work->data; + work = work->next; + if (strcmp(extension, ext) == 0) return i; + i++; + } + return 0; +} + +gchar *sidecar_file_data_list_to_string(FileData *fd) +{ + GList *work; + GString *result = g_string_new(""); + + work = fd->sidecar_files; + while (work) + { + FileData *sfd = work->data; + result = g_string_append(result, "+ "); + result = g_string_append(result, sfd->extension); + work = work->next; + if (work) result = g_string_append_c(result, ' '); + } + + return g_string_free(result, FALSE); +} + +/* + *----------------------------------------------------------------------------- + * load file list + *----------------------------------------------------------------------------- + */ + +static SortType filelist_sort_method = SORT_NONE; +static gint filelist_sort_ascend = TRUE; + + +gint filelist_sort_compare_filedata(FileData *fa, FileData *fb) +{ + if (!filelist_sort_ascend) + { + FileData *tmp = fa; + fa = fb; + fb = tmp; + } + + switch (filelist_sort_method) + { + case SORT_SIZE: + if (fa->size < fb->size) return -1; + if (fa->size > fb->size) return 1; + return CASE_SORT(fa->name, fb->name); /* fall back to name */ + break; + case SORT_TIME: + if (fa->date < fb->date) return -1; + if (fa->date > fb->date) return 1; + return CASE_SORT(fa->name, fb->name); /* fall back to name */ + break; +#ifdef HAVE_STRVERSCMP + case SORT_NUMBER: + return strverscmp(fa->name, fb->name); + break; +#endif + case SORT_NAME: + default: + return CASE_SORT(fa->name, fb->name); + break; + } +} + +gint filelist_sort_compare_filedata_full(FileData *fa, FileData *fb, SortType method, gint ascend) +{ + filelist_sort_method = method; + filelist_sort_ascend = ascend; + return filelist_sort_compare_filedata(fa, fb); +} + +static gint filelist_sort_file_cb(void *a, void *b) +{ + return filelist_sort_compare_filedata(a, b); +} + +GList *filelist_sort_full(GList *list, SortType method, gint ascend, GCompareFunc cb) +{ + filelist_sort_method = method; + filelist_sort_ascend = ascend; + return g_list_sort(list, cb); +} + +GList *filelist_insert_sort_full(GList *list, void *data, SortType method, gint ascend, GCompareFunc cb) +{ + filelist_sort_method = method; + filelist_sort_ascend = ascend; + return g_list_insert_sorted(list, data, cb); +} + +GList *filelist_sort(GList *list, SortType method, gint ascend) +{ + return filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb); +} + +GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend) +{ + return filelist_insert_sort_full(list, fd, method, ascend, (GCompareFunc) filelist_sort_file_cb); +} + + +static GList *filelist_filter_out_sidecars(GList *flist) +{ + GList *work = flist; + GList *flist_filtered = NULL; + + while (work) + { + FileData *fd = work->data; + work = work->next; + if (fd->parent) /* remove fd's that are children */ + file_data_unref(fd); + else + flist_filtered = g_list_prepend(flist_filtered, fd); + } + g_list_free(flist); + return flist_filtered; +} + +static gint filelist_read_real(const gchar *path, GList **files, GList **dirs, gint follow_symlinks) +{ + DIR *dp; + struct dirent *dir; + struct stat ent_sbuf; + gchar *pathl; + GList *dlist; + GList *flist; + + dlist = NULL; + flist = NULL; + + pathl = path_from_utf8(path); + if (!pathl || (dp = opendir(pathl)) == NULL) + { + g_free(pathl); + if (files) *files = NULL; + if (dirs) *dirs = NULL; + return FALSE; + } + + /* root dir fix */ + if (pathl[0] == '/' && pathl[1] == '\0') + { + g_free(pathl); + pathl = g_strdup(""); + } + + while ((dir = readdir(dp)) != NULL) + { + gchar *name = dir->d_name; + if (options->file_filter.show_hidden_files || !ishidden(name)) + { + gchar *filepath = g_strconcat(pathl, "/", name, NULL); + if ((follow_symlinks ? + stat(filepath, &ent_sbuf) : + lstat(filepath, &ent_sbuf)) >= 0) + { + if (S_ISDIR(ent_sbuf.st_mode)) + { + /* we ignore the .thumbnails dir for cleanliness */ + if ((dirs) && + !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) && + strcmp(name, GQ_CACHE_LOCAL_THUMB) != 0 && + strcmp(name, GQ_CACHE_LOCAL_METADATA) != 0 && + strcmp(name, THUMB_FOLDER_LOCAL) != 0) + { + dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE)); + } + } + else + { + if ((files) && filter_name_exists(name)) + { + flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE)); + } + } + } + g_free(filepath); + } + } + + closedir(dp); + + g_free(pathl); + + flist = filelist_filter_out_sidecars(flist); + + if (dirs) *dirs = dlist; + if (files) *files = flist; + + return TRUE; +} + +gint filelist_read(const gchar *path, GList **files, GList **dirs) +{ + return filelist_read_real(path, files, dirs, TRUE); +} + +gint filelist_read_lstat(const gchar *path, GList **files, GList **dirs) +{ + return filelist_read_real(path, files, dirs, FALSE); +} + +void filelist_free(GList *list) +{ + GList *work; + + work = list; + while (work) + { + file_data_unref((FileData *)work->data); + work = work->next; + } + + g_list_free(list); +} + + +GList *filelist_copy(GList *list) +{ + GList *new_list = NULL; + GList *work; + + work = list; + while (work) + { + FileData *fd; + + fd = work->data; + work = work->next; + + new_list = g_list_prepend(new_list, file_data_ref(fd)); + } + + return g_list_reverse(new_list); +} + +GList *filelist_from_path_list(GList *list) +{ + GList *new_list = NULL; + GList *work; + + work = list; + while (work) + { + gchar *path; + + path = work->data; + work = work->next; + + new_list = g_list_prepend(new_list, file_data_new_simple(path)); + } + + return g_list_reverse(new_list); +} + +GList *filelist_to_path_list(GList *list) +{ + GList *new_list = NULL; + GList *work; + + work = list; + while (work) + { + FileData *fd; + + fd = work->data; + work = work->next; + + new_list = g_list_prepend(new_list, g_strdup(fd->path)); + } + + return g_list_reverse(new_list); +} + +GList *filelist_filter(GList *list, gint is_dir_list) +{ + GList *work; + + if (!is_dir_list && options->file_filter.disable && options->file_filter.show_hidden_files) return list; + + work = list; + while (work) + { + FileData *fd = (FileData *)(work->data); + const gchar *name = fd->name; + + if ((!options->file_filter.show_hidden_files && ishidden(name)) || + (!is_dir_list && !filter_name_exists(name)) || + (is_dir_list && name[0] == '.' && (strcmp(name, GQ_CACHE_LOCAL_THUMB) == 0 || + strcmp(name, GQ_CACHE_LOCAL_METADATA) == 0)) ) + { + GList *link = work; + work = work->next; + list = g_list_remove_link(list, link); + file_data_unref(fd); + g_list_free(link); + } + else + { + work = work->next; + } + } + + return list; +} + +/* + *----------------------------------------------------------------------------- + * filelist recursive + *----------------------------------------------------------------------------- + */ + +static gint filelist_sort_path_cb(gconstpointer a, gconstpointer b) +{ + return CASE_SORT(((FileData *)a)->path, ((FileData *)b)->path); +} + +GList *filelist_sort_path(GList *list) +{ + return g_list_sort(list, filelist_sort_path_cb); +} + +static void filelist_recursive_append(GList **list, GList *dirs) +{ + GList *work; + + work = dirs; + while (work) + { + FileData *fd = (FileData *)(work->data); + const gchar *path = fd->path; + GList *f = NULL; + GList *d = NULL; + + if (filelist_read(path, &f, &d)) + { + f = filelist_filter(f, FALSE); + f = filelist_sort_path(f); + *list = g_list_concat(*list, f); + + d = filelist_filter(d, TRUE); + d = filelist_sort_path(d); + filelist_recursive_append(list, d); + filelist_free(d); + } + + work = work->next; + } +} + +GList *filelist_recursive(const gchar *path) +{ + GList *list = NULL; + GList *d = NULL; + + if (!filelist_read(path, &list, &d)) return NULL; + list = filelist_filter(list, FALSE); + list = filelist_sort_path(list); + + d = filelist_filter(d, TRUE); + d = filelist_sort_path(d); + filelist_recursive_append(&list, d); + filelist_free(d); + + return list; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/filedata.h Mon May 05 19:11:12 2008 +0000 @@ -0,0 +1,52 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 The Geeqie Team + * + * Author: John Ellis + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + + +#ifndef FILEDATA_H +#define FILEDATA_H + +gchar *text_from_size(gint64 size); +gchar *text_from_size_abrev(gint64 size); +const gchar *text_from_time(time_t t); + +/* this expects a utf-8 path */ +FileData *file_data_new_simple(const gchar *path_utf8); + +FileData *file_data_ref(FileData *fd); +void file_data_unref(FileData *fd); + +void file_data_do_change(FileData *fd); +gboolean file_data_add_change_info(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest); +void file_data_change_info_free(FileDataChangeInfo *fdci, FileData *fd); + +gchar *sidecar_file_data_list_to_string(FileData *fd); + +gint filelist_sort_compare_filedata(FileData *fa, FileData *fb); +gint filelist_sort_compare_filedata_full(FileData *fa, FileData *fb, SortType method, gint ascend); +GList *filelist_sort(GList *list, SortType method, gint ascend); +GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend); +GList *filelist_sort_full(GList *list, SortType method, gint ascend, GCompareFunc cb); +GList *filelist_insert_sort_full(GList *list, void *data, SortType method, gint ascend, GCompareFunc cb); + +gint filelist_read(const gchar *path, GList **files, GList **dirs); +gint filelist_read_lstat(const gchar *path, GList **files, GList **dirs); +void filelist_free(GList *list); +GList *filelist_copy(GList *list); +GList *filelist_from_path_list(GList *list); +GList *filelist_to_path_list(GList *list); + +GList *filelist_filter(GList *list, gint is_dir_list); + +GList *filelist_sort_path(GList *list); +GList *filelist_recursive(const gchar *path); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/filefilter.c Mon May 05 19:11:12 2008 +0000 @@ -0,0 +1,489 @@ +/* + * Geeqie + * (C) 2006 John Ellis + * Copyright (C) 2008 The Geeqie Team + * + * Author: John Ellis + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + + +#include "main.h" +#include "filefilter.h" + +#include "cache.h" +#include "debug.h" +#include "rcfile.h" +#include "secure_save.h" +#include "thumb_standard.h" +#include "ui_fileops.h" + + +/* + *----------------------------------------------------------------------------- + * file filtering + *----------------------------------------------------------------------------- + */ + +static GList *filter_list = NULL; +static GList *extension_list = NULL; +static GList *sidecar_ext_list = NULL; + +static GList *file_class_extension_list[FILE_FORMAT_CLASSES]; + + +gint ishidden(const gchar *name) +{ + if (name[0] != '.') return FALSE; + if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE; + return TRUE; +} + +static FilterEntry *filter_entry_new(const gchar *key, const gchar *description, + const gchar *extensions, FileFormatClass file_class, gint enabled) +{ + FilterEntry *fe; + + fe = g_new0(FilterEntry, 1); + fe->key = g_strdup(key); + fe->description = g_strdup(description); + fe->extensions = g_strdup(extensions); + fe->enabled = enabled; + fe->file_class = file_class; + + return fe; +} + +static void filter_entry_free(FilterEntry *fe) +{ + if (!fe) return; + + g_free(fe->key); + g_free(fe->description); + g_free(fe->extensions); + g_free(fe); +} + +GList *filter_get_list(void) +{ + return filter_list; +} + +void filter_remove_entry(FilterEntry *fe) +{ + if (!g_list_find(filter_list, fe)) return; + + filter_list = g_list_remove(filter_list, fe); + filter_entry_free(fe); +} + +static gint filter_key_exists(const gchar *key) +{ + GList *work; + + if (!key) return FALSE; + + work = filter_list; + while (work) + { + FilterEntry *fe = work->data; + work = work->next; + + if (strcmp(fe->key, key) == 0) return TRUE; + } + + return FALSE; +} + +void filter_add(const gchar *key, const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled) +{ + filter_list = g_list_append(filter_list, filter_entry_new(key, description, extensions, file_class, enabled)); +} + +void filter_add_unique(const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled) +{ + gchar *key; + gint n; + + key = g_strdup("user0"); + n = 1; + while (filter_key_exists(key)) + { + g_free(key); + if (n > 999) return; + key = g_strdup_printf("user%d", n); + n++; + } + + filter_add(key, description, extensions, file_class, enabled); + g_free(key); +} + +static void filter_add_if_missing(const gchar *key, const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled) +{ + GList *work; + + if (!key) return; + + work = filter_list; + while (work) + { + FilterEntry *fe = work->data; + work = work->next; + if (fe->key && strcmp(fe->key, key) == 0) + { + if (fe->file_class == FORMAT_CLASS_UNKNOWN) + fe->file_class = file_class; /* for compatibility */ + return; + } + } + + filter_add(key, description, extensions, file_class, enabled); +} + +void filter_reset(void) +{ + GList *work; + + work = filter_list; + while (work) + { + FilterEntry *fe = work->data; + work = work->next; + filter_entry_free(fe); + } + + g_list_free(filter_list); + filter_list = NULL; +} + +void filter_add_defaults(void) +{ + GSList *list, *work; + + list = gdk_pixbuf_get_formats(); + work = list; + while (work) + { + GdkPixbufFormat *format; + gchar *name; + gchar *desc; + gchar **extensions; + GString *filter = NULL; + gint i; + + format = work->data; + work = work->next; + + name = gdk_pixbuf_format_get_name(format); + desc = gdk_pixbuf_format_get_description(format); + extensions = gdk_pixbuf_format_get_extensions(format); + + i = 0; + while (extensions[i]) + { + if (!filter) + { + filter = g_string_new("."); + filter = g_string_append(filter, extensions[i]); + } + else + { + filter = g_string_append(filter, ";."); + filter = g_string_append(filter, extensions[i]); + } + i++; + } + + DEBUG_1("loader reported [%s] [%s] [%s]", name, desc, filter->str); + + filter_add_if_missing(name, desc, filter->str, FORMAT_CLASS_IMAGE, TRUE); + + g_free(name); + g_free(desc); + g_strfreev(extensions); + g_string_free(filter, TRUE); + } + g_slist_free(list); + + /* add defaults even if gdk-pixbuf does not have them, but disabled */ + filter_add_if_missing("jpeg", "JPEG group", ".jpg;.jpeg;.jpe", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("png", "Portable Network Graphic", ".png", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("tiff", "Tiff", ".tif;.tiff", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("pnm", "Packed Pixel formats", ".pbm;.pgm;.pnm;.ppm", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("gif", "Graphics Interchange Format", ".gif", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("xbm", "X bitmap", ".xbm", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("xpm", "X pixmap", ".xpm", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("bmp", "Bitmap", ".bmp", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("ico", "Icon file", ".ico;.cur", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("ras", "Raster", ".ras", FORMAT_CLASS_IMAGE, FALSE); + filter_add_if_missing("svg", "Scalable Vector Graphics", ".svg", FORMAT_CLASS_IMAGE, FALSE); + + /* non-image files that might be desirable to show */ + filter_add_if_missing("xmp", "XMP sidecar", ".xmp", FORMAT_CLASS_META, TRUE); + + /* These are the raw camera formats with embedded jpeg/exif. + * (see format_raw.c and/or exiv2.cc) + */ + filter_add_if_missing("arw", "Sony raw format", ".arw;.srf;.sr2", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("crw", "Canon raw format", ".crw;.cr2", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("kdc", "Kodak raw format", ".kdc;.dcr", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("raf", "Fujifilm raw format", ".raf", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("mef", "Mamiya raw format", ".mef;.mos", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("mrw", "Minolta raw format", ".mrw", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("nef", "Nikon raw format", ".nef", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("orf", "Olympus raw format", ".orf", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("pef", "Pentax or Samsung raw format", ".pef;.ptx", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("dng", "Adobe Digital Negative raw format", ".dng", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("x3f", "Sigma raw format", ".x3f", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("raw", "Panasonic raw format", ".raw", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("r3d", "Red raw format", ".r3d", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("3fr", "Hasselblad raw format", ".3fr", FORMAT_CLASS_RAWIMAGE, TRUE); + filter_add_if_missing("erf", "Epson raw format", ".erf", FORMAT_CLASS_RAWIMAGE, TRUE); +} + +GList *filter_to_list(const gchar *extensions) +{ + GList *list = NULL; + const gchar *p; + + if (!extensions) return NULL; + + p = extensions; + while (*p != '\0') + { + const gchar *b; + gint l = 0; + + b = p; + while (*p != '\0' && *p != ';') + { + p++; + l++; + } + list = g_list_append(list, g_strndup(b, l)); + if (*p == ';') p++; + } + + return list; +} + +void filter_rebuild(void) +{ + GList *work; + gint i; + + string_list_free(extension_list); + extension_list = NULL; + + for (i = 0; i < FILE_FORMAT_CLASSES; i++) + { + string_list_free(file_class_extension_list[i]); + file_class_extension_list[i] = NULL; + } + + work = filter_list; + while (work) + { + FilterEntry *fe; + + fe = work->data; + work = work->next; + + if (fe->enabled) + { + GList *ext; + + ext = filter_to_list(fe->extensions); + if (ext) extension_list = g_list_concat(extension_list, ext); + + if (fe->file_class >= 0 && fe->file_class < FILE_FORMAT_CLASSES) + { + ext = filter_to_list(fe->extensions); + if (ext) file_class_extension_list[fe->file_class] = g_list_concat(file_class_extension_list[fe->file_class], ext); + } + else + { + printf("WARNING: invalid file class %d\n", fe->file_class); + } + } + } +} + +gint filter_name_exists(const gchar *name) +{ + GList *work; + gint ln; + + if (!extension_list || options->file_filter.disable) return TRUE; + + ln = strlen(name); + work = extension_list; + while (work) + { + gchar *filter = work->data; + gint lf = strlen(filter); + + if (ln >= lf) + { + if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE; + } + work = work->next; + } + + return FALSE; +} + +gint filter_file_class(const gchar *name, FileFormatClass file_class) +{ + GList *work; + gint ln; + + if (file_class < 0 || file_class >= FILE_FORMAT_CLASSES) + { + printf("WARNING: invalid file class %d\n", file_class); + return FALSE; + } + + ln = strlen(name); + work = file_class_extension_list[file_class]; + while (work) + { + gchar *filter = work->data; + gint lf = strlen(filter); + + if (ln >= lf) + { + if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE; + } + work = work->next; + } + + return FALSE; +} + +void filter_write_list(SecureSaveInfo *ssi) +{ + GList *work; + + work = filter_list; + while (work) + { + FilterEntry *fe = work->data; + work = work->next; + + gchar *extensions = escquote_value(fe->extensions); + gchar *description = escquote_value(fe->description); + + secure_fprintf(ssi, "file_filter.ext: \"%s%s\" %s %s %d\n", + (fe->enabled) ? "" : "#", + fe->key, extensions, description, fe->file_class); + g_free(extensions); + g_free(description); + } +} + +void filter_parse(const gchar *text) +{ + const gchar *p; + gchar *key; + gchar *ext; + gchar *desc; + gint enabled = TRUE; + gint file_class; + + if (!text || text[0] != '"') return; + + key = quoted_value(text, &p); + if (!key) return; + + ext = quoted_value(p, &p); + desc = quoted_value(p, &p); + + file_class = strtol(p, NULL, 10); + + if (file_class < 0 || file_class >= FILE_FORMAT_CLASSES) file_class = FORMAT_CLASS_UNKNOWN; + + if (key && key[0] == '#') + { + gchar *tmp; + tmp = g_strdup(key + 1); + g_free(key); + key = tmp; + + enabled = FALSE; + } + + if (key && strlen(key) > 0 && ext) filter_add(key, desc, ext, file_class, enabled); + + g_free(key); + g_free(ext); + g_free(desc); +} + +/* + *----------------------------------------------------------------------------- + * sidecar extension list + *----------------------------------------------------------------------------- + */ + +GList *sidecar_ext_get_list(void) +{ + return sidecar_ext_list; +} + +void sidecar_ext_parse(const gchar *text, gint quoted) +{ + GList *work; + gchar *value; + + work = sidecar_ext_list; + while (work) + { + gchar *ext = work->data; + work = work->next; + g_free(ext); + } + g_list_free(sidecar_ext_list); + sidecar_ext_list = NULL; + + if (quoted) + value = quoted_value(text, NULL); + else + value = g_strdup(text); + + if (value == NULL) return; + + sidecar_ext_list = filter_to_list(value); + + g_free(value); +} + +void sidecar_ext_write(SecureSaveInfo *ssi) +{ + secure_fprintf(ssi, "sidecar.ext: \"%s\"\n", sidecar_ext_to_string()); +} + +char *sidecar_ext_to_string() +{ + GList *work; + GString *str = g_string_new(""); + + work = sidecar_ext_list; + while (work) + { + gchar *ext = work->data; + work = work->next; + g_string_append(str, ext); + if (work) g_string_append(str, ";"); + } + return g_string_free(str, FALSE); +} + +void sidecar_ext_add_defaults() +{ + sidecar_ext_parse(".jpg;.cr2;.nef;.crw;.xmp", FALSE); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/filefilter.h Mon May 05 19:11:12 2008 +0000 @@ -0,0 +1,52 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 The Geeqie Team + * + * Author: John Ellis + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + + +#ifndef FILEFILTER_H +#define FILEFILTER_H + + +typedef struct _FilterEntry FilterEntry; +struct _FilterEntry { + gchar *key; + gchar *description; + gchar *extensions; + FileFormatClass file_class; + gint enabled; +}; + +/* you can change, but not add or remove entries from the returned list */ +GList *filter_get_list(void); +void filter_remove_entry(FilterEntry *fe); + +void filter_add(const gchar *key, const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled); +void filter_add_unique(const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled); +void filter_add_defaults(void); +void filter_reset(void); +void filter_rebuild(void); +GList *filter_to_list(const gchar *extensions); + +gint filter_name_exists(const gchar *name); +gint filter_file_class(const gchar *name, FileFormatClass file_class); + +void filter_write_list(SecureSaveInfo *ssi); +void filter_parse(const gchar *text); + +void sidecar_ext_parse(const gchar *text, gint quoted); +void sidecar_ext_write(SecureSaveInfo *ssi); +char *sidecar_ext_to_string(); +void sidecar_ext_add_defaults(); +GList *sidecar_ext_get_list(void); + +gint ishidden(const gchar *name); + +#endif
--- a/src/filelist.c Mon May 05 09:21:01 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1353 +0,0 @@ -/* - * Geeqie - * (C) 2006 John Ellis - * Copyright (C) 2008 The Geeqie Team - * - * Author: John Ellis - * - * This software is released under the GNU General Public License (GNU GPL). - * Please read the included file COPYING for more information. - * This software comes with no warranty of any kind, use at your own risk! - */ - - -#include "main.h" -#include "filelist.h" - -#include "cache.h" -#include "debug.h" -#include "rcfile.h" -#include "secure_save.h" -#include "thumb_standard.h" -#include "ui_fileops.h" - - -/* - *----------------------------------------------------------------------------- - * file filtering - *----------------------------------------------------------------------------- - */ - -static GList *filter_list = NULL; -static GList *extension_list = NULL; -static GList *sidecar_ext_list = NULL; - -static GList *file_class_extension_list[FILE_FORMAT_CLASSES]; - -static gint sidecar_file_priority(const gchar *path); - - -gint ishidden(const gchar *name) -{ - if (name[0] != '.') return FALSE; - if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE; - return TRUE; -} - -static FilterEntry *filter_entry_new(const gchar *key, const gchar *description, - const gchar *extensions, FileFormatClass file_class, gint enabled) -{ - FilterEntry *fe; - - fe = g_new0(FilterEntry, 1); - fe->key = g_strdup(key); - fe->description = g_strdup(description); - fe->extensions = g_strdup(extensions); - fe->enabled = enabled; - fe->file_class = file_class; - - return fe; -} - -static void filter_entry_free(FilterEntry *fe) -{ - if (!fe) return; - - g_free(fe->key); - g_free(fe->description); - g_free(fe->extensions); - g_free(fe); -} - -GList *filter_get_list(void) -{ - return filter_list; -} - -void filter_remove_entry(FilterEntry *fe) -{ - if (!g_list_find(filter_list, fe)) return; - - filter_list = g_list_remove(filter_list, fe); - filter_entry_free(fe); -} - -static gint filter_key_exists(const gchar *key) -{ - GList *work; - - if (!key) return FALSE; - - work = filter_list; - while (work) - { - FilterEntry *fe = work->data; - work = work->next; - - if (strcmp(fe->key, key) == 0) return TRUE; - } - - return FALSE; -} - -void filter_add(const gchar *key, const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled) -{ - filter_list = g_list_append(filter_list, filter_entry_new(key, description, extensions, file_class, enabled)); -} - -void filter_add_unique(const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled) -{ - gchar *key; - gint n; - - key = g_strdup("user0"); - n = 1; - while (filter_key_exists(key)) - { - g_free(key); - if (n > 999) return; - key = g_strdup_printf("user%d", n); - n++; - } - - filter_add(key, description, extensions, file_class, enabled); - g_free(key); -} - -static void filter_add_if_missing(const gchar *key, const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled) -{ - GList *work; - - if (!key) return; - - work = filter_list; - while (work) - { - FilterEntry *fe = work->data; - work = work->next; - if (fe->key && strcmp(fe->key, key) == 0) - { - if (fe->file_class == FORMAT_CLASS_UNKNOWN) - fe->file_class = file_class; /* for compatibility */ - return; - } - } - - filter_add(key, description, extensions, file_class, enabled); -} - -void filter_reset(void) -{ - GList *work; - - work = filter_list; - while (work) - { - FilterEntry *fe = work->data; - work = work->next; - filter_entry_free(fe); - } - - g_list_free(filter_list); - filter_list = NULL; -} - -void filter_add_defaults(void) -{ - GSList *list, *work; - - list = gdk_pixbuf_get_formats(); - work = list; - while (work) - { - GdkPixbufFormat *format; - gchar *name; - gchar *desc; - gchar **extensions; - GString *filter = NULL; - gint i; - - format = work->data; - work = work->next; - - name = gdk_pixbuf_format_get_name(format); - desc = gdk_pixbuf_format_get_description(format); - extensions = gdk_pixbuf_format_get_extensions(format); - - i = 0; - while (extensions[i]) - { - if (!filter) - { - filter = g_string_new("."); - filter = g_string_append(filter, extensions[i]); - } - else - { - filter = g_string_append(filter, ";."); - filter = g_string_append(filter, extensions[i]); - } - i++; - } - - DEBUG_1("loader reported [%s] [%s] [%s]", name, desc, filter->str); - - filter_add_if_missing(name, desc, filter->str, FORMAT_CLASS_IMAGE, TRUE); - - g_free(name); - g_free(desc); - g_strfreev(extensions); - g_string_free(filter, TRUE); - } - g_slist_free(list); - - /* add defaults even if gdk-pixbuf does not have them, but disabled */ - filter_add_if_missing("jpeg", "JPEG group", ".jpg;.jpeg;.jpe", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("png", "Portable Network Graphic", ".png", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("tiff", "Tiff", ".tif;.tiff", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("pnm", "Packed Pixel formats", ".pbm;.pgm;.pnm;.ppm", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("gif", "Graphics Interchange Format", ".gif", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("xbm", "X bitmap", ".xbm", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("xpm", "X pixmap", ".xpm", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("bmp", "Bitmap", ".bmp", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("ico", "Icon file", ".ico;.cur", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("ras", "Raster", ".ras", FORMAT_CLASS_IMAGE, FALSE); - filter_add_if_missing("svg", "Scalable Vector Graphics", ".svg", FORMAT_CLASS_IMAGE, FALSE); - - /* non-image files that might be desirable to show */ - filter_add_if_missing("xmp", "XMP sidecar", ".xmp", FORMAT_CLASS_META, TRUE); - - /* These are the raw camera formats with embedded jpeg/exif. - * (see format_raw.c and/or exiv2.cc) - */ - filter_add_if_missing("arw", "Sony raw format", ".arw;.srf;.sr2", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("crw", "Canon raw format", ".crw;.cr2", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("kdc", "Kodak raw format", ".kdc;.dcr", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("raf", "Fujifilm raw format", ".raf", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("mef", "Mamiya raw format", ".mef;.mos", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("mrw", "Minolta raw format", ".mrw", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("nef", "Nikon raw format", ".nef", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("orf", "Olympus raw format", ".orf", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("pef", "Pentax or Samsung raw format", ".pef;.ptx", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("dng", "Adobe Digital Negative raw format", ".dng", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("x3f", "Sigma raw format", ".x3f", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("raw", "Panasonic raw format", ".raw", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("r3d", "Red raw format", ".r3d", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("3fr", "Hasselblad raw format", ".3fr", FORMAT_CLASS_RAWIMAGE, TRUE); - filter_add_if_missing("erf", "Epson raw format", ".erf", FORMAT_CLASS_RAWIMAGE, TRUE); -} - -GList *filter_to_list(const gchar *extensions) -{ - GList *list = NULL; - const gchar *p; - - if (!extensions) return NULL; - - p = extensions; - while (*p != '\0') - { - const gchar *b; - gint l = 0; - - b = p; - while (*p != '\0' && *p != ';') - { - p++; - l++; - } - list = g_list_append(list, g_strndup(b, l)); - if (*p == ';') p++; - } - - return list; -} - -void filter_rebuild(void) -{ - GList *work; - gint i; - - string_list_free(extension_list); - extension_list = NULL; - - for (i = 0; i < FILE_FORMAT_CLASSES; i++) - { - string_list_free(file_class_extension_list[i]); - file_class_extension_list[i] = NULL; - } - - work = filter_list; - while (work) - { - FilterEntry *fe; - - fe = work->data; - work = work->next; - - if (fe->enabled) - { - GList *ext; - - ext = filter_to_list(fe->extensions); - if (ext) extension_list = g_list_concat(extension_list, ext); - - if (fe->file_class >= 0 && fe->file_class < FILE_FORMAT_CLASSES) - { - ext = filter_to_list(fe->extensions); - if (ext) file_class_extension_list[fe->file_class] = g_list_concat(file_class_extension_list[fe->file_class], ext); - } - else - { - printf("WARNING: invalid file class %d\n", fe->file_class); - } - } - } -} - -gint filter_name_exists(const gchar *name) -{ - GList *work; - gint ln; - - if (!extension_list || options->file_filter.disable) return TRUE; - - ln = strlen(name); - work = extension_list; - while (work) - { - gchar *filter = work->data; - gint lf = strlen(filter); - - if (ln >= lf) - { - if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE; - } - work = work->next; - } - - return FALSE; -} - -gint filter_file_class(const gchar *name, FileFormatClass file_class) -{ - GList *work; - gint ln; - - if (file_class < 0 || file_class >= FILE_FORMAT_CLASSES) - { - printf("WARNING: invalid file class %d\n", file_class); - return FALSE; - } - - ln = strlen(name); - work = file_class_extension_list[file_class]; - while (work) - { - gchar *filter = work->data; - gint lf = strlen(filter); - - if (ln >= lf) - { - if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE; - } - work = work->next; - } - - return FALSE; -} - -void filter_write_list(SecureSaveInfo *ssi) -{ - GList *work; - - work = filter_list; - while (work) - { - FilterEntry *fe = work->data; - work = work->next; - - gchar *extensions = escquote_value(fe->extensions); - gchar *description = escquote_value(fe->description); - - secure_fprintf(ssi, "file_filter.ext: \"%s%s\" %s %s %d\n", - (fe->enabled) ? "" : "#", - fe->key, extensions, description, fe->file_class); - g_free(extensions); - g_free(description); - } -} - -void filter_parse(const gchar *text) -{ - const gchar *p; - gchar *key; - gchar *ext; - gchar *desc; - gint enabled = TRUE; - gint file_class; - - if (!text || text[0] != '"') return; - - key = quoted_value(text, &p); - if (!key) return; - - ext = quoted_value(p, &p); - desc = quoted_value(p, &p); - - file_class = strtol(p, NULL, 10); - - if (file_class < 0 || file_class >= FILE_FORMAT_CLASSES) file_class = FORMAT_CLASS_UNKNOWN; - - if (key && key[0] == '#') - { - gchar *tmp; - tmp = g_strdup(key + 1); - g_free(key); - key = tmp; - - enabled = FALSE; - } - - if (key && strlen(key) > 0 && ext) filter_add(key, desc, ext, file_class, enabled); - - g_free(key); - g_free(ext); - g_free(desc); -} - -/* - *----------------------------------------------------------------------------- - * sidecar extension list - *----------------------------------------------------------------------------- - */ - -static GList *sidecar_ext_get_list(void) -{ - return sidecar_ext_list; -} - -void sidecar_ext_parse(const gchar *text, gint quoted) -{ - GList *work; - gchar *value; - - work = sidecar_ext_list; - while (work) - { - gchar *ext = work->data; - work = work->next; - g_free(ext); - } - g_list_free(sidecar_ext_list); - sidecar_ext_list = NULL; - - if (quoted) - value = quoted_value(text, NULL); - else - value = g_strdup(text); - - if (value == NULL) return; - - sidecar_ext_list = filter_to_list(value); - - g_free(value); -} - -void sidecar_ext_write(SecureSaveInfo *ssi) -{ - secure_fprintf(ssi, "sidecar.ext: \"%s\"\n", sidecar_ext_to_string()); -} - -char *sidecar_ext_to_string() -{ - GList *work; - GString *str = g_string_new(""); - - work = sidecar_ext_list; - while (work) - { - gchar *ext = work->data; - work = work->next; - g_string_append(str, ext); - if (work) g_string_append(str, ";"); - } - return g_string_free(str, FALSE); -} - -void sidecar_ext_add_defaults() -{ - sidecar_ext_parse(".jpg;.cr2;.nef;.crw;.xmp", FALSE); -} - -/* - *----------------------------------------------------------------------------- - * text conversion utils - *----------------------------------------------------------------------------- - */ - -gchar *text_from_size(gint64 size) -{ - gchar *a, *b; - gchar *s, *d; - gint l, n, i; - - /* what I would like to use is printf("%'d", size) - * BUT: not supported on every libc :( - */ - if (size > G_MAXUINT) - { - /* the %lld conversion is not valid in all libcs, so use a simple work-around */ - a = g_strdup_printf("%d%09d", (guint)(size / 1000000000), (guint)(size % 1000000000)); - } - else - { - a = g_strdup_printf("%d", (guint)size); - } - l = strlen(a); - n = (l - 1)/ 3; - if (n < 1) return a; - - b = g_new(gchar, l + n + 1); - - s = a; - d = b; - i = l - n * 3; - while (*s != '\0') - { - if (i < 1) - { - i = 3; - *d = ','; - d++; - } - - *d = *s; - s++; - d++; - i--; - } - *d = '\0'; - - g_free(a); - return b; -} - -gchar *text_from_size_abrev(gint64 size) -{ - if (size < (gint64)1024) - { - return g_strdup_printf(_("%d bytes"), (gint)size); - } - if (size < (gint64)1048576) - { - return g_strdup_printf(_("%.1f K"), (double)size / 1024.0); - } - if (size < (gint64)1073741824) - { - return g_strdup_printf(_("%.1f MB"), (double)size / 1048576.0); - } - - /* to avoid overflowing the double, do division in two steps */ - size /= 1048576; - return g_strdup_printf(_("%.1f GB"), (double)size / 1024.0); -} - -/* note: returned string is valid until next call to text_from_time() */ -const gchar *text_from_time(time_t t) -{ - static gchar *ret = NULL; - gchar buf[128]; - gint buflen; - struct tm *btime; - GError *error = NULL; - - btime = localtime(&t); - - /* the %x warning about 2 digit years is not an error */ - buflen = strftime(buf, sizeof(buf), "%x %H:%M", btime); - if (buflen < 1) return ""; - - g_free(ret); - ret = g_locale_to_utf8(buf, buflen, NULL, NULL, &error); - if (error) - { - printf("Error converting locale strftime to UTF-8: %s\n", error->message); - g_error_free(error); - return ""; - } - - return ret; -} - -/* - *----------------------------------------------------------------------------- - * file info struct - *----------------------------------------------------------------------------- - */ - -FileData *file_data_merge_sidecar_files(FileData *target, FileData *source); -static void file_data_check_sidecars(FileData *fd); -FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd); - - -static void file_data_set_path(FileData *fd, const gchar *path) -{ - - if (strcmp(path, "/") == 0) - { - fd->path = g_strdup(path); - fd->name = fd->path; - fd->extension = fd->name + 1; - return; - } - - fd->path = g_strdup(path); - fd->name = filename_from_path(fd->path); - - if (strcmp(fd->name, "..") == 0) - { - gchar *dir = remove_level_from_path(path); - g_free(fd->path); - fd->path = remove_level_from_path(dir); - g_free(dir); - fd->name = ".."; - fd->extension = fd->name + 2; - return; - } - else if (strcmp(fd->name, ".") == 0) - { - g_free(fd->path); - fd->path = remove_level_from_path(path); - fd->name = "."; - fd->extension = fd->name + 1; - return; - } - - fd->extension = extension_from_path(fd->path); - if (fd->extension == NULL) - fd->extension = fd->name + strlen(fd->name); -} - -static void file_data_check_changed_files(FileData *fd, struct stat *st) -{ - GList *work; - if (fd->size != st->st_size || - fd->date != st->st_mtime) - { - fd->size = st->st_size; - fd->date = st->st_mtime; - if (fd->pixbuf) g_object_unref(fd->pixbuf); - fd->pixbuf = NULL; - } - - work = fd->sidecar_files; - while (work) - { - FileData *sfd = work->data; - struct stat st; - - if (!stat_utf8(sfd->path, &st)) - { - file_data_disconnect_sidecar_file(fd, sfd); - } - - file_data_check_changed_files(sfd, &st); - work = work->next; - } -} - -static GHashTable *file_data_pool = NULL; - -static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars) -{ - FileData *fd; - - DEBUG_2("file_data_new: '%s' %d", path_utf8, check_sidecars); - - if (!file_data_pool) - file_data_pool = g_hash_table_new(g_str_hash, g_str_equal); - - fd = g_hash_table_lookup(file_data_pool, path_utf8); - if (fd) - { - file_data_check_changed_files(fd, st); - DEBUG_2("file_data_pool hit: '%s'", fd->path); - return file_data_ref(fd); - } - - fd = g_new0(FileData, 1); - - file_data_set_path(fd, path_utf8); - - fd->original_path = g_strdup(path_utf8); - fd->size = st->st_size; - fd->date = st->st_mtime; - fd->pixbuf = NULL; - fd->sidecar_files = NULL; - fd->ref = 1; - fd->magick = 0x12345678; - - g_hash_table_insert(file_data_pool, fd->original_path, fd); - - if (check_sidecars && sidecar_file_priority(fd->extension)) - file_data_check_sidecars(fd); - return fd; -} - -static void file_data_check_sidecars(FileData *fd) -{ - int base_len = fd->extension - fd->path; - GString *fname = g_string_new_len(fd->path, base_len); - FileData *parent_fd = NULL; - GList *work = sidecar_ext_get_list(); - while (work) - { - /* check for possible sidecar files; - the sidecar files created here are referenced only via fd->sidecar_files or fd->parent, - they have fd->ref set to 0 and file_data unref must chack and free them all together - (using fd->ref would cause loops and leaks) - */ - - FileData *new_fd; - - gchar *ext = work->data; - work = work->next; - - if (strcmp(ext, fd->extension) == 0) - { - new_fd = fd; /* processing the original file */ - } - else - { - struct stat nst; - g_string_truncate(fname, base_len); - g_string_append(fname, ext); - - if (!stat_utf8(fname->str, &nst)) - continue; - - new_fd = file_data_new(fname->str, &nst, FALSE); - new_fd->ref--; /* do not use ref here */ - } - - if (!parent_fd) - parent_fd = new_fd; /* parent is the one with the highest prio, found first */ - else - file_data_merge_sidecar_files(parent_fd, new_fd); - } - g_string_free(fname, TRUE); -} - - -static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars) -{ - gchar *path_utf8 = path_to_utf8(path); - FileData *ret = file_data_new(path_utf8, st, check_sidecars); - g_free(path_utf8); - return ret; -} - -FileData *file_data_new_simple(const gchar *path_utf8) -{ - struct stat st; - - if (!stat_utf8(path_utf8, &st)) - { - st.st_size = 0; - st.st_mtime = 0; - } - - return file_data_new(path_utf8, &st, TRUE); -} - -FileData *file_data_add_sidecar_file(FileData *target, FileData *sfd) -{ - sfd->parent = target; - if(!g_list_find(target->sidecar_files, sfd)) - target->sidecar_files = g_list_prepend(target->sidecar_files, sfd); - return target; -} - - -FileData *file_data_merge_sidecar_files(FileData *target, FileData *source) -{ - GList *work; - file_data_add_sidecar_file(target, source); - - work = source->sidecar_files; - while (work) - { - FileData *sfd = work->data; - file_data_add_sidecar_file(target, sfd); - work = work->next; - } - - g_list_free(source->sidecar_files); - source->sidecar_files = NULL; - - target->sidecar_files = filelist_sort(target->sidecar_files, SORT_NAME, TRUE); - return target; -} - - - -FileData *file_data_ref(FileData *fd) -{ - if (fd == NULL) return NULL; - -// return g_memdup(fd, sizeof(FileData)); - g_assert(fd->magick == 0x12345678); - fd->ref++; - return fd; -} - -static void file_data_free(FileData *fd) -{ - g_assert(fd->magick == 0x12345678); - g_assert(fd->ref == 0); - - g_hash_table_remove(file_data_pool, fd->original_path); - - g_free(fd->path); - g_free(fd->original_path); - if (fd->pixbuf) g_object_unref(fd->pixbuf); - - - g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */ - - file_data_change_info_free(NULL, fd); - g_free(fd); -} - -void file_data_unref(FileData *fd) -{ - if (fd == NULL) return; - g_assert(fd->magick == 0x12345678); - - fd->ref--; - DEBUG_2("file_data_unref (%d): '%s'", fd->ref, fd->path); - - if (fd->ref == 0) - { - FileData *parent = fd->parent ? fd->parent : fd; - - GList *work; - - if (parent->ref > 0) - return; - - work = parent->sidecar_files; - while (work) - { - FileData *sfd = work->data; - if (sfd->ref > 0) - return; - work = work->next; - } - - /* none of parent/children is referenced, we can free everything */ - - DEBUG_2("file_data_unref: deleting '%s', parent '%s'", fd->path, parent->path); - - work = parent->sidecar_files; - while (work) - { - FileData *sfd = work->data; - file_data_free(sfd); - work = work->next; - } - - g_list_free(parent->sidecar_files); - parent->sidecar_files = NULL; - - file_data_free(parent); - - } -} - -FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd) -{ - sfd->parent = target; - g_assert(g_list_find(target->sidecar_files, sfd)); - - target->sidecar_files = g_list_remove(target->sidecar_files, sfd); - sfd->parent = NULL; - - if (sfd->ref == 0) { - file_data_free(sfd); - return NULL; - } - - return sfd; -} - -/* compare name without extension */ -gint file_data_compare_name_without_ext(FileData *fd1, FileData *fd2) -{ - size_t len1 = fd1->extension - fd1->name; - size_t len2 = fd2->extension - fd2->name; - - if (len1 < len2) return -1; - if (len1 > len2) return 1; - - return strncmp(fd1->name, fd2->name, len1); -} - -void file_data_do_change(FileData *fd) -{ -//FIXME sidecars - g_assert(fd->change); - g_free(fd->path); - g_hash_table_remove(file_data_pool, fd->original_path); - g_free(fd->original_path); - file_data_set_path(fd, fd->change->dest); - fd->original_path = g_strdup(fd->change->dest); - g_hash_table_insert(file_data_pool, fd->original_path, fd); - -} - -gboolean file_data_add_change_info(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest) -{ - - FileDataChangeInfo *fdci; - - if (fd->change) return FALSE; - - fdci = g_new0(FileDataChangeInfo, 1); - - fdci->type = type; - - if (src) - fdci->source = g_strdup(src); - else - fdci->source = g_strdup(fd->path); - - if (dest) - fdci->dest = g_strdup(dest); - - fd->change = fdci; - return TRUE; -} - -void file_data_change_info_free(FileDataChangeInfo *fdci, FileData *fd) -{ - if (!fdci && fd) - fdci = fd->change; - - if (!fdci) - return; - - g_free(fdci->source); - g_free(fdci->dest); - - g_free(fdci); - - if (fd) - fd->change = NULL; -} - - - - -/* - *----------------------------------------------------------------------------- - * sidecar file info struct - *----------------------------------------------------------------------------- - */ - - - -static gint sidecar_file_priority(const gchar *path) -{ - const char *extension = extension_from_path(path); - int i = 1; - GList *work; - if (extension == NULL) - return 0; - - work = sidecar_ext_get_list(); - - while (work) { - gchar *ext = work->data; - work = work->next; - if (strcmp(extension, ext) == 0) return i; - i++; - } - return 0; -} - -gchar *sidecar_file_data_list_to_string(FileData *fd) -{ - GList *work; - GString *result = g_string_new(""); - - work = fd->sidecar_files; - while (work) - { - FileData *sfd = work->data; - result = g_string_append(result, "+ "); - result = g_string_append(result, sfd->extension); - work = work->next; - if (work) result = g_string_append_c(result, ' '); - } - - return g_string_free(result, FALSE); -} - -/* - *----------------------------------------------------------------------------- - * load file list - *----------------------------------------------------------------------------- - */ - -static SortType filelist_sort_method = SORT_NONE; -static gint filelist_sort_ascend = TRUE; - - -gint filelist_sort_compare_filedata(FileData *fa, FileData *fb) -{ - if (!filelist_sort_ascend) - { - FileData *tmp = fa; - fa = fb; - fb = tmp; - } - - switch (filelist_sort_method) - { - case SORT_SIZE: - if (fa->size < fb->size) return -1; - if (fa->size > fb->size) return 1; - return CASE_SORT(fa->name, fb->name); /* fall back to name */ - break; - case SORT_TIME: - if (fa->date < fb->date) return -1; - if (fa->date > fb->date) return 1; - return CASE_SORT(fa->name, fb->name); /* fall back to name */ - break; -#ifdef HAVE_STRVERSCMP - case SORT_NUMBER: - return strverscmp(fa->name, fb->name); - break; -#endif - case SORT_NAME: - default: - return CASE_SORT(fa->name, fb->name); - break; - } -} - -gint filelist_sort_compare_filedata_full(FileData *fa, FileData *fb, SortType method, gint ascend) -{ - filelist_sort_method = method; - filelist_sort_ascend = ascend; - return filelist_sort_compare_filedata(fa, fb); -} - -static gint filelist_sort_file_cb(void *a, void *b) -{ - return filelist_sort_compare_filedata(a, b); -} - -GList *filelist_sort_full(GList *list, SortType method, gint ascend, GCompareFunc cb) -{ - filelist_sort_method = method; - filelist_sort_ascend = ascend; - return g_list_sort(list, cb); -} - -GList *filelist_insert_sort_full(GList *list, void *data, SortType method, gint ascend, GCompareFunc cb) -{ - filelist_sort_method = method; - filelist_sort_ascend = ascend; - return g_list_insert_sorted(list, data, cb); -} - -GList *filelist_sort(GList *list, SortType method, gint ascend) -{ - return filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb); -} - -GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend) -{ - return filelist_insert_sort_full(list, fd, method, ascend, (GCompareFunc) filelist_sort_file_cb); -} - - -static GList *filelist_filter_out_sidecars(GList *flist) -{ - GList *work = flist; - GList *flist_filtered = NULL; - - while (work) - { - FileData *fd = work->data; - work = work->next; - if (fd->parent) /* remove fd's that are children */ - file_data_unref(fd); - else - flist_filtered = g_list_prepend(flist_filtered, fd); - } - g_list_free(flist); - return flist_filtered; -} - -static gint filelist_read_real(const gchar *path, GList **files, GList **dirs, gint follow_symlinks) -{ - DIR *dp; - struct dirent *dir; - struct stat ent_sbuf; - gchar *pathl; - GList *dlist; - GList *flist; - - dlist = NULL; - flist = NULL; - - pathl = path_from_utf8(path); - if (!pathl || (dp = opendir(pathl)) == NULL) - { - g_free(pathl); - if (files) *files = NULL; - if (dirs) *dirs = NULL; - return FALSE; - } - - /* root dir fix */ - if (pathl[0] == '/' && pathl[1] == '\0') - { - g_free(pathl); - pathl = g_strdup(""); - } - - while ((dir = readdir(dp)) != NULL) - { - gchar *name = dir->d_name; - if (options->file_filter.show_hidden_files || !ishidden(name)) - { - gchar *filepath = g_strconcat(pathl, "/", name, NULL); - if ((follow_symlinks ? - stat(filepath, &ent_sbuf) : - lstat(filepath, &ent_sbuf)) >= 0) - { - if (S_ISDIR(ent_sbuf.st_mode)) - { - /* we ignore the .thumbnails dir for cleanliness */ - if ((dirs) && - !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) && - strcmp(name, GQ_CACHE_LOCAL_THUMB) != 0 && - strcmp(name, GQ_CACHE_LOCAL_METADATA) != 0 && - strcmp(name, THUMB_FOLDER_LOCAL) != 0) - { - dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE)); - } - } - else - { - if ((files) && filter_name_exists(name)) - { - flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE)); - } - } - } - g_free(filepath); - } - } - - closedir(dp); - - g_free(pathl); - - flist = filelist_filter_out_sidecars(flist); - - if (dirs) *dirs = dlist; - if (files) *files = flist; - - return TRUE; -} - -gint filelist_read(const gchar *path, GList **files, GList **dirs) -{ - return filelist_read_real(path, files, dirs, TRUE); -} - -gint filelist_read_lstat(const gchar *path, GList **files, GList **dirs) -{ - return filelist_read_real(path, files, dirs, FALSE); -} - -void filelist_free(GList *list) -{ - GList *work; - - work = list; - while (work) - { - file_data_unref((FileData *)work->data); - work = work->next; - } - - g_list_free(list); -} - - -GList *filelist_copy(GList *list) -{ - GList *new_list = NULL; - GList *work; - - work = list; - while (work) - { - FileData *fd; - - fd = work->data; - work = work->next; - - new_list = g_list_prepend(new_list, file_data_ref(fd)); - } - - return g_list_reverse(new_list); -} - -GList *filelist_from_path_list(GList *list) -{ - GList *new_list = NULL; - GList *work; - - work = list; - while (work) - { - gchar *path; - - path = work->data; - work = work->next; - - new_list = g_list_prepend(new_list, file_data_new_simple(path)); - } - - return g_list_reverse(new_list); -} - -GList *filelist_to_path_list(GList *list) -{ - GList *new_list = NULL; - GList *work; - - work = list; - while (work) - { - FileData *fd; - - fd = work->data; - work = work->next; - - new_list = g_list_prepend(new_list, g_strdup(fd->path)); - } - - return g_list_reverse(new_list); -} - -GList *filelist_filter(GList *list, gint is_dir_list) -{ - GList *work; - - if (!is_dir_list && options->file_filter.disable && options->file_filter.show_hidden_files) return list; - - work = list; - while (work) - { - FileData *fd = (FileData *)(work->data); - const gchar *name = fd->name; - - if ((!options->file_filter.show_hidden_files && ishidden(name)) || - (!is_dir_list && !filter_name_exists(name)) || - (is_dir_list && name[0] == '.' && (strcmp(name, GQ_CACHE_LOCAL_THUMB) == 0 || - strcmp(name, GQ_CACHE_LOCAL_METADATA) == 0)) ) - { - GList *link = work; - work = work->next; - list = g_list_remove_link(list, link); - file_data_unref(fd); - g_list_free(link); - } - else - { - work = work->next; - } - } - - return list; -} - -/* - *----------------------------------------------------------------------------- - * filelist recursive - *----------------------------------------------------------------------------- - */ - -static gint filelist_sort_path_cb(gconstpointer a, gconstpointer b) -{ - return CASE_SORT(((FileData *)a)->path, ((FileData *)b)->path); -} - -GList *filelist_sort_path(GList *list) -{ - return g_list_sort(list, filelist_sort_path_cb); -} - -static void filelist_recursive_append(GList **list, GList *dirs) -{ - GList *work; - - work = dirs; - while (work) - { - FileData *fd = (FileData *)(work->data); - const gchar *path = fd->path; - GList *f = NULL; - GList *d = NULL; - - if (filelist_read(path, &f, &d)) - { - f = filelist_filter(f, FALSE); - f = filelist_sort_path(f); - *list = g_list_concat(*list, f); - - d = filelist_filter(d, TRUE); - d = filelist_sort_path(d); - filelist_recursive_append(list, d); - filelist_free(d); - } - - work = work->next; - } -} - -GList *filelist_recursive(const gchar *path) -{ - GList *list = NULL; - GList *d = NULL; - - if (!filelist_read(path, &list, &d)) return NULL; - list = filelist_filter(list, FALSE); - list = filelist_sort_path(list); - - d = filelist_filter(d, TRUE); - d = filelist_sort_path(d); - filelist_recursive_append(&list, d); - filelist_free(d); - - return list; -}
--- a/src/filelist.h Mon May 05 09:21:01 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Geeqie - * (C) 2004 John Ellis - * Copyright (C) 2008 The Geeqie Team - * - * Author: John Ellis - * - * This software is released under the GNU General Public License (GNU GPL). - * Please read the included file COPYING for more information. - * This software comes with no warranty of any kind, use at your own risk! - */ - - -#ifndef FILELIST_H -#define FILELIST_H - - -typedef struct _FilterEntry FilterEntry; -struct _FilterEntry { - gchar *key; - gchar *description; - gchar *extensions; - FileFormatClass file_class; - gint enabled; -}; - -/* you can change, but not add or remove entries from the returned list */ -GList *filter_get_list(void); -void filter_remove_entry(FilterEntry *fe); - -void filter_add(const gchar *key, const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled); -void filter_add_unique(const gchar *description, const gchar *extensions, FileFormatClass file_class, gint enabled); -void filter_add_defaults(void); -void filter_reset(void); -void filter_rebuild(void); -GList *filter_to_list(const gchar *extensions); - -gint filter_name_exists(const gchar *name); -gint filter_file_class(const gchar *name, FileFormatClass file_class); - -void filter_write_list(SecureSaveInfo *ssi); -void filter_parse(const gchar *text); - -void sidecar_ext_parse(const gchar *text, gint quoted); -void sidecar_ext_write(SecureSaveInfo *ssi); -char *sidecar_ext_to_string(); -void sidecar_ext_add_defaults(); - -gint ishidden(const gchar *name); - - -gchar *text_from_size(gint64 size); -gchar *text_from_size_abrev(gint64 size); -const gchar *text_from_time(time_t t); - -/* this expects a utf-8 path */ -FileData *file_data_new_simple(const gchar *path_utf8); - -FileData *file_data_ref(FileData *fd); -void file_data_unref(FileData *fd); - -void file_data_do_change(FileData *fd); -gboolean file_data_add_change_info(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest); -void file_data_change_info_free(FileDataChangeInfo *fdci, FileData *fd); - -gchar *sidecar_file_data_list_to_string(FileData *fd); - -gint filelist_sort_compare_filedata(FileData *fa, FileData *fb); -gint filelist_sort_compare_filedata_full(FileData *fa, FileData *fb, SortType method, gint ascend); -GList *filelist_sort(GList *list, SortType method, gint ascend); -GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend); -GList *filelist_sort_full(GList *list, SortType method, gint ascend, GCompareFunc cb); -GList *filelist_insert_sort_full(GList *list, void *data, SortType method, gint ascend, GCompareFunc cb); - -gint filelist_read(const gchar *path, GList **files, GList **dirs); -gint filelist_read_lstat(const gchar *path, GList **files, GList **dirs); -void filelist_free(GList *list); -GList *filelist_copy(GList *list); -GList *filelist_from_path_list(GList *list); -GList *filelist_to_path_list(GList *list); - -GList *filelist_filter(GList *list, gint is_dir_list); - -GList *filelist_sort_path(GList *list); -GList *filelist_recursive(const gchar *path); - -#endif
--- a/src/image-load.c Mon May 05 09:21:01 2008 +0000 +++ b/src/image-load.c Mon May 05 19:11:12 2008 +0000 @@ -16,7 +16,7 @@ #include "debug.h" #include "exif.h" -#include "filelist.h" +#include "filedata.h" #include "ui_fileops.h" #include <fcntl.h>
--- a/src/image-overlay.c Mon May 05 09:21:01 2008 +0000 +++ b/src/image-overlay.c Mon May 05 19:11:12 2008 +0000 @@ -15,7 +15,7 @@ #include "collect.h" #include "exif.h" -#include "filelist.h" +#include "filedata.h" #include "image.h" #include "img-view.h" #include "layout.h"
--- a/src/image.c Mon May 05 09:21:01 2008 +0000 +++ b/src/image.c Mon May 05 19:11:12 2008 +0000 @@ -28,7 +28,7 @@ #include "pixbuf_util.h" #include "ui_fileops.h" -#include "filelist.h" +#include "filedata.h" #include <math.h>
--- a/src/img-view.c Mon May 05 09:21:01 2008 +0000 +++ b/src/img-view.c Mon May 05 19:11:12 2008 +0000 @@ -18,7 +18,7 @@ #include "collect-io.h" #include "dnd.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" #include "fullscreen.h" #include "image.h" #include "image-overlay.h"
--- a/src/info.c Mon May 05 09:21:01 2008 +0000 +++ b/src/info.c Mon May 05 19:11:12 2008 +0000 @@ -17,7 +17,7 @@ #include "bar_info.h" #include "bar_exif.h" #include "dnd.h" -#include "filelist.h" +#include "filedata.h" #include "image.h" #include "image-load.h" #include "pixbuf-renderer.h"
--- a/src/layout.c Mon May 05 09:21:01 2008 +0000 +++ b/src/layout.c Mon May 05 19:11:12 2008 +0000 @@ -15,7 +15,7 @@ #include "color-man.h" #include "debug.h" -#include "filelist.h" +#include "filedata.h" #include "histogram.h" #include "image.h" #include "image-overlay.h"
--- a/src/layout_image.c Mon May 05 09:21:01 2008 +0000 +++ b/src/layout_image.c Mon May 05 19:11:12 2008 +0000 @@ -17,7 +17,7 @@ #include "dnd.h" #include "debug.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" #include "fullscreen.h" #include "image.h" #include "image-overlay.h"
--- a/src/layout_util.c Mon May 05 09:21:01 2008 +0000 +++ b/src/layout_util.c Mon May 05 19:11:12 2008 +0000 @@ -23,7 +23,7 @@ #include "compat.h" #include "dupe.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" #include "image-overlay.h" #include "img-view.h" #include "info.h"
--- a/src/main.c Mon May 05 09:21:01 2008 +0000 +++ b/src/main.c Mon May 05 19:11:12 2008 +0000 @@ -19,7 +19,8 @@ #include "debug.h" #include "dnd.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" +#include "filefilter.h" #include "fullscreen.h" #include "image-overlay.h" #include "img-view.h"
--- a/src/menu.c Mon May 05 09:21:01 2008 +0000 +++ b/src/menu.c Mon May 05 19:11:12 2008 +0000 @@ -18,7 +18,7 @@ #include "collect.h" #include "collect-dlg.h" #include "dupe.h" -#include "filelist.h" +#include "filedata.h" #include "img-view.h" #include "preferences.h" #include "slideshow.h"
--- a/src/pan-types.h Mon May 05 09:21:01 2008 +0000 +++ b/src/pan-types.h Mon May 05 19:11:12 2008 +0000 @@ -16,7 +16,7 @@ #include "cache.h" #include "cache-loader.h" -#include "filelist.h" +#include "filedata.h" #include "image.h" #include "image-load.h" #include "pixbuf_util.h"
--- a/src/preferences.c Mon May 05 09:21:01 2008 +0000 +++ b/src/preferences.c Mon May 05 19:11:12 2008 +0000 @@ -17,7 +17,8 @@ #include "cache_maint.h" #include "debug.h" #include "editors.h" -#include "filelist.h" +#include "filedata.h" +#include "filefilter.h" #include "fullscreen.h" #include "image.h" #include "image-overlay.h"
--- a/src/print.c Mon May 05 09:21:01 2008 +0000 +++ b/src/print.c Mon May 05 19:11:12 2008 +0000 @@ -15,7 +15,7 @@ #include "print.h" #include "debug.h" -#include "filelist.h" +#include "filedata.h" #include "image.h" #include "image-load.h" #include "pixbuf_util.h"
--- a/src/rcfile.c Mon May 05 09:21:01 2008 +0000 +++ b/src/rcfile.c Mon May 05 19:11:12 2008 +0000 @@ -17,7 +17,7 @@ #include "rcfile.h" #include "bar_exif.h" -#include "filelist.h" +#include "filefilter.h" #include "secure_save.h" #include "slideshow.h" #include "ui_fileops.h"
--- a/src/search.c Mon May 05 09:21:01 2008 +0000 +++ b/src/search.c Mon May 05 19:11:12 2008 +0000 @@ -24,7 +24,7 @@ #include "info.h" #include "editors.h" #include "img-view.h" -#include "filelist.h" +#include "filedata.h" #include "layout_image.h" #include "menu.h" #include "print.h"
--- a/src/slideshow.c Mon May 05 09:21:01 2008 +0000 +++ b/src/slideshow.c Mon May 05 19:11:12 2008 +0000 @@ -15,7 +15,7 @@ #include "collect.h" #include "image.h" #include "slideshow.h" -#include "filelist.h" +#include "filedata.h" #include "layout.h" #include "layout_image.h"
--- a/src/thumb.c Mon May 05 09:21:01 2008 +0000 +++ b/src/thumb.c Mon May 05 19:11:12 2008 +0000 @@ -17,7 +17,7 @@ #include "cache.h" #include "debug.h" #include "image-load.h" -#include "filelist.h" +#include "filedata.h" #include "pixbuf_util.h" #include "thumb_standard.h" #include "ui_fileops.h"
--- a/src/ui_bookmark.c Mon May 05 09:21:01 2008 +0000 +++ b/src/ui_bookmark.c Mon May 05 19:11:12 2008 +0000 @@ -24,7 +24,7 @@ #include <gdk/gdkkeysyms.h> /* for key values */ #include "main.h" -#include "filelist.h" +#include "filedata.h" #include "debug.h" #include "secure_save.h"
--- a/src/ui_utildlg.c Mon May 05 09:21:01 2008 +0000 +++ b/src/ui_utildlg.c Mon May 05 19:11:12 2008 +0000 @@ -26,7 +26,7 @@ #include "main.h" #include "ui_utildlg.h" -#include "filelist.h" +#include "filedata.h" #include "ui_fileops.h" #include "ui_misc.h" #include "ui_pathsel.h"
--- a/src/utilops.c Mon May 05 09:21:01 2008 +0000 +++ b/src/utilops.c Mon May 05 19:11:12 2008 +0000 @@ -20,7 +20,8 @@ #include "collect.h" #include "debug.h" #include "dupe.h" -#include "filelist.h" +#include "filedata.h" +#include "filefilter.h" #include "image.h" #include "img-view.h" #include "layout.h"
--- a/src/view_dir.c Mon May 05 09:21:01 2008 +0000 +++ b/src/view_dir.c Mon May 05 19:11:12 2008 +0000 @@ -14,7 +14,7 @@ #include "dnd.h" #include "dupe.h" -#include "filelist.h" +#include "filedata.h" #include "layout_image.h" #include "layout_util.h" #include "ui_bookmark.h"
--- a/src/view_dir_list.c Mon May 05 09:21:01 2008 +0000 +++ b/src/view_dir_list.c Mon May 05 19:11:12 2008 +0000 @@ -15,7 +15,7 @@ #include "dnd.h" #include "dupe.h" -#include "filelist.h" +#include "filedata.h" #include "layout.h" #include "layout_image.h" #include "layout_util.h"
--- a/src/view_dir_tree.c Mon May 05 09:21:01 2008 +0000 +++ b/src/view_dir_tree.c Mon May 05 19:11:12 2008 +0000 @@ -16,7 +16,7 @@ #include "dnd.h" #include "dupe.h" -#include "filelist.h" +#include "filedata.h" #include "layout.h" #include "layout_image.h" #include "layout_util.h"
--- a/src/view_file_icon.c Mon May 05 09:21:01 2008 +0000 +++ b/src/view_file_icon.c Mon May 05 19:11:12 2008 +0000 @@ -22,7 +22,7 @@ #include "editors.h" #include "img-view.h" #include "info.h" -#include "filelist.h" +#include "filedata.h" #include "layout.h" #include "layout_image.h" #include "menu.h"
--- a/src/view_file_list.h Mon May 05 09:21:01 2008 +0000 +++ b/src/view_file_list.h Mon May 05 19:11:12 2008 +0000 @@ -14,7 +14,7 @@ #define VIEW_FILE_LIST_H -#include "filelist.h" +#include "filedata.h" gint vflist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data); gint vflist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data);