[Muine] Patch - Drag and drop



I wrote this patch a while ago, but as Jorn has been real busy, I
figured I should spread some love to the list.

It drag-and-drops the hell out of Muine.  Songs and playlists can be
dragged to and from any of the dialogs to anywhere.

It's my first foray into C#, so it might be kinda sucky.  Jorn said he
was going to revise it to make it not so sucky.

-s.
? dnd_source.diff
? muine-dnd-.diff
? muine-dnd-1089930316.diff
? muine-dnd-1089932158.diff
? muine-dnd-1090021855.diff
? m4/gnome-common.m4
? src/dnd_files.diff
Index: libmuine/pointer-list-model.c
===================================================================
RCS file: /cvs/gnome/muine/libmuine/pointer-list-model.c,v
retrieving revision 1.5
diff -u -r1.5 pointer-list-model.c
--- libmuine/pointer-list-model.c	14 Feb 2004 21:10:27 -0000	1.5
+++ libmuine/pointer-list-model.c	16 Jul 2004 23:50:59 -0000
@@ -218,7 +218,7 @@
 {
   g_return_val_if_fail (IS_POINTER_LIST_MODEL (drag_source), FALSE);
 
-  return (POINTER_LIST_MODEL (drag_source)->sort_func == NULL);
+  return TRUE;
 }
   
 static gboolean
@@ -546,6 +546,33 @@
   path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
   gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
   gtk_tree_path_free (path);
+
+  return TRUE;
+}
+
+gboolean
+pointer_list_model_insert (PointerListModel *model, gpointer pointer, gpointer ins) 
+{
+  GtkTreeIter iter, iter2;
+  GtkTreePath *path;
+  GSequencePtr new_ptr;
+ 
+  new_ptr = g_sequence_append (model->pointers, pointer);
+
+  if ( pointer_list_model_pointer_get_iter(model, ins, &iter2))
+
+  put_before(model, new_ptr, g_sequence_ptr_next(iter2.user_data));
+
+  g_hash_table_insert (model->reverse_map, pointer, new_ptr);
+    
+  iter.stamp = model->stamp;
+  iter.user_data = new_ptr;
+  
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+  gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
+  gtk_tree_path_free (path);
+
+  
 
   return TRUE;
 }
Index: libmuine/pointer-list-model.h
===================================================================
RCS file: /cvs/gnome/muine/libmuine/pointer-list-model.h,v
retrieving revision 1.4
diff -u -r1.4 pointer-list-model.h
--- libmuine/pointer-list-model.h	11 Feb 2004 18:22:58 -0000	1.4
+++ libmuine/pointer-list-model.h	16 Jul 2004 23:50:59 -0000
@@ -60,6 +60,9 @@
 GtkTreeModel *pointer_list_model_new            (void);
 gboolean      pointer_list_model_add            (PointerListModel *model,
 					         gpointer          pointer);
+gboolean      pointer_list_model_insert         (PointerListModel *model,
+						 gpointer          pointer,
+						 gpointer          ins);
 void          pointer_list_model_remove         (PointerListModel *model,
 					         gpointer          pointer);
 void          pointer_list_model_remove_iter    (PointerListModel *model,
Index: libmuine/pointer-list-view.c
===================================================================
RCS file: /cvs/gnome/muine/libmuine/pointer-list-view.c,v
retrieving revision 1.23
diff -u -r1.23 pointer-list-view.c
--- libmuine/pointer-list-view.c	9 Apr 2004 10:16:53 -0000	1.23
+++ libmuine/pointer-list-view.c	16 Jul 2004 23:51:01 -0000
@@ -246,6 +246,14 @@
 }
 
 void
+pointer_list_view_insert (PointerListView *view,
+			  gpointer pointer,
+			  gpointer ins)
+{
+  pointer_list_model_insert (view->model, pointer, ins);
+}
+
+void
 pointer_list_view_changed (PointerListView *view,
 			   gpointer pointer)
 {
@@ -297,6 +305,18 @@
 
 	return pointer_list_model_get_pointer (view->model, &iter);
 }
