[Banshee-List] Child source final (v0.6)



Hey,

The "gtk d&d is crack" version patch of child source support for Banshee
is out! All the issues everyone pointed out should be fixed now.

For the awesome minimode plugin users - a patch which makes minimode
work with this has been sent to the list.

Good luck & Have fun!

Lukas
? po/stamp-it
? src/.SourceView.cs.swp
? src/Banshee.Base/ChildSource.cs
Index: src/PlayerInterface.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/PlayerInterface.cs,v
retrieving revision 1.174
diff -u -r1.174 PlayerInterface.cs
--- src/PlayerInterface.cs	14 Apr 2006 15:33:43 -0000	1.174
+++ src/PlayerInterface.cs	15 Apr 2006 19:22:36 -0000
@@ -593,7 +593,6 @@
             LoadSourceView();
             
             SourceManager.AddSource(LibrarySource.Instance, true);
-            PlaylistUtil.LoadSources();
 
             if(LocalQueueSource.Instance.Count > 0) {
                 SourceManager.AddSource(LocalQueueSource.Instance);
@@ -1435,7 +1434,7 @@
             playlist.Rename(PlaylistUtil.GoodUniqueName(playlist.Tracks));
             playlist.Commit();
             
-            SourceManager.AddSource(playlist);
+            LibrarySource.Instance.AddChildSource(playlist);
         }
         
         private void OnItemAddToPlaylistActivated(object o, EventArgs args)
@@ -1854,7 +1853,7 @@
         {
             PlaylistSource playlist = new PlaylistSource();
             playlist.Rename(PlaylistUtil.UniqueName);
-            SourceManager.AddSource(playlist);
+            LibrarySource.Instance.AddChildSource(playlist);
         }
         
         private void OnImportFolderAction(object o, EventArgs args)
Index: src/SourceView.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/SourceView.cs,v
retrieving revision 1.45
diff -u -r1.45 SourceView.cs
--- src/SourceView.cs	18 Feb 2006 16:25:52 -0000	1.45
+++ src/SourceView.cs	15 Apr 2006 19:22:36 -0000
@@ -67,37 +67,37 @@
         private TreeIter newPlaylistIter = TreeIter.Zero;
         private bool newPlaylistVisible = false;
         
-        private ListStore store;
+        private TreeStore store;
         private int currentTimeout = -1;
-
+	
         public SourceView()
         {
-            TreeViewColumn col = new TreeViewColumn();
+	    // Hidden expander column
+	    TreeViewColumn col = new TreeViewColumn();
+	    col.Visible = false;
+	    AppendColumn(col);
+	    ExpanderColumn = col;
+		
+            col = new TreeViewColumn();
             SourceRowRenderer renderer = new SourceRowRenderer();
             col.Title = Catalog.GetString("Source");
             col.PackStart(renderer, true);
             col.SetCellDataFunc(renderer, new TreeCellDataFunc(SourceCellDataFunc));
             AppendColumn(col);
             
-            store = new ListStore(typeof(Source));
+            store = new TreeStore(typeof(Source));
             Model = store;
             HeadersVisible = false;
             
             CursorChanged += OnCursorChanged;
             RefreshList();
-            
+
             SourceManager.SourceAdded += delegate(SourceAddedArgs args) {
-                if(FindSource(args.Source).Equals(TreeIter.Zero)) {
-                    TreeIter iter = store.Insert(args.Position);
-                    store.SetValue(iter, 0, args.Source);
-                }
+		AddSource (args.Source, args.Position);
             };
             
             SourceManager.SourceRemoved += delegate(SourceEventArgs args) {
-                TreeIter iter = FindSource(args.Source);
-                if(!iter.Equals(TreeIter.Zero)) {
-                    store.Remove(ref iter);
-                }
+		RemoveSource (args.Source);
             };
             
             SourceManager.ActiveSourceChanged += delegate(SourceEventArgs args) {
@@ -109,8 +109,11 @@
             };
         }
 
