Fix #705: Toolbar status class filter
authorColin Clark <colin.clark@cclark.uk>
Fri, 9 Aug 2019 08:50:33 +0000 (09:50 +0100)
committerColin Clark <colin.clark@cclark.uk>
Fri, 9 Aug 2019 08:50:33 +0000 (09:50 +0100)
https://github.com/BestImageViewer/geeqie/issues/705

In the file filter box there is a menu to select which classes are to be
filtered

13 files changed:
doc/docbook/GuideMainWindowFilePane.xml
doc/docbook/GuideOptionsFiltering.xml
src/filedata.c
src/filedata.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_list.c

index fa08605..2cb4794 100644 (file)
@@ -81,6 +81,7 @@
       <keycap>Enter</keycap>\r
       .\r
     </para>\r
+    <para>Additionally a drop-down box permits any of the file <link linkend="Filetypes">Classes</link> to be selected or deselected from the viewed list.</para>\r
     <para />\r
   </section>\r
   <section id="Multipleselection">\r
index 55e560d..64e977c 100644 (file)
           <listitem>\r
             This may be used to define sets of file types, for use in the\r
             <emphasis>Grouping</emphasis>\r
-            function described above. The drop-down list has 6 entries:\r
+            function described above. The drop-down list has 7 entries:\r
             <itemizedlist>\r
               <listitem>Unknown</listitem>\r
               <listitem>Image</listitem>\r
               <listitem>Metadata</listitem>\r
               <listitem>Video</listitem>\r
               <listitem>Collection</listitem>\r
+              <listitem>Document</listitem>\r
             </itemizedlist>\r
           </listitem>\r
         </varlistentry>\r
index e258052..ca86d75 100644 (file)
@@ -1890,6 +1890,46 @@ GList *file_data_filter_file_filter_list(GList *list, GRegex *filter)
        return list;
 }
 
+static gboolean file_data_filter_class(FileData *fd, guint filter)
+{
+       gint i;
+
+       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+               {
+               if (filter & (1 << i))
+                       {
+                       if ((FileFormatClass)i == filter_file_get_class(fd->path))
+                               {
+                               return TRUE;
+                               }
+                       }
+               }
+
+       return FALSE;
+}
+
+GList *file_data_filter_class_list(GList *list, guint filter)
+{
+       GList *work;
+
+       work = list;
+       while (work)
+               {
+               FileData *fd = work->data;
+               GList *link = work;
+               work = work->next;
+
+               if (!file_data_filter_class(fd, filter))
+                       {
+                       list = g_list_remove_link(list, link);
+                       file_data_unref(fd);
+                       g_list_free(link);
+                       }
+               }
+
+       return list;
+}
+
 static void file_data_notify_mark_func(gpointer key, gpointer value, gpointer user_data)
 {
        FileData *fd = value;
index 4664ded..736dab0 100644 (file)
@@ -103,6 +103,8 @@ GList *file_data_filter_marks_list(GList *list, guint filter);
 gboolean file_data_filter_file_filter(FileData *fd, GRegex *filter);
 GList *file_data_filter_file_filter_list(GList *list, GRegex *filter);
 
+GList *file_data_filter_class_list(GList *list, guint filter);
+
 gint file_data_get_user_orientation(FileData *fd);
 void file_data_set_user_orientation(FileData *fd, gint value);
 
index 4da0f21..9945938 100644 (file)
@@ -210,6 +210,10 @@ ConfOptions *init_options(ConfOptions *options)
        options->mouse_button_8 = g_strdup("Back");
        options->mouse_button_9 = g_strdup("Forward");
 
+       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+               {
+               options->class_filter[i] = TRUE;
+               }
        return options;
 }
 
index 85b674e..fcfe961 100644 (file)
@@ -321,6 +321,9 @@ struct _ConfOptions
        gchar *mouse_button_8;
        gchar *mouse_button_9;
 
+       /* class file filter */
+       gboolean class_filter[FILE_FORMAT_CLASSES];
+
        gboolean read_metadata_in_idle;
 
        GList *disabled_plugins;
index 41304ba..dcdbb20 100644 (file)
@@ -117,8 +117,7 @@ gchar *format_class_list[] = {
        N_("Metadata"),
        N_("Video"),
        N_("Collection"),
-       N_("Document"),
-       N_("HEIF")
+       N_("Document")
        };
 
 /* config memory values */
index 9484132..aba8702 100644 (file)
@@ -562,6 +562,23 @@ static void write_marks_tooltips(GString *outstr, gint indent)
        WRITE_NL(); WRITE_STRING("</marks_tooltips>");
 }
 
