[nautilus] Collect results from both search providers



commit 79869fd920fcc70a901044c7ee362038ea42b27a
Author: William Jon McCann <jmccann redhat com>
Date:   Tue Jul 17 18:09:04 2012 -0400

    Collect results from both search providers
    
    Previously we would only use the compiled in search provider. Now
    it has been changed to run both providers at the same time and
    merge the results by URI.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=680137

 libnautilus-private/Makefile.am                    |    2 +
 libnautilus-private/nautilus-debug.c               |    1 +
 libnautilus-private/nautilus-debug.h               |    1 +
 libnautilus-private/nautilus-search-directory.c    |   11 +-
 .../nautilus-search-engine-simple.c                |   47 ++--
 .../nautilus-search-engine-simple.h                |    6 +-
 .../nautilus-search-engine-tracker.c               |   60 +++---
 .../nautilus-search-engine-tracker.h               |    6 +-
 libnautilus-private/nautilus-search-engine.c       |  267 +++++++++++++-------
 libnautilus-private/nautilus-search-engine.h       |   22 --
 libnautilus-private/nautilus-search-provider.c     |  170 +++++++++++++
 libnautilus-private/nautilus-search-provider.h     |   68 +++++
 test/test-nautilus-search-engine.c                 |    5 +-
 13 files changed, 485 insertions(+), 181 deletions(-)
---
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am
index 28719cd..ee613e0 100644
--- a/libnautilus-private/Makefile.am
+++ b/libnautilus-private/Makefile.am
@@ -156,6 +156,8 @@ libnautilus_private_la_SOURCES = \
 	nautilus-search-directory.h \
 	nautilus-search-directory-file.c \
 	nautilus-search-directory-file.h \
+	nautilus-search-provider.c \
+	nautilus-search-provider.h \
 	nautilus-search-engine.c \
 	nautilus-search-engine.h \
 	nautilus-search-engine-simple.c \
diff --git a/libnautilus-private/nautilus-debug.c b/libnautilus-private/nautilus-debug.c
index b6ac673..a514431 100644
--- a/libnautilus-private/nautilus-debug.c
+++ b/libnautilus-private/nautilus-debug.c
@@ -48,6 +48,7 @@ static GDebugKey keys[] = {
   { "Mime", NAUTILUS_DEBUG_MIME },
   { "Places", NAUTILUS_DEBUG_PLACES },
   { "Previewer", NAUTILUS_DEBUG_PREVIEWER },
+  { "Search", NAUTILUS_DEBUG_SEARCH },
   { "Smclient", NAUTILUS_DEBUG_SMCLIENT },
   { "Window", NAUTILUS_DEBUG_WINDOW },
   { "Undo", NAUTILUS_DEBUG_UNDO },
diff --git a/libnautilus-private/nautilus-debug.h b/libnautilus-private/nautilus-debug.h
index ea2e1d1..8eb8693 100644
--- a/libnautilus-private/nautilus-debug.h
+++ b/libnautilus-private/nautilus-debug.h
@@ -47,6 +47,7 @@ typedef enum {
   NAUTILUS_DEBUG_SMCLIENT = 1 << 12,
   NAUTILUS_DEBUG_WINDOW = 1 << 13,
   NAUTILUS_DEBUG_UNDO = 1 << 14,
+  NAUTILUS_DEBUG_SEARCH = 1 << 15,
 } DebugFlags;
 
 void nautilus_debug_set_flags (DebugFlags flags);
diff --git a/libnautilus-private/nautilus-search-directory.c b/libnautilus-private/nautilus-search-directory.c
index 59d4bba..bb82337 100644
--- a/libnautilus-private/nautilus-search-directory.c
+++ b/libnautilus-private/nautilus-search-directory.c
@@ -28,6 +28,7 @@
 #include "nautilus-file.h"
 #include "nautilus-file-private.h"
 #include "nautilus-file-utilities.h"
+#include "nautilus-search-provider.h"
 #include "nautilus-search-engine.h"
 #include <eel/eel-glib-extensions.h>
 #include <gtk/gtk.h>
@@ -139,17 +140,17 @@ start_or_stop_search_engine (NautilusSearchDirectory *search, gboolean adding)
 		search->details->search_running = TRUE;
 		search->details->search_finished = FALSE;
 		ensure_search_engine (search);
-		nautilus_search_engine_set_query (search->details->engine, search->details->query);
+		nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (search->details->engine), search->details->query);
 
 		reset_file_list (search);
 
-		nautilus_search_engine_start (search->details->engine);
+		nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (search->details->engine));
 	} else if (!adding && (!search->details->monitor_list ||
 		   !search->details->pending_callback_list) &&
 		   search->details->engine &&
 		   search->details->search_running) {
 		search->details->search_running = FALSE;
-		nautilus_search_engine_stop (search->details->engine);
+		nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (search->details->engine));
 
 		reset_file_list (search);
 	}
@@ -603,7 +604,7 @@ search_force_reload (NautilusDirectory *directory)
 	reset_file_list (search);
 	
 	if (search->details->search_running) {
-		nautilus_search_engine_stop (search->details->engine);
+		nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (search->details->engine));
 		search->details->search_running = FALSE;
 	}
 }
@@ -690,7 +691,7 @@ search_dispose (GObject *object)
 
 	if (search->details->engine) {
 		if (search->details->search_running) {
-			nautilus_search_engine_stop (search->details->engine);
+			nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (search->details->engine));
 		}
 		
 		g_object_unref (search->details->engine);
