Sort/search on file class
authorColin Clark <colin.clark@cclark.uk>
Wed, 3 Jan 2018 17:49:15 +0000 (17:49 +0000)
committerColin Clark <colin.clark@cclark.uk>
Wed, 3 Jan 2018 17:49:15 +0000 (17:49 +0000)
Implement sort and search on file class (raw image, video etc.)

Note that the sort order is set by an enumerated type in typedefs.h, but
cannot be easily changed because the class is saved in the filter
section of geeqierc.xml as an integer.

doc/docbook/GuideImageSearchSearch.xml
doc/docbook/GuideMainWindowStatusBar.xml
src/collect.c
src/filedata.c
src/menu.c
src/search.c
src/typedefs.h
web/help/GuideImageSearchSearch.html
web/help/GuideMainWindowStatusBar.html

index f1719ea..55a7082 100644 (file)
           </note>\r
         </listitem>\r
       </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Class</guilabel>\r
+        </term>\r
+        <listitem>\r
+          The search will match if the file's class is, or is not, one of the following types.\r
+          <itemizedlist>\r
+            <listitem>Unknown</listitem>\r
+            <listitem>Image</listitem>\r
+            <listitem>Raw Image</listitem>\r
+            <listitem>Video</listitem>\r
+            <listitem>Metadata</listitem>\r
+          </itemizedlist>\r
+        </listitem>\r
+      </varlistentry>\r
     </variablelist>\r
     <para />\r
     <para />\r
index d749b37..6c32703 100644 (file)
           <guilabel>Size</guilabel>\r
         </term>\r
         <listitem>\r
-          <para>Image are sorted by file size on disk.</para>\r
+          <para>Images are sorted by file size on disk.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Rating</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>Image are sorted by Xmp.xmp.Rating.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Class</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>Image are sorted by class. The class types, and sort order, is:</para>\r
+          <itemizedlist>\r
+            <listitem>Unknown</listitem>\r
+            <listitem>Image</listitem>\r
+            <listitem>Raw Image</listitem>\r
+            <listitem>Video</listitem>\r
+            <listitem>Metadata</listitem>\r
+          </itemizedlist>\r
         </listitem>\r
       </varlistentry>\r
       <varlistentry>\r
@@ -70,7 +93,7 @@
         </listitem>\r
       </varlistentry>\r
     </variablelist>\r
-    <para />\r
+    <note>When images have equal rank, for example in rating or class sorts, within each section images will be sorted by filename.</note>\r
   </section>\r
   <section id="Filelist">\r
     <title>File list</title>\r
index 33d5285..cc2dd6e 100644 (file)
@@ -172,6 +172,10 @@ static gint collection_list_sort_cb(gconstpointer a, gconstpointer b)
                case SORT_PATH:
                        return utf8_compare(cia->fd->path, cib->fd->path, options->file_sort.case_sensitive);
                        break;
+               case SORT_CLASS:
+                       if (cia->fd->format_class < cib->fd->format_class) return -1;
+                       if (cia->fd->format_class > cib->fd->format_class) return 1;
+                       break;
 #ifdef HAVE_STRVERSCMP
                case SORT_NUMBER:
                        return strverscmp(cia->fd->name, cib->fd->name);
index 3862277..301f448 100644 (file)
@@ -1051,6 +1051,11 @@ gint filelist_sort_compare_filedata(FileData *fa, FileData *fb)
                        if (fa->rating > fb->rating) return 1;
                        /* fall back to name */
                        break;
+               case SORT_CLASS:
+                       if (fa->format_class < fb->format_class) return -1;
+                       if (fa->format_class > fb->format_class) return 1;
+                       /* fall back to name */
+                       break;
 #ifdef HAVE_STRVERSCMP
                case SORT_NUMBER:
                        ret = strverscmp(fa->name, fb->name);
index d5a0c7a..8fc6995 100644 (file)
@@ -163,6 +163,9 @@ gchar *sort_type_get_text(SortType method)
                case SORT_RATING:
                        return _("Sort by rating");
                        break;
+               case SORT_CLASS:
+                       return _("Sort by class");
+                       break;
                case SORT_NAME:
                default:
                        return _("Sort by name");