+static void write_class_filter(GString *outstr, gint indent)
+{
+       gint i;
+
+       WRITE_NL(); WRITE_STRING("<class_filter>");
+       indent++;
+       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+               {
+               WRITE_NL(); WRITE_STRING("<filter_type ");
+               write_char_option(outstr, indent, "filter", format_class_list[i]);
+               write_bool_option(outstr, indent, "enabled", options->class_filter[i]);
+               WRITE_STRING("/>");
+               }
+       indent--;
+       WRITE_NL(); WRITE_STRING("</class_filter>");
+}
+
 static void write_disabled_plugins(GString *outstr, gint indent)
 {
        GtkTreeIter iter;
@@ -653,6 +670,9 @@ gboolean save_config_to_file(const gchar *utf8_path, ConfOptions *options)
        WRITE_SEPARATOR();
        write_disabled_plugins(outstr, indent);
 
+       WRITE_SEPARATOR();
+       write_class_filter(outstr, indent);
+
        WRITE_SEPARATOR();
        keyword_tree_write_config(outstr, indent);
        indent--;
@@ -1050,6 +1070,49 @@ static void options_parse_marks_tooltips(GQParserData *parser_data, GMarkupParse
                }
 }
 
+static void class_filter_load_filter_type(const gchar **attribute_names, const gchar **attribute_values)
+{
+       gint i;
+       gint index;
+
+       while (*attribute_names)
+               {
+               const gchar *option = *attribute_names++;
+               const gchar *value = *attribute_values++;
+               if (g_strcmp0("filter", option) == 0)
+                       {
+                       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+                               {
+                               if (g_strcmp0(format_class_list[i], value) == 0)
+                                       {
+                                       index = i;
+                                       }
+                               }
+                       continue;
+                       }
+
+               if (READ_BOOL_FULL("enabled", options->class_filter[index]))
+                       {
+                       continue;
+                       }
+               log_printf("unknown attribute %s = %s\n", option, value);
+               }
+}
+
+static void options_parse_class_filter(GQParserData *parser_data, GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
+{
+       if (g_ascii_strcasecmp(element_name, "filter_type") == 0)
+               {
+               class_filter_load_filter_type(attribute_names, attribute_values);
+               options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+               }
+       else
+               {
+               log_printf("unexpected in <profile>: <%s>\n", element_name);
+               options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+               }
+}
+
 static void options_parse_disabled_plugins(GQParserData *parser_data, GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
 {
        if (g_ascii_strcasecmp(element_name, "plugin") == 0)
@@ -1139,6 +1202,10 @@ static void options_parse_global(GQParserData *parser_data, GMarkupParseContext
                options_load_marks_tooltips(parser_data, context, element_name, attribute_names, attribute_values, data, error);
                options_parse_func_push(parser_data, options_parse_marks_tooltips, NULL, NULL);
                }
+       else if (g_ascii_strcasecmp(element_name, "class_filter") == 0)
+               {
+               options_parse_func_push(parser_data, options_parse_class_filter, NULL, NULL);
+               }
        else if (g_ascii_strcasecmp(element_name, "keyword_tree") == 0)
                {
                if (!keyword_tree) keyword_tree_new();
index 1067798..77bde72 100644 (file)
@@ -148,6 +148,7 @@ typedef enum {
        FILE_FORMAT_CLASSES
 } FileFormatClass;
 
+/* defined in preferences.c */
 extern gchar *format_class_list[];
 
 typedef enum {
index 5c519a2..d921a3a 100644 (file)
@@ -45,6 +45,8 @@ void vf_sort_set(ViewFile *vf, SortType type, gboolean ascend);
 guint vf_marks_get_filter(ViewFile *vf);
 void vf_mark_filter_toggle(ViewFile *vf, gint mark);
 
+guint vf_class_get_filter(ViewFile *vf);
+
 GList *vf_selection_get_one(ViewFile *vf, FileData *fd);
 GList *vf_pop_menu_file_list(ViewFile *vf);
 GtkWidget *vf_pop_menu(ViewFile *vf);
index 7d9ac93..b11fd10 100644 (file)
@@ -969,6 +969,97 @@ void vf_file_filter_set(ViewFile *vf, gboolean enable)
        vf_refresh(vf);
 }
 
+static gboolean vf_file_filter_class_cb(GtkWidget *widget, gpointer data)
+{
+       ViewFile *vf = data;
+       gint i;
+
+       gboolean state = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+
+       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+               {
+               if (g_strcmp0(format_class_list[i], gtk_menu_item_get_label(GTK_MENU_ITEM(widget))) == 0)
+                       {
+                       options->class_filter[i] = state;
+                       }
+               }
+       vf_refresh(vf);
+
+       return TRUE;
+}
+
+static gboolean vf_file_filter_class_set_all_cb(GtkWidget *widget, gpointer data)
+{
+       ViewFile *vf = data;
+       GtkWidget *parent;
+       GList *children;
+       GtkWidget *child;
+       gint i;
+       gboolean state;
+
+       if (g_strcmp0("Select all", gtk_menu_item_get_label(GTK_MENU_ITEM(widget))) == 0)
+               {
+               state == TRUE;
+               }
+       else
+               {
+               state = FALSE;
+               }
+
+       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+               {
+               options->class_filter[i] = state;
+               }
+
+       i = 0;
+       parent = gtk_widget_get_parent(widget);
+       children = gtk_container_get_children(GTK_CONTAINER(parent));
+       while (children)
+               {
+               child = children->data;
+               if (i < FILE_FORMAT_CLASSES)
+                       {
+                       gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(child), state);
+                       }
+               i++;
+               children = children->next;
+               }
+       g_list_free(children);
+       vf_refresh(vf);
+
+       return TRUE;
+}
+
+static GtkWidget *class_filter_menu (ViewFile *vf)
+{
+       GtkWidget *menu;
+       GtkWidget *menu_item;
+       int i;
+
+       menu = gtk_menu_new();
+
+       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+           {
+               menu_item = gtk_check_menu_item_new_with_label(format_class_list[i]);
+               gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), options->class_filter[i]);
+               g_signal_connect(G_OBJECT(menu_item), "toggled", G_CALLBACK(vf_file_filter_class_cb), vf);
+               gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_item);
+               gtk_widget_show(menu_item);
+               }
+
+       menu_item = gtk_menu_item_new_with_label(_("Select all"));
+       gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_item);
+       gtk_widget_show(menu_item);
+       g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(vf_file_filter_class_set_all_cb), vf);
+
+       menu_item = gtk_menu_item_new_with_label(_("Select none"));
+       gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_item);
+       gtk_widget_show(menu_item);
+       g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(vf_file_filter_class_set_all_cb), vf);
+
+       return menu;
+}
+
 static GtkWidget *vf_file_filter_init(ViewFile *vf)
 {
        GtkWidget *frame = gtk_frame_new(NULL);
@@ -976,6 +1067,8 @@ static GtkWidget *vf_file_filter_init(ViewFile *vf)
        GList *work;
        gint n = 0;
        GtkWidget *combo_entry;
+       GtkWidget *menubar;
+       GtkWidget *menuitem;
 
        vf->file_filter.combo = gtk_combo_box_text_new_with_entry();
        combo_entry = gtk_bin_get_child(GTK_BIN(vf->file_filter.combo));
@@ -1007,6 +1100,19 @@ static GtkWidget *vf_file_filter_init(ViewFile *vf)
        gtk_container_add(GTK_CONTAINER(frame), hbox);
        gtk_widget_show(hbox);
 
+       menubar = gtk_menu_bar_new();
+       gtk_widget_set_hexpand(menubar, TRUE);
+       gtk_box_pack_start(GTK_BOX(hbox), menubar, FALSE, TRUE, 0);
+       gtk_widget_show(menubar);
+
+       menuitem = gtk_menu_item_new_with_label(_("Class"));
+       gtk_widget_set_tooltip_text(GTK_WIDGET(menuitem), _("Select Class filter"));
+       gtk_menu_item_set_submenu(GTK_MENU_ITEM (menuitem), class_filter_menu(vf));
+       gtk_menu_shell_append(GTK_MENU_SHELL (menubar), menuitem);
+       gtk_widget_show(menuitem);
+
+       gtk_widget_show(menuitem);
+
        return frame;
 }
 
