changeset 2777:813be27b1cd5

Addl fix #323: Rating system https://github.com/BestImageViewer/geeqie/issues/323 Preserve show star rating setting User option to select the character for Star and Rejected - Preferences/General
author Colin Clark <colin.clark@cclark.uk>
date Fri, 22 Jun 2018 19:20:08 +0100
parents 5df076fe2eaf
children 7ff610000acc
files doc/docbook/GuideOptionsGeneral.xml src/main.h src/misc.c src/options.c src/options.h src/preferences.c src/rcfile.c web/help/GuideMainWindowStatusBar.html web/help/GuideOptionsGeneral.html
diffstat 9 files changed, 207 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docbook/GuideOptionsGeneral.xml	Fri Jun 22 10:38:37 2018 +0100
+++ b/doc/docbook/GuideOptionsGeneral.xml	Fri Jun 22 19:20:08 2018 +0100
@@ -140,6 +140,10 @@
       </varlistentry>
     </variablelist>
   </section>
+  <section id="StarRatingCharacters">
+    <title>Star Rating</title>
+    <para>The characters used to display the Star Rating are defined here. They are defined as a hexadecimal Unicode character. The complete list of Unicode characters can be found in many places on the Internet.</para>
+  </section>
   <section id="Slideshow">
     <title>Slide show</title>
     <variablelist>
--- a/src/main.h	Fri Jun 22 10:38:37 2018 +0100
+++ b/src/main.h	Fri Jun 22 19:20:08 2018 +0100
@@ -130,6 +130,9 @@
 #define HELP_SEARCH_ENGINE "https://duckduckgo.com/?q=site:geeqie.org/help "
 
 #define STAR_RATING_NOT_READ -12345
+#define STAR_RATING_REJECTED 0x274C //Unicode Character 'Cross Mark'
+#define STAR_RATING_STAR 0x2738 //Unicode Character 'Heavy Eight Pointed Rectilinear Black Star'
+
 /*
  *----------------------------------------------------------------------------
  * main.c
--- a/src/misc.c	Fri Jun 22 10:38:37 2018 +0100
+++ b/src/misc.c	Fri Jun 22 19:20:08 2018 +0100
@@ -298,12 +298,10 @@
 {
 	gchar *ret;
 	GString *str = g_string_new(NULL);
-	gunichar rejected = 0x274C; //Unicode Character 'CROSS MARK'
-	gunichar star = 0x2738; //Unicode Character 'Heavy Eight Pointed Rectilinear Black Star'
 
 	if (rating == -1)
 		{
-		str = g_string_append_unichar(str, rejected);
+		str = g_string_append_unichar(str, options->star_rating.rejected);
 		ret = g_strdup(str->str);
 		g_string_free(str, TRUE);
 		}
@@ -311,7 +309,7 @@
 		{
 		while (rating > 0)
 			{
-			str = g_string_append_unichar(str, star);
+			str = g_string_append_unichar(str, options->star_rating.star);
 			rating = rating - 1;
 			}
 		ret = g_strdup(str->str);
--- a/src/options.c	Fri Jun 22 10:38:37 2018 +0100
+++ b/src/options.c	Fri Jun 22 19:20:08 2018 +0100
@@ -189,6 +189,8 @@
 	options->log_window.timer_data = FALSE;
 
 	options->read_metadata_in_idle = FALSE;
+	options->star_rating.star = STAR_RATING_STAR;
+	options->star_rating.rejected = STAR_RATING_REJECTED;
 	return options;
 }
 
--- a/src/options.h	Fri Jun 22 10:38:37 2018 +0100
+++ b/src/options.h	Fri Jun 22 19:20:08 2018 +0100
@@ -290,6 +290,12 @@
 		gboolean timer_data;
 	} log_window;
 
+	/* star rating */
+	struct {
+		gunichar star;
+		gunichar rejected;
+	} star_rating;
+
 	gboolean read_metadata_in_idle;
 };
 
--- a/src/preferences.c	Fri Jun 22 10:38:37 2018 +0100
+++ b/src/preferences.c	Fri Jun 22 19:20:08 2018 +0100
@@ -413,6 +413,9 @@
 	config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
 
 	options->read_metadata_in_idle = c_options->read_metadata_in_idle;
+
+	options->star_rating.star = c_options->star_rating.star;
+	options->star_rating.rejected = c_options->star_rating.rejected;
 #ifdef DEBUG
 	set_debug_level(debug_c);
 #endif
@@ -1600,6 +1603,94 @@
 		}
 }
 