diff --git a/libnautilus-private/nautilus-search-engine-simple.c b/libnautilus-private/nautilus-search-engine-simple.c
index dd1e6c4..4ce6e99 100644
--- a/libnautilus-private/nautilus-search-engine-simple.c
+++ b/libnautilus-private/nautilus-search-engine-simple.c
@@ -22,6 +22,7 @@
  */
 
 #include <config.h>
+#include "nautilus-search-provider.h"
 #include "nautilus-search-engine-simple.h"
 
 #include <string.h>
@@ -55,8 +56,13 @@ struct NautilusSearchEngineSimpleDetails {
 	gboolean query_finished;
 };
 
-G_DEFINE_TYPE (NautilusSearchEngineSimple, nautilus_search_engine_simple,
-	       NAUTILUS_TYPE_SEARCH_ENGINE);
+static void nautilus_search_provider_init (NautilusSearchProviderIface  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NautilusSearchEngineSimple,
+			 nautilus_search_engine_simple,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SEARCH_PROVIDER,
+						nautilus_search_provider_init))
 
 static void
 finalize (GObject *object)
@@ -134,7 +140,7 @@ search_thread_done_idle (gpointer user_data)
 	data = user_data;
 
 	if (!g_cancellable_is_cancelled (data->cancellable)) {
-		nautilus_search_engine_finished (NAUTILUS_SEARCH_ENGINE (data->engine));
+		nautilus_search_provider_finished (NAUTILUS_SEARCH_PROVIDER (data->engine));
 		data->engine->details->active_search = NULL;
 	}
 	
@@ -157,8 +163,8 @@ search_thread_add_hits_idle (gpointer user_data)
 	hits = user_data;
 
 	if (!g_cancellable_is_cancelled (hits->thread_data->cancellable)) {
-		nautilus_search_engine_hits_added (NAUTILUS_SEARCH_ENGINE (hits->thread_data->engine),
-						   hits->uris);
+		nautilus_search_provider_hits_added (NAUTILUS_SEARCH_PROVIDER (hits->thread_data->engine),
+						     hits->uris);
 	}
 
 	g_list_free_full (hits->uris, g_free);
@@ -323,13 +329,13 @@ search_thread_func (gpointer user_data)
 }
 
 static void
