diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index 2bba90235a..2159607032 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -6127,13 +6127,12 @@ search_engine_hits_added_cb (GtkSearchEngine *engine, { GList *l, *files; GFile *file; - const char *uri; files = NULL; for (l = hits; l; l = l->next) { - uri = (const gchar *)l->data; - file = g_file_new_for_uri (uri); + GtkSearchHit *hit = (GtkSearchHit *)l->data; + file = g_file_new_for_uri (hit->uri); if (!file) continue; files = g_list_prepend (files, file); diff --git a/gtk/gtksearchengine.c b/gtk/gtksearchengine.c index 519df726c5..5e8a19c1de 100644 --- a/gtk/gtksearchengine.c +++ b/gtk/gtksearchengine.c @@ -190,16 +190,17 @@ hits_added (GtkSearchEngine *engine, { GtkSearchEngine *composite = GTK_SEARCH_ENGINE (data); GList *added, *l; + GtkSearchHit *hit; added = NULL; for (l = hits; l; l = l->next) { - gchar *hit = l->data; + hit = l->data; if (!g_hash_table_contains (composite->priv->hits, hit)) { - hit = g_strdup (hit); + hit = _gtk_search_hit_dup (hit); g_hash_table_add (composite->priv->hits, hit); added = g_list_prepend (added, hit); } @@ -272,6 +273,47 @@ error (GtkSearchEngine *engine, update_status (composite); } +static gboolean +search_hit_equal (gconstpointer a, gconstpointer b) +{ + const GtkSearchHit *ha = (const GtkSearchHit *)a; + const GtkSearchHit *hb = (const GtkSearchHit *)b; + + return g_str_equal (ha->uri, hb->uri); +} + + +static guint +search_hit_hash (gconstpointer a) +{ + const GtkSearchHit *ha = (const GtkSearchHit *)a; + + return g_str_hash (ha->uri); +} + +GtkSearchHit * +_gtk_search_hit_dup (GtkSearchHit *hit) +{ + GtkSearchHit *dup; + + dup = g_new (GtkSearchHit, 1); + dup->uri = g_strdup (hit->uri); + if (hit->info) + dup->info = g_object_ref (hit->info); + else + dup->info = NULL; + + return dup; +} + +void +_gtk_search_hit_free (GtkSearchHit *hit) +{ + g_free (hit->uri); + g_clear_object (&hit->info); + g_free (hit); +} + static void connect_engine_signals (GtkSearchEngine *engine, gpointer data) @@ -310,7 +352,8 @@ _gtk_search_engine_new (void) g_debug ("Using simple search engine"); connect_engine_signals (engine->priv->simple, engine); - engine->priv->hits = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + engine->priv->hits = g_hash_table_new_full (search_hit_hash, search_hit_equal, + (GDestroyNotify)_gtk_search_hit_free, NULL); return engine; } diff --git a/gtk/gtksearchengine.h b/gtk/gtksearchengine.h index fc4b6d64ed..8f86cd8e4d 100644 --- a/gtk/gtksearchengine.h +++ b/gtk/gtksearchengine.h @@ -23,6 +23,7 @@ #define __GTK_SEARCH_ENGINE_H__ #include "gtkquery.h" +#include G_BEGIN_DECLS @@ -37,6 +38,15 @@ typedef struct _GtkSearchEngine GtkSearchEngine; typedef struct _GtkSearchEngineClass GtkSearchEngineClass; typedef struct _GtkSearchEnginePrivate GtkSearchEnginePrivate; +typedef struct _GtkSearchHit GtkSearchHit; + +struct _GtkSearchHit +{ + gint ref_count; + gchar *uri; + GFileInfo *info; /* may be NULL */ +}; + struct _GtkSearchEngine { GObject parent; @@ -81,6 +91,9 @@ void _gtk_search_engine_finished (GtkSearchEngine *engine); void _gtk_search_engine_error (GtkSearchEngine *engine, const gchar *error_message); +void _gtk_search_hit_free (GtkSearchHit *hit); +GtkSearchHit *_gtk_search_hit_dup (GtkSearchHit *hit); + G_END_DECLS #endif /* __GTK_SEARCH_ENGINE_H__ */ diff --git a/gtk/gtksearchenginesimple.c b/gtk/gtksearchenginesimple.c index 596673b591..3b1381cd03 100644 --- a/gtk/gtksearchenginesimple.c +++ b/gtk/gtksearchenginesimple.c @@ -137,20 +137,20 @@ search_thread_done_idle (gpointer user_data) typedef struct { - GList *uris; + GList *hits; SearchThreadData *thread_data; -} SearchHits; +} Batch; static gboolean search_thread_add_hits_idle (gpointer user_data) { - SearchHits *hits = user_data; + Batch *batch = user_data; - if (!g_cancellable_is_cancelled (hits->thread_data->cancellable)) - _gtk_search_engine_hits_added (GTK_SEARCH_ENGINE (hits->thread_data->engine), hits->uris); + if (!g_cancellable_is_cancelled (batch->thread_data->cancellable)) + _gtk_search_engine_hits_added (GTK_SEARCH_ENGINE (batch->thread_data->engine), batch->hits); - g_list_free_full (hits->uris, g_free); - g_free (hits); + g_list_free_full (batch->hits, (GDestroyNotify)_gtk_search_hit_free); + g_free (batch); return FALSE; } @@ -158,7 +158,7 @@ search_thread_add_hits_idle (gpointer user_data) static void send_batch (SearchThreadData *data) { - SearchHits *hits; + Batch *batch; data->n_processed_files = 0; @@ -166,11 +166,11 @@ send_batch (SearchThreadData *data) { guint id; - hits = g_new (SearchHits, 1); - hits->uris = data->hits; - hits->thread_data = data; + batch = g_new (Batch, 1); + batch->hits = data->hits; + batch->thread_data = data; - id = gdk_threads_add_idle (search_thread_add_hits_idle, hits); + id = gdk_threads_add_idle (search_thread_add_hits_idle, batch); g_source_set_name_by_id (id, "[gtk+] search_thread_add_hits_idle"); } @@ -208,7 +208,14 @@ visit_directory (GFile *dir, SearchThreadData *data) continue; if (gtk_query_matches_string (data->query, display_name)) - data->hits = g_list_prepend (data->hits, g_file_get_uri (child)); + { + GtkSearchHit *hit; + + hit = g_new (GtkSearchHit, 1); + hit->uri = g_file_get_uri (child); + hit->info = g_object_ref (info); + data->hits = g_list_prepend (data->hits, hit); + } data->n_processed_files++; if (data->n_processed_files > BATCH_SIZE) diff --git a/gtk/gtksearchenginetracker.c b/gtk/gtksearchenginetracker.c index cb815b7d55..562b14d646 100644 --- a/gtk/gtksearchenginetracker.c +++ b/gtk/gtksearchenginetracker.c @@ -173,21 +173,6 @@ get_query_results (GtkSearchEngineTracker *engine, user_data); } -/* Stolen from libtracker-common */ -static GList * -string_list_to_gslist (gchar **strv) -{ - GList *list; - gsize i; - - list = NULL; - - for (i = 0; strv[i]; i++) - list = g_list_prepend (list, g_strdup (strv[i])); - - return g_list_reverse (list); -} - /* Stolen from libtracker-sparql */ static gchar * sparql_escape_string (const gchar *literal) @@ -283,9 +268,9 @@ query_callback (GObject *object, GVariant *reply; GVariant *r; GVariantIter iter; - gchar **result; GError *error = NULL; gint i, n; + GtkSearchHit *hit; tracker = GTK_SEARCH_ENGINE_TRACKER (user_data); @@ -310,7 +295,8 @@ query_callback (GObject *object, r = g_variant_get_child_value (reply, 0); g_variant_iter_init (&iter, r); n = g_variant_iter_n_children (&iter); - result = g_new0 (gchar *, n + 1); + hit = g_new (GtkSearchHit, n); + hits = NULL; for (i = 0; i < n; i++) { GVariant *v; @@ -318,16 +304,16 @@ query_callback (GObject *object, v = g_variant_iter_next_value (&iter); strv = g_variant_get_strv (v, NULL); - result[i] = (gchar*)strv[0]; + hit[i].uri = (gchar*)strv[0]; + hit[i].info = NULL; g_free (strv); + hits = g_list_prepend (hits, &hit[i]); } - /* We iterate result by result, not n at a time. */ - hits = string_list_to_gslist (result); _gtk_search_engine_hits_added (GTK_SEARCH_ENGINE (tracker), hits); _gtk_search_engine_finished (GTK_SEARCH_ENGINE (tracker)); g_list_free (hits); - g_free (result); + g_free (hit); g_variant_unref (reply); g_variant_unref (r);