[brasero] Split search widget between the UI itself and the search engine that is now abstracted



commit 551f9348c5e71de70dc5d2f2c3f37abd1b6d397c
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date:   Sun Nov 8 09:25:10 2009 +0100

    Split search widget between the UI itself and the search engine that is now abstracted

 libbrasero-media/Makefile.am  |    3 +-
 src/Makefile.am               |    6 +-
 src/brasero-audio-disc.c      |    2 +-
 src/brasero-mime-filter.c     |  104 ++---
 src/brasero-mime-filter.h     |    6 +-
 src/brasero-project-manager.c |    2 +-
 src/brasero-search-beagle.c   | 1167 +++++++++--------------------------------
 src/brasero-search-beagle.h   |   78 ++--
 src/brasero-search-engine.c   |  360 +++++++++++++
 src/brasero-search-engine.h   |  155 ++++++
 src/brasero-search-entry.c    |   94 +---
 src/brasero-search-entry.h    |    9 +-
 src/brasero-search.c          |  920 ++++++++++++++++-----------------
 13 files changed, 1324 insertions(+), 1582 deletions(-)
---
diff --git a/libbrasero-media/Makefile.am b/libbrasero-media/Makefile.am
index fec2045..e31bd54 100644
--- a/libbrasero-media/Makefile.am
+++ b/libbrasero-media/Makefile.am
@@ -127,7 +127,8 @@ libbrasero_media_la_SOURCES =		\
 	scsi-inquiry.c         \
 	scsi-prevent-allow-medium-removal.c         \
 	scsi-inquiry.h         \
-	brasero-drive-priv.h         
+	brasero-drive-priv.h         \
+	../src/brasero-search-engine.c
 
 # FreeBSD's SCSI CAM interface
 if HAVE_CAM_LIB_H
diff --git a/src/Makefile.am b/src/Makefile.am
index 0e5e63a..8804c53 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -125,7 +125,11 @@ brasero_SOURCES = \
 	brasero-setting.h        \
 	brasero-setting.c        \
 	brasero-search.h        \
-	brasero-search.c
+	brasero-search.c        \
+	brasero-search-beagle.h        \
+	brasero-search-beagle.c        \
+	brasero-search-engine.h        \
+	brasero-search-engine.c
 
 brasero_LDADD =						\
 	$(top_builddir)/libbrasero-media/libbrasero-media.la	\
diff --git a/src/brasero-audio-disc.c b/src/brasero-audio-disc.c
index ac76daf..dd3e7c9 100644
--- a/src/brasero-audio-disc.c
+++ b/src/brasero-audio-disc.c
@@ -1002,7 +1002,7 @@ brasero_audio_disc_add_uri (BraseroDisc *disc,
 	GtkTreePath *treepath = NULL;
 	BraseroAudioDisc *audio_disc;
 	BraseroDiscResult result;
-g_print ("RECEIVED\n");
+
 	audio_disc = BRASERO_AUDIO_DISC (disc);
 	result = brasero_audio_disc_add_uri_real (audio_disc,
 						  uri,
diff --git a/src/brasero-mime-filter.c b/src/brasero-mime-filter.c
index fcb0baf..1b2b16d 100644
--- a/src/brasero-mime-filter.c
+++ b/src/brasero-mime-filter.c
@@ -106,7 +106,7 @@ brasero_mime_filter_init (BraseroMimeFilter * obj)
 	obj->priv = g_new0 (BraseroMimeFilterPrivate, 1);
 
 	store = gtk_list_store_new (BRASERO_MIME_FILTER_NB_COL,
-				    G_TYPE_STRING,
+				    G_TYPE_ICON,
 				    G_TYPE_STRING,
 				    G_TYPE_INT,
 				    G_TYPE_POINTER);
@@ -118,7 +118,7 @@ brasero_mime_filter_init (BraseroMimeFilter * obj)
 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (obj->combo), renderer,
 				    FALSE);
 	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (obj->combo),
-				       renderer, "icon-name",
+				       renderer, "gicon",
 				       BRASERO_MIME_FILTER_ICON_COL);
 
 	renderer = gtk_cell_renderer_text_new ();
@@ -161,50 +161,47 @@ brasero_mime_filter_finalize (GObject * object)
 GtkWidget *
 brasero_mime_filter_new ()
 {
-	BraseroMimeFilter *obj;
-
-	obj =
-	    BRASERO_MIME_FILTER (g_object_new
-				 (BRASERO_TYPE_MIME_FILTER, NULL));
-
-	return GTK_WIDGET (obj);
+	return g_object_new (BRASERO_TYPE_MIME_FILTER, NULL);
 }
 
 void
-brasero_mime_filter_unref_mime (BraseroMimeFilter * filter, char *mime)
+brasero_mime_filter_unref_mime (BraseroMimeFilter * filter, const char *mime)
 {
 	GtkFileFilter *item;
 
 	item = g_hash_table_lookup (filter->priv->table, mime);
+	g_print ("IIII %p %s\n", item, mime);
 	if (item)
 		g_object_unref (item);
 }
 
 static void
-brasero_mime_filter_destroy_item_cb (GtkFileFilter *item,
-				     BraseroMimeFilter *filter)
+brasero_mime_filter_destroy_item_cb (BraseroMimeFilter *filter,
+                                     GtkFileFilter *item,
+                                     gboolean is_last_ref)
 {
 	GtkTreeModel *model;
-	GtkTreeIter row;
 	GtkFileFilter *item2;
+	GtkTreeIter row;
 
 	g_hash_table_remove (filter->priv->table,
 			     gtk_file_filter_get_name (item));
 
 	/* Now we must remove the item from the combo as well */
 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (filter->combo));
