changeset 2770:2e819f4a7a41

Read metadata in the idle loop Selecting sort-by DateOriginal, DateDigitized or Rating caused Geeqie to freeze while the metadata was read for the whole folder contents. This commit reads those data in the idle loop and thus prevents the freeze. There is an option in Preferences/Metadata to autmatically read the metadata in the idle loop whenever a new folder is selected.
author Colin Clark <colin.clark@cclark.uk>
date Mon, 18 Jun 2018 18:53:46 +0100
parents ed8cc78cb9dd
children 3aa4c31b93ff
files doc/docbook/GuideMainWindowStatusBar.xml doc/docbook/GuideOptionsMetadata.xml src/filedata.c src/filedata.h src/layout.c src/layout_image.c src/main.h src/options.c src/options.h src/preferences.c src/rcfile.c src/typedefs.h src/view_file.h src/view_file/view_file.c src/view_file/view_file_icon.c src/view_file/view_file_icon.h src/view_file/view_file_list.c src/view_file/view_file_list.h web/help/GuideMainWindowStatusBar.html web/help/GuideOptionsMetadata.html web/help/GuideReferenceXmpExif.html web/help/GuideSidebarsInfo.html
diffstat 22 files changed, 286 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docbook/GuideMainWindowStatusBar.xml	Thu Jun 07 14:13:43 2018 +0100
+++ b/doc/docbook/GuideMainWindowStatusBar.xml	Mon Jun 18 18:53:46 2018 +0100
@@ -6,8 +6,14 @@
   <para />
   <section id="ProgressBar">
     <title>Progress Bar</title>
-    <para>The Progress bar updates to display the current state of thumbnail generation. When this section contains no text, thumbnail generation is idle. When “Loading thumbs...” is displayed, thumbnails are currently being generated when Geeqie is idle; the progress bar will update to display the percentage of thumbnails that are completed.</para>
-    <para />
+    <para>
+      The Progress bar updates to display the current state of thumbnail generation, or the reading of metadata in the current folder.
+      <para />
+      When “Loading thumbs...” is displayed, thumbnails are currently being generated when Geeqie is idle; the progress bar will update to display the percentage of thumbnails that are completed.
+      <para />
+      When “Loading meta...” is displayed, certain metadata is being loaded when Geeqie is idle; the progress bar will update to display the percentage of files that have been read. Refer to
+      <link linkend="PreLoadMetadata">Preferences metadata.</link>
+    </para>
   </section>
   <section id="Sortmethod">
     <title>Sort method</title>
--- a/doc/docbook/GuideOptionsMetadata.xml	Thu Jun 07 14:13:43 2018 +0100
+++ b/doc/docbook/GuideOptionsMetadata.xml	Mon Jun 18 18:53:46 2018 +0100
@@ -158,4 +158,29 @@
     </itemizedlist>
     <para />
   </section>
+  <section id="PreLoadMetadata">
+    <title>Pre-load metadata</title>
+    <itemizedlist>
+      <listitem>
+        <para>
+          <guilabel>Read metadata in background</guilabel>
+          <para />
+          Using the folder sorting options:
+          <para />
+          <guilabel>Exif date original</guilabel>
+          <para />
+          <guilabel>Exif date digitized</guilabel>
+          <para />
+          <guilabel>Rating</guilabel>
+          <para />
+          requires metadata to be read from all files in a folder before the sort action can be made. If a folder contains a large number of file, this can take a noticeable period of time.
+          <para />
+          If this option is checked, Geeqie will automatically read the required metatada in the background as soon as a folder is opened. This will reduce the amount of time you have to wait until the sort is completed.
+          <para />
+          If you do not use these sort otions, leave this option unchecked.
+        </para>
+      </listitem>
+    </itemizedlist>
+    <para />
+  </section>
 </section>
--- a/src/filedata.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/filedata.c	Mon Jun 18 18:53:46 2018 +0100
@@ -429,7 +429,7 @@
 	fd->ref = 1;
 	fd->magick = FD_MAGICK;
 	fd->exifdate = 0;
-	fd->rating = 0;
+	fd->rating = STAR_RATING_NOT_READ;
 	fd->format_class = filter_file_get_class(path_utf8);
 
 	if (disable_sidecars) fd->disable_grouping = TRUE;