+
+#if 0
+gpointer
+pointer_list_get_handle_from_row_reference(PointerListView *view,
+					   GtkTreeRowReference *row)
+{
+        GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(row);
+	gpointer pointer = pointer_list_get_handle_from_path(view, sourcerow);
+	gtk_tree_path_free(sourcerow);
+	return pointer;
+}
+#endif
 
 int
 pointer_list_view_get_length (PointerListView *view)
Index: libmuine/pointer-list-view.h
===================================================================
RCS file: /cvs/gnome/muine/libmuine/pointer-list-view.h,v
retrieving revision 1.14
diff -u -r1.14 pointer-list-view.h
--- libmuine/pointer-list-view.h	9 Apr 2004 10:16:53 -0000	1.14
+++ libmuine/pointer-list-view.h	16 Jul 2004 23:51:01 -0000
@@ -59,6 +59,9 @@
 						    gboolean expand);
 void             pointer_list_view_append          (PointerListView *view,
 				                    gpointer pointer);
+void             pointer_list_view_insert          (PointerListView *view,
+						    gpointer pointer,
+						    gpointer ins);
 void             pointer_list_view_changed         (PointerListView *view,
 			                            gpointer pointer);
 void             pointer_list_view_remove          (PointerListView *view,
@@ -69,6 +72,11 @@
 GList *          pointer_list_view_get_contents    (PointerListView *view);
 gpointer	 pointer_list_get_handle_from_path (PointerListView *view,
 						    GtkTreePath *path);
+#if 0
+gpointer         pointer_list_get_handle_from_row_reference
+						    (PointerListView *view,
+						     GtkTreeRowReference *row);
+#endif
 int              pointer_list_view_get_length      (PointerListView *view);
 gboolean         pointer_list_view_contains        (PointerListView *view,
 				                    gpointer pointer);
Index: src/AddAlbumWindow.cs
===================================================================
RCS file: /cvs/gnome/muine/src/AddAlbumWindow.cs,v
retrieving revision 1.38
diff -u -r1.38 AddAlbumWindow.cs
--- src/AddAlbumWindow.cs	20 Jun 2004 18:53:26 -0000	1.38
+++ src/AddAlbumWindow.cs	16 Jul 2004 23:51:01 -0000
@@ -19,6 +19,7 @@
 
 using System;
 using System.Collections;
+using System.Runtime.InteropServices;
 
 using Gtk;
 using GLib;
@@ -44,15 +45,19 @@
 	private CellRenderer pixbuf_renderer;
 	private Gdk.Pixbuf nothing_pixbuf;
 	
-	private enum TargetType {
-		UriList,
-		Uri
-	}
-
 	private static TargetEntry [] cover_drag_entries = new TargetEntry [] {
-		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList),
-		new TargetEntry ("x-special/gnome-icon-list", 0, (uint) TargetType.UriList),
-		new TargetEntry ("_NETSCAPE_URL", 0, (uint) TargetType.Uri)
+		/* We accept MUINE_ALBUM because if we don't, dragging a row within AddAlbumWindow.view
+		 * will accept the text/uri-list and Muine will copy an entire album to /tmp before realizing
+		 * it's not an album cover */
+		new TargetEntry ("MUINE_ALBUM_LIST", TargetFlags.App, (uint) PlaylistWindow.TargetType.Album),
+		new TargetEntry ("text/uri-list", 0, (uint) PlaylistWindow.TargetType.UriList),
+		new TargetEntry ("x-special/gnome-icon-list", 0, (uint) PlaylistWindow.TargetType.UriList),
+		new TargetEntry ("_NETSCAPE_URL", 0, (uint) PlaylistWindow.TargetType.Uri)
+	};
+
+	private static TargetEntry [] source_entries = new TargetEntry [] {
+		new TargetEntry ("MUINE_ALBUM_LIST", TargetFlags.App, (uint) PlaylistWindow.TargetType.Album),
+		new TargetEntry ("text/uri-list", 0, (uint) PlaylistWindow.TargetType.UriList),
 	};
 
 	public AddAlbumWindow () : base (IntPtr.Zero)