-	if (gtk_tree_model_get_iter_first (model, &row) == TRUE) {
-		do {
-			gtk_tree_model_get (model, &row,
-					    BRASERO_MIME_FILTER_FILTER_COL, &item2,
-					    -1);
-
-			if (item == item2) {
-				gtk_list_store_remove (GTK_LIST_STORE (model), &row);
-				break;
-			}
-		} while (gtk_tree_model_iter_next (model, &row) == TRUE);
-	}
+	if (!gtk_tree_model_get_iter_first (model, &row))
+		return;
+
+	do {
+		gtk_tree_model_get (model, &row,
+				    BRASERO_MIME_FILTER_FILTER_COL, &item2,
+				    -1);
+
+		if (item == item2) {
+			gtk_list_store_remove (GTK_LIST_STORE (model), &row);
+			break;
+		}
+	} while (gtk_tree_model_iter_next (model, &row));
 
 	/* we check that the first entry at least is visible */
 	if (gtk_combo_box_get_active (GTK_COMBO_BOX (filter->combo)) == -1
@@ -214,62 +211,43 @@ brasero_mime_filter_destroy_item_cb (GtkFileFilter *item,
 }
 
 void
-brasero_mime_filter_add_mime (BraseroMimeFilter *filter, const gchar *mime)
+brasero_mime_filter_add_mime (BraseroMimeFilter *filter,
+                              const gchar *mime)
 {
 	GtkFileFilter *item;
 
 	item = g_hash_table_lookup (filter->priv->table, mime);
-	if (item == NULL) {
+	if (!item) {
 		GIcon *icon;
 		GtkTreeIter row;
 		GtkTreeModel *model;
 		const gchar *description;
-		const gchar *icon_string = BRASERO_DEFAULT_ICON;
 
 		description = g_content_type_get_description (mime);
-
 		icon = g_content_type_get_icon (mime);
-		if (G_IS_THEMED_ICON (icon)) {
-			const gchar * const *names = NULL;
-
-			names = g_themed_icon_get_names (G_THEMED_ICON (icon));
-			if (names) {
-				gint i;
-				GtkIconTheme *theme;
-
-				theme = gtk_icon_theme_get_default ();
-				for (i = 0; names [i]; i++) {
-					if (gtk_icon_theme_has_icon (theme, names [i])) {
-						icon_string = names [i];
-						break;
-					}
-				}
-			}
-		}
-		
+
 		/* create the GtkFileFilter */
 		item = gtk_file_filter_new ();
 		gtk_file_filter_set_name (item, mime);
 		gtk_file_filter_add_mime_type (item, mime);
-		g_signal_connect (G_OBJECT (item), "destroy",
-				  G_CALLBACK (brasero_mime_filter_destroy_item_cb),
-				  filter);
-
 		g_hash_table_insert (filter->priv->table,
 				     g_strdup (mime),
 				     item);
 
+		g_object_add_toggle_ref (G_OBJECT (item),
+		                         (GToggleNotify) brasero_mime_filter_destroy_item_cb,
+		                         filter);
+
 		model = gtk_combo_box_get_model (GTK_COMBO_BOX (filter->combo));
 		gtk_list_store_append (GTK_LIST_STORE (model), &row);
 
-		g_object_ref (item);
+		g_object_ref_sink (item);
 		gtk_list_store_set (GTK_LIST_STORE (model), &row,
 				    BRASERO_MIME_FILTER_DISPLAY_COL, description,
-				    BRASERO_MIME_FILTER_ICON_COL, icon_string,
+				    BRASERO_MIME_FILTER_ICON_COL, icon,
 				    BRASERO_MIME_FILTER_FILTER_COL, item,
 				    -1);
-		g_object_ref_sink (GTK_OBJECT (item));
-//		g_object_unref (icon);
+		g_object_unref (icon);
 
 		/* we check that the first entry at least is visible */
 		if (gtk_combo_box_get_active (GTK_COMBO_BOX (filter->combo)) == -1
@@ -314,14 +292,13 @@ brasero_mime_filter_add_filter (BraseroMimeFilter *filter,
 }
 
 gboolean
-brasero_mime_filter_filter (BraseroMimeFilter * filter, char *filename,
-			    char *uri, char *display_name, char *mime_type)
+brasero_mime_filter_filter (BraseroMimeFilter * filter, const char *filename,
+			    const char *uri, const char *display_name, const char *mime_type)
 {
 	GtkTreeModel *model;
 	GtkFileFilterInfo info;
 	GtkFileFilter *item;
 	GtkTreeIter row;
-	gboolean result;
 
 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (filter->combo));
 	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (filter->combo), &row) == FALSE)
@@ -333,17 +310,16 @@ brasero_mime_filter_filter (BraseroMimeFilter * filter, char *filename,
 
 	info.contains = gtk_file_filter_get_needed (item);
 	if (info.contains & GTK_FILE_FILTER_FILENAME)
-		info.filename = filename;
+		info.filename = (gchar *) filename;
 
 	if (info.contains & GTK_FILE_FILTER_URI)
-		info.uri = uri;
+		info.uri = (gchar *) uri;
 
 	if (info.contains & GTK_FILE_FILTER_DISPLAY_NAME)
-		info.display_name = display_name;
+		info.display_name = (gchar *) display_name;
 
 	if (info.contains & GTK_FILE_FILTER_MIME_TYPE)
-		info.mime_type = mime_type;
+		info.mime_type =  (gchar *) mime_type;
 
-	result = gtk_file_filter_filter (item, &info);
-	return result;
+	return gtk_file_filter_filter (item, &info);
 }
diff --git a/src/brasero-mime-filter.h b/src/brasero-mime-filter.h
index cdb6b60..7c0bd93 100644
--- a/src/brasero-mime-filter.h
+++ b/src/brasero-mime-filter.h
@@ -66,10 +66,10 @@ void brasero_mime_filter_add_filter (BraseroMimeFilter * filter,
 void brasero_mime_filter_add_mime (BraseroMimeFilter * filter,
 				   const char *mime);
 void brasero_mime_filter_unref_mime (BraseroMimeFilter * filter,
-				     char *mime);
+				     const char *mime);
 gboolean brasero_mime_filter_filter (BraseroMimeFilter * filter,
-				     char *filename, char *uri,
-				     char *display_name, char *mime_type);
+				     const char *filename, const char *uri,
+				     const char *display_name, const char *mime_type);
 
 G_END_DECLS
 
diff --git a/src/brasero-project-manager.c b/src/brasero-project-manager.c
index 3cb9ec9..9dc78d1 100644
--- a/src/brasero-project-manager.c
+++ b/src/brasero-project-manager.c
@@ -51,7 +51,7 @@
 #include "brasero-project-type-chooser.h"
 
 #ifdef BUILD_SEARCH
-#include "brasero-search-beagle.h"
+#include "brasero-search.h"
 #endif
 
 #ifdef BUILD_PLAYLIST
diff --git a/src/brasero-search-beagle.c b/src/brasero-search-beagle.c
index 240ad96..00bf6ae 100644
--- a/src/brasero-search-beagle.c
+++ b/src/brasero-search-beagle.c
@@ -1,41 +1,32 @@
-/***************************************************************************
-*            search.c
-*
-*  dim mai 22 11:20:54 2005
-*  Copyright  2005  Philippe Rouquier
-*  brasero-app wanadoo fr
-****************************************************************************/
-
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
+ * Brasero
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ * 
  *  Brasero is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
- *
- *  Brasero 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 General Public License
- *  along with this program; if not, write to:
+ * 
+ * brasero 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with brasero.  If not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
  */
 
-
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
 
-#ifdef BUILD_SEARCH
-
-#include <string.h>
-
 #include <glib.h>
-#include <glib/gi18n-lib.h>
 #include <glib-object.h>
+#include <glib/gi18n-lib.h>
 
 #include <gio/gio.h>
 
@@ -43,464 +34,204 @@
 
 #include <beagle/beagle.h>
 
-#include "brasero-misc.h"
-
-#include "brasero-app.h"
-#include "brasero-utils.h"
-#include "brasero-search-entry.h"
-#include "brasero-mime-filter.h"
 #include "brasero-search-beagle.h"
-#include "eggtreemultidnd.h"
-
-#include "brasero-uri-container.h"
-#include "brasero-layout-object.h"
+#include "brasero-search-engine.h"
 
 
-struct BraseroSearchPrivate {
+typedef struct _BraseroSearchBeaglePrivate BraseroSearchBeaglePrivate;
+struct _BraseroSearchBeaglePrivate
+{
 	BeagleClient *client;
 	BeagleQuery *query;
 
-	GtkWidget *tree;
-	GtkWidget *entry;
-	GtkWidget *filter;
-	GtkWidget *filters;
-	GtkWidget *right;
-	GtkWidget *left;
-	GtkWidget *results_label;
-
-	GSList *hits;
-	gint hits_num;
-	gint first_hit;
-
-	gint max_results;
-
-	guint id;
-	guint activity;
+	GSList * hits;
 };
 
-static GObjectClass *parent_class = NULL;
-
-enum {
-	TARGET_URIS_LIST,
-};
-
-static GtkTargetEntry ntables_find[] = {
-	{"text/uri-list", 0, TARGET_URIS_LIST}
-};
-static guint nb_ntables_find = sizeof (ntables_find) / sizeof (ntables_find[0]);
-
-enum {
-	BRASERO_SEARCH_TREE_ICON_COL,
-	BRASERO_SEARCH_TREE_TITLE_COL,
-	BRASERO_SEARCH_TREE_DESCRIPTION_COL,
-	BRASERO_SEARCH_TREE_SCORE_COL,
-	BRASERO_SEARCH_TREE_URI_COL,
-	BRASERO_SEARCH_TREE_MIME_COL,
-	BRASERO_SEARCH_TREE_NB_COL
-};
-
-#define BRASERO_SEARCH_SPACING 6
-
-static void brasero_search_iface_uri_container_init (BraseroURIContainerIFace *iface);
-static void brasero_search_iface_layout_object_init (BraseroLayoutObjectIFace *iface);
-
-G_DEFINE_TYPE_WITH_CODE (BraseroSearch,
-			 brasero_search,
-			 GTK_TYPE_VBOX,
-			 G_IMPLEMENT_INTERFACE (BRASERO_TYPE_URI_CONTAINER,
-					        brasero_search_iface_uri_container_init)
-			 G_IMPLEMENT_INTERFACE (BRASERO_TYPE_LAYOUT_OBJECT,
-					        brasero_search_iface_layout_object_init));
+#define BRASERO_SEARCH_BEAGLE_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_SEARCH_BEAGLE, BraseroSearchBeaglePrivate))
 
+static void brasero_search_beagle_init_engine (BraseroSearchEngineIface *iface);
 
+G_DEFINE_TYPE_WITH_CODE (BraseroSearchBeagle,
+			 brasero_search_beagle,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (BRASERO_TYPE_SEARCH_ENGINE,
+					        brasero_search_beagle_init_engine));
 
 static gboolean
-brasero_search_try_again (BraseroSearch *search)
+brasero_search_beagle_is_available (BraseroSearchEngine *engine)
 {
-	search->priv->client = beagle_client_new (NULL);
-	if (!search->priv->client)
+	BraseroSearchBeaglePrivate *priv;
+
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (engine);
+	if (priv->client)
 		return TRUE;
 
-	gtk_widget_set_sensitive (GTK_WIDGET (search), TRUE);
-	search->priv->id = 0;
-	return FALSE;
+	priv->client = beagle_client_new (NULL);
+	return (priv->client != NULL);
 }
 
-static void
-brasero_search_increase_activity (BraseroSearch *search)
+static gint
+brasero_search_beagle_num_hits (BraseroSearchEngine *engine)
 {
-	search->priv->activity ++;
-	if (search->priv->activity == 1) {
-		GdkCursor *cursor;
+	BraseroSearchBeaglePrivate *priv;
 
-		cursor = gdk_cursor_new (GDK_WATCH);
-		gdk_window_set_cursor (GTK_WIDGET (search)->window, cursor);
-		gdk_cursor_unref (cursor);
-	}
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (engine);
+	return g_slist_length (priv->hits);
 }
 
-static void
-brasero_search_decrease_activity (BraseroSearch *search)
+static const gchar *
+brasero_search_beagle_uri_from_hit (BraseroSearchEngine *engine,
+                                     gpointer hit)
 {
-	if (search->priv->activity == 0)
-		return;
-
-	search->priv->activity --;
-	if (!search->priv->activity)
-		gdk_window_set_cursor (GTK_WIDGET (search)->window, NULL);
+	return beagle_hit_get_uri (BEAGLE_HIT (hit));
 }
 
-static void
-brasero_search_update_header (BraseroSearch *search)
+static gchar *
+brasero_search_beagle_name_from_hit (BraseroSearchEngine *engine,
+                                     gpointer hit)
 {
-	gchar *string;
-
-	if (search->priv->hits_num) {
-		gint last;
-		gchar *tmp;
-
-		last = search->priv->first_hit + search->priv->max_results;
-		last = last <= search->priv->hits_num ? last : search->priv->hits_num;
-		tmp = g_strdup_printf (_("Results %iâ??%i (out of %i)"),
-				       search->priv->first_hit + 1,
-				       last,
-				       search->priv->hits_num);
-		string = g_strdup_printf ("<b>%s</b>", tmp);
-		g_free (tmp);
-	}
-	else
-		string = g_strdup_printf ("<b>%s</b>", _("No results"));
+	gchar *name;
+	const gchar *uri;
+	gchar *unescaped_uri;
 
-	gtk_label_set_markup (GTK_LABEL (search->priv->results_label), string);
-	g_free (string);
+	uri = beagle_hit_get_uri (BEAGLE_HIT (hit));
 
-	if (search->priv->first_hit + search->priv->max_results < search->priv->hits_num)
-		gtk_widget_set_sensitive (search->priv->right, TRUE);
-	else
-		gtk_widget_set_sensitive (search->priv->right, FALSE);
+	/* beagle return badly formed uri not
+	 * encoded in UTF-8 locale charset so we
+	 * check them just in case */
+	unescaped_uri = g_uri_unescape_string (uri, NULL);
+	if (!g_utf8_validate (unescaped_uri, -1, NULL)) {
+		g_free (unescaped_uri);
+		return NULL;
+	}
 
-	if (search->priv->first_hit > 0)
-		gtk_widget_set_sensitive (search->priv->left, TRUE);
-	else
-		gtk_widget_set_sensitive (search->priv->left, FALSE);
-}
+	name = g_path_get_basename (unescaped_uri);
+	g_free (unescaped_uri);
 
-static void
-brasero_search_empty_tree (BraseroSearch *search)
-{
-	GtkTreeModel *model;
-	GtkTreeIter row;
-	gchar *mime;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-
-	if (gtk_tree_model_get_iter_first (model, &row) == TRUE) {
-		do {
-			gtk_tree_model_get (model, &row,
-					    BRASERO_SEARCH_TREE_MIME_COL, &mime, 
-					    -1);
-			brasero_mime_filter_unref_mime (BRASERO_MIME_FILTER (search->priv->filter), mime);
-			g_free (mime);
-		} while (gtk_list_store_remove (GTK_LIST_STORE (model), &row) == TRUE);
-	}
+	return name;
 }
 
-/**
- * Start of beagle specific code
- **/
-
-static GSList *
-brasero_search_add_hit_to_tree (BraseroSearch *search,
-				GSList *list,
-				gint max)
+static const gchar *
+brasero_search_beagle_mime_from_hit (BraseroSearchEngine *engine,
+                                     gpointer hit)
 {
-	GtkTreeModel *model;
-	GtkTreeIter row;
-	BeagleHit *hit;
-	GSList *iter;
-	GSList *next;
-
-	gchar *name, *mime; 
-	const gchar *icon_string = BRASERO_DEFAULT_ICON;
-	const gchar *description;
-	GIcon *icon;
-	gint score;
-	gint num;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-
-	num = 0;
-	for (iter = list; iter && num < max; iter = next, num ++) {
-		gchar *unescaped_uri, *uri;
-		GFile *file;
-
-		hit = iter->data;
-		next = iter->next;
-
-		uri = g_strdup (beagle_hit_get_uri (hit));
-
-		/* beagle return badly formed uri not encoded in UTF-8
-		 * locale charset so we check them just in case */
-		unescaped_uri = g_uri_unescape_string (uri, NULL);
-		if (!g_utf8_validate (unescaped_uri, -1, NULL)) {
-			g_free (unescaped_uri);
-			g_free (uri);
-			continue;
-		}
-
-		file = g_file_new_for_uri (uri);
-
-		name = g_path_get_basename (unescaped_uri);
-		g_free (unescaped_uri);
-
-		mime = g_strdup (beagle_hit_get_mime_type (hit));
-		if (!mime) {
-			g_warning ("Strange beagle reports a URI (%s) but cannot tell the mime.\n", uri);
-			g_free (name);
-			g_free (uri);
-			continue;
-		}
-
-		if (!strcmp (mime, "inode/directory")) {
-			g_free (mime);
-			mime = g_strdup ("x-directory/normal");
-		}
-
-		description = g_content_type_get_description (mime);
-
-		icon = g_content_type_get_icon (mime);
-		icon_string = NULL;
-		if (G_IS_THEMED_ICON (icon)) {
-			const gchar * const *names = NULL;
-
-			names = g_themed_icon_get_names (G_THEMED_ICON (icon));
-			if (names) {
-				gint i;
-				GtkIconTheme *theme;
-
-				theme = gtk_icon_theme_get_default ();
-				for (i = 0; names [i]; i++) {
-					if (gtk_icon_theme_has_icon (theme, names [i])) {
-						icon_string = names [i];
-						break;
-					}
-				}
-			}
-		}
-
-		score = (int) (beagle_hit_get_score (hit) * 100);
-
-		gtk_list_store_append (GTK_LIST_STORE (model), &row);
-		gtk_list_store_set (GTK_LIST_STORE (model), &row,
-				    BRASERO_SEARCH_TREE_ICON_COL, icon_string,
-				    BRASERO_SEARCH_TREE_TITLE_COL, name,
-				    BRASERO_SEARCH_TREE_DESCRIPTION_COL, description,
-				    BRASERO_SEARCH_TREE_URI_COL, uri,
-				    BRASERO_SEARCH_TREE_SCORE_COL, score,
-				    BRASERO_SEARCH_TREE_MIME_COL, mime,
-				    -1);
-
-		/* add the mime type to the filter combo */
-		brasero_mime_filter_add_mime (BRASERO_MIME_FILTER (search->priv->filter), mime);
-
-		g_object_unref (icon);
-		g_free (name);
-		g_free (mime);
-		g_free (uri);
-	}
-
-	return iter;
+	return beagle_hit_get_mime_type (BEAGLE_HIT (hit));
 }
 
-static void
-brasero_search_left_button_clicked_cb (GtkButton *button,
-				       BraseroSearch *search)
+static const gchar *
+brasero_search_beagle_description_from_hit (BraseroSearchEngine *engine,
+                                            gpointer hit)
 {
-	GSList *first;
-
-	if (!search->priv->first_hit)
-		return;
-
-	search->priv->first_hit -= search->priv->max_results;
-	if (search->priv->first_hit < 0)
-		search->priv->first_hit = 0;
+	const gchar *mime;
 
-	first = g_slist_nth (search->priv->hits, search->priv->first_hit);
+	mime = beagle_hit_get_mime_type (BEAGLE_HIT (hit));
+	if (!mime)
+		return NULL;
 
-	brasero_search_empty_tree (search);
-	brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
-	brasero_search_update_header (search);
+	return g_content_type_get_description (mime);
 }
 
-static void
-brasero_search_right_button_clicked_cb (GtkButton *button,
-					BraseroSearch *search)
+static int
+brasero_search_beagle_score_from_hit (BraseroSearchEngine *engine,
+                                      gpointer hit)
 {
-	GSList *first;
-
-	if (search->priv->first_hit + search->priv->max_results > search->priv->hits_num)
-		return;
-
-	search->priv->first_hit += search->priv->max_results;
-	first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-
-	brasero_search_empty_tree (search);
-	brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
-	brasero_search_update_header (search);
+	return (int) (beagle_hit_get_score (BEAGLE_HIT (hit)) * 100);
 }
 
-static void
-brasero_search_max_results_num_changed_cb (GtkComboBox *combo,
-					   BraseroSearch *search)
+static GIcon *
+brasero_search_beagle_icon_from_hit (BraseroSearchEngine *engine,
+                                     gpointer hit)
 {
-	gint index;
-
-	index = gtk_combo_box_get_active (combo);
-	switch (index) {
-	case 0:
-		search->priv->max_results = 20;
-		break;
-	case 1:
-		search->priv->max_results = 50;
-		break;
-	case 2:
-		search->priv->max_results = 100;
-		break;
-	}
+	const gchar *mime;
 
-	if (search->priv->hits_num) {
-		GSList *first;
+	mime = beagle_hit_get_mime_type (BEAGLE_HIT (hit));
+	if (!mime)
+		return NULL;
 
-		brasero_search_empty_tree (search);
-		first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-		brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
-	}
+	if (!strcmp (mime, "inode/directory"))
+		mime = "x-directory/normal";
 
-	brasero_search_update_header (search);
+	return g_content_type_get_icon (mime);
 }
 
-static void
-brasero_search_check_for_possible_missing (BraseroSearch *search)
+static gboolean
+brasero_search_beagle_add_hit_to_tree (BraseroSearchEngine *search,
+                                       GtkTreeModel *model,
+                                       gint range_start,
+                                       gint range_end)
 {
-	gint num_missing;
-	gint num_displayed;
-	gint num_remaining;
-	GtkTreeModel *model;
+	BraseroSearchBeaglePrivate *priv;
+	GSList *iter;
+	gint num;
 
-	/* now let's see if we should append new results */
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (search);
 
-	num_displayed = gtk_tree_model_iter_n_children (model, NULL);
-	num_missing = search->priv->max_results - num_displayed;
-	num_remaining = search->priv->hits_num - search->priv->first_hit;
+	num = 0;
+	iter = g_slist_nth (priv->hits, range_start);
 
-	if (num_displayed == num_remaining)
-		return;
+	for (; iter && num < range_end - range_start; iter = iter->next, num ++) {
+		BeagleHit *hit;
+		GtkTreeIter row;
 
-	if (num_missing > 0) {
-		GSList *first;
+		hit = iter->data;
 
-		first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-		brasero_search_add_hit_to_tree (search, first, num_missing);
+		gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &row, -1,
+		                                   BRASERO_SEARCH_TREE_HIT_COL, hit,
+		                                   -1);
 	}
-}
 
-/**
- * Really Beagle specific code
- **/
-
-static gint
-_sort_hits_by_score (BeagleHit *a, BeagleHit *b)
-{
-	gdouble score_a, score_b;
-
-	score_a = beagle_hit_get_score (a);
-	score_b = beagle_hit_get_score (b);
-
-	if (score_b == score_a)
-		return 0;
-
-	if (score_b > score_a);
-		return -1;
-
-	return 1;
+	return TRUE;
 }
 
 static void
 brasero_search_beagle_hit_added_cb (BeagleQuery *query,
 				    BeagleHitsAddedResponse *response,
-				    BraseroSearch *search)
+				    BraseroSearchBeagle *search)
 {
 	GSList *list;
+	GSList *iter;
+	BraseroSearchBeaglePrivate *priv;
+
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (search);
 
 	/* NOTE : list must not be modified nor freed */
 	list = beagle_hits_added_response_get_hits (response);
-	search->priv->hits_num += g_slist_length (list);
-
 	list = g_slist_copy (list);
-	g_slist_foreach (list, (GFunc) beagle_hit_ref, NULL);
 
-	if (!search->priv->hits) {
-		search->priv->hits = g_slist_sort (list, (GCompareFunc) _sort_hits_by_score);
-		brasero_search_add_hit_to_tree (search, search->priv->hits, search->priv->max_results);
-	}
-	else {
-		GSList *first;
+	if (priv->hits)
+		priv->hits = g_slist_concat (priv->hits, list);
+	else
+		priv->hits = list;
 
-		search->priv->hits = g_slist_concat (search->priv->hits, list);
-		search->priv->hits = g_slist_sort (search->priv->hits, (GCompareFunc) _sort_hits_by_score);
+	for (iter = list; iter; iter = iter->next) {
+		BeagleHit *hit;
 
-		brasero_search_empty_tree (search);
-		first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-		brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
-	}
+		hit = iter->data;
+		beagle_hit_ref (hit);
 
-	brasero_search_update_header (search);
-	brasero_search_check_for_possible_missing (search);
+		brasero_search_engine_hit_added (BRASERO_SEARCH_ENGINE (search), hit);
+	}
 }
 
 static void
 brasero_search_beagle_hit_substracted_cb (BeagleQuery *query,
 					  BeagleHitsSubtractedResponse *response,
-					  BraseroSearch *search)
+					  BraseroSearchBeagle *search)
 {
-	gchar *uri;
 	GSList *list, *iter;
-	const gchar *removed_uri;
-
-	GtkTreeModel *model;
-	GtkTreeIter row;
+	BraseroSearchBeaglePrivate *priv;
 
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (search);
 
 	list = beagle_hits_subtracted_response_get_uris (response);
 	for (iter = list; iter; iter = iter->next) {
 		GSList *next, *hit_iter;
+		const gchar *removed_uri;
 
 		removed_uri = iter->data;
 
-		if (gtk_tree_model_get_iter_first (model, &row)) {
-			do {
-				gtk_tree_model_get (model, &row,
-						    BRASERO_SEARCH_TREE_URI_COL,
-						    &uri, -1);
-				if (!strcmp (uri, removed_uri)) {
-					g_free (uri);
-					gtk_list_store_remove
-					    (GTK_LIST_STORE (model), &row);
-					break;
-				}
-
-				g_free (uri);
-			} while (gtk_tree_model_iter_next (model, &row));
-		}
-
 		/* see if it isn't in the hits that are still waiting */
-		for (hit_iter = search->priv->hits; hit_iter; hit_iter = next) {
+		for (hit_iter = priv->hits; hit_iter; hit_iter = next) {
 			BeagleHit *hit;
 			const char *hit_uri;
 	
@@ -509,617 +240,227 @@ brasero_search_beagle_hit_substracted_cb (BeagleQuery *query,
 
 			hit_uri = beagle_hit_get_uri (hit);
 			if (!strcmp (hit_uri, removed_uri)) {
-				search->priv->hits = g_slist_remove (search->priv->hits, hit);
+				priv->hits = g_slist_remove (priv->hits, hit);
+				brasero_search_engine_hit_removed (BRASERO_SEARCH_ENGINE (search), hit);
 				beagle_hit_unref (hit);
-
-				search->priv->hits_num --;
 			}
 		}
 	}
-
-	brasero_search_update_header (search);
-	brasero_search_check_for_possible_missing (search);
 }
 
 static void
 brasero_search_beagle_finished_cb (BeagleQuery *query,
 				   BeagleFinishedResponse *response,
-				   BraseroSearch *search)
-{
-	brasero_search_update_header (search);
-	brasero_search_decrease_activity (search);
-}
-
-static void
-brasero_search_beagle_error_dialog (BraseroSearch *search, GError *error)
+				   BraseroSearchBeagle *search)
 {
-	brasero_app_alert (brasero_app_get_default (),
-			   _("Error querying Beagle."),
-			   error->message,
-			   GTK_MESSAGE_ERROR);
+	brasero_search_engine_query_finished (BRASERO_SEARCH_ENGINE (search));
 }
 
 static void
 brasero_search_beagle_error_cb (BeagleRequest *request,
 				GError *error,
-				BraseroSearch *search)
+				BraseroSearchEngine *search)
 {
-	brasero_search_update_header (search);
-	if (error)
-		brasero_search_beagle_error_dialog (search, error);
-	brasero_search_decrease_activity (search);
+	brasero_search_engine_query_error (BRASERO_SEARCH_ENGINE (search), error);
 }
 
-static void
-brasero_search_entry_activated_cb (BraseroSearchEntry *entry,
-				   BraseroSearch *search)
+static gboolean
+brasero_search_beagle_query_start (BraseroSearchEngine *search)
 {
-	BeagleQuery *query;
+	BraseroSearchBeaglePrivate *priv;
 	GError *error = NULL;
 
-	/* we first empty everything including the filter box */
-	brasero_search_empty_tree (search);
-	if (search->priv->query) {
-		brasero_search_decrease_activity (search);
-		g_object_unref (search->priv->query);
-		search->priv->query = NULL;
-	}
-
-	if (search->priv->hits) {
-		g_slist_foreach (search->priv->hits, (GFunc) beagle_hit_unref, NULL);
-		g_slist_free (search->priv->hits);
-		search->priv->hits = NULL;
-	}
-
-	search->priv->hits_num = 0;
-	search->priv->first_hit = 0;
-	brasero_search_update_header (search);
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (search);
 
 	/* search itself */
-	query = brasero_search_entry_get_query (entry);
-	if (!query) {
-		g_warning ("No query\n");
-		return;
+	if (!priv->query) {
+		g_warning ("No query");
+		return FALSE;
 	}
 
-	beagle_query_set_max_hits (query, 10000);
-	g_signal_connect (G_OBJECT (query), "hits-added",
+	beagle_query_set_max_hits (priv->query, 10000);
+	g_signal_connect (G_OBJECT (priv->query), "hits-added",
 			  G_CALLBACK (brasero_search_beagle_hit_added_cb),
 			  search);
-	g_signal_connect (G_OBJECT (query), "hits-subtracted",
+	g_signal_connect (G_OBJECT (priv->query), "hits-subtracted",
 			  G_CALLBACK
 			  (brasero_search_beagle_hit_substracted_cb),
 			  search);
-	g_signal_connect (G_OBJECT (query), "finished",
+	g_signal_connect (G_OBJECT (priv->query), "finished",
 			  G_CALLBACK (brasero_search_beagle_finished_cb),
 			  search);
-	g_signal_connect (G_OBJECT (query), "error",
+	g_signal_connect (G_OBJECT (priv->query), "error",
 			  G_CALLBACK (brasero_search_beagle_error_cb),
 			  search);
-	beagle_client_send_request_async (search->priv->client,
-					  BEAGLE_REQUEST (query),
+
+	beagle_client_send_request_async (priv->client,
+					  BEAGLE_REQUEST (priv->query),
 					  &error);
 	if (error) {
-		brasero_search_beagle_error_dialog (search, error);
+		brasero_search_engine_query_error (BRASERO_SEARCH_ENGINE (search), error);
 		g_error_free (error);
+		return FALSE;
 	}
-	else {
-		search->priv->query = query;
-		brasero_search_increase_activity (search);
-	}
-}
-
-/**
- * End of beagle specific code
- **/
 
-static gboolean
-brasero_search_is_visible_cb (GtkTreeModel *model,
-			      GtkTreeIter *iter,
-			      BraseroSearch *search)
-{
-	char *filename, *uri, *display_name, *mime_type;
-	gboolean result;
-
-	gtk_tree_model_get (model, iter,
-			    BRASERO_SEARCH_TREE_TITLE_COL, &filename,
-			    BRASERO_SEARCH_TREE_URI_COL, &uri,
-			    BRASERO_SEARCH_TREE_TITLE_COL, &display_name,
-			    BRASERO_SEARCH_TREE_MIME_COL, &mime_type, -1);
-
-	result = brasero_mime_filter_filter (BRASERO_MIME_FILTER (search->priv->filter),
-					     filename,
-					     uri,
-					     display_name,
-					     mime_type);
-
-	g_free (filename);
-	g_free (uri);
-	g_free (display_name);
-	g_free (mime_type);
-	return result;
-}
-
-static void
-brasero_search_mime_filter_changed (GtkComboBox *combo,
-				    BraseroSearch *search)
-{
-	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree))));
+	return TRUE;
 }
 
 static void
-brasero_search_tree_activated_cb (GtkTreeView *tree,
-				  GtkTreeIter *row,
-				  GtkTreeViewColumn *column,
-				  BraseroSearch *search)
+brasero_search_beagle_clean (BraseroSearchBeagle *beagle)
 {
-	brasero_uri_container_uri_activated (BRASERO_URI_CONTAINER (search));
-}
+	BraseroSearchBeaglePrivate *priv;
 
-static char **
-brasero_search_get_selected_rows (BraseroSearch *search)
-{
-	GtkTreeSelection *selection;
-	GtkTreeModel *model;
-	GtkTreeIter row;
-	GList *rows, *iter;
-	gchar **uris = NULL, *uri;
-	gint i;
-
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (search->priv->tree));
-	rows = gtk_tree_selection_get_selected_rows (selection, &model);
-	if (rows == NULL)
-		return NULL;
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (beagle);
 
-	uris = g_new0 (char *, g_list_length (rows) + 1);
-	for (iter = rows, i = 0; iter != NULL; iter = iter->next, i++) {
-		gtk_tree_model_get_iter (model,
-					 &row,
-					 (GtkTreePath *) iter->data);
-		gtk_tree_path_free (iter->data);
-		gtk_tree_model_get (model, &row,
-				    BRASERO_SEARCH_TREE_URI_COL, &uri,
-				    -1);
-		uris[i] = uri;
+	if (priv->query) {
+		g_object_unref (priv->query);
+		priv->query = NULL;
 	}
 
-	g_list_free (rows);
-	return uris;
-}
-
-static void
-brasero_search_drag_data_get_cb (GtkTreeView *tree,
-				 GdkDragContext *drag_context,
-				 GtkSelectionData *selection_data,
-				 guint info,
-				 guint time, BraseroSearch *search)
-{
-	gchar **uris;
-
-	uris = brasero_search_get_selected_rows (search);
-	gtk_selection_data_set_uris (selection_data, uris);
-	g_strfreev (uris);
+	if (priv->hits) {
+		g_slist_foreach (priv->hits, (GFunc) beagle_hit_unref, NULL);
+		g_slist_free (priv->hits);
+		priv->hits = NULL;
+	}
 }
 
-static gchar *
-brasero_search_get_selected_uri (BraseroURIContainer *container)
+static gboolean
+brasero_search_beagle_query_set (BraseroSearchEngine *search,
+                                 BraseroSearchScope scope,
+                                 const gchar *keywords)
 {
-	BraseroSearch *search;
-	gchar **uris = NULL;
-	gchar *uri;
+	BeagleQueryPartHuman *text;
+	BeagleQueryPartOr *or_part = NULL;
+	BraseroSearchBeaglePrivate *priv;
 
-	search = BRASERO_SEARCH (container);
-	uris = brasero_search_get_selected_rows (search);
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (search);
 
-	if (uris) {
-		uri = g_strdup (uris [0]);
-		g_strfreev (uris);
-		return uri;
-	}
+	brasero_search_beagle_clean (BRASERO_SEARCH_BEAGLE (search));
+	priv->query = beagle_query_new ();
 
-	return NULL;
-}
+	if ((scope & BRASERO_SEARCH_SCOPE_WILDCARD) == 0) {
+		BeagleQueryPartHuman *text;
 
-static gchar **
-brasero_search_get_selected_uris (BraseroURIContainer *container)
-{
-	BraseroSearch *search;
+		text = beagle_query_part_human_new ();
+		beagle_query_part_human_set_string (text, keywords);
+		beagle_query_part_set_logic (BEAGLE_QUERY_PART (text),
+					     BEAGLE_QUERY_PART_LOGIC_REQUIRED);
 
-	search = BRASERO_SEARCH (container);
-	return brasero_search_get_selected_rows (search);
-}
+		beagle_query_add_part (priv->query, BEAGLE_QUERY_PART (text));
+	}
 
-static void
-brasero_search_tree_selection_changed_cb (GtkTreeSelection *selection,
-					  BraseroSearch *search)
-{
-	brasero_uri_container_uri_selected (BRASERO_URI_CONTAINER (search));
-}
+	text = beagle_query_part_human_new ();
+	beagle_query_part_human_set_string (text, "type:File");
+	beagle_query_add_part (priv->query, BEAGLE_QUERY_PART (text));
 
-static void
-brasero_search_get_proportion (BraseroLayoutObject *object,
-			       gint *header,
-			       gint *center,
-			       gint *footer) 
-{
-	GtkRequisition requisition;
+	if (scope & BRASERO_SEARCH_SCOPE_DOCUMENTS) {
+		BeagleQueryPartProperty *filetype;
 
-	gtk_widget_size_request (BRASERO_SEARCH (object)->priv->filters,
-				 &requisition);
-	*footer = requisition.height + BRASERO_SEARCH_SPACING;
-}
+		if (!or_part)
+			or_part = beagle_query_part_or_new ();
 
-static void
-brasero_search_set_context (BraseroLayoutObject *object,
-			    BraseroLayoutType type)
-{
-	BraseroSearch *self;
-
-	self = BRASERO_SEARCH (object);
-	brasero_search_entry_set_context (BRASERO_SEARCH_ENTRY (self->priv->entry), type);
-}
-
-static void
-brasero_search_column_clicked (GtkTreeViewColumn *column,
-			       BraseroSearch *search)
-{
-	gint model_id;
-	gint column_id;
-	GtkTreeModel *model;
-	GtkSortType model_order;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-
-	gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
-					      &model_id,
-					      &model_order);
-	column_id = gtk_tree_view_column_get_sort_column_id (column);
-
-	if (column_id == model_id && model_order == GTK_SORT_DESCENDING) {
-		gtk_tree_view_column_set_sort_indicator (column, FALSE);
-		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-						      BRASERO_SEARCH_TREE_SCORE_COL,
-						      GTK_SORT_DESCENDING);
-	}
-	else if (model_id == BRASERO_SEARCH_TREE_SCORE_COL) {
-		gtk_tree_view_column_set_sort_indicator (column, TRUE);
-		gtk_tree_view_column_set_sort_order (column, GTK_SORT_ASCENDING);
-		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-						      column_id,
-						      GTK_SORT_ASCENDING);
-	}
-	else {
-		gtk_tree_view_column_set_sort_order (column, GTK_SORT_DESCENDING);
-		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-						      column_id,
-						      GTK_SORT_DESCENDING);
+		filetype = beagle_query_part_property_new ();
+		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
+		beagle_query_part_property_set_key (filetype, "beagle:FileType");
+		beagle_query_part_property_set_value (filetype, "document");
+		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
 	}
 
-	g_signal_stop_emission_by_name (column, "clicked");
-}
+	if (scope & BRASERO_SEARCH_SCOPE_PICTURES) {
+		BeagleQueryPartProperty *filetype;
 
-static void
-brasero_search_init (BraseroSearch *obj)
-{
-	gchar *string;
-	GtkWidget *box;
-	GtkWidget *box1;
-	GtkWidget *label;
-	GtkWidget *combo;
-	GtkWidget *button;
-	GtkWidget *scroll;
-	GtkListStore *store;
-	GtkTreeModel *model;
-	GtkWidget *separator;
-	GtkTreeViewColumn *column;
-	GtkCellRenderer *renderer;
-	GtkFileFilter *file_filter;
-	GtkTreeSelection *selection;
-
-	gtk_box_set_spacing (GTK_BOX (obj), BRASERO_SEARCH_SPACING);
-	obj->priv = g_new0 (BraseroSearchPrivate, 1);
-
-	/* separator */
-	separator = gtk_hseparator_new ();
-	gtk_box_pack_start (GTK_BOX (obj), separator, FALSE, FALSE, 0);
-
-	/* Entry */
-	obj->priv->entry = brasero_search_entry_new ();
-	g_signal_connect (G_OBJECT (obj->priv->entry), 
-			  "activated",
-			  G_CALLBACK (brasero_search_entry_activated_cb),
-			  obj);
-	gtk_box_pack_start (GTK_BOX (obj), obj->priv->entry, FALSE, FALSE, 0);
-
-	/* separator */
-	separator = gtk_hseparator_new ();
-	gtk_box_pack_start (GTK_BOX (obj), separator, FALSE, FALSE, 0);
-
-	/* results navigation */
-	box = gtk_hbox_new (FALSE, 6);
-	gtk_box_pack_start (GTK_BOX (obj), box, FALSE, FALSE, 0);
-
-	button = brasero_utils_make_button (_("Previous Results"),
-					    GTK_STOCK_GO_BACK,
-					    NULL,
-					    GTK_ICON_SIZE_BUTTON);
-	gtk_button_set_alignment (GTK_BUTTON (button), 0.0, 0.5);
-	gtk_widget_set_sensitive (button, FALSE);
-	g_signal_connect (G_OBJECT (button), 
-			  "clicked",
-			  G_CALLBACK (brasero_search_left_button_clicked_cb),
-			  obj);
-	gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
-	obj->priv->left = button;
-
-	string = g_strdup_printf ("<b>%s</b>", _("No results"));
-	label = gtk_label_new (string);
-	g_free (string);
-
-	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-	gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
-	obj->priv->results_label = label;
-
-	button = brasero_utils_make_button (_("Next Results"),
-					    GTK_STOCK_GO_FORWARD,
-					    NULL,
-					    GTK_ICON_SIZE_BUTTON);
-	gtk_button_set_alignment (GTK_BUTTON (button), 1.0, 0.5);
-	gtk_widget_set_sensitive (button, FALSE);
-	g_signal_connect (G_OBJECT (button), 
-			  "clicked",
-			  G_CALLBACK (brasero_search_right_button_clicked_cb),
-			  obj);
-	gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
-	obj->priv->right = button;
-
-	/* Tree */
-	obj->priv->tree = gtk_tree_view_new ();
-	gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (obj->priv->tree), TRUE);
-	egg_tree_multi_drag_add_drag_support (GTK_TREE_VIEW (obj->priv->tree));
-
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (obj->priv->tree));
-	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
-
-	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (obj->priv->tree), TRUE);
-	g_signal_connect (G_OBJECT (obj->priv->tree), 
-			  "row-activated",
-			  G_CALLBACK (brasero_search_tree_activated_cb),
-			  obj);
-	g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (obj->priv->tree))),
-			  "changed",
-			  G_CALLBACK (brasero_search_tree_selection_changed_cb),
-			  obj);
-
-	gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (obj->priv->tree), TRUE);
-	store = gtk_list_store_new (BRASERO_SEARCH_TREE_NB_COL,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING,
-				    G_TYPE_INT,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING);
-
-	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
-					      BRASERO_SEARCH_TREE_SCORE_COL,
-					      GTK_SORT_DESCENDING);
-
-	model = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
-	g_object_unref (G_OBJECT (store));
-	gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
-						(GtkTreeModelFilterVisibleFunc) brasero_search_is_visible_cb,
-						obj,
-						NULL);
-
-	gtk_tree_view_set_model (GTK_TREE_VIEW (obj->priv->tree), model);
-	g_object_unref (G_OBJECT (model));
-
-	column = gtk_tree_view_column_new ();
-	g_signal_connect (column,
-			  "clicked",
-			  G_CALLBACK (brasero_search_column_clicked),
-			  obj);
-
-	gtk_tree_view_column_set_resizable (column, TRUE);
-	gtk_tree_view_column_set_title (column, _("Files"));
-	gtk_tree_view_column_set_min_width (column, 128);
-	gtk_tree_view_column_set_sort_column_id (column,
-						 BRASERO_SEARCH_TREE_TITLE_COL);
-
-	renderer = gtk_cell_renderer_pixbuf_new ();
-	gtk_tree_view_column_pack_start (column, renderer, FALSE);
-	gtk_tree_view_column_add_attribute (column, renderer, "icon-name",
-					    BRASERO_SEARCH_TREE_ICON_COL);
-
-	renderer = gtk_cell_renderer_text_new ();
-	gtk_tree_view_column_pack_start (column, renderer, TRUE);
-	gtk_tree_view_column_add_attribute (column, renderer, "text",
-					    BRASERO_SEARCH_TREE_TITLE_COL);
-
-	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree),
-				     column);
-
-	renderer = gtk_cell_renderer_text_new ();
-	column =  gtk_tree_view_column_new_with_attributes (_("Description"),
-							    renderer, "text",
-						            BRASERO_SEARCH_TREE_DESCRIPTION_COL,
-						            NULL);
-	gtk_tree_view_column_set_resizable (column, TRUE);
-	gtk_tree_view_column_set_min_width (column, 128);
-	gtk_tree_view_column_set_sort_column_id (column,
-						 BRASERO_SEARCH_TREE_DESCRIPTION_COL);
-	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree),
-				     column);
-	g_signal_connect (column,
-			  "clicked",
-			  G_CALLBACK (brasero_search_column_clicked),
-			  obj);
-
-	/* dnd */
-	gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (obj->priv->tree),
-						GDK_BUTTON1_MASK,
-						ntables_find,
-						nb_ntables_find,
-						GDK_ACTION_COPY);
-
-	g_signal_connect (G_OBJECT (obj->priv->tree), 
-			  "drag-data-get",
-			  G_CALLBACK (brasero_search_drag_data_get_cb),
-			  obj);
-
-	scroll = gtk_scrolled_window_new (NULL, NULL);
-	gtk_container_add (GTK_CONTAINER (scroll), obj->priv->tree);
-	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
-					     GTK_SHADOW_IN);
-	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
-					GTK_POLICY_AUTOMATIC,
-					GTK_POLICY_AUTOMATIC);
-	gtk_box_pack_start (GTK_BOX (obj), scroll, TRUE, TRUE, 0);
-
-	/* filter combo */
-	box = gtk_hbox_new (FALSE, 32);
-	obj->priv->filters = box;
-	gtk_box_pack_end (GTK_BOX (obj), box, FALSE, FALSE, 0);
-
-	obj->priv->filter = brasero_mime_filter_new ();
-	g_signal_connect (G_OBJECT (BRASERO_MIME_FILTER (obj->priv->filter)->combo),
-			  "changed",
-			  G_CALLBACK (brasero_search_mime_filter_changed),
-			  obj);
-
-	file_filter = gtk_file_filter_new ();
-	gtk_file_filter_set_name (file_filter, _("All files"));
-	gtk_file_filter_add_pattern (file_filter, "*");
-	brasero_mime_filter_add_filter (BRASERO_MIME_FILTER (obj->priv->filter),
-					file_filter);
-	g_object_unref (file_filter);
-
-	gtk_box_pack_end (GTK_BOX (box), obj->priv->filter, FALSE, FALSE, 0);
-
-	box1 = gtk_hbox_new (FALSE, 6);
-	gtk_box_pack_end (GTK_BOX (box), box1, FALSE, FALSE, 0);
-
-	label = gtk_label_new (_("Number of results displayed"));
-	gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
-
-	combo = gtk_combo_box_new_text ();
-	g_signal_connect (combo,
-			  "changed",
-			  G_CALLBACK (brasero_search_max_results_num_changed_cb),
-			  obj);
-	gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "20");
-	gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "50");
-	gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "100");
-
-	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 1);
-	obj->priv->max_results = 50;
-
-	gtk_box_pack_start (GTK_BOX (box1), combo, FALSE, FALSE, 0);
+		if (!or_part)
+			or_part = beagle_query_part_or_new ();
 
