mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-12 20:00:09 +00:00
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.
This commit is contained in:
parent
f87f43b622
commit
33b5c26f41
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
191
gtk/gtksearchenginemodel.c
Normal file
191
gtk/gtksearchenginemodel.c
Normal file
@ -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);
|
||||
}
|
44
gtk/gtksearchenginemodel.h
Normal file
44
gtk/gtksearchenginemodel.h
Normal file
@ -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__ */
|
Loading…
Reference in New Issue
Block a user