@@ -211,6 +214,7 @@ GtkWidget *submenu_add_sort(GtkWidget *menu, GCallback func, gpointer data,
        submenu_add_sort_item(submenu, func, SORT_EXIFTIME, 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);
        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 257b0ac..f046302 100644 (file)
@@ -144,6 +144,10 @@ struct _SearchData
        GtkWidget *spin_rating;
        GtkWidget *spin_rating_end;
 
+       GtkWidget *check_class;
+       GtkWidget *menu_class;
+       GtkWidget *class_type;
+
        FileData *search_dir_fd;
        gboolean   search_path_recurse;
        gchar *search_name;
@@ -180,6 +184,7 @@ struct _SearchData
        MatchType match_comment;
        MatchType match_rating;
        MatchType match_gps;
+       MatchType match_class;
 
        gboolean match_name_enable;
        gboolean match_size_enable;
@@ -189,6 +194,7 @@ struct _SearchData
        gboolean match_keywords_enable;
        gboolean match_comment_enable;
        gboolean match_rating_enable;
+       gboolean match_class_enable;
 
        GList *search_folder_list;
        GList *search_done_list;
@@ -290,6 +296,11 @@ static const MatchList text_search_menu_gps[] = {
        { N_("greater than"),   SEARCH_MATCH_OVER }
 };
 
+static const MatchList text_search_menu_class[] = {
+       { N_("is"),     SEARCH_MATCH_EQUAL },
+       { N_("is not"), SEARCH_MATCH_NONE }
+};
+
 static GList *search_window_list = NULL;
 
 
@@ -2032,6 +2043,49 @@ static gboolean search_file_next(SearchData *sd)
                        }
                }
 