-        private TreeIter FindSource(Source source) {
-            for(int i = 0, n = store.IterNChildren(); i < n; i++) {
+	// FIXME: This is lame and could use some recusrion instead. I may get
+	// around to fixing it soon!
+        private TreeIter FindSource(Source source)
+	{
+            for(int i = 0, m = store.IterNChildren(); i < m; i++) {
                 TreeIter iter = TreeIter.Zero;
                 if(!store.IterNthChild(out iter, i)) {
                     continue;
@@ -119,10 +122,39 @@
                 if((store.GetValue(iter, 0) as Source) == source) {
                     return iter;
                 }
+		
+		for (int j = 0, n = store.IterNChildren(iter); j < n; j++) {
+			TreeIter citer = TreeIter.Zero;
+			if(!store.IterNthChild(out citer, iter, j)) {
+                	    continue;
+	                }
+    
+                	if((store.GetValue(citer, 0) as Source) == source) {
+	                    return citer;
+                	}
+		}
             }
 
             return TreeIter.Zero;
         }
+
+	private bool UpdateView()
+	{
+	    for(int i = 0, m = store.IterNChildren(); i < m; i++) {
+                TreeIter iter = TreeIter.Zero;
+                if(!store.IterNthChild(out iter, i)) {
+                    continue;
+                }
+                
+                if(store.IterNChildren(iter) > 0) {
+                    ExpanderColumn = Columns[1];
+		    return true;
+                }
+	    }
+	    
+	    ExpanderColumn = Columns[0];
+	    return false;
+	}
                     
         protected void SourceCellDataFunc(TreeViewColumn tree_column,
             CellRenderer cell, TreeModel tree_model, TreeIter iter)
@@ -150,11 +182,55 @@
             source.Rename(text);
         }
         
+	private void AddSource(Source source)
+	{
+		AddSource (source, -1);
+	}
+
+	private void AddSource(Source source, int position)
+	{
+		if(FindSource(source).Equals(TreeIter.Zero)) {
+                	TreeIter iter = store.InsertNode(position);
+                	store.SetValue(iter, 0, source);
+			
+			foreach (ChildSource s in source.Children) {
+				TreeIter i = store.AppendNode(iter);
+        	        	store.SetValue(i, 0, s);
+			}
+		    
+			source.ChildSourceAdded += delegate(SourceEventArgs e) {
+				TreeIter i = store.AppendNode(iter);
+        	        	store.SetValue(i, 0, e.Source);
+				Expand(iter);
+			};
+
+			Expand(iter);
+		}
+
+		UpdateView();
+	}
+
+	private void RemoveSource(Source source)
+	{
+                TreeIter iter = FindSource(source);
+                if(!iter.Equals(TreeIter.Zero)) {
+                    store.Remove(ref iter);
+                }
+
+		UpdateView();
+	}
+	
+	private void Expand(TreeIter iter)
+	{
+		TreePath path = store.GetPath (iter);
+		ExpandRow (path, true);
+	}
+	
         private void RefreshList()
         {
             store.Clear();
             foreach(Source source in SourceManager.Sources) {
-                store.AppendValues(source);
+                AddSource (source);
             }
         } 
         
@@ -188,62 +264,76 @@
             return false;
         }
         
-        protected override bool OnDragMotion(Gdk.DragContext context, int x, int y, uint time)
+	protected override bool OnDragMotion(Gdk.DragContext context, int x, int y, uint time)
         {
             base.OnDragMotion(context, x, y, time);
-            SetDragDestRow(null, TreeViewDropPosition.IntoOrAfter);
-            Gdk.Drag.Status(context, 0, time);
+	    SetDragDestRow(null, TreeViewDropPosition.IntoOrAfter);
+            Gdk.Drag.Status(context, Gdk.DragAction.Copy, time);
 
-            // TODO: Support other drag sources
-            if(!(SourceManager.ActiveSource is LibrarySource)) {
-                return true;
-            }
-            
-            if(!newPlaylistVisible) {
-                newPlaylistIter = store.AppendValues(newPlaylistSource);
+            // FIXME: We need to handle this nicer
+            //if(!((SourceManager.ActiveSource is LibrarySource)
+	    //|| ((SourceManager.ActiveSource is PlaylistSource) && (SourceManager.ActiveSource as PlaylistSource).Local))) {
+            //      return true;
+            //}
+	    
+            if (!newPlaylistVisible) {
+       		TreeIter library = FindSource(LibrarySource.Instance);
+                newPlaylistIter = store.AppendNode(library);
+		store.SetValue(newPlaylistIter, 0, newPlaylistSource);
                 newPlaylistVisible = true;
-            }
 
+		UpdateView ();
+		Expand(library);
+            }
+	    
             TreePath path;
             TreeViewDropPosition pos;
-            if(!GetDestRowAtPos(x, y, out path, out pos)) {
-                path = store.GetPath(newPlaylistIter);
-            }
+            if(GetDestRowAtPos(x, y, out path, out pos)) {
+                Source source = GetSource(path);
+                SetDragDestRow(path, TreeViewDropPosition.IntoOrAfter);
+	            
+                // TODO: Support other drag destinations
+                if((source is PlaylistSource) || (source is DapSource)) {
+                    return true;
+                }
 
-            Source source = GetSource(path);
-            if(source == null) {
-                return true;
-            }
-            
-            // TODO: Support other drag destinations
-            if(!(source is PlaylistSource) && !(source is DapSource)) {
-                return true;
-            }
+                Gdk.Drag.Status(context, 0, time);
+		return true;
+	    }
             
-            SetDragDestRow(path, TreeViewDropPosition.IntoOrAfter);
-            Gdk.Drag.Status(context, Gdk.DragAction.Copy, time);
             return true;
         }
         
+	private Source final_drag_source = null;
+	private uint final_drag_start_time = 0;
+	
         protected override void OnDragLeave(Gdk.DragContext context, uint time)
         {
-            if(newPlaylistVisible) {
+            TreePath path;
+            TreeViewDropPosition pos;
+            GetDragDestRow (out path, out pos);
+
+            if(path == null)
+                path = store.GetPath(newPlaylistIter);
+		
+            final_drag_source = GetSource (path);
+	    final_drag_start_time = context.StartTime;
+	    
+            if (newPlaylistVisible) {
                 store.Remove(ref newPlaylistIter);
                 newPlaylistVisible = false;
+                UpdateView ();
             }
         }
 
         protected override void OnDragDataReceived(Gdk.DragContext context, int x, int y,
             Gtk.SelectionData selectionData, uint info, uint time)
-        {
-            TreePath destPath;
-            TreeViewDropPosition pos;
-            
+        {       
             string rawData = Dnd.SelectionDataToString(selectionData);        
             string [] rawDataArray = Dnd.SplitSelectionData(rawData);
             if(rawData.Length <= 0) {
                 Gtk.Drag.Finish(context, false, false, time);
-                return;        
+                return;
             }
             
             ArrayList tracks = new ArrayList();
@@ -255,21 +345,24 @@
                     continue;
                 }
             }
-            
-            if(GetDestRowAtPos(x, y, out destPath, out pos)) {
-                Source source = GetSource(destPath);
-                if(source is PlaylistSource || source is DapSource) {
-                    source.AddTrack(tracks);
-                    source.Commit();
-                }
-            } else {
-                PlaylistSource playlist = new PlaylistSource();
-                playlist.AddTrack(tracks);
-                playlist.Rename(PlaylistUtil.GoodUniqueName(playlist.Tracks));
-                playlist.Commit();
-                SourceManager.AddSource(playlist);
+
+	    if(final_drag_start_time == context.StartTime) {
+                if(final_drag_source == newPlaylistSource) {
+                    PlaylistSource playlist = new PlaylistSource();
+                    playlist.AddTrack(tracks);
+                    playlist.Rename(PlaylistUtil.GoodUniqueName(playlist.Tracks));
+                    playlist.Commit();
+                    LibrarySource.Instance.AddChildSource(playlist);
+                    UpdateView ();
+		} else {
+                    Source source = final_drag_source;
+                    if(source is PlaylistSource || source is DapSource) {
+                        source.AddTrack(tracks);
+                        source.Commit();
+                    }
+		}
             }
-            
+	    
             Gtk.Drag.Finish(context, true, false, time);
         }
         
@@ -282,23 +375,23 @@
         {
             TreeIter iter;
         
+	    //Console.WriteLine (path.ToString ());
+	    
             if(store.GetIter(out iter, path)) {
                 return store.GetValue(iter, 0) as Source;
             }
-            
+	    
             return null;
         }
         
         public void ResetHighlight()
         {
-            TreeIter iter = TreeIter.Zero;
+            TreeIter iter = FindSource (SourceManager.ActiveSource);
             
-            if(!store.IterNthChild(out iter, SourceManager.ActiveSourceIndex)) {
-                return;
+            if(!iter.Equals(TreeIter.Zero)){
+                Selection.SelectIter(iter);
             }
-             
-            Selection.SelectIter(iter);
-        }
+         }
         
         public Source HighlightedSource {
             get {
@@ -489,3 +582,5 @@
         }
     }
 }
+
+
Index: src/Banshee.Base/Library.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/Library.cs,v
retrieving revision 1.10
diff -u -r1.10 Library.cs
--- src/Banshee.Base/Library.cs	9 Apr 2006 21:30:23 -0000	1.10
+++ src/Banshee.Base/Library.cs	15 Apr 2006 19:22:37 -0000
@@ -56,7 +56,6 @@
         public BansheeDatabase Db;
         public Hashtable Tracks = new Hashtable();
         public Hashtable TracksFnKeyed = new Hashtable();
-        public Hashtable Playlists = new Hashtable();
         
         public event EventHandler Reloaded;
         public event EventHandler Updated;
Index: src/Banshee.Base/LibraryTrackInfo.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/LibraryTrackInfo.cs,v
retrieving revision 1.9
diff -u -r1.9 LibraryTrackInfo.cs
--- src/Banshee.Base/LibraryTrackInfo.cs	9 Apr 2006 21:30:23 -0000	1.9
+++ src/Banshee.Base/LibraryTrackInfo.cs	15 Apr 2006 19:22:37 -0000
@@ -423,12 +423,12 @@
             }
         }
 