-nautilus_search_engine_simple_start (NautilusSearchEngine *engine)
+nautilus_search_engine_simple_start (NautilusSearchProvider *provider)
 {
 	NautilusSearchEngineSimple *simple;
 	SearchThreadData *data;
 	GThread *thread;
 	
-	simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (engine);
+	simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (provider);
 
 	if (simple->details->active_search != NULL) {
 		return;
@@ -348,11 +354,11 @@ nautilus_search_engine_simple_start (NautilusSearchEngine *engine)
 }
 
 static void
-nautilus_search_engine_simple_stop (NautilusSearchEngine *engine)
+nautilus_search_engine_simple_stop (NautilusSearchProvider *provider)
 {
 	NautilusSearchEngineSimple *simple;
 
-	simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (engine);
+	simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (provider);
 
 	if (simple->details->active_search != NULL) {
 		g_cancellable_cancel (simple->details->active_search->cancellable);
@@ -361,11 +367,12 @@ nautilus_search_engine_simple_stop (NautilusSearchEngine *engine)
 }
 
 static void
-nautilus_search_engine_simple_set_query (NautilusSearchEngine *engine, NautilusQuery *query)
+nautilus_search_engine_simple_set_query (NautilusSearchProvider *provider,
+					 NautilusQuery          *query)
 {
 	NautilusSearchEngineSimple *simple;
 
-	simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (engine);
+	simple = NAUTILUS_SEARCH_ENGINE_SIMPLE (provider);
 
 	if (query) {
 		g_object_ref (query);
@@ -379,19 +386,21 @@ nautilus_search_engine_simple_set_query (NautilusSearchEngine *engine, NautilusQ
 }
 
 static void
+nautilus_search_provider_init (NautilusSearchProviderIface *iface)
+{
+	iface->set_query = nautilus_search_engine_simple_set_query;
+	iface->start = nautilus_search_engine_simple_start;
+	iface->stop = nautilus_search_engine_simple_stop;
+}
+
+static void
 nautilus_search_engine_simple_class_init (NautilusSearchEngineSimpleClass *class)
 {
 	GObjectClass *gobject_class;
-	NautilusSearchEngineClass *engine_class;
 
 	gobject_class = G_OBJECT_CLASS (class);
 	gobject_class->finalize = finalize;
 
-	engine_class = NAUTILUS_SEARCH_ENGINE_CLASS (class);
-	engine_class->set_query = nautilus_search_engine_simple_set_query;
-	engine_class->start = nautilus_search_engine_simple_start;
-	engine_class->stop = nautilus_search_engine_simple_stop;
-
 	g_type_class_add_private (class, sizeof (NautilusSearchEngineSimpleDetails));
 }
 
@@ -402,10 +411,10 @@ nautilus_search_engine_simple_init (NautilusSearchEngineSimple *engine)
 						       NautilusSearchEngineSimpleDetails);
 }
 
-NautilusSearchEngine *
+NautilusSearchEngineSimple *
 nautilus_search_engine_simple_new (void)
 {
-	NautilusSearchEngine *engine;
+	NautilusSearchEngineSimple *engine;
 
 	engine = g_object_new (NAUTILUS_TYPE_SEARCH_ENGINE_SIMPLE, NULL);
 
diff --git a/libnautilus-private/nautilus-search-engine-simple.h b/libnautilus-private/nautilus-search-engine-simple.h
index be7bfb1..bd11197 100644
--- a/libnautilus-private/nautilus-search-engine-simple.h
+++ b/libnautilus-private/nautilus-search-engine-simple.h
@@ -36,16 +36,16 @@
 typedef struct NautilusSearchEngineSimpleDetails NautilusSearchEngineSimpleDetails;
 
 typedef struct NautilusSearchEngineSimple {
-	NautilusSearchEngine parent;
+	GObject parent;
 	NautilusSearchEngineSimpleDetails *details;
 } NautilusSearchEngineSimple;
 
 typedef struct {
-	NautilusSearchEngineClass parent_class;
+	GObjectClass parent_class;
 } NautilusSearchEngineSimpleClass;
 
 GType          nautilus_search_engine_simple_get_type  (void);
 
-NautilusSearchEngine* nautilus_search_engine_simple_new       (void);
+NautilusSearchEngineSimple* nautilus_search_engine_simple_new       (void);
 
 #endif /* NAUTILUS_SEARCH_ENGINE_SIMPLE_H */
diff --git a/libnautilus-private/nautilus-search-engine-tracker.c b/libnautilus-private/nautilus-search-engine-tracker.c
index 49bffb3..fc9c5ec 100644
--- a/libnautilus-private/nautilus-search-engine-tracker.c
+++ b/libnautilus-private/nautilus-search-engine-tracker.c
@@ -22,6 +22,7 @@
  */
 
 #include <config.h>
+#include "nautilus-search-provider.h"
 #include "nautilus-search-engine-tracker.h"
 #include <string.h>
 #include <gio/gio.h>
@@ -36,9 +37,13 @@ struct NautilusSearchEngineTrackerDetails {
 	GCancellable  *cancellable;
 };
 
-G_DEFINE_TYPE (NautilusSearchEngineTracker,
-	       nautilus_search_engine_tracker,
-	       NAUTILUS_TYPE_SEARCH_ENGINE);
+static void nautilus_search_provider_init (NautilusSearchProviderIface  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NautilusSearchEngineTracker,
+			 nautilus_search_engine_tracker,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SEARCH_PROVIDER,
+						nautilus_search_provider_init))
 
 static void
 finalize (GObject *object)
@@ -89,19 +94,14 @@ cursor_callback (GObject      *object,
 	success = tracker_sparql_cursor_next_finish (cursor, result, &error);
 
 	if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-		tracker->details->query_pending = FALSE;
-		nautilus_search_engine_error (NAUTILUS_SEARCH_ENGINE (tracker), error->message);
-		g_error_free (error);
-		g_object_unref (cursor);
-
-		return;
+		nautilus_search_provider_error (NAUTILUS_SEARCH_PROVIDER (tracker), error->message);
 	}
 
 	g_clear_error (&error);
 
 	if (!success) {
 		tracker->details->query_pending = FALSE;
-		nautilus_search_engine_finished (NAUTILUS_SEARCH_ENGINE (tracker));
+		nautilus_search_provider_finished (NAUTILUS_SEARCH_PROVIDER (tracker));
 		g_object_unref (cursor);
 
 		return;
@@ -109,7 +109,7 @@ cursor_callback (GObject      *object,
 
 	/* We iterate result by result, not n at a time. */
 	hits = g_list_append (NULL, (gchar*) tracker_sparql_cursor_get_string (cursor, 0, NULL));
-	nautilus_search_engine_hits_added (NAUTILUS_SEARCH_ENGINE (tracker), hits);
+	nautilus_search_provider_hits_added (NAUTILUS_SEARCH_PROVIDER (tracker), hits);
 	g_list_free (hits);
 
 	/* Get next */
@@ -134,17 +134,14 @@ query_callback (GObject      *object,
 	                                                 &error);
 
 	if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-		tracker->details->query_pending = FALSE;
-		nautilus_search_engine_error (NAUTILUS_SEARCH_ENGINE (tracker), error->message);
-		g_error_free (error);
-		return;
+		nautilus_search_provider_error (NAUTILUS_SEARCH_PROVIDER (tracker), error->message);
 	}
 
 	g_clear_error (&error);
 
 	if (!cursor) {
 		tracker->details->query_pending = FALSE;
-		nautilus_search_engine_finished (NAUTILUS_SEARCH_ENGINE (tracker));
+		nautilus_search_provider_finished (NAUTILUS_SEARCH_PROVIDER (tracker));
 		return;
 	}
 
@@ -152,7 +149,7 @@ query_callback (GObject      *object,
 }
 
 static void
-nautilus_search_engine_tracker_start (NautilusSearchEngine *engine)
+nautilus_search_engine_tracker_start (NautilusSearchProvider *provider)
 {
 	NautilusSearchEngineTracker *tracker;
 	gchar	*query_text, *search_text, *location_uri, *downcase;
@@ -160,7 +157,7 @@ nautilus_search_engine_tracker_start (NautilusSearchEngine *engine)
 	GList *mimetypes, *l;
 	gint mime_count;
 
-	tracker = NAUTILUS_SEARCH_ENGINE_TRACKER (engine);
+	tracker = NAUTILUS_SEARCH_ENGINE_TRACKER (provider);
 
 	if (tracker->details->query_pending) {
 		return;
@@ -232,11 +229,11 @@ nautilus_search_engine_tracker_start (NautilusSearchEngine *engine)
 }
 
 static void
-nautilus_search_engine_tracker_stop (NautilusSearchEngine *engine)
+nautilus_search_engine_tracker_stop (NautilusSearchProvider *provider)
 {
 	NautilusSearchEngineTracker *tracker;
 
-	tracker = NAUTILUS_SEARCH_ENGINE_TRACKER (engine);
+	tracker = NAUTILUS_SEARCH_ENGINE_TRACKER (provider);
 	
 	if (tracker->details->query && tracker->details->query_pending) {
 		g_cancellable_cancel (tracker->details->cancellable);
@@ -246,11 +243,12 @@ nautilus_search_engine_tracker_stop (NautilusSearchEngine *engine)
 }
 
 static void
-nautilus_search_engine_tracker_set_query (NautilusSearchEngine *engine, NautilusQuery *query)
+nautilus_search_engine_tracker_set_query (NautilusSearchProvider *provider,
+					  NautilusQuery *query)
 {
 	NautilusSearchEngineTracker *tracker;
 
-	tracker = NAUTILUS_SEARCH_ENGINE_TRACKER (engine);
+	tracker = NAUTILUS_SEARCH_ENGINE_TRACKER (provider);
 
 	if (query) {
 		g_object_ref (query);
@@ -264,19 +262,21 @@ nautilus_search_engine_tracker_set_query (NautilusSearchEngine *engine, Nautilus
 }
 
 static void
+nautilus_search_provider_init (NautilusSearchProviderIface *iface)
+{
+	iface->set_query = nautilus_search_engine_tracker_set_query;
+	iface->start = nautilus_search_engine_tracker_start;
+	iface->stop = nautilus_search_engine_tracker_stop;
+}
+
+static void
 nautilus_search_engine_tracker_class_init (NautilusSearchEngineTrackerClass *class)
 {
 	GObjectClass *gobject_class;
-	NautilusSearchEngineClass *engine_class;
 
 	gobject_class = G_OBJECT_CLASS (class);
 	gobject_class->finalize = finalize;
 
-	engine_class = NAUTILUS_SEARCH_ENGINE_CLASS (class);
-	engine_class->set_query = nautilus_search_engine_tracker_set_query;
-	engine_class->start = nautilus_search_engine_tracker_start;
-	engine_class->stop = nautilus_search_engine_tracker_stop;
-
 	g_type_class_add_private (class, sizeof (NautilusSearchEngineTrackerDetails));
 }
 
@@ -288,7 +288,7 @@ nautilus_search_engine_tracker_init (NautilusSearchEngineTracker *engine)
 }
 
 
-NautilusSearchEngine *
+NautilusSearchEngineTracker *
 nautilus_search_engine_tracker_new (void)
 {
 	NautilusSearchEngineTracker *engine;
@@ -306,5 +306,5 @@ nautilus_search_engine_tracker_new (void)
 	engine = g_object_new (NAUTILUS_TYPE_SEARCH_ENGINE_TRACKER, NULL);
 	engine->details->connection = connection;
 
-	return NAUTILUS_SEARCH_ENGINE (engine);
+	return engine;
 }
diff --git a/libnautilus-private/nautilus-search-engine-tracker.h b/libnautilus-private/nautilus-search-engine-tracker.h
index 7c6dc33..a7db293 100644
--- a/libnautilus-private/nautilus-search-engine-tracker.h
+++ b/libnautilus-private/nautilus-search-engine-tracker.h
@@ -36,16 +36,16 @@
 typedef struct NautilusSearchEngineTrackerDetails NautilusSearchEngineTrackerDetails;
 
 typedef struct NautilusSearchEngineTracker {
-	NautilusSearchEngine parent;
+	GObject parent;
 	NautilusSearchEngineTrackerDetails *details;
 } NautilusSearchEngineTracker;
 
 typedef struct {
-	NautilusSearchEngineClass parent_class;
+	GObjectClass parent_class;
 } NautilusSearchEngineTrackerClass;
 
 GType nautilus_search_engine_tracker_get_type (void);
 
-NautilusSearchEngine* nautilus_search_engine_tracker_new (void);
+NautilusSearchEngineTracker* nautilus_search_engine_tracker_new (void);
 
 #endif /* NAUTILUS_SEARCH_ENGINE_TRACKER_H */
diff --git a/libnautilus-private/nautilus-search-engine.c b/libnautilus-private/nautilus-search-engine.c
index 1ff24c8..946a863 100644
--- a/libnautilus-private/nautilus-search-engine.c
+++ b/libnautilus-private/nautilus-search-engine.c
@@ -22,149 +22,222 @@
  */
 
 #include <config.h>
+
+#include <glib/gi18n.h>
+#include "nautilus-search-provider.h"
 #include "nautilus-search-engine.h"
 #include "nautilus-search-engine-simple.h"
+#define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH
+#include "nautilus-debug.h"
 
 #ifdef ENABLE_TRACKER
 #include "nautilus-search-engine-tracker.h"
 #endif
 
-enum {
-	HITS_ADDED,
-	HITS_SUBTRACTED,
-	FINISHED,
-	ERROR,
-	LAST_SIGNAL
-}; 
+struct NautilusSearchEngineDetails
+{
+	NautilusSearchEngineSimple *simple;
+#ifdef ENABLE_TRACKER
+	NautilusSearchEngineTracker *tracker;
+#endif
+	GHashTable *uris;
+	guint num_providers;
+	guint providers_finished;
+	guint providers_error;
+};
 
-static guint signals[LAST_SIGNAL];
+static void nautilus_search_provider_init (NautilusSearchProviderIface  *iface);
 
-G_DEFINE_ABSTRACT_TYPE (NautilusSearchEngine, nautilus_search_engine,
-			G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_CODE (NautilusSearchEngine,
+			 nautilus_search_engine,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SEARCH_PROVIDER,
+						nautilus_search_provider_init))
 
 static void
-nautilus_search_engine_class_init (NautilusSearchEngineClass *class)
+nautilus_search_engine_set_query (NautilusSearchProvider *provider,
+				  NautilusQuery          *query)
 {
-	signals[HITS_ADDED] =
-		g_signal_new ("hits-added",
-		              G_TYPE_FROM_CLASS (class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NautilusSearchEngineClass, hits_added),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__POINTER,
-		              G_TYPE_NONE, 1,
-			      G_TYPE_POINTER);
-
-	signals[HITS_SUBTRACTED] =
-		g_signal_new ("hits-subtracted",
-		              G_TYPE_FROM_CLASS (class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NautilusSearchEngineClass, hits_subtracted),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__POINTER,
-		              G_TYPE_NONE, 1,
-			      G_TYPE_POINTER);
-
-	signals[FINISHED] =
-		g_signal_new ("finished",
-		              G_TYPE_FROM_CLASS (class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NautilusSearchEngineClass, finished),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__VOID,
-		              G_TYPE_NONE, 0);
-	
-	signals[ERROR] =
-		g_signal_new ("error",
-		              G_TYPE_FROM_CLASS (class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NautilusSearchEngineClass, error),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__STRING,
-		              G_TYPE_NONE, 1,
-			      G_TYPE_STRING);
-
+	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (provider);
+#ifdef ENABLE_TRACKER
+	nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (engine->details->tracker), query);
+#endif
+	nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (engine->details->simple), query);
 }
 
 static void
-nautilus_search_engine_init (NautilusSearchEngine *engine)
+nautilus_search_engine_start (NautilusSearchProvider *provider)
 {
+	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (provider);
+	engine->details->providers_finished = 0;
+	engine->details->providers_error = 0;
+#ifdef ENABLE_TRACKER
+	nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (engine->details->tracker));
+#endif
+	nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (engine->details->simple));
 }
 
-NautilusSearchEngine *
-nautilus_search_engine_new (void)
+static void
+nautilus_search_engine_stop (NautilusSearchProvider *provider)
 {
-	NautilusSearchEngine *engine;
-	
-#ifdef ENABLE_TRACKER	
-	engine = nautilus_search_engine_tracker_new ();
-	if (engine) {
-		return engine;
-	}
+	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (provider);
+#ifdef ENABLE_TRACKER
+	nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (engine->details->tracker));
 #endif
-	
-	engine = nautilus_search_engine_simple_new ();
-	return engine;
+	nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (engine->details->simple));
 }
 