@@ -98,6 +103,11 @@
 		text_renderer = new CellRendererText ();
 		view.AddColumn (text_renderer, new HandleView.CellDataFunc (TextCellDataFunc), true);
 
+		view.EnableModelDragSource (Gdk.ModifierType.Button1Mask, 
+					source_entries, Gdk.DragAction.Copy);
+		view.DragDataGet += new DragDataGetHandler (DragDataGetCallback);
+	
+
 		scrolledwindow.Add (view);
 
 		view.Realize ();
@@ -371,5 +381,45 @@
 		search_entry.Text = "";
 
 		process_changes_immediately = false;
+	}
+
+	[DllImport ("libgobject-2.0-0.dll")]
+	private static extern IntPtr g_object_get_data (IntPtr obj, string key);
+	private void DragDataGetCallback (object o, DragDataGetArgs args)
+	{
+		List albums = view.SelectedPointers;
+
+		switch (args.Info) {
+		case (uint) PlaylistWindow.TargetType.UriList:
+			string files = "";
+			foreach (int p in albums) {
+				IntPtr i = new IntPtr(p);
+				Album album = Album.FromHandle(i);
+				string tmpdir = System.IO.Path.GetTempPath() + StringUtils.JoinHumanReadable (album.Artists, 3) + " - " + album.Name;
+				System.IO.Directory.CreateDirectory(tmpdir);
+				foreach (Song s in album.Songs) {
+					try {
+						System.IO.File.Copy(s.Filename, tmpdir + System.IO.Path.DirectorySeparatorChar + 
+								System.IO.Path.GetFileName(s.Filename), false);
+					} catch {}
+				}
+				files += StringUtils.UriFromLocalPath(tmpdir) + "\r\n";
+			}	
+			args.SelectionData.Set(Gdk.Atom.Intern("text/uri-list", false),
+						8, System.Text.Encoding.ASCII.GetBytes(files));
+			break;	
+	
+		case (uint) PlaylistWindow.TargetType.Album:
+			string ptrs = "";
+			foreach (int p in albums) {
+				IntPtr s = new IntPtr(p);
+				ptrs += s.ToString() + "\r\n";
+			}
+			args.SelectionData.Set(Gdk.Atom.Intern("MUINE_SONG_LIST", false),
+					8, System.Text.Encoding.ASCII.GetBytes(ptrs));
+			break;
+		default:
+			break;	
+		}
 	}
 }
Index: src/AddSongWindow.cs
===================================================================
RCS file: /cvs/gnome/muine/src/AddSongWindow.cs,v
retrieving revision 1.34
diff -u -r1.34 AddSongWindow.cs
--- src/AddSongWindow.cs	20 Jun 2004 18:53:26 -0000	1.34
+++ src/AddSongWindow.cs	16 Jul 2004 23:51:02 -0000
@@ -19,6 +19,7 @@
 
 using System;
 using System.Collections;
+using System.Runtime.InteropServices;
 
 using Gtk;
 using GLib;
@@ -43,6 +44,11 @@
 	private CellRenderer text_renderer;
 
 	private static int FakeLength = 150;