-}
+		filetype = beagle_query_part_property_new ();
+		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
+		beagle_query_part_property_set_key (filetype, "beagle:FileType");
+		beagle_query_part_property_set_value (filetype, "image");
+		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
+	}
 
-static void
-brasero_search_destroy (GtkObject *object)
-{
-	BraseroSearch *search;
+	if (scope & BRASERO_SEARCH_SCOPE_MUSIC) {
+		BeagleQueryPartProperty *filetype;
 
-	search = BRASERO_SEARCH (object);
-	if (search->priv->query) {
-		g_object_unref (search->priv->query);
-		search->priv->query = NULL;
-	}
+		if (!or_part)
+			or_part = beagle_query_part_or_new ();
 
-	if (search->priv->client) {
-		g_object_unref (search->priv->client);
-		search->priv->client = NULL;
+		filetype = beagle_query_part_property_new ();
+		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
+		beagle_query_part_property_set_key (filetype, "beagle:FileType");
+		beagle_query_part_property_set_value (filetype, "audio");
+		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
 	}
 
-	if (search->priv->tree) {
-		g_signal_handlers_disconnect_by_func (gtk_tree_view_get_selection (GTK_TREE_VIEW (search->priv->tree)),
-		                                      brasero_search_tree_selection_changed_cb,
-		                                      search);
+	if (scope & BRASERO_SEARCH_SCOPE_VIDEO) {
+		BeagleQueryPartProperty *filetype;
 
-		g_signal_handlers_disconnect_by_func (search->priv->filter,
-						      brasero_search_mime_filter_changed,
-						      search);
+		if (!or_part)
+			or_part = beagle_query_part_or_new ();
 
-		brasero_search_empty_tree (search);
-		search->priv->filter = NULL;
-		search->priv->tree = NULL;
+		filetype = beagle_query_part_property_new ();
+		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
+		beagle_query_part_property_set_key (filetype, "beagle:FileType");
+		beagle_query_part_property_set_value (filetype, "video");
+		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
 	}
 
-	if (search->priv->id) {
-		g_source_remove (search->priv->id);
-		search->priv->id = 0;
-	}
+	if (!or_part)
+		return FALSE;
 
-	if (search->priv->hits) {
-		g_slist_foreach (search->priv->hits, (GFunc) beagle_hit_unref, NULL);
-		g_slist_free (search->priv->hits);
-		search->priv->hits = NULL;
-	}
-
-	if (GTK_OBJECT_CLASS (parent_class)->destroy)
-		GTK_OBJECT_CLASS (parent_class)->destroy (object);
+	beagle_query_add_part (priv->query, BEAGLE_QUERY_PART (or_part));
+	return TRUE;
 }
 
 static void
-brasero_search_finalize (GObject *object)
+brasero_search_beagle_init_engine (BraseroSearchEngineIface *iface)
 {
-	BraseroSearch *cobj;
-
-	cobj = BRASERO_SEARCH (object);
-
-	g_free (cobj->priv);
-	G_OBJECT_CLASS (parent_class)->finalize (object);
+	iface->is_available = brasero_search_beagle_is_available;
+	iface->uri_from_hit = brasero_search_beagle_uri_from_hit;
+	iface->name_from_hit = brasero_search_beagle_name_from_hit;
+	iface->icon_from_hit = brasero_search_beagle_icon_from_hit;
+	iface->score_from_hit = brasero_search_beagle_score_from_hit;
+	iface->mime_from_hit = brasero_search_beagle_mime_from_hit;
+	iface->description_from_hit = brasero_search_beagle_description_from_hit;
+	iface->query_set = brasero_search_beagle_query_set;
+	iface->query_start = brasero_search_beagle_query_start;
+	iface->add_hits = brasero_search_beagle_add_hit_to_tree;
+	iface->num_hits = brasero_search_beagle_num_hits;
 }
 
 static void
-brasero_search_iface_layout_object_init (BraseroLayoutObjectIFace *iface)
+brasero_search_beagle_init (BraseroSearchBeagle *object)
 {
-	iface->get_proportion = brasero_search_get_proportion;
-	iface->set_context = brasero_search_set_context;
-}
+	BraseroSearchBeaglePrivate *priv;
 
-static void
-brasero_search_iface_uri_container_init (BraseroURIContainerIFace *iface)
-{
-	iface->get_selected_uri = brasero_search_get_selected_uri;
-	iface->get_selected_uris = brasero_search_get_selected_uris;
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (object);
+
+	priv->client = beagle_client_new (NULL);
 }
 
 static void
-brasero_search_class_init (BraseroSearchClass *klass)
+brasero_search_beagle_finalize (GObject *object)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+	BraseroSearchBeaglePrivate *priv;
 
-	parent_class = g_type_class_peek_parent (klass);
-	object_class->finalize = brasero_search_finalize;
-	gtkobject_class->destroy = brasero_search_destroy;
-}
+	priv = BRASERO_SEARCH_BEAGLE_PRIVATE (object);
 
-GtkWidget *
-brasero_search_new ()
-{
-	BraseroSearch *obj;
+	if (priv->client) {
+		g_object_unref (priv->client);
+		priv->client = NULL;
+	}
 
-	obj = BRASERO_SEARCH (g_object_new (BRASERO_TYPE_SEARCH, NULL));
+	brasero_search_beagle_clean (BRASERO_SEARCH_BEAGLE (object));
+	G_OBJECT_CLASS (brasero_search_beagle_parent_class)->finalize (object);
+}
 
-	/* FIXME : there are better ways to do the following with the new API
-	 * see beagle_util_daemon_is_running (void) */
-	obj->priv->client = beagle_client_new (NULL);
-	if (!obj->priv->client) {
-		gtk_widget_set_sensitive (GTK_WIDGET (obj), FALSE);
+static void
+brasero_search_beagle_class_init (BraseroSearchBeagleClass *klass)
+{
+	GObjectClass* object_class = G_OBJECT_CLASS (klass);
 
-		/* we will retry in 10 seconds */
-		obj->priv->id = g_timeout_add_seconds (10,
-						       (GSourceFunc) brasero_search_try_again,
-						       obj);
-	}
+	g_type_class_add_private (klass, sizeof (BraseroSearchBeaglePrivate));
 
-	return GTK_WIDGET (obj);
+	object_class->finalize = brasero_search_beagle_finalize;
 }
 
-#endif
diff --git a/src/brasero-search-beagle.h b/src/brasero-search-beagle.h
index 08339ac..fd0a8e9 100644
--- a/src/brasero-search-beagle.h
+++ b/src/brasero-search-beagle.h
@@ -1,66 +1,54 @@
-/***************************************************************************
-*            search.h
-*
-*  dim mai 22 11:20:54 2005
-*  Copyright  2005  Philippe Rouquier
-*  brasero-app wanadoo fr
-****************************************************************************/
-
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
+ * Brasero
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ * 
  *  Brasero is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
- *
- *  Brasero 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 General Public License
- *  along with this program; if not, write to:
+ * 
+ * brasero 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with brasero.  If not, write to:
  * 	The Free Software Foundation, Inc.,
  * 	51 Franklin Street, Fifth Floor
  * 	Boston, MA  02110-1301, USA.
  */
 
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#ifdef BUILD_SEARCH
-
-#ifndef SEARCH_H
-#define SEARCH_H
+#ifndef _BRASERO_SEARCH_BEAGLE_H_
+#define _BRASERO_SEARCH_BEAGLE_H_
 
-#include <glib.h>
 #include <glib-object.h>
-#include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
-#define BRASERO_TYPE_SEARCH         (brasero_search_get_type ())
-#define BRASERO_SEARCH(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), BRASERO_TYPE_SEARCH, BraseroSearch))
-#define BRASERO_SEARCH_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), BRASERO_TYPE_SEARCH, BraseroSearchClass))
-#define BRASERO_IS_SEARCH(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), BRASERO_TYPE_SEARCH))
-#define BRASERO_IS_SEARCH_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), BRASERO_TYPE_SEARCH))
-#define BRASERO_SEARCH_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), BRASERO_TYPE_SEARCH, BraseroSearchClass))
-typedef struct BraseroSearchPrivate BraseroSearchPrivate;
+#define BRASERO_TYPE_SEARCH_BEAGLE             (brasero_search_beagle_get_type ())
+#define BRASERO_SEARCH_BEAGLE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), BRASERO_TYPE_SEARCH_BEAGLE, BraseroSearchBeagle))
+#define BRASERO_SEARCH_BEAGLE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), BRASERO_TYPE_SEARCH_BEAGLE, BraseroSearchBeagleClass))
+#define BRASERO_IS_SEARCH_BEAGLE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BRASERO_TYPE_SEARCH_BEAGLE))
+#define BRASERO_IS_SEARCH_BEAGLE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), BRASERO_TYPE_SEARCH_BEAGLE))
+#define BRASERO_SEARCH_BEAGLE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), BRASERO_TYPE_SEARCH_BEAGLE, BraseroSearchBeagleClass))
 
-typedef struct {
-	GtkVBox parent;
-	BraseroSearchPrivate *priv;
-} BraseroSearch;
+typedef struct _BraseroSearchBeagleClass BraseroSearchBeagleClass;
+typedef struct _BraseroSearchBeagle BraseroSearchBeagle;
 
-typedef struct {
-	GtkVBoxClass parent_class;;
-} BraseroSearchClass;
+struct _BraseroSearchBeagleClass
+{
+	GObjectClass parent_class;
+};
 
-GType brasero_search_get_type (void);
-GtkWidget *brasero_search_new (void);
+struct _BraseroSearchBeagle
+{
+	GObject parent_instance;
+};
 
-G_END_DECLS
+GType brasero_search_beagle_get_type (void) G_GNUC_CONST;
 
-#endif
+G_END_DECLS
 
-#endif
+#endif /* _BRASERO_SEARCH_BEAGLE_H_ */
diff --git a/src/brasero-search-engine.c b/src/brasero-search-engine.c
new file mode 100644
index 0000000..9d1b7ce
--- /dev/null
+++ b/src/brasero-search-engine.c
@@ -0,0 +1,360 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Brasero
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ * 
+ *  Brasero is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ * brasero 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with brasero.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "brasero-search-engine.h"
+
+static void brasero_search_engine_base_init (gpointer g_class);
+
+typedef enum {
+	SEARCH_FINISHED,
+	SEARCH_ERROR,
+	HIT_REMOVED,
+	HIT_ADDED,
+	LAST_SIGNAL
+} BraseroSearchEngineSignalType;
+
+static guint brasero_search_engine_signals [LAST_SIGNAL] = { 0 };
+
+gboolean
+brasero_search_engine_is_available (BraseroSearchEngine *search)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), FALSE);
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->is_available)
+		return FALSE;
+
+	return (* iface->is_available) (search);
+}
+
+gboolean
+brasero_search_engine_start_query (BraseroSearchEngine *search)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), FALSE);
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->query_start)
+		return FALSE;
+
+	return (* iface->query_start) (search);
+}
+
+gboolean
+brasero_search_engine_set_query (BraseroSearchEngine *search,
+                                   BraseroSearchScope scope,
+                                   const gchar *keywords)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), FALSE);
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->query_set)
+		return FALSE;
+
+	return (* iface->query_set) (search, scope, keywords);
+}
+
+gboolean
+brasero_search_engine_add_hits (BraseroSearchEngine *search,
+                                GtkTreeModel *model,
+                                gint range_start,
+                                gint range_end)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), FALSE);
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->add_hits)
+		return FALSE;
+
+	return iface->add_hits (search, model, range_start, range_end);
+}
+
+GIcon *
+brasero_search_engine_icon_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
+
+	if (!hit)
+		return NULL;
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->icon_from_hit)
+		return FALSE;
+
+	return (* iface->icon_from_hit) (search, hit);
+}
+
+gchar *
+brasero_search_engine_name_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
+
+	if (!hit)
+		return NULL;
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->name_from_hit)
+		return FALSE;
+
+	return (* iface->name_from_hit) (search, hit);
+}
+
+const gchar *
+brasero_search_engine_uri_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
+
+	if (!hit)
+		return NULL;
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->uri_from_hit)
+		return FALSE;
+
+	return (* iface->uri_from_hit) (search, hit);
+}
+
+const gchar *
+brasero_search_engine_mime_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
+
+	if (!hit)
+		return NULL;
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->mime_from_hit)
+		return FALSE;
+
+	return (* iface->mime_from_hit) (search, hit);
+}
+
+const gchar *
+brasero_search_engine_description_from_hit (BraseroSearchEngine *search,
+                                            gpointer hit)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), NULL);
+
+	if (!hit)
+		return NULL;
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->description_from_hit)
+		return FALSE;
+
+	return (* iface->description_from_hit) (search, hit);
+}
+
+gint
+brasero_search_engine_score_from_hit (BraseroSearchEngine *search,
+                                      gpointer hit)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), 0);
+
+	if (!hit)
+		return 0;
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->score_from_hit)
+		return FALSE;
+
+	return (* iface->score_from_hit) (search, hit);
+}
+
+gint
+brasero_search_engine_num_hits (BraseroSearchEngine *search)
+{
+	BraseroSearchEngineIface *iface;
+
+	g_return_val_if_fail (BRASERO_IS_SEARCH_ENGINE (search), 0);
+
+	iface = BRASERO_SEARCH_ENGINE_GET_IFACE (search);
+	if (!iface->num_hits)
+		return FALSE;
+
+	return (* iface->num_hits) (search);
+}
+
+void
+brasero_search_engine_query_finished (BraseroSearchEngine *search)
+{
+	g_signal_emit (search,
+	               brasero_search_engine_signals [SEARCH_FINISHED],
+	               0);
+}
+
+void
+brasero_search_engine_hit_removed (BraseroSearchEngine *search,
+                                   gpointer hit)
+{
+	g_signal_emit (search,
+	               brasero_search_engine_signals [HIT_REMOVED],
+	               0,
+	               hit);
+}
+
+void
+brasero_search_engine_hit_added (BraseroSearchEngine *search,
+                                 gpointer hit)
+{
+	g_signal_emit (search,
+	               brasero_search_engine_signals [HIT_ADDED],
+	               0,
+	               hit);
+}
+
+void
+brasero_search_engine_query_error (BraseroSearchEngine *search,
+                                   GError *error)
+{
+	g_signal_emit (search,
+	               brasero_search_engine_signals [SEARCH_ERROR],
+	               0,
+	               error);
+}
+
+GType
+brasero_search_engine_get_type()
+{
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo our_info = {
+			sizeof (BraseroSearchEngineIface),
+			brasero_search_engine_base_init,
+			NULL,
+			NULL,
+			NULL,
+			NULL,
+			0,
+			0,
+			NULL
+		};
+
+		type = g_type_register_static (G_TYPE_INTERFACE, 
+					       "BraseroSearchEngine",
+					       &our_info,
+					       0);
+
+		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+	}
+
+	return type;
+}
+
+static void
+brasero_search_engine_base_init (gpointer g_class)
+{
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	brasero_search_engine_signals [SEARCH_ERROR] =
+	    g_signal_new ("search_error",
+			  BRASERO_TYPE_SEARCH_ENGINE,
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_ACTION|G_SIGNAL_NO_RECURSE,
+			  G_STRUCT_OFFSET (BraseroSearchEngineIface, search_error),
+			  NULL,
+			  NULL,
+			  g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE,
+			  0);
+	brasero_search_engine_signals [SEARCH_FINISHED] =
+	    g_signal_new ("search_finished",
+			  BRASERO_TYPE_SEARCH_ENGINE,
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_ACTION|G_SIGNAL_NO_RECURSE,
+			  G_STRUCT_OFFSET (BraseroSearchEngineIface, search_finished),
+			  NULL,
+			  NULL,
+			  g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE,
+			  0);
+	brasero_search_engine_signals [HIT_REMOVED] =
+	    g_signal_new ("hit_removed",
+			  BRASERO_TYPE_SEARCH_ENGINE,
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_ACTION|G_SIGNAL_NO_RECURSE,
+			  G_STRUCT_OFFSET (BraseroSearchEngineIface, hit_removed),
+			  NULL,
+			  NULL,
+			  g_cclosure_marshal_VOID__POINTER,
+			  G_TYPE_NONE,
+			  1,
+	                  G_TYPE_POINTER);
+	brasero_search_engine_signals [HIT_ADDED] =
+	    g_signal_new ("hit_added",
+			  BRASERO_TYPE_SEARCH_ENGINE,
+			  G_SIGNAL_RUN_LAST|G_SIGNAL_ACTION|G_SIGNAL_NO_RECURSE,
+			  G_STRUCT_OFFSET (BraseroSearchEngineIface, hit_added),
+			  NULL,
+			  NULL,
+			  g_cclosure_marshal_VOID__POINTER,
+			  G_TYPE_NONE,
+			  1,
+	                  G_TYPE_POINTER);
+	initialized = TRUE;
+}
+
+#include "brasero-search-beagle.h"
+
+BraseroSearchEngine *search_engine = NULL;
+
+BraseroSearchEngine *
+brasero_search_engine_get_default (void)
+{
+	if (!search_engine)
+		search_engine = g_object_new (BRASERO_TYPE_SEARCH_BEAGLE, NULL);
+	else
+		g_object_ref (search_engine);
+
+	return search_engine;
+}
diff --git a/src/brasero-search-engine.h b/src/brasero-search-engine.h
new file mode 100644
index 0000000..9f7659f
--- /dev/null
+++ b/src/brasero-search-engine.h
@@ -0,0 +1,155 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Brasero
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ * 
+ *  Brasero is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ * brasero 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with brasero.  If not, write to:
+ * 	The Free Software Foundation, Inc.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _SEARCH_ENGINE_H
+#define _SEARCH_ENGINE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+enum {
+	BRASERO_SEARCH_TREE_HIT_COL		= 0,
+	BRASERO_SEARCH_TREE_NB_COL
+};
+
+typedef enum {
+	BRASERO_SEARCH_SCOPE_NONE		= 0,
+	BRASERO_SEARCH_SCOPE_VIDEO		= 1,
+	BRASERO_SEARCH_SCOPE_MUSIC		= 1 << 1,
+	BRASERO_SEARCH_SCOPE_PICTURES	= 1 << 2,
+	BRASERO_SEARCH_SCOPE_DOCUMENTS	= 1 << 3,
+	BRASERO_SEARCH_SCOPE_WILDCARD	= 1 << 4
+} BraseroSearchScope;
+
+#define BRASERO_TYPE_SEARCH_ENGINE         (brasero_search_engine_get_type ())
+#define BRASERO_SEARCH_ENGINE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), BRASERO_TYPE_SEARCH_ENGINE, BraseroSearchEngine))
+#define BRASERO_IS_SEARCH_ENGINE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), BRASERO_TYPE_SEARCH_ENGINE))
+#define BRASERO_SEARCH_ENGINE_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), BRASERO_TYPE_SEARCH_ENGINE, BraseroSearchEngineIface))
+
+typedef struct _BraseroSearchEngine        BraseroSearchEngine;
+typedef struct _BraseroSearchEngineIface   BraseroSearchEngineIface;
+
+struct _BraseroSearchEngineIface {
+	GTypeInterface g_iface;
+
+	/* <Signals> */
+	void	(*search_error)			(BraseroSearchEngine *search);
+	void	(*search_finished)			(BraseroSearchEngine *search);
+	void	(*hit_removed)			(BraseroSearchEngine *search,
+					                   gpointer hit);
+	void	(*hit_added)				(BraseroSearchEngine *search,
+						                 gpointer hit);
+
+	/* <Virtual functions> */
+	gboolean	(*is_available)			(BraseroSearchEngine *search);
+	gboolean	(*query_set)			(BraseroSearchEngine *search,
+					                     BraseroSearchScope scope,
+					                     const gchar *keywords);
+
+	gboolean	(*query_start)		(BraseroSearchEngine *search);
+
+	gboolean	(*add_hits)			(BraseroSearchEngine *search,
+					                    GtkTreeModel *model,
+					                    gint range_start,
+					                    gint range_end);
+
+	gint			(*num_hits)			(BraseroSearchEngine *engine);
+
+	const gchar*	(*uri_from_hit)		(BraseroSearchEngine *engine,
+				                        gpointer hit);
+	gchar*		(*name_from_hit)		(BraseroSearchEngine *engine,
+				                        gpointer hit);
+	GIcon*		(*icon_from_hit)		(BraseroSearchEngine *engine,
+				                         gpointer hit);
+	gint			(*score_from_hit)		(BraseroSearchEngine *engine,
+						                      gpointer hit);
+	const gchar *	(*mime_from_hit)		(BraseroSearchEngine *engine,
+				                              gpointer hit);
+	const gchar *	(*description_from_hit)	(BraseroSearchEngine *engine,
+				                               gpointer hit);
+};
+
+GType brasero_search_engine_get_type (void);
+
+BraseroSearchEngine *
+brasero_search_engine_get_default (void);
+
+gboolean
+brasero_search_engine_is_available (BraseroSearchEngine *search);
+
+gint
+brasero_search_engine_num_hits (BraseroSearchEngine *search);
+
+gboolean
+brasero_search_engine_set_query (BraseroSearchEngine *search,
+                                 BraseroSearchScope scope,
+                                 const gchar *keywords);
+
+gboolean
+brasero_search_engine_start_query (BraseroSearchEngine *search);
+
+void
+brasero_search_engine_query_finished (BraseroSearchEngine *search);
+
+void
+brasero_search_engine_query_error (BraseroSearchEngine *search,
+                                   GError *error);
+
+void
+brasero_search_engine_hit_removed (BraseroSearchEngine *search,
+                                   gpointer hit);
+void
+brasero_search_engine_hit_added (BraseroSearchEngine *search,
+                                 gpointer hit);
+
+GIcon *
+brasero_search_engine_icon_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit);
+gchar *
+brasero_search_engine_name_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit);
+const gchar *
+brasero_search_engine_uri_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit);
+const gchar *
+brasero_search_engine_mime_from_hit (BraseroSearchEngine *search,
+                                     gpointer hit);
+const gchar *
+brasero_search_engine_description_from_hit (BraseroSearchEngine *search,
+                                            gpointer hit);
+gint
+brasero_search_engine_score_from_hit (BraseroSearchEngine *search,
+                                      gpointer hit);
+
+gint
+brasero_search_engine_add_hits (BraseroSearchEngine *search,
+                                GtkTreeModel *model,
+                                gint range_start,
+                                gint range_end);
+
+G_END_DECLS
+
+#endif /* _SEARCH_ENGINE_H */
diff --git a/src/brasero-search-entry.c b/src/brasero-search-entry.c
index 6416d17..86598c6 100644
--- a/src/brasero-search-entry.c
+++ b/src/brasero-search-entry.c
@@ -38,8 +38,6 @@
 
 #include <gtk/gtk.h>
 
