--- rhythmbox-0.8.8/widgets/rb-property-view.c	2005-02-08 18:41:59.207072477 +0100
+++ rhythmbox-0.8.8.perso/widgets/rb-property-view.c	2005-02-08 18:34:17.000000000 +0100
@@ -108,9 +108,26 @@
 
 static guint rb_property_view_signals[LAST_SIGNAL] = { 0 };
 
-static const GtkTargetEntry target_album  [] = { { "text/x-rhythmbox-album",  0, 0 } };
-static const GtkTargetEntry target_genre  [] = { { "text/x-rhythmbox-genre",  0, 0 } };
-static const GtkTargetEntry target_artist [] = { { "text/x-rhythmbox-artist", 0, 0 } };
+enum {
+	TARGET_ALBUMS,
+	TARGET_GENRE,
+	TARGET_ARTISTS,
+	TARGET_URIS,
+};
+
+#define N_TARGETS 2
+static const GtkTargetEntry targets_album  [N_TARGETS] = {
+	{ "text/x-rhythmbox-album",  0, TARGET_ALBUMS },
+	{ "text/uri-list", 0, TARGET_URIS },
+};
+static const GtkTargetEntry targets_genre  [N_TARGETS] = {
+	{ "text/x-rhythmbox-genre",  0, TARGET_GENRE },
+	{ "text/uri-list", 0, TARGET_URIS },
+};
+static const GtkTargetEntry targets_artist [N_TARGETS] = {
+	{ "text/x-rhythmbox-artist", 0, TARGET_ARTISTS },
+	{ "text/uri-list", 0, TARGET_URIS },
+};
 
 GType
 rb_property_view_get_type (void)
@@ -463,25 +480,129 @@
 	g_free (str);
 }
 
+/*Going through hoops to avoid nested functions*/
+struct QueryModelCbStruct { RhythmDB* db; GString* reply; }; 
+static gboolean query_model_cb (GtkTreeModel *query_model,
+	GtkTreePath *path, GtkTreeIter *iter,
+	struct QueryModelCbStruct *data);
+static gboolean query_model_cb (GtkTreeModel *query_model,
+	GtkTreePath *path, GtkTreeIter *iter,
+	struct QueryModelCbStruct *data) {
+	const char* uri;
+	RhythmDBEntry* entry;
+
+	gtk_tree_model_get (query_model, iter, 0, &entry, -1);
+	uri = rhythmdb_entry_get_string (data->db, entry, RHYTHMDB_PROP_LOCATION);
+	g_string_append (data->reply, uri);
+	g_string_append (data->reply, "\r\n");
+
+	rhythmdb_entry_unref (data->db, entry);
+	return (FALSE);
+}
 
 static void
 rb_property_view_drag_data_get (GtkWidget *widget, GdkDragContext *context,
-				GtkSelectionData *selection_data, guint info,
-				guint time, gpointer data)
+                                GtkSelectionData *selection_data, guint info,
+                                guint time, gpointer data)
 {
-        const char *str;
-        RBPropertyView *view;
-        GtkTreeModel *model;
-        GtkTreeIter iter;
-        GList *selected_rows;
-
-        view = RB_PROPERTY_VIEW (data);
-
-        selected_rows = gtk_tree_selection_get_selected_rows (view->priv->selection, &model);
-        g_assert (gtk_tree_model_get_iter (model, &iter, selected_rows->data));
-        gtk_tree_model_get(model, &iter, 0, &str, -1);
-        gtk_selection_data_set (selection_data, selection_data->target,
-                                8, str, strlen (str));
+	if (info == TARGET_URIS) {
+		/*We get all entries for selected property entries - other filters that have been set don't apply, the user can have them by selecting all then dragging from the entry view*/
+		RBPropertyView* view;
+			view = RB_PROPERTY_VIEW (data);
+		RhythmDB* db = view->priv->db;
+		
+		GList* selected_rows;
+		GtkTreeModel* query_model = GTK_TREE_MODEL (rhythmdb_query_model_new_empty(db));
+		GtkTreeModel* model;
+		GPtrArray* subquery = g_ptr_array_new();
+		GString* reply = g_string_new ("");
+		GList* row;
+		GtkTreeIter iter;
+		gboolean is_all;
+
+		selected_rows = gtk_tree_selection_get_selected_rows (
+			view->priv->selection, &model);
+
+		gtk_tree_model_get_iter (model, &iter, (GtkTreePath*)selected_rows->data);		
+		gtk_tree_model_get (model, &iter,
+				RHYTHMDB_PROPERTY_MODEL_COLUMN_PRIORITY, &is_all, -1);
+		if (!is_all) {
+			for (row=selected_rows; row; row = row->next) {
+				gtk_tree_model_get_iter (model, &iter, (GtkTreePath*)row->data);
+				char* name;
+
+				gtk_tree_model_get (model, &iter,
+					RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE, &name, -1);
+				if (row->next) {
+					rhythmdb_query_append (db, subquery,
+							RHYTHMDB_QUERY_PROP_EQUALS,
+								view->priv->propid, name,
+						RHYTHMDB_QUERY_DISJUNCTION,
+						RHYTHMDB_QUERY_END);				
+				} else {
+					rhythmdb_query_append (db, subquery,
+							RHYTHMDB_QUERY_PROP_EQUALS,
+								view->priv->propid, name,
+						RHYTHMDB_QUERY_END);				
+				}
+
+				g_free (name);
+			}
+			/*filter out radios*/
+			rhythmdb_do_full_query (db, query_model,
+					RHYTHMDB_QUERY_PROP_EQUALS,
+						RHYTHMDB_PROP_TYPE, RHYTHMDB_ENTRY_TYPE_SONG,
+					RHYTHMDB_QUERY_SUBQUERY,
+						subquery,
+				RHYTHMDB_QUERY_END);
+		} else {
+			/*filter out radios*/
+			rhythmdb_do_full_query (db, query_model,
+					RHYTHMDB_QUERY_PROP_EQUALS,
+						RHYTHMDB_PROP_TYPE, RHYTHMDB_ENTRY_TYPE_SONG,
+				RHYTHMDB_QUERY_END);			
+		}
+
+		g_list_foreach (selected_rows, (GFunc)gtk_tree_path_free, NULL);
+		g_list_free (selected_rows);
+
+		struct QueryModelCbStruct tmp;
+			tmp.db = db; tmp.reply = reply;
+		/*Too bad that we're on the main thread. Why doesn't gtk call us async?
+		How does file-roller manage? - it seems it refuses the drop when it isn't done unpacking. In which case, we should tweak the drop acknowledgement, and prepare the query using do_full_query_async. The query would be hooked to the drag context.*/
+		gtk_tree_model_foreach (query_model,
+			(GtkTreeModelForeachFunc)query_model_cb,
+			&tmp);
+		
+		g_object_unref (query_model);
+
+		gtk_selection_data_set (selection_data,
+		                        selection_data->target,
+		                        8, reply->str,
+		                        reply->len);
+		g_string_free (reply, TRUE);
+	} else {
+		/*We could add more cases and more targets, like an albums target for artists. OTOH, no one uses these targets for now, so they could be completely removed*/
+		/*The part below doesn't allow multiple selection - delete it?*/
+		RBPropertyView *view;
+
+		GtkTreeIter iter;
+		char* title;
+		GtkTreeModel *model;
+		GList *rows;
+
+		view = RB_PROPERTY_VIEW (data);
+		rows = gtk_tree_selection_get_selected_rows (view->priv->selection, &model);
+		gtk_tree_model_get_iter (model, &iter, (GtkTreePath*)rows->data);
+		gtk_tree_model_get (model, &iter,
+				RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE, &title, -1);
+		gtk_selection_data_set (selection_data, selection_data->target,
+		                        8, title, strlen(title));
+
+		g_free (title);
+		g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
+		g_list_free (rows);
+	}
 }
 
 static GObject *