+static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
+									GdkEvent *event, gpointer userdata)
+{
+	gchar *rating_symbol;
+
+	if (pos == GTK_ENTRY_ICON_PRIMARY)
+		{
+		rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
+		gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
+		g_free(rating_symbol);
+		}
+	else
+		{
+		gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
+		gtk_widget_grab_focus(GTK_WIDGET(userdata));
+		gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
+		}
+}
+
+static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
+									GdkEvent *event, gpointer userdata)
+{
+	gchar *rating_symbol;
+
+	if (pos == GTK_ENTRY_ICON_PRIMARY)
+		{
+		rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
+		gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
+		g_free(rating_symbol);
+		}
+	else
+		{
+		gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
+		gtk_widget_grab_focus(GTK_WIDGET(userdata));
+		gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
+		}
+}
+
+static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
+{
+	GtkContainer *hbox = data;
+	GString *str = g_string_new(NULL);
+	GtkEntry *hex_code_entry;
+	gchar *hex_code_full;
+	gchar **hex_code;
+	GList *list;
+	guint64 hex_value = 0;
+
+	list = gtk_container_get_children(hbox);
+
+	hex_code_entry = g_list_nth_data(list, 2);
+	hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
+
+	hex_code = g_strsplit(hex_code_full, "+", 2);
+	if (hex_code[0] && hex_code[1])
+		{
+		g_ascii_string_to_unsigned(hex_code[1], 16, 0, 0x10FFFF, &hex_value, NULL);
+		}
+	if (!hex_value)
+		{
+		hex_value = 0x003F; // Unicode 'Question Mark'
+		}
+	str = g_string_append_unichar(str, hex_value);
+	gtk_label_set_text(g_list_nth_data(list, 1), str->str);
+
+	g_strfreev(hex_code);
+	g_string_free(str, TRUE);
+	g_free(hex_code_full);
+
+	return hex_value;
+}
+
+static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
+{
+	guint64 star_symbol;
+
+	star_symbol = star_rating_symbol_test(widget, data);
+	c_options->star_rating.star = star_symbol;
+}
+
+static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
+{
+	guint64 rejected_symbol;
+
+	rejected_symbol = star_rating_symbol_test(widget, data);
+	c_options->star_rating.rejected = rejected_symbol;
+}
+
 /* general options tab */
 static void config_tab_general(GtkWidget *notebook)
 {
@@ -1614,6 +1705,9 @@
 	GtkWidget *spin;
 	gint hours, minutes, remainder;
 	gdouble seconds;
+	GtkWidget *star_rating_entry;
+	GString *str;
+	gchar *rating_symbol;
 
 	vbox = scrolled_notebook_page(notebook, _("General"));
 
@@ -1660,6 +1754,75 @@
 // 			      options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
 #endif
 
+	group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
+
+	c_options->star_rating.star = options->star_rating.star;
+	c_options->star_rating.rejected = options->star_rating.rejected;
+
+	str = g_string_new(NULL);
+	hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+	pref_label_new(hbox, "Star character: ");
+	str = g_string_append_unichar(str, options->star_rating.star);
+	pref_label_new(hbox, g_strdup(str->str));
+	rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
+	star_rating_entry = gtk_entry_new();
+	gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
+	gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
+	gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
+	gtk_widget_show(star_rating_entry);
+	button = pref_button_new(NULL, NULL, _("Set"), FALSE,
+					G_CALLBACK(star_rating_star_test_cb), hbox);
+	gtk_widget_set_tooltip_text(button, _("Display selected character"));
+	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+	gtk_widget_show(button);
+	gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
+	gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
+	gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_SECONDARY, _("Clear"));
+	gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
+	gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_PRIMARY, _("Default"));
+	g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
+						G_CALLBACK(star_rating_star_icon_cb),
+						star_rating_entry);
+
+	g_string_free(str, TRUE);
+	g_free(rating_symbol);
+
+	str = g_string_new(NULL);
+	hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+	pref_label_new(hbox, "Rejected character: ");
+	str = g_string_append_unichar(str, options->star_rating.rejected);
+	pref_label_new(hbox, g_strdup(str->str));
+	rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
+	star_rating_entry = gtk_entry_new();
+	gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
+	gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
+	gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
+	gtk_widget_show(star_rating_entry);
+	button = pref_button_new(NULL, NULL, _("Set"), FALSE,
+					G_CALLBACK(star_rating_rejected_test_cb), hbox);
+	gtk_widget_set_tooltip_text(button, _("Display selected character"));
+	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+	gtk_widget_show(button);
+	gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
+	gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
+	gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_SECONDARY, _("Clear"));
+	gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
+	gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
+						GTK_ENTRY_ICON_PRIMARY, _("Default"));
+	g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
+						G_CALLBACK(star_rating_rejected_icon_cb),
+						star_rating_entry);
+
+	g_string_free(str, TRUE);
+	g_free(rating_symbol);
+
 	group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
 
 	c_options->slideshow.delay = options->slideshow.delay;