-#include <beagle/beagle.h>
-
 #include "brasero-search-entry.h"
 #include "brasero-layout.h"
 #include "brasero-setting.h"
@@ -621,88 +619,32 @@ end:
 	brasero_search_entry_save_history (entry);
 }
 
-BeagleQuery *
-brasero_search_entry_get_query (BraseroSearchEntry *entry)
+gboolean
+brasero_search_entry_set_query (BraseroSearchEntry *entry,
+                                BraseroSearchEngine *search)
 {
-	BeagleQuery *query;
-	BeagleQueryPartHuman *text;
-	BeagleQueryPartOr *or_part = NULL;
-
-	/* Not sure about all this */
-	query = beagle_query_new ();
-
-	if (strcmp (entry->priv->keywords, _("All files"))) {
-		BeagleQueryPartHuman *text;
-
-		text = beagle_query_part_human_new ();
-		beagle_query_part_human_set_string (text, entry->priv->keywords);
-		beagle_query_part_set_logic (BEAGLE_QUERY_PART (text),
-					     BEAGLE_QUERY_PART_LOGIC_REQUIRED);
-
-		beagle_query_add_part (query, BEAGLE_QUERY_PART (text));
-	}
-
-	text = beagle_query_part_human_new ();
-	beagle_query_part_human_set_string (text, "type:File");
-	beagle_query_add_part (query, BEAGLE_QUERY_PART (text));
-
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->documents))) {
-		BeagleQueryPartProperty *filetype;
-
-		if (!or_part)
-			or_part = beagle_query_part_or_new ();
+	BraseroSearchScope scope;
 
-		filetype = beagle_query_part_property_new ();
-		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
-		beagle_query_part_property_set_key (filetype, "beagle:FileType");
-		beagle_query_part_property_set_value (filetype, "document");
-		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
-	}
-
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->pictures))) {
-		BeagleQueryPartProperty *filetype;
+	if (!strcmp (entry->priv->keywords, _("All files")))
+		scope = BRASERO_SEARCH_SCOPE_WILDCARD;
 
-		if (!or_part)
-			or_part = beagle_query_part_or_new ();
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->documents)))
+		scope |= BRASERO_SEARCH_SCOPE_DOCUMENTS;
 