+
+	private static TargetEntry [] source_entries = new TargetEntry [] {
+		new TargetEntry ("MUINE_SONG", TargetFlags.App, (uint) PlaylistWindow.TargetType.Song),
+		new TargetEntry ("text/uri-list", 0, (uint) PlaylistWindow.TargetType.UriList),
+	};
 	
 	public AddSongWindow () : base (IntPtr.Zero)
 	{
@@ -76,15 +82,19 @@
 
 		view = new HandleView ();
 
-		view.Reorderable = false;
+		text_renderer = new CellRendererText ();
+		view.AddColumn (text_renderer, new HandleView.CellDataFunc (CellDataFunc), true);
+
+
 		view.Selection.Mode = SelectionMode.Multiple;
 		view.SortFunc = new HandleView.CompareFunc (SortFunc);
 		view.RowActivated += new HandleView.RowActivatedHandler (HandleRowActivated);
 		view.SelectionChanged += new HandleView.SelectionChangedHandler (HandleSelectionChanged);
 
-		text_renderer = new CellRendererText ();
-		view.AddColumn (text_renderer, new HandleView.CellDataFunc (CellDataFunc), true);
-
+		view.EnableModelDragSource (Gdk.ModifierType.Button1Mask, 
+					source_entries, Gdk.DragAction.Copy);
+		view.DragDataGet += new DragDataGetHandler (DragDataGetCallback);
+	
 		scrolledwindow.Add (view);
 
 		view.Realize ();
@@ -322,4 +332,36 @@
 
 		process_changes_immediately = false;
 	}
+
+	[DllImport ("libgobject-2.0-0.dll")]
+	private static extern IntPtr g_object_get_data (IntPtr obj, string key);
+	private void DragDataGetCallback (object o, DragDataGetArgs args)
+	{
+		List songs = view.SelectedPointers;
+
+		switch (args.Info) {
+		case (uint) PlaylistWindow.TargetType.UriList:
+			string files = "";
+			foreach (int p in songs) {
+				IntPtr s = new IntPtr(p);
+				files += StringUtils.UriFromLocalPath(Song.FromHandle(s).Filename) + "\r\n";
+			}
+	
+			args.SelectionData.Set(Gdk.Atom.Intern("text/uri-list", false),
+						8, System.Text.Encoding.ASCII.GetBytes(files));
+			break;	
+		case (uint) PlaylistWindow.TargetType.Song:
+			string ptrs = "";
+			foreach (int p in songs) {
+				IntPtr s = new IntPtr(p);
+				ptrs += s.ToString() + "\r\n";
+			}
+			args.SelectionData.Set(Gdk.Atom.Intern("MUINE_SONG_LIST", false),
+					8, System.Text.Encoding.ASCII.GetBytes(ptrs));
+			break;
+		default:
+			break;	
+		}
+	}
+
 }
Index: src/Album.cs
===================================================================
RCS file: /cvs/gnome/muine/src/Album.cs,v
retrieving revision 1.25
diff -u -r1.25 Album.cs
--- src/Album.cs	20 Jun 2004 18:53:26 -0000	1.25
+++ src/Album.cs	16 Jul 2004 23:51:02 -0000
@@ -273,4 +273,6 @@
 
 		return (n_matches == search_bits.Length);
 	}
+	
+
 }
Index: src/CoverImage.cs
===================================================================
RCS file: /cvs/gnome/muine/src/CoverImage.cs,v
retrieving revision 1.10
diff -u -r1.10 CoverImage.cs
--- src/CoverImage.cs	5 Jun 2004 16:49:46 -0000	1.10
+++ src/CoverImage.cs	16 Jul 2004 23:51:02 -0000
@@ -44,15 +44,10 @@
 		Dispose ();
 	}
 
-	private enum TargetType {
-		UriList,
-		Uri
-	}
-
 	private static TargetEntry [] cover_drag_entries = new TargetEntry [] {
-		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList),
-		new TargetEntry ("x-special/gnome-icon-list", 0, (uint) TargetType.UriList),
-		new TargetEntry ("_NETSCAPE_URL", 0, (uint) TargetType.Uri)
+		new TargetEntry ("text/uri-list", 0, (uint) PlaylistWindow.TargetType.UriList),
+		new TargetEntry ("x-special/gnome-icon-list", 0, (uint) PlaylistWindow.TargetType.UriList),
+		new TargetEntry ("_NETSCAPE_URL", 0, (uint) PlaylistWindow.TargetType.Uri)
 	};
 
 	private void Sync ()
