summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2015-07-01 12:51:20 -0700
committerMatthias Clasen <mclasen@redhat.com>2015-07-04 00:29:25 -0400
commit33b5c26f419aab0c072a7ac49f450e861459b852 (patch)
tree04cbbc3a282a446a6dd4120c08ed80d93cec5c60
parentf87f43b6229d2314523c925d0f3584ab23c7adf9 (diff)
downloadgtk+-33b5c26f419aab0c072a7ac49f450e861459b852.tar.gz
file chooser: Add and use a model search engine
This search engine reuses the GFileInfo that is already loaded for the file list, to ensure that hits from the current directory always appear promptly.
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtkfilechooserwidget.c13
-rw-r--r--gtk/gtksearchengine.c57
-rw-r--r--gtk/gtksearchengine.h4
-rw-r--r--gtk/gtksearchenginemodel.c191
-rw-r--r--gtk/gtksearchenginemodel.h44
6 files changed, 306 insertions, 5 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 861f186370..4795f84222 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -496,6 +496,7 @@ gtk_private_h_sources = \
gtkscaleprivate.h \
gtksearchengine.h \
gtksearchenginesimple.h \
+ gtksearchenginemodel.h \
gtksearchentryprivate.h \
gtkselectionprivate.h \
gtksidebarrowprivate.h \
@@ -545,6 +546,7 @@ gtk_base_c_sources = \
gtksearchentry.c \
gtksearchengine.c \
gtksearchenginesimple.c \
+ gtksearchenginemodel.c \
fnmatch.c \
gtkaboutdialog.c \
gtkaccelgroup.c \
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index eb34ef7eb7..32931702cf 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -248,6 +248,7 @@ struct _GtkFileChooserWidgetPrivate {
GtkSearchEngine *search_engine;
GtkQuery *search_query;
GtkFileSystemModel *search_model;
+ GtkFileSystemModel *model_for_search;
/* OPERATION_MODE_RECENT */
GtkRecentManager *recent_manager;
@@ -659,6 +660,7 @@ gtk_file_chooser_widget_finalize (GObject *object)
stop_loading_and_clear_list_model (impl, FALSE);
search_clear_model (impl, FALSE);
recent_clear_model (impl, FALSE);
+ g_clear_object (&impl->priv->model_for_search);
/* stopping the load above should have cleared this */
g_assert (priv->load_timeout_id == 0);
@@ -2600,6 +2602,7 @@ operation_mode_stop (GtkFileChooserWidget *impl, OperationMode mode)
break;
case OPERATION_MODE_SEARCH:
+ g_clear_object (&impl->priv->model_for_search);
search_stop_searching (impl, FALSE);
search_clear_model (impl, TRUE);
break;
@@ -3684,6 +3687,8 @@ load_set_model (GtkFileChooserWidget *impl)
profile_msg (" gtk_tree_view_set_model end", NULL);
priv->list_sort_ascending = TRUE;
+ g_set_object (&priv->model_for_search, priv->browse_files_model);
+
profile_end ("end", NULL);
}
@@ -6419,12 +6424,11 @@ search_clear_model (GtkFileChooserWidget *impl,
{
GtkFileChooserWidgetPrivate *priv = impl->priv;
+ g_clear_object (&priv->search_model);
+
if (!priv->search_model)
return;
- g_object_unref (priv->search_model);
- priv->search_model = NULL;
-
if (remove_from_treeview)
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view), NULL);
}
@@ -6537,6 +6541,7 @@ search_start_query (GtkFileChooserWidget *impl,
g_object_unref (file);
}
+ _gtk_search_engine_set_model (priv->search_engine, priv->model_for_search);
_gtk_search_engine_set_query (priv->search_engine, priv->search_query);
g_signal_connect (priv->search_engine, "hits-added",
@@ -6734,6 +6739,8 @@ populate_model_with_recent_items (GtkFileChooserWidget *impl, GList *items)
if (limit != -1 && n >= limit)
break;
}
+
+ g_set_object (&priv->model_for_search, priv->recent_model);
}
static void
diff --git a/gtk/gtksearchengine.c b/gtk/gtksearchengine.c
index 67110f936b..8a92a220c1 100644
--- a/gtk/gtksearchengine.c
+++ b/gtk/gtksearchengine.c
@@ -23,6 +23,7 @@
#include "gtksearchengine.h"
#include "gtksearchenginesimple.h"
#include "gtksearchenginetracker.h"
+#include "gtksearchenginemodel.h"
#include "gtksearchenginequartz.h"
#include <gdk/gdk.h> /* for GDK_WINDOWING_QUARTZ */
@@ -40,9 +41,15 @@ struct _GtkSearchEnginePrivate {
gboolean simple_running;
gchar *simple_error;
+ GtkSearchEngine *model;
+ gboolean model_running;
+ gchar *model_error;
+
gboolean running;
gboolean recursive;
GHashTable *hits;
+
+ GtkQuery *query;
};
enum
@@ -61,11 +68,16 @@ static void
set_query (GtkSearchEngine *engine,
GtkQuery *query)
{
+ g_set_object (&engine->priv->query, query);
+
if (engine->priv->native)
_gtk_search_engine_set_query (engine->priv->native, query);
if (engine->priv->simple)
_gtk_search_engine_set_query (engine->priv->simple, query);
+
+ if (engine->priv->model)
+ _gtk_search_engine_set_query (engine->priv->model, query);
}
static void
@@ -87,6 +99,13 @@ start (GtkSearchEngine *engine)
engine->priv->simple_running = TRUE;
}
+ if (engine->priv->model)
+ {
+ g_clear_pointer (&engine->priv->model_error, g_free);
+ _gtk_search_engine_start (engine->priv->model);
+ engine->priv->model_running = TRUE;
+ }
+
engine->priv->running = TRUE;
}
@@ -105,6 +124,12 @@ stop (GtkSearchEngine *engine)
engine->priv->simple_running = FALSE;
}
+ if (engine->priv->model)
+ {
+ _gtk_search_engine_stop (engine->priv->model);
+ engine->priv->model_running = FALSE;
+ }
+
engine->priv->running = FALSE;
g_hash_table_remove_all (engine->priv->hits);
@@ -121,8 +146,13 @@ finalize (GObject *object)
g_clear_object (&engine->priv->simple);
g_free (engine->priv->simple_error);
+ g_clear_object (&engine->priv->model);
+ g_free (engine->priv->model_error);
+
g_clear_pointer (&engine->priv->hits, g_hash_table_unref);
+ g_clear_object (&engine->priv->query);
+
G_OBJECT_CLASS (_gtk_search_engine_parent_class)->finalize (object);
}
@@ -222,6 +252,8 @@ update_status (GtkSearchEngine *engine)
_gtk_search_engine_error (engine, engine->priv->native_error);
else if (engine->priv->simple_error)
_gtk_search_engine_error (engine, engine->priv->simple_error);
+ else if (engine->priv->model_error)
+ _gtk_search_engine_error (engine, engine->priv->model_error);
else
_gtk_search_engine_finished (engine);
}
@@ -238,6 +270,8 @@ finished (GtkSearchEngine *engine,
composite->priv->native_running = FALSE;
else if (engine == composite->priv->simple)
composite->priv->simple_running = FALSE;
+ else if (engine == composite->priv->model)
+ composite->priv->model_running = FALSE;
update_status (composite);
}
@@ -257,10 +291,16 @@ error (GtkSearchEngine *engine,
}
else if (engine == composite->priv->simple)
{
- g_free (composite->priv->native_error);
- composite->priv->native_error = g_strdup (message);
+ g_free (composite->priv->simple_error);
+ composite->priv->simple_error = g_strdup (message);
composite->priv->simple_running = FALSE;
}
+ else if (engine == composite->priv->model)
+ {
+ g_free (composite->priv->model_error);
+ composite->priv->model_error = g_strdup (message);
+ composite->priv->model_running = FALSE;
+ }
update_status (composite);
}
@@ -432,3 +472,16 @@ _gtk_search_engine_get_recursive (GtkSearchEngine *engine)
return engine->priv->recursive;
}
+
+void
+_gtk_search_engine_set_model (GtkSearchEngine *engine,
+ GtkFileSystemModel *model)
+{
+ g_clear_object (&engine->priv->model);
+ if (model)
+ {
+ engine->priv->model = _gtk_search_engine_model_new (model);
+ if (engine->priv->query)
+ _gtk_search_engine_set_query (engine->priv->model, engine->priv->query);
+ }
+}
diff --git a/gtk/gtksearchengine.h b/gtk/gtksearchengine.h
index 9e92e3185d..e49eeb8c79 100644
--- a/gtk/gtksearchengine.h
+++ b/gtk/gtksearchengine.h
@@ -23,6 +23,7 @@
#define __GTK_SEARCH_ENGINE_H__
#include "gtkquery.h"
+#include "gtkfilesystemmodel.h"
#include <gio/gio.h>
G_BEGIN_DECLS
@@ -91,6 +92,9 @@ gboolean _gtk_search_engine_get_recursive (GtkSearchEngine *engine);
void _gtk_search_hit_free (GtkSearchHit *hit);
GtkSearchHit *_gtk_search_hit_dup (GtkSearchHit *hit);
+void _gtk_search_engine_set_model (GtkSearchEngine *engine,
+ GtkFileSystemModel *model);
+
G_END_DECLS
#endif /* __GTK_SEARCH_ENGINE_H__ */
diff --git a/gtk/gtksearchenginemodel.c b/gtk/gtksearchenginemodel.c
new file mode 100644
index 0000000000..93003b5b55
--- /dev/null
+++ b/gtk/gtksearchenginemodel.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen <mclasen@redhat.com>
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include <gdk/gdk.h>
+
+#include "gtksearchenginemodel.h"
+#include "gtkprivate.h"
+
+#include <string.h>
+
+#define BATCH_SIZE 500
+
+struct _GtkSearchEngineModel
+{
+ GtkSearchEngine parent;
+
+ GtkFileSystemModel *model;
+ GtkQuery *query;
+
+ gboolean query_finished;
+ guint idle;
+};
+
+struct _GtkSearchEngineModelClass
+{
+ GtkSearchEngineClass parent_class;
+};
+
+G_DEFINE_TYPE (GtkSearchEngineModel, _gtk_search_engine_model, GTK_TYPE_SEARCH_ENGINE)
+
+static void
+gtk_search_engine_model_dispose (GObject *object)
+{
+ GtkSearchEngineModel *model = GTK_SEARCH_ENGINE_MODEL (object);
+
+ g_clear_object (&model->query);
+ g_clear_object (&model->model);
+
+ G_OBJECT_CLASS (_gtk_search_engine_model_parent_class)->dispose (object);
+}
+
+gboolean
+info_matches_query (GtkQuery *query,
+ GFileInfo *info)
+{
+ const gchar *display_name;
+
+ display_name = g_file_info_get_display_name (info);
+ if (display_name == NULL)
+ return FALSE;
+
+ if (g_file_info_get_is_hidden (info))
+ return FALSE;
+
+ if (!gtk_query_matches_string (query, display_name))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+do_search (gpointer data)
+{
+ GtkSearchEngineModel *model = data;
+ GtkTreeIter iter;
+ GList *hits = NULL;
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model->model), &iter))
+ {
+ do
+ {
+ GFileInfo *info;
+ GFile *file;
+ gchar *uri;
+
+ info = _gtk_file_system_model_get_info (model->model, &iter);
+ if (info_matches_query (model->query, info))
+ {
+ file = _gtk_file_system_model_get_file (model->model, &iter);
+ uri = g_file_get_uri (file);
+ hits = g_list_prepend (hits, uri);
+ }
+ }
+ while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model->model), &iter));
+
+ if (hits)
+ {
+ _gtk_search_engine_hits_added (GTK_SEARCH_ENGINE (model), hits);
+ g_list_free_full (hits, g_free);
+ }
+ }
+
+ model->idle = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+gtk_search_engine_model_start (GtkSearchEngine *engine)
+{
+ GtkSearchEngineModel *model;
+
+ model = GTK_SEARCH_ENGINE_MODEL (engine);
+
+ if (model->query == NULL)
+ return;
+
+ model->idle = g_idle_add (do_search, engine);
+}
+
+static void
+gtk_search_engine_model_stop (GtkSearchEngine *engine)
+{
+ GtkSearchEngineModel *model;
+
+ model = GTK_SEARCH_ENGINE_MODEL (engine);
+
+ if (model->idle != 0)
+ {
+ g_source_remove (model->idle);
+ model->idle = 0;
+ }
+}
+
+static void
+gtk_search_engine_model_set_query (GtkSearchEngine *engine,
+ GtkQuery *query)
+{
+ GtkSearchEngineModel *model;
+
+ model = GTK_SEARCH_ENGINE_MODEL (engine);
+
+ if (query)
+ g_object_ref (query);
+
+ if (model->query)
+ g_object_unref (model->query);
+
+ model->query = query;
+}
+
+static void
+_gtk_search_engine_model_class_init (GtkSearchEngineModelClass *class)
+{
+ GObjectClass *gobject_class;
+ GtkSearchEngineClass *engine_class;
+
+ gobject_class = G_OBJECT_CLASS (class);
+ gobject_class->dispose = gtk_search_engine_model_dispose;
+
+ engine_class = GTK_SEARCH_ENGINE_CLASS (class);
+ engine_class->set_query = gtk_search_engine_model_set_query;
+ engine_class->start = gtk_search_engine_model_start;
+ engine_class->stop = gtk_search_engine_model_stop;
+}
+
+static void
+_gtk_search_engine_model_init (GtkSearchEngineModel *engine)
+{
+}
+
+GtkSearchEngine *
+_gtk_search_engine_model_new (GtkFileSystemModel *model)
+{
+ GtkSearchEngineModel *engine;
+
+ engine = GTK_SEARCH_ENGINE_MODEL (g_object_new (GTK_TYPE_SEARCH_ENGINE_MODEL, NULL));
+ engine->model = g_object_ref (model);
+
+ return GTK_SEARCH_ENGINE (engine);
+}
diff --git a/gtk/gtksearchenginemodel.h b/gtk/gtksearchenginemodel.h
new file mode 100644
index 0000000000..a7cedab2a0
--- /dev/null
+++ b/gtk/gtksearchenginemodel.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Matthias Clasen
+ */
+
+#ifndef __GTK_SEARCH_ENGINE_MODEL_H__
+#define __GTK_SEARCH_ENGINE_MODEL_H__
+
+#include "gtksearchengine.h"
+#include "gtkfilesystemmodel.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SEARCH_ENGINE_MODEL (_gtk_search_engine_model_get_type ())
+#define GTK_SEARCH_ENGINE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SEARCH_ENGINE_MODEL, GtkSearchEngineModel))
+#define GTK_SEARCH_ENGINE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SEARCH_ENGINE_MODEL, GtkSearchEngineModelClass))
+#define GTK_IS_SEARCH_ENGINE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SEARCH_ENGINE_MODEL))
+#define GTK_IS_SEARCH_ENGINE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SEARCH_ENGINE_MODEL))
+#define GTK_SEARCH_ENGINE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SEARCH_ENGINE_MODEL, GtkSearchEngineModelClass))
+
+typedef struct _GtkSearchEngineModel GtkSearchEngineModel;
+typedef struct _GtkSearchEngineModelClass GtkSearchEngineModelClass;
+
+GType _gtk_search_engine_model_get_type (void);
+
+GtkSearchEngine *_gtk_search_engine_model_new (GtkFileSystemModel *model);
+
+G_END_DECLS
+
+#endif /* __GTK_SEARCH_ENGINE_MODEL_H__ */