-		filetype = beagle_query_part_property_new ();
-		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
-		beagle_query_part_property_set_key (filetype, "beagle:FileType");
-		beagle_query_part_property_set_value (filetype, "image");
-		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
-	}
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->pictures)))
+		scope |= BRASERO_SEARCH_SCOPE_PICTURES;
 
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->music))) {
-		BeagleQueryPartProperty *filetype;
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->music)))
+		scope |= BRASERO_SEARCH_SCOPE_MUSIC;
 
-		if (!or_part)
-			or_part = beagle_query_part_or_new ();
-
-		filetype = beagle_query_part_property_new ();
-		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
-		beagle_query_part_property_set_key (filetype, "beagle:FileType");
-		beagle_query_part_property_set_value (filetype, "audio");
-		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
-	}
-
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->video))) {
-		BeagleQueryPartProperty *filetype;
-
-		if (!or_part)
-			or_part = beagle_query_part_or_new ();
-
-		filetype = beagle_query_part_property_new ();
-		beagle_query_part_property_set_property_type (filetype, BEAGLE_PROPERTY_TYPE_KEYWORD);
-		beagle_query_part_property_set_key (filetype, "beagle:FileType");
-		beagle_query_part_property_set_value (filetype, "video");
-		beagle_query_part_or_add_subpart (or_part, BEAGLE_QUERY_PART (filetype));
-	}
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->priv->video)))
+		scope |= BRASERO_SEARCH_SCOPE_VIDEO;
 
