[gtk+/icon-browser-fuzzy-search] A quick attampt at using fuzzy search in the icon browser
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/icon-browser-fuzzy-search] A quick attampt at using fuzzy search in the icon browser
- Date: Sat, 3 Jun 2017 04:21:52 +0000 (UTC)
commit cc58b0e20414357e4b0384704bccec175f186b8d
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Jun 3 00:20:46 2017 -0400
A quick attampt at using fuzzy search in the icon browser
This is using the fuzzy search code from libdazzle.
demos/icon-browser/Makefile.am | 8 +++-
demos/icon-browser/iconbrowserwin.c | 97 +++++++++++++++++++++++++++++++++--
demos/icon-browser/main.c | 76 +++++++++++++++++++++++++++
demos/icon-browser/window.ui | 5 ++-
4 files changed, 180 insertions(+), 6 deletions(-)
---
diff --git a/demos/icon-browser/Makefile.am b/demos/icon-browser/Makefile.am
index 6de3fe7..1837198 100644
--- a/demos/icon-browser/Makefile.am
+++ b/demos/icon-browser/Makefile.am
@@ -21,6 +21,11 @@ gtk3_icon_browser_SOURCES = \
iconbrowserapp.c iconbrowserapp.h \
iconbrowserwin.c iconbrowserwin.h \
iconstore.c iconstore.h \
+ fuzzy/dzl-fuzzy-index-builder.c fuzzy/dzl-fuzzy-index-builder.h \
+ fuzzy/dzl-fuzzy-index.c fuzzy/dzl-fuzzy-index.h \
+ fuzzy/dzl-fuzzy-util.c fuzzy/dzl-fuzzy-util.h \
+ fuzzy/dzl-fuzzy-index-cursor.c fuzzy/dzl-fuzzy-index-cursor.h \
+ fuzzy/dzl-fuzzy-index-match.c fuzzy/dzl-fuzzy-index-match.h \
resources.c
BUILT_SOURCES = \
@@ -34,7 +39,8 @@ EXTRA_DIST = \
menus.ui \
iconbrowser.gresource.xml \
window.ui \
- icon.list
+ icon.list \
+ icon.index
# ------------------- MSVC Build Items ----------------
MSVCPROJS = gtk3-icon-browser
diff --git a/demos/icon-browser/iconbrowserwin.c b/demos/icon-browser/iconbrowserwin.c
index 7e33622..3062db6 100644
--- a/demos/icon-browser/iconbrowserwin.c
+++ b/demos/icon-browser/iconbrowserwin.c
@@ -3,6 +3,8 @@
#include "iconbrowserwin.h"
#include "iconstore.h"
#include <gtk/gtk.h>
+#include <fuzzy/dzl-fuzzy-index.h>
+#include <fuzzy/dzl-fuzzy-index-match.h>
typedef struct
{
@@ -32,6 +34,7 @@ struct _IconBrowserWindow
gboolean symbolic;
GtkWidget *symbolic_radio;
GtkTreeModelFilter *filter_model;
+ GtkTreeModelSort *sort_model;
GtkWidget *details;
GtkListStore *store;
@@ -47,6 +50,9 @@ struct _IconBrowserWindow
GtkWidget *image4;
GtkWidget *image5;
GtkWidget *description;
+
+ DzlFuzzyIndex *index;
+ GHashTable *visible;
};
struct _IconBrowserWindowClass
@@ -57,6 +63,31 @@ struct _IconBrowserWindowClass
G_DEFINE_TYPE(IconBrowserWindow, icon_browser_window, GTK_TYPE_APPLICATION_WINDOW);
static void
+query_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ IconBrowserWindow *win = data;
+ GListModel *model;
+ GError *error = NULL;
+ int i;
+
+ model = dzl_fuzzy_index_query_finish (win->index, result, &error);
+ g_print ("%d matches found.\n", g_list_model_get_n_items (model));
+
+ g_hash_table_remove_all (win->visible);
+ for (i = 0; i < g_list_model_get_n_items (model); i++)
+ {
+ DzlFuzzyIndexMatch *match = g_list_model_get_item (model, i);
+ GVariant *document = dzl_fuzzy_index_match_get_document (match);
+ char *str = g_variant_dup_string (document, NULL);
+ g_hash_table_insert (win->visible, str, GINT_TO_POINTER (i + 1));
+ }
+ g_object_unref (model);
+ gtk_tree_model_filter_refilter (win->filter_model);
+}
+
+static void
search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
{
const gchar *text;
@@ -66,7 +97,7 @@ search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
if (text[0] == '\0')
return;
- gtk_tree_model_filter_refilter (win->filter_model);
+ dzl_fuzzy_index_query_async (win->index, text, 0, NULL, query_cb, win);
}
static GdkPixbuf *
@@ -301,11 +332,9 @@ icon_visible_func (GtkTreeModel *model,
gchar *name;
gint column;
gboolean search;
- const gchar *search_text;
gboolean visible;
search = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (win->search));
- search_text = gtk_entry_get_text (GTK_ENTRY (win->searchentry));
if (win->symbolic)
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
@@ -319,7 +348,7 @@ icon_visible_func (GtkTreeModel *model,
if (!name)
visible = FALSE;
else if (search)
- visible = strstr (name, search_text) != NULL;
+ visible = g_hash_table_lookup (win->visible, name) != NULL;
else
visible = win->current_context != NULL && g_strcmp0 (context, win->current_context->id) == 0;
@@ -355,6 +384,8 @@ search_mode_toggled (GObject *searchbar, GParamSpec *pspec, IconBrowserWindow *w
{
if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (searchbar)))
gtk_list_box_unselect_all (GTK_LIST_BOX (win->context_list));
+
+ gtk_tree_model_filter_refilter (win->filter_model);
}
static void
@@ -391,12 +422,56 @@ setup_image_dnd (GtkWidget *image)
g_signal_connect (parent, "drag-data-get", G_CALLBACK (get_image_data), NULL);
}
+static gint
+sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer data)
+{
+ IconBrowserWindow *win = data;
+ char *aname = NULL;
+ char *bname = NULL;
+ int column;
+ int apos, bpos;
+ gboolean search;
+ int ret;
+
+ search = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (win->search));
+
+ if (win->symbolic)
+ column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
+ else
+ column = ICON_STORE_NAME_COLUMN;
+
+ gtk_tree_model_get (model, a, column, &aname, -1);
+ gtk_tree_model_get (model, b, column, &bname, -1);
+
+ if (!aname || !bname)
+ ret = 0;
+ else if (search)
+ {
+ apos = GPOINTER_TO_INT (g_hash_table_lookup (win->visible, aname));
+ bpos = GPOINTER_TO_INT (g_hash_table_lookup (win->visible, bname));
+
+ ret = apos - bpos;
+ }
+ else
+ ret = strcmp (aname, bname);
+
+ g_free (aname);
+ g_free (bname);
+
+ return ret;
+}
+
static void
icon_browser_window_init (IconBrowserWindow *win)
{
GtkTargetList *list;
GtkTargetEntry *targets;
gint n_targets;
+ GFile *file;
+ GError *error = NULL;
gtk_widget_init_template (GTK_WIDGET (win));
@@ -421,6 +496,7 @@ icon_browser_window_init (IconBrowserWindow *win)
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
gtk_tree_model_filter_set_visible_func (win->filter_model, icon_visible_func, win, NULL);
+ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (win->sort_model), sort_func, win, NULL);
gtk_window_set_transient_for (GTK_WINDOW (win->details), GTK_WINDOW (win));
g_signal_connect (win->searchbar, "notify::search-mode-enabled",
@@ -429,6 +505,18 @@ icon_browser_window_init (IconBrowserWindow *win)
symbolic_toggled (GTK_TOGGLE_BUTTON (win->symbolic_radio), win);
populate (win);
+
+ win->index = dzl_fuzzy_index_new ();
+ file = g_file_new_for_path ("icon.index");
+ if (!dzl_fuzzy_index_load_file (win->index, file, NULL, &error))
+ {
+ g_printerr ("Failed to load index: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (file);
+
+ win->visible = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
static void
@@ -441,6 +529,7 @@ icon_browser_window_class_init (IconBrowserWindowClass *class)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, context_list);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, filter_model);
+ gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, sort_model);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, symbolic_radio);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, details);
diff --git a/demos/icon-browser/main.c b/demos/icon-browser/main.c
index 7dd5eee..9bd58c4 100644
--- a/demos/icon-browser/main.c
+++ b/demos/icon-browser/main.c
@@ -1,8 +1,84 @@
+#include <string.h>
#include <gtk/gtk.h>
#include <iconbrowserapp.h>
+#include <fuzzy/dzl-fuzzy-index-builder.h>
+
+static void
+build_fuzzy_index (void)
+{
+ DzlFuzzyIndexBuilder *builder;
+ GFile *file;
+ GKeyFile *kf;
+ char *data;
+ gsize length;
+ char **groups;
+ int i;
+ GFile *outfile;
+ GError *error = NULL;
+
+ builder = dzl_fuzzy_index_builder_new ();
+ dzl_fuzzy_index_builder_set_case_sensitive (builder, FALSE);
+
+ file = g_file_new_for_uri ("resource:/org/gtk/iconbrowser/gtk/icon.list");
+ g_file_load_contents (file, NULL, &data, &length, NULL, NULL);
+
+ kf = g_key_file_new ();
+ g_key_file_load_from_data (kf, data, length, G_KEY_FILE_NONE, NULL);
+
+ groups = g_key_file_get_groups (kf, &length);
+ for (i = 0; i < length; i++)
+ {
+ const char *context;
+ char **keys;
+ gsize len;
+ int j;
+
+ context = groups[i];
+
+ keys = g_key_file_get_keys (kf, context, &len, NULL);
+ for (j = 0; j < len; j++)
+ {
+ const char *key = keys[j];
+ char *symbolic;
+
+ if (strcmp (key, "Name") == 0 || strcmp (key, "Description") == 0)
+ continue;
+
+ dzl_fuzzy_index_builder_insert (builder, key, g_variant_new_string (key));
+
+ symbolic = g_strconcat (key, "-symbolic", NULL);
+
+ dzl_fuzzy_index_builder_insert (builder, symbolic, g_variant_new_string (symbolic));
+
+ g_free (symbolic);
+ }
+ g_strfreev (keys);
+ }
+ g_strfreev (groups);
+
+ outfile = g_file_new_for_path ("icon.index");
+
+ if (!dzl_fuzzy_index_builder_write (builder, outfile, G_PRIORITY_DEFAULT, NULL, &error))
+ {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ g_print ("icon.index written\n");
+ }
+
+ g_object_unref (builder);
+}
int
main (int argc, char *argv[])
{
+ if (argc == 2 && strcmp (argv[1], "--generate-index") == 0)
+ {
+ build_fuzzy_index ();
+ return 0;
+ }
+
return g_application_run (G_APPLICATION (icon_browser_app_new ()), argc, argv);
}
diff --git a/demos/icon-browser/window.ui b/demos/icon-browser/window.ui
index c4e4b87..0eeb8a0 100644
--- a/demos/icon-browser/window.ui
+++ b/demos/icon-browser/window.ui
@@ -3,8 +3,11 @@
<!-- interface-requires gtk+ 3.8 -->
<object class="IconStore" id="store">
</object>
+ <object class="GtkTreeModelSort" id="sort_model">
+ <property name="model">store</property>
+ </object>
<object class="GtkTreeModelFilter" id="filter_model">
- <property name="child_model">store</property>
+ <property name="child_model">sort_model</property>
</object>
<template class="IconBrowserWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Icon Browser</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]