-		static string Choose (string priority, string fallback)
-		{
-			if (priority == null || priority.Length == 0)
-				return fallback;
-			return priority;
-		}
+	static string Choose (string priority, string fallback)
+	{
+		if (priority == null || priority.Length == 0)
+			return fallback;
+		return priority;
+	}
 		
         private void LoadFromFile(string filename)
         {
@@ -487,5 +487,10 @@
             Core.Library.Db.Execute(query);*/
             Save();
         }
+
+	public bool Valid()
+	{
+		return File.Exists(Uri.AbsolutePath);
+	}
     }
 }
Index: src/Banshee.Base/Makefile.am
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/Makefile.am,v
retrieving revision 1.28
diff -u -r1.28 Makefile.am
--- src/Banshee.Base/Makefile.am	9 Apr 2006 21:30:23 -0000	1.28
+++ src/Banshee.Base/Makefile.am	15 Apr 2006 19:22:37 -0000
@@ -35,6 +35,7 @@
 SOURCES_SOURCES = \
 	$(srcdir)/SourceManager.cs \
 	$(srcdir)/Source.cs \
+	$(srcdir)/ChildSource.cs \
 	$(srcdir)/Sources/LibrarySource.cs \
 	$(srcdir)/Sources/PlaylistSource.cs \
 	$(srcdir)/Sources/AudioCdSource.cs \