-	if (!or_part)
-		return query;
+	brasero_search_engine_set_query (search,
+	                                 scope,
+	                                 entry->priv->keywords);
 
-	beagle_query_add_part (query, BEAGLE_QUERY_PART (or_part));
-	return query;
+	return TRUE;
 }
 
 void
diff --git a/src/brasero-search-entry.h b/src/brasero-search-entry.h
index 72638e1..b2d4a3d 100644
--- a/src/brasero-search-entry.h
+++ b/src/brasero-search-entry.h
@@ -37,11 +37,11 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include <beagle/beagle-query.h>
-
 #include "brasero-layout.h"
+#include "brasero-search-engine.h"
 
 G_BEGIN_DECLS
+
 #define BRASERO_TYPE_SEARCH_ENTRY         (brasero_search_entry_get_type ())
 #define BRASERO_SEARCH_ENTRY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), BRASERO_TYPE_SEARCH_ENTRY, BraseroSearchEntry))
 #define BRASERO_SEARCH_ENTRY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), BRASERO_TYPE_SEARCH_ENTRY, BraseroSearchEntryClass))
@@ -66,8 +66,9 @@ typedef struct {
 GType brasero_search_entry_get_type (void);
 GtkWidget *brasero_search_entry_new (void);
 
-BeagleQuery *
-brasero_search_entry_get_query (BraseroSearchEntry *entry);
+gboolean
+brasero_search_entry_set_query (BraseroSearchEntry *entry,
+                                BraseroSearchEngine *search);
 
 void
 brasero_search_entry_set_context (BraseroSearchEntry *entry,
diff --git a/src/brasero-search.c b/src/brasero-search.c
index f5dfb44..c4cf895 100644
--- a/src/brasero-search.c
+++ b/src/brasero-search.c
@@ -43,7 +43,8 @@
 
 #include <gtk/gtk.h>
 
-#include <beagle/beagle.h>
+#include "brasero-search.h"
+#include "brasero-search-engine.h"
 
 #include "brasero-misc.h"
 
@@ -51,7 +52,7 @@
 #include "brasero-utils.h"
 #include "brasero-search-entry.h"
 #include "brasero-mime-filter.h"
-#include "brasero-search-beagle.h"
+#include "brasero-search-engine.h"
 #include "eggtreemultidnd.h"
 
 #include "brasero-uri-container.h"
@@ -59,8 +60,7 @@
 
 
 struct BraseroSearchPrivate {
-	BeagleClient *client;
-	BeagleQuery *query;
+	GtkTreeViewColumn *sort_column;
 
 	GtkWidget *tree;
 	GtkWidget *entry;
@@ -70,18 +70,14 @@ struct BraseroSearchPrivate {
 	GtkWidget *left;
 	GtkWidget *results_label;
 
-	GSList *hits;
-	gint hits_num;
+	BraseroSearchEngine *engine;
 	gint first_hit;
 
 	gint max_results;
 
-	guint id;
-	guint activity;
+	int id;
 };
 
-static GObjectClass *parent_class = NULL;
-
 enum {
 	TARGET_URIS_LIST,
 };
@@ -91,16 +87,6 @@ static GtkTargetEntry ntables_find[] = {
 };
 static guint nb_ntables_find = sizeof (ntables_find) / sizeof (ntables_find[0]);
 
-enum {
-	BRASERO_SEARCH_TREE_ICON_COL,
-	BRASERO_SEARCH_TREE_TITLE_COL,
-	BRASERO_SEARCH_TREE_DESCRIPTION_COL,
-	BRASERO_SEARCH_TREE_SCORE_COL,
-	BRASERO_SEARCH_TREE_URI_COL,
-	BRASERO_SEARCH_TREE_MIME_COL,
-	BRASERO_SEARCH_TREE_NB_COL
-};
-
 #define BRASERO_SEARCH_SPACING 6
 
 static void brasero_search_iface_uri_container_init (BraseroURIContainerIFace *iface);
@@ -116,57 +102,102 @@ G_DEFINE_TYPE_WITH_CODE (BraseroSearch,
 
 
 
-static gboolean
-brasero_search_try_again (BraseroSearch *search)
+static void
+brasero_search_column_icon_cb (GtkTreeViewColumn *tree_column,
+                               GtkCellRenderer *cell,
+                               GtkTreeModel *model,
+                               GtkTreeIter *iter,
+                               gpointer data)
+{
+	GIcon *icon;
+	gpointer hit = NULL;
+
+	gtk_tree_model_get (model, iter,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit,
+	                    -1);
+
+	icon = brasero_search_engine_icon_from_hit (BRASERO_SEARCH (data)->priv->engine, hit);
+	g_object_set (G_OBJECT (cell),
+		      "gicon", icon,
+		      NULL);
+	g_object_unref (icon);
+}
+
+static void
+brasero_search_column_name_cb (GtkTreeViewColumn *tree_column,
+                               GtkCellRenderer *cell,
+                               GtkTreeModel *model,
+                               GtkTreeIter *iter,
+                               gpointer data)
+{
+	gchar *name;
+	gpointer hit = NULL;
+
+	gtk_tree_model_get (model, iter,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit,
+	                    -1);
+
+	name = brasero_search_engine_name_from_hit (BRASERO_SEARCH (data)->priv->engine, hit);
+	g_object_set (G_OBJECT (cell),
+		      "text", name,
+		      NULL);
+	g_free (name);
+}
+
+static void
+brasero_search_column_description_cb (GtkTreeViewColumn *tree_column,
+                                      GtkCellRenderer *cell,
+                                      GtkTreeModel *model,
+                                      GtkTreeIter *iter,
+                                      gpointer data)
 {
-	search->priv->client = beagle_client_new (NULL);
-	if (!search->priv->client)
-		return TRUE;
+	const gchar *description;
+	gpointer hit = NULL;
+
+	gtk_tree_model_get (model, iter,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit,
+	                    -1);
 
-	gtk_widget_set_sensitive (GTK_WIDGET (search), TRUE);
-	search->priv->id = 0;
-	return FALSE;
+	description = brasero_search_engine_description_from_hit (BRASERO_SEARCH (data)->priv->engine, hit);
+	g_object_set (G_OBJECT (cell),
+		      "text", description,
+		      NULL);
 }
 
 static void
 brasero_search_increase_activity (BraseroSearch *search)
 {
-	search->priv->activity ++;
-	if (search->priv->activity == 1) {
-		GdkCursor *cursor;
+	GdkCursor *cursor;
 
-		cursor = gdk_cursor_new (GDK_WATCH);
-		gdk_window_set_cursor (GTK_WIDGET (search)->window, cursor);
-		gdk_cursor_unref (cursor);
-	}
+	cursor = gdk_cursor_new (GDK_WATCH);
+	gdk_window_set_cursor (GTK_WIDGET (search)->window, cursor);
+	gdk_cursor_unref (cursor);
 }
 
 static void
 brasero_search_decrease_activity (BraseroSearch *search)
 {
-	if (search->priv->activity == 0)
-		return;
-
-	search->priv->activity --;
-	if (!search->priv->activity)
-		gdk_window_set_cursor (GTK_WIDGET (search)->window, NULL);
+	gdk_window_set_cursor (GTK_WIDGET (search)->window, NULL);
 }
 
 static void
 brasero_search_update_header (BraseroSearch *search)
 {
 	gchar *string;
+	gint num_hits;
 
-	if (search->priv->hits_num) {
+	num_hits = brasero_search_engine_num_hits (search->priv->engine);
+	if (num_hits) {
 		gint last;
 		gchar *tmp;
 
 		last = search->priv->first_hit + search->priv->max_results;
-		last = last <= search->priv->hits_num ? last : search->priv->hits_num;
+		last = MIN (last, num_hits);
+
 		tmp = g_strdup_printf (_("Results %iâ??%i (out of %i)"),
 				       search->priv->first_hit + 1,
 				       last,
-				       search->priv->hits_num);
+				       num_hits);
 		string = g_strdup_printf ("<b>%s</b>", tmp);
 		g_free (tmp);
 	}
@@ -176,7 +207,7 @@ brasero_search_update_header (BraseroSearch *search)
 	gtk_label_set_markup (GTK_LABEL (search->priv->results_label), string);
 	g_free (string);
 
-	if (search->priv->first_hit + search->priv->max_results < search->priv->hits_num)
+	if (search->priv->first_hit + search->priv->max_results < num_hits)
 		gtk_widget_set_sensitive (search->priv->right, TRUE);
 	else
 		gtk_widget_set_sensitive (search->priv->right, FALSE);
@@ -191,166 +222,103 @@ static void
 brasero_search_empty_tree (BraseroSearch *search)
 {
 	GtkTreeModel *model;
+	GtkTreeModel *sort;
 	GtkTreeIter row;
-	gchar *mime;
 
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+	sort = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
+	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (sort));
 
-	if (gtk_tree_model_get_iter_first (model, &row) == TRUE) {
+	if (gtk_tree_model_get_iter_first (model, &row)) {
 		do {
+			gpointer hit;
+			const gchar *mime;
+
+			hit = NULL;
 			gtk_tree_model_get (model, &row,
-					    BRASERO_SEARCH_TREE_MIME_COL, &mime, 
+					    BRASERO_SEARCH_TREE_HIT_COL, &hit,
 					    -1);
+
+			if (!hit)
+				continue;
+
+			mime = brasero_search_engine_mime_from_hit (search->priv->engine, hit);
+			if (!mime)
+				continue;
+
 			brasero_mime_filter_unref_mime (BRASERO_MIME_FILTER (search->priv->filter), mime);
-			g_free (mime);
-		} while (gtk_list_store_remove (GTK_LIST_STORE (model), &row) == TRUE);
+		} while (gtk_list_store_remove (GTK_LIST_STORE (model), &row));
 	}
 }
 
-/**
- * Start of beagle specific code
- **/
-
-static GSList *
-brasero_search_add_hit_to_tree (BraseroSearch *search,
-				GSList *list,
-				gint max)
+static void
+brasero_search_row_inserted (GtkTreeModel *model,
+                             GtkTreePath *path,
+                             GtkTreeIter *iter,
+                             BraseroSearch *search)
 {
-	GtkTreeModel *model;
-	GtkTreeIter row;
-	BeagleHit *hit;
-	GSList *iter;
-	GSList *next;
-
-	gchar *name, *mime; 
-	const gchar *icon_string = BRASERO_DEFAULT_ICON;
-	const gchar *description;
-	GIcon *icon;
-	gint score;
-	gint num;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+	const gchar *mime;
+	gpointer hit = NULL;
 
-	num = 0;
-	for (iter = list; iter && num < max; iter = next, num ++) {
-		gchar *unescaped_uri, *uri;
-		GFile *file;
-
-		hit = iter->data;
-		next = iter->next;
-
-		uri = g_strdup (beagle_hit_get_uri (hit));
+	gtk_tree_model_get (model, iter,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit,
+	                    -1);
 
-		/* beagle return badly formed uri not encoded in UTF-8
-		 * locale charset so we check them just in case */
-		unescaped_uri = g_uri_unescape_string (uri, NULL);
-		if (!g_utf8_validate (unescaped_uri, -1, NULL)) {
-			g_free (unescaped_uri);
-			g_free (uri);
-			continue;
-		}
+	if (!hit)
+		return;
 
-		file = g_file_new_for_uri (uri);
+	mime = brasero_search_engine_mime_from_hit (search->priv->engine, hit);
 
-		name = g_path_get_basename (unescaped_uri);
-		g_free (unescaped_uri);
+	/* add the mime type to the filter combo */
+	brasero_mime_filter_add_mime (BRASERO_MIME_FILTER (search->priv->filter), mime);
+}
 
-		mime = g_strdup (beagle_hit_get_mime_type (hit));
-		if (!mime) {
-			g_warning ("Strange beagle reports a URI (%s) but cannot tell the mime.\n", uri);
-			g_free (name);
-			g_free (uri);
-			continue;
-		}
+static gboolean
+brasero_search_update_tree (BraseroSearch *search)
+{
+	GtkTreeModel *model;
+	GtkTreeModel *sort;
+	gint max_hits;
+	gint last_hit;
 
-		if (!strcmp (mime, "inode/directory")) {
-			g_free (mime);
-			mime = g_strdup ("x-directory/normal");
-		}
+	if (search->priv->first_hit < 0)
+		search->priv->first_hit = 0;
 
-		description = g_content_type_get_description (mime);
-
-		icon = g_content_type_get_icon (mime);
-		icon_string = NULL;
-		if (G_IS_THEMED_ICON (icon)) {
-			const gchar * const *names = NULL;
-
-			names = g_themed_icon_get_names (G_THEMED_ICON (icon));
-			if (names) {
-				gint i;
-				GtkIconTheme *theme;
-
-				theme = gtk_icon_theme_get_default ();
-				for (i = 0; names [i]; i++) {
-					if (gtk_icon_theme_has_icon (theme, names [i])) {
-						icon_string = names [i];
-						break;
-					}
-				}
-			}
-		}
+	max_hits = brasero_search_engine_num_hits (search->priv->engine);
+	if (search->priv->first_hit > max_hits) {
+		search->priv->first_hit = max_hits;
+		return FALSE;
+	}
 
-		score = (int) (beagle_hit_get_score (hit) * 100);
+	last_hit = MIN (max_hits, search->priv->max_results + search->priv->first_hit);
 
-		gtk_list_store_append (GTK_LIST_STORE (model), &row);
-		gtk_list_store_set (GTK_LIST_STORE (model), &row,
-				    BRASERO_SEARCH_TREE_ICON_COL, icon_string,
-				    BRASERO_SEARCH_TREE_TITLE_COL, name,
-				    BRASERO_SEARCH_TREE_DESCRIPTION_COL, description,
-				    BRASERO_SEARCH_TREE_URI_COL, uri,
-				    BRASERO_SEARCH_TREE_SCORE_COL, score,
-				    BRASERO_SEARCH_TREE_MIME_COL, mime,
-				    -1);
+	brasero_search_empty_tree (search);
 
-		/* add the mime type to the filter combo */
-		brasero_mime_filter_add_mime (BRASERO_MIME_FILTER (search->priv->filter), mime);
+	sort = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
+	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (sort));
 
-		g_object_unref (icon);
-		g_free (name);
-		g_free (mime);
-		g_free (uri);
-	}
+	brasero_search_engine_add_hits (search->priv->engine,
+	                                model,
+	                                search->priv->first_hit,
+	                                last_hit);
 
-	return iter;
+	brasero_search_update_header (search);
+	return TRUE;
 }
 
 static void
 brasero_search_left_button_clicked_cb (GtkButton *button,
 				       BraseroSearch *search)
 {
-	GSList *first;
-
-	if (!search->priv->first_hit)
-		return;
-
 	search->priv->first_hit -= search->priv->max_results;
-	if (search->priv->first_hit < 0)
-		search->priv->first_hit = 0;
-
-	first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-
-	brasero_search_empty_tree (search);
-	brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
-	brasero_search_update_header (search);
+	brasero_search_update_tree (search);
 }
 
 static void
 brasero_search_right_button_clicked_cb (GtkButton *button,
 					BraseroSearch *search)
 {
-	GSList *first;
-
-	if (search->priv->first_hit + search->priv->max_results > search->priv->hits_num)
-		return;
-
 	search->priv->first_hit += search->priv->max_results;
-	first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-
-	brasero_search_empty_tree (search);
-	brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
-	brasero_search_update_header (search);
+	brasero_search_update_tree (search);
 }
 
 static void
@@ -358,6 +326,12 @@ brasero_search_max_results_num_changed_cb (GtkComboBox *combo,
 					   BraseroSearch *search)
 {
 	gint index;
+	gint page_num;
+
+	if (search->priv->max_results)
+		page_num = search->priv->first_hit / search->priv->max_results;
+	else
+		page_num = 0;
 
 	index = gtk_combo_box_get_active (combo);
 	switch (index) {
@@ -372,273 +346,158 @@ brasero_search_max_results_num_changed_cb (GtkComboBox *combo,
 		break;
 	}
 
-	if (search->priv->hits_num) {
-		GSList *first;
-
-		brasero_search_empty_tree (search);
-		first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-		brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
-	}
-
-	brasero_search_update_header (search);
+	search->priv->first_hit = page_num * search->priv->max_results;
+	brasero_search_update_tree (search);
 }
 
 static void
-brasero_search_check_for_possible_missing (BraseroSearch *search)
+brasero_search_finished_cb (BraseroSearchEngine *engine,
+                            BraseroSearch *search)
 {
-	gint num_missing;
-	gint num_displayed;
-	gint num_remaining;
-	GtkTreeModel *model;
-
-	/* now let's see if we should append new results */
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-
-	num_displayed = gtk_tree_model_iter_n_children (model, NULL);
-	num_missing = search->priv->max_results - num_displayed;
-	num_remaining = search->priv->hits_num - search->priv->first_hit;
-
-	if (num_displayed == num_remaining)
-		return;
-
-	if (num_missing > 0) {
-		GSList *first;
-
-		first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-		brasero_search_add_hit_to_tree (search, first, num_missing);
-	}
+	brasero_search_decrease_activity (search);
 }
 
-/**
- * Really Beagle specific code
- **/
-
-static gint
-_sort_hits_by_score (BeagleHit *a, BeagleHit *b)
+static void
+brasero_search_error_cb (BraseroSearchEngine *engine,
+                         GError *error,
+                         BraseroSearch *search)
 {
-	gdouble score_a, score_b;
-
-	score_a = beagle_hit_get_score (a);
-	score_b = beagle_hit_get_score (b);
-
-	if (score_b == score_a)
-		return 0;
-
-	if (score_b > score_a);
-		return -1;
+	brasero_search_update_header (search);
+	if (error)
+		brasero_app_alert (brasero_app_get_default (),
+				   _("Error querying for keywords."),
+				   error->message,
+				   GTK_MESSAGE_ERROR);
 
-	return 1;
+	brasero_search_decrease_activity (search);
 }
 
 static void
-brasero_search_beagle_hit_added_cb (BeagleQuery *query,
-				    BeagleHitsAddedResponse *response,
-				    BraseroSearch *search)
+brasero_search_hit_added_cb (BraseroSearchEngine *engine,
+                             gpointer hit,
+                             BraseroSearch *search)
 {
-	GSList *list;
-
-	/* NOTE : list must not be modified nor freed */
-	list = beagle_hits_added_response_get_hits (response);
-	search->priv->hits_num += g_slist_length (list);
-
-	list = g_slist_copy (list);
-	g_slist_foreach (list, (GFunc) beagle_hit_ref, NULL);
+	gint num;
+	gint hit_num;
+	GtkTreeIter iter;
+	const gchar *mime;
+	GtkTreeModel *model;
 
-	if (!search->priv->hits) {
-		search->priv->hits = g_slist_sort (list, (GCompareFunc) _sort_hits_by_score);
-		brasero_search_add_hit_to_tree (search, search->priv->hits, search->priv->max_results);
+	hit_num = brasero_search_engine_num_hits (search->priv->engine);
+	if (hit_num < search->priv->first_hit
+	&& hit_num >= search->priv->first_hit + search->priv->max_results) {
+		brasero_search_update_header (search);
+		return;
 	}
-	else {
-		GSList *first;
 
-		search->priv->hits = g_slist_concat (search->priv->hits, list);
-		search->priv->hits = g_slist_sort (search->priv->hits, (GCompareFunc) _sort_hits_by_score);
+	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
+	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
 
-		brasero_search_empty_tree (search);
-		first = g_slist_nth (search->priv->hits, search->priv->first_hit);
-		brasero_search_add_hit_to_tree (search, first, search->priv->max_results);
+	num = gtk_tree_model_iter_n_children (model, NULL);
+	if (num >= search->priv->max_results) {
+		brasero_search_update_header (search);
+		return;
 	}
 
+	gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, -1,
+	                                   BRASERO_SEARCH_TREE_HIT_COL, hit,
+	                                   -1);
+
+	mime = brasero_search_engine_mime_from_hit (search->priv->engine, hit);
 	brasero_search_update_header (search);
-	brasero_search_check_for_possible_missing (search);
 }
 
 static void
-brasero_search_beagle_hit_substracted_cb (BeagleQuery *query,
-					  BeagleHitsSubtractedResponse *response,
-					  BraseroSearch *search)
+brasero_search_hit_removed_cb (BraseroSearchEngine *engine,
+                               gpointer hit,
+                               BraseroSearch *search)
 {
-	gchar *uri;
-	GSList *list, *iter;
-	const gchar *removed_uri;
-
+	int num = 0;
+	int range_end;
+	int range_start;
+	GtkTreeIter iter;
 	GtkTreeModel *model;
-	GtkTreeIter row;
 
 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
 	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
 
-	list = beagle_hits_subtracted_response_get_uris (response);
-	for (iter = list; iter; iter = iter->next) {
-		GSList *next, *hit_iter;
-
-		removed_uri = iter->data;
-
-		if (gtk_tree_model_get_iter_first (model, &row)) {
-			do {
-				gtk_tree_model_get (model, &row,
-						    BRASERO_SEARCH_TREE_URI_COL,
-						    &uri, -1);
-				if (!strcmp (uri, removed_uri)) {
-					g_free (uri);
-					gtk_list_store_remove
-					    (GTK_LIST_STORE (model), &row);
-					break;
-				}
-
-				g_free (uri);
-			} while (gtk_tree_model_iter_next (model, &row));
-		}
+	if (!gtk_tree_model_get_iter_first (model, &iter))
+		return;
+
+	do {
+		gpointer model_hit;
+
+		model_hit = NULL;
+		gtk_tree_model_get (model, &iter,
+				    BRASERO_SEARCH_TREE_HIT_COL, &model_hit,
+				    -1);
+
+		if (hit == model_hit) {
+			const gchar *mime;
+
+			mime = brasero_search_engine_mime_from_hit (search->priv->engine, hit);
+			brasero_mime_filter_unref_mime (BRASERO_MIME_FILTER (search->priv->filter), mime);
 
-		/* see if it isn't in the hits that are still waiting */
-		for (hit_iter = search->priv->hits; hit_iter; hit_iter = next) {
-			BeagleHit *hit;
-			const char *hit_uri;
-	
-			next = hit_iter->next;
-			hit = hit_iter->data;
-
-			hit_uri = beagle_hit_get_uri (hit);
-			if (!strcmp (hit_uri, removed_uri)) {
-				search->priv->hits = g_slist_remove (search->priv->hits, hit);
-				beagle_hit_unref (hit);
-
-				search->priv->hits_num --;
-			}
+			gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+			break;
 		}
-	}
 
-	brasero_search_update_header (search);
-	brasero_search_check_for_possible_missing (search);
-}
+		num ++;
+	} while (gtk_tree_model_iter_next (model, &iter));
 
-static void
-brasero_search_beagle_finished_cb (BeagleQuery *query,
-				   BeagleFinishedResponse *response,
-				   BraseroSearch *search)
-{
-	brasero_search_update_header (search);
-	brasero_search_decrease_activity (search);
-}
+	if (num < search->priv->first_hit
+	&& num >= search->priv->first_hit + search->priv->max_results) {
+		brasero_search_update_header (search);
+		return;
+	}
 
-static void
-brasero_search_beagle_error_dialog (BraseroSearch *search, GError *error)
-{
-	brasero_app_alert (brasero_app_get_default (),
-			   _("Error querying Beagle."),
-			   error->message,
-			   GTK_MESSAGE_ERROR);
-}
+	range_start = search->priv->first_hit + search->priv->max_results - 1;
+	range_end = search->priv->first_hit + search->priv->max_results;
+	brasero_search_engine_add_hits (search->priv->engine,
+	                                model,
+	                                range_start,
+	                                range_end);
 
-static void
-brasero_search_beagle_error_cb (BeagleRequest *request,
-				GError *error,
-				BraseroSearch *search)
-{
 	brasero_search_update_header (search);
-	if (error)
-		brasero_search_beagle_error_dialog (search, error);
-	brasero_search_decrease_activity (search);
 }
 
 static void
 brasero_search_entry_activated_cb (BraseroSearchEntry *entry,
 				   BraseroSearch *search)
 {
-	BeagleQuery *query;
-	GError *error = NULL;
+	brasero_search_increase_activity (search);
 
 	/* we first empty everything including the filter box */
 	brasero_search_empty_tree (search);
-	if (search->priv->query) {
-		brasero_search_decrease_activity (search);
-		g_object_unref (search->priv->query);
-		search->priv->query = NULL;
-	}
-
-	if (search->priv->hits) {
-		g_slist_foreach (search->priv->hits, (GFunc) beagle_hit_unref, NULL);
-		g_slist_free (search->priv->hits);
-		search->priv->hits = NULL;
-	}
-
-	search->priv->hits_num = 0;
-	search->priv->first_hit = 0;
+	brasero_search_entry_set_query (entry, search->priv->engine);
+	brasero_search_engine_start_query (search->priv->engine);
 	brasero_search_update_header (search);
-
-	/* search itself */
-	query = brasero_search_entry_get_query (entry);
-	if (!query) {
-		g_warning ("No query\n");
-		return;
-	}
-
-	beagle_query_set_max_hits (query, 10000);
-	g_signal_connect (G_OBJECT (query), "hits-added",
-			  G_CALLBACK (brasero_search_beagle_hit_added_cb),
-			  search);
-	g_signal_connect (G_OBJECT (query), "hits-subtracted",
-			  G_CALLBACK
-			  (brasero_search_beagle_hit_substracted_cb),
-			  search);
-	g_signal_connect (G_OBJECT (query), "finished",
-			  G_CALLBACK (brasero_search_beagle_finished_cb),
-			  search);
-	g_signal_connect (G_OBJECT (query), "error",
-			  G_CALLBACK (brasero_search_beagle_error_cb),
-			  search);
-	beagle_client_send_request_async (search->priv->client,
-					  BEAGLE_REQUEST (query),
-					  &error);
-	if (error) {
-		brasero_search_beagle_error_dialog (search, error);
-		g_error_free (error);
-	}
-	else {
-		search->priv->query = query;
-		brasero_search_increase_activity (search);
-	}
 }
 
-/**
- * End of beagle specific code
- **/
-
 static gboolean
 brasero_search_is_visible_cb (GtkTreeModel *model,
 			      GtkTreeIter *iter,
 			      BraseroSearch *search)
 {
-	char *filename, *uri, *display_name, *mime_type;
+	const gchar *uri, *mime;
+	gpointer hit = NULL;
 	gboolean result;
+	gchar *name;
 
 	gtk_tree_model_get (model, iter,
-			    BRASERO_SEARCH_TREE_TITLE_COL, &filename,
-			    BRASERO_SEARCH_TREE_URI_COL, &uri,
-			    BRASERO_SEARCH_TREE_TITLE_COL, &display_name,
-			    BRASERO_SEARCH_TREE_MIME_COL, &mime_type, -1);
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit,
+	                    -1);
 
+	name = brasero_search_engine_name_from_hit (search->priv->engine, hit);
+	uri = brasero_search_engine_uri_from_hit (search->priv->engine, hit);
+	mime = brasero_search_engine_mime_from_hit (search->priv->engine, hit);
 	result = brasero_mime_filter_filter (BRASERO_MIME_FILTER (search->priv->filter),
-					     filename,
+					     name,
 					     uri,
-					     display_name,
-					     mime_type);
+					     name,
+					     mime);
 
-	g_free (filename);
-	g_free (uri);
-	g_free (display_name);
-	g_free (mime_type);
+	g_free (name);
 	return result;
 }
 
@@ -663,10 +522,10 @@ brasero_search_get_selected_rows (BraseroSearch *search)
 {
 	GtkTreeSelection *selection;
 	GtkTreeModel *model;
-	GtkTreeIter row;
+	gchar **uris = NULL;
 	GList *rows, *iter;
-	gchar **uris = NULL, *uri;
-	gint i;
+	GtkTreeIter row;
+	int i;
 
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (search->priv->tree));
 	rows = gtk_tree_selection_get_selected_rows (selection, &model);
@@ -675,14 +534,18 @@ brasero_search_get_selected_rows (BraseroSearch *search)
 
 	uris = g_new0 (char *, g_list_length (rows) + 1);
 	for (iter = rows, i = 0; iter != NULL; iter = iter->next, i++) {
+		gpointer hit;
+
 		gtk_tree_model_get_iter (model,
 					 &row,
 					 (GtkTreePath *) iter->data);
 		gtk_tree_path_free (iter->data);
+
+		hit = NULL;
 		gtk_tree_model_get (model, &row,
-				    BRASERO_SEARCH_TREE_URI_COL, &uri,
+				    BRASERO_SEARCH_TREE_HIT_COL, &hit,
 				    -1);
-		uris[i] = uri;
+		uris[i] = g_strdup (brasero_search_engine_uri_from_hit (search->priv->engine, hit));
 	}
 
 	g_list_free (rows);
@@ -761,46 +624,141 @@ brasero_search_set_context (BraseroLayoutObject *object,
 	brasero_search_entry_set_context (BRASERO_SEARCH_ENTRY (self->priv->entry), type);
 }
 
+static gint
+brasero_search_sort_name (GtkTreeModel *model,
+                          GtkTreeIter  *iter1,
+                          GtkTreeIter  *iter2,
+                          gpointer user_data)
+{
+	gint res;
+	gpointer hit1, hit2;
+	gchar *name1, *name2;
+	BraseroSearch *search = BRASERO_SEARCH (user_data);
+
+	gtk_tree_model_get (model, iter1,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit1,
+	                    -1);
+	gtk_tree_model_get (model, iter2,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit2,
+	                    -1);
+
+	name1 = brasero_search_engine_name_from_hit (search->priv->engine, hit1);
+	name2 = brasero_search_engine_name_from_hit (search->priv->engine, hit2);
+
+	res = g_strcmp0 (name1, name2);
+	g_free (name1);
+	g_free (name2);
+
+	return res;
+}
+
+static gint
+brasero_search_sort_description (GtkTreeModel *model,
+                                 GtkTreeIter  *iter1,
+                                 GtkTreeIter  *iter2,
+                                 gpointer user_data)
+{
+	gpointer hit1, hit2;
+	BraseroSearch *search = BRASERO_SEARCH (user_data);
+
+	gtk_tree_model_get (model, iter1,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit1,
+	                    -1);
+	gtk_tree_model_get (model, iter2,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit2,
+	                    -1);
+
+	return g_strcmp0 (brasero_search_engine_description_from_hit (search->priv->engine, hit1),
+	                  brasero_search_engine_description_from_hit (search->priv->engine, hit2));
+}
+
+static gint
+brasero_search_sort_score (GtkTreeModel *model,
+                           GtkTreeIter  *iter1,
+                           GtkTreeIter  *iter2,
+                           gpointer user_data)
+{
+	gpointer hit1, hit2;
+	BraseroSearch *search = BRASERO_SEARCH (user_data);
+
+	gtk_tree_model_get (model, iter1,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit1,
+	                    -1);
+	gtk_tree_model_get (model, iter2,
+	                    BRASERO_SEARCH_TREE_HIT_COL, &hit2,
+	                    -1);
+
+	return brasero_search_engine_score_from_hit (search->priv->engine, hit1) -
+		    brasero_search_engine_score_from_hit (search->priv->engine, hit2);
+}
+
 static void
 brasero_search_column_clicked (GtkTreeViewColumn *column,
 			       BraseroSearch *search)
 {
-	gint model_id;
-	gint column_id;
+	GtkTreeModel *sort;
 	GtkTreeModel *model;
 	GtkSortType model_order;
 
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+	sort = gtk_tree_view_get_model (GTK_TREE_VIEW (search->priv->tree));
+	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (sort));
 
 	gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
-					      &model_id,
+					      NULL,
 					      &model_order);
-	column_id = gtk_tree_view_column_get_sort_column_id (column);
 
-	if (column_id == model_id && model_order == GTK_SORT_DESCENDING) {
-		gtk_tree_view_column_set_sort_indicator (column, FALSE);
-		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-						      BRASERO_SEARCH_TREE_SCORE_COL,
-						      GTK_SORT_DESCENDING);
-	}
-	else if (model_id == BRASERO_SEARCH_TREE_SCORE_COL) {
+	if (!gtk_tree_view_column_get_sort_indicator (column)) {
+		GtkTreeIterCompareFunc sort_func;
+
+		if (search->priv->sort_column)
+			gtk_tree_view_column_set_sort_indicator (search->priv->sort_column, FALSE);
+
+		search->priv->sort_column = column;
 		gtk_tree_view_column_set_sort_indicator (column, TRUE);
+
 		gtk_tree_view_column_set_sort_order (column, GTK_SORT_ASCENDING);
 		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-						      column_id,
-						      GTK_SORT_ASCENDING);
+		                                      GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+		                                      GTK_SORT_ASCENDING);
+
+		sort_func = g_object_get_data (G_OBJECT (column), "SortFunc");
+		gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
+							 sort_func,
+							 search,
+							 NULL);
+	}
+	else if (model_order == GTK_SORT_DESCENDING) {
+		gtk_tree_view_column_set_sort_indicator (column, FALSE);
+		gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
+							 brasero_search_sort_score,
+							 search,
+							 NULL);
+		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+		                                      GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+		                                      GTK_SORT_ASCENDING);
 	}
 	else {
 		gtk_tree_view_column_set_sort_order (column, GTK_SORT_DESCENDING);
 		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-						      column_id,
-						      GTK_SORT_DESCENDING);
+		                                      GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+		                                      GTK_SORT_DESCENDING);
 	}
 
 	g_signal_stop_emission_by_name (column, "clicked");
 }
 
