changeset 2696:f090fbf9362f

Sort/search on file class 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.
author Colin Clark <colin.clark@cclark.uk>
date Wed, 03 Jan 2018 17:49:15 +0000
parents 226c02528774
children 10ca4efb9d48 940f217da9ec
files 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
diffstat 9 files changed, 167 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docbook/GuideImageSearchSearch.xml	Wed Jan 03 16:10:35 2018 +0000
+++ b/doc/docbook/GuideImageSearchSearch.xml	Wed Jan 03 17:49:15 2018 +0000
@@ -161,6 +161,21 @@
           </note>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term>
+          <guilabel>Class</guilabel>
+        </term>
+        <listitem>
+          The search will match if the file's class is, or is not, one of the following types.
+          <itemizedlist>
+            <listitem>Unknown</listitem>
+            <listitem>Image</listitem>
+            <listitem>Raw Image</listitem>
+            <listitem>Video</listitem>
+            <listitem>Metadata</listitem>
+          </itemizedlist>
+        </listitem>
+      </varlistentry>
     </variablelist>
     <para />
     <para />
--- a/doc/docbook/GuideMainWindowStatusBar.xml	Wed Jan 03 16:10:35 2018 +0000
+++ b/doc/docbook/GuideMainWindowStatusBar.xml	Wed Jan 03 17:49:15 2018 +0000
@@ -58,7 +58,30 @@
           <guilabel>Size</guilabel>
         </term>
         <listitem>
-          <para>Image are sorted by file size on disk.</para>
+          <para>Images are sorted by file size on disk.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <guilabel>Rating</guilabel>
+        </term>
+        <listitem>
+          <para>Image are sorted by Xmp.xmp.Rating.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <guilabel>Class</guilabel>
+        </term>
+        <listitem>
+          <para>Image are sorted by class. The class types, and sort order, is:</para>
+          <itemizedlist>
+            <listitem>Unknown</listitem>
+            <listitem>Image</listitem>
+            <listitem>Raw Image</listitem>
+            <listitem>Video</listitem>
+            <listitem>Metadata</listitem>
+          </itemizedlist>
         </listitem>
       </varlistentry>
       <varlistentry>
@@ -70,7 +93,7 @@
         </listitem>
       </varlistentry>
     </variablelist>
-    <para />
+    <note>When images have equal rank, for example in rating or class sorts, within each section images will be sorted by filename.</note>
   </section>
   <section id="Filelist">
     <title>File list</title>
--- a/src/collect.c	Wed Jan 03 16:10:35 2018 +0000
+++ b/src/collect.c	Wed Jan 03 17:49:15 2018 +0000
@@ -172,6 +172,10 @@
 		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);
--- a/src/filedata.c	Wed Jan 03 16:10:35 2018 +0000
+++ b/src/filedata.c	Wed Jan 03 17:49:15 2018 +0000
@@ -1051,6 +1051,11 @@
 			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);
--- a/src/menu.c	Wed Jan 03 16:10:35 2018 +0000
+++ b/src/menu.c	Wed Jan 03 17:49:15 2018 +0000
@@ -163,6 +163,9 @@
 		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 @@
 	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);
 
--- a/src/search.c	Wed Jan 03 16:10:35 2018 +0000
+++ b/src/search.c	Wed Jan 03 17:49:15 2018 +0000
@@ -144,6 +144,10 @@
 	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 @@
 	MatchType match_comment;
 	MatchType match_rating;
 	MatchType match_gps;
+	MatchType match_class;
 
 	gboolean match_name_enable;
 	gboolean match_size_enable;
@@ -189,6 +194,7 @@
 	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 @@
 	{ 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 @@
 			}
 		}
 
+	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 @@
 				(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 @@
 	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 @@
 
 	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);
--- a/src/typedefs.h	Wed Jan 03 16:10:35 2018 +0000
+++ b/src/typedefs.h	Wed Jan 03 17:49:15 2018 +0000
@@ -74,7 +74,8 @@
 	SORT_PATH,
 	SORT_NUMBER,
 	SORT_EXIFTIME,
-	SORT_RATING
+	SORT_RATING,
+	SORT_CLASS
 } SortType;
 
 typedef enum {
--- a/web/help/GuideImageSearchSearch.html	Wed Jan 03 16:10:35 2018 +0000
+++ b/web/help/GuideImageSearchSearch.html	Wed Jan 03 17:49:15 2018 +0000
@@ -606,6 +606,19 @@
             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>
--- a/web/help/GuideMainWindowStatusBar.html	Wed Jan 03 16:10:35 2018 +0000
+++ b/web/help/GuideMainWindowStatusBar.html	Wed Jan 03 17:49:15 2018 +0000
@@ -516,7 +516,26 @@
           <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 @@
           <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>