@@ -477,7 +477,10 @@
 		return;
 		}
 
-	file->exif = exif_read_fd(file);
+	if (!file->exif)
+		{
+		exif_read_fd(file);
+		}
 
 	if (file->exif)
 		{
@@ -512,7 +515,10 @@
 		return;
 		}
 
-	file->exif = exif_read_fd(file);
+	if (!file->exif)
+		{
+		exif_read_fd(file);
+		}
 
 	if (file->exif)
 		{
@@ -539,6 +545,18 @@
 		}
 }
 
+void read_rating_data(FileData *file)
+{
+	gchar *rating_str;
+
+	rating_str = metadata_read_string(file, RATING_KEY, METADATA_PLAIN);
+	if (rating_str)
+		{
+		file->rating = atoi(rating_str);
+		g_free(rating_str);
+		}
+}
+
 void set_exif_time_data(GList *files)
 {
 	DEBUG_1("%s set_exif_time_data: ...", get_exec_time());
@@ -1161,18 +1179,6 @@
 
 GList *filelist_sort(GList *list, SortType method, gboolean ascend)
 {
-	if (method == SORT_EXIFTIME)
-		{
-		set_exif_time_data(list);
-		}
-	if (method == SORT_EXIFTIMEDIGITIZED)
-		{
-		set_exif_time_digitized_data(list);
-		}
-	if (method == SORT_RATING)
-		{
-		set_rating_data(list);
-		}
 	return filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb);
 }
 
--- a/src/filedata.h	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/filedata.h	Mon Jun 18 18:53:46 2018 +0100
@@ -167,5 +167,6 @@
 gboolean marks_list_save(gchar *path, gboolean clear);
 gboolean marks_list_load(const gchar *path);
 void marks_clear_all();
+void read_rating_data(FileData *file);
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/layout.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/layout.c	Mon Jun 18 18:53:46 2018 +0100
@@ -363,6 +363,10 @@
 
 	type = (SortType)GPOINTER_TO_INT(data);
 
+	if (type == SORT_EXIFTIME || type == SORT_EXIFTIMEDIGITIZED || type == SORT_RATING)
+		{
+		vf_read_metadata_in_idle(lw->vf);
+		}
 	layout_sort_set(lw, type, lw->sort_ascend);
 }
 
@@ -547,11 +551,30 @@
 
 void layout_status_update_progress(LayoutWindow *lw, gdouble val, const gchar *text)
 {
+	static gdouble thumb = 0;
+	static gdouble meta = 0;
+
 	if (!layout_valid(&lw)) return;
 	if (!lw->info_progress_bar) return;
 
+	/* Give priority to the loading meta data message
+	 */
+	if(!g_strcmp0(text, "Loading thumbs..."))
+		{
+		thumb = val;
+		if (meta)
+			{
+			return;
+			}
+		}
+	else
+		{
+		meta = val;
+		}
+
 	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(lw->info_progress_bar), val);
-	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(lw->info_progress_bar), (text) ? text : " ");
+	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(lw->info_progress_bar),
+									val ? ((text) ? text : " ") : " ");
 }
 
 void layout_status_update_info(LayoutWindow *lw, const gchar *text)
@@ -1096,6 +1119,11 @@
 	if (options->metadata.confirm_on_dir_change && dir_changed)
 		metadata_write_queue_confirm(FALSE, NULL, NULL);
 
+	if (lw->vf && (options->read_metadata_in_idle || (lw->sort_method == SORT_EXIFTIME || lw->sort_method == SORT_EXIFTIMEDIGITIZED || lw->sort_method == SORT_RATING)))
+		{
+		vf_read_metadata_in_idle(lw->vf);
+		}
+
 	return TRUE;
 }
 
--- a/src/layout_image.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/layout_image.c	Mon Jun 18 18:53:46 2018 +0100
@@ -1125,6 +1125,7 @@
 static void image_alter_rating(FileData *fd_n, const gchar *rating)
 {
 	metadata_write_string(fd_n, RATING_KEY, rating);
+	read_rating_data(fd_n);
 }
 
 void layout_image_rating(LayoutWindow *lw, const gchar *rating)