@@ -494,7 +615,7 @@
 	RBPropertyView *view;
 	RBPropertyViewClass *klass;
 	GObjectClass *parent_class; 
-	const GtkTargetEntry *target;
+	const GtkTargetEntry *targets;
  
 
 
@@ -511,25 +632,25 @@
         switch (view->priv->propid)
 	{
 	case RHYTHMDB_PROP_GENRE:
-		target = target_genre;
+		targets = targets_genre;
 		break;
         case RHYTHMDB_PROP_ALBUM:
-                target = target_album;
+                targets = targets_album;
 		break;
         case RHYTHMDB_PROP_ARTIST:
-                target = target_artist;
+                targets = targets_artist;
 		break;
 	default:
-		target = NULL;
+		targets = NULL;
 		g_assert_not_reached ();
 	}
 
         gtk_drag_source_set (GTK_WIDGET(view->priv->treeview),
                              GDK_BUTTON1_MASK,
-                             target, 1,
+                             targets, N_TARGETS,
                              GDK_ACTION_COPY);
 
-        g_signal_connect_object (G_OBJECT (view->priv->treeview), "drag_data_get",
+	g_signal_connect_object (G_OBJECT (view->priv->treeview), "drag_data_get",
 				 G_CALLBACK (rb_property_view_drag_data_get), view, 0);
 
 	g_signal_connect_object (G_OBJECT (view->priv->treeview),
@@ -658,3 +779,4 @@
 		}
 	}
 }
+
--- rhythmbox-0.8.8/rhythmdb/rhythmdb.h	2005-02-08 18:41:59.208072337 +0100
+++ rhythmbox-0.8.8.perso/rhythmdb/rhythmdb.h	2005-02-04 14:27:29.000000000 +0100
@@ -164,7 +164,7 @@
 						 const char *uri);
 
 	void		(*impl_entry_set)	(RhythmDB *db, RhythmDBEntry *entry,
-						 guint propid, const GValue *value);
+	                                 guint propid, const GValue *value);
 
 	void		(*impl_entry_get)	(RhythmDB *db, RhythmDBEntry *entry,
 						 guint propid, GValue *value);
@@ -270,12 +270,19 @@
 /**
  * Returns a freshly allocated GtkTreeModel which represents the query.
  * The extended arguments alternate between RhythmDBQueryType args
- * and their values.  Here's an example:
- *
- * rhythmdb_do_full_query (db, RHYTHMDB_QUERY_PROP_EQUALS, "genre", "Classical",
- *                          RHYTHMDB_QUERY_PROP_GREATER, "rating", 5,
- *                          RHYTHMDB_QUERY_END);
+ * and their values. Items are prioritized like algebraic expressions, and
+ * implicitly ANDed. Here's an example:
  *
+rhythmdb_do_full_query (db,
+			RHYTHMDB_QUERY_PROP_EQUALS,
+ 				RHYTHMDB_PROP_ARTIST, "Pink Floyd",
+		RHYTHMDB_QUERY_DISJUNCTION,
+			RHYTHMDB_QUERY_PROP_EQUALS,
+				RHYTHMDB_PROP_GENRE, "Classical",
+			RHYTHMDB_QUERY_PROP_GREATER,
+				RHYTHMDB_PROP_RATING, 5,
+	RHYTHMDB_QUERY_END);
+ * Which means: artist = Pink Floyd OR (genre = Classical AND rating >= 5)
  */
 void		rhythmdb_do_full_query			(RhythmDB *db,
 							 GtkTreeModel *main_model,