@@ -94,7 +89,7 @@
 		string fn;
 		
 		switch (args.Info) {
-		case (uint) TargetType.Uri:
+		case (uint) PlaylistWindow.TargetType.Uri:
 			uri_list = Regex.Split (data, "\n");
 			fn = uri_list [0];
 			
@@ -121,7 +116,7 @@
 			}
 
 			break;
-		case (uint) TargetType.UriList:
+		case (uint) PlaylistWindow.TargetType.UriList:
 			uri_list = Regex.Split (data, "\r\n");
 			fn = StringUtils.LocalPathFromUri (uri_list [0]);
 
Index: src/HandleView.cs
===================================================================
RCS file: /cvs/gnome/muine/src/HandleView.cs,v
retrieving revision 1.20
diff -u -r1.20 HandleView.cs
--- src/HandleView.cs	11 May 2004 17:52:42 -0000	1.20
+++ src/HandleView.cs	16 Jul 2004 23:51:03 -0000
@@ -33,11 +33,12 @@
 	private static extern uint g_signal_connect_data (IntPtr obj, string name,
 							  SignalDelegate cb, IntPtr data,
 							  IntPtr p, int flags);
-
+		
 	public HandleView () : base (IntPtr.Zero)
 	{
 		Raw = pointer_list_view_new ();
-
+		//Reorderable = true;		
+	
 		g_signal_connect_data (Raw, "pointer_activated", new SignalDelegate (PointerActivatedCallback),
 				       IntPtr.Zero, IntPtr.Zero, 0);
 		g_signal_connect_data (Raw, "pointers_reordered", new SignalDelegate (PointersReorderedCallback),
@@ -96,6 +97,16 @@
 		pointer_list_view_append (Raw, handle);
 	}
 
+	
+	[DllImport ("libmuine")]
+	private static extern void pointer_list_view_insert (IntPtr view,
+							     IntPtr pointer,
+	                                                     IntPtr ins);
+	public void Insert (IntPtr handle, IntPtr ins)
+	{
+		pointer_list_view_insert (Raw, handle, ins);
+	}
+
 	[DllImport ("libmuine")]
 	private static extern bool pointer_list_view_contains (IntPtr view,
 							       IntPtr pointer);
@@ -170,7 +181,6 @@
 
 	[DllImport ("libmuine")]
 	private static extern IntPtr pointer_list_view_get_selection (IntPtr view);
-
 	public List SelectedPointers {
 		get {
 			List ret = new List (pointer_list_view_get_selection (Raw), typeof (int));
@@ -328,7 +338,7 @@
 	{
 		bool go = false;
 		bool ret = false;
-		
+			
 		Gdk.ModifierType mod = 0;
 
 		if ((e.State != 0) &&
@@ -395,7 +405,7 @@
 		if (SelectionChanged != null)
 			SelectionChanged ();
 	}
-
+	
 	public delegate void SelectionChangedHandler ();
 	public event SelectionChangedHandler SelectionChanged;
 }
Index: src/PlaylistWindow.cs
===================================================================
RCS file: /cvs/gnome/muine/src/PlaylistWindow.cs,v
retrieving revision 1.126
diff -u -r1.126 PlaylistWindow.cs
--- src/PlaylistWindow.cs	20 Jun 2004 18:59:39 -0000	1.126
+++ src/PlaylistWindow.cs	16 Jul 2004 23:51:06 -0000
@@ -21,6 +21,7 @@
 using System.Collections;
 using System.IO;
 using System.Text.RegularExpressions;
+using System.Runtime.InteropServices;
 
 using Gtk;
 using GLib;
@@ -90,14 +91,34 @@
 	/* Multimedia Key handler */
 	private MmKeys mmkeys;
 
+	private static TargetEntry [] drag_entries = new TargetEntry [] {
+		new TargetEntry ("MUINE_SONG_LIST", TargetFlags.App, (uint) TargetType.Song),
+		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList)
+	};
+
 	/* Drag and drop targets. */
-	private enum TargetType {
-		UriList
+	public enum TargetType {
+		ModelRow,
+		UriList,
+		Song,
+		Album,
+		Uri
 	};
 
-	private static TargetEntry [] drag_entries = new TargetEntry [] {
-		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList)
+	private static TargetEntry [] playlist_source_entries = new TargetEntry [] {
+		new TargetEntry ("MUINE_TREE_MODEL_ROW", TargetFlags.Widget, (uint) TargetType.ModelRow),
+		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList),
+		new TargetEntry	("text/plain", 0, (uint) TargetType.UriList)
 	};
+		
+	private static TargetEntry [] playlist_dest_entries = new TargetEntry[] {
+		new TargetEntry ("MUINE_TREE_MODEL_ROW", TargetFlags.Widget, (uint) TargetType.ModelRow),
+		new TargetEntry ("MUINE_SONG_LIST", TargetFlags.App, (uint) TargetType.Song),
+		new TargetEntry ("MUINE_ALBUM_LIST", TargetFlags.App, (uint) TargetType.Album),
+		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList),
+	};
+		
+
 
 	public delegate void PlayerChangedSongHandler (Song song, bool hasfocus);
 
@@ -185,36 +206,56 @@
 		string fn;
 
 		switch (args.Info) {
+
 		case (uint) TargetType.UriList:
 			uri_list = Regex.Split (data, "\r\n");
-			fn = StringUtils.LocalPathFromUri (uri_list [0]);
+			bool first = true;
+			foreach (string s in uri_list) {
+				fn = StringUtils.LocalPathFromUri (s);
 
-			if (fn == null) {
-				Drag.Finish (args.Context, false, false, args.Time);
+				if (fn == null) {
+					Drag.Finish (args.Context, false, false, args.Time);
 				return;
-			}
+				}
+				
+	
+				DirectoryInfo dinfo = new DirectoryInfo (fn);
+				if (dinfo.Exists) {
 				
+					ProgressWindow pw = new ProgressWindow (this, dinfo.Name);
+		
+					Muine.DB.AddWatchedFolder (dinfo.FullName);
+					HandleDirectory	(dinfo, pw);
+		
+					pw.Done ();
+
+				} else {
+					FileInfo finfo = new FileInfo (fn);
+					if (!finfo.Exists) {
+						Drag.Finish (args.Context, false, false, args.Time);
+						return;
+					}	
+					if (FileUtils.IsPlaylist (fn)) {
+						OpenPlaylist (fn);
+						first = false;		
+					} else {
+					/* load as music file */
+						if (first) {
+							PlayFile (finfo.FullName);
+							first = false;
+						} else {
+							QueueFile (finfo.FullName);
+						}
+					}	
+				}
+			}
+			Drag.Finish(args.Context, true, false, args.Time);
 			break;
 
 		default:
 			Drag.Finish (args.Context, false, false, args.Time);
 			return;
 		}
-
-		DirectoryInfo dinfo = new DirectoryInfo (fn);
-		if (!dinfo.Exists) {
-			Drag.Finish (args.Context, false, false, args.Time);
-			return;
-		}
-			
-		ProgressWindow pw = new ProgressWindow (this, dinfo.Name);
-		
-		Muine.DB.AddWatchedFolder (dinfo.FullName);
-		HandleDirectory (dinfo, pw);
-		
-		pw.Done ();
-
-		Drag.Finish (args.Context, true, false, args.Time);
 	}
 
 	public void CheckFirstStartUp () 