--- a/src/main.h	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/main.h	Mon Jun 18 18:53:46 2018 +0100
@@ -128,6 +128,8 @@
 #define TIMEZONE_DATABASE "timezone21.bin"
 
 #define HELP_SEARCH_ENGINE "https://duckduckgo.com/?q=site:geeqie.org/help "
+
+#define STAR_RATING_NOT_READ -12345
 /*
  *----------------------------------------------------------------------------
  * main.c
--- a/src/options.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/options.c	Mon Jun 18 18:53:46 2018 +0100
@@ -187,6 +187,7 @@
 	options->log_window.paused = FALSE;
 	options->log_window.timer_data = FALSE;
 
+	options->read_metadata_in_idle = FALSE;
 	return options;
 }
 
--- a/src/options.h	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/options.h	Mon Jun 18 18:53:46 2018 +0100
@@ -288,6 +288,8 @@
 		gboolean line_wrap;
 		gboolean timer_data;
 	} log_window;
+
+	gboolean read_metadata_in_idle;
 };
 
 ConfOptions *options;
--- a/src/preferences.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/preferences.c	Mon Jun 18 18:53:46 2018 +0100
@@ -412,6 +412,7 @@
 	options->with_rename = c_options->with_rename;
 	config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
 
+	options->read_metadata_in_idle = c_options->read_metadata_in_idle;
 #ifdef DEBUG
 	set_debug_level(debug_c);
 #endif
@@ -2220,6 +2221,12 @@
 
 	pref_checkbox_new_int(group, _("Write metadata on directory change"),
 			      options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
+
+	group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
+
+	ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
+					  options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
+	gtk_widget_set_tooltip_text(ct_button,"On folder change, read DateTimeOriginal, DateTimeDigitized and Star Rating in the idle loop.\nIf this is not selected, initial loading of the folder will be faster but sorting on these items will be slower");
 }
 
 /* metadata tab */
--- a/src/rcfile.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/rcfile.c	Mon Jun 18 18:53:46 2018 +0100
@@ -479,6 +479,8 @@
 	WRITE_NL(); WRITE_INT(*options, stereo.fixed_x2);
 	WRITE_NL(); WRITE_INT(*options, stereo.fixed_y2);
 
+	WRITE_NL(); WRITE_BOOL(*options, read_metadata_in_idle);
+
 	/* copy move rename */
 	WRITE_NL(); WRITE_INT(*options, cp_mv_rn.auto_start);
 	WRITE_NL(); WRITE_INT(*options, cp_mv_rn.auto_padding);
@@ -802,6 +804,8 @@
 		if (READ_INT(*options, stereo.fixed_x2)) continue;
 		if (READ_INT(*options, stereo.fixed_y2)) continue;
 
+		if (READ_BOOL(*options, read_metadata_in_idle)) continue;
+
 		/* copy move rename */
 		if (READ_INT(*options, cp_mv_rn.auto_start))  continue;
 		if (READ_INT(*options, cp_mv_rn.auto_padding)) continue;
--- a/src/typedefs.h	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/typedefs.h	Mon Jun 18 18:53:46 2018 +0100
@@ -595,6 +595,7 @@
 	GHashTable *modified_xmp; // hash table which contains unwritten xmp metadata in format: key->list of string values
 	GList *cached_metadata;
 	gint rating;
+	gboolean metadata_in_idle_loaded;
 
 	SelectionType selected;  // Used by view_file_icon.
 };
@@ -887,6 +888,8 @@
 
 	/* file list for edit menu */
 	GList *editmenu_fd_list;
+
+	guint read_metadata_in_idle_id;
 };
 
 struct _ViewFileInfoList
--- a/src/view_file.h	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/view_file.h	Mon Jun 18 18:53:46 2018 +0100
@@ -72,6 +72,6 @@
 void vf_thumb_update(ViewFile *vf);
 void vf_thumb_cleanup(ViewFile *vf);
 void vf_thumb_stop(ViewFile *vf);
-
+void vf_read_metadata_in_idle(ViewFile *vf);
 #endif /* VIEW_FILE_H */
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/view_file/view_file.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/view_file/view_file.c	Mon Jun 18 18:53:46 2018 +0100
@@ -404,6 +404,11 @@
 
 	type = (SortType)GPOINTER_TO_INT(data);
 
