diff -rN -u -p old-sblb/rhythmdb/rhythmdb-query-model.c new-sblb/rhythmdb/rhythmdb-query-model.c
--- old-sblb/rhythmdb/rhythmdb-query-model.c	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/rhythmdb/rhythmdb-query-model.c	2006-03-13 23:02:26.000000000 +1000
@@ -54,6 +54,7 @@ G_DEFINE_TYPE_WITH_CODE(RhythmDBQueryMod
 static void rhythmdb_query_model_init (RhythmDBQueryModel *shell_player);
 static GObject *rhythmdb_query_model_constructor (GType type, guint n_construct_properties,
 						  GObjectConstructParam *construct_properties);
+static void rhythmdb_query_model_dispose (GObject *object);
 static void rhythmdb_query_model_finalize (GObject *object);
 static void rhythmdb_query_model_set_property (GObject *object,
 					       guint prop_id,
@@ -252,6 +253,7 @@ rhythmdb_query_model_class_init (RhythmD
 	object_class->set_property = rhythmdb_query_model_set_property;
 	object_class->get_property = rhythmdb_query_model_get_property;
 
+	object_class->dispose = rhythmdb_query_model_dispose;
 	object_class->finalize = rhythmdb_query_model_finalize;
 	object_class->constructor = rhythmdb_query_model_constructor;
 
@@ -616,7 +618,7 @@ _unref_entry (RhythmDBEntry *entry, gpoi
 }
 
 static void
-rhythmdb_query_model_finalize (GObject *object)
+rhythmdb_query_model_dispose (GObject *object)
 {
 	RhythmDBQueryModel *model;
 
@@ -627,21 +629,8 @@ rhythmdb_query_model_finalize (GObject *
 
 	g_return_if_fail (model->priv != NULL);
 
-	rb_debug ("finalizing query model");
-
-	g_hash_table_foreach (model->priv->reverse_map, (GHFunc) _unref_entry, model->priv->db);
-	g_hash_table_foreach (model->priv->limited_reverse_map, (GHFunc) _unref_entry, model->priv->db);
+	rb_debug ("disposing query model %p", object);
 		
-	g_hash_table_destroy (model->priv->reverse_map);
-	g_sequence_free (model->priv->entries);
-	g_hash_table_destroy (model->priv->limited_reverse_map);
-	g_sequence_free (model->priv->limited_entries);
-
-	if (model->priv->query)
-		rhythmdb_query_free (model->priv->query);
-	if (model->priv->original_query)
-		rhythmdb_query_free (model->priv->original_query);
-
 	if (model->priv->base_model) {
 		g_signal_handlers_disconnect_by_func (G_OBJECT (model->priv->base_model),
 						      G_CALLBACK (rhythmdb_query_model_base_row_inserted),
@@ -662,8 +651,37 @@ rhythmdb_query_model_finalize (GObject *
 						      G_CALLBACK (rhythmdb_query_model_base_entry_removed),
 						      model);
 		g_object_unref (G_OBJECT (model->priv->base_model));
+		model->priv->base_model = NULL;
 	}
+	
+	G_OBJECT_CLASS (rhythmdb_query_model_parent_class)->dispose (object);
+}
+
+static void
+rhythmdb_query_model_finalize (GObject *object)
+{
+	RhythmDBQueryModel *model;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (RHYTHMDB_IS_QUERY_MODEL (object));
+
+	model = RHYTHMDB_QUERY_MODEL (object);
+
+	g_return_if_fail (model->priv != NULL);
+
+	rb_debug ("finalizing query model %p", object);
+
+	g_hash_table_foreach (model->priv->reverse_map, (GHFunc) _unref_entry, model->priv->db);
+	g_hash_table_destroy (model->priv->reverse_map);
+	g_sequence_free (model->priv->entries);
+	g_hash_table_foreach (model->priv->limited_reverse_map, (GHFunc) _unref_entry, model->priv->db);
+	g_hash_table_destroy (model->priv->limited_reverse_map);
+	g_sequence_free (model->priv->limited_entries);
 
+	if (model->priv->query)
+		rhythmdb_query_free (model->priv->query);
+	if (model->priv->original_query)
+		rhythmdb_query_free (model->priv->original_query);
 
 	G_OBJECT_CLASS (rhythmdb_query_model_parent_class)->finalize (object);
 }
diff -rN -u -p old-sblb/shell/rb-play-order.c new-sblb/shell/rb-play-order.c
--- old-sblb/shell/rb-play-order.c	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/shell/rb-play-order.c	2006-03-13 23:02:26.000000000 +1000
@@ -503,7 +503,6 @@ rb_play_order_query_model_changed (RBPla
 
 	if (new_model != NULL) {
 		porder->priv->query_model = new_model;
-		g_object_ref (G_OBJECT (porder->priv->query_model));
 		g_signal_connect_object (G_OBJECT (porder->priv->query_model),
 					 "row-inserted",
 					 G_CALLBACK (rb_play_order_entry_added_cb),
diff -rN -u -p old-sblb/sources/rb-auto-playlist-source.c new-sblb/sources/rb-auto-playlist-source.c
--- old-sblb/sources/rb-auto-playlist-source.c	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/sources/rb-auto-playlist-source.c	2006-03-13 23:02:26.000000000 +1000
@@ -52,13 +52,15 @@ static void impl_save_contents_to_xml (R
 
 static void rb_auto_playlist_source_songs_sort_order_changed_cb (RBEntryView *view, 
 								 RBAutoPlaylistSource *source); 
-static void rb_auto_playlist_source_do_query (RBAutoPlaylistSource *source);
+static void rb_auto_playlist_source_do_query (RBAutoPlaylistSource *source,
+					      gboolean subset);
 
 /* browser stuff */
 static GList *impl_get_property_views (RBSource *source);
 void rb_auto_playlist_source_browser_views_activated_cb (GtkWidget *widget,
 							 RBAutoPlaylistSource *source);
 static void rb_auto_playlist_source_browser_changed_cb (RBLibraryBrowser *entry,
+							GParamSpec *pspec,
 							RBAutoPlaylistSource *source);
 
 
@@ -135,6 +137,12 @@ rb_auto_playlist_source_finalize (GObjec
 	if (priv->cached_all_query)
 		g_object_unref (G_OBJECT (priv->cached_all_query));
 
+	if (priv->query)
+		rhythmdb_query_free (priv->query);
+
+	if (priv->search_text)
+		g_free (priv->search_text);
+
 	G_OBJECT_CLASS (rb_auto_playlist_source_parent_class)->finalize (object);
 }
 
@@ -155,7 +163,7 @@ rb_auto_playlist_source_constructor (GTy
 
 	priv->browser = rb_library_browser_new (rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source)));
 	gtk_paned_pack1 (GTK_PANED (priv->paned), GTK_WIDGET (priv->browser), TRUE, FALSE);
-	g_signal_connect_object (G_OBJECT (priv->browser), "changed",
+	g_signal_connect_object (G_OBJECT (priv->browser), "notify::output-model",
 				 G_CALLBACK (rb_auto_playlist_source_browser_changed_cb),
 				 source, 0);
 
@@ -273,33 +281,37 @@ impl_reset_filters (RBSource *source)
 		priv->search_text = NULL;
 	}
 
-	if (changed) {
-		rb_auto_playlist_source_do_query (RB_AUTO_PLAYLIST_SOURCE (source));
-		rb_source_notify_filter_changed (source);
-	}
+	if (changed)
+		rb_auto_playlist_source_do_query (RB_AUTO_PLAYLIST_SOURCE (source), FALSE);
 }
 
 static void
 impl_search (RBSource *source, const char *search_text)
 {
 	RBAutoPlaylistSourcePrivate *priv = RB_AUTO_PLAYLIST_SOURCE_GET_PRIVATE (source);
+	char *old_search_text = NULL;
+	gboolean subset = FALSE;
 
 	if (search_text == NULL && priv->search_text == NULL)
 		return;
-	if (search_text != NULL && priv->search_text != NULL &&
-	    !strcmp (search_text, priv->search_text))
+	if (search_text != NULL && priv->search_text != NULL
+	    && !strcmp (search_text, priv->search_text))
 		return;
 
-	if (search_text[0] == '\0')
-		search_text = NULL;
+	rb_debug ("doing search for \"%s\"", search_text[0] != '\0' ? search_text : "(NULL)");
 
-	rb_debug ("doing search for \"%s\"", search_text ? search_text : "(NULL)");
+	old_search_text = priv->search_text;
+	if (search_text[0] == '\0') {
+		priv->search_text = NULL;
+	} else {
+		priv->search_text = g_strdup (search_text);
 
-	g_free (priv->search_text);
-	priv->search_text = g_strdup (search_text);
-	rb_auto_playlist_source_do_query (RB_AUTO_PLAYLIST_SOURCE (source));
+		if (old_search_text != NULL)
+			subset = (g_str_has_prefix (priv->search_text, old_search_text));
+	}
+	g_free (old_search_text);
 
-	rb_source_notify_filter_changed (source);
+	rb_auto_playlist_source_do_query (RB_AUTO_PLAYLIST_SOURCE (source), subset);
 }
 
 static GList *
@@ -437,69 +449,55 @@ impl_save_contents_to_xml (RBPlaylistSou
 	rhythmdb_query_serialize (rb_playlist_source_get_db (psource), query, node);
 }
 
-static GPtrArray *
-construct_query_from_selection (RBAutoPlaylistSource *source)
-{
-	RBAutoPlaylistSourcePrivate *priv = RB_AUTO_PLAYLIST_SOURCE_GET_PRIVATE (source);
-	RhythmDB *db = rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source));
-	GPtrArray *query = rhythmdb_query_copy (priv->query);
-	GPtrArray *browser_query;
-
-	if (priv->search_text) {
-		rhythmdb_query_append (db,
-				       query,
-				       RHYTHMDB_QUERY_PROP_LIKE,
-				       RHYTHMDB_PROP_SEARCH_MATCH,
-				       priv->search_text,
-				       RHYTHMDB_QUERY_END);
-	}
-
-	browser_query = rb_library_browser_construct_query (priv->browser);
-	rhythmdb_query_concatenate (query, browser_query);
-	rhythmdb_query_free (browser_query);
-
-	return query;
-}
-
 static void
-rb_auto_playlist_source_do_query (RBAutoPlaylistSource *source)
+rb_auto_playlist_source_do_query (RBAutoPlaylistSource *source, gboolean subset)
 {
 	RBAutoPlaylistSourcePrivate *priv = RB_AUTO_PLAYLIST_SOURCE_GET_PRIVATE (source);
 	RhythmDB *db = rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source));
 	RhythmDBQueryModel *query_model;
-	gboolean is_all_query;
+	GPtrArray *query;
 
 	g_assert (priv->cached_all_query);
 	
-	is_all_query = (!rb_library_browser_has_selection (priv->browser) &&
-			(priv->search_text == NULL));
+	if (!priv->search_text) {
+		rb_library_browser_set_model (priv->browser,
+					      priv->cached_all_query,
+					      FALSE);
+		return;
+	}
 
-	if (is_all_query) {
-		g_object_ref (priv->cached_all_query);
-		query_model = priv->cached_all_query;
+	query = rhythmdb_query_copy (priv->query);
+	rhythmdb_query_append (db,
+			       query,
+			       RHYTHMDB_QUERY_PROP_LIKE,
+			       RHYTHMDB_PROP_SEARCH_MATCH,
+			       priv->search_text,
+			       RHYTHMDB_QUERY_END);
+
+	if (subset) {
+		/* just apply the new query to the existing query model */
+		g_object_get (G_OBJECT (priv->browser), "input-model", &query_model, NULL);
+		g_object_set (G_OBJECT (query_model), "query", query, NULL);
+		rhythmdb_query_model_reapply_query (query_model, FALSE);
+		g_object_unref (G_OBJECT (query_model));
 	} else {
-		GPtrArray *query;
-	
+		/* otherwise, we need a new query model */
 		query_model = g_object_new (RHYTHMDB_TYPE_QUERY_MODEL,
 					    "db", db,
 					    "max-count", priv->limit_count,
 					    "max-size", priv->limit_mb,
 					    "max-time", priv->limit_time, 
 					    NULL);
+		rb_library_browser_set_model (priv->browser, query_model, TRUE);
 
-		query = construct_query_from_selection (source);
 		rhythmdb_do_full_query_async_parsed (db, 
 						     RHYTHMDB_QUERY_RESULTS (query_model), 
 						     query);
-		rhythmdb_query_free (query);
+		g_object_unref (G_OBJECT (query_model));
 	}
-
-	rb_debug ("setting query model");
-	rb_entry_view_set_model (rb_source_get_entry_view (RB_SOURCE (source)), query_model);
-	g_object_set (RB_SOURCE (source), "query-model", query_model, NULL);
-
-	g_object_unref (G_OBJECT (query_model));
+	rhythmdb_query_free (query);
 }
+
 void
 rb_auto_playlist_source_set_query (RBAutoPlaylistSource *source,
 				    GPtrArray *query,
@@ -534,12 +532,11 @@ rb_auto_playlist_source_set_query (RBAut
 					      "max-size", priv->limit_mb,
 					      "max-time", priv->limit_time, 
 					      NULL);
+	rb_library_browser_set_model (priv->browser, priv->cached_all_query, TRUE);
 	rhythmdb_do_full_query_async_parsed (db, 
 					     RHYTHMDB_QUERY_RESULTS (priv->cached_all_query), 
 					     query);
 
-	rb_auto_playlist_source_do_query (source);
-	rb_library_browser_set_model (priv->browser, priv->cached_all_query);
 
 	priv->query_resetting = FALSE;
 }
@@ -578,8 +575,18 @@ rb_auto_playlist_source_songs_sort_order
 }
 
 static void
-rb_auto_playlist_source_browser_changed_cb (RBLibraryBrowser *entry, RBAutoPlaylistSource *source)
+rb_auto_playlist_source_browser_changed_cb (RBLibraryBrowser *browser,
+					    GParamSpec *pspec,
+					    RBAutoPlaylistSource *source)
 {
-	rb_auto_playlist_source_do_query (source);
+	RBEntryView *songs = rb_source_get_entry_view (RB_SOURCE (source));
+	RhythmDBQueryModel *query_model;
+	
+	g_object_get (G_OBJECT (browser), "output-model", &query_model, NULL);
+	rb_entry_view_set_model (songs, query_model);
+	rb_playlist_source_set_query_model (RB_PLAYLIST_SOURCE (source), query_model);
+	g_object_unref (G_OBJECT (query_model));
+	
 	rb_source_notify_filter_changed (RB_SOURCE (source));
 }
+
diff -rN -u -p old-sblb/sources/rb-iradio-source.c new-sblb/sources/rb-iradio-source.c
--- old-sblb/sources/rb-iradio-source.c	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/sources/rb-iradio-source.c	2006-03-13 23:02:26.000000000 +1000
@@ -47,13 +47,6 @@
 #include "rb-debug.h"
 #include "eel-gconf-extensions.h"
 
-typedef enum
-{
-	RB_IRADIO_QUERY_TYPE_ALL,
-	RB_IRADIO_QUERY_TYPE_GENRE,
-	RB_IRADIO_QUERY_TYPE_SEARCH,
-} RBIRadioQueryType;
-
 static void rb_iradio_source_class_init (RBIRadioSourceClass *klass);
 static void rb_iradio_source_init (RBIRadioSource *source);
 static GObject *rb_iradio_source_constructor (GType type, guint n_construct_properties,
@@ -102,7 +95,7 @@ static RBSourceEOFType impl_handle_eos (
 static gboolean impl_show_popup (RBSource *source);
 static GList *impl_get_ui_actions (RBSource *source);
 
-static void rb_iradio_source_do_query (RBIRadioSource *source, RBIRadioQueryType type);
+static void rb_iradio_source_do_query (RBIRadioSource *source);
 
 void rb_iradio_source_show_columns_changed_cb (GtkToggleButton *button,
 					     RBIRadioSource *source);
@@ -136,6 +129,7 @@ struct RBIRadioSourcePrivate
 
 	RBPropertyView *genres;
 	RBEntryView *stations;
+	gboolean setting_new_query;
 
 	gboolean initialized;
 
@@ -145,8 +139,6 @@ struct RBIRadioSourcePrivate
 	gboolean firstrun_done;
 	
 	RhythmDBEntryType entry_type;
-
-	RhythmDBQueryModel *all_query;
 };
 
 #define RB_IRADIO_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_IRADIO_SOURCE, RBIRadioSourcePrivate))
@@ -244,10 +236,6 @@ rb_iradio_source_dispose (GObject *objec
 
 	source = RB_IRADIO_SOURCE (object);
 
-	if (source->priv->all_query) {
-		g_object_unref (source->priv->all_query);
-		source->priv->all_query = NULL;
-	}
 	if (source->priv->db) {
 		g_object_unref (source->priv->db);
 		source->priv->db = NULL;
@@ -368,7 +356,7 @@ rb_iradio_source_constructor (GType type
 				    source);
 	gtk_widget_show_all (GTK_WIDGET (source));
 
-	rb_iradio_source_do_query (source, RB_IRADIO_QUERY_TYPE_ALL);
+	rb_iradio_source_do_query (source);
 
 	return G_OBJECT (source);
 }
@@ -516,7 +504,7 @@ impl_search (RBSource *asource, const ch
 
 	g_free (source->priv->search_text);
 	source->priv->search_text = g_strdup (search_text);
-	rb_iradio_source_do_query (source, RB_IRADIO_QUERY_TYPE_SEARCH);
+	rb_iradio_source_do_query (source);
 
 	rb_source_notify_filter_changed (RB_SOURCE (source));
 }
@@ -673,9 +661,12 @@ static void
 genre_selected_cb (RBPropertyView *propview, const char *name,
 		   RBIRadioSource *iradio_source)
 {
+	if (iradio_source->priv->setting_new_query)
+		return;
+
 	g_free (iradio_source->priv->selected_genre);
 	iradio_source->priv->selected_genre = g_strdup (name);
-	rb_iradio_source_do_query (iradio_source, RB_IRADIO_QUERY_TYPE_GENRE);
+	rb_iradio_source_do_query (iradio_source);
 
 	rb_source_notify_filter_changed (RB_SOURCE (iradio_source));
 }
@@ -683,10 +674,13 @@ genre_selected_cb (RBPropertyView *propv
 static void
 genre_selection_reset_cb (RBPropertyView *propview, RBIRadioSource *iradio_source)
 {
+	if (iradio_source->priv->setting_new_query)
+		return;
+	
 	g_free (iradio_source->priv->selected_genre);
 	iradio_source->priv->selected_genre = NULL;
 
-	rb_iradio_source_do_query (iradio_source, RB_IRADIO_QUERY_TYPE_GENRE);
+	rb_iradio_source_do_query (iradio_source);
 
 	rb_source_notify_filter_changed (RB_SOURCE (iradio_source));
 }
@@ -710,79 +704,105 @@ rb_iradio_source_show_browser (RBIRadioS
 }
 
 static void
-rb_iradio_source_do_query (RBIRadioSource *source, RBIRadioQueryType qtype)
+rb_iradio_source_do_query (RBIRadioSource *source)
 {
 	RhythmDBEntryType entry_type;
-	RhythmDBQueryModel *query_model;
+	RhythmDBQueryModel *genre_query_model = NULL;
+	RhythmDBQueryModel *station_query_model = NULL;
 	RhythmDBPropertyModel *genre_model;
-	GtkTreeModel *model;
 	GPtrArray *query;
 
-	if ((qtype == RB_IRADIO_QUERY_TYPE_ALL) && (source->priv->all_query)) {
-		rb_debug ("using cached query");
-		rb_entry_view_set_model (source->priv->stations, RHYTHMDB_QUERY_MODEL (source->priv->all_query));
-		return;
-	}
+	/* don't update the selection while we're rebuilding the query */
+	source->priv->setting_new_query = TRUE;
 
+	/* construct and run the query for the search box.
+	 * this is used as the model for the genre view.
+	 */
+	
 	g_object_get (G_OBJECT (source), "entry-type", &entry_type, NULL);
 	query = rhythmdb_query_parse (source->priv->db,
 				      RHYTHMDB_QUERY_PROP_EQUALS,
 				      RHYTHMDB_PROP_TYPE,
 				      entry_type,
 				      RHYTHMDB_QUERY_END);
-	query_model = rhythmdb_query_model_new_empty (source->priv->db);
-
-	if (qtype == RB_IRADIO_QUERY_TYPE_ALL) {
-		rb_debug ("building new all query");
-		rb_property_view_reset (source->priv->genres);
-		g_free (source->priv->selected_genre);
-		source->priv->selected_genre = NULL;
-
-		genre_model = rb_property_view_get_model (source->priv->genres);
-		g_object_set (G_OBJECT (genre_model), "query-model", query_model, NULL);
-		g_object_unref (G_OBJECT (genre_model));
-
-		source->priv->all_query = query_model;
-	} else {
-		if (source->priv->search_text) {
-			GPtrArray *subquery = rhythmdb_query_parse (source->priv->db,
-								    RHYTHMDB_QUERY_PROP_LIKE,
-								    RHYTHMDB_PROP_GENRE_FOLDED,
-								    source->priv->search_text,
-								    RHYTHMDB_QUERY_DISJUNCTION,
-								    RHYTHMDB_QUERY_PROP_LIKE,
-								    RHYTHMDB_PROP_TITLE_FOLDED,
-								    source->priv->search_text,
-								    RHYTHMDB_QUERY_END);
-			rhythmdb_query_append (source->priv->db,
-					       query,
-					       RHYTHMDB_QUERY_SUBQUERY,
-					       subquery,
-					       RHYTHMDB_QUERY_END);
-		}
+	genre_query_model = rhythmdb_query_model_new_empty (source->priv->db);
 
-
-		if (source->priv->selected_genre)
-			rhythmdb_query_append (source->priv->db,
-					       query,
-					       RHYTHMDB_QUERY_PROP_EQUALS,
-					       RHYTHMDB_PROP_GENRE,
-					       source->priv->selected_genre,
-					       RHYTHMDB_QUERY_END);
+	if (source->priv->search_text) {
+		GPtrArray *subquery = rhythmdb_query_parse (source->priv->db,
+							    RHYTHMDB_QUERY_PROP_LIKE,
+							    RHYTHMDB_PROP_GENRE_FOLDED,
+							    source->priv->search_text,
+							    RHYTHMDB_QUERY_DISJUNCTION,
+							    RHYTHMDB_QUERY_PROP_LIKE,
+							    RHYTHMDB_PROP_TITLE_FOLDED,
+							    source->priv->search_text,
+							    RHYTHMDB_QUERY_END);
+		rb_debug ("searching for \"%s\"", source->priv->search_text);
+		rhythmdb_query_append (source->priv->db,
+				       query,
+				       RHYTHMDB_QUERY_SUBQUERY,
+				       subquery,
+				       RHYTHMDB_QUERY_END);
 	}
 
-
-	model = GTK_TREE_MODEL (query_model);
-	
-	rb_entry_view_set_model (source->priv->stations, RHYTHMDB_QUERY_MODEL (query_model));
-	g_object_set (G_OBJECT (source), "query-model", query_model, NULL);
+	genre_model = rb_property_view_get_model (source->priv->genres);
+	g_object_set (G_OBJECT (genre_model), "query-model", genre_query_model, NULL);
 
 	rhythmdb_do_full_query_parsed (source->priv->db, 
-				       RHYTHMDB_QUERY_RESULTS (model), 
+				       RHYTHMDB_QUERY_RESULTS (genre_query_model), 
 				       query);
 
 	rhythmdb_query_free (query);
+	query = NULL;
+	
+	/* check the selected genre is still available, and if not, select 'all' */
+	if (source->priv->selected_genre != NULL) {
+		GList *sel = NULL;
+		if (!rhythmdb_property_model_iter_from_string (genre_model,
+							       source->priv->selected_genre,
+							       NULL)) {
+			g_free (source->priv->selected_genre);
+			source->priv->selected_genre = NULL;
+		}
+
+		sel = g_list_prepend (sel, source->priv->selected_genre);
+		rb_property_view_set_selection (source->priv->genres, sel);
+		g_list_free (sel);
+	} 
+	g_object_unref (G_OBJECT (genre_model));
+
+	/* if a genre is selected, construct a new query for it, and create
+	 * a new model based on the search box query model.  otherwise, just
+	 * reuse the search box query model.
+	 */
+	
+	if (source->priv->selected_genre != NULL) {
+		rb_debug ("matching on genre \"%s\"", source->priv->selected_genre);
+		station_query_model = rhythmdb_query_model_new_empty (source->priv->db);
+		query = rhythmdb_query_parse (source->priv->db,
+					      RHYTHMDB_QUERY_PROP_EQUALS,
+					      RHYTHMDB_PROP_GENRE,
+					      source->priv->selected_genre,
+					      RHYTHMDB_QUERY_END);
+
+		g_object_set (station_query_model, 
+			      "query", query,
+			      "base-model", genre_query_model,
+			      NULL);
+		rhythmdb_query_free (query);
+		query = NULL;
+	} else {
+		station_query_model = genre_query_model;
+	}
+
+	rb_entry_view_set_model (source->priv->stations, station_query_model);
+	g_object_set (G_OBJECT (source), "query-model", station_query_model, NULL);
+
+	g_object_unref (G_OBJECT (genre_query_model));
+	if (station_query_model != genre_query_model)
+		g_object_unref (G_OBJECT (station_query_model));
 
+	source->priv->setting_new_query = FALSE;
 }
 
 static void
diff -rN -u -p old-sblb/sources/rb-library-source.c new-sblb/sources/rb-library-source.c
--- old-sblb/sources/rb-library-source.c	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/sources/rb-library-source.c	2006-03-13 23:02:26.000000000 +1000
@@ -74,6 +74,7 @@ static void rb_library_source_library_lo
 						   GdkEventFocus *event,
 						   RBLibrarySource *source);
 static void rb_library_source_browser_changed_cb (RBLibraryBrowser *entry,
+						  GParamSpec *param,
 						  RBLibrarySource *source);
 
 static void paned_size_allocate_cb (GtkWidget *widget,
@@ -110,11 +111,9 @@ static gboolean impl_receive_drag (RBSou
 static gboolean impl_show_popup (RBSource *source);
 static const char * impl_get_paned_key (RBLibrarySource *source);
 static GList *impl_get_search_actions (RBSource *source);
-static void rb_library_source_do_query (RBLibrarySource *source);
 
 void rb_library_source_browser_views_activated_cb (GtkWidget *widget,
 						 RBLibrarySource *source);
-static GPtrArray * construct_query_from_selection (RBLibrarySource *source);
 static void songs_view_drag_data_received_cb (GtkWidget *widget,
 					      GdkDragContext *dc,
 					      gint x, gint y,
@@ -123,6 +122,8 @@ static void songs_view_drag_data_receive
 					      RBLibrarySource *source);
 static void rb_library_source_watch_toggled_cb (GtkToggleButton *button,
 						RBLibrarySource *source);
+static void rb_library_source_do_query (RBLibrarySource *source,
+					gboolean subset);
 
 #define CONF_UI_LIBRARY_DIR CONF_PREFIX "/ui/library"
 #define CONF_STATE_LIBRARY_DIR CONF_PREFIX "/state/library"
@@ -327,6 +328,13 @@ rb_library_source_dispose (GObject *obje
 		g_free (source->priv->search_text);
 		source->priv->search_text = NULL;
 	}
+	
+	if (source->priv->cached_all_query) {
+		g_object_unref (G_OBJECT (source->priv->cached_all_query));
+		source->priv->cached_all_query = NULL;
+	}
+	
+	G_OBJECT_CLASS (rb_library_source_parent_class)->dispose (object);
 }
 
 static void
@@ -351,9 +359,6 @@ rb_library_source_finalize (GObject *obj
 
 	g_free (source->priv->sorting_key);
 
-	if (source->priv->cached_all_query)
-		g_object_unref (G_OBJECT (source->priv->cached_all_query));
-
 	G_OBJECT_CLASS (rb_library_source_parent_class)->finalize (object);
 }
 
@@ -408,7 +413,7 @@ search_action_changed (GtkRadioAction  *
 	if (active) {
 		/* update query */
 		source->priv->search_prop = search_action_to_prop (GTK_ACTION (current));
-		rb_library_source_do_query (source);
+		rb_library_source_do_query (source, FALSE);
 		rb_source_notify_filter_changed (RB_SOURCE (source));
 	}
 }
@@ -450,7 +455,7 @@ rb_library_source_constructor (GType typ
 
 	source->priv->browser = rb_library_browser_new (source->priv->db);
 	gtk_paned_pack1 (GTK_PANED (source->priv->paned), GTK_WIDGET (source->priv->browser), TRUE, FALSE);
-	g_signal_connect_object (G_OBJECT (source->priv->browser), "changed",
+	g_signal_connect_object (G_OBJECT (source->priv->browser), "notify::output-model",
 				 G_CALLBACK (rb_library_source_browser_changed_cb),
 				 source, 0);
 
@@ -541,12 +546,11 @@ rb_library_source_constructor (GType typ
 				    (GConfClientNotifyFunc) rb_library_source_library_location_changed, source);
 
 	source->priv->cached_all_query = rhythmdb_query_model_new_empty (source->priv->db);
+	rb_library_browser_set_model (source->priv->browser, source->priv->cached_all_query, TRUE);
 	rhythmdb_do_full_query_async (source->priv->db,
 				      RHYTHMDB_QUERY_RESULTS (source->priv->cached_all_query),
 				      RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, source->priv->entry_type,
 				      RHYTHMDB_QUERY_END);
-	rb_library_browser_set_model (source->priv->browser, source->priv->cached_all_query);
-	rb_library_source_do_query (source);
 
 	return G_OBJECT (source);
 }
@@ -690,31 +694,23 @@ static void
 impl_search (RBSource *asource, const char *search_text)
 {
 	RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
+	char *old_search_text = NULL;
+	gboolean subset = FALSE;
 
-	if (source->priv->initialized) {
-		if (search_text == NULL && source->priv->search_text == NULL)
-			return;
-		if (search_text != NULL &&
-		    source->priv->search_text != NULL
-		    && !strcmp (search_text, source->priv->search_text))
-			return;
-	}
-
-	source->priv->initialized = TRUE;
-	if (search_text != NULL && search_text[0] == '\0')
-		search_text = NULL;
-
-	rb_debug ("doing search for \"%s\"", search_text ? search_text : "(NULL)");
+	rb_debug ("doing search for \"%s\"", search_text[0] != '\0' ? search_text : "(NULL)");
 
-	g_free (source->priv->search_text);
-	if (search_text)
-		source->priv->search_text = g_utf8_casefold (search_text, -1);
-	else
+	old_search_text = source->priv->search_text;
+	if (search_text[0] == '\0') {
 		source->priv->search_text = NULL;
-	source->priv->search_text = g_strdup (search_text);
-	rb_library_source_do_query (source);
+	} else {
+		source->priv->search_text = g_strdup (search_text);
 
-	rb_source_notify_filter_changed (RB_SOURCE (source));
+		if (old_search_text != NULL)
+			subset = (g_str_has_prefix (source->priv->search_text, old_search_text));
+	}
+	g_free (old_search_text);
+
+	rb_library_source_do_query (source, subset);
 }
 
 
@@ -753,10 +749,8 @@ impl_reset_filters (RBSource *asource)
 	g_free (source->priv->search_text);
 	source->priv->search_text = NULL;
 #endif
-	if (changed) {
-		rb_library_source_do_query (source);
-		rb_source_notify_filter_changed (RB_SOURCE (source));
-	}
+	if (changed)
+		rb_library_source_do_query (source, FALSE);
 }
   
 static GtkWidget *
@@ -1177,95 +1171,76 @@ rb_library_source_has_drop_support (RBLi
 	return klass->impl_has_drop_support (source);
 }
 
-static GPtrArray *
-construct_query_from_selection (RBLibrarySource *source)
+static void
+songs_view_drag_data_received_cb (GtkWidget *widget,
+				  GdkDragContext *dc,
+				  gint x, gint y,
+				  GtkSelectionData *selection_data,
+				  guint info, guint time,
+				  RBLibrarySource *source)
 {
+	rb_debug ("data dropped on the library source song view");
+	rb_source_receive_drag (RB_SOURCE (source), selection_data);
+}
+
+static void
+rb_library_source_browser_changed_cb (RBLibraryBrowser *browser, 
+				      GParamSpec *pspec,
+				      RBLibrarySource *source)
+{
+	RhythmDBQueryModel *query_model;
+	
+	g_object_get (G_OBJECT (browser), "output-model", &query_model, NULL);
+	rb_entry_view_set_model (source->priv->songs, query_model);
+	g_object_set (RB_SOURCE (source), "query-model", query_model, NULL);
+	g_object_unref (G_OBJECT (query_model));
+	
+	rb_source_notify_filter_changed (RB_SOURCE (source));
+}
+
+static void
+rb_library_source_do_query (RBLibrarySource *source, gboolean subset)
+{
+	RhythmDBQueryModel *query_model;
 	GPtrArray *query;
 	RhythmDBEntryType entry_type;
-	GPtrArray *browser_query;
-
+	
+	/* use the cached 'all' query to optimise the no-search case */
+	if (!source->priv->search_text) {
+		rb_library_browser_set_model (source->priv->browser, 
+					      source->priv->cached_all_query, 
+					      FALSE);
+		return;
+	}
+	
 	g_object_get (G_OBJECT (source), "entry-type", &entry_type, NULL);
 	query = rhythmdb_query_parse (source->priv->db,
 				      RHYTHMDB_QUERY_PROP_EQUALS,
 				      RHYTHMDB_PROP_TYPE,
 				      entry_type,
+				      RHYTHMDB_QUERY_PROP_LIKE,
+				      source->priv->search_prop,
+				      source->priv->search_text,
 				      RHYTHMDB_QUERY_END);
 
-	/* select where type="song"
-	 */
-
-	if (source->priv->search_text) {
-		GPtrArray *subquery;
-
-		subquery = rhythmdb_query_parse (source->priv->db,
-						 RHYTHMDB_QUERY_PROP_LIKE,
-						 source->priv->search_prop,
-						 source->priv->search_text,
-						 RHYTHMDB_QUERY_END);
-		rhythmdb_query_append (source->priv->db,
-				       query,
-				       RHYTHMDB_QUERY_SUBQUERY,
-				       subquery,
-				       RHYTHMDB_QUERY_END);
-		/* select where type="song" and
-		 *  (genre like "foo" or artist like "foo" or album like "foo")
+	if (subset) {
+		/* if we're appending text to an existing search string, the results will be a subset
+		 * of the existing results, so we can just change the query on the existing query 
+		 * model and reapply the query.
 		 */
-	}
-
-	
-	browser_query = rb_library_browser_construct_query (source->priv->browser);
-	rhythmdb_query_concatenate (query, browser_query);
-	rhythmdb_query_free (browser_query);
-
-	return query;
-}
-
-static void
-rb_library_source_do_query (RBLibrarySource *source)
-{
-	RhythmDBQueryModel *query_model;
-	gboolean is_all_query;
-
-	is_all_query = (!rb_library_browser_has_selection (source->priv->browser) &&
-			(source->priv->search_text == NULL));
-
-	if (is_all_query) {
-		g_object_ref (source->priv->cached_all_query);
-		query_model = source->priv->cached_all_query;
+		g_object_get (G_OBJECT (source->priv->browser), "input-model", &query_model, NULL);
+		g_object_set (G_OBJECT (query_model), "query", query, NULL);
+		rhythmdb_query_model_reapply_query (query_model, FALSE);
+		g_object_unref (G_OBJECT (query_model));
 	} else {
-		GPtrArray *query;
-	
+		/* otherwise build a query based on the search text and feed it to the browser */
 		query_model = rhythmdb_query_model_new_empty (source->priv->db);
-
-		query = construct_query_from_selection (source);
+		rb_library_browser_set_model (source->priv->browser, query_model, TRUE);
 		rhythmdb_do_full_query_async_parsed (source->priv->db, 
 						     RHYTHMDB_QUERY_RESULTS (query_model), 
-						     query);
-		rhythmdb_query_free (query);
+						     query); 
+		g_object_unref (G_OBJECT (query_model));
 	}
-
-	rb_debug ("setting query model");
-	rb_entry_view_set_model (source->priv->songs, query_model);
-	g_object_set (RB_SOURCE (source), "query-model", query_model, NULL);
-
-	g_object_unref (G_OBJECT (query_model));
+	rhythmdb_query_free (query); 
 }
 
-static void
-songs_view_drag_data_received_cb (GtkWidget *widget,
-				  GdkDragContext *dc,
-				  gint x, gint y,
-				  GtkSelectionData *selection_data,
-				  guint info, guint time,
-				  RBLibrarySource *source)
-{
-	rb_debug ("data dropped on the library source song view");
-	rb_source_receive_drag (RB_SOURCE (source), selection_data);
-}
-
-static void
-rb_library_source_browser_changed_cb (RBLibraryBrowser *entry, RBLibrarySource *source)
-{
-	rb_library_source_do_query (source);
-	rb_source_notify_filter_changed (RB_SOURCE (source));
-}
diff -rN -u -p old-sblb/sources/rb-static-playlist-source.c new-sblb/sources/rb-static-playlist-source.c
--- old-sblb/sources/rb-static-playlist-source.c	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/sources/rb-static-playlist-source.c	2006-03-13 23:02:26.000000000 +1000
@@ -38,6 +38,7 @@
 
 static GObject *rb_static_playlist_source_constructor (GType type, guint n_construct_properties,
 						       GObjectConstructParam *construct_properties);
+static void rb_static_playlist_source_dispose (GObject *object);
 static void rb_static_playlist_source_finalize (GObject *object);
 
 /* source methods */
@@ -48,6 +49,7 @@ static void impl_search (RBSource *asour
 static void impl_browser_toggled (RBSource *source, gboolean enabled);
 static void impl_reset_filters (RBSource *asource);
 static gboolean impl_receive_drag (RBSource *source, GtkSelectionData *data);
+static GPtrArray *construct_query_from_selection (RBStaticPlaylistSource *source);
 
 /* playlist methods */
 static void impl_save_contents_to_xml (RBPlaylistSource *source,
@@ -59,7 +61,8 @@ static GList *impl_get_property_views (R
 void rb_static_playlist_source_browser_views_activated_cb (GtkWidget *widget,
 							 RBStaticPlaylistSource *source);
 static void rb_static_playlist_source_browser_changed_cb (RBLibraryBrowser *entry,
-							RBStaticPlaylistSource *source);
+							  GParamSpec *pspec,
+							  RBStaticPlaylistSource *source);
 
 static void rb_static_playlist_source_do_query (RBStaticPlaylistSource *source);
 
@@ -103,6 +106,7 @@ rb_static_playlist_source_class_init (RB
 	RBPlaylistSourceClass *playlist_class = RB_PLAYLIST_SOURCE_CLASS (klass);
 	
 	object_class->constructor = rb_static_playlist_source_constructor;
+	object_class->dispose = rb_static_playlist_source_dispose;
 	object_class->finalize = rb_static_playlist_source_finalize;
 
 	source_class->impl_can_cut = (RBSourceFeatureFunc) rb_true_function;
@@ -139,6 +143,21 @@ rb_static_playlist_source_init (RBStatic
 }
 
 static void
+rb_static_playlist_source_dispose (GObject *object)
+{
+	RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object);
+	if (!priv)
+		return;
+
+	if (priv->base_model) {
+		g_object_unref (G_OBJECT (priv->base_model));
+		priv->base_model = NULL;
+	}
+
+	G_OBJECT_CLASS (rb_static_playlist_source_parent_class)->finalize (object);
+}
+
+static void
 rb_static_playlist_source_finalize (GObject *object)
 {
 	RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object);
@@ -161,16 +180,17 @@ rb_static_playlist_source_constructor (G
 
 	priv->base_model = rb_playlist_source_get_query_model (RB_PLAYLIST_SOURCE (psource));
 	g_object_set (G_OBJECT (priv->base_model), "show-hidden", TRUE, NULL);
+	g_object_ref (G_OBJECT (priv->base_model));
 
 	priv->paned = gtk_vpaned_new ();
 
 	priv->browser = rb_library_browser_new (rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source)));
 	gtk_paned_pack1 (GTK_PANED (priv->paned), GTK_WIDGET (priv->browser), TRUE, FALSE);
-	g_signal_connect_object (G_OBJECT (priv->browser), "changed",
+	g_signal_connect_object (G_OBJECT (priv->browser), "notify::output-model",
 				 G_CALLBACK (rb_static_playlist_source_browser_changed_cb),
 				 source, 0);
 
-	rb_library_browser_set_model (priv->browser, priv->base_model);	
+	rb_library_browser_set_model (priv->browser, priv->base_model, FALSE);
 	rb_static_playlist_source_do_query (source);
 			 
 	/* reparent the entry view */
@@ -304,23 +324,25 @@ static void
 impl_search (RBSource *source, const char *search_text)
 {
 	RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source);
+	char *old_search_text = NULL;
 
 	if (search_text == NULL && priv->search_text == NULL)
 		return;
-	if (search_text != NULL && priv->search_text != NULL &&
-	    !strcmp (search_text, priv->search_text))
+	if (search_text != NULL && priv->search_text != NULL
+	    && !strcmp (search_text, priv->search_text))
 		return;
 
-	if (search_text[0] == '\0')
-		search_text = NULL;
+	rb_debug ("doing search for \"%s\"", search_text[0] != '\0' ? search_text : "(NULL)");
 
-	rb_debug ("doing search for \"%s\"", search_text ? search_text : "(NULL)");
+	old_search_text = priv->search_text;
+	if (search_text[0] == '\0') {
+		priv->search_text = NULL;
+	} else {
+		priv->search_text = g_strdup (search_text);
+	}
+	g_free (old_search_text);
 
-	g_free (priv->search_text);
-	priv->search_text = g_strdup (search_text);
 	rb_static_playlist_source_do_query (RB_STATIC_PLAYLIST_SOURCE (source));
-
-	rb_source_notify_filter_changed (source);
 }
 
 static GList *
@@ -347,43 +369,62 @@ impl_browser_toggled (RBSource *source, 
 		gtk_widget_hide (GTK_WIDGET (priv->browser));
 }
 
-static void
-rb_static_playlist_source_do_query (RBStaticPlaylistSource *source)
+static GPtrArray *
+construct_query_from_selection (RBStaticPlaylistSource *source)
 {
 	RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source);
 	RBPlaylistSource *psource = RB_PLAYLIST_SOURCE (source);
-	RhythmDB *db = rb_playlist_source_get_db (psource);
+	RhythmDB *db = rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (psource));
 	GPtrArray *query = NULL;
-	GPtrArray *browser_query;
-	
-	if (priv->filter_model)
-		g_object_unref (priv->filter_model);
-	priv->filter_model = rhythmdb_query_model_new_empty (db);
-	g_object_set (G_OBJECT (priv->filter_model), "base-model", priv->base_model, NULL);
 
 	query = g_ptr_array_new();
 
 	if (priv->search_text) {
 		rhythmdb_query_append (db,
 				       query,
-				       RHYTHMDB_QUERY_PROP_LIKE, RHYTHMDB_PROP_SEARCH_MATCH, priv->search_text,
+				       RHYTHMDB_QUERY_PROP_LIKE,
+				       RHYTHMDB_PROP_SEARCH_MATCH,
+				       priv->search_text,
 				       RHYTHMDB_QUERY_END);
 	}
 
-	browser_query = rb_library_browser_construct_query (priv->browser);
-	rhythmdb_query_concatenate (query, browser_query);
-	rhythmdb_query_free (browser_query);
+	return query;
+}
 
+static void
+rb_static_playlist_source_do_query (RBStaticPlaylistSource *source)
+{
+	RBStaticPlaylistSourcePrivate *priv = RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source);
+	RBPlaylistSource *psource = RB_PLAYLIST_SOURCE (source);
+	RhythmDB *db = rb_playlist_source_get_db (psource);
+	GPtrArray *query;
+	
+	if (priv->filter_model)
+		g_object_unref (priv->filter_model);
+	priv->filter_model = rhythmdb_query_model_new_empty (db);
+	g_object_set (G_OBJECT (priv->filter_model), "base-model", priv->base_model, NULL);
+
+	query = construct_query_from_selection (source);
 	g_object_set (G_OBJECT (priv->filter_model), "query", query, NULL);
 	rhythmdb_query_free (query);
+
 	rhythmdb_query_model_reapply_query (priv->filter_model, TRUE);
-	rb_playlist_source_set_query_model (psource, priv->filter_model);
+	rb_library_browser_set_model (priv->browser, priv->filter_model, FALSE);
 }
 
 static void
-rb_static_playlist_source_browser_changed_cb (RBLibraryBrowser *entry, RBStaticPlaylistSource *source)
+rb_static_playlist_source_browser_changed_cb (RBLibraryBrowser *browser, 
+					      GParamSpec *pspec,
+					      RBStaticPlaylistSource *source)
 {
-	rb_static_playlist_source_do_query (source);
+	RBEntryView *songs = rb_source_get_entry_view (RB_SOURCE (source));
+	RhythmDBQueryModel *query_model;
+	
+	g_object_get (G_OBJECT (browser), "output-model", &query_model, NULL);
+	rb_entry_view_set_model (songs, query_model);
+	rb_playlist_source_set_query_model (RB_PLAYLIST_SOURCE (source), query_model);
+	g_object_unref (G_OBJECT (query_model));
+	
 	rb_source_notify_filter_changed (RB_SOURCE (source));
 }
 
diff -rN -u -p old-sblb/widgets/rb-library-browser.c new-sblb/widgets/rb-library-browser.c
--- old-sblb/widgets/rb-library-browser.c	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/widgets/rb-library-browser.c	2006-03-13 23:02:26.000000000 +1000
@@ -52,7 +52,6 @@ static void rb_library_browser_get_prope
 					     GValue *value,
 					     GParamSpec *pspec);
 
-static void rb_library_browser_notify_changed (RBLibraryBrowser *widget);
 static void view_property_selected_cb (RBPropertyView *view,
 				       GList *selection,
 				       RBLibraryBrowser *widget);
@@ -73,7 +72,8 @@ G_DEFINE_TYPE (RBLibraryBrowser, rb_libr
 typedef struct
 {
 	RhythmDB *db;
-	RhythmDBQueryModel *model;
+	RhythmDBQueryModel *input_model;
+	RhythmDBQueryModel *output_model;
 
 	guint browser_view_notify_id;
 	GSList *browser_views_group;
@@ -85,18 +85,12 @@ typedef struct
 
 enum
 {
-	CHANGED,
-	LAST_SIGNAL
-};
-
-enum
-{
 	PROP_0,
-	PROP_DB
+	PROP_DB,
+	PROP_INPUT_MODEL,
+	PROP_OUTPUT_MODEL
 };
 
-static guint rb_library_browser_signals[LAST_SIGNAL] = { 0 };
-
 typedef struct {
 	RhythmDBPropType type;
 	const char *name;
@@ -126,16 +120,21 @@ rb_library_browser_class_init (RBLibrary
 							      "RhythmDB instance",
 							      RHYTHMDB_TYPE,
 							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	g_object_class_install_property (object_class,
+					 PROP_INPUT_MODEL,
+					 g_param_spec_object ("input-model",
+							      "input-model",
+							      "input RhythmDBQueryModel instance",
+							      RHYTHMDB_TYPE_QUERY_MODEL,
+							      G_PARAM_READABLE));
+	g_object_class_install_property (object_class,
+					 PROP_OUTPUT_MODEL,
+					 g_param_spec_object ("output-model",
+							      "output-model",
+							      "output RhythmDBQueryModel instance",
+							      RHYTHMDB_TYPE_QUERY_MODEL,
+							      G_PARAM_READABLE));
 
-	rb_library_browser_signals[CHANGED] =
-		g_signal_new ("changed",
-			      G_OBJECT_CLASS_TYPE (object_class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (RBLibraryBrowserClass, changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE,
-			      0);
 
 	g_type_class_add_private (klass, sizeof (RBLibraryBrowserPrivate));
 }
@@ -248,6 +247,12 @@ rb_library_browser_get_property (GObject
 	case PROP_DB:
 		g_value_set_object (value, priv->db);
 		break;
+	case PROP_INPUT_MODEL:
+		g_value_set_object (value, priv->input_model);
+		break;
+	case PROP_OUTPUT_MODEL:
+		g_value_set_object (value, priv->output_model);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -332,12 +337,6 @@ view_selection_reset_cb (RBPropertyView 
 }
 
 static void
-rb_library_browser_notify_changed (RBLibraryBrowser *widget)
-{
-	g_signal_emit (G_OBJECT (widget), rb_library_browser_signals[CHANGED], 0);
-}
-
-static void
 reset_view_cb (RhythmDBPropType prop, RBPropertyView *view, RBLibraryBrowser *widget)
 {
 	rb_property_view_set_selection (view, NULL);
@@ -411,59 +410,179 @@ prop_to_index (RhythmDBPropType type)
 }
 
 static void
-rebuild_child_model (RBLibraryBrowser *widget, gint property_index)
+ignore_selection_changes (RBLibraryBrowser *widget, RBPropertyView *view, gboolean block)
+{
+	if (block) {
+		g_signal_handlers_block_by_func (view, view_selection_reset_cb, widget);
+		g_signal_handlers_block_by_func (view, view_property_selected_cb, widget);
+	} else {
+		g_signal_handlers_unblock_by_func (view, view_selection_reset_cb, widget);
+		g_signal_handlers_unblock_by_func (view, view_property_selected_cb, widget);
+	}
+}
+
+typedef struct {
+	RBLibraryBrowser *widget;
+	RBPropertyView *view;
+	GList *selections;
+	RhythmDBQueryModel *model;
+	guint handler_id;
+} SelectionRestoreData;
+
+static void
+selection_restore_data_destroy (SelectionRestoreData *data)
+{
+	g_object_unref (G_OBJECT (data->widget));
+	g_free (data);
+}
+
+static void
+query_complete_cb (RhythmDBQueryModel *model,
+		   SelectionRestoreData *data)
+{
+	ignore_selection_changes (data->widget, data->view, FALSE);
+	rb_property_view_set_selection (data->view, data->selections);
+
+	g_signal_handler_disconnect (data->model, data->handler_id);
+}
+
+static void
+restore_selection (RBLibraryBrowser *widget,
+		   gint property_index,
+		   gboolean query_pending)
+{
+	RBLibraryBrowserPrivate *priv = RB_LIBRARY_BROWSER_GET_PRIVATE (widget);
+	RBPropertyView *view;
+	GList *selections;
+	SelectionRestoreData *data;
+
+	view = g_hash_table_lookup (priv->property_views, (gpointer)browser_properties[property_index].type);
+	selections = g_hash_table_lookup (priv->selections, (gpointer)browser_properties[property_index].type);
+
+	if (query_pending) {
+		g_object_ref (G_OBJECT (widget));
+
+		data = g_new0 (SelectionRestoreData, 1);
+		data->widget = widget;
+		data->view = view;
+		data->selections = selections;
+		data->model = priv->input_model;
+
+		data->handler_id = 
+			g_signal_connect_data (priv->input_model,
+					       "complete",
+					       G_CALLBACK (query_complete_cb),
+					       data,
+					       (GClosureNotify) selection_restore_data_destroy,
+					       0);
+	} else {
+		ignore_selection_changes (widget, view, FALSE);
+		rb_property_view_set_selection (view, selections);
+	}
+}
+
+static void
+rebuild_output_model (RBLibraryBrowser *widget)
+{
+	RBLibraryBrowserPrivate *priv = RB_LIBRARY_BROWSER_GET_PRIVATE (widget);
+	RBPropertyView *view;
+	RhythmDBPropertyModel *prop_model;
+	int prop_index = num_browser_properties - 1;
+	GList *selections;
+	RhythmDBQueryModel *base_model;
+	GPtrArray *query;
+
+	if (priv->output_model)
+		g_object_unref (G_OBJECT (priv->output_model));
+
+	/* get the query model for the previous property view */
+	view = g_hash_table_lookup (priv->property_views, (gpointer)browser_properties[prop_index].type);
+	prop_model = rb_property_view_get_model (view);
+	g_object_get (G_OBJECT (prop_model), "query-model", &base_model, NULL);
+	g_object_unref (G_OBJECT (prop_model));
+
+	selections = g_hash_table_lookup (priv->selections, (gpointer)browser_properties[prop_index].type);
+	if (selections != NULL) {
+		query = g_ptr_array_new ();
+		rhythmdb_query_append_prop_multiple (priv->db,
+						     query,
+						     browser_properties[prop_index].type,
+						     selections);
+
+		priv->output_model = rhythmdb_query_model_new_empty (priv->db);
+		g_object_set (G_OBJECT (priv->output_model), "base-model", base_model, NULL);
+
+
+		g_object_set (G_OBJECT (priv->output_model), "query", query, NULL);
+		rhythmdb_query_model_reapply_query (priv->output_model, TRUE);
+		rhythmdb_query_free (query);
+	} else {
+		priv->output_model = base_model;
+		g_object_ref (G_OBJECT (priv->output_model));
+	}
+
+	g_object_notify (G_OBJECT (widget), "output-model");
+	g_object_unref (G_OBJECT (base_model));
+}
+
+static void
+rebuild_child_model (RBLibraryBrowser *widget, gint property_index, gboolean query_pending)
 {
 	RBLibraryBrowserPrivate *priv = RB_LIBRARY_BROWSER_GET_PRIVATE (widget);
 	RhythmDBPropertyModel *prop_model;
 	RhythmDBQueryModel *base_model, *child_model;
 	RBPropertyView *view;
 	GPtrArray *query;
-	GList *selections, *saved_selections;
+	GList *selections;
 
 	g_assert (property_index >= 0);
 	g_assert (property_index < num_browser_properties);
 
 	/* there is no model after the last one to update*/
-	if (property_index == num_browser_properties - 1)
+	if (property_index == num_browser_properties - 1) {
+		rebuild_output_model (widget);
 		return;
+	}
 
-	/* save the selections of the next model */
-	saved_selections = g_hash_table_lookup (priv->selections,
-						(gpointer)browser_properties[property_index+1].type);
-	saved_selections = rb_string_list_copy (saved_selections);
-			
 	/* get the query model for the previous property view */
 	view = g_hash_table_lookup (priv->property_views, (gpointer)browser_properties[property_index].type);
 	prop_model = rb_property_view_get_model (view);
 	g_object_get (G_OBJECT (prop_model), "query-model", &base_model, NULL);
+	g_object_unref (G_OBJECT (prop_model));
 
 	/* create a new query model based on it, filtered by the selections of the previous property view */
 	selections = g_hash_table_lookup (priv->selections, (gpointer)browser_properties[property_index].type);
-	query = g_ptr_array_new ();
-	rhythmdb_query_append_prop_multiple (priv->db,
-					     query,
-					     browser_properties[property_index].type,
-					     selections);
-
-	child_model = rhythmdb_query_model_new_empty (priv->db);
-	g_object_set (G_OBJECT (child_model), "base-model", base_model, NULL);
-	g_object_unref (G_OBJECT (base_model));
-
-	g_object_set (G_OBJECT (child_model), "query", query, NULL);
-	rhythmdb_query_model_reapply_query (child_model, TRUE);
-	rhythmdb_query_free (query);
+	if (selections != NULL) {
+		query = g_ptr_array_new ();
+		rhythmdb_query_append_prop_multiple (priv->db,
+						     query,
+						     browser_properties[property_index].type,
+						     selections);
+
+		child_model = rhythmdb_query_model_new_empty (priv->db);
+		g_object_set (G_OBJECT (child_model), "base-model", base_model, NULL);
+
+		g_object_set (G_OBJECT (child_model), "query", query, NULL);
+		rhythmdb_query_model_reapply_query (child_model, TRUE);
+		rhythmdb_query_free (query);
+	} else {
+		child_model = base_model;
+	}
 	
 	/* apply it as the query model of the current property view */
 	view = g_hash_table_lookup (priv->property_views, (gpointer)browser_properties[property_index+1].type);
+	ignore_selection_changes (widget, view, TRUE);
+
 	prop_model = rb_property_view_get_model (view);
 	g_object_set (G_OBJECT (prop_model), "query-model", child_model, NULL);
-	g_object_unref (G_OBJECT (child_model));
+	g_object_unref (G_OBJECT (prop_model));
 
-	rebuild_child_model (widget, property_index + 1);
+	g_object_unref (G_OBJECT (base_model));
+	if (child_model != base_model)
+		g_object_unref (G_OBJECT (child_model));
 
-	/* restore the old selection */
-	rb_property_view_set_selection (view, saved_selections);
-	rb_list_deep_free (saved_selections);
+	rebuild_child_model (widget, property_index + 1, query_pending);
+	restore_selection (widget, property_index + 1, query_pending);
 }
 
 void
@@ -482,8 +601,7 @@ rb_library_browser_set_selection (RBLibr
 	else
 		g_hash_table_remove (priv->selections, (gpointer)type);
 
-	rebuild_child_model (widget, prop_to_index (type));
-	rb_library_browser_notify_changed (widget);
+	rebuild_child_model (widget, prop_to_index (type), FALSE);
 }
 
 GList*
@@ -495,21 +613,28 @@ rb_library_browser_get_property_views (R
 }
 
 void
-rb_library_browser_set_model (RBLibraryBrowser *widget, RhythmDBQueryModel *model)
+rb_library_browser_set_model (RBLibraryBrowser *widget, 
+			      RhythmDBQueryModel *model,
+			      gboolean query_pending)
 {
 	RBLibraryBrowserPrivate *priv = RB_LIBRARY_BROWSER_GET_PRIVATE (widget);
 	RBPropertyView *view;
 	RhythmDBPropertyModel *prop_model;
-	
-	if (priv->model)
-		g_object_unref (G_OBJECT (priv->model));
 
-	priv->model = model;
-	g_object_ref (model);
+	if (priv->input_model)
+		g_object_unref (G_OBJECT (priv->input_model));
+
+	priv->input_model = model;
+	g_object_ref (G_OBJECT (model));
 
 	view = g_hash_table_lookup (priv->property_views, (gpointer)browser_properties[0].type);
+	ignore_selection_changes (widget, view, TRUE);
+
 	prop_model = rb_property_view_get_model (view);
-	g_object_set (G_OBJECT (prop_model), "query-model", priv->model, NULL);
+	g_object_set (G_OBJECT (prop_model), "query-model", priv->input_model, NULL);
+	g_object_unref (G_OBJECT (prop_model));
 
-	rebuild_child_model (widget, 0);
+	rebuild_child_model (widget, 0, query_pending);
+	restore_selection (widget, 0, query_pending);
 }
+
diff -rN -u -p old-sblb/widgets/rb-library-browser.h new-sblb/widgets/rb-library-browser.h
--- old-sblb/widgets/rb-library-browser.h	2006-03-13 23:02:26.000000000 +1000
+++ new-sblb/widgets/rb-library-browser.h	2006-03-13 23:02:26.000000000 +1000
@@ -44,14 +44,14 @@ typedef struct
 typedef struct
 {
 	GtkHBoxClass parent;
-
-	void (*changed) (RBLibraryBrowser *entry);
 } RBLibraryBrowserClass;
 
-GType		rb_library_browser_get_type (void);
+GType			rb_library_browser_get_type (void);
 RBLibraryBrowser *	rb_library_browser_new      (RhythmDB *db);
 
-void rb_library_browser_set_model (RBLibraryBrowser *widget, RhythmDBQueryModel *model);
+void 			rb_library_browser_set_model (RBLibraryBrowser *widget, 
+						      RhythmDBQueryModel *model,
+						      gboolean query_pending);
 
 gboolean rb_library_browser_reset (RBLibraryBrowser *widget);
 GPtrArray* rb_library_browser_construct_query (RBLibraryBrowser *widget);