Index: src/Banshee.Base/Source.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/Source.cs,v
retrieving revision 1.7
diff -u -r1.7 Source.cs
--- src/Banshee.Base/Source.cs	13 Feb 2006 22:18:08 -0000	1.7
+++ src/Banshee.Base/Source.cs	15 Apr 2006 19:22:40 -0000
@@ -54,15 +54,20 @@
         private int order;
         private string name;
 
+        private ArrayList child_sources;
+
         public event EventHandler Updated;
         public event TrackEventHandler TrackAdded;
         public event TrackEventHandler TrackRemoved;
         public event EventHandler ViewChanged;
+        public event SourceEventHandler ChildSourceAdded;
+        public event SourceEventHandler ChildSourceRemoved;
         
         protected Source(string name, int order)
         {
             this.name = name;
             this.order = order;
+            this.child_sources = new ArrayList ();
         }
         
         public void Dispose()
@@ -173,6 +178,37 @@
             }
         }
         
+	public virtual void AddChildSource(ChildSource source)
+	{
+		source.SetParentSource(source);
+		child_sources.Add(source);
+		
+    		SourceEventHandler handler = ChildSourceAdded;
+    		if(handler != null) {
+			SourceEventArgs evargs = new SourceEventArgs();
+	                evargs.Source = source;
+                	handler(evargs);
+	        }
+	}
+
+	public virtual void RemoveChildSource(ChildSource source)
+	{
+		child_sources.Remove(source);
+
+    		SourceEventHandler handler = ChildSourceRemoved;
+    		if(handler != null) {
+			SourceEventArgs evargs = new SourceEventArgs();
+	                evargs.Source = source;
+                	handler(evargs);
+	        }
+	}
+	
+	public ICollection Children {
+            get {
+                return child_sources;
+            }
+	}
+
         public virtual int Count {
             get {
                 return -1;
Index: src/Banshee.Base/SourceManager.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/SourceManager.cs,v
retrieving revision 1.7
diff -u -r1.7 SourceManager.cs
--- src/Banshee.Base/SourceManager.cs	18 Feb 2006 16:25:52 -0000	1.7
+++ src/Banshee.Base/SourceManager.cs	15 Apr 2006 19:22:40 -0000
@@ -216,18 +216,6 @@
             });
         }
         