-void
-nautilus_search_engine_set_query (NautilusSearchEngine *engine, NautilusQuery *query)
+static void
+search_provider_hits_added (NautilusSearchProvider *provider,
+			    GList                  *hits,
+			    NautilusSearchEngine   *engine)
 {
-	g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine));
-	g_return_if_fail (NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->set_query != NULL);
-
-	NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->set_query (engine, query);
+	GList *added = NULL;
+	GList *l;
+
+	for (l = hits; l != NULL; l = l->next) {
+		char *uri = l->data;
+		int count;
+		count = GPOINTER_TO_INT (g_hash_table_lookup (engine->details->uris, uri));
+		if (count == 0)
+			added = g_list_prepend (added, uri);
+		g_hash_table_replace (engine->details->uris, g_strdup (uri), GINT_TO_POINTER (count++));
+	}
+	if (added != NULL) {
+		nautilus_search_provider_hits_added (NAUTILUS_SEARCH_PROVIDER (engine), g_list_reverse (added));
+		g_list_free (added);
+	}
 }
 
-void
-nautilus_search_engine_start (NautilusSearchEngine *engine)
+static void
+search_provider_hits_subtracted (NautilusSearchProvider *provider,
+				 GList                  *hits,
+				 NautilusSearchEngine   *engine)
 {
-	g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine));
-	g_return_if_fail (NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->start != NULL);
-
-	NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->start (engine);
+	GList *removed = NULL;
+	GList *l;
+
+	for (l = hits; l != NULL; l = l->next) {
+		char *uri = l->data;
+		int count;
+		count = GPOINTER_TO_INT (g_hash_table_lookup (engine->details->uris, uri));
+		g_assert (count > 0);
+		if (count == 1) {
+			removed = g_list_prepend (removed, uri);
+			g_hash_table_remove (engine->details->uris, uri);
+		} else {
+			g_hash_table_replace (engine->details->uris, g_strdup (uri), GINT_TO_POINTER (count--));
+		}
+	}
+	if (removed != NULL) {
+		nautilus_search_provider_hits_subtracted (NAUTILUS_SEARCH_PROVIDER (engine), g_list_reverse (removed));
+		g_list_free (removed);
+	}
 }
 
