From 92c6523db91dd8f148ecc30f20fcde8f4818401d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Juuso=20R=C3=A4s=C3=A4nen?= Date: Thu, 23 Dec 2010 00:38:40 +0100 Subject: [PATCH] Allow to sort files according to Exif-date I also like the idea about sorting files according to Exif-date. This behaviour seemed to be implemented in the pan-view but not in the main browser view. I created a little patch to "correct" this issue. ;) This satisfies my own needs, although the exif-date reading could be probably somehow optimised(?).. now the GUI becomes unresponsive for few seconds if there are a lot of pictures in the directory... --- src/filedata.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/menu.c | 4 +++ src/typedefs.h | 4 ++- 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/filedata.c b/src/filedata.c index 9cc94249..3ec68b29 100644 --- a/src/filedata.c +++ b/src/filedata.c @@ -22,6 +22,8 @@ #include "trash.h" #include "histogram.h" +#include "exif.h" + #include static GHashTable *file_data_pool = NULL; @@ -32,6 +34,8 @@ static void file_data_check_sidecars(const GList *basename_list); static void file_data_disconnect_sidecar_file(FileData *target, FileData *sfd); +static SortType filelist_sort_method = SORT_NONE; +static gboolean filelist_sort_ascend = TRUE; /* *----------------------------------------------------------------------------- @@ -406,6 +410,63 @@ static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolea return ret; } +void init_exif_time_data(GList *files) { + FileData *file; + DEBUG_1("%s init_exif_time_data: ...", get_exec_time()); + while (files) + { + file = files->data; + + if (file) + file->exifdate = 0; + + files = files->next; + } +} + +void set_exif_time_data(GList *files) { + gchar *tmp; + uint year, month, day, hour, min, sec; + struct tm time_str; + FileData *file; + DEBUG_1("%s set_exif_time_data: ...", get_exec_time()); + while (files) + { + file = files->data; + + if (file->exifdate > 0) + { + files = files->next; + DEBUG_1("%s set_exif_time_data: Already exists for %s", get_exec_time(), file->path); + continue; + } + + DEBUG_1("%s set_exif_time_data: Getting exiftime for %s", get_exec_time(), file->path); + + file->exif = exif_read_fd(file); + + if (file->exif) + { + tmp = exif_get_data_as_text(file->exif, "Exif.Photo.DateTimeOriginal"); + if (tmp) + { + sscanf(tmp, "%4d:%2d:%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec); + time_str.tm_year = year - 1900; + time_str.tm_mon = month - 1; + time_str.tm_mday = day; + time_str.tm_hour = hour; + time_str.tm_min = min; + time_str.tm_sec = sec; + time_str.tm_isdst = 0; + + file->exifdate = mktime(&time_str); + } + } + files = files->next; + } + +} + FileData *file_data_new_no_grouping(const gchar *path_utf8) { struct stat st; @@ -772,9 +833,6 @@ void file_data_disable_grouping_list(GList *fd_list, gboolean disable) *----------------------------------------------------------------------------- */ -static SortType filelist_sort_method = SORT_NONE; -static gboolean filelist_sort_ascend = TRUE; - gint filelist_sort_compare_filedata(FileData *fa, FileData *fb) { @@ -800,6 +858,11 @@ gint filelist_sort_compare_filedata(FileData *fa, FileData *fb) if (fa->date > fb->date) return 1; /* fall back to name */ break; + case SORT_EXIFTIME: + if (fa->exifdate < fb->exifdate) return -1; + if (fa->exifdate > fb->exifdate) return 1; + /* fall back to name */ + break; #ifdef HAVE_STRVERSCMP case SORT_NUMBER: ret = strverscmp(fa->name, fb->name); @@ -851,6 +914,10 @@ GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gb GList *filelist_sort(GList *list, SortType method, gboolean ascend) { + if (method == SORT_EXIFTIME) + { + set_exif_time_data(list); + } return filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb); } @@ -1064,6 +1131,9 @@ static gboolean filelist_read_real(const gchar *dir_path, GList **files, GList * } if (basename_hash) file_data_basename_hash_free(basename_hash); + // Call a separate function to initialize the exif datestamps for the found files.. + if (files) init_exif_time_data(*files); + return TRUE; } diff --git a/src/menu.c b/src/menu.c index e586218e..eb9c50bf 100644 --- a/src/menu.c +++ b/src/menu.c @@ -135,6 +135,9 @@ gchar *sort_type_get_text(SortType method) case SORT_TIME: return _("Sort by date"); break; + case SORT_EXIFTIME: + return _("Sort by Exif-date"); + break; case SORT_NONE: return _("Unsorted"); break; @@ -188,6 +191,7 @@ GtkWidget *submenu_add_sort(GtkWidget *menu, GCallback func, gpointer data, submenu_add_sort_item(submenu, func, SORT_NUMBER, show_current, type); #endif submenu_add_sort_item(submenu, func, SORT_TIME, show_current, type); + submenu_add_sort_item(submenu, func, SORT_EXIFTIME, show_current, type); submenu_add_sort_item(submenu, func, SORT_SIZE, show_current, type); if (include_path) submenu_add_sort_item(submenu, func, SORT_PATH, show_current, type); if (include_none) submenu_add_sort_item(submenu, func, SORT_NONE, show_current, type); diff --git a/src/typedefs.h b/src/typedefs.h index 6739bb67..1ccde471 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -50,7 +50,8 @@ typedef enum { SORT_SIZE, SORT_TIME, SORT_PATH, - SORT_NUMBER + SORT_NUMBER, + SORT_EXIFTIME } SortType; typedef enum { @@ -521,6 +522,7 @@ struct _FileData { gint exif_orientation; ExifData *exif; + time_t exifdate; GHashTable *modified_xmp; // hash table which contains unwritten xmp metadata in format: key->list of string values GList *cached_metadata; }; -- 2.20.1