@@ -414,7 +455,6 @@
 	{
 		playlist = new HandleView ();
 
-		playlist.Reorderable = true; 
 		playlist.Selection.Mode = SelectionMode.Multiple;
 
 		pixbuf_renderer = new ColoredCellRendererPixbuf ();
@@ -423,10 +463,20 @@
 		text_renderer = new CellRendererText ();
 		playlist.AddColumn (text_renderer, new HandleView.CellDataFunc (TextCellDataFunc), true);
 
+		playlist.Reorderable = true;
 		playlist.RowActivated += new HandleView.RowActivatedHandler (HandlePlaylistRowActivated);
 		playlist.RowsReordered += new HandleView.RowsReorderedHandler (HandlePlaylistRowsReordered);
 		playlist.SelectionChanged += new HandleView.SelectionChangedHandler (HandlePlaylistSelectionChanged);
 
+		playlist.EnableModelDragSource (Gdk.ModifierType.Button1Mask, playlist_source_entries, 
+			Gdk.DragAction.Copy | Gdk.DragAction.Link | Gdk.DragAction.Move);
+		playlist.DragDataGet += new DragDataGetHandler (DragDataGetCallback);
+	
+		playlist.DragDataReceived += new DragDataReceivedHandler (HandlePLDragDataReceived);
+		playlist.DragMotion += new DragMotionHandler (HandleDragMotion);
+		Gtk.Drag.DestSet (playlist, DestDefaults.All,
+				  playlist_dest_entries, Gdk.DragAction.Copy | Gdk.DragAction.Move);
+
 		playlist.Show ();
 
 		((Container) glade_xml ["scrolledwindow"]).Add (playlist);
@@ -1037,6 +1087,25 @@
 		NSongsChanged ();
 	}
 
