Allow to sort files according to Exif-date
authorJuuso Räsänen <juusora@gmail.com>
Wed, 22 Dec 2010 23:38:40 +0000 (00:38 +0100)
committerLaurent Monin <zas@norz.org>
Thu, 16 Aug 2012 21:27:08 +0000 (23:27 +0200)
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
src/menu.c
src/typedefs.h

index 9cc9424..3ec68b2 100644 (file)
@@ -22,6 +22,8 @@
 #include "trash.h"
 #include "histogram.h"
 
+#include "exif.h"
+
 #include <errno.h>
 
 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;
 }
 
index e586218..eb9c50b 100644 (file)
@@ -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);
index 6739bb6..1ccde47 100644 (file)
@@ -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;
 };