+	if (type == SORT_EXIFTIME || type == SORT_EXIFTIMEDIGITIZED || type == SORT_RATING)
+		{
+		vf_read_metadata_in_idle(vf);
+		}
+
 	if (vf->layout)
 		{
 		layout_sort_set(vf->layout, type, vf->sort_ascend);
@@ -697,6 +702,10 @@
 		gtk_widget_destroy(vf->popup);
 		}
 
+	if (vf->read_metadata_in_idle_id)
+		{
+		g_idle_remove_by_data(vf);
+		}
 	file_data_unref(vf->dir_fd);
 	g_free(vf->info);
 	g_free(vf);
@@ -848,6 +857,7 @@
 	vf->type = type;
 	vf->sort_method = SORT_NAME;
 	vf->sort_ascend = TRUE;
+	vf->read_metadata_in_idle_id = 0;
 
 	vf->scrolled = gtk_scrolled_window_new(NULL, NULL);
 	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(vf->scrolled), GTK_SHADOW_IN);
@@ -926,6 +936,20 @@
 	return (gdouble)done / count;
 }
 
+static gdouble vf_read_metadata_in_idle_progress(ViewFile *vf)
+{
+	gint count = 0;
+	gint done = 0;
+
+	switch (vf->type)
+		{
+		case FILEVIEW_LIST: vflist_read_metadata_progress_count(vf->list, &count, &done); break;
+		case FILEVIEW_ICON: vficon_read_metadata_progress_count(vf->list, &count, &done); break;
+		}
+
+	return (gdouble)done / count;
+}
+
 static void vf_set_thumb_fd(ViewFile *vf, FileData *fd)
 {
 	switch (vf->type)
@@ -1197,4 +1221,74 @@
 		}
 }
 
+static gboolean vf_read_metadata_in_idle_cb(gpointer data)
+{
+	FileData *fd;
+	ViewFile *vf = data;
+	GList *list_entry;
+	GList *work;
+
+	vf_thumb_status(vf, vf_read_metadata_in_idle_progress(vf), _("Loading meta..."));
+
+	work = vf->list;
+
+	while (work)
+		{
+		fd = work->data;
+
+		if (fd && !fd->metadata_in_idle_loaded)
+			{
+			if (!fd->exifdate)
+				{
+				read_exif_time_data(fd);
+				}
+			if (!fd->exifdate_digitized)
+				{
+				read_exif_time_digitized_data(fd);
+				}
+			if (fd->rating == STAR_RATING_NOT_READ)
+				{
+				read_rating_data(fd);
+				}
+			fd->metadata_in_idle_loaded = TRUE;
+			return TRUE;
+			}
+		work = work->next;
+		}
+
+	vf_thumb_status(vf, 0.0, NULL);
+	vf->read_metadata_in_idle_id = 0;
+	vf_refresh(vf);
+	return FALSE;
+}
+
+static void vf_read_metadata_in_idle_finished_cb(gpointer data)
+{
+	ViewFile *vf = data;
+
+	vf_thumb_status(vf, 0.0, "Loading meta...");
+	vf->read_metadata_in_idle_id = 0;
+}
+
+void vf_read_metadata_in_idle(ViewFile *vf)
+{
+	GList *work;
+	FileData *fd;
+
+	if (!vf) return;
+
+	if (vf->read_metadata_in_idle_id)
+		{
+		g_idle_remove_by_data(vf);
+		}
+	vf->read_metadata_in_idle_id = 0;
+
+	if (vf->list)
+		{
+		vf->read_metadata_in_idle_id = g_idle_add_full(G_PRIORITY_LOW, vf_read_metadata_in_idle_cb, vf, vf_read_metadata_in_idle_finished_cb);
+		}
+
+	return;
+}
+
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
--- a/src/view_file/view_file_icon.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/view_file/view_file_icon.c	Mon Jun 18 18:53:46 2018 +0100
@@ -1690,6 +1690,19 @@
 		}
 }
 