--- a/src/rcfile.c	Fri Jun 22 10:38:37 2018 +0100
+++ b/src/rcfile.c	Fri Jun 22 19:20:08 2018 +0100
@@ -306,6 +306,7 @@
 {
 	/* General Options */
 	WRITE_NL(); WRITE_BOOL(*options, show_icon_names);
+	WRITE_NL(); WRITE_BOOL(*options, show_star_rating);
 	WRITE_SEPARATOR();
 
 	WRITE_NL(); WRITE_BOOL(*options, tree_descend_subdirs);
@@ -481,6 +482,9 @@
 
 	WRITE_NL(); WRITE_BOOL(*options, read_metadata_in_idle);
 
+	WRITE_NL(); WRITE_UINT(*options, star_rating.star);
+	WRITE_NL(); WRITE_UINT(*options, star_rating.rejected);
+
 	/* copy move rename */
 	WRITE_NL(); WRITE_INT(*options, cp_mv_rn.auto_start);
 	WRITE_NL(); WRITE_INT(*options, cp_mv_rn.auto_padding);
@@ -638,6 +642,7 @@
 
 		/* General options */
 		if (READ_BOOL(*options, show_icon_names)) continue;
+		if (READ_BOOL(*options, show_star_rating)) continue;
 
 		if (READ_BOOL(*options, tree_descend_subdirs)) continue;
 		if (READ_BOOL(*options, view_dir_list_single_click_enter)) continue;
@@ -806,6 +811,9 @@
 
 		if (READ_BOOL(*options, read_metadata_in_idle)) continue;
 
+		if (READ_UINT(*options, star_rating.star)) continue;
+		if (READ_UINT(*options, star_rating.rejected)) 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/web/help/GuideMainWindowStatusBar.html	Fri Jun 22 10:38:37 2018 +0100
+++ b/web/help/GuideMainWindowStatusBar.html	Fri Jun 22 19:20:08 2018 +0100
@@ -453,8 +453,8 @@
 <li class="linktrail linktrail-first"><a class="linktrail" href="GuideIndex.html" title="The Geeqie User Manual">The Geeqie User Manual</a></li>
 <li class="linktrail linktrail-last"><a class="linktrail" href="GuideMainWindow.html" title="Main Window">Main Window</a></li>
 </ul>
-<p class="para block block-first">The status bar contains information and details about the contents of the main window. Information displayed includes the progress of generating thumbnails, the number of files in the file list with byte size, the current file selection count including byte size, details about the currently displayed image, and the zoom setting. The current sort preference is also displayed, and can be adjusted from the status bar.</p>
-<p class="para block">The status bar is comprised of five sections, from left to right these are a progress bar, sort method, file list counts, image details, and zoom setting. Each section is described below.</p>
+<p class="para block block-first">The status bar contains information and details about the contents of the main window. Information displayed includes the progress of generating thumbnails, the number of files in the file list with byte size, the current file selection count including byte size, details about the currently displayed image, and the zoom and image scroll settings. The current sort preference is also displayed, and can be adjusted from the status bar.</p>
+<p class="para block">The status bar is comprised of five sections, from left to right these are a progress bar, sort method, file list counts, image details, and zoom and scroll setting. Each section is described below.</p>
 <p class="para block"></p>
 <div class="autotoc"><ul>
 <li>
@@ -566,7 +566,7 @@
 <p class="para block"></p>
 <div class="autotoc"><ul>
 <li>
-<span class="label">2.6.5.1. </span><a class="xref" href="GuideMainWindowStatusBar.html#Zoom" title="Zoom">Zoom</a>
+<span class="label">2.6.5.1. </span><a class="xref" href="GuideMainWindowStatusBar.html#ZoomAndScroll" title="Zoom and Scroll">Zoom and Scroll</a>
 </li>
 <li>
 <span class="label">2.6.5.2. </span><a class="xref" href="GuideMainWindowStatusBar.html#ExifRotate" title="Exif rotate">Exif rotate</a>
@@ -582,7 +582,7 @@
 </li>
 </ul></div>
 <div class="division section">
-<a name="Zoom"></a><div class="header"><h3 class="section title"><span class="title"><span class="label">2.6.5.1. </span>Zoom</span></h3></div>
+<a name="ZoomAndScroll"></a><div class="header"><h3 class="section title"><span class="title"><span class="label">2.6.5.1. </span>Zoom and Scroll</span></h3></div>
 <p class="para block block-first">The button label displays the current zoom ratio. A ratio of 1:1 is the image's original size. When the left number is larger the image is displayed larger than original size, when the right number is larger the image is displayed smaller.</p>
 <p class="para block">A tilde (~) appears within the ratio display when the zoom is set to fit the image within the display area. In this zoom mode the ratio is automatically adjusted, and the displayed ratio may not be the actual ratio because the status bar display rounds the actual value to the nearest tenth (0.1).</p>
 <p class="para block"></p>
--- a/web/help/GuideOptionsGeneral.html	Fri Jun 22 10:38:37 2018 +0100
+++ b/web/help/GuideOptionsGeneral.html	Fri Jun 22 19:20:08 2018 +0100
@@ -462,16 +462,19 @@
 <span class="label">11.1.1. </span><a class="xref" href="GuideOptionsGeneral.html#PreferencesThumbnails" title="Thumbnails">Thumbnails</a>
 </li>
 <li>
-<span class="label">11.1.2. </span><a class="xref" href="GuideOptionsGeneral.html#Slideshow" title="Slide show">Slide show</a>
+<span class="label">11.1.2. </span><a class="xref" href="GuideOptionsGeneral.html#StarRatingCharacters" title="Star Rating">Star Rating</a>
+</li>
+<li>
+<span class="label">11.1.3. </span><a class="xref" href="GuideOptionsGeneral.html#Slideshow" title="Slide show">Slide show</a>
 </li>
 <li>
-<span class="label">11.1.3. </span><a class="xref" href="GuideOptionsGeneral.html#ImageLoadingandCaching" title="Image loading and caching">Image loading and caching</a>
+<span class="label">11.1.4. </span><a class="xref" href="GuideOptionsGeneral.html#ImageLoadingandCaching" title="Image loading and caching">Image loading and caching</a>
 </li>
 <li>
-<span class="label">11.1.4. </span><a class="xref" href="GuideOptionsGeneral.html#InfoSidebar" title="Info Sidebar component heights">Info Sidebar component heights</a>
+<span class="label">11.1.5. </span><a class="xref" href="GuideOptionsGeneral.html#InfoSidebar" title="Info Sidebar component heights">Info Sidebar component heights</a>
 </li>
 <li>
-<span class="label">11.1.5. </span><a class="xref" href="GuideOptionsGeneral.html#OnLineHelpSearch" title="On-line help search">On-line help search</a>
+<span class="label">11.1.6. </span><a class="xref" href="GuideOptionsGeneral.html#OnLineHelpSearch" title="On-line help search">On-line help search</a>
 </li>
 </ul></div>
 <div class="division section">
@@ -591,7 +594,11 @@
 </dl></div>
 </div>
 <div class="division section">
-<a name="Slideshow"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.2. </span>Slide show</span></h2></div>
+<a name="StarRatingCharacters"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.2. </span>Star Rating</span></h2></div>
+<p class="para block block-first">The characters used to display the Star Rating are defined here. They are defined as a hexadecimal Unicode character. The complete list of Unicode characters can be found in many places on the Internet.</p>
+</div>
+<div class="division section">
+<a name="Slideshow"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.3. </span>Slide show</span></h2></div>
 <div class="block list variablelist"><dl class="variablelist">
 <dt class="term dt-first">
           <span class="guilabel">Delay between image change</span>
@@ -617,7 +624,7 @@
 </dl></div>
 </div>
 <div class="division section">
-<a name="ImageLoadingandCaching"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.3. </span>Image loading and caching</span></h2></div>
+<a name="ImageLoadingandCaching"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.4. </span>Image loading and caching</span></h2></div>
 <div class="block list variablelist"><dl class="variablelist">
 <dt class="term dt-first">
           <span class="guilabel">Decoded image cache size</span>
@@ -646,7 +653,7 @@
 </dl></div>
 </div>
 <div class="division section">
-<a name="InfoSidebar"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.4. </span>Info Sidebar component heights</span></h2></div>
+<a name="InfoSidebar"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.5. </span>Info Sidebar component heights</span></h2></div>
 <p class="para block block-first">
       The heights of the following components can be set individually:
       <div class="block list itemizedlist"><ul class="itemizedlist">
@@ -661,7 +668,7 @@
 <div class="block list variablelist"><dl class="variablelist"></dl></div>
 </div>
 <div class="division section">
-<a name="OnLineHelpSearch"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.5. </span>On-line help search</span></h2></div>
+<a name="OnLineHelpSearch"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">11.1.6. </span>On-line help search</span></h2></div>
 <p class="para block block-first">
       An internet search engine may be used to search the help files on Geeqie's website. The string used to conduct the search is defined here. In most cases it will be in one of two formats:
       <p class="para block block-first"></p>