+static gboolean
+brasero_search_try_again (BraseroSearch *search)
+{
+	if (brasero_search_engine_is_available (search->priv->engine)) {
+		gtk_widget_set_sensitive (GTK_WIDGET (search), TRUE);
+		search->priv->id = 0;
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 static void
 brasero_search_init (BraseroSearch *obj)
 {
@@ -822,6 +780,24 @@ brasero_search_init (BraseroSearch *obj)
 	gtk_box_set_spacing (GTK_BOX (obj), BRASERO_SEARCH_SPACING);
 	obj->priv = g_new0 (BraseroSearchPrivate, 1);
 
+	obj->priv->engine = brasero_search_engine_get_default ();
+	g_signal_connect (obj->priv->engine,
+	                  "search-finished",
+	                  G_CALLBACK (brasero_search_finished_cb),
+	                  obj);
+	g_signal_connect (obj->priv->engine,
+	                  "search-error",
+	                  G_CALLBACK (brasero_search_error_cb),
+	                  obj);
+	g_signal_connect (obj->priv->engine,
+	                  "hit-removed",
+	                  G_CALLBACK (brasero_search_hit_removed_cb),
+	                  obj);
+	g_signal_connect (obj->priv->engine,
+	                  "hit-added",
+	                  G_CALLBACK (brasero_search_hit_added_cb),
+	                  obj);
+
 	/* separator */
 	separator = gtk_hseparator_new ();
 	gtk_box_pack_start (GTK_BOX (obj), separator, FALSE, FALSE, 0);
@@ -877,7 +853,34 @@ brasero_search_init (BraseroSearch *obj)
 	obj->priv->right = button;
 
 	/* Tree */
-	obj->priv->tree = gtk_tree_view_new ();
+	store = gtk_list_store_new (BRASERO_SEARCH_TREE_NB_COL,
+				    G_TYPE_POINTER);
+
+	gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
+	                                         brasero_search_sort_score,
+        	                                 obj,
+                	                         NULL);
+
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+					      GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+					      GTK_SORT_ASCENDING);
+
+	g_signal_connect (store,
+	                  "row-inserted",
+	                  G_CALLBACK (brasero_search_row_inserted),
+	                  obj);
+
+	model = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
+	g_object_unref (G_OBJECT (store));
+
+	gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
+						(GtkTreeModelFilterVisibleFunc) brasero_search_is_visible_cb,
+						obj,
+						NULL);
+
+	obj->priv->tree = gtk_tree_view_new_with_model (model);
+	g_object_unref (G_OBJECT (model));
+
 	gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (obj->priv->tree), TRUE);
 	egg_tree_multi_drag_add_drag_support (GTK_TREE_VIEW (obj->priv->tree));
 