+void vficon_read_metadata_progress_count(GList *list, gint *count, gint *done)
+{
+	GList *work = list;
+	while (work)
+		{
+		FileData *fd = work->data;
+		work = work->next;
+
+		if (fd->metadata_in_idle_loaded) (*done)++;
+		(*count)++;
+		}
+}
+
 void vficon_set_thumb_fd(ViewFile *vf, FileData *fd)
 {
 	GtkTreeModel *store;
--- a/src/view_file/view_file_icon.h	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/view_file/view_file_icon.h	Mon Jun 18 18:53:46 2018 +0100
@@ -68,6 +68,7 @@
 
 
 void vficon_thumb_progress_count(GList *list, gint *count, gint *done);
+void vficon_read_metadata_progress_count(GList *list, gint *count, gint *done);
 void vficon_set_thumb_fd(ViewFile *vf, FileData *fd);
 FileData *vficon_thumb_next_fd(ViewFile *vf);
 void vficon_thumb_reset_all(ViewFile *vf);
--- a/src/view_file/view_file_list.c	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/view_file/view_file_list.c	Mon Jun 18 18:53:46 2018 +0100
@@ -1079,6 +1079,24 @@
 		}
 }
 
+void vflist_read_metadata_progress_count(GList *list, gint *count, gint *done)
+{
+	GList *work = list;
+	while (work)
+		{
+		FileData *fd = work->data;
+		work = work->next;
+
+		if (fd->metadata_in_idle_loaded) (*done)++;
+
+		if (fd->sidecar_files)
+			{
+			vflist_read_metadata_progress_count(fd->sidecar_files, count, done);
+			}
+		(*count)++;
+		}
+}
+
 void vflist_set_thumb_fd(ViewFile *vf, FileData *fd)
 {
 	GtkTreeStore *store;
--- a/src/view_file/view_file_list.h	Thu Jun 07 14:13:43 2018 +0100
+++ b/src/view_file/view_file_list.h	Mon Jun 18 18:53:46 2018 +0100
@@ -69,6 +69,7 @@
 void vflist_color_set(ViewFile *vf, FileData *fd, gboolean color_set);
 
 void vflist_thumb_progress_count(GList *list, gint *count, gint *done);
+void vflist_read_metadata_progress_count(GList *list, gint *count, gint *done);
 void vflist_set_thumb_fd(ViewFile *vf, FileData *fd);
 FileData *vflist_thumb_next_fd(ViewFile *vf);
 void vflist_thumb_reset_all(ViewFile *vf);
--- a/web/help/GuideMainWindowStatusBar.html	Thu Jun 07 14:13:43 2018 +0100
+++ b/web/help/GuideMainWindowStatusBar.html	Mon Jun 18 18:53:46 2018 +0100
@@ -475,8 +475,14 @@
 </ul></div>
 <div class="division section">
 <a name="ProgressBar"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.6.1. </span>Progress Bar</span></h2></div>
-<p class="para block block-first">The Progress bar updates to display the current state of thumbnail generation. When this section contains no text, thumbnail generation is idle. When “Loading thumbs...” is displayed, thumbnails are currently being generated when Geeqie is idle; the progress bar will update to display the percentage of thumbnails that are completed.</p>
-<p class="para block"></p>
+<p class="para block block-first">
+      The Progress bar updates to display the current state of thumbnail generation, or the reading of metadata in the current folder.
+      <p class="para block block-first"></p>
+      When “Loading thumbs...” is displayed, thumbnails are currently being generated when Geeqie is idle; the progress bar will update to display the percentage of thumbnails that are completed.
+      <p class="para block"></p>
+      When “Loading meta...” is displayed, certain metadata is being loaded when Geeqie is idle; the progress bar will update to display the percentage of files that have been read. Refer to
+      <a class="link" href="GuideOptionsMetadata.html#PreLoadMetadata" title="Pre-load metadata">Preferences metadata.</a>
+    </p>
 </div>
 <div class="division section">
 <a name="Sortmethod"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.6.2. </span>Sort method</span></h2></div>
--- a/web/help/GuideOptionsMetadata.html	Thu Jun 07 14:13:43 2018 +0100
+++ b/web/help/GuideOptionsMetadata.html	Mon Jun 18 18:53:46 2018 +0100
@@ -484,6 +484,9 @@
 <li>
 <span class="label">11.6.5. </span><a class="xref" href="GuideOptionsMetadata.html#AutoSaveOptions" title="Auto-save options">Auto-save options</a>
 </li>
+<li>
+<span class="label">11.6.6. </span><a class="xref" href="GuideOptionsMetadata.html#PreLoadMetadata" title="Pre-load metadata">Pre-load metadata</a>
+</li>
 </ul></div>
 <div class="division section">
 <a name="MetadataWritingProcess"></a><div class="header"><h2 class="section title"><span class="title"><a name="titleMetadataWritingProcess"></a><span class="label">11.6.1. </span>Metadata writing process</span></h2></div>
@@ -628,6 +631,29 @@
 </ul></div>
 <p class="para block"></p>
 </div>
+<div class="division section">
+<a name="PreLoadMetadata"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.6.6. </span>Pre-load metadata</span></h2></div>
+<div class="block list itemizedlist"><ul class="itemizedlist"><li class="li-first">
+        <span class="para">
+          <span class="guilabel">Read metadata in background</span>
+          <p class="para block"></p>
+          Using the folder sorting options:
+          <p class="para block"></p>
+          <span class="guilabel">Exif date original</span>
+          <p class="para block"></p>
+          <span class="guilabel">Exif date digitized</span>
+          <p class="para block"></p>
+          <span class="guilabel">Rating</span>
+          <p class="para block"></p>
+          requires metadata to be read from all files in a folder before the sort action can be made. If a folder contains a large number of file, this can take a noticeable period of time.
+          <p class="para block"></p>
+          If this option is checked, Geeqie will automatically read the required metatada in the background as soon as a folder is opened. This will reduce the amount of time you have to wait until the sort is completed.
+          <p class="para block"></p>
+          If you do not use these sort otions, leave this option unchecked.
+        </span>
+      </li></ul></div>
+<p class="para block"></p>
+</div>
 </div></div>
 <div class="navbar navbar-bottom"><table class="navbar"><tr>
 <td class="navbar-prev"><a class="navbar-prev" href="GuideOptionsFiltering.html" title="Files Options">Files Options</a></td>
--- a/web/help/GuideReferenceXmpExif.html	Thu Jun 07 14:13:43 2018 +0100
+++ b/web/help/GuideReferenceXmpExif.html	Mon Jun 18 18:53:46 2018 +0100
@@ -733,10 +733,10 @@
             </td>
 </tr>
 <tr class="tr-shade">
-<td class="td-colsep">
+<td class="td-colsep td-rowsep">
               <span class="para">formatted.timezone</span>
             </td>
-<td class="td-colsep">
+<td class="td-colsep td-rowsep">
               <span class="para">
                 Exif.GPSInfo.GPSLatitude
                 <p class="para block block-first"></p>
@@ -747,13 +747,24 @@
                 Exif.GPSInfo.GPSLongitudeRef
               </span>
             </td>
-<td>
+<td class="td-rowsep">
               <span class="para">
                 Timezone indicated by lat/long
                 <a name="-noteref-ref1"></a><sup><a class="footnote" href="#ref1">2</a></sup>
               </span>
             </td>
 </tr>
+<tr>
+<td class="td-colsep">
+              <span class="para">formatted.star_rating</span>
+            </td>
+<td class="td-colsep">
+              <span class="para">Xmp.xmp.Rating</span>
+            </td>
+<td>
+              <span class="para">Rating shown as a set of 🟊  characters</span>
+            </td>
+</tr>
 </tbody>
 </table>
 </div>
--- a/web/help/GuideSidebarsInfo.html	Thu Jun 07 14:13:43 2018 +0100
+++ b/web/help/GuideSidebarsInfo.html	Mon Jun 18 18:53:46 2018 +0100
@@ -730,8 +730,12 @@
 <td class="td-rowsep">file date and time in human readable form</td>
 </tr>
 <tr class="tr-shade">
-<td class="td-colsep">file.mode</td>
-<td>file mode flags</td>
+<td class="td-colsep td-rowsep">file.mode</td>
+<td class="td-rowsep">file mode flags</td>
+</tr>
+<tr>
+<td class="td-colsep">file.ctime</td>
+<td>refer to operating system documentation for the meaning of ctime</td>
 </tr>
 </tbody></table>
 </div>