diff options
-rw-r--r-- | demos/icon-browser/Makefile.am | 8 | ||||
-rw-r--r-- | demos/icon-browser/iconbrowserwin.c | 97 | ||||
-rw-r--r-- | demos/icon-browser/main.c | 76 | ||||
-rw-r--r-- | 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 6de3fe7de5..1837198700 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 7e33622b4d..3062db64cb 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 7dd5eee550..9bd58c4dbe 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 c4e4b873c9..0eeb8a0fc4 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> |