@@ -1346,6 +1452,27 @@ GRegex *vf_file_filter_get_filter(ViewFile *vf)
        return ret;
 }
 
+guint vf_class_get_filter(ViewFile *vf)
+{
+       guint ret = 0;
+       gint i;
+
+       if (!gtk_widget_get_visible(vf->file_filter.combo))
+               {
+               return G_MAXUINT;
+               }
+
+       for ( i = 0; i < FILE_FORMAT_CLASSES; i++)
+               {
+               if (options->class_filter[i])
+                       {
+                       ret |= 1 << i;
+                       }
+               }
+
+       return ret;
+}
+
 void vf_set_layout(ViewFile *vf, LayoutWindow *layout)
 {
        vf->layout = layout;
index ab4d5c8..b819a86 100644 (file)
@@ -1850,6 +1850,10 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position)
                new_filelist = file_data_filter_marks_list(new_filelist, vf_marks_get_filter(vf));
                new_filelist = g_list_first(new_filelist);
                new_filelist = file_data_filter_file_filter_list(new_filelist, vf_file_filter_get_filter(vf));
+
+               new_filelist = g_list_first(new_filelist);
+               new_filelist = file_data_filter_class_list(new_filelist, vf_class_get_filter(vf));
+
                }
 
        vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend); /* the list might not be sorted if there were renames */
index 418f25b..4b428de 100644 (file)
@@ -1809,6 +1809,10 @@ gboolean vflist_refresh(ViewFile *vf)
                vf->list = file_data_filter_marks_list(vf->list, vf_marks_get_filter(vf));
                vf->list = g_list_first(vf->list);
                vf->list = file_data_filter_file_filter_list(vf->list, vf_file_filter_get_filter(vf));
+
+               vf->list = g_list_first(vf->list);
+               vf->list = file_data_filter_class_list(vf->list, vf_class_get_filter(vf));
+
                file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
 
                DEBUG_1("%s vflist_refresh: sort", get_exec_time());