+static void
+search_provider_error (NautilusSearchProvider *provider,
+		       const char             *error_message,
+		       NautilusSearchEngine   *engine)
 
-void
-nautilus_search_engine_stop (NautilusSearchEngine *engine)
 {
-	g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine));
-	g_return_if_fail (NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->stop != NULL);
-
-	NAUTILUS_SEARCH_ENGINE_GET_CLASS (engine)->stop (engine);
+	DEBUG ("Search provider error: %s", error_message);
+	engine->details->providers_error++;
+	if (engine->details->providers_error == engine->details->num_providers) {
+		nautilus_search_provider_error (NAUTILUS_SEARCH_PROVIDER (engine),
+						_("Unable to complete the requested search"));
+	}
 }
 
-void	       
-nautilus_search_engine_hits_added (NautilusSearchEngine *engine, GList *hits)
+static void
+search_provider_finished (NautilusSearchProvider *provider,
+			  NautilusSearchEngine   *engine)
+
 {
-	g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine));
+	engine->details->providers_finished++;
+	if (engine->details->providers_finished == engine->details->num_providers)
+		nautilus_search_provider_finished (NAUTILUS_SEARCH_PROVIDER (engine));
+}
 
-	g_signal_emit (engine, signals[HITS_ADDED], 0, hits);
+static void
+connect_provider_signals (NautilusSearchEngine   *engine,
+			  NautilusSearchProvider *provider)
+{
+	g_signal_connect (provider, "hits-added",
+			  G_CALLBACK (search_provider_hits_added),
+			  engine);
+	g_signal_connect (provider, "hits-subtracted",
+			  G_CALLBACK (search_provider_hits_subtracted),
+			  engine);
+	g_signal_connect (provider, "finished",
+			  G_CALLBACK (search_provider_finished),
+			  engine);
+	g_signal_connect (provider, "error",
+			  G_CALLBACK (search_provider_error),
+			  engine);
 }
 