+       if (match && sd->match_class_enable)
+               {
+               tested = TRUE;
+               match = FALSE;
+               gint class;
+               FileFormatClass search_class;
+
+               if (g_strcmp0(gtk_combo_box_text_get_active_text(
+                                               GTK_COMBO_BOX_TEXT(sd->class_type)), _("Image")) == 0)
+                       {
+                       search_class = FORMAT_CLASS_IMAGE;
+                       }
+               else if (g_strcmp0(gtk_combo_box_text_get_active_text(
+                                               GTK_COMBO_BOX_TEXT(sd->class_type)), _("Raw Image")) == 0)
+                       {
+                       search_class = FORMAT_CLASS_RAWIMAGE;
+                       }
+               else if (g_strcmp0(gtk_combo_box_text_get_active_text(
+                                               GTK_COMBO_BOX_TEXT(sd->class_type)), _("Video")) == 0)
+                       {
+                       search_class = FORMAT_CLASS_VIDEO;
+                       }
+               else if (g_strcmp0(gtk_combo_box_text_get_active_text(
+                                               GTK_COMBO_BOX_TEXT(sd->class_type)), _("Metadata")) == 0)
+                       {
+                       search_class = FORMAT_CLASS_META;
+                       }
+               else
+                       {
+                       search_class = FORMAT_CLASS_UNKNOWN;
+                       }
+
+               class = fd->format_class;
+               if (sd->match_class == SEARCH_MATCH_EQUAL)
+                       {
+                       match = (class == search_class);
+                       }
+               else if (sd->match_class == SEARCH_MATCH_NONE)
+                       {
+                       match = (class != search_class);
+                       }
+               }
+
        if (match && sd->match_gps_enable)
                {
                /* Calculate the distance the image is from the specified origin.
@@ -2618,6 +2672,13 @@ static void menu_choice_rating_cb(GtkWidget *combo, gpointer data)
                                (sd->match_rating == SEARCH_MATCH_BETWEEN));
 }
 
+static void menu_choice_class_cb(GtkWidget *combo, gpointer data)
+{
+       SearchData *sd = data;
+
+       if (!menu_choice_get_match_type(combo, &sd->match_class)) return;
+}
+
 static void menu_choice_date_cb(GtkWidget *combo, gpointer data)
 {
        SearchData *sd = data;
@@ -2847,6 +2908,7 @@ void search_new(FileData *dir_fd, FileData *example_file)
        sd->match_keywords = SEARCH_MATCH_ALL;
        sd->match_comment = SEARCH_MATCH_CONTAINS;
        sd->match_rating = SEARCH_MATCH_EQUAL;
+       sd->match_class = SEARCH_MATCH_EQUAL;
 
        sd->match_name_enable = TRUE;
 
@@ -3062,6 +3124,22 @@ void search_new(FileData *dir_fd, FileData *example_file)
 
        gtk_widget_show(sd->entry_gps_coord);
 
+       /* Search for image class */
+       hbox = menu_choice(sd->box_search, &sd->check_class, &sd->menu_class,
+                          _("Image class"), &sd->match_class_enable,
+                          text_search_menu_class, sizeof(text_search_menu_class) / sizeof(MatchList),
+                          G_CALLBACK(menu_choice_class_cb), sd);
+
+       sd->class_type = gtk_combo_box_text_new();
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Image"));
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Raw Image"));
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Video"));
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Metadata"));
+       gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Unknown"));
+       gtk_box_pack_start(GTK_BOX(hbox), sd->class_type, FALSE, FALSE, 0);
+       gtk_combo_box_set_active(GTK_COMBO_BOX(sd->class_type), 0);
+       gtk_widget_show(sd->class_type);
+
        /* Done the types of searches */
 
        scrolled = gtk_scrolled_window_new(NULL, NULL);
index 8e55ea4..6f25027 100644 (file)
@@ -74,7 +74,8 @@ typedef enum {
        SORT_PATH,
        SORT_NUMBER,
        SORT_EXIFTIME,
-       SORT_RATING
+       SORT_RATING,
+       SORT_CLASS
 } SortType;
 
 typedef enum {
index 1ede40f..3018009 100644 (file)
@@ -606,6 +606,19 @@ dd.answer div.label { float: left; }
             for details on how to create this file.
           </div></div>
         </dd>
+<dt class="term">
+          <span class="guilabel">Class</span>
+        </dt>
+<dd>
+          The search will match if the file's class is, or is not, one of the following types.
+          <div class="block list itemizedlist"><ul class="itemizedlist">
+<li class="li-first">Unknown</li>
+<li>Image</li>
+<li>Raw Image</li>
+<li>Video</li>
+<li>Metadata</li>
+</ul></div>
+        </dd>
 </dl></div>
 <p class="para block"></p>
 <p class="para block"></p>
index bbc8246..5a1e458 100644 (file)
@@ -516,7 +516,26 @@ dd.answer div.label { float: left; }
           <span class="guilabel">Size</span>
         </dt>
 <dd>
-          <p class="para block block-first">Image are sorted by file size on disk.</p>
+          <p class="para block block-first">Images are sorted by file size on disk.</p>
+        </dd>
+<dt class="term">
+          <span class="guilabel">Rating</span>
+        </dt>
+<dd>
+          <p class="para block block-first">Image are sorted by Xmp.xmp.Rating.</p>
+        </dd>
+<dt class="term">
+          <span class="guilabel">Class</span>
+        </dt>
+<dd>
+          <p class="para block block-first">Image are sorted by class. The class types, and sort order, is:</p>
+          <div class="block list itemizedlist"><ul class="itemizedlist">
+<li class="li-first">Unknown</li>
+<li>Image</li>
+<li>Raw Image</li>
+<li>Video</li>
+<li>Metadata</li>
+</ul></div>
         </dd>
 <dt class="term">
           <span class="guilabel">Ascending</span>
@@ -525,7 +544,7 @@ dd.answer div.label { float: left; }
           <p class="para block block-first">Toggles between increasing and decreasing sort order. A check will appear next to this entry to indicate ascending sort order.</p>
         </dd>
 </dl></div>
-<p class="para block"></p>
+<div class="admonition block note block-indent"><div class="note-inner">When images have equal rank, for example in rating or class sorts, within each section images will be sorted by filename.</div></div>
 </div>
 <div class="division section">
 <a name="Filelist"></a><div class="header"><h2 class="section title"><span class="title"><span class="label">2.6.3. </span>File list</span></h2></div>