-        public static int ActiveSourceIndex {
-            get {
-                for(int i = 0; i < sources.Count; i++) {
-                    if((sources[i] as Source) == active_source) {
-                        return i;
-                    }
-                }
-                
-                return -1;
-            }
-        }
-        
         public static ICollection Sources {
             get {
                 return sources;
Index: src/Banshee.Base/Sources/LibrarySource.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/Sources/LibrarySource.cs,v
retrieving revision 1.6
diff -u -r1.6 LibrarySource.cs
--- src/Banshee.Base/Sources/LibrarySource.cs	20 Mar 2006 08:38:39 -0000	1.6
+++ src/Banshee.Base/Sources/LibrarySource.cs	15 Apr 2006 19:22:42 -0000
@@ -58,6 +58,10 @@
                 OnTrackAdded(args.Track);
                 OnUpdated();
             };  
+
+            foreach (ChildSource playlist in PlaylistUtil.LoadSources()) {
+		    AddChildSource (playlist);
+	    }
         }
         
         public override void RemoveTrack(TrackInfo track)
Index: src/Banshee.Base/Sources/PlaylistSource.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/Sources/PlaylistSource.cs,v
retrieving revision 1.5
diff -u -r1.5 PlaylistSource.cs
--- src/Banshee.Base/Sources/PlaylistSource.cs	13 Feb 2006 22:18:10 -0000	1.5
+++ src/Banshee.Base/Sources/PlaylistSource.cs	15 Apr 2006 19:22:42 -0000
@@ -36,9 +36,10 @@
 
 namespace Banshee.Sources
 {
-    public class PlaylistSource : Source
+    public class PlaylistSource : ChildSource
     {
         private static ArrayList playlists = new ArrayList();
+	
         public static IEnumerable Playlists {
             get {
                 return playlists;
@@ -53,12 +54,16 @@
         
         private ArrayList tracks = new ArrayList();
         private int id;
-    
+	
         public PlaylistSource() : this(0)
         {
         }
-    
-        public PlaylistSource(int id) : base(Catalog.GetString("New Playlist"), 500)
+
+	public PlaylistSource(string name) : base(name, 500)
+	{
+	}
+
+	public PlaylistSource(int id) : base(Catalog.GetString("New Playlist"), 500)
         {
             this.id = id;
             
@@ -138,10 +143,8 @@
  
         public override void AddTrack(TrackInfo track)
         {
-            if(track is LibraryTrackInfo) {
-                tracks.Add(track);
-                OnUpdated();
-            }
+            tracks.Add(track);
+            OnUpdated();
         }
         
         public override void RemoveTrack(TrackInfo track)
@@ -246,18 +249,28 @@
                 return IconThemeUtils.LoadIcon(22, "source-playlist");
             }
         }
+
+        public bool Local {
+            get {
+                return (id > 0);
+            }
+        }  
     }
     
     public static class PlaylistUtil
     {
-        public static void LoadSources()
+        public static ICollection LoadSources()
         {
-            IDataReader reader = Globals.Library.Db.Query("SELECT PlaylistID FROM Playlists");
+	    ArrayList sources = new ArrayList ();
+	    
+	    IDataReader reader = Globals.Library.Db.Query("SELECT PlaylistID FROM Playlists");
             while(reader.Read()) {
                 PlaylistSource playlist = new PlaylistSource(Convert.ToInt32(reader[0]));
-                SourceManager.AddSource(playlist);
+		sources.Add (playlist);
             }
             reader.Dispose();
+
+	    return sources;
         }
     
         internal static int GetPlaylistID(string name)
--- /dev/null	2006-04-03 19:40:38.000000000 +0200
+++ src/Banshee.Base/ChildSource.cs	2006-04-14 12:01:04.000000000 +0200
@@ -0,0 +1,63 @@
+
+/***************************************************************************
+ *  ChildSource.cs
+ *
+ *  Copyright (C) 2006 Novell
+ *  Written by Lukas Lipka (lukas pmad net)
+ ****************************************************************************/
+
+/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW: 
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of this software and associated documentation files (the "Software"),  
+ *  to deal in the Software without restriction, including without limitation  
+ *  the rights to use, copy, modify, merge, publish, distribute, sublicense,  
+ *  and/or sell copies of the Software, and to permit persons to whom the  
+ *  Software is furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in 
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ *  DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+ 
+namespace Banshee.Sources
+{
+    public class ChildSource : Source
+    {
+	private Source parent;	    
+
+	protected ChildSource(string name, int position) : base(name, position)
+	{
+	}
+
+	public override void AddChildSource(ChildSource source)
+	{
+            throw new Exception("Cannot add a child source to a child source!");
+	}
+
+	public override void RemoveChildSource(ChildSource source)
+	{
+            throw new Exception("Cannot remove a child source from a child source!");
+	}
+
+	public void SetParentSource(Source source)
+	{
+            parent = source;
+	}
+
+	public Source Parent {
+            get {
+                return parent;
+            }
+	}
+    }
+}


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