Addl fix #323: Rating system
authorColin Clark <colin.clark@cclark.uk>
Fri, 22 Jun 2018 18:20:08 +0000 (19:20 +0100)
committerColin Clark <colin.clark@cclark.uk>
Fri, 22 Jun 2018 18:20:08 +0000 (19:20 +0100)
https://github.com/BestImageViewer/geeqie/issues/323

Preserve show star rating setting
User option to select the character for Star and Rejected -
Preferences/General

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

index 328b819..5f6288f 100644 (file)
       </varlistentry>\r
     </variablelist>\r
   </section>\r
+  <section id="StarRatingCharacters">\r
+    <title>Star Rating</title>\r
+    <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>\r
+  </section>\r
   <section id="Slideshow">\r
     <title>Slide show</title>\r
     <variablelist>\r
index 6bf9f99..1048fd2 100644 (file)
 #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
index 2b2b68b..70b01ef 100644 (file)
@@ -298,12 +298,10 @@ gchar *convert_rating_to_stars(gint rating)
 {
        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 @@ gchar *convert_rating_to_stars(gint rating)
                {
                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);
index 129ce9c..b3e0ced 100644 (file)
@@ -189,6 +189,8 @@ ConfOptions *init_options(ConfOptions *options)
        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;
 }
 
index 51f546f..a1300e9 100644 (file)
@@ -290,6 +290,12 @@ struct _ConfOptions
                gboolean timer_data;
        } log_window;
 
+       /* star rating */
+       struct {
+               gunichar star;
+               gunichar rejected;
+       } star_rating;
+
        gboolean read_metadata_in_idle;
 };
 
index 4eb6ad6..3ea10cf 100644 (file)
@@ -413,6 +413,9 @@ static void config_window_apply(void)
        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 help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPositi
                }
 }
 
+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 @@ static void config_tab_general(GtkWidget *notebook)
        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 @@ static void config_tab_general(GtkWidget *notebook)
 //                           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;
index f293117..804e92f 100644 (file)
@@ -306,6 +306,7 @@ static void write_global_attributes(GString *outstr, gint indent)
 {
        /* 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 @@ static void write_global_attributes(GString *outstr, gint indent)
 
        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 @@ static gboolean load_global_params(const gchar **attribute_names, const gchar **
 
                /* 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 @@ static gboolean load_global_params(const gchar **attribute_names, const gchar **
 
                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;
index 5670855..8d0e427 100644 (file)
@@ -453,8 +453,8 @@ dd.answer div.label { float: left; }
 <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 @@ dd.answer div.label { float: left; }
 <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 @@ dd.answer div.label { float: left; }
 </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>
index 6d5e053..669bd7d 100644 (file)
@@ -462,16 +462,19 @@ dd.answer div.label { float: left; }
 <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#ImageLoadingandCaching" title="Image loading and caching">Image loading and caching</a>
+<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.4. </span><a class="xref" href="GuideOptionsGeneral.html#InfoSidebar" title="Info Sidebar component heights">Info Sidebar component heights</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.5. </span><a class="xref" href="GuideOptionsGeneral.html#OnLineHelpSearch" title="On-line help search">On-line help search</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.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 @@ dd.answer div.label { float: left; }
 </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 @@ dd.answer div.label { float: left; }
 </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 @@ dd.answer div.label { float: left; }
 </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 @@ dd.answer div.label { float: left; }
 <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>