+static void
+nautilus_search_provider_init (NautilusSearchProviderIface *iface)
+{
+	iface->set_query = nautilus_search_engine_set_query;
+	iface->start = nautilus_search_engine_start;
+	iface->stop = nautilus_search_engine_stop;
+}
 
-void	       
-nautilus_search_engine_hits_subtracted (NautilusSearchEngine *engine, GList *hits)
+static void
+nautilus_search_engine_finalize (GObject *object)
 {
-	g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine));
+	NautilusSearchEngine *engine = NAUTILUS_SEARCH_ENGINE (object);
 
-	g_signal_emit (engine, signals[HITS_SUBTRACTED], 0, hits);
+	g_hash_table_destroy (engine->details->uris);
+
+#ifdef ENABLE_TRACKER
+	g_clear_object (&engine->details->tracker);
+#endif
+	g_clear_object (&engine->details->simple);
+
+	G_OBJECT_CLASS (nautilus_search_engine_parent_class)->finalize (object);
 }
 
+static void
+nautilus_search_engine_class_init (NautilusSearchEngineClass *class)
+{
+	GObjectClass *object_class;
+
+	object_class = (GObjectClass *) class;
+
+	object_class->finalize = nautilus_search_engine_finalize;
+
+	g_type_class_add_private (class, sizeof (NautilusSearchEngineDetails));
+}
 
-void	       
-nautilus_search_engine_finished (NautilusSearchEngine *engine)
+static void
+nautilus_search_engine_init (NautilusSearchEngine *engine)
 {
-	g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine));
+	engine->details = G_TYPE_INSTANCE_GET_PRIVATE (engine,
+						       NAUTILUS_TYPE_SEARCH_ENGINE,
+						       NautilusSearchEngineDetails);
 
-	g_signal_emit (engine, signals[FINISHED], 0);
+	engine->details->uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+#ifdef ENABLE_TRACKER
+	engine->details->tracker = nautilus_search_engine_tracker_new ();
+	connect_provider_signals (engine, NAUTILUS_SEARCH_PROVIDER (engine->details->tracker));
+	engine->details->num_providers++;
+#endif
+
+	engine->details->simple = nautilus_search_engine_simple_new ();
+	connect_provider_signals (engine, NAUTILUS_SEARCH_PROVIDER (engine->details->simple));
+	engine->details->num_providers++;
 }
 
-void
-nautilus_search_engine_error (NautilusSearchEngine *engine, const char *error_message)
+NautilusSearchEngine *
+nautilus_search_engine_new (void)
 {
-	g_return_if_fail (NAUTILUS_IS_SEARCH_ENGINE (engine));
+	NautilusSearchEngine *engine;
+
+	engine = g_object_new (NAUTILUS_TYPE_SEARCH_ENGINE, NULL);
 
-	g_signal_emit (engine, signals[ERROR], 0, error_message);
+	return engine;
 }
diff --git a/libnautilus-private/nautilus-search-engine.h b/libnautilus-private/nautilus-search-engine.h
index 35bf9f9..2e802d1 100644
--- a/libnautilus-private/nautilus-search-engine.h
+++ b/libnautilus-private/nautilus-search-engine.h
@@ -25,7 +25,6 @@
 #define NAUTILUS_SEARCH_ENGINE_H
 
 #include <glib-object.h>
-#include <libnautilus-private/nautilus-query.h>
 
 #define NAUTILUS_TYPE_SEARCH_ENGINE		(nautilus_search_engine_get_type ())
 #define NAUTILUS_SEARCH_ENGINE(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_SEARCH_ENGINE, NautilusSearchEngine))