+	public void InsertFile (string file, Song song)
+	{
+		Song song2 = (Song) Muine.DB.Songs[file];
+			if (song2 == null) {
+			/* try to create a new song object */
+			try {
+				song2 = new Song (file);
+			} catch {
+				return;
+			}
+
+			song2.Orphan = true;
+		}
+
+		if (song2 == null)
+			return;
+		playlist.Insert(song2.Handle, song.Handle);
+	}
+
 	private void HandlePlaySongsEvent (List songs)
 	{
 		bool first = true;
@@ -1582,6 +1651,159 @@
 		if (n_songs_changed)
 			NSongsChanged ();
 	}
+	
+	[DllImport ("libmuine")]
+	private static extern IntPtr pointer_list_get_handle_from_row_reference (IntPtr view, IntPtr row);
+
+	[DllImport ("libgobject-2.0-0.dll")]
+	private static extern IntPtr g_object_get_data (IntPtr obj, string key);
+	private void DragDataGetCallback (object o, DragDataGetArgs args)
+	{
+		List songs = playlist.SelectedPointers;
+
+		switch (args.Info) {
+		case (uint) TargetType.UriList:
+			string files = "";
+			foreach (int p in songs) {
+				IntPtr s = new IntPtr(p);
+				files += StringUtils.UriFromLocalPath(Song.FromHandle(s).Filename) + "\r\n";
+			}
+	
+			args.SelectionData.Set(Gdk.Atom.Intern("text/uri-list", false),
+						8, System.Text.Encoding.ASCII.GetBytes(files));
+			break;	
+		case (uint) TargetType.ModelRow:
+			string ptrs = "";
+			foreach (int p in songs) {
+				IntPtr s = new IntPtr(p);
+				ptrs += s.ToString() + "\r\n";
+			}
+			args.SelectionData.Set(Gdk.Atom.Intern("MUINE_SONG_LIST", false),
+					8, System.Text.Encoding.ASCII.GetBytes(ptrs));
+			break;
+		default:
+			break;	
+		}
+	}
+
+	private void HandlePLDragDataReceived (object o, DragDataReceivedArgs args)
+	{
+		TreePath path;
+		string ptrs;
+		Song song = null;		
+		if (playlist.GetPathAtPos (args.X, args.Y, out path)) {
+			IntPtr song_ptr = playlist.GetHandleFromPath (path);
+			 song = Song.FromHandle (song_ptr);
+		}
+		switch (args.Info) {
+		case (uint) TargetType.Song:
+		case (uint) TargetType.ModelRow:
+			ptrs = StringUtils.SelectionDataToString (args.SelectionData);
+			string [] sngs = Regex.Split (ptrs, "\r\n");
+			foreach (string newsong in sngs) {
+				IntPtr new_ptr;
+				try { 
+					new_ptr = new IntPtr(Int64.Parse(newsong)); 
+				} catch { 	
+					continue;
+				 }
+				Song s2 = Song.FromHandle(new_ptr);
+				if (args.Info == (uint)TargetType.ModelRow)
+					RemoveSong(new_ptr);
+				if (song != null) {
+					playlist.Insert(s2.Handle, song.Handle);
+					song = s2;
+				} else  {
+					playlist.Append(s2.Handle);
+					song = s2;
+				}
+				playlist.Select(new_ptr);
+			}
+			break;
+		case (uint) TargetType.Album:
+			ptrs = StringUtils.SelectionDataToString (args.SelectionData);
+			string [] albms = Regex.Split (ptrs, "\r\n");
+			foreach (string newalbum in albms) {
+				IntPtr new_ptr;
+				try {
+					new_ptr = new IntPtr(Int64.Parse(newalbum));
+				 } catch { continue; }
+				Album album = Album.FromHandle(new_ptr);
+				foreach (Song s in album.Songs) {
+					if (song != null) {
+						playlist.Insert(s.Handle, song.Handle);
+						song = s;
+					} else {
+						playlist.Append(s.Handle);
+					}
+				}	
+			}
+			break;
+		case (uint) TargetType.UriList:
+			string data = StringUtils.SelectionDataToString(args.SelectionData);
+			string[] uri_list = Regex.Split (data, "\r\n");
+			bool first = true;
+			foreach (string s in uri_list) {
+				string fn = StringUtils.LocalPathFromUri (s);
+
+				if (fn == null) {
+					Drag.Finish (args.Context, false, false, args.Time);
+				return;
+				}
+				
+	
+				DirectoryInfo dinfo = new DirectoryInfo (fn);
+				if (dinfo.Exists) {
+				
+					ProgressWindow pw = new ProgressWindow (this, dinfo.Name);
+		
+					Muine.DB.AddWatchedFolder (dinfo.FullName);
+					HandleDirectory	(dinfo, pw);
+		
+					pw.Done ();
+
+				} else {
+					FileInfo finfo = new FileInfo (fn);
+					if (!finfo.Exists) {
+						Drag.Finish (args.Context, false, false, args.Time);
+						return;
+					}	
+					if (FileUtils.IsPlaylist (fn)) {
+						OpenPlaylist (fn);
+						first = false;		
+					} else {
+					/* load as music file */
+						if (song == null) {
+							if (first) {
+								PlayFile (finfo.FullName);
+								first = false;
+							} else {
+								QueueFile (finfo.FullName);
+							}
+						} else {
+							InsertFile (finfo.FullName, song);
+						}	
+					}	
+				}
+			}
+			break;
+		default:
+			break;
+		}
+	Drag.Finish(args.Context, true, false, args.Time);
+
+	}
+
+	private void HandleDragMotion (object o, DragMotionArgs args)
+	{
+		TreePath path;
+
+		if (!playlist.GetPathAtPos (args.X, args.Y, out path))
+			return;
+	
+		playlist.SetDragDestRow (path, Gtk.TreeViewDropPosition.After);
+	}
+
 
 	public void AddChildWindowIfVisible (Window window)
 	{
Index: src/StringUtils.cs
===================================================================
RCS file: /cvs/gnome/muine/src/StringUtils.cs,v
retrieving revision 1.14
diff -u -r1.14 StringUtils.cs
--- src/StringUtils.cs	5 Jun 2004 16:49:46 -0000	1.14
+++ src/StringUtils.cs	16 Jul 2004 23:51:06 -0000
@@ -111,4 +111,17 @@
 		else
 			return GLib.Marshaller.PtrToStringGFree (p);
 	}
+
+	[DllImport ("libgnomevfs-2.dll")]
+	private static extern IntPtr gnome_vfs_get_uri_from_local_path (string str);
+
+	public static string UriFromLocalPath (string path)
+	{
+		IntPtr p = gnome_vfs_get_uri_from_local_path (path);
+
+		if (p == IntPtr.Zero)
+			return null;
+		else
+			return GLib.Marshaller.PtrToStringGFree (p);
+	}
 }


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