@@ -895,69 +898,60 @@ brasero_search_init (BraseroSearch *obj)
 			  obj);
 
 	gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (obj->priv->tree), TRUE);
-	store = gtk_list_store_new (BRASERO_SEARCH_TREE_NB_COL,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING,
-				    G_TYPE_INT,
-				    G_TYPE_STRING,
-				    G_TYPE_STRING);
-
-	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
-					      BRASERO_SEARCH_TREE_SCORE_COL,
-					      GTK_SORT_DESCENDING);
 
-	model = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
-	g_object_unref (G_OBJECT (store));
-	gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
-						(GtkTreeModelFilterVisibleFunc) brasero_search_is_visible_cb,
-						obj,
-						NULL);
+	column = gtk_tree_view_column_new ();
 
-	gtk_tree_view_set_model (GTK_TREE_VIEW (obj->priv->tree), model);
-	g_object_unref (G_OBJECT (model));
+	gtk_tree_view_column_set_clickable (column, TRUE);
+	gtk_tree_view_column_set_resizable (column, TRUE);
+	gtk_tree_view_column_set_title (column, _("Files"));
+	gtk_tree_view_column_set_min_width (column, 128);
 
-	column = gtk_tree_view_column_new ();
+	g_object_set_data (G_OBJECT (column), "SortFunc", brasero_search_sort_name);
 	g_signal_connect (column,
 			  "clicked",
 			  G_CALLBACK (brasero_search_column_clicked),
 			  obj);
 
-	gtk_tree_view_column_set_resizable (column, TRUE);
-	gtk_tree_view_column_set_title (column, _("Files"));
-	gtk_tree_view_column_set_min_width (column, 128);
-	gtk_tree_view_column_set_sort_column_id (column,
-						 BRASERO_SEARCH_TREE_TITLE_COL);
-
 	renderer = gtk_cell_renderer_pixbuf_new ();
 	gtk_tree_view_column_pack_start (column, renderer, FALSE);
-	gtk_tree_view_column_add_attribute (column, renderer, "icon-name",
-					    BRASERO_SEARCH_TREE_ICON_COL);
+	gtk_tree_view_column_set_cell_data_func (column,
+	                                         renderer,
+	                                         brasero_search_column_icon_cb,
+	                                         obj,
+	                                         NULL);
 
 	renderer = gtk_cell_renderer_text_new ();
 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
-	gtk_tree_view_column_add_attribute (column, renderer, "text",
-					    BRASERO_SEARCH_TREE_TITLE_COL);
+	gtk_tree_view_column_set_cell_data_func (column,
+	                                         renderer,
+	                                         brasero_search_column_name_cb,
+	                                         obj,
+	                                         NULL);
 
 	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree),
 				     column);
 
-	renderer = gtk_cell_renderer_text_new ();
-	column =  gtk_tree_view_column_new_with_attributes (_("Description"),
-							    renderer, "text",
-						            BRASERO_SEARCH_TREE_DESCRIPTION_COL,
-						            NULL);
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_title (column, _("Description"));
+	gtk_tree_view_column_set_clickable (column, TRUE);
 	gtk_tree_view_column_set_resizable (column, TRUE);
 	gtk_tree_view_column_set_min_width (column, 128);
-	gtk_tree_view_column_set_sort_column_id (column,
-						 BRASERO_SEARCH_TREE_DESCRIPTION_COL);
-	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree),
-				     column);
+
+	g_object_set_data (G_OBJECT (column), "SortFunc", brasero_search_sort_description);
 	g_signal_connect (column,
 			  "clicked",
 			  G_CALLBACK (brasero_search_column_clicked),
 			  obj);
 
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, renderer, TRUE);
+	gtk_tree_view_column_set_cell_data_func (column,
+	                                         renderer,
+	                                         brasero_search_column_description_cb,
+	                                         obj,
+	                                         NULL);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (obj->priv->tree),
+				     column);
 	/* dnd */
 	gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (obj->priv->tree),
 						GDK_BUTTON1_MASK,
@@ -1019,6 +1013,14 @@ brasero_search_init (BraseroSearch *obj)
 
 	gtk_box_pack_start (GTK_BOX (box1), combo, FALSE, FALSE, 0);
 
+	if (!brasero_search_engine_is_available (obj->priv->engine)) {
+		gtk_widget_set_sensitive (GTK_WIDGET (obj), FALSE);
+
+		/* we will retry in 10 seconds */
+		obj->priv->id = g_timeout_add_seconds (10,
+		                                       (GSourceFunc) brasero_search_try_again,
+		                                       obj);
+	} 
 }
 
 static void
@@ -1027,16 +1029,6 @@ brasero_search_destroy (GtkObject *object)
 	BraseroSearch *search;
 
 	search = BRASERO_SEARCH (object);
-	if (search->priv->query) {
-		g_object_unref (search->priv->query);
-		search->priv->query = NULL;
-	}
-
-	if (search->priv->client) {
-		g_object_unref (search->priv->client);
-		search->priv->client = NULL;
-	}
-
 	if (search->priv->tree) {
 		g_signal_handlers_disconnect_by_func (gtk_tree_view_get_selection (GTK_TREE_VIEW (search->priv->tree)),
 		                                      brasero_search_tree_selection_changed_cb,
@@ -1056,14 +1048,13 @@ brasero_search_destroy (GtkObject *object)
 		search->priv->id = 0;
 	}
 
-	if (search->priv->hits) {
-		g_slist_foreach (search->priv->hits, (GFunc) beagle_hit_unref, NULL);
-		g_slist_free (search->priv->hits);
-		search->priv->hits = NULL;
+	if (search->priv->engine) {
+		g_object_unref (search->priv->engine);
+		search->priv->engine = NULL;
 	}
 
-	if (GTK_OBJECT_CLASS (parent_class)->destroy)
-		GTK_OBJECT_CLASS (parent_class)->destroy (object);
+	if (GTK_OBJECT_CLASS (brasero_search_parent_class)->destroy)
+		GTK_OBJECT_CLASS (brasero_search_parent_class)->destroy (object);
 }
 
 static void
@@ -1074,7 +1065,7 @@ brasero_search_finalize (GObject *object)
 	cobj = BRASERO_SEARCH (object);
 
 	g_free (cobj->priv);
-	G_OBJECT_CLASS (parent_class)->finalize (object);
+	G_OBJECT_CLASS (brasero_search_parent_class)->finalize (object);
 }
 
 static void
@@ -1097,7 +1088,6 @@ brasero_search_class_init (BraseroSearchClass *klass)
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
 
-	parent_class = g_type_class_peek_parent (klass);
 	object_class->finalize = brasero_search_finalize;
 	gtkobject_class->destroy = brasero_search_destroy;
 }
@@ -1105,23 +1095,7 @@ brasero_search_class_init (BraseroSearchClass *klass)
 GtkWidget *
 brasero_search_new ()
 {
-	BraseroSearch *obj;
-
-	obj = BRASERO_SEARCH (g_object_new (BRASERO_TYPE_SEARCH, NULL));
-
-	/* FIXME : there are better ways to do the following with the new API
-	 * see beagle_util_daemon_is_running (void) */
-	obj->priv->client = beagle_client_new (NULL);
-	if (!obj->priv->client) {
-		gtk_widget_set_sensitive (GTK_WIDGET (obj), FALSE);
-
-		/* we will retry in 10 seconds */
-		obj->priv->id = g_timeout_add_seconds (10,
-						       (GSourceFunc) brasero_search_try_again,
-						       obj);
-	}
-
-	return GTK_WIDGET (obj);
+	return g_object_new (BRASERO_TYPE_SEARCH, NULL);
 }
 
 #endif



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