@@ -43,31 +42,10 @@ typedef struct NautilusSearchEngine {
 
 typedef struct {
 	GObjectClass parent_class;
-	
-	/* VTable */
-	void (*set_query) (NautilusSearchEngine *engine, NautilusQuery *query);
-	void (*start) (NautilusSearchEngine *engine);
-	void (*stop) (NautilusSearchEngine *engine);
-
-	/* Signals */
-	void (*hits_added) (NautilusSearchEngine *engine, GList *hits);
-	void (*hits_subtracted) (NautilusSearchEngine *engine, GList *hits);
-	void (*finished) (NautilusSearchEngine *engine);
-	void (*error) (NautilusSearchEngine *engine, const char *error_message);
 } NautilusSearchEngineClass;
 
 GType          nautilus_search_engine_get_type  (void);
-gboolean       nautilus_search_engine_enabled (void);
 
 NautilusSearchEngine* nautilus_search_engine_new       (void);
 
-void           nautilus_search_engine_set_query (NautilusSearchEngine *engine, NautilusQuery *query);
-void	       nautilus_search_engine_start (NautilusSearchEngine *engine);
-void	       nautilus_search_engine_stop (NautilusSearchEngine *engine);
-
-void	       nautilus_search_engine_hits_added (NautilusSearchEngine *engine, GList *hits);
-void	       nautilus_search_engine_hits_subtracted (NautilusSearchEngine *engine, GList *hits);
-void	       nautilus_search_engine_finished (NautilusSearchEngine *engine);
-void	       nautilus_search_engine_error (NautilusSearchEngine *engine, const char *error_message);
-
 #endif /* NAUTILUS_SEARCH_ENGINE_H */
diff --git a/libnautilus-private/nautilus-search-provider.c b/libnautilus-private/nautilus-search-provider.c
new file mode 100644
index 0000000..71fbb57
--- /dev/null
+++ b/libnautilus-private/nautilus-search-provider.c
@@ -0,0 +1,170 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ *  Copyright (C) 2012 Red Hat, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library 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
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <config.h>
+#include "nautilus-search-provider.h"
+
+#include <glib-object.h>
+
+enum {
+       HITS_ADDED,
+       HITS_SUBTRACTED,
+       FINISHED,
+       ERROR,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+static void nautilus_search_provider_base_init (gpointer g_iface);
+
+GType
+nautilus_search_provider_get_type (void)
+{
+	static GType search_provider_type = 0;
+
+	if (!search_provider_type) {
+		const GTypeInfo search_provider_info = {
+			sizeof (NautilusSearchProviderIface), /* class_size */
+			nautilus_search_provider_base_init,   /* base_init */
+			NULL,           /* base_finalize */
+			NULL,
+			NULL,           /* class_finalize */
+			NULL,           /* class_data */
+			0,
+			0,              /* n_preallocs */
+			NULL
+		};
+
+		search_provider_type = g_type_register_static (G_TYPE_INTERFACE,
+							       "NautilusSearchProvider",
+							       &search_provider_info,
+							       0);
+
+		g_type_interface_add_prerequisite (search_provider_type, G_TYPE_OBJECT);
+	}
+
+	return search_provider_type;
+}
+
+static void
+nautilus_search_provider_base_init (gpointer g_iface)
+{
+	static gboolean initialized = FALSE;
+
+	if (initialized) {
+		return;
+	}
+
+	signals[HITS_ADDED] = g_signal_new ("hits-added",
+					    NAUTILUS_TYPE_SEARCH_PROVIDER,
+					    G_SIGNAL_RUN_LAST,
+					    G_STRUCT_OFFSET (NautilusSearchProviderIface, hits_added),
+					    NULL, NULL,
+					    g_cclosure_marshal_VOID__POINTER,
+					    G_TYPE_NONE, 1,
+					    G_TYPE_POINTER);
+	signals[HITS_SUBTRACTED] = g_signal_new ("hits-subtracted",
+						 NAUTILUS_TYPE_SEARCH_PROVIDER,
+						 G_SIGNAL_RUN_LAST,
+						 G_STRUCT_OFFSET (NautilusSearchProviderIface, hits_subtracted),
+						 NULL, NULL,
+						 g_cclosure_marshal_VOID__POINTER,
+						 G_TYPE_NONE, 1,
+						 G_TYPE_POINTER);
+
+	signals[FINISHED] = g_signal_new ("finished",
+					  NAUTILUS_TYPE_SEARCH_PROVIDER,
+					  G_SIGNAL_RUN_LAST,
+					  G_STRUCT_OFFSET (NautilusSearchProviderIface, finished),
+					  NULL, NULL,
+					  g_cclosure_marshal_VOID__VOID,
+					  G_TYPE_NONE, 0);
+
+	signals[ERROR] = g_signal_new ("error",
+				       NAUTILUS_TYPE_SEARCH_PROVIDER,
+				       G_SIGNAL_RUN_LAST,
+				       G_STRUCT_OFFSET (NautilusSearchProviderIface, error),
+				       NULL, NULL,
+				       g_cclosure_marshal_VOID__STRING,
+				       G_TYPE_NONE, 1,
+				       G_TYPE_STRING);
+
+	initialized = TRUE;
+}
+
+void
+nautilus_search_provider_set_query (NautilusSearchProvider *provider, NautilusQuery *query)
+{
+	g_return_if_fail (NAUTILUS_IS_SEARCH_PROVIDER (provider));
+	g_return_if_fail (NAUTILUS_SEARCH_PROVIDER_GET_IFACE (provider)->set_query != NULL);
+
+	NAUTILUS_SEARCH_PROVIDER_GET_IFACE (provider)->set_query (provider, query);
+}
+
+void
+nautilus_search_provider_start (NautilusSearchProvider *provider)
+{
+	g_return_if_fail (NAUTILUS_IS_SEARCH_PROVIDER (provider));
+	g_return_if_fail (NAUTILUS_SEARCH_PROVIDER_GET_IFACE (provider)->start != NULL);
+
+	NAUTILUS_SEARCH_PROVIDER_GET_IFACE (provider)->start (provider);
+}
+
+void
+nautilus_search_provider_stop (NautilusSearchProvider *provider)
+{
+	g_return_if_fail (NAUTILUS_IS_SEARCH_PROVIDER (provider));
+	g_return_if_fail (NAUTILUS_SEARCH_PROVIDER_GET_IFACE (provider)->stop != NULL);
+
+	NAUTILUS_SEARCH_PROVIDER_GET_IFACE (provider)->stop (provider);
+}
+
+void
+nautilus_search_provider_hits_added (NautilusSearchProvider *provider, GList *hits)
+{
+	g_return_if_fail (NAUTILUS_IS_SEARCH_PROVIDER (provider));
+
+	g_signal_emit (provider, signals[HITS_ADDED], 0, hits);
+}
+
+void
+nautilus_search_provider_hits_subtracted (NautilusSearchProvider *provider, GList *hits)
+{
+	g_return_if_fail (NAUTILUS_IS_SEARCH_PROVIDER (provider));
+
+	g_signal_emit (provider, signals[HITS_SUBTRACTED], 0, hits);
+}
+
+void
+nautilus_search_provider_finished (NautilusSearchProvider *provider)
+{
+	g_return_if_fail (NAUTILUS_IS_SEARCH_PROVIDER (provider));
+
+	g_signal_emit (provider, signals[FINISHED], 0);
+}
+
+void
+nautilus_search_provider_error (NautilusSearchProvider *provider, const char *error_message)
+{
+	g_return_if_fail (NAUTILUS_IS_SEARCH_PROVIDER (provider));
+
+	g_signal_emit (provider, signals[ERROR], 0, error_message);
+}
diff --git a/libnautilus-private/nautilus-search-provider.h b/libnautilus-private/nautilus-search-provider.h
new file mode 100644
index 0000000..07f2bff
--- /dev/null
+++ b/libnautilus-private/nautilus-search-provider.h
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (C) 2012 Red Hat, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library 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
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef NAUTILUS_SEARCH_PROVIDER_H
+#define NAUTILUS_SEARCH_PROVIDER_H
+
+#include <glib-object.h>
+#include <libnautilus-private/nautilus-query.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_SEARCH_PROVIDER           (nautilus_search_provider_get_type ())
+#define NAUTILUS_SEARCH_PROVIDER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_SEARCH_PROVIDER, NautilusSearchProvider))
+#define NAUTILUS_IS_SEARCH_PROVIDER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_SEARCH_PROVIDER))
+#define NAUTILUS_SEARCH_PROVIDER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_SEARCH_PROVIDER, NautilusSearchProviderIface))
+
+typedef struct _NautilusSearchProvider       NautilusSearchProvider;
+typedef struct _NautilusSearchProviderIface  NautilusSearchProviderIface;
+
+struct _NautilusSearchProviderIface {
+        GTypeInterface g_iface;
+
+        /* VTable */
+        void (*set_query) (NautilusSearchProvider *provider, NautilusQuery *query);
+        void (*start) (NautilusSearchProvider *provider);
+        void (*stop) (NautilusSearchProvider *provider);
+
+        /* Signals */
+        void (*hits_added) (NautilusSearchProvider *provider, GList *hits);
+        void (*hits_subtracted) (NautilusSearchProvider *provider, GList *hits);
+        void (*finished) (NautilusSearchProvider *provider);
+        void (*error) (NautilusSearchProvider *provider, const char *error_message);
+};
+
+GType          nautilus_search_provider_get_type        (void) G_GNUC_CONST;
+
+/* Interface Functions */
+void           nautilus_search_provider_set_query       (NautilusSearchProvider *provider,
+                                                         NautilusQuery *query);
+void           nautilus_search_provider_start           (NautilusSearchProvider *provider);
+void           nautilus_search_provider_stop            (NautilusSearchProvider *provider);
+
+void           nautilus_search_provider_hits_added      (NautilusSearchProvider *provider,
+                                                         GList *hits);
+void           nautilus_search_provider_hits_subtracted (NautilusSearchProvider *provider,
+                                                         GList *hits);
+void           nautilus_search_provider_finished        (NautilusSearchProvider *provider);
+void           nautilus_search_provider_error           (NautilusSearchProvider *provider,
+                                                         const char *error_message);
+
+G_END_DECLS
+
+#endif
diff --git a/test/test-nautilus-search-engine.c b/test/test-nautilus-search-engine.c
index 6dac732..096076b 100644
--- a/test/test-nautilus-search-engine.c
+++ b/test/test-nautilus-search-engine.c
@@ -1,3 +1,4 @@
+#include <libnautilus-private/nautilus-search-provider.h>
 #include <libnautilus-private/nautilus-search-engine.h>
 #include <gtk/gtk.h>
 
@@ -46,10 +47,10 @@ main (int argc, char* argv[])
 
 	query = nautilus_query_new ();
 	nautilus_query_set_text (query, "richard hult");
-	nautilus_search_engine_set_query (engine, query);
+	nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (engine), query);
 	g_object_unref (query);
 
-	nautilus_search_engine_start (engine);
+	nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (engine));
        
 	gtk_main ();
 	return 0;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]