# HG changeset patch # User Colin Clark # Date 1515013108 0 # Node ID 940f217da9ec4cae3d9d5b44c48bd7605f0bd78b # Parent f090fbf9362f0ae01d7e5d137e21821fecba2100 Sort/search on Exif.Photo.DateTimeDigitized Implement sort and search on Exif.Photo.DateTimeDigitized Note: pan view not included diff -r f090fbf9362f -r 940f217da9ec doc/docbook/GuideImageSearchSearch.xml --- a/doc/docbook/GuideImageSearchSearch.xml Wed Jan 03 17:49:15 2018 +0000 +++ b/doc/docbook/GuideImageSearchSearch.xml Wed Jan 03 20:58:28 2018 +0000 @@ -89,7 +89,7 @@ File date - The search will match if the file modification time on disk is equal to, before, after, or between the entered date, depending on the method selected from the drop down menu. The + The search will match if the file date is equal to, before, after, or between the entered date, depending on the method selected from the drop down menu. The between test is inclusive, for example a file with date of 10/04/2003 will match if the date parameters are between 10/04/2003 and 12/31/2003. @@ -103,9 +103,10 @@ button displays a pop up calendar to enter the date. - The - Exif date - checkbox permits searches to be made on the exif date of images. If an image does not have an exif date, it will default to 01 January 1970. + One of four date types may be selected. They are described in the + Reference section + . + If an image does not have an exif date, it will default to 01 January 1970. diff -r f090fbf9362f -r 940f217da9ec doc/docbook/GuideMainWindowStatusBar.xml --- a/doc/docbook/GuideMainWindowStatusBar.xml Wed Jan 03 17:49:15 2018 +0000 +++ b/doc/docbook/GuideMainWindowStatusBar.xml Wed Jan 03 20:58:28 2018 +0000 @@ -39,18 +39,14 @@ - File Creation Date + File Date - Images are sorted by file creation date. - - - - - Exif Date - - - Images are sorted by file Exif date. + + Images are sorted by one of four types of file date. They are described in the + Reference section + . + diff -r f090fbf9362f -r 940f217da9ec src/collect.c --- a/src/collect.c Wed Jan 03 17:49:15 2018 +0000 +++ b/src/collect.c Wed Jan 03 20:58:28 2018 +0000 @@ -169,6 +169,18 @@ if (cia->fd->cdate > cib->fd->cdate) return 1; return 0; break; + case SORT_EXIFTIME: + if (cia->fd->exifdate < cib->fd->exifdate) return -1; + if (cia->fd->exifdate > cib->fd->exifdate) return 1; + break; + case SORT_EXIFTIMEDIGITIZED: + if (cia->fd->exifdate_digitized < cib->fd->exifdate_digitized) return -1; + if (cia->fd->exifdate_digitized > cib->fd->exifdate_digitized) return 1; + break; + case SORT_RATING: + if (cia->fd->rating < cib->fd->rating) return -1; + if (cia->fd->rating > cib->fd->rating) return 1; + break; case SORT_PATH: return utf8_compare(cia->fd->path, cib->fd->path, options->file_sort.case_sensitive); break; diff -r f090fbf9362f -r 940f217da9ec src/exif-common.c --- a/src/exif-common.c Wed Jan 03 17:49:15 2018 +0000 +++ b/src/exif-common.c Wed Jan 03 20:58:28 2018 +0000 @@ -250,6 +250,57 @@ return text; } +static gchar *exif_build_formatted_DateTimeDigitized(ExifData *exif) +{ + gchar *text = exif_get_data_as_text(exif, "Exif.Photo.DateTimeDigitized"); + gchar *subsec = NULL; + gchar buf[128]; + gchar *tmp; + gint buflen; + struct tm tm; + GError *error = NULL; + + if (text) + { + subsec = exif_get_data_as_text(exif, "Exif.Photo.SubSecTimeDigitized"); + } + else + { + text = exif_get_data_as_text(exif, "Exif.Image.DateTime"); + if (text) subsec = exif_get_data_as_text(exif, "Exif.Photo.SubSecTime"); + } + + /* Convert the stuff into a tm struct */ + memset(&tm, 0, sizeof(tm)); /* Uh, strptime could let garbage in tm! */ + if (text && strptime(text, "%Y:%m:%d %H:%M:%S", &tm)) + { + buflen = strftime(buf, sizeof(buf), "%x %X", &tm); + if (buflen > 0) + { + tmp = g_locale_to_utf8(buf, buflen, NULL, NULL, &error); + if (error) + { + log_printf("Error converting locale strftime to UTF-8: %s\n", error->message); + g_error_free(error); + } + else + { + g_free(text); + text = g_strdup(tmp); + } + } + } + + if (subsec) + { + tmp = text; + text = g_strconcat(tmp, ".", subsec, NULL); + g_free(tmp); + g_free(subsec); + } + return text; +} + static gchar *exif_build_formatted_ShutterSpeed(ExifData *exif) { ExifRational *r; @@ -563,6 +614,7 @@ ExifFormattedText ExifFormattedList[] = { EXIF_FORMATTED_TAG(Camera, N_("Camera")), EXIF_FORMATTED_TAG(DateTime, N_("Date")), + EXIF_FORMATTED_TAG(DateTimeDigitized, N_("DateDigitized")), EXIF_FORMATTED_TAG(ShutterSpeed, N_("Shutter speed")), EXIF_FORMATTED_TAG(Aperture, N_("Aperture")), EXIF_FORMATTED_TAG(ExposureBias, N_("Exposure bias")), diff -r f090fbf9362f -r 940f217da9ec src/filedata.c --- a/src/filedata.c Wed Jan 03 17:49:15 2018 +0000 +++ b/src/filedata.c Wed Jan 03 20:58:28 2018 +0000 @@ -503,6 +503,41 @@ } } +void read_exif_time_digitized_data(FileData *file) +{ + if (file->exifdate > 0) + { + DEBUG_1("%s set_exif_time_digitized_data: Already exists for %s", get_exec_time(), file->path); + return; + } + + file->exif = exif_read_fd(file); + + if (file->exif) + { + gchar *tmp = exif_get_data_as_text(file->exif, "Exif.Photo.DateTimeDigitized"); + DEBUG_2("%s set_exif_time_digitized_data: reading %p %s", get_exec_time(), file, file->path); + + if (tmp) + { + struct tm time_str; + uint year, month, day, hour, min, sec; + + 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_digitized = mktime(&time_str); + g_free(tmp); + } + } +} + void set_exif_time_data(GList *files) { DEBUG_1("%s set_exif_time_data: ...", get_exec_time()); @@ -516,6 +551,19 @@ } } +void set_exif_time_digitized_data(GList *files) +{ + DEBUG_1("%s set_exif_time_digitized_data: ...", get_exec_time()); + + while (files) + { + FileData *file = files->data; + + read_exif_time_digitized_data(file); + files = files->next; + } +} + void set_rating_data(GList *files) { gchar *rating_str; @@ -1046,6 +1094,11 @@ if (fa->exifdate > fb->exifdate) return 1; /* fall back to name */ break; + case SORT_EXIFTIMEDIGITIZED: + if (fa->exifdate_digitized < fb->exifdate_digitized) return -1; + if (fa->exifdate_digitized > fb->exifdate_digitized) return 1; + /* fall back to name */ + break; case SORT_RATING: if (fa->rating < fb->rating) return -1; if (fa->rating > fb->rating) return 1; @@ -1111,6 +1164,10 @@ { set_exif_time_data(list); } + if (method == SORT_EXIFTIMEDIGITIZED) + { + set_exif_time_digitized_data(list); + } if (method == SORT_RATING) { set_rating_data(list); diff -r f090fbf9362f -r 940f217da9ec src/filedata.h --- a/src/filedata.h Wed Jan 03 17:49:15 2018 +0000 +++ b/src/filedata.h Wed Jan 03 20:58:28 2018 +0000 @@ -162,5 +162,6 @@ gboolean file_data_unregister_real_time_monitor(FileData *fd); void read_exif_time_data(FileData *file); +void read_exif_time_digitized_data(FileData *file); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r f090fbf9362f -r 940f217da9ec src/lua.c --- a/src/lua.c Wed Jan 03 17:49:15 2018 +0000 +++ b/src/lua.c Wed Jan 03 20:58:28 2018 +0000 @@ -167,7 +167,22 @@ lua_pushnil(L); return 1; } - } // if (strcmp(key, "Exif.Photo.Da... + } + else if (strcmp(key, "Exif.Photo.DateTimeDigitized") == 0) + { + memset(&tm, 0, sizeof(tm)); + if (value && strptime(value, "%Y:%m:%d %H:%M:%S", &tm)) + { + datetime = mktime(&tm); + lua_pushnumber(L, datetime); + return 1; + } + else + { + lua_pushnil(L); + return 1; + } + } lua_pushstring(L, value); return 1; } diff -r f090fbf9362f -r 940f217da9ec src/menu.c --- a/src/menu.c Wed Jan 03 17:49:15 2018 +0000 +++ b/src/menu.c Wed Jan 03 20:58:28 2018 +0000 @@ -149,7 +149,10 @@ return _("Sort by file creation date"); break; case SORT_EXIFTIME: - return _("Sort by Exif-date"); + return _("Sort by Exif date original"); + break; + case SORT_EXIFTIMEDIGITIZED: + return _("Sort by Exif date digitized"); break; case SORT_NONE: return _("Unsorted"); @@ -212,6 +215,7 @@ submenu_add_sort_item(submenu, func, SORT_TIME, show_current, type); submenu_add_sort_item(submenu, func, SORT_CTIME, show_current, type); submenu_add_sort_item(submenu, func, SORT_EXIFTIME, show_current, type); + submenu_add_sort_item(submenu, func, SORT_EXIFTIMEDIGITIZED, show_current, type); submenu_add_sort_item(submenu, func, SORT_SIZE, show_current, type); submenu_add_sort_item(submenu, func, SORT_RATING, show_current, type); submenu_add_sort_item(submenu, func, SORT_CLASS, show_current, type); diff -r f090fbf9362f -r 940f217da9ec src/search.c --- a/src/search.c Wed Jan 03 17:49:15 2018 +0000 +++ b/src/search.c Wed Jan 03 20:58:28 2018 +0000 @@ -119,6 +119,7 @@ GtkWidget *menu_date; GtkWidget *date_sel; GtkWidget *date_sel_end; + GtkWidget *date_type; GtkWidget *check_dimensions; GtkWidget *menu_dimensions; @@ -172,7 +173,6 @@ gint search_rating; gint search_rating_end; gboolean search_comment_match_case; - gboolean search_date_exif; MatchType search_type; @@ -1859,11 +1859,23 @@ tested = TRUE; match = FALSE; - if (sd->search_date_exif) + if (g_strcmp0(gtk_combo_box_text_get_active_text( + GTK_COMBO_BOX_TEXT(sd->date_type)), _("Changed")) == 0) + { + file_date = fd->cdate; + } + else if (g_strcmp0(gtk_combo_box_text_get_active_text( + GTK_COMBO_BOX_TEXT(sd->date_type)), _("Original")) == 0) { read_exif_time_data(fd); file_date = fd->exifdate; } + else if (g_strcmp0(gtk_combo_box_text_get_active_text( + GTK_COMBO_BOX_TEXT(sd->date_type)), _("Digitized")) == 0) + { + read_exif_time_digitized_data(fd); + file_date = fd->exifdate_digitized; + } else { file_date = fd->date; @@ -2998,6 +3010,7 @@ _("File date is"), &sd->match_date_enable, text_search_menu_date, sizeof(text_search_menu_date) / sizeof(MatchList), G_CALLBACK(menu_choice_date_cb), sd); + sd->date_sel = date_selection_new(); date_selection_time_set(sd->date_sel, time(NULL)); gtk_box_pack_start(GTK_BOX(hbox), sd->date_sel, FALSE, FALSE, 0); @@ -3010,8 +3023,16 @@ date_selection_time_set(sd->date_sel_end, time(NULL)); gtk_box_pack_start(GTK_BOX(hbox2), sd->date_sel_end, FALSE, FALSE, 0); gtk_widget_show(sd->date_sel_end); - pref_checkbox_new_int(hbox, _("Exif date"), - sd->search_date_exif, &sd->search_date_exif); + + sd->date_type = gtk_combo_box_text_new(); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->date_type), _("Modified")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->date_type), _("Status Changed")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->date_type), _("Original")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->date_type), _("Digitized")); + gtk_box_pack_start(GTK_BOX(hbox), sd->date_type, FALSE, FALSE, 0); + gtk_combo_box_set_active(GTK_COMBO_BOX(sd->date_type), 0); + gtk_widget_set_tooltip_text(sd->date_type, "Modified (mtime)\nStatus Changed (ctime)\nOriginal (Exif.Photo.DateTimeOriginal)\nDigitized (Exif.Photo.DateTimeDigitized)"); + gtk_widget_show(sd->date_type); /* Search for image dimensions */ hbox = menu_choice(sd->box_search, &sd->check_dimensions, &sd->menu_dimensions, diff -r f090fbf9362f -r 940f217da9ec src/typedefs.h --- a/src/typedefs.h Wed Jan 03 17:49:15 2018 +0000 +++ b/src/typedefs.h Wed Jan 03 20:58:28 2018 +0000 @@ -74,6 +74,7 @@ SORT_PATH, SORT_NUMBER, SORT_EXIFTIME, + SORT_EXIFTIMEDIGITIZED, SORT_RATING, SORT_CLASS } SortType; @@ -588,6 +589,7 @@ ExifData *exif; time_t exifdate; + time_t exifdate_digitized; GHashTable *modified_xmp; // hash table which contains unwritten xmp metadata in format: key->list of string values GList *cached_metadata; gint rating; diff -r f090fbf9362f -r 940f217da9ec web/help/GuideImageSearchSearch.html --- a/web/help/GuideImageSearchSearch.html Wed Jan 03 17:49:15 2018 +0000 +++ b/web/help/GuideImageSearchSearch.html Wed Jan 03 20:58:28 2018 +0000 @@ -543,7 +543,7 @@ File date
- The search will match if the file modification time on disk is equal to, before, after, or between the entered date, depending on the method selected from the drop down menu. The + The search will match if the file date is equal to, before, after, or between the entered date, depending on the method selected from the drop down menu. The between test is inclusive, for example a file with date of 10/04/2003 will match if the date parameters are between 10/04/2003 and 12/31/2003.

@@ -557,9 +557,10 @@ button displays a pop up calendar to enter the date.

- The - Exif date - checkbox permits searches to be made on the exif date of images. If an image does not have an exif date, it will default to 01 January 1970. + One of four date types may be selected. They are described in the + Reference section + . +
If an image does not have an exif date, it will default to 01 January 1970.
Image dimensions diff -r f090fbf9362f -r 940f217da9ec web/help/GuideMainWindowStatusBar.html --- a/web/help/GuideMainWindowStatusBar.html Wed Jan 03 17:49:15 2018 +0000 +++ b/web/help/GuideMainWindowStatusBar.html Wed Jan 03 20:58:28 2018 +0000 @@ -501,16 +501,14 @@

Images are sorted by file modification date.

- File Creation Date + File Date
-

Images are sorted by file creation date.

-
-
- Exif Date -
-
-

Images are sorted by file Exif date.

+

+ Images are sorted by one of four types of file date. They are described